0

I have recently been working on Bezier curves and have come across a very interesting snippet of code relating to finding the normal of a Bezier curve. It is the only of its kind I can find and there were no comments left as to how it was derived. the code is as follows :

    internal static Vector3 EvaluateSplineSegmentNormal (SplinePoint pointA, SplinePoint pointB, float t) {
        // Evaluate the normal for value t between points A and B
        return ((6.0f * (t * t)) - (6.0f * t)) * pointA.position 
            + ((3.0f * (t * t)) - ((4.0f * t) + 1)) * pointA.GetHandle(Direction.Forward)
            + ((3.0f * (t * t)) - (2.0f * t)) * pointB.GetHandle(Direction.Backward)
            + ((-6.0f * (t * t)) + (6.0f * t)) * pointB.position;
    }

Where the primary info in it is represented here :

            NP0 = (6*t*t - 6*);
            NC0 = (3*t*t - 4*t + 1);
            NC1 = (3*t*t - 2*t);
            NP1 = (-6*t*t + 6*t);

Where NP0, NC0, NC1, NP1 represent a similar concept as what P0,P1,P2,P3 are multiplied by respectively in this Wikipedia article. In the Hermite curve Article, the basis functions H00,H01,H10,H11 are a good analogy for NP0, NC0, NC1, NP1.

My question is how does this work, if it even does, and how was it derived so I can do the same for a Hermite curve as well. The go to answer for finding the normal would be to just use the vector given by the derivative and cross it with the up vector for example, I have yet to see any other instance where a separate set of polynomials were used to calculate normals, but that is exactly what I need in order to have a generalised function that can take any size vector/value in my program.

If it helps any, I will include the data I have to compute a point and the derivative in the same style as above, I know that the derivative is not usually represented as 4 distinct polynomials to multiply by, so I did some basic rearranging and have tested to confirm it works properly.

            //Calculates curve position at t[0, 1]
            P0 = (-1*t*t*t + 3*t*t - 3*t + 1);
            C0 = (3*t*t*t - 6*t*t + 3*t);
            C1 = (-3*t*t*t + 3*t*t);
            P1 = (t*t*t);

            //Calculates tangent at t[0, 1]
            DP0 = (-3*t*t + 6*t - 3);
            DC0 = (9*t*t - 12*t + 3);
            DC1 = (-9*t*t + 6*t);
            DP1 = (3*t*t);

The way to use these values to compute the point is as follows:

    Point = P0*startPoint + C0*startHandle + C1*endHandle + P1*endPoint;

Any help would be appreciated, I have been going though countless scientific papers and code examples for so long that the word Bezier gives me ptsd-esque flashbacks at this point.

