bbox.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. var vec2 = require("./vector");
  2. var curve = require("./curve");
  3. /**
  4. * @author Yi Shen(https://github.com/pissang)
  5. */
  6. var mathMin = Math.min;
  7. var mathMax = Math.max;
  8. var mathSin = Math.sin;
  9. var mathCos = Math.cos;
  10. var PI2 = Math.PI * 2;
  11. var start = vec2.create();
  12. var end = vec2.create();
  13. var extremity = vec2.create();
  14. /**
  15. * 从顶点数组中计算出最小包围盒,写入`min`和`max`中
  16. * @module zrender/core/bbox
  17. * @param {Array<Object>} points 顶点数组
  18. * @param {number} min
  19. * @param {number} max
  20. */
  21. function fromPoints(points, min, max) {
  22. if (points.length === 0) {
  23. return;
  24. }
  25. var p = points[0];
  26. var left = p[0];
  27. var right = p[0];
  28. var top = p[1];
  29. var bottom = p[1];
  30. var i;
  31. for (i = 1; i < points.length; i++) {
  32. p = points[i];
  33. left = mathMin(left, p[0]);
  34. right = mathMax(right, p[0]);
  35. top = mathMin(top, p[1]);
  36. bottom = mathMax(bottom, p[1]);
  37. }
  38. min[0] = left;
  39. min[1] = top;
  40. max[0] = right;
  41. max[1] = bottom;
  42. }
  43. /**
  44. * @memberOf module:zrender/core/bbox
  45. * @param {number} x0
  46. * @param {number} y0
  47. * @param {number} x1
  48. * @param {number} y1
  49. * @param {Array.<number>} min
  50. * @param {Array.<number>} max
  51. */
  52. function fromLine(x0, y0, x1, y1, min, max) {
  53. min[0] = mathMin(x0, x1);
  54. min[1] = mathMin(y0, y1);
  55. max[0] = mathMax(x0, x1);
  56. max[1] = mathMax(y0, y1);
  57. }
  58. var xDim = [];
  59. var yDim = [];
  60. /**
  61. * 从三阶贝塞尔曲线(p0, p1, p2, p3)中计算出最小包围盒,写入`min`和`max`中
  62. * @memberOf module:zrender/core/bbox
  63. * @param {number} x0
  64. * @param {number} y0
  65. * @param {number} x1
  66. * @param {number} y1
  67. * @param {number} x2
  68. * @param {number} y2
  69. * @param {number} x3
  70. * @param {number} y3
  71. * @param {Array.<number>} min
  72. * @param {Array.<number>} max
  73. */
  74. function fromCubic(x0, y0, x1, y1, x2, y2, x3, y3, min, max) {
  75. var cubicExtrema = curve.cubicExtrema;
  76. var cubicAt = curve.cubicAt;
  77. var i;
  78. var n = cubicExtrema(x0, x1, x2, x3, xDim);
  79. min[0] = Infinity;
  80. min[1] = Infinity;
  81. max[0] = -Infinity;
  82. max[1] = -Infinity;
  83. for (i = 0; i < n; i++) {
  84. var x = cubicAt(x0, x1, x2, x3, xDim[i]);
  85. min[0] = mathMin(x, min[0]);
  86. max[0] = mathMax(x, max[0]);
  87. }
  88. n = cubicExtrema(y0, y1, y2, y3, yDim);
  89. for (i = 0; i < n; i++) {
  90. var y = cubicAt(y0, y1, y2, y3, yDim[i]);
  91. min[1] = mathMin(y, min[1]);
  92. max[1] = mathMax(y, max[1]);
  93. }
  94. min[0] = mathMin(x0, min[0]);
  95. max[0] = mathMax(x0, max[0]);
  96. min[0] = mathMin(x3, min[0]);
  97. max[0] = mathMax(x3, max[0]);
  98. min[1] = mathMin(y0, min[1]);
  99. max[1] = mathMax(y0, max[1]);
  100. min[1] = mathMin(y3, min[1]);
  101. max[1] = mathMax(y3, max[1]);
  102. }
  103. /**
  104. * 从二阶贝塞尔曲线(p0, p1, p2)中计算出最小包围盒,写入`min`和`max`中
  105. * @memberOf module:zrender/core/bbox
  106. * @param {number} x0
  107. * @param {number} y0
  108. * @param {number} x1
  109. * @param {number} y1
  110. * @param {number} x2
  111. * @param {number} y2
  112. * @param {Array.<number>} min
  113. * @param {Array.<number>} max
  114. */
  115. function fromQuadratic(x0, y0, x1, y1, x2, y2, min, max) {
  116. var quadraticExtremum = curve.quadraticExtremum;
  117. var quadraticAt = curve.quadraticAt; // Find extremities, where derivative in x dim or y dim is zero
  118. var tx = mathMax(mathMin(quadraticExtremum(x0, x1, x2), 1), 0);
  119. var ty = mathMax(mathMin(quadraticExtremum(y0, y1, y2), 1), 0);
  120. var x = quadraticAt(x0, x1, x2, tx);
  121. var y = quadraticAt(y0, y1, y2, ty);
  122. min[0] = mathMin(x0, x2, x);
  123. min[1] = mathMin(y0, y2, y);
  124. max[0] = mathMax(x0, x2, x);
  125. max[1] = mathMax(y0, y2, y);
  126. }
  127. /**
  128. * 从圆弧中计算出最小包围盒,写入`min`和`max`中
  129. * @method
  130. * @memberOf module:zrender/core/bbox
  131. * @param {number} x
  132. * @param {number} y
  133. * @param {number} rx
  134. * @param {number} ry
  135. * @param {number} startAngle
  136. * @param {number} endAngle
  137. * @param {number} anticlockwise
  138. * @param {Array.<number>} min
  139. * @param {Array.<number>} max
  140. */
  141. function fromArc(x, y, rx, ry, startAngle, endAngle, anticlockwise, min, max) {
  142. var vec2Min = vec2.min;
  143. var vec2Max = vec2.max;
  144. var diff = Math.abs(startAngle - endAngle);
  145. if (diff % PI2 < 1e-4 && diff > 1e-4) {
  146. // Is a circle
  147. min[0] = x - rx;
  148. min[1] = y - ry;
  149. max[0] = x + rx;
  150. max[1] = y + ry;
  151. return;
  152. }
  153. start[0] = mathCos(startAngle) * rx + x;
  154. start[1] = mathSin(startAngle) * ry + y;
  155. end[0] = mathCos(endAngle) * rx + x;
  156. end[1] = mathSin(endAngle) * ry + y;
  157. vec2Min(min, start, end);
  158. vec2Max(max, start, end); // Thresh to [0, Math.PI * 2]
  159. startAngle = startAngle % PI2;
  160. if (startAngle < 0) {
  161. startAngle = startAngle + PI2;
  162. }
  163. endAngle = endAngle % PI2;
  164. if (endAngle < 0) {
  165. endAngle = endAngle + PI2;
  166. }
  167. if (startAngle > endAngle && !anticlockwise) {
  168. endAngle += PI2;
  169. } else if (startAngle < endAngle && anticlockwise) {
  170. startAngle += PI2;
  171. }
  172. if (anticlockwise) {
  173. var tmp = endAngle;
  174. endAngle = startAngle;
  175. startAngle = tmp;
  176. } // var number = 0;
  177. // var step = (anticlockwise ? -Math.PI : Math.PI) / 2;
  178. for (var angle = 0; angle < endAngle; angle += Math.PI / 2) {
  179. if (angle > startAngle) {
  180. extremity[0] = mathCos(angle) * rx + x;
  181. extremity[1] = mathSin(angle) * ry + y;
  182. vec2Min(min, extremity, min);
  183. vec2Max(max, extremity, max);
  184. }
  185. }
  186. }
  187. exports.fromPoints = fromPoints;
  188. exports.fromLine = fromLine;
  189. exports.fromCubic = fromCubic;
  190. exports.fromQuadratic = fromQuadratic;
  191. exports.fromArc = fromArc;