在“JavaScript图形实例:SierPinski三角形”中,我们介绍了SierPinski三角形的基本绘制方法,在“JavaScript图形实例:迭代函数系统生成图形”一文中,介绍了采用IFS方法生成SierPinski三角形的方法。下面再介绍两种SierPinski三角形的构造方法,以扩展知识面。 1.随机点法采用随机点的方法可以得到SierPinski三角形。具体过程为: (1)任意取平面上三点A、B、C,组成一个三角形,并任意取三角形ABC内的一点P; (2)求出P和A、B、C三个顶点中任意一个顶点的中点P1; (3)描出该中点P1; (4)将P1作为新的P点,转步骤(2),直到描出的点数达到规定要求(如10000个点)。 按上述思想,编写如下的HTML文件。在编程时,为简单计,不保证初始的P点一定在三角形ABC内(有可能在三角形外会描出几个散点,但不影响最后结果),也没有判断A、B、C三点可能共线的情况(此时无法构成三角形)。有兴趣的读者可以自行处理这两种情况,以完善代码。 <!DOCTYPE html> <head> <title>随机SierPinski三角形</title> </head> <body> <canvas id="myCanvas" width="300" height="300" style="border:3px double #996633;"> </canvas> <script type="text/javascript"> var canvas=document.getElementById('myCanvas'); var ctx=canvas.getContext('2d'); function draw() { ctx.fillStyle="#EEEEFF"; ctx.fillRect(0,0,300,300); ctx.fillStyle="red"; ctx.font="32px"; var ax=Math.floor(Math.random()*200+50); var ay=Math.floor(Math.random()*200+50); var bx=Math.floor(Math.random()*200+50); var by=Math.floor(Math.random()*200+50); var cx=Math.floor(Math.random()*200+50); var cy=Math.floor(Math.random()*200+50); var px=Math.floor(Math.random()*200+50); var py=Math.floor(Math.random()*200+50); var dx=0; var dy=0; for (i=0; i<10000; i++) { index =Math.floor(Math.random()*3+1); if (index==1) { dx = (ax + px)/2; dy = (ay + py)/2; } else if (index == 2) { dx = (bx + px)/2; dy = (by + py)/2; } else { dx = (cx + px)/2; dy = (cy + py)/2; } ctx.fillText('.',dx,dy); px = dx; py = dy; } } draw(); </script> </body> </html> 在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中绘制出一个SierPinski三角形,如图1所示。 图1 SierPinski三角形 将程序中的调用语句“draw()”改写为“window.setInterval('draw()', 1500);”,则在浏览器窗口中会每隔1.5秒绘制一个随机SierPinski三角形,如图2所示。 图2 每隔1.5秒绘制一个随机SierPinski三角形 由图2可以看出,有些三角形太小,甚至有些成一条直线,因此,可以改写上面的程序,要求随机取点A、B、C时,保证三个边长均大于100,且三点不共线。改写的HTML文件内容如下。 <!DOCTYPE html> <head> <title>随机SierPinski三角形</title> </head> <body> <canvas id="myCanvas" width="300" height="300" style="border:3px double #996633;"> </canvas> <script type="text/javascript"> var canvas=document.getElementById('myCanvas'); var ctx=canvas.getContext('2d'); function draw() { ctx.fillStyle="#EEEEFF"; ctx.fillRect(0,0,300,300); ctx.fillStyle="red"; ctx.font="32px"; while (1) { var ax=Math.floor(Math.random()*200+50); var ay=Math.floor(Math.random()*200+50); var bx=Math.floor(Math.random()*200+50); var by=Math.floor(Math.random()*200+50); var cx=Math.floor(Math.random()*200+50); var cy=Math.floor(Math.random()*200+50); ab=Math.sqrt((bx-ax)*(bx-ax)+(by-ay)*(by-ay)); ac=Math.sqrt((cx-ax)*(cx-ax)+(cy-ay)*(cy-ay)); bc=Math.sqrt((cx-bx)*(cx-bx)+(cy-by)*(cy-by)); if (ab<100 || ac<100 || bc<100) continue; if (ab+bc==ac || ab+ac==bc || ac+bc==ab) continue; var px=Math.floor(Math.random()*200+50); var py=Math.floor(Math.random()*200+50); break; } var dx=0; var dy=0; for (i=0; i<10000; i++) { index =Math.floor(Math.random()*3+1); if (index==1) { dx = (ax + px)/2; dy = (ay + py)/2; } else if (index == 2) { dx = (bx + px)/2; dy = (by + py)/2; } else { dx = (cx + px)/2; dy = (cy + py)/2; } ctx.fillText('.',dx,dy); px = dx; py = dy; } } window.setInterval('draw()', 1500); </script> </body> </html> 在浏览器中打开包含这段改写后的HTML代码的html文件,在浏览器窗口中也会每隔1.5秒绘制一个随机SierPinski三角形,如图3所示,此时每个随机SierPinski三角形的最小边长均会超过100,三角形不会显得较小。 图3 每隔1.5秒绘制一个较大的随机SierPinski三角形 上面程序中随机点法构造SierPinski三角形是描点10000个得到的。为展示描点过程,编写如下的HTML文件。 <!DOCTYPE html> <head> <title>随机SierPinski三角形</title> </head> <body> <canvas id="myCanvas" width="400" height="400" style="border:3px double #996633;"> </canvas> <script type="text/javascript"> var canvas=document.getElementById('myCanvas'); var ctx=canvas.getContext('2d'); ctx.fillStyle="#EEEEFF"; ctx.fillRect(0,0,400,400); ctx.fillStyle="red"; ctx.font="32px"; while (1) { var ax=Math.floor(Math.random()*400); var ay=Math.floor(Math.random()*400); var bx=Math.floor(Math.random()*400); var by=Math.floor(Math.random()*400); var cx=Math.floor(Math.random()*400); var cy=Math.floor(Math.random()*400); ab=Math.sqrt((bx-ax)*(bx-ax)+(by-ay)*(by-ay)); ac=Math.sqrt((cx-ax)*(cx-ax)+(cy-ay)*(cy-ay)); bc=Math.sqrt((cx-bx)*(cx-bx)+(cy-by)*(cy-by)); if (ab<200 || ac<200 || bc<200) continue; if (ab+bc==ac || ab+ac==bc || ac+bc==ab) continue; var px=Math.floor(Math.random()*400); var py=Math.floor(Math.random()*400); break; } var i=0; function draw() { index =Math.floor(Math.random()*3+1); if (index==1) { dx = (ax + px)/2; dy = (ay + py)/2; } else if (index == 2) { dx = (bx + px)/2; dy = (by + py)/2; } else { dx = (cx + px)/2; dy = (cy + py)/2; } ctx.fillText('.',dx,dy); px = dx; py = dy; i++; if (i>=10000) { ctx.fillStyle="#EEEEFF"; ctx.fillRect(0,0,400,400); ctx.fillStyle="red"; i=0; } } window.setInterval('draw()',1); </script> </body> </html> 在浏览器中打开包含这段HTML代码的html文件,在浏览器窗口中呈现出一个随机SierPinski三角形的喷出过程,如图4所示。
图4 随机SierPinski三角形的喷出过程 2.按组合数的奇偶性直接描点构造SierPinski三角形设有如下的杨辉三角形,若将杨辉三角形的奇数处画圆点,偶数处留空,则会得到SierPinski三角形。
由于杨辉三角中第i行第j列的数字正是组合数C(i,j)的结果。因此,对杨辉三角形中各行各列数字的讨论转化为对组合数C(n,m)的讨论。 组合数的奇偶性判定方法为: 对于C(n,m),若n&m == m 则C(n,m)为奇数,否则为偶数。 根据这个结论,直接编写如下的HTML文件。 <!DOCTYPE html> <head> <title>按组合数奇偶性构造SierPinski三角形</title> <script type="text/javascript"> function draw(id) { var canvas=document.getElementById(id); if (canvas==null) return false; var ctx=canvas.getContext('2d'); ctx.fillStyle="#EEEEFF"; ctx.fillRect(0,0,300,300); ctx.fillStyle="red"; for (i=0;i<256;i++) { for (j=0;j<=i;j++) if ((i&j)==j) ctx.fillText('.',j+30,i+30); } } </script> </head> <body onload="draw('myCanvas');"> <canvas id="myCanvas" width="300" height="300" style="border:3px double #996633;"> </canvas> </body> </html> 在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中绘制出如图5所示的SierPinski三角形。 图5 SierPinski三角形 |
|