参考博客:c++分形树绘制
js 利用canvas绘制直线、曲线
1、算法描述
假设A点坐标为(x,y),B点坐标为(x0,y0),C点坐标为(x1,y1),D点坐标为(x2,y2),α为主干和枝干的夹角(父枝干和子枝干的夹角),angle为当前要描绘的树干与x轴正方形的夹角(注意angle与α的关系),L为主干的长度。
初始状态下,angle=π/2
。
实现的算法步骤:
1、画出主干AB,即线段(x,y)-(x0,y0)。
2、计算出D点的坐标,由于屏幕坐标系x正方向为水平向右,y正方向为水平向下,因此
x2 = x0 + 2/3L * cos(angle-α)
, y2 = y0 - 2/3L * sin(angle-α)
(注意是减号)。
3、计算出C点的坐标, x1 = x0 - 2/3L * cos(angle+α)
, y1 = y0 - 2/3L * sin(angle+α)
。
4、将D点替换B点,B点替换A点,重复步骤1,画出枝干BD(也即新的“AB”)
5、将C点替换B点,B点替换A点,重复步骤1,画出枝干BC(也即新的“AB”)
6、重新计算枝干长度(应为L乘以一个小于1的系数),这里举例2/3,
则将L设为2/3L,angle分别设为angle+α和angle-α,重复步骤2-6,画出以BC和BD为父枝干的子枝干,直至递归终止条件满足(L小于某个值)
2、代码部分
//html
<html>
<head>
<meta charset="utf-8">
<title>分形树</title>
</head>
<body onload='init()'>
<canvas id="canvas" style="background-color: black;">
</body>
</html>
//js
var canvas, context;
//主干与枝干的夹角
var arg = Math.PI / 15;
function drawTree(px, py, ang, scale, len) {
//引入偏移随机角度,改变一下形状
var rn = Math.random()*10 * (Math.PI / 180);
var x = Math.floor(scale*len*Math.cos(ang));
var y = Math.floor(scale*len*Math.sin(ang));
//设置线条颜色
context.strokeStyle = 'white';
// 设置线条的宽度
context.lineWidth = 1;
// 绘制直线
context.beginPath();
// 起点
context.moveTo(px, py);
// 终点
context.lineTo(px+x, py-y);
context.closePath();
context.stroke();
//终止递归
if (scale*len<20)
return;
//递归画出左右分枝
drawTree(px + x, py - y, ang - arg + rn, scale, scale*len);
drawTree(px + x, py - y, ang + arg + rn, scale, scale*len);
}
function init() {
canvas = document.getElementById('canvas');
canvas.width = 1000;
canvas.height = 400;
// 拿到上下文
context = canvas.getContext('2d');
// 画分形树
drawTree(300,300,Math.PI/2,0.82,75);
}