metro.js 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import { FunctionExt } from '@antv/x6-common';
  2. import { Point, Line, Angle } from '@antv/x6-geometry';
  3. import { resolve } from './manhattan/options';
  4. import { manhattan } from './manhattan/index';
  5. const defaults = {
  6. maxDirectionChange: 45,
  7. // an array of directions to find next points on the route
  8. // different from start/end directions
  9. directions() {
  10. const step = resolve(this.step, this);
  11. const cost = resolve(this.cost, this);
  12. const diagonalCost = Math.ceil(Math.sqrt((step * step) << 1)); // eslint-disable-line no-bitwise
  13. return [
  14. { cost, offsetX: step, offsetY: 0 },
  15. { cost: diagonalCost, offsetX: step, offsetY: step },
  16. { cost, offsetX: 0, offsetY: step },
  17. { cost: diagonalCost, offsetX: -step, offsetY: step },
  18. { cost, offsetX: -step, offsetY: 0 },
  19. { cost: diagonalCost, offsetX: -step, offsetY: -step },
  20. { cost, offsetX: 0, offsetY: -step },
  21. { cost: diagonalCost, offsetX: step, offsetY: -step },
  22. ];
  23. },
  24. // a simple route used in situations when main routing method fails
  25. // (exceed max number of loop iterations, inaccessible)
  26. fallbackRoute(from, to, options) {
  27. // Find a route which breaks by 45 degrees ignoring all obstacles.
  28. const theta = from.theta(to);
  29. const route = [];
  30. let a = { x: to.x, y: from.y };
  31. let b = { x: from.x, y: to.y };
  32. if (theta % 180 > 90) {
  33. const t = a;
  34. a = b;
  35. b = t;
  36. }
  37. const p1 = theta % 90 < 45 ? a : b;
  38. const l1 = new Line(from, p1);
  39. const alpha = 90 * Math.ceil(theta / 90);
  40. const p2 = Point.fromPolar(l1.squaredLength(), Angle.toRad(alpha + 135), p1);
  41. const l2 = new Line(to, p2);
  42. const intersectionPoint = l1.intersectsWithLine(l2);
  43. const point = intersectionPoint || to;
  44. const directionFrom = intersectionPoint ? point : from;
  45. const quadrant = 360 / options.directions.length;
  46. const angleTheta = directionFrom.theta(to);
  47. const normalizedAngle = Angle.normalize(angleTheta + quadrant / 2);
  48. const directionAngle = quadrant * Math.floor(normalizedAngle / quadrant);
  49. options.previousDirectionAngle = directionAngle;
  50. if (point)
  51. route.push(point.round());
  52. route.push(to);
  53. return route;
  54. },
  55. };
  56. export const metro = function (vertices, options, linkView) {
  57. return FunctionExt.call(manhattan, this, vertices, Object.assign(Object.assign({}, defaults), options), linkView);
  58. };
  59. //# sourceMappingURL=metro.js.map