@rxflow/manhattan
Version:
Manhattan routing algorithm for ReactFlow - generates orthogonal paths with obstacle avoidance
81 lines (74 loc) • 2.65 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.lineSegmentCrossesRect = lineSegmentCrossesRect;
exports.lineSegmentIntersectsRect = lineSegmentIntersectsRect;
exports.lineSegmentsIntersect = lineSegmentsIntersect;
var _Point = require("./Point");
/**
* Check if a line segment intersects with a rectangle
*/
function lineSegmentIntersectsRect(p1, p2, rect) {
// Check if either endpoint is inside the rectangle
if (rect.containsPoint(p1) || rect.containsPoint(p2)) {
return true;
}
// Check if line segment intersects any of the rectangle's edges
const rectPoints = [new _Point.Point(rect.x, rect.y), new _Point.Point(rect.x + rect.width, rect.y), new _Point.Point(rect.x + rect.width, rect.y + rect.height), new _Point.Point(rect.x, rect.y + rect.height)];
for (let i = 0; i < 4; i++) {
const r1 = rectPoints[i];
const r2 = rectPoints[(i + 1) % 4];
if (lineSegmentsIntersect(p1, p2, r1, r2)) {
return true;
}
}
return false;
}
/**
* Check if a line segment crosses through a rectangle (not just touching edges)
*/
function lineSegmentCrossesRect(p1, p2, rect) {
const tolerance = 1;
// Check if segment passes through the interior of the rectangle
// We sample points along the segment and check if any are strictly inside
const steps = 10;
for (let i = 1; i < steps; i++) {
const t = i / steps;
const x = p1.x + (p2.x - p1.x) * t;
const y = p1.y + (p2.y - p1.y) * t;
if (x > rect.x + tolerance && x < rect.x + rect.width - tolerance && y > rect.y + tolerance && y < rect.y + rect.height - tolerance) {
return true;
}
}
return false;
}
/**
* Check if two line segments intersect
*/
function lineSegmentsIntersect(p1, p2, p3, p4) {
const d1 = direction(p3, p4, p1);
const d2 = direction(p3, p4, p2);
const d3 = direction(p1, p2, p3);
const d4 = direction(p1, p2, p4);
if ((d1 > 0 && d2 < 0 || d1 < 0 && d2 > 0) && (d3 > 0 && d4 < 0 || d3 < 0 && d4 > 0)) {
return true;
}
if (d1 === 0 && onSegment(p3, p1, p4)) return true;
if (d2 === 0 && onSegment(p3, p2, p4)) return true;
if (d3 === 0 && onSegment(p1, p3, p2)) return true;
if (d4 === 0 && onSegment(p1, p4, p2)) return true;
return false;
}
/**
* Calculate direction of point p3 relative to line p1-p2
*/
function direction(p1, p2, p3) {
return (p3.x - p1.x) * (p2.y - p1.y) - (p2.x - p1.x) * (p3.y - p1.y);
}
/**
* Check if point p2 is on line segment p1-p3
*/
function onSegment(p1, p2, p3) {
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);
}