@rxflow/manhattan 0.0.1-alpha.12 → 0.0.1-alpha.13
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findRoute.d.ts","sourceRoot":"","sources":["../../src/pathfinder/findRoute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"findRoute.d.ts","sourceRoot":"","sources":["../../src/pathfinder/findRoute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAyN9C;;GAEG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,SAAS,EACrB,UAAU,EAAE,SAAS,EACrB,YAAY,EAAE,KAAK,EACnB,YAAY,EAAE,KAAK,EACnB,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,eAAe,GACvB,KAAK,EAAE,GAAG,IAAI,CAqThB"}
|
|
@@ -7,6 +7,60 @@ exports.findRoute = findRoute;
|
|
|
7
7
|
var _geometry = require("../geometry");
|
|
8
8
|
var _SortedSet = require("./SortedSet");
|
|
9
9
|
var _utils = require("../utils");
|
|
10
|
+
/**
|
|
11
|
+
* Find the closest accessible point in a given direction using step-based search with linear refinement
|
|
12
|
+
*
|
|
13
|
+
* Algorithm:
|
|
14
|
+
* 1. Try moving by step increments (step, 2*step, 3*step...) until finding an accessible point
|
|
15
|
+
* 2. Once found, linearly search backward from (n-1)*step+1 to n*step to find the closest accessible point
|
|
16
|
+
* 3. Returns null if no accessible point found within maxSteps
|
|
17
|
+
*/
|
|
18
|
+
function findAccessibleNeighbor(from, directionX, directionY, step, map, precision, maxSteps = 20) {
|
|
19
|
+
// Normalize direction
|
|
20
|
+
const length = Math.sqrt(directionX * directionX + directionY * directionY);
|
|
21
|
+
const ndx = directionX / length;
|
|
22
|
+
const ndy = directionY / length;
|
|
23
|
+
|
|
24
|
+
// 1. Try the first step directly (most common case)
|
|
25
|
+
const firstStepPoint = new _geometry.Point(from.x + ndx * step, from.y + ndy * step).round(precision);
|
|
26
|
+
if (map.isAccessible(firstStepPoint)) {
|
|
27
|
+
// First step is accessible, no need for refinement
|
|
28
|
+
return firstStepPoint;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 2. First step blocked, search outward by step increments
|
|
32
|
+
let stepMultiplier = 2;
|
|
33
|
+
let foundAccessibleDistance = -1;
|
|
34
|
+
while (stepMultiplier <= maxSteps) {
|
|
35
|
+
const distance = stepMultiplier * step;
|
|
36
|
+
const testPoint = new _geometry.Point(from.x + ndx * distance, from.y + ndy * distance).round(precision);
|
|
37
|
+
if (map.isAccessible(testPoint)) {
|
|
38
|
+
foundAccessibleDistance = distance;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
stepMultiplier++;
|
|
42
|
+
}
|
|
43
|
+
if (foundAccessibleDistance < 0) {
|
|
44
|
+
return null; // No accessible point found
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 3. Linear search within the last step interval to find closest accessible point
|
|
48
|
+
// Search from (n-1)*step+1 to n*step
|
|
49
|
+
const outerDistance = foundAccessibleDistance;
|
|
50
|
+
const innerDistance = foundAccessibleDistance - step;
|
|
51
|
+
|
|
52
|
+
// Search backward from outer to inner to find the closest accessible point
|
|
53
|
+
for (let dist = innerDistance + 1; dist < outerDistance; dist++) {
|
|
54
|
+
const testPoint = new _geometry.Point(from.x + ndx * dist, from.y + ndy * dist).round(precision);
|
|
55
|
+
if (map.isAccessible(testPoint)) {
|
|
56
|
+
return testPoint;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// If no closer point found, return the outer distance point
|
|
61
|
+
return new _geometry.Point(from.x + ndx * outerDistance, from.y + ndy * outerDistance).round(precision);
|
|
62
|
+
}
|
|
63
|
+
|
|
10
64
|
/**
|
|
11
65
|
* Generate smart points based on position using extensionDistance and binary search
|
|
12
66
|
*
|
|
@@ -74,29 +128,23 @@ function generateSmartPoints(anchor, bbox, position, grid, map, options, isTarge
|
|
|
74
128
|
stepMultiplier++;
|
|
75
129
|
}
|
|
76
130
|
|
|
77
|
-
// 3. If we found an accessible point, refine by
|
|
131
|
+
// 3. If we found an accessible point, refine by linear search within the last step interval
|
|
78
132
|
if (foundAccessibleDistance > 0) {
|
|
79
133
|
const outerDistance = foundAccessibleDistance;
|
|
80
134
|
const innerDistance = foundAccessibleDistance - options.step;
|
|
81
135
|
console.log(`[generateSmartPoints] Refining between ${innerDistance} and ${outerDistance}`);
|
|
82
136
|
|
|
83
|
-
//
|
|
84
|
-
let left = innerDistance;
|
|
85
|
-
let right = outerDistance;
|
|
137
|
+
// Linear search from innerDistance+1 to outerDistance to find the closest accessible point
|
|
86
138
|
let bestDistance = outerDistance;
|
|
87
139
|
|
|
88
|
-
//
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
console.log(`[generateSmartPoints] Binary search testing distance ${mid.toFixed(1)}: (${testPoint.x}, ${testPoint.y})`);
|
|
140
|
+
// Search forward from inner to outer to find the first accessible point
|
|
141
|
+
for (let dist = innerDistance + 1; dist < outerDistance; dist++) {
|
|
142
|
+
const testPoint = new _geometry.Point(anchor.x + actualDirection.x * dist, anchor.y + actualDirection.y * dist).round(options.precision);
|
|
143
|
+
console.log(`[generateSmartPoints] Linear search testing distance ${dist}: (${testPoint.x}, ${testPoint.y})`);
|
|
93
144
|
if (map.isAccessible(testPoint)) {
|
|
94
|
-
bestDistance =
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
} else {
|
|
98
|
-
left = mid;
|
|
99
|
-
console.log(`[generateSmartPoints] Point blocked, searching further (left=${left})`);
|
|
145
|
+
bestDistance = dist;
|
|
146
|
+
console.log(`[generateSmartPoints] Found closest accessible point at distance ${dist}`);
|
|
147
|
+
break;
|
|
100
148
|
}
|
|
101
149
|
}
|
|
102
150
|
|
|
@@ -234,12 +282,17 @@ function findRoute(sourceBBox, targetBBox, sourceAnchor, targetAnchor, map, opti
|
|
|
234
282
|
continue;
|
|
235
283
|
}
|
|
236
284
|
|
|
237
|
-
//
|
|
238
|
-
const neighborPoint = (
|
|
285
|
+
// Find the closest accessible neighbor in this direction using binary search
|
|
286
|
+
const neighborPoint = findAccessibleNeighbor(currentPoint, direction.offsetX, direction.offsetY, options.step, map, precision);
|
|
287
|
+
|
|
288
|
+
// Skip if no accessible neighbor found in this direction
|
|
289
|
+
if (!neighborPoint) {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
239
292
|
const neighborKey = (0, _utils.getKey)(neighborPoint);
|
|
240
293
|
|
|
241
|
-
// Skip if closed
|
|
242
|
-
if (openSet.isClose(neighborKey)
|
|
294
|
+
// Skip if already closed
|
|
295
|
+
if (openSet.isClose(neighborKey)) {
|
|
243
296
|
continue;
|
|
244
297
|
}
|
|
245
298
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findRoute.d.ts","sourceRoot":"","sources":["../../src/pathfinder/findRoute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"findRoute.d.ts","sourceRoot":"","sources":["../../src/pathfinder/findRoute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAyN9C;;GAEG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,SAAS,EACrB,UAAU,EAAE,SAAS,EACrB,YAAY,EAAE,KAAK,EACnB,YAAY,EAAE,KAAK,EACnB,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,eAAe,GACvB,KAAK,EAAE,GAAG,IAAI,CAqThB"}
|
|
@@ -5,6 +5,61 @@ import { Point } from "../geometry";
|
|
|
5
5
|
import { SortedSet } from "./SortedSet";
|
|
6
6
|
import { getGrid, round, getDirectionAngle, getDirectionChange, getGridOffsets, getRectPoints, getCost, getKey, reconstructRoute } from "../utils";
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Find the closest accessible point in a given direction using step-based search with linear refinement
|
|
10
|
+
*
|
|
11
|
+
* Algorithm:
|
|
12
|
+
* 1. Try moving by step increments (step, 2*step, 3*step...) until finding an accessible point
|
|
13
|
+
* 2. Once found, linearly search backward from (n-1)*step+1 to n*step to find the closest accessible point
|
|
14
|
+
* 3. Returns null if no accessible point found within maxSteps
|
|
15
|
+
*/
|
|
16
|
+
function findAccessibleNeighbor(from, directionX, directionY, step, map, precision) {
|
|
17
|
+
var maxSteps = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : 20;
|
|
18
|
+
// Normalize direction
|
|
19
|
+
var length = Math.sqrt(directionX * directionX + directionY * directionY);
|
|
20
|
+
var ndx = directionX / length;
|
|
21
|
+
var ndy = directionY / length;
|
|
22
|
+
|
|
23
|
+
// 1. Try the first step directly (most common case)
|
|
24
|
+
var firstStepPoint = new Point(from.x + ndx * step, from.y + ndy * step).round(precision);
|
|
25
|
+
if (map.isAccessible(firstStepPoint)) {
|
|
26
|
+
// First step is accessible, no need for refinement
|
|
27
|
+
return firstStepPoint;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 2. First step blocked, search outward by step increments
|
|
31
|
+
var stepMultiplier = 2;
|
|
32
|
+
var foundAccessibleDistance = -1;
|
|
33
|
+
while (stepMultiplier <= maxSteps) {
|
|
34
|
+
var distance = stepMultiplier * step;
|
|
35
|
+
var testPoint = new Point(from.x + ndx * distance, from.y + ndy * distance).round(precision);
|
|
36
|
+
if (map.isAccessible(testPoint)) {
|
|
37
|
+
foundAccessibleDistance = distance;
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
stepMultiplier++;
|
|
41
|
+
}
|
|
42
|
+
if (foundAccessibleDistance < 0) {
|
|
43
|
+
return null; // No accessible point found
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 3. Linear search within the last step interval to find closest accessible point
|
|
47
|
+
// Search from (n-1)*step+1 to n*step
|
|
48
|
+
var outerDistance = foundAccessibleDistance;
|
|
49
|
+
var innerDistance = foundAccessibleDistance - step;
|
|
50
|
+
|
|
51
|
+
// Search backward from outer to inner to find the closest accessible point
|
|
52
|
+
for (var dist = innerDistance + 1; dist < outerDistance; dist++) {
|
|
53
|
+
var _testPoint = new Point(from.x + ndx * dist, from.y + ndy * dist).round(precision);
|
|
54
|
+
if (map.isAccessible(_testPoint)) {
|
|
55
|
+
return _testPoint;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// If no closer point found, return the outer distance point
|
|
60
|
+
return new Point(from.x + ndx * outerDistance, from.y + ndy * outerDistance).round(precision);
|
|
61
|
+
}
|
|
62
|
+
|
|
8
63
|
/**
|
|
9
64
|
* Generate smart points based on position using extensionDistance and binary search
|
|
10
65
|
*
|
|
@@ -73,29 +128,23 @@ function generateSmartPoints(anchor, bbox, position, grid, map, options) {
|
|
|
73
128
|
stepMultiplier++;
|
|
74
129
|
}
|
|
75
130
|
|
|
76
|
-
// 3. If we found an accessible point, refine by
|
|
131
|
+
// 3. If we found an accessible point, refine by linear search within the last step interval
|
|
77
132
|
if (foundAccessibleDistance > 0) {
|
|
78
133
|
var outerDistance = foundAccessibleDistance;
|
|
79
134
|
var innerDistance = foundAccessibleDistance - options.step;
|
|
80
135
|
console.log("[generateSmartPoints] Refining between ".concat(innerDistance, " and ").concat(outerDistance));
|
|
81
136
|
|
|
82
|
-
//
|
|
83
|
-
var left = innerDistance;
|
|
84
|
-
var right = outerDistance;
|
|
137
|
+
// Linear search from innerDistance+1 to outerDistance to find the closest accessible point
|
|
85
138
|
var bestDistance = outerDistance;
|
|
86
139
|
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
var
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
console.log("[generateSmartPoints] Point accessible, searching closer (right=".concat(right, ")"));
|
|
96
|
-
} else {
|
|
97
|
-
left = mid;
|
|
98
|
-
console.log("[generateSmartPoints] Point blocked, searching further (left=".concat(left, ")"));
|
|
140
|
+
// Search forward from inner to outer to find the first accessible point
|
|
141
|
+
for (var dist = innerDistance + 1; dist < outerDistance; dist++) {
|
|
142
|
+
var _testPoint2 = new Point(anchor.x + actualDirection.x * dist, anchor.y + actualDirection.y * dist).round(options.precision);
|
|
143
|
+
console.log("[generateSmartPoints] Linear search testing distance ".concat(dist, ": (").concat(_testPoint2.x, ", ").concat(_testPoint2.y, ")"));
|
|
144
|
+
if (map.isAccessible(_testPoint2)) {
|
|
145
|
+
bestDistance = dist;
|
|
146
|
+
console.log("[generateSmartPoints] Found closest accessible point at distance ".concat(dist));
|
|
147
|
+
break;
|
|
99
148
|
}
|
|
100
149
|
}
|
|
101
150
|
|
|
@@ -267,12 +316,17 @@ export function findRoute(sourceBBox, targetBBox, sourceAnchor, targetAnchor, ma
|
|
|
267
316
|
continue;
|
|
268
317
|
}
|
|
269
318
|
|
|
270
|
-
//
|
|
271
|
-
var neighborPoint =
|
|
319
|
+
// Find the closest accessible neighbor in this direction using binary search
|
|
320
|
+
var neighborPoint = findAccessibleNeighbor(currentPoint, direction.offsetX, direction.offsetY, options.step, map, precision);
|
|
321
|
+
|
|
322
|
+
// Skip if no accessible neighbor found in this direction
|
|
323
|
+
if (!neighborPoint) {
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
272
326
|
var neighborKey = getKey(neighborPoint);
|
|
273
327
|
|
|
274
|
-
// Skip if closed
|
|
275
|
-
if (openSet.isClose(neighborKey)
|
|
328
|
+
// Skip if already closed
|
|
329
|
+
if (openSet.isClose(neighborKey)) {
|
|
276
330
|
continue;
|
|
277
331
|
}
|
|
278
332
|
|
package/package.json
CHANGED