@cardenelabs/cdl 0.64.1 → 0.66.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,92 @@ CDL (Chainome Diagram Language) の主要変更履歴。
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.66.0] - 2026-09-15
9
+
10
+ ### Fixed
11
+
12
+ - **段の違う箱を繋ぐ矢印が、間の箱を貫くのを直した** (#867)
13
+
14
+ 段の違う箱を横に繋ぐ経路は「横に走る → 縦に折れる → 横に走る」 の L 字を描く。 折れる位置は箱を避けて左右に
15
+ 退くが、**退いた後に横の走りが箱を横切るかを一度も見ていなかった**。 退けた分だけ横の走りが伸びるため、
16
+ 避けたはずの同じ箱を横切る。
17
+
18
+ 段 0 に 検査 (x 40-360) と 記録 (x 1864-2184)、段 1 に背の高い 成形機 (x 648-968) と 塗装機 (x 1256-1576) を
19
+ 並べ、成形機から記録へ引いた形。
20
+
21
+ ```
22
+ 変更前 ... M 968 486 L 1630 486 Q 1644 486, 1644 472 L 1644 150 Q 1644 136, 1658 136 L 1864 136
23
+ 変更後 ... M 968 486 L 1174 486 Q 1188 486, 1188 472 L 1188 150 Q 1188 136, 1202 136 L 1864 136
24
+ ```
25
+
26
+ 変更前は `y = 486` の横の走りが `x = 968` から `1644` まで伸び、その間の 塗装機 (x 1256-1576、y 296-676) を
27
+ 横切っていた。 絵の検査の `edge-node-cross` が 1 件出る形。
28
+
29
+ 退く向きは「折れる位置を動かす量が少ない側」 だけで決めていた。 この形は右へ 228 と左へ 228 で並び、
30
+ 同点を右に倒す規則が塞がる側を選んでいた。
31
+
32
+ 直した点は 2 つ。
33
+
34
+ | 直した点 | 変更前 | 変更後 |
35
+ |---|---|---|
36
+ | 退く向き | 動かす量が少ない側 | 横の走りが横切らない側を先に見る。 左右で同じ時だけ動かす量が少ない側 |
37
+ | 退く判定の起点 | 縦の走りと説明文の帯だけ | 横の走りが箱を通る形も数える |
38
+
39
+ 起点を広げないと、最初の折れる位置で既に横の走りが箱を横切っている形は 1 度も退かない。 繋ぎ元と同じ段に
40
+ 箱を置き、折れる位置より手前に来るように並べると出る (実測 = 受付 → 出荷 の矢印が、間の 控え を横切る)。
41
+
42
+ 横切るかの判定は箱の矩形そのもので行い、余白を足さない。 絵の検査が箱の矩形で貫通を数えるため、余白を足すと
43
+ 「検査は通るのに経路だけ動く」 図が出る。 端がちょうど箱の縁に載る形も通さない = 箱の縁から出る線は必ず縁に
44
+ 載るので、閉じた側にすると自分の出入口を障害物と読む。
45
+
46
+ dragon の見本帳 505 枚の辺 472 本を並べ直して突き合わせた結果、**変わった道筋は 0 本**。 横切る箱が無い
47
+ 図では折れる位置が 2 つの箱のちょうど中間に残る。
48
+
49
+ dragon の見本帳で合流する矢印が間の部品を貫いた原因 (dragon#2011)。
50
+
51
+ ## [0.65.0] - 2026-09-15
52
+
53
+ ### Fixed
54
+
55
+ - **横に並んだ箱の高さが近い時に、矢印の角が裏返るのを直した** (#865)
56
+
57
+ 横に並んだ箱を繋ぐ経路は「横に走る → 縦に折れる → 横に走る」 の L 字で、角は「手前で 14 だけ直線を止め、弧で
58
+ 14 先へ抜ける」 形で丸める。 縦の走りは両端の 2 角が 14 ずつ使うため 28 が要るが、**その長さがあるかを
59
+ 一度も見ていなかった**。
60
+
61
+ 2 つの箱の中心の高さが 28 より近いと、止めた点が走りの向こう側へ回り込む。 直線が逆走し、角の外へ突起が出る。
62
+ 中心の高さが 506 と 516 の対で実測した形。
63
+
64
+ ```
65
+ 変更前 ... M 360 506 L 486 506 Q 500 506, 500 520 L 500 502 Q 500 516, 514 516 L 640 516
66
+ 変更後 ... M 360 506 L 495 506 Q 500 506, 500 511 L 500 511 Q 500 516, 505 516 L 640 516
67
+ ```
68
+
69
+ 変更前の縦の走りは `520` から `502` へ 18 戻っている。 進む向きは下 (506 → 516) なので逆走。
70
+
71
+ 丸みを、その角が使える長さで頭打ちにする。 縦の走りは両端の 2 角で使うので半分、横の走りは片端の 1 角しか
72
+ 使わないのでそのまま渡す。
73
+
74
+ | 走り | 渡す長さ | 効く場面 |
75
+ |---|---|---|
76
+ | 縦 (折れる位置の上下) | `|B.y - A.y| / 2` | 中心の高さが 28 より近い対 |
77
+ | 横 (箱から折れる位置まで) | `|midX - A.x|` と `|B.x - midX|` | 箱どうしの隙間が 28 より狭い対 |
78
+
79
+ 頭打ちは `midX` (折れる位置) が決まってから計算する。 説明文を避ける繰り返しが `midX` を中央から動かすため、
80
+ 中央のつもりで先に計算すると、動いた後の横の走りを測り損ねる。
81
+
82
+ 同じ規則は経路を組み直す側 (`verticesToPath`) が既に持っており、L 字の分岐だけが持っていなかった。
83
+ 丸みが足りている対 (中心の高さの差 28 以上、隙間 28 以上) の `d` は 1 文字も変わらない。
84
+
85
+ dragon の見本帳で、高さの違う部品どうしを矢印で繋ぐ形が出せなかった原因 (dragon#2012)。
86
+
87
+ ### Fixed (公開作業の取りこぼし)
88
+
89
+ - **`v0.64.1` の tag と比較 link を後から付けた**
90
+
91
+ 0.64.1 は npm に公開済だったが、tag も比較 link も残っていなかった。 版から commit を辿れない状態で、
92
+ 変更履歴の検査 3 件が落ちたままになっていた。 tag は公開済の commit (`f2a4be9`) に付けた。
93
+
8
94
  ## [0.64.1] - 2026-09-15
9
95
 
10
96
  ### Fixed
@@ -2727,7 +2813,10 @@ Initial OSS release.
2727
2813
  使わない = annotated tag を push しても GitHub Release は作られず、 Release を作っていない版で
2728
2814
  行き止まりになる。
2729
2815
 
2730
- [Unreleased]: https://github.com/cardene777/cdl/compare/v0.64.0...HEAD
2816
+ [Unreleased]: https://github.com/cardene777/cdl/compare/v0.66.0...HEAD
2817
+ [0.66.0]: https://github.com/cardene777/cdl/compare/v0.65.0...v0.66.0
2818
+ [0.65.0]: https://github.com/cardene777/cdl/compare/v0.64.1...v0.65.0
2819
+ [0.64.1]: https://github.com/cardene777/cdl/compare/v0.64.0...v0.64.1
2731
2820
  [0.64.0]: https://github.com/cardene777/cdl/compare/v0.63.0...v0.64.0
2732
2821
  [0.63.0]: https://github.com/cardene777/cdl/compare/v0.62.0...v0.63.0
2733
2822
  [0.62.0]: https://github.com/cardene777/cdl/compare/v0.61.0...v0.62.0
package/dist/index.cjs CHANGED
@@ -18757,6 +18757,13 @@ var VERTICAL_DETOUR_CORNER = 14;
18757
18757
  function verticalCornerDir(from, to) {
18758
18758
  return to < from ? -1 : 1;
18759
18759
  }
18760
+ function cornerRadiusFor(\u534A\u5F84, ...\u8D70\u308A) {
18761
+ return Math.min(\u534A\u5F84, ...\u8D70\u308A.map((v) => Math.abs(v)));
18762
+ }
18763
+ function runCrossesBox(\u8D70\u308A, \u7BB1) {
18764
+ if (\u8D70\u308A.y <= \u7BB1.cy - \u7BB1.h / 2 || \u8D70\u308A.y >= \u7BB1.cy + \u7BB1.h / 2) return false;
18765
+ return \u7BB1.cx + \u7BB1.w / 2 > Math.min(\u8D70\u308A.x1, \u8D70\u308A.x2) && \u7BB1.cx - \u7BB1.w / 2 < Math.max(\u8D70\u308A.x1, \u8D70\u308A.x2);
18766
+ }
18760
18767
  var VERTICAL_DETOUR_EXIT = 45;
18761
18768
  function nearestBoxDistance(anchorX, dir, verticalTop, verticalBottom, boxes) {
18762
18769
  let nearest = Infinity;
@@ -19749,21 +19756,32 @@ function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _from
19749
19756
  const labelIntersect = oTop < labelBottom && oBottom > labelTop;
19750
19757
  return segIntersect || labelIntersect;
19751
19758
  };
19759
+ const \u6A2A\u306E\u8D70\u308A\u304C\u585E\u304C\u308B = (mx) => labelObstacles.some((o) => {
19760
+ if (o.id === from.id || o.id === to.id) return false;
19761
+ return runCrossesBox({ y: A.y, x1: A.x, x2: mx }, o) || runCrossesBox({ y: B.y, x1: mx, x2: B.x }, o);
19762
+ });
19752
19763
  let iter = 0;
19753
19764
  while (iter < 12) {
19754
19765
  const band = labelBand(midX2);
19755
- const hit = labelObstacles.find((o) => intersects(o, band));
19766
+ const hit = labelObstacles.find((o) => intersects(o, band)) ?? labelObstacles.find(
19767
+ (o) => o.id !== from.id && o.id !== to.id && (runCrossesBox({ y: A.y, x1: A.x, x2: midX2 }, o) || runCrossesBox({ y: B.y, x1: midX2, x2: B.x }, o))
19768
+ );
19756
19769
  if (!hit) break;
19757
19770
  const hitLeft = hit.cx - hit.w / 2;
19758
19771
  const hitRight = hit.cx + hit.w / 2;
19759
19772
  const retreatRight = hitRight + labelHalfW + CLEARANCE_NODE_LABEL + 4;
19760
19773
  const retreatLeft = hitLeft - labelHalfW - CLEARANCE_NODE_LABEL - 4;
19774
+ const \u53F3\u304C\u585E\u304C\u308B = \u6A2A\u306E\u8D70\u308A\u304C\u585E\u304C\u308B(retreatRight);
19775
+ const \u5DE6\u304C\u585E\u304C\u308B = \u6A2A\u306E\u8D70\u308A\u304C\u585E\u304C\u308B(retreatLeft);
19761
19776
  const dRight = Math.abs(retreatRight - midX2);
19762
19777
  const dLeft = Math.abs(retreatLeft - midX2);
19763
- midX2 = dRight <= dLeft ? retreatRight : retreatLeft;
19778
+ const \u6B21 = \u53F3\u304C\u585E\u304C\u308B === \u5DE6\u304C\u585E\u304C\u308B ? dRight <= dLeft ? retreatRight : retreatLeft : \u53F3\u304C\u585E\u304C\u308B ? retreatLeft : retreatRight;
19779
+ if (\u6B21 === midX2) break;
19780
+ midX2 = \u6B21;
19764
19781
  iter++;
19765
19782
  }
19766
19783
  }
19784
+ const lCorner = cornerRadiusFor(corner, (B.y - A.y) / 2, midX2 - A.x, B.x - midX2);
19767
19785
  let verticalMidY = (A.y + B.y) / 2;
19768
19786
  if (labelHalfW > 0) {
19769
19787
  const labelBoxH = 36;
@@ -19801,10 +19819,10 @@ function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _from
19801
19819
  }
19802
19820
  }
19803
19821
  if (edge?.overlay) {
19804
- const exitEndX = midX2 - xDir * corner;
19805
- const enterStartX = midX2 + xDir * corner;
19806
- const midStartY = A.y + yDir * corner;
19807
- const midEndY = B.y - yDir * corner;
19822
+ const exitEndX = midX2 - xDir * lCorner;
19823
+ const enterStartX = midX2 + xDir * lCorner;
19824
+ const midStartY = A.y + yDir * lCorner;
19825
+ const midEndY = B.y - yDir * lCorner;
19808
19826
  const segments = [
19809
19827
  { len: Math.abs(exitEndX - A.x), midXVal: (A.x + exitEndX) / 2, midYVal: A.y },
19810
19828
  { len: Math.abs(midEndY - midStartY), midXVal: midX2, midYVal: (midStartY + midEndY) / 2 },
@@ -19813,10 +19831,10 @@ function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _from
19813
19831
  const longest = segments.reduce((a, b) => b.len > a.len ? b : a);
19814
19832
  return {
19815
19833
  d: `M ${A.x} ${A.y}
19816
- L ${midX2 - xDir * corner} ${A.y}
19817
- Q ${midX2} ${A.y}, ${midX2} ${A.y + yDir * corner}
19818
- L ${midX2} ${B.y - yDir * corner}
19819
- Q ${midX2} ${B.y}, ${midX2 + xDir * corner} ${B.y}
19834
+ L ${midX2 - xDir * lCorner} ${A.y}
19835
+ Q ${midX2} ${A.y}, ${midX2} ${A.y + yDir * lCorner}
19836
+ L ${midX2} ${B.y - yDir * lCorner}
19837
+ Q ${midX2} ${B.y}, ${midX2 + xDir * lCorner} ${B.y}
19820
19838
  L ${B.x} ${B.y}`,
19821
19839
  labelX: longest.midXVal,
19822
19840
  labelY: longest.midYVal,
@@ -19825,10 +19843,10 @@ function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _from
19825
19843
  }
19826
19844
  return {
19827
19845
  d: `M ${A.x} ${A.y}
19828
- L ${midX2 - xDir * corner} ${A.y}
19829
- Q ${midX2} ${A.y}, ${midX2} ${A.y + yDir * corner}
19830
- L ${midX2} ${B.y - yDir * corner}
19831
- Q ${midX2} ${B.y}, ${midX2 + xDir * corner} ${B.y}
19846
+ L ${midX2 - xDir * lCorner} ${A.y}
19847
+ Q ${midX2} ${A.y}, ${midX2} ${A.y + yDir * lCorner}
19848
+ L ${midX2} ${B.y - yDir * lCorner}
19849
+ Q ${midX2} ${B.y}, ${midX2 + xDir * lCorner} ${B.y}
19832
19850
  L ${B.x} ${B.y}`,
19833
19851
  labelX: midX2,
19834
19852
  labelY: verticalMidY,