@cardenelabs/cdl 0.29.0 → 0.30.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 +54 -1
- package/dist/index.cjs +132 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +132 -12
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +132 -12
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +132 -12
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/src/layout/edges.ts +167 -13
- package/src/layout.ts +4 -0
package/dist/react.js
CHANGED
|
@@ -8391,16 +8391,112 @@ function separateSharedStraightRuns(edges, nodes) {
|
|
|
8391
8391
|
e.d = verticesToPath(verts.get(e.id));
|
|
8392
8392
|
}
|
|
8393
8393
|
}
|
|
8394
|
+
function pullOutgoingFirstCorner(edges, nodes) {
|
|
8395
|
+
if (edges.length < 2) return;
|
|
8396
|
+
const \u675F = /* @__PURE__ */ new Map();
|
|
8397
|
+
const \u540C\u3058\u7D44\u306E\u6570 = /* @__PURE__ */ new Map();
|
|
8398
|
+
for (const e of edges) {
|
|
8399
|
+
const key = `${e.from}::${e.fromSide}`;
|
|
8400
|
+
const list = \u675F.get(key) ?? [];
|
|
8401
|
+
list.push(e);
|
|
8402
|
+
\u675F.set(key, list);
|
|
8403
|
+
const pair = `${e.from}->${e.to}`;
|
|
8404
|
+
\u540C\u3058\u7D44\u306E\u6570.set(pair, (\u540C\u3058\u7D44\u306E\u6570.get(pair) ?? 0) + 1);
|
|
8405
|
+
}
|
|
8406
|
+
let \u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F = false;
|
|
8407
|
+
for (const list of \u675F.values()) {
|
|
8408
|
+
if (list.length < 2) continue;
|
|
8409
|
+
const \u4E26\u3073 = list.flatMap((e) => {
|
|
8410
|
+
const pts = pathVertices(e.d);
|
|
8411
|
+
if (!pts || pts.length < 2) return [];
|
|
8412
|
+
return [{ e, pts, \u6700\u521D\u306E\u9577\u3055: Math.hypot(pts[1].x - pts[0].x, pts[1].y - pts[0].y) }];
|
|
8413
|
+
}).sort((a, b) => b.\u6700\u521D\u306E\u9577\u3055 - a.\u6700\u521D\u306E\u9577\u3055);
|
|
8414
|
+
for (const { e, pts, \u6700\u521D\u306E\u9577\u3055 } of \u4E26\u3073.slice(1)) {
|
|
8415
|
+
if ((\u540C\u3058\u7D44\u306E\u6570.get(`${e.from}->${e.to}`) ?? 0) > 1) continue;
|
|
8416
|
+
if (pts.length < 3 || \u6700\u521D\u306E\u9577\u3055 <= EDGE_STUB_OUT + VERTICAL_DETOUR_CORNER) continue;
|
|
8417
|
+
const \u6A2A = e.fromSide === "left" || e.fromSide === "right";
|
|
8418
|
+
if (!runIsAligned(pts, 0, \u6A2A ? 1 : 0)) continue;
|
|
8419
|
+
const \u79FB\u52D5\u91CF = \u6700\u521D\u306E\u9577\u3055 - (EDGE_STUB_OUT + VERTICAL_DETOUR_CORNER);
|
|
8420
|
+
const ux = (pts[1].x - pts[0].x) / \u6700\u521D\u306E\u9577\u3055;
|
|
8421
|
+
const uy = (pts[1].y - pts[0].y) / \u6700\u521D\u306E\u9577\u3055;
|
|
8422
|
+
const \u8A66\u3057 = pts.map(
|
|
8423
|
+
(p, i) => i === 1 || i === 2 ? { x: p.x - ux * \u79FB\u52D5\u91CF, y: p.y - uy * \u79FB\u52D5\u91CF } : p
|
|
8424
|
+
);
|
|
8425
|
+
const \u8A66\u3057D = verticesToPath(\u8A66\u3057);
|
|
8426
|
+
const \u8A66\u3057\u533A\u9593 = flattenPathSegments(extractPathSegments(\u8A66\u3057D));
|
|
8427
|
+
if (nodes.some(
|
|
8428
|
+
(n) => n.id !== e.from && n.id !== e.to && segmentsCrossRect(\u8A66\u3057\u533A\u9593, nodeRect(n))
|
|
8429
|
+
)) {
|
|
8430
|
+
continue;
|
|
8431
|
+
}
|
|
8432
|
+
const \u524D = e.d;
|
|
8433
|
+
const \u524D\u306E\u4EA4\u5DEE = countEdgeCrossings(edges).count;
|
|
8434
|
+
e.d = \u8A66\u3057D;
|
|
8435
|
+
if (countEdgeCrossings(edges).count > \u524D\u306E\u4EA4\u5DEE) {
|
|
8436
|
+
e.d = \u524D;
|
|
8437
|
+
continue;
|
|
8438
|
+
}
|
|
8439
|
+
e.d = \u524D;
|
|
8440
|
+
if (!\u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F) {
|
|
8441
|
+
slideLabelsAlongOwnPath(edges, nodes);
|
|
8442
|
+
\u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F = true;
|
|
8443
|
+
}
|
|
8444
|
+
const labelBox = computeLabelBBoxWorld(e);
|
|
8445
|
+
const label = { x: labelBox.x + labelBox.w / 2, y: labelBox.y + labelBox.h / 2 };
|
|
8446
|
+
const \u7DDA\u5206\u307E\u3067\u306E\u8DDD\u96E22 = (a, b) => {
|
|
8447
|
+
const dx = b.x - a.x;
|
|
8448
|
+
const dy = b.y - a.y;
|
|
8449
|
+
const len2 = dx * dx + dy * dy;
|
|
8450
|
+
const t = len2 === 0 ? 0 : Math.max(0, Math.min(1, ((label.x - a.x) * dx + (label.y - a.y) * dy) / len2));
|
|
8451
|
+
return (label.x - (a.x + dx * t)) ** 2 + (label.y - (a.y + dy * t)) ** 2;
|
|
8452
|
+
};
|
|
8453
|
+
const \u52D5\u304F\u533A\u9593\u3078\u306E\u8DDD\u96E2 = \u7DDA\u5206\u307E\u3067\u306E\u8DDD\u96E22(pts[1], pts[2]);
|
|
8454
|
+
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);
|
|
8455
|
+
e.d = \u8A66\u3057D;
|
|
8456
|
+
if (label\u3082\u52D5\u304B\u3059) {
|
|
8457
|
+
e.labelX -= ux * \u79FB\u52D5\u91CF;
|
|
8458
|
+
e.labelY -= uy * \u79FB\u52D5\u91CF;
|
|
8459
|
+
}
|
|
8460
|
+
}
|
|
8461
|
+
}
|
|
8462
|
+
}
|
|
8394
8463
|
var ENDPOINT_FAN_STEP = 56;
|
|
8395
8464
|
var ENDPOINT_FAN_MIN = 20;
|
|
8396
8465
|
var ENDPOINT_FAN_RUNUP = 40;
|
|
8466
|
+
var MIXED_ROOT_OVERLAP_MIN = 24;
|
|
8397
8467
|
function fanIncomingEndpoints(edges, nodes) {
|
|
8398
8468
|
if (edges.length < 2) return;
|
|
8399
8469
|
const nmap = new Map(nodes.map((n) => [n.id, n]));
|
|
8470
|
+
const \u5E73\u5766\u306A\u533A\u9593 = new Map(edges.map((e) => [e.id, flattenPathSegments(extractPathSegments(e.d))]));
|
|
8471
|
+
const \u8EF8\u306B\u5E73\u884C\u306A\u91CD\u306A\u308A\u9577\u3055 = (\u4E00\u65B9, \u4ED6\u65B9) => {
|
|
8472
|
+
let \u5408\u8A08 = 0;
|
|
8473
|
+
for (const a of \u5E73\u5766\u306A\u533A\u9593.get(\u4E00\u65B9.id) ?? []) {
|
|
8474
|
+
const a\u306F\u6C34\u5E73 = Math.abs(a.y2 - a.y1) <= 1;
|
|
8475
|
+
const a\u306F\u5782\u76F4 = Math.abs(a.x2 - a.x1) <= 1;
|
|
8476
|
+
for (const b of \u5E73\u5766\u306A\u533A\u9593.get(\u4ED6\u65B9.id) ?? []) {
|
|
8477
|
+
const b\u306F\u6C34\u5E73 = Math.abs(b.y2 - b.y1) <= 1;
|
|
8478
|
+
const b\u306F\u5782\u76F4 = Math.abs(b.x2 - b.x1) <= 1;
|
|
8479
|
+
if (a\u306F\u6C34\u5E73 && b\u306F\u6C34\u5E73 && Math.abs(a.y1 - b.y1) <= 1) {
|
|
8480
|
+
\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)));
|
|
8481
|
+
}
|
|
8482
|
+
if (a\u306F\u5782\u76F4 && b\u306F\u5782\u76F4 && Math.abs(a.x1 - b.x1) <= 1) {
|
|
8483
|
+
\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)));
|
|
8484
|
+
}
|
|
8485
|
+
}
|
|
8486
|
+
}
|
|
8487
|
+
return \u5408\u8A08;
|
|
8488
|
+
};
|
|
8400
8489
|
const \u540C\u3058\u7D44\u306E\u6570 = /* @__PURE__ */ new Map();
|
|
8401
8490
|
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);
|
|
8402
8491
|
const \u675F = /* @__PURE__ */ new Map();
|
|
8492
|
+
const \u51FA\u308B\u7DDA = /* @__PURE__ */ new Map();
|
|
8403
8493
|
for (const e of edges) {
|
|
8494
|
+
if (nmap.has(e.from)) {
|
|
8495
|
+
const key2 = `${e.from}::${e.fromSide}`;
|
|
8496
|
+
const list2 = \u51FA\u308B\u7DDA.get(key2) ?? [];
|
|
8497
|
+
list2.push(e);
|
|
8498
|
+
\u51FA\u308B\u7DDA.set(key2, list2);
|
|
8499
|
+
}
|
|
8404
8500
|
if (!nmap.has(e.to)) continue;
|
|
8405
8501
|
if ((\u540C\u3058\u7D44\u306E\u6570.get(`${e.from}->${e.to}`) ?? 0) > 1) continue;
|
|
8406
8502
|
const key = `${e.to}::${e.toSide}`;
|
|
@@ -8408,27 +8504,48 @@ function fanIncomingEndpoints(edges, nodes) {
|
|
|
8408
8504
|
list.push(e);
|
|
8409
8505
|
\u675F.set(key, list);
|
|
8410
8506
|
}
|
|
8411
|
-
for (const [, list] of \u675F) {
|
|
8412
|
-
|
|
8507
|
+
for (const [key, list] of \u675F) {
|
|
8508
|
+
const \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B = (\u51FA\u308B\u7DDA.get(key) ?? []).some(
|
|
8509
|
+
(\u51FA\u7DDA) => list.some(
|
|
8510
|
+
(\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
|
|
8511
|
+
)
|
|
8512
|
+
);
|
|
8513
|
+
if (list.length < 2 && !\u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B) continue;
|
|
8413
8514
|
const n = nmap.get(list[0].to);
|
|
8414
8515
|
const \u6A2A = list[0].toSide === "left" || list[0].toSide === "right";
|
|
8415
8516
|
const \u8FBA\u306E\u9577\u3055 = \u6A2A ? n.h : n.w;
|
|
8416
8517
|
const \u4F7F\u3048\u308B\u5E452 = \u8FBA\u306E\u9577\u3055 - 2 * ARROW_ENDPOINT_CENTER_TOL;
|
|
8417
8518
|
if (\u4F7F\u3048\u308B\u5E452 <= 0) continue;
|
|
8418
|
-
const \u9593
|
|
8519
|
+
const \u5E2D\u306E\u9593 = \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B ? list.length : list.length - 1;
|
|
8520
|
+
const \u9593\u9694 = Math.min(ENDPOINT_FAN_STEP, \u4F7F\u3048\u308B\u5E452 / \u5E2D\u306E\u9593);
|
|
8419
8521
|
if (\u9593\u9694 < ENDPOINT_FAN_MIN) continue;
|
|
8420
|
-
const \
|
|
8522
|
+
const \u8FBA\u306E\u4E2D\u5FC3 = \u6A2A ? n.cy : n.cx;
|
|
8523
|
+
const \u4E26\u3073 = list.map((e) => {
|
|
8524
|
+
const \u533A\u9593 = extractPathSegments(e.d);
|
|
8525
|
+
const last = \u533A\u9593[\u533A\u9593.length - 1];
|
|
8526
|
+
const \u9577\u3044\u52A9\u8D70 = last === void 0 ? 0 : Math.hypot(last.x2 - last.x1, last.y2 - last.y1);
|
|
8527
|
+
const \u4E2D\u5FC3\u3092\u88DC\u3046 = \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B || list.length === 2;
|
|
8528
|
+
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);
|
|
8529
|
+
return { e, \u9577\u3044\u52A9\u8D70, \u6DF1\u3055 };
|
|
8530
|
+
}).sort((a, b) => a.\u6DF1\u3055 - b.\u6DF1\u3055 || (a.e.id < b.e.id ? -1 : 1));
|
|
8421
8531
|
const \u4E2D\u5FC3 = (\u4E26\u3073.length - 1) * \u9593\u9694 / 2;
|
|
8532
|
+
let \u8CA0\u5074\u306E\u5E2D = 0;
|
|
8533
|
+
let \u6B63\u5074\u306E\u5E2D = 0;
|
|
8422
8534
|
for (let k = 0; k < \u4E26\u3073.length; k++) {
|
|
8423
|
-
const d = k * \u9593\u9694 - \u4E2D\u5FC3;
|
|
8535
|
+
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;
|
|
8424
8536
|
if (Math.abs(d) < 1e-3) continue;
|
|
8425
8537
|
const e = \u4E26\u3073[k].e;
|
|
8426
|
-
const \u5DEE\u66FF = \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, nodes);
|
|
8427
|
-
if (\u5DEE\u66FF === null) continue;
|
|
8428
8538
|
const \u524D = e.d;
|
|
8429
8539
|
const \u524D\u306E\u4EA4\u5DEE = countEdgeCrossings(edges).count;
|
|
8430
|
-
|
|
8431
|
-
|
|
8540
|
+
const \u9577\u3044\u52A9\u8D70 = \u4E26\u3073[k].\u9577\u3044\u52A9\u8D70;
|
|
8541
|
+
for (const \u52A9\u8D70 of [\u9577\u3044\u52A9\u8D70, ENDPOINT_FAN_RUNUP]) {
|
|
8542
|
+
e.d = \u524D;
|
|
8543
|
+
const \u5DEE\u66FF = \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, \u52A9\u8D70, nodes);
|
|
8544
|
+
if (\u5DEE\u66FF === null) continue;
|
|
8545
|
+
e.d = \u5DEE\u66FF;
|
|
8546
|
+
if (countEdgeCrossings(edges).count <= \u524D\u306E\u4EA4\u5DEE) break;
|
|
8547
|
+
e.d = \u524D;
|
|
8548
|
+
}
|
|
8432
8549
|
}
|
|
8433
8550
|
}
|
|
8434
8551
|
}
|
|
@@ -8441,7 +8558,7 @@ function \u8FBA\u304B\u3089\u96E2\u308C\u305F\u5074\u306E\u4F4D\u7F6E(e, \u6A2A)
|
|
|
8441
8558
|
}
|
|
8442
8559
|
return null;
|
|
8443
8560
|
}
|
|
8444
|
-
function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, nodes) {
|
|
8561
|
+
function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, \u52A9\u8D70, nodes) {
|
|
8445
8562
|
if ((e.d.match(/M/g) ?? []).length !== 1) return null;
|
|
8446
8563
|
const segs = extractPathSegments(e.d);
|
|
8447
8564
|
if (segs.length === 0) return null;
|
|
@@ -8454,7 +8571,8 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
|
|
|
8454
8571
|
if (\u9577\u3055 < ENDPOINT_FAN_RUNUP + 1) return null;
|
|
8455
8572
|
const ux = (last.x1 - last.x2) / \u9577\u3055;
|
|
8456
8573
|
const uy = (last.y1 - last.y2) / \u9577\u3055;
|
|
8457
|
-
const \
|
|
8574
|
+
const \u4E38\u3081\u305F\u52A9\u8D70 = Math.min(\u52A9\u8D70, \u9577\u3055);
|
|
8575
|
+
const \u6298\u308C1 = { x: last.x2 + ux * \u4E38\u3081\u305F\u52A9\u8D70, y: last.y2 + uy * \u4E38\u3081\u305F\u52A9\u8D70 };
|
|
8458
8576
|
const \u6298\u308C2 = \u6A2A ? { x: \u6298\u308C1.x, y: \u6298\u308C1.y + d } : { x: \u6298\u308C1.x + d, y: \u6298\u308C1.y };
|
|
8459
8577
|
const \u7D42\u70B9 = \u6A2A ? { x: last.x2, y: last.y2 + d } : { x: last.x2 + d, y: last.y2 };
|
|
8460
8578
|
const \u65B0\u533A\u9593 = [
|
|
@@ -8476,7 +8594,8 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
|
|
|
8476
8594
|
}
|
|
8477
8595
|
parts.push(`L ${s.x2} ${s.y2}`);
|
|
8478
8596
|
}
|
|
8479
|
-
|
|
8597
|
+
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;
|
|
8598
|
+
if (!\u6298\u308C1\u306F\u76F4\u524D\u306E\u6298\u308C) parts.push(`L ${round1(\u6298\u308C1.x)} ${round1(\u6298\u308C1.y)}`);
|
|
8480
8599
|
parts.push(`L ${round1(\u6298\u308C2.x)} ${round1(\u6298\u308C2.y)}`);
|
|
8481
8600
|
parts.push(`L ${round1(\u7D42\u70B9.x)} ${round1(\u7D42\u70B9.y)}`);
|
|
8482
8601
|
return parts.join(" ");
|
|
@@ -8959,6 +9078,7 @@ function layout(diag) {
|
|
|
8959
9078
|
diag.edges.filter((e) => e.posX1 !== void 0 && e.posY1 !== void 0 && e.posX2 !== void 0 && e.posY2 !== void 0).map((e) => e.id)
|
|
8960
9079
|
);
|
|
8961
9080
|
bowSharedStraightPaths(edges, nodesFinal, positionedEdgeIds);
|
|
9081
|
+
pullOutgoingFirstCorner(edges, nodesFinal);
|
|
8962
9082
|
fanIncomingEndpoints(edges, nodesFinal);
|
|
8963
9083
|
separateSharedStraightRuns(edges, nodesFinal);
|
|
8964
9084
|
hopEdgeCrossings(edges);
|