edge.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // 这个里面的函数有些在core中已经存在,为了解耦关系,没有引用
  2. var SegmentDirection;
  3. (function (SegmentDirection) {
  4. SegmentDirection["HORIZONTAL"] = "horizontal";
  5. SegmentDirection["VERTICAL"] = "vertical";
  6. })(SegmentDirection || (SegmentDirection = {}));
  7. /**
  8. * 判断一个点是否在线段中
  9. * @param point 判断的点
  10. * @param start 线段的起点
  11. * @param end 线段的终点
  12. * @param deviation 误差范围
  13. * @returns boolean
  14. */
  15. export var isInSegment = function (point, start, end, deviation) {
  16. if (deviation === void 0) { deviation = 0; }
  17. var distance = distToSegment(point, start, end);
  18. return distance <= deviation;
  19. };
  20. function sqr(x) {
  21. return x * x;
  22. }
  23. function dist2(v, w) {
  24. return sqr(v.x - w.x) + sqr(v.y - w.y);
  25. }
  26. export var distToSegmentSquared = function (p, v, w) {
  27. var l2 = dist2(v, w);
  28. if (l2 === 0)
  29. return dist2(p, v);
  30. var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
  31. t = Math.max(0, Math.min(1, t));
  32. return dist2(p, {
  33. x: v.x + t * (w.x - v.x),
  34. y: v.y + t * (w.y - v.y),
  35. });
  36. };
  37. export var distToSegment = function (point, start, end) { return Math.sqrt(distToSegmentSquared(point, start, end)); };
  38. /* 获取节点bbox */
  39. var getNodeBBox = function (node) {
  40. var x = node.x, y = node.y, width = node.width, height = node.height;
  41. var bBox = {
  42. minX: x - width / 2,
  43. minY: y - height / 2,
  44. maxX: x + width / 2,
  45. maxY: y + height / 2,
  46. x: x,
  47. y: y,
  48. width: width,
  49. height: height,
  50. centerX: x,
  51. centerY: y,
  52. };
  53. return bBox;
  54. };
  55. /* 判断线段的方向 */
  56. var segmentDirection = function (start, end) {
  57. var direction;
  58. if (start.x === end.x) {
  59. direction = SegmentDirection.VERTICAL;
  60. }
  61. else if (start.y === end.y) {
  62. direction = SegmentDirection.HORIZONTAL;
  63. }
  64. return direction;
  65. };
  66. // 节点是够在线段内,求出节点与线段的交点
  67. export var crossPointInSegment = function (node, start, end) {
  68. var bBox = getNodeBBox(node);
  69. var direction = segmentDirection(start, end);
  70. var maxX = Math.max(start.x, end.x);
  71. var minX = Math.min(start.x, end.x);
  72. var maxY = Math.max(start.y, end.y);
  73. var minY = Math.min(start.y, end.y);
  74. var x = node.x, y = node.y, width = node.width, height = node.height;
  75. if (direction === SegmentDirection.HORIZONTAL) {
  76. // 同一水平线
  77. if (maxX >= bBox.maxX && minX <= bBox.minX) {
  78. return {
  79. startCrossPoint: {
  80. x: start.x > end.x ? x + (width / 2) : x - (width / 2),
  81. y: start.y,
  82. },
  83. endCrossPoint: {
  84. x: start.x > end.x ? x - (width / 2) : x + (width / 2),
  85. y: start.y,
  86. },
  87. };
  88. }
  89. }
  90. else if (direction === SegmentDirection.VERTICAL) {
  91. // 同一垂直线
  92. if (maxY >= bBox.maxY && minY <= bBox.minY) {
  93. return {
  94. startCrossPoint: {
  95. x: start.x,
  96. y: start.y > end.y ? y + (height / 2) : y - (height / 2),
  97. },
  98. endCrossPoint: {
  99. x: start.x,
  100. y: start.y > end.y ? y - (height / 2) : y + (height / 2),
  101. },
  102. };
  103. }
  104. }
  105. };
  106. // 节点是否在线段内
  107. // eslint-disable-next-line max-len
  108. export var isNodeInSegment = function (node, polyline, deviation) {
  109. if (deviation === void 0) { deviation = 0; }
  110. var x = node.x, y = node.y;
  111. var pointsList = polyline.pointsList;
  112. for (var i = 0; i < pointsList.length - 1; i++) {
  113. if (isInSegment({ x: x, y: y }, pointsList[i], pointsList[i + 1], deviation)) {
  114. var bBoxCross = crossPointInSegment(node, pointsList[i], pointsList[i + 1]);
  115. if (bBoxCross) {
  116. return {
  117. crossIndex: i + 1,
  118. crossPoints: bBoxCross,
  119. };
  120. }
  121. }
  122. }
  123. return {
  124. crossIndex: -1,
  125. crossPoints: {
  126. startCrossPoint: { x: 0, y: 0 },
  127. endCrossPoint: { x: 0, y: 0 },
  128. },
  129. };
  130. };