@cardenelabs/cdl 0.29.0 → 0.30.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/CHANGELOG.md +82 -1
- package/dist/index.cjs +136 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +136 -13
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +136 -13
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +136 -13
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/src/layout/edges.ts +173 -14
- package/src/layout.ts +4 -0
package/dist/index.js
CHANGED
|
@@ -19673,16 +19673,112 @@ function separateSharedStraightRuns(edges, nodes) {
|
|
|
19673
19673
|
e.d = verticesToPath(verts.get(e.id));
|
|
19674
19674
|
}
|
|
19675
19675
|
}
|
|
19676
|
+
function pullOutgoingFirstCorner(edges, nodes) {
|
|
19677
|
+
if (edges.length < 2) return;
|
|
19678
|
+
const \u675F = /* @__PURE__ */ new Map();
|
|
19679
|
+
const \u540C\u3058\u7D44\u306E\u6570 = /* @__PURE__ */ new Map();
|
|
19680
|
+
for (const e of edges) {
|
|
19681
|
+
const key = `${e.from}::${e.fromSide}`;
|
|
19682
|
+
const list = \u675F.get(key) ?? [];
|
|
19683
|
+
list.push(e);
|
|
19684
|
+
\u675F.set(key, list);
|
|
19685
|
+
const pair = `${e.from}->${e.to}`;
|
|
19686
|
+
\u540C\u3058\u7D44\u306E\u6570.set(pair, (\u540C\u3058\u7D44\u306E\u6570.get(pair) ?? 0) + 1);
|
|
19687
|
+
}
|
|
19688
|
+
let \u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F = false;
|
|
19689
|
+
for (const list of \u675F.values()) {
|
|
19690
|
+
if (list.length < 2) continue;
|
|
19691
|
+
const \u4E26\u3073 = list.flatMap((e) => {
|
|
19692
|
+
const pts = pathVertices(e.d);
|
|
19693
|
+
if (!pts || pts.length < 2) return [];
|
|
19694
|
+
return [{ e, pts, \u6700\u521D\u306E\u9577\u3055: Math.hypot(pts[1].x - pts[0].x, pts[1].y - pts[0].y) }];
|
|
19695
|
+
}).sort((a, b) => b.\u6700\u521D\u306E\u9577\u3055 - a.\u6700\u521D\u306E\u9577\u3055);
|
|
19696
|
+
for (const { e, pts, \u6700\u521D\u306E\u9577\u3055 } of \u4E26\u3073.slice(1)) {
|
|
19697
|
+
if ((\u540C\u3058\u7D44\u306E\u6570.get(`${e.from}->${e.to}`) ?? 0) > 1) continue;
|
|
19698
|
+
if (pts.length < 3 || \u6700\u521D\u306E\u9577\u3055 <= EDGE_STUB_OUT + VERTICAL_DETOUR_CORNER) continue;
|
|
19699
|
+
const \u6A2A = e.fromSide === "left" || e.fromSide === "right";
|
|
19700
|
+
if (!runIsAligned(pts, 0, \u6A2A ? 1 : 0)) continue;
|
|
19701
|
+
const \u79FB\u52D5\u91CF = \u6700\u521D\u306E\u9577\u3055 - (EDGE_STUB_OUT + VERTICAL_DETOUR_CORNER);
|
|
19702
|
+
const ux = (pts[1].x - pts[0].x) / \u6700\u521D\u306E\u9577\u3055;
|
|
19703
|
+
const uy = (pts[1].y - pts[0].y) / \u6700\u521D\u306E\u9577\u3055;
|
|
19704
|
+
const \u8A66\u3057 = pts.map(
|
|
19705
|
+
(p, i) => i === 1 || i === 2 ? { x: p.x - ux * \u79FB\u52D5\u91CF, y: p.y - uy * \u79FB\u52D5\u91CF } : p
|
|
19706
|
+
);
|
|
19707
|
+
const \u8A66\u3057D = verticesToPath(\u8A66\u3057);
|
|
19708
|
+
const \u8A66\u3057\u533A\u9593 = flattenPathSegments(extractPathSegments(\u8A66\u3057D));
|
|
19709
|
+
if (nodes.some(
|
|
19710
|
+
(n) => n.id !== e.from && n.id !== e.to && segmentsCrossRect(\u8A66\u3057\u533A\u9593, nodeRect(n))
|
|
19711
|
+
)) {
|
|
19712
|
+
continue;
|
|
19713
|
+
}
|
|
19714
|
+
const \u524D = e.d;
|
|
19715
|
+
const \u524D\u306E\u4EA4\u5DEE = countEdgeCrossings(edges).count;
|
|
19716
|
+
e.d = \u8A66\u3057D;
|
|
19717
|
+
if (countEdgeCrossings(edges).count > \u524D\u306E\u4EA4\u5DEE) {
|
|
19718
|
+
e.d = \u524D;
|
|
19719
|
+
continue;
|
|
19720
|
+
}
|
|
19721
|
+
e.d = \u524D;
|
|
19722
|
+
if (!\u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F) {
|
|
19723
|
+
slideLabelsAlongOwnPath(edges, nodes);
|
|
19724
|
+
\u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F = true;
|
|
19725
|
+
}
|
|
19726
|
+
const labelBox = computeLabelBBoxWorld(e);
|
|
19727
|
+
const label = { x: labelBox.x + labelBox.w / 2, y: labelBox.y + labelBox.h / 2 };
|
|
19728
|
+
const \u7DDA\u5206\u307E\u3067\u306E\u8DDD\u96E22 = (a, b) => {
|
|
19729
|
+
const dx = b.x - a.x;
|
|
19730
|
+
const dy = b.y - a.y;
|
|
19731
|
+
const len2 = dx * dx + dy * dy;
|
|
19732
|
+
const t = len2 === 0 ? 0 : Math.max(0, Math.min(1, ((label.x - a.x) * dx + (label.y - a.y) * dy) / len2));
|
|
19733
|
+
return (label.x - (a.x + dx * t)) ** 2 + (label.y - (a.y + dy * t)) ** 2;
|
|
19734
|
+
};
|
|
19735
|
+
const \u52D5\u304F\u533A\u9593\u3078\u306E\u8DDD\u96E2 = \u7DDA\u5206\u307E\u3067\u306E\u8DDD\u96E22(pts[1], pts[2]);
|
|
19736
|
+
const label\u3082\u52D5\u304B\u3059 = pts.slice(0, -1).every((p, i) => \u7DDA\u5206\u307E\u3067\u306E\u8DDD\u96E22(p, pts[i + 1]) >= \u52D5\u304F\u533A\u9593\u3078\u306E\u8DDD\u96E2 - 1e-6);
|
|
19737
|
+
e.d = \u8A66\u3057D;
|
|
19738
|
+
if (label\u3082\u52D5\u304B\u3059) {
|
|
19739
|
+
e.labelX -= ux * \u79FB\u52D5\u91CF;
|
|
19740
|
+
e.labelY -= uy * \u79FB\u52D5\u91CF;
|
|
19741
|
+
}
|
|
19742
|
+
}
|
|
19743
|
+
}
|
|
19744
|
+
}
|
|
19676
19745
|
var ENDPOINT_FAN_STEP = 56;
|
|
19677
19746
|
var ENDPOINT_FAN_MIN = 20;
|
|
19678
19747
|
var ENDPOINT_FAN_RUNUP = 40;
|
|
19748
|
+
var MIXED_ROOT_OVERLAP_MIN = 24;
|
|
19679
19749
|
function fanIncomingEndpoints(edges, nodes) {
|
|
19680
19750
|
if (edges.length < 2) return;
|
|
19681
19751
|
const nmap = new Map(nodes.map((n) => [n.id, n]));
|
|
19752
|
+
const \u5E73\u5766\u306A\u533A\u9593 = new Map(edges.map((e) => [e.id, flattenPathSegments(extractPathSegments(e.d))]));
|
|
19753
|
+
const \u8EF8\u306B\u5E73\u884C\u306A\u91CD\u306A\u308A\u9577\u3055 = (\u4E00\u65B9, \u4ED6\u65B9) => {
|
|
19754
|
+
let \u5408\u8A08 = 0;
|
|
19755
|
+
for (const a of \u5E73\u5766\u306A\u533A\u9593.get(\u4E00\u65B9.id) ?? []) {
|
|
19756
|
+
const a\u306F\u6C34\u5E73 = Math.abs(a.y2 - a.y1) <= 1;
|
|
19757
|
+
const a\u306F\u5782\u76F4 = Math.abs(a.x2 - a.x1) <= 1;
|
|
19758
|
+
for (const b of \u5E73\u5766\u306A\u533A\u9593.get(\u4ED6\u65B9.id) ?? []) {
|
|
19759
|
+
const b\u306F\u6C34\u5E73 = Math.abs(b.y2 - b.y1) <= 1;
|
|
19760
|
+
const b\u306F\u5782\u76F4 = Math.abs(b.x2 - b.x1) <= 1;
|
|
19761
|
+
if (a\u306F\u6C34\u5E73 && b\u306F\u6C34\u5E73 && Math.abs(a.y1 - b.y1) <= 1) {
|
|
19762
|
+
\u5408\u8A08 += Math.max(0, Math.min(Math.max(a.x1, a.x2), Math.max(b.x1, b.x2)) - Math.max(Math.min(a.x1, a.x2), Math.min(b.x1, b.x2)));
|
|
19763
|
+
}
|
|
19764
|
+
if (a\u306F\u5782\u76F4 && b\u306F\u5782\u76F4 && Math.abs(a.x1 - b.x1) <= 1) {
|
|
19765
|
+
\u5408\u8A08 += Math.max(0, Math.min(Math.max(a.y1, a.y2), Math.max(b.y1, b.y2)) - Math.max(Math.min(a.y1, a.y2), Math.min(b.y1, b.y2)));
|
|
19766
|
+
}
|
|
19767
|
+
}
|
|
19768
|
+
}
|
|
19769
|
+
return \u5408\u8A08;
|
|
19770
|
+
};
|
|
19682
19771
|
const \u540C\u3058\u7D44\u306E\u6570 = /* @__PURE__ */ new Map();
|
|
19683
19772
|
for (const e of edges) \u540C\u3058\u7D44\u306E\u6570.set(`${e.from}->${e.to}`, (\u540C\u3058\u7D44\u306E\u6570.get(`${e.from}->${e.to}`) ?? 0) + 1);
|
|
19684
19773
|
const \u675F = /* @__PURE__ */ new Map();
|
|
19774
|
+
const \u51FA\u308B\u7DDA = /* @__PURE__ */ new Map();
|
|
19685
19775
|
for (const e of edges) {
|
|
19776
|
+
if (nmap.has(e.from)) {
|
|
19777
|
+
const key2 = `${e.from}::${e.fromSide}`;
|
|
19778
|
+
const list2 = \u51FA\u308B\u7DDA.get(key2) ?? [];
|
|
19779
|
+
list2.push(e);
|
|
19780
|
+
\u51FA\u308B\u7DDA.set(key2, list2);
|
|
19781
|
+
}
|
|
19686
19782
|
if (!nmap.has(e.to)) continue;
|
|
19687
19783
|
if ((\u540C\u3058\u7D44\u306E\u6570.get(`${e.from}->${e.to}`) ?? 0) > 1) continue;
|
|
19688
19784
|
const key = `${e.to}::${e.toSide}`;
|
|
@@ -19690,27 +19786,48 @@ function fanIncomingEndpoints(edges, nodes) {
|
|
|
19690
19786
|
list.push(e);
|
|
19691
19787
|
\u675F.set(key, list);
|
|
19692
19788
|
}
|
|
19693
|
-
for (const [, list] of \u675F) {
|
|
19694
|
-
|
|
19789
|
+
for (const [key, list] of \u675F) {
|
|
19790
|
+
const \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B = (\u51FA\u308B\u7DDA.get(key) ?? []).some(
|
|
19791
|
+
(\u51FA\u7DDA) => list.some(
|
|
19792
|
+
(\u5165\u7DDA) => !(\u5165\u7DDA.from === \u51FA\u7DDA.to && \u5165\u7DDA.to === \u51FA\u7DDA.from) && \u8EF8\u306B\u5E73\u884C\u306A\u91CD\u306A\u308A\u9577\u3055(\u5165\u7DDA, \u51FA\u7DDA) >= MIXED_ROOT_OVERLAP_MIN
|
|
19793
|
+
)
|
|
19794
|
+
);
|
|
19795
|
+
if (list.length < 2 && !\u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B) continue;
|
|
19695
19796
|
const n = nmap.get(list[0].to);
|
|
19696
19797
|
const \u6A2A = list[0].toSide === "left" || list[0].toSide === "right";
|
|
19697
19798
|
const \u8FBA\u306E\u9577\u3055 = \u6A2A ? n.h : n.w;
|
|
19698
19799
|
const \u4F7F\u3048\u308B\u5E452 = \u8FBA\u306E\u9577\u3055 - 2 * ARROW_ENDPOINT_CENTER_TOL;
|
|
19699
19800
|
if (\u4F7F\u3048\u308B\u5E452 <= 0) continue;
|
|
19700
|
-
const \u9593
|
|
19801
|
+
const \u5E2D\u306E\u9593 = \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B ? list.length : list.length - 1;
|
|
19802
|
+
const \u9593\u9694 = Math.min(ENDPOINT_FAN_STEP, \u4F7F\u3048\u308B\u5E452 / \u5E2D\u306E\u9593);
|
|
19701
19803
|
if (\u9593\u9694 < ENDPOINT_FAN_MIN) continue;
|
|
19702
|
-
const \
|
|
19804
|
+
const \u8FBA\u306E\u4E2D\u5FC3 = \u6A2A ? n.cy : n.cx;
|
|
19805
|
+
const \u4E26\u3073 = list.map((e) => {
|
|
19806
|
+
const \u533A\u9593 = extractPathSegments(e.d);
|
|
19807
|
+
const last = \u533A\u9593[\u533A\u9593.length - 1];
|
|
19808
|
+
const \u9577\u3044\u52A9\u8D70 = last === void 0 ? 0 : Math.hypot(last.x2 - last.x1, last.y2 - last.y1);
|
|
19809
|
+
const \u4E2D\u5FC3\u3092\u88DC\u3046 = \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B || list.length === 2;
|
|
19810
|
+
const \u6DF1\u3055 = \u8FBA\u304B\u3089\u96E2\u308C\u305F\u5074\u306E\u4F4D\u7F6E(e, \u6A2A) ?? (\u4E2D\u5FC3\u3092\u88DC\u3046 ? \u8FBA\u306E\u4E2D\u5FC3 : 0);
|
|
19811
|
+
return { e, \u9577\u3044\u52A9\u8D70, \u6DF1\u3055 };
|
|
19812
|
+
}).sort((a, b) => a.\u6DF1\u3055 - b.\u6DF1\u3055 || (a.e.id < b.e.id ? -1 : 1));
|
|
19703
19813
|
const \u4E2D\u5FC3 = (\u4E26\u3073.length - 1) * \u9593\u9694 / 2;
|
|
19814
|
+
let \u8CA0\u5074\u306E\u5E2D = 0;
|
|
19815
|
+
let \u6B63\u5074\u306E\u5E2D = 0;
|
|
19704
19816
|
for (let k = 0; k < \u4E26\u3073.length; k++) {
|
|
19705
|
-
const d = k * \u9593\u9694 - \u4E2D\u5FC3;
|
|
19817
|
+
const d = \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B ? \u4E26\u3073[k].\u6DF1\u3055 < \u8FBA\u306E\u4E2D\u5FC3 ? -(++\u8CA0\u5074\u306E\u5E2D * \u9593\u9694) : ++\u6B63\u5074\u306E\u5E2D * \u9593\u9694 : k * \u9593\u9694 - \u4E2D\u5FC3;
|
|
19706
19818
|
if (Math.abs(d) < 1e-3) continue;
|
|
19707
19819
|
const e = \u4E26\u3073[k].e;
|
|
19708
|
-
const \u5DEE\u66FF = \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, nodes);
|
|
19709
|
-
if (\u5DEE\u66FF === null) continue;
|
|
19710
19820
|
const \u524D = e.d;
|
|
19711
19821
|
const \u524D\u306E\u4EA4\u5DEE = countEdgeCrossings(edges).count;
|
|
19712
|
-
|
|
19713
|
-
|
|
19822
|
+
const \u9577\u3044\u52A9\u8D70 = \u4E26\u3073[k].\u9577\u3044\u52A9\u8D70;
|
|
19823
|
+
for (const \u52A9\u8D70 of [\u9577\u3044\u52A9\u8D70, ENDPOINT_FAN_RUNUP]) {
|
|
19824
|
+
e.d = \u524D;
|
|
19825
|
+
const \u5DEE\u66FF = \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, \u52A9\u8D70, nodes);
|
|
19826
|
+
if (\u5DEE\u66FF === null) continue;
|
|
19827
|
+
e.d = \u5DEE\u66FF;
|
|
19828
|
+
if (countEdgeCrossings(edges).count <= \u524D\u306E\u4EA4\u5DEE) break;
|
|
19829
|
+
e.d = \u524D;
|
|
19830
|
+
}
|
|
19714
19831
|
}
|
|
19715
19832
|
}
|
|
19716
19833
|
}
|
|
@@ -19723,7 +19840,7 @@ function \u8FBA\u304B\u3089\u96E2\u308C\u305F\u5074\u306E\u4F4D\u7F6E(e, \u6A2A)
|
|
|
19723
19840
|
}
|
|
19724
19841
|
return null;
|
|
19725
19842
|
}
|
|
19726
|
-
function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, nodes) {
|
|
19843
|
+
function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, \u52A9\u8D70, nodes) {
|
|
19727
19844
|
if ((e.d.match(/M/g) ?? []).length !== 1) return null;
|
|
19728
19845
|
const segs = extractPathSegments(e.d);
|
|
19729
19846
|
if (segs.length === 0) return null;
|
|
@@ -19736,7 +19853,12 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
|
|
|
19736
19853
|
if (\u9577\u3055 < ENDPOINT_FAN_RUNUP + 1) return null;
|
|
19737
19854
|
const ux = (last.x1 - last.x2) / \u9577\u3055;
|
|
19738
19855
|
const uy = (last.y1 - last.y2) / \u9577\u3055;
|
|
19739
|
-
const
|
|
19856
|
+
const head = segs[0];
|
|
19857
|
+
const \u6700\u5F8C\u306E\u533A\u9593\u304C\u8D77\u70B9\u3092\u542B\u3080 = Math.abs(last.x1 - head.x1) <= 0.5 && Math.abs(last.y1 - head.y1) <= 0.5;
|
|
19858
|
+
const \u52A9\u8D70\u4E0A\u9650 = \u6700\u5F8C\u306E\u533A\u9593\u304C\u8D77\u70B9\u3092\u542B\u3080 ? \u9577\u3055 - EDGE_STUB_OUT : \u9577\u3055;
|
|
19859
|
+
const \u4E38\u3081\u305F\u52A9\u8D70 = Math.min(\u52A9\u8D70, \u52A9\u8D70\u4E0A\u9650);
|
|
19860
|
+
if (\u4E38\u3081\u305F\u52A9\u8D70 < ENDPOINT_FAN_RUNUP) return null;
|
|
19861
|
+
const \u6298\u308C1 = { x: last.x2 + ux * \u4E38\u3081\u305F\u52A9\u8D70, y: last.y2 + uy * \u4E38\u3081\u305F\u52A9\u8D70 };
|
|
19740
19862
|
const \u6298\u308C2 = \u6A2A ? { x: \u6298\u308C1.x, y: \u6298\u308C1.y + d } : { x: \u6298\u308C1.x + d, y: \u6298\u308C1.y };
|
|
19741
19863
|
const \u7D42\u70B9 = \u6A2A ? { x: last.x2, y: last.y2 + d } : { x: last.x2 + d, y: last.y2 };
|
|
19742
19864
|
const \u65B0\u533A\u9593 = [
|
|
@@ -19747,7 +19869,6 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
|
|
|
19747
19869
|
if (nodes.some((n) => n.id !== e.from && n.id !== e.to && segmentsCrossRect(\u65B0\u533A\u9593, nodeRect(n)))) {
|
|
19748
19870
|
return null;
|
|
19749
19871
|
}
|
|
19750
|
-
const head = segs[0];
|
|
19751
19872
|
const parts = [`M ${head.x1} ${head.y1}`];
|
|
19752
19873
|
for (let i = 0; i < segs.length - 1; i++) {
|
|
19753
19874
|
const s = segs[i];
|
|
@@ -19758,7 +19879,8 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
|
|
|
19758
19879
|
}
|
|
19759
19880
|
parts.push(`L ${s.x2} ${s.y2}`);
|
|
19760
19881
|
}
|
|
19761
|
-
|
|
19882
|
+
const \u6298\u308C1\u306F\u76F4\u524D\u306E\u6298\u308C = Math.abs(\u6298\u308C1.x - last.x1) <= 0.5 && Math.abs(\u6298\u308C1.y - last.y1) <= 0.5;
|
|
19883
|
+
if (!\u6298\u308C1\u306F\u76F4\u524D\u306E\u6298\u308C) parts.push(`L ${round1(\u6298\u308C1.x)} ${round1(\u6298\u308C1.y)}`);
|
|
19762
19884
|
parts.push(`L ${round1(\u6298\u308C2.x)} ${round1(\u6298\u308C2.y)}`);
|
|
19763
19885
|
parts.push(`L ${round1(\u7D42\u70B9.x)} ${round1(\u7D42\u70B9.y)}`);
|
|
19764
19886
|
return parts.join(" ");
|
|
@@ -20241,6 +20363,7 @@ function layout(diag) {
|
|
|
20241
20363
|
diag.edges.filter((e) => e.posX1 !== void 0 && e.posY1 !== void 0 && e.posX2 !== void 0 && e.posY2 !== void 0).map((e) => e.id)
|
|
20242
20364
|
);
|
|
20243
20365
|
bowSharedStraightPaths(edges, nodesFinal, positionedEdgeIds);
|
|
20366
|
+
pullOutgoingFirstCorner(edges, nodesFinal);
|
|
20244
20367
|
fanIncomingEndpoints(edges, nodesFinal);
|
|
20245
20368
|
separateSharedStraightRuns(edges, nodesFinal);
|
|
20246
20369
|
hopEdgeCrossings(edges);
|