@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,259 @@
|
|
|
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 _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
3
|
+
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); } }
|
|
4
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
5
|
+
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; }
|
|
6
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
7
|
+
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); }
|
|
8
|
+
/**
|
|
9
|
+
* GlobalGrid class for consistent path alignment
|
|
10
|
+
* Feature: manhattan-optimization
|
|
11
|
+
*
|
|
12
|
+
* This class ensures all paths align to a unified global grid,
|
|
13
|
+
* solving the path overlap problem where paths should share segments.
|
|
14
|
+
*/
|
|
15
|
+
import { Point } from "../geometry";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Global grid configuration
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* GlobalGrid class for managing grid alignment
|
|
23
|
+
*
|
|
24
|
+
* Key features:
|
|
25
|
+
* - Uses a fixed global origin (0, 0) for consistent alignment across all paths
|
|
26
|
+
* - Supports configurable step sizes
|
|
27
|
+
* - Provides methods for snapping points to grid
|
|
28
|
+
* - Ensures path segments can properly overlap when they should
|
|
29
|
+
*/
|
|
30
|
+
export var GlobalGrid = /*#__PURE__*/function () {
|
|
31
|
+
function GlobalGrid(config) {
|
|
32
|
+
var _config$origin;
|
|
33
|
+
_classCallCheck(this, GlobalGrid);
|
|
34
|
+
/** Grid origin point */
|
|
35
|
+
_defineProperty(this, "origin", void 0);
|
|
36
|
+
/** Grid step size in X direction */
|
|
37
|
+
_defineProperty(this, "stepX", void 0);
|
|
38
|
+
/** Grid step size in Y direction */
|
|
39
|
+
_defineProperty(this, "stepY", void 0);
|
|
40
|
+
this.origin = (_config$origin = config.origin) !== null && _config$origin !== void 0 ? _config$origin : new Point(0, 0);
|
|
41
|
+
this.stepX = config.stepX;
|
|
42
|
+
this.stepY = config.stepY;
|
|
43
|
+
|
|
44
|
+
// Validate step sizes
|
|
45
|
+
if (this.stepX <= 0 || this.stepY <= 0) {
|
|
46
|
+
throw new Error('Grid step sizes must be positive');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Create a GlobalGrid with uniform step size
|
|
52
|
+
*/
|
|
53
|
+
_createClass(GlobalGrid, [{
|
|
54
|
+
key: "snapValue",
|
|
55
|
+
value:
|
|
56
|
+
/**
|
|
57
|
+
* Snap a single value to the grid
|
|
58
|
+
*/
|
|
59
|
+
function snapValue(value, step) {
|
|
60
|
+
var originOffset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
61
|
+
var adjusted = value - originOffset;
|
|
62
|
+
var snapped = Math.round(adjusted / step) * step;
|
|
63
|
+
return snapped + originOffset;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Snap a point to the global grid
|
|
68
|
+
*/
|
|
69
|
+
}, {
|
|
70
|
+
key: "snapToGrid",
|
|
71
|
+
value: function snapToGrid(point) {
|
|
72
|
+
return new Point(this.snapValue(point.x, this.stepX, this.origin.x), this.snapValue(point.y, this.stepY, this.origin.y));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Snap a point to grid and apply precision rounding
|
|
77
|
+
*/
|
|
78
|
+
}, {
|
|
79
|
+
key: "snapToGridWithPrecision",
|
|
80
|
+
value: function snapToGridWithPrecision(point, precision) {
|
|
81
|
+
return this.snapToGrid(point).round(precision);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Check if a point is on the grid (within tolerance)
|
|
86
|
+
*/
|
|
87
|
+
}, {
|
|
88
|
+
key: "isOnGrid",
|
|
89
|
+
value: function isOnGrid(point) {
|
|
90
|
+
var tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.001;
|
|
91
|
+
var snapped = this.snapToGrid(point);
|
|
92
|
+
return Math.abs(point.x - snapped.x) < tolerance && Math.abs(point.y - snapped.y) < tolerance;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get the nearest grid point in a specific direction
|
|
97
|
+
*/
|
|
98
|
+
}, {
|
|
99
|
+
key: "getNearestGridPoint",
|
|
100
|
+
value: function getNearestGridPoint(point, direction) {
|
|
101
|
+
var adjustedX = point.x - this.origin.x;
|
|
102
|
+
var adjustedY = point.y - this.origin.y;
|
|
103
|
+
var snappedX;
|
|
104
|
+
var snappedY;
|
|
105
|
+
switch (direction) {
|
|
106
|
+
case 'up':
|
|
107
|
+
snappedX = Math.round(adjustedX / this.stepX) * this.stepX;
|
|
108
|
+
snappedY = Math.floor(adjustedY / this.stepY) * this.stepY;
|
|
109
|
+
break;
|
|
110
|
+
case 'down':
|
|
111
|
+
snappedX = Math.round(adjustedX / this.stepX) * this.stepX;
|
|
112
|
+
snappedY = Math.ceil(adjustedY / this.stepY) * this.stepY;
|
|
113
|
+
break;
|
|
114
|
+
case 'left':
|
|
115
|
+
snappedX = Math.floor(adjustedX / this.stepX) * this.stepX;
|
|
116
|
+
snappedY = Math.round(adjustedY / this.stepY) * this.stepY;
|
|
117
|
+
break;
|
|
118
|
+
case 'right':
|
|
119
|
+
snappedX = Math.ceil(adjustedX / this.stepX) * this.stepX;
|
|
120
|
+
snappedY = Math.round(adjustedY / this.stepY) * this.stepY;
|
|
121
|
+
break;
|
|
122
|
+
case 'nearest':
|
|
123
|
+
default:
|
|
124
|
+
snappedX = Math.round(adjustedX / this.stepX) * this.stepX;
|
|
125
|
+
snappedY = Math.round(adjustedY / this.stepY) * this.stepY;
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
return new Point(snappedX + this.origin.x, snappedY + this.origin.y);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Get all grid points within a rectangle
|
|
133
|
+
*/
|
|
134
|
+
}, {
|
|
135
|
+
key: "getGridPointsInRect",
|
|
136
|
+
value: function getGridPointsInRect(minX, minY, maxX, maxY) {
|
|
137
|
+
var points = [];
|
|
138
|
+
|
|
139
|
+
// Snap bounds to grid
|
|
140
|
+
var startX = this.snapValue(minX, this.stepX, this.origin.x);
|
|
141
|
+
var startY = this.snapValue(minY, this.stepY, this.origin.y);
|
|
142
|
+
var endX = this.snapValue(maxX, this.stepX, this.origin.x);
|
|
143
|
+
var endY = this.snapValue(maxY, this.stepY, this.origin.y);
|
|
144
|
+
for (var x = startX; x <= endX; x += this.stepX) {
|
|
145
|
+
for (var y = startY; y <= endY; y += this.stepY) {
|
|
146
|
+
points.push(new Point(x, y));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return points;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Calculate the grid distance between two points
|
|
154
|
+
* (number of grid steps, not actual distance)
|
|
155
|
+
*/
|
|
156
|
+
}, {
|
|
157
|
+
key: "gridDistance",
|
|
158
|
+
value: function gridDistance(p1, p2) {
|
|
159
|
+
var dx = Math.abs(p2.x - p1.x) / this.stepX;
|
|
160
|
+
var dy = Math.abs(p2.y - p1.y) / this.stepY;
|
|
161
|
+
return {
|
|
162
|
+
x: Math.round(dx),
|
|
163
|
+
y: Math.round(dy),
|
|
164
|
+
total: Math.round(dx) + Math.round(dy)
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Snap an array of points to the grid
|
|
170
|
+
*/
|
|
171
|
+
}, {
|
|
172
|
+
key: "snapPathToGrid",
|
|
173
|
+
value: function snapPathToGrid(points) {
|
|
174
|
+
var _this = this;
|
|
175
|
+
return points.map(function (p) {
|
|
176
|
+
return _this.snapToGrid(p);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Snap path to grid and remove duplicate consecutive points
|
|
182
|
+
*/
|
|
183
|
+
}, {
|
|
184
|
+
key: "snapAndSimplifyPath",
|
|
185
|
+
value: function snapAndSimplifyPath(points) {
|
|
186
|
+
var tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.001;
|
|
187
|
+
if (points.length === 0) return [];
|
|
188
|
+
var snapped = this.snapPathToGrid(points);
|
|
189
|
+
var simplified = [snapped[0]];
|
|
190
|
+
for (var i = 1; i < snapped.length; i++) {
|
|
191
|
+
var prev = simplified[simplified.length - 1];
|
|
192
|
+
var curr = snapped[i];
|
|
193
|
+
|
|
194
|
+
// Skip if same as previous point
|
|
195
|
+
if (Math.abs(prev.x - curr.x) < tolerance && Math.abs(prev.y - curr.y) < tolerance) {
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
simplified.push(curr);
|
|
199
|
+
}
|
|
200
|
+
return simplified;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get grid offset for a direction
|
|
205
|
+
*/
|
|
206
|
+
}, {
|
|
207
|
+
key: "getDirectionOffset",
|
|
208
|
+
value: function getDirectionOffset(direction) {
|
|
209
|
+
switch (direction) {
|
|
210
|
+
case 'up':
|
|
211
|
+
return new Point(0, -this.stepY);
|
|
212
|
+
case 'down':
|
|
213
|
+
return new Point(0, this.stepY);
|
|
214
|
+
case 'left':
|
|
215
|
+
return new Point(-this.stepX, 0);
|
|
216
|
+
case 'right':
|
|
217
|
+
return new Point(this.stepX, 0);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Clone this grid with optional overrides
|
|
223
|
+
*/
|
|
224
|
+
}, {
|
|
225
|
+
key: "clone",
|
|
226
|
+
value: function clone(overrides) {
|
|
227
|
+
var _overrides$stepX, _overrides$stepY, _overrides$origin;
|
|
228
|
+
return new GlobalGrid({
|
|
229
|
+
stepX: (_overrides$stepX = overrides === null || overrides === void 0 ? void 0 : overrides.stepX) !== null && _overrides$stepX !== void 0 ? _overrides$stepX : this.stepX,
|
|
230
|
+
stepY: (_overrides$stepY = overrides === null || overrides === void 0 ? void 0 : overrides.stepY) !== null && _overrides$stepY !== void 0 ? _overrides$stepY : this.stepY,
|
|
231
|
+
origin: (_overrides$origin = overrides === null || overrides === void 0 ? void 0 : overrides.origin) !== null && _overrides$origin !== void 0 ? _overrides$origin : this.origin.clone()
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Create a string representation for debugging
|
|
237
|
+
*/
|
|
238
|
+
}, {
|
|
239
|
+
key: "toString",
|
|
240
|
+
value: function toString() {
|
|
241
|
+
return "GlobalGrid(origin: ".concat(this.origin.toString(), ", stepX: ").concat(this.stepX, ", stepY: ").concat(this.stepY, ")");
|
|
242
|
+
}
|
|
243
|
+
}], [{
|
|
244
|
+
key: "uniform",
|
|
245
|
+
value: function uniform(step, origin) {
|
|
246
|
+
return new GlobalGrid({
|
|
247
|
+
stepX: step,
|
|
248
|
+
stepY: step,
|
|
249
|
+
origin: origin
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}]);
|
|
253
|
+
return GlobalGrid;
|
|
254
|
+
}();
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Default global grid instance with step size 10
|
|
258
|
+
*/
|
|
259
|
+
export var defaultGlobalGrid = GlobalGrid.uniform(10);
|
|
@@ -0,0 +1,360 @@
|
|
|
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 _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
3
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
5
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
6
|
+
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; } } }; }
|
|
7
|
+
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); }
|
|
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
|
+
* PerformanceMonitor - 性能监控器
|
|
19
|
+
*
|
|
20
|
+
* 提供路径计算的性能监控和调试信息
|
|
21
|
+
* - 计时功能
|
|
22
|
+
* - 指标收集(迭代次数、查询次数等)
|
|
23
|
+
* - 指标导出和日志
|
|
24
|
+
*
|
|
25
|
+
* Feature: manhattan-optimization
|
|
26
|
+
* Requirements: 3.5, 5.5
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 性能指标接口
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 日志级别
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 性能监控配置
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 默认性能监控配置
|
|
43
|
+
*/
|
|
44
|
+
export var DEFAULT_PERFORMANCE_MONITOR_CONFIG = {
|
|
45
|
+
enableLogging: false,
|
|
46
|
+
enableMetrics: false,
|
|
47
|
+
logLevel: 'info'
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 创建空的性能指标
|
|
52
|
+
*/
|
|
53
|
+
function createEmptyMetrics() {
|
|
54
|
+
return {
|
|
55
|
+
pathfindingTime: 0,
|
|
56
|
+
iterations: 0,
|
|
57
|
+
obstacleQueries: 0,
|
|
58
|
+
cacheHitRate: 0,
|
|
59
|
+
pathPointCount: 0
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 性能监控器
|
|
65
|
+
*/
|
|
66
|
+
export var PerformanceMonitor = /*#__PURE__*/function () {
|
|
67
|
+
function PerformanceMonitor() {
|
|
68
|
+
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
69
|
+
_classCallCheck(this, PerformanceMonitor);
|
|
70
|
+
_defineProperty(this, "config", void 0);
|
|
71
|
+
_defineProperty(this, "metrics", new Map());
|
|
72
|
+
_defineProperty(this, "activeTimers", new Map());
|
|
73
|
+
_defineProperty(this, "globalCounters", {
|
|
74
|
+
totalCacheHits: 0,
|
|
75
|
+
totalCacheQueries: 0
|
|
76
|
+
});
|
|
77
|
+
this.config = _objectSpread(_objectSpread({}, DEFAULT_PERFORMANCE_MONITOR_CONFIG), config);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 开始监控
|
|
82
|
+
*/
|
|
83
|
+
_createClass(PerformanceMonitor, [{
|
|
84
|
+
key: "startMonitoring",
|
|
85
|
+
value: function startMonitoring(label) {
|
|
86
|
+
if (!this.config.enableMetrics) return;
|
|
87
|
+
var startTime = performance.now();
|
|
88
|
+
this.activeTimers.set(label, startTime);
|
|
89
|
+
|
|
90
|
+
// 初始化指标
|
|
91
|
+
this.metrics.set(label, _objectSpread(_objectSpread({}, createEmptyMetrics()), {}, {
|
|
92
|
+
startTime: startTime
|
|
93
|
+
}));
|
|
94
|
+
this.log('debug', "[PerformanceMonitor] Started monitoring: ".concat(label));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 结束监控并记录
|
|
99
|
+
*/
|
|
100
|
+
}, {
|
|
101
|
+
key: "endMonitoring",
|
|
102
|
+
value: function endMonitoring(label) {
|
|
103
|
+
var endTime = performance.now();
|
|
104
|
+
var startTime = this.activeTimers.get(label);
|
|
105
|
+
if (!startTime) {
|
|
106
|
+
this.log('warn', "[PerformanceMonitor] No active timer for: ".concat(label));
|
|
107
|
+
return createEmptyMetrics();
|
|
108
|
+
}
|
|
109
|
+
var metrics = this.metrics.get(label) || createEmptyMetrics();
|
|
110
|
+
metrics.pathfindingTime = endTime - startTime;
|
|
111
|
+
metrics.endTime = endTime;
|
|
112
|
+
metrics.cacheHitRate = this.calculateCacheHitRate();
|
|
113
|
+
this.metrics.set(label, metrics);
|
|
114
|
+
this.activeTimers.delete(label);
|
|
115
|
+
this.log('info', "[PerformanceMonitor] ".concat(label, ": ").concat(metrics.pathfindingTime.toFixed(2), "ms, ").concat(metrics.iterations, " iterations, ").concat(metrics.pathPointCount, " points"));
|
|
116
|
+
return metrics;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 记录迭代次数
|
|
121
|
+
*/
|
|
122
|
+
}, {
|
|
123
|
+
key: "recordIterations",
|
|
124
|
+
value: function recordIterations(label, count) {
|
|
125
|
+
if (!this.config.enableMetrics) return;
|
|
126
|
+
var metrics = this.metrics.get(label);
|
|
127
|
+
if (metrics) {
|
|
128
|
+
metrics.iterations = count;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 增加障碍物查询计数
|
|
134
|
+
*/
|
|
135
|
+
}, {
|
|
136
|
+
key: "incrementObstacleQueries",
|
|
137
|
+
value: function incrementObstacleQueries(label) {
|
|
138
|
+
var count = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
139
|
+
if (!this.config.enableMetrics) return;
|
|
140
|
+
var metrics = this.metrics.get(label);
|
|
141
|
+
if (metrics) {
|
|
142
|
+
metrics.obstacleQueries += count;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* 记录路径点数量
|
|
148
|
+
*/
|
|
149
|
+
}, {
|
|
150
|
+
key: "recordPathPointCount",
|
|
151
|
+
value: function recordPathPointCount(label, count) {
|
|
152
|
+
if (!this.config.enableMetrics) return;
|
|
153
|
+
var metrics = this.metrics.get(label);
|
|
154
|
+
if (metrics) {
|
|
155
|
+
metrics.pathPointCount = count;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 记录缓存命中
|
|
161
|
+
*/
|
|
162
|
+
}, {
|
|
163
|
+
key: "recordCacheHit",
|
|
164
|
+
value: function recordCacheHit() {
|
|
165
|
+
if (!this.config.enableMetrics) return;
|
|
166
|
+
this.globalCounters.totalCacheHits++;
|
|
167
|
+
this.globalCounters.totalCacheQueries++;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 记录缓存未命中
|
|
172
|
+
*/
|
|
173
|
+
}, {
|
|
174
|
+
key: "recordCacheMiss",
|
|
175
|
+
value: function recordCacheMiss() {
|
|
176
|
+
if (!this.config.enableMetrics) return;
|
|
177
|
+
this.globalCounters.totalCacheQueries++;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* 计算缓存命中率
|
|
182
|
+
*/
|
|
183
|
+
}, {
|
|
184
|
+
key: "calculateCacheHitRate",
|
|
185
|
+
value: function calculateCacheHitRate() {
|
|
186
|
+
if (this.globalCounters.totalCacheQueries === 0) return 0;
|
|
187
|
+
return this.globalCounters.totalCacheHits / this.globalCounters.totalCacheQueries;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* 获取指定标签的指标
|
|
192
|
+
*/
|
|
193
|
+
}, {
|
|
194
|
+
key: "getMetrics",
|
|
195
|
+
value: function getMetrics(label) {
|
|
196
|
+
return this.metrics.get(label);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 获取所有指标
|
|
201
|
+
*/
|
|
202
|
+
}, {
|
|
203
|
+
key: "getAllMetrics",
|
|
204
|
+
value: function getAllMetrics() {
|
|
205
|
+
return new Map(this.metrics);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 清除指标
|
|
210
|
+
*/
|
|
211
|
+
}, {
|
|
212
|
+
key: "clearMetrics",
|
|
213
|
+
value: function clearMetrics() {
|
|
214
|
+
this.metrics.clear();
|
|
215
|
+
this.activeTimers.clear();
|
|
216
|
+
this.globalCounters = {
|
|
217
|
+
totalCacheHits: 0,
|
|
218
|
+
totalCacheQueries: 0
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* 导出为日志字符串
|
|
224
|
+
*/
|
|
225
|
+
}, {
|
|
226
|
+
key: "exportToLog",
|
|
227
|
+
value: function exportToLog() {
|
|
228
|
+
var lines = ['=== Performance Metrics ==='];
|
|
229
|
+
var _iterator = _createForOfIteratorHelper(this.metrics),
|
|
230
|
+
_step;
|
|
231
|
+
try {
|
|
232
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
233
|
+
var _step$value = _slicedToArray(_step.value, 2),
|
|
234
|
+
label = _step$value[0],
|
|
235
|
+
metrics = _step$value[1];
|
|
236
|
+
lines.push("\n[".concat(label, "]"));
|
|
237
|
+
lines.push(" Time: ".concat(metrics.pathfindingTime.toFixed(2), "ms"));
|
|
238
|
+
lines.push(" Iterations: ".concat(metrics.iterations));
|
|
239
|
+
lines.push(" Obstacle Queries: ".concat(metrics.obstacleQueries));
|
|
240
|
+
lines.push(" Path Points: ".concat(metrics.pathPointCount));
|
|
241
|
+
lines.push(" Cache Hit Rate: ".concat((metrics.cacheHitRate * 100).toFixed(1), "%"));
|
|
242
|
+
}
|
|
243
|
+
} catch (err) {
|
|
244
|
+
_iterator.e(err);
|
|
245
|
+
} finally {
|
|
246
|
+
_iterator.f();
|
|
247
|
+
}
|
|
248
|
+
lines.push('\n=== Global Stats ===');
|
|
249
|
+
lines.push(" Total Cache Queries: ".concat(this.globalCounters.totalCacheQueries));
|
|
250
|
+
lines.push(" Total Cache Hits: ".concat(this.globalCounters.totalCacheHits));
|
|
251
|
+
lines.push(" Overall Cache Hit Rate: ".concat((this.calculateCacheHitRate() * 100).toFixed(1), "%"));
|
|
252
|
+
return lines.join('\n');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* 获取摘要统计
|
|
257
|
+
*/
|
|
258
|
+
}, {
|
|
259
|
+
key: "getSummary",
|
|
260
|
+
value: function getSummary() {
|
|
261
|
+
var totalTime = 0;
|
|
262
|
+
var maxTime = 0;
|
|
263
|
+
var minTime = Infinity;
|
|
264
|
+
var totalIterations = 0;
|
|
265
|
+
var _iterator2 = _createForOfIteratorHelper(this.metrics.values()),
|
|
266
|
+
_step2;
|
|
267
|
+
try {
|
|
268
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
269
|
+
var metrics = _step2.value;
|
|
270
|
+
totalTime += metrics.pathfindingTime;
|
|
271
|
+
maxTime = Math.max(maxTime, metrics.pathfindingTime);
|
|
272
|
+
minTime = Math.min(minTime, metrics.pathfindingTime);
|
|
273
|
+
totalIterations += metrics.iterations;
|
|
274
|
+
}
|
|
275
|
+
} catch (err) {
|
|
276
|
+
_iterator2.e(err);
|
|
277
|
+
} finally {
|
|
278
|
+
_iterator2.f();
|
|
279
|
+
}
|
|
280
|
+
var count = this.metrics.size;
|
|
281
|
+
return {
|
|
282
|
+
totalTime: totalTime,
|
|
283
|
+
avgTime: count > 0 ? totalTime / count : 0,
|
|
284
|
+
maxTime: count > 0 ? maxTime : 0,
|
|
285
|
+
minTime: count > 0 && minTime !== Infinity ? minTime : 0,
|
|
286
|
+
totalIterations: totalIterations,
|
|
287
|
+
cacheHitRate: this.calculateCacheHitRate()
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* 内部日志方法
|
|
293
|
+
*/
|
|
294
|
+
}, {
|
|
295
|
+
key: "log",
|
|
296
|
+
value: function log(level, message) {
|
|
297
|
+
if (!this.config.enableLogging) return;
|
|
298
|
+
var levels = ['error', 'warn', 'info', 'debug'];
|
|
299
|
+
var configLevelIndex = levels.indexOf(this.config.logLevel);
|
|
300
|
+
var messageLevelIndex = levels.indexOf(level);
|
|
301
|
+
if (messageLevelIndex <= configLevelIndex) {
|
|
302
|
+
switch (level) {
|
|
303
|
+
case 'error':
|
|
304
|
+
console.error(message);
|
|
305
|
+
break;
|
|
306
|
+
case 'warn':
|
|
307
|
+
console.warn(message);
|
|
308
|
+
break;
|
|
309
|
+
case 'info':
|
|
310
|
+
console.info(message);
|
|
311
|
+
break;
|
|
312
|
+
case 'debug':
|
|
313
|
+
console.debug(message);
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* 更新配置
|
|
321
|
+
*/
|
|
322
|
+
}, {
|
|
323
|
+
key: "updateConfig",
|
|
324
|
+
value: function updateConfig(config) {
|
|
325
|
+
this.config = _objectSpread(_objectSpread({}, this.config), config);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* 获取当前配置
|
|
330
|
+
*/
|
|
331
|
+
}, {
|
|
332
|
+
key: "getConfig",
|
|
333
|
+
value: function getConfig() {
|
|
334
|
+
return _objectSpread({}, this.config);
|
|
335
|
+
}
|
|
336
|
+
}]);
|
|
337
|
+
return PerformanceMonitor;
|
|
338
|
+
}();
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* 全局性能监控器实例(可选使用)
|
|
342
|
+
*/
|
|
343
|
+
var globalMonitor = null;
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* 获取全局性能监控器
|
|
347
|
+
*/
|
|
348
|
+
export function getGlobalPerformanceMonitor() {
|
|
349
|
+
if (!globalMonitor) {
|
|
350
|
+
globalMonitor = new PerformanceMonitor();
|
|
351
|
+
}
|
|
352
|
+
return globalMonitor;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* 重置全局性能监控器
|
|
357
|
+
*/
|
|
358
|
+
export function resetGlobalPerformanceMonitor() {
|
|
359
|
+
globalMonitor = null;
|
|
360
|
+
}
|
|
@@ -36,16 +36,13 @@ export function getAnchorPoints(anchor, position, extensionDistance, step, obsta
|
|
|
36
36
|
console.warn("[getAnchorPoints] Invalid position: ".concat(position));
|
|
37
37
|
return [anchor];
|
|
38
38
|
}
|
|
39
|
-
console.log("[getAnchorPoints] Finding points for position '".concat(position, "' from (").concat(anchor.x, ", ").concat(anchor.y, ")"));
|
|
40
39
|
|
|
41
40
|
// 1. First try extensionDistance
|
|
42
41
|
var extensionPoint = new Point(anchor.x + dir.dx * extensionDistance, anchor.y + dir.dy * extensionDistance);
|
|
43
42
|
if (obstacleMap.isAccessible(extensionPoint)) {
|
|
44
|
-
console.log("[getAnchorPoints] Extension point (".concat(extensionPoint.x, ", ").concat(extensionPoint.y, ") is accessible"));
|
|
45
43
|
points.push(extensionPoint);
|
|
46
44
|
return points;
|
|
47
45
|
}
|
|
48
|
-
console.log("[getAnchorPoints] Extension point (".concat(extensionPoint.x, ", ").concat(extensionPoint.y, ") is blocked, trying binary search"));
|
|
49
46
|
|
|
50
47
|
// 2. If extensionDistance point is blocked, use binary search with step
|
|
51
48
|
// Try: step -> step/2 -> step/4 -> ... -> 1px
|
|
@@ -53,7 +50,6 @@ export function getAnchorPoints(anchor, position, extensionDistance, step, obsta
|
|
|
53
50
|
while (distance >= 1) {
|
|
54
51
|
var testPoint = new Point(anchor.x + dir.dx * distance, anchor.y + dir.dy * distance);
|
|
55
52
|
if (obstacleMap.isAccessible(testPoint)) {
|
|
56
|
-
console.log("[getAnchorPoints] Found accessible point at distance ".concat(distance, "px: (").concat(testPoint.x, ", ").concat(testPoint.y, ")"));
|
|
57
53
|
points.push(testPoint);
|
|
58
54
|
return points;
|
|
59
55
|
}
|