123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- "use strict";
- var Vector2 = require('./vector2');
- var start = Vector2.create();
- var end = Vector2.create();
- var extremity = Vector2.create();
- function getCubicBezierXYatT(startPt, controlPt1, controlPt2, endPt, T) {
- var x = CubicN(T, startPt.x, controlPt1.x, controlPt2.x, endPt.x);
- var y = CubicN(T, startPt.y, controlPt1.y, controlPt2.y, endPt.y);
- return {
- x: x,
- y: y
- };
- } // cubic helper formula at T distance
- function CubicN(T, a, b, c, d) {
- var t2 = T * T;
- var t3 = t2 * T;
- 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;
- }
- function cubicBezierBounds(c) {
- var minX = Infinity;
- var maxX = -Infinity;
- var minY = Infinity;
- var maxY = -Infinity;
- var s = {
- x: c[0],
- y: c[1]
- };
- var c1 = {
- x: c[2],
- y: c[3]
- };
- var c2 = {
- x: c[4],
- y: c[5]
- };
- var e = {
- x: c[6],
- y: c[7]
- };
- for (var t = 0; t < 100; t++) {
- var pt = getCubicBezierXYatT(s, c1, c2, e, t / 100);
- if (pt.x < minX) {
- minX = pt.x;
- }
- if (pt.x > maxX) {
- maxX = pt.x;
- }
- if (pt.y < minY) {
- minY = pt.y;
- }
- if (pt.y > maxY) {
- maxY = pt.y;
- }
- }
- return {
- minX: minX,
- minY: minY,
- maxX: maxX,
- maxY: maxY
- };
- }
- module.exports = {
- getBBoxFromPoints: function getBBoxFromPoints(points, lineWidth) {
- if (points.length === 0) {
- return;
- }
- var p = points[0];
- var left = p.x;
- var right = p.x;
- var top = p.y;
- var bottom = p.y;
- var len = points.length;
- for (var i = 1; i < len; i++) {
- p = points[i];
- left = Math.min(left, p.x);
- right = Math.max(right, p.x);
- top = Math.min(top, p.y);
- bottom = Math.max(bottom, p.y);
- }
- lineWidth = lineWidth / 2 || 0;
- return {
- minX: left - lineWidth,
- minY: top - lineWidth,
- maxX: right + lineWidth,
- maxY: bottom + lineWidth
- };
- },
- getBBoxFromLine: function getBBoxFromLine(x0, y0, x1, y1, lineWidth) {
- lineWidth = lineWidth / 2 || 0;
- return {
- minX: Math.min(x0, x1) - lineWidth,
- minY: Math.min(y0, y1) - lineWidth,
- maxX: Math.max(x0, x1) + lineWidth,
- maxY: Math.max(y0, y1) + lineWidth
- };
- },
- getBBoxFromArc: function getBBoxFromArc(x, y, r, startAngle, endAngle, anticlockwise) {
- var diff = Math.abs(startAngle - endAngle);
- if (diff % (Math.PI * 2) < 1e-4 && diff > 1e-4) {
- // Is a circle
- return {
- minX: x - r,
- minY: y - r,
- maxX: x + r,
- maxY: y + r
- };
- }
- start[0] = Math.cos(startAngle) * r + x;
- start[1] = Math.sin(startAngle) * r + y;
- end[0] = Math.cos(endAngle) * r + x;
- end[1] = Math.sin(endAngle) * r + y;
- var min = [0, 0];
- var max = [0, 0];
- Vector2.min(min, start, end);
- Vector2.max(max, start, end); // Thresh to [0, Math.PI * 2]
- startAngle = startAngle % (Math.PI * 2);
- if (startAngle < 0) {
- startAngle = startAngle + Math.PI * 2;
- }
- endAngle = endAngle % (Math.PI * 2);
- if (endAngle < 0) {
- endAngle = endAngle + Math.PI * 2;
- }
- if (startAngle > endAngle && !anticlockwise) {
- endAngle += Math.PI * 2;
- } else if (startAngle < endAngle && anticlockwise) {
- startAngle += Math.PI * 2;
- }
- if (anticlockwise) {
- var tmp = endAngle;
- endAngle = startAngle;
- startAngle = tmp;
- }
- for (var angle = 0; angle < endAngle; angle += Math.PI / 2) {
- if (angle > startAngle) {
- extremity[0] = Math.cos(angle) * r + x;
- extremity[1] = Math.sin(angle) * r + y;
- Vector2.min(min, extremity, min);
- Vector2.max(max, extremity, max);
- }
- }
- return {
- minX: min[0],
- minY: min[1],
- maxX: max[0],
- maxY: max[1]
- };
- },
- getBBoxFromBezierGroup: function getBBoxFromBezierGroup(points, lineWidth) {
- var minX = Infinity;
- var maxX = -Infinity;
- var minY = Infinity;
- var maxY = -Infinity;
- for (var i = 0, len = points.length; i < len; i++) {
- var bbox = cubicBezierBounds(points[i]);
- if (bbox.minX < minX) {
- minX = bbox.minX;
- }
- if (bbox.maxX > maxX) {
- maxX = bbox.maxX;
- }
- if (bbox.minY < minY) {
- minY = bbox.minY;
- }
- if (bbox.maxY > maxY) {
- maxY = bbox.maxY;
- }
- }
- lineWidth = lineWidth / 2 || 0;
- return {
- minX: minX - lineWidth,
- minY: minY - lineWidth,
- maxX: maxX + lineWidth,
- maxY: maxY + lineWidth
- };
- }
- };
|