@knowvah/dot-engine 2.3.0 → 2.4.0
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/common/arith.d.ts +12 -0
- package/dist/common/arith.d.ts.map +1 -1
- package/dist/common/edge-in-box.d.ts +31 -0
- package/dist/common/edge-in-box.d.ts.map +1 -0
- package/dist/common/htmltable-emit.d.ts +1 -1
- package/dist/common/htmltable-emit.d.ts.map +1 -1
- package/dist/common/make-label.d.ts +3 -1
- package/dist/common/make-label.d.ts.map +1 -1
- package/dist/common/poly-gencode.d.ts +12 -1
- package/dist/common/poly-gencode.d.ts.map +1 -1
- package/dist/gvc/device.d.ts.map +1 -1
- package/dist/gvc/emit-gates.d.ts +35 -0
- package/dist/gvc/emit-gates.d.ts.map +1 -0
- package/dist/gvc/job.d.ts +4 -0
- package/dist/gvc/job.d.ts.map +1 -1
- package/dist/gvc/viewport.d.ts +13 -0
- package/dist/gvc/viewport.d.ts.map +1 -1
- package/dist/index.js +1030 -742
- package/dist/index.js.map +4 -4
- package/dist/layout/circo/blockpath.d.ts +1 -38
- package/dist/layout/circo/blockpath.d.ts.map +1 -1
- package/dist/layout/circo/crossings.d.ts +59 -0
- package/dist/layout/circo/crossings.d.ts.map +1 -0
- package/dist/layout/dot/edge-route-chain.d.ts +5 -3
- package/dist/layout/dot/edge-route-chain.d.ts.map +1 -1
- package/dist/layout/dot/edge-route.d.ts.map +1 -1
- package/dist/layout/dot/index.d.ts +10 -2
- package/dist/layout/dot/index.d.ts.map +1 -1
- package/dist/layout/dot/ortho-adapter.d.ts +7 -3
- package/dist/layout/dot/ortho-adapter.d.ts.map +1 -1
- package/dist/layout/dot/pack-components.d.ts +4 -1
- package/dist/layout/dot/pack-components.d.ts.map +1 -1
- package/dist/layout/dot/splines-flat-multi.d.ts +7 -5
- package/dist/layout/dot/splines-flat-multi.d.ts.map +1 -1
- package/dist/layout/dot/splines-flat.d.ts +2 -13
- package/dist/layout/dot/splines-flat.d.ts.map +1 -1
- package/dist/layout/dot/splines-route.d.ts.map +1 -1
- package/dist/layout/neato/constraint-adjust.d.ts +32 -0
- package/dist/layout/neato/constraint-adjust.d.ts.map +1 -1
- package/dist/layout/neato/multispline.d.ts.map +1 -1
- package/dist/layout/neato/splines.d.ts.map +1 -1
- package/dist/layout/pack/poly-place.d.ts.map +1 -1
- package/dist/layout/sfdp/__fixtures__/pcp-rotate-native.d.ts +23 -0
- package/dist/layout/sfdp/__fixtures__/pcp-rotate-native.d.ts.map +1 -0
- package/dist/layout/sfdp/spring-driver.d.ts +6 -0
- package/dist/layout/sfdp/spring-driver.d.ts.map +1 -1
- package/dist/ortho/index.d.ts +4 -1
- package/dist/ortho/index.d.ts.map +1 -1
- package/dist/ortho/maze.d.ts +5 -2
- package/dist/ortho/maze.d.ts.map +1 -1
- package/dist/ortho/partition.d.ts +8 -1
- package/dist/ortho/partition.d.ts.map +1 -1
- package/dist/ortho/trap-segment.d.ts +2 -1
- package/dist/ortho/trap-segment.d.ts.map +1 -1
- package/dist/ortho/trapezoid.d.ts.map +1 -1
- package/dist/parser/index.d.ts +0 -7
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/number-scan.d.ts +31 -0
- package/dist/parser/number-scan.d.ts.map +1 -0
- package/dist/pathplan/route.d.ts.map +1 -1
- package/dist/pathplan/solvers.d.ts +15 -3
- package/dist/pathplan/solvers.d.ts.map +1 -1
- package/dist/render/dot/edge-draw.d.ts +12 -0
- package/dist/render/dot/edge-draw.d.ts.map +1 -1
- package/dist/render/svg-graph.d.ts +6 -5
- package/dist/render/svg-graph.d.ts.map +1 -1
- package/dist/render/svg.d.ts +2 -21
- package/dist/render/svg.d.ts.map +1 -1
- package/dist/render.js +1030 -742
- package/dist/render.js.map +4 -4
- package/dist/xdot/parse.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/common/arith.ts +25 -0
- package/src/common/edge-in-box.ts +54 -0
- package/src/common/graph-init.ts +3 -3
- package/src/common/htmltable-emit.ts +4 -2
- package/src/common/make-label.ts +3 -1
- package/src/common/poly-gencode.ts +18 -4
- package/src/gvc/device.ts +8 -41
- package/src/gvc/edge-labels.ts +30 -13
- package/src/gvc/emit-gates.ts +89 -0
- package/src/gvc/job.ts +4 -0
- package/src/gvc/viewport.ts +29 -0
- package/src/layout/circo/blockpath.ts +6 -125
- package/src/layout/circo/crossings.ts +171 -0
- package/src/layout/dot/__fixtures__/2784.dot +1 -0
- package/src/layout/dot/__fixtures__/2784.native-16.1.svg +48 -0
- package/src/layout/dot/edge-route-chain.ts +11 -5
- package/src/layout/dot/edge-route.ts +19 -8
- package/src/layout/dot/index.ts +14 -4
- package/src/layout/dot/ortho-adapter.ts +11 -6
- package/src/layout/dot/pack-components.ts +11 -4
- package/src/layout/dot/splines-flat-multi.ts +21 -8
- package/src/layout/dot/splines-flat.ts +8 -35
- package/src/layout/dot/splines-route.ts +10 -2
- package/src/layout/dot/splines.ts +6 -6
- package/src/layout/neato/constraint-adjust.ts +10 -4
- package/src/layout/neato/multispline.ts +26 -9
- package/src/layout/neato/splines.ts +7 -7
- package/src/layout/pack/poly-place.ts +9 -2
- package/src/layout/sfdp/__fixtures__/pcp-rotate-native.ts +94 -0
- package/src/layout/sfdp/spring-driver.ts +45 -13
- package/src/ortho/index.ts +22 -13
- package/src/ortho/maze.ts +8 -2
- package/src/ortho/partition.ts +17 -2
- package/src/ortho/trap-segment.ts +47 -24
- package/src/ortho/trapezoid.ts +24 -15
- package/src/parser/dot.js +345 -380
- package/src/parser/dot.pegjs +25 -10
- package/src/parser/index.ts +15 -0
- package/src/parser/number-scan.ts +118 -0
- package/src/pathplan/route.ts +79 -34
- package/src/pathplan/solvers.ts +78 -50
- package/src/render/dot/edge-draw.ts +25 -0
- package/src/render/svg-graph.ts +77 -47
- package/src/render/svg-helpers.ts +2 -2
- package/src/render/svg.ts +4 -41
- package/src/xdot/parse.ts +19 -5
|
@@ -198,6 +198,7 @@ export function swapSegEndpoints(s: SegmentT): void {
|
|
|
198
198
|
|
|
199
199
|
/**
|
|
200
200
|
* Insert one segment into the trapezoidation.
|
|
201
|
+
* @returns 0 on success, -1 when threading met an invalid trapezoid (16.1)
|
|
201
202
|
* @see lib/ortho/trapezoid.c:add_segment
|
|
202
203
|
*/
|
|
203
204
|
export function addSegment(
|
|
@@ -205,7 +206,7 @@ export function addSegment(
|
|
|
205
206
|
seg: SegmentT[],
|
|
206
207
|
tr: TrapT[],
|
|
207
208
|
qs: QNode[],
|
|
208
|
-
):
|
|
209
|
+
): number {
|
|
209
210
|
const s = { ...seg[segnum] };
|
|
210
211
|
let isSwapped = false;
|
|
211
212
|
if (greaterThanOrEq(s.v1, s.v0) && !equalTo(s.v1, s.v0)) {
|
|
@@ -214,31 +215,49 @@ export function addSegment(
|
|
|
214
215
|
isSwapped = true;
|
|
215
216
|
}
|
|
216
217
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
218
|
+
const ctx: ThreadCtx = { s, seg, tr, qs, segnum, tribot: false, isSwapped };
|
|
219
|
+
const tfirst = firstTrap(ctx);
|
|
220
|
+
const tlast = lastTrap(ctx);
|
|
221
|
+
if (threadSegment(ctx, tfirst, tlast) !== 0) return -1;
|
|
222
|
+
seg[segnum].isInserted = true;
|
|
223
|
+
return 0;
|
|
224
|
+
}
|
|
223
225
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
226
|
+
/** add_segment locals the threading loop reads (one C stack frame). */
|
|
227
|
+
interface ThreadCtx {
|
|
228
|
+
s: SegmentT; seg: SegmentT[]; tr: TrapT[]; qs: QNode[];
|
|
229
|
+
segnum: number; tribot: boolean; isSwapped: boolean;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** add_segment: insert v0 in the tree, or locate it if already present. */
|
|
233
|
+
function firstTrap(c: ThreadCtx): number {
|
|
234
|
+
if (!inserted(c.segnum, c.seg, c.isSwapped ? LASTPT : FIRSTPT)) {
|
|
235
|
+
return insertV0(c.s, c.seg, c.tr, c.qs, c.segnum);
|
|
231
236
|
}
|
|
237
|
+
return locateEndpoint(c.s.v0, c.s.v1, c.s.root0, c.seg, c.qs);
|
|
238
|
+
}
|
|
232
239
|
|
|
233
|
-
|
|
234
|
-
|
|
240
|
+
/**
|
|
241
|
+
* add_segment: insert v1 in the tree, or (v1 already present) get the
|
|
242
|
+
* lowermost intersecting trapezoid and mark the bottom as a triangle.
|
|
243
|
+
*/
|
|
244
|
+
function lastTrap(c: ThreadCtx): number {
|
|
245
|
+
if (!inserted(c.segnum, c.seg, c.isSwapped ? FIRSTPT : LASTPT)) {
|
|
246
|
+
return insertV1(c.s, c.seg, c.tr, c.qs, c.segnum);
|
|
247
|
+
}
|
|
248
|
+
c.tribot = true;
|
|
249
|
+
return locateEndpoint(c.s.v1, c.s.v0, c.s.root1, c.seg, c.qs);
|
|
235
250
|
}
|
|
236
251
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
252
|
+
/**
|
|
253
|
+
* Split every trapezoid s crosses, top to bottom, then merge both sides.
|
|
254
|
+
* Returns -1 (after C's stderr line) when a crossed trapezoid has no valid
|
|
255
|
+
* lower neighbour — graphviz 16.1 (3c01aaeb4) returns from add_segment there;
|
|
256
|
+
* 15.x printed "add_segment: error" and broke out of the loop.
|
|
257
|
+
* @see lib/ortho/trapezoid.c:add_segment (threading loop)
|
|
258
|
+
*/
|
|
259
|
+
function threadSegment(c: ThreadCtx, tfirst: number, tlast: number): number {
|
|
260
|
+
const { s, seg, tr, qs, segnum, tribot, isSwapped } = c;
|
|
242
261
|
let tfirstr = INVALID_TRAP;
|
|
243
262
|
let tlastr = INVALID_TRAP;
|
|
244
263
|
let t = tfirst;
|
|
@@ -258,12 +277,17 @@ function threadSegment(
|
|
|
258
277
|
if (equalTo(tr[t].lo, tr[tlast].lo)) tlastr = tn;
|
|
259
278
|
|
|
260
279
|
const tSav = t; const tnSav = tn;
|
|
280
|
+
if (!isValidTrap(tr[t].d0) && !isValidTrap(tr[t].d1)) { // error
|
|
281
|
+
console.error("trapezoid segment construction failed");
|
|
282
|
+
return -1;
|
|
283
|
+
}
|
|
261
284
|
t = advanceT(s, seg, tr, t, tn, tlast, segnum, isSwapped, tribot);
|
|
262
285
|
tr[tSav].rseg = segnum; tr[tnSav].lseg = segnum;
|
|
263
286
|
}
|
|
264
287
|
|
|
265
288
|
mergeTrapezoids(segnum, tfirst, tlast, S_LEFT, tr, qs);
|
|
266
289
|
mergeTrapezoids(segnum, tfirstr, tlastr, S_RIGHT, tr, qs);
|
|
290
|
+
return 0;
|
|
267
291
|
}
|
|
268
292
|
|
|
269
293
|
function advanceT(
|
|
@@ -271,9 +295,8 @@ function advanceT(
|
|
|
271
295
|
t: number, tn: number, tlast: number,
|
|
272
296
|
segnum: number, isSwapped: boolean, tribot: boolean,
|
|
273
297
|
): number {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
} else if (isValidTrap(tr[t].d0) && !isValidTrap(tr[t].d1)) {
|
|
298
|
+
// The "neither below is valid" error case returns from threadSegment first.
|
|
299
|
+
if (isValidTrap(tr[t].d0) && !isValidTrap(tr[t].d1)) {
|
|
277
300
|
handleD0Only(s, seg, tr, t, tn, tlast, segnum, isSwapped, tribot);
|
|
278
301
|
return tr[t].d0;
|
|
279
302
|
} else if (!isValidTrap(tr[t].d0) && isValidTrap(tr[t].d1)) {
|
package/src/ortho/trapezoid.ts
CHANGED
|
@@ -31,29 +31,20 @@ export function constructTrapezoids(
|
|
|
31
31
|
permute: number[],
|
|
32
32
|
): TrapT[] {
|
|
33
33
|
const qs: QNode[] = [];
|
|
34
|
-
const tr: TrapT[] = [];
|
|
35
|
-
// index 0 is a sentinel (invalid trap)
|
|
36
|
-
tr.push({
|
|
37
|
-
lseg: 0, rseg: 0,
|
|
38
|
-
hi: { x: 0, y: 0 }, lo: { x: 0, y: 0 },
|
|
39
|
-
u0: 0, u1: 0, d0: 0, d1: 0,
|
|
40
|
-
sink: 0, usave: 0, uside: 0, isValid: false,
|
|
41
|
-
});
|
|
34
|
+
const tr: TrapT[] = [sentinelTrap()];
|
|
42
35
|
|
|
43
36
|
let segi = 0;
|
|
44
37
|
const root = initQueryStructure(permute[segi++], seg, tr, qs);
|
|
38
|
+
seedRoots(nseg, seg, root);
|
|
45
39
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
seg[i].root1 = root;
|
|
49
|
-
}
|
|
50
|
-
|
|
40
|
+
// C (16.1, 3660b260e): an add_segment failure LIST_FREEs the trapezoid list
|
|
41
|
+
// and jumps to `done`, so the caller receives an EMPTY list.
|
|
51
42
|
const logstar = mathLogstarN(nseg);
|
|
52
43
|
for (let h = 1; h <= logstar; h++) {
|
|
53
44
|
const lo = mathN(nseg, h - 1) + 1;
|
|
54
45
|
const hi = mathN(nseg, h);
|
|
55
46
|
for (let i = lo; i <= hi; i++) {
|
|
56
|
-
addSegment(permute[segi++], seg, tr, qs);
|
|
47
|
+
if (addSegment(permute[segi++], seg, tr, qs) !== 0) return [];
|
|
57
48
|
}
|
|
58
49
|
for (let i = 1; i <= nseg; i++) {
|
|
59
50
|
findNewRoots(i, seg, tr, qs);
|
|
@@ -62,12 +53,30 @@ export function constructTrapezoids(
|
|
|
62
53
|
|
|
63
54
|
const remaining = mathN(nseg, logstar) + 1;
|
|
64
55
|
for (let i = remaining; i <= nseg; i++) {
|
|
65
|
-
addSegment(permute[segi++], seg, tr, qs);
|
|
56
|
+
if (addSegment(permute[segi++], seg, tr, qs) !== 0) return [];
|
|
66
57
|
}
|
|
67
58
|
|
|
68
59
|
return tr;
|
|
69
60
|
}
|
|
70
61
|
|
|
62
|
+
/** Index 0 of the trapezoid list is a sentinel (invalid trap). */
|
|
63
|
+
function sentinelTrap(): TrapT {
|
|
64
|
+
return {
|
|
65
|
+
lseg: 0, rseg: 0,
|
|
66
|
+
hi: { x: 0, y: 0 }, lo: { x: 0, y: 0 },
|
|
67
|
+
u0: 0, u1: 0, d0: 0, d1: 0,
|
|
68
|
+
sink: 0, usave: 0, uside: 0, isValid: false,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** construct_trapezoids: every segment starts at the initial query root. */
|
|
73
|
+
function seedRoots(nseg: number, seg: SegmentT[], root: number): void {
|
|
74
|
+
for (let i = 1; i <= nseg; i++) {
|
|
75
|
+
seg[i].root0 = root;
|
|
76
|
+
seg[i].root1 = root;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
71
80
|
// ─── init_query_structure ─────────────────────────────────────────────────────
|
|
72
81
|
|
|
73
82
|
import {
|