そういえば書いたことなかったのでやってみた。
概念
- 何度再帰するか決める(depth)
- 座標を指定する(x1, y1)
- 方向を指定する(θ)
- x1, y1から、その方向に線を引く(x2, y2)
- 再帰回数が残っていれば、引いた先(x2, y2) から、任意の角rとして θ-r, θ+r方向へ線を引く
コード
注意: 伸ばす長さ、角度に乱数が入っている
{sin, cos, PI} = Math
drawLine = (ctx, p1, p2) ->
ctx.beginPath();
ctx.strokeStyle = 'gray'
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.stroke();
drawTree = (
ctx # canvas context
x1, y1 # position
len # length of node
stand # current dir
depth # recursion count
) ->
rl = Math.abs(0.5 - Math.random()) * len
x2 = x1 + rl * cos(stand)
y2 = y1 + rl * sin(stand)
drawLine(ctx, {x: x1, y: y1}, {x: x2, y: y2})
if depth > 0
diffdir = Math.random() * PI / 6
drawTree(ctx, x2, y2, len, stand + diffdir, depth-1)
drawTree(ctx, x2, y2, len, stand - diffdir, depth-1)
window.addEventListener 'load', ->
canvas = document.createElement 'canvas'
canvas.width=800
canvas.height=600
document.body.appendChild(canvas)
ctx = canvas.getContext('2d')
for x in [1..30]
drawTree(ctx, 600*Math.random(), 400*Math.random(), 20, -PI/2, 8)