@cardenelabs/cdl 0.20.1 → 0.21.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/CHANGELOG.md CHANGED
@@ -5,6 +5,28 @@ CDL (Chainome Diagram Language) の主要変更履歴。
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.21.0] - 2026-08-29
9
+
10
+ ### Fixed
11
+
12
+ - **説明どうしの近接と、線から逃げられない説明を解消した** (#592)
13
+
14
+ 説明を動かす後処理 (`resolveEdgeLabelOverlapsWithChainAndPropagate`) に 2 つの穴があった。
15
+
16
+ 1 つ目は **説明どうしの近接を見ていなかった** こと。 重なった時しか動かさない一方、検査は
17
+ 36 の間隔を要求するので 33 しか空かない組が残っていた (見本 7 図が同じ形)。 節や縦列の
18
+ 見出しには近接を見る rule があり、説明どうしだけが抜けていた。
19
+
20
+ 2 つ目は **線を動かせない時に何もしなかった** こと。 線をどの向きにも動かせない場合は
21
+ 「説明の近接より経路の破損の方が重い」 として諦めていたが、説明は動かしても経路を壊さない。
22
+ 説明の側を逃がす。
23
+
24
+ 押し出す量に 2 の余裕を足した。 要求ちょうどに置くと px へ投影する丸めで割れる
25
+ (実測で押し出した先が `gap=32.0px (need 32px)` で error)。
26
+
27
+ dragon の見本で `clearance` の error が 7 図から 1 図に減った。 残る 1 図は engine が
28
+ world unit で、検査が px で測ることによる差 (viewBox 2511 の図で 14 world が 9px になる)。
29
+
8
30
  ## [0.20.1] - 2026-08-29
9
31
 
10
32
  ### Fixed
@@ -1039,7 +1061,8 @@ Initial OSS release.
1039
1061
  使わない = annotated tag を push しても GitHub Release は作られず、 Release を作っていない版で
1040
1062
  行き止まりになる。
1041
1063
 
1042
- [Unreleased]: https://github.com/cardene777/cdl/compare/v0.20.1...HEAD
1064
+ [Unreleased]: https://github.com/cardene777/cdl/compare/v0.21.0...HEAD
1065
+ [0.21.0]: https://github.com/cardene777/cdl/compare/v0.20.1...v0.21.0
1043
1066
  [0.20.1]: https://github.com/cardene777/cdl/compare/v0.20.0...v0.20.1
1044
1067
  [0.20.0]: https://github.com/cardene777/cdl/compare/v0.19.0...v0.20.0
1045
1068
  [0.19.0]: https://github.com/cardene777/cdl/compare/v0.18.1...v0.19.0
package/dist/index.cjs CHANGED
@@ -12093,6 +12093,7 @@ function footerShapeDrawTop(node) {
12093
12093
 
12094
12094
  // src/layout/collisions.ts
12095
12095
  var LANE_LABEL_CLEARANCE_MARGIN = 2;
12096
+ var NEAR_MISS_MARGIN = LANE_LABEL_CLEARANCE_MARGIN;
12096
12097
  function collectBBoxes(lanes, nodes, edges) {
12097
12098
  const out = [];
12098
12099
  for (const lane of lanes) {
@@ -12920,8 +12921,8 @@ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClea
12920
12921
  };
12921
12922
  const shift = computeOverlapShift(label, inflated);
12922
12923
  if (!shift) continue;
12923
- const amount = shift.amount - minClearance;
12924
- if (amount <= 0) continue;
12924
+ const amount = shift.amount - minClearance + NEAR_MISS_MARGIN;
12925
+ if (amount <= NEAR_MISS_MARGIN) continue;
12925
12926
  out.push({
12926
12927
  target: { kind: "label", id: label.id },
12927
12928
  axis: shift.axis,
@@ -12962,6 +12963,36 @@ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClea
12962
12963
  out.push({ target: { kind: "label", id: moveBox.id }, ...shift });
12963
12964
  }
12964
12965
  }
12966
+ for (let i = 0; i < labels.length; i++) {
12967
+ for (let j = i + 1; j < labels.length; j++) {
12968
+ const a = labels[i];
12969
+ const b = labels[j];
12970
+ if (computeOverlapShift(a, b)) continue;
12971
+ const orderA = edgeOrder.get(a.id);
12972
+ const orderB = edgeOrder.get(b.id);
12973
+ const moveBox = orderA > orderB ? a : b;
12974
+ const staticBox = orderA > orderB ? b : a;
12975
+ const required = requiredNearClearance(moveBox.kind, staticBox.kind);
12976
+ const inflated = {
12977
+ ...staticBox,
12978
+ x: staticBox.x - required,
12979
+ y: staticBox.y - required,
12980
+ w: staticBox.w + required * 2,
12981
+ h: staticBox.h + required * 2
12982
+ };
12983
+ const shift = computeOverlapShift(moveBox, inflated);
12984
+ if (!shift) continue;
12985
+ const amount = shift.amount - minClearance + NEAR_MISS_MARGIN;
12986
+ if (amount <= NEAR_MISS_MARGIN) continue;
12987
+ out.push({
12988
+ target: { kind: "label", id: moveBox.id },
12989
+ axis: shift.axis,
12990
+ sign: shift.sign,
12991
+ amount,
12992
+ chain: false
12993
+ });
12994
+ }
12995
+ }
12965
12996
  for (const label of labels) {
12966
12997
  const currentShift = getLabelChainShift(label.id);
12967
12998
  if (currentShift.dx === 0 && currentShift.dy === 0) continue;
@@ -13057,12 +13088,46 @@ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClea
13057
13088
  if (bestSideIdx < 0) continue;
13058
13089
  const amount = pathLabelClearance - gap + pathLabelClearance;
13059
13090
  const ordered = edgeProbes.map((p, idx) => ({ p, idx })).sort((a, b) => probeDist[a.idx] - probeDist[b.idx]);
13091
+ let \u7DDA\u3092\u52D5\u304B\u305B\u305F = false;
13060
13092
  for (const { p } of ordered) {
13061
13093
  const axis = p.axis;
13062
13094
  if (!pathShiftIsSafe(e.id, axis, p.sign, amount)) continue;
13063
13095
  out.push({ target: { kind: "edge-path", id: e.id }, axis, sign: p.sign, amount });
13096
+ \u7DDA\u3092\u52D5\u304B\u305B\u305F = true;
13064
13097
  break;
13065
13098
  }
13099
+ if (!\u7DDA\u3092\u52D5\u304B\u305B\u305F) {
13100
+ const \u82AF = { x: label.x + label.w / 2, y: label.y + label.h / 2 };
13101
+ let \u8FD1\u3044\u70B9 = null;
13102
+ let \u6700\u77ED = Infinity;
13103
+ for (const seg of segs) {
13104
+ for (const \u70B9 of [
13105
+ { x: seg.x1, y: seg.y1 },
13106
+ { x: seg.x2, y: seg.y2 },
13107
+ { x: (seg.x1 + seg.x2) / 2, y: (seg.y1 + seg.y2) / 2 }
13108
+ ]) {
13109
+ const d = Math.hypot(\u70B9.x - \u82AF.x, \u70B9.y - \u82AF.y);
13110
+ if (d < \u6700\u77ED) {
13111
+ \u6700\u77ED = d;
13112
+ \u8FD1\u3044\u70B9 = \u70B9;
13113
+ }
13114
+ }
13115
+ }
13116
+ if (\u8FD1\u3044\u70B9) {
13117
+ const dx = \u82AF.x - \u8FD1\u3044\u70B9.x;
13118
+ const dy = \u82AF.y - \u8FD1\u3044\u70B9.y;
13119
+ const axis = Math.abs(dx) >= Math.abs(dy) ? "x" : "y";
13120
+ const \u5411\u304D = axis === "x" ? dx : dy;
13121
+ const sign = \u5411\u304D >= 0 ? 1 : -1;
13122
+ out.push({
13123
+ target: { kind: "label", id: label.id },
13124
+ axis,
13125
+ sign,
13126
+ amount: pathLabelClearance - gap + NEAR_MISS_MARGIN,
13127
+ chain: false
13128
+ });
13129
+ }
13130
+ }
13066
13131
  }
13067
13132
  }
13068
13133
  for (const label of labels) {