@cardenelabs/cdl 0.47.0 → 0.49.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/dist/react.js CHANGED
@@ -1839,7 +1839,7 @@ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClea
1839
1839
  { axis: "y", sign: dy >= 0 ? 1 : -1 },
1840
1840
  { axis: "x", sign: dx >= 0 ? 1 : -1 }
1841
1841
  ];
1842
- const \u52D5\u304B\u3057\u305F\u7BB1 = (axis, sign) => ({
1842
+ const \u52D5\u304B\u3057\u305F\u7BB12 = (axis, sign) => ({
1843
1843
  ...label,
1844
1844
  x: label.x + (axis === "x" ? sign * \u91CF : 0),
1845
1845
  y: label.y + (axis === "y" ? sign * \u91CF : 0)
@@ -1864,7 +1864,7 @@ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClea
1864
1864
  return false;
1865
1865
  };
1866
1866
  for (const \u5019 of \u5019\u88DC) {
1867
- if (\u60AA\u304F\u3059\u308B(\u52D5\u304B\u3057\u305F\u7BB1(\u5019.axis, \u5019.sign))) continue;
1867
+ if (\u60AA\u304F\u3059\u308B(\u52D5\u304B\u3057\u305F\u7BB12(\u5019.axis, \u5019.sign))) continue;
1868
1868
  out.push({
1869
1869
  target: { kind: "label", id: label.id },
1870
1870
  axis: \u5019.axis,
@@ -2030,15 +2030,7 @@ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClea
2030
2030
  edgePathShifts: edgePathShiftMap
2031
2031
  };
2032
2032
  }
2033
- function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
2034
- if (edges.length === 0) return edges;
2035
- const labeledIds = new Set(
2036
- edges.filter((e) => e.label?.trim() || e.sub?.trim()).map((e) => e.id)
2037
- );
2038
- if (labeledIds.size === 0) return edges;
2039
- const \u7BB1\u305F\u3061 = obstacles.filter((o) => o.kind === "node" || o.kind === "lane-label");
2040
- const edgeById = /* @__PURE__ */ new Map();
2041
- for (const e of edges) edgeById.set(e.id, e);
2033
+ function \u7DDA\u306E\u6E2C\u308A\u65B9\u3092\u4F5C\u308B() {
2042
2034
  const \u533A\u9593cache = /* @__PURE__ */ new Map();
2043
2035
  const \u533A\u9593 = (id, d) => {
2044
2036
  const hit = \u533A\u9593cache.get(id);
@@ -2074,7 +2066,143 @@ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
2074
2066
  const dy = Math.max(0, Math.max(box.y - (b.y + b.h), b.y - (box.y + box.h)));
2075
2067
  return Math.hypot(dx, dy) >= \u4F59\u88D5;
2076
2068
  };
2077
- const \u6700\u5927\u79FB\u52D5 = CHAIN_SHIFT_MAX_ACCUMULATED * 2;
2069
+ return { \u533A\u9593, \u9060\u3044 };
2070
+ }
2071
+ var \u672D\u306E\u6700\u5927\u79FB\u52D5 = CHAIN_SHIFT_MAX_ACCUMULATED * 2;
2072
+ var \u96E2\u308C\u91CF = (a, b) => ({
2073
+ x: Math.max(a.x - (b.x + b.w), b.x - (a.x + a.w)),
2074
+ y: Math.max(a.y - (b.y + b.h), b.y - (a.y + a.h))
2075
+ });
2076
+ var \u52D5\u304B\u3057\u305F\u7BB1 = (box, axis, sign, amount) => ({
2077
+ ...box,
2078
+ x: box.x + (axis === "x" ? sign * amount : 0),
2079
+ y: box.y + (axis === "y" ? sign * amount : 0)
2080
+ });
2081
+ function \u672D\u306E\u79FB\u52D5\u3092\u585E\u3050\u76F8\u624B\u3092\u63A2\u3059(\u5468\u308A, label, \u884C\u304D\u5148) {
2082
+ const { \u7BB1\u305F\u3061, labels, edges, edgeById, \u6E2C\u308A\u65B9 } = \u5468\u308A;
2083
+ for (const obs of \u7BB1\u305F\u3061) {
2084
+ const \u524D = computeGap(label, obs);
2085
+ const \u5F8C = computeGap(\u884C\u304D\u5148, obs);
2086
+ if (\u5F8C < Math.min(\u524D, requiredNearClearance("edge-label", obs.kind))) return { \u76F8\u624B: `${obs.kind}:${obs.id}`, \u524D, \u5F8C };
2087
+ }
2088
+ const \u672D\u306E\u8981\u6C42 = requiredNearClearance("edge-label", "edge-label");
2089
+ for (const \u4ED6 of labels) {
2090
+ if (\u4ED6.id === label.id) continue;
2091
+ const \u524D = computeGap(label, \u4ED6);
2092
+ const \u5F8C = computeGap(\u884C\u304D\u5148, \u4ED6);
2093
+ if (\u5F8C < Math.min(\u524D, \u672D\u306E\u8981\u6C42)) return { \u76F8\u624B: `edge-label:${\u4ED6.id}`, \u524D, \u5F8C };
2094
+ }
2095
+ const \u81EA\u5206 = edgeById.get(label.id);
2096
+ const \u81EA\u5206\u306E\u533A\u9593 = \u81EA\u5206 ? \u6E2C\u308A\u65B9.\u533A\u9593(\u81EA\u5206.id, \u81EA\u5206.d) : [];
2097
+ if (\u81EA\u5206\u306E\u533A\u9593.length > 0) {
2098
+ const \u524D = measurePathLabelGapSegs(\u81EA\u5206\u306E\u533A\u9593, label);
2099
+ const \u5F8C = measurePathLabelGapSegs(\u81EA\u5206\u306E\u533A\u9593, \u884C\u304D\u5148);
2100
+ if (\u5F8C > Math.max(\u524D, DIST_LABEL_PATH_MAX)) return { \u76F8\u624B: "\u81EA\u5206\u306E\u7DDA", \u524D, \u5F8C };
2101
+ }
2102
+ for (const \u76F8\u624B of edges) {
2103
+ if (\u76F8\u624B.id === label.id) continue;
2104
+ if (\u6E2C\u308A\u65B9.\u9060\u3044(label, \u76F8\u624B.id, \u76F8\u624B.d, LABEL_TO_PATH_CLEARANCE) && \u6E2C\u308A\u65B9.\u9060\u3044(\u884C\u304D\u5148, \u76F8\u624B.id, \u76F8\u624B.d, LABEL_TO_PATH_CLEARANCE)) continue;
2105
+ const segs = segmentsExcludingOwnPath(\u6E2C\u308A\u65B9.\u533A\u9593(\u76F8\u624B.id, \u76F8\u624B.d), \u81EA\u5206\u306E\u533A\u9593);
2106
+ if (segs.length === 0) continue;
2107
+ const \u524D = measurePathLabelGapSegs(segs, label);
2108
+ const \u5F8C = measurePathLabelGapSegs(segs, \u884C\u304D\u5148);
2109
+ if (\u5F8C < Math.min(\u524D, LABEL_TO_PATH_CLEARANCE)) return { \u76F8\u624B: `edge-path:${\u76F8\u624B.id}`, \u524D, \u5F8C };
2110
+ }
2111
+ return null;
2112
+ }
2113
+ function \u77E9\u5F62\u306E\u5019\u88DC(label, static\u7BB1, required) {
2114
+ const sep = \u96E2\u308C\u91CF(label, static\u7BB1);
2115
+ const \u5411\u304D = (axis) => {
2116
+ const a = axis === "x" ? label.x + label.w / 2 : label.y + label.h / 2;
2117
+ const b = axis === "x" ? static\u7BB1.x + static\u7BB1.w / 2 : static\u7BB1.y + static\u7BB1.h / 2;
2118
+ return a >= b ? 1 : -1;
2119
+ };
2120
+ return [
2121
+ { axis: "x", sign: \u5411\u304D("x"), amount: required - sep.x + NEAR_MISS_MARGIN },
2122
+ { axis: "y", sign: \u5411\u304D("y"), amount: required - sep.y + NEAR_MISS_MARGIN }
2123
+ ];
2124
+ }
2125
+ function \u7DDA\u304B\u3089\u96E2\u308C\u308B\u91CF(segs, label, gap, axis, sign) {
2126
+ const \u6700\u5927\u79FB\u52D5 = \u672D\u306E\u6700\u5927\u79FB\u52D5;
2127
+ const \u6E80\u305F\u3059 = (\u91CF) => measurePathLabelGapSegs(segs, \u52D5\u304B\u3057\u305F\u7BB1(label, axis, sign, \u91CF)) >= LABEL_TO_PATH_CLEARANCE;
2128
+ let lo = 0;
2129
+ let hi = Math.max(4, LABEL_TO_PATH_CLEARANCE - gap);
2130
+ while (!\u6E80\u305F\u3059(hi)) {
2131
+ if (hi >= \u6700\u5927\u79FB\u52D5) return null;
2132
+ lo = hi;
2133
+ hi = Math.min(hi * 2, \u6700\u5927\u79FB\u52D5);
2134
+ }
2135
+ for (let k = 0; k < 12; k += 1) {
2136
+ const mid = (lo + hi) / 2;
2137
+ if (\u6E80\u305F\u3059(mid)) hi = mid;
2138
+ else lo = mid;
2139
+ }
2140
+ return hi + NEAR_MISS_MARGIN;
2141
+ }
2142
+ var \u5411\u304D\u306E\u9806 = [
2143
+ { axis: "y", sign: -1, \u540D\u524D: "\u4E0A" },
2144
+ { axis: "y", sign: 1, \u540D\u524D: "\u4E0B" },
2145
+ { axis: "x", sign: -1, \u540D\u524D: "\u5DE6" },
2146
+ { axis: "x", sign: 1, \u540D\u524D: "\u53F3" }
2147
+ ];
2148
+ function \u672D\u304C\u52D5\u3051\u306A\u3044\u7406\u7531(labelId, \u76F8\u624B, edges, obstacles) {
2149
+ const edgeById = new Map(edges.map((e) => [e.id, e]));
2150
+ const \u81EA\u5206 = edgeById.get(labelId);
2151
+ if (!\u81EA\u5206) return null;
2152
+ const labels = edges.filter((e) => e.label?.trim() || e.sub?.trim()).map((e) => ({ kind: "edge-label", id: e.id, ...computeLabelBBoxWorld(e) }));
2153
+ const label = labels.find((l) => l.id === labelId);
2154
+ if (!label) return null;
2155
+ const \u6E2C\u308A\u65B9 = \u7DDA\u306E\u6E2C\u308A\u65B9\u3092\u4F5C\u308B();
2156
+ const \u5468\u308A = {
2157
+ \u7BB1\u305F\u3061: obstacles.filter((o) => o.kind === "node" || o.kind === "lane-label"),
2158
+ labels,
2159
+ edges,
2160
+ edgeById,
2161
+ \u6E2C\u308A\u65B9
2162
+ };
2163
+ const \u5019\u88DC = [];
2164
+ if (\u76F8\u624B.kind === "edge-path") {
2165
+ const \u7DDA = edgeById.get(\u76F8\u624B.id);
2166
+ if (!\u7DDA) return null;
2167
+ const segs = segmentsExcludingOwnPath(\u6E2C\u308A\u65B9.\u533A\u9593(\u7DDA.id, \u7DDA.d), \u6E2C\u308A\u65B9.\u533A\u9593(\u81EA\u5206.id, \u81EA\u5206.d));
2168
+ if (segs.length === 0) return null;
2169
+ const gap = measurePathLabelGapSegs(segs, label);
2170
+ for (const \u5411\u304D of \u5411\u304D\u306E\u9806) {
2171
+ \u5019\u88DC.push({ axis: \u5411\u304D.axis, sign: \u5411\u304D.sign, amount: \u7DDA\u304B\u3089\u96E2\u308C\u308B\u91CF(segs, label, gap, \u5411\u304D.axis, \u5411\u304D.sign) });
2172
+ }
2173
+ } else {
2174
+ const required = requiredNearClearance("edge-label", \u76F8\u624B.kind);
2175
+ for (const c of \u77E9\u5F62\u306E\u5019\u88DC(label, \u76F8\u624B, required)) {
2176
+ if (c.amount > 0) \u5019\u88DC.push(c);
2177
+ }
2178
+ }
2179
+ if (\u5019\u88DC.length === 0) return null;
2180
+ const \u7406\u7531 = [];
2181
+ for (const c of \u5019\u88DC) {
2182
+ const \u9806 = \u5411\u304D\u306E\u9806.findIndex((v) => v.axis === c.axis && v.sign === c.sign);
2183
+ const \u540D\u524D = \u5411\u304D\u306E\u9806[\u9806].\u540D\u524D;
2184
+ if (c.amount === null || c.amount > \u672D\u306E\u6700\u5927\u79FB\u52D5) {
2185
+ \u7406\u7531.push({ \u9806, \u6587: `${\u540D\u524D}=\u4E0A\u9650 ${\u672D\u306E\u6700\u5927\u79FB\u52D5} \u3092\u8D8A\u3048\u308B` });
2186
+ continue;
2187
+ }
2188
+ const \u585E\u3050 = \u672D\u306E\u79FB\u52D5\u3092\u585E\u3050\u76F8\u624B\u3092\u63A2\u3059(\u5468\u308A, label, \u52D5\u304B\u3057\u305F\u7BB1(label, c.axis, c.sign, c.amount));
2189
+ if (!\u585E\u3050) return null;
2190
+ \u7406\u7531.push({ \u9806, \u6587: `${\u540D\u524D}=${\u585E\u3050.\u76F8\u624B} (${\u585E\u3050.\u524D.toFixed(0)}\u2192${\u585E\u3050.\u5F8C.toFixed(0)})` });
2191
+ }
2192
+ return `\u9003\u3052\u5834\u306A\u3057: ${\u7406\u7531.sort((a, b) => a.\u9806 - b.\u9806).map((r) => r.\u6587).join(" / ")}`;
2193
+ }
2194
+ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
2195
+ if (edges.length === 0) return edges;
2196
+ const labeledIds = new Set(
2197
+ edges.filter((e) => e.label?.trim() || e.sub?.trim()).map((e) => e.id)
2198
+ );
2199
+ if (labeledIds.size === 0) return edges;
2200
+ const \u7BB1\u305F\u3061 = obstacles.filter((o) => o.kind === "node" || o.kind === "lane-label");
2201
+ const edgeById = /* @__PURE__ */ new Map();
2202
+ for (const e of edges) edgeById.set(e.id, e);
2203
+ const \u6E2C\u308A\u65B9 = \u7DDA\u306E\u6E2C\u308A\u65B9\u3092\u4F5C\u308B();
2204
+ const { \u533A\u9593, \u9060\u3044 } = \u6E2C\u308A\u65B9;
2205
+ const \u6700\u5927\u79FB\u52D5 = \u672D\u306E\u6700\u5927\u79FB\u52D5;
2078
2206
  const shiftMap = /* @__PURE__ */ new Map();
2079
2207
  const getShift = (id) => shiftMap.get(id) ?? { dx: 0, dy: 0 };
2080
2208
  const labelBBoxes = () => {
@@ -2087,50 +2215,12 @@ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
2087
2215
  }
2088
2216
  return out;
2089
2217
  };
2090
- const \u96E2\u308C\u91CF = (a, b) => ({
2091
- x: Math.max(a.x - (b.x + b.w), b.x - (a.x + a.w)),
2092
- y: Math.max(a.y - (b.y + b.h), b.y - (a.y + a.h))
2093
- });
2094
- const \u52D5\u304B\u3057\u305F\u7BB1 = (box, axis, sign, amount) => ({
2095
- ...box,
2096
- x: box.x + (axis === "x" ? sign * amount : 0),
2097
- y: box.y + (axis === "y" ? sign * amount : 0)
2098
- });
2099
2218
  for (let iter = 0; iter < maxIter; iter += 1) {
2100
2219
  const labels = labelBBoxes();
2101
2220
  const \u672D\u306E\u8981\u6C42 = requiredNearClearance("edge-label", "edge-label");
2102
2221
  let \u52D5\u3044\u305F = false;
2103
2222
  const \u4ECA\u56DE\u52D5\u304B\u3057\u305F = /* @__PURE__ */ new Set();
2104
- const \u5B89\u5168\u304B = (label, \u884C\u304D\u5148) => {
2105
- for (const obs of \u7BB1\u305F\u3061) {
2106
- const \u524D = computeGap(label, obs);
2107
- const \u5F8C = computeGap(\u884C\u304D\u5148, obs);
2108
- if (\u5F8C < Math.min(\u524D, requiredNearClearance("edge-label", obs.kind))) return false;
2109
- }
2110
- for (const \u4ED6 of labels) {
2111
- if (\u4ED6.id === label.id) continue;
2112
- const \u524D = computeGap(label, \u4ED6);
2113
- const \u5F8C = computeGap(\u884C\u304D\u5148, \u4ED6);
2114
- if (\u5F8C < Math.min(\u524D, \u672D\u306E\u8981\u6C42)) return false;
2115
- }
2116
- const \u81EA\u5206 = edgeById.get(label.id);
2117
- const \u81EA\u5206\u306E\u533A\u9593 = \u81EA\u5206 ? \u533A\u9593(\u81EA\u5206.id, \u81EA\u5206.d) : [];
2118
- if (\u81EA\u5206\u306E\u533A\u9593.length > 0) {
2119
- const \u524D = measurePathLabelGapSegs(\u81EA\u5206\u306E\u533A\u9593, label);
2120
- const \u5F8C = measurePathLabelGapSegs(\u81EA\u5206\u306E\u533A\u9593, \u884C\u304D\u5148);
2121
- if (\u5F8C > Math.max(\u524D, DIST_LABEL_PATH_MAX)) return false;
2122
- }
2123
- for (const \u76F8\u624B of edges) {
2124
- if (\u76F8\u624B.id === label.id) continue;
2125
- if (\u9060\u3044(label, \u76F8\u624B.id, \u76F8\u624B.d, LABEL_TO_PATH_CLEARANCE) && \u9060\u3044(\u884C\u304D\u5148, \u76F8\u624B.id, \u76F8\u624B.d, LABEL_TO_PATH_CLEARANCE)) continue;
2126
- const segs = segmentsExcludingOwnPath(\u533A\u9593(\u76F8\u624B.id, \u76F8\u624B.d), \u81EA\u5206\u306E\u533A\u9593);
2127
- if (segs.length === 0) continue;
2128
- const \u524D = measurePathLabelGapSegs(segs, label);
2129
- const \u5F8C = measurePathLabelGapSegs(segs, \u884C\u304D\u5148);
2130
- if (\u5F8C < Math.min(\u524D, LABEL_TO_PATH_CLEARANCE)) return false;
2131
- }
2132
- return true;
2133
- };
2223
+ const \u5B89\u5168\u304B = (label, \u884C\u304D\u5148) => \u672D\u306E\u79FB\u52D5\u3092\u585E\u3050\u76F8\u624B\u3092\u63A2\u3059({ \u7BB1\u305F\u3061, labels, edges, edgeById, \u6E2C\u308A\u65B9 }, label, \u884C\u304D\u5148) === null;
2134
2224
  const \u9003\u304C\u3059 = (label, \u5019\u88DC) => {
2135
2225
  for (const c of \u5019\u88DC.slice().sort((a, b) => a.amount - b.amount)) {
2136
2226
  if (c.amount <= 0) continue;
@@ -2146,18 +2236,6 @@ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
2146
2236
  }
2147
2237
  return false;
2148
2238
  };
2149
- const \u77E9\u5F62\u306E\u5019\u88DC = (label, static\u7BB1, required) => {
2150
- const sep = \u96E2\u308C\u91CF(label, static\u7BB1);
2151
- const \u5411\u304D = (axis) => {
2152
- const a = axis === "x" ? label.x + label.w / 2 : label.y + label.h / 2;
2153
- const b = axis === "x" ? static\u7BB1.x + static\u7BB1.w / 2 : static\u7BB1.y + static\u7BB1.h / 2;
2154
- return a >= b ? 1 : -1;
2155
- };
2156
- return [
2157
- { axis: "x", sign: \u5411\u304D("x"), amount: required - sep.x + NEAR_MISS_MARGIN },
2158
- { axis: "y", sign: \u5411\u304D("y"), amount: required - sep.y + NEAR_MISS_MARGIN }
2159
- ];
2160
- };
2161
2239
  for (const label of labels) {
2162
2240
  if (\u4ECA\u56DE\u52D5\u304B\u3057\u305F.has(label.id)) continue;
2163
2241
  for (const obs of \u7BB1\u305F\u3061) {
@@ -2214,22 +2292,7 @@ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
2214
2292
  }
2215
2293
  }
2216
2294
  if (!\u8FD1\u3044\u70B9) continue;
2217
- const \u5FC5\u8981\u91CF = (axis, sign) => {
2218
- const \u6E80\u305F\u3059 = (\u91CF) => measurePathLabelGapSegs(segs, \u52D5\u304B\u3057\u305F\u7BB1(label, axis, sign, \u91CF)) >= LABEL_TO_PATH_CLEARANCE;
2219
- let lo = 0;
2220
- let hi = Math.max(4, LABEL_TO_PATH_CLEARANCE - gap);
2221
- while (!\u6E80\u305F\u3059(hi)) {
2222
- if (hi >= \u6700\u5927\u79FB\u52D5) return null;
2223
- lo = hi;
2224
- hi = Math.min(hi * 2, \u6700\u5927\u79FB\u52D5);
2225
- }
2226
- for (let k = 0; k < 12; k += 1) {
2227
- const mid = (lo + hi) / 2;
2228
- if (\u6E80\u305F\u3059(mid)) hi = mid;
2229
- else lo = mid;
2230
- }
2231
- return hi + NEAR_MISS_MARGIN;
2232
- };
2295
+ const \u5FC5\u8981\u91CF = (axis, sign) => \u7DDA\u304B\u3089\u96E2\u308C\u308B\u91CF(segs, label, gap, axis, sign);
2233
2296
  const dx = \u82AF.x - \u8FD1\u3044\u70B9.x;
2234
2297
  const dy = \u82AF.y - \u8FD1\u3044\u70B9.y;
2235
2298
  const \u5019\u88DC = [];
@@ -4965,9 +5028,15 @@ function visualValidateLaid(laid, diag, opts) {
4965
5028
  const counts = emptyCounts();
4966
5029
  const profile = "production";
4967
5030
  const skipped = SKIPPED_AXES[profile];
4968
- const push = (axis, detail, severity = "error") => {
5031
+ const push = (axis, detail, severity = "error", reason) => {
4969
5032
  if (skipped.has(axis)) return;
4970
- violations.push({ axis, diagramId: safeDiagramId(diag), detail, severity });
5033
+ violations.push({
5034
+ axis,
5035
+ diagramId: safeDiagramId(diag),
5036
+ detail,
5037
+ severity,
5038
+ ...reason !== void 0 ? { reason } : {}
5039
+ });
4971
5040
  counts[axis]++;
4972
5041
  };
4973
5042
  return visualValidateInner(
@@ -5279,10 +5348,19 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
5279
5348
  }
5280
5349
  }
5281
5350
  const nears = detectNearCollisions(bboxes, laid.edges);
5351
+ const \u672D\u306E\u969C\u5BB3\u7269 = bboxes.filter((b) => b.kind === "node" || b.kind === "lane-label");
5352
+ const \u8FBA\u306E\u9806 = new Map(laid.edges.map((e, i) => [e.id, i]));
5282
5353
  for (const n of nears) {
5354
+ const a\u306F\u672D = n.a.kind === "edge-label";
5355
+ const b\u306F\u672D = n.b.kind === "edge-label";
5356
+ const \u52D5\u304B\u3059 = a\u306F\u672D && b\u306F\u672D ? (\u8FBA\u306E\u9806.get(n.a.id) ?? 0) > (\u8FBA\u306E\u9806.get(n.b.id) ?? 0) ? n.a : n.b : a\u306F\u672D ? n.a : b\u306F\u672D ? n.b : null;
5357
+ const \u76F8\u624B = \u52D5\u304B\u3059 === n.a ? n.b : n.a;
5358
+ const reason = \u52D5\u304B\u3059 !== null ? \u672D\u304C\u52D5\u3051\u306A\u3044\u7406\u7531(\u52D5\u304B\u3059.id, \u76F8\u624B, laid.edges, \u672D\u306E\u969C\u5BB3\u7269) ?? void 0 : void 0;
5283
5359
  push(
5284
5360
  "clearance",
5285
- `${n.a.kind}:${n.a.id} \u2194 ${n.b.kind}:${n.b.id} gap=${n.gap.toFixed(1)}px (need ${n.required}px)`
5361
+ `${n.a.kind}:${n.a.id} \u2194 ${n.b.kind}:${n.b.id} gap=${n.gap.toFixed(1)}px (need ${n.required}px)`,
5362
+ "error",
5363
+ reason
5286
5364
  );
5287
5365
  }
5288
5366
  const PROXIMITY_WARN_THRESHOLD = DIST_LABEL_PATH_MAX;
@@ -8280,33 +8358,73 @@ function placeAvoidingSiblingPaths(args) {
8280
8358
  }
8281
8359
  };
8282
8360
  consider([...wants]);
8361
+ const \u62BC\u3059\u91CF = (idx, side, pos) => {
8362
+ let \u8981\u308B = 0;
8363
+ for (const i of idx) {
8364
+ const box = boxes[i];
8365
+ const rect = { x: box.x, y: pos[i] - box.h / 2, w: box.w, h: box.h };
8366
+ for (const probe of probeSegs[i]) {
8367
+ if (measurePathLabelGapSegs(probe.segs, rect) >= CLEARANCE_PATH_LABEL) continue;
8368
+ let lo = Infinity;
8369
+ let hi = -Infinity;
8370
+ for (const seg of probe.segs) {
8371
+ const c = clipY(seg, box.x, box.x + box.w);
8372
+ if (!c) continue;
8373
+ lo = Math.min(lo, c.lo);
8374
+ hi = Math.max(hi, c.hi);
8375
+ }
8376
+ if (lo > hi) continue;
8377
+ const \u884C\u304D\u5148 = side === "above" ? lo - box.h / 2 - CLEARANCE_PATH_LABEL : hi + box.h / 2 + CLEARANCE_PATH_LABEL;
8378
+ \u8981\u308B = Math.max(\u8981\u308B, side === "above" ? pos[i] - \u884C\u304D\u5148 : \u884C\u304D\u5148 - pos[i]);
8379
+ }
8380
+ }
8381
+ return Math.max(0, \u8981\u308B);
8382
+ };
8283
8383
  if (bands.some((b) => b !== null)) {
8284
8384
  for (let split = 0; split <= order.length; split++) {
8285
8385
  const above = order.slice(0, split);
8286
8386
  const below = order.slice(split);
8287
- const out = new Array(members.length);
8288
- for (const [idx, side] of [
8289
- [above, "above"],
8290
- [below, "below"]
8291
- ]) {
8292
- if (idx.length === 0) continue;
8293
- const ys = spread(idx);
8294
- let shift = 0;
8295
- for (let k = 0; k < idx.length; k++) {
8296
- const band = bands[idx[k]];
8297
- if (!band) continue;
8298
- shift = side === "above" ? Math.min(shift, band.lo - ys[k]) : Math.max(shift, band.hi - ys[k]);
8299
- }
8300
- for (let k = 0; k < idx.length; k++) out[idx[k]] = ys[k] + shift;
8301
- }
8302
- if (above.length > 0 && below.length > 0) {
8387
+ const \u9593\u3092\u7A7A\u3051\u308B = (out) => {
8388
+ if (above.length === 0 || below.length === 0) return;
8303
8389
  const lastIdx = above[above.length - 1];
8304
8390
  const firstIdx = below[0];
8305
8391
  const need = (sizes[lastIdx] + sizes[firstIdx]) / 2 + CLEARANCE_LABEL_LABEL;
8306
8392
  const deficit = need - (out[firstIdx] - out[lastIdx]);
8307
- if (deficit > 0) for (const i of below) out[i] += deficit;
8308
- }
8309
- consider(out);
8393
+ if (deficit > 0) for (const i of below) out[i] = out[i] + deficit;
8394
+ };
8395
+ const \u5E2F\u3092\u8D8A\u3048\u308B = () => {
8396
+ const out = new Array(members.length);
8397
+ for (const [idx, side] of [
8398
+ [above, "above"],
8399
+ [below, "below"]
8400
+ ]) {
8401
+ if (idx.length === 0) continue;
8402
+ const ys = spread(idx);
8403
+ let shift = 0;
8404
+ for (let k = 0; k < idx.length; k++) {
8405
+ const band = bands[idx[k]];
8406
+ if (!band) continue;
8407
+ shift = side === "above" ? Math.min(shift, band.lo - ys[k]) : Math.max(shift, band.hi - ys[k]);
8408
+ }
8409
+ for (let k = 0; k < idx.length; k++) out[idx[k]] = ys[k] + shift;
8410
+ }
8411
+ \u9593\u3092\u7A7A\u3051\u308B(out);
8412
+ return out;
8413
+ };
8414
+ const \u62BC\u3057\u3066\u8D8A\u3048\u308B = () => {
8415
+ const out = \u5E2F\u3092\u8D8A\u3048\u308B();
8416
+ for (let round = 0; round < 4; round += 1) {
8417
+ const a = \u62BC\u3059\u91CF(above, "above", out);
8418
+ const b = \u62BC\u3059\u91CF(below, "below", out);
8419
+ if (a === 0 && b === 0) return out;
8420
+ for (const i of above) out[i] = out[i] - a;
8421
+ for (const i of below) out[i] = out[i] + b;
8422
+ }
8423
+ return \u62BC\u3059\u91CF(above, "above", out) === 0 && \u62BC\u3059\u91CF(below, "below", out) === 0 ? out : null;
8424
+ };
8425
+ consider(\u5E2F\u3092\u8D8A\u3048\u308B());
8426
+ const \u62BC\u3057\u305F = \u62BC\u3057\u3066\u8D8A\u3048\u308B();
8427
+ if (\u62BC\u3057\u305F) consider(\u62BC\u3057\u305F);
8310
8428
  }
8311
8429
  }
8312
8430
  const plain = spread(all);