JavaScript图形实例:圆内螺线
数学中有各式各样富含诗意的曲线,螺旋线就是其中比较特别的一类。螺旋线这个名词来源于希腊文,它的原意是“旋卷”或“缠卷”。例如,平面螺旋线便是以一个固定点开始向外逐圈旋绕而形成的曲线。
阿基米德螺线和黄金螺旋线就是典型的螺旋线。下面我们探讨一种典型的螺旋线:圆内螺线。
1.圆内螺线的形成方式
在固定的大圆中内切一个运动的小圆,在小圆滚动的过程中,其上一个定点P所形成的轨迹,即为圆内螺线。点P会随着两圆半径比值的不同而出现不同轨迹。例如,当小圆半径等于大圆的四分之一时,形成的轨迹则是星形线,如图1所示。参见百度百科的词条“圆内螺线”(https://baike.so.com/doc/388206-411038.html)。

图1 圆内螺线的形成示意图
圆内螺线的笛卡尔坐标参数方程为:
x=cosθ+[cos(nθ)]/n
y=sinθ-[sin(nθ)]/n (0≤θ≤2π, n为大圆半径与小圆半径的比值)
编写如下的HTML代码。
<!DOCTYPE html>
<head>
<title>圆内螺线(一)</title>
<script type="text/javascript">
function draw(id)
{
var canvas=document.getElementById(id);
if (canvas==null)
return false;
var context=canvas.getContext('2d');
context.fillStyle="#EEEEFF";
context.fillRect(0,0,300,300);
context.strokeStyle="red";
context.lineWidth=2;
context.save();
context.translate(150,150);
var R=80; // R+r 为大圆半径
var r=20; // 小圆半径
context.beginPath();
context.arc(0,0,R+r,0,Math.PI*2,true);
context.closePath();
context.stroke();
context.beginPath();
context.arc(0,0,R-r,0,Math.PI*2,true);
context.closePath();
context.stroke();
context.beginPath();
for (theta=0;theta<2*Math.PI;theta+=Math.PI/100)
{
n=R/r;
var x = R*(Math.cos(theta)+Math.cos(n*theta)/n);
var y = R*(Math.sin(theta)-Math.sin(n*theta)/n);
if (theta==0)
context.moveTo(x,y);
else
context.lineTo(x,y);
}
context.closePath();
context.stroke();
context.restore();
}
</script>
</head>
<body onload="draw('myCanvas');">
<canvas id="myCanvas" width="300" height="300"></canvas>
</body>
</html>
将上述HTML代码保存到一个html文本文件中,再在浏览器中打开包含这段HTML代码的html文件,可以看到在画布中绘制出圆内螺线图案1,如图2所示。

图2 圆内螺线图案1(R=5r)
将大圆半径与小圆半径的比值修改为9,即修改语句“var r=20;”为“var r=10”,则在画布中绘制出如图3所示的圆内螺线图案2。

图3 圆内螺线图案2(R=9r)
2.带结环的圆内螺线
我们修改圆内螺线的参数方程,使得螺线在交接处出现结环。修改的参数方程为:
n=(R+r)/r;
x = (R+r)*cos(θ)+(r+o)*cos(n*θ)
y = (R+r)*sin(θ)-(r+o)* sin (n*θ) (0≤θ≤2π)
编写的HTML文件内容如下。
<!DOCTYPE html>
<head>
<title>圆内螺线(二)</title>
<script type="text/javascript">
function draw(id)
{
var canvas=document.getElementById(id);
if (canvas==null)
return false;
var context=canvas.getContext('2d');
context.fillStyle="#EEEEFF";
context.fillRect(0,0,300,300);
context.strokeStyle="red";
context.lineWidth=2;
context.save();
context.translate(150,150);
var R=60; // R+r 为大圆半径
var r=15; // 小圆半径
var o=15;
context.beginPath();
context.arc(0,0,R+2*r+o,0,Math.PI*2,true);
context.closePath();
context.stroke();
context.beginPath();
context.arc(0,0,R-o,0,Math.PI*2,true);
context.closePath();
context.stroke();
context.beginPath();
for (theta=0;theta<2*Math.PI;theta+=Math.PI/100)
{
n=(R+r)/r;
var x = (R+r)*Math.cos(theta)+(r+o)*Math.cos(n*theta);
var y = (R+r)*Math.sin(theta)-(r+o)*Math.sin(n*theta);
if (theta==0)
context.moveTo(x,y);
else
context.lineTo(x,y);
}
context.stroke();
context.restore();
}
</script>
</head>
<body onload="draw('myCanvas');">
<canvas id="myCanvas" width="300" height="300"></canvas>
</body>
</html>
将上述HTML代码保存到一个html文本文件中,再在浏览器中打开包含这段HTML代码的html文件,可以看到在画布中绘制出带结环的圆内螺线图案,如图4所示。

图4 带结环的圆内螺线图案
上面绘制图4的代码不是很完善,例如,我们修改语句“var r=15;”为“var r=24;”,其他语句保持不变,则在画布中绘制出如图5所示图案。这个图案显然不是一条封闭曲线,也就是图案未绘制完整。修改循环控制语句,使得θ范围为[0,3π],则在画布中绘制出如图6所示图案,这条曲线仍未封闭;当修改循环控制语句,使得θ范围为[0,4π],才在画布中绘制出如图7所示的封闭曲线图案。

图5 0≤θ≤2π绘制的图案

图6 0≤θ≤3π绘制的图案

图7 0≤θ≤4π绘制的图案
如何修改程序,使得图案绘制时,无需事先确定θ的取值范围,当曲线闭合时,自动结束绘制呢?
取θ=0时的坐标(x0,y0)为起始点,之后按给定的参数方程依次计算坐标(x,y)并绘图,当计算的坐标点(x,y)与(x0,y0)重合时,结束图形绘制。
<!DOCTYPE html>
<head>
<title>圆内螺线(三)</title>
<script type="text/javascript">
function draw(id)
{
var canvas=document.getElementById(id);
if (canvas==null)
return false;
var context=canvas.getContext('2d');
context.fillStyle="#EEEEFF";
context.fillRect(0,0,300,300);
context.strokeStyle="red";
context.lineWidth=2;
context.save();
context.translate(150,150);
var R=60; // R+r 为大圆半径
var r=24; // 小圆半径
var o=15;
context.beginPath();
context.arc(0,0,R+2*r+o,0,Math.PI*2,true);
context.closePath();
context.stroke();
context.beginPath();
context.arc(0,0,R-o,0,Math.PI*2,true);
context.closePath();
context.stroke();
var x1 = R+2*r+o; // theta=0 时的值
var y1 = 0;
var i = 1;
context.beginPath();
context.moveTo(x1,y1);
do {
if (i>20000) break; // θ最大可达200π
theta=i*Math.PI/100;
n=(R+r)/r;
var x2 = (R+r)*Math.cos(theta)+(r+o)*Math.cos(n*theta);
var y2 = (R+r)*Math.sin(theta)-(r+o)*Math.sin(n*theta);
context.lineTo(x2,y2);
i++;
} while (x2 != x1 && y2 != y1);
context.stroke();
context.restore();
}
</script>
</head>
<body onload="draw('myCanvas');">
<canvas id="myCanvas" width="300" height="300"></canvas>
</body>
</html>
3.另类圆内螺线
修改参数方程为:
n=(R+r)/r;
x = (R+r)*cos(θ)-(r+o)*cos(n*θ)
y = (R+r)*sin(θ)-(r+o)* sin (n*θ) (0≤θ≤kπ,R、r、o取适当值)
编写如下的HTML代码。
<!DOCTYPE html>
<head>
<title>圆内螺线(四)</title>
<script type="text/javascript">
function draw(id)
{
var canvas=document.getElementById(id);
if (canvas==null)
return false;
var context=canvas.getContext('2d');
context.fillStyle="#EEEEFF";
context.fillRect(0,0,300,300);
context.strokeStyle="red";
context.lineWidth=2;
context.save();
context.translate(150,150);
var R=180;
var r=-96;
var o=60;
var x0 = R-o; // theta=0 时的值
var y0 = 0;
var i = 1;
context.beginPath();
context.moveTo(x0,y0);
do {
if (i>20000) break; // θ最大可达200π
theta=i*Math.PI/100;
n=(R+r)/r;
var x = (R+r)*Math.cos(theta)-(r+o)*Math.cos(n*theta);
var y = (R+r)*Math.sin(theta)-(r+o)*Math.sin(n*theta);
context.lineTo(x,y);
i++;
} while (x != x0 && y != y0);
context.stroke();
context.restore();
}
</script>
</head>
<body onload="draw('myCanvas');">
<canvas id="myCanvas" width="300" height="300"></canvas>
</body>
</html>
将上述HTML代码保存到一个html文本文件中,再在浏览器中打开包含这段HTML代码的html文件,可以看到在画布中绘制出另类螺旋线图案,如图8所示。

图8 R=180,r=-96,o=60时的螺旋线
修改绘制图8程序中的R、r、o初始值,可以绘制出不同的螺旋曲线。例如,若指定R=160,r=-96,o=40,则在画布中绘制出图9所示的图案;若指定R=160,r=-56,o=40,则在画布中绘制出图10所示的图案;若指定R=66,r=18,o=15,则在画布中绘制出图11所示的图案。

图9 R=160,r=-96,o=40时的螺旋线

图10 R=160,r=-56,o=40时的螺旋线

图11 R=66,r=18,o=15时的螺旋线
JavaScript图形实例:圆内螺线的更多相关文章
- JavaScript图形实例:随机SierPinski三角形
在“JavaScript图形实例:SierPinski三角形”中,我们介绍了SierPinski三角形的基本绘制方法,在“JavaScript图形实例:迭代函数系统生成图形”一文中,介绍了采用IFS方 ...
- JavaScript图形实例:线段构图
在“JavaScript图形实例:四瓣花型图案”和“JavaScript图形实例:蝴蝶结图案”中,我们绘制图形时,主要采用的方法是先根据给定的曲线参数方程计算出两点坐标,然后将两点用线段连接起来,线段 ...
- JavaScript图形实例:再谈IFS生成图形
在“JavaScript图形实例:迭代函数系统生成图形”一文中,我们介绍了采用迭代函数系统(Iterated Function System,IFS)创建分形图案的一些实例.在该文中,仿射变换函数W的 ...
- JavaScript图形实例:图形放大镜效果
1. 基本四瓣花型图案 根据四瓣花卉线的参数方程: t= r*(1+sin(12*θ)/5)*(0.5+sin(4*θ)/2); x=t*cos(θ)); y=t*sin(θ)); 编写如下的HTML ...
- JavaScript图形实例:阿基米德螺线
1.阿基米德螺线 阿基米德螺线亦称“等速螺线”.当一点P沿动射线OP以等速率运动的同时,该射线又以等角速度绕点O旋转,点P的轨迹称为“阿基米德螺线”. 阿基米德螺线的笛卡尔坐标方程式为: r=10*( ...
- JavaScript图形实例:图形的旋转变换
旋转变换:图形上的各点绕一固定点沿圆周路径作转动称为旋转变换.可用旋转角表示旋转量的大小. 旋转变换通常约定以逆时针方向为正方向.最简单的旋转变换是以坐标原点(0,0)为旋转中心,这时,平面上一点P( ...
- JavaScript图形实例:Canvas API
1.Canvas概述 Canvas API(画布)用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript操作的位图(bitmap). 要使用HTML5在浏览器窗口中绘制 ...
- JavaScript图形实例:合成花卉图
我们知道在直角坐标系中,圆的方程可描述为: X=R*COS(α) Y=R*SIN(α) 用循环依次取α值为0~2π,计算出X和Y,在canvas画布中将坐标点(X,Y)用线连起来,可绘制出一个圆.编写 ...
- JavaScript图形实例:正多边形
圆心位于坐标原点,半径为R的圆的参数方程为 X=R*COS(θ) Y=R*SIN(θ) 在圆上取N个等分点,将这N个点首尾连接N条边,可以得到一个正N边形. 1.正多边形阵列 构造一个8行8列的正N( ...
随机推荐
- 【音乐欣赏】《Wrong》 - Far Out / Emilia Ali
曲名:Wrong 作者:Far Out / Emilia Ali [00:16.03]Ride body on mine [00:18.07]Griping your waist as I was o ...
- Linux 设备驱动IO操作
每个外设都是通过读写其寄存器来控制的.外设寄存器也称为I/O端口,通常包括:控制寄存器.状态寄存器和数据寄存器三大类. 根据CPU体系结构的不同,CPU对IO端口的编址方式有两种: (1)I/O映射方 ...
- python基础之函数,递归,内置函数
一.数学定义的函数与python中的函数 初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因 ...
- Python socket day1
客户端和服务端通过ip地址确认互相身份.(ip:用来在网络中标记一台电脑) 如果A,B两个人IP地址相同,接受到的信息有时候A收到,有时候B收到 当你用QQ时,双击选中头像其实就是选中了对方的IP地址 ...
- Druid数据源SQL数据库与Spring监控
Druid监控概要说明 为什么要监控? Druid是什么?德鲁伊 URL监控配置说明 配置步骤 步骤 配置 第一步 web.xml 配置 WebStatFilter 第二步 WebStatFilter ...
- 关于报错:Warning: Cannot modify header information - headers already sent by (output started at
8月5日,第一个项目即将完成,测试时,发现登录功能会出现小问题:记住密码的时候会报错 Warning: Cannot modify header information - headers alrea ...
- 【快学SpringBoot】快速上手好用方便的Spring Cache缓存框架
前言 缓存,在开发中是非常常用的.在高并发系统中,如果没有缓存,纯靠数据库来扛,那么数据库压力会非常大,搞不好还会出现宕机的情况.本篇文章,将会带大家学习Spring Cache缓存框架. 原创声明 ...
- 如何让div中的img图片显示在div下面。
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title>& ...
- Java 11 New Features
前言 北京时间 2018年9 月 26 日,Oracle 官方宣布 Java 11 正式发布.这是 Java 大版本周期变化后的第一个长期支持版本,非常值得关注.从官网即可下载, 最新发布的 Java ...
- Spring学习(十)
需要的jar包 1.Spring核心必须依赖的库:commons-logging-1.1.1.jar2.Spring IoC部分核心库: spring-beans-4.3.9.RELEASE.jar ...