Question regarding Bezier Curve - through points
#1
After using the 3D lathe process, I redraw the 2D line using the Bezier Through Points with the original _section points to give the profile more accuracy. The curved line goes all the way from 0 to 1 on the x-Axis. There is functionality to move along the curve which shows the current radius. My question is this - if I know specifically locations on the x-axis of the curve, is there a way to get the corresponding Radius position at those locations?
#2
If I understand you correctly, then the GetPositionOnCurve method on the bezierCurve object should get you the correct result - the method takes a single parameter t argument that can have any value from 0 to 1; 0 meaning the start of the curve and 1 the end of the curve.
Andrej Benedik
#3
If I understand correctly, 't' is a percentage of the length of the curve. My curve always starts at a height X=0 (top) and always ends at height X=1 (bottom), so my question is this - what is the Radius (y?) when x = .12 and I don't know what 't' is at this point?
#4
I understand now.

The solution to this depends on how the points that define the curve are specified.

If all the points are defined with the same x steps, then you can simple use the GetPositionOnCurve where t = x. An example would be (first column x, second column r):

0.0 r1
0.2 r2
0.4 r3
0.6 r4
0.8 r5
1.0 r6


But I assume the user of your application can define the points in the way he wants. In this case the distribution of x values in not equal - for example:

0.0 r1
0.6 r2
0.8 r3
1.0 r4

If you would call GetPositionOnCurve with t = 0.5, you would get a value between second and third radius and not a value for x = 0.5 (between r1 and r2 and closer to r2).

If the x values are always increasing (if the curve does not go down and then up again), then it is possible to use bisection algorithm to find the radius value for given x.

The following code does that:

Code:
public static double GetRadius(double x, BezierCurve bezierCurve)
{
    double accuracy = 0.00001; // How accurate the result should be (lower number means bigger accuracy but more steps - no worried for performance - this is executed very fast)

    double tLower = 0;
    double tUpper = 1;
            
    int count = 0;

    while (count < 10000) // just in case we cannot find the number accurate enough we limit number of iterations
    {
        double middle = (tLower + tUpper) / 2.0;

        Point3D pMiddle = bezierCurve.GetPositionOnCurve(middle);
        double middleX = pMiddle.X;

        if (Math.Abs(middleX - x) <= accuracy) // If we have a result that is accurate enough ...
            return pMiddle.Y;                  // ... we can return the Y value

        if (middleX < x)
            tLower = middle;
        else
            tUpper = middle;

        count ++;
    }

    return double.NaN; // No result found (maybe the x is out of range or accuracy is too small number)
}

The GetRadius method can be tested with the following:

Code:
var controlPoints = new List<Point3D>();

controlPoints.Add(new Point3D(0.0, 50, 0));
controlPoints.Add(new Point3D(0.5, 100, 0));
controlPoints.Add(new Point3D(0.8, 70, 0));
controlPoints.Add(new Point3D(1.0, 50, 0));


var bezierCurve = BezierCurve.CreateFromCurvePositions(controlPoints);

double radius = GetRadius(0.2, bezierCurve); // Get radius for x = 0.2
radius = GetRadius(0.4, bezierCurve);
radius = GetRadius(0.99, bezierCurve);

Because CreateFromCurvePositions requires Point3D collection, I have converted the list of 2D points with x and radius into Point3D where X = x, Y = radius, Z = 0

You can play with different accuracy settings and check how accurate the results are and how many iterations are needed for that (set breakpoint to return statement and check the count value).

Note once again that this works only when the x values are always ascending (or always descending) and do change direction - in this case there would be multiple solutions but this algorithm would not find them.

I hope that this will work well for you.
Andrej Benedik
#5
Ah - just as I suspected, I just have to use the bisection algorithm - something they neglected to teach me in my basic math classes 40 years ago. :-<

Your solution is simple and elegant, just as I thought it would be. Now, if I was just smart enough to figure these things out on my own.

Thanks again for your great support and great products.

Lloyd
  


Forum Jump:


Users browsing this thread:
1 Guest(s)