@rxflow/manhattan 0.0.2-alpha.8 → 0.0.2

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.
Files changed (157) hide show
  1. package/README.md +214 -10
  2. package/esm/getManHattanPath.js +92 -69
  3. package/esm/obstacle/ObstacleMap.js +218 -99
  4. package/esm/obstacle/QuadTree.js +488 -0
  5. package/esm/options/resolver.js +147 -18
  6. package/esm/pathfinder/PathCache.js +278 -0
  7. package/esm/pathfinder/findRoute.js +98 -44
  8. package/esm/pathfinder/index.js +2 -1
  9. package/esm/svg/pathConverter.js +170 -1
  10. package/esm/utils/AdaptiveStepCalculator.js +252 -0
  11. package/esm/utils/ErrorRecovery.js +499 -0
  12. package/esm/utils/GlobalGrid.js +259 -0
  13. package/esm/utils/PerformanceMonitor.js +360 -0
  14. package/esm/utils/getAnchorPoints.js +0 -4
  15. package/esm/utils/grid.js +18 -13
  16. package/esm/utils/heuristics.js +144 -0
  17. package/esm/utils/index.js +7 -1
  18. package/esm/utils/pathProcessing.js +270 -0
  19. package/esm/utils/pathValidation.js +0 -1
  20. package/esm/utils/rect.js +11 -4
  21. package/esm/utils/route.js +18 -2
  22. package/package.json +10 -2
  23. package/cjs/geometry/Line.d.ts +0 -21
  24. package/cjs/geometry/Line.d.ts.map +0 -1
  25. package/cjs/geometry/Line.js +0 -88
  26. package/cjs/geometry/Point.d.ts +0 -49
  27. package/cjs/geometry/Point.d.ts.map +0 -1
  28. package/cjs/geometry/Point.js +0 -94
  29. package/cjs/geometry/Rectangle.d.ts +0 -41
  30. package/cjs/geometry/Rectangle.d.ts.map +0 -1
  31. package/cjs/geometry/Rectangle.js +0 -65
  32. package/cjs/geometry/collision.d.ts +0 -15
  33. package/cjs/geometry/collision.d.ts.map +0 -1
  34. package/cjs/geometry/collision.js +0 -81
  35. package/cjs/geometry/index.d.ts +0 -5
  36. package/cjs/geometry/index.d.ts.map +0 -1
  37. package/cjs/geometry/index.js +0 -45
  38. package/cjs/getManHattanPath.d.ts +0 -53
  39. package/cjs/getManHattanPath.d.ts.map +0 -1
  40. package/cjs/getManHattanPath.js +0 -418
  41. package/cjs/index.d.ts +0 -16
  42. package/cjs/index.d.ts.map +0 -1
  43. package/cjs/index.js +0 -117
  44. package/cjs/obstacle/ObstacleMap.d.ts +0 -34
  45. package/cjs/obstacle/ObstacleMap.d.ts.map +0 -1
  46. package/cjs/obstacle/ObstacleMap.js +0 -223
  47. package/cjs/obstacle/index.d.ts +0 -2
  48. package/cjs/obstacle/index.d.ts.map +0 -1
  49. package/cjs/obstacle/index.js +0 -12
  50. package/cjs/options/defaults.d.ts +0 -16
  51. package/cjs/options/defaults.d.ts.map +0 -1
  52. package/cjs/options/defaults.js +0 -39
  53. package/cjs/options/index.d.ts +0 -4
  54. package/cjs/options/index.d.ts.map +0 -1
  55. package/cjs/options/index.js +0 -38
  56. package/cjs/options/resolver.d.ts +0 -10
  57. package/cjs/options/resolver.d.ts.map +0 -1
  58. package/cjs/options/resolver.js +0 -120
  59. package/cjs/options/types.d.ts +0 -169
  60. package/cjs/options/types.d.ts.map +0 -1
  61. package/cjs/options/types.js +0 -5
  62. package/cjs/pathfinder/SortedSet.d.ts +0 -35
  63. package/cjs/pathfinder/SortedSet.d.ts.map +0 -1
  64. package/cjs/pathfinder/SortedSet.js +0 -95
  65. package/cjs/pathfinder/findRoute.d.ts +0 -8
  66. package/cjs/pathfinder/findRoute.d.ts.map +0 -1
  67. package/cjs/pathfinder/findRoute.js +0 -330
  68. package/cjs/pathfinder/index.d.ts +0 -3
  69. package/cjs/pathfinder/index.d.ts.map +0 -1
  70. package/cjs/pathfinder/index.js +0 -19
  71. package/cjs/svg/index.d.ts +0 -3
  72. package/cjs/svg/index.d.ts.map +0 -1
  73. package/cjs/svg/index.js +0 -31
  74. package/cjs/svg/pathConverter.d.ts +0 -10
  75. package/cjs/svg/pathConverter.d.ts.map +0 -1
  76. package/cjs/svg/pathConverter.js +0 -116
  77. package/cjs/svg/pathParser.d.ts +0 -11
  78. package/cjs/svg/pathParser.d.ts.map +0 -1
  79. package/cjs/svg/pathParser.js +0 -76
  80. package/cjs/utils/direction.d.ts +0 -24
  81. package/cjs/utils/direction.d.ts.map +0 -1
  82. package/cjs/utils/direction.js +0 -54
  83. package/cjs/utils/getAnchorPoints.d.ts +0 -15
  84. package/cjs/utils/getAnchorPoints.d.ts.map +0 -1
  85. package/cjs/utils/getAnchorPoints.js +0 -75
  86. package/cjs/utils/grid.d.ts +0 -27
  87. package/cjs/utils/grid.d.ts.map +0 -1
  88. package/cjs/utils/grid.js +0 -66
  89. package/cjs/utils/index.d.ts +0 -8
  90. package/cjs/utils/index.d.ts.map +0 -1
  91. package/cjs/utils/index.js +0 -82
  92. package/cjs/utils/node.d.ts +0 -27
  93. package/cjs/utils/node.d.ts.map +0 -1
  94. package/cjs/utils/node.js +0 -36
  95. package/cjs/utils/pathValidation.d.ts +0 -11
  96. package/cjs/utils/pathValidation.d.ts.map +0 -1
  97. package/cjs/utils/pathValidation.js +0 -130
  98. package/cjs/utils/rect.d.ts +0 -9
  99. package/cjs/utils/rect.d.ts.map +0 -1
  100. package/cjs/utils/rect.js +0 -103
  101. package/cjs/utils/route.d.ts +0 -19
  102. package/cjs/utils/route.d.ts.map +0 -1
  103. package/cjs/utils/route.js +0 -76
  104. package/esm/geometry/Line.d.ts +0 -21
  105. package/esm/geometry/Line.d.ts.map +0 -1
  106. package/esm/geometry/Point.d.ts +0 -49
  107. package/esm/geometry/Point.d.ts.map +0 -1
  108. package/esm/geometry/Rectangle.d.ts +0 -41
  109. package/esm/geometry/Rectangle.d.ts.map +0 -1
  110. package/esm/geometry/collision.d.ts +0 -15
  111. package/esm/geometry/collision.d.ts.map +0 -1
  112. package/esm/geometry/index.d.ts +0 -5
  113. package/esm/geometry/index.d.ts.map +0 -1
  114. package/esm/getManHattanPath.d.ts +0 -53
  115. package/esm/getManHattanPath.d.ts.map +0 -1
  116. package/esm/index.d.ts +0 -16
  117. package/esm/index.d.ts.map +0 -1
  118. package/esm/obstacle/ObstacleMap.d.ts +0 -34
  119. package/esm/obstacle/ObstacleMap.d.ts.map +0 -1
  120. package/esm/obstacle/index.d.ts +0 -2
  121. package/esm/obstacle/index.d.ts.map +0 -1
  122. package/esm/options/defaults.d.ts +0 -16
  123. package/esm/options/defaults.d.ts.map +0 -1
  124. package/esm/options/index.d.ts +0 -4
  125. package/esm/options/index.d.ts.map +0 -1
  126. package/esm/options/resolver.d.ts +0 -10
  127. package/esm/options/resolver.d.ts.map +0 -1
  128. package/esm/options/types.d.ts +0 -169
  129. package/esm/options/types.d.ts.map +0 -1
  130. package/esm/pathfinder/SortedSet.d.ts +0 -35
  131. package/esm/pathfinder/SortedSet.d.ts.map +0 -1
  132. package/esm/pathfinder/findRoute.d.ts +0 -8
  133. package/esm/pathfinder/findRoute.d.ts.map +0 -1
  134. package/esm/pathfinder/index.d.ts +0 -3
  135. package/esm/pathfinder/index.d.ts.map +0 -1
  136. package/esm/svg/index.d.ts +0 -3
  137. package/esm/svg/index.d.ts.map +0 -1
  138. package/esm/svg/pathConverter.d.ts +0 -10
  139. package/esm/svg/pathConverter.d.ts.map +0 -1
  140. package/esm/svg/pathParser.d.ts +0 -11
  141. package/esm/svg/pathParser.d.ts.map +0 -1
  142. package/esm/utils/direction.d.ts +0 -24
  143. package/esm/utils/direction.d.ts.map +0 -1
  144. package/esm/utils/getAnchorPoints.d.ts +0 -15
  145. package/esm/utils/getAnchorPoints.d.ts.map +0 -1
  146. package/esm/utils/grid.d.ts +0 -27
  147. package/esm/utils/grid.d.ts.map +0 -1
  148. package/esm/utils/index.d.ts +0 -8
  149. package/esm/utils/index.d.ts.map +0 -1
  150. package/esm/utils/node.d.ts +0 -27
  151. package/esm/utils/node.d.ts.map +0 -1
  152. package/esm/utils/pathValidation.d.ts +0 -11
  153. package/esm/utils/pathValidation.d.ts.map +0 -1
  154. package/esm/utils/rect.d.ts +0 -9
  155. package/esm/utils/rect.d.ts.map +0 -1
  156. package/esm/utils/route.d.ts +0 -19
  157. package/esm/utils/route.d.ts.map +0 -1
