@crazyhappyone/auto-graph 0.1.1 → 0.1.3
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/README.md +6 -1
- package/README.zh-CN.md +6 -1
- package/dist/cli/index.cjs +293 -21
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +293 -21
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +293 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +293 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -3256,6 +3256,7 @@ function routeEdge(input) {
|
|
|
3256
3256
|
const diagnostics = [];
|
|
3257
3257
|
const softObstacles = input.obstacles ?? [];
|
|
3258
3258
|
const hardObstacles = input.hardObstacles ?? [];
|
|
3259
|
+
const maxAttempts = input.maxRoutingAttempts ?? 5;
|
|
3259
3260
|
const defaultAnchors = defaultAnchorsForGeometry(
|
|
3260
3261
|
input.source.box,
|
|
3261
3262
|
input.target.box,
|
|
@@ -3351,6 +3352,51 @@ function routeEdge(input) {
|
|
|
3351
3352
|
)
|
|
3352
3353
|
);
|
|
3353
3354
|
if (hardClearCandidate !== void 0) {
|
|
3355
|
+
let bestPoints2 = hardClearCandidate.points;
|
|
3356
|
+
if (input.kind === "obstacle-avoiding") {
|
|
3357
|
+
const allObstacles = [...softObstacles, ...hardObstacles];
|
|
3358
|
+
for (const candidate of candidateRoutes) {
|
|
3359
|
+
if (routeCrossesBoxes(candidate.points, hardObstacles) || routeIntersectsEndpointInteriors(
|
|
3360
|
+
candidate.points,
|
|
3361
|
+
candidate.endpointObstacles
|
|
3362
|
+
)) {
|
|
3363
|
+
continue;
|
|
3364
|
+
}
|
|
3365
|
+
const rerouted2 = greedyRerouteAroundObstacles(
|
|
3366
|
+
candidate.points,
|
|
3367
|
+
allObstacles,
|
|
3368
|
+
maxAttempts
|
|
3369
|
+
);
|
|
3370
|
+
if (!routeCrossesBoxes(rerouted2, allObstacles) && !routeIntersectsEndpointInteriors(
|
|
3371
|
+
rerouted2,
|
|
3372
|
+
candidate.endpointObstacles
|
|
3373
|
+
)) {
|
|
3374
|
+
return {
|
|
3375
|
+
points: finalizeRoute(
|
|
3376
|
+
rerouted2,
|
|
3377
|
+
softObstacles,
|
|
3378
|
+
hardObstacles,
|
|
3379
|
+
diagnostics
|
|
3380
|
+
),
|
|
3381
|
+
diagnostics
|
|
3382
|
+
};
|
|
3383
|
+
}
|
|
3384
|
+
}
|
|
3385
|
+
const rerouted = greedyRerouteAroundObstacles(
|
|
3386
|
+
bestPoints2,
|
|
3387
|
+
allObstacles,
|
|
3388
|
+
Math.min(maxAttempts, 3)
|
|
3389
|
+
);
|
|
3390
|
+
const reroutedAvoidsEndpointInteriors = !routeIntersectsEndpointInteriors(
|
|
3391
|
+
rerouted,
|
|
3392
|
+
hardClearCandidate.endpointObstacles
|
|
3393
|
+
);
|
|
3394
|
+
if (reroutedAvoidsEndpointInteriors) {
|
|
3395
|
+
if (routeCrossesBoxes(rerouted, hardObstacles) && !routeCrossesBoxes(bestPoints2, hardObstacles)) ; else {
|
|
3396
|
+
bestPoints2 = rerouted;
|
|
3397
|
+
}
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3354
3400
|
diagnostics.push({
|
|
3355
3401
|
severity: "warning",
|
|
3356
3402
|
code: "routing.obstacle.unavoidable",
|
|
@@ -3358,7 +3404,7 @@ function routeEdge(input) {
|
|
|
3358
3404
|
});
|
|
3359
3405
|
return {
|
|
3360
3406
|
points: finalizeRoute(
|
|
3361
|
-
|
|
3407
|
+
bestPoints2,
|
|
3362
3408
|
softObstacles,
|
|
3363
3409
|
hardObstacles,
|
|
3364
3410
|
diagnostics
|
|
@@ -3367,6 +3413,33 @@ function routeEdge(input) {
|
|
|
3367
3413
|
};
|
|
3368
3414
|
}
|
|
3369
3415
|
if (hardObstacles.length > 0) {
|
|
3416
|
+
let bestPoints2 = candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors);
|
|
3417
|
+
if (input.kind === "obstacle-avoiding") {
|
|
3418
|
+
const allObstacles = [...softObstacles, ...hardObstacles];
|
|
3419
|
+
for (const candidate of candidateRoutes) {
|
|
3420
|
+
const rerouted = greedyRerouteAroundObstacles(
|
|
3421
|
+
candidate.points,
|
|
3422
|
+
allObstacles,
|
|
3423
|
+
maxAttempts
|
|
3424
|
+
);
|
|
3425
|
+
if (!routeCrossesBoxes(rerouted, allObstacles)) {
|
|
3426
|
+
return {
|
|
3427
|
+
points: finalizeRoute(
|
|
3428
|
+
rerouted,
|
|
3429
|
+
softObstacles,
|
|
3430
|
+
hardObstacles,
|
|
3431
|
+
diagnostics
|
|
3432
|
+
),
|
|
3433
|
+
diagnostics
|
|
3434
|
+
};
|
|
3435
|
+
}
|
|
3436
|
+
}
|
|
3437
|
+
bestPoints2 = greedyRerouteAroundObstacles(
|
|
3438
|
+
candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors),
|
|
3439
|
+
allObstacles,
|
|
3440
|
+
maxAttempts
|
|
3441
|
+
);
|
|
3442
|
+
}
|
|
3370
3443
|
diagnostics.push({
|
|
3371
3444
|
severity: "error",
|
|
3372
3445
|
code: "routing.evidence.crossing_forbidden",
|
|
@@ -3374,7 +3447,7 @@ function routeEdge(input) {
|
|
|
3374
3447
|
});
|
|
3375
3448
|
return {
|
|
3376
3449
|
points: finalizeRoute(
|
|
3377
|
-
|
|
3450
|
+
bestPoints2,
|
|
3378
3451
|
softObstacles,
|
|
3379
3452
|
hardObstacles,
|
|
3380
3453
|
diagnostics
|
|
@@ -3382,6 +3455,33 @@ function routeEdge(input) {
|
|
|
3382
3455
|
diagnostics
|
|
3383
3456
|
};
|
|
3384
3457
|
}
|
|
3458
|
+
let bestPoints = candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors);
|
|
3459
|
+
if (input.kind === "obstacle-avoiding") {
|
|
3460
|
+
const allObstacles = [...softObstacles, ...hardObstacles];
|
|
3461
|
+
for (const candidate of candidateRoutes) {
|
|
3462
|
+
const rerouted = greedyRerouteAroundObstacles(
|
|
3463
|
+
candidate.points,
|
|
3464
|
+
allObstacles,
|
|
3465
|
+
maxAttempts
|
|
3466
|
+
);
|
|
3467
|
+
if (!routeCrossesBoxes(rerouted, allObstacles)) {
|
|
3468
|
+
return {
|
|
3469
|
+
points: finalizeRoute(
|
|
3470
|
+
rerouted,
|
|
3471
|
+
softObstacles,
|
|
3472
|
+
hardObstacles,
|
|
3473
|
+
diagnostics
|
|
3474
|
+
),
|
|
3475
|
+
diagnostics
|
|
3476
|
+
};
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
bestPoints = greedyRerouteAroundObstacles(
|
|
3480
|
+
candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors),
|
|
3481
|
+
allObstacles,
|
|
3482
|
+
maxAttempts
|
|
3483
|
+
);
|
|
3484
|
+
}
|
|
3385
3485
|
diagnostics.push({
|
|
3386
3486
|
severity: "warning",
|
|
3387
3487
|
code: "routing.obstacle.unavoidable",
|
|
@@ -3389,7 +3489,7 @@ function routeEdge(input) {
|
|
|
3389
3489
|
});
|
|
3390
3490
|
return {
|
|
3391
3491
|
points: finalizeRoute(
|
|
3392
|
-
|
|
3492
|
+
bestPoints,
|
|
3393
3493
|
softObstacles,
|
|
3394
3494
|
hardObstacles,
|
|
3395
3495
|
diagnostics
|
|
@@ -3547,6 +3647,70 @@ function insetBox(box, margin) {
|
|
|
3547
3647
|
height: box.height - margin * 2
|
|
3548
3648
|
};
|
|
3549
3649
|
}
|
|
3650
|
+
function greedyRerouteAroundObstacles(points, obstacles, maxIterations) {
|
|
3651
|
+
let current = [...points];
|
|
3652
|
+
for (let iter = 0; iter < maxIterations; iter++) {
|
|
3653
|
+
const improved = pushRouteAwayFromObstacles(current, obstacles);
|
|
3654
|
+
if (improved === null) {
|
|
3655
|
+
break;
|
|
3656
|
+
}
|
|
3657
|
+
current = improved;
|
|
3658
|
+
if (!routeCrossesBoxes(current, obstacles)) {
|
|
3659
|
+
break;
|
|
3660
|
+
}
|
|
3661
|
+
}
|
|
3662
|
+
return current;
|
|
3663
|
+
}
|
|
3664
|
+
function pushRouteAwayFromObstacles(points, obstacles) {
|
|
3665
|
+
const result = [];
|
|
3666
|
+
let improved = false;
|
|
3667
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
3668
|
+
const a = points[i];
|
|
3669
|
+
const b = points[i + 1];
|
|
3670
|
+
if (a === void 0 || b === void 0) {
|
|
3671
|
+
result.push(a ?? b ?? { x: 0, y: 0 });
|
|
3672
|
+
continue;
|
|
3673
|
+
}
|
|
3674
|
+
result.push(a);
|
|
3675
|
+
const intersectors = obstacles.filter(
|
|
3676
|
+
(obs) => segmentIntersectsBox(a, b, obs)
|
|
3677
|
+
);
|
|
3678
|
+
if (intersectors.length === 0) {
|
|
3679
|
+
continue;
|
|
3680
|
+
}
|
|
3681
|
+
const mx = (a.x + b.x) / 2;
|
|
3682
|
+
const my = (a.y + b.y) / 2;
|
|
3683
|
+
const isHorizontal = a.y === b.y;
|
|
3684
|
+
const margin = 12;
|
|
3685
|
+
let bestWaypoint = null;
|
|
3686
|
+
let bestDist = Infinity;
|
|
3687
|
+
for (const obs of intersectors) {
|
|
3688
|
+
const candidates = isHorizontal ? [
|
|
3689
|
+
{ x: mx, y: obs.y - margin },
|
|
3690
|
+
{ x: mx, y: obs.y + obs.height + margin }
|
|
3691
|
+
] : [
|
|
3692
|
+
{ x: obs.x - margin, y: my },
|
|
3693
|
+
{ x: obs.x + obs.width + margin, y: my }
|
|
3694
|
+
];
|
|
3695
|
+
for (const wp of candidates) {
|
|
3696
|
+
const dist = Math.hypot(wp.x - mx, wp.y - my);
|
|
3697
|
+
if (dist < bestDist) {
|
|
3698
|
+
bestDist = dist;
|
|
3699
|
+
bestWaypoint = wp;
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3702
|
+
}
|
|
3703
|
+
if (bestWaypoint !== null) {
|
|
3704
|
+
result.push(bestWaypoint);
|
|
3705
|
+
improved = true;
|
|
3706
|
+
}
|
|
3707
|
+
}
|
|
3708
|
+
const last = points[points.length - 1];
|
|
3709
|
+
if (last !== void 0) {
|
|
3710
|
+
result.push(last);
|
|
3711
|
+
}
|
|
3712
|
+
return improved ? result : null;
|
|
3713
|
+
}
|
|
3550
3714
|
function fallbackRoute(input, defaultAnchors) {
|
|
3551
3715
|
return [
|
|
3552
3716
|
getEdgePort(
|
|
@@ -4133,7 +4297,9 @@ function solveDiagram(diagram, options = {}) {
|
|
|
4133
4297
|
styledEdges,
|
|
4134
4298
|
nodeGeometryById,
|
|
4135
4299
|
coordinatedNodes,
|
|
4136
|
-
[...nodeGeometryById.values()].map(
|
|
4300
|
+
[...nodeGeometryById.values()].map(
|
|
4301
|
+
(geometry) => options.routingGutter === void 0 ? geometry.obstacleBox : expandBox(geometry.obstacleBox, options.routingGutter)
|
|
4302
|
+
),
|
|
4137
4303
|
[...softObstacles, ...titleBarObstacles],
|
|
4138
4304
|
routingTextObstacles,
|
|
4139
4305
|
hardObstacles,
|
|
@@ -4148,7 +4314,9 @@ function solveDiagram(diagram, options = {}) {
|
|
|
4148
4314
|
...baseTextAnnotations.map((annotation) => annotation.box),
|
|
4149
4315
|
...frameTextAnnotation.map((annotation) => annotation.box)
|
|
4150
4316
|
],
|
|
4151
|
-
options.textMeasurer
|
|
4317
|
+
options.textMeasurer,
|
|
4318
|
+
options.labelPlacement,
|
|
4319
|
+
options.labelOffset
|
|
4152
4320
|
);
|
|
4153
4321
|
const textAnnotations = [
|
|
4154
4322
|
...baseTextAnnotations,
|
|
@@ -6086,7 +6254,8 @@ function coordinateBaseTextAnnotations(input) {
|
|
|
6086
6254
|
}
|
|
6087
6255
|
return annotations;
|
|
6088
6256
|
}
|
|
6089
|
-
function coordinateEdgeTextAnnotations(edges, obstacleBoxes, textMeasurer) {
|
|
6257
|
+
function coordinateEdgeTextAnnotations(edges, obstacleBoxes, textMeasurer, labelPlacement, labelOffset3) {
|
|
6258
|
+
const labelBaseOffset = labelPlacement === "beside" ? labelOffset3 ?? 16 : 10;
|
|
6090
6259
|
const measurer = textMeasurer ?? createDefaultTextMeasurer();
|
|
6091
6260
|
const annotations = [];
|
|
6092
6261
|
const placedLabelBoxes = [];
|
|
@@ -6113,7 +6282,8 @@ function coordinateEdgeTextAnnotations(edges, obstacleBoxes, textMeasurer) {
|
|
|
6113
6282
|
layout2,
|
|
6114
6283
|
edges,
|
|
6115
6284
|
obstacleBoxes,
|
|
6116
|
-
placedLabelBoxes
|
|
6285
|
+
placedLabelBoxes,
|
|
6286
|
+
labelBaseOffset
|
|
6117
6287
|
);
|
|
6118
6288
|
placedLabelBoxes.push({
|
|
6119
6289
|
x: center.x - layout2.box.width / 2,
|
|
@@ -6397,8 +6567,8 @@ function fallbackLabelLayout(text) {
|
|
|
6397
6567
|
diagnostics: []
|
|
6398
6568
|
};
|
|
6399
6569
|
}
|
|
6400
|
-
function edgeLabelAnchor(edge, layout2, edges, obstacleBoxes, placedLabelBoxes) {
|
|
6401
|
-
const placement = labelPlacementOnPolyline2(edge.points);
|
|
6570
|
+
function edgeLabelAnchor(edge, layout2, edges, obstacleBoxes, placedLabelBoxes, baseOffset = 10) {
|
|
6571
|
+
const placement = labelPlacementOnPolyline2(edge.points, baseOffset);
|
|
6402
6572
|
if (placement === void 0) {
|
|
6403
6573
|
return { x: 0, y: 0 };
|
|
6404
6574
|
}
|
|
@@ -6453,9 +6623,7 @@ function edgeLabelAnchorCandidates(points, placement, layout2) {
|
|
|
6453
6623
|
{ x: placement.x, y: placement.y + offset }
|
|
6454
6624
|
);
|
|
6455
6625
|
}
|
|
6456
|
-
|
|
6457
|
-
}
|
|
6458
|
-
if (segment.start.x === segment.end.x) {
|
|
6626
|
+
} else if (segment.start.x === segment.end.x) {
|
|
6459
6627
|
const needed = layout2.box.width / 2 + EDGE_LABEL_CLEARANCE;
|
|
6460
6628
|
const maxSteps = Math.max(12, Math.ceil(needed / EDGE_LABEL_CLEARANCE));
|
|
6461
6629
|
for (let step = 1; step <= maxSteps; step += 1) {
|
|
@@ -6465,14 +6633,90 @@ function edgeLabelAnchorCandidates(points, placement, layout2) {
|
|
|
6465
6633
|
{ x: placement.x - offset, y: placement.y }
|
|
6466
6634
|
);
|
|
6467
6635
|
}
|
|
6468
|
-
|
|
6636
|
+
} else {
|
|
6637
|
+
const dx = segment.end.x - segment.start.x;
|
|
6638
|
+
const dy = segment.end.y - segment.start.y;
|
|
6639
|
+
const segLen = Math.hypot(dx, dy);
|
|
6640
|
+
if (segLen > 0) {
|
|
6641
|
+
const nx = -dy / segLen;
|
|
6642
|
+
const ny = dx / segLen;
|
|
6643
|
+
const needed = (Math.abs(nx) * layout2.box.width + Math.abs(ny) * layout2.box.height) / 2 + EDGE_LABEL_CLEARANCE;
|
|
6644
|
+
const maxSteps = Math.max(12, Math.ceil(needed / EDGE_LABEL_CLEARANCE));
|
|
6645
|
+
for (let step = 1; step <= maxSteps; step += 1) {
|
|
6646
|
+
const offset = EDGE_LABEL_CLEARANCE * step;
|
|
6647
|
+
candidates.push(
|
|
6648
|
+
{ x: placement.x + nx * offset, y: placement.y + ny * offset },
|
|
6649
|
+
{ x: placement.x - nx * offset, y: placement.y - ny * offset }
|
|
6650
|
+
);
|
|
6651
|
+
}
|
|
6652
|
+
}
|
|
6653
|
+
}
|
|
6654
|
+
const totalLen = points.reduce((sum, p, idx) => {
|
|
6655
|
+
if (idx === 0) return 0;
|
|
6656
|
+
const prev = points[idx - 1];
|
|
6657
|
+
return sum + Math.hypot((p?.x ?? 0) - (prev?.x ?? 0), (p?.y ?? 0) - (prev?.y ?? 0));
|
|
6658
|
+
}, 0);
|
|
6659
|
+
if (totalLen > 200) {
|
|
6660
|
+
for (const ratio of [0.25, 0.75]) {
|
|
6661
|
+
const qp = labelPlacementAtRatio(points, ratio, totalLen);
|
|
6662
|
+
if (qp !== void 0) {
|
|
6663
|
+
candidates.push(qp);
|
|
6664
|
+
const qTargetDist = totalLen * ratio;
|
|
6665
|
+
let qTravelled = 0;
|
|
6666
|
+
let seg;
|
|
6667
|
+
for (let si = 1; si < points.length; si++) {
|
|
6668
|
+
const sp = points[si - 1];
|
|
6669
|
+
const sc = points[si];
|
|
6670
|
+
if (sp === void 0 || sc === void 0) continue;
|
|
6671
|
+
const sl = Math.hypot(sc.x - sp.x, sc.y - sp.y);
|
|
6672
|
+
if (sl <= 0) continue;
|
|
6673
|
+
if (qTravelled + sl >= qTargetDist) {
|
|
6674
|
+
seg = { start: sp, end: sc, length: sl };
|
|
6675
|
+
break;
|
|
6676
|
+
}
|
|
6677
|
+
qTravelled += sl;
|
|
6678
|
+
}
|
|
6679
|
+
if (seg !== void 0) {
|
|
6680
|
+
const segLen = Math.hypot(
|
|
6681
|
+
seg.end.x - seg.start.x,
|
|
6682
|
+
seg.end.y - seg.start.y
|
|
6683
|
+
);
|
|
6684
|
+
const qpNeeded = seg.start.y === seg.end.y ? layout2.box.height / 2 + EDGE_LABEL_CLEARANCE : seg.start.x === seg.end.x ? layout2.box.width / 2 + EDGE_LABEL_CLEARANCE : (Math.abs(seg.start.y - seg.end.y) * layout2.box.width + Math.abs(seg.end.x - seg.start.x) * layout2.box.height) / (2 * segLen) + EDGE_LABEL_CLEARANCE;
|
|
6685
|
+
const qpMaxSteps = Math.max(
|
|
6686
|
+
12,
|
|
6687
|
+
Math.ceil(qpNeeded / EDGE_LABEL_CLEARANCE)
|
|
6688
|
+
);
|
|
6689
|
+
for (let step = 1; step <= qpMaxSteps; step += 1) {
|
|
6690
|
+
const offset = EDGE_LABEL_CLEARANCE * step;
|
|
6691
|
+
if (seg.start.y === seg.end.y) {
|
|
6692
|
+
candidates.push(
|
|
6693
|
+
{ x: qp.x, y: qp.y - offset },
|
|
6694
|
+
{ x: qp.x, y: qp.y + offset }
|
|
6695
|
+
);
|
|
6696
|
+
} else if (seg.start.x === seg.end.x) {
|
|
6697
|
+
candidates.push(
|
|
6698
|
+
{ x: qp.x - offset, y: qp.y },
|
|
6699
|
+
{ x: qp.x + offset, y: qp.y }
|
|
6700
|
+
);
|
|
6701
|
+
} else {
|
|
6702
|
+
const nx = -(seg.end.y - seg.start.y) / segLen;
|
|
6703
|
+
const ny = (seg.end.x - seg.start.x) / segLen;
|
|
6704
|
+
candidates.push(
|
|
6705
|
+
{ x: qp.x + nx * offset, y: qp.y + ny * offset },
|
|
6706
|
+
{ x: qp.x - nx * offset, y: qp.y - ny * offset }
|
|
6707
|
+
);
|
|
6708
|
+
}
|
|
6709
|
+
}
|
|
6710
|
+
}
|
|
6711
|
+
}
|
|
6712
|
+
}
|
|
6469
6713
|
}
|
|
6470
6714
|
return candidates;
|
|
6471
6715
|
}
|
|
6472
|
-
function labelPlacementOnPolyline2(points) {
|
|
6473
|
-
return labelSegmentOnPolyline(points)?.placement;
|
|
6716
|
+
function labelPlacementOnPolyline2(points, baseOffset = 10) {
|
|
6717
|
+
return labelSegmentOnPolyline(points, baseOffset)?.placement;
|
|
6474
6718
|
}
|
|
6475
|
-
function labelSegmentOnPolyline(points) {
|
|
6719
|
+
function labelSegmentOnPolyline(points, baseOffset = 10) {
|
|
6476
6720
|
const segments = nonZeroSegments2(points);
|
|
6477
6721
|
const totalLength = segments.reduce(
|
|
6478
6722
|
(sum, segment) => sum + segment.length,
|
|
@@ -6487,7 +6731,7 @@ function labelSegmentOnPolyline(points) {
|
|
|
6487
6731
|
const ratio = remaining / segment.length;
|
|
6488
6732
|
const x = segment.start.x + (segment.end.x - segment.start.x) * ratio;
|
|
6489
6733
|
const y = segment.start.y + (segment.end.y - segment.start.y) * ratio;
|
|
6490
|
-
const offset2 = labelOffset2(segment);
|
|
6734
|
+
const offset2 = labelOffset2(segment, baseOffset);
|
|
6491
6735
|
return {
|
|
6492
6736
|
start: segment.start,
|
|
6493
6737
|
end: segment.end,
|
|
@@ -6522,8 +6766,36 @@ function nonZeroSegments2(points) {
|
|
|
6522
6766
|
}
|
|
6523
6767
|
return segments;
|
|
6524
6768
|
}
|
|
6525
|
-
function
|
|
6526
|
-
|
|
6769
|
+
function labelPlacementAtRatio(points, ratio, totalLength) {
|
|
6770
|
+
if (points.length < 2 || ratio < 0 || ratio > 1) {
|
|
6771
|
+
return void 0;
|
|
6772
|
+
}
|
|
6773
|
+
const targetDist = totalLength * ratio;
|
|
6774
|
+
let travelled = 0;
|
|
6775
|
+
for (let idx = 1; idx < points.length; idx++) {
|
|
6776
|
+
const prev = points[idx - 1];
|
|
6777
|
+
const curr = points[idx];
|
|
6778
|
+
if (prev === void 0 || curr === void 0) {
|
|
6779
|
+
continue;
|
|
6780
|
+
}
|
|
6781
|
+
const segLen = Math.hypot(curr.x - prev.x, curr.y - prev.y);
|
|
6782
|
+
if (segLen <= 0) {
|
|
6783
|
+
continue;
|
|
6784
|
+
}
|
|
6785
|
+
if (travelled + segLen >= targetDist) {
|
|
6786
|
+
const t = (targetDist - travelled) / segLen;
|
|
6787
|
+
const offset = labelOffset2({ start: prev, end: curr, length: segLen });
|
|
6788
|
+
return {
|
|
6789
|
+
x: prev.x + (curr.x - prev.x) * t + offset.x,
|
|
6790
|
+
y: prev.y + (curr.y - prev.y) * t + offset.y
|
|
6791
|
+
};
|
|
6792
|
+
}
|
|
6793
|
+
travelled += segLen;
|
|
6794
|
+
}
|
|
6795
|
+
return void 0;
|
|
6796
|
+
}
|
|
6797
|
+
function labelOffset2(segment, baseOffset = 10) {
|
|
6798
|
+
const offset = baseOffset;
|
|
6527
6799
|
const dx = segment.end.x - segment.start.x;
|
|
6528
6800
|
const dy = segment.end.y - segment.start.y;
|
|
6529
6801
|
return {
|
|
@@ -6635,7 +6907,7 @@ function isValidEdgeId(value) {
|
|
|
6635
6907
|
return value.length > 0 && EDGE_ID_PATTERN.test(value);
|
|
6636
6908
|
}
|
|
6637
6909
|
var directionSchema = z.enum(["TB", "LR", "BT", "RL"]);
|
|
6638
|
-
var routeKindSchema = z.enum(["orthogonal", "straight"]);
|
|
6910
|
+
var routeKindSchema = z.enum(["orthogonal", "straight", "obstacle-avoiding"]);
|
|
6639
6911
|
var outputFormatSchema = z.enum(["svg", "excalidraw"]);
|
|
6640
6912
|
var edgeStrokeStyleSchema = z.enum(["solid", "dashed"]);
|
|
6641
6913
|
var edgeArrowheadSchema = z.enum(["triangle", "hollowTriangle"]);
|
|
@@ -7234,7 +7506,7 @@ function renderDiagramDsl(source, options = {}) {
|
|
|
7234
7506
|
return { diagnostics };
|
|
7235
7507
|
}
|
|
7236
7508
|
const solved = solveDiagram(normalized.diagram, {
|
|
7237
|
-
routeKind: normalized.diagram.metadata?.routeKind === "straight" ? "straight" : "orthogonal",
|
|
7509
|
+
routeKind: normalized.diagram.metadata?.routeKind === "straight" ? "straight" : normalized.diagram.metadata?.routeKind === "obstacle-avoiding" ? "obstacle-avoiding" : "orthogonal",
|
|
7238
7510
|
...solvePortShiftingOption(normalized.diagram.metadata?.portShifting),
|
|
7239
7511
|
...options.textMeasurer === void 0 ? {} : { textMeasurer: options.textMeasurer }
|
|
7240
7512
|
});
|