Parse

File Parse graph-connections.js

This tree is parsed live from the source file.

Classes

  • {{ item.name }}

    • {{ key }}

Not Classes

{{ getTree() }}

Comments

{{ getTreeComments() }}

Source

            /*
title: Graph
---

This _graph chain_ stores one to one relationships, with methods to iterate
the chain in two directions. This allows use to grab the standard `A -> B -> C`,
and `C -> B -> A`.

        // some points
        const head = new Point()
        const points = new PointList(head, ...others)

        // setup connections
        const g = new GraphConnections;

        g.connect(0, 1, 2, 3, 4)
              g.connect(2, 5)
                 g.connect(5, 6, 7, 8)

Iterate one-to-one relationships (a depth of 1):

    let ps = points
    g.forPair((_a, _b)=>{
        followPoint( ps.getById(_a), ps.getById(_b), 50)
    }, this.reverse)


Provide a _forward_ function, walking thourhg the chain start from the chosen _head_:

    let head = this.g.head.uuid
    let ps = points

    let f = (key,fromKey,a)=>{
        followPoint( ps.getById(fromKey), ps.getById(key), 50)
    }

    g.getForward(head, f)

Manual iteration:

    let ps = points
    let forwardGraph = g.forward
    for(let k in forwardGraph) {
        let v = forwardGraph[k]

        for(let i of v) {
            followPoint(ps[parseInt(k)], ps[parseInt(i)], 50)
        }
    }

Capture re-visits for deeper chains.

        const graphChain = function(head, ps) {
            let visits = {}

            let pairCallback = (key, fromKey, allTargets)=>{
                constraints.distance(ps[fromKey], ps[key], 50)

                if(visits[fromKey] == undefined) { visits[fromKey] = 0 }
                if(visits[key] == undefined) { visits[key] = 0 }

                visits[fromKey] += 1
                visits[key] += 1
            }

            g.walkForward(head, pairCallback)
        }

        graphChain(head, points)

---

The graph can resolve a "star based" configuration:

    A      C
      \   /
        B
        |
        D
        |
        E

Each connection is given in a pair, from an origin node (the `head`)

    head = B

    B -> C
    B -> D [ -> E ]
    D -> E
    B -> A

## Where it's used

The `followPoint` method allows a point to _follow_ another point, at a distance.
This is a lot like constraints but with a _one to one_ relationship in a single
direction.



*/

class GraphConnections {
    constructor(){
        this.forward = {}
        this.reverse = {}
        /* neighbours by connections.
        When reversing; we grab the rear node,
        and in reverse, we iterate siblings. */
        this.siblings = {}
    }

    connect(...items){
        /* split an array into overlapping pairs

            [0,1,2,3,4,5]
            [0,1]
            [1,2]
            [2,3]
            ...
        */
        for(let i = 0; i < items.length; i += 1) {
            let [a,b] = items.slice(i-1, i+1);
            this.add(a, b)
        }
        // this.g.add(pid(a), pid(b))
    }

    add(a, b) {
        /* Add forward.

        this builds the following:

        {
            "0": [1 ],
            "1": [0, 2 ],
            "2": [1, 3, 5],
            "3": [2, 4],
            "4": [3 ],
            "5": [2, 6],
            "6": [5 ]
        }

        For connections, we walk (from a key numer) in a direction, generating pairs.
        Some keys will fork - but that should generated the connected pair set.

        e.g, pulling '3',

            3 -> 2, 4
                    4 -> [3]      <= not executed,
                 2 -> 1, [3], 5   <= skip 3, as "2"
                      1 -> 0, 2   <= skip 2, as "1"
                             ...
        */
        if(this.forward[a] == undefined) {
            this.forward[a] = []
        }

        this.forward[a].push(b)

        if(this.forward[b] == undefined) {
            this.forward[b] = []
        }

        this.forward[b].push(a)
    }

    getChain(fromId, func) {
        let g = this.forward

        let entries = g[fromId]

        if(entries == undefined) {
            func(fromId, true)
            return
        }

        for(let k of entries) {
            func(fromId, false)
            this.getChain(k, func)
        }
    }

    walkForward(fromId, func, previousId, count=0, maxCount) {
        let g = this.forward
        if(maxCount == undefined) { maxCount = 11 }
        if(count >= maxCount) {
            console.log('Kill depth')
            return
        }
        let entries = g[fromId]
        if(entries == undefined) {
            return
        }

        for(let k of entries) {
            if(previousId == k) {
                /* This is back through the original chain.*/
                continue
            }
            func(k, fromId, entries)
            this.walkForward(k, func, fromId, count+=1)
        }
    }

    forPair(func, reverse=false) {
        let g = this.forward
        // if(reverse == true) {
        //     g = this.reverse
        // }

        for(let k in g) {
            let v = g[k]
            for(let i of v) {
                if(i == k) {
                    /* reverse chain*/
                    continue
                }
                func(k, i)
            }
        }

    }
}


class DirectionalGraphConnections extends GraphConnections {

    add(a, b) {
        /* Add forward.

        this builds the following:

        {
            "0": [1 ],
            "1": [0, 2 ],
            "2": [1, 3, 5],
            "3": [2, 4],
            "4": [3 ],
            "5": [2, 6],
            "6": [5 ]
        }

        For connections, we walk (from a key numer) in a direction, generating pairs.
        Some keys will fork - but that should generated the connected pair set.

        e.g, pulling '3',

            3 -> 2, 4
                    4 -> [3]      <= not executed,
                 2 -> 1, [3], 5   <= skip 3, as "2"
                      1 -> 0, 2   <= skip 2, as "1"
                             ...
        */
        if(this.forward[a] == undefined) {
            this.forward[a] = []
        }

        this.forward[a].push(b)

        // if(this.forward[b] == undefined) {
        //     this.forward[b] = []
        // }

        // this.forward[b].push(a)
    }

}

copy