@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;AA+I9C;;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,CA6ShB"}
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 binary search within the last step interval
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
- // Binary search within the last step interval to find the closest accessible point
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
- // Binary search with precision of 1px
89
- while (right - left > 1) {
90
- const mid = (left + right) / 2;
91
- const testPoint = new _geometry.Point(anchor.x + actualDirection.x * mid, anchor.y + actualDirection.y * mid).round(options.precision);
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 = mid;
95
- right = mid;
96
- console.log(`[generateSmartPoints] Point accessible, searching closer (right=${right})`);
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
- // Calculate neighbor point (no grid alignment)
238
- const neighborPoint = (0, _utils.round)(currentPoint.clone().translate(direction.gridOffsetX || 0, direction.gridOffsetY || 0), precision);
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 or not accessible
242
- if (openSet.isClose(neighborKey) || !map.isAccessible(neighborPoint)) {
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;AA+I9C;;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,CA6ShB"}
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 binary search within the last step interval
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
- // Binary search within the last step interval to find the closest accessible point
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
- // Binary search with precision of 1px
88
- while (right - left > 1) {
89
- var mid = (left + right) / 2;
90
- var _testPoint = new Point(anchor.x + actualDirection.x * mid, anchor.y + actualDirection.y * mid).round(options.precision);
91
- console.log("[generateSmartPoints] Binary search testing distance ".concat(mid.toFixed(1), ": (").concat(_testPoint.x, ", ").concat(_testPoint.y, ")"));
92
- if (map.isAccessible(_testPoint)) {
93
- bestDistance = mid;
94
- right = mid;
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
- // Calculate neighbor point (no grid alignment)
271
- var neighborPoint = round(currentPoint.clone().translate(direction.gridOffsetX || 0, direction.gridOffsetY || 0), precision);
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 or not accessible
275
- if (openSet.isClose(neighborKey) || !map.isAccessible(neighborPoint)) {
328
+ // Skip if already closed
329
+ if (openSet.isClose(neighborKey)) {
276
330
  continue;
277
331
  }
278
332
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rxflow/manhattan",
3
- "version": "0.0.1-alpha.12",
3
+ "version": "0.0.1-alpha.13",
4
4
  "description": "Manhattan routing algorithm for ReactFlow - generates orthogonal paths with obstacle avoidance",
5
5
  "keywords": [
6
6
  "reactflow",