@crazyhappyone/auto-graph 0.2.9 → 0.2.11
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/cli/index.cjs +201 -38
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +201 -38
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +201 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +201 -38
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.cjs
CHANGED
|
@@ -4740,7 +4740,7 @@ function segmentCrossesAnyObstacle(a, b, obstacles) {
|
|
|
4740
4740
|
}
|
|
4741
4741
|
|
|
4742
4742
|
// src/routing/routes.ts
|
|
4743
|
-
function checkBacktracking(points, source, target, diagnostics) {
|
|
4743
|
+
function checkBacktracking(points, source, target, diagnostics, maxRatio) {
|
|
4744
4744
|
if (points.length < 2) return;
|
|
4745
4745
|
const direct = Math.hypot(target.x - source.x, target.y - source.y);
|
|
4746
4746
|
if (direct <= 0) return;
|
|
@@ -4750,7 +4750,7 @@ function checkBacktracking(points, source, target, diagnostics) {
|
|
|
4750
4750
|
const b = points[i + 1];
|
|
4751
4751
|
routeLen += Math.hypot(b.x - a.x, b.y - a.y);
|
|
4752
4752
|
}
|
|
4753
|
-
const threshold =
|
|
4753
|
+
const threshold = maxRatio ?? 20;
|
|
4754
4754
|
if (routeLen > direct * threshold) {
|
|
4755
4755
|
diagnostics.push({
|
|
4756
4756
|
severity: "warning",
|
|
@@ -4768,8 +4768,20 @@ function routeEdge(input) {
|
|
|
4768
4768
|
const diagnostics = [];
|
|
4769
4769
|
const softObstacles = input.obstacles ?? [];
|
|
4770
4770
|
const hardObstacles = input.hardObstacles ?? [];
|
|
4771
|
+
let bestRejectedPath;
|
|
4772
|
+
let bestRejectedCrossings = Number.POSITIVE_INFINITY;
|
|
4771
4773
|
const softObstacleIndex = input.obstacleIndex ?? createBoxSpatialIndex(indexedBoxes(softObstacles));
|
|
4772
4774
|
const hardObstacleIndex = input.hardObstacleIndex ?? createBoxSpatialIndex(indexedBoxes(hardObstacles));
|
|
4775
|
+
const recordRejected = (candidate) => {
|
|
4776
|
+
if (routeIntersectsObstacles(candidate, hardObstacles, hardObstacleIndex)) {
|
|
4777
|
+
return;
|
|
4778
|
+
}
|
|
4779
|
+
const crossings = countObstacleCrossings(candidate, softObstacles);
|
|
4780
|
+
if (crossings < bestRejectedCrossings) {
|
|
4781
|
+
bestRejectedCrossings = crossings;
|
|
4782
|
+
bestRejectedPath = candidate;
|
|
4783
|
+
}
|
|
4784
|
+
};
|
|
4773
4785
|
const maxAttempts = input.maxRoutingAttempts ?? 5;
|
|
4774
4786
|
const defaultAnchors = defaultAnchorsForGeometry(
|
|
4775
4787
|
input.source.box,
|
|
@@ -4829,13 +4841,14 @@ function routeEdge(input) {
|
|
|
4829
4841
|
targetAnchor
|
|
4830
4842
|
);
|
|
4831
4843
|
const allObstacles = [...softObstacles, ...hardObstacles];
|
|
4844
|
+
const corridorMargin = input.corridorMargin ?? 32;
|
|
4832
4845
|
const corridorObstacles = filterObstaclesByCorridor(
|
|
4833
4846
|
source,
|
|
4834
4847
|
target,
|
|
4835
4848
|
allObstacles,
|
|
4836
4849
|
[],
|
|
4837
4850
|
// endpointObstacles passed separately via options
|
|
4838
|
-
|
|
4851
|
+
corridorMargin
|
|
4839
4852
|
);
|
|
4840
4853
|
const cornerObstacles = corridorObstacles.length === 0 && allObstacles.length > 0 ? allObstacles : corridorObstacles;
|
|
4841
4854
|
let cornerPath = findCornerGraphPath(
|
|
@@ -4858,7 +4871,7 @@ function routeEdge(input) {
|
|
|
4858
4871
|
source,
|
|
4859
4872
|
target,
|
|
4860
4873
|
allObstacles,
|
|
4861
|
-
{ endpointObstacles, margin: 0 },
|
|
4874
|
+
{ endpointObstacles, margin: 0, corridorMargin },
|
|
4862
4875
|
diagnostics
|
|
4863
4876
|
);
|
|
4864
4877
|
if (path !== null && path.length >= 2) {
|
|
@@ -4875,9 +4888,16 @@ function routeEdge(input) {
|
|
|
4875
4888
|
softObstacles,
|
|
4876
4889
|
softObstacleIndex
|
|
4877
4890
|
) && !routeIntersectsObstacles(finalized, hardObstacles, hardObstacleIndex)) {
|
|
4878
|
-
checkBacktracking(
|
|
4891
|
+
checkBacktracking(
|
|
4892
|
+
finalized,
|
|
4893
|
+
source,
|
|
4894
|
+
target,
|
|
4895
|
+
diagnostics,
|
|
4896
|
+
input.maxBacktrackingRatio
|
|
4897
|
+
);
|
|
4879
4898
|
return { points: finalized, diagnostics };
|
|
4880
4899
|
}
|
|
4900
|
+
recordRejected(finalized);
|
|
4881
4901
|
if (cornerPath !== null) {
|
|
4882
4902
|
const fullCornerPath = cornerObstacles.length < allObstacles.length ? findCornerGraphPath(
|
|
4883
4903
|
source,
|
|
@@ -4904,15 +4924,22 @@ function routeEdge(input) {
|
|
|
4904
4924
|
hardObstacles,
|
|
4905
4925
|
hardObstacleIndex
|
|
4906
4926
|
)) {
|
|
4907
|
-
checkBacktracking(
|
|
4927
|
+
checkBacktracking(
|
|
4928
|
+
fullFinalized,
|
|
4929
|
+
source,
|
|
4930
|
+
target,
|
|
4931
|
+
diagnostics,
|
|
4932
|
+
input.maxBacktrackingRatio
|
|
4933
|
+
);
|
|
4908
4934
|
return { points: fullFinalized, diagnostics };
|
|
4909
4935
|
}
|
|
4936
|
+
recordRejected(fullFinalized);
|
|
4910
4937
|
}
|
|
4911
4938
|
const gridPath = findObstacleFreePath(
|
|
4912
4939
|
source,
|
|
4913
4940
|
target,
|
|
4914
4941
|
allObstacles,
|
|
4915
|
-
{ endpointObstacles, margin: 0 },
|
|
4942
|
+
{ endpointObstacles, margin: 0, corridorMargin },
|
|
4916
4943
|
diagnostics
|
|
4917
4944
|
);
|
|
4918
4945
|
if (gridPath !== null && gridPath.length >= 2) {
|
|
@@ -4933,9 +4960,16 @@ function routeEdge(input) {
|
|
|
4933
4960
|
hardObstacles,
|
|
4934
4961
|
hardObstacleIndex
|
|
4935
4962
|
)) {
|
|
4936
|
-
checkBacktracking(
|
|
4963
|
+
checkBacktracking(
|
|
4964
|
+
gridFinalized,
|
|
4965
|
+
source,
|
|
4966
|
+
target,
|
|
4967
|
+
diagnostics,
|
|
4968
|
+
input.maxBacktrackingRatio
|
|
4969
|
+
);
|
|
4937
4970
|
return { points: gridFinalized, diagnostics };
|
|
4938
4971
|
}
|
|
4972
|
+
recordRejected(gridFinalized);
|
|
4939
4973
|
}
|
|
4940
4974
|
}
|
|
4941
4975
|
}
|
|
@@ -4999,7 +5033,8 @@ function routeEdge(input) {
|
|
|
4999
5033
|
finalizedClean,
|
|
5000
5034
|
candidate.points[0],
|
|
5001
5035
|
candidate.points[candidate.points.length - 1],
|
|
5002
|
-
diagnostics
|
|
5036
|
+
diagnostics,
|
|
5037
|
+
input.maxBacktrackingRatio
|
|
5003
5038
|
);
|
|
5004
5039
|
return { points: finalizedClean, diagnostics };
|
|
5005
5040
|
}
|
|
@@ -5065,13 +5100,41 @@ function routeEdge(input) {
|
|
|
5065
5100
|
code: "routing.obstacle.unavoidable",
|
|
5066
5101
|
message: "No bounded orthogonal route candidate avoided all soft obstacles."
|
|
5067
5102
|
});
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5103
|
+
const finalizedSoftBest = finalizeRoute(
|
|
5104
|
+
bestPoints2,
|
|
5105
|
+
softObstacles,
|
|
5106
|
+
hardObstacles,
|
|
5107
|
+
diagnostics
|
|
5108
|
+
);
|
|
5109
|
+
let softFallback = finalizedSoftBest;
|
|
5110
|
+
if (bestRejectedPath !== void 0) {
|
|
5111
|
+
const finalizedRejected = finalizeRoute(
|
|
5112
|
+
bestRejectedPath,
|
|
5071
5113
|
softObstacles,
|
|
5072
5114
|
hardObstacles,
|
|
5073
5115
|
diagnostics
|
|
5074
|
-
)
|
|
5116
|
+
);
|
|
5117
|
+
const rejectedCrossings = countObstacleCrossings(
|
|
5118
|
+
finalizedRejected,
|
|
5119
|
+
softObstacles
|
|
5120
|
+
);
|
|
5121
|
+
const heuristicCrossings = countObstacleCrossings(
|
|
5122
|
+
finalizedSoftBest,
|
|
5123
|
+
softObstacles
|
|
5124
|
+
);
|
|
5125
|
+
if (rejectedCrossings < heuristicCrossings) {
|
|
5126
|
+
softFallback = finalizedRejected;
|
|
5127
|
+
}
|
|
5128
|
+
}
|
|
5129
|
+
checkBacktracking(
|
|
5130
|
+
softFallback,
|
|
5131
|
+
softFallback[0],
|
|
5132
|
+
softFallback[softFallback.length - 1],
|
|
5133
|
+
diagnostics,
|
|
5134
|
+
input.maxBacktrackingRatio
|
|
5135
|
+
);
|
|
5136
|
+
return {
|
|
5137
|
+
points: softFallback,
|
|
5075
5138
|
diagnostics
|
|
5076
5139
|
};
|
|
5077
5140
|
}
|
|
@@ -5103,6 +5166,22 @@ function routeEdge(input) {
|
|
|
5103
5166
|
maxAttempts
|
|
5104
5167
|
);
|
|
5105
5168
|
}
|
|
5169
|
+
if (bestRejectedPath !== void 0) {
|
|
5170
|
+
diagnostics.push({
|
|
5171
|
+
severity: "warning",
|
|
5172
|
+
code: "routing.obstacle.unavoidable",
|
|
5173
|
+
message: "Using A* route with minor soft-obstacle crossings to avoid hard evidence obstacles."
|
|
5174
|
+
});
|
|
5175
|
+
return {
|
|
5176
|
+
points: finalizeRoute(
|
|
5177
|
+
bestRejectedPath,
|
|
5178
|
+
softObstacles,
|
|
5179
|
+
hardObstacles,
|
|
5180
|
+
diagnostics
|
|
5181
|
+
),
|
|
5182
|
+
diagnostics
|
|
5183
|
+
};
|
|
5184
|
+
}
|
|
5106
5185
|
diagnostics.push({
|
|
5107
5186
|
severity: "error",
|
|
5108
5187
|
code: "routing.evidence.crossing_forbidden",
|
|
@@ -5150,13 +5229,41 @@ function routeEdge(input) {
|
|
|
5150
5229
|
code: "routing.obstacle.unavoidable",
|
|
5151
5230
|
message: "No bounded orthogonal route candidate avoided all obstacles."
|
|
5152
5231
|
});
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5232
|
+
const finalizedBestPoints = finalizeRoute(
|
|
5233
|
+
bestPoints,
|
|
5234
|
+
softObstacles,
|
|
5235
|
+
hardObstacles,
|
|
5236
|
+
diagnostics
|
|
5237
|
+
);
|
|
5238
|
+
let fallbackPoints = finalizedBestPoints;
|
|
5239
|
+
if (bestRejectedPath !== void 0) {
|
|
5240
|
+
const finalizedRejected = finalizeRoute(
|
|
5241
|
+
bestRejectedPath,
|
|
5156
5242
|
softObstacles,
|
|
5157
5243
|
hardObstacles,
|
|
5158
5244
|
diagnostics
|
|
5159
|
-
)
|
|
5245
|
+
);
|
|
5246
|
+
const rejectedCrossings = countObstacleCrossings(
|
|
5247
|
+
finalizedRejected,
|
|
5248
|
+
softObstacles
|
|
5249
|
+
);
|
|
5250
|
+
const heuristicCrossings = countObstacleCrossings(
|
|
5251
|
+
finalizedBestPoints,
|
|
5252
|
+
softObstacles
|
|
5253
|
+
);
|
|
5254
|
+
if (rejectedCrossings < heuristicCrossings) {
|
|
5255
|
+
fallbackPoints = finalizedRejected;
|
|
5256
|
+
}
|
|
5257
|
+
}
|
|
5258
|
+
checkBacktracking(
|
|
5259
|
+
fallbackPoints,
|
|
5260
|
+
fallbackPoints[0],
|
|
5261
|
+
fallbackPoints[fallbackPoints.length - 1],
|
|
5262
|
+
diagnostics,
|
|
5263
|
+
input.maxBacktrackingRatio
|
|
5264
|
+
);
|
|
5265
|
+
return {
|
|
5266
|
+
points: fallbackPoints,
|
|
5160
5267
|
diagnostics
|
|
5161
5268
|
};
|
|
5162
5269
|
}
|
|
@@ -5655,6 +5762,24 @@ function routeIntersectsObstacles(points, obstacles, spatialIndex) {
|
|
|
5655
5762
|
}
|
|
5656
5763
|
return false;
|
|
5657
5764
|
}
|
|
5765
|
+
function countObstacleCrossings(points, obstacles) {
|
|
5766
|
+
let count = 0;
|
|
5767
|
+
for (const obstacle of obstacles) {
|
|
5768
|
+
validateBox(obstacle);
|
|
5769
|
+
for (let pointIndex = 0; pointIndex < points.length - 1; pointIndex += 1) {
|
|
5770
|
+
const a = points[pointIndex];
|
|
5771
|
+
const b = points[pointIndex + 1];
|
|
5772
|
+
if (a === void 0 || b === void 0) {
|
|
5773
|
+
continue;
|
|
5774
|
+
}
|
|
5775
|
+
if (intersectsAabb(segmentBox2(a, b), obstacle)) {
|
|
5776
|
+
count += 1;
|
|
5777
|
+
break;
|
|
5778
|
+
}
|
|
5779
|
+
}
|
|
5780
|
+
}
|
|
5781
|
+
return count;
|
|
5782
|
+
}
|
|
5658
5783
|
function routeIntersectsEndpointInteriors(points, endpointInteriors) {
|
|
5659
5784
|
for (let index = 0; index < points.length - 1; index += 1) {
|
|
5660
5785
|
const a = points[index];
|
|
@@ -5889,7 +6014,8 @@ function solveDiagram(diagram, options = {}) {
|
|
|
5889
6014
|
constrained.boxes,
|
|
5890
6015
|
constrained.locks,
|
|
5891
6016
|
options?.overlapSpacing ?? 40,
|
|
5892
|
-
Math.max(0, options?.minLaneGutter ?? 0)
|
|
6017
|
+
Math.max(0, options?.minLaneGutter ?? 0),
|
|
6018
|
+
options.distributeContainedChildren ?? true
|
|
5893
6019
|
);
|
|
5894
6020
|
removeResolvedOverlapDiagnostics(diagnostics, constrained.boxes);
|
|
5895
6021
|
diagnostics.push(...swimlaneContracts.diagnostics);
|
|
@@ -6056,7 +6182,8 @@ function solveDiagram(diagram, options = {}) {
|
|
|
6056
6182
|
diagram.direction,
|
|
6057
6183
|
options,
|
|
6058
6184
|
diagnostics,
|
|
6059
|
-
coordinatedGroups
|
|
6185
|
+
coordinatedGroups,
|
|
6186
|
+
contentBounds
|
|
6060
6187
|
);
|
|
6061
6188
|
const edgeTextAnnotations = coordinateEdgeTextAnnotations(
|
|
6062
6189
|
coordinatedEdges,
|
|
@@ -6475,7 +6602,7 @@ function reportCjkTypographyDiagnostics(path, typography, previousStyle, diagnos
|
|
|
6475
6602
|
function containsCjk(value) {
|
|
6476
6603
|
return /[\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]/u.test(value);
|
|
6477
6604
|
}
|
|
6478
|
-
function applySwimlaneLayoutContracts(swimlanes, constraints, edges, topToBottomFlow, nodeBoxes, locks, overlapSpacing, laneGutter) {
|
|
6605
|
+
function applySwimlaneLayoutContracts(swimlanes, constraints, edges, topToBottomFlow, nodeBoxes, locks, overlapSpacing, laneGutter, distributeContainedChildren) {
|
|
6479
6606
|
const layouts = /* @__PURE__ */ new Map();
|
|
6480
6607
|
const diagnostics = [];
|
|
6481
6608
|
const movedChildIds = /* @__PURE__ */ new Set();
|
|
@@ -6494,7 +6621,9 @@ function applySwimlaneLayoutContracts(swimlanes, constraints, edges, topToBottom
|
|
|
6494
6621
|
locks,
|
|
6495
6622
|
diagnostics,
|
|
6496
6623
|
movedChildIds,
|
|
6497
|
-
laneGutter
|
|
6624
|
+
laneGutter,
|
|
6625
|
+
constraints,
|
|
6626
|
+
distributeContainedChildren
|
|
6498
6627
|
);
|
|
6499
6628
|
if (layout2 !== void 0) {
|
|
6500
6629
|
layouts.set(swimlane.id, layout2);
|
|
@@ -6686,7 +6815,7 @@ function isStackRunaway(boxes, nodes, direction, options) {
|
|
|
6686
6815
|
const maxWidth = Math.max(...nodeBoxes.map((box) => box.width));
|
|
6687
6816
|
return xSpread <= Math.max(maxWidth, options.overlapSpacing ?? 40);
|
|
6688
6817
|
}
|
|
6689
|
-
function applySingleSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes, locks, diagnostics, movedChildIds, laneGutter) {
|
|
6818
|
+
function applySingleSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes, locks, diagnostics, movedChildIds, laneGutter, constraints, distributeContainedChildren) {
|
|
6690
6819
|
const headerHeight = swimlane.headerHeight ?? 28;
|
|
6691
6820
|
const padding = swimlane.padding ?? 16;
|
|
6692
6821
|
const laneBounds = swimlane.lanes.map((lane) => {
|
|
@@ -6711,7 +6840,9 @@ function applySingleSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes
|
|
|
6711
6840
|
locks,
|
|
6712
6841
|
diagnostics,
|
|
6713
6842
|
movedChildIds,
|
|
6714
|
-
laneGutter
|
|
6843
|
+
laneGutter,
|
|
6844
|
+
constraints,
|
|
6845
|
+
distributeContainedChildren
|
|
6715
6846
|
);
|
|
6716
6847
|
}
|
|
6717
6848
|
return applyHorizontalSwimlaneContract(
|
|
@@ -6726,13 +6857,29 @@ function applySingleSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes
|
|
|
6726
6857
|
laneGutter
|
|
6727
6858
|
);
|
|
6728
6859
|
}
|
|
6729
|
-
function applyVerticalSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes, laneBounds, headerHeight, padding, locks, diagnostics, movedChildIds, laneGutter) {
|
|
6860
|
+
function applyVerticalSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes, laneBounds, headerHeight, padding, locks, diagnostics, movedChildIds, laneGutter, constraints, distributeContainedChildren) {
|
|
6730
6861
|
const populatedBounds = laneBounds.filter(
|
|
6731
6862
|
(box) => box !== void 0
|
|
6732
6863
|
);
|
|
6733
6864
|
const top = Math.min(...populatedBounds.map((box) => box.y));
|
|
6734
6865
|
const left = Math.min(...populatedBounds.map((box) => box.x));
|
|
6735
6866
|
const maxChildHeight = Math.max(...populatedBounds.map((box) => box.height));
|
|
6867
|
+
const containedChildIds = /* @__PURE__ */ new Set();
|
|
6868
|
+
if (distributeContainedChildren) {
|
|
6869
|
+
for (const c of constraints) {
|
|
6870
|
+
if (c.kind !== "containment") continue;
|
|
6871
|
+
if (nodeBoxes.get(c.containerId) === void 0) continue;
|
|
6872
|
+
const distributable = c.childIds.filter((childId) => {
|
|
6873
|
+
if (nodeBoxes.get(childId) === void 0) return false;
|
|
6874
|
+
const lock = locks.get(childId);
|
|
6875
|
+
return lock === void 0 || lock.source === "fixed-position";
|
|
6876
|
+
});
|
|
6877
|
+
if (distributable.length < 2) continue;
|
|
6878
|
+
for (const childId of distributable) {
|
|
6879
|
+
containedChildIds.add(childId);
|
|
6880
|
+
}
|
|
6881
|
+
}
|
|
6882
|
+
}
|
|
6736
6883
|
const flowRanks = topToBottomFlow ? rankVerticalSwimlaneChildren(swimlane, edges) : /* @__PURE__ */ new Map();
|
|
6737
6884
|
const maxRank = flowRanks.size === 0 ? 0 : Math.max(...Array.from(flowRanks.values()));
|
|
6738
6885
|
const rankStackGap = Math.max(8, padding / 2);
|
|
@@ -6749,7 +6896,8 @@ function applyVerticalSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBox
|
|
|
6749
6896
|
nodeBoxes,
|
|
6750
6897
|
flowRanks,
|
|
6751
6898
|
locks,
|
|
6752
|
-
rankStackGap
|
|
6899
|
+
rankStackGap,
|
|
6900
|
+
containedChildIds
|
|
6753
6901
|
);
|
|
6754
6902
|
const slotWidth = Math.max(
|
|
6755
6903
|
Math.max(...populatedBounds.map((box) => box.width)),
|
|
@@ -6771,7 +6919,10 @@ function applyVerticalSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBox
|
|
|
6771
6919
|
const distributable = lane.children.filter(
|
|
6772
6920
|
(childId) => !locks.has(childId)
|
|
6773
6921
|
);
|
|
6774
|
-
|
|
6922
|
+
const coveredByContainment = lane.children.some(
|
|
6923
|
+
(childId) => containedChildIds.has(childId)
|
|
6924
|
+
);
|
|
6925
|
+
if (!coveredByContainment && distributable.length >= CROSS_AXIS_SPREAD_THRESHOLD) {
|
|
6775
6926
|
moveRankedVerticalLaneChildren(
|
|
6776
6927
|
lane.children,
|
|
6777
6928
|
nodeBoxes,
|
|
@@ -6799,6 +6950,9 @@ function applyVerticalSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBox
|
|
|
6799
6950
|
);
|
|
6800
6951
|
continue;
|
|
6801
6952
|
}
|
|
6953
|
+
const rankedCoveredByContainment = lane.children.some(
|
|
6954
|
+
(childId) => containedChildIds.has(childId)
|
|
6955
|
+
);
|
|
6802
6956
|
moveRankedVerticalLaneChildren(
|
|
6803
6957
|
lane.children,
|
|
6804
6958
|
nodeBoxes,
|
|
@@ -6809,7 +6963,8 @@ function applyVerticalSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBox
|
|
|
6809
6963
|
rankSpacing,
|
|
6810
6964
|
rankStackGap,
|
|
6811
6965
|
{ x: target.x, y: laneContentTop },
|
|
6812
|
-
slotWidth - padding * 2
|
|
6966
|
+
slotWidth - padding * 2,
|
|
6967
|
+
rankedCoveredByContainment
|
|
6813
6968
|
);
|
|
6814
6969
|
}
|
|
6815
6970
|
return {
|
|
@@ -6925,9 +7080,12 @@ function crossAxisSpreadWidth(items, gap) {
|
|
|
6925
7080
|
0
|
|
6926
7081
|
);
|
|
6927
7082
|
}
|
|
6928
|
-
function maxCrossAxisSpreadWidth(swimlane, nodeBoxes, flowRanks, locks, gap) {
|
|
7083
|
+
function maxCrossAxisSpreadWidth(swimlane, nodeBoxes, flowRanks, locks, gap, containedChildIds) {
|
|
6929
7084
|
let maxWidth = 0;
|
|
6930
7085
|
for (const lane of swimlane.lanes) {
|
|
7086
|
+
if (containedChildIds !== void 0 && lane.children.some((childId) => containedChildIds.has(childId))) {
|
|
7087
|
+
continue;
|
|
7088
|
+
}
|
|
6931
7089
|
for (const stack of rankStacks(
|
|
6932
7090
|
lane.children,
|
|
6933
7091
|
nodeBoxes,
|
|
@@ -6940,7 +7098,7 @@ function maxCrossAxisSpreadWidth(swimlane, nodeBoxes, flowRanks, locks, gap) {
|
|
|
6940
7098
|
}
|
|
6941
7099
|
return maxWidth;
|
|
6942
7100
|
}
|
|
6943
|
-
function moveRankedVerticalLaneChildren(childIds, nodeBoxes, locks, diagnostics, movedChildIds, flowRanks, rankSpacing, rankStackGap, target, contentWidth) {
|
|
7101
|
+
function moveRankedVerticalLaneChildren(childIds, nodeBoxes, locks, diagnostics, movedChildIds, flowRanks, rankSpacing, rankStackGap, target, contentWidth, suppressSpread) {
|
|
6944
7102
|
for (const [rank, stack] of rankStacks(childIds, nodeBoxes, flowRanks)) {
|
|
6945
7103
|
const unlocked = [];
|
|
6946
7104
|
for (const item of stack) {
|
|
@@ -6969,7 +7127,7 @@ function moveRankedVerticalLaneChildren(childIds, nodeBoxes, locks, diagnostics,
|
|
|
6969
7127
|
}
|
|
6970
7128
|
nodeBoxes.set(childId, next);
|
|
6971
7129
|
} else {
|
|
6972
|
-
const shouldSpread = unlocked.length >= CROSS_AXIS_SPREAD_THRESHOLD;
|
|
7130
|
+
const shouldSpread = !suppressSpread && unlocked.length >= CROSS_AXIS_SPREAD_THRESHOLD;
|
|
6973
7131
|
if (!shouldSpread) {
|
|
6974
7132
|
let yOffset = 0;
|
|
6975
7133
|
for (const { childId, box } of unlocked) {
|
|
@@ -8098,14 +8256,21 @@ function evidenceOverlapDiagnostic(block, conflict) {
|
|
|
8098
8256
|
}
|
|
8099
8257
|
};
|
|
8100
8258
|
}
|
|
8101
|
-
function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacles, textObstacles, hardObstacles, direction, options, diagnostics, groups) {
|
|
8259
|
+
function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacles, textObstacles, hardObstacles, direction, options, diagnostics, groups, contentBounds) {
|
|
8102
8260
|
const coordinated = [];
|
|
8103
8261
|
const coordinatedNodeById = new Map(
|
|
8104
8262
|
coordinatedNodes.map((node) => [node.id, node])
|
|
8105
8263
|
);
|
|
8264
|
+
const corridorMarginOption = options.corridorMargin ?? "auto";
|
|
8265
|
+
const corridorMargin = typeof corridorMarginOption === "number" ? corridorMarginOption : Math.max(
|
|
8266
|
+
200,
|
|
8267
|
+
Math.hypot(contentBounds.width, contentBounds.height) * 0.3
|
|
8268
|
+
);
|
|
8269
|
+
const routingGutter = options.routingGutter ?? 160;
|
|
8270
|
+
const queryGutter = (options.routeKind ?? "orthogonal") === "obstacle-avoiding" ? Math.max(routingGutter, corridorMargin) : routingGutter;
|
|
8106
8271
|
const nodeObstacleIndex = createBoxSpatialIndex(
|
|
8107
8272
|
obstacles.map((box, index) => ({ id: `node-obstacle:${index}`, box })),
|
|
8108
|
-
|
|
8273
|
+
queryGutter
|
|
8109
8274
|
);
|
|
8110
8275
|
for (const edge of edges) {
|
|
8111
8276
|
const source = nodes.get(edge.source.nodeId);
|
|
@@ -8127,11 +8292,7 @@ function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacle
|
|
|
8127
8292
|
const sourcePort = coordinatedNodeById.get(edge.source.nodeId)?.ports?.find((port) => port.id === edge.source.portId);
|
|
8128
8293
|
const targetPort = coordinatedNodeById.get(edge.target.nodeId)?.ports?.find((port) => port.id === edge.target.portId);
|
|
8129
8294
|
const routeTextObstacles = textObstacles.filter((annotation) => !isEdgeConnectedTextAnnotation(edge, annotation)).map((annotation) => annotation.box);
|
|
8130
|
-
const corridor = edgeCorridorBox(
|
|
8131
|
-
source.box,
|
|
8132
|
-
target.box,
|
|
8133
|
-
options.routingGutter ?? 160
|
|
8134
|
-
);
|
|
8295
|
+
const corridor = edgeCorridorBox(source.box, target.box, queryGutter);
|
|
8135
8296
|
const routeNodeObstacles = queryBoxSpatialIndex(nodeObstacleIndex, corridor).map((entry) => entry.box).filter(
|
|
8136
8297
|
(obstacle) => !sameBox(obstacle, source.obstacleBox) && !sameBox(obstacle, target.obstacleBox)
|
|
8137
8298
|
);
|
|
@@ -8149,7 +8310,9 @@ function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacle
|
|
|
8149
8310
|
...routeTextObstacles
|
|
8150
8311
|
],
|
|
8151
8312
|
hardObstacles,
|
|
8152
|
-
|
|
8313
|
+
corridorMargin,
|
|
8314
|
+
...options.maxRoutingAttempts === void 0 ? {} : { maxRoutingAttempts: options.maxRoutingAttempts },
|
|
8315
|
+
...options.maxBacktrackingRatio === void 0 ? {} : { maxBacktrackingRatio: options.maxBacktrackingRatio }
|
|
8153
8316
|
});
|
|
8154
8317
|
diagnostics.push(
|
|
8155
8318
|
...route.diagnostics.map((diagnostic) => ({
|