Subdivision
by soulwire
HTML
<script src="https://raw.github.com/soulwire/sketch.js/master/js/sketch.js"></script>
<script src="http://dat-gui.googlecode.com/git/build/dat.gui.js"></script>
<div id="container"></div>
CoffeeScript
# ----------------------------------------
# Vertex
# ----------------------------------------
class Vertex
constructor: ( @x = 0.0, @y = 0.0 ) ->
# squared distance to another vertex
distanceSq: ( v ) -> (dx = v.x - @x) * dx + (dy = v.y - @y) * dy
# distance to another vertex
distance: ( v ) -> sqrt (dx = v.x - @x) * dx + (dy = v.y - @y) * dy
# radian angle to another vertex
angle: ( v ) -> atan2 v.y - @y, v.x - @x
# linear interpolation between this and another vertex
lerp: ( v, f ) -> new Vertex @x + (v.x - @x) * f, @y + (v.y - @y) * f
# duplicate this vertex
clone: -> new Vertex @x, @y
# ----------------------------------------
# Polygon
# ----------------------------------------
class Polygon
constructor: ( @vertices... ) ->
# assign principal generation
@generation = 0
# subdivides this polygon into 2 and returns both
subdivide: ( randomness = 0.0, opposite = 0.5 ) ->
# current number of sides
nv = @vertices.length
# choose two unique indices
i1 = ~~random nv
i2 = if do random < opposite then ~~(i1 + nv / 2) % nv else ~~random nv
i2 = ~~random nv while i2 is i1
# choose lerp points
l1 = 0.5 + random randomness * -0.5, randomness * 0.5
l2 = 0.5 + random randomness * -0.5, randomness * 0.5
# create new vertices as linear interpolations between adjacent
v1 = @vertices[i1].lerp @vertices[(i1 + 1) % nv], l1
v2 = @vertices[i2].lerp @vertices[(i2 + 1) % nv], l2
# winding iterators
[j1, j2] = [i1, i2]
# first polygon winds clockwise from v1 to v2
p1 = new Polygon v1
p1.vertices.push @vertices[ j1 = (j1 + 1) % nv ] while j1 isnt i2
p1.vertices.push v2
# second polygon winds clockwise from v2 to v1
p2 = new Polygon v2
p2.vertices.push @vertices[ j2 = (j2 + 1) % nv ] while j2 isnt i1
p2.vertices.push...