ZXYNINE
  • 712
  • 4
  • 5
  • 1
    You already know how to calculate the tangent. Just rotate it by 90 degrees and normalize the length. – Matt Timmermans Apr 14 '22 at 00:54
  • @MattTimmermans As stated, I need this to be generic meaning I do not know what type of vector be it 2d or 3d or what have you. I am computing the polynomial result at t which is then provided to the user to multiply the components so I cannot use lin. alg. operations as I will never even have the points to do that with. – ZXYNINE Apr 14 '22 at 01:05
  • A curve only has a normal in 2D. In 3D, a *surface* has a normal. Also, the normal isn't a weighted sum of the points, unless you rotate them around some other point by 90 degrees first, and even then you'd have to fix the length. – Matt Timmermans Apr 14 '22 at 01:08
  • @MattTimmermans actually, the statement about 3d only having a normal when talking about surfaces i dont think is entirely true, specifically when talking about curves. Technically I think the unit normal vector is using the same/similar concept as a surface normal, but no matter what the term normal is used along with binormal when referring to splines/curves. Heres a neat visialisation - https://www.youtube.com/watch?v=wQe-Msr9OJA – ZXYNINE Apr 14 '22 at 01:52
  • @ZXYNINE in 3D normal to point on curve is a plane ... the normal/binormal is just representation of that plane and there are infinite rotations possible for it ... so if you really want just polynomial in 3D then stick to the tangent which also describes the plane normal... rotating tangent in 2D is simple you just swap `x,y` and negate one of them. To get tangent you just partialy derive polynomial by each coordinate or by t if you got already separated axises (that is how your `DP0,1,2,3` is derived from `P0,1,2,3` I in 3D use cross product and some align vector (like camera view direction) – Spektre Apr 14 '22 at 06:36
  • @Spektre The normal in relations to splines and curves as I am using it has the full name "Principal Unit Normal Vector" and it actually only has one direction so long as the curve is not straight (i.e its a curve lol). This is because it is defined as the direction that the curve is turning using the tangent as an orthagonal base. That is computed by taking the second derivative of the point and then normalizing it. This is all fine and dandy, but as I mentioned to Matt, I cannot do operations on points directly as my functions never compute them, only the polynomials. – ZXYNINE Apr 14 '22 at 07:21
  • @ZXYNINE what you describing is the result of cross product of two consequent line segments (3 consequent points with small delta ... aligning to local plane of the curve) on the curve ... what is the problem ? you can rotate or cross product polynomials in the same way as point or vectors ... you just end up with polynomial function instead of coordinate scalar value ... – Spektre Apr 14 '22 at 08:22
  • In order to find a point on the curve, the 4 points of a cubic bezier need to be multiplied by each of these polynomials P0,C0,C1,P1 (the polynomials) with B0,B1,B2,B3 (Bezier points) and then the results summed like so : P0*B0 + C0*B1 + C1*B2 + P1*B3, My function will not have access to the bezier points which is why I am computing only the polynomial sections. I do not know if i would be able to do what you are suggesting in that case , though now that i think of it, dot products are flexible. Is that the case? – ZXYNINE Apr 14 '22 at 08:48
  • @Spektre As for your question about what the problem is, my main question is centred around the values found in that function I mentioned at the start and how those were even found/if they are right. I would just like to know that the values in it are even correct to begin with so Im not loosing my mind trying to find a way to derive an incorrect function – ZXYNINE Apr 14 '22 at 08:52
  • @ZXYNINE the form you wrote your polynomial is weird see [the `CX` coefficients for Bezier](https://stackoverflow.com/a/22582447/2521214) its the left side in that commented code section using lower case control point coordinates `x0,x1,...` to obtain tangent you simply derive that by `t` to obtain normal simply cross product 2 consequent tangents (`t` and `t+dt` where dt is small (limit dt->0) ) Also your function has just 2 points where is the rest ? the polynomials of yours use `t^3` so you need 4 control points/vectors to describe cubic curve – Spektre Apr 14 '22 at 09:25
  • @Spektre My function has no points whatsoever, it only calculates the values you multiply each bezier point by, this is why there are four variables for the point and for the derivative. Im using the explicit bezier formula - P(t) = ((1 - t)^3) * P0 + (3t(1-t)^2) * P1 + (3t^2 (1-t)) * P2 + (t^3) * P3 where P1..P3 are the bezier points (which i do not have) and so I am just calulating what each one is multiplied by -> (-1*t*t*t + 3*t*t - 3*t + 1) = ((1 - t)^3), and (3*t*t*t - 6*t*t + 3*t) = (3t(1-t)^2), and (-3*t*t*t + 3*t*t) = (3t^2 (1-t)), and (t*t*t) = (t^3) – ZXYNINE Apr 14 '22 at 10:08
  • @ZXYNINE if you do not have `P0...P3` what do you have ? You can not have cubic bezier curve without any input data ... – Spektre Apr 14 '22 at 10:13
  • @Spektre All i am doing is naming each basis polynomial essentially, I chose P0 for the start point scalar, C0 for the starts controlPoint scalar, C1 is the ends control point scalar, P1 is the end point scalar – ZXYNINE Apr 14 '22 at 10:14
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/243892/discussion-between-zxynine-and-spektre). – ZXYNINE Apr 14 '22 at 10:15

1 Answers1

0

This article will show you how to compute the curvature vector from first and 2nd derivatives of a parametric curve. Once you have the curvature vector, just unitize it to get the "principal unit normal vector".

fang
  • 3,473
  • 1
  • 13
  • 19