calculateBounds method
Returns the true bounds of this curve, filling bounds with the
axis-aligned bounding box values for left, top, right, and bottom,
in that order.
Implementation
void calculateBounds(List<double> bounds, {bool approximate = false}) {
assert(bounds.length == 4, 'Bounds array size should be 4.');
// A curve might be of zero-length, with both anchors co-lated.
// Just return the point itself.
if (zeroLength()) {
bounds[0] = anchor0X;
bounds[1] = anchor0Y;
bounds[2] = anchor0X;
bounds[3] = anchor0Y;
return;
}
var minX = math.min(anchor0X, anchor1X);
var minY = math.min(anchor0Y, anchor1Y);
var maxX = math.max(anchor0X, anchor1X);
var maxY = math.max(anchor0Y, anchor1Y);
if (approximate) {
// Approximate bounds use the bounding box of all anchors and
// controls.
bounds[0] = math.min(minX, math.min(control0X, control1X));
bounds[1] = math.min(minY, math.min(control0Y, control1Y));
bounds[2] = math.max(maxX, math.max(control0X, control1X));
bounds[3] = math.max(maxY, math.max(control0Y, control1Y));
return;
}
// Find the derivative, which is a quadratic Bezier. Then we can solve
// for t using the quadratic formula.
final xa = -anchor0X + 3 * control0X - 3 * control1X + anchor1X;
final xb = 2 * anchor0X - 4 * control0X + 2 * control1X;
final xc = -anchor0X + control0X;
if (_zeroIsh(xa)) {
// Try Muller's method instead; it can find a single root when a is 0.
if (xb != 0) {
final t = 2 * xc / (-2 * xb);
if (t >= 0 && t <= 1) {
final x = pointOnCurve(t).x;
if (x < minX) minX = x;
if (x > maxX) maxX = x;
}
}
} else {
final xs = xb * xb - 4 * xa * xc;
if (xs >= 0) {
final t1 = (-xb + math.sqrt(xs)) / (2 * xa);
if (t1 >= 0 && t1 <= 1) {
final x = pointOnCurve(t1).x;
if (x < minX) minX = x;
if (x > maxX) maxX = x;
}
final t2 = (-xb - math.sqrt(xs)) / (2 * xa);
if (t2 >= 0 && t2 <= 1) {
final x = pointOnCurve(t2).x;
if (x < minX) minX = x;
if (x > maxX) maxX = x;
}
}
}
// Repeat the above for y coordinate
final ya = -anchor0Y + 3 * control0Y - 3 * control1Y + anchor1Y;
final yb = 2 * anchor0Y - 4 * control0Y + 2 * control1Y;
final yc = -anchor0Y + control0Y;
if (_zeroIsh(ya)) {
if (yb != 0) {
final t = 2 * yc / (-2 * yb);
if (t >= 0 && t <= 1) {
final y = pointOnCurve(t).y;
if (y < minY) minY = y;
if (y > maxY) maxY = y;
}
}
} else {
final ys = yb * yb - 4 * ya * yc;
if (ys >= 0) {
final t1 = (-yb + math.sqrt(ys)) / (2 * ya);
if (t1 >= 0 && t1 <= 1) {
final y = pointOnCurve(t1).y;
if (y < minY) minY = y;
if (y > maxY) maxY = y;
}
final t2 = (-yb - math.sqrt(ys)) / (2 * ya);
if (t2 >= 0 && t2 <= 1) {
final y = pointOnCurve(t2).y;
if (y < minY) minY = y;
if (y > maxY) maxY = y;
}
}
}
bounds[0] = minX;
bounds[1] = minY;
bounds[2] = maxX;
bounds[3] = maxY;
}