@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.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 = 10;
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
- 32
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(finalized, source, target, diagnostics);
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(fullFinalized, source, target, diagnostics);
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(gridFinalized, source, target, diagnostics);
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
- return {
5066
- points: finalizeRoute(
5067
- bestPoints2,
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
- return {
5151
- points: finalizeRoute(
5152
- bestPoints,
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
- if (distributable.length >= CROSS_AXIS_SPREAD_THRESHOLD) {
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
- options.routingGutter ?? 160
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
- ...options.maxRoutingAttempts === void 0 ? {} : { maxRoutingAttempts: options.maxRoutingAttempts }
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) => ({