UNPKG

@rxflow/manhattan

Version:

Manhattan routing algorithm for ReactFlow - generates orthogonal paths with obstacle avoidance

73 lines (67 loc) 2.37 kB
import { Point } from "./Point"; /** * Check if a line segment intersects with a rectangle */ export 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 var rectPoints = [new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Point(rect.x, rect.y + rect.height)]; for (var i = 0; i < 4; i++) { var r1 = rectPoints[i]; var 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) */ export function lineSegmentCrossesRect(p1, p2, rect) { var 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 var steps = 10; for (var i = 1; i < steps; i++) { var t = i / steps; var x = p1.x + (p2.x - p1.x) * t; var 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 */ export function lineSegmentsIntersect(p1, p2, p3, p4) { var d1 = direction(p3, p4, p1); var d2 = direction(p3, p4, p2); var d3 = direction(p1, p2, p3); var 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); }