08-27-周三_17-09-29
This commit is contained in:
89
node_modules/dagre-layout/lib/rank/feasible-tree.js
generated
vendored
Normal file
89
node_modules/dagre-layout/lib/rank/feasible-tree.js
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
import _ from 'lodash'
|
||||
import { Graph } from 'graphlibrary'
|
||||
|
||||
import { slack } from './util'
|
||||
|
||||
/*
|
||||
* Constructs a spanning tree with tight edges and adjusted the input node's
|
||||
* ranks to achieve this. A tight edge is one that is has a length that matches
|
||||
* its "minlen" attribute.
|
||||
*
|
||||
* The basic structure for this function is derived from Gansner, et al., "A
|
||||
* Technique for Drawing Directed Graphs."
|
||||
*
|
||||
* Pre-conditions:
|
||||
*
|
||||
* 1. Graph must be a DAG.
|
||||
* 2. Graph must be connected.
|
||||
* 3. Graph must have at least one node.
|
||||
* 5. Graph nodes must have been previously assigned a "rank" property that
|
||||
* respects the "minlen" property of incident edges.
|
||||
* 6. Graph edges must have a "minlen" property.
|
||||
*
|
||||
* Post-conditions:
|
||||
*
|
||||
* - Graph nodes will have their rank adjusted to ensure that all edges are
|
||||
* tight.
|
||||
*
|
||||
* Returns a tree (undirected graph) that is constructed using only "tight"
|
||||
* edges.
|
||||
*/
|
||||
function feasibleTree (g) {
|
||||
const t = new Graph({ directed: false })
|
||||
|
||||
// Choose arbitrary node from which to start our tree
|
||||
const start = g.nodes()[0]
|
||||
const size = g.nodeCount()
|
||||
t.setNode(start, {})
|
||||
|
||||
let edge
|
||||
let delta
|
||||
while (tightTree(t, g) < size) {
|
||||
edge = findMinSlackEdge(t, g)
|
||||
delta = t.hasNode(edge.v) ? slack(g, edge) : -slack(g, edge)
|
||||
shiftRanks(t, g, delta)
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds a maximal tree of tight edges and returns the number of nodes in the
|
||||
* tree.
|
||||
*/
|
||||
function tightTree (t, g) {
|
||||
function dfs (v) {
|
||||
_.forEach(g.nodeEdges(v), function (e) {
|
||||
const edgeV = e.v
|
||||
const w = (v === edgeV) ? e.w : edgeV
|
||||
if (!t.hasNode(w) && !slack(g, e)) {
|
||||
t.setNode(w, {})
|
||||
t.setEdge(v, w, {})
|
||||
dfs(w)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
_.forEach(t.nodes(), dfs)
|
||||
return t.nodeCount()
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds the edge with the smallest slack that is incident on tree and returns
|
||||
* it.
|
||||
*/
|
||||
function findMinSlackEdge (t, g) {
|
||||
return _.minBy(g.edges(), function (e) {
|
||||
if (t.hasNode(e.v) !== t.hasNode(e.w)) {
|
||||
return slack(g, e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function shiftRanks (t, g, delta) {
|
||||
_.forEach(t.nodes(), function (v) {
|
||||
g.node(v).rank += delta
|
||||
})
|
||||
}
|
||||
|
||||
export default feasibleTree
|
Reference in New Issue
Block a user