65.9K
CodeProject 正在变化。 阅读更多。
Home

与螺旋共舞。

starIconstarIconstarIconstarIconstarIcon

5.00/5 (15投票s)

2017年11月3日

CPOL

12分钟阅读

viewsIcon

21865

downloadIcon

420

了解并使用纯JavaScript生成和绘制螺旋的技术。提供演示不同类型螺旋的网页。

引言

螺旋是几个世纪以来一直为人所知的令人惊叹的图像。它们无处不在,可以在自然界(从贝壳和植物到星系)、艺术和机械(从微小的腕表到大型卡车和火车)等领域找到。

这是维基百科 [1] 的一个简单定义

“在数学中,螺旋是一种从一个点发散的曲线,当它围绕该点旋转时,离该点越来越远。”


这是来自Rosetta Code Wiki (RC) [2] 的另一个便捷定义

“多螺旋是一种由多个线段组成的螺旋,其中每条线段比前一条线段大(或小)给定的量。每条线段也以给定的角度改变方向。”

应该强调的是,有大量的螺旋示例,包括JavaScript在内的多种语言。只需在互联网上搜索您感兴趣的特定类型的螺旋。

一些最重要二维螺旋类型包括:阿基米德螺旋 [1]、多螺旋 [2] 和沃格尔螺旋 [3,4]。但这取决于研究者的看法,即什么最重要?我们在这里不进行任何研究,我们只是练习与螺旋“共舞”。偶尔,会提到或强调一些属性,以便更好地理解。

本文的目的是证明,即使是编程新手也可以开始用JavaScript绘制螺旋。

由于本文的目标读者是初学者,因此主要使用非常简单易懂的代码块(如下面用于阿基米德螺旋的代码)。例外情况稍后会清楚标明。

该项目为初学者或中级开发人员提供了一套项目组件,作为生成无限数量简单(非花哨)螺旋的桌面生成器。所有 3 种重要的螺旋类型(上面提到)都涵盖在内。

开发人员应通过阅读项目文件的源代码来获得自学。只将简要讨论一些主要片段,因为只使用了非常简单的数学和简单、简短、清晰的函数。因此,通过示例学习绘制螺旋。

任何用户都可以将此项目软件用作桌面应用程序。只需下载并开始使用。

只有 3 个 HTML 页面和 1 个 JavaScript 文件构成了您开始与螺旋“共舞”所需的整个紧凑源代码。任何拥有计算机的人都已经拥有一个可靠的工具可以做到这一点:浏览器,而它唯一的要求是支持“canvas”对象。

生成和绘制螺旋的常用技术

任何生成螺旋的函数都具有典型结构,这反映了使用极坐标系 [5] 更适合描述任何螺旋的事实。因此,在极坐标系中,大多数螺旋(和其他图形)具有如下的唯一方程/函数:r = f(theta),其中半径r是角度theta的单调连续函数。

极坐标rtheta可以转换为笛卡尔坐标x和y如下 [5]:x=r*cos(theta)y=r*sin(theta)。注意:在下面的片段中,t用于代替theta

备注

  • 典型的极螺旋函数的两个主要来源是 [1,6]。有时,来自不同来源的相同命名的绘制螺旋可能看起来不同。更不用说当应用一个或两个附加系数或函数时。
  • 此外,还发现了一些独特的函数,并且它们都被引用了。
  • 是的!我在互联网上找到了所有函数,但在几乎所有情况下,它们都被简化和统一(有时是重构)以适应上面所示的典型函数。

 

下面的 JavaScript 片段展示了如何使用线生成和绘制阿基米德螺旋。注意:为了清晰起见,在阿基米德螺旋函数开头附加了设置全局变量的代码片段。

  // GLOBAL VARS
  var cvs, ctx, cw, c; // canvas, context, canvas width and center
  var clr; //color
  var pm, st, it, n, a, b; // init pars: pm - plot mode, st - spiral type,
                           // it - init angle, n - dots, a,b - coefficients.
  var r, t, x, y;          // radius, theta angle, coordinates.
  var pi=Math.PI, pi2=pi*2, pi3=pi/360, snm, h3;
  // ******************************************
  // *** The Archimedean Spiral #1 c-w (clockwise) ***
  function pspArchi1() {
    snm="The Archimedean Spiral #1"; console.log(snm); h3.innerText=snm;
    if (pm=="d") {it=pi3; n=6000; a=2; b=5; c=320;}
    console.log("PARs:", it, "/", n, "/", a, "/", b, "/", c);
    ctx.beginPath(); // creating Path for lines
    for(var i=0; i<n; i++) {
      t=it*i; r=a+b*t;  // calculating theta and radius, and coodinates (below)
      x = r*Math.cos(t) + c; y = r*Math.sin(t) + c; // calculating x and y
      //if (i<5) {console.log("t,r,x,y:", t, "/",  r, "/",x, "/", y)} // 4 test
      //if (i>n-5) {console.log("t,r,x,y:", t, "/",  r, "/", x, "/", y)}
      ctx.lineTo(x, y); // saving line in the Path
    }//fend i
    ctx.stroke(); // plotting saved in the Path lines
  }//func end

 

 

