Edge.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import {cells, edges, epsilon} from "./Diagram";
  2. export function createEdge(left, right, v0, v1) {
  3. var edge = [null, null],
  4. index = edges.push(edge) - 1;
  5. edge.left = left;
  6. edge.right = right;
  7. if (v0) setEdgeEnd(edge, left, right, v0);
  8. if (v1) setEdgeEnd(edge, right, left, v1);
  9. cells[left.index].halfedges.push(index);
  10. cells[right.index].halfedges.push(index);
  11. return edge;
  12. }
  13. export function createBorderEdge(left, v0, v1) {
  14. var edge = [v0, v1];
  15. edge.left = left;
  16. return edge;
  17. }
  18. export function setEdgeEnd(edge, left, right, vertex) {
  19. if (!edge[0] && !edge[1]) {
  20. edge[0] = vertex;
  21. edge.left = left;
  22. edge.right = right;
  23. } else if (edge.left === right) {
  24. edge[1] = vertex;
  25. } else {
  26. edge[0] = vertex;
  27. }
  28. }
  29. // Liang–Barsky line clipping.
  30. function clipEdge(edge, x0, y0, x1, y1) {
  31. var a = edge[0],
  32. b = edge[1],
  33. ax = a[0],
  34. ay = a[1],
  35. bx = b[0],
  36. by = b[1],
  37. t0 = 0,
  38. t1 = 1,
  39. dx = bx - ax,
  40. dy = by - ay,
  41. r;
  42. r = x0 - ax;
  43. if (!dx && r > 0) return;
  44. r /= dx;
  45. if (dx < 0) {
  46. if (r < t0) return;
  47. if (r < t1) t1 = r;
  48. } else if (dx > 0) {
  49. if (r > t1) return;
  50. if (r > t0) t0 = r;
  51. }
  52. r = x1 - ax;
  53. if (!dx && r < 0) return;
  54. r /= dx;
  55. if (dx < 0) {
  56. if (r > t1) return;
  57. if (r > t0) t0 = r;
  58. } else if (dx > 0) {
  59. if (r < t0) return;
  60. if (r < t1) t1 = r;
  61. }
  62. r = y0 - ay;
  63. if (!dy && r > 0) return;
  64. r /= dy;
  65. if (dy < 0) {
  66. if (r < t0) return;
  67. if (r < t1) t1 = r;
  68. } else if (dy > 0) {
  69. if (r > t1) return;
  70. if (r > t0) t0 = r;
  71. }
  72. r = y1 - ay;
  73. if (!dy && r < 0) return;
  74. r /= dy;
  75. if (dy < 0) {
  76. if (r > t1) return;
  77. if (r > t0) t0 = r;
  78. } else if (dy > 0) {
  79. if (r < t0) return;
  80. if (r < t1) t1 = r;
  81. }
  82. if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check?
  83. if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy];
  84. if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy];
  85. return true;
  86. }
  87. function connectEdge(edge, x0, y0, x1, y1) {
  88. var v1 = edge[1];
  89. if (v1) return true;
  90. var v0 = edge[0],
  91. left = edge.left,
  92. right = edge.right,
  93. lx = left[0],
  94. ly = left[1],
  95. rx = right[0],
  96. ry = right[1],
  97. fx = (lx + rx) / 2,
  98. fy = (ly + ry) / 2,
  99. fm,
  100. fb;
  101. if (ry === ly) {
  102. if (fx < x0 || fx >= x1) return;
  103. if (lx > rx) {
  104. if (!v0) v0 = [fx, y0];
  105. else if (v0[1] >= y1) return;
  106. v1 = [fx, y1];
  107. } else {
  108. if (!v0) v0 = [fx, y1];
  109. else if (v0[1] < y0) return;
  110. v1 = [fx, y0];
  111. }
  112. } else {
  113. fm = (lx - rx) / (ry - ly);
  114. fb = fy - fm * fx;
  115. if (fm < -1 || fm > 1) {
  116. if (lx > rx) {
  117. if (!v0) v0 = [(y0 - fb) / fm, y0];
  118. else if (v0[1] >= y1) return;
  119. v1 = [(y1 - fb) / fm, y1];
  120. } else {
  121. if (!v0) v0 = [(y1 - fb) / fm, y1];
  122. else if (v0[1] < y0) return;
  123. v1 = [(y0 - fb) / fm, y0];
  124. }
  125. } else {
  126. if (ly < ry) {
  127. if (!v0) v0 = [x0, fm * x0 + fb];
  128. else if (v0[0] >= x1) return;
  129. v1 = [x1, fm * x1 + fb];
  130. } else {
  131. if (!v0) v0 = [x1, fm * x1 + fb];
  132. else if (v0[0] < x0) return;
  133. v1 = [x0, fm * x0 + fb];
  134. }
  135. }
  136. }
  137. edge[0] = v0;
  138. edge[1] = v1;
  139. return true;
  140. }
  141. export function clipEdges(x0, y0, x1, y1) {
  142. var i = edges.length,
  143. edge;
  144. while (i--) {
  145. if (!connectEdge(edge = edges[i], x0, y0, x1, y1)
  146. || !clipEdge(edge, x0, y0, x1, y1)
  147. || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon
  148. || Math.abs(edge[0][1] - edge[1][1]) > epsilon)) {
  149. delete edges[i];
  150. }
  151. }
  152. }