@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.
- package/README.md +214 -10
- package/esm/getManHattanPath.js +92 -69
- package/esm/obstacle/ObstacleMap.js +218 -99
- package/esm/obstacle/QuadTree.js +488 -0
- package/esm/options/resolver.js +147 -18
- package/esm/pathfinder/PathCache.js +278 -0
- package/esm/pathfinder/findRoute.js +98 -44
- package/esm/pathfinder/index.js +2 -1
- package/esm/svg/pathConverter.js +170 -1
- package/esm/utils/AdaptiveStepCalculator.js +252 -0
- package/esm/utils/ErrorRecovery.js +499 -0
- package/esm/utils/GlobalGrid.js +259 -0
- package/esm/utils/PerformanceMonitor.js +360 -0
- package/esm/utils/getAnchorPoints.js +0 -4
- package/esm/utils/grid.js +18 -13
- package/esm/utils/heuristics.js +144 -0
- package/esm/utils/index.js +7 -1
- package/esm/utils/pathProcessing.js +270 -0
- package/esm/utils/pathValidation.js +0 -1
- package/esm/utils/rect.js +11 -4
- package/esm/utils/route.js +18 -2
- package/package.json +10 -2
- package/cjs/geometry/Line.d.ts +0 -21
- package/cjs/geometry/Line.d.ts.map +0 -1
- package/cjs/geometry/Line.js +0 -88
- package/cjs/geometry/Point.d.ts +0 -49
- package/cjs/geometry/Point.d.ts.map +0 -1
- package/cjs/geometry/Point.js +0 -94
- package/cjs/geometry/Rectangle.d.ts +0 -41
- package/cjs/geometry/Rectangle.d.ts.map +0 -1
- package/cjs/geometry/Rectangle.js +0 -65
- package/cjs/geometry/collision.d.ts +0 -15
- package/cjs/geometry/collision.d.ts.map +0 -1
- package/cjs/geometry/collision.js +0 -81
- package/cjs/geometry/index.d.ts +0 -5
- package/cjs/geometry/index.d.ts.map +0 -1
- package/cjs/geometry/index.js +0 -45
- package/cjs/getManHattanPath.d.ts +0 -53
- package/cjs/getManHattanPath.d.ts.map +0 -1
- package/cjs/getManHattanPath.js +0 -418
- package/cjs/index.d.ts +0 -16
- package/cjs/index.d.ts.map +0 -1
- package/cjs/index.js +0 -117
- package/cjs/obstacle/ObstacleMap.d.ts +0 -34
- package/cjs/obstacle/ObstacleMap.d.ts.map +0 -1
- package/cjs/obstacle/ObstacleMap.js +0 -223
- package/cjs/obstacle/index.d.ts +0 -2
- package/cjs/obstacle/index.d.ts.map +0 -1
- package/cjs/obstacle/index.js +0 -12
- package/cjs/options/defaults.d.ts +0 -16
- package/cjs/options/defaults.d.ts.map +0 -1
- package/cjs/options/defaults.js +0 -39
- package/cjs/options/index.d.ts +0 -4
- package/cjs/options/index.d.ts.map +0 -1
- package/cjs/options/index.js +0 -38
- package/cjs/options/resolver.d.ts +0 -10
- package/cjs/options/resolver.d.ts.map +0 -1
- package/cjs/options/resolver.js +0 -120
- package/cjs/options/types.d.ts +0 -169
- package/cjs/options/types.d.ts.map +0 -1
- package/cjs/options/types.js +0 -5
- package/cjs/pathfinder/SortedSet.d.ts +0 -35
- package/cjs/pathfinder/SortedSet.d.ts.map +0 -1
- package/cjs/pathfinder/SortedSet.js +0 -95
- package/cjs/pathfinder/findRoute.d.ts +0 -8
- package/cjs/pathfinder/findRoute.d.ts.map +0 -1
- package/cjs/pathfinder/findRoute.js +0 -330
- package/cjs/pathfinder/index.d.ts +0 -3
- package/cjs/pathfinder/index.d.ts.map +0 -1
- package/cjs/pathfinder/index.js +0 -19
- package/cjs/svg/index.d.ts +0 -3
- package/cjs/svg/index.d.ts.map +0 -1
- package/cjs/svg/index.js +0 -31
- package/cjs/svg/pathConverter.d.ts +0 -10
- package/cjs/svg/pathConverter.d.ts.map +0 -1
- package/cjs/svg/pathConverter.js +0 -116
- package/cjs/svg/pathParser.d.ts +0 -11
- package/cjs/svg/pathParser.d.ts.map +0 -1
- package/cjs/svg/pathParser.js +0 -76
- package/cjs/utils/direction.d.ts +0 -24
- package/cjs/utils/direction.d.ts.map +0 -1
- package/cjs/utils/direction.js +0 -54
- package/cjs/utils/getAnchorPoints.d.ts +0 -15
- package/cjs/utils/getAnchorPoints.d.ts.map +0 -1
- package/cjs/utils/getAnchorPoints.js +0 -75
- package/cjs/utils/grid.d.ts +0 -27
- package/cjs/utils/grid.d.ts.map +0 -1
- package/cjs/utils/grid.js +0 -66
- package/cjs/utils/index.d.ts +0 -8
- package/cjs/utils/index.d.ts.map +0 -1
- package/cjs/utils/index.js +0 -82
- package/cjs/utils/node.d.ts +0 -27
- package/cjs/utils/node.d.ts.map +0 -1
- package/cjs/utils/node.js +0 -36
- package/cjs/utils/pathValidation.d.ts +0 -11
- package/cjs/utils/pathValidation.d.ts.map +0 -1
- package/cjs/utils/pathValidation.js +0 -130
- package/cjs/utils/rect.d.ts +0 -9
- package/cjs/utils/rect.d.ts.map +0 -1
- package/cjs/utils/rect.js +0 -103
- package/cjs/utils/route.d.ts +0 -19
- package/cjs/utils/route.d.ts.map +0 -1
- package/cjs/utils/route.js +0 -76
- package/esm/geometry/Line.d.ts +0 -21
- package/esm/geometry/Line.d.ts.map +0 -1
- package/esm/geometry/Point.d.ts +0 -49
- package/esm/geometry/Point.d.ts.map +0 -1
- package/esm/geometry/Rectangle.d.ts +0 -41
- package/esm/geometry/Rectangle.d.ts.map +0 -1
- package/esm/geometry/collision.d.ts +0 -15
- package/esm/geometry/collision.d.ts.map +0 -1
- package/esm/geometry/index.d.ts +0 -5
- package/esm/geometry/index.d.ts.map +0 -1
- package/esm/getManHattanPath.d.ts +0 -53
- package/esm/getManHattanPath.d.ts.map +0 -1
- package/esm/index.d.ts +0 -16
- package/esm/index.d.ts.map +0 -1
- package/esm/obstacle/ObstacleMap.d.ts +0 -34
- package/esm/obstacle/ObstacleMap.d.ts.map +0 -1
- package/esm/obstacle/index.d.ts +0 -2
- package/esm/obstacle/index.d.ts.map +0 -1
- package/esm/options/defaults.d.ts +0 -16
- package/esm/options/defaults.d.ts.map +0 -1
- package/esm/options/index.d.ts +0 -4
- package/esm/options/index.d.ts.map +0 -1
- package/esm/options/resolver.d.ts +0 -10
- package/esm/options/resolver.d.ts.map +0 -1
- package/esm/options/types.d.ts +0 -169
- package/esm/options/types.d.ts.map +0 -1
- package/esm/pathfinder/SortedSet.d.ts +0 -35
- package/esm/pathfinder/SortedSet.d.ts.map +0 -1
- package/esm/pathfinder/findRoute.d.ts +0 -8
- package/esm/pathfinder/findRoute.d.ts.map +0 -1
- package/esm/pathfinder/index.d.ts +0 -3
- package/esm/pathfinder/index.d.ts.map +0 -1
- package/esm/svg/index.d.ts +0 -3
- package/esm/svg/index.d.ts.map +0 -1
- package/esm/svg/pathConverter.d.ts +0 -10
- package/esm/svg/pathConverter.d.ts.map +0 -1
- package/esm/svg/pathParser.d.ts +0 -11
- package/esm/svg/pathParser.d.ts.map +0 -1
- package/esm/utils/direction.d.ts +0 -24
- package/esm/utils/direction.d.ts.map +0 -1
- package/esm/utils/getAnchorPoints.d.ts +0 -15
- package/esm/utils/getAnchorPoints.d.ts.map +0 -1
- package/esm/utils/grid.d.ts +0 -27
- package/esm/utils/grid.d.ts.map +0 -1
- package/esm/utils/index.d.ts +0 -8
- package/esm/utils/index.d.ts.map +0 -1
- package/esm/utils/node.d.ts +0 -27
- package/esm/utils/node.d.ts.map +0 -1
- package/esm/utils/pathValidation.d.ts +0 -11
- package/esm/utils/pathValidation.d.ts.map +0 -1
- package/esm/utils/rect.d.ts +0 -9
- package/esm/utils/rect.d.ts.map +0 -1
- package/esm/utils/route.d.ts +0 -19
- package/esm/utils/route.d.ts.map +0 -1
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
3
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
4
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
5
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
6
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
7
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
8
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
9
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
10
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
11
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
12
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
|
|
13
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
14
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
15
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
16
|
+
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); }
|
|
17
|
+
/**
|
|
18
|
+
* QuadTree implementation for efficient spatial queries
|
|
19
|
+
* Feature: manhattan-optimization
|
|
20
|
+
*
|
|
21
|
+
* A QuadTree is a tree data structure that recursively subdivides 2D space
|
|
22
|
+
* into four quadrants. This enables O(log n) spatial queries instead of O(n).
|
|
23
|
+
*/
|
|
24
|
+
import { Rectangle } from "../geometry";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Item stored in the QuadTree
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* QuadTree configuration
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Default QuadTree configuration
|
|
36
|
+
*/
|
|
37
|
+
var DEFAULT_CONFIG = {
|
|
38
|
+
maxItems: 8,
|
|
39
|
+
maxDepth: 8,
|
|
40
|
+
minSize: 10
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* QuadTree node for spatial partitioning
|
|
45
|
+
*/
|
|
46
|
+
export var QuadTree = /*#__PURE__*/function () {
|
|
47
|
+
function QuadTree(bounds) {
|
|
48
|
+
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
49
|
+
var depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
50
|
+
_classCallCheck(this, QuadTree);
|
|
51
|
+
_defineProperty(this, "bounds", void 0);
|
|
52
|
+
_defineProperty(this, "items", void 0);
|
|
53
|
+
_defineProperty(this, "children", void 0);
|
|
54
|
+
_defineProperty(this, "depth", void 0);
|
|
55
|
+
_defineProperty(this, "config", void 0);
|
|
56
|
+
this.bounds = bounds;
|
|
57
|
+
this.items = [];
|
|
58
|
+
this.children = null;
|
|
59
|
+
this.depth = depth;
|
|
60
|
+
this.config = _objectSpread(_objectSpread({}, DEFAULT_CONFIG), config);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Insert an item into the QuadTree
|
|
65
|
+
*/
|
|
66
|
+
_createClass(QuadTree, [{
|
|
67
|
+
key: "insert",
|
|
68
|
+
value: function insert(item) {
|
|
69
|
+
// Check if item intersects this node's bounds
|
|
70
|
+
if (!this.intersects(item.bounds)) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// If we have children, try to insert into them
|
|
75
|
+
if (this.children !== null) {
|
|
76
|
+
return this.insertIntoChildren(item);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Add to this node
|
|
80
|
+
this.items.push(item);
|
|
81
|
+
|
|
82
|
+
// Check if we need to split
|
|
83
|
+
if (this.shouldSplit()) {
|
|
84
|
+
this.split();
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Insert an item with just bounds and data
|
|
91
|
+
*/
|
|
92
|
+
}, {
|
|
93
|
+
key: "insertRect",
|
|
94
|
+
value: function insertRect(bounds, data) {
|
|
95
|
+
return this.insert({
|
|
96
|
+
bounds: bounds,
|
|
97
|
+
data: data
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Query all items that intersect with the given bounds
|
|
103
|
+
*/
|
|
104
|
+
}, {
|
|
105
|
+
key: "query",
|
|
106
|
+
value: function query(bounds) {
|
|
107
|
+
var results = [];
|
|
108
|
+
this.queryInternal(bounds, results);
|
|
109
|
+
return results;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Query all items that contain the given point
|
|
114
|
+
*/
|
|
115
|
+
}, {
|
|
116
|
+
key: "queryPoint",
|
|
117
|
+
value: function queryPoint(point) {
|
|
118
|
+
var results = [];
|
|
119
|
+
this.queryPointInternal(point, results);
|
|
120
|
+
return results;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Get all items in the tree
|
|
125
|
+
*/
|
|
126
|
+
}, {
|
|
127
|
+
key: "getAllItems",
|
|
128
|
+
value: function getAllItems() {
|
|
129
|
+
var results = _toConsumableArray(this.items);
|
|
130
|
+
if (this.children !== null) {
|
|
131
|
+
var _iterator = _createForOfIteratorHelper(this.children),
|
|
132
|
+
_step;
|
|
133
|
+
try {
|
|
134
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
135
|
+
var child = _step.value;
|
|
136
|
+
results.push.apply(results, _toConsumableArray(child.getAllItems()));
|
|
137
|
+
}
|
|
138
|
+
} catch (err) {
|
|
139
|
+
_iterator.e(err);
|
|
140
|
+
} finally {
|
|
141
|
+
_iterator.f();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return results;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Clear all items from the tree
|
|
149
|
+
*/
|
|
150
|
+
}, {
|
|
151
|
+
key: "clear",
|
|
152
|
+
value: function clear() {
|
|
153
|
+
this.items = [];
|
|
154
|
+
this.children = null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Get the total number of items in the tree
|
|
159
|
+
*/
|
|
160
|
+
}, {
|
|
161
|
+
key: "size",
|
|
162
|
+
get: function get() {
|
|
163
|
+
var count = this.items.length;
|
|
164
|
+
if (this.children !== null) {
|
|
165
|
+
var _iterator2 = _createForOfIteratorHelper(this.children),
|
|
166
|
+
_step2;
|
|
167
|
+
try {
|
|
168
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
169
|
+
var child = _step2.value;
|
|
170
|
+
count += child.size;
|
|
171
|
+
}
|
|
172
|
+
} catch (err) {
|
|
173
|
+
_iterator2.e(err);
|
|
174
|
+
} finally {
|
|
175
|
+
_iterator2.f();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return count;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Get the depth of the tree
|
|
183
|
+
*/
|
|
184
|
+
}, {
|
|
185
|
+
key: "getMaxDepth",
|
|
186
|
+
value: function getMaxDepth() {
|
|
187
|
+
if (this.children === null) {
|
|
188
|
+
return this.depth;
|
|
189
|
+
}
|
|
190
|
+
var maxChildDepth = this.depth;
|
|
191
|
+
var _iterator3 = _createForOfIteratorHelper(this.children),
|
|
192
|
+
_step3;
|
|
193
|
+
try {
|
|
194
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
195
|
+
var child = _step3.value;
|
|
196
|
+
maxChildDepth = Math.max(maxChildDepth, child.getMaxDepth());
|
|
197
|
+
}
|
|
198
|
+
} catch (err) {
|
|
199
|
+
_iterator3.e(err);
|
|
200
|
+
} finally {
|
|
201
|
+
_iterator3.f();
|
|
202
|
+
}
|
|
203
|
+
return maxChildDepth;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Internal query implementation
|
|
208
|
+
*/
|
|
209
|
+
}, {
|
|
210
|
+
key: "queryInternal",
|
|
211
|
+
value: function queryInternal(bounds, results) {
|
|
212
|
+
// Check if query bounds intersects this node
|
|
213
|
+
if (!this.intersects(bounds)) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Check items in this node
|
|
218
|
+
var _iterator4 = _createForOfIteratorHelper(this.items),
|
|
219
|
+
_step4;
|
|
220
|
+
try {
|
|
221
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
222
|
+
var item = _step4.value;
|
|
223
|
+
if (this.rectanglesIntersect(item.bounds, bounds)) {
|
|
224
|
+
results.push(item);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Query children
|
|
229
|
+
} catch (err) {
|
|
230
|
+
_iterator4.e(err);
|
|
231
|
+
} finally {
|
|
232
|
+
_iterator4.f();
|
|
233
|
+
}
|
|
234
|
+
if (this.children !== null) {
|
|
235
|
+
var _iterator5 = _createForOfIteratorHelper(this.children),
|
|
236
|
+
_step5;
|
|
237
|
+
try {
|
|
238
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
239
|
+
var child = _step5.value;
|
|
240
|
+
child.queryInternal(bounds, results);
|
|
241
|
+
}
|
|
242
|
+
} catch (err) {
|
|
243
|
+
_iterator5.e(err);
|
|
244
|
+
} finally {
|
|
245
|
+
_iterator5.f();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Internal point query implementation
|
|
252
|
+
*/
|
|
253
|
+
}, {
|
|
254
|
+
key: "queryPointInternal",
|
|
255
|
+
value: function queryPointInternal(point, results) {
|
|
256
|
+
// Check if point is within this node's bounds
|
|
257
|
+
if (!this.containsPoint(point)) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Check items in this node
|
|
262
|
+
var _iterator6 = _createForOfIteratorHelper(this.items),
|
|
263
|
+
_step6;
|
|
264
|
+
try {
|
|
265
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
266
|
+
var item = _step6.value;
|
|
267
|
+
if (item.bounds.containsPoint(point)) {
|
|
268
|
+
results.push(item);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Query children
|
|
273
|
+
} catch (err) {
|
|
274
|
+
_iterator6.e(err);
|
|
275
|
+
} finally {
|
|
276
|
+
_iterator6.f();
|
|
277
|
+
}
|
|
278
|
+
if (this.children !== null) {
|
|
279
|
+
var _iterator7 = _createForOfIteratorHelper(this.children),
|
|
280
|
+
_step7;
|
|
281
|
+
try {
|
|
282
|
+
for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
|
|
283
|
+
var child = _step7.value;
|
|
284
|
+
child.queryPointInternal(point, results);
|
|
285
|
+
}
|
|
286
|
+
} catch (err) {
|
|
287
|
+
_iterator7.e(err);
|
|
288
|
+
} finally {
|
|
289
|
+
_iterator7.f();
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Check if this node should split
|
|
296
|
+
*/
|
|
297
|
+
}, {
|
|
298
|
+
key: "shouldSplit",
|
|
299
|
+
value: function shouldSplit() {
|
|
300
|
+
return this.items.length > this.config.maxItems && this.depth < this.config.maxDepth && this.bounds.width > this.config.minSize * 2 && this.bounds.height > this.config.minSize * 2;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Split this node into four children
|
|
305
|
+
*/
|
|
306
|
+
}, {
|
|
307
|
+
key: "split",
|
|
308
|
+
value: function split() {
|
|
309
|
+
var halfWidth = this.bounds.width / 2;
|
|
310
|
+
var halfHeight = this.bounds.height / 2;
|
|
311
|
+
var x = this.bounds.x;
|
|
312
|
+
var y = this.bounds.y;
|
|
313
|
+
var nextDepth = this.depth + 1;
|
|
314
|
+
this.children = [
|
|
315
|
+
// Top-left
|
|
316
|
+
new QuadTree(new Rectangle(x, y, halfWidth, halfHeight), this.config, nextDepth),
|
|
317
|
+
// Top-right
|
|
318
|
+
new QuadTree(new Rectangle(x + halfWidth, y, halfWidth, halfHeight), this.config, nextDepth),
|
|
319
|
+
// Bottom-left
|
|
320
|
+
new QuadTree(new Rectangle(x, y + halfHeight, halfWidth, halfHeight), this.config, nextDepth),
|
|
321
|
+
// Bottom-right
|
|
322
|
+
new QuadTree(new Rectangle(x + halfWidth, y + halfHeight, halfWidth, halfHeight), this.config, nextDepth)];
|
|
323
|
+
|
|
324
|
+
// Redistribute items to children
|
|
325
|
+
var itemsToRedistribute = this.items;
|
|
326
|
+
this.items = [];
|
|
327
|
+
var _iterator8 = _createForOfIteratorHelper(itemsToRedistribute),
|
|
328
|
+
_step8;
|
|
329
|
+
try {
|
|
330
|
+
for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
|
|
331
|
+
var item = _step8.value;
|
|
332
|
+
this.insertIntoChildren(item);
|
|
333
|
+
}
|
|
334
|
+
} catch (err) {
|
|
335
|
+
_iterator8.e(err);
|
|
336
|
+
} finally {
|
|
337
|
+
_iterator8.f();
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Insert item into appropriate children
|
|
343
|
+
*/
|
|
344
|
+
}, {
|
|
345
|
+
key: "insertIntoChildren",
|
|
346
|
+
value: function insertIntoChildren(item) {
|
|
347
|
+
if (this.children === null) {
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
var inserted = false;
|
|
351
|
+
var _iterator9 = _createForOfIteratorHelper(this.children),
|
|
352
|
+
_step9;
|
|
353
|
+
try {
|
|
354
|
+
for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
|
|
355
|
+
var child = _step9.value;
|
|
356
|
+
if (child.insert(item)) {
|
|
357
|
+
inserted = true;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// If item doesn't fit in any child (spans multiple), keep in this node
|
|
362
|
+
} catch (err) {
|
|
363
|
+
_iterator9.e(err);
|
|
364
|
+
} finally {
|
|
365
|
+
_iterator9.f();
|
|
366
|
+
}
|
|
367
|
+
if (!inserted) {
|
|
368
|
+
this.items.push(item);
|
|
369
|
+
inserted = true;
|
|
370
|
+
}
|
|
371
|
+
return inserted;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Check if a rectangle intersects this node's bounds
|
|
376
|
+
*/
|
|
377
|
+
}, {
|
|
378
|
+
key: "intersects",
|
|
379
|
+
value: function intersects(rect) {
|
|
380
|
+
return this.rectanglesIntersect(this.bounds, rect);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Check if two rectangles intersect
|
|
385
|
+
*/
|
|
386
|
+
}, {
|
|
387
|
+
key: "rectanglesIntersect",
|
|
388
|
+
value: function rectanglesIntersect(a, b) {
|
|
389
|
+
return !(a.x + a.width <= b.x || b.x + b.width <= a.x || a.y + a.height <= b.y || b.y + b.height <= a.y);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Check if this node's bounds contain a point
|
|
394
|
+
*/
|
|
395
|
+
}, {
|
|
396
|
+
key: "containsPoint",
|
|
397
|
+
value: function containsPoint(point) {
|
|
398
|
+
return point.x >= this.bounds.x && point.x <= this.bounds.x + this.bounds.width && point.y >= this.bounds.y && point.y <= this.bounds.y + this.bounds.height;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Get statistics about the tree
|
|
403
|
+
*/
|
|
404
|
+
}, {
|
|
405
|
+
key: "getStats",
|
|
406
|
+
value: function getStats() {
|
|
407
|
+
var stats = {
|
|
408
|
+
totalItems: 0,
|
|
409
|
+
maxDepth: 0,
|
|
410
|
+
nodeCount: 0,
|
|
411
|
+
itemsPerNode: 0
|
|
412
|
+
};
|
|
413
|
+
this.collectStats(stats);
|
|
414
|
+
stats.itemsPerNode = stats.nodeCount > 0 ? stats.totalItems / stats.nodeCount : 0;
|
|
415
|
+
return stats;
|
|
416
|
+
}
|
|
417
|
+
}, {
|
|
418
|
+
key: "collectStats",
|
|
419
|
+
value: function collectStats(stats) {
|
|
420
|
+
stats.totalItems += this.items.length;
|
|
421
|
+
stats.maxDepth = Math.max(stats.maxDepth, this.depth);
|
|
422
|
+
stats.nodeCount++;
|
|
423
|
+
if (this.children !== null) {
|
|
424
|
+
var _iterator10 = _createForOfIteratorHelper(this.children),
|
|
425
|
+
_step10;
|
|
426
|
+
try {
|
|
427
|
+
for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
|
|
428
|
+
var child = _step10.value;
|
|
429
|
+
child.collectStats(stats);
|
|
430
|
+
}
|
|
431
|
+
} catch (err) {
|
|
432
|
+
_iterator10.e(err);
|
|
433
|
+
} finally {
|
|
434
|
+
_iterator10.f();
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}]);
|
|
439
|
+
return QuadTree;
|
|
440
|
+
}();
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Create a QuadTree with bounds that cover all given rectangles
|
|
444
|
+
*/
|
|
445
|
+
export function createQuadTreeFromRects(items, config) {
|
|
446
|
+
if (items.length === 0) {
|
|
447
|
+
return new QuadTree(new Rectangle(0, 0, 1000, 1000), config);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Calculate bounding box of all items
|
|
451
|
+
var minX = Infinity;
|
|
452
|
+
var minY = Infinity;
|
|
453
|
+
var maxX = -Infinity;
|
|
454
|
+
var maxY = -Infinity;
|
|
455
|
+
var _iterator11 = _createForOfIteratorHelper(items),
|
|
456
|
+
_step11;
|
|
457
|
+
try {
|
|
458
|
+
for (_iterator11.s(); !(_step11 = _iterator11.n()).done;) {
|
|
459
|
+
var item = _step11.value;
|
|
460
|
+
minX = Math.min(minX, item.bounds.x);
|
|
461
|
+
minY = Math.min(minY, item.bounds.y);
|
|
462
|
+
maxX = Math.max(maxX, item.bounds.x + item.bounds.width);
|
|
463
|
+
maxY = Math.max(maxY, item.bounds.y + item.bounds.height);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Add some padding
|
|
467
|
+
} catch (err) {
|
|
468
|
+
_iterator11.e(err);
|
|
469
|
+
} finally {
|
|
470
|
+
_iterator11.f();
|
|
471
|
+
}
|
|
472
|
+
var padding = 100;
|
|
473
|
+
var bounds = new Rectangle(minX - padding, minY - padding, maxX - minX + padding * 2, maxY - minY + padding * 2);
|
|
474
|
+
var tree = new QuadTree(bounds, config);
|
|
475
|
+
var _iterator12 = _createForOfIteratorHelper(items),
|
|
476
|
+
_step12;
|
|
477
|
+
try {
|
|
478
|
+
for (_iterator12.s(); !(_step12 = _iterator12.n()).done;) {
|
|
479
|
+
var _item = _step12.value;
|
|
480
|
+
tree.insert(_item);
|
|
481
|
+
}
|
|
482
|
+
} catch (err) {
|
|
483
|
+
_iterator12.e(err);
|
|
484
|
+
} finally {
|
|
485
|
+
_iterator12.f();
|
|
486
|
+
}
|
|
487
|
+
return tree;
|
|
488
|
+
}
|