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...