@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.cjs CHANGED
@@ -4808,7 +4808,10 @@ function findObstacleFreePath(source, target, obstacles, options = {}, diagnosti
4808
4808
  detail: {
4809
4809
  xsCount: xs.length,
4810
4810
  ysCount: ys.length,
4811
- maxNodes
4811
+ maxNodes,
4812
+ obstacleCount: obstacles.length,
4813
+ stage: "corridor-filtered",
4814
+ ...corridorMargin === void 0 ? {} : { corridorMargin }
4812
4815
  }
4813
4816
  });
4814
4817
  return null;
@@ -4854,7 +4857,14 @@ function findObstacleFreePath(source, target, obstacles, options = {}, diagnosti
4854
4857
  severity: "warning",
4855
4858
  code: "routing.astar.grid_overflow",
4856
4859
  message: `A* full-retry grid overflow: ${xsFull.length * ysFull.length} nodes > ${maxNodes} limit. Falling back to heuristic routing.`,
4857
- detail: { xsCount: xsFull.length, ysCount: ysFull.length, maxNodes }
4860
+ detail: {
4861
+ xsCount: xsFull.length,
4862
+ ysCount: ysFull.length,
4863
+ maxNodes,
4864
+ obstacleCount: obstacles.length,
4865
+ stage: "full-retry",
4866
+ ...corridorMargin === void 0 ? {} : { corridorMargin }
4867
+ }
4858
4868
  });
4859
4869
  return null;
4860
4870
  }
@@ -5097,6 +5107,64 @@ function areCollinear(a, b, c) {
5097
5107
  return a.x === b.x && b.x === c.x || a.y === b.y && b.y === c.y;
5098
5108
  }
5099
5109
 
5110
+ // src/routing/budget.ts
5111
+ var MIN_CORNER_BUDGET = 600;
5112
+ var MAX_CORNER_BUDGET = 3e3;
5113
+ var MIN_NODE_BUDGET = 4e3;
5114
+ var MAX_NODE_BUDGET = 64e3;
5115
+ var CORNERS_PER_OBSTACLE = 12;
5116
+ var CORNER_HEADROOM = 2;
5117
+ var GRID_SAFETY_FACTOR = 3;
5118
+ var CORRIDOR_SCALING_K = 0.5;
5119
+ var CORRIDOR_SCALING_BASE = 200;
5120
+ function computeRoutingBudget(cornerObstacles, allObstacles, corridorMargin, overrides = {}) {
5121
+ const adaptiveMaxCorners = deriveMaxCorners(
5122
+ cornerObstacles.length,
5123
+ corridorMargin
5124
+ );
5125
+ const adaptiveMaxNodes = deriveMaxNodes(
5126
+ allObstacles.length,
5127
+ corridorMargin
5128
+ );
5129
+ return {
5130
+ maxCorners: resolveBudget(
5131
+ overrides.maxCorners,
5132
+ adaptiveMaxCorners,
5133
+ MIN_CORNER_BUDGET,
5134
+ MAX_CORNER_BUDGET
5135
+ ),
5136
+ maxNodes: resolveBudget(
5137
+ overrides.maxNodes,
5138
+ adaptiveMaxNodes,
5139
+ MIN_NODE_BUDGET,
5140
+ MAX_NODE_BUDGET
5141
+ ),
5142
+ cornerObstacleCount: cornerObstacles.length,
5143
+ gridObstacleCount: allObstacles.length,
5144
+ corridorMargin
5145
+ };
5146
+ }
5147
+ function deriveMaxCorners(obstacleCount, corridorMargin) {
5148
+ const base = 2 + obstacleCount * CORNERS_PER_OBSTACLE * CORNER_HEADROOM;
5149
+ const corridorFactor = corridorScalingFactor(corridorMargin);
5150
+ return Math.ceil(base * corridorFactor);
5151
+ }
5152
+ function deriveMaxNodes(obstacleCount, corridorMargin) {
5153
+ const base = 4 * obstacleCount * obstacleCount + 4 * obstacleCount + 100;
5154
+ const corridorFactor = corridorScalingFactor(corridorMargin);
5155
+ return Math.ceil(base * GRID_SAFETY_FACTOR * corridorFactor);
5156
+ }
5157
+ function corridorScalingFactor(corridorMargin) {
5158
+ return 1 + corridorMargin / CORRIDOR_SCALING_BASE * CORRIDOR_SCALING_K;
5159
+ }
5160
+ function resolveBudget(override, adaptive, min, max) {
5161
+ const chosen = override !== void 0 && Number.isFinite(override) && override >= 1 ? override : adaptive;
5162
+ return clamp(chosen, min, max);
5163
+ }
5164
+ function clamp(value, min, max) {
5165
+ return Math.max(min, Math.min(max, value));
5166
+ }
5167
+
5100
5168
  // src/routing/visibility-router.ts
