UNPKG

@rxflow/manhattan

Version:

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

76 lines (70 loc) 2.43 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseSVGPath = parseSVGPath; exports.simplifyPath = simplifyPath; var _geometry = require("../geometry"); /** * Parse SVG path string to extract points * Simplified parser that handles M, L, Q commands */ function parseSVGPath(pathString) { const points = []; const commands = pathString.match(/[MLQ][^MLQ]*/g); if (!commands) return points; for (const command of commands) { const type = command[0]; const coords = command.slice(1).trim().split(/[\s,]+/).map(Number); if (type === 'M' || type === 'L') { // MoveTo or LineTo: x, y if (coords.length >= 2) { points.push(new _geometry.Point(coords[0], coords[1])); } } else if (type === 'Q') { // Quadratic Bezier: cx, cy, x, y // We sample points along the curve for collision detection if (coords.length >= 4) { const prevPoint = points[points.length - 1]; if (prevPoint) { const cx = coords[0]; const cy = coords[1]; const x = coords[2]; const y = coords[3]; // Sample 10 points along the bezier curve for better accuracy // This ensures we don't miss intersections with obstacles for (let t = 0.1; t <= 1; t += 0.1) { const bx = (1 - t) * (1 - t) * prevPoint.x + 2 * (1 - t) * t * cx + t * t * x; const by = (1 - t) * (1 - t) * prevPoint.y + 2 * (1 - t) * t * cy + t * t * y; points.push(new _geometry.Point(bx, by)); } } } } } return points; } /** * Simplify path by removing collinear intermediate points */ function simplifyPath(points) { if (points.length <= 2) { return points; } const simplified = [points[0]]; for (let i = 1; i < points.length - 1; i++) { const prev = simplified[simplified.length - 1]; const current = points[i]; const next = points[i + 1]; // Check if current point is collinear with prev and next const isHorizontalLine = prev.y === current.y && current.y === next.y; const isVerticalLine = prev.x === current.x && current.x === next.x; // Only keep the point if it's not collinear (i.e., it's a corner) if (!isHorizontalLine && !isVerticalLine) { simplified.push(current); } } // Always add the last point simplified.push(points[points.length - 1]); return simplified; }