@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.
@@ -4164,7 +4164,10 @@ function findObstacleFreePath(source, target, obstacles, options = {}, diagnosti
4164
4164
  detail: {
4165
4165
  xsCount: xs.length,
4166
4166
  ysCount: ys.length,
4167
- maxNodes
4167
+ maxNodes,
4168
+ obstacleCount: obstacles.length,
4169
+ stage: "corridor-filtered",
4170
+ ...corridorMargin === void 0 ? {} : { corridorMargin }
4168
4171
  }
4169
4172
  });
4170
4173
  return null;
@@ -4210,7 +4213,14 @@ function findObstacleFreePath(source, target, obstacles, options = {}, diagnosti
4210
4213
  severity: "warning",
4211
4214
  code: "routing.astar.grid_overflow",
4212
4215
  message: `A* full-retry grid overflow: ${xsFull.length * ysFull.length} nodes > ${maxNodes} limit. Falling back to heuristic routing.`,
4213
- detail: { xsCount: xsFull.length, ysCount: ysFull.length, maxNodes }
4216
+ detail: {
4217
+ xsCount: xsFull.length,
4218
+ ysCount: ysFull.length,
4219
+ maxNodes,
4220
+ obstacleCount: obstacles.length,
4221
+ stage: "full-retry",
4222
+ ...corridorMargin === void 0 ? {} : { corridorMargin }
4223
+ }
4214
4224
  });
4215
4225
  return null;
4216
4226
  }
@@ -4453,6 +4463,64 @@ function areCollinear(a, b, c) {
4453
4463
  return a.x === b.x && b.x === c.x || a.y === b.y && b.y === c.y;
4454
4464
  }
4455
4465
 
4466
+ // src/routing/budget.ts
4467
+ var MIN_CORNER_BUDGET = 600;
4468
+ var MAX_CORNER_BUDGET = 3e3;
4469
+ var MIN_NODE_BUDGET = 4e3;
4470
+ var MAX_NODE_BUDGET = 64e3;
4471
+ var CORNERS_PER_OBSTACLE = 12;
4472
+ var CORNER_HEADROOM = 2;
4473
+ var GRID_SAFETY_FACTOR = 3;
4474
+ var CORRIDOR_SCALING_K = 0.5;
4475
+ var CORRIDOR_SCALING_BASE = 200;
4476
+ function computeRoutingBudget(cornerObstacles, allObstacles, corridorMargin, overrides = {}) {
4477
+ const adaptiveMaxCorners = deriveMaxCorners(
4478
+ cornerObstacles.length,
4479
+ corridorMargin
4480
+ );
4481
+ const adaptiveMaxNodes = deriveMaxNodes(
4482
+ allObstacles.length,
4483
+ corridorMargin
4484
+ );
4485
+ return {
4486
+ maxCorners: resolveBudget(
4487
+ overrides.maxCorners,
4488
+ adaptiveMaxCorners,
4489
+ MIN_CORNER_BUDGET,
4490
+ MAX_CORNER_BUDGET
4491
+ ),
4492
+ maxNodes: resolveBudget(
4493
+ overrides.maxNodes,
4494
+ adaptiveMaxNodes,
4495
+ MIN_NODE_BUDGET,
4496
+ MAX_NODE_BUDGET
4497
+ ),
4498
+ cornerObstacleCount: cornerObstacles.length,
4499
+ gridObstacleCount: allObstacles.length,
4500
+ corridorMargin
4501
+ };
4502
+ }
4503
+ function deriveMaxCorners(obstacleCount, corridorMargin) {
4504
+ const base = 2 + obstacleCount * CORNERS_PER_OBSTACLE * CORNER_HEADROOM;
4505
+ const corridorFactor = corridorScalingFactor(corridorMargin);
4506
+ return Math.ceil(base * corridorFactor);
4507
+ }
4508
+ function deriveMaxNodes(obstacleCount, corridorMargin) {
4509
+ const base = 4 * obstacleCount * obstacleCount + 4 * obstacleCount + 100;
4510
+ const corridorFactor = corridorScalingFactor(corridorMargin);
4511
+ return Math.ceil(base * GRID_SAFETY_FACTOR * corridorFactor);
4512
+ }
4513
+ function corridorScalingFactor(corridorMargin) {
4514
+ return 1 + corridorMargin / CORRIDOR_SCALING_BASE * CORRIDOR_SCALING_K;
4515
+ }
4516
+ function resolveBudget(override, adaptive, min, max) {
4517
+ const chosen = override !== void 0 && Number.isFinite(override) && override >= 1 ? override : adaptive;
4518
+ return clamp(chosen, min, max);
4519
+ }
4520
+ function clamp(value, min, max) {
4521
+ return Math.max(min, Math.min(max, value));
4522
+ }
4523
+
4456
4524
  // src/routing/visibility-router.ts
