@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/dist/index.d.cts
CHANGED
|
@@ -688,6 +688,8 @@ interface RouteEdgeInput {
|
|
|
688
688
|
targetAnchor?: AnchorName;
|
|
689
689
|
obstacles?: readonly Box[];
|
|
690
690
|
hardObstacles?: readonly Box[];
|
|
691
|
+
/** Maximum greedy rerouting iterations (default 5). */
|
|
692
|
+
maxRoutingAttempts?: number;
|
|
691
693
|
}
|
|
692
694
|
interface RouteEdgeResult {
|
|
693
695
|
points: Point[];
|
|
@@ -729,6 +731,12 @@ interface SolveDiagramOptions {
|
|
|
729
731
|
textMeasurer?: TextMeasurer;
|
|
730
732
|
/** When true, promote deliverability-breaking diagnostics to errors. */
|
|
731
733
|
strict?: boolean;
|
|
734
|
+
/** Maximum greedy rerouting iterations per edge (default 5). */
|
|
735
|
+
maxRoutingAttempts?: number;
|
|
736
|
+
/** Edge label placement mode: "beside" offsets away from the edge, "on-path" (default) places at the midpoint. */
|
|
737
|
+
labelPlacement?: "beside" | "on-path";
|
|
738
|
+
/** Pixels to offset edge labels from the edge path when labelPlacement is "beside". */
|
|
739
|
+
labelOffset?: number;
|
|
732
740
|
}
|
|
733
741
|
interface PortShiftingOptions {
|
|
734
742
|
enabled?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -688,6 +688,8 @@ interface RouteEdgeInput {
|
|
|
688
688
|
targetAnchor?: AnchorName;
|
|
689
689
|
obstacles?: readonly Box[];
|
|
690
690
|
hardObstacles?: readonly Box[];
|
|
691
|
+
/** Maximum greedy rerouting iterations (default 5). */
|
|
692
|
+
maxRoutingAttempts?: number;
|
|
691
693
|
}
|
|
692
694
|
interface RouteEdgeResult {
|
|
693
695
|
points: Point[];
|
|
@@ -729,6 +731,12 @@ interface SolveDiagramOptions {
|
|
|
729
731
|
textMeasurer?: TextMeasurer;
|
|
730
732
|
/** When true, promote deliverability-breaking diagnostics to errors. */
|
|
731
733
|
strict?: boolean;
|
|
734
|
+
/** Maximum greedy rerouting iterations per edge (default 5). */
|
|
735
|
+
maxRoutingAttempts?: number;
|
|
736
|
+
/** Edge label placement mode: "beside" offsets away from the edge, "on-path" (default) places at the midpoint. */
|
|
737
|
+
labelPlacement?: "beside" | "on-path";
|
|
738
|
+
/** Pixels to offset edge labels from the edge path when labelPlacement is "beside". */
|
|
739
|
+
labelOffset?: number;
|
|
732
740
|
}
|
|
733
741
|
interface PortShiftingOptions {
|
|
734
742
|
enabled?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -96,6 +96,9 @@ function applyLayoutConstraints(input) {
|
|
|
96
96
|
const nodeById = new Map(input.nodes.map((node) => [node.id, node]));
|
|
97
97
|
applyFixedPositionLocks(input.nodes, boxes, locks, diagnostics);
|
|
98
98
|
applyExactPositions(input.constraints, boxes, locks, diagnostics, nodeById);
|
|
99
|
+
if (input.distributeContainedChildren) {
|
|
100
|
+
yieldFixedPositionLocks(input, boxes, locks);
|
|
101
|
+
}
|
|
99
102
|
applyContainment(input.constraints, boxes, locks, diagnostics, false);
|
|
100
103
|
applyRelative(input.constraints, boxes, locks, diagnostics);
|
|
101
104
|
applyAlign(input.constraints, boxes, locks, diagnostics);
|
|
@@ -109,6 +112,13 @@ function applyLayoutConstraints(input) {
|
|
|
109
112
|
);
|
|
110
113
|
applyContainment(input.constraints, boxes, locks, diagnostics, true);
|
|
111
114
|
applyDistributeContained(input, boxes, locks, diagnostics);
|
|
115
|
+
if (input.distributeContainedChildren) {
|
|
116
|
+
const diagBefore = diagnostics.length;
|
|
117
|
+
applyContainment(input.constraints, boxes, locks, diagnostics, true);
|
|
118
|
+
applyDistributeContained(input, boxes, locks, diagnostics);
|
|
119
|
+
dedupReplayDiagnostics(diagnostics, diagBefore);
|
|
120
|
+
}
|
|
121
|
+
removeResolvedConstraintDiagnostics(input.constraints, boxes, diagnostics);
|
|
112
122
|
reportOverlaps(boxes, diagnostics, containmentOverlapKeys(input.constraints));
|
|
113
123
|
reportIntraContainerOverflow(input, boxes, diagnostics);
|
|
114
124
|
return { boxes, locks, diagnostics };
|
|
@@ -154,6 +164,62 @@ function applyFixedPositionLocks(nodes, boxes, locks, diagnostics) {
|
|
|
154
164
|
locks.set(node.id, { nodeId: node.id, source: "fixed-position" });
|
|
155
165
|
}
|
|
156
166
|
}
|
|
167
|
+
function dedupReplayDiagnostics(diagnostics, keepUpTo) {
|
|
168
|
+
const seen = /* @__PURE__ */ new Set();
|
|
169
|
+
for (let i = 0; i < keepUpTo && i < diagnostics.length; i += 1) {
|
|
170
|
+
const d = diagnostics[i];
|
|
171
|
+
if (d === void 0) continue;
|
|
172
|
+
seen.add(diagnosticFingerprint(d));
|
|
173
|
+
}
|
|
174
|
+
for (let i = diagnostics.length - 1; i >= keepUpTo; i -= 1) {
|
|
175
|
+
const d = diagnostics[i];
|
|
176
|
+
if (d === void 0) continue;
|
|
177
|
+
const fp = diagnosticFingerprint(d);
|
|
178
|
+
if (seen.has(fp)) {
|
|
179
|
+
diagnostics.splice(i, 1);
|
|
180
|
+
} else {
|
|
181
|
+
seen.add(fp);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function diagnosticFingerprint(d) {
|
|
186
|
+
const nodeId = typeof d.detail?.nodeId === "string" ? d.detail.nodeId : "";
|
|
187
|
+
const containerId = typeof d.detail?.containerId === "string" ? d.detail.containerId : "";
|
|
188
|
+
return `${d.code}|${nodeId}|${containerId}`;
|
|
189
|
+
}
|
|
190
|
+
function yieldFixedPositionLocks(input, boxes, locks) {
|
|
191
|
+
for (const c of input.constraints) {
|
|
192
|
+
if (c.kind !== "containment") continue;
|
|
193
|
+
const container = boxes.get(c.containerId);
|
|
194
|
+
if (container === void 0) continue;
|
|
195
|
+
const content = contentBox(container, c.padding);
|
|
196
|
+
const mainAxis = input.direction === "LR" || input.direction === "RL" ? "width" : "height";
|
|
197
|
+
const crossAxis = mainAxis === "width" ? "height" : "width";
|
|
198
|
+
let eligible = 0;
|
|
199
|
+
for (const childId of c.childIds) {
|
|
200
|
+
const box = boxes.get(childId);
|
|
201
|
+
if (box === void 0) continue;
|
|
202
|
+
const lock = locks.get(childId);
|
|
203
|
+
if (lock?.source === "exact-position") continue;
|
|
204
|
+
const fits = box[mainAxis] <= content[mainAxis] && box[crossAxis] <= content[crossAxis];
|
|
205
|
+
if (fits) {
|
|
206
|
+
eligible += 1;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (eligible < 2) continue;
|
|
210
|
+
for (const childId of c.childIds) {
|
|
211
|
+
const lock = locks.get(childId);
|
|
212
|
+
if (lock?.source === "fixed-position") {
|
|
213
|
+
const box = boxes.get(childId);
|
|
214
|
+
if (box === void 0) continue;
|
|
215
|
+
const fits = box[mainAxis] <= content[mainAxis] && box[crossAxis] <= content[crossAxis];
|
|
216
|
+
if (fits) {
|
|
217
|
+
locks.delete(childId);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
157
223
|
function applyExactPositions(constraints, boxes, locks, diagnostics, nodeById) {
|
|
158
224
|
for (const constraint of constraints) {
|
|
159
225
|
if (constraint.kind !== "exact-position") {
|
|
@@ -226,7 +292,7 @@ function applyContainment(constraints, boxes, locks, diagnostics, reportOverflow
|
|
|
226
292
|
code: "constraints.locked-target-not-moved",
|
|
227
293
|
message: `Locked child ${childId} was not moved into containment.`,
|
|
228
294
|
path: ["constraints", constraint.id ?? constraint.containerId],
|
|
229
|
-
detail: { nodeId: childId }
|
|
295
|
+
detail: { nodeId: childId, containerId: constraint.containerId }
|
|
230
296
|
});
|
|
231
297
|
if (!isInside(child, content)) {
|
|
232
298
|
diagnostics.push({
|
|
@@ -378,6 +444,60 @@ function repairOverlaps(input, boxes, locks, diagnostics, siblingPairs) {
|
|
|
378
444
|
}
|
|
379
445
|
reportOverlaps(boxes, diagnostics, ignoredPairs);
|
|
380
446
|
}
|
|
447
|
+
function removeResolvedConstraintDiagnostics(constraints, boxes, diagnostics) {
|
|
448
|
+
for (let i = diagnostics.length - 1; i >= 0; i -= 1) {
|
|
449
|
+
const d = diagnostics[i];
|
|
450
|
+
if (d === void 0) continue;
|
|
451
|
+
if (d.code === "constraints.overlap.unresolved") {
|
|
452
|
+
const aId = d.detail?.firstId;
|
|
453
|
+
const bId = d.detail?.secondId;
|
|
454
|
+
if (typeof aId !== "string" || typeof bId !== "string") continue;
|
|
455
|
+
const a = boxes.get(aId);
|
|
456
|
+
const b = boxes.get(bId);
|
|
457
|
+
if (a !== void 0 && b !== void 0 && !intersectsAabb(a, b)) {
|
|
458
|
+
diagnostics.splice(i, 1);
|
|
459
|
+
}
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
if (d.code === "constraints.containment.impossible" || d.code === "constraints.locked-target-not-moved" && typeof d.message === "string" && d.message.includes("not moved into containment")) {
|
|
463
|
+
const nodeId = d.detail?.nodeId;
|
|
464
|
+
if (typeof nodeId !== "string") continue;
|
|
465
|
+
const child = boxes.get(nodeId);
|
|
466
|
+
if (child === void 0) continue;
|
|
467
|
+
const diagContainerId = typeof d.detail?.containerId === "string" ? d.detail.containerId : void 0;
|
|
468
|
+
let resolved = false;
|
|
469
|
+
for (const c of constraints) {
|
|
470
|
+
if (c.kind !== "containment") continue;
|
|
471
|
+
if (!c.childIds.includes(nodeId)) continue;
|
|
472
|
+
if (diagContainerId !== void 0 && c.containerId !== diagContainerId) {
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
const container = boxes.get(c.containerId);
|
|
476
|
+
if (container === void 0) continue;
|
|
477
|
+
const content = contentBox(container, c.padding);
|
|
478
|
+
if (isInside(child, content)) {
|
|
479
|
+
diagnostics.splice(i, 1);
|
|
480
|
+
resolved = true;
|
|
481
|
+
}
|
|
482
|
+
break;
|
|
483
|
+
}
|
|
484
|
+
if (!resolved && diagContainerId !== void 0) {
|
|
485
|
+
for (const c of constraints) {
|
|
486
|
+
if (c.kind !== "containment") continue;
|
|
487
|
+
if (c.containerId !== diagContainerId) continue;
|
|
488
|
+
if (!c.childIds.includes(nodeId)) continue;
|
|
489
|
+
const container = boxes.get(c.containerId);
|
|
490
|
+
if (container === void 0) continue;
|
|
491
|
+
const content = contentBox(container, c.padding);
|
|
492
|
+
if (isInside(child, content)) {
|
|
493
|
+
diagnostics.splice(i, 1);
|
|
494
|
+
}
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
381
501
|
function reportOverlaps(boxes, diagnostics, ignoredPairs = /* @__PURE__ */ new Set()) {
|
|
382
502
|
const ids = [...boxes.keys()].sort();
|
|
383
503
|
const reported = new Set(
|
|
@@ -685,6 +805,12 @@ function applyDistributeContained(input, boxes, locks, diagnostics) {
|
|
|
685
805
|
continue;
|
|
686
806
|
}
|
|
687
807
|
if (locks.has(childId)) {
|
|
808
|
+
const lock = locks.get(childId);
|
|
809
|
+
if (lock?.source === "fixed-position") {
|
|
810
|
+
unlocked.push({ id: childId, box });
|
|
811
|
+
locks.delete(childId);
|
|
812
|
+
continue;
|
|
813
|
+
}
|
|
688
814
|
diagnostics.push({
|
|
689
815
|
severity: "warning",
|
|
690
816
|
code: "constraints.locked-target-not-moved",
|
|
@@ -743,6 +869,7 @@ function applyDistributeContained(input, boxes, locks, diagnostics) {
|
|
|
743
869
|
});
|
|
744
870
|
}
|
|
745
871
|
boxes.set(child.id, clamped);
|
|
872
|
+
locks.delete(child.id);
|
|
746
873
|
pos = clamped[axis] + clamped[mainSize] + minGap;
|
|
747
874
|
}
|
|
748
875
|
diagnostics.push({
|
|
@@ -3859,6 +3986,7 @@ function routeEdge(input) {
|
|
|
3859
3986
|
const diagnostics = [];
|
|
3860
3987
|
const softObstacles = input.obstacles ?? [];
|
|
3861
3988
|
const hardObstacles = input.hardObstacles ?? [];
|
|
3989
|
+
const maxAttempts = input.maxRoutingAttempts ?? 5;
|
|
3862
3990
|
const defaultAnchors = defaultAnchorsForGeometry(
|
|
3863
3991
|
input.source.box,
|
|
3864
3992
|
input.target.box,
|
|
@@ -3967,7 +4095,7 @@ function routeEdge(input) {
|
|
|
3967
4095
|
const rerouted2 = greedyRerouteAroundObstacles(
|
|
3968
4096
|
candidate.points,
|
|
3969
4097
|
allObstacles,
|
|
3970
|
-
|
|
4098
|
+
maxAttempts
|
|
3971
4099
|
);
|
|
3972
4100
|
if (!routeCrossesBoxes(rerouted2, allObstacles) && !routeIntersectsEndpointInteriors(
|
|
3973
4101
|
rerouted2,
|
|
@@ -3987,7 +4115,7 @@ function routeEdge(input) {
|
|
|
3987
4115
|
const rerouted = greedyRerouteAroundObstacles(
|
|
3988
4116
|
bestPoints2,
|
|
3989
4117
|
allObstacles,
|
|
3990
|
-
|
|
4118
|
+
maxAttempts
|
|
3991
4119
|
);
|
|
3992
4120
|
const reroutedAvoidsEndpointInteriors = !routeIntersectsEndpointInteriors(
|
|
3993
4121
|
rerouted,
|
|
@@ -4022,7 +4150,7 @@ function routeEdge(input) {
|
|
|
4022
4150
|
const rerouted = greedyRerouteAroundObstacles(
|
|
4023
4151
|
candidate.points,
|
|
4024
4152
|
allObstacles,
|
|
4025
|
-
|
|
4153
|
+
maxAttempts
|
|
4026
4154
|
);
|
|
4027
4155
|
if (!routeCrossesBoxes(rerouted, allObstacles)) {
|
|
4028
4156
|
return {
|
|
@@ -4039,7 +4167,7 @@ function routeEdge(input) {
|
|
|
4039
4167
|
bestPoints2 = greedyRerouteAroundObstacles(
|
|
4040
4168
|
candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors),
|
|
4041
4169
|
allObstacles,
|
|
4042
|
-
|
|
4170
|
+
maxAttempts
|
|
4043
4171
|
);
|
|
4044
4172
|
}
|
|
4045
4173
|
diagnostics.push({
|
|
@@ -4064,7 +4192,7 @@ function routeEdge(input) {
|
|
|
4064
4192
|
const rerouted = greedyRerouteAroundObstacles(
|
|
4065
4193
|
candidate.points,
|
|
4066
4194
|
allObstacles,
|
|
4067
|
-
|
|
4195
|
+
maxAttempts
|
|
4068
4196
|
);
|
|
4069
4197
|
if (!routeCrossesBoxes(rerouted, allObstacles)) {
|
|
4070
4198
|
return {
|
|
@@ -4081,7 +4209,7 @@ function routeEdge(input) {
|
|
|
4081
4209
|
bestPoints = greedyRerouteAroundObstacles(
|
|
4082
4210
|
candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors),
|
|
4083
4211
|
allObstacles,
|
|
4084
|
-
|
|
4212
|
+
maxAttempts
|
|
4085
4213
|
);
|
|
4086
4214
|
}
|
|
4087
4215
|
diagnostics.push({
|
|
@@ -4749,9 +4877,7 @@ function solveDiagram(diagram, options = {}) {
|
|
|
4749
4877
|
options?.overlapSpacing ?? 40,
|
|
4750
4878
|
Math.max(0, options?.minLaneGutter ?? 0)
|
|
4751
4879
|
);
|
|
4752
|
-
|
|
4753
|
-
removeResolvedOverlapDiagnostics(diagnostics, constrained.boxes);
|
|
4754
|
-
}
|
|
4880
|
+
removeResolvedOverlapDiagnostics(diagnostics, constrained.boxes);
|
|
4755
4881
|
diagnostics.push(...swimlaneContracts.diagnostics);
|
|
4756
4882
|
const coordinatedNodes = coordinateNodes(
|
|
4757
4883
|
styledNodes,
|
|
@@ -4916,7 +5042,9 @@ function solveDiagram(diagram, options = {}) {
|
|
|
4916
5042
|
...baseTextAnnotations.map((annotation) => annotation.box),
|
|
4917
5043
|
...frameTextAnnotation.map((annotation) => annotation.box)
|
|
4918
5044
|
],
|
|
4919
|
-
options.textMeasurer
|
|
5045
|
+
options.textMeasurer,
|
|
5046
|
+
options.labelPlacement,
|
|
5047
|
+
options.labelOffset
|
|
4920
5048
|
);
|
|
4921
5049
|
const textAnnotations = [
|
|
4922
5050
|
...baseTextAnnotations,
|
|
@@ -6695,7 +6823,8 @@ function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacle
|
|
|
6695
6823
|
...softObstacles,
|
|
6696
6824
|
...routeTextObstacles
|
|
6697
6825
|
],
|
|
6698
|
-
hardObstacles
|
|
6826
|
+
hardObstacles,
|
|
6827
|
+
...options.maxRoutingAttempts === void 0 ? {} : { maxRoutingAttempts: options.maxRoutingAttempts }
|
|
6699
6828
|
});
|
|
6700
6829
|
diagnostics.push(
|
|
6701
6830
|
...route.diagnostics.map((diagnostic) => ({
|
|
@@ -6857,7 +6986,8 @@ function coordinateBaseTextAnnotations(input) {
|
|
|
6857
6986
|
}
|
|
6858
6987
|
return annotations;
|
|
6859
6988
|
}
|
|
6860
|
-
function coordinateEdgeTextAnnotations(edges, obstacleBoxes, textMeasurer) {
|
|
6989
|
+
function coordinateEdgeTextAnnotations(edges, obstacleBoxes, textMeasurer, labelPlacement, labelOffset3) {
|
|
6990
|
+
const labelBaseOffset = labelPlacement === "beside" ? labelOffset3 ?? 16 : 10;
|
|
6861
6991
|
const measurer = textMeasurer ?? createDefaultTextMeasurer();
|
|
6862
6992
|
const annotations = [];
|
|
6863
6993
|
const placedLabelBoxes = [];
|
|
@@ -6884,7 +7014,8 @@ function coordinateEdgeTextAnnotations(edges, obstacleBoxes, textMeasurer) {
|
|
|
6884
7014
|
layout2,
|
|
6885
7015
|
edges,
|
|
6886
7016
|
obstacleBoxes,
|
|
6887
|
-
placedLabelBoxes
|
|
7017
|
+
placedLabelBoxes,
|
|
7018
|
+
labelBaseOffset
|
|
6888
7019
|
);
|
|
6889
7020
|
placedLabelBoxes.push({
|
|
6890
7021
|
x: center.x - layout2.box.width / 2,
|
|
@@ -7168,15 +7299,16 @@ function fallbackLabelLayout(text) {
|
|
|
7168
7299
|
diagnostics: []
|
|
7169
7300
|
};
|
|
7170
7301
|
}
|
|
7171
|
-
function edgeLabelAnchor(edge, layout2, edges, obstacleBoxes, placedLabelBoxes) {
|
|
7172
|
-
const placement = labelPlacementOnPolyline2(edge.points);
|
|
7302
|
+
function edgeLabelAnchor(edge, layout2, edges, obstacleBoxes, placedLabelBoxes, baseOffset = 10) {
|
|
7303
|
+
const placement = labelPlacementOnPolyline2(edge.points, baseOffset);
|
|
7173
7304
|
if (placement === void 0) {
|
|
7174
7305
|
return { x: 0, y: 0 };
|
|
7175
7306
|
}
|
|
7176
7307
|
for (const candidate of edgeLabelAnchorCandidates(
|
|
7177
7308
|
edge.points,
|
|
7178
7309
|
placement,
|
|
7179
|
-
layout2
|
|
7310
|
+
layout2,
|
|
7311
|
+
baseOffset
|
|
7180
7312
|
)) {
|
|
7181
7313
|
const labelBox = {
|
|
7182
7314
|
x: candidate.x - layout2.box.width / 2,
|
|
@@ -7208,8 +7340,8 @@ function edgeLabelAnchor(edge, layout2, edges, obstacleBoxes, placedLabelBoxes)
|
|
|
7208
7340
|
}
|
|
7209
7341
|
return placement;
|
|
7210
7342
|
}
|
|
7211
|
-
function edgeLabelAnchorCandidates(points, placement, layout2) {
|
|
7212
|
-
const segment = labelSegmentOnPolyline(points);
|
|
7343
|
+
function edgeLabelAnchorCandidates(points, placement, layout2, baseOffset = 10) {
|
|
7344
|
+
const segment = labelSegmentOnPolyline(points, baseOffset);
|
|
7213
7345
|
if (segment === void 0) {
|
|
7214
7346
|
return [placement];
|
|
7215
7347
|
}
|
|
@@ -7259,7 +7391,7 @@ function edgeLabelAnchorCandidates(points, placement, layout2) {
|
|
|
7259
7391
|
}, 0);
|
|
7260
7392
|
if (totalLen > 200) {
|
|
7261
7393
|
for (const ratio of [0.25, 0.75]) {
|
|
7262
|
-
const qp = labelPlacementAtRatio(points, ratio, totalLen);
|
|
7394
|
+
const qp = labelPlacementAtRatio(points, ratio, totalLen, baseOffset);
|
|
7263
7395
|
if (qp !== void 0) {
|
|
7264
7396
|
candidates.push(qp);
|
|
7265
7397
|
const qTargetDist = totalLen * ratio;
|
|
@@ -7314,10 +7446,10 @@ function edgeLabelAnchorCandidates(points, placement, layout2) {
|
|
|
7314
7446
|
}
|
|
7315
7447
|
return candidates;
|
|
7316
7448
|
}
|
|
7317
|
-
function labelPlacementOnPolyline2(points) {
|
|
7318
|
-
return labelSegmentOnPolyline(points)?.placement;
|
|
7449
|
+
function labelPlacementOnPolyline2(points, baseOffset = 10) {
|
|
7450
|
+
return labelSegmentOnPolyline(points, baseOffset)?.placement;
|
|
7319
7451
|
}
|
|
7320
|
-
function labelSegmentOnPolyline(points) {
|
|
7452
|
+
function labelSegmentOnPolyline(points, baseOffset = 10) {
|
|
7321
7453
|
const segments = nonZeroSegments2(points);
|
|
7322
7454
|
const totalLength = segments.reduce(
|
|
7323
7455
|
(sum, segment) => sum + segment.length,
|
|
@@ -7332,7 +7464,7 @@ function labelSegmentOnPolyline(points) {
|
|
|
7332
7464
|
const ratio = remaining / segment.length;
|
|
7333
7465
|
const x = segment.start.x + (segment.end.x - segment.start.x) * ratio;
|
|
7334
7466
|
const y = segment.start.y + (segment.end.y - segment.start.y) * ratio;
|
|
7335
|
-
const offset2 = labelOffset2(segment);
|
|
7467
|
+
const offset2 = labelOffset2(segment, baseOffset);
|
|
7336
7468
|
return {
|
|
7337
7469
|
start: segment.start,
|
|
7338
7470
|
end: segment.end,
|
|
@@ -7345,7 +7477,7 @@ function labelSegmentOnPolyline(points) {
|
|
|
7345
7477
|
if (last === void 0) {
|
|
7346
7478
|
return void 0;
|
|
7347
7479
|
}
|
|
7348
|
-
const offset = labelOffset2(last);
|
|
7480
|
+
const offset = labelOffset2(last, baseOffset);
|
|
7349
7481
|
return {
|
|
7350
7482
|
start: last.start,
|
|
7351
7483
|
end: last.end,
|
|
@@ -7367,7 +7499,7 @@ function nonZeroSegments2(points) {
|
|
|
7367
7499
|
}
|
|
7368
7500
|
return segments;
|
|
7369
7501
|
}
|
|
7370
|
-
function labelPlacementAtRatio(points, ratio, totalLength) {
|
|
7502
|
+
function labelPlacementAtRatio(points, ratio, totalLength, baseOffset = 10) {
|
|
7371
7503
|
if (points.length < 2 || ratio < 0 || ratio > 1) {
|
|
7372
7504
|
return void 0;
|
|
7373
7505
|
}
|
|
@@ -7385,7 +7517,10 @@ function labelPlacementAtRatio(points, ratio, totalLength) {
|
|
|
7385
7517
|
}
|
|
7386
7518
|
if (travelled + segLen >= targetDist) {
|
|
7387
7519
|
const t = (targetDist - travelled) / segLen;
|
|
7388
|
-
const offset = labelOffset2(
|
|
7520
|
+
const offset = labelOffset2(
|
|
7521
|
+
{ start: prev, end: curr, length: segLen },
|
|
7522
|
+
baseOffset
|
|
7523
|
+
);
|
|
7389
7524
|
return {
|
|
7390
7525
|
x: prev.x + (curr.x - prev.x) * t + offset.x,
|
|
7391
7526
|
y: prev.y + (curr.y - prev.y) * t + offset.y
|
|
@@ -7395,8 +7530,8 @@ function labelPlacementAtRatio(points, ratio, totalLength) {
|
|
|
7395
7530
|
}
|
|
7396
7531
|
return void 0;
|
|
7397
7532
|
}
|
|
7398
|
-
function labelOffset2(segment) {
|
|
7399
|
-
const offset =
|
|
7533
|
+
function labelOffset2(segment, baseOffset = 10) {
|
|
7534
|
+
const offset = baseOffset;
|
|
7400
7535
|
const dx = segment.end.x - segment.start.x;
|
|
7401
7536
|
const dy = segment.end.y - segment.start.y;
|
|
7402
7537
|
return {
|