You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
2.2 KiB
90 lines
2.2 KiB
"use strict"; |
|
|
|
var _ = require("./lodash"); |
|
var util = require("./util"); |
|
|
|
module.exports = { |
|
run: run, |
|
undo: undo |
|
}; |
|
|
|
/* |
|
* Breaks any long edges in the graph into short segments that span 1 layer |
|
* each. This operation is undoable with the denormalize function. |
|
* |
|
* Pre-conditions: |
|
* |
|
* 1. The input graph is a DAG. |
|
* 2. Each node in the graph has a "rank" property. |
|
* |
|
* Post-condition: |
|
* |
|
* 1. All edges in the graph have a length of 1. |
|
* 2. Dummy nodes are added where edges have been split into segments. |
|
* 3. The graph is augmented with a "dummyChains" attribute which contains |
|
* the first dummy in each chain of dummy nodes produced. |
|
*/ |
|
function run(g) { |
|
g.graph().dummyChains = []; |
|
_.forEach(g.edges(), function(edge) { normalizeEdge(g, edge); }); |
|
} |
|
|
|
function normalizeEdge(g, e) { |
|
var v = e.v; |
|
var vRank = g.node(v).rank; |
|
var w = e.w; |
|
var wRank = g.node(w).rank; |
|
var name = e.name; |
|
var edgeLabel = g.edge(e); |
|
var labelRank = edgeLabel.labelRank; |
|
|
|
if (wRank === vRank + 1) return; |
|
|
|
g.removeEdge(e); |
|
|
|
var dummy, attrs, i; |
|
for (i = 0, ++vRank; vRank < wRank; ++i, ++vRank) { |
|
edgeLabel.points = []; |
|
attrs = { |
|
width: 0, height: 0, |
|
edgeLabel: edgeLabel, edgeObj: e, |
|
rank: vRank |
|
}; |
|
dummy = util.addDummyNode(g, "edge", attrs, "_d"); |
|
if (vRank === labelRank) { |
|
attrs.width = edgeLabel.width; |
|
attrs.height = edgeLabel.height; |
|
attrs.dummy = "edge-label"; |
|
attrs.labelpos = edgeLabel.labelpos; |
|
} |
|
g.setEdge(v, dummy, { weight: edgeLabel.weight }, name); |
|
if (i === 0) { |
|
g.graph().dummyChains.push(dummy); |
|
} |
|
v = dummy; |
|
} |
|
|
|
g.setEdge(v, w, { weight: edgeLabel.weight }, name); |
|
} |
|
|
|
function undo(g) { |
|
_.forEach(g.graph().dummyChains, function(v) { |
|
var node = g.node(v); |
|
var origLabel = node.edgeLabel; |
|
var w; |
|
g.setEdge(node.edgeObj, origLabel); |
|
while (node.dummy) { |
|
w = g.successors(v)[0]; |
|
g.removeNode(v); |
|
origLabel.points.push({ x: node.x, y: node.y }); |
|
if (node.dummy === "edge-label") { |
|
origLabel.x = node.x; |
|
origLabel.y = node.y; |
|
origLabel.width = node.width; |
|
origLabel.height = node.height; |
|
} |
|
v = w; |
|
node = g.node(v); |
|
} |
|
}); |
|
}
|
|
|