@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/cli/index.cjs +112 -8
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +112 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +112 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +112 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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: {
|
|
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: {
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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) {
|