JavaScript图形实例:Koch曲线
Koch曲线的构造过程是:取一条长度为L0的直线段,将其三等分,保留两端的线段,将中间的一段改换成夹角为60度的两个等长直线;再将长度为L0/3的4个直线段分别进行三等分,并将它们中间的一段均改换成夹角为60度的两段长为L0/9的直线段;重复以上操作直至无穷,可得以一条具有自相似结构的折线,如图1所示。

图1 Koch曲线的生成
Koch曲线采用递归过程易于实现,编写如下的HTML代码。
<!DOCTYPE html>
<head>
<title>Koch曲线</title>
</head>
<body>
<canvas id="myCanvas" width="600" height="400" style="border:3px double #996633;">
</canvas>
<script type="text/javascript">
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var maxdepth =5;
var curdepth = 0;
ctx.lineWidth = 2;
Koch({x:50,y:150},{x:550,y:150},Math.PI/3);
function Koch(p1,p2,angle)
{
curdepth++;
if (curdepth<=maxdepth)
{
var x1=(2*p1.x+p2.x)/3;
var y1=(2*p1.y+p2.y)/3;
var x3=(2*p2.x+p1.x)/3;
var y3=(2*p2.y+p1.y)/3;
var x2=(x3-x1)*Math.cos(angle)-(y3-y1)*Math.sin(angle)+x1;
var y2=(x3-x1)*Math.sin(angle)+(y3-y1)*Math.cos(angle)+y1;
Koch(p1,{x:x1,y:y1},Math.PI/3);
Koch({x:x1,y:y1},{x:x2,y:y2},Math.PI/3);
Koch({x:x2,y:y2},{x:x3,y:y3},Math.PI/3);
Koch({x:x3,y:y3},p2,Math.PI/3);
}
if (curdepth>maxdepth)
draw([p1,{x:x1,y:y1},{x:x2,y:y2},{x:x3,y:y3},p2]);
curdepth--;
}
function draw(points)
{
ctx.strokeStyle = "red";
ctx.beginPath()
ctx.moveTo(points[0].x,points[0].y)
for(i=1;i<points.length;i++)
{
ctx.lineTo(points[i].x,points[i].y);
}
ctx.closePath()
ctx.stroke()
}
</script>
</body>
</html>
在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中绘制出的Koch曲线,如图2所示。

图2 递归深度maxdepth =5的Koch曲线
由图1和2可知,Koch曲线的初始图元是直线,但最终结果却是一条参差不齐的曲线,很像雪花的边缘,如果将3条这样的曲线围在一起,便得到Koch雪花的图案。这样,初始图元不是一条直线,而是一个等边三角形。Koch雪花的生成示例如图3所示。

图3 Koch雪花的生成
在程序设计时,定义好等边三角形的三个顶点坐标,调用三次Koch递归过程,以实现等边三角形三条边各自的Koch曲线生成,即可得到Koch雪花图案。编写的HTML文件如下。
<!DOCTYPE html>
<head>
<title>Koch雪花</title>
</head>
<body>
<canvas id="myCanvas" width="600" height="600" style="border:3px double #996633;">
</canvas>
<script type="text/javascript">
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var maxdepth =5;
var curdepth = 0;
ctx.lineWidth = 2;
Koch({x:50,y:450},{x:500,y:450},Math.PI/3);
Koch({x:275,y:450-225*Math.sqrt(3)},{x:50,y:450},Math.PI/3);
Koch({x:500,y:450},{x:275,y:450-225*Math.sqrt(3)},Math.PI/3);
function Koch(p1,p2,angle)
{
curdepth++;
if (curdepth<=maxdepth)
{
var x1=(2*p1.x+p2.x)/3;
var y1=(2*p1.y+p2.y)/3;
var x3=(2*p2.x+p1.x)/3;
var y3=(2*p2.y+p1.y)/3;
var x2=(x3-x1)*Math.cos(angle)-(y3-y1)*Math.sin(angle)+x1;
var y2=(x3-x1)*Math.sin(angle)+(y3-y1)*Math.cos(angle)+y1;
Koch(p1,{x:x1,y:y1},Math.PI/3);
Koch({x:x1,y:y1},{x:x2,y:y2},Math.PI/3);
Koch({x:x2,y:y2},{x:x3,y:y3},Math.PI/3);
Koch({x:x3,y:y3},p2,Math.PI/3);
}
if (curdepth>maxdepth)
draw([p1,{x:x1,y:y1},{x:x2,y:y2},{x:x3,y:y3},p2]);
curdepth--;
}
function draw(points)
{
ctx.strokeStyle = "red";
ctx.beginPath()
ctx.moveTo(points[0].x,points[0].y)
for(i=1;i<points.length;i++)
{
ctx.lineTo(points[i].x,points[i].y);
}
ctx.closePath()
ctx.stroke()
}
</script>
</body>
</html>
在浏览器中打开包含这段HTML代码的html文件,在浏览器窗口中可能会绘制出如图4所示的Koch雪花图案。

