数学中有各式各样富含诗意的曲线,螺旋线就是其中比较特别的一类。螺旋线这个名词来源于希腊文,它的原意是“旋卷”或“缠卷”。例如,平面螺旋线便是以一个固定点开始向外逐圈旋绕而形成的曲线。

阿基米德螺线和黄金螺旋线就是典型的螺旋线。下面我们探讨一种典型的螺旋线:圆内螺线。

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图形实例:圆内螺线的更多相关文章

  1. JavaScript图形实例:随机SierPinski三角形

    在“JavaScript图形实例:SierPinski三角形”中,我们介绍了SierPinski三角形的基本绘制方法,在“JavaScript图形实例:迭代函数系统生成图形”一文中,介绍了采用IFS方 ...

  2. JavaScript图形实例:线段构图

    在“JavaScript图形实例:四瓣花型图案”和“JavaScript图形实例:蝴蝶结图案”中,我们绘制图形时,主要采用的方法是先根据给定的曲线参数方程计算出两点坐标,然后将两点用线段连接起来,线段 ...

  3. JavaScript图形实例:再谈IFS生成图形

    在“JavaScript图形实例:迭代函数系统生成图形”一文中,我们介绍了采用迭代函数系统(Iterated Function System,IFS)创建分形图案的一些实例.在该文中,仿射变换函数W的 ...

  4. JavaScript图形实例:图形放大镜效果

    1. 基本四瓣花型图案 根据四瓣花卉线的参数方程: t= r*(1+sin(12*θ)/5)*(0.5+sin(4*θ)/2); x=t*cos(θ)); y=t*sin(θ)); 编写如下的HTML ...

  5. JavaScript图形实例:阿基米德螺线

    1.阿基米德螺线 阿基米德螺线亦称“等速螺线”.当一点P沿动射线OP以等速率运动的同时,该射线又以等角速度绕点O旋转,点P的轨迹称为“阿基米德螺线”. 阿基米德螺线的笛卡尔坐标方程式为: r=10*( ...

  6. JavaScript图形实例:图形的旋转变换

    旋转变换:图形上的各点绕一固定点沿圆周路径作转动称为旋转变换.可用旋转角表示旋转量的大小. 旋转变换通常约定以逆时针方向为正方向.最简单的旋转变换是以坐标原点(0,0)为旋转中心,这时,平面上一点P( ...

  7. JavaScript图形实例:Canvas API

    1.Canvas概述 Canvas API(画布)用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript操作的位图(bitmap). 要使用HTML5在浏览器窗口中绘制 ...

  8. JavaScript图形实例:合成花卉图

    我们知道在直角坐标系中,圆的方程可描述为: X=R*COS(α) Y=R*SIN(α) 用循环依次取α值为0~2π,计算出X和Y,在canvas画布中将坐标点(X,Y)用线连起来,可绘制出一个圆.编写 ...

  9. JavaScript图形实例:正多边形

    圆心位于坐标原点,半径为R的圆的参数方程为 X=R*COS(θ) Y=R*SIN(θ) 在圆上取N个等分点,将这N个点首尾连接N条边,可以得到一个正N边形. 1.正多边形阵列 构造一个8行8列的正N( ...

随机推荐

  1. DataGridView编辑后立即更新到数据库的两种方法

    DataGridView控件是微软预先写好的一个显示数据的控件,功能非常强大,可以显示来自数据库表的数据和XML等其他来源的数据. 方法一:基于DataAdapter对象创建一个CommandBuli ...

  2. 密码学笔记——eval(function(p,a,c,k,e,d) 加密破解

    密码学笔记——eval(function(p,a,c,k,e,d) 的加密破解 例题: 小明某天在看js的时候,突然看到了这么一段代码,发现怎么也理不出代码逻辑,你能帮帮他吗? 格式:SimCTF{} ...

  3. buuctf 变异凯撒

    加密密文:afZ_r9VYfScOeO_UL^RWUc 格式:flag{ } 这里我们发现a, f, Z, _的ASCii码是 97, 102, 90, 95 而再看这里flag{}的ASCii码是- ...

  4. bugku web 5

    首先进入网站http://123.206.87.240:8002/web5/index.php 进入之后就会看到 然后点击F12就会打开后台 然后就会发现有一串东西就是这个然后经过搜索是jsfuck ...

  5. Django视图层、模板层

    过滤器方法 upper 大写方式输出 add 给value加上一个数值 capfirst 第一个字母大写 center 输出指定长度的字符串,把变量居中 cut 删除指定字符串 date 格式化日期 ...

  6. JavaScript复习总结一(入门)

    总是执着想学各种框架,但忘了基础学好才最重要.每次打开菜鸟教程想重温基础内容,然后就像翻开英文字典,永远在abandon...还是需要做个笔记. 一来加深学习印象,二来等下次打开学习可以知道自己上次学 ...

  7. Python 多任务(进程) day1(2)

    进程和线程的简单区别: 功能:进程:能够完成多任务,比如 在一台电脑上能够运行多个QQ一份资源有一个执行的剪头,有多份资源就可以执行多个语句线程:能够完成多任务,比如 在一个QQ中的多个聊天窗口一份资 ...

  8. Day1 面向对象编程与Java核心类

    this变量 在方法内部,可以使用一个隐含的变量this,它始终指向当前实例.如果没有命名冲突,可以省略this. 但是,如果有局部变量和字段重名,那么局部变量优先级更高,就必须加上this. 构造方 ...

  9. appium 无法通过工具定位webview页面元素的问题

    app里面页面有原生和webview的,或者H5的 1.手机百度搜索结果页面 手机百度,点击搜索输入框,输入关键字点击搜索,出来的搜索结果页面,无法通过UI automator viewer来定位元素 ...

  10. PHP扩展安装之phpize

    phpize命令是准备php扩展安装的编译环境的.用于手动编译安装php扩展. 一般使用pecl来安装php扩展. 如果pecl没法安装,比如在防火墙后面,或要安装的扩展在pecl还没有兼容包.则使用 ...