Quadratic bezier curve how to find bounding box?

Started by
8 comments, last by cadjunkie 5 years, 7 months ago

Hi

 

I have this function which draws a quadratic bezier curve:

 


        public static Vector3 Position(float t, Vector3 a, Vector3 b, Vector3 anchor)
        {
            var oneMinusT = 1 - t;
            var sumA = oneMinusT * oneMinusT * a;
            var sumB = 2 * oneMinusT * t * anchor;
            var sumC = t * t * b;

            return sumA + sumB + sumC;
        }


And i want to now find the bounding box for it. But i can't seem to get it to work. I used this equation:

https://stackoverflow.com/a/1099291/5736835

But i don't get the correct result.

This is my code for it:

 


        var p0 = waypointA.Position;
        var p1 = waypointB.Position;
        var p2 = anchorPoint;
        var extrema = Vector3.zero;

        var tx = (p0.x - p1.x) / (p0.x - 2 * p1.x + p2.x);
        extrema.x = QuadraticBezier.Position(tx, waypointA.Position, waypointB.Position, anchorPoint).x;

        var tz = (p0.z - p1.z) / (p0.z - 2 * p1.z + p2.z);
        extrema.z = QuadraticBezier.Position(tz, waypointA.Position, waypointB.Position, anchorPoint).z;

        Extrema = extrema;

        min = Vector3.Min(waypointA.Position, waypointB.Position);
        max = Vector3.Max(waypointA.Position, waypointB.Position);


        min = Vector3.Min(min, Extrema);
        max = Vector3.Max(max, Extrema);

        var center = (min + max) / 2f;
        var size = max - min;

        Bounds = new Bounds(center,size);


This was the visual end result of it:
image.png.61c5a297642b61819cb8517c6b900cbf.png

Definitely not correct. The extrema point is the yellow sphere at the bottom. which is clearly not in the correct place, since its not even on the curve let alone the furthest point.

Am hoping some one knows how to solve this - i am not the best at maths so am trying to figure this out but its quite a challenge. I also found this as a guide on how to calculate it but i don't know how i would do that mathematically:

 

Quote

Computing the bounding box for a Bézier curve:

  1. Find all t value(s) for the curve derivative's x- and y-roots.
  2. Discard any t value that's lower than 0 or higher than 1, because Bézier curves only use the interval [0,1].
  3. Determine the lowest and highest value when plugging the values t=0, t=1 and each of the found roots into the original functions: the lowest value is the lower bound, and the highest value is the upper bound for the bounding box we want to construct.

 

If any one is able to help with this i would be very grateful, have been stuck on this for some time now. :(

 

Edit: Just to note i use the X:Z plane so my Vector3's all have Y position equal to zero.
 

Advertisement

It looks like your extrema is mirrored to the wrong side of the v_0, v_2 line. Double-check your math. Otherwise, your process appears correct.

RIP GameDev.net: launched 2 unusably-broken forum engines in as many years, and now has ceased operating as a forum at all, happy to remain naught but an advertising platform with an attached social media presense, headed by a staff who by their own admission have no idea what their userbase wants or expects.Here's to the good times; shame they exist in the past.
1 minute ago, Wyrframe said:

It looks like your extrema is mirrored to the wrong side of the v_0, v_2 line. Double-check your math. Otherwise, your process appears correct.

I don't think the extrema is correct because if you draw a dashed line from the visual extrema, it doesn't seem to be in the correct place even if it wasn't reflected:

image.png.e17eb056aeef7126b0111b6462d99913.png

And you're right it is mirror'd but i don't know why - i can't see my mistake.

That would be where it goes if you mirrored across the X axis only. Mirror across the P0,P1 line, and you'll see it's very close (within the error of the size of your circles, as far as I can tell).

It doesn't look like you're checking tx,tz for being in valid range; if they're out of [0,1] range, then don't include them in extrema-point calculation.

Are the green/red points the bounds of the calculated rectangle? If not, what are those?

And by double-check your math, a good process is to do it by hand using some simple, integer coordinates. If you can't get sane results, the technique is wrong. If you get sane results but your code doesn't reproduce it, debug the code one step at a time to find the divergence.

RIP GameDev.net: launched 2 unusably-broken forum engines in as many years, and now has ceased operating as a forum at all, happy to remain naught but an advertising platform with an attached social media presense, headed by a staff who by their own admission have no idea what their userbase wants or expects.Here's to the good times; shame they exist in the past.

Yeah the red and green points represent the bounds.

 

I did add the range check but it made no difference:

 


        var extrema = Vector3.zero;
        var tx = (p0.x - p1.x) / (p0.x - 2 * p1.x + p2.x);
        if (tx >= 0 && tx <= 1)
        {
            extrema.x = QuadraticBezier.Position(tx, waypointA.Position, waypointB.Position, anchorPoint).x;
            min.x = Mathf.Min(min.x, extrema.x);
            max.x = Mathf.Max(max.x, extrema.x);
        }

        var tz = (p0.z - p1.z) / (p0.z - 2 * p1.z + p2.z);
        if (tz >= 0 && tz <= 1)
        {
            extrema.z = QuadraticBezier.Position(tz, waypointA.Position, waypointB.Position, anchorPoint).z;
            min.z = Mathf.Min(min.z, extrema.z);
            max.z = Mathf.Max(max.z, extrema.z);
        }

 

I am a little bit out of my depth as i am not good with maths. From what i can gather by the step by step info in my first post, i would need to find the equation of my bezier curve, not sure how i work that out, then find the derivative (theres only one derivative for a quadratic) then find the roots which will give me the stationary point on the curve.

But my maths knowledge does not come close to even figuring out how to do that sadly.

 

You might double-check and make sure your mapping from the 'A, B, anchor' representation to the 'p0, p1, p2' representation is correct. (It may already be correct, but it seemed worth mentioning.)

Just now, Zakwayda said:

You might double-check and make sure your mapping from the 'A, B, anchor' representation to the 'p0, p1, p2' representation is correct. (It may already be correct, but it seemed worth mentioning.)

Well i am unsure which one is the anchor point in the stack overflow answer which was the main confusing. I assumed p1 was the anchor/handle point. 

Quote

I assumed p1 was the anchor/handle point.

In your code it looks like you have p2 mapped to the anchor point though.

In any case, p1 = anchor does seem likely. Right now it looks like you have:

p0 = A, p1 = B, p2 = anchor

Whereas it seems like it would be worth trying this instead:

p0 = A, p1 = anchor, p2 = B

Your p0, p1, and p2 are not consistent with the order for the method you're using for calculating position. According to how you calculate your derivative, your anchor point should be p1.

EDIT: Just saw this was answered. Doh!

This topic is closed to new replies.

Advertisement