@rxflow/manhattan 0.0.1-alpha.0
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 +35 -0
- package/cjs/geometry/Line.d.ts +21 -0
- package/cjs/geometry/Line.d.ts.map +1 -0
- package/cjs/geometry/Line.js +88 -0
- package/cjs/geometry/Point.d.ts +49 -0
- package/cjs/geometry/Point.d.ts.map +1 -0
- package/cjs/geometry/Point.js +94 -0
- package/cjs/geometry/Rectangle.d.ts +41 -0
- package/cjs/geometry/Rectangle.d.ts.map +1 -0
- package/cjs/geometry/Rectangle.js +65 -0
- package/cjs/geometry/index.d.ts +4 -0
- package/cjs/geometry/index.d.ts.map +1 -0
- package/cjs/geometry/index.js +26 -0
- package/cjs/getManHattanPath.d.ts +60 -0
- package/cjs/getManHattanPath.d.ts.map +1 -0
- package/cjs/getManHattanPath.js +285 -0
- package/cjs/index.d.ts +16 -0
- package/cjs/index.d.ts.map +1 -0
- package/cjs/index.js +117 -0
- package/cjs/obstacle/ObstacleMap.d.ts +28 -0
- package/cjs/obstacle/ObstacleMap.d.ts.map +1 -0
- package/cjs/obstacle/ObstacleMap.js +171 -0
- package/cjs/obstacle/index.d.ts +2 -0
- package/cjs/obstacle/index.d.ts.map +1 -0
- package/cjs/obstacle/index.js +12 -0
- package/cjs/options/defaults.d.ts +16 -0
- package/cjs/options/defaults.d.ts.map +1 -0
- package/cjs/options/defaults.js +39 -0
- package/cjs/options/index.d.ts +4 -0
- package/cjs/options/index.d.ts.map +1 -0
- package/cjs/options/index.js +38 -0
- package/cjs/options/resolver.d.ts +10 -0
- package/cjs/options/resolver.d.ts.map +1 -0
- package/cjs/options/resolver.js +118 -0
- package/cjs/options/types.d.ts +156 -0
- package/cjs/options/types.d.ts.map +1 -0
- package/cjs/options/types.js +5 -0
- package/cjs/pathfinder/SortedSet.d.ts +35 -0
- package/cjs/pathfinder/SortedSet.d.ts.map +1 -0
- package/cjs/pathfinder/SortedSet.js +95 -0
- package/cjs/pathfinder/findRoute.d.ts +8 -0
- package/cjs/pathfinder/findRoute.d.ts.map +1 -0
- package/cjs/pathfinder/findRoute.js +156 -0
- package/cjs/pathfinder/index.d.ts +3 -0
- package/cjs/pathfinder/index.d.ts.map +1 -0
- package/cjs/pathfinder/index.js +19 -0
- package/cjs/svg/index.d.ts +2 -0
- package/cjs/svg/index.d.ts.map +1 -0
- package/cjs/svg/index.js +18 -0
- package/cjs/svg/pathConverter.d.ts +10 -0
- package/cjs/svg/pathConverter.d.ts.map +1 -0
- package/cjs/svg/pathConverter.js +105 -0
- package/cjs/utils/direction.d.ts +24 -0
- package/cjs/utils/direction.d.ts.map +1 -0
- package/cjs/utils/direction.js +54 -0
- package/cjs/utils/grid.d.ts +26 -0
- package/cjs/utils/grid.d.ts.map +1 -0
- package/cjs/utils/grid.js +78 -0
- package/cjs/utils/index.d.ts +6 -0
- package/cjs/utils/index.d.ts.map +1 -0
- package/cjs/utils/index.js +60 -0
- package/cjs/utils/node.d.ts +27 -0
- package/cjs/utils/node.d.ts.map +1 -0
- package/cjs/utils/node.js +36 -0
- package/cjs/utils/rect.d.ts +9 -0
- package/cjs/utils/rect.d.ts.map +1 -0
- package/cjs/utils/rect.js +103 -0
- package/cjs/utils/route.d.ts +19 -0
- package/cjs/utils/route.d.ts.map +1 -0
- package/cjs/utils/route.js +76 -0
- package/esm/geometry/Line.d.ts +21 -0
- package/esm/geometry/Line.d.ts.map +1 -0
- package/esm/geometry/Line.js +96 -0
- package/esm/geometry/Point.d.ts +49 -0
- package/esm/geometry/Point.d.ts.map +1 -0
- package/esm/geometry/Point.js +117 -0
- package/esm/geometry/Rectangle.d.ts +41 -0
- package/esm/geometry/Rectangle.d.ts.map +1 -0
- package/esm/geometry/Rectangle.js +81 -0
- package/esm/geometry/index.d.ts +4 -0
- package/esm/geometry/index.d.ts.map +1 -0
- package/esm/geometry/index.js +3 -0
- package/esm/getManHattanPath.d.ts +60 -0
- package/esm/getManHattanPath.d.ts.map +1 -0
- package/esm/getManHattanPath.js +291 -0
- package/esm/index.d.ts +16 -0
- package/esm/index.d.ts.map +1 -0
- package/esm/index.js +24 -0
- package/esm/obstacle/ObstacleMap.d.ts +28 -0
- package/esm/obstacle/ObstacleMap.d.ts.map +1 -0
- package/esm/obstacle/ObstacleMap.js +183 -0
- package/esm/obstacle/index.d.ts +2 -0
- package/esm/obstacle/index.d.ts.map +1 -0
- package/esm/obstacle/index.js +1 -0
- package/esm/options/defaults.d.ts +16 -0
- package/esm/options/defaults.d.ts.map +1 -0
- package/esm/options/defaults.js +33 -0
- package/esm/options/index.d.ts +4 -0
- package/esm/options/index.d.ts.map +1 -0
- package/esm/options/index.js +3 -0
- package/esm/options/resolver.d.ts +10 -0
- package/esm/options/resolver.d.ts.map +1 -0
- package/esm/options/resolver.js +114 -0
- package/esm/options/types.d.ts +156 -0
- package/esm/options/types.d.ts.map +1 -0
- package/esm/options/types.js +1 -0
- package/esm/pathfinder/SortedSet.d.ts +35 -0
- package/esm/pathfinder/SortedSet.d.ts.map +1 -0
- package/esm/pathfinder/SortedSet.js +110 -0
- package/esm/pathfinder/findRoute.d.ts +8 -0
- package/esm/pathfinder/findRoute.d.ts.map +1 -0
- package/esm/pathfinder/findRoute.js +189 -0
- package/esm/pathfinder/index.d.ts +3 -0
- package/esm/pathfinder/index.d.ts.map +1 -0
- package/esm/pathfinder/index.js +2 -0
- package/esm/svg/index.d.ts +2 -0
- package/esm/svg/index.d.ts.map +1 -0
- package/esm/svg/index.js +1 -0
- package/esm/svg/pathConverter.d.ts +10 -0
- package/esm/svg/pathConverter.d.ts.map +1 -0
- package/esm/svg/pathConverter.js +107 -0
- package/esm/utils/direction.d.ts +24 -0
- package/esm/utils/direction.d.ts.map +1 -0
- package/esm/utils/direction.js +46 -0
- package/esm/utils/grid.d.ts +26 -0
- package/esm/utils/grid.d.ts.map +1 -0
- package/esm/utils/grid.js +70 -0
- package/esm/utils/index.d.ts +6 -0
- package/esm/utils/index.d.ts.map +1 -0
- package/esm/utils/index.js +5 -0
- package/esm/utils/node.d.ts +27 -0
- package/esm/utils/node.d.ts.map +1 -0
- package/esm/utils/node.js +30 -0
- package/esm/utils/rect.d.ts +9 -0
- package/esm/utils/rect.d.ts.map +1 -0
- package/esm/utils/rect.js +121 -0
- package/esm/utils/route.d.ts +19 -0
- package/esm/utils/route.d.ts.map +1 -0
- package/esm/utils/route.js +80 -0
- package/package.json +43 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
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; } } }; }
|
|
2
|
+
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); }
|
|
3
|
+
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; }
|
|
4
|
+
import { SortedSet } from "./SortedSet";
|
|
5
|
+
import { getGrid, align, round, getDirectionAngle, getDirectionChange, getGridOffsets, getRectPoints, getCost, getKey, reconstructRoute } from "../utils";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Find route between two points using A* algorithm
|
|
9
|
+
*/
|
|
10
|
+
export function findRoute(sourceBBox, targetBBox, sourceAnchor, targetAnchor, map, options) {
|
|
11
|
+
var precision = options.precision;
|
|
12
|
+
|
|
13
|
+
// Round anchor points
|
|
14
|
+
var sourceEndpoint = round(sourceAnchor.clone(), precision);
|
|
15
|
+
var targetEndpoint = round(targetAnchor.clone(), precision);
|
|
16
|
+
|
|
17
|
+
// Get grid for this route
|
|
18
|
+
var grid = getGrid(options.step, sourceEndpoint, targetEndpoint);
|
|
19
|
+
|
|
20
|
+
// Get pathfinding points
|
|
21
|
+
var startPoint = sourceEndpoint;
|
|
22
|
+
var endPoint = targetEndpoint;
|
|
23
|
+
|
|
24
|
+
// Get start and end points around rectangles
|
|
25
|
+
var startPoints = getRectPoints(startPoint, sourceBBox, options.startDirections, grid, options);
|
|
26
|
+
var endPoints = getRectPoints(targetEndpoint, targetBBox, options.endDirections, grid, options);
|
|
27
|
+
console.log('[findRoute] Start points from getRectPoints:', startPoints.map(function (p) {
|
|
28
|
+
return "(".concat(p.x, ", ").concat(p.y, ")");
|
|
29
|
+
}));
|
|
30
|
+
console.log('[findRoute] End points from getRectPoints:', endPoints.map(function (p) {
|
|
31
|
+
return "(".concat(p.x, ", ").concat(p.y, ")");
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
// Take into account only accessible rect points
|
|
35
|
+
startPoints = startPoints.filter(function (p) {
|
|
36
|
+
return map.isAccessible(p);
|
|
37
|
+
});
|
|
38
|
+
endPoints = endPoints.filter(function (p) {
|
|
39
|
+
return map.isAccessible(p);
|
|
40
|
+
});
|
|
41
|
+
console.log('[findRoute] Start points after filter:', startPoints.map(function (p) {
|
|
42
|
+
return "(".concat(p.x, ", ").concat(p.y, ")");
|
|
43
|
+
}));
|
|
44
|
+
console.log('[findRoute] End points after filter:', endPoints.map(function (p) {
|
|
45
|
+
return "(".concat(p.x, ", ").concat(p.y, ")");
|
|
46
|
+
}));
|
|
47
|
+
|
|
48
|
+
// Ensure we always have at least the anchor points
|
|
49
|
+
// This handles edge cases where anchor is on the node boundary
|
|
50
|
+
if (startPoints.length === 0) {
|
|
51
|
+
startPoints = [align(startPoint, grid, precision)];
|
|
52
|
+
}
|
|
53
|
+
if (endPoints.length === 0) {
|
|
54
|
+
endPoints = [align(endPoint, grid, precision)];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Initialize A* data structures
|
|
58
|
+
var openSet = new SortedSet();
|
|
59
|
+
var points = new Map();
|
|
60
|
+
var parents = new Map();
|
|
61
|
+
var costs = new Map();
|
|
62
|
+
|
|
63
|
+
// Add all start points to open set
|
|
64
|
+
var _iterator = _createForOfIteratorHelper(startPoints),
|
|
65
|
+
_step;
|
|
66
|
+
try {
|
|
67
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
68
|
+
var _startPoint = _step.value;
|
|
69
|
+
var key = getKey(_startPoint);
|
|
70
|
+
openSet.add(key, getCost(_startPoint, endPoints));
|
|
71
|
+
points.set(key, _startPoint);
|
|
72
|
+
costs.set(key, 0);
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
_iterator.e(err);
|
|
76
|
+
} finally {
|
|
77
|
+
_iterator.f();
|
|
78
|
+
}
|
|
79
|
+
var previousRouteDirectionAngle = options.previousDirectionAngle;
|
|
80
|
+
var isPathBeginning = previousRouteDirectionAngle === undefined;
|
|
81
|
+
|
|
82
|
+
// Get directions with grid offsets
|
|
83
|
+
var directions = getGridOffsets(grid, options);
|
|
84
|
+
var numDirections = directions.length;
|
|
85
|
+
|
|
86
|
+
// Create set of end point keys for quick lookup
|
|
87
|
+
var endPointsKeys = new Set(endPoints.map(function (p) {
|
|
88
|
+
return getKey(p);
|
|
89
|
+
}));
|
|
90
|
+
|
|
91
|
+
// Check if start and end points are the same
|
|
92
|
+
var sameStartEndPoints = startPoints.length === endPoints.length && startPoints.every(function (sp, i) {
|
|
93
|
+
return sp.equals(endPoints[i]);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Main A* loop
|
|
97
|
+
var loopsRemaining = options.maxLoopCount;
|
|
98
|
+
while (!openSet.isEmpty() && loopsRemaining > 0) {
|
|
99
|
+
// Get the closest item and mark it CLOSED
|
|
100
|
+
var currentKey = openSet.pop();
|
|
101
|
+
if (!currentKey) break;
|
|
102
|
+
var currentPoint = points.get(currentKey);
|
|
103
|
+
var currentParent = parents.get(currentKey);
|
|
104
|
+
var currentCost = costs.get(currentKey);
|
|
105
|
+
var isStartPoint = currentPoint.equals(startPoint);
|
|
106
|
+
var isRouteBeginning = currentParent === undefined;
|
|
107
|
+
|
|
108
|
+
// Calculate previous direction angle
|
|
109
|
+
var previousDirectionAngle = void 0;
|
|
110
|
+
if (!isRouteBeginning) {
|
|
111
|
+
previousDirectionAngle = getDirectionAngle(currentParent, currentPoint, numDirections, grid, options);
|
|
112
|
+
} else if (!isPathBeginning) {
|
|
113
|
+
previousDirectionAngle = previousRouteDirectionAngle;
|
|
114
|
+
} else if (!isStartPoint) {
|
|
115
|
+
previousDirectionAngle = getDirectionAngle(startPoint, currentPoint, numDirections, grid, options);
|
|
116
|
+
} else {
|
|
117
|
+
previousDirectionAngle = null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Check if we reached any endpoint
|
|
121
|
+
var skipEndCheck = isRouteBeginning && sameStartEndPoints;
|
|
122
|
+
if (!skipEndCheck && endPointsKeys.has(currentKey)) {
|
|
123
|
+
options.previousDirectionAngle = previousDirectionAngle;
|
|
124
|
+
return reconstructRoute(parents, points, currentPoint, startPoint, endPoint);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Explore neighbors in all directions
|
|
128
|
+
var _iterator2 = _createForOfIteratorHelper(directions),
|
|
129
|
+
_step2;
|
|
130
|
+
try {
|
|
131
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
132
|
+
var _previousDirectionAng;
|
|
133
|
+
var direction = _step2.value;
|
|
134
|
+
var directionAngle = direction.angle;
|
|
135
|
+
var directionChange = getDirectionChange((_previousDirectionAng = previousDirectionAngle) !== null && _previousDirectionAng !== void 0 ? _previousDirectionAng : 0, directionAngle);
|
|
136
|
+
|
|
137
|
+
// Don't use the point if direction changed too rapidly
|
|
138
|
+
if (!(isPathBeginning && isStartPoint) && directionChange > options.maxDirectionChange) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Calculate neighbor point
|
|
143
|
+
var neighborPoint = align(currentPoint.clone().translate(direction.gridOffsetX || 0, direction.gridOffsetY || 0), grid, precision);
|
|
144
|
+
var neighborKey = getKey(neighborPoint);
|
|
145
|
+
|
|
146
|
+
// Skip if closed or not accessible
|
|
147
|
+
if (openSet.isClose(neighborKey) || !map.isAccessible(neighborPoint)) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Check if neighbor is an end point
|
|
152
|
+
if (endPointsKeys.has(neighborKey)) {
|
|
153
|
+
var isEndPoint = neighborPoint.equals(endPoint);
|
|
154
|
+
if (!isEndPoint) {
|
|
155
|
+
var endDirectionAngle = getDirectionAngle(neighborPoint, endPoint, numDirections, grid, options);
|
|
156
|
+
var endDirectionChange = getDirectionChange(directionAngle, endDirectionAngle);
|
|
157
|
+
if (endDirectionChange > options.maxDirectionChange) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Calculate costs
|
|
164
|
+
var neighborCost = direction.cost;
|
|
165
|
+
var neighborPenalty = isStartPoint ? 0 : options.penalties[directionChange] || 0;
|
|
166
|
+
var costFromStart = currentCost + neighborCost + neighborPenalty;
|
|
167
|
+
|
|
168
|
+
// Update if not in open set or found better path
|
|
169
|
+
if (!openSet.isOpen(neighborKey) || costFromStart < (costs.get(neighborKey) || Infinity)) {
|
|
170
|
+
points.set(neighborKey, neighborPoint);
|
|
171
|
+
parents.set(neighborKey, currentPoint);
|
|
172
|
+
costs.set(neighborKey, costFromStart);
|
|
173
|
+
openSet.add(neighborKey, costFromStart + getCost(neighborPoint, endPoints));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
} catch (err) {
|
|
177
|
+
_iterator2.e(err);
|
|
178
|
+
} finally {
|
|
179
|
+
_iterator2.f();
|
|
180
|
+
}
|
|
181
|
+
loopsRemaining -= 1;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// No path found, try fallback
|
|
185
|
+
if (options.fallbackRoute) {
|
|
186
|
+
return options.fallbackRoute(startPoint, endPoint);
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pathfinder/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svg/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA"}
|
package/esm/svg/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { pointsToPath, snapPathToGrid } from "./pathConverter";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Point } from '../geometry';
|
|
2
|
+
/**
|
|
3
|
+
* Convert array of points to SVG path string
|
|
4
|
+
*/
|
|
5
|
+
export declare function pointsToPath(points: Point[], precision: number, borderRadius?: number): string;
|
|
6
|
+
/**
|
|
7
|
+
* Snap path to grid by aligning consecutive points
|
|
8
|
+
*/
|
|
9
|
+
export declare function snapPathToGrid(points: Point[], gridSize: number): Point[];
|
|
10
|
+
//# sourceMappingURL=pathConverter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathConverter.d.ts","sourceRoot":"","sources":["../../src/svg/pathConverter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAEnC;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAE,MAAU,GAAG,MAAM,CAgEjG;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,KAAK,EAAE,CAgCzE"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
2
|
+
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."); }
|
|
3
|
+
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); }
|
|
4
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
5
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
6
|
+
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; }
|
|
7
|
+
/**
|
|
8
|
+
* Convert array of points to SVG path string
|
|
9
|
+
*/
|
|
10
|
+
export function pointsToPath(points, precision) {
|
|
11
|
+
var borderRadius = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
12
|
+
if (points.length === 0) {
|
|
13
|
+
return '';
|
|
14
|
+
}
|
|
15
|
+
var factor = Math.pow(10, precision);
|
|
16
|
+
var roundCoord = function roundCoord(value) {
|
|
17
|
+
return Math.round(value * factor) / factor;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// If no border radius or only 2 points, use simple line path
|
|
21
|
+
if (borderRadius === 0 || points.length <= 2) {
|
|
22
|
+
var _firstPoint = points[0];
|
|
23
|
+
var _path = "M ".concat(roundCoord(_firstPoint.x), " ").concat(roundCoord(_firstPoint.y));
|
|
24
|
+
for (var i = 1; i < points.length; i++) {
|
|
25
|
+
var point = points[i];
|
|
26
|
+
_path += " L ".concat(roundCoord(point.x), " ").concat(roundCoord(point.y));
|
|
27
|
+
}
|
|
28
|
+
return _path;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Start with M (moveTo) command for first point
|
|
32
|
+
var firstPoint = points[0];
|
|
33
|
+
var path = "M ".concat(roundCoord(firstPoint.x), " ").concat(roundCoord(firstPoint.y));
|
|
34
|
+
|
|
35
|
+
// Process each segment with rounded corners
|
|
36
|
+
for (var _i = 1; _i < points.length - 1; _i++) {
|
|
37
|
+
var prev = points[_i - 1];
|
|
38
|
+
var current = points[_i];
|
|
39
|
+
var next = points[_i + 1];
|
|
40
|
+
|
|
41
|
+
// Calculate the distance from prev to current and current to next
|
|
42
|
+
var distToPrev = Math.sqrt(Math.pow(current.x - prev.x, 2) + Math.pow(current.y - prev.y, 2));
|
|
43
|
+
var distToNext = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2));
|
|
44
|
+
|
|
45
|
+
// Use the smaller of borderRadius or half the segment length
|
|
46
|
+
var radius = Math.min(borderRadius, distToPrev / 2, distToNext / 2);
|
|
47
|
+
|
|
48
|
+
// Calculate the point before the corner (on the line from prev to current)
|
|
49
|
+
var beforeCornerRatio = (distToPrev - radius) / distToPrev;
|
|
50
|
+
var beforeCorner = {
|
|
51
|
+
x: prev.x + (current.x - prev.x) * beforeCornerRatio,
|
|
52
|
+
y: prev.y + (current.y - prev.y) * beforeCornerRatio
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Calculate the point after the corner (on the line from current to next)
|
|
56
|
+
var afterCornerRatio = radius / distToNext;
|
|
57
|
+
var afterCorner = {
|
|
58
|
+
x: current.x + (next.x - current.x) * afterCornerRatio,
|
|
59
|
+
y: current.y + (next.y - current.y) * afterCornerRatio
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Draw line to the point before corner
|
|
63
|
+
path += " L ".concat(roundCoord(beforeCorner.x), " ").concat(roundCoord(beforeCorner.y));
|
|
64
|
+
|
|
65
|
+
// Draw quadratic bezier curve for the rounded corner
|
|
66
|
+
path += " Q ".concat(roundCoord(current.x), " ").concat(roundCoord(current.y), " ").concat(roundCoord(afterCorner.x), " ").concat(roundCoord(afterCorner.y));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Draw line to the last point
|
|
70
|
+
var lastPoint = points[points.length - 1];
|
|
71
|
+
path += " L ".concat(roundCoord(lastPoint.x), " ").concat(roundCoord(lastPoint.y));
|
|
72
|
+
return path;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Snap path to grid by aligning consecutive points
|
|
77
|
+
*/
|
|
78
|
+
export function snapPathToGrid(points, gridSize) {
|
|
79
|
+
if (points.length <= 1) {
|
|
80
|
+
return points;
|
|
81
|
+
}
|
|
82
|
+
var snappedPoints = _toConsumableArray(points);
|
|
83
|
+
|
|
84
|
+
// Don't snap the first and last points (anchors)
|
|
85
|
+
// Don't snap the second and second-to-last points (extension points)
|
|
86
|
+
// Only snap intermediate segments
|
|
87
|
+
for (var i = 2; i < snappedPoints.length - 3; i++) {
|
|
88
|
+
var first = snappedPoints[i];
|
|
89
|
+
var second = snappedPoints[i + 1];
|
|
90
|
+
if (first.x === second.x) {
|
|
91
|
+
// Vertical line - snap X coordinate
|
|
92
|
+
var x = gridSize * Math.round(first.x / gridSize);
|
|
93
|
+
if (first.x !== x) {
|
|
94
|
+
first.x = x;
|
|
95
|
+
second.x = x;
|
|
96
|
+
}
|
|
97
|
+
} else if (first.y === second.y) {
|
|
98
|
+
// Horizontal line - snap Y coordinate
|
|
99
|
+
var y = gridSize * Math.round(first.y / gridSize);
|
|
100
|
+
if (first.y !== y) {
|
|
101
|
+
first.y = y;
|
|
102
|
+
second.y = y;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return snappedPoints;
|
|
107
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Point } from '../geometry';
|
|
2
|
+
import type { ResolvedOptions } from '../options';
|
|
3
|
+
import type { Grid } from './grid';
|
|
4
|
+
/**
|
|
5
|
+
* Get direction angle from start point to end point
|
|
6
|
+
* Corrects for grid deformation between start and end
|
|
7
|
+
*/
|
|
8
|
+
export declare function getDirectionAngle(start: Point, end: Point, directionCount: number, grid: Grid, options: ResolvedOptions): number;
|
|
9
|
+
/**
|
|
10
|
+
* Get the change in direction between two direction angles
|
|
11
|
+
*/
|
|
12
|
+
export declare function getDirectionChange(angle1: number, angle2: number): number;
|
|
13
|
+
/**
|
|
14
|
+
* Fix direction offsets according to current grid
|
|
15
|
+
*/
|
|
16
|
+
export declare function getGridOffsets(grid: Grid, options: ResolvedOptions): {
|
|
17
|
+
cost: number;
|
|
18
|
+
offsetX: number;
|
|
19
|
+
offsetY: number;
|
|
20
|
+
angle?: number | undefined;
|
|
21
|
+
gridOffsetX?: number | undefined;
|
|
22
|
+
gridOffsetY?: number | undefined;
|
|
23
|
+
}[];
|
|
24
|
+
//# sourceMappingURL=direction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"direction.d.ts","sourceRoot":"","sources":["../../src/utils/direction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAyBlC;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,KAAK,EACV,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,eAAe,GACvB,MAAM,CAKR;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGzE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe;;;;;;;IASlE"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Point } from "../geometry";
|
|
2
|
+
import { normalizeAngle } from "../options/resolver";
|
|
3
|
+
/**
|
|
4
|
+
* Fix angle end point to account for grid deformation
|
|
5
|
+
*/
|
|
6
|
+
function fixAngleEnd(start, end, grid, options) {
|
|
7
|
+
var step = options.step;
|
|
8
|
+
var diffX = end.x - start.x;
|
|
9
|
+
var diffY = end.y - start.y;
|
|
10
|
+
var gridStepsX = diffX / grid.x;
|
|
11
|
+
var gridStepsY = diffY / grid.y;
|
|
12
|
+
var distanceX = gridStepsX * step;
|
|
13
|
+
var distanceY = gridStepsY * step;
|
|
14
|
+
return new Point(start.x + distanceX, start.y + distanceY);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get direction angle from start point to end point
|
|
19
|
+
* Corrects for grid deformation between start and end
|
|
20
|
+
*/
|
|
21
|
+
export function getDirectionAngle(start, end, directionCount, grid, options) {
|
|
22
|
+
var quadrant = 360 / directionCount;
|
|
23
|
+
var angleTheta = start.theta(fixAngleEnd(start, end, grid, options));
|
|
24
|
+
var normalizedAngle = normalizeAngle(angleTheta + quadrant / 2);
|
|
25
|
+
return quadrant * Math.floor(normalizedAngle / quadrant);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get the change in direction between two direction angles
|
|
30
|
+
*/
|
|
31
|
+
export function getDirectionChange(angle1, angle2) {
|
|
32
|
+
var change = Math.abs(angle1 - angle2);
|
|
33
|
+
return change > 180 ? 360 - change : change;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Fix direction offsets according to current grid
|
|
38
|
+
*/
|
|
39
|
+
export function getGridOffsets(grid, options) {
|
|
40
|
+
var step = options.step;
|
|
41
|
+
options.directions.forEach(function (direction) {
|
|
42
|
+
direction.gridOffsetX = direction.offsetX / step * grid.x;
|
|
43
|
+
direction.gridOffsetY = direction.offsetY / step * grid.y;
|
|
44
|
+
});
|
|
45
|
+
return options.directions;
|
|
46
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Point } from '../geometry';
|
|
2
|
+
/**
|
|
3
|
+
* Grid interface for dynamic grid system
|
|
4
|
+
*/
|
|
5
|
+
export interface Grid {
|
|
6
|
+
source: Point;
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get grid size in x and y dimensions, adapted to source and target positions
|
|
12
|
+
*/
|
|
13
|
+
export declare function getGrid(step: number, source: Point, target: Point): Grid;
|
|
14
|
+
/**
|
|
15
|
+
* Snap a value to grid
|
|
16
|
+
*/
|
|
17
|
+
export declare function snapToGrid(value: number, gridSize: number): number;
|
|
18
|
+
/**
|
|
19
|
+
* Align point to grid and apply precision
|
|
20
|
+
*/
|
|
21
|
+
export declare function align(point: Point, grid: Grid, precision: number): Point;
|
|
22
|
+
/**
|
|
23
|
+
* Round point coordinates
|
|
24
|
+
*/
|
|
25
|
+
export declare function round(point: Point, precision: number): Point;
|
|
26
|
+
//# sourceMappingURL=grid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../src/utils/grid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAEnC;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,MAAM,EAAE,KAAK,CAAA;IACb,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AA2BD;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,GAAG,IAAI,CAMxE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAElE;AAYD;;GAEG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK,CAExE;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK,CAE5D"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Point } from "../geometry";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Grid interface for dynamic grid system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get grid dimension for a single axis
|
|
9
|
+
*/
|
|
10
|
+
function getGridDimension(diff, step) {
|
|
11
|
+
// Return step if diff = 0
|
|
12
|
+
if (!diff) {
|
|
13
|
+
return step;
|
|
14
|
+
}
|
|
15
|
+
var abs = Math.abs(diff);
|
|
16
|
+
var count = Math.round(abs / step);
|
|
17
|
+
|
|
18
|
+
// Return abs if less than one step apart
|
|
19
|
+
if (!count) {
|
|
20
|
+
return abs;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Otherwise, return corrected step
|
|
24
|
+
var roundedDiff = count * step;
|
|
25
|
+
var remainder = abs - roundedDiff;
|
|
26
|
+
var correction = remainder / count;
|
|
27
|
+
return step + correction;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get grid size in x and y dimensions, adapted to source and target positions
|
|
32
|
+
*/
|
|
33
|
+
export function getGrid(step, source, target) {
|
|
34
|
+
return {
|
|
35
|
+
source: source.clone(),
|
|
36
|
+
x: getGridDimension(target.x - source.x, step),
|
|
37
|
+
y: getGridDimension(target.y - source.y, step)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Snap a value to grid
|
|
43
|
+
*/
|
|
44
|
+
export function snapToGrid(value, gridSize) {
|
|
45
|
+
return Math.round(value / gridSize) * gridSize;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Snap a point to grid
|
|
50
|
+
*/
|
|
51
|
+
function snapPointToGrid(point, grid) {
|
|
52
|
+
var source = grid.source;
|
|
53
|
+
var x = snapToGrid(point.x - source.x, grid.x) + source.x;
|
|
54
|
+
var y = snapToGrid(point.y - source.y, grid.y) + source.y;
|
|
55
|
+
return new Point(x, y);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Align point to grid and apply precision
|
|
60
|
+
*/
|
|
61
|
+
export function align(point, grid, precision) {
|
|
62
|
+
return snapPointToGrid(point.clone(), grid).round(precision);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Round point coordinates
|
|
67
|
+
*/
|
|
68
|
+
export function round(point, precision) {
|
|
69
|
+
return point.round(precision);
|
|
70
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAA;AACtB,cAAc,aAAa,CAAA;AAC3B,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { InternalNode } from '../options';
|
|
2
|
+
/**
|
|
3
|
+
* Node dimensions interface
|
|
4
|
+
*/
|
|
5
|
+
export interface NodeDimensions {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Get node dimensions following ReactFlow's internal logic
|
|
11
|
+
* Priority: measured > direct property > initialWidth/Height > 0
|
|
12
|
+
*
|
|
13
|
+
* @param node - ReactFlow internal node
|
|
14
|
+
* @returns Node dimensions with width and height
|
|
15
|
+
*/
|
|
16
|
+
export declare function getNodeDimensions(node: InternalNode): NodeDimensions;
|
|
17
|
+
/**
|
|
18
|
+
* Get node absolute position from internals
|
|
19
|
+
*
|
|
20
|
+
* @param node - ReactFlow internal node
|
|
21
|
+
* @returns Absolute position { x, y }
|
|
22
|
+
*/
|
|
23
|
+
export declare function getNodePosition(node: InternalNode): {
|
|
24
|
+
x: number;
|
|
25
|
+
y: number;
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/utils/node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CAKpE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAE5E"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node dimensions interface
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get node dimensions following ReactFlow's internal logic
|
|
7
|
+
* Priority: measured > direct property > initialWidth/Height > 0
|
|
8
|
+
*
|
|
9
|
+
* @param node - ReactFlow internal node
|
|
10
|
+
* @returns Node dimensions with width and height
|
|
11
|
+
*/
|
|
12
|
+
export function getNodeDimensions(node) {
|
|
13
|
+
var _ref, _ref2, _node$measured$width, _node$measured, _ref3, _ref4, _node$measured$height, _node$measured2;
|
|
14
|
+
var width = (_ref = (_ref2 = (_node$measured$width = (_node$measured = node.measured) === null || _node$measured === void 0 ? void 0 : _node$measured.width) !== null && _node$measured$width !== void 0 ? _node$measured$width : node.width) !== null && _ref2 !== void 0 ? _ref2 : node.initialWidth) !== null && _ref !== void 0 ? _ref : 0;
|
|
15
|
+
var height = (_ref3 = (_ref4 = (_node$measured$height = (_node$measured2 = node.measured) === null || _node$measured2 === void 0 ? void 0 : _node$measured2.height) !== null && _node$measured$height !== void 0 ? _node$measured$height : node.height) !== null && _ref4 !== void 0 ? _ref4 : node.initialHeight) !== null && _ref3 !== void 0 ? _ref3 : 0;
|
|
16
|
+
return {
|
|
17
|
+
width: width,
|
|
18
|
+
height: height
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get node absolute position from internals
|
|
24
|
+
*
|
|
25
|
+
* @param node - ReactFlow internal node
|
|
26
|
+
* @returns Absolute position { x, y }
|
|
27
|
+
*/
|
|
28
|
+
export function getNodePosition(node) {
|
|
29
|
+
return node.internals.positionAbsolute;
|
|
30
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Point, Rectangle } from '../geometry';
|
|
2
|
+
import type { ResolvedOptions, Direction } from '../options';
|
|
3
|
+
import type { Grid } from './grid';
|
|
4
|
+
/**
|
|
5
|
+
* Get points around a rectangle taking given directions into account
|
|
6
|
+
* Lines are drawn from anchor in given directions, intersections recorded
|
|
7
|
+
*/
|
|
8
|
+
export declare function getRectPoints(anchor: Point, bbox: Rectangle, directionList: Direction[], grid: Grid, options: ResolvedOptions): Point[];
|
|
9
|
+
//# sourceMappingURL=rect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rect.d.ts","sourceRoot":"","sources":["../../src/utils/rect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAQ,MAAM,aAAa,CAAA;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC5D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AA6ClC;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,KAAK,EACb,IAAI,EAAE,SAAS,EACf,aAAa,EAAE,SAAS,EAAE,EAC1B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,eAAe,GACvB,KAAK,EAAE,CAsET"}
|