loop.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { Angle, Point, Line } from '@antv/x6-geometry';
  2. function rollup(points, merge) {
  3. if (merge != null && merge !== false) {
  4. const amount = typeof merge === 'boolean' ? 0 : merge;
  5. if (amount > 0) {
  6. const center1 = Point.create(points[1]).move(points[2], amount);
  7. const center2 = Point.create(points[1]).move(points[0], amount);
  8. return [center1.toJSON(), ...points, center2.toJSON()];
  9. }
  10. {
  11. const center = points[1];
  12. return [Object.assign({}, center), ...points, Object.assign({}, center)];
  13. }
  14. }
  15. return points;
  16. }
  17. export const loop = function (vertices, options, edgeView) {
  18. const width = options.width || 50;
  19. const height = options.height || 80;
  20. const halfHeight = height / 2;
  21. const angle = options.angle || 'auto';
  22. const sourceAnchor = edgeView.sourceAnchor;
  23. const targetAnchor = edgeView.targetAnchor;
  24. const sourceBBox = edgeView.sourceBBox;
  25. const targetBBox = edgeView.targetBBox;
  26. if (sourceAnchor.equals(targetAnchor)) {
  27. const getVertices = (angle) => {
  28. const rad = Angle.toRad(angle);
  29. const sin = Math.sin(rad);
  30. const cos = Math.cos(rad);
  31. const center = new Point(sourceAnchor.x + cos * width, sourceAnchor.y + sin * width);
  32. const ref = new Point(center.x - cos * halfHeight, center.y - sin * halfHeight);
  33. const p1 = ref.clone().rotate(-90, center);
  34. const p2 = ref.clone().rotate(90, center);
  35. return [p1.toJSON(), center.toJSON(), p2.toJSON()];
  36. };
  37. const validate = (end) => {
  38. const start = sourceAnchor.clone().move(end, -1);
  39. const line = new Line(start, end);
  40. return (!sourceBBox.containsPoint(end) && !sourceBBox.intersectsWithLine(line));
  41. };
  42. const angles = [0, 90, 180, 270, 45, 135, 225, 315];
  43. if (typeof angle === 'number') {
  44. return rollup(getVertices(angle), options.merge);
  45. }
  46. const center = sourceBBox.getCenter();
  47. if (center.equals(sourceAnchor)) {
  48. return rollup(getVertices(0), options.merge);
  49. }
  50. const deg = center.angleBetween(sourceAnchor, center.clone().translate(1, 0));
  51. let ret = getVertices(deg);
  52. if (validate(ret[1])) {
  53. return rollup(ret, options.merge);
  54. }
  55. // return the best vertices
  56. for (let i = 1, l = angles.length; i < l; i += 1) {
  57. ret = getVertices(deg + angles[i]);
  58. if (validate(ret[1])) {
  59. return rollup(ret, options.merge);
  60. }
  61. }
  62. return rollup(ret, options.merge);
  63. }
  64. {
  65. const line = new Line(sourceAnchor, targetAnchor);
  66. let parallel = line.parallel(-width);
  67. let center = parallel.getCenter();
  68. let p1 = parallel.start.clone().move(parallel.end, halfHeight);
  69. let p2 = parallel.end.clone().move(parallel.start, halfHeight);
  70. const ref = line.parallel(-1);
  71. const line1 = new Line(ref.start, center);
  72. const line2 = new Line(ref.end, center);
  73. if (sourceBBox.containsPoint(center) ||
  74. targetBBox.containsPoint(center) ||
  75. sourceBBox.intersectsWithLine(line1) ||
  76. sourceBBox.intersectsWithLine(line2) ||
  77. targetBBox.intersectsWithLine(line1) ||
  78. targetBBox.intersectsWithLine(line2)) {
  79. parallel = line.parallel(width);
  80. center = parallel.getCenter();
  81. p1 = parallel.start.clone().move(parallel.end, halfHeight);
  82. p2 = parallel.end.clone().move(parallel.start, halfHeight);
  83. }
  84. if (options.merge) {
  85. const line = new Line(sourceAnchor, targetAnchor);
  86. const normal = new Line(center, line.center).setLength(Number.MAX_SAFE_INTEGER);
  87. const intersects1 = sourceBBox.intersectsWithLine(normal);
  88. const intersects2 = targetBBox.intersectsWithLine(normal);
  89. const intersects = intersects1
  90. ? Array.isArray(intersects1)
  91. ? intersects1
  92. : [intersects1]
  93. : [];
  94. if (intersects2) {
  95. if (Array.isArray(intersects2)) {
  96. intersects.push(...intersects2);
  97. }
  98. else {
  99. intersects.push(intersects2);
  100. }
  101. }
  102. const anchor = line.center.closest(intersects);
  103. if (anchor) {
  104. edgeView.sourceAnchor = anchor.clone();
  105. edgeView.targetAnchor = anchor.clone();
  106. }
  107. else {
  108. edgeView.sourceAnchor = line.center.clone();
  109. edgeView.targetAnchor = line.center.clone();
  110. }
  111. }
  112. return rollup([p1.toJSON(), center.toJSON(), p2.toJSON()], options.merge);
  113. }
  114. };
  115. //# sourceMappingURL=loop.js.map