@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/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
- if (list.length < 2) continue;
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\u9694 = Math.min(ENDPOINT_FAN_STEP, \u4F7F\u3048\u308B\u5E452 / (list.length - 1));
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 \u4E26\u3073 = list.map((e) => ({ e, \u6DF1\u3055: \u8FBA\u304B\u3089\u96E2\u308C\u305F\u5074\u306E\u4F4D\u7F6E(e, \u6A2A) ?? 0 })).sort((a, b) => a.\u6DF1\u3055 - b.\u6DF1\u3055 || (a.e.id < b.e.id ? -1 : 1));
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
- e.d = \u5DEE\u66FF;
19713
- if (countEdgeCrossings(edges).count > \u524D\u306E\u4EA4\u5DEE) e.d = \u524D;
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 \u6298\u308C1 = { x: last.x2 + ux * ENDPOINT_FAN_RUNUP, y: last.y2 + uy * ENDPOINT_FAN_RUNUP };
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
- parts.push(`L ${round1(\u6298\u308C1.x)} ${round1(\u6298\u308C1.y)}`);
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);