ngx-diagrams
Version:
> Light Weight, Modular, Typed Diagram Engine for Angular
77 lines • 12.2 kB
JavaScript
import * as PF from 'pathfinding';
export const ROUTING_SCALING_FACTOR = 10;
export class PathFinding {
constructor(diagramEngine, heuristic = PF.Heuristic.manhattan) {
this.diagramEngine = diagramEngine;
this.pathFinderInstance = new PF.AStarFinder({
heuristic,
diagonalMovement: PF.DiagonalMovement.Always,
weight: 0,
});
}
/**
* Taking as argument a fully unblocked walking matrix, this method
* finds a direct path from point A to B.
*/
calculateDirectPath(from, to) {
const matrix = this.diagramEngine.getCanvasMatrix();
const grid = new PF.Grid(matrix);
const fromX = this.diagramEngine.translateRoutingX(Math.floor(from.x / ROUTING_SCALING_FACTOR));
const toX = this.diagramEngine.translateRoutingX(Math.floor(to.x / ROUTING_SCALING_FACTOR));
const fromY = this.diagramEngine.translateRoutingX(Math.floor(from.y / ROUTING_SCALING_FACTOR));
const toY = this.diagramEngine.translateRoutingX(Math.floor(to.y / ROUTING_SCALING_FACTOR));
const path = this.pathFinderInstance.findPath(fromX, fromY, toX, toY, grid);
return path;
}
/**
* Using @link{#calculateDirectPath}'s result as input, we here
* determine the first walkable point found in the matrix that includes
* blocked paths.
*/
calculateLinkStartEndCoords(matrix, path) {
const startIndex = path.findIndex((point) => matrix[point[1]][point[0]] === 0);
const endIndex = path.length -
1 -
path
.slice()
.reverse()
.findIndex((point) => matrix[point[1]][point[0]] === 0);
// are we trying to create a path exclusively through blocked areas?
// if so, let's fallback to the linear routing
if (startIndex === -1 || endIndex === -1) {
return undefined;
}
const pathToStart = path.slice(0, startIndex);
const pathToEnd = path.slice(endIndex);
return {
start: {
x: path[startIndex][0],
y: path[startIndex][1],
},
end: {
x: path[endIndex][0],
y: path[endIndex][1],
},
pathToStart,
pathToEnd,
};
}
/**
* Puts everything together: merges the paths from/to the centre of the ports,
* with the path calculated around other elements.
*/
calculateDynamicPath(routingMatrix, start, end, pathToStart, pathToEnd) {
// generate the path based on the matrix with obstacles
const grid = new PF.Grid(routingMatrix);
const dynamicPath = this.pathFinderInstance.findPath(start.x, start.y, end.x, end.y, grid);
// aggregate everything to have the calculated path ready for rendering
const pathCoords = pathToStart
.concat(dynamicPath, pathToEnd)
.map((coords) => [
this.diagramEngine.translateRoutingX(coords[0], true),
this.diagramEngine.translateRoutingY(coords[1], true),
]);
return PF.Util.compressPath(pathCoords);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnQtcm91dGluZy5wbHVnaW4uanMiLCJzb3VyY2VSb290IjoiLi4vLi4vLi4vLi4vbGlicy9uZ3gtZGlhZ3JhbXMvc3JjLyIsInNvdXJjZXMiOlsibGliL3BsdWdpbnMvc21hcnQtcm91dGluZy5wbHVnaW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFbEMsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsRUFBRSxDQUFDO0FBRXpDLE1BQU0sT0FBTyxXQUFXO0lBT3RCLFlBQ1UsYUFBNEIsRUFDcEMsU0FBUyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsU0FBUztRQUQxQixrQkFBYSxHQUFiLGFBQWEsQ0FBZTtRQUdwQyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxFQUFFLENBQUMsV0FBVyxDQUFDO1lBQzNDLFNBQVM7WUFDVCxnQkFBZ0IsRUFBRSxFQUFFLENBQUMsZ0JBQWdCLENBQUMsTUFBTTtZQUM1QyxNQUFNLEVBQUUsQ0FBQztTQUNWLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7O09BR0c7SUFDSCxtQkFBbUIsQ0FDakIsSUFHQyxFQUNELEVBR0M7UUFFRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3BELE1BQU0sSUFBSSxHQUFHLElBQUksRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUVqQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLGlCQUFpQixDQUNoRCxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsc0JBQXNCLENBQUMsQ0FDNUMsQ0FBQztRQUNGLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsaUJBQWlCLENBQzlDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxzQkFBc0IsQ0FBQyxDQUMxQyxDQUFD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SUFBSSxDQUFDO1lBQ3JELElBQUksQ0FBQyxhQUFhLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQztTQUN0RCxDQUFDLENBQUM7UUFFTCxPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzFDLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERpYWdyYW1FbmdpbmUgfSBmcm9tICcuLi9zZXJ2aWNlcy9lbmdpbmUuc2VydmljZSc7XG5pbXBvcnQgKiBhcyBQRiBmcm9tICdwYXRoZmluZGluZyc7XG5cbmV4cG9ydCBjb25zdCBST1VUSU5HX1NDQUxJTkdfRkFDVE9SID0gMTA7XG5cbmV4cG9ydCBjbGFzcyBQYXRoRmluZGluZyB7XG4gIHByaXZhdGUgcGF0aEZpbmRlckluc3RhbmNlOlxuICAgIHwgUEYuSlBGTmV2ZXJNb3ZlRGlhZ29uYWxseVxuICAgIHwgUEYuSlBGQWx3YXlzTW92ZURpYWdvbmFsbHlcbiAgICB8IFBGLkpQRk1vdmVEaWFnb25hbGx5SWZOb09ic3RhY2xlc1xuICAgIHwgUEYuSlBGTW92ZURpYWdvbmFsbHlJZkF0TW9zdE9uZU9ic3RhY2xlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZGlhZ3JhbUVuZ2luZTogRGlhZ3JhbUVuZ2luZSxcbiAgICBoZXVyaXN0aWMgPSBQRi5IZXVyaXN0aWMubWFuaGF0dGFuXG4gICkge1xuICAgIHRoaXMucGF0aEZpbmRlckluc3RhbmNlID0gbmV3IFBGLkFTdGFyRmluZGVyKHtcbiAgICAgIGhldXJpc3RpYyxcbiAgICAgIGRpYWdvbmFsTW92ZW1lbnQ6IFBGLkRpYWdvbmFsTW92ZW1lbnQuQWx3YXlzLFxuICAgICAgd2VpZ2h0OiAwLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRha2luZyBhcyBhcmd1bWVudCBhIGZ1bGx5IHVuYmxvY2tlZCB3YWxraW5nIG1hdHJpeCwgdGhpcyBtZXRob2RcbiAgICogZmluZHMgYSBkaXJlY3QgcGF0aCBmcm9tIHBvaW50IEEgdG8gQi5cbiAgICovXG4gIGNhbGN1bGF0ZURpcmVjdFBhdGgoXG4gICAgZnJvbToge1xuICAgICAgeDogbnVtYmVyO1xuICAgICAgeTogbnVtYmVyO1xuICAgIH0sXG4gICAgdG86IHtcbiAgICAgIHg6IG51bWJlcjtcbiAgICAgIHk6IG51bWJlcjtcbiAgICB9XG4gICk6IG51bWJlcltdW10ge1xuICAgIGNvbnN0IG1hdHJpeCA9IHRoaXMuZGlhZ3JhbUVuZ2luZS5nZXRDYW52YXNNYXRyaXgoKTtcbiAgICBjb25zdCBncmlkID0gbmV3IFBGLkdyaWQobWF0cml4KTtcblxuICAgIGNvbnN0IGZyb21YID0gdGhpcy5kaWFncmFtRW5naW5lLnRyYW5zbGF0ZVJvdXRpbmdYKFxuICAgICAgTWF0aC5mbG9vcihmcm9tLnggLyBST1VUSU5HX1NDQUxJTkdfRkFDVE9SKVxuICAgICk7XG4gICAgY29uc3QgdG9YID0gdGhpcy5kaWFncmFtRW5naW5lLnRyYW5zbGF0ZVJvdXRpbmdYKFxuICAgICAgTWF0aC5mbG9vcih0by54IC8gUk9VVElOR19TQ0FMSU5HX0ZBQ1RPUilcbiAgICApO1xuICAgIGNvbnN0IGZyb21ZID0gdGhpcy5kaWFncmFtRW5naW5lLnRyYW5zbGF0ZVJvdXRpbmdYKFxuICAgICAgTWF0aC5mbG9vcihmcm9tLnkgLyBST1VUSU5HX1NDQUxJTkdfRkFDVE9SKVxuICAgICk7XG4gICAgY29uc3QgdG9ZID0gdGhpcy5kaWFncmFtRW5naW5lLnRyYW5zbGF0ZVJvdXRpbmdYKFxuICAgICAgTWF0aC5mbG9vcih0by55IC8gUk9VVElOR19TQ0FMSU5HX0ZBQ1RPUilcbiAgICApO1xuXG4gICAgY29uc3QgcGF0aCA9IHRoaXMucGF0aEZpbmRlckluc3RhbmNlLmZpbmRQYXRoKGZyb21YLCBmcm9tWSwgdG9YLCB0b1ksIGdyaWQpO1xuICAgIHJldHVybiBwYXRoO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzaW5nIEBsaW5reyNjYWxjdWxhdGVEaXJlY3RQYXRofSdzIHJlc3VsdCBhcyBpbnB1dCwgd2UgaGVyZVxuICAgKiBkZXRlcm1pbmUgdGhlIGZpcnN0IHdhbGthYmxlIHBvaW50IGZvdW5kIGluIHRoZSBtYXRyaXggdGhhdCBpbmNsdWRlc1xuICAgKiBibG9ja2VkIHBhdGhzLlxuICAgKi9cbiAgY2FsY3VsYXRlTGlua1N0YXJ0RW5kQ29vcmRzKFxuICAgIG1hdHJpeDogbnVtYmVyW11bXSxcbiAgICBwYXRoOiBudW1iZXJbXVtdXG4gICk6IHtcbiAgICBzdGFydDoge1xuICAgICAgeDogbnVtYmVyO1xuICAgICAgeTogbnVtYmVyO1xuICAgIH07XG4gICAgZW5kOiB7XG4gICAgICB4OiBudW1iZXI7XG4gICAgICB5OiBudW1iZXI7XG4gICAgfTtcbiAgICBwYXRoVG9TdGFydDogbnVtYmVyW11bXTtcbiAgICBwYXRoVG9FbmQ6IG51bWJlcltdW107XG4gIH0ge1xuICAgIGNvbnN0IHN0YXJ0SW5kZXggPSBwYXRoLmZpbmRJbmRleChcbiAgICAgIChwb2ludCkgPT4gbWF0cml4W3BvaW50WzFdXVtwb2ludFswXV0gPT09IDBcbiAgICApO1xuICAgIGNvbnN0IGVuZEluZGV4ID1cbiAgICAgIHBhdGgubGVuZ3RoIC1cbiAgICAgIDEgLVxuICAgICAgcGF0aFxuICAgICAgICAuc2xpY2UoKVxuICAgICAgICAucmV2ZXJzZSgpXG4gICAgICAgIC5maW5kSW5kZXgoKHBvaW50KSA9PiBtYXRyaXhbcG9pbnRbMV1dW3BvaW50WzBdXSA9PT0gMCk7XG5cbiAgICAvLyBhcmUgd2UgdHJ5aW5nIHRvIGNyZWF0ZSBhIHBhdGggZXhjbHVzaXZlbHkgdGhyb3VnaCBibG9ja2VkIGFyZWFzP1xuICAgIC8vIGlmIHNvLCBsZXQncyBmYWxsYmFjayB0byB0aGUgbGluZWFyIHJvdXRpbmdcbiAgICBpZiAoc3RhcnRJbmRleCA9PT0gLTEgfHwgZW5kSW5kZXggPT09IC0xKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGNvbnN0IHBhdGhUb1N0YXJ0ID0gcGF0aC5zbGljZSgwLCBzdGFydEluZGV4KTtcbiAgICBjb25zdCBwYXRoVG9FbmQgPSBwYXRoLnNsaWNlKGVuZEluZGV4KTtcblxuICAgIHJldHVybiB7XG4gICAgICBzdGFydDoge1xuICAgICAgICB4OiBwYXRoW3N0YXJ0SW5kZXhdWzBdLFxuICAgICAgICB5OiBwYXRoW3N0YXJ0SW5kZXhdWzFdLFxuICAgICAgfSxcbiAgICAgIGVuZDoge1xuICAgICAgICB4OiBwYXRoW2VuZEluZGV4XVswXSxcbiAgICAgICAgeTogcGF0aFtlbmRJbmRleF1bMV0sXG4gICAgICB9LFxuICAgICAgcGF0aFRvU3RhcnQsXG4gICAgICBwYXRoVG9FbmQsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQdXRzIGV2ZXJ5dGhpbmcgdG9nZXRoZXI6IG1lcmdlcyB0aGUgcGF0aHMgZnJvbS90byB0aGUgY2VudHJlIG9mIHRoZSBwb3J0cyxcbiAgICogd2l0aCB0aGUgcGF0aCBjYWxjdWxhdGVkIGFyb3VuZCBvdGhlciBlbGVtZW50cy5cbiAgICovXG4gIGNhbGN1bGF0ZUR5bmFtaWNQYXRoKFxuICAgIHJvdXRpbmdNYXRyaXg6IG51bWJlcltdW10sXG4gICAgc3RhcnQ6IHtcbiAgICAgIHg6IG51bWJlcjtcbiAgICAgIHk6IG51bWJlcjtcbiAgICB9LFxuICAgIGVuZDoge1xuICAgICAgeDogbnVtYmVyO1xuICAgICAgeTogbnVtYmVyO1xuICAgIH0sXG4gICAgcGF0aFRvU3RhcnQ6IG51bWJlcltdW10sXG4gICAgcGF0aFRvRW5kOiBudW1iZXJbXVtdXG4gICkge1xuICAgIC8vIGdlbmVyYXRlIHRoZSBwYXRoIGJhc2VkIG9uIHRoZSBtYXRyaXggd2l0aCBvYnN0YWNsZXNcbiAgICBjb25zdCBncmlkID0gbmV3IFBGLkdyaWQocm91dGluZ01hdHJpeCk7XG4gICAgY29uc3QgZHluYW1pY1BhdGggPSB0aGlzLnBhdGhGaW5kZXJJbnN0YW5jZS5maW5kUGF0aChcbiAgICAgIHN0YXJ0LngsXG4gICAgICBzdGFydC55LFxuICAgICAgZW5kLngsXG4gICAgICBlbmQueSxcbiAgICAgIGdyaWRcbiAgICApO1xuXG4gICAgLy8gYWdncmVnYXRlIGV2ZXJ5dGhpbmcgdG8gaGF2ZSB0aGUgY2FsY3VsYXRlZCBwYXRoIHJlYWR5IGZvciByZW5kZXJpbmdcbiAgICBjb25zdCBwYXRoQ29vcmRzID0gcGF0aFRvU3RhcnRcbiAgICAgIC5jb25jYXQoZHluYW1pY1BhdGgsIHBhdGhUb0VuZClcbiAgICAgIC5tYXAoKGNvb3JkcykgPT4gW1xuICAgICAgICB0aGlzLmRpYWdyYW1FbmdpbmUudHJhbnNsYXRlUm91dGluZ1goY29vcmRzWzBdLCB0cnVlKSxcbiAgICAgICAgdGhpcy5kaWFncmFtRW5naW5lLnRyYW5zbGF0ZVJvdXRpbmdZKGNvb3Jkc1sxXSwgdHJ1ZSksXG4gICAgICBdKTtcblxuICAgIHJldHVybiBQRi5VdGlsLmNvbXByZXNzUGF0aChwYXRoQ29vcmRzKTtcbiAgfVxufVxuIl19