@crazyhappyone/auto-graph 0.2.11 → 0.2.12

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/index.d.cts CHANGED
@@ -776,6 +776,12 @@ interface RouteEdgeInput {
776
776
  /** Route-length / direct-distance ratio above which a backtracking
777
777
  * warning is emitted (default 20). */
778
778
  maxBacktrackingRatio?: number;
779
+ /** Max corner-graph vertices. Undefined → adaptive (derived from
780
+ * corridor size + obstacle count, clamped to a safe range). */
781
+ maxCorners?: number;
782
+ /** Max grid A* nodes. Undefined → adaptive (derived from obstacle
783
+ * count + corridor, clamped to a safe range). */
784
+ maxNodes?: number;
779
785
  }
780
786
  interface RouteEdgeResult {
781
787
  points: Point[];
package/dist/index.d.ts CHANGED
@@ -776,6 +776,12 @@ interface RouteEdgeInput {
776
776
  /** Route-length / direct-distance ratio above which a backtracking
777
777
  * warning is emitted (default 20). */
778
778
  maxBacktrackingRatio?: number;
779
+ /** Max corner-graph vertices. Undefined → adaptive (derived from
780
+ * corridor size + obstacle count, clamped to a safe range). */
781
+ maxCorners?: number;
782
+ /** Max grid A* nodes. Undefined → adaptive (derived from obstacle
783
+ * count + corridor, clamped to a safe range). */
784
+ maxNodes?: number;
779
785
  }
780
786
  interface RouteEdgeResult {
781
787
  points: Point[];
package/dist/index.js CHANGED
@@ -4805,7 +4805,10 @@ function findObstacleFreePath(source, target, obstacles, options = {}, diagnosti
4805
4805
  detail: {
4806
4806
  xsCount: xs.length,
4807
4807
  ysCount: ys.length,
4808
- maxNodes
4808
+ maxNodes,
4809
+ obstacleCount: obstacles.length,
4810
+ stage: "corridor-filtered",
4811
+ ...corridorMargin === void 0 ? {} : { corridorMargin }
4809
4812
  }
4810
4813
  });
4811
4814
  return null;
@@ -4851,7 +4854,14 @@ function findObstacleFreePath(source, target, obstacles, options = {}, diagnosti
4851
4854
  severity: "warning",
4852
4855
  code: "routing.astar.grid_overflow",
4853
4856
  message: `A* full-retry grid overflow: ${xsFull.length * ysFull.length} nodes > ${maxNodes} limit. Falling back to heuristic routing.`,
4854
- detail: { xsCount: xsFull.length, ysCount: ysFull.length, maxNodes }
4857
+ detail: {
4858
+ xsCount: xsFull.length,
4859
+ ysCount: ysFull.length,
4860
+ maxNodes,
4861
+ obstacleCount: obstacles.length,
4862
+ stage: "full-retry",
4863
+ ...corridorMargin === void 0 ? {} : { corridorMargin }
4864
+ }
4855
4865
  });
4856
4866
  return null;
4857
4867
  }
@@ -5094,6 +5104,64 @@ function areCollinear(a, b, c) {
5094
5104
  return a.x === b.x && b.x === c.x || a.y === b.y && b.y === c.y;
5095
5105
  }
5096
5106
 
5107
+ // src/routing/budget.ts
5108
+ var MIN_CORNER_BUDGET = 600;
5109
+ var MAX_CORNER_BUDGET = 3e3;
5110
+ var MIN_NODE_BUDGET = 4e3;
5111
+ var MAX_NODE_BUDGET = 64e3;
5112
+ var CORNERS_PER_OBSTACLE = 12;
5113
+ var CORNER_HEADROOM = 2;
5114
+ var GRID_SAFETY_FACTOR = 3;
5115
+ var CORRIDOR_SCALING_K = 0.5;
5116
+ var CORRIDOR_SCALING_BASE = 200;
5117
+ function computeRoutingBudget(cornerObstacles, allObstacles, corridorMargin, overrides = {}) {
5118
+ const adaptiveMaxCorners = deriveMaxCorners(
5119
+ cornerObstacles.length,
5120
+ corridorMargin
5121
+ );
5122
+ const adaptiveMaxNodes = deriveMaxNodes(
5123
+ allObstacles.length,
5124
+ corridorMargin
5125
+ );
5126
+ return {
5127
+ maxCorners: resolveBudget(
5128
+ overrides.maxCorners,
5129
+ adaptiveMaxCorners,
5130
+ MIN_CORNER_BUDGET,
5131
+ MAX_CORNER_BUDGET
5132
+ ),
5133
+ maxNodes: resolveBudget(
5134
+ overrides.maxNodes,
5135
+ adaptiveMaxNodes,
5136
+ MIN_NODE_BUDGET,
5137
+ MAX_NODE_BUDGET
5138
+ ),
5139
+ cornerObstacleCount: cornerObstacles.length,
5140
+ gridObstacleCount: allObstacles.length,
5141
+ corridorMargin
5142
+ };
5143
+ }
5144
+ function deriveMaxCorners(obstacleCount, corridorMargin) {
5145
+ const base = 2 + obstacleCount * CORNERS_PER_OBSTACLE * CORNER_HEADROOM;
5146
+ const corridorFactor = corridorScalingFactor(corridorMargin);
5147
+ return Math.ceil(base * corridorFactor);
5148
+ }
5149
+ function deriveMaxNodes(obstacleCount, corridorMargin) {
5150
+ const base = 4 * obstacleCount * obstacleCount + 4 * obstacleCount + 100;
5151
+ const corridorFactor = corridorScalingFactor(corridorMargin);
5152
+ return Math.ceil(base * GRID_SAFETY_FACTOR * corridorFactor);
5153
+ }
5154
+ function corridorScalingFactor(corridorMargin) {
5155
+ return 1 + corridorMargin / CORRIDOR_SCALING_BASE * CORRIDOR_SCALING_K;
5156
+ }
5157
+ function resolveBudget(override, adaptive, min, max) {
5158
+ const chosen = override !== void 0 && Number.isFinite(override) && override >= 1 ? override : adaptive;
5159
+ return clamp(chosen, min, max);
5160
+ }
5161
+ function clamp(value, min, max) {
5162
+ return Math.max(min, Math.min(max, value));
5163
+ }
5164
+
5097
5165
  // src/routing/visibility-router.ts