图4 递归深度maxdepth =5的Koch雪花图案
JavaScript图形实例:Koch曲线的更多相关文章
- JavaScript图形实例:线段构图
在“JavaScript图形实例:四瓣花型图案”和“JavaScript图形实例:蝴蝶结图案”中,我们绘制图形时,主要采用的方法是先根据给定的曲线参数方程计算出两点坐标,然后将两点用线段连接起来,线段 ...
- JavaScript动画实例:曲线的绘制
在“JavaScript图形实例:曲线方程”一文中,我们给出了15个曲线方程绘制图形的实例.这些曲线都是根据其曲线方程,在[0,2π]区间取一系列角度值,根据给定角度值计算对应的各点坐标,然后在计算出 ...
- JavaScript图形实例:再谈IFS生成图形
在“JavaScript图形实例:迭代函数系统生成图形”一文中,我们介绍了采用迭代函数系统(Iterated Function System,IFS)创建分形图案的一些实例.在该文中,仿射变换函数W的 ...
- JavaScript图形实例:随机SierPinski三角形
在“JavaScript图形实例:SierPinski三角形”中,我们介绍了SierPinski三角形的基本绘制方法,在“JavaScript图形实例:迭代函数系统生成图形”一文中,介绍了采用IFS方 ...
- JavaScript图形实例:Hilbert曲线
德国数学家David Hilbert在1891年构造了一种曲线,首先把一个正方形等分成四个小正方形,依次从西北角的正方形中心出发往南到西南正方形中心,再往东到东南角的正方形中心,再往北到东北角正方形中 ...
- JavaScript图形实例:四瓣花型图案
设有坐标计算公式如下: X=L*(1+SIN(4α))*COS(α) Y=L*(1+SIN(4α))*SIN(α) 用循环依次取α值为0~2π,计算出X和Y,在canvas画布中对坐标位置(X,Y)描 ...
- JavaScript图形实例:图形的旋转变换
旋转变换:图形上的各点绕一固定点沿圆周路径作转动称为旋转变换.可用旋转角表示旋转量的大小. 旋转变换通常约定以逆时针方向为正方向.最简单的旋转变换是以坐标原点(0,0)为旋转中心,这时,平面上一点P( ...
- JavaScript图形实例:圆内螺线
数学中有各式各样富含诗意的曲线,螺旋线就是其中比较特别的一类.螺旋线这个名词来源于希腊文,它的原意是“旋卷”或“缠卷”.例如,平面螺旋线便是以一个固定点开始向外逐圈旋绕而形成的曲线. 阿基米德螺线和黄 ...
- JavaScript图形实例:正多边形
圆心位于坐标原点,半径为R的圆的参数方程为 X=R*COS(θ) Y=R*SIN(θ) 在圆上取N个等分点,将这N个点首尾连接N条边,可以得到一个正N边形. 1.正多边形阵列 构造一个8行8列的正N( ...
随机推荐
- Winform最基础的DBHelper类
PS:我已经忘记了n遍了 class DBHelper { //连接数据库 public static string connstring = @"Data Source=DESKTOP-8 ...
- 数据的存储结构浅析LSM-Tree和B-tree
目录 顺序存储与哈希索引 SSTable和LSM tree B-Tree 存储结构的比对 小结 本篇主要讨论的是不同存储结构(主要是LSM-tree和B-tree),它们应对的不同场景,所采用的底层存 ...
- 我们为什么要用hibernate
1.hibernate对JDBC访问数据库的代码做了一个封装,简化了数据访问繁琐的代码. 2.hibernate的性能非常好,因为它是个轻量级框架.映射的灵活性很好,它支持各种关系型数据库,从一对一到 ...
- Java学习之IO流及网络编程
一.字节 1.1字节输入流(java.io.InputStream) 此抽象类是表示字节输入流的所有类的超类 1.1.1定义了所有子类共性的方法: int read() 从输入流中读取数据的下 ...
- ecshop php商城系统数据库结构及表的介绍分析
ecshop共86张表,确实比较多,不过功能确实最完善的. 表结构分析 ecs_account_log // 用户账目日志表 ecs_activity // 活动表(代码,名称,开始,结束,描述) ...
- <WP8开发学习笔记>修改panorama全景控件的标题的大小
panorama(全景)控件非常具有WinPhone特色,但是那个巨大的标题许多时候会让人觉得违和.怎么修改它呢? 最开始想到的是加一个FontSize,结果毫无影响.╮(╯-╰)╭ <phon ...
- Codeforces Round #561 (Div. 2) A Tale of Two Lands 【二分】
A Tale of Two Lands 题目链接(点击) The legend of the foundation of Vectorland talks of two integers xx and ...
- TensorFlow从0到1之TensorFlow实现单层感知机(20)
简单感知机是一个单层神经网络.它使用阈值激活函数,正如 Marvin Minsky 在论文中所证明的,它只能解决线性可分的问题.虽然这限制了单层感知机只能应用于线性可分问题,但它具有学习能力已经很好了 ...
- c常用函数-strchr和strrchr
strchr和strrchr strrchr函数用于查找指定字符在一个字符串中最后一次出现的位置,然后返回指向该位置的指针 strchr函数用于查找指定字符在一个字符串中第一次出现的位置,然后返回指向 ...
- Android使用OkHttp实现登录注册功能
客户端 在客户端,这里将登录和注册放在了同一个界面,在账号和密码两个EditText中输入内容后,按下LOGIN按钮,进行登录:按下REGISTER按钮,进行注册. 在写代码之前,先添加OkHttp的 ...