             requestAnimationFrame animate
             @renderer.render @scene, @camera
 
+    addChain: (text) =>
+        chainVis = new ChainVis @scene, @camera, @font, @texture
+        chainVis.start text
+
+    addNetwork: (network) =>
+        colocationVis = new ColocationVis @scene, @camera, @font, @texture
+        colocationVis.start network
+
     setTexture: (@texture) ->
         maxAni = @renderer.getMaxAnisotropy()
 


    CAMERA_PAN_DURATION = 2000 * SPEED_MULTIPLIER
    FADE_DURATION = 3000 * SPEED_MULTIPLIER
    CHAIN_FADE_DELAY = 5000 * SPEED_MULTIPLIER

    CAMERA_Z = -9



        @animateLines root

class ColocationVis extends Main
    constructor: (@scene, @camera, @font, @texture) ->
        console.info "New ColocationVis."

    start: (data) ->
        @_addNetwork data

    _addNetwork: (network) =>
        radius = 700
        rotation = Math.PI / 2.2

        network_object = new THREE.Object3D()
        network_object.scale.multiplyScalar(@scaleText)
        network_object.rotateX rotation
        @scene.add network_object

        root = makeTree network
        root = setNetworkPositions root, radius

        traverse = (node) =>
            return if ! node.position?

            node = @setTextObject(node)
            text_object = node._text_object
            text_object.rotateX -rotation
            network_object.add text_object

            faded_in = @fadeToArray(1, 1000) text_object.children

            if node.children
                faded_in.then =>
                    @panCameraToBBox(text_object)
                .then =>
                    if node.parent?
                        siblings = node.parent.children.filter (child) ->
                            return child._text_object isnt text_object
                        if node.parent.parent
                            siblings = siblings.concat(node.parent.parent)
                        promises = siblings.map (sibling) =>
                            @fadeToArray(0, 1000) sibling._text_object.children
                        return Promise.all promises
                .then ->
                    node.children.forEach traverse

        traverse(root)

    setNetworkPositions = (root, radius) =>
        root.position = new THREE.Vector3()

        radianScale = d3.scale.ordinal()
            .rangePoints [0, 2 * Math.PI]

        traverse = (node) ->
            return if ! node.children?
            offset = if node.parent? then getRadians(node.parent, node) else 0

            circle_nodes = if node.parent?
                [node.parent].concat(node.children)
            else node.children

            radianScale.domain d3.range(circle_nodes.length + 1)

            circle_nodes.forEach (circle_node, index) ->
                radians = radianScale(index) + offset
                pos = new THREE.Vector3(
                    radius * Math.cos(radians) + node.position.x,
                    radius * Math.sin(radians) + node.position.y
                    # 0,
                    # radius * Math.sin(radians) + node.position.z
                )
                if circle_node.position?
                    # check = pos.y.toFixed(3) is circle_node.position.y.toFixed(3)
                    # assert(check)
                else
                    circle_node.position = pos

            if node.children?
                node.children.forEach traverse

        traverse(root)
        return root

    getRadians = (a, b) ->
        dx = a.position.x - b.position.x
        dy = a.position.y - b.position.y
        Math.atan2(dy, dx)

    makeTree = (network) =>
        network = network.map (d) ->
            val: d.word
            children: d.colocations

        _makeTree = (child, parent, index, array) ->
            child.parent = parent

            # Find the index of this child in the parent's children array
            child_index = parent.children
                .map (d) -> d.val
                .indexOf child.val

            # Set the child's "amount" to match the parent's child object
            parents_child = parent.children[child_index]
            child.amt = parents_child.amt

            # Set the parent's reference to match the child object
            parent.children[child_index] = child

            return parent

        network.reduceRight(_makeTree)

class ChainVis extends Main
    constructor: (@scene, @camera, @font, @texture) ->
        console.info "New ChainVis."

    start: (data) =>
        @_addChain data

    _addChain: (text) =>
