JavaScript圖形實例:圓內螺線

        數學中有各式各樣富含詩意的曲線,螺旋線就是其中比較特別的一類。螺旋線這個名詞來源於希臘文,它的原意是「旋卷」或「纏卷」。例如,平面螺旋線即是以一個固定點開始向外逐圈旋繞而造成的曲線。javascript

阿基米德螺線和黃金螺旋線就是典型的螺旋線。下面咱們探討一種典型的螺旋線:圓內螺線。html

1.圓內螺線的造成方式

        在固定的大圓中內切一個運動的小圓,在小圓滾動的過程當中,其上一個定點P所造成的軌跡,即爲圓內螺線。點P會隨着兩圓半徑比值的不一樣而出現不一樣軌跡。例如,當小圓半徑等於大圓的四分之一時,造成的軌跡則是星形線,如圖1所示。參見百度百科的詞條「圓內螺線」(https://baike.so.com/doc/388206-411038.html)。java

 

圖1  圓內螺線的造成示意圖canvas

圓內螺線的笛卡爾座標參數方程爲:瀏覽器

x=cosθ+[cos(nθ)]/n3d

y=sinθ-[sin(nθ)]/n      (0≤θ≤2π, n爲大圓半徑與小圓半徑的比值)rest

編寫以下的HTML代碼。htm

<!DOCTYPE html>blog

<head>ip

<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時的螺旋線 

相關文章
相關標籤/搜索