正如您所见,该函数相当简单,只有 12 行代码。

这是给您初学者的第一个非常简单的练习

练习#1。创建 HTML 页面,仅生成和绘制“阿基米德螺旋 #1”。
您需要将上面显示的 JavaScript 片段包装在 HTML 标签(之前和之后)中。此外,为所有未赋值的变量添加默认值。例如,clr="navy"; pm="d" 等。


如果您不是完全的初学者,这应该花费您不到 10 分钟。如果超过,那也没关系。继续练习。这种简单的页面(仅用于一个图形)是测试新图形的好工具。

让我们回到螺旋。

只有 3 个要素定义了螺旋的独特图像和类型

  • 两个基本系数:it - 初始 theta 角和n - 点/线的数量。它们定义了螺旋的图像和大小。
  • 唯一的极函数:r=f(t)。此函数可以使用附加系数定义,例如a, b, c等。此外,还可以在此函数中使用其他函数。极函数定义了螺旋的类型(意味着:主要是典型的图像)。

 

在某些情况下,这两个基本系数不会改变螺旋的类型,但在其他情况下,螺旋可能会转化为另一种类型,甚至退化为单行。您在测试时会发现这一点。

备注

  • 这类带有类似循环的函数被大量使用。但在许多情况下,您需要即兴发挥,尤其是当螺旋具有 2 个对称分支时。例如,欧拉、费马等。因此,公式和循环不同,或者它们被固定、简化等。
  • 下表 1 中省略了许多重要细节。请参阅页面代码了解它们。
  • 欢迎您随意使用项目中任何页面的代码,但请记住要存档副本。

 

下表 1 包含前 17 个螺旋几乎所有的使用公式。注意:i) 已删除前缀“Math.”。ii) “Reg.”标记正则函数;“Diff.”标记独特函数。iii) 在“螺旋生成器”页面中找到螺旋“Super 2”的代码。
 

表 1. 螺旋和公式
螺旋 线 1 线 2 注释
阿基米德 1 t=it*i; r=a+b*t; x=r*cos(t)+c; y=r*sin(t)+c; 正则
阿基米德 2 t=it*i; r=a+b*t; y=r*cos(t)+c; x=r*sin(t)+c; 正则
欧拉 t+=dt; //dt=it/n; x+=cos(t*t)*dt; y+=sin(t*t)*dt; 独特
费马 t=it*i; r=a*sqrt(t); x=r*cos(t)+c; y=r*sin(t)+c; 2 部分
双曲线 t=it*i; r=a/t; x=r*cos(t)+c; y=r*sin(t)+c; 正则
法螺 t=it*i; r=sqrt(a/t); x=r*cos(t)+c; y=r*sin(t)+c; 正则
对数 t=it*i*10; r=a*(exp(b*t)); x=r*cos(t)+c; y=r*sin(t)+c; 正则
西奥多鲁斯 t=it*i; r=sqrt(i); x=sc*r*cos(t)+c; y=sc*r*sin(t)+c; 独特
斐波那契 t=it*i; r=(pow(gm,i)-pow(gn,i))/sq5; x=a*r*cos(t)+c; y=a*r*sin(t)+c; 独特
渐开线 t=it*i; r=a; x=r*(cos(t)+t*sin(t))+c; y=r*(sin(t)-t*cos(t))+c; 独特
超级 t=it*i; r=c*sqrt(i/n); x=r*cos(t)+c; y=r*sin(t)+c; 正则
原子 t=it*i*10; r=t/(t-a); x=sc*r*cos(t)+c; y=sc*r*sin(t) + c; 正则
阿策马 t=i; x=sin(t)/t-2*cos(t)-t*sin(t)+c; y=-cos(t)/t-2*sin(t)+t*cos(t)+c; 独特
沃格尔 t=it*i; r=sqrt(i)/sqrt(n); x=sc*r*cos(t)+c; y=sc*r*sin(t)+ c; 独特
蜗杆线 t=it*i*10; r=sin(t)/t; x=sc*r*cos(t)+c; y=sc*r*sin(t)+c; 正则
萨克斯 sqi=sqrt(i) x=a*-cos(sqi*pi2)*sqi+c; y=a*sin(sqi*pi2)*sqi+c; 独特

