尋找二次曲線的範圍
當你需要找到二次貝塞爾曲線的邊界矩形時,可以使用以下高效能方法。
// This method was discovered by Blindman67 and solves by first normalising the control point thereby reducing the algorithm complexity
// x1,y1, x2,y2, x3,y3 Start, Control, and End coords of bezier
// [extent] is optional and if provided the extent will be added to it allowing you to use the function
// to get the extent of many beziers.
// returns extent object (if not supplied a new extent is created)
// Extent object properties
// top, left,right,bottom,width,height
function getQuadraticCurevExtent(x1, y1, x2, y2, x3, y3, extent) {
var brx, bx, x, bry, by, y, px, py;
// solve quadratic for bounds by BM67 normalizing equation
brx = x3 - x1; // get x range
bx = x2 - x1; // get x control point offset
x = bx / brx; // normalise control point which is used to check if maxima is in range
// do the same for the y points
bry = y3 - y1;
by = y2 - y1;
y = by / bry;
px = x1; // set defaults in case maximas outside range
py = y1;
// find top/left, top/right, bottom/left, or bottom/right
if (x < 0 || x > 1) { // check if x maxima is on the curve
px = bx * bx / (2 * bx - brx) + x1; // get the x maxima
}
if (y < 0 || y > 1) { // same as x
py = by * by / (2 * by - bry) + y1;
}
// create extent object and add extent
if (extent === undefined) {
extent = {};
extent.left = Math.min(x1, x3, px);
extent.top = Math.min(y1, y3, py);
extent.right = Math.max(x1, x3, px);
extent.bottom = Math.max(y1, y3, py);
} else { // use spplied extent and extend it to fit this curve
extent.left = Math.min(x1, x3, px, extent.left);
extent.top = Math.min(y1, y3, py, extent.top);
extent.right = Math.max(x1, x3, px, extent.right);
extent.bottom = Math.max(y1, y3, py, extent.bottom);
}
extent.width = extent.right - extent.left;
extent.height = extent.bottom - extent.top;
return extent;
}