數學中有各式各樣富含詩意的曲線,螺旋線就是其中比較特別的一類,螺旋線這個名詞來源于希臘文,它的原意是“旋卷”或“纏卷”,例如,平面螺旋線便是以一個固定點開始向外逐圈旋繞而形成的曲線,
阿基米德螺線和黃金螺旋線就是典型的螺旋線,下面我們探討一種典型的螺旋線:圓內螺線,
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 onl oad="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 onl oad="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 onl oad="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 onl oad="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時的螺旋線
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/14226.html
標籤:其他
