@dagrejs/dagre 1.1.0 → 1.1.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.
- package/dist/dagre.js +16 -5
- package/dist/dagre.min.js +4 -4
- package/lib/acyclic.js +18 -10
- package/lib/add-border-segments.js +11 -19
- package/lib/coordinate-system.js +15 -5
- package/lib/data/list.js +7 -8
- package/lib/debug.js +14 -25
- package/lib/greedy-fas.js +30 -35
- package/lib/layout.js +102 -105
- package/lib/nesting-graph.js +21 -18
- package/lib/normalize.js +18 -22
- package/lib/order/add-subgraph-constraints.js +2 -6
- package/lib/order/barycenter.js +6 -14
- package/lib/order/build-layer-graph.js +13 -19
- package/lib/order/cross-count.js +10 -13
- package/lib/order/index.js +23 -23
- package/lib/order/init-order.js +7 -8
- package/lib/order/resolve-conflicts.js +19 -9
- package/lib/order/sort-subgraph.js +22 -16
- package/lib/order/sort.js +12 -13
- package/lib/parent-dummy-chains.js +19 -17
- package/lib/position/bk.js +84 -40
- package/lib/position/index.js +9 -10
- package/lib/rank/feasible-tree.js +17 -14
- package/lib/rank/index.js +15 -25
- package/lib/rank/network-simplex.js +39 -18
- package/lib/rank/util.js +12 -6
- package/lib/util.js +57 -42
- package/lib/version.js +1 -8
- package/package.json +3 -15
- package/lib/index.js +0 -38
- package/mjs-lib/acyclic.js +0 -62
- package/mjs-lib/add-border-segments.js +0 -35
- package/mjs-lib/coordinate-system.js +0 -65
- package/mjs-lib/data/list.js +0 -56
- package/mjs-lib/debug.js +0 -30
- package/mjs-lib/greedy-fas.js +0 -125
- package/mjs-lib/index.js +0 -9
- package/mjs-lib/layout.js +0 -405
- package/mjs-lib/nesting-graph.js +0 -120
- package/mjs-lib/normalize.js +0 -84
- package/mjs-lib/order/add-subgraph-constraints.js +0 -49
- package/mjs-lib/order/barycenter.js +0 -24
- package/mjs-lib/order/build-layer-graph.js +0 -71
- package/mjs-lib/order/cross-count.js +0 -64
- package/mjs-lib/order/index.js +0 -70
- package/mjs-lib/order/init-order.js +0 -34
- package/mjs-lib/order/resolve-conflicts.js +0 -116
- package/mjs-lib/order/sort-subgraph.js +0 -71
- package/mjs-lib/order/sort.js +0 -54
- package/mjs-lib/parent-dummy-chains.js +0 -82
- package/mjs-lib/position/bk.js +0 -409
- package/mjs-lib/position/index.js +0 -30
- package/mjs-lib/rank/feasible-tree.js +0 -93
- package/mjs-lib/rank/index.js +0 -46
- package/mjs-lib/rank/network-simplex.js +0 -233
- package/mjs-lib/rank/util.js +0 -58
- package/mjs-lib/util.js +0 -305
- package/mjs-lib/version.js +0 -1
package/lib/position/bk.js
CHANGED
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
exports.addConflict = addConflict;
|
|
7
|
-
exports.alignCoordinates = alignCoordinates;
|
|
8
|
-
exports.balance = balance;
|
|
9
|
-
exports.findSmallestWidthAlignment = findSmallestWidthAlignment;
|
|
10
|
-
exports.findType1Conflicts = findType1Conflicts;
|
|
11
|
-
exports.findType2Conflicts = findType2Conflicts;
|
|
12
|
-
exports.hasConflict = hasConflict;
|
|
13
|
-
exports.horizontalCompaction = horizontalCompaction;
|
|
14
|
-
exports.positionX = positionX;
|
|
15
|
-
exports.verticalAlignment = verticalAlignment;
|
|
16
|
-
var _graphlib = require("@dagrejs/graphlib");
|
|
17
|
-
var util = _interopRequireWildcard(require("../util.js"));
|
|
18
|
-
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
19
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
3
|
+
let Graph = require("@dagrejs/graphlib").Graph;
|
|
4
|
+
let util = require("../util");
|
|
5
|
+
|
|
20
6
|
/*
|
|
21
7
|
* This module provides coordinate assignment based on Brandes and Köpf, "Fast
|
|
22
8
|
* and Simple Horizontal Coordinate Assignment."
|
|
23
9
|
*/
|
|
24
10
|
|
|
11
|
+
module.exports = {
|
|
12
|
+
positionX: positionX,
|
|
13
|
+
findType1Conflicts: findType1Conflicts,
|
|
14
|
+
findType2Conflicts: findType2Conflicts,
|
|
15
|
+
addConflict: addConflict,
|
|
16
|
+
hasConflict: hasConflict,
|
|
17
|
+
verticalAlignment: verticalAlignment,
|
|
18
|
+
horizontalCompaction: horizontalCompaction,
|
|
19
|
+
alignCoordinates: alignCoordinates,
|
|
20
|
+
findSmallestWidthAlignment: findSmallestWidthAlignment,
|
|
21
|
+
balance: balance
|
|
22
|
+
};
|
|
23
|
+
|
|
25
24
|
/*
|
|
26
25
|
* Marks all edges in the graph with a type-1 conflict with the "type1Conflict"
|
|
27
26
|
* property. A type-1 conflict is one where a non-inner segment crosses an
|
|
@@ -41,6 +40,7 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
|
|
|
41
40
|
*/
|
|
42
41
|
function findType1Conflicts(g, layering) {
|
|
43
42
|
let conflicts = {};
|
|
43
|
+
|
|
44
44
|
function visitLayer(prevLayer, layer) {
|
|
45
45
|
let
|
|
46
46
|
// last visited node in the previous layer that is incident on an inner
|
|
@@ -51,15 +51,18 @@ function findType1Conflicts(g, layering) {
|
|
|
51
51
|
scanPos = 0,
|
|
52
52
|
prevLayerLength = prevLayer.length,
|
|
53
53
|
lastNode = layer[layer.length - 1];
|
|
54
|
+
|
|
54
55
|
layer.forEach((v, i) => {
|
|
55
56
|
let w = findOtherInnerSegmentNode(g, v),
|
|
56
57
|
k1 = w ? g.node(w).order : prevLayerLength;
|
|
58
|
+
|
|
57
59
|
if (w || v === lastNode) {
|
|
58
|
-
layer.slice(scanPos, i
|
|
60
|
+
layer.slice(scanPos, i+1).forEach(scanNode => {
|
|
59
61
|
g.predecessors(scanNode).forEach(u => {
|
|
60
62
|
let uLabel = g.node(u),
|
|
61
63
|
uPos = uLabel.order;
|
|
62
|
-
if ((uPos < k0 || k1 < uPos) &&
|
|
64
|
+
if ((uPos < k0 || k1 < uPos) &&
|
|
65
|
+
!(uLabel.dummy && g.node(scanNode).dummy)) {
|
|
63
66
|
addConflict(conflicts, u, scanNode);
|
|
64
67
|
}
|
|
65
68
|
});
|
|
@@ -68,13 +71,18 @@ function findType1Conflicts(g, layering) {
|
|
|
68
71
|
k0 = k1;
|
|
69
72
|
}
|
|
70
73
|
});
|
|
74
|
+
|
|
71
75
|
return layer;
|
|
72
76
|
}
|
|
77
|
+
|
|
73
78
|
layering.length && layering.reduce(visitLayer);
|
|
79
|
+
|
|
74
80
|
return conflicts;
|
|
75
81
|
}
|
|
82
|
+
|
|
76
83
|
function findType2Conflicts(g, layering) {
|
|
77
84
|
let conflicts = {};
|
|
85
|
+
|
|
78
86
|
function scan(south, southPos, southEnd, prevNorthBorder, nextNorthBorder) {
|
|
79
87
|
let v;
|
|
80
88
|
util.range(southPos, southEnd).forEach(i => {
|
|
@@ -82,17 +90,21 @@ function findType2Conflicts(g, layering) {
|
|
|
82
90
|
if (g.node(v).dummy) {
|
|
83
91
|
g.predecessors(v).forEach(u => {
|
|
84
92
|
let uNode = g.node(u);
|
|
85
|
-
if (uNode.dummy &&
|
|
93
|
+
if (uNode.dummy &&
|
|
94
|
+
(uNode.order < prevNorthBorder || uNode.order > nextNorthBorder)) {
|
|
86
95
|
addConflict(conflicts, u, v);
|
|
87
96
|
}
|
|
88
97
|
});
|
|
89
98
|
}
|
|
90
99
|
});
|
|
91
100
|
}
|
|
101
|
+
|
|
102
|
+
|
|
92
103
|
function visitLayer(north, south) {
|
|
93
104
|
let prevNorthPos = -1,
|
|
94
105
|
nextNorthPos,
|
|
95
106
|
southPos = 0;
|
|
107
|
+
|
|
96
108
|
south.forEach((v, southLookahead) => {
|
|
97
109
|
if (g.node(v).dummy === "border") {
|
|
98
110
|
let predecessors = g.predecessors(v);
|
|
@@ -105,28 +117,35 @@ function findType2Conflicts(g, layering) {
|
|
|
105
117
|
}
|
|
106
118
|
scan(south, southPos, south.length, nextNorthPos, north.length);
|
|
107
119
|
});
|
|
120
|
+
|
|
108
121
|
return south;
|
|
109
122
|
}
|
|
123
|
+
|
|
110
124
|
layering.length && layering.reduce(visitLayer);
|
|
125
|
+
|
|
111
126
|
return conflicts;
|
|
112
127
|
}
|
|
128
|
+
|
|
113
129
|
function findOtherInnerSegmentNode(g, v) {
|
|
114
130
|
if (g.node(v).dummy) {
|
|
115
131
|
return g.predecessors(v).find(u => g.node(u).dummy);
|
|
116
132
|
}
|
|
117
133
|
}
|
|
134
|
+
|
|
118
135
|
function addConflict(conflicts, v, w) {
|
|
119
136
|
if (v > w) {
|
|
120
137
|
let tmp = v;
|
|
121
138
|
v = w;
|
|
122
139
|
w = tmp;
|
|
123
140
|
}
|
|
141
|
+
|
|
124
142
|
let conflictsV = conflicts[v];
|
|
125
143
|
if (!conflictsV) {
|
|
126
144
|
conflicts[v] = conflictsV = {};
|
|
127
145
|
}
|
|
128
146
|
conflictsV[w] = true;
|
|
129
147
|
}
|
|
148
|
+
|
|
130
149
|
function hasConflict(conflicts, v, w) {
|
|
131
150
|
if (v > w) {
|
|
132
151
|
let tmp = v;
|
|
@@ -159,6 +178,7 @@ function verticalAlignment(g, layering, conflicts, neighborFn) {
|
|
|
159
178
|
pos[v] = order;
|
|
160
179
|
});
|
|
161
180
|
});
|
|
181
|
+
|
|
162
182
|
layering.forEach(layer => {
|
|
163
183
|
let prevIdx = -1;
|
|
164
184
|
layer.forEach(v => {
|
|
@@ -168,7 +188,9 @@ function verticalAlignment(g, layering, conflicts, neighborFn) {
|
|
|
168
188
|
let mp = (ws.length - 1) / 2;
|
|
169
189
|
for (let i = Math.floor(mp), il = Math.ceil(mp); i <= il; ++i) {
|
|
170
190
|
let w = ws[i];
|
|
171
|
-
if (align[v] === v &&
|
|
191
|
+
if (align[v] === v &&
|
|
192
|
+
prevIdx < pos[w] &&
|
|
193
|
+
!hasConflict(conflicts, v, w)) {
|
|
172
194
|
align[w] = v;
|
|
173
195
|
align[v] = root[v] = root[w];
|
|
174
196
|
prevIdx = pos[w];
|
|
@@ -177,11 +199,10 @@ function verticalAlignment(g, layering, conflicts, neighborFn) {
|
|
|
177
199
|
}
|
|
178
200
|
});
|
|
179
201
|
});
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
align: align
|
|
183
|
-
};
|
|
202
|
+
|
|
203
|
+
return { root: root, align: align };
|
|
184
204
|
}
|
|
205
|
+
|
|
185
206
|
function horizontalCompaction(g, layering, root, align, reverseSep) {
|
|
186
207
|
// This portion of the algorithm differs from BK due to a number of problems.
|
|
187
208
|
// Instead of their algorithm we construct a new block graph and do two
|
|
@@ -191,6 +212,7 @@ function horizontalCompaction(g, layering, root, align, reverseSep) {
|
|
|
191
212
|
let xs = {},
|
|
192
213
|
blockG = buildBlockGraph(g, layering, root, reverseSep),
|
|
193
214
|
borderType = reverseSep ? "borderLeft" : "borderRight";
|
|
215
|
+
|
|
194
216
|
function iterate(setXsFunc, nextNodesFunc) {
|
|
195
217
|
let stack = blockG.nodes();
|
|
196
218
|
let elem = stack.pop();
|
|
@@ -203,6 +225,7 @@ function horizontalCompaction(g, layering, root, align, reverseSep) {
|
|
|
203
225
|
stack.push(elem);
|
|
204
226
|
stack = stack.concat(nextNodesFunc(elem));
|
|
205
227
|
}
|
|
228
|
+
|
|
206
229
|
elem = stack.pop();
|
|
207
230
|
}
|
|
208
231
|
}
|
|
@@ -219,22 +242,28 @@ function horizontalCompaction(g, layering, root, align, reverseSep) {
|
|
|
219
242
|
let min = blockG.outEdges(elem).reduce((acc, e) => {
|
|
220
243
|
return Math.min(acc, xs[e.w] - blockG.edge(e));
|
|
221
244
|
}, Number.POSITIVE_INFINITY);
|
|
245
|
+
|
|
222
246
|
let node = g.node(elem);
|
|
223
247
|
if (min !== Number.POSITIVE_INFINITY && node.borderType !== borderType) {
|
|
224
248
|
xs[elem] = Math.max(xs[elem], min);
|
|
225
249
|
}
|
|
226
250
|
}
|
|
251
|
+
|
|
227
252
|
iterate(pass1, blockG.predecessors.bind(blockG));
|
|
228
253
|
iterate(pass2, blockG.successors.bind(blockG));
|
|
229
254
|
|
|
230
255
|
// Assign x coordinates to all nodes
|
|
231
256
|
Object.keys(align).forEach(v => xs[v] = xs[root[v]]);
|
|
257
|
+
|
|
232
258
|
return xs;
|
|
233
259
|
}
|
|
260
|
+
|
|
261
|
+
|
|
234
262
|
function buildBlockGraph(g, layering, root, reverseSep) {
|
|
235
|
-
let blockGraph = new
|
|
263
|
+
let blockGraph = new Graph(),
|
|
236
264
|
graphLabel = g.graph(),
|
|
237
265
|
sepFn = sep(graphLabel.nodesep, graphLabel.edgesep, reverseSep);
|
|
266
|
+
|
|
238
267
|
layering.forEach(layer => {
|
|
239
268
|
let u;
|
|
240
269
|
layer.forEach(v => {
|
|
@@ -248,6 +277,7 @@ function buildBlockGraph(g, layering, root, reverseSep) {
|
|
|
248
277
|
u = v;
|
|
249
278
|
});
|
|
250
279
|
});
|
|
280
|
+
|
|
251
281
|
return blockGraph;
|
|
252
282
|
}
|
|
253
283
|
|
|
@@ -258,11 +288,14 @@ function findSmallestWidthAlignment(g, xss) {
|
|
|
258
288
|
return Object.values(xss).reduce((currentMinAndXs, xs) => {
|
|
259
289
|
let max = Number.NEGATIVE_INFINITY;
|
|
260
290
|
let min = Number.POSITIVE_INFINITY;
|
|
291
|
+
|
|
261
292
|
Object.entries(xs).forEach(([v, x]) => {
|
|
262
293
|
let halfWidth = width(g, v) / 2;
|
|
294
|
+
|
|
263
295
|
max = Math.max(x + halfWidth, max);
|
|
264
296
|
min = Math.min(x - halfWidth, min);
|
|
265
297
|
});
|
|
298
|
+
|
|
266
299
|
const newMin = max - min;
|
|
267
300
|
if (newMin < currentMinAndXs[0]) {
|
|
268
301
|
currentMinAndXs = [newMin, xs];
|
|
@@ -282,22 +315,27 @@ function alignCoordinates(xss, alignTo) {
|
|
|
282
315
|
let alignToVals = Object.values(alignTo),
|
|
283
316
|
alignToMin = Math.min(...alignToVals),
|
|
284
317
|
alignToMax = Math.max(...alignToVals);
|
|
318
|
+
|
|
285
319
|
["u", "d"].forEach(vert => {
|
|
286
320
|
["l", "r"].forEach(horiz => {
|
|
287
321
|
let alignment = vert + horiz,
|
|
288
322
|
xs = xss[alignment];
|
|
323
|
+
|
|
289
324
|
if (xs === alignTo) return;
|
|
325
|
+
|
|
290
326
|
let xsVals = Object.values(xs);
|
|
291
327
|
let delta = alignToMin - Math.min(...xsVals);
|
|
292
328
|
if (horiz !== "l") {
|
|
293
329
|
delta = alignToMax - Math.max(...xsVals);
|
|
294
330
|
}
|
|
331
|
+
|
|
295
332
|
if (delta) {
|
|
296
333
|
xss[alignment] = util.mapValues(xs, x => x + delta);
|
|
297
334
|
}
|
|
298
335
|
});
|
|
299
336
|
});
|
|
300
337
|
}
|
|
338
|
+
|
|
301
339
|
function balance(xss, align) {
|
|
302
340
|
return util.mapValues(xss.ul, (num, v) => {
|
|
303
341
|
if (align) {
|
|
@@ -308,9 +346,13 @@ function balance(xss, align) {
|
|
|
308
346
|
}
|
|
309
347
|
});
|
|
310
348
|
}
|
|
349
|
+
|
|
311
350
|
function positionX(g) {
|
|
312
351
|
let layering = util.buildLayerMatrix(g);
|
|
313
|
-
let conflicts = Object.assign(
|
|
352
|
+
let conflicts = Object.assign(
|
|
353
|
+
findType1Conflicts(g, layering),
|
|
354
|
+
findType2Conflicts(g, layering));
|
|
355
|
+
|
|
314
356
|
let xss = {};
|
|
315
357
|
let adjustedLayering;
|
|
316
358
|
["u", "d"].forEach(vert => {
|
|
@@ -321,60 +363,62 @@ function positionX(g) {
|
|
|
321
363
|
return Object.values(inner).reverse();
|
|
322
364
|
});
|
|
323
365
|
}
|
|
366
|
+
|
|
324
367
|
let neighborFn = (vert === "u" ? g.predecessors : g.successors).bind(g);
|
|
325
368
|
let align = verticalAlignment(g, adjustedLayering, conflicts, neighborFn);
|
|
326
|
-
let xs = horizontalCompaction(g, adjustedLayering,
|
|
369
|
+
let xs = horizontalCompaction(g, adjustedLayering,
|
|
370
|
+
align.root, align.align, horiz === "r");
|
|
327
371
|
if (horiz === "r") {
|
|
328
372
|
xs = util.mapValues(xs, x => -x);
|
|
329
373
|
}
|
|
330
374
|
xss[vert + horiz] = xs;
|
|
331
375
|
});
|
|
332
376
|
});
|
|
377
|
+
|
|
378
|
+
|
|
333
379
|
let smallestWidth = findSmallestWidthAlignment(g, xss);
|
|
334
380
|
alignCoordinates(xss, smallestWidth);
|
|
335
381
|
return balance(xss, g.graph().align);
|
|
336
382
|
}
|
|
383
|
+
|
|
337
384
|
function sep(nodeSep, edgeSep, reverseSep) {
|
|
338
385
|
return (g, v, w) => {
|
|
339
386
|
let vLabel = g.node(v);
|
|
340
387
|
let wLabel = g.node(w);
|
|
341
388
|
let sum = 0;
|
|
342
389
|
let delta;
|
|
390
|
+
|
|
343
391
|
sum += vLabel.width / 2;
|
|
344
392
|
if (vLabel.hasOwnProperty("labelpos")) {
|
|
345
393
|
switch (vLabel.labelpos.toLowerCase()) {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
break;
|
|
349
|
-
case "r":
|
|
350
|
-
delta = vLabel.width / 2;
|
|
351
|
-
break;
|
|
394
|
+
case "l": delta = -vLabel.width / 2; break;
|
|
395
|
+
case "r": delta = vLabel.width / 2; break;
|
|
352
396
|
}
|
|
353
397
|
}
|
|
354
398
|
if (delta) {
|
|
355
399
|
sum += reverseSep ? delta : -delta;
|
|
356
400
|
}
|
|
357
401
|
delta = 0;
|
|
402
|
+
|
|
358
403
|
sum += (vLabel.dummy ? edgeSep : nodeSep) / 2;
|
|
359
404
|
sum += (wLabel.dummy ? edgeSep : nodeSep) / 2;
|
|
405
|
+
|
|
360
406
|
sum += wLabel.width / 2;
|
|
361
407
|
if (wLabel.hasOwnProperty("labelpos")) {
|
|
362
408
|
switch (wLabel.labelpos.toLowerCase()) {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
break;
|
|
366
|
-
case "r":
|
|
367
|
-
delta = -wLabel.width / 2;
|
|
368
|
-
break;
|
|
409
|
+
case "l": delta = wLabel.width / 2; break;
|
|
410
|
+
case "r": delta = -wLabel.width / 2; break;
|
|
369
411
|
}
|
|
370
412
|
}
|
|
371
413
|
if (delta) {
|
|
372
414
|
sum += reverseSep ? delta : -delta;
|
|
373
415
|
}
|
|
374
416
|
delta = 0;
|
|
417
|
+
|
|
375
418
|
return sum;
|
|
376
419
|
};
|
|
377
420
|
}
|
|
421
|
+
|
|
378
422
|
function width(g, v) {
|
|
379
423
|
return g.node(v).width;
|
|
380
424
|
}
|
package/lib/position/index.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
exports
|
|
7
|
-
|
|
8
|
-
var _bk = require("./bk.js");
|
|
9
|
-
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
10
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
3
|
+
let util = require("../util");
|
|
4
|
+
let positionX = require("./bk").positionX;
|
|
5
|
+
|
|
6
|
+
module.exports = position;
|
|
7
|
+
|
|
11
8
|
function position(g) {
|
|
12
9
|
g = util.asNonCompoundGraph(g);
|
|
10
|
+
|
|
13
11
|
positionY(g);
|
|
14
|
-
Object.entries(
|
|
12
|
+
Object.entries(positionX(g)).forEach(([v, x]) => g.node(v).x = x);
|
|
15
13
|
}
|
|
14
|
+
|
|
16
15
|
function positionY(g) {
|
|
17
16
|
let layering = util.buildLayerMatrix(g);
|
|
18
17
|
let rankSep = g.graph().ranksep;
|
|
@@ -30,4 +29,4 @@ function positionY(g) {
|
|
|
30
29
|
prevY += maxHeight + rankSep;
|
|
31
30
|
});
|
|
32
31
|
}
|
|
33
|
-
|
|
32
|
+
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
exports
|
|
7
|
-
|
|
8
|
-
var _util = require("./util.js");
|
|
3
|
+
var Graph = require("@dagrejs/graphlib").Graph;
|
|
4
|
+
var slack = require("./util").slack;
|
|
5
|
+
|
|
6
|
+
module.exports = feasibleTree;
|
|
7
|
+
|
|
9
8
|
/*
|
|
10
9
|
* Constructs a spanning tree with tight edges and adjusted the input node's
|
|
11
10
|
* ranks to achieve this. A tight edge is one that is has a length that matches
|
|
@@ -32,20 +31,20 @@ var _util = require("./util.js");
|
|
|
32
31
|
* edges.
|
|
33
32
|
*/
|
|
34
33
|
function feasibleTree(g) {
|
|
35
|
-
var t = new
|
|
36
|
-
directed: false
|
|
37
|
-
});
|
|
34
|
+
var t = new Graph({ directed: false });
|
|
38
35
|
|
|
39
36
|
// Choose arbitrary node from which to start our tree
|
|
40
37
|
var start = g.nodes()[0];
|
|
41
38
|
var size = g.nodeCount();
|
|
42
39
|
t.setNode(start, {});
|
|
40
|
+
|
|
43
41
|
var edge, delta;
|
|
44
42
|
while (tightTree(t, g) < size) {
|
|
45
43
|
edge = findMinSlackEdge(t, g);
|
|
46
|
-
delta = t.hasNode(edge.v) ?
|
|
44
|
+
delta = t.hasNode(edge.v) ? slack(g, edge) : -slack(g, edge);
|
|
47
45
|
shiftRanks(t, g, delta);
|
|
48
46
|
}
|
|
47
|
+
|
|
49
48
|
return t;
|
|
50
49
|
}
|
|
51
50
|
|
|
@@ -57,14 +56,15 @@ function tightTree(t, g) {
|
|
|
57
56
|
function dfs(v) {
|
|
58
57
|
g.nodeEdges(v).forEach(e => {
|
|
59
58
|
var edgeV = e.v,
|
|
60
|
-
w = v === edgeV ? e.w : edgeV;
|
|
61
|
-
if (!t.hasNode(w) && !
|
|
59
|
+
w = (v === edgeV) ? e.w : edgeV;
|
|
60
|
+
if (!t.hasNode(w) && !slack(g, e)) {
|
|
62
61
|
t.setNode(w, {});
|
|
63
62
|
t.setEdge(v, w, {});
|
|
64
63
|
dfs(w);
|
|
65
64
|
}
|
|
66
65
|
});
|
|
67
66
|
}
|
|
67
|
+
|
|
68
68
|
t.nodes().forEach(dfs);
|
|
69
69
|
return t.nodeCount();
|
|
70
70
|
}
|
|
@@ -75,18 +75,21 @@ function tightTree(t, g) {
|
|
|
75
75
|
*/
|
|
76
76
|
function findMinSlackEdge(t, g) {
|
|
77
77
|
const edges = g.edges();
|
|
78
|
+
|
|
78
79
|
return edges.reduce((acc, edge) => {
|
|
79
80
|
let edgeSlack = Number.POSITIVE_INFINITY;
|
|
80
81
|
if (t.hasNode(edge.v) !== t.hasNode(edge.w)) {
|
|
81
|
-
edgeSlack =
|
|
82
|
+
edgeSlack = slack(g, edge);
|
|
82
83
|
}
|
|
84
|
+
|
|
83
85
|
if (edgeSlack < acc[0]) {
|
|
84
86
|
return [edgeSlack, edge];
|
|
85
87
|
}
|
|
88
|
+
|
|
86
89
|
return acc;
|
|
87
90
|
}, [Number.POSITIVE_INFINITY, null])[1];
|
|
88
91
|
}
|
|
92
|
+
|
|
89
93
|
function shiftRanks(t, g, delta) {
|
|
90
94
|
t.nodes().forEach(v => g.node(v).rank += delta);
|
|
91
95
|
}
|
|
92
|
-
module.exports = exports.default;
|
package/lib/rank/index.js
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = rank;
|
|
7
|
-
var rankUtil = _interopRequireWildcard(require("./util.js"));
|
|
8
|
-
var _feasibleTree = _interopRequireDefault(require("./feasible-tree.js"));
|
|
9
|
-
var _networkSimplex = _interopRequireDefault(require("./network-simplex.js"));
|
|
10
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
-
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
12
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
3
|
+
var rankUtil = require("./util");
|
|
13
4
|
var longestPath = rankUtil.longestPath;
|
|
5
|
+
var feasibleTree = require("./feasible-tree");
|
|
6
|
+
var networkSimplex = require("./network-simplex");
|
|
7
|
+
|
|
8
|
+
module.exports = rank;
|
|
9
|
+
|
|
14
10
|
/*
|
|
15
11
|
* Assigns a rank to each node in the input graph that respects the "minlen"
|
|
16
12
|
* constraint specified on edges between nodes.
|
|
@@ -31,28 +27,22 @@ var longestPath = rankUtil.longestPath;
|
|
|
31
27
|
* fix them up later.
|
|
32
28
|
*/
|
|
33
29
|
function rank(g) {
|
|
34
|
-
switch
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
tightTreeRanker(g);
|
|
40
|
-
break;
|
|
41
|
-
case "longest-path":
|
|
42
|
-
longestPathRanker(g);
|
|
43
|
-
break;
|
|
44
|
-
default:
|
|
45
|
-
networkSimplexRanker(g);
|
|
30
|
+
switch(g.graph().ranker) {
|
|
31
|
+
case "network-simplex": networkSimplexRanker(g); break;
|
|
32
|
+
case "tight-tree": tightTreeRanker(g); break;
|
|
33
|
+
case "longest-path": longestPathRanker(g); break;
|
|
34
|
+
default: networkSimplexRanker(g);
|
|
46
35
|
}
|
|
47
36
|
}
|
|
48
37
|
|
|
49
38
|
// A fast and simple ranker, but results are far from optimal.
|
|
50
39
|
var longestPathRanker = longestPath;
|
|
40
|
+
|
|
51
41
|
function tightTreeRanker(g) {
|
|
52
42
|
longestPath(g);
|
|
53
|
-
(
|
|
43
|
+
feasibleTree(g);
|
|
54
44
|
}
|
|
45
|
+
|
|
55
46
|
function networkSimplexRanker(g) {
|
|
56
|
-
(
|
|
47
|
+
networkSimplex(g);
|
|
57
48
|
}
|
|
58
|
-
module.exports = exports.default;
|