@cardenelabs/cdl 0.20.1 → 0.21.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 +44 -1
- package/dist/index.cjs +104 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +104 -2
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +104 -2
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +104 -2
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/src/layout/collisions.ts +162 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,47 @@ CDL (Chainome Diagram Language) の主要変更履歴。
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.21.1] - 2026-08-29
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **線の縦区間に張り付いた説明を離すようにした** (#594)
|
|
13
|
+
|
|
14
|
+
説明が別の線の縦区間の真下に居る形で、隙間が 0 のまま残っていた。
|
|
15
|
+
|
|
16
|
+
線の押し出しは発火している。 ただし安全判定 (`pathShiftIsSafe`) は「経路を壊さないか」
|
|
17
|
+
しか見ないので、**離れない向きへ動かして終わる**。 その時「線で逃がせた」 と数えるため、
|
|
18
|
+
cardene777/cdl#592 で入れた逃がし (説明の側を動かす) にも回らなかった。 繰り返しを 12 回まで
|
|
19
|
+
回しても隙間は 0 のままだと実測した。
|
|
20
|
+
|
|
21
|
+
押し出しは今までどおり出したまま、**離れなかった時は「逃がせた」 と数えない**。
|
|
22
|
+
出さない形にすると、離れないなりに効いていた押し出しが消えて別の 3 図が壊れる。
|
|
23
|
+
|
|
24
|
+
逃がす向きは **行き先を線ごとに確かめて** 選ぶ。 全体の最小距離だけで比べると、いま 0 の
|
|
25
|
+
線が離れるぶん別の線が 0 になっても「悪くなっていない」 と読める。
|
|
26
|
+
|
|
27
|
+
## [0.21.0] - 2026-08-29
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- **説明どうしの近接と、線から逃げられない説明を解消した** (#592)
|
|
32
|
+
|
|
33
|
+
説明を動かす後処理 (`resolveEdgeLabelOverlapsWithChainAndPropagate`) に 2 つの穴があった。
|
|
34
|
+
|
|
35
|
+
1 つ目は **説明どうしの近接を見ていなかった** こと。 重なった時しか動かさない一方、検査は
|
|
36
|
+
36 の間隔を要求するので 33 しか空かない組が残っていた (見本 7 図が同じ形)。 節や縦列の
|
|
37
|
+
見出しには近接を見る rule があり、説明どうしだけが抜けていた。
|
|
38
|
+
|
|
39
|
+
2 つ目は **線を動かせない時に何もしなかった** こと。 線をどの向きにも動かせない場合は
|
|
40
|
+
「説明の近接より経路の破損の方が重い」 として諦めていたが、説明は動かしても経路を壊さない。
|
|
41
|
+
説明の側を逃がす。
|
|
42
|
+
|
|
43
|
+
押し出す量に 2 の余裕を足した。 要求ちょうどに置くと px へ投影する丸めで割れる
|
|
44
|
+
(実測で押し出した先が `gap=32.0px (need 32px)` で error)。
|
|
45
|
+
|
|
46
|
+
dragon の見本で `clearance` の error が 7 図から 1 図に減った。 残る 1 図は engine が
|
|
47
|
+
world unit で、検査が px で測ることによる差 (viewBox 2511 の図で 14 world が 9px になる)。
|
|
48
|
+
|
|
8
49
|
## [0.20.1] - 2026-08-29
|
|
9
50
|
|
|
10
51
|
### Fixed
|
|
@@ -1039,7 +1080,9 @@ Initial OSS release.
|
|
|
1039
1080
|
使わない = annotated tag を push しても GitHub Release は作られず、 Release を作っていない版で
|
|
1040
1081
|
行き止まりになる。
|
|
1041
1082
|
|
|
1042
|
-
[Unreleased]: https://github.com/cardene777/cdl/compare/v0.
|
|
1083
|
+
[Unreleased]: https://github.com/cardene777/cdl/compare/v0.21.1...HEAD
|
|
1084
|
+
[0.21.1]: https://github.com/cardene777/cdl/compare/v0.21.0...v0.21.1
|
|
1085
|
+
[0.21.0]: https://github.com/cardene777/cdl/compare/v0.20.1...v0.21.0
|
|
1043
1086
|
[0.20.1]: https://github.com/cardene777/cdl/compare/v0.20.0...v0.20.1
|
|
1044
1087
|
[0.20.0]: https://github.com/cardene777/cdl/compare/v0.19.0...v0.20.0
|
|
1045
1088
|
[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 <=
|
|
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,83 @@ 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;
|
|
13095
|
+
const \u52D5\u304B\u3057\u305F\u5F8C = measurePathLabelGapSegs(
|
|
13096
|
+
simulateShiftedSegments(e, axis === "x" ? p.sign * amount : 0, axis === "y" ? p.sign * amount : 0),
|
|
13097
|
+
label
|
|
13098
|
+
);
|
|
13063
13099
|
out.push({ target: { kind: "edge-path", id: e.id }, axis, sign: p.sign, amount });
|
|
13100
|
+
\u7DDA\u3092\u52D5\u304B\u305B\u305F = \u52D5\u304B\u3057\u305F\u5F8C > gap;
|
|
13064
13101
|
break;
|
|
13065
13102
|
}
|
|
13103
|
+
if (!\u7DDA\u3092\u52D5\u304B\u305B\u305F) {
|
|
13104
|
+
const \u82AF = { x: label.x + label.w / 2, y: label.y + label.h / 2 };
|
|
13105
|
+
let \u8FD1\u3044\u70B9 = null;
|
|
13106
|
+
let \u6700\u77ED = Infinity;
|
|
13107
|
+
for (const seg of segs) {
|
|
13108
|
+
for (const \u70B9 of [
|
|
13109
|
+
{ x: seg.x1, y: seg.y1 },
|
|
13110
|
+
{ x: seg.x2, y: seg.y2 },
|
|
13111
|
+
{ x: (seg.x1 + seg.x2) / 2, y: (seg.y1 + seg.y2) / 2 }
|
|
13112
|
+
]) {
|
|
13113
|
+
const d = Math.hypot(\u70B9.x - \u82AF.x, \u70B9.y - \u82AF.y);
|
|
13114
|
+
if (d < \u6700\u77ED) {
|
|
13115
|
+
\u6700\u77ED = d;
|
|
13116
|
+
\u8FD1\u3044\u70B9 = \u70B9;
|
|
13117
|
+
}
|
|
13118
|
+
}
|
|
13119
|
+
}
|
|
13120
|
+
if (\u8FD1\u3044\u70B9) {
|
|
13121
|
+
const dx = \u82AF.x - \u8FD1\u3044\u70B9.x;
|
|
13122
|
+
const dy = \u82AF.y - \u8FD1\u3044\u70B9.y;
|
|
13123
|
+
const \u91CF = pathLabelClearance - gap + NEAR_MISS_MARGIN;
|
|
13124
|
+
const \u5019\u88DC = Math.abs(dx) >= Math.abs(dy) ? [
|
|
13125
|
+
{ axis: "x", sign: dx >= 0 ? 1 : -1 },
|
|
13126
|
+
{ axis: "y", sign: dy >= 0 ? 1 : -1 }
|
|
13127
|
+
] : [
|
|
13128
|
+
{ axis: "y", sign: dy >= 0 ? 1 : -1 },
|
|
13129
|
+
{ axis: "x", sign: dx >= 0 ? 1 : -1 }
|
|
13130
|
+
];
|
|
13131
|
+
const \u52D5\u304B\u3057\u305F\u7BB1 = (axis, sign) => ({
|
|
13132
|
+
...label,
|
|
13133
|
+
x: label.x + (axis === "x" ? sign * \u91CF : 0),
|
|
13134
|
+
y: label.y + (axis === "y" ? sign * \u91CF : 0)
|
|
13135
|
+
});
|
|
13136
|
+
const \u7DDA\u3054\u3068\u306E\u8DDD\u96E2 = (\u7BB1) => {
|
|
13137
|
+
const \u51FA = /* @__PURE__ */ new Map();
|
|
13138
|
+
for (const \u4ED6 of edges) {
|
|
13139
|
+
if (\u4ED6.id === label.id) continue;
|
|
13140
|
+
const segs2 = segmentsExcludingOwnPath(shiftedSegments(\u4ED6.id, \u4ED6.d), ownSegsOf(label.id));
|
|
13141
|
+
if (segs2.length === 0) continue;
|
|
13142
|
+
\u51FA.set(\u4ED6.id, measurePathLabelGapSegs(segs2, \u7BB1));
|
|
13143
|
+
}
|
|
13144
|
+
return \u51FA;
|
|
13145
|
+
};
|
|
13146
|
+
const \u3044\u307E\u306E\u8DDD\u96E2 = \u7DDA\u3054\u3068\u306E\u8DDD\u96E2(label);
|
|
13147
|
+
const \u60AA\u304F\u3059\u308B = (\u7BB1) => {
|
|
13148
|
+
const \u5F8C = \u7DDA\u3054\u3068\u306E\u8DDD\u96E2(\u7BB1);
|
|
13149
|
+
for (const [id, \u524D\u306E\u5024] of \u3044\u307E\u306E\u8DDD\u96E2) {
|
|
13150
|
+
const \u5F8C\u306E\u5024 = \u5F8C.get(id) ?? Infinity;
|
|
13151
|
+
if (\u5F8C\u306E\u5024 < Math.min(\u524D\u306E\u5024, pathLabelClearance)) return true;
|
|
13152
|
+
}
|
|
13153
|
+
return false;
|
|
13154
|
+
};
|
|
13155
|
+
for (const \u5019 of \u5019\u88DC) {
|
|
13156
|
+
if (\u60AA\u304F\u3059\u308B(\u52D5\u304B\u3057\u305F\u7BB1(\u5019.axis, \u5019.sign))) continue;
|
|
13157
|
+
out.push({
|
|
13158
|
+
target: { kind: "label", id: label.id },
|
|
13159
|
+
axis: \u5019.axis,
|
|
13160
|
+
sign: \u5019.sign,
|
|
13161
|
+
amount: \u91CF,
|
|
13162
|
+
chain: false
|
|
13163
|
+
});
|
|
13164
|
+
break;
|
|
13165
|
+
}
|
|
13166
|
+
}
|
|
13167
|
+
}
|
|
13066
13168
|
}
|
|
13067
13169
|
}
|
|
13068
13170
|
for (const label of labels) {
|