@crazyhappyone/auto-graph 0.1.2 → 0.1.4
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 +164 -29
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +164 -29
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +164 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +164 -29
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -70,7 +70,12 @@ if (parsed.value === undefined) {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
const normalized = normalizeDiagramDsl(parsed.value);
|
|
73
|
-
const coordinated = solveDiagram(normalized.diagram
|
|
73
|
+
const coordinated = solveDiagram(normalized.diagram, {
|
|
74
|
+
routeKind: "obstacle-avoiding",
|
|
75
|
+
maxRoutingAttempts: 8,
|
|
76
|
+
labelPlacement: "beside",
|
|
77
|
+
labelOffset: 16,
|
|
78
|
+
});
|
|
74
79
|
|
|
75
80
|
const svg = exportSvg(coordinated, { title: "Architecture" });
|
|
76
81
|
const excalidraw = exportExcalidraw(coordinated);
|
package/README.zh-CN.md
CHANGED
|
@@ -70,7 +70,12 @@ if (parsed.value === undefined) {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
const normalized = normalizeDiagramDsl(parsed.value);
|
|
73
|
-
const coordinated = solveDiagram(normalized.diagram
|
|
73
|
+
const coordinated = solveDiagram(normalized.diagram, {
|
|
74
|
+
routeKind: "obstacle-avoiding",
|
|
75
|
+
maxRoutingAttempts: 8,
|
|
76
|
+
labelPlacement: "beside",
|
|
77
|
+
labelOffset: 16,
|
|
78
|
+
});
|
|
74
79
|
|
|
75
80
|
const svg = exportSvg(coordinated, { title: "Architecture" });
|
|
76
81
|
const excalidraw = exportExcalidraw(coordinated);
|
package/dist/cli/index.cjs
CHANGED
|
@@ -1292,6 +1292,9 @@ function applyLayoutConstraints(input) {
|
|
|
1292
1292
|
const nodeById = new Map(input.nodes.map((node) => [node.id, node]));
|
|
1293
1293
|
applyFixedPositionLocks(input.nodes, boxes, locks, diagnostics);
|
|
1294
1294
|
applyExactPositions(input.constraints, boxes, locks, diagnostics, nodeById);
|
|
1295
|
+
if (input.distributeContainedChildren) {
|
|
1296
|
+
yieldFixedPositionLocks(input, boxes, locks);
|
|
1297
|
+
}
|
|
1295
1298
|
applyContainment(input.constraints, boxes, locks, diagnostics, false);
|
|
1296
1299
|
applyRelative(input.constraints, boxes, locks, diagnostics);
|
|
1297
1300
|
applyAlign(input.constraints, boxes, locks, diagnostics);
|
|
@@ -1305,6 +1308,13 @@ function applyLayoutConstraints(input) {
|
|
|
1305
1308
|
);
|
|
1306
1309
|
applyContainment(input.constraints, boxes, locks, diagnostics, true);
|
|
1307
1310
|
applyDistributeContained(input, boxes, locks, diagnostics);
|
|
1311
|
+
if (input.distributeContainedChildren) {
|
|
1312
|
+
const diagBefore = diagnostics.length;
|
|
1313
|
+
applyContainment(input.constraints, boxes, locks, diagnostics, true);
|
|
1314
|
+
applyDistributeContained(input, boxes, locks, diagnostics);
|
|
1315
|
+
dedupReplayDiagnostics(diagnostics, diagBefore);
|
|
1316
|
+
}
|
|
1317
|
+
removeResolvedConstraintDiagnostics(input.constraints, boxes, diagnostics);
|
|
1308
1318
|
reportOverlaps(boxes, diagnostics, containmentOverlapKeys(input.constraints));
|
|
1309
1319
|
reportIntraContainerOverflow(input, boxes, diagnostics);
|
|
1310
1320
|
return { boxes, locks, diagnostics };
|
|
@@ -1350,6 +1360,62 @@ function applyFixedPositionLocks(nodes, boxes, locks, diagnostics) {
|
|
|
1350
1360
|
locks.set(node.id, { nodeId: node.id, source: "fixed-position" });
|
|
1351
1361
|
}
|
|
1352
1362
|
}
|
|
1363
|
+
function dedupReplayDiagnostics(diagnostics, keepUpTo) {
|
|
1364
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1365
|
+
for (let i = 0; i < keepUpTo && i < diagnostics.length; i += 1) {
|
|
1366
|
+
const d = diagnostics[i];
|
|
1367
|
+
if (d === void 0) continue;
|
|
1368
|
+
seen.add(diagnosticFingerprint(d));
|
|
1369
|
+
}
|
|
1370
|
+
for (let i = diagnostics.length - 1; i >= keepUpTo; i -= 1) {
|
|
1371
|
+
const d = diagnostics[i];
|
|
1372
|
+
if (d === void 0) continue;
|
|
1373
|
+
const fp = diagnosticFingerprint(d);
|
|
1374
|
+
if (seen.has(fp)) {
|
|
1375
|
+
diagnostics.splice(i, 1);
|
|
1376
|
+
} else {
|
|
1377
|
+
seen.add(fp);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
function diagnosticFingerprint(d) {
|
|
1382
|
+
const nodeId = typeof d.detail?.nodeId === "string" ? d.detail.nodeId : "";
|
|
1383
|
+
const containerId = typeof d.detail?.containerId === "string" ? d.detail.containerId : "";
|
|
1384
|
+
return `${d.code}|${nodeId}|${containerId}`;
|
|
1385
|
+
}
|
|
1386
|
+
function yieldFixedPositionLocks(input, boxes, locks) {
|
|
1387
|
+
for (const c of input.constraints) {
|
|
1388
|
+
if (c.kind !== "containment") continue;
|
|
1389
|
+
const container = boxes.get(c.containerId);
|
|
1390
|
+
if (container === void 0) continue;
|
|
1391
|
+
const content = contentBox(container, c.padding);
|
|
1392
|
+
const mainAxis = input.direction === "LR" || input.direction === "RL" ? "width" : "height";
|
|
1393
|
+
const crossAxis = mainAxis === "width" ? "height" : "width";
|
|
1394
|
+
let eligible = 0;
|
|
1395
|
+
for (const childId of c.childIds) {
|
|
1396
|
+
const box = boxes.get(childId);
|
|
1397
|
+
if (box === void 0) continue;
|
|
1398
|
+
const lock = locks.get(childId);
|
|
1399
|
+
if (lock?.source === "exact-position") continue;
|
|
1400
|
+
const fits = box[mainAxis] <= content[mainAxis] && box[crossAxis] <= content[crossAxis];
|
|
1401
|
+
if (fits) {
|
|
1402
|
+
eligible += 1;
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
if (eligible < 2) continue;
|
|
1406
|
+
for (const childId of c.childIds) {
|
|
1407
|
+
const lock = locks.get(childId);
|
|
1408
|
+
if (lock?.source === "fixed-position") {
|
|
1409
|
+
const box = boxes.get(childId);
|
|
1410
|
+
if (box === void 0) continue;
|
|
1411
|
+
const fits = box[mainAxis] <= content[mainAxis] && box[crossAxis] <= content[crossAxis];
|
|
1412
|
+
if (fits) {
|
|
1413
|
+
locks.delete(childId);
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1353
1419
|
function applyExactPositions(constraints, boxes, locks, diagnostics, nodeById) {
|
|
1354
1420
|
for (const constraint of constraints) {
|
|
1355
1421
|
if (constraint.kind !== "exact-position") {
|
|
@@ -1422,7 +1488,7 @@ function applyContainment(constraints, boxes, locks, diagnostics, reportOverflow
|
|
|
1422
1488
|
code: "constraints.locked-target-not-moved",
|
|
1423
1489
|
message: `Locked child ${childId} was not moved into containment.`,
|
|
1424
1490
|
path: ["constraints", constraint.id ?? constraint.containerId],
|
|
1425
|
-
detail: { nodeId: childId }
|
|
1491
|
+
detail: { nodeId: childId, containerId: constraint.containerId }
|
|
1426
1492
|
});
|
|
1427
1493
|
if (!isInside(child, content)) {
|
|
1428
1494
|
diagnostics.push({
|
|
@@ -1574,6 +1640,60 @@ function repairOverlaps(input, boxes, locks, diagnostics, siblingPairs) {
|
|
|
1574
1640
|
}
|
|
1575
1641
|
reportOverlaps(boxes, diagnostics, ignoredPairs);
|
|
1576
1642
|
}
|
|
1643
|
+
function removeResolvedConstraintDiagnostics(constraints, boxes, diagnostics) {
|
|
1644
|
+
for (let i = diagnostics.length - 1; i >= 0; i -= 1) {
|
|
1645
|
+
const d = diagnostics[i];
|
|
1646
|
+
if (d === void 0) continue;
|
|
1647
|
+
if (d.code === "constraints.overlap.unresolved") {
|
|
1648
|
+
const aId = d.detail?.firstId;
|
|
1649
|
+
const bId = d.detail?.secondId;
|
|
1650
|
+
if (typeof aId !== "string" || typeof bId !== "string") continue;
|
|
1651
|
+
const a = boxes.get(aId);
|
|
1652
|
+
const b = boxes.get(bId);
|
|
1653
|
+
if (a !== void 0 && b !== void 0 && !intersectsAabb(a, b)) {
|
|
1654
|
+
diagnostics.splice(i, 1);
|
|
1655
|
+
}
|
|
1656
|
+
continue;
|
|
1657
|
+
}
|
|
1658
|
+
if (d.code === "constraints.containment.impossible" || d.code === "constraints.locked-target-not-moved" && typeof d.message === "string" && d.message.includes("not moved into containment")) {
|
|
1659
|
+
const nodeId = d.detail?.nodeId;
|
|
1660
|
+
if (typeof nodeId !== "string") continue;
|
|
1661
|
+
const child = boxes.get(nodeId);
|
|
1662
|
+
if (child === void 0) continue;
|
|
1663
|
+
const diagContainerId = typeof d.detail?.containerId === "string" ? d.detail.containerId : void 0;
|
|
1664
|
+
let resolved = false;
|
|
1665
|
+
for (const c of constraints) {
|
|
1666
|
+
if (c.kind !== "containment") continue;
|
|
1667
|
+
if (!c.childIds.includes(nodeId)) continue;
|
|
1668
|
+
if (diagContainerId !== void 0 && c.containerId !== diagContainerId) {
|
|
1669
|
+
continue;
|
|
1670
|
+
}
|
|
1671
|
+
const container = boxes.get(c.containerId);
|
|
1672
|
+
if (container === void 0) continue;
|
|
1673
|
+
const content = contentBox(container, c.padding);
|
|
1674
|
+
if (isInside(child, content)) {
|
|
1675
|
+
diagnostics.splice(i, 1);
|
|
1676
|
+
resolved = true;
|
|
1677
|
+
}
|
|
1678
|
+
break;
|
|
1679
|
+
}
|
|
1680
|
+
if (!resolved && diagContainerId !== void 0) {
|
|
1681
|
+
for (const c of constraints) {
|
|
1682
|
+
if (c.kind !== "containment") continue;
|
|
1683
|
+
if (c.containerId !== diagContainerId) continue;
|
|
1684
|
+
if (!c.childIds.includes(nodeId)) continue;
|
|
1685
|
+
const container = boxes.get(c.containerId);
|
|
1686
|
+
if (container === void 0) continue;
|
|
1687
|
+
const content = contentBox(container, c.padding);
|
|
1688
|
+
if (isInside(child, content)) {
|
|
1689
|
+
diagnostics.splice(i, 1);
|
|
1690
|
+
}
|
|
1691
|
+
break;
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1577
1697
|
function reportOverlaps(boxes, diagnostics, ignoredPairs = /* @__PURE__ */ new Set()) {
|
|
1578
1698
|
const ids = [...boxes.keys()].sort();
|
|
1579
1699
|
const reported = new Set(
|
|
@@ -1881,6 +2001,12 @@ function applyDistributeContained(input, boxes, locks, diagnostics) {
|
|
|
1881
2001
|
continue;
|
|
1882
2002
|
}
|
|
1883
2003
|
if (locks.has(childId)) {
|
|
2004
|
+
const lock = locks.get(childId);
|
|
2005
|
+
if (lock?.source === "fixed-position") {
|
|
2006
|
+
unlocked.push({ id: childId, box });
|
|
2007
|
+
locks.delete(childId);
|
|
2008
|
+
continue;
|
|
2009
|
+
}
|
|
1884
2010
|
diagnostics.push({
|
|
1885
2011
|
severity: "warning",
|
|
1886
2012
|
code: "constraints.locked-target-not-moved",
|
|
@@ -1939,6 +2065,7 @@ function applyDistributeContained(input, boxes, locks, diagnostics) {
|
|
|
1939
2065
|
});
|
|
1940
2066
|
}
|
|
1941
2067
|
boxes.set(child.id, clamped);
|
|
2068
|
+
locks.delete(child.id);
|
|
1942
2069
|
pos = clamped[axis] + clamped[mainSize] + minGap;
|
|
1943
2070
|
}
|
|
1944
2071
|
diagnostics.push({
|
|
@@ -3259,6 +3386,7 @@ function routeEdge(input) {
|
|
|
3259
3386
|
const diagnostics = [];
|
|
3260
3387
|
const softObstacles = input.obstacles ?? [];
|
|
3261
3388
|
const hardObstacles = input.hardObstacles ?? [];
|
|
3389
|
+
const maxAttempts = input.maxRoutingAttempts ?? 5;
|
|
3262
3390
|
const defaultAnchors = defaultAnchorsForGeometry(
|
|
3263
3391
|
input.source.box,
|
|
3264
3392
|
input.target.box,
|
|
@@ -3367,7 +3495,7 @@ function routeEdge(input) {
|
|
|
3367
3495
|
const rerouted2 = greedyRerouteAroundObstacles(
|
|
3368
3496
|
candidate.points,
|
|
3369
3497
|
allObstacles,
|
|
3370
|
-
|
|
3498
|
+
maxAttempts
|
|
3371
3499
|
);
|
|
3372
3500
|
if (!routeCrossesBoxes(rerouted2, allObstacles) && !routeIntersectsEndpointInteriors(
|
|
3373
3501
|
rerouted2,
|
|
@@ -3387,7 +3515,7 @@ function routeEdge(input) {
|
|
|
3387
3515
|
const rerouted = greedyRerouteAroundObstacles(
|
|
3388
3516
|
bestPoints2,
|
|
3389
3517
|
allObstacles,
|
|
3390
|
-
|
|
3518
|
+
maxAttempts
|
|
3391
3519
|
);
|
|
3392
3520
|
const reroutedAvoidsEndpointInteriors = !routeIntersectsEndpointInteriors(
|
|
3393
3521
|
rerouted,
|
|
@@ -3422,7 +3550,7 @@ function routeEdge(input) {
|
|
|
3422
3550
|
const rerouted = greedyRerouteAroundObstacles(
|
|
3423
3551
|
candidate.points,
|
|
3424
3552
|
allObstacles,
|
|
3425
|
-
|
|
3553
|
+
maxAttempts
|
|
3426
3554
|
);
|
|
3427
3555
|
if (!routeCrossesBoxes(rerouted, allObstacles)) {
|
|
3428
3556
|
return {
|
|
@@ -3439,7 +3567,7 @@ function routeEdge(input) {
|
|
|
3439
3567
|
bestPoints2 = greedyRerouteAroundObstacles(
|
|
3440
3568
|
candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors),
|
|
3441
3569
|
allObstacles,
|
|
3442
|
-
|
|
3570
|
+
maxAttempts
|
|
3443
3571
|
);
|
|
3444
3572
|
}
|
|
3445
3573
|
diagnostics.push({
|
|
@@ -3464,7 +3592,7 @@ function routeEdge(input) {
|
|
|
3464
3592
|
const rerouted = greedyRerouteAroundObstacles(
|
|
3465
3593
|
candidate.points,
|
|
3466
3594
|
allObstacles,
|
|
3467
|
-
|
|
3595
|
+
maxAttempts
|
|
3468
3596
|
);
|
|
3469
3597
|
if (!routeCrossesBoxes(rerouted, allObstacles)) {
|
|
3470
3598
|
return {
|
|
@@ -3481,7 +3609,7 @@ function routeEdge(input) {
|
|
|
3481
3609
|
bestPoints = greedyRerouteAroundObstacles(
|
|
3482
3610
|
candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors),
|
|
3483
3611
|
allObstacles,
|
|
3484
|
-
|
|
3612
|
+
maxAttempts
|
|
3485
3613
|
);
|
|
3486
3614
|
}
|
|
3487
3615
|
diagnostics.push({
|
|
@@ -4149,9 +4277,7 @@ function solveDiagram(diagram, options = {}) {
|
|
|
4149
4277
|
options?.overlapSpacing ?? 40,
|
|
4150
4278
|
Math.max(0, options?.minLaneGutter ?? 0)
|
|
4151
4279
|
);
|
|
4152
|
-
|
|
4153
|
-
removeResolvedOverlapDiagnostics(diagnostics, constrained.boxes);
|
|
4154
|
-
}
|
|
4280
|
+
removeResolvedOverlapDiagnostics(diagnostics, constrained.boxes);
|
|
4155
4281
|
diagnostics.push(...swimlaneContracts.diagnostics);
|
|
4156
4282
|
const coordinatedNodes = coordinateNodes(
|
|
4157
4283
|
styledNodes,
|
|
@@ -4316,7 +4442,9 @@ function solveDiagram(diagram, options = {}) {
|
|
|
4316
4442
|
...baseTextAnnotations.map((annotation) => annotation.box),
|
|
4317
4443
|
...frameTextAnnotation.map((annotation) => annotation.box)
|
|
4318
4444
|
],
|
|
4319
|
-
options.textMeasurer
|
|
4445
|
+
options.textMeasurer,
|
|
4446
|
+
options.labelPlacement,
|
|
4447
|
+
options.labelOffset
|
|
4320
4448
|
);
|
|
4321
4449
|
const textAnnotations = [
|
|
4322
4450
|
...baseTextAnnotations,
|
|
@@ -6092,7 +6220,8 @@ function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacle
|
|
|
6092
6220
|
...softObstacles,
|
|
6093
6221
|
...routeTextObstacles
|
|
6094
6222
|
],
|
|
6095
|
-
hardObstacles
|
|
6223
|
+
hardObstacles,
|
|
6224
|
+
...options.maxRoutingAttempts === void 0 ? {} : { maxRoutingAttempts: options.maxRoutingAttempts }
|
|
6096
6225
|
});
|
|
6097
6226
|
diagnostics.push(
|
|
6098
6227
|
...route.diagnostics.map((diagnostic) => ({
|
|
@@ -6254,7 +6383,8 @@ function coordinateBaseTextAnnotations(input) {
|
|
|
6254
6383
|
}
|
|
6255
6384
|
return annotations;
|
|
6256
6385
|
}
|
|
6257
|
-
function coordinateEdgeTextAnnotations(edges, obstacleBoxes, textMeasurer) {
|
|
6386
|
+
function coordinateEdgeTextAnnotations(edges, obstacleBoxes, textMeasurer, labelPlacement, labelOffset3) {
|
|
6387
|
+
const labelBaseOffset = labelPlacement === "beside" ? labelOffset3 ?? 16 : 10;
|
|
6258
6388
|
const measurer = textMeasurer ?? createDefaultTextMeasurer();
|
|
6259
6389
|
const annotations = [];
|
|
6260
6390
|
const placedLabelBoxes = [];
|
|
@@ -6281,7 +6411,8 @@ function coordinateEdgeTextAnnotations(edges, obstacleBoxes, textMeasurer) {
|
|
|
6281
6411
|
layout2,
|
|
6282
6412
|
edges,
|
|
6283
6413
|
obstacleBoxes,
|
|
6284
|
-
placedLabelBoxes
|
|
6414
|
+
placedLabelBoxes,
|
|
6415
|
+
labelBaseOffset
|
|
6285
6416
|
);
|
|
6286
6417
|
placedLabelBoxes.push({
|
|
6287
6418
|
x: center.x - layout2.box.width / 2,
|
|
@@ -6565,15 +6696,16 @@ function fallbackLabelLayout(text) {
|
|
|
6565
6696
|
diagnostics: []
|
|
6566
6697
|
};
|
|
6567
6698
|
}
|
|
6568
|
-
function edgeLabelAnchor(edge, layout2, edges, obstacleBoxes, placedLabelBoxes) {
|
|
6569
|
-
const placement = labelPlacementOnPolyline2(edge.points);
|
|
6699
|
+
function edgeLabelAnchor(edge, layout2, edges, obstacleBoxes, placedLabelBoxes, baseOffset = 10) {
|
|
6700
|
+
const placement = labelPlacementOnPolyline2(edge.points, baseOffset);
|
|
6570
6701
|
if (placement === void 0) {
|
|
6571
6702
|
return { x: 0, y: 0 };
|
|
6572
6703
|
}
|
|
6573
6704
|
for (const candidate of edgeLabelAnchorCandidates(
|
|
6574
6705
|
edge.points,
|
|
6575
6706
|
placement,
|
|
6576
|
-
layout2
|
|
6707
|
+
layout2,
|
|
6708
|
+
baseOffset
|
|
6577
6709
|
)) {
|
|
6578
6710
|
const labelBox = {
|
|
6579
6711
|
x: candidate.x - layout2.box.width / 2,
|
|
@@ -6605,8 +6737,8 @@ function edgeLabelAnchor(edge, layout2, edges, obstacleBoxes, placedLabelBoxes)
|
|
|
6605
6737
|
}
|
|
6606
6738
|
return placement;
|
|
6607
6739
|
}
|
|
6608
|
-
function edgeLabelAnchorCandidates(points, placement, layout2) {
|
|
6609
|
-
const segment = labelSegmentOnPolyline(points);
|
|
6740
|
+
function edgeLabelAnchorCandidates(points, placement, layout2, baseOffset = 10) {
|
|
6741
|
+
const segment = labelSegmentOnPolyline(points, baseOffset);
|
|
6610
6742
|
if (segment === void 0) {
|
|
6611
6743
|
return [placement];
|
|
6612
6744
|
}
|
|
@@ -6656,7 +6788,7 @@ function edgeLabelAnchorCandidates(points, placement, layout2) {
|
|
|
6656
6788
|
}, 0);
|
|
6657
6789
|
if (totalLen > 200) {
|
|
6658
6790
|
for (const ratio of [0.25, 0.75]) {
|
|
6659
|
-
const qp = labelPlacementAtRatio(points, ratio, totalLen);
|
|
6791
|
+
const qp = labelPlacementAtRatio(points, ratio, totalLen, baseOffset);
|
|
6660
6792
|
if (qp !== void 0) {
|
|
6661
6793
|
candidates.push(qp);
|
|
6662
6794
|
const qTargetDist = totalLen * ratio;
|
|
@@ -6711,10 +6843,10 @@ function edgeLabelAnchorCandidates(points, placement, layout2) {
|
|
|
6711
6843
|
}
|
|
6712
6844
|
return candidates;
|
|
6713
6845
|
}
|
|
6714
|
-
function labelPlacementOnPolyline2(points) {
|
|
6715
|
-
return labelSegmentOnPolyline(points)?.placement;
|
|
6846
|
+
function labelPlacementOnPolyline2(points, baseOffset = 10) {
|
|
6847
|
+
return labelSegmentOnPolyline(points, baseOffset)?.placement;
|
|
6716
6848
|
}
|
|
6717
|
-
function labelSegmentOnPolyline(points) {
|
|
6849
|
+
function labelSegmentOnPolyline(points, baseOffset = 10) {
|
|
6718
6850
|
const segments = nonZeroSegments2(points);
|
|
6719
6851
|
const totalLength = segments.reduce(
|
|
6720
6852
|
(sum, segment) => sum + segment.length,
|
|
@@ -6729,7 +6861,7 @@ function labelSegmentOnPolyline(points) {
|
|
|
6729
6861
|
const ratio = remaining / segment.length;
|
|
6730
6862
|
const x = segment.start.x + (segment.end.x - segment.start.x) * ratio;
|
|
6731
6863
|
const y = segment.start.y + (segment.end.y - segment.start.y) * ratio;
|
|
6732
|
-
const offset2 = labelOffset2(segment);
|
|
6864
|
+
const offset2 = labelOffset2(segment, baseOffset);
|
|
6733
6865
|
return {
|
|
6734
6866
|
start: segment.start,
|
|
6735
6867
|
end: segment.end,
|
|
@@ -6742,7 +6874,7 @@ function labelSegmentOnPolyline(points) {
|
|
|
6742
6874
|
if (last === void 0) {
|
|
6743
6875
|
return void 0;
|
|
6744
6876
|
}
|
|
6745
|
-
const offset = labelOffset2(last);
|
|
6877
|
+
const offset = labelOffset2(last, baseOffset);
|
|
6746
6878
|
return {
|
|
6747
6879
|
start: last.start,
|
|
6748
6880
|
end: last.end,
|
|
@@ -6764,7 +6896,7 @@ function nonZeroSegments2(points) {
|
|
|
6764
6896
|
}
|
|
6765
6897
|
return segments;
|
|
6766
6898
|
}
|
|
6767
|
-
function labelPlacementAtRatio(points, ratio, totalLength) {
|
|
6899
|
+
function labelPlacementAtRatio(points, ratio, totalLength, baseOffset = 10) {
|
|
6768
6900
|
if (points.length < 2 || ratio < 0 || ratio > 1) {
|
|
6769
6901
|
return void 0;
|
|
6770
6902
|
}
|
|
@@ -6782,7 +6914,10 @@ function labelPlacementAtRatio(points, ratio, totalLength) {
|
|
|
6782
6914
|
}
|
|
6783
6915
|
if (travelled + segLen >= targetDist) {
|
|
6784
6916
|
const t = (targetDist - travelled) / segLen;
|
|
6785
|
-
const offset = labelOffset2(
|
|
6917
|
+
const offset = labelOffset2(
|
|
6918
|
+
{ start: prev, end: curr, length: segLen },
|
|
6919
|
+
baseOffset
|
|
6920
|
+
);
|
|
6786
6921
|
return {
|
|
6787
6922
|
x: prev.x + (curr.x - prev.x) * t + offset.x,
|
|
6788
6923
|
y: prev.y + (curr.y - prev.y) * t + offset.y
|
|
@@ -6792,8 +6927,8 @@ function labelPlacementAtRatio(points, ratio, totalLength) {
|
|
|
6792
6927
|
}
|
|
6793
6928
|
return void 0;
|
|
6794
6929
|
}
|
|
6795
|
-
function labelOffset2(segment) {
|
|
6796
|
-
const offset =
|
|
6930
|
+
function labelOffset2(segment, baseOffset = 10) {
|
|
6931
|
+
const offset = baseOffset;
|
|
6797
6932
|
const dx = segment.end.x - segment.start.x;
|
|
6798
6933
|
const dy = segment.end.y - segment.start.y;
|
|
6799
6934
|
return {
|