obstacle-map.js 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.ObstacleMap = void 0;
  4. const x6_common_1 = require("@antv/x6-common");
  5. const x6_geometry_1 = require("@antv/x6-geometry");
  6. /**
  7. * Helper structure to identify whether a point lies inside an obstacle.
  8. */
  9. class ObstacleMap {
  10. constructor(options) {
  11. this.options = options;
  12. this.mapGridSize = 100;
  13. this.map = {};
  14. }
  15. /**
  16. * Builds a map of all nodes for quicker obstacle queries i.e. is a point
  17. * contained in any obstacle?
  18. *
  19. * A simplified grid search.
  20. */
  21. build(model, edge) {
  22. const options = this.options;
  23. // source or target node could be excluded from set of obstacles
  24. const excludedTerminals = options.excludeTerminals.reduce((memo, type) => {
  25. const terminal = edge[type];
  26. if (terminal) {
  27. const cell = model.getCell(terminal.cell);
  28. if (cell) {
  29. memo.push(cell);
  30. }
  31. }
  32. return memo;
  33. }, []);
  34. let excludedAncestors = [];
  35. const source = model.getCell(edge.getSourceCellId());
  36. if (source) {
  37. excludedAncestors = x6_common_1.ArrayExt.union(excludedAncestors, source.getAncestors().map((cell) => cell.id));
  38. }
  39. const target = model.getCell(edge.getTargetCellId());
  40. if (target) {
  41. excludedAncestors = x6_common_1.ArrayExt.union(excludedAncestors, target.getAncestors().map((cell) => cell.id));
  42. }
  43. // The graph is divided into smaller cells, where each holds information
  44. // about which node belong to it. When we query whether a point lies
  45. // inside an obstacle we don't need to go through all obstacles, we check
  46. // only those in a particular cell.
  47. const mapGridSize = this.mapGridSize;
  48. model.getNodes().reduce((map, node) => {
  49. const excludedTerminal = excludedTerminals.some((cell) => cell.id === node.id);
  50. const excludedShape = node.shape
  51. ? options.excludeShapes.includes(node.shape)
  52. : false;
  53. const excludedNode = options.excludeNodes.some((item) => {
  54. if (typeof item === 'string') {
  55. return node.id === item;
  56. }
  57. return item === node;
  58. });
  59. const excludedAncestor = excludedAncestors.includes(node.id);
  60. const excluded = excludedShape || excludedTerminal || excludedNode || excludedAncestor;
  61. if (node.isVisible() && !excluded) {
  62. const bbox = node.getBBox().moveAndExpand(options.paddingBox);
  63. const origin = bbox.getOrigin().snapToGrid(mapGridSize);
  64. const corner = bbox.getCorner().snapToGrid(mapGridSize);
  65. for (let x = origin.x; x <= corner.x; x += mapGridSize) {
  66. for (let y = origin.y; y <= corner.y; y += mapGridSize) {
  67. const key = new x6_geometry_1.Point(x, y).toString();
  68. if (map[key] == null) {
  69. map[key] = [];
  70. }
  71. map[key].push(bbox);
  72. }
  73. }
  74. }
  75. return map;
  76. }, this.map);
  77. return this;
  78. }
  79. isAccessible(point) {
  80. const key = point.clone().snapToGrid(this.mapGridSize).toString();
  81. const rects = this.map[key];
  82. return rects ? rects.every((rect) => !rect.containsPoint(point)) : true;
  83. }
  84. }
  85. exports.ObstacleMap = ObstacleMap;
  86. //# sourceMappingURL=obstacle-map.js.map