5098
5166
  function findCornerGraphPath(source, target, obstacles, options = {}, diagnostics) {
5099
5167
  const margin = options.margin ?? 0;
@@ -5107,7 +5175,12 @@ function findCornerGraphPath(source, target, obstacles, options = {}, diagnostic
5107
5175
  severity: "warning",
5108
5176
  code: "routing.visibility.corner_overflow",
5109
5177
  message: `Corner graph overflow: ${vertices.length} vertices > ${maxCorners}. Falling back to grid A*.`,
5110
- detail: { vertexCount: vertices.length, maxCorners }
5178
+ detail: {
5179
+ vertexCount: vertices.length,
5180
+ maxCorners,
5181
+ obstacleCount: obstacles.length,
5182
+ ...options.corridorMargin === void 0 ? {} : { corridorMargin: options.corridorMargin }
5183
+ }
5111
5184
  });
5112
5185
  return null;
5113
5186
  }
@@ -5492,11 +5565,22 @@ function routeEdge(input) {
5492
5565
  corridorMargin
5493
5566
  );
5494
5567
  const cornerObstacles = corridorObstacles.length === 0 && allObstacles.length > 0 ? allObstacles : corridorObstacles;
5568
+ const budget = computeRoutingBudget(
5569
+ cornerObstacles,
5570
+ allObstacles,
5571
+ corridorMargin,
5572
+ { maxCorners: input.maxCorners, maxNodes: input.maxNodes }
5573
+ );
5495
5574
  let cornerPath = findCornerGraphPath(
5496
5575
  source,
5497
5576
  target,
5498
5577
  cornerObstacles,
5499
- { endpointObstacles, margin: 2 },
5578
+ {
5579
+ endpointObstacles,
5580
+ margin: 2,
5581
+ maxCorners: budget.maxCorners,
5582
+ corridorMargin
5583
+ },
5500
5584
  diagnostics
5501
5585
  );
5502
5586
  if (cornerPath === null && cornerObstacles.length < allObstacles.length) {
@@ -5504,7 +5588,12 @@ function routeEdge(input) {
5504
5588
  source,
5505
5589
  target,
5506
5590
  allObstacles,
5507
- { endpointObstacles, margin: 2 },
5591
+ {
5592
+ endpointObstacles,
5593
+ margin: 2,
5594
+ maxCorners: budget.maxCorners,
5595
+ corridorMargin
5596
+ },
5508
5597
  diagnostics
5509
5598
  );
5510
5599
  }
@@ -5512,7 +5601,12 @@ function routeEdge(input) {
5512
5601
  source,
5513
5602
  target,
5514
5603
  allObstacles,
5515
- { endpointObstacles, margin: 0, corridorMargin },
5604
+ {
5605
+ endpointObstacles,
5606
+ margin: 0,
5607
+ corridorMargin,
5608
+ maxNodes: budget.maxNodes
5609
+ },
5516
5610
  diagnostics
5517
5611
  );
5518
5612
  if (path !== null && path.length >= 2) {
@@ -5544,7 +5638,12 @@ function routeEdge(input) {
5544
5638
  source,
5545
5639
  target,
5546
5640
  allObstacles,
5547
- { endpointObstacles, margin: 2 },
5641
+ {
5642
+ endpointObstacles,
5643
+ margin: 2,
5644
+ maxCorners: budget.maxCorners,
5645
+ corridorMargin
5646
+ },
5548
5647
  diagnostics
5549
5648
  ) : null;
5550
5649
  if (fullCornerPath !== null && fullCornerPath.length >= 2) {
@@ -5580,7 +5679,12 @@ function routeEdge(input) {
5580
5679
  source,
5581
5680
  target,
5582
5681
  allObstacles,
5583
- { endpointObstacles, margin: 0, corridorMargin },
5682
+ {
5683
+ endpointObstacles,
5684
+ margin: 0,
5685
+ corridorMargin,
5686
+ maxNodes: budget.maxNodes
5687
+ },
5584
5688
  diagnostics
5585
5689
  );
5586
5690
  if (gridPath !== null && gridPath.length >= 2) {