@knowvah/dot-engine 1.6.0 → 1.6.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/api/geometry.d.ts +5 -2
- package/dist/api/geometry.d.ts.map +1 -1
- package/dist/api.js +2 -4
- package/dist/api.js.map +2 -2
- package/dist/cdt/splay.d.ts.map +1 -1
- package/dist/common/htmltable-emit-rules.d.ts.map +1 -1
- package/dist/common/shape-clip.d.ts +17 -0
- package/dist/common/shape-clip.d.ts.map +1 -0
- package/dist/index.js +599 -578
- package/dist/index.js.map +4 -4
- package/dist/layout/dot/edge-route.d.ts.map +1 -1
- package/dist/layout/dot/pack-components.d.ts.map +1 -1
- package/dist/layout/dot/sameport.d.ts +1 -13
- package/dist/layout/dot/sameport.d.ts.map +1 -1
- package/dist/layout/dot/self-loop.d.ts.map +1 -1
- package/dist/layout/dot/splines-groups.d.ts.map +1 -1
- package/dist/layout/neato/index.d.ts.map +1 -1
- package/dist/layout/neato/init.d.ts.map +1 -1
- package/dist/ortho/ortho-route.d.ts.map +1 -1
- package/dist/render/dot.d.ts.map +1 -1
- package/dist/render.js +1209 -1186
- package/dist/render.js.map +4 -4
- package/package.json +14 -5
- package/src/api/geometry.ts +8 -7
- package/src/cdt/splay.ts +0 -2
- package/src/common/arm-pow.ts +3 -3
- package/src/common/htmltable-emit-rules.ts +0 -10
- package/src/common/random.ts +2 -2
- package/src/common/shape-clip.ts +48 -0
- package/src/common/spline-midpoint.ts +1 -1
- package/src/layout/circo/circular.ts +1 -1
- package/src/layout/dot/edge-route.ts +18 -6
- package/src/layout/dot/ns.ts +1 -1
- package/src/layout/dot/pack-components.ts +0 -1
- package/src/layout/dot/sameport.ts +1 -25
- package/src/layout/dot/self-loop.ts +4 -2
- package/src/layout/dot/splines-flat-labeled.ts +1 -1
- package/src/layout/dot/splines-groups.ts +8 -1
- package/src/layout/neato/cdt-surface.ts +1 -1
- package/src/layout/neato/index.ts +0 -3
- package/src/layout/neato/init.ts +0 -1
- package/src/ortho/ortho-route.ts +1 -3
- package/src/ortho/trap-query.ts +1 -1
- package/src/render/dot.ts +3 -10
- package/src/vpsc/Solver.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -19894,7 +19894,7 @@ function leaveEdge(ctx) {
|
|
|
19894
19894
|
}
|
|
19895
19895
|
if (j > 0) {
|
|
19896
19896
|
ctx.sI = 0;
|
|
19897
|
-
[rv
|
|
19897
|
+
[rv] = leaveEdgeScan(ctx, j, cnt, rv);
|
|
19898
19898
|
}
|
|
19899
19899
|
return rv;
|
|
19900
19900
|
}
|
|
@@ -28461,6 +28461,393 @@ function dotPosition(g) {
|
|
|
28461
28461
|
return 0;
|
|
28462
28462
|
}
|
|
28463
28463
|
|
|
28464
|
+
// src/common/shape-clip.ts
|
|
28465
|
+
function shapeClip0(ctx, insidefn, n, curve, leftInside) {
|
|
28466
|
+
const saveRealSize = n.info.rw;
|
|
28467
|
+
const c = curve.map((p) => ({ x: p.x - n.info.coord.x, y: p.y - n.info.coord.y }));
|
|
28468
|
+
bezierClip(ctx, insidefn, c, leftInside);
|
|
28469
|
+
for (let i = 0; i < 4; i++) {
|
|
28470
|
+
curve[i] = { x: c[i].x + n.info.coord.x, y: c[i].y + n.info.coord.y };
|
|
28471
|
+
}
|
|
28472
|
+
n.info.rw = saveRealSize;
|
|
28473
|
+
}
|
|
28474
|
+
function shapeClip(n, curve) {
|
|
28475
|
+
const insidefn = n.info.shape?.fns?.insidefn ?? null;
|
|
28476
|
+
if (insidefn === null) return;
|
|
28477
|
+
const ctx = { nodeCoord: n.info.coord, rw: n.info.rw, bp: null, node: n };
|
|
28478
|
+
const saveRealSize = n.info.rw;
|
|
28479
|
+
const leftInside = insidefn(ctx, { x: curve[0].x - n.info.coord.x, y: curve[0].y - n.info.coord.y });
|
|
28480
|
+
n.info.rw = saveRealSize;
|
|
28481
|
+
shapeClip0(ctx, insidefn, n, curve, leftInside);
|
|
28482
|
+
}
|
|
28483
|
+
|
|
28484
|
+
// src/layout/dot/sameport.ts
|
|
28485
|
+
function sameedge(same, e, id) {
|
|
28486
|
+
for (const grp of same) {
|
|
28487
|
+
if (grp.id === id) {
|
|
28488
|
+
grp.edges.push(e);
|
|
28489
|
+
return;
|
|
28490
|
+
}
|
|
28491
|
+
}
|
|
28492
|
+
same.push({ id, edges: [e] });
|
|
28493
|
+
}
|
|
28494
|
+
function computeBoundaryOffset(u, x, y, ranksep) {
|
|
28495
|
+
const r = Math.max(
|
|
28496
|
+
(u.info.lw ?? 0) + (u.info.rw ?? 0),
|
|
28497
|
+
(u.info.ht ?? 0) + ranksep
|
|
28498
|
+
);
|
|
28499
|
+
const x2 = x * r + u.info.coord.x;
|
|
28500
|
+
const y2 = y * r + u.info.coord.y;
|
|
28501
|
+
const curve = [
|
|
28502
|
+
{ x: u.info.coord.x, y: u.info.coord.y },
|
|
28503
|
+
{ x: (2 * u.info.coord.x + x2) / 3, y: (2 * u.info.coord.y + y2) / 3 },
|
|
28504
|
+
{ x: (2 * x2 + u.info.coord.x) / 3, y: (2 * y2 + u.info.coord.y) / 3 },
|
|
28505
|
+
{ x: x2, y: y2 }
|
|
28506
|
+
];
|
|
28507
|
+
shapeClip(u, curve);
|
|
28508
|
+
return {
|
|
28509
|
+
x1: curve[0].x - u.info.coord.x,
|
|
28510
|
+
y1: curve[0].y - u.info.coord.y
|
|
28511
|
+
};
|
|
28512
|
+
}
|
|
28513
|
+
function averageDirection(u, edges) {
|
|
28514
|
+
let sx = 0, sy = 0;
|
|
28515
|
+
for (const e of edges) {
|
|
28516
|
+
const v = e.head === u ? e.tail : e.head;
|
|
28517
|
+
const dx = v.info.coord.x - u.info.coord.x;
|
|
28518
|
+
const dy = v.info.coord.y - u.info.coord.y;
|
|
28519
|
+
const r2 = Math.hypot(dx, dy);
|
|
28520
|
+
if (r2 !== 0) {
|
|
28521
|
+
sx += dx / r2;
|
|
28522
|
+
sy += dy / r2;
|
|
28523
|
+
}
|
|
28524
|
+
}
|
|
28525
|
+
const r = Math.hypot(sx, sy);
|
|
28526
|
+
return r !== 0 ? { x: sx / r, y: sy / r } : { x: 0, y: 0 };
|
|
28527
|
+
}
|
|
28528
|
+
function buildSharedPort(u, edges, ranksep) {
|
|
28529
|
+
const dir = averageDirection(u, edges);
|
|
28530
|
+
const { x1, y1 } = computeBoundaryOffset(u, dir.x, dir.y, ranksep);
|
|
28531
|
+
const px = cround(x1);
|
|
28532
|
+
const py = cround(y1);
|
|
28533
|
+
const lw = u.info.lw ?? 0;
|
|
28534
|
+
const rw = u.info.rw ?? 0;
|
|
28535
|
+
const order = lw + rw !== 0 ? MC_SCALE * (lw + px) / (lw + rw) : 0;
|
|
28536
|
+
return {
|
|
28537
|
+
p: { x: px, y: py },
|
|
28538
|
+
theta: 0,
|
|
28539
|
+
bp: null,
|
|
28540
|
+
defined: true,
|
|
28541
|
+
constrained: false,
|
|
28542
|
+
clip: false,
|
|
28543
|
+
dyna: false,
|
|
28544
|
+
order,
|
|
28545
|
+
side: 0,
|
|
28546
|
+
name: null
|
|
28547
|
+
};
|
|
28548
|
+
}
|
|
28549
|
+
function assignHeadIfMatch(f, u, prt) {
|
|
28550
|
+
if (f.head === u) f.info.head_port = prt;
|
|
28551
|
+
if (f.tail === u) f.info.tail_port = prt;
|
|
28552
|
+
}
|
|
28553
|
+
function assignPortForwardChain(e, u, prt) {
|
|
28554
|
+
for (let f = e; f !== void 0; f = (f.info.edge_type ?? 0) === VIRTUAL && (f.head.info.node_type ?? 0) === VIRTUAL && (f.head.info.out?.size ?? 0) === 1 ? f.head.info.out.list[0] : void 0) {
|
|
28555
|
+
assignHeadIfMatch(f, u, prt);
|
|
28556
|
+
}
|
|
28557
|
+
}
|
|
28558
|
+
function assignPortBackwardChain(e, u, prt) {
|
|
28559
|
+
for (let f = e; f !== void 0; f = (f.info.edge_type ?? 0) === VIRTUAL && (f.tail.info.node_type ?? 0) === VIRTUAL && (f.tail.info.in?.size ?? 0) === 1 ? f.tail.info.in.list[0] : void 0) {
|
|
28560
|
+
assignHeadIfMatch(f, u, prt);
|
|
28561
|
+
}
|
|
28562
|
+
}
|
|
28563
|
+
function assignPortToAllVirts(e, u, prt) {
|
|
28564
|
+
for (let virt = e; virt !== void 0; virt = virt.info.to_virt) {
|
|
28565
|
+
assignPortForwardChain(virt, u, prt);
|
|
28566
|
+
assignPortBackwardChain(virt, u, prt);
|
|
28567
|
+
}
|
|
28568
|
+
}
|
|
28569
|
+
function sameport(u, edges, ranksep) {
|
|
28570
|
+
if (edges.length < 2) return;
|
|
28571
|
+
const prt = buildSharedPort(u, edges, ranksep);
|
|
28572
|
+
for (const e of edges) assignPortToAllVirts(e, u, prt);
|
|
28573
|
+
u.info.has_port = true;
|
|
28574
|
+
}
|
|
28575
|
+
function graphHasSamehead(g) {
|
|
28576
|
+
for (const e of g.edges) {
|
|
28577
|
+
if (e.info.samehead !== void 0) return true;
|
|
28578
|
+
}
|
|
28579
|
+
return false;
|
|
28580
|
+
}
|
|
28581
|
+
function graphHasSametail(g) {
|
|
28582
|
+
for (const e of g.edges) {
|
|
28583
|
+
if (e.info.sametail !== void 0) return true;
|
|
28584
|
+
}
|
|
28585
|
+
return false;
|
|
28586
|
+
}
|
|
28587
|
+
function collectSamehead(n) {
|
|
28588
|
+
const same = [];
|
|
28589
|
+
for (const e of n.root.edges) {
|
|
28590
|
+
if (e.head === n && e.tail === n) continue;
|
|
28591
|
+
const id = e.head === n ? e.info.samehead : void 0;
|
|
28592
|
+
if (id && id !== "") sameedge(same, e, id);
|
|
28593
|
+
}
|
|
28594
|
+
return same;
|
|
28595
|
+
}
|
|
28596
|
+
function collectSametail(n) {
|
|
28597
|
+
const same = [];
|
|
28598
|
+
for (const e of n.root.edges) {
|
|
28599
|
+
if (e.head === n && e.tail === n) continue;
|
|
28600
|
+
const id = e.tail === n ? e.info.sametail : void 0;
|
|
28601
|
+
if (id && id !== "") sameedge(same, e, id);
|
|
28602
|
+
}
|
|
28603
|
+
return same;
|
|
28604
|
+
}
|
|
28605
|
+
function applyGroupsToNode(n, groups, ranksep) {
|
|
28606
|
+
for (const grp of groups) {
|
|
28607
|
+
if (grp.edges.length > 1) sameport(n, grp.edges, ranksep);
|
|
28608
|
+
}
|
|
28609
|
+
}
|
|
28610
|
+
function dotSameports(g) {
|
|
28611
|
+
const hasSH = graphHasSamehead(g);
|
|
28612
|
+
const hasST = graphHasSametail(g);
|
|
28613
|
+
if (!hasSH && !hasST) return;
|
|
28614
|
+
const ranksep = g.info.ranksep ?? 0;
|
|
28615
|
+
for (const n of nodesInSeq(g)) {
|
|
28616
|
+
if (hasSH) applyGroupsToNode(n, collectSamehead(n), ranksep);
|
|
28617
|
+
if (hasST) applyGroupsToNode(n, collectSametail(n), ranksep);
|
|
28618
|
+
}
|
|
28619
|
+
}
|
|
28620
|
+
|
|
28621
|
+
// src/common/spline-midpoint.ts
|
|
28622
|
+
function dist2(p, q) {
|
|
28623
|
+
const dx = p.x - q.x;
|
|
28624
|
+
const dy = p.y - q.y;
|
|
28625
|
+
return dx * dx + dy * dy;
|
|
28626
|
+
}
|
|
28627
|
+
function distPt(p, q) {
|
|
28628
|
+
return Math.sqrt(dist2(p, q));
|
|
28629
|
+
}
|
|
28630
|
+
function evalBez4(pts, t) {
|
|
28631
|
+
const u = 1 - t;
|
|
28632
|
+
const [p0, p1, p2, p3] = pts;
|
|
28633
|
+
return {
|
|
28634
|
+
x: u * u * u * p0.x + 3 * u * u * t * p1.x + 3 * u * t * t * p2.x + t * t * t * p3.x,
|
|
28635
|
+
y: u * u * u * p0.y + 3 * u * u * t * p1.y + 3 * u * t * t * p2.y + t * t * t * p3.y
|
|
28636
|
+
};
|
|
28637
|
+
}
|
|
28638
|
+
function dotneatoClosest(spl, pt) {
|
|
28639
|
+
let besti = 0;
|
|
28640
|
+
let bestj = -1;
|
|
28641
|
+
let bestd2 = Number.MAX_VALUE;
|
|
28642
|
+
for (let i = 0; i < spl.list.length; i++) {
|
|
28643
|
+
const bz2 = spl.list[i];
|
|
28644
|
+
const n = bz2.size ?? bz2.list.length;
|
|
28645
|
+
for (let j2 = 0; j2 < n; j2++) {
|
|
28646
|
+
const d2 = dist2(bz2.list[j2], pt);
|
|
28647
|
+
if (bestj === -1 || d2 < bestd2) {
|
|
28648
|
+
besti = i;
|
|
28649
|
+
bestj = j2;
|
|
28650
|
+
bestd2 = d2;
|
|
28651
|
+
}
|
|
28652
|
+
}
|
|
28653
|
+
}
|
|
28654
|
+
const bz = spl.list[besti];
|
|
28655
|
+
const bzn = bz.size ?? bz.list.length;
|
|
28656
|
+
let j = bestj === bzn - 1 ? bestj - 1 : bestj;
|
|
28657
|
+
j = 3 * Math.floor(j / 3);
|
|
28658
|
+
const c = [bz.list[j], bz.list[j + 1], bz.list[j + 2], bz.list[j + 3]];
|
|
28659
|
+
let lo = 0;
|
|
28660
|
+
let hi = 1;
|
|
28661
|
+
let dlo2 = dist2(c[0], pt);
|
|
28662
|
+
let dhi2 = dist2(c[3], pt);
|
|
28663
|
+
let pt2;
|
|
28664
|
+
for (; ; ) {
|
|
28665
|
+
const t = (lo + hi) / 2;
|
|
28666
|
+
pt2 = evalBez4(c, t);
|
|
28667
|
+
if (Math.abs(dlo2 - dhi2) < 1 || Math.abs(hi - lo) < 1e-5) break;
|
|
28668
|
+
if (dlo2 < dhi2) {
|
|
28669
|
+
hi = t;
|
|
28670
|
+
dhi2 = dist2(pt2, pt);
|
|
28671
|
+
} else {
|
|
28672
|
+
lo = t;
|
|
28673
|
+
dlo2 = dist2(pt2, pt);
|
|
28674
|
+
}
|
|
28675
|
+
}
|
|
28676
|
+
return pt2;
|
|
28677
|
+
}
|
|
28678
|
+
function polylineMidpoint(spl) {
|
|
28679
|
+
let total = 0;
|
|
28680
|
+
for (const bz of spl.list) {
|
|
28681
|
+
for (let j = 0, k = 3; k < bz.list.length; j += 3, k += 3)
|
|
28682
|
+
total += distPt(bz.list[j], bz.list[k]);
|
|
28683
|
+
}
|
|
28684
|
+
total /= 2;
|
|
28685
|
+
for (const bz of spl.list) {
|
|
28686
|
+
for (let j = 0, k = 3; k < bz.list.length; j += 3, k += 3) {
|
|
28687
|
+
const pf = bz.list[j];
|
|
28688
|
+
const qf = bz.list[k];
|
|
28689
|
+
const d = distPt(pf, qf);
|
|
28690
|
+
if (d >= total) {
|
|
28691
|
+
return {
|
|
28692
|
+
x: fma(qf.x, total, pf.x * (d - total)) / d,
|
|
28693
|
+
y: fma(qf.y, total, pf.y * (d - total)) / d
|
|
28694
|
+
};
|
|
28695
|
+
}
|
|
28696
|
+
total -= d;
|
|
28697
|
+
}
|
|
28698
|
+
}
|
|
28699
|
+
const first = spl.list[0];
|
|
28700
|
+
return first.sflag ? first.sp : first.list[0];
|
|
28701
|
+
}
|
|
28702
|
+
function splEndPoints(spl) {
|
|
28703
|
+
const first = spl.list[0];
|
|
28704
|
+
const p = first.sflag ? first.sp : first.list[0];
|
|
28705
|
+
const last = spl.list[spl.list.length - 1];
|
|
28706
|
+
const q = last.eflag ? last.ep : last.list[last.list.length - 1];
|
|
28707
|
+
return { p, q };
|
|
28708
|
+
}
|
|
28709
|
+
|
|
28710
|
+
// src/common/splines-path-shared.ts
|
|
28711
|
+
function addBox(P, b) {
|
|
28712
|
+
if (b.ll.x < b.ur.x && b.ll.y < b.ur.y) {
|
|
28713
|
+
P.boxes[P.nbox++] = b;
|
|
28714
|
+
}
|
|
28715
|
+
}
|
|
28716
|
+
function concSlope(n) {
|
|
28717
|
+
const inE = n.info.in;
|
|
28718
|
+
const outE = n.info.out;
|
|
28719
|
+
const cntIn = inE?.size ?? 0;
|
|
28720
|
+
const cntOut = outE?.size ?? 0;
|
|
28721
|
+
let sIn = 0;
|
|
28722
|
+
let sOut = 0;
|
|
28723
|
+
for (let i = 0; i < cntIn; i++) sIn += inE.list[i].tail.info.coord.x;
|
|
28724
|
+
for (let i = 0; i < cntOut; i++) sOut += outE.list[i].head.info.coord.x;
|
|
28725
|
+
const x1 = n.info.coord.x - sIn / cntIn;
|
|
28726
|
+
const y1 = n.info.coord.y - inE.list[0].tail.info.coord.y;
|
|
28727
|
+
const x2 = sOut / cntOut - n.info.coord.x;
|
|
28728
|
+
const y2 = outE.list[0].head.info.coord.y - n.info.coord.y;
|
|
28729
|
+
return (Math.atan2(y1, x1) + Math.atan2(y2, x2)) / 2;
|
|
28730
|
+
}
|
|
28731
|
+
var SIDE_PORT = ["s", "e", "n", "w"];
|
|
28732
|
+
var ALL_SIDES2 = TOP | BOTTOM | LEFT | RIGHT;
|
|
28733
|
+
function cvtPt(p, rankdir) {
|
|
28734
|
+
switch (rankdir) {
|
|
28735
|
+
case RANKDIR_BT:
|
|
28736
|
+
return { x: p.x, y: -p.y };
|
|
28737
|
+
case RANKDIR_LR:
|
|
28738
|
+
return { x: -p.y, y: p.x };
|
|
28739
|
+
case RANKDIR_RL:
|
|
28740
|
+
return { x: p.y, y: p.x };
|
|
28741
|
+
default:
|
|
28742
|
+
return { x: p.x, y: p.y };
|
|
28743
|
+
}
|
|
28744
|
+
}
|
|
28745
|
+
function nodeBoxLocal(n, flip) {
|
|
28746
|
+
const lw = n.info.lw, ht22 = n.info.ht / 2;
|
|
28747
|
+
return flip ? { ll: { x: -ht22, y: -lw }, ur: { x: ht22, y: lw } } : { ll: { x: -lw, y: -ht22 }, ur: { x: lw, y: ht22 } };
|
|
28748
|
+
}
|
|
28749
|
+
function faceMidpoint(b, ix) {
|
|
28750
|
+
const cx = (b.ll.x + b.ur.x) / 2, cy = (b.ll.y + b.ur.y) / 2;
|
|
28751
|
+
if (ix === BOTTOM_IX) return { x: cx, y: b.ll.y };
|
|
28752
|
+
if (ix === RIGHT_IX) return { x: b.ur.x, y: cy };
|
|
28753
|
+
if (ix === TOP_IX) return { x: cx, y: b.ur.y };
|
|
28754
|
+
return { x: b.ll.x, y: cy };
|
|
28755
|
+
}
|
|
28756
|
+
function closestSide(n, other, port) {
|
|
28757
|
+
const sides = port.side;
|
|
28758
|
+
if (sides === 0 || sides === ALL_SIDES2) return null;
|
|
28759
|
+
const rkd = (n.root.info.rankdir ?? 0) & 3;
|
|
28760
|
+
const pt = cvtPt(n.info.coord, rkd);
|
|
28761
|
+
const opt = cvtPt(other.info.coord, rkd);
|
|
28762
|
+
const b = port.bp ?? nodeBoxLocal(n, rkd === RANKDIR_LR || rkd === RANKDIR_RL);
|
|
28763
|
+
let rv = null;
|
|
28764
|
+
let mind = 0;
|
|
28765
|
+
for (let i = 0; i < 4; i++) {
|
|
28766
|
+
if ((sides & 1 << i) === 0) continue;
|
|
28767
|
+
const m = faceMidpoint(b, i);
|
|
28768
|
+
const d = dist2({ x: m.x + pt.x, y: m.y + pt.y }, opt);
|
|
28769
|
+
if (rv === null || d < mind) {
|
|
28770
|
+
mind = d;
|
|
28771
|
+
rv = SIDE_PORT[i];
|
|
28772
|
+
}
|
|
28773
|
+
}
|
|
28774
|
+
return rv;
|
|
28775
|
+
}
|
|
28776
|
+
function resolvePort(n, other, port) {
|
|
28777
|
+
if (!port.dyna) return port;
|
|
28778
|
+
const compass = closestSide(n, other, port);
|
|
28779
|
+
const rv = makePort();
|
|
28780
|
+
rv.name = port.name;
|
|
28781
|
+
compassPort(n, { bp: port.bp, compass: compass ?? "", sides: port.side }, rv);
|
|
28782
|
+
return rv;
|
|
28783
|
+
}
|
|
28784
|
+
function walkToOrig(e) {
|
|
28785
|
+
let cur = e;
|
|
28786
|
+
while (cur.info.to_orig != null && cur.info.edge_type !== 0) {
|
|
28787
|
+
cur = cur.info.to_orig;
|
|
28788
|
+
}
|
|
28789
|
+
return cur;
|
|
28790
|
+
}
|
|
28791
|
+
function clearClipForOrig(e, n, isTail) {
|
|
28792
|
+
const orig = walkToOrig(e);
|
|
28793
|
+
if (isTail) {
|
|
28794
|
+
if (n === orig.tail) orig.info.tail_port.clip = false;
|
|
28795
|
+
else orig.info.head_port.clip = false;
|
|
28796
|
+
} else {
|
|
28797
|
+
if (n === orig.head) orig.info.head_port.clip = false;
|
|
28798
|
+
else orig.info.tail_port.clip = false;
|
|
28799
|
+
}
|
|
28800
|
+
}
|
|
28801
|
+
function applyDefaultBoxes(P, et, endp) {
|
|
28802
|
+
if (et === FLATEDGE) {
|
|
28803
|
+
if (endp.sidemask === TOP) endp.boxes[0].ll.y = P.start.p.y;
|
|
28804
|
+
else endp.boxes[0].ur.y = P.start.p.y;
|
|
28805
|
+
} else {
|
|
28806
|
+
endp.boxes[0].ur.y = P.start.p.y;
|
|
28807
|
+
endp.sidemask = BOTTOM;
|
|
28808
|
+
P.start.p.y -= 1;
|
|
28809
|
+
}
|
|
28810
|
+
}
|
|
28811
|
+
function applyEndDefaultBoxes(P, et, endp) {
|
|
28812
|
+
if (et === FLATEDGE) {
|
|
28813
|
+
if (endp.sidemask === TOP) endp.boxes[0].ll.y = P.end.p.y;
|
|
28814
|
+
else endp.boxes[0].ur.y = P.end.p.y;
|
|
28815
|
+
} else {
|
|
28816
|
+
endp.boxes[0].ll.y = P.end.p.y;
|
|
28817
|
+
endp.sidemask = TOP;
|
|
28818
|
+
P.end.p.y += 1;
|
|
28819
|
+
}
|
|
28820
|
+
}
|
|
28821
|
+
function invokePboxfn(fns, n, port, side, endp) {
|
|
28822
|
+
if (!fns?.pboxfn) return 0;
|
|
28823
|
+
const kptr = [endp.boxn];
|
|
28824
|
+
const mask = fns.pboxfn(n, port, side, endp.boxes, kptr);
|
|
28825
|
+
endp.boxn = kptr[0];
|
|
28826
|
+
return mask;
|
|
28827
|
+
}
|
|
28828
|
+
function setStartTheta(P, e, merge) {
|
|
28829
|
+
if (merge) {
|
|
28830
|
+
P.start.theta = concSlope(e.tail);
|
|
28831
|
+
P.start.constrained = true;
|
|
28832
|
+
} else if (e.info.tail_port.constrained) {
|
|
28833
|
+
P.start.theta = e.info.tail_port.theta;
|
|
28834
|
+
P.start.constrained = true;
|
|
28835
|
+
} else {
|
|
28836
|
+
P.start.constrained = false;
|
|
28837
|
+
}
|
|
28838
|
+
}
|
|
28839
|
+
function setEndTheta(P, e, merge) {
|
|
28840
|
+
if (merge) {
|
|
28841
|
+
P.end.theta = concSlope(e.head) + Math.PI;
|
|
28842
|
+
P.end.constrained = true;
|
|
28843
|
+
} else if (e.info.head_port.constrained) {
|
|
28844
|
+
P.end.theta = e.info.head_port.theta;
|
|
28845
|
+
P.end.constrained = true;
|
|
28846
|
+
} else {
|
|
28847
|
+
P.end.constrained = false;
|
|
28848
|
+
}
|
|
28849
|
+
}
|
|
28850
|
+
|
|
28464
28851
|
// src/pathplan/solvers.ts
|
|
28465
28852
|
var EPS2 = 1e-7;
|
|
28466
28853
|
var Solver = class _Solver {
|
|
@@ -29250,567 +29637,6 @@ function computeSpline(boxes, startPt, endPt) {
|
|
|
29250
29637
|
return tryRouteSpline(polyEdgesFromPts(polygon), wpts) ?? linearBezier(startPt, endPt);
|
|
29251
29638
|
}
|
|
29252
29639
|
|
|
29253
|
-
// src/layout/dot/edge-route-boxes.ts
|
|
29254
|
-
var FUDGE2 = 2;
|
|
29255
|
-
function makeTailBox(nb, startPy) {
|
|
29256
|
-
return { ll: nb.ll, ur: { x: nb.ur.x, y: startPy } };
|
|
29257
|
-
}
|
|
29258
|
-
function makeHeadBox(nb, endPy) {
|
|
29259
|
-
return { ll: { x: nb.ll.x, y: endPy }, ur: nb.ur };
|
|
29260
|
-
}
|
|
29261
|
-
function makeRankBox(p) {
|
|
29262
|
-
return {
|
|
29263
|
-
ll: { x: p.llx, y: p.headCy + p.headHt2 },
|
|
29264
|
-
ur: { x: p.urx, y: p.tailCy - p.tailHt1 }
|
|
29265
|
-
};
|
|
29266
|
-
}
|
|
29267
|
-
function makeMaximalBbox(box, ht1, ht22) {
|
|
29268
|
-
return {
|
|
29269
|
-
ll: { x: box.center.x - box.lw - FUDGE2, y: box.center.y - ht1 },
|
|
29270
|
-
ur: { x: box.center.x + box.rw + FUDGE2, y: box.center.y + ht22 }
|
|
29271
|
-
};
|
|
29272
|
-
}
|
|
29273
|
-
|
|
29274
|
-
// src/layout/dot/edge-route-routing.ts
|
|
29275
|
-
var ARROW_LENGTH2 = 10;
|
|
29276
|
-
var CLIP_BOTH = { tail: true, head: true };
|
|
29277
|
-
function buildRankCorridor(tailBox, headBox, rank3, ports) {
|
|
29278
|
-
const startPy = tailBox.center.y;
|
|
29279
|
-
const endPy = headBox.center.y;
|
|
29280
|
-
const tailNb = makeMaximalBbox(tailBox, rank3.tailHt1, rank3.tailHt2);
|
|
29281
|
-
const headNb = makeMaximalBbox(headBox, rank3.headHt1, rank3.headHt2);
|
|
29282
|
-
const rp = {
|
|
29283
|
-
llx: rank3.leftBound,
|
|
29284
|
-
urx: rank3.rightBound,
|
|
29285
|
-
tailCy: tailBox.center.y,
|
|
29286
|
-
tailHt1: rank3.tailHt1,
|
|
29287
|
-
headCy: headBox.center.y,
|
|
29288
|
-
headHt2: rank3.headHt2
|
|
29289
|
-
};
|
|
29290
|
-
return {
|
|
29291
|
-
startPt: ports?.tailP ?? { x: tailBox.center.x, y: startPy - 1 },
|
|
29292
|
-
endPt: ports?.headP ?? { x: headBox.center.x, y: endPy + 1 },
|
|
29293
|
-
boxes: [makeTailBox(tailNb, startPy), makeRankBox(rp), makeHeadBox(headNb, endPy)]
|
|
29294
|
-
};
|
|
29295
|
-
}
|
|
29296
|
-
function normalArrowLen(penwidth = DEFAULT_NODEPENWIDTH) {
|
|
29297
|
-
const ARROWWIDTH = 0.35;
|
|
29298
|
-
return ARROW_LENGTH2 + penwidth * Math.sqrt(1 + ARROWWIDTH * ARROWWIDTH) / (2 * ARROWWIDTH);
|
|
29299
|
-
}
|
|
29300
|
-
function nodeInsideFn2(box) {
|
|
29301
|
-
const halfW = (box.lw + box.rw) / 2;
|
|
29302
|
-
const halfH = box.ht / 2;
|
|
29303
|
-
const pw = box.penwidth ?? DEFAULT_NODEPENWIDTH;
|
|
29304
|
-
return box.isEllipse ? makeEllipseInsideFn(halfW, halfH, pw) : makeBoxInsideFn(halfW, halfH, pw);
|
|
29305
|
-
}
|
|
29306
|
-
function clipToNodes(bezier, tailBox, headBox, penwidth = DEFAULT_NODEPENWIDTH, clip = CLIP_BOTH) {
|
|
29307
|
-
const step1 = clip.tail ? bezierClipNode(bezier, tailBox.center.x, tailBox.center.y, nodeInsideFn2(tailBox), true) : bezier;
|
|
29308
|
-
const step2 = clip.head ? bezierClipNode(step1, headBox.center.x, headBox.center.y, nodeInsideFn2(headBox), false) : step1;
|
|
29309
|
-
const arrowTip = step2[3];
|
|
29310
|
-
const elen = normalArrowLen(penwidth);
|
|
29311
|
-
const clipped = arrowEndClip(step2, arrowTip, elen);
|
|
29312
|
-
const arrowDir = normalizeVec({
|
|
29313
|
-
x: clipped[3].x - arrowTip.x,
|
|
29314
|
-
y: clipped[3].y - arrowTip.y
|
|
29315
|
-
});
|
|
29316
|
-
return { clipped, arrowTip, arrowDir };
|
|
29317
|
-
}
|
|
29318
|
-
function routeWithRank(tailBox, headBox, rank3, penwidth = DEFAULT_NODEPENWIDTH, port) {
|
|
29319
|
-
const corridor = port ? { tailP: port.tailP, headP: port.headP } : void 0;
|
|
29320
|
-
const { startPt, endPt, boxes } = buildRankCorridor(tailBox, headBox, rank3, corridor);
|
|
29321
|
-
const bezier = computeSpline(boxes, startPt, endPt);
|
|
29322
|
-
const clip = port ? { tail: port.clipTail, head: port.clipHead } : CLIP_BOTH;
|
|
29323
|
-
const { clipped, arrowTip, arrowDir } = clipToNodes(bezier, tailBox, headBox, penwidth, clip);
|
|
29324
|
-
return { bezierPts: clipped, arrowTip, arrowDir };
|
|
29325
|
-
}
|
|
29326
|
-
function routeSimple(tailBox, headBox, routeBezierFn) {
|
|
29327
|
-
const dir = normalizeVec({
|
|
29328
|
-
x: headBox.center.x - tailBox.center.x,
|
|
29329
|
-
y: headBox.center.y - tailBox.center.y
|
|
29330
|
-
});
|
|
29331
|
-
const headToTail = negateVec(dir);
|
|
29332
|
-
const tailClip = clipToNodeBox(tailBox, dir);
|
|
29333
|
-
const arrowTip = clipToNodeBox(headBox, headToTail);
|
|
29334
|
-
return {
|
|
29335
|
-
bezierPts: routeBezierFn(tailClip, offsetPoint(arrowTip, headToTail, ARROW_LENGTH2)),
|
|
29336
|
-
arrowTip,
|
|
29337
|
-
arrowDir: headToTail
|
|
29338
|
-
};
|
|
29339
|
-
}
|
|
29340
|
-
|
|
29341
|
-
// src/layout/dot/edge-route-helpers.ts
|
|
29342
|
-
function defaultEdgeDir(g) {
|
|
29343
|
-
return g.kind === "directed" || g.kind === "strict-directed" ? "forward" : "none";
|
|
29344
|
-
}
|
|
29345
|
-
var ELLIPSE_SHAPES = /* @__PURE__ */ new Set([
|
|
29346
|
-
"ellipse",
|
|
29347
|
-
"oval",
|
|
29348
|
-
"circle",
|
|
29349
|
-
"egg",
|
|
29350
|
-
"doublecircle",
|
|
29351
|
-
"Mcircle",
|
|
29352
|
-
"point"
|
|
29353
|
-
]);
|
|
29354
|
-
function recordClipBox(n) {
|
|
29355
|
-
const f = n.info.shape_info;
|
|
29356
|
-
if (!f?.b) return void 0;
|
|
29357
|
-
const halfW = (f.b.ur.x - f.b.ll.x) / 2;
|
|
29358
|
-
return { lw: halfW, rw: halfW, ht: f.b.ur.y - f.b.ll.y };
|
|
29359
|
-
}
|
|
29360
|
-
function nodePenwidthOf(n, g) {
|
|
29361
|
-
const v = nodeAttr(n, g, "penwidth");
|
|
29362
|
-
const pw = v !== void 0 ? parseFloat(v) : NaN;
|
|
29363
|
-
return Number.isFinite(pw) && pw >= 0 ? pw : DEFAULT_NODEPENWIDTH;
|
|
29364
|
-
}
|
|
29365
|
-
function nodeBoxOf(n, g) {
|
|
29366
|
-
const shapeName = nodeAttr(n, g, "shape") ?? "ellipse";
|
|
29367
|
-
const penwidth = nodePenwidthOf(n, g);
|
|
29368
|
-
if (shapeName === "record" || shapeName === "Mrecord") {
|
|
29369
|
-
const rb = recordClipBox(n);
|
|
29370
|
-
if (rb) return { center: n.info.coord, ...rb, isEllipse: false, penwidth };
|
|
29371
|
-
}
|
|
29372
|
-
const si = n.info.shape_info;
|
|
29373
|
-
if (si?.option?.fixedshape === true && si.vertices) {
|
|
29374
|
-
const ext = fixedShapeSize(si);
|
|
29375
|
-
const flip = g.root.info.flip === true;
|
|
29376
|
-
const w = flip ? ext.h : ext.w;
|
|
29377
|
-
const h = flip ? ext.w : ext.h;
|
|
29378
|
-
return {
|
|
29379
|
-
center: n.info.coord,
|
|
29380
|
-
lw: w / 2,
|
|
29381
|
-
rw: w / 2,
|
|
29382
|
-
ht: h,
|
|
29383
|
-
isEllipse: ELLIPSE_SHAPES.has(shapeName),
|
|
29384
|
-
penwidth: 0
|
|
29385
|
-
};
|
|
29386
|
-
}
|
|
29387
|
-
return {
|
|
29388
|
-
center: n.info.coord,
|
|
29389
|
-
lw: n.info.lw > 0 ? n.info.lw : 27,
|
|
29390
|
-
rw: n.info.rw > 0 ? n.info.rw : 27,
|
|
29391
|
-
ht: n.info.ht > 0 ? n.info.ht : 36,
|
|
29392
|
-
isEllipse: ELLIPSE_SHAPES.has(shapeName),
|
|
29393
|
-
penwidth
|
|
29394
|
-
};
|
|
29395
|
-
}
|
|
29396
|
-
function edgeRenderPenwidth(e) {
|
|
29397
|
-
return resolvePenWidth(parseStyleFlags(e.attrs.get("style")), e.attrs.get("penwidth"));
|
|
29398
|
-
}
|
|
29399
|
-
function edgePenwidthAttr(e) {
|
|
29400
|
-
const pw = parseFloat(e.attrs.get("penwidth") ?? "");
|
|
29401
|
-
return isNaN(pw) ? 1 : pw;
|
|
29402
|
-
}
|
|
29403
|
-
function makeBezierRecord(bezierPts, arrowTip) {
|
|
29404
|
-
return {
|
|
29405
|
-
list: bezierPts,
|
|
29406
|
-
size: bezierPts.length,
|
|
29407
|
-
sflag: 0,
|
|
29408
|
-
eflag: 1,
|
|
29409
|
-
sp: bezierPts[0] ?? { x: 0, y: 0 },
|
|
29410
|
-
ep: arrowTip
|
|
29411
|
-
};
|
|
29412
|
-
}
|
|
29413
|
-
function makeSplineRecord(bz) {
|
|
29414
|
-
return { list: [bz], size: 1, bb: { ll: { x: 0, y: 0 }, ur: { x: 0, y: 0 } } };
|
|
29415
|
-
}
|
|
29416
|
-
function installEdgeSpline(e, bezierPts, arrowTip) {
|
|
29417
|
-
e.info.spl = makeSplineRecord(makeBezierRecord(bezierPts, arrowTip));
|
|
29418
|
-
const bb = e.tail.root.info.bb;
|
|
29419
|
-
if (bb != null) {
|
|
29420
|
-
for (let i = 0; i + 3 < bezierPts.length; i += 3) {
|
|
29421
|
-
updateBbBz(bb, [bezierPts[i], bezierPts[i + 1], bezierPts[i + 2], bezierPts[i + 3]]);
|
|
29422
|
-
}
|
|
29423
|
-
}
|
|
29424
|
-
}
|
|
29425
|
-
function isUsableSpline(raw) {
|
|
29426
|
-
if (raw.length < 4) return false;
|
|
29427
|
-
const p0 = raw[0];
|
|
29428
|
-
const p1 = raw[1];
|
|
29429
|
-
return p0.x !== p1.x || p0.y !== p1.y;
|
|
29430
|
-
}
|
|
29431
|
-
function routeBezier(from, to) {
|
|
29432
|
-
const noBarriers = [];
|
|
29433
|
-
const zero = { x: 0, y: 0 };
|
|
29434
|
-
const raw = routeSpline(noBarriers, [from, to], [zero, zero]);
|
|
29435
|
-
if (!isUsableSpline(raw)) return linearBezier(from, to);
|
|
29436
|
-
return [raw[0], raw[1], raw[2], raw[3]];
|
|
29437
|
-
}
|
|
29438
|
-
function straightEdgeSplineWithRank(tailBox, headBox, rankInfo, penwidth = 1, port) {
|
|
29439
|
-
return rankInfo !== void 0 ? routeWithRank(tailBox, headBox, rankInfo, penwidth, port) : routeSimple(tailBox, headBox, routeBezier);
|
|
29440
|
-
}
|
|
29441
|
-
|
|
29442
|
-
// src/layout/dot/sameport.ts
|
|
29443
|
-
function sameedge(same, e, id) {
|
|
29444
|
-
for (const grp of same) {
|
|
29445
|
-
if (grp.id === id) {
|
|
29446
|
-
grp.edges.push(e);
|
|
29447
|
-
return;
|
|
29448
|
-
}
|
|
29449
|
-
}
|
|
29450
|
-
same.push({ id, edges: [e] });
|
|
29451
|
-
}
|
|
29452
|
-
function shapeClip(u, curve) {
|
|
29453
|
-
const box = nodeBoxOf(u, u.root);
|
|
29454
|
-
const clipped = bezierClipNode(curve, box.center.x, box.center.y, nodeInsideFn2(box), true);
|
|
29455
|
-
for (let i = 0; i < curve.length && i < clipped.length; i++) curve[i] = clipped[i];
|
|
29456
|
-
}
|
|
29457
|
-
function computeBoundaryOffset(u, x, y, ranksep) {
|
|
29458
|
-
const r = Math.max(
|
|
29459
|
-
(u.info.lw ?? 0) + (u.info.rw ?? 0),
|
|
29460
|
-
(u.info.ht ?? 0) + ranksep
|
|
29461
|
-
);
|
|
29462
|
-
const x2 = x * r + u.info.coord.x;
|
|
29463
|
-
const y2 = y * r + u.info.coord.y;
|
|
29464
|
-
const curve = [
|
|
29465
|
-
{ x: u.info.coord.x, y: u.info.coord.y },
|
|
29466
|
-
{ x: (2 * u.info.coord.x + x2) / 3, y: (2 * u.info.coord.y + y2) / 3 },
|
|
29467
|
-
{ x: (2 * x2 + u.info.coord.x) / 3, y: (2 * y2 + u.info.coord.y) / 3 },
|
|
29468
|
-
{ x: x2, y: y2 }
|
|
29469
|
-
];
|
|
29470
|
-
shapeClip(u, curve);
|
|
29471
|
-
return {
|
|
29472
|
-
x1: curve[0].x - u.info.coord.x,
|
|
29473
|
-
y1: curve[0].y - u.info.coord.y
|
|
29474
|
-
};
|
|
29475
|
-
}
|
|
29476
|
-
function averageDirection(u, edges) {
|
|
29477
|
-
let sx = 0, sy = 0;
|
|
29478
|
-
for (const e of edges) {
|
|
29479
|
-
const v = e.head === u ? e.tail : e.head;
|
|
29480
|
-
const dx = v.info.coord.x - u.info.coord.x;
|
|
29481
|
-
const dy = v.info.coord.y - u.info.coord.y;
|
|
29482
|
-
const r2 = Math.hypot(dx, dy);
|
|
29483
|
-
if (r2 !== 0) {
|
|
29484
|
-
sx += dx / r2;
|
|
29485
|
-
sy += dy / r2;
|
|
29486
|
-
}
|
|
29487
|
-
}
|
|
29488
|
-
const r = Math.hypot(sx, sy);
|
|
29489
|
-
return r !== 0 ? { x: sx / r, y: sy / r } : { x: 0, y: 0 };
|
|
29490
|
-
}
|
|
29491
|
-
function buildSharedPort(u, edges, ranksep) {
|
|
29492
|
-
const dir = averageDirection(u, edges);
|
|
29493
|
-
const { x1, y1 } = computeBoundaryOffset(u, dir.x, dir.y, ranksep);
|
|
29494
|
-
const px = cround(x1);
|
|
29495
|
-
const py = cround(y1);
|
|
29496
|
-
const lw = u.info.lw ?? 0;
|
|
29497
|
-
const rw = u.info.rw ?? 0;
|
|
29498
|
-
const order = lw + rw !== 0 ? MC_SCALE * (lw + px) / (lw + rw) : 0;
|
|
29499
|
-
return {
|
|
29500
|
-
p: { x: px, y: py },
|
|
29501
|
-
theta: 0,
|
|
29502
|
-
bp: null,
|
|
29503
|
-
defined: true,
|
|
29504
|
-
constrained: false,
|
|
29505
|
-
clip: false,
|
|
29506
|
-
dyna: false,
|
|
29507
|
-
order,
|
|
29508
|
-
side: 0,
|
|
29509
|
-
name: null
|
|
29510
|
-
};
|
|
29511
|
-
}
|
|
29512
|
-
function assignHeadIfMatch(f, u, prt) {
|
|
29513
|
-
if (f.head === u) f.info.head_port = prt;
|
|
29514
|
-
if (f.tail === u) f.info.tail_port = prt;
|
|
29515
|
-
}
|
|
29516
|
-
function assignPortForwardChain(e, u, prt) {
|
|
29517
|
-
for (let f = e; f !== void 0; f = (f.info.edge_type ?? 0) === VIRTUAL && (f.head.info.node_type ?? 0) === VIRTUAL && (f.head.info.out?.size ?? 0) === 1 ? f.head.info.out.list[0] : void 0) {
|
|
29518
|
-
assignHeadIfMatch(f, u, prt);
|
|
29519
|
-
}
|
|
29520
|
-
}
|
|
29521
|
-
function assignPortBackwardChain(e, u, prt) {
|
|
29522
|
-
for (let f = e; f !== void 0; f = (f.info.edge_type ?? 0) === VIRTUAL && (f.tail.info.node_type ?? 0) === VIRTUAL && (f.tail.info.in?.size ?? 0) === 1 ? f.tail.info.in.list[0] : void 0) {
|
|
29523
|
-
assignHeadIfMatch(f, u, prt);
|
|
29524
|
-
}
|
|
29525
|
-
}
|
|
29526
|
-
function assignPortToAllVirts(e, u, prt) {
|
|
29527
|
-
for (let virt = e; virt !== void 0; virt = virt.info.to_virt) {
|
|
29528
|
-
assignPortForwardChain(virt, u, prt);
|
|
29529
|
-
assignPortBackwardChain(virt, u, prt);
|
|
29530
|
-
}
|
|
29531
|
-
}
|
|
29532
|
-
function sameport(u, edges, ranksep) {
|
|
29533
|
-
if (edges.length < 2) return;
|
|
29534
|
-
const prt = buildSharedPort(u, edges, ranksep);
|
|
29535
|
-
for (const e of edges) assignPortToAllVirts(e, u, prt);
|
|
29536
|
-
u.info.has_port = true;
|
|
29537
|
-
}
|
|
29538
|
-
function graphHasSamehead(g) {
|
|
29539
|
-
for (const e of g.edges) {
|
|
29540
|
-
if (e.info.samehead !== void 0) return true;
|
|
29541
|
-
}
|
|
29542
|
-
return false;
|
|
29543
|
-
}
|
|
29544
|
-
function graphHasSametail(g) {
|
|
29545
|
-
for (const e of g.edges) {
|
|
29546
|
-
if (e.info.sametail !== void 0) return true;
|
|
29547
|
-
}
|
|
29548
|
-
return false;
|
|
29549
|
-
}
|
|
29550
|
-
function collectSamehead(n) {
|
|
29551
|
-
const same = [];
|
|
29552
|
-
for (const e of n.root.edges) {
|
|
29553
|
-
if (e.head === n && e.tail === n) continue;
|
|
29554
|
-
const id = e.head === n ? e.info.samehead : void 0;
|
|
29555
|
-
if (id && id !== "") sameedge(same, e, id);
|
|
29556
|
-
}
|
|
29557
|
-
return same;
|
|
29558
|
-
}
|
|
29559
|
-
function collectSametail(n) {
|
|
29560
|
-
const same = [];
|
|
29561
|
-
for (const e of n.root.edges) {
|
|
29562
|
-
if (e.head === n && e.tail === n) continue;
|
|
29563
|
-
const id = e.tail === n ? e.info.sametail : void 0;
|
|
29564
|
-
if (id && id !== "") sameedge(same, e, id);
|
|
29565
|
-
}
|
|
29566
|
-
return same;
|
|
29567
|
-
}
|
|
29568
|
-
function applyGroupsToNode(n, groups, ranksep) {
|
|
29569
|
-
for (const grp of groups) {
|
|
29570
|
-
if (grp.edges.length > 1) sameport(n, grp.edges, ranksep);
|
|
29571
|
-
}
|
|
29572
|
-
}
|
|
29573
|
-
function dotSameports(g) {
|
|
29574
|
-
const hasSH = graphHasSamehead(g);
|
|
29575
|
-
const hasST = graphHasSametail(g);
|
|
29576
|
-
if (!hasSH && !hasST) return;
|
|
29577
|
-
const ranksep = g.info.ranksep ?? 0;
|
|
29578
|
-
for (const n of nodesInSeq(g)) {
|
|
29579
|
-
if (hasSH) applyGroupsToNode(n, collectSamehead(n), ranksep);
|
|
29580
|
-
if (hasST) applyGroupsToNode(n, collectSametail(n), ranksep);
|
|
29581
|
-
}
|
|
29582
|
-
}
|
|
29583
|
-
|
|
29584
|
-
// src/common/spline-midpoint.ts
|
|
29585
|
-
function dist2(p, q) {
|
|
29586
|
-
const dx = p.x - q.x;
|
|
29587
|
-
const dy = p.y - q.y;
|
|
29588
|
-
return dx * dx + dy * dy;
|
|
29589
|
-
}
|
|
29590
|
-
function distPt(p, q) {
|
|
29591
|
-
return Math.sqrt(dist2(p, q));
|
|
29592
|
-
}
|
|
29593
|
-
function evalBez4(pts, t) {
|
|
29594
|
-
const u = 1 - t;
|
|
29595
|
-
const [p0, p1, p2, p3] = pts;
|
|
29596
|
-
return {
|
|
29597
|
-
x: u * u * u * p0.x + 3 * u * u * t * p1.x + 3 * u * t * t * p2.x + t * t * t * p3.x,
|
|
29598
|
-
y: u * u * u * p0.y + 3 * u * u * t * p1.y + 3 * u * t * t * p2.y + t * t * t * p3.y
|
|
29599
|
-
};
|
|
29600
|
-
}
|
|
29601
|
-
function dotneatoClosest(spl, pt) {
|
|
29602
|
-
let besti = 0;
|
|
29603
|
-
let bestj = -1;
|
|
29604
|
-
let bestd2 = Number.MAX_VALUE;
|
|
29605
|
-
for (let i = 0; i < spl.list.length; i++) {
|
|
29606
|
-
const bz2 = spl.list[i];
|
|
29607
|
-
const n = bz2.size ?? bz2.list.length;
|
|
29608
|
-
for (let j2 = 0; j2 < n; j2++) {
|
|
29609
|
-
const d2 = dist2(bz2.list[j2], pt);
|
|
29610
|
-
if (bestj === -1 || d2 < bestd2) {
|
|
29611
|
-
besti = i;
|
|
29612
|
-
bestj = j2;
|
|
29613
|
-
bestd2 = d2;
|
|
29614
|
-
}
|
|
29615
|
-
}
|
|
29616
|
-
}
|
|
29617
|
-
const bz = spl.list[besti];
|
|
29618
|
-
const bzn = bz.size ?? bz.list.length;
|
|
29619
|
-
let j = bestj === bzn - 1 ? bestj - 1 : bestj;
|
|
29620
|
-
j = 3 * Math.floor(j / 3);
|
|
29621
|
-
const c = [bz.list[j], bz.list[j + 1], bz.list[j + 2], bz.list[j + 3]];
|
|
29622
|
-
let lo = 0;
|
|
29623
|
-
let hi = 1;
|
|
29624
|
-
let dlo2 = dist2(c[0], pt);
|
|
29625
|
-
let dhi2 = dist2(c[3], pt);
|
|
29626
|
-
let pt2 = c[0];
|
|
29627
|
-
for (; ; ) {
|
|
29628
|
-
const t = (lo + hi) / 2;
|
|
29629
|
-
pt2 = evalBez4(c, t);
|
|
29630
|
-
if (Math.abs(dlo2 - dhi2) < 1 || Math.abs(hi - lo) < 1e-5) break;
|
|
29631
|
-
if (dlo2 < dhi2) {
|
|
29632
|
-
hi = t;
|
|
29633
|
-
dhi2 = dist2(pt2, pt);
|
|
29634
|
-
} else {
|
|
29635
|
-
lo = t;
|
|
29636
|
-
dlo2 = dist2(pt2, pt);
|
|
29637
|
-
}
|
|
29638
|
-
}
|
|
29639
|
-
return pt2;
|
|
29640
|
-
}
|
|
29641
|
-
function polylineMidpoint(spl) {
|
|
29642
|
-
let total = 0;
|
|
29643
|
-
for (const bz of spl.list) {
|
|
29644
|
-
for (let j = 0, k = 3; k < bz.list.length; j += 3, k += 3)
|
|
29645
|
-
total += distPt(bz.list[j], bz.list[k]);
|
|
29646
|
-
}
|
|
29647
|
-
total /= 2;
|
|
29648
|
-
for (const bz of spl.list) {
|
|
29649
|
-
for (let j = 0, k = 3; k < bz.list.length; j += 3, k += 3) {
|
|
29650
|
-
const pf = bz.list[j];
|
|
29651
|
-
const qf = bz.list[k];
|
|
29652
|
-
const d = distPt(pf, qf);
|
|
29653
|
-
if (d >= total) {
|
|
29654
|
-
return {
|
|
29655
|
-
x: fma(qf.x, total, pf.x * (d - total)) / d,
|
|
29656
|
-
y: fma(qf.y, total, pf.y * (d - total)) / d
|
|
29657
|
-
};
|
|
29658
|
-
}
|
|
29659
|
-
total -= d;
|
|
29660
|
-
}
|
|
29661
|
-
}
|
|
29662
|
-
const first = spl.list[0];
|
|
29663
|
-
return first.sflag ? first.sp : first.list[0];
|
|
29664
|
-
}
|
|
29665
|
-
function splEndPoints(spl) {
|
|
29666
|
-
const first = spl.list[0];
|
|
29667
|
-
const p = first.sflag ? first.sp : first.list[0];
|
|
29668
|
-
const last = spl.list[spl.list.length - 1];
|
|
29669
|
-
const q = last.eflag ? last.ep : last.list[last.list.length - 1];
|
|
29670
|
-
return { p, q };
|
|
29671
|
-
}
|
|
29672
|
-
|
|
29673
|
-
// src/common/splines-path-shared.ts
|
|
29674
|
-
function addBox(P, b) {
|
|
29675
|
-
if (b.ll.x < b.ur.x && b.ll.y < b.ur.y) {
|
|
29676
|
-
P.boxes[P.nbox++] = b;
|
|
29677
|
-
}
|
|
29678
|
-
}
|
|
29679
|
-
function concSlope(n) {
|
|
29680
|
-
const inE = n.info.in;
|
|
29681
|
-
const outE = n.info.out;
|
|
29682
|
-
const cntIn = inE?.size ?? 0;
|
|
29683
|
-
const cntOut = outE?.size ?? 0;
|
|
29684
|
-
let sIn = 0;
|
|
29685
|
-
let sOut = 0;
|
|
29686
|
-
for (let i = 0; i < cntIn; i++) sIn += inE.list[i].tail.info.coord.x;
|
|
29687
|
-
for (let i = 0; i < cntOut; i++) sOut += outE.list[i].head.info.coord.x;
|
|
29688
|
-
const x1 = n.info.coord.x - sIn / cntIn;
|
|
29689
|
-
const y1 = n.info.coord.y - inE.list[0].tail.info.coord.y;
|
|
29690
|
-
const x2 = sOut / cntOut - n.info.coord.x;
|
|
29691
|
-
const y2 = outE.list[0].head.info.coord.y - n.info.coord.y;
|
|
29692
|
-
return (Math.atan2(y1, x1) + Math.atan2(y2, x2)) / 2;
|
|
29693
|
-
}
|
|
29694
|
-
var SIDE_PORT = ["s", "e", "n", "w"];
|
|
29695
|
-
var ALL_SIDES2 = TOP | BOTTOM | LEFT | RIGHT;
|
|
29696
|
-
function cvtPt(p, rankdir) {
|
|
29697
|
-
switch (rankdir) {
|
|
29698
|
-
case RANKDIR_BT:
|
|
29699
|
-
return { x: p.x, y: -p.y };
|
|
29700
|
-
case RANKDIR_LR:
|
|
29701
|
-
return { x: -p.y, y: p.x };
|
|
29702
|
-
case RANKDIR_RL:
|
|
29703
|
-
return { x: p.y, y: p.x };
|
|
29704
|
-
default:
|
|
29705
|
-
return { x: p.x, y: p.y };
|
|
29706
|
-
}
|
|
29707
|
-
}
|
|
29708
|
-
function nodeBoxLocal(n, flip) {
|
|
29709
|
-
const lw = n.info.lw, ht22 = n.info.ht / 2;
|
|
29710
|
-
return flip ? { ll: { x: -ht22, y: -lw }, ur: { x: ht22, y: lw } } : { ll: { x: -lw, y: -ht22 }, ur: { x: lw, y: ht22 } };
|
|
29711
|
-
}
|
|
29712
|
-
function faceMidpoint(b, ix) {
|
|
29713
|
-
const cx = (b.ll.x + b.ur.x) / 2, cy = (b.ll.y + b.ur.y) / 2;
|
|
29714
|
-
if (ix === BOTTOM_IX) return { x: cx, y: b.ll.y };
|
|
29715
|
-
if (ix === RIGHT_IX) return { x: b.ur.x, y: cy };
|
|
29716
|
-
if (ix === TOP_IX) return { x: cx, y: b.ur.y };
|
|
29717
|
-
return { x: b.ll.x, y: cy };
|
|
29718
|
-
}
|
|
29719
|
-
function closestSide(n, other, port) {
|
|
29720
|
-
const sides = port.side;
|
|
29721
|
-
if (sides === 0 || sides === ALL_SIDES2) return null;
|
|
29722
|
-
const rkd = (n.root.info.rankdir ?? 0) & 3;
|
|
29723
|
-
const pt = cvtPt(n.info.coord, rkd);
|
|
29724
|
-
const opt = cvtPt(other.info.coord, rkd);
|
|
29725
|
-
const b = port.bp ?? nodeBoxLocal(n, rkd === RANKDIR_LR || rkd === RANKDIR_RL);
|
|
29726
|
-
let rv = null;
|
|
29727
|
-
let mind = 0;
|
|
29728
|
-
for (let i = 0; i < 4; i++) {
|
|
29729
|
-
if ((sides & 1 << i) === 0) continue;
|
|
29730
|
-
const m = faceMidpoint(b, i);
|
|
29731
|
-
const d = dist2({ x: m.x + pt.x, y: m.y + pt.y }, opt);
|
|
29732
|
-
if (rv === null || d < mind) {
|
|
29733
|
-
mind = d;
|
|
29734
|
-
rv = SIDE_PORT[i];
|
|
29735
|
-
}
|
|
29736
|
-
}
|
|
29737
|
-
return rv;
|
|
29738
|
-
}
|
|
29739
|
-
function resolvePort(n, other, port) {
|
|
29740
|
-
if (!port.dyna) return port;
|
|
29741
|
-
const compass = closestSide(n, other, port);
|
|
29742
|
-
const rv = makePort();
|
|
29743
|
-
rv.name = port.name;
|
|
29744
|
-
compassPort(n, { bp: port.bp, compass: compass ?? "", sides: port.side }, rv);
|
|
29745
|
-
return rv;
|
|
29746
|
-
}
|
|
29747
|
-
function walkToOrig(e) {
|
|
29748
|
-
let cur = e;
|
|
29749
|
-
while (cur.info.to_orig != null && cur.info.edge_type !== 0) {
|
|
29750
|
-
cur = cur.info.to_orig;
|
|
29751
|
-
}
|
|
29752
|
-
return cur;
|
|
29753
|
-
}
|
|
29754
|
-
function clearClipForOrig(e, n, isTail) {
|
|
29755
|
-
const orig = walkToOrig(e);
|
|
29756
|
-
if (isTail) {
|
|
29757
|
-
if (n === orig.tail) orig.info.tail_port.clip = false;
|
|
29758
|
-
else orig.info.head_port.clip = false;
|
|
29759
|
-
} else {
|
|
29760
|
-
if (n === orig.head) orig.info.head_port.clip = false;
|
|
29761
|
-
else orig.info.tail_port.clip = false;
|
|
29762
|
-
}
|
|
29763
|
-
}
|
|
29764
|
-
function applyDefaultBoxes(P, et, endp) {
|
|
29765
|
-
if (et === FLATEDGE) {
|
|
29766
|
-
if (endp.sidemask === TOP) endp.boxes[0].ll.y = P.start.p.y;
|
|
29767
|
-
else endp.boxes[0].ur.y = P.start.p.y;
|
|
29768
|
-
} else {
|
|
29769
|
-
endp.boxes[0].ur.y = P.start.p.y;
|
|
29770
|
-
endp.sidemask = BOTTOM;
|
|
29771
|
-
P.start.p.y -= 1;
|
|
29772
|
-
}
|
|
29773
|
-
}
|
|
29774
|
-
function applyEndDefaultBoxes(P, et, endp) {
|
|
29775
|
-
if (et === FLATEDGE) {
|
|
29776
|
-
if (endp.sidemask === TOP) endp.boxes[0].ll.y = P.end.p.y;
|
|
29777
|
-
else endp.boxes[0].ur.y = P.end.p.y;
|
|
29778
|
-
} else {
|
|
29779
|
-
endp.boxes[0].ll.y = P.end.p.y;
|
|
29780
|
-
endp.sidemask = TOP;
|
|
29781
|
-
P.end.p.y += 1;
|
|
29782
|
-
}
|
|
29783
|
-
}
|
|
29784
|
-
function invokePboxfn(fns, n, port, side, endp) {
|
|
29785
|
-
if (!fns?.pboxfn) return 0;
|
|
29786
|
-
const kptr = [endp.boxn];
|
|
29787
|
-
const mask = fns.pboxfn(n, port, side, endp.boxes, kptr);
|
|
29788
|
-
endp.boxn = kptr[0];
|
|
29789
|
-
return mask;
|
|
29790
|
-
}
|
|
29791
|
-
function setStartTheta(P, e, merge) {
|
|
29792
|
-
if (merge) {
|
|
29793
|
-
P.start.theta = concSlope(e.tail);
|
|
29794
|
-
P.start.constrained = true;
|
|
29795
|
-
} else if (e.info.tail_port.constrained) {
|
|
29796
|
-
P.start.theta = e.info.tail_port.theta;
|
|
29797
|
-
P.start.constrained = true;
|
|
29798
|
-
} else {
|
|
29799
|
-
P.start.constrained = false;
|
|
29800
|
-
}
|
|
29801
|
-
}
|
|
29802
|
-
function setEndTheta(P, e, merge) {
|
|
29803
|
-
if (merge) {
|
|
29804
|
-
P.end.theta = concSlope(e.head) + Math.PI;
|
|
29805
|
-
P.end.constrained = true;
|
|
29806
|
-
} else if (e.info.head_port.constrained) {
|
|
29807
|
-
P.end.theta = e.info.head_port.theta;
|
|
29808
|
-
P.end.constrained = true;
|
|
29809
|
-
} else {
|
|
29810
|
-
P.end.constrained = false;
|
|
29811
|
-
}
|
|
29812
|
-
}
|
|
29813
|
-
|
|
29814
29640
|
// src/layout/dot/edge-route-rank.ts
|
|
29815
29641
|
var MINW = 16;
|
|
29816
29642
|
function computeLeftBound(g) {
|
|
@@ -30865,7 +30691,7 @@ function rankY(g, r) {
|
|
|
30865
30691
|
return g.info.rank[r].v[0].info.coord?.y ?? 0;
|
|
30866
30692
|
}
|
|
30867
30693
|
function sizeyAtMaxrank(g, n, r) {
|
|
30868
|
-
if (r > 0) return rankY(g, r - 1) - (n.info.coord?.y ?? 0);
|
|
30694
|
+
if (r - (g.info.abomShift ?? 0) > 0) return rankY(g, r - 1) - (n.info.coord?.y ?? 0);
|
|
30869
30695
|
return n.info.ht ?? 0;
|
|
30870
30696
|
}
|
|
30871
30697
|
function sizeyAtMinrank(g, n, r) {
|
|
@@ -33702,7 +33528,7 @@ function makeFlatLabeledEdge(g, e) {
|
|
|
33702
33528
|
const et = edgeType(g);
|
|
33703
33529
|
if (et === EDGETYPE_LINE) {
|
|
33704
33530
|
const ps2 = flatLabeledLinePoints(e.tail, e.head, e);
|
|
33705
|
-
|
|
33531
|
+
clipAndInstall(e, e.head, ps2, ps2.length, buildDotSinfo());
|
|
33706
33532
|
return true;
|
|
33707
33533
|
}
|
|
33708
33534
|
const tailIsLeft = (e.tail.info.order ?? 0) <= (e.head.info.order ?? 0);
|
|
@@ -33886,6 +33712,195 @@ function makeAdjFlatNoPortEdge(g, e) {
|
|
|
33886
33712
|
return true;
|
|
33887
33713
|
}
|
|
33888
33714
|
|
|
33715
|
+
// src/layout/dot/edge-route-boxes.ts
|
|
33716
|
+
var FUDGE2 = 2;
|
|
33717
|
+
function makeTailBox(nb, startPy) {
|
|
33718
|
+
return { ll: nb.ll, ur: { x: nb.ur.x, y: startPy } };
|
|
33719
|
+
}
|
|
33720
|
+
function makeHeadBox(nb, endPy) {
|
|
33721
|
+
return { ll: { x: nb.ll.x, y: endPy }, ur: nb.ur };
|
|
33722
|
+
}
|
|
33723
|
+
function makeRankBox(p) {
|
|
33724
|
+
return {
|
|
33725
|
+
ll: { x: p.llx, y: p.headCy + p.headHt2 },
|
|
33726
|
+
ur: { x: p.urx, y: p.tailCy - p.tailHt1 }
|
|
33727
|
+
};
|
|
33728
|
+
}
|
|
33729
|
+
function makeMaximalBbox(box, ht1, ht22) {
|
|
33730
|
+
return {
|
|
33731
|
+
ll: { x: box.center.x - box.lw - FUDGE2, y: box.center.y - ht1 },
|
|
33732
|
+
ur: { x: box.center.x + box.rw + FUDGE2, y: box.center.y + ht22 }
|
|
33733
|
+
};
|
|
33734
|
+
}
|
|
33735
|
+
|
|
33736
|
+
// src/layout/dot/edge-route-routing.ts
|
|
33737
|
+
var ARROW_LENGTH2 = 10;
|
|
33738
|
+
var CLIP_BOTH = { tail: true, head: true };
|
|
33739
|
+
function buildRankCorridor(tailBox, headBox, rank3, ports) {
|
|
33740
|
+
const startPy = tailBox.center.y;
|
|
33741
|
+
const endPy = headBox.center.y;
|
|
33742
|
+
const tailNb = makeMaximalBbox(tailBox, rank3.tailHt1, rank3.tailHt2);
|
|
33743
|
+
const headNb = makeMaximalBbox(headBox, rank3.headHt1, rank3.headHt2);
|
|
33744
|
+
const rp = {
|
|
33745
|
+
llx: rank3.leftBound,
|
|
33746
|
+
urx: rank3.rightBound,
|
|
33747
|
+
tailCy: tailBox.center.y,
|
|
33748
|
+
tailHt1: rank3.tailHt1,
|
|
33749
|
+
headCy: headBox.center.y,
|
|
33750
|
+
headHt2: rank3.headHt2
|
|
33751
|
+
};
|
|
33752
|
+
return {
|
|
33753
|
+
startPt: ports?.tailP ?? { x: tailBox.center.x, y: startPy - 1 },
|
|
33754
|
+
endPt: ports?.headP ?? { x: headBox.center.x, y: endPy + 1 },
|
|
33755
|
+
boxes: [makeTailBox(tailNb, startPy), makeRankBox(rp), makeHeadBox(headNb, endPy)]
|
|
33756
|
+
};
|
|
33757
|
+
}
|
|
33758
|
+
function normalArrowLen(penwidth = DEFAULT_NODEPENWIDTH) {
|
|
33759
|
+
const ARROWWIDTH = 0.35;
|
|
33760
|
+
return ARROW_LENGTH2 + penwidth * Math.sqrt(1 + ARROWWIDTH * ARROWWIDTH) / (2 * ARROWWIDTH);
|
|
33761
|
+
}
|
|
33762
|
+
function nodeInsideFn2(box) {
|
|
33763
|
+
const halfW = (box.lw + box.rw) / 2;
|
|
33764
|
+
const halfH = box.ht / 2;
|
|
33765
|
+
const pw = box.penwidth ?? DEFAULT_NODEPENWIDTH;
|
|
33766
|
+
return box.isEllipse ? makeEllipseInsideFn(halfW, halfH, pw) : makeBoxInsideFn(halfW, halfH, pw);
|
|
33767
|
+
}
|
|
33768
|
+
function clipToNodes(bezier, tailBox, headBox, penwidth = DEFAULT_NODEPENWIDTH, clip = CLIP_BOTH) {
|
|
33769
|
+
const step1 = clip.tail ? bezierClipNode(bezier, tailBox.center.x, tailBox.center.y, nodeInsideFn2(tailBox), true) : bezier;
|
|
33770
|
+
const step2 = clip.head ? bezierClipNode(step1, headBox.center.x, headBox.center.y, nodeInsideFn2(headBox), false) : step1;
|
|
33771
|
+
const arrowTip = step2[3];
|
|
33772
|
+
const elen = normalArrowLen(penwidth);
|
|
33773
|
+
const clipped = arrowEndClip(step2, arrowTip, elen);
|
|
33774
|
+
const arrowDir = normalizeVec({
|
|
33775
|
+
x: clipped[3].x - arrowTip.x,
|
|
33776
|
+
y: clipped[3].y - arrowTip.y
|
|
33777
|
+
});
|
|
33778
|
+
return { clipped, arrowTip, arrowDir };
|
|
33779
|
+
}
|
|
33780
|
+
function routeWithRank(tailBox, headBox, rank3, penwidth = DEFAULT_NODEPENWIDTH, port) {
|
|
33781
|
+
const corridor = port ? { tailP: port.tailP, headP: port.headP } : void 0;
|
|
33782
|
+
const { startPt, endPt, boxes } = buildRankCorridor(tailBox, headBox, rank3, corridor);
|
|
33783
|
+
const bezier = computeSpline(boxes, startPt, endPt);
|
|
33784
|
+
const clip = port ? { tail: port.clipTail, head: port.clipHead } : CLIP_BOTH;
|
|
33785
|
+
const { clipped, arrowTip, arrowDir } = clipToNodes(bezier, tailBox, headBox, penwidth, clip);
|
|
33786
|
+
return { bezierPts: clipped, arrowTip, arrowDir };
|
|
33787
|
+
}
|
|
33788
|
+
function routeSimple(tailBox, headBox, routeBezierFn) {
|
|
33789
|
+
const dir = normalizeVec({
|
|
33790
|
+
x: headBox.center.x - tailBox.center.x,
|
|
33791
|
+
y: headBox.center.y - tailBox.center.y
|
|
33792
|
+
});
|
|
33793
|
+
const headToTail = negateVec(dir);
|
|
33794
|
+
const tailClip = clipToNodeBox(tailBox, dir);
|
|
33795
|
+
const arrowTip = clipToNodeBox(headBox, headToTail);
|
|
33796
|
+
return {
|
|
33797
|
+
bezierPts: routeBezierFn(tailClip, offsetPoint(arrowTip, headToTail, ARROW_LENGTH2)),
|
|
33798
|
+
arrowTip,
|
|
33799
|
+
arrowDir: headToTail
|
|
33800
|
+
};
|
|
33801
|
+
}
|
|
33802
|
+
|
|
33803
|
+
// src/layout/dot/edge-route-helpers.ts
|
|
33804
|
+
function defaultEdgeDir(g) {
|
|
33805
|
+
return g.kind === "directed" || g.kind === "strict-directed" ? "forward" : "none";
|
|
33806
|
+
}
|
|
33807
|
+
var ELLIPSE_SHAPES = /* @__PURE__ */ new Set([
|
|
33808
|
+
"ellipse",
|
|
33809
|
+
"oval",
|
|
33810
|
+
"circle",
|
|
33811
|
+
"egg",
|
|
33812
|
+
"doublecircle",
|
|
33813
|
+
"Mcircle",
|
|
33814
|
+
"point"
|
|
33815
|
+
]);
|
|
33816
|
+
function recordClipBox(n) {
|
|
33817
|
+
const f = n.info.shape_info;
|
|
33818
|
+
if (!f?.b) return void 0;
|
|
33819
|
+
const halfW = (f.b.ur.x - f.b.ll.x) / 2;
|
|
33820
|
+
return { lw: halfW, rw: halfW, ht: f.b.ur.y - f.b.ll.y };
|
|
33821
|
+
}
|
|
33822
|
+
function nodePenwidthOf(n, g) {
|
|
33823
|
+
const v = nodeAttr(n, g, "penwidth");
|
|
33824
|
+
const pw = v !== void 0 ? parseFloat(v) : NaN;
|
|
33825
|
+
return Number.isFinite(pw) && pw >= 0 ? pw : DEFAULT_NODEPENWIDTH;
|
|
33826
|
+
}
|
|
33827
|
+
function nodeBoxOf(n, g) {
|
|
33828
|
+
const shapeName = nodeAttr(n, g, "shape") ?? "ellipse";
|
|
33829
|
+
const penwidth = nodePenwidthOf(n, g);
|
|
33830
|
+
if (shapeName === "record" || shapeName === "Mrecord") {
|
|
33831
|
+
const rb = recordClipBox(n);
|
|
33832
|
+
if (rb) return { center: n.info.coord, ...rb, isEllipse: false, penwidth };
|
|
33833
|
+
}
|
|
33834
|
+
const si = n.info.shape_info;
|
|
33835
|
+
if (si?.option?.fixedshape === true && si.vertices) {
|
|
33836
|
+
const ext = fixedShapeSize(si);
|
|
33837
|
+
const flip = g.root.info.flip === true;
|
|
33838
|
+
const w = flip ? ext.h : ext.w;
|
|
33839
|
+
const h = flip ? ext.w : ext.h;
|
|
33840
|
+
return {
|
|
33841
|
+
center: n.info.coord,
|
|
33842
|
+
lw: w / 2,
|
|
33843
|
+
rw: w / 2,
|
|
33844
|
+
ht: h,
|
|
33845
|
+
isEllipse: ELLIPSE_SHAPES.has(shapeName),
|
|
33846
|
+
penwidth: 0
|
|
33847
|
+
};
|
|
33848
|
+
}
|
|
33849
|
+
return {
|
|
33850
|
+
center: n.info.coord,
|
|
33851
|
+
lw: n.info.lw > 0 ? n.info.lw : 27,
|
|
33852
|
+
rw: n.info.rw > 0 ? n.info.rw : 27,
|
|
33853
|
+
ht: n.info.ht > 0 ? n.info.ht : 36,
|
|
33854
|
+
isEllipse: ELLIPSE_SHAPES.has(shapeName),
|
|
33855
|
+
penwidth
|
|
33856
|
+
};
|
|
33857
|
+
}
|
|
33858
|
+
function edgeRenderPenwidth(e) {
|
|
33859
|
+
return resolvePenWidth(parseStyleFlags(e.attrs.get("style")), e.attrs.get("penwidth"));
|
|
33860
|
+
}
|
|
33861
|
+
function edgePenwidthAttr(e) {
|
|
33862
|
+
const pw = parseFloat(e.attrs.get("penwidth") ?? "");
|
|
33863
|
+
return isNaN(pw) ? 1 : pw;
|
|
33864
|
+
}
|
|
33865
|
+
function makeBezierRecord(bezierPts, arrowTip) {
|
|
33866
|
+
return {
|
|
33867
|
+
list: bezierPts,
|
|
33868
|
+
size: bezierPts.length,
|
|
33869
|
+
sflag: 0,
|
|
33870
|
+
eflag: 1,
|
|
33871
|
+
sp: bezierPts[0] ?? { x: 0, y: 0 },
|
|
33872
|
+
ep: arrowTip
|
|
33873
|
+
};
|
|
33874
|
+
}
|
|
33875
|
+
function makeSplineRecord(bz) {
|
|
33876
|
+
return { list: [bz], size: 1, bb: { ll: { x: 0, y: 0 }, ur: { x: 0, y: 0 } } };
|
|
33877
|
+
}
|
|
33878
|
+
function installEdgeSpline(e, bezierPts, arrowTip) {
|
|
33879
|
+
e.info.spl = makeSplineRecord(makeBezierRecord(bezierPts, arrowTip));
|
|
33880
|
+
const bb = e.tail.root.info.bb;
|
|
33881
|
+
if (bb != null) {
|
|
33882
|
+
for (let i = 0; i + 3 < bezierPts.length; i += 3) {
|
|
33883
|
+
updateBbBz(bb, [bezierPts[i], bezierPts[i + 1], bezierPts[i + 2], bezierPts[i + 3]]);
|
|
33884
|
+
}
|
|
33885
|
+
}
|
|
33886
|
+
}
|
|
33887
|
+
function isUsableSpline(raw) {
|
|
33888
|
+
if (raw.length < 4) return false;
|
|
33889
|
+
const p0 = raw[0];
|
|
33890
|
+
const p1 = raw[1];
|
|
33891
|
+
return p0.x !== p1.x || p0.y !== p1.y;
|
|
33892
|
+
}
|
|
33893
|
+
function routeBezier(from, to) {
|
|
33894
|
+
const noBarriers = [];
|
|
33895
|
+
const zero = { x: 0, y: 0 };
|
|
33896
|
+
const raw = routeSpline(noBarriers, [from, to], [zero, zero]);
|
|
33897
|
+
if (!isUsableSpline(raw)) return linearBezier(from, to);
|
|
33898
|
+
return [raw[0], raw[1], raw[2], raw[3]];
|
|
33899
|
+
}
|
|
33900
|
+
function straightEdgeSplineWithRank(tailBox, headBox, rankInfo, penwidth = 1, port) {
|
|
33901
|
+
return rankInfo !== void 0 ? routeWithRank(tailBox, headBox, rankInfo, penwidth, port) : routeSimple(tailBox, headBox, routeBezier);
|
|
33902
|
+
}
|
|
33903
|
+
|
|
33889
33904
|
// src/layout/dot/edge-route.ts
|
|
33890
33905
|
function coordsDefined(e) {
|
|
33891
33906
|
return e.tail.info.coord !== void 0 && e.head.info.coord !== void 0;
|
|
@@ -33989,8 +34004,14 @@ function hasSidePort(e) {
|
|
|
33989
34004
|
const hp = resolvePort(e.head, e.tail, e.info.head_port);
|
|
33990
34005
|
return (tp.side ?? 0) !== 0 || (hp.side ?? 0) !== 0;
|
|
33991
34006
|
}
|
|
34007
|
+
function hasDefinedPort(e) {
|
|
34008
|
+
return e.info.tail_port.defined || e.info.head_port.defined;
|
|
34009
|
+
}
|
|
34010
|
+
function isAdjacentPortFlat(e, g) {
|
|
34011
|
+
return e.tail.info.rank !== void 0 && e.tail.info.rank === e.head.info.rank && isFlatAdjacent(g, e) && hasDefinedPort(e);
|
|
34012
|
+
}
|
|
33992
34013
|
function isGroupableFlat(x, g) {
|
|
33993
|
-
return x.info.spl === void 0 && x
|
|
34014
|
+
return x.info.spl === void 0 && isAdjacentPortFlat(x, g);
|
|
33994
34015
|
}
|
|
33995
34016
|
function collectAdjacentFlatGroup(e, g) {
|
|
33996
34017
|
const u = e.tail, v = e.head;
|
|
@@ -34031,7 +34052,7 @@ function routeFlatEdge(e, g) {
|
|
|
34031
34052
|
if (isLostFlatAdjRecordEdge(g, e)) return true;
|
|
34032
34053
|
if (makeFlatLabeledEdge(g, e)) return true;
|
|
34033
34054
|
if (makeAdjFlatNoPortEdge(g, e)) return true;
|
|
34034
|
-
if (hasSidePort(e) && routeFaithfulSidePort(e, g)) return true;
|
|
34055
|
+
if ((hasSidePort(e) || isAdjacentPortFlat(e, g)) && routeFaithfulSidePort(e, g)) return true;
|
|
34035
34056
|
if (e.tail.info.rank !== void 0 && e.tail.info.rank === e.head.info.rank && e.info.label === void 0 && !isFlatAdjacent(g, e)) {
|
|
34036
34057
|
const group = collectNonAdjacentFlatGroup(e, g);
|
|
34037
34058
|
if (group.length > 0 && routeFlatEdgeGroupFaithful(g, group, group.length) && e.info.spl !== void 0) return true;
|
|
@@ -34085,8 +34106,8 @@ var M_LEFT = 2;
|
|
|
34085
34106
|
var M_BOTTOM = 3;
|
|
34086
34107
|
|
|
34087
34108
|
// src/common/random.ts
|
|
34088
|
-
var A =
|
|
34089
|
-
var C =
|
|
34109
|
+
var A = BigInt("0x5deece66d");
|
|
34110
|
+
var C = BigInt("0xb");
|
|
34090
34111
|
var MASK48 = (1n << 48n) - 1n;
|
|
34091
34112
|
var TWO48 = 2 ** 48;
|
|
34092
34113
|
var state = 0x330en;
|
|
@@ -36628,8 +36649,11 @@ function dispatchEdgeGroup(g, group, ctx) {
|
|
|
36628
36649
|
}
|
|
36629
36650
|
return;
|
|
36630
36651
|
}
|
|
36631
|
-
if (nodeRankOf(e0.tail) === nodeRankOf(e0.head)) return;
|
|
36632
36652
|
const uniq = dedupByOrig(group);
|
|
36653
|
+
if (nodeRankOf(e0.tail) === nodeRankOf(e0.head)) {
|
|
36654
|
+
for (const e of uniq) routeLoneEdge(e, g);
|
|
36655
|
+
return;
|
|
36656
|
+
}
|
|
36633
36657
|
if (uniq.length <= 1) {
|
|
36634
36658
|
const runOrig = routeEntryRun(g, e0);
|
|
36635
36659
|
if (runOrig !== null) {
|
|
@@ -40941,7 +40965,6 @@ var Cdt = class {
|
|
|
40941
40965
|
v1 = r.v1;
|
|
40942
40966
|
v2 = r.v2;
|
|
40943
40967
|
v3 = r.v3;
|
|
40944
|
-
prev = r.e1;
|
|
40945
40968
|
e2 = r.e2;
|
|
40946
40969
|
e3 = r.e3;
|
|
40947
40970
|
}
|
|
@@ -44282,9 +44305,9 @@ var POW_LOG_TABLE_BITS = 7;
|
|
|
44282
44305
|
var N_LOG = 1 << POW_LOG_TABLE_BITS;
|
|
44283
44306
|
var EXP_TABLE_BITS = 7;
|
|
44284
44307
|
var N_EXP = 1 << EXP_TABLE_BITS;
|
|
44285
|
-
var OFF =
|
|
44286
|
-
var INF_BITS =
|
|
44287
|
-
var ONE_BITS =
|
|
44308
|
+
var OFF = BigInt("0x3fe6955500000000");
|
|
44309
|
+
var INF_BITS = BigInt("0x7ff0000000000000");
|
|
44310
|
+
var ONE_BITS = BigInt("0x3ff0000000000000");
|
|
44288
44311
|
var SIGN_BIAS = 2048 << EXP_TABLE_BITS;
|
|
44289
44312
|
var C22 = EC[0];
|
|
44290
44313
|
var C3 = EC[1];
|
|
@@ -49363,7 +49386,7 @@ function circoLayout(g) {
|
|
|
49363
49386
|
dg.components = comps;
|
|
49364
49387
|
let blockCount = 0;
|
|
49365
49388
|
if (comps.length === 1) {
|
|
49366
|
-
|
|
49389
|
+
circularLayout(comps[0], g, blockCount, allEdges3);
|
|
49367
49390
|
copyPositions(comps[0]);
|
|
49368
49391
|
adjustNodesFull(g);
|
|
49369
49392
|
} else {
|
|
@@ -53433,10 +53456,8 @@ function snapshotEdge(edge, flipY) {
|
|
|
53433
53456
|
head: edge.head.name,
|
|
53434
53457
|
points: collectEdgePoints(edge, flipY)
|
|
53435
53458
|
};
|
|
53436
|
-
const
|
|
53437
|
-
if (
|
|
53438
|
-
geom.label = { x: lbl.pos.x, y: flipY(lbl.pos.y) };
|
|
53439
|
-
}
|
|
53459
|
+
const label = placedLabelPos(edge.info.label, flipY);
|
|
53460
|
+
if (label !== void 0) geom.label = label;
|
|
53440
53461
|
const tailLabel = placedLabelPos(edge.info.tail_label, flipY);
|
|
53441
53462
|
if (tailLabel !== void 0) geom.tailLabel = tailLabel;
|
|
53442
53463
|
const headLabel = placedLabelPos(edge.info.head_label, flipY);
|