@antv/x6
Version:
JavaScript diagramming library that uses SVG and HTML for rendering.
76 lines • 3.22 kB
JavaScript
import { ArrayExt } from '../../../util';
import { Point } from '../../../geometry';
/**
* Helper structure to identify whether a point lies inside an obstacle.
*/
export class ObstacleMap {
constructor(options) {
this.options = options;
this.mapGridSize = 100;
this.map = {};
}
/**
* Builds a map of all nodes for quicker obstacle queries i.e. is a point
* contained in any obstacle?
*
* A simplified grid search.
*/
build(model, edge) {
const options = this.options;
// source or target node could be excluded from set of obstacles
const excludedTerminals = options.excludeTerminals.reduce((memo, type) => {
const terminal = edge[type];
if (terminal) {
const cell = model.getCell(terminal.cell);
if (cell) {
memo.push(cell);
}
}
return memo;
}, []);
let excludedAncestors = [];
const source = model.getCell(edge.getSourceCellId());
if (source) {
excludedAncestors = ArrayExt.union(excludedAncestors, source.getAncestors().map((cell) => cell.id));
}
const target = model.getCell(edge.getTargetCellId());
if (target) {
excludedAncestors = ArrayExt.union(excludedAncestors, target.getAncestors().map((cell) => cell.id));
}
// The graph is divided into smaller cells, where each holds information
// about which node belong to it. When we query whether a point lies
// inside an obstacle we don't need to go through all obstacles, we check
// only those in a particular cell.
const mapGridSize = this.mapGridSize;
model.getNodes().reduce((map, node) => {
const shape = node.shape;
const excludeShapes = options.excludeShapes;
const excType = shape ? excludeShapes.includes(shape) : false;
const excTerminal = excludedTerminals.some((cell) => cell.id === node.id);
const excAncestor = excludedAncestors.includes(node.id);
const excluded = excType || excTerminal || excAncestor;
if (!excluded) {
const bbox = node.getBBox().moveAndExpand(options.paddingBox);
const origin = bbox.getOrigin().snapToGrid(mapGridSize);
const corner = bbox.getCorner().snapToGrid(mapGridSize);
for (let x = origin.x; x <= corner.x; x += mapGridSize) {
for (let y = origin.y; y <= corner.y; y += mapGridSize) {
const key = new Point(x, y).toString();
if (map[key] == null) {
map[key] = [];
}
map[key].push(bbox);
}
}
}
return map;
}, this.map);
return this;
}
isAccessible(point) {
const key = point.clone().snapToGrid(this.mapGridSize).toString();
const rects = this.map[key];
return rects ? rects.every((rect) => !rect.containsPoint(point)) : true;
}
}
//# sourceMappingURL=obstacle-map.js.map