@rxflow/manhattan
Version:
Manhattan routing algorithm for ReactFlow - generates orthogonal paths with obstacle avoidance
76 lines (69 loc) • 1.95 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getCost = getCost;
exports.getKey = getKey;
exports.normalizePoint = normalizePoint;
exports.reconstructRoute = reconstructRoute;
var _geometry = require("../geometry");
/**
* Normalize a point to a unit direction vector
*/
function normalizePoint(point) {
return new _geometry.Point(point.x === 0 ? 0 : Math.abs(point.x) / point.x, point.y === 0 ? 0 : Math.abs(point.y) / point.y);
}
/**
* Get string key for a point
*/
function getKey(point) {
return point.toString();
}
/**
* Calculate minimum Manhattan distance from a point to multiple anchors
*/
function getCost(from, anchors) {
let min = Infinity;
for (const anchor of anchors) {
const dist = from.manhattanDistance(anchor);
if (dist < min) {
min = dist;
}
}
return min;
}
/**
* Reconstruct route by concatenating points with their parents
* Removes redundant points in the same direction
*/
function reconstructRoute(parents, points, tailPoint, startPoint, endPoint) {
const route = [];
let prevDiff = normalizePoint(endPoint.diff(tailPoint));
// tailPoint is assumed to be aligned already
let currentKey = getKey(tailPoint);
let parent = parents.get(currentKey);
let point;
while (parent) {
// point is assumed to be aligned already
point = points.get(currentKey);
if (point) {
const diff = normalizePoint(point.diff(parent));
if (!diff.equals(prevDiff)) {
route.unshift(point);
prevDiff = diff;
}
}
// parent is assumed to be aligned already
currentKey = getKey(parent);
parent = parents.get(currentKey);
}
// leadPoint is assumed to be aligned already
const leadPoint = points.get(currentKey);
if (leadPoint) {
const fromDiff = normalizePoint(leadPoint.diff(startPoint));
if (!fromDiff.equals(prevDiff)) {
route.unshift(leadPoint);
}
}
return route;
}