此表可以即时查看螺旋代码主要部分之间的差异。

使用页面

使用“螺旋生成器”页面

 

建议从“螺旋生成器”页面开始,这是我们“共舞”的主要部分,也具有教育意义。您可以尝试不同的螺旋类型、颜色和其他参数,或者仅使用默认参数遍历所有类型。

注意:默认参数已选择以适合画布,并显示特定螺旋最典型的图像。强烈建议从默认值开始。

  图 4:“螺旋生成器”页面的两种模式(部分显示) 

SG (default values)     SG (input values)

在此页面的下拉列表中,前 9 个螺旋是众所周知的 [1],而其他螺旋则“发现”于 [6] 和其他来源 [7-11]。

请自己看:极螺旋家族在下面的图中。每张图都绘制了 8 个螺旋,使用来自 [1] 的极函数。

  图 1:前 8 个螺旋来自 [1]:阿基米德、欧拉、费马、双曲线、法螺、对数、西奥多鲁斯和斐波那契。 

The Archimedean spiral #1 The Euler spiral The Fermat spiral The Hyperbolic spiral

The Lituus spiral The Logarithmic spiral The Theodorus spiral The Fibonacci spiral

提示:右键单击任何螺旋,即可将其保存为原始 640x640 大小的图像。选择“png”类型以匹配原始类型。

 

  图 2:渐开线、超级、变化、原子、阿策马、沃格尔、蜗杆线、萨克斯和超级 2 螺旋。 

 

The Involute of a circle spiral The Super spiral The Atomic spiral The Atzema spiral

The Vogel spiral The Cochleoid spiral The Sacks spiral The Super 2 spiral

上图 2 中的渐开线螺旋来自 [1]。其他大部分来自 [6],沃格尔 [3,4] 和萨克斯 [11] 螺旋除外。

第二、第四、第七和第八个螺旋实际上是多螺旋,但这将在稍后简要讨论。

第五个螺旋通常被称为“向日葵种子/花朵”螺旋。它有许多可见的顺时针和逆时针螺旋臂。

这是给您初学者的第二个相当简单的练习

练习#2。修改之前创建的页面:i) 查找“大圆点”函数(在源文件中)并将其添加到脚本中;ii) 更改绘图线函数以使用添加的函数;iii) 调整“it”、“n”等参数,以绘制一个漂亮的大圆点阿基米德螺旋。

使用“多螺旋家族生成器”页面

 

“多螺旋家族生成器”页面非常简单。它允许用户选择以下参数:颜色、方向、比例、点数和范围。最后 3 个参数控制绘制的多螺旋的大小。此外,“范围”充当样式更改参数。

下面显示的 JavaScript 片段演示了如何使用线条生成和绘制多螺旋。

  // rng - range, sc - scale, cc - canvas center
  var it=Math.PI*rng/cc, t, x, y; // it - init theta, t - theta.
  for(var i=0; i<n; i++) {
    t=it*i;
    x = sc*t*Math.cos(d*t)+cc; y = sc*t*Math.sin(d*t)+cc;
    ctx.lineTo(x, y);
  }//fend i

注意:这里没有计算r!角度t的公式相同,但it不同。此外,对于坐标x,y使用了略有不同的公式。请参阅Rosetta Code Wiki [2] 上的 gnuplot 和 JavaScript 版本

此页面是研究一般螺旋和多螺旋的良好工具。但同样,任何研究或应用都不是本文的目标。

真正有趣的是:仅更改参数“范围”,用户就可以绘制出各种令人惊叹的螺旋!数千种外观不同的螺旋。

下图 3 展示了具有三角形、正方形、五边形和星形图案的 4 个多螺旋。

  图 3:具有三角形、正方形、五边形和星形图案的多螺旋, 

Polyspiral (triangular pattern) Polyspiral (square pattern) Polyspiral (pentagon pattern) Polyspiral (star pattern)

您是否注意到图 2 中的超级螺旋看起来与图 3 中的第二个螺旋相同?它们都是多螺旋,尽管使用了不同的公式。但我们这里不讨论这个问题。只需注意一种螺旋类型可以通过某些独特的系数组合转化为另一种类型 [4]。

我们在那里与螺旋共舞,但反过来,多螺旋向我们展示了它们自己的滑动舞步(见上图 3)

  • 有时它们是直线带转弯:“方块舞”、“星星舞”等。
  • 或者有时它们从左到右(反之亦然)移动,留下较短的舞步线段(上面的五边形图案)。
  • 或者有时它们从左到右(反之亦然)跳跃,覆盖其他舞步线段(上面的三角形图案)。

 