@@ -10,28 +10,59 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
10
10
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
11
11
  import { Point, Rectangle } from "../geometry";
12
12
  import { getNodePosition, getNodeDimensions } from "../utils";
13
+ import { createQuadTreeFromRects } from "./QuadTree";
13
14
 
14
15
  /**
15
16
  * ObstacleMap class for managing obstacles in pathfinding
16
- * Uses a grid-based spatial partitioning for efficient queries
17
+ * Feature: manhattan-optimization
18
+ *
19
+ * Uses QuadTree for efficient spatial queries (O(log n) instead of O(n))
20
+ * Includes query caching for repeated accessibility checks
17
21
  */
18
22
  export var ObstacleMap = /*#__PURE__*/function () {
19
23
  function ObstacleMap(options) {
20
24
  _classCallCheck(this, ObstacleMap);
21
25
  _defineProperty(this, "options", void 0);
22
- _defineProperty(this, "mapGridSize", void 0);
23
- _defineProperty(this, "map", void 0);
26
+ _defineProperty(this, "quadTree", null);
27
+ _defineProperty(this, "obstacles", []);
24
28
  _defineProperty(this, "sourceAnchor", void 0);
25
29
  _defineProperty(this, "targetAnchor", void 0);
30
+ // Query cache for repeated accessibility checks
31
+ _defineProperty(this, "accessibilityCache", new Map());
32
+ _defineProperty(this, "cacheHits", 0);
33
+ _defineProperty(this, "cacheMisses", 0);
26
34
  this.options = options;
27
- this.mapGridSize = 100;
28
- this.map = new Map();
29
35
  }
30
36
 
31
37
  /**
32
- * Build obstacle map from node lookup
38
+ * Get cache statistics for performance monitoring
33
39
  */
34
40
  _createClass(ObstacleMap, [{
41
+ key: "getCacheStats",
42
+ value: function getCacheStats() {
43
+ var total = this.cacheHits + this.cacheMisses;
44
+ return {
45
+ hits: this.cacheHits,
46
+ misses: this.cacheMisses,
47
+ hitRate: total > 0 ? this.cacheHits / total : 0
48
+ };
49
+ }
50
+
51
+ /**
52
+ * Clear the accessibility cache
53
+ */
54
+ }, {
55
+ key: "clearCache",
56
+ value: function clearCache() {
57
+ this.accessibilityCache.clear();
58
+ this.cacheHits = 0;
59
+ this.cacheMisses = 0;
60
+ }
61
+
62
+ /**
63
+ * Build obstacle map from node lookup using QuadTree
64
+ */
65
+ }, {
35
66
  key: "build",
36
67
  value: function build(nodeLookup, sourceNodeId, targetNodeId, sourceAnchor, targetAnchor) {
37
68
  var _this = this;
@@ -45,17 +76,19 @@ export var ObstacleMap = /*#__PURE__*/function () {
45
76
  this.sourceAnchor = sourceAnchor;
46
77
  this.targetAnchor = targetAnchor;
47
78
 
48
- // Iterate through all nodes
79
+ // Clear previous data
80
+ this.obstacles = [];
81
+ this.clearCache();
82
+
83
+ // Collect all obstacles
49
84
  nodeLookup.forEach(function (node) {
50
85
  // Check if node should be excluded
51
86
  var isExcludedNode = excludeNodes.includes(node.id);
52
87
  var isExcludedShape = node.type ? excludeShapes.includes(node.type) : false;
53
88
  var isSourceTerminal = excludeTerminals.includes('source') && node.id === sourceNodeId;
54
89
  var isTargetTerminal = excludeTerminals.includes('target') && node.id === targetNodeId;
55
- var isSource = node.id === sourceNodeId;
56
- var isTarget = node.id === targetNodeId;
57
90
 
58
- // Skip if node should be excluded (but not source/target - we handle them specially)
91
+ // Skip if node should be excluded
59
92
  if (isExcludedNode || isExcludedShape || isSourceTerminal || isTargetTerminal) {
60
93
  return;
61
94
  }
@@ -64,129 +97,215 @@ export var ObstacleMap = /*#__PURE__*/function () {
64
97
  var position = getNodePosition(node);
65
98
  var dimensions = getNodeDimensions(node);
66
99
  var bbox = new Rectangle(position.x, position.y, dimensions.width, dimensions.height).moveAndExpand(paddingBox);
67
-
68
- // For source and target nodes, add them as full obstacles
69
- // We'll handle anchor accessibility in isAccessible() method
70
- if (isSource) {
71
- console.log('[ObstacleMap] Adding source node as obstacle:');
72
- console.log(' Node ID:', node.id);
73
- console.log(' BBox:', "(".concat(bbox.x, ", ").concat(bbox.y, ", ").concat(bbox.width, ", ").concat(bbox.height, ")"));
74
- console.log(' Anchor:', sourceAnchor ? "(".concat(sourceAnchor.x, ", ").concat(sourceAnchor.y, ")") : 'none');
75
- } else if (isTarget) {
76
- console.log('[ObstacleMap] Adding target node as obstacle:');
77
- console.log(' Node ID:', node.id);
78
- console.log(' BBox:', "(".concat(bbox.x, ", ").concat(bbox.y, ", ").concat(bbox.width, ", ").concat(bbox.height, ")"));
79
- console.log(' Anchor:', targetAnchor ? "(".concat(targetAnchor.x, ", ").concat(targetAnchor.y, ")") : 'none');
80
- }
81
-
82
- // Map bbox to grid cells
83
- var origin = bbox.getOrigin().snapToGrid(_this.mapGridSize);
84
- var corner = bbox.getCorner().snapToGrid(_this.mapGridSize);
85
- for (var x = origin.x; x <= corner.x; x += _this.mapGridSize) {
86
- for (var y = origin.y; y <= corner.y; y += _this.mapGridSize) {
87
- var key = new Point(x, y).toString();
88
- if (!_this.map.has(key)) {
89
- _this.map.set(key, []);
90
- }
91
- _this.map.get(key).push(bbox);
92
- }
93
- }
100
+ _this.obstacles.push({
101
+ bounds: bbox,
102
+ nodeId: node.id
103
+ });
94
104
  });
95
- return this;
96
- }
97
105
 
98
- /**
99
- * Shrink bbox to exclude the area around the anchor point
100
- * This allows paths to start/end at the anchor but prevents crossing the node
101
- */
102
- }, {
103
- key: "shrinkBBoxAroundAnchor",
104
- value: function shrinkBBoxAroundAnchor(bbox, anchor, nodePosition, nodeDimensions) {
105
- var tolerance = 1;
106
- var step = this.options.step || 10;
107
- var margin = step * 3; // Increased margin for better clearance
108
-
109
- // Determine which edge the anchor is on (relative to original node position)
110
- var onLeft = Math.abs(anchor.x - nodePosition.x) < tolerance;
111
- var onRight = Math.abs(anchor.x - (nodePosition.x + nodeDimensions.width)) < tolerance;
112
- var onTop = Math.abs(anchor.y - nodePosition.y) < tolerance;
113
- var onBottom = Math.abs(anchor.y - (nodePosition.y + nodeDimensions.height)) < tolerance;
114
- console.log('[shrinkBBoxAroundAnchor] Edge detection:');
115
- console.log(' anchor.x:', anchor.x, 'nodePosition.x:', nodePosition.x, 'diff:', Math.abs(anchor.x - nodePosition.x));
116
- console.log(' anchor.x:', anchor.x, 'nodeRight:', nodePosition.x + nodeDimensions.width, 'diff:', Math.abs(anchor.x - (nodePosition.x + nodeDimensions.width)));
117
- console.log(' onLeft:', onLeft, 'onRight:', onRight, 'onTop:', onTop, 'onBottom:', onBottom);
118
- console.log(' margin:', margin);
119
-
120
- // Shrink bbox based on anchor position
121
- if (onLeft) {
122
- // Anchor on left edge - exclude left portion
123
- return new Rectangle(bbox.x + margin, bbox.y, Math.max(0, bbox.width - margin), bbox.height);
124
- } else if (onRight) {
125
- // Anchor on right edge - exclude right portion
126
- return new Rectangle(bbox.x, bbox.y, Math.max(0, bbox.width - margin), bbox.height);
127
- } else if (onTop) {
128
- // Anchor on top edge - exclude top portion
129
- return new Rectangle(bbox.x, bbox.y + margin, bbox.width, Math.max(0, bbox.height - margin));
130
- } else if (onBottom) {
131
- // Anchor on bottom edge - exclude bottom portion
132
- return new Rectangle(bbox.x, bbox.y, bbox.width, Math.max(0, bbox.height - margin));
133
- }
134
-
135
- // If anchor is not on an edge, return original bbox
136
- return bbox;
106
+ // Build QuadTree from obstacles
107
+ this.quadTree = createQuadTreeFromRects(this.obstacles.map(function (o) {
108
+ return {
109
+ bounds: o.bounds,
110
+ data: o.nodeId
111
+ };
112
+ }));
113
+ return this;
137
114
  }
138
115
 
139
116
  /**
140
117
  * Check if a point is accessible (not inside any obstacle)
141
- * Uses binary search optimization: step -> step/2 -> step/4 -> ... -> 1px
118
+ * Uses QuadTree for efficient spatial queries with caching
142
119
  */
143
120
  }, {
144
121
  key: "isAccessible",
145
122
  value: function isAccessible(point) {
146
123
  var checkRadius = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
147
- var key = point.clone().snapToGrid(this.mapGridSize).toString();
148
- var rects = this.map.get(key);
149
- if (!rects) {
150
- return true;
124
+ // Generate cache key
125
+ var cacheKey = "".concat(point.x, ",").concat(point.y, ",").concat(checkRadius);
126
+
127
+ // Check cache first
128
+ if (this.accessibilityCache.has(cacheKey)) {
129
+ this.cacheHits++;
130
+ return this.accessibilityCache.get(cacheKey);
151
131
  }
132
+ this.cacheMisses++;
152
133
 
153
134
  // Check if point is near an anchor - if so, allow it
154
135
  var margin = (this.options.step || 10) * 3;
155
136
  if (this.sourceAnchor) {
156
137
  var distToSource = Math.abs(point.x - this.sourceAnchor.x) + Math.abs(point.y - this.sourceAnchor.y);
157
138
  if (distToSource < margin) {
158
- console.log("[isAccessible] Point (".concat(point.x, ", ").concat(point.y, "): accessible (near source anchor)"));
139
+ this.accessibilityCache.set(cacheKey, true);
159
140
  return true;
160
141
  }
161
142
  }
162
143
  if (this.targetAnchor) {
163
144
  var distToTarget = Math.abs(point.x - this.targetAnchor.x) + Math.abs(point.y - this.targetAnchor.y);
164
145
  if (distToTarget < margin) {
165
- console.log("[isAccessible] Point (".concat(point.x, ", ").concat(point.y, "): accessible (near target anchor)"));
146
+ this.accessibilityCache.set(cacheKey, true);
166
147
  return true;
167
148
  }
168
149
  }
169
150
 
151
+ // If no QuadTree, point is accessible
152
+ if (!this.quadTree) {
153
+ this.accessibilityCache.set(cacheKey, true);
154
+ return true;
155
+ }
156
+
157
+ // Query QuadTree for obstacles at this point
158
+ var obstacles = this.quadTree.queryPoint(point);
159
+
170
160
  // If checkRadius is specified, use binary search to find accessible points
171
- if (checkRadius > 0) {
172
- return this.isAccessibleWithBinarySearch(point, checkRadius, rects);
161
+ if (checkRadius > 0 && obstacles.length > 0) {
162
+ var result = this.isAccessibleWithBinarySearch(point, checkRadius, obstacles.map(function (o) {
163
+ return o.bounds;
164
+ }));
165
+ this.accessibilityCache.set(cacheKey, result);
166
+ return result;
173
167
  }
174
- var accessible = rects.every(function (rect) {
175
- return !rect.containsPoint(point);
176
- });
168
+ var accessible = obstacles.length === 0;
169
+ this.accessibilityCache.set(cacheKey, accessible);
170
+ return accessible;
171
+ }
177
172
 
178
- // Debug: log points on the direct path
179
- if (point.y === 40 && point.x >= 0 && point.x <= 545) {
180
- console.log("[isAccessible] Point (".concat(point.x, ", ").concat(point.y, "): ").concat(accessible ? 'accessible' : 'BLOCKED'));
173
+ /**
174
+ * Check if an anchor point has sufficient clearance around it
175
+ * This ensures the path can start/end at the anchor without being blocked
176
+ */
177
+ }, {
178
+ key: "hasAnchorClearance",
179
+ value: function hasAnchorClearance(anchor, direction) {
180
+ var step = this.options.step || 10;
181
+ var clearanceDistance = step * 2;
182
+
183
+ // Direction vectors
184
+ var directionVectors = {
185
+ top: {
186
+ dx: 0,
187
+ dy: -1
188
+ },
189
+ right: {
190
+ dx: 1,
191
+ dy: 0
192
+ },
193
+ bottom: {
194
+ dx: 0,
195
+ dy: 1
196
+ },
197
+ left: {
198
+ dx: -1,
199
+ dy: 0
200
+ }
201
+ };
202
+ var dir = directionVectors[direction];
203
+ if (!dir) return true;
204
+
205
+ // Check points along the direction
206
+ for (var dist = step; dist <= clearanceDistance; dist += step) {
207
+ var testPoint = new Point(anchor.x + dir.dx * dist, anchor.y + dir.dy * dist);
208
+
209
+ // Temporarily remove anchor from consideration
210
+ var originalSourceAnchor = this.sourceAnchor;
211
+ var originalTargetAnchor = this.targetAnchor;
212
+ this.sourceAnchor = undefined;
213
+ this.targetAnchor = undefined;
214
+ var accessible = this.isAccessibleWithoutCache(testPoint);
215
+
216
+ // Restore anchors
217
+ this.sourceAnchor = originalSourceAnchor;
218
+ this.targetAnchor = originalTargetAnchor;
181
219
  if (!accessible) {
182
- rects.forEach(function (rect, i) {
183
- if (rect.containsPoint(point)) {
184
- console.log(" Blocked by rect ".concat(i, ": (").concat(rect.x, ", ").concat(rect.y, ", ").concat(rect.width, ", ").concat(rect.height, ")"));
185
- }
186
- });
220
+ return false;
187
221
  }
188
222
  }
189
- return accessible;
223
+ return true;
224
+ }
225
+
226
+ /**
227
+ * Check accessibility without using cache (for internal use)
228
+ */
229
+ }, {
230
+ key: "isAccessibleWithoutCache",
231
+ value: function isAccessibleWithoutCache(point) {
232
+ if (!this.quadTree) {
233
+ return true;
234
+ }
235
+ var obstacles = this.quadTree.queryPoint(point);
236
+ return obstacles.length === 0;
237
+ }
238
+
239
+ /**
240
+ * Find the nearest accessible point from an anchor in a given direction
241
+ * Uses binary search for efficiency
242
+ */
243
+ }, {
244
+ key: "findNearestAccessiblePoint",
245
+ value: function findNearestAccessiblePoint(anchor, direction, maxDistance) {
246
+ var directionVectors = {
247
+ top: {
248
+ dx: 0,
249
+ dy: -1
250
+ },
251
+ right: {
252
+ dx: 1,
253
+ dy: 0
254
+ },
255
+ bottom: {
256
+ dx: 0,
257
+ dy: 1
258
+ },
259
+ left: {
260
+ dx: -1,
261
+ dy: 0
262
+ }
263
+ };
264
+ var dir = directionVectors[direction];
265
+ if (!dir) return null;
266
+ var step = this.options.step || 10;
267
+
268
+ // First, find an accessible point using linear search
269
+ var foundDistance = -1;
270
+ for (var dist = step; dist <= maxDistance; dist += step) {
271
+ var testPoint = new Point(anchor.x + dir.dx * dist, anchor.y + dir.dy * dist);
272
+ if (this.isAccessible(testPoint)) {
273
+ foundDistance = dist;
274
+ break;
275
+ }
276
+ }
277
+ if (foundDistance < 0) {
278
+ return null;
279
+ }
280
+
281
+ // Binary search to find the closest accessible point
282
+ var left = Math.max(0, foundDistance - step);
283
+ var right = foundDistance;
284
+ var bestDistance = foundDistance;
285
+ while (right - left > 1) {
286
+ var mid = Math.floor((left + right) / 2);
287
+ var _testPoint = new Point(anchor.x + dir.dx * mid, anchor.y + dir.dy * mid);
288
+ if (this.isAccessible(_testPoint)) {
289
+ bestDistance = mid;
290
+ right = mid;
291
+ } else {
292
+ left = mid;
293
+ }
294
+ }
295
+ return new Point(anchor.x + dir.dx * bestDistance, anchor.y + dir.dy * bestDistance);
296
+ }
297
+
298
+ /**
299
+ * Batch check accessibility for multiple points (optimized)
300
+ * Returns array of booleans in same order as input points
301
+ */
302
+ }, {
303
+ key: "areAccessible",
304
+ value: function areAccessible(points) {
305
+ var _this2 = this;
306
+ return points.map(function (point) {
307
+ return _this2.isAccessible(point);
308
+ });
190
309
  }
191
310
 
192
311
  /**