bbox.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. "use strict";
  2. exports.__esModule = true;
  3. exports.getBBoxFromPoints = getBBoxFromPoints;
  4. exports.getBBoxFromLine = getBBoxFromLine;
  5. exports.getBBoxFromArc = getBBoxFromArc;
  6. exports.getBBoxFromBezierGroup = getBBoxFromBezierGroup;
  7. var _vector = _interopRequireDefault(require("./vector2"));
  8. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
  9. var start = _vector["default"].create();
  10. var end = _vector["default"].create();
  11. var extremity = _vector["default"].create();
  12. function getCubicBezierXYatT(startPt, controlPt1, controlPt2, endPt, T) {
  13. var x = CubicN(T, startPt.x, controlPt1.x, controlPt2.x, endPt.x);
  14. var y = CubicN(T, startPt.y, controlPt1.y, controlPt2.y, endPt.y);
  15. return {
  16. x: x,
  17. y: y
  18. };
  19. } // cubic helper formula at T distance
  20. function CubicN(T, a, b, c, d) {
  21. var t2 = T * T;
  22. var t3 = t2 * T;
  23. return a + (-a * 3 + T * (3 * a - a * T)) * T + (3 * b + T * (-6 * b + b * 3 * T)) * T + (c * 3 - c * 3 * T) * t2 + d * t3;
  24. }
  25. function cubicBezierBounds(c) {
  26. var minX = Infinity;
  27. var maxX = -Infinity;
  28. var minY = Infinity;
  29. var maxY = -Infinity;
  30. var s = {
  31. x: c[0],
  32. y: c[1]
  33. };
  34. var c1 = {
  35. x: c[2],
  36. y: c[3]
  37. };
  38. var c2 = {
  39. x: c[4],
  40. y: c[5]
  41. };
  42. var e = {
  43. x: c[6],
  44. y: c[7]
  45. };
  46. for (var t = 0; t < 100; t++) {
  47. var pt = getCubicBezierXYatT(s, c1, c2, e, t / 100);
  48. if (pt.x < minX) {
  49. minX = pt.x;
  50. }
  51. if (pt.x > maxX) {
  52. maxX = pt.x;
  53. }
  54. if (pt.y < minY) {
  55. minY = pt.y;
  56. }
  57. if (pt.y > maxY) {
  58. maxY = pt.y;
  59. }
  60. }
  61. return {
  62. minX: minX,
  63. minY: minY,
  64. maxX: maxX,
  65. maxY: maxY
  66. };
  67. }
  68. function getBBoxFromPoints(points, lineWidth) {
  69. if (points.length === 0) {
  70. return;
  71. }
  72. var p = points[0];
  73. var left = p.x;
  74. var right = p.x;
  75. var top = p.y;
  76. var bottom = p.y;
  77. var len = points.length;
  78. for (var i = 1; i < len; i++) {
  79. p = points[i];
  80. left = Math.min(left, p.x);
  81. right = Math.max(right, p.x);
  82. top = Math.min(top, p.y);
  83. bottom = Math.max(bottom, p.y);
  84. }
  85. lineWidth = lineWidth / 2 || 0;
  86. return {
  87. minX: left - lineWidth,
  88. minY: top - lineWidth,
  89. maxX: right + lineWidth,
  90. maxY: bottom + lineWidth
  91. };
  92. }
  93. function getBBoxFromLine(x0, y0, x1, y1, lineWidth) {
  94. lineWidth = lineWidth / 2 || 0;
  95. return {
  96. minX: Math.min(x0, x1) - lineWidth,
  97. minY: Math.min(y0, y1) - lineWidth,
  98. maxX: Math.max(x0, x1) + lineWidth,
  99. maxY: Math.max(y0, y1) + lineWidth
  100. };
  101. }
  102. function getBBoxFromArc(x, y, r, startAngle, endAngle, anticlockwise) {
  103. var diff = Math.abs(startAngle - endAngle);
  104. if (diff % (Math.PI * 2) < 1e-4 && diff > 1e-4) {
  105. // Is a circle
  106. return {
  107. minX: x - r,
  108. minY: y - r,
  109. maxX: x + r,
  110. maxY: y + r
  111. };
  112. }
  113. start[0] = Math.cos(startAngle) * r + x;
  114. start[1] = Math.sin(startAngle) * r + y;
  115. end[0] = Math.cos(endAngle) * r + x;
  116. end[1] = Math.sin(endAngle) * r + y;
  117. var min = [0, 0];
  118. var max = [0, 0];
  119. _vector["default"].min(min, start, end);
  120. _vector["default"].max(max, start, end); // Thresh to [0, Math.PI * 2]
  121. startAngle = startAngle % (Math.PI * 2);
  122. if (startAngle < 0) {
  123. startAngle = startAngle + Math.PI * 2;
  124. }
  125. endAngle = endAngle % (Math.PI * 2);
  126. if (endAngle < 0) {
  127. endAngle = endAngle + Math.PI * 2;
  128. }
  129. if (startAngle > endAngle && !anticlockwise) {
  130. endAngle += Math.PI * 2;
  131. } else if (startAngle < endAngle && anticlockwise) {
  132. startAngle += Math.PI * 2;
  133. }
  134. if (anticlockwise) {
  135. var tmp = endAngle;
  136. endAngle = startAngle;
  137. startAngle = tmp;
  138. }
  139. for (var angle = 0; angle < endAngle; angle += Math.PI / 2) {
  140. if (angle > startAngle) {
  141. extremity[0] = Math.cos(angle) * r + x;
  142. extremity[1] = Math.sin(angle) * r + y;
  143. _vector["default"].min(min, extremity, min);
  144. _vector["default"].max(max, extremity, max);
  145. }
  146. }
  147. return {
  148. minX: min[0],
  149. minY: min[1],
  150. maxX: max[0],
  151. maxY: max[1]
  152. };
  153. }
  154. function getBBoxFromBezierGroup(points, lineWidth) {
  155. var minX = Infinity;
  156. var maxX = -Infinity;
  157. var minY = Infinity;
  158. var maxY = -Infinity;
  159. for (var i = 0, len = points.length; i < len; i++) {
  160. var bbox = cubicBezierBounds(points[i]);
  161. if (bbox.minX < minX) {
  162. minX = bbox.minX;
  163. }
  164. if (bbox.maxX > maxX) {
  165. maxX = bbox.maxX;
  166. }
  167. if (bbox.minY < minY) {
  168. minY = bbox.minY;
  169. }
  170. if (bbox.maxY > maxY) {
  171. maxY = bbox.maxY;
  172. }
  173. }
  174. lineWidth = lineWidth / 2 || 0;
  175. return {
  176. minX: minX - lineWidth,
  177. minY: minY - lineWidth,
  178. maxX: maxX + lineWidth,
  179. maxY: maxY + lineWidth
  180. };
  181. }