5101
5169
  function findCornerGraphPath(source, target, obstacles, options = {}, diagnostics) {
5102
5170
  const margin = options.margin ?? 0;
@@ -5110,7 +5178,12 @@ function findCornerGraphPath(source, target, obstacles, options = {}, diagnostic
5110
5178
  severity: "warning",
5111
5179
  code: "routing.visibility.corner_overflow",
5112
5180
  message: `Corner graph overflow: ${vertices.length} vertices > ${maxCorners}. Falling back to grid A*.`,
5113
- detail: { vertexCount: vertices.length, maxCorners }
5181
+ detail: {
5182
+ vertexCount: vertices.length,
5183
+ maxCorners,
5184
+ obstacleCount: obstacles.length,
5185
+ ...options.corridorMargin === void 0 ? {} : { corridorMargin: options.corridorMargin }
5186
+ }
5114
5187
  });
5115
5188
  return null;
5116
5189
  }
@@ -5495,11 +5568,22 @@ function routeEdge(input) {
5495
5568
  corridorMargin
5496
5569
  );
5497
5570
  const cornerObstacles = corridorObstacles.length === 0 && allObstacles.length > 0 ? allObstacles : corridorObstacles;
5571
+ const budget = computeRoutingBudget(
5572
+ cornerObstacles,
5573
+ allObstacles,
5574
+ corridorMargin,
5575
+ { maxCorners: input.maxCorners, maxNodes: input.maxNodes }
5576
+ );
5498
5577
  let cornerPath = findCornerGraphPath(
5499
5578
  source,
5500
5579
  target,
5501
5580
  cornerObstacles,
5502
- { endpointObstacles, margin: 2 },
5581
+ {
5582
+ endpointObstacles,
5583
+ margin: 2,
5584
+ maxCorners: budget.maxCorners,
5585
+ corridorMargin
5586
+ },
5503
5587
  diagnostics
5504
5588
  );
5505
5589
  if (cornerPath === null && cornerObstacles.length < allObstacles.length) {
@@ -5507,7 +5591,12 @@ function routeEdge(input) {
5507
5591
  source,
5508
5592
  target,
5509
5593
  allObstacles,
5510
- { endpointObstacles, margin: 2 },
5594
+ {
5595
+ endpointObstacles,
5596
+ margin: 2,
5597
+ maxCorners: budget.maxCorners,
5598
+ corridorMargin
5599
+ },
5511
5600
  diagnostics
5512
5601
  );
5513
5602
  }
@@ -5515,7 +5604,12 @@ function routeEdge(input) {
5515
5604
  source,
5516
5605
  target,
5517
5606
  allObstacles,
5518
- { endpointObstacles, margin: 0, corridorMargin },
5607
+ {
5608
+ endpointObstacles,
5609
+ margin: 0,
5610
+ corridorMargin,
5611
+ maxNodes: budget.maxNodes
5612
+ },
5519
5613
  diagnostics
5520
5614
  );
5521
5615
  if (path !== null && path.length >= 2) {
@@ -5547,7 +5641,12 @@ function routeEdge(input) {
5547
5641
  source,
5548
5642
  target,
5549
5643
  allObstacles,
5550
- { endpointObstacles, margin: 2 },
5644
+ {
5645
+ endpointObstacles,
5646
+ margin: 2,
5647
+ maxCorners: budget.maxCorners,
5648
+ corridorMargin
5649
+ },
5551
5650
  diagnostics
5552
5651
  ) : null;
5553
5652
  if (fullCornerPath !== null && fullCornerPath.length >= 2) {
@@ -5583,7 +5682,12 @@ function routeEdge(input) {
5583
5682
  source,
5584
5683
  target,
5585
5684
  allObstacles,
5586
- { endpointObstacles, margin: 0, corridorMargin },
5685
+ {
5686
+ endpointObstacles,
5687
+ margin: 0,
5688
+ corridorMargin,
5689
+ maxNodes: budget.maxNodes
5690
+ },
5587
5691
  diagnostics
5588
5692
  );
5589
5693
  if (gridPath !== null && gridPath.length >= 2) {