@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,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.findRoute = findRoute;
|
|
7
|
+
var _SortedSet = require("./SortedSet");
|
|
8
|
+
var _utils = require("../utils");
|
|
9
|
+
/**
|
|
10
|
+
* Find route between two points using A* algorithm
|
|
11
|
+
*/
|
|
12
|
+
function findRoute(sourceBBox, targetBBox, sourceAnchor, targetAnchor, map, options) {
|
|
13
|
+
const precision = options.precision;
|
|
14
|
+
|
|
15
|
+
// Round anchor points
|
|
16
|
+
const sourceEndpoint = (0, _utils.round)(sourceAnchor.clone(), precision);
|
|
17
|
+
const targetEndpoint = (0, _utils.round)(targetAnchor.clone(), precision);
|
|
18
|
+
|
|
19
|
+
// Get grid for this route
|
|
20
|
+
const grid = (0, _utils.getGrid)(options.step, sourceEndpoint, targetEndpoint);
|
|
21
|
+
|
|
22
|
+
// Get pathfinding points
|
|
23
|
+
const startPoint = sourceEndpoint;
|
|
24
|
+
const endPoint = targetEndpoint;
|
|
25
|
+
|
|
26
|
+
// Get start and end points around rectangles
|
|
27
|
+
let startPoints = (0, _utils.getRectPoints)(startPoint, sourceBBox, options.startDirections, grid, options);
|
|
28
|
+
let endPoints = (0, _utils.getRectPoints)(targetEndpoint, targetBBox, options.endDirections, grid, options);
|
|
29
|
+
console.log('[findRoute] Start points from getRectPoints:', startPoints.map(p => `(${p.x}, ${p.y})`));
|
|
30
|
+
console.log('[findRoute] End points from getRectPoints:', endPoints.map(p => `(${p.x}, ${p.y})`));
|
|
31
|
+
|
|
32
|
+
// Take into account only accessible rect points
|
|
33
|
+
startPoints = startPoints.filter(p => map.isAccessible(p));
|
|
34
|
+
endPoints = endPoints.filter(p => map.isAccessible(p));
|
|
35
|
+
console.log('[findRoute] Start points after filter:', startPoints.map(p => `(${p.x}, ${p.y})`));
|
|
36
|
+
console.log('[findRoute] End points after filter:', endPoints.map(p => `(${p.x}, ${p.y})`));
|
|
37
|
+
|
|
38
|
+
// Ensure we always have at least the anchor points
|
|
39
|
+
// This handles edge cases where anchor is on the node boundary
|
|
40
|
+
if (startPoints.length === 0) {
|
|
41
|
+
startPoints = [(0, _utils.align)(startPoint, grid, precision)];
|
|
42
|
+
}
|
|
43
|
+
if (endPoints.length === 0) {
|
|
44
|
+
endPoints = [(0, _utils.align)(endPoint, grid, precision)];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Initialize A* data structures
|
|
48
|
+
const openSet = new _SortedSet.SortedSet();
|
|
49
|
+
const points = new Map();
|
|
50
|
+
const parents = new Map();
|
|
51
|
+
const costs = new Map();
|
|
52
|
+
|
|
53
|
+
// Add all start points to open set
|
|
54
|
+
for (const startPoint of startPoints) {
|
|
55
|
+
const key = (0, _utils.getKey)(startPoint);
|
|
56
|
+
openSet.add(key, (0, _utils.getCost)(startPoint, endPoints));
|
|
57
|
+
points.set(key, startPoint);
|
|
58
|
+
costs.set(key, 0);
|
|
59
|
+
}
|
|
60
|
+
const previousRouteDirectionAngle = options.previousDirectionAngle;
|
|
61
|
+
const isPathBeginning = previousRouteDirectionAngle === undefined;
|
|
62
|
+
|
|
63
|
+
// Get directions with grid offsets
|
|
64
|
+
const directions = (0, _utils.getGridOffsets)(grid, options);
|
|
65
|
+
const numDirections = directions.length;
|
|
66
|
+
|
|
67
|
+
// Create set of end point keys for quick lookup
|
|
68
|
+
const endPointsKeys = new Set(endPoints.map(p => (0, _utils.getKey)(p)));
|
|
69
|
+
|
|
70
|
+
// Check if start and end points are the same
|
|
71
|
+
const sameStartEndPoints = startPoints.length === endPoints.length && startPoints.every((sp, i) => sp.equals(endPoints[i]));
|
|
72
|
+
|
|
73
|
+
// Main A* loop
|
|
74
|
+
let loopsRemaining = options.maxLoopCount;
|
|
75
|
+
while (!openSet.isEmpty() && loopsRemaining > 0) {
|
|
76
|
+
// Get the closest item and mark it CLOSED
|
|
77
|
+
const currentKey = openSet.pop();
|
|
78
|
+
if (!currentKey) break;
|
|
79
|
+
const currentPoint = points.get(currentKey);
|
|
80
|
+
const currentParent = parents.get(currentKey);
|
|
81
|
+
const currentCost = costs.get(currentKey);
|
|
82
|
+
const isStartPoint = currentPoint.equals(startPoint);
|
|
83
|
+
const isRouteBeginning = currentParent === undefined;
|
|
84
|
+
|
|
85
|
+
// Calculate previous direction angle
|
|
86
|
+
let previousDirectionAngle;
|
|
87
|
+
if (!isRouteBeginning) {
|
|
88
|
+
previousDirectionAngle = (0, _utils.getDirectionAngle)(currentParent, currentPoint, numDirections, grid, options);
|
|
89
|
+
} else if (!isPathBeginning) {
|
|
90
|
+
previousDirectionAngle = previousRouteDirectionAngle;
|
|
91
|
+
} else if (!isStartPoint) {
|
|
92
|
+
previousDirectionAngle = (0, _utils.getDirectionAngle)(startPoint, currentPoint, numDirections, grid, options);
|
|
93
|
+
} else {
|
|
94
|
+
previousDirectionAngle = null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Check if we reached any endpoint
|
|
98
|
+
const skipEndCheck = isRouteBeginning && sameStartEndPoints;
|
|
99
|
+
if (!skipEndCheck && endPointsKeys.has(currentKey)) {
|
|
100
|
+
options.previousDirectionAngle = previousDirectionAngle;
|
|
101
|
+
return (0, _utils.reconstructRoute)(parents, points, currentPoint, startPoint, endPoint);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Explore neighbors in all directions
|
|
105
|
+
for (const direction of directions) {
|
|
106
|
+
const directionAngle = direction.angle;
|
|
107
|
+
const directionChange = (0, _utils.getDirectionChange)(previousDirectionAngle ?? 0, directionAngle);
|
|
108
|
+
|
|
109
|
+
// Don't use the point if direction changed too rapidly
|
|
110
|
+
if (!(isPathBeginning && isStartPoint) && directionChange > options.maxDirectionChange) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Calculate neighbor point
|
|
115
|
+
const neighborPoint = (0, _utils.align)(currentPoint.clone().translate(direction.gridOffsetX || 0, direction.gridOffsetY || 0), grid, precision);
|
|
116
|
+
const neighborKey = (0, _utils.getKey)(neighborPoint);
|
|
117
|
+
|
|
118
|
+
// Skip if closed or not accessible
|
|
119
|
+
if (openSet.isClose(neighborKey) || !map.isAccessible(neighborPoint)) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Check if neighbor is an end point
|
|
124
|
+
if (endPointsKeys.has(neighborKey)) {
|
|
125
|
+
const isEndPoint = neighborPoint.equals(endPoint);
|
|
126
|
+
if (!isEndPoint) {
|
|
127
|
+
const endDirectionAngle = (0, _utils.getDirectionAngle)(neighborPoint, endPoint, numDirections, grid, options);
|
|
128
|
+
const endDirectionChange = (0, _utils.getDirectionChange)(directionAngle, endDirectionAngle);
|
|
129
|
+
if (endDirectionChange > options.maxDirectionChange) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Calculate costs
|
|
136
|
+
const neighborCost = direction.cost;
|
|
137
|
+
const neighborPenalty = isStartPoint ? 0 : options.penalties[directionChange] || 0;
|
|
138
|
+
const costFromStart = currentCost + neighborCost + neighborPenalty;
|
|
139
|
+
|
|
140
|
+
// Update if not in open set or found better path
|
|
141
|
+
if (!openSet.isOpen(neighborKey) || costFromStart < (costs.get(neighborKey) || Infinity)) {
|
|
142
|
+
points.set(neighborKey, neighborPoint);
|
|
143
|
+
parents.set(neighborKey, currentPoint);
|
|
144
|
+
costs.set(neighborKey, costFromStart);
|
|
145
|
+
openSet.add(neighborKey, costFromStart + (0, _utils.getCost)(neighborPoint, endPoints));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
loopsRemaining -= 1;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// No path found, try fallback
|
|
152
|
+
if (options.fallbackRoute) {
|
|
153
|
+
return options.fallbackRoute(startPoint, endPoint);
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
@@ -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,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "SortedSet", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _SortedSet.SortedSet;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "findRoute", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _findRoute.findRoute;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
var _SortedSet = require("./SortedSet");
|
|
19
|
+
var _findRoute = require("./findRoute");
|
|
@@ -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/cjs/svg/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "pointsToPath", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _pathConverter.pointsToPath;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "snapPathToGrid", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _pathConverter.snapPathToGrid;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
var _pathConverter = require("./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,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.pointsToPath = pointsToPath;
|
|
7
|
+
exports.snapPathToGrid = snapPathToGrid;
|
|
8
|
+
/**
|
|
9
|
+
* Convert array of points to SVG path string
|
|
10
|
+
*/
|
|
11
|
+
function pointsToPath(points, precision, borderRadius = 0) {
|
|
12
|
+
if (points.length === 0) {
|
|
13
|
+
return '';
|
|
14
|
+
}
|
|
15
|
+
const factor = Math.pow(10, precision);
|
|
16
|
+
const roundCoord = value => Math.round(value * factor) / factor;
|
|
17
|
+
|
|
18
|
+
// If no border radius or only 2 points, use simple line path
|
|
19
|
+
if (borderRadius === 0 || points.length <= 2) {
|
|
20
|
+
const firstPoint = points[0];
|
|
21
|
+
let path = `M ${roundCoord(firstPoint.x)} ${roundCoord(firstPoint.y)}`;
|
|
22
|
+
for (let i = 1; i < points.length; i++) {
|
|
23
|
+
const point = points[i];
|
|
24
|
+
path += ` L ${roundCoord(point.x)} ${roundCoord(point.y)}`;
|
|
25
|
+
}
|
|
26
|
+
return path;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Start with M (moveTo) command for first point
|
|
30
|
+
const firstPoint = points[0];
|
|
31
|
+
let path = `M ${roundCoord(firstPoint.x)} ${roundCoord(firstPoint.y)}`;
|
|
32
|
+
|
|
33
|
+
// Process each segment with rounded corners
|
|
34
|
+
for (let i = 1; i < points.length - 1; i++) {
|
|
35
|
+
const prev = points[i - 1];
|
|
36
|
+
const current = points[i];
|
|
37
|
+
const next = points[i + 1];
|
|
38
|
+
|
|
39
|
+
// Calculate the distance from prev to current and current to next
|
|
40
|
+
const distToPrev = Math.sqrt(Math.pow(current.x - prev.x, 2) + Math.pow(current.y - prev.y, 2));
|
|
41
|
+
const distToNext = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2));
|
|
42
|
+
|
|
43
|
+
// Use the smaller of borderRadius or half the segment length
|
|
44
|
+
const radius = Math.min(borderRadius, distToPrev / 2, distToNext / 2);
|
|
45
|
+
|
|
46
|
+
// Calculate the point before the corner (on the line from prev to current)
|
|
47
|
+
const beforeCornerRatio = (distToPrev - radius) / distToPrev;
|
|
48
|
+
const beforeCorner = {
|
|
49
|
+
x: prev.x + (current.x - prev.x) * beforeCornerRatio,
|
|
50
|
+
y: prev.y + (current.y - prev.y) * beforeCornerRatio
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Calculate the point after the corner (on the line from current to next)
|
|
54
|
+
const afterCornerRatio = radius / distToNext;
|
|
55
|
+
const afterCorner = {
|
|
56
|
+
x: current.x + (next.x - current.x) * afterCornerRatio,
|
|
57
|
+
y: current.y + (next.y - current.y) * afterCornerRatio
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Draw line to the point before corner
|
|
61
|
+
path += ` L ${roundCoord(beforeCorner.x)} ${roundCoord(beforeCorner.y)}`;
|
|
62
|
+
|
|
63
|
+
// Draw quadratic bezier curve for the rounded corner
|
|
64
|
+
path += ` Q ${roundCoord(current.x)} ${roundCoord(current.y)} ${roundCoord(afterCorner.x)} ${roundCoord(afterCorner.y)}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Draw line to the last point
|
|
68
|
+
const lastPoint = points[points.length - 1];
|
|
69
|
+
path += ` L ${roundCoord(lastPoint.x)} ${roundCoord(lastPoint.y)}`;
|
|
70
|
+
return path;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Snap path to grid by aligning consecutive points
|
|
75
|
+
*/
|
|
76
|
+
function snapPathToGrid(points, gridSize) {
|
|
77
|
+
if (points.length <= 1) {
|
|
78
|
+
return points;
|
|
79
|
+
}
|
|
80
|
+
const snappedPoints = [...points];
|
|
81
|
+
|
|
82
|
+
// Don't snap the first and last points (anchors)
|
|
83
|
+
// Don't snap the second and second-to-last points (extension points)
|
|
84
|
+
// Only snap intermediate segments
|
|
85
|
+
for (let i = 2; i < snappedPoints.length - 3; i++) {
|
|
86
|
+
const first = snappedPoints[i];
|
|
87
|
+
const second = snappedPoints[i + 1];
|
|
88
|
+
if (first.x === second.x) {
|
|
89
|
+
// Vertical line - snap X coordinate
|
|
90
|
+
const x = gridSize * Math.round(first.x / gridSize);
|
|
91
|
+
if (first.x !== x) {
|
|
92
|
+
first.x = x;
|
|
93
|
+
second.x = x;
|
|
94
|
+
}
|
|
95
|
+
} else if (first.y === second.y) {
|
|
96
|
+
// Horizontal line - snap Y coordinate
|
|
97
|
+
const y = gridSize * Math.round(first.y / gridSize);
|
|
98
|
+
if (first.y !== y) {
|
|
99
|
+
first.y = y;
|
|
100
|
+
second.y = y;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return snappedPoints;
|
|
105
|
+
}
|
|
@@ -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,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getDirectionAngle = getDirectionAngle;
|
|
7
|
+
exports.getDirectionChange = getDirectionChange;
|
|
8
|
+
exports.getGridOffsets = getGridOffsets;
|
|
9
|
+
var _geometry = require("../geometry");
|
|
10
|
+
var _resolver = require("../options/resolver");
|
|
11
|
+
/**
|
|
12
|
+
* Fix angle end point to account for grid deformation
|
|
13
|
+
*/
|
|
14
|
+
function fixAngleEnd(start, end, grid, options) {
|
|
15
|
+
const step = options.step;
|
|
16
|
+
const diffX = end.x - start.x;
|
|
17
|
+
const diffY = end.y - start.y;
|
|
18
|
+
const gridStepsX = diffX / grid.x;
|
|
19
|
+
const gridStepsY = diffY / grid.y;
|
|
20
|
+
const distanceX = gridStepsX * step;
|
|
21
|
+
const distanceY = gridStepsY * step;
|
|
22
|
+
return new _geometry.Point(start.x + distanceX, start.y + distanceY);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get direction angle from start point to end point
|
|
27
|
+
* Corrects for grid deformation between start and end
|
|
28
|
+
*/
|
|
29
|
+
function getDirectionAngle(start, end, directionCount, grid, options) {
|
|
30
|
+
const quadrant = 360 / directionCount;
|
|
31
|
+
const angleTheta = start.theta(fixAngleEnd(start, end, grid, options));
|
|
32
|
+
const normalizedAngle = (0, _resolver.normalizeAngle)(angleTheta + quadrant / 2);
|
|
33
|
+
return quadrant * Math.floor(normalizedAngle / quadrant);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get the change in direction between two direction angles
|
|
38
|
+
*/
|
|
39
|
+
function getDirectionChange(angle1, angle2) {
|
|
40
|
+
const change = Math.abs(angle1 - angle2);
|
|
41
|
+
return change > 180 ? 360 - change : change;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Fix direction offsets according to current grid
|
|
46
|
+
*/
|
|
47
|
+
function getGridOffsets(grid, options) {
|
|
48
|
+
const step = options.step;
|
|
49
|
+
options.directions.forEach(direction => {
|
|
50
|
+
direction.gridOffsetX = direction.offsetX / step * grid.x;
|
|
51
|
+
direction.gridOffsetY = direction.offsetY / step * grid.y;
|
|
52
|
+
});
|
|
53
|
+
return options.directions;
|
|
54
|
+
}
|
|
@@ -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,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.align = align;
|
|
7
|
+
exports.getGrid = getGrid;
|
|
8
|
+
exports.round = round;
|
|
9
|
+
exports.snapToGrid = snapToGrid;
|
|
10
|
+
var _geometry = require("../geometry");
|
|
11
|
+
/**
|
|
12
|
+
* Grid interface for dynamic grid system
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get grid dimension for a single axis
|
|
17
|
+
*/
|
|
18
|
+
function getGridDimension(diff, step) {
|
|
19
|
+
// Return step if diff = 0
|
|
20
|
+
if (!diff) {
|
|
21
|
+
return step;
|
|
22
|
+
}
|
|
23
|
+
const abs = Math.abs(diff);
|
|
24
|
+
const count = Math.round(abs / step);
|
|
25
|
+
|
|
26
|
+
// Return abs if less than one step apart
|
|
27
|
+
if (!count) {
|
|
28
|
+
return abs;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Otherwise, return corrected step
|
|
32
|
+
const roundedDiff = count * step;
|
|
33
|
+
const remainder = abs - roundedDiff;
|
|
34
|
+
const correction = remainder / count;
|
|
35
|
+
return step + correction;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get grid size in x and y dimensions, adapted to source and target positions
|
|
40
|
+
*/
|
|
41
|
+
function getGrid(step, source, target) {
|
|
42
|
+
return {
|
|
43
|
+
source: source.clone(),
|
|
44
|
+
x: getGridDimension(target.x - source.x, step),
|
|
45
|
+
y: getGridDimension(target.y - source.y, step)
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Snap a value to grid
|
|
51
|
+
*/
|
|
52
|
+
function snapToGrid(value, gridSize) {
|
|
53
|
+
return Math.round(value / gridSize) * gridSize;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Snap a point to grid
|
|
58
|
+
*/
|
|
59
|
+
function snapPointToGrid(point, grid) {
|
|
60
|
+
const source = grid.source;
|
|
61
|
+
const x = snapToGrid(point.x - source.x, grid.x) + source.x;
|
|
62
|
+
const y = snapToGrid(point.y - source.y, grid.y) + source.y;
|
|
63
|
+
return new _geometry.Point(x, y);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Align point to grid and apply precision
|
|
68
|
+
*/
|
|
69
|
+
function align(point, grid, precision) {
|
|
70
|
+
return snapPointToGrid(point.clone(), grid).round(precision);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Round point coordinates
|
|
75
|
+
*/
|
|
76
|
+
function round(point, precision) {
|
|
77
|
+
return point.round(precision);
|
|
78
|
+
}
|
|
@@ -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,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _grid = require("./grid");
|
|
7
|
+
Object.keys(_grid).forEach(function (key) {
|
|
8
|
+
if (key === "default" || key === "__esModule") return;
|
|
9
|
+
if (key in exports && exports[key] === _grid[key]) return;
|
|
10
|
+
Object.defineProperty(exports, key, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function () {
|
|
13
|
+
return _grid[key];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
var _direction = require("./direction");
|
|
18
|
+
Object.keys(_direction).forEach(function (key) {
|
|
19
|
+
if (key === "default" || key === "__esModule") return;
|
|
20
|
+
if (key in exports && exports[key] === _direction[key]) return;
|
|
21
|
+
Object.defineProperty(exports, key, {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get: function () {
|
|
24
|
+
return _direction[key];
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
var _rect = require("./rect");
|
|
29
|
+
Object.keys(_rect).forEach(function (key) {
|
|
30
|
+
if (key === "default" || key === "__esModule") return;
|
|
31
|
+
if (key in exports && exports[key] === _rect[key]) return;
|
|
32
|
+
Object.defineProperty(exports, key, {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get: function () {
|
|
35
|
+
return _rect[key];
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
var _route = require("./route");
|
|
40
|
+
Object.keys(_route).forEach(function (key) {
|
|
41
|
+
if (key === "default" || key === "__esModule") return;
|
|
42
|
+
if (key in exports && exports[key] === _route[key]) return;
|
|
43
|
+
Object.defineProperty(exports, key, {
|
|
44
|
+
enumerable: true,
|
|
45
|
+
get: function () {
|
|
46
|
+
return _route[key];
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
var _node = require("./node");
|
|
51
|
+
Object.keys(_node).forEach(function (key) {
|
|
52
|
+
if (key === "default" || key === "__esModule") return;
|
|
53
|
+
if (key in exports && exports[key] === _node[key]) return;
|
|
54
|
+
Object.defineProperty(exports, key, {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function () {
|
|
57
|
+
return _node[key];
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -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,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getNodeDimensions = getNodeDimensions;
|
|
7
|
+
exports.getNodePosition = getNodePosition;
|
|
8
|
+
/**
|
|
9
|
+
* Node dimensions interface
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get node dimensions following ReactFlow's internal logic
|
|
14
|
+
* Priority: measured > direct property > initialWidth/Height > 0
|
|
15
|
+
*
|
|
16
|
+
* @param node - ReactFlow internal node
|
|
17
|
+
* @returns Node dimensions with width and height
|
|
18
|
+
*/
|
|
19
|
+
function getNodeDimensions(node) {
|
|
20
|
+
const width = node.measured?.width ?? node.width ?? node.initialWidth ?? 0;
|
|
21
|
+
const height = node.measured?.height ?? node.height ?? node.initialHeight ?? 0;
|
|
22
|
+
return {
|
|
23
|
+
width,
|
|
24
|
+
height
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get node absolute position from internals
|
|
30
|
+
*
|
|
31
|
+
* @param node - ReactFlow internal node
|
|
32
|
+
* @returns Absolute position { x, y }
|
|
33
|
+
*/
|
|
34
|
+
function getNodePosition(node) {
|
|
35
|
+
return node.internals.positionAbsolute;
|
|
36
|
+
}
|
|
@@ -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
|