还没说服?要查看许多不同的“舞步”,您需要测试此页面。使用下表 2 中提供的示例,其中仅包含选定的/测试的螺旋参数。尝试其中至少一些会很有趣,而且不仅仅是初学者。

表 2. 测试样本
Scale 范围(s) 注释
2 100 80 8 边形图案
2 100 160,480,800,1120 正方形图案
2 100 210,430,850,1070 三角形图案
2 100 240 星形图案 (sc=1.2)
2 100 280,300, 310 星形图案 (sc=1.2)
2 100 320,640,960 一条直线
2 100 330--400,880--950,970--1060,1080--1110 星形图案 (sc=1.2)
0.4 100 770 五边形图案

使用“乌拉姆螺旋”页面

乌拉姆螺旋被包含进来,作为稍微复杂一些的螺旋的示例。此外,它已经在 PARY/GP 和 R [12] 中经过多次测试。

这是这里唯一需要不同生成和绘图技术的螺旋。您可以在包含的 VOE.js (v.2.0.) 中找到绘图辅助函数。

在此页面上,用户可以选择 3 种绘图/打印样式之一(使用默认的 n 和 sc 值)

  • 绘图(n=100;sc=3)。
  • 使用星号绘图和打印(n=10;sc=5)。
  • 使用数字绘图和打印(n=10;sc=5)。

 

注意:在控制台(Chrome)中查找“打印”的螺旋。

下面展示了使用星号和数字“打印”的乌拉姆螺旋样本。

 |                    |	 |                               |
 |           *   *    |	 |                61    59       |
 |     *           *  |	 |       37                31    |
 |   *   *       *    |	 |    67    17          13       |
 |         *   *   *  |	 |              5     3    29    |
 |       *     * *   *|	 |          19        2 11    53 |
 |     *   *          |	 |       41     7                |
 |   *       *        |	 |    71          23             |
 |     *       *      |	 |       43          47          |
 |   *           *    |	 |    73                79       |

 

结论

 

即使您现在是初学者,您也已经有了几十个绘制不同螺旋的极函数。我建议您进行以下练习

练习#3。尝试“发明”您自己的螺旋(也许是新的,前所未见的)。您需要创建一个真正的新的函数r = f(theta)等。一切都在开头描述。此外,您已经有了一个简单的页面来实现它。(我希望如此……)

不要作弊,即不要使用 [6] 或其他来源。我要求您“发明”自己的螺旋,这并不难。还记得您已经修改过的阿基米德螺旋吗?它只有 12 行脚本代码,但您只需要更改 2 行!

理论和实践用途可以在网上找到。目标是证明绘制二维螺旋并没有什么困难或神奇之处。此外,还将展示一些处理 HTML 页面选项、使用 canvas、使用点、大点和线绘制螺旋、利用辅助函数等简单方法。

再次强调,有大量的螺旋样本,包括 JavaScript [2,7,12] 在内的多种语言。

最后,我希望即使是初学者也能成为设计师、发明家和令人惊叹的新螺旋的创造者。

参考文献

  1. 螺旋,维基百科,自由的百科全书,网址:https://en.wikipedia.org/wiki/Spiral。
  2. 多螺旋,Rosetta Code Wiki,网址:http://rosettacode.org/wiki/Polyspiral。
  3. Vogel, H (1979)。一种更好的构造向日葵头部的方法。数学生物科学。44 (44):pp. 179-189。doi:10.1016/0025-5564(79)90080-4。
  4. Prusinkiewicz, P.; Lindenmayer, A. (1990)。植物的算法之美。Springer-Verlag。pp. 101-107。ISBN 978-0-387-97297-8。
  5. 极坐标系,维基百科,自由的百科全书,网址:https://en.wikipedia.org/wiki/Polar_coordinate_system。
  6. Wassenaar J. 数学曲线,网址:http://www.2dcurves.com/spiral/spiral.html
  7. 阿基米德螺旋,Rosetta Code Wiki,网址:http://rosettacode.org/wiki/Archimedean_spiral。
  8. 费马螺旋,维基百科,自由的百科全书,网址:https://en.wikipedia.org/wiki/Fermat%27s_spiral。
  9. 超级螺旋,可汗学院,网址:https://www.khanacademy.org/computer-programming/super-spiral/823021393。
  10. 变化螺旋,可汗学院,网址:https://www.khanacademy.org/computer-programming/spiral-of-change/1144297869
  11. 萨克斯螺旋,网址:http://www.dcs.gla.ac.uk/~jhw/spirals/。
  12. 乌拉姆螺旋(用于素数),Rosetta Code Wiki,网址:http://rosettacode.org/wiki/Ulam_spiral_(for_primes)。
© . All rights reserved.