Calculating the bounding box of cubic bezier curve

怎甘沉沦 提交于 2019-12-30 06:29:30

问题


I am trying to find an algorithm to calculate the bounding box of a given cubic bezier curve. The curve is in 3D space.

Is there a mathematic way to do this except of sampling points on the curve and calculating the bounding box of these points?


回答1:


Most of this is addressed in An algorithm to find bounding box of closed bezier curves? except here we have cubic Beziers and there they were dealing with quadratic Bezier curves.

Essentially you need to take the derivatives of each of the coordinate functions. If the x-coord is given by

x = A (1-t)^3 +3 B t (1-t)^2 + 3 C t^2 (1-t) + D t^3

differentiating with respect to t.

dx/dt =  3 (B - A) (1-t)^2 + 6 (C - B) (1-t) t + 3 (D - C) t^2
      =  [3 (D - C) - 6 (C - B) + 3 (B - A)] t^2
       + [ -6 (B - A) - 6 (C - B)] t
       + 3 (B - A) 
      =  (3 D - 9 C + 9 B - 3 A) t^2 + (6 A - 12 B + 6 C) t + 3 (B - A)

this is a quadratic which we can write at a t^2 + b t + c. We want to solve dx/dt = 0 which you can do using the quadratic formula

- b +/- sqrt(b^2-4 a c)
-----------------------
        2 a

Solving this will either gives two solutions t0, t1 say, no solutions or in rare case just one solution. We are only interest in solutions with 0 <= t <= 1. You will have a maximum of four candidate points, the two end points and the two solutions. Its a simple matter to find which of these give the extreme points.

You can repeat the same process for each coordinate and then get the bounding box.

I've put this for the 2D case in a js fiddle http://jsfiddle.net/SalixAlba/QQnvm/4/




回答2:


Finding the bounding box of a cubic Bezier curve (or even B-spline curve of any degree) is typically done by finding the bounding box of the curve's control polygon. Since the curve is always bounded by its control polygon, the bounding box obtained via the control polygon is guaranteed to enclose the curve. You can also perform knot insertion to the curve and make the control polygon become closer to the curve itself. So, the general algorithm will go like this:

1) Find the bounding box (denoted as BBox1) of the current B-spline curve from its control polygon.
2) Insert knot at the mid-parameter of each Bezier segment in the B-spline curve.
3) Find the bounding box (denoted as BBox2) of the new B-spline curve.
4) Compare BBox2 against BBox1. If BBox2 is pretty much the same size as BBox1, we are done. If BBox2 is considerably smaller than BBox1, repeat step 2 to 4 until convergence.




回答3:


this article explain the details and also has a live html5 demo:
Calculating / Computing the Bounding Box of Cubic Bezier

I found a javascript in Snap.svg to calculate that: here
see the bezierBBox and curveDim functions.

I rewrite a javascript function.

//(x0,y0) is start point; (x1,y1),(x2,y2) is control points; (x3,y3) is end point.
function bezierMinMax(x0, y0, x1, y1, x2, y2, x3, y3) {
    var tvalues = [], xvalues = [], yvalues = [],
        a, b, c, t, t1, t2, b2ac, sqrtb2ac;
    for (var i = 0; i < 2; ++i) {
        if (i == 0) {
            b = 6 * x0 - 12 * x1 + 6 * x2;
            a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;
            c = 3 * x1 - 3 * x0;
        } else {
            b = 6 * y0 - 12 * y1 + 6 * y2;
            a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;
            c = 3 * y1 - 3 * y0;
        }
        if (Math.abs(a) < 1e-12) {
            if (Math.abs(b) < 1e-12) {
                continue;
            }
            t = -c / b;
            if (0 < t && t < 1) {
                tvalues.push(t);
            }
            continue;
        }
        b2ac = b * b - 4 * c * a;
        if (b2ac < 0) {
            if (Math.abs(b2ac) < 1e-12) {
                t = -b / (2 * a);
                if (0 < t && t < 1) {
                    tvalues.push(t);
                }
            }
            continue;
        }
        sqrtb2ac = Math.sqrt(b2ac);
        t1 = (-b + sqrtb2ac) / (2 * a);
        if (0 < t1 && t1 < 1) {
            tvalues.push(t1);
        }
        t2 = (-b - sqrtb2ac) / (2 * a);
        if (0 < t2 && t2 < 1) {
            tvalues.push(t2);
        }
    }

    var j = tvalues.length, mt;
    while (j--) {
        t = tvalues[j];
        mt = 1 - t;
        xvalues[j] = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3);
        yvalues[j] = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3);
    }

    xvalues.push(x0,x3);
    yvalues.push(y0,y3);

    return {
        min: {x: Math.min.apply(0, xvalues), y: Math.min.apply(0, yvalues)},
        max: {x: Math.max.apply(0, xvalues), y: Math.max.apply(0, yvalues)}
    };
}


来源:https://stackoverflow.com/questions/24809978/calculating-the-bounding-box-of-cubic-bezier-curve

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!