@dagrejs/dagre 1.1.8 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/dagre.cjs.js +3 -0
  2. package/{index.js → dist/dagre.cjs.js.LEGAL.txt} +2 -12
  3. package/dist/dagre.cjs.js.map +7 -0
  4. package/dist/dagre.d.ts +104 -0
  5. package/dist/dagre.esm.js +3 -0
  6. package/dist/dagre.esm.js.LEGAL.txt +23 -0
  7. package/dist/dagre.esm.js.map +7 -0
  8. package/dist/dagre.js +2183 -4321
  9. package/dist/dagre.js.LEGAL.txt +23 -0
  10. package/dist/dagre.js.map +7 -0
  11. package/dist/dagre.min.js +3 -815
  12. package/dist/dagre.min.js.LEGAL.txt +23 -0
  13. package/dist/dagre.min.js.map +7 -0
  14. package/package.json +20 -24
  15. package/index.d.ts +0 -147
  16. package/lib/acyclic.js +0 -67
  17. package/lib/add-border-segments.js +0 -37
  18. package/lib/coordinate-system.js +0 -70
  19. package/lib/data/list.js +0 -58
  20. package/lib/debug.js +0 -31
  21. package/lib/greedy-fas.js +0 -124
  22. package/lib/layout.js +0 -405
  23. package/lib/nesting-graph.js +0 -126
  24. package/lib/normalize.js +0 -89
  25. package/lib/order/add-subgraph-constraints.js +0 -51
  26. package/lib/order/barycenter.js +0 -26
  27. package/lib/order/build-layer-graph.js +0 -79
  28. package/lib/order/cross-count.js +0 -66
  29. package/lib/order/index.js +0 -111
  30. package/lib/order/init-order.js +0 -37
  31. package/lib/order/resolve-conflicts.js +0 -118
  32. package/lib/order/sort-subgraph.js +0 -73
  33. package/lib/order/sort.js +0 -56
  34. package/lib/parent-dummy-chains.js +0 -84
  35. package/lib/position/bk.js +0 -424
  36. package/lib/position/index.js +0 -32
  37. package/lib/rank/feasible-tree.js +0 -95
  38. package/lib/rank/index.js +0 -54
  39. package/lib/rank/network-simplex.js +0 -235
  40. package/lib/rank/util.js +0 -67
  41. package/lib/util.js +0 -331
  42. package/lib/version.js +0 -1
