@rxflow/manhattan 0.0.1-alpha.0 → 0.0.1-alpha.10
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/cjs/geometry/collision.d.ts +15 -0
- package/cjs/geometry/collision.d.ts.map +1 -0
- package/cjs/geometry/collision.js +81 -0
- package/cjs/geometry/index.d.ts +1 -0
- package/cjs/geometry/index.d.ts.map +1 -1
- package/cjs/geometry/index.js +20 -1
- package/cjs/getManHattanPath.d.ts +7 -14
- package/cjs/getManHattanPath.d.ts.map +1 -1
- package/cjs/getManHattanPath.js +54 -54
- package/cjs/options/defaults.js +1 -1
- package/cjs/svg/index.d.ts +1 -0
- package/cjs/svg/index.d.ts.map +1 -1
- package/cjs/svg/index.js +14 -1
- package/cjs/svg/pathParser.d.ts +11 -0
- package/cjs/svg/pathParser.d.ts.map +1 -0
- package/cjs/svg/pathParser.js +76 -0
- package/cjs/utils/grid.d.ts.map +1 -1
- package/cjs/utils/grid.js +3 -17
- package/cjs/utils/index.d.ts +1 -0
- package/cjs/utils/index.d.ts.map +1 -1
- package/cjs/utils/index.js +11 -0
- package/cjs/utils/pathValidation.d.ts +11 -0
- package/cjs/utils/pathValidation.d.ts.map +1 -0
- package/cjs/utils/pathValidation.js +130 -0
- package/esm/geometry/collision.d.ts +15 -0
- package/esm/geometry/collision.d.ts.map +1 -0
- package/esm/geometry/collision.js +73 -0
- package/esm/geometry/index.d.ts +1 -0
- package/esm/geometry/index.d.ts.map +1 -1
- package/esm/geometry/index.js +2 -1
- package/esm/getManHattanPath.d.ts +7 -14
- package/esm/getManHattanPath.d.ts.map +1 -1
- package/esm/getManHattanPath.js +70 -64
- package/esm/options/defaults.js +1 -1
- package/esm/svg/index.d.ts +1 -0
- package/esm/svg/index.d.ts.map +1 -1
- package/esm/svg/index.js +2 -1
- package/esm/svg/pathParser.d.ts +11 -0
- package/esm/svg/pathParser.d.ts.map +1 -0
- package/esm/svg/pathParser.js +82 -0
- package/esm/utils/grid.d.ts.map +1 -1
- package/esm/utils/grid.js +3 -17
- package/esm/utils/index.d.ts +1 -0
- package/esm/utils/index.d.ts.map +1 -1
- package/esm/utils/index.js +2 -1
- package/esm/utils/pathValidation.d.ts +11 -0
- package/esm/utils/pathValidation.d.ts.map +1 -0
- package/esm/utils/pathValidation.js +162 -0
- package/package.json +1 -1
package/esm/utils/grid.d.ts.map
CHANGED
|
@@ -1 +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;
|
|
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;AAWD;;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"}
|
package/esm/utils/grid.js
CHANGED
|
@@ -8,23 +8,9 @@ import { Point } from "../geometry";
|
|
|
8
8
|
* Get grid dimension for a single axis
|
|
9
9
|
*/
|
|
10
10
|
function getGridDimension(diff, step) {
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
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;
|
|
11
|
+
// Always return fixed step size to maintain consistent padding
|
|
12
|
+
// This ensures paths stay at least 'padding' distance from obstacles
|
|
13
|
+
return step;
|
|
28
14
|
}
|
|
29
15
|
|
|
30
16
|
/**
|
package/esm/utils/index.d.ts
CHANGED
package/esm/utils/index.d.ts.map
CHANGED
|
@@ -1 +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"}
|
|
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;AACtB,cAAc,kBAAkB,CAAA"}
|
package/esm/utils/index.js
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Point } from '../geometry';
|
|
2
|
+
import type { NodeLookup } from '../options';
|
|
3
|
+
/**
|
|
4
|
+
* Check if a path intersects with any obstacles (nodes)
|
|
5
|
+
* A path is considered to intersect if it has >= 2 unique intersection points with a node
|
|
6
|
+
*
|
|
7
|
+
* Note: pathPoints should be pre-processed by parseSVGPath which samples bezier curves
|
|
8
|
+
* into line segments, so this function works correctly with curved paths
|
|
9
|
+
*/
|
|
10
|
+
export declare function pathIntersectsObstacles(pathPoints: Point[], nodeLookup: NodeLookup): boolean;
|
|
11
|
+
//# sourceMappingURL=pathValidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathValidation.d.ts","sourceRoot":"","sources":["../../src/utils/pathValidation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAa,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAyF5C;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAoC5F"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
2
|
+
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."); }
|
|
3
|
+
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; } }
|
|
4
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
5
|
+
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; } } }; }
|
|
6
|
+
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); }
|
|
7
|
+
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; }
|
|
8
|
+
import { Point, Rectangle } from "../geometry";
|
|
9
|
+
import { getNodeDimensions, getNodePosition } from "./node";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Get node bounding box
|
|
13
|
+
*/
|
|
14
|
+
function getNodeBBox(nodeId, nodeLookup) {
|
|
15
|
+
var node = nodeLookup.get(nodeId);
|
|
16
|
+
if (!node) return null;
|
|
17
|
+
var dimensions = getNodeDimensions(node);
|
|
18
|
+
var position = getNodePosition(node);
|
|
19
|
+
return new Rectangle(position.x, position.y, dimensions.width, dimensions.height);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Find unique intersection points between a line segment and a rectangle
|
|
24
|
+
* Returns array of intersection points (deduplicated)
|
|
25
|
+
*/
|
|
26
|
+
function findSegmentRectIntersections(p1, p2, rect) {
|
|
27
|
+
var intersections = [];
|
|
28
|
+
var tolerance = 0.01;
|
|
29
|
+
|
|
30
|
+
// Define rectangle edges
|
|
31
|
+
var edges = [{
|
|
32
|
+
start: new Point(rect.x, rect.y),
|
|
33
|
+
end: new Point(rect.x + rect.width, rect.y)
|
|
34
|
+
},
|
|
35
|
+
// Top
|
|
36
|
+
{
|
|
37
|
+
start: new Point(rect.x + rect.width, rect.y),
|
|
38
|
+
end: new Point(rect.x + rect.width, rect.y + rect.height)
|
|
39
|
+
},
|
|
40
|
+
// Right
|
|
41
|
+
{
|
|
42
|
+
start: new Point(rect.x + rect.width, rect.y + rect.height),
|
|
43
|
+
end: new Point(rect.x, rect.y + rect.height)
|
|
44
|
+
},
|
|
45
|
+
// Bottom
|
|
46
|
+
{
|
|
47
|
+
start: new Point(rect.x, rect.y + rect.height),
|
|
48
|
+
end: new Point(rect.x, rect.y)
|
|
49
|
+
} // Left
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
// Find intersection point with each edge
|
|
53
|
+
var _loop = function _loop() {
|
|
54
|
+
var edge = _edges[_i];
|
|
55
|
+
var intersection = getLineSegmentIntersection(p1, p2, edge.start, edge.end);
|
|
56
|
+
if (intersection) {
|
|
57
|
+
// Check if this point is already in the list (avoid duplicates at corners)
|
|
58
|
+
var isDuplicate = intersections.some(function (existing) {
|
|
59
|
+
return Math.abs(existing.x - intersection.x) < tolerance && Math.abs(existing.y - intersection.y) < tolerance;
|
|
60
|
+
});
|
|
61
|
+
if (!isDuplicate) {
|
|
62
|
+
intersections.push(intersection);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
for (var _i = 0, _edges = edges; _i < _edges.length; _i++) {
|
|
67
|
+
_loop();
|
|
68
|
+
}
|
|
69
|
+
return intersections;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get intersection point between two line segments (if exists)
|
|
74
|
+
*/
|
|
75
|
+
function getLineSegmentIntersection(p1, p2, p3, p4) {
|
|
76
|
+
var d1 = direction(p3, p4, p1);
|
|
77
|
+
var d2 = direction(p3, p4, p2);
|
|
78
|
+
var d3 = direction(p1, p2, p3);
|
|
79
|
+
var d4 = direction(p1, p2, p4);
|
|
80
|
+
if ((d1 > 0 && d2 < 0 || d1 < 0 && d2 > 0) && (d3 > 0 && d4 < 0 || d3 < 0 && d4 > 0)) {
|
|
81
|
+
// Lines intersect, calculate intersection point
|
|
82
|
+
var t = ((p3.x - p1.x) * (p3.y - p4.y) - (p3.y - p1.y) * (p3.x - p4.x)) / ((p1.x - p2.x) * (p3.y - p4.y) - (p1.y - p2.y) * (p3.x - p4.x));
|
|
83
|
+
return new Point(p1.x + t * (p2.x - p1.x), p1.y + t * (p2.y - p1.y));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Check collinear cases
|
|
87
|
+
if (d1 === 0 && onSegment(p3, p1, p4)) return p1.clone();
|
|
88
|
+
if (d2 === 0 && onSegment(p3, p2, p4)) return p2.clone();
|
|
89
|
+
if (d3 === 0 && onSegment(p1, p3, p2)) return p3.clone();
|
|
90
|
+
if (d4 === 0 && onSegment(p1, p4, p2)) return p4.clone();
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
function direction(p1, p2, p3) {
|
|
94
|
+
return (p3.x - p1.x) * (p2.y - p1.y) - (p2.x - p1.x) * (p3.y - p1.y);
|
|
95
|
+
}
|
|
96
|
+
function onSegment(p1, p2, p3) {
|
|
97
|
+
return p2.x >= Math.min(p1.x, p3.x) && p2.x <= Math.max(p1.x, p3.x) && p2.y >= Math.min(p1.y, p3.y) && p2.y <= Math.max(p1.y, p3.y);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Check if a path intersects with any obstacles (nodes)
|
|
102
|
+
* A path is considered to intersect if it has >= 2 unique intersection points with a node
|
|
103
|
+
*
|
|
104
|
+
* Note: pathPoints should be pre-processed by parseSVGPath which samples bezier curves
|
|
105
|
+
* into line segments, so this function works correctly with curved paths
|
|
106
|
+
*/
|
|
107
|
+
export function pathIntersectsObstacles(pathPoints, nodeLookup) {
|
|
108
|
+
var tolerance = 0.01;
|
|
109
|
+
|
|
110
|
+
// Iterate through all nodes (including source and target)
|
|
111
|
+
var _iterator = _createForOfIteratorHelper(nodeLookup),
|
|
112
|
+
_step;
|
|
113
|
+
try {
|
|
114
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
115
|
+
var _step$value = _slicedToArray(_step.value, 1),
|
|
116
|
+
nodeId = _step$value[0];
|
|
117
|
+
var nodeBBox = getNodeBBox(nodeId, nodeLookup);
|
|
118
|
+
if (!nodeBBox) continue;
|
|
119
|
+
var allIntersections = [];
|
|
120
|
+
|
|
121
|
+
// Collect all unique intersection points for this node
|
|
122
|
+
for (var i = 0; i < pathPoints.length - 1; i++) {
|
|
123
|
+
var p1 = pathPoints[i];
|
|
124
|
+
var p2 = pathPoints[i + 1];
|
|
125
|
+
var segmentIntersections = findSegmentRectIntersections(p1, p2, nodeBBox);
|
|
126
|
+
|
|
127
|
+
// Add to global list, avoiding duplicates
|
|
128
|
+
var _iterator2 = _createForOfIteratorHelper(segmentIntersections),
|
|
129
|
+
_step2;
|
|
130
|
+
try {
|
|
131
|
+
var _loop2 = function _loop2() {
|
|
132
|
+
var intersection = _step2.value;
|
|
133
|
+
var isDuplicate = allIntersections.some(function (existing) {
|
|
134
|
+
return Math.abs(existing.x - intersection.x) < tolerance && Math.abs(existing.y - intersection.y) < tolerance;
|
|
135
|
+
});
|
|
136
|
+
if (!isDuplicate) {
|
|
137
|
+
allIntersections.push(intersection);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
141
|
+
_loop2();
|
|
142
|
+
}
|
|
143
|
+
} catch (err) {
|
|
144
|
+
_iterator2.e(err);
|
|
145
|
+
} finally {
|
|
146
|
+
_iterator2.f();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// If path has 2 or more unique intersections with this node, it crosses through it
|
|
151
|
+
if (allIntersections.length >= 2) {
|
|
152
|
+
console.log("[pathIntersectsObstacles] Path crosses node ".concat(nodeId, " with ").concat(allIntersections.length, " intersections"));
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
} catch (err) {
|
|
157
|
+
_iterator.e(err);
|
|
158
|
+
} finally {
|
|
159
|
+
_iterator.f();
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
}
|
package/package.json
CHANGED