4457
4525
  function findCornerGraphPath(source, target, obstacles, options = {}, diagnostics) {
4458
4526
  const margin = options.margin ?? 0;
@@ -4466,7 +4534,12 @@ function findCornerGraphPath(source, target, obstacles, options = {}, diagnostic
4466
4534
  severity: "warning",
4467
4535
  code: "routing.visibility.corner_overflow",
4468
4536
  message: `Corner graph overflow: ${vertices.length} vertices > ${maxCorners}. Falling back to grid A*.`,
4469
- detail: { vertexCount: vertices.length, maxCorners }
4537
+ detail: {
4538
+ vertexCount: vertices.length,
4539
+ maxCorners,
4540
+ obstacleCount: obstacles.length,
4541
+ ...options.corridorMargin === void 0 ? {} : { corridorMargin: options.corridorMargin }
4542
+ }
4470
4543
  });
4471
4544
  return null;
4472
4545
  }
@@ -4851,11 +4924,22 @@ function routeEdge(input) {
4851
4924
  corridorMargin
4852
4925
  );
4853
4926
  const cornerObstacles = corridorObstacles.length === 0 && allObstacles.length > 0 ? allObstacles : corridorObstacles;
4927
+ const budget = computeRoutingBudget(
4928
+ cornerObstacles,
4929
+ allObstacles,
4930
+ corridorMargin,
4931
+ { maxCorners: input.maxCorners, maxNodes: input.maxNodes }
4932
+ );
4854
4933
  let cornerPath = findCornerGraphPath(
4855
4934
  source,
4856
4935
  target,
4857
4936
  cornerObstacles,
4858
- { endpointObstacles, margin: 2 },
4937
+ {
4938
+ endpointObstacles,
4939
+ margin: 2,
4940
+ maxCorners: budget.maxCorners,
4941
+ corridorMargin
4942
+ },
4859
4943
  diagnostics
4860
4944
  );
4861
4945
  if (cornerPath === null && cornerObstacles.length < allObstacles.length) {
@@ -4863,7 +4947,12 @@ function routeEdge(input) {
4863
4947
  source,
4864
4948
  target,
4865
4949
  allObstacles,
4866
- { endpointObstacles, margin: 2 },
4950
+ {
4951
+ endpointObstacles,
4952
+ margin: 2,
4953
+ maxCorners: budget.maxCorners,
4954
+ corridorMargin
4955
+ },
4867
4956
  diagnostics
4868
4957
  );
4869
4958
  }
@@ -4871,7 +4960,12 @@ function routeEdge(input) {
4871
4960
  source,
4872
4961
  target,
4873
4962
  allObstacles,
4874
- { endpointObstacles, margin: 0, corridorMargin },
4963
+ {
4964
+ endpointObstacles,
4965
+ margin: 0,
4966
+ corridorMargin,
4967
+ maxNodes: budget.maxNodes
4968
+ },
4875
4969
  diagnostics
4876
4970
  );
4877
4971
  if (path !== null && path.length >= 2) {
@@ -4903,7 +4997,12 @@ function routeEdge(input) {
4903
4997
  source,
4904
4998
  target,
4905
4999
  allObstacles,
4906
- { endpointObstacles, margin: 2 },
5000
+ {
5001
+ endpointObstacles,
5002
+ margin: 2,
5003
+ maxCorners: budget.maxCorners,
5004
+ corridorMargin
5005
+ },
4907
5006
  diagnostics
4908
5007
  ) : null;
4909
5008
  if (fullCornerPath !== null && fullCornerPath.length >= 2) {
@@ -4939,7 +5038,12 @@ function routeEdge(input) {
4939
5038
  source,
4940
5039
  target,
4941
5040
  allObstacles,
4942
- { endpointObstacles, margin: 0, corridorMargin },
5041
+ {
5042
+ endpointObstacles,
5043
+ margin: 0,
5044
+ corridorMargin,
5045
+ maxNodes: budget.maxNodes
5046
+ },
4943
5047
  diagnostics
4944
5048
  );
4945
5049
  if (gridPath !== null && gridPath.length >= 2) {