package/lib/layout.js DELETED
@@ -1,405 +0,0 @@
1
- "use strict";
2
-
3
- let acyclic = require("./acyclic");
4
- let normalize = require("./normalize");
5
- let rank = require("./rank");
6
- let normalizeRanks = require("./util").normalizeRanks;
7
- let parentDummyChains = require("./parent-dummy-chains");
8
- let removeEmptyRanks = require("./util").removeEmptyRanks;
9
- let nestingGraph = require("./nesting-graph");
10
- let addBorderSegments = require("./add-border-segments");
11
- let coordinateSystem = require("./coordinate-system");
12
- let order = require("./order");
13
- let position = require("./position");
14
- let util = require("./util");
15
- let Graph = require("@dagrejs/graphlib").Graph;
16
-
17
- module.exports = layout;
18
-
19
- function layout(g, opts) {
20
- let time = opts && opts.debugTiming ? util.time : util.notime;
21
- time("layout", () => {
22
- let layoutGraph =
23
- time(" buildLayoutGraph", () => buildLayoutGraph(g));
24
- time(" runLayout", () => runLayout(layoutGraph, time, opts));
25
- time(" updateInputGraph", () => updateInputGraph(g, layoutGraph));
26
- });
27
- }
28
-
29
- function runLayout(g, time, opts) {
30
- time(" makeSpaceForEdgeLabels", () => makeSpaceForEdgeLabels(g));
31
- time(" removeSelfEdges", () => removeSelfEdges(g));
32
- time(" acyclic", () => acyclic.run(g));
33
- time(" nestingGraph.run", () => nestingGraph.run(g));
34
- time(" rank", () => rank(util.asNonCompoundGraph(g)));
35
- time(" injectEdgeLabelProxies", () => injectEdgeLabelProxies(g));
36
- time(" removeEmptyRanks", () => removeEmptyRanks(g));
37
- time(" nestingGraph.cleanup", () => nestingGraph.cleanup(g));
38
- time(" normalizeRanks", () => normalizeRanks(g));
39
- time(" assignRankMinMax", () => assignRankMinMax(g));
40
- time(" removeEdgeLabelProxies", () => removeEdgeLabelProxies(g));
41
- time(" normalize.run", () => normalize.run(g));
42
- time(" parentDummyChains", () => parentDummyChains(g));
43
- time(" addBorderSegments", () => addBorderSegments(g));
44
- time(" order", () => order(g, opts));
45
- time(" insertSelfEdges", () => insertSelfEdges(g));
46
- time(" adjustCoordinateSystem", () => coordinateSystem.adjust(g));
47
- time(" position", () => position(g));
48
- time(" positionSelfEdges", () => positionSelfEdges(g));
49
- time(" removeBorderNodes", () => removeBorderNodes(g));
50
- time(" normalize.undo", () => normalize.undo(g));
51
- time(" fixupEdgeLabelCoords", () => fixupEdgeLabelCoords(g));
52
- time(" undoCoordinateSystem", () => coordinateSystem.undo(g));
53
- time(" translateGraph", () => translateGraph(g));
54
- time(" assignNodeIntersects", () => assignNodeIntersects(g));
55
- time(" reversePoints", () => reversePointsForReversedEdges(g));
56
- time(" acyclic.undo", () => acyclic.undo(g));
57
- }
58
-
59
- /*
60
- * Copies final layout information from the layout graph back to the input
61
- * graph. This process only copies whitelisted attributes from the layout graph
62
- * to the input graph, so it serves as a good place to determine what
63
- * attributes can influence layout.
64
- */
65
- function updateInputGraph(inputGraph, layoutGraph) {
66
- inputGraph.nodes().forEach(v => {
67
- let inputLabel = inputGraph.node(v);
68
- let layoutLabel = layoutGraph.node(v);
69
-
70
- if (inputLabel) {
71
- inputLabel.x = layoutLabel.x;
72
- inputLabel.y = layoutLabel.y;
73
- inputLabel.rank = layoutLabel.rank;
74
-
75
- if (layoutGraph.children(v).length) {
76
- inputLabel.width = layoutLabel.width;
77
- inputLabel.height = layoutLabel.height;
78
- }
79
- }
80
- });
81
-
82
- inputGraph.edges().forEach(e => {
83
- let inputLabel = inputGraph.edge(e);
84
- let layoutLabel = layoutGraph.edge(e);
85
-
86
- inputLabel.points = layoutLabel.points;
87
- if (Object.hasOwn(layoutLabel, "x")) {
88
- inputLabel.x = layoutLabel.x;
89
- inputLabel.y = layoutLabel.y;
90
- }
91
- });
92
-
93
- inputGraph.graph().width = layoutGraph.graph().width;
94
- inputGraph.graph().height = layoutGraph.graph().height;
95
- }
96
-
97
- let graphNumAttrs = ["nodesep", "edgesep", "ranksep", "marginx", "marginy"];
98
- let graphDefaults = { ranksep: 50, edgesep: 20, nodesep: 50, rankdir: "tb" };
99
- let graphAttrs = ["acyclicer", "ranker", "rankdir", "align"];
100
- let nodeNumAttrs = ["width", "height", "rank"];
101
- let nodeDefaults = { width: 0, height: 0 };
102
- let edgeNumAttrs = ["minlen", "weight", "width", "height", "labeloffset"];
103
- let edgeDefaults = {
104
- minlen: 1, weight: 1, width: 0, height: 0,
105
- labeloffset: 10, labelpos: "r"
106
- };
107
- let edgeAttrs = ["labelpos"];
108
-
109
- /*
110
- * Constructs a new graph from the input graph, which can be used for layout.
111
- * This process copies only whitelisted attributes from the input graph to the
112
- * layout graph. Thus this function serves as a good place to determine what
113
- * attributes can influence layout.
114
- */
115
- function buildLayoutGraph(inputGraph) {
116
- let g = new Graph({ multigraph: true, compound: true });
117
- let graph = canonicalize(inputGraph.graph());
118
-
119
- g.setGraph(Object.assign({},
120
- graphDefaults,
121
- selectNumberAttrs(graph, graphNumAttrs),
122
- util.pick(graph, graphAttrs)));
123
-
124
- inputGraph.nodes().forEach(v => {
125
- let node = canonicalize(inputGraph.node(v));
126
- const newNode = selectNumberAttrs(node, nodeNumAttrs);
127
- Object.keys(nodeDefaults).forEach(k => {
128
- if (newNode[k] === undefined) {
129
- newNode[k] = nodeDefaults[k];
130
- }
131
- });
132
-
133
- g.setNode(v, newNode);
134
- g.setParent(v, inputGraph.parent(v));
135
- });
136
-
137
- inputGraph.edges().forEach(e => {
138
- let edge = canonicalize(inputGraph.edge(e));
139
- g.setEdge(e, Object.assign({},
140
- edgeDefaults,
141
- selectNumberAttrs(edge, edgeNumAttrs),
142
- util.pick(edge, edgeAttrs)));
143
- });
144
-
145
- return g;
146
- }
147
-
148
- /*
149
- * This idea comes from the Gansner paper: to account for edge labels in our
150
- * layout we split each rank in half by doubling minlen and halving ranksep.
151
- * Then we can place labels at these mid-points between nodes.
152
- *
153
- * We also add some minimal padding to the width to push the label for the edge
154
- * away from the edge itself a bit.
155
- */
156
- function makeSpaceForEdgeLabels(g) {
157
- let graph = g.graph();
158
- graph.ranksep /= 2;
159
- g.edges().forEach(e => {
160
- let edge = g.edge(e);
161
- edge.minlen *= 2;
162
- if (edge.labelpos.toLowerCase() !== "c") {
163
- if (graph.rankdir === "TB" || graph.rankdir === "BT") {
164
- edge.width += edge.labeloffset;
165
- } else {
166
- edge.height += edge.labeloffset;
167
- }
168
- }
169
- });
170
- }
171
-
172
- /*
173
- * Creates temporary dummy nodes that capture the rank in which each edge's
174
- * label is going to, if it has one of non-zero width and height. We do this
175
- * so that we can safely remove empty ranks while preserving balance for the
176
- * label's position.
177
- */
178
- function injectEdgeLabelProxies(g) {
179
- g.edges().forEach(e => {
180
- let edge = g.edge(e);
181
- if (edge.width && edge.height) {
182
- let v = g.node(e.v);
183
- let w = g.node(e.w);
184
- let label = { rank: (w.rank - v.rank) / 2 + v.rank, e: e };
185
- util.addDummyNode(g, "edge-proxy", label, "_ep");
186
- }
187
- });
188
- }
189
-
190
- function assignRankMinMax(g) {
191
- let maxRank = 0;
192
- g.nodes().forEach(v => {
193
- let node = g.node(v);
194
- if (node.borderTop) {
195
- node.minRank = g.node(node.borderTop).rank;
196
- node.maxRank = g.node(node.borderBottom).rank;
197
- maxRank = Math.max(maxRank, node.maxRank);
198
- }
199
- });
200
- g.graph().maxRank = maxRank;
201
- }
202
-
203
- function removeEdgeLabelProxies(g) {
204
- g.nodes().forEach(v => {
205
- let node = g.node(v);
206
- if (node.dummy === "edge-proxy") {
207
- g.edge(node.e).labelRank = node.rank;
208
- g.removeNode(v);
209
- }
210
- });
211
- }
212
-
213
- function translateGraph(g) {
214
- let minX = Number.POSITIVE_INFINITY;
215
- let maxX = 0;
216
- let minY = Number.POSITIVE_INFINITY;
217
- let maxY = 0;
218
- let graphLabel = g.graph();
219
- let marginX = graphLabel.marginx || 0;
220
- let marginY = graphLabel.marginy || 0;
221
-
222
- function getExtremes(attrs) {
223
- let x = attrs.x;
224
- let y = attrs.y;
225
- let w = attrs.width;
226
- let h = attrs.height;
227
- minX = Math.min(minX, x - w / 2);
228
- maxX = Math.max(maxX, x + w / 2);
229
- minY = Math.min(minY, y - h / 2);
230
- maxY = Math.max(maxY, y + h / 2);
231
- }
232
-
233
- g.nodes().forEach(v => getExtremes(g.node(v)));
234
- g.edges().forEach(e => {
235
- let edge = g.edge(e);
236
- if (Object.hasOwn(edge, "x")) {
237
- getExtremes(edge);
238
- }
239
- });
240
-
241
- minX -= marginX;
242
- minY -= marginY;
243
-
244
- g.nodes().forEach(v => {
245
- let node = g.node(v);
246
- node.x -= minX;
247
- node.y -= minY;
248
- });
249
-
250
- g.edges().forEach(e => {
251
- let edge = g.edge(e);
252
- edge.points.forEach(p => {
253
- p.x -= minX;
254
- p.y -= minY;
255
- });
256
- if (Object.hasOwn(edge, "x")) { edge.x -= minX; }
257
- if (Object.hasOwn(edge, "y")) { edge.y -= minY; }
258
- });
259
-
260
- graphLabel.width = maxX - minX + marginX;
261
- graphLabel.height = maxY - minY + marginY;
262
- }
263
-
264
- function assignNodeIntersects(g) {
265
- g.edges().forEach(e => {
266
- let edge = g.edge(e);
267
- let nodeV = g.node(e.v);
268
- let nodeW = g.node(e.w);
269
- let p1, p2;
270
- if (!edge.points) {
271
- edge.points = [];
272
- p1 = nodeW;
273
- p2 = nodeV;
274
- } else {
275
- p1 = edge.points[0];
276
- p2 = edge.points[edge.points.length - 1];
277
- }
278
- edge.points.unshift(util.intersectRect(nodeV, p1));
279
- edge.points.push(util.intersectRect(nodeW, p2));
280
- });
281
- }
282
-
283
- function fixupEdgeLabelCoords(g) {
284
- g.edges().forEach(e => {
285
- let edge = g.edge(e);
286
- if (Object.hasOwn(edge, "x")) {
287
- if (edge.labelpos === "l" || edge.labelpos === "r") {
288
- edge.width -= edge.labeloffset;
289
- }
290
- switch (edge.labelpos) {
291
- case "l": edge.x -= edge.width / 2 + edge.labeloffset; break;
292
- case "r": edge.x += edge.width / 2 + edge.labeloffset; break;
293
- }
294
- }
295
- });
296
- }
297
-
298
- function reversePointsForReversedEdges(g) {
299
- g.edges().forEach(e => {
300
- let edge = g.edge(e);
301
- if (edge.reversed) {
302
- edge.points.reverse();
303
- }
304
- });
305
- }
306
-
307
- function removeBorderNodes(g) {
308
- g.nodes().forEach(v => {
309
- if (g.children(v).length) {
310
- let node = g.node(v);
311
- let t = g.node(node.borderTop);
312
- let b = g.node(node.borderBottom);
313
- let l = g.node(node.borderLeft[node.borderLeft.length - 1]);
314
- let r = g.node(node.borderRight[node.borderRight.length - 1]);
315
-
316
- node.width = Math.abs(r.x - l.x);
317
- node.height = Math.abs(b.y - t.y);
318
- node.x = l.x + node.width / 2;
319
- node.y = t.y + node.height / 2;
320
- }
321
- });
322
-
323
- g.nodes().forEach(v => {
324
- if (g.node(v).dummy === "border") {
325
- g.removeNode(v);
326
- }
327
- });
328
- }
329
-
330
- function removeSelfEdges(g) {
331
- g.edges().forEach(e => {
332
- if (e.v === e.w) {
333
- var node = g.node(e.v);
334
- if (!node.selfEdges) {
335
- node.selfEdges = [];
336
- }
337
- node.selfEdges.push({ e: e, label: g.edge(e) });
338
- g.removeEdge(e);
339
- }
340
- });
341
- }
342
-
343
- function insertSelfEdges(g) {
344
- var layers = util.buildLayerMatrix(g);
345
- layers.forEach(layer => {
346
- var orderShift = 0;
347
- layer.forEach((v, i) => {
348
- var node = g.node(v);
349
- node.order = i + orderShift;
350
- (node.selfEdges || []).forEach(selfEdge => {
351
- util.addDummyNode(g, "selfedge", {
352
- width: selfEdge.label.width,
353
- height: selfEdge.label.height,
354
- rank: node.rank,
355
- order: i + (++orderShift),
356
- e: selfEdge.e,
357
- label: selfEdge.label
358
- }, "_se");
359
- });
360
- delete node.selfEdges;
361
- });
362
- });
363
- }
364
-
365
- function positionSelfEdges(g) {
366
- g.nodes().forEach(v => {
367
- var node = g.node(v);
368
- if (node.dummy === "selfedge") {
369
- var selfNode = g.node(node.e.v);
370
- var x = selfNode.x + selfNode.width / 2;
371
- var y = selfNode.y;
372
- var dx = node.x - x;
373
- var dy = selfNode.height / 2;
374
- g.setEdge(node.e, node.label);
375
- g.removeNode(v);
376
- node.label.points = [
377
- { x: x + 2 * dx / 3, y: y - dy },
378
- { x: x + 5 * dx / 6, y: y - dy },
379
- { x: x + dx , y: y },
380
- { x: x + 5 * dx / 6, y: y + dy },
381
- { x: x + 2 * dx / 3, y: y + dy }
382
- ];
383
- node.label.x = node.x;
384
- node.label.y = node.y;
385
- }
386
- });
387
- }
388
-
389
- function selectNumberAttrs(obj, attrs) {
390
- return util.mapValues(util.pick(obj, attrs), Number);
391
- }
392
-
393
- function canonicalize(attrs) {
394
- var newAttrs = {};
395
- if (attrs) {
396
- Object.entries(attrs).forEach(([k, v]) => {
397
- if (typeof k === "string") {
398
- k = k.toLowerCase();
399
- }
400
-
401
- newAttrs[k] = v;
402
- });
403
- }
404
- return newAttrs;
405
- }
@@ -1,126 +0,0 @@
1
- let util = require("./util");
2
-
3
- module.exports = {
4
- run,
5
- cleanup,
6
- };
7
-
8
- /*
9
- * A nesting graph creates dummy nodes for the tops and bottoms of subgraphs,
10
- * adds appropriate edges to ensure that all cluster nodes are placed between
11
- * these boundaries, and ensures that the graph is connected.
12
- *
13
- * In addition we ensure, through the use of the minlen property, that nodes
14
- * and subgraph border nodes to not end up on the same rank.
15
- *
16
- * Preconditions:
17
- *
18
- * 1. Input graph is a DAG
19
- * 2. Nodes in the input graph has a minlen attribute
20
- *
21
- * Postconditions:
22
- *
23
- * 1. Input graph is connected.
24
- * 2. Dummy nodes are added for the tops and bottoms of subgraphs.
25
- * 3. The minlen attribute for nodes is adjusted to ensure nodes do not
26
- * get placed on the same rank as subgraph border nodes.
27
- *
28
- * The nesting graph idea comes from Sander, "Layout of Compound Directed
29
- * Graphs."
30
- */
31
- function run(g) {
32
- let root = util.addDummyNode(g, "root", {}, "_root");
33
- let depths = treeDepths(g);
34
- let depthsArr = Object.values(depths);
35
- let height = util.applyWithChunking(Math.max, depthsArr) - 1; // Note: depths is an Object not an array
36
- let nodeSep = 2 * height + 1;
37
-
38
- g.graph().nestingRoot = root;
39
-
40
- // Multiply minlen by nodeSep to align nodes on non-border ranks.
41
- g.edges().forEach(e => g.edge(e).minlen *= nodeSep);
42
-
43
- // Calculate a weight that is sufficient to keep subgraphs vertically compact
44
- let weight = sumWeights(g) + 1;
45
-
46
- // Create border nodes and link them up
47
- g.children().forEach(child => dfs(g, root, nodeSep, weight, height, depths, child));
48
-
49
- // Save the multiplier for node layers for later removal of empty border
50
- // layers.
51
- g.graph().nodeRankFactor = nodeSep;
52
- }
53
-
54
- function dfs(g, root, nodeSep, weight, height, depths, v) {
55
- let children = g.children(v);
56
- if (!children.length) {
57
- if (v !== root) {
58
- g.setEdge(root, v, { weight: 0, minlen: nodeSep });
59
- }
60
- return;
61
- }
62
-
63
- let top = util.addBorderNode(g, "_bt");
64
- let bottom = util.addBorderNode(g, "_bb");
65
- let label = g.node(v);
66
-
67
- g.setParent(top, v);
68
- label.borderTop = top;
69
- g.setParent(bottom, v);
70
- label.borderBottom = bottom;
71
-
72
- children.forEach(child => {
73
- dfs(g, root, nodeSep, weight, height, depths, child);
74
-
75
- let childNode = g.node(child);
76
- let childTop = childNode.borderTop ? childNode.borderTop : child;
77
- let childBottom = childNode.borderBottom ? childNode.borderBottom : child;
78
- let thisWeight = childNode.borderTop ? weight : 2 * weight;
79
- let minlen = childTop !== childBottom ? 1 : height - depths[v] + 1;
80
-
81
- g.setEdge(top, childTop, {
82
- weight: thisWeight,
83
- minlen: minlen,
84
- nestingEdge: true
85
- });
86
-
87
- g.setEdge(childBottom, bottom, {
88
- weight: thisWeight,
89
- minlen: minlen,
90
- nestingEdge: true
91
- });
92
- });
93
-
94
- if (!g.parent(v)) {
95
- g.setEdge(root, top, { weight: 0, minlen: height + depths[v] });
96
- }
97
- }
98
-
99
- function treeDepths(g) {
100
- var depths = {};
101
- function dfs(v, depth) {
102
- var children = g.children(v);
103
- if (children && children.length) {
104
- children.forEach(child => dfs(child, depth + 1));
105
- }
106
- depths[v] = depth;
107
- }
108
- g.children().forEach(v => dfs(v, 1));
109
- return depths;
110
- }
111
-
112
- function sumWeights(g) {
113
- return g.edges().reduce((acc, e) => acc + g.edge(e).weight, 0);
114
- }
115
-
116
- function cleanup(g) {
117
- var graphLabel = g.graph();
118
- g.removeNode(graphLabel.nestingRoot);
119
- delete graphLabel.nestingRoot;
120
- g.edges().forEach(e => {
121
- var edge = g.edge(e);
122
- if (edge.nestingEdge) {
123
- g.removeEdge(e);
124
- }
125
- });
126
- }
package/lib/normalize.js DELETED
@@ -1,89 +0,0 @@
1
- "use strict";
2
-
3
- let util = require("./util");
4
-
5
- module.exports = {
6
- run: run,
7
- undo: undo
8
- };
9
-
10
- /*
11
- * Breaks any long edges in the graph into short segments that span 1 layer
12
- * each. This operation is undoable with the denormalize function.
13
- *
14
- * Pre-conditions:
15
- *
16
- * 1. The input graph is a DAG.
17
- * 2. Each node in the graph has a "rank" property.
18
- *
19
- * Post-condition:
20
- *
21
- * 1. All edges in the graph have a length of 1.
22
- * 2. Dummy nodes are added where edges have been split into segments.
23
- * 3. The graph is augmented with a "dummyChains" attribute which contains
24
- * the first dummy in each chain of dummy nodes produced.
25
- */
26
- function run(g) {
27
- g.graph().dummyChains = [];
28
- g.edges().forEach(edge => normalizeEdge(g, edge));
29
- }
30
-
31
- function normalizeEdge(g, e) {
32
- let v = e.v;
33
- let vRank = g.node(v).rank;
34
- let w = e.w;
35
- let wRank = g.node(w).rank;
36
- let name = e.name;
37
- let edgeLabel = g.edge(e);
38
- let labelRank = edgeLabel.labelRank;
39
-
40
- if (wRank === vRank + 1) return;
41
-
42
- g.removeEdge(e);
43
-
44
- let dummy, attrs, i;
45
- for (i = 0, ++vRank; vRank < wRank; ++i, ++vRank) {
46
- edgeLabel.points = [];
47
- attrs = {
48
- width: 0, height: 0,
49
- edgeLabel: edgeLabel, edgeObj: e,
50
- rank: vRank
51
- };
52
- dummy = util.addDummyNode(g, "edge", attrs, "_d");
53
- if (vRank === labelRank) {
54
- attrs.width = edgeLabel.width;
55
- attrs.height = edgeLabel.height;
56
- attrs.dummy = "edge-label";
57
- attrs.labelpos = edgeLabel.labelpos;
58
- }
59
- g.setEdge(v, dummy, { weight: edgeLabel.weight }, name);
60
- if (i === 0) {
61
- g.graph().dummyChains.push(dummy);
62
- }
63
- v = dummy;
64
- }
65
-
66
- g.setEdge(v, w, { weight: edgeLabel.weight }, name);
67
- }
68
-
69
- function undo(g) {
70
- g.graph().dummyChains.forEach(v => {
71
- let node = g.node(v);
72
- let origLabel = node.edgeLabel;
73
- let w;
74
- g.setEdge(node.edgeObj, origLabel);
75
- while (node.dummy) {
76
- w = g.successors(v)[0];
77
- g.removeNode(v);
78
- origLabel.points.push({ x: node.x, y: node.y });
79
- if (node.dummy === "edge-label") {
80
- origLabel.x = node.x;
81
- origLabel.y = node.y;
82
- origLabel.width = node.width;
83
- origLabel.height = node.height;
84
- }
85
- v = w;
86
- node = g.node(v);
87
- }
88
- });
89
- }
@@ -1,51 +0,0 @@
1
- module.exports = addSubgraphConstraints;
2
-
3
- function addSubgraphConstraints(g, cg, vs) {
4
- let prev = {},
5
- rootPrev;
6
-
7
- vs.forEach(v => {
8
- let child = g.parent(v),
9
- parent,
10
- prevChild;
11
- while (child) {
12
- parent = g.parent(child);
13
- if (parent) {
14
- prevChild = prev[parent];
15
- prev[parent] = child;
16
- } else {
17
- prevChild = rootPrev;
18
- rootPrev = child;
19
- }
20
- if (prevChild && prevChild !== child) {
21
- cg.setEdge(prevChild, child);
22
- return;
23
- }
24
- child = parent;
25
- }
26
- });
27
-
28
- /*
29
- function dfs(v) {
30
- var children = v ? g.children(v) : g.children();
31
- if (children.length) {
32
- var min = Number.POSITIVE_INFINITY,
33
- subgraphs = [];
34
- children.forEach(function(child) {
35
- var childMin = dfs(child);
36
- if (g.children(child).length) {
37
- subgraphs.push({ v: child, order: childMin });
38
- }
39
- min = Math.min(min, childMin);
40
- });
41
- _.sortBy(subgraphs, "order").reduce(function(prev, curr) {
42
- cg.setEdge(prev.v, curr.v);
43
- return curr;
44
- });
45
- return min;
46
- }
47
- return g.node(v).order;
48
- }
49
- dfs(undefined);
50
- */
51
- }
@@ -1,26 +0,0 @@
1
- module.exports = barycenter;
2
-
3
- function barycenter(g, movable = []) {
4
- return movable.map(v => {
5
- let inV = g.inEdges(v);
6
- if (!inV.length) {
7
- return { v: v };
8
- } else {
9
- let result = inV.reduce((acc, e) => {
10
- let edge = g.edge(e),
11
- nodeU = g.node(e.v);
12
- return {
13
- sum: acc.sum + (edge.weight * nodeU.order),
14
- weight: acc.weight + edge.weight
15
- };
16
- }, { sum: 0, weight: 0 });
17
-
18
- return {
19
- v: v,
20
- barycenter: result.sum / result.weight,
21
- weight: result.weight
22
- };
23
- }
24
- });
25
- }
26
-