@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.js
CHANGED
|
@@ -4737,7 +4737,7 @@ function segmentCrossesAnyObstacle(a, b, obstacles) {
|
|
|
4737
4737
|
}
|
|
4738
4738
|
|
|
4739
4739
|
// src/routing/routes.ts
|
|
4740
|
-
function checkBacktracking(points, source, target, diagnostics) {
|
|
4740
|
+
function checkBacktracking(points, source, target, diagnostics, maxRatio) {
|
|
4741
4741
|
if (points.length < 2) return;
|
|
4742
4742
|
const direct = Math.hypot(target.x - source.x, target.y - source.y);
|
|
4743
4743
|
if (direct <= 0) return;
|
|
@@ -4747,7 +4747,7 @@ function checkBacktracking(points, source, target, diagnostics) {
|
|
|
4747
4747
|
const b = points[i + 1];
|
|
4748
4748
|
routeLen += Math.hypot(b.x - a.x, b.y - a.y);
|
|
4749
4749
|
}
|
|
4750
|
-
const threshold =
|
|
4750
|
+
const threshold = maxRatio ?? 20;
|
|
4751
4751
|
if (routeLen > direct * threshold) {
|
|
4752
4752
|
diagnostics.push({
|
|
4753
4753
|
severity: "warning",
|
|
@@ -4765,8 +4765,20 @@ function routeEdge(input) {
|
|
|
4765
4765
|
const diagnostics = [];
|
|
4766
4766
|
const softObstacles = input.obstacles ?? [];
|
|
4767
4767
|
const hardObstacles = input.hardObstacles ?? [];
|
|
4768
|
+
let bestRejectedPath;
|
|
4769
|
+
let bestRejectedCrossings = Number.POSITIVE_INFINITY;
|
|
4768
4770
|
const softObstacleIndex = input.obstacleIndex ?? createBoxSpatialIndex(indexedBoxes(softObstacles));
|
|
4769
4771
|
const hardObstacleIndex = input.hardObstacleIndex ?? createBoxSpatialIndex(indexedBoxes(hardObstacles));
|
|
4772
|
+
const recordRejected = (candidate) => {
|
|
4773
|
+
if (routeIntersectsObstacles(candidate, hardObstacles, hardObstacleIndex)) {
|
|
4774
|
+
return;
|
|
4775
|
+
}
|
|
4776
|
+
const crossings = countObstacleCrossings(candidate, softObstacles);
|
|
4777
|
+
if (crossings < bestRejectedCrossings) {
|
|
4778
|
+
bestRejectedCrossings = crossings;
|
|
4779
|
+
bestRejectedPath = candidate;
|
|
4780
|
+
}
|
|
4781
|
+
};
|
|
4770
4782
|
const maxAttempts = input.maxRoutingAttempts ?? 5;
|
|
4771
4783
|
const defaultAnchors = defaultAnchorsForGeometry(
|
|
4772
4784
|
input.source.box,
|
|
@@ -4826,13 +4838,14 @@ function routeEdge(input) {
|
|
|
4826
4838
|
targetAnchor
|
|
4827
4839
|
);
|
|
4828
4840
|
const allObstacles = [...softObstacles, ...hardObstacles];
|
|
4841
|
+
const corridorMargin = input.corridorMargin ?? 32;
|
|
4829
4842
|
const corridorObstacles = filterObstaclesByCorridor(
|
|
4830
4843
|
source,
|
|
4831
4844
|
target,
|
|
4832
4845
|
allObstacles,
|
|
4833
4846
|
[],
|
|
4834
4847
|
// endpointObstacles passed separately via options
|
|
4835
|
-
|
|
4848
|
+
corridorMargin
|
|
4836
4849
|
);
|
|
4837
4850
|
const cornerObstacles = corridorObstacles.length === 0 && allObstacles.length > 0 ? allObstacles : corridorObstacles;
|
|
4838
4851
|
let cornerPath = findCornerGraphPath(
|
|
@@ -4855,7 +4868,7 @@ function routeEdge(input) {
|
|
|
4855
4868
|
source,
|
|
4856
4869
|
target,
|
|
4857
4870
|
allObstacles,
|
|
4858
|
-
{ endpointObstacles, margin: 0 },
|
|
4871
|
+
{ endpointObstacles, margin: 0, corridorMargin },
|
|
4859
4872
|
diagnostics
|
|
4860
4873
|
);
|
|
4861
4874
|
if (path !== null && path.length >= 2) {
|
|
@@ -4872,9 +4885,16 @@ function routeEdge(input) {
|
|
|
4872
4885
|
softObstacles,
|
|
4873
4886
|
softObstacleIndex
|
|
4874
4887
|
) && !routeIntersectsObstacles(finalized, hardObstacles, hardObstacleIndex)) {
|
|
4875
|
-
checkBacktracking(
|
|
4888
|
+
checkBacktracking(
|
|
4889
|
+
finalized,
|
|
4890
|
+
source,
|
|
4891
|
+
target,
|
|
4892
|
+
diagnostics,
|
|
4893
|
+
input.maxBacktrackingRatio
|
|
4894
|
+
);
|
|
4876
4895
|
return { points: finalized, diagnostics };
|
|
4877
4896
|
}
|
|
4897
|
+
recordRejected(finalized);
|
|
4878
4898
|
if (cornerPath !== null) {
|
|
4879
4899
|
const fullCornerPath = cornerObstacles.length < allObstacles.length ? findCornerGraphPath(
|
|
4880
4900
|
source,
|
|
@@ -4901,15 +4921,22 @@ function routeEdge(input) {
|
|
|
4901
4921
|
hardObstacles,
|
|
4902
4922
|
hardObstacleIndex
|
|
4903
4923
|
)) {
|
|
4904
|
-
checkBacktracking(
|
|
4924
|
+
checkBacktracking(
|
|
4925
|
+
fullFinalized,
|
|
4926
|
+
source,
|
|
4927
|
+
target,
|
|
4928
|
+
diagnostics,
|
|
4929
|
+
input.maxBacktrackingRatio
|
|
4930
|
+
);
|
|
4905
4931
|
return { points: fullFinalized, diagnostics };
|
|
4906
4932
|
}
|
|
4933
|
+
recordRejected(fullFinalized);
|
|
4907
4934
|
}
|
|
4908
4935
|
const gridPath = findObstacleFreePath(
|
|
4909
4936
|
source,
|
|
4910
4937
|
target,
|
|
4911
4938
|
allObstacles,
|
|
4912
|
-
{ endpointObstacles, margin: 0 },
|
|
4939
|
+
{ endpointObstacles, margin: 0, corridorMargin },
|
|
4913
4940
|
diagnostics
|
|
4914
4941
|
);
|
|
4915
4942
|
if (gridPath !== null && gridPath.length >= 2) {
|
|
@@ -4930,9 +4957,16 @@ function routeEdge(input) {
|
|
|
4930
4957
|
hardObstacles,
|
|
4931
4958
|
hardObstacleIndex
|
|
4932
4959
|
)) {
|
|
4933
|
-
checkBacktracking(
|
|
4960
|
+
checkBacktracking(
|
|
4961
|
+
gridFinalized,
|
|
4962
|
+
source,
|
|
4963
|
+
target,
|
|
4964
|
+
diagnostics,
|
|
4965
|
+
input.maxBacktrackingRatio
|
|
4966
|
+
);
|
|
4934
4967
|
return { points: gridFinalized, diagnostics };
|
|
4935
4968
|
}
|
|
4969
|
+
recordRejected(gridFinalized);
|
|
4936
4970
|
}
|
|
4937
4971
|
}
|
|
4938
4972
|
}
|
|
@@ -4996,7 +5030,8 @@ function routeEdge(input) {
|
|
|
4996
5030
|
finalizedClean,
|
|
4997
5031
|
candidate.points[0],
|
|
4998
5032
|
candidate.points[candidate.points.length - 1],
|
|
4999
|
-
diagnostics
|
|
5033
|
+
diagnostics,
|
|
5034
|
+
input.maxBacktrackingRatio
|
|
5000
5035
|
);
|
|
5001
5036
|
return { points: finalizedClean, diagnostics };
|
|
5002
5037
|
}
|
|
@@ -5062,13 +5097,41 @@ function routeEdge(input) {
|
|
|
5062
5097
|
code: "routing.obstacle.unavoidable",
|
|
5063
5098
|
message: "No bounded orthogonal route candidate avoided all soft obstacles."
|
|
5064
5099
|
});
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5100
|
+
const finalizedSoftBest = finalizeRoute(
|
|
5101
|
+
bestPoints2,
|
|
5102
|
+
softObstacles,
|
|
5103
|
+
hardObstacles,
|
|
5104
|
+
diagnostics
|
|
5105
|
+
);
|
|
5106
|
+
let softFallback = finalizedSoftBest;
|
|
5107
|
+
if (bestRejectedPath !== void 0) {
|
|
5108
|
+
const finalizedRejected = finalizeRoute(
|
|
5109
|
+
bestRejectedPath,
|
|
5068
5110
|
softObstacles,
|
|
5069
5111
|
hardObstacles,
|
|
5070
5112
|
diagnostics
|
|
5071
|
-
)
|
|
5113
|
+
);
|
|
5114
|
+
const rejectedCrossings = countObstacleCrossings(
|
|
5115
|
+
finalizedRejected,
|
|
5116
|
+
softObstacles
|
|
5117
|
+
);
|
|
5118
|
+
const heuristicCrossings = countObstacleCrossings(
|
|
5119
|
+
finalizedSoftBest,
|
|
5120
|
+
softObstacles
|
|
5121
|
+
);
|
|
5122
|
+
if (rejectedCrossings < heuristicCrossings) {
|
|
5123
|
+
softFallback = finalizedRejected;
|
|
5124
|
+
}
|
|
5125
|
+
}
|
|
5126
|
+
checkBacktracking(
|
|
5127
|
+
softFallback,
|
|
5128
|
+
softFallback[0],
|
|
5129
|
+
softFallback[softFallback.length - 1],
|
|
5130
|
+
diagnostics,
|
|
5131
|
+
input.maxBacktrackingRatio
|
|
5132
|
+
);
|
|
5133
|
+
return {
|
|
5134
|
+
points: softFallback,
|
|
5072
5135
|
diagnostics
|
|
5073
5136
|
};
|
|
5074
5137
|
}
|
|
@@ -5100,6 +5163,22 @@ function routeEdge(input) {
|
|
|
5100
5163
|
maxAttempts
|
|
5101
5164
|
);
|
|
5102
5165
|
}
|
|
5166
|
+
if (bestRejectedPath !== void 0) {
|
|
5167
|
+
diagnostics.push({
|
|
5168
|
+
severity: "warning",
|
|
5169
|
+
code: "routing.obstacle.unavoidable",
|
|
5170
|
+
message: "Using A* route with minor soft-obstacle crossings to avoid hard evidence obstacles."
|
|
5171
|
+
});
|
|
5172
|
+
return {
|
|
5173
|
+
points: finalizeRoute(
|
|
5174
|
+
bestRejectedPath,
|
|
5175
|
+
softObstacles,
|
|
5176
|
+
hardObstacles,
|
|
5177
|
+
diagnostics
|
|
5178
|
+
),
|
|
5179
|
+
diagnostics
|
|
5180
|
+
};
|
|
5181
|
+
}
|
|
5103
5182
|
diagnostics.push({
|
|
5104
5183
|
severity: "error",
|
|
5105
5184
|
code: "routing.evidence.crossing_forbidden",
|
|
@@ -5147,13 +5226,41 @@ function routeEdge(input) {
|
|
|
5147
5226
|
code: "routing.obstacle.unavoidable",
|
|
5148
5227
|
message: "No bounded orthogonal route candidate avoided all obstacles."
|
|
5149
5228
|
});
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5229
|
+
const finalizedBestPoints = finalizeRoute(
|
|
5230
|
+
bestPoints,
|
|
5231
|
+
softObstacles,
|
|
5232
|
+
hardObstacles,
|
|
5233
|
+
diagnostics
|
|
5234
|
+
);
|
|
5235
|
+
let fallbackPoints = finalizedBestPoints;
|
|
5236
|
+
if (bestRejectedPath !== void 0) {
|
|
5237
|
+
const finalizedRejected = finalizeRoute(
|
|
5238
|
+
bestRejectedPath,
|
|
5153
5239
|
softObstacles,
|
|
5154
5240
|
hardObstacles,
|
|
5155
5241
|
diagnostics
|
|
5156
|
-
)
|
|
5242
|
+
);
|
|
5243
|
+
const rejectedCrossings = countObstacleCrossings(
|
|
5244
|
+
finalizedRejected,
|
|
5245
|
+
softObstacles
|
|
5246
|
+
);
|
|
5247
|
+
const heuristicCrossings = countObstacleCrossings(
|
|
5248
|
+
finalizedBestPoints,
|
|
5249
|
+
softObstacles
|
|
5250
|
+
);
|
|
5251
|
+
if (rejectedCrossings < heuristicCrossings) {
|
|
5252
|
+
fallbackPoints = finalizedRejected;
|
|
5253
|
+
}
|
|
5254
|
+
}
|
|
5255
|
+
checkBacktracking(
|
|
5256
|
+
fallbackPoints,
|
|
5257
|
+
fallbackPoints[0],
|
|
5258
|
+
fallbackPoints[fallbackPoints.length - 1],
|
|
5259
|
+
diagnostics,
|
|
5260
|
+
input.maxBacktrackingRatio
|
|
5261
|
+
);
|
|
5262
|
+
return {
|
|
5263
|
+
points: fallbackPoints,
|
|
5157
5264
|
diagnostics
|
|
5158
5265
|
};
|
|
5159
5266
|
}
|
|
@@ -5652,6 +5759,24 @@ function routeIntersectsObstacles(points, obstacles, spatialIndex) {
|
|
|
5652
5759
|
}
|
|
5653
5760
|
return false;
|
|
5654
5761
|
}
|
|
5762
|
+
function countObstacleCrossings(points, obstacles) {
|
|
5763
|
+
let count = 0;
|
|
5764
|
+
for (const obstacle of obstacles) {
|
|
5765
|
+
validateBox(obstacle);
|
|
5766
|
+
for (let pointIndex = 0; pointIndex < points.length - 1; pointIndex += 1) {
|
|
5767
|
+
const a = points[pointIndex];
|
|
5768
|
+
const b = points[pointIndex + 1];
|
|
5769
|
+
if (a === void 0 || b === void 0) {
|
|
5770
|
+
continue;
|
|
5771
|
+
}
|
|
5772
|
+
if (intersectsAabb(segmentBox2(a, b), obstacle)) {
|
|
5773
|
+
count += 1;
|
|
5774
|
+
break;
|
|
5775
|
+
}
|
|
5776
|
+
}
|
|
5777
|
+
}
|
|
5778
|
+
return count;
|
|
5779
|
+
}
|
|
5655
5780
|
function routeIntersectsEndpointInteriors(points, endpointInteriors) {
|
|
5656
5781
|
for (let index = 0; index < points.length - 1; index += 1) {
|
|
5657
5782
|
const a = points[index];
|
|
@@ -5886,7 +6011,8 @@ function solveDiagram(diagram, options = {}) {
|
|
|
5886
6011
|
constrained.boxes,
|
|
5887
6012
|
constrained.locks,
|
|
5888
6013
|
options?.overlapSpacing ?? 40,
|
|
5889
|
-
Math.max(0, options?.minLaneGutter ?? 0)
|
|
6014
|
+
Math.max(0, options?.minLaneGutter ?? 0),
|
|
6015
|
+
options.distributeContainedChildren ?? true
|
|
5890
6016
|
);
|
|
5891
6017
|
removeResolvedOverlapDiagnostics(diagnostics, constrained.boxes);
|
|
5892
6018
|
diagnostics.push(...swimlaneContracts.diagnostics);
|
|
@@ -6053,7 +6179,8 @@ function solveDiagram(diagram, options = {}) {
|
|
|
6053
6179
|
diagram.direction,
|
|
6054
6180
|
options,
|
|
6055
6181
|
diagnostics,
|
|
6056
|
-
coordinatedGroups
|
|
6182
|
+
coordinatedGroups,
|
|
6183
|
+
contentBounds
|
|
6057
6184
|
);
|
|
6058
6185
|
const edgeTextAnnotations = coordinateEdgeTextAnnotations(
|
|
6059
6186
|
coordinatedEdges,
|
|
@@ -6472,7 +6599,7 @@ function reportCjkTypographyDiagnostics(path, typography, previousStyle, diagnos
|
|
|
6472
6599
|
function containsCjk(value) {
|
|
6473
6600
|
return /[\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]/u.test(value);
|
|
6474
6601
|
}
|
|
6475
|
-
function applySwimlaneLayoutContracts(swimlanes, constraints, edges, topToBottomFlow, nodeBoxes, locks, overlapSpacing, laneGutter) {
|
|
6602
|
+
function applySwimlaneLayoutContracts(swimlanes, constraints, edges, topToBottomFlow, nodeBoxes, locks, overlapSpacing, laneGutter, distributeContainedChildren) {
|
|
6476
6603
|
const layouts = /* @__PURE__ */ new Map();
|
|
6477
6604
|
const diagnostics = [];
|
|
6478
6605
|
const movedChildIds = /* @__PURE__ */ new Set();
|
|
@@ -6491,7 +6618,9 @@ function applySwimlaneLayoutContracts(swimlanes, constraints, edges, topToBottom
|
|
|
6491
6618
|
locks,
|
|
6492
6619
|
diagnostics,
|
|
6493
6620
|
movedChildIds,
|
|
6494
|
-
laneGutter
|
|
6621
|
+
laneGutter,
|
|
6622
|
+
constraints,
|
|
6623
|
+
distributeContainedChildren
|
|
6495
6624
|
);
|
|
6496
6625
|
if (layout2 !== void 0) {
|
|
6497
6626
|
layouts.set(swimlane.id, layout2);
|
|
@@ -6683,7 +6812,7 @@ function isStackRunaway(boxes, nodes, direction, options) {
|
|
|
6683
6812
|
const maxWidth = Math.max(...nodeBoxes.map((box) => box.width));
|
|
6684
6813
|
return xSpread <= Math.max(maxWidth, options.overlapSpacing ?? 40);
|
|
6685
6814
|
}
|
|
6686
|
-
function applySingleSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes, locks, diagnostics, movedChildIds, laneGutter) {
|
|
6815
|
+
function applySingleSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes, locks, diagnostics, movedChildIds, laneGutter, constraints, distributeContainedChildren) {
|
|
6687
6816
|
const headerHeight = swimlane.headerHeight ?? 28;
|
|
6688
6817
|
const padding = swimlane.padding ?? 16;
|
|
6689
6818
|
const laneBounds = swimlane.lanes.map((lane) => {
|
|
@@ -6708,7 +6837,9 @@ function applySingleSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes
|
|
|
6708
6837
|
locks,
|
|
6709
6838
|
diagnostics,
|
|
6710
6839
|
movedChildIds,
|
|
6711
|
-
laneGutter
|
|
6840
|
+
laneGutter,
|
|
6841
|
+
constraints,
|
|
6842
|
+
distributeContainedChildren
|
|
6712
6843
|
);
|
|
6713
6844
|
}
|
|
6714
6845
|
return applyHorizontalSwimlaneContract(
|
|
@@ -6723,13 +6854,29 @@ function applySingleSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes
|
|
|
6723
6854
|
laneGutter
|
|
6724
6855
|
);
|
|
6725
6856
|
}
|
|
6726
|
-
function applyVerticalSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes, laneBounds, headerHeight, padding, locks, diagnostics, movedChildIds, laneGutter) {
|
|
6857
|
+
function applyVerticalSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes, laneBounds, headerHeight, padding, locks, diagnostics, movedChildIds, laneGutter, constraints, distributeContainedChildren) {
|
|
6727
6858
|
const populatedBounds = laneBounds.filter(
|
|
6728
6859
|
(box) => box !== void 0
|
|
6729
6860
|
);
|
|
6730
6861
|
const top = Math.min(...populatedBounds.map((box) => box.y));
|
|
6731
6862
|
const left = Math.min(...populatedBounds.map((box) => box.x));
|
|
6732
6863
|
const maxChildHeight = Math.max(...populatedBounds.map((box) => box.height));
|
|
6864
|
+
const containedChildIds = /* @__PURE__ */ new Set();
|
|
6865
|
+
if (distributeContainedChildren) {
|
|
6866
|
+
for (const c of constraints) {
|
|
6867
|
+
if (c.kind !== "containment") continue;
|
|
6868
|
+
if (nodeBoxes.get(c.containerId) === void 0) continue;
|
|
6869
|
+
const distributable = c.childIds.filter((childId) => {
|
|
6870
|
+
if (nodeBoxes.get(childId) === void 0) return false;
|
|
6871
|
+
const lock = locks.get(childId);
|
|
6872
|
+
return lock === void 0 || lock.source === "fixed-position";
|
|
6873
|
+
});
|
|
6874
|
+
if (distributable.length < 2) continue;
|
|
6875
|
+
for (const childId of distributable) {
|
|
6876
|
+
containedChildIds.add(childId);
|
|
6877
|
+
}
|
|
6878
|
+
}
|
|
6879
|
+
}
|
|
6733
6880
|
const flowRanks = topToBottomFlow ? rankVerticalSwimlaneChildren(swimlane, edges) : /* @__PURE__ */ new Map();
|
|
6734
6881
|
const maxRank = flowRanks.size === 0 ? 0 : Math.max(...Array.from(flowRanks.values()));
|
|
6735
6882
|
const rankStackGap = Math.max(8, padding / 2);
|
|
@@ -6746,7 +6893,8 @@ function applyVerticalSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBox
|
|
|
6746
6893
|
nodeBoxes,
|
|
6747
6894
|
flowRanks,
|
|
6748
6895
|
locks,
|
|
6749
|
-
rankStackGap
|
|
6896
|
+
rankStackGap,
|
|
6897
|
+
containedChildIds
|
|
6750
6898
|
);
|
|
6751
6899
|
const slotWidth = Math.max(
|
|
6752
6900
|
Math.max(...populatedBounds.map((box) => box.width)),
|
|
@@ -6768,7 +6916,10 @@ function applyVerticalSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBox
|
|
|
6768
6916
|
const distributable = lane.children.filter(
|
|
6769
6917
|
(childId) => !locks.has(childId)
|
|
6770
6918
|
);
|
|
6771
|
-
|
|
6919
|
+
const coveredByContainment = lane.children.some(
|
|
6920
|
+
(childId) => containedChildIds.has(childId)
|
|
6921
|
+
);
|
|
6922
|
+
if (!coveredByContainment && distributable.length >= CROSS_AXIS_SPREAD_THRESHOLD) {
|
|
6772
6923
|
moveRankedVerticalLaneChildren(
|
|
6773
6924
|
lane.children,
|
|
6774
6925
|
nodeBoxes,
|
|
@@ -6796,6 +6947,9 @@ function applyVerticalSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBox
|
|
|
6796
6947
|
);
|
|
6797
6948
|
continue;
|
|
6798
6949
|
}
|
|
6950
|
+
const rankedCoveredByContainment = lane.children.some(
|
|
6951
|
+
(childId) => containedChildIds.has(childId)
|
|
6952
|
+
);
|
|
6799
6953
|
moveRankedVerticalLaneChildren(
|
|
6800
6954
|
lane.children,
|
|
6801
6955
|
nodeBoxes,
|
|
@@ -6806,7 +6960,8 @@ function applyVerticalSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBox
|
|
|
6806
6960
|
rankSpacing,
|
|
6807
6961
|
rankStackGap,
|
|
6808
6962
|
{ x: target.x, y: laneContentTop },
|
|
6809
|
-
slotWidth - padding * 2
|
|
6963
|
+
slotWidth - padding * 2,
|
|
6964
|
+
rankedCoveredByContainment
|
|
6810
6965
|
);
|
|
6811
6966
|
}
|
|
6812
6967
|
return {
|
|
@@ -6922,9 +7077,12 @@ function crossAxisSpreadWidth(items, gap) {
|
|
|
6922
7077
|
0
|
|
6923
7078
|
);
|
|
6924
7079
|
}
|
|
6925
|
-
function maxCrossAxisSpreadWidth(swimlane, nodeBoxes, flowRanks, locks, gap) {
|
|
7080
|
+
function maxCrossAxisSpreadWidth(swimlane, nodeBoxes, flowRanks, locks, gap, containedChildIds) {
|
|
6926
7081
|
let maxWidth = 0;
|
|
6927
7082
|
for (const lane of swimlane.lanes) {
|
|
7083
|
+
if (containedChildIds !== void 0 && lane.children.some((childId) => containedChildIds.has(childId))) {
|
|
7084
|
+
continue;
|
|
7085
|
+
}
|
|
6928
7086
|
for (const stack of rankStacks(
|
|
6929
7087
|
lane.children,
|
|
6930
7088
|
nodeBoxes,
|
|
@@ -6937,7 +7095,7 @@ function maxCrossAxisSpreadWidth(swimlane, nodeBoxes, flowRanks, locks, gap) {
|
|
|
6937
7095
|
}
|
|
6938
7096
|
return maxWidth;
|
|
6939
7097
|
}
|
|
6940
|
-
function moveRankedVerticalLaneChildren(childIds, nodeBoxes, locks, diagnostics, movedChildIds, flowRanks, rankSpacing, rankStackGap, target, contentWidth) {
|
|
7098
|
+
function moveRankedVerticalLaneChildren(childIds, nodeBoxes, locks, diagnostics, movedChildIds, flowRanks, rankSpacing, rankStackGap, target, contentWidth, suppressSpread) {
|
|
6941
7099
|
for (const [rank, stack] of rankStacks(childIds, nodeBoxes, flowRanks)) {
|
|
6942
7100
|
const unlocked = [];
|
|
6943
7101
|
for (const item of stack) {
|
|
@@ -6966,7 +7124,7 @@ function moveRankedVerticalLaneChildren(childIds, nodeBoxes, locks, diagnostics,
|
|
|
6966
7124
|
}
|
|
6967
7125
|
nodeBoxes.set(childId, next);
|
|
6968
7126
|
} else {
|
|
6969
|
-
const shouldSpread = unlocked.length >= CROSS_AXIS_SPREAD_THRESHOLD;
|
|
7127
|
+
const shouldSpread = !suppressSpread && unlocked.length >= CROSS_AXIS_SPREAD_THRESHOLD;
|
|
6970
7128
|
if (!shouldSpread) {
|
|
6971
7129
|
let yOffset = 0;
|
|
6972
7130
|
for (const { childId, box } of unlocked) {
|
|
@@ -8095,14 +8253,21 @@ function evidenceOverlapDiagnostic(block, conflict) {
|
|
|
8095
8253
|
}
|
|
8096
8254
|
};
|
|
8097
8255
|
}
|
|
8098
|
-
function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacles, textObstacles, hardObstacles, direction, options, diagnostics, groups) {
|
|
8256
|
+
function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacles, textObstacles, hardObstacles, direction, options, diagnostics, groups, contentBounds) {
|
|
8099
8257
|
const coordinated = [];
|
|
8100
8258
|
const coordinatedNodeById = new Map(
|
|
8101
8259
|
coordinatedNodes.map((node) => [node.id, node])
|
|
8102
8260
|
);
|
|
8261
|
+
const corridorMarginOption = options.corridorMargin ?? "auto";
|
|
8262
|
+
const corridorMargin = typeof corridorMarginOption === "number" ? corridorMarginOption : Math.max(
|
|
8263
|
+
200,
|
|
8264
|
+
Math.hypot(contentBounds.width, contentBounds.height) * 0.3
|
|
8265
|
+
);
|
|
8266
|
+
const routingGutter = options.routingGutter ?? 160;
|
|
8267
|
+
const queryGutter = (options.routeKind ?? "orthogonal") === "obstacle-avoiding" ? Math.max(routingGutter, corridorMargin) : routingGutter;
|
|
8103
8268
|
const nodeObstacleIndex = createBoxSpatialIndex(
|
|
8104
8269
|
obstacles.map((box, index) => ({ id: `node-obstacle:${index}`, box })),
|
|
8105
|
-
|
|
8270
|
+
queryGutter
|
|
8106
8271
|
);
|
|
8107
8272
|
for (const edge of edges) {
|
|
8108
8273
|
const source = nodes.get(edge.source.nodeId);
|
|
@@ -8124,11 +8289,7 @@ function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacle
|
|
|
8124
8289
|
const sourcePort = coordinatedNodeById.get(edge.source.nodeId)?.ports?.find((port) => port.id === edge.source.portId);
|
|
8125
8290
|
const targetPort = coordinatedNodeById.get(edge.target.nodeId)?.ports?.find((port) => port.id === edge.target.portId);
|
|
8126
8291
|
const routeTextObstacles = textObstacles.filter((annotation) => !isEdgeConnectedTextAnnotation(edge, annotation)).map((annotation) => annotation.box);
|
|
8127
|
-
const corridor = edgeCorridorBox(
|
|
8128
|
-
source.box,
|
|
8129
|
-
target.box,
|
|
8130
|
-
options.routingGutter ?? 160
|
|
8131
|
-
);
|
|
8292
|
+
const corridor = edgeCorridorBox(source.box, target.box, queryGutter);
|
|
8132
8293
|
const routeNodeObstacles = queryBoxSpatialIndex(nodeObstacleIndex, corridor).map((entry) => entry.box).filter(
|
|
8133
8294
|
(obstacle) => !sameBox(obstacle, source.obstacleBox) && !sameBox(obstacle, target.obstacleBox)
|
|
8134
8295
|
);
|
|
@@ -8146,7 +8307,9 @@ function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacle
|
|
|
8146
8307
|
...routeTextObstacles
|
|
8147
8308
|
],
|
|
8148
8309
|
hardObstacles,
|
|
8149
|
-
|
|
8310
|
+
corridorMargin,
|
|
8311
|
+
...options.maxRoutingAttempts === void 0 ? {} : { maxRoutingAttempts: options.maxRoutingAttempts },
|
|
8312
|
+
...options.maxBacktrackingRatio === void 0 ? {} : { maxBacktrackingRatio: options.maxBacktrackingRatio }
|
|
8150
8313
|
});
|
|
8151
8314
|
diagnostics.push(
|
|
8152
8315
|
...route.diagnostics.map((diagnostic) => ({
|