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

在“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三角形

(0)

相关推荐

  • JavaScript动画实例:烟花绽放迎新年

    先编写一个烟花绽放的动画效果. 放烟花时,一个烟花可分为两个阶段:(1)烟花上升到空中:(2)烟花炸开成碎片,炸开的碎片慢慢消散. 为此抽象出两个对象类:Firework和Particle.其中,Fi ...

  • JavaScript小游戏实例:简单的键盘练习

    键盘是一种常用的输入设备,灵活熟练地使用键盘进行输入是计算机用户需掌握的一门基本功.下面我们编写一个简单的键盘练习游戏. 1.刺破气泡交互式小动画 在编写简单的键盘练习游戏之前,先设计一个简单地刺破气 ...

  • JavaScript动画实例:运动的字母特效

    已知圆的坐标方程为: X=R*SIN(θ) Y=R*COS(θ)     (0≤θ≤2π) 给定初始坐标位置(X,Y),按照圆的坐标方程,从角度angle = 0开始,每间隔angleSpeed = ...

  • JavaScript图形实例:SierPinski三角形

    JavaScript图形实例:SierPinski三角形

  • JavaScript图形实例:Canvas API

    JavaScript图形实例:Canvas API

  • JavaScript图形实例:H分形

    H分形是由一个字母H演化出迷宫一样场景的分形图案,其构造过程是:取一个中心点(x,y),以此中心点绘制一条长为L的水平直线和两条长为H的竖直直线,构成一个字母"H"的形状:再以两条 ...

  • JavaScript图形实例:Hilbert曲线

    德国数学家David Hilbert在1891年构造了一种曲线,首先把一个正方形等分成四个小正方形,依次从西北角的正方形中心出发往南到西南正方形中心,再往东到东南角的正方形中心,再往北到东北角正方形中 ...

  • JavaScript图形实例:再谈IFS生成图形

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

  • JavaScript图形实例:Levy曲线及其变形

    Levy曲线是将一条线段不停地分形成两条长度相等且相互垂直的线段而生成的.Levy分形的最后很像一个英文字母C,所以也称它为C曲线. Levy曲线的生成示意如图1所示. 图1  Levy曲线的生成 1 ...

  • JavaScript图形实例:黄金螺旋线

    黄金螺旋线是根据斐波那契数列画出来的螺旋曲线.自然界中存在许多黄金螺旋线的图案,是自然界最完美的经典黄金比例.例如,如图1所示的海螺身上的曲线,图2所示的漩涡,图3所示的人耳. 图1 海螺 图2  漩 ...

  • JavaScript图形实例:窗花图案

    JavaScript图形实例:窗花图案

  • JavaScript图形实例:曲线方程

    在HTML5 Canvas画布中,我们可以根据曲线的方程绘制出曲线.例如,在笛卡尔坐标系中,圆的方程为: x=r*cos(θ) y=r*sin(θ)     (0≤θ≤2π) 编写如下的HTML代码. ...