GetPointAtChordLength(double Length)?

Hello,

I want to achieve something quite similar to what the Curve.DivideByLength(double segmentLength) method do, that is “Divide the curve into specific length segments”. Here, all segments will be of length segmentLength.

But instead of giving only one segmentLength I want to input a list of segment length (double[] segmentLengths that acts as a division pattern. For instance, if the list is [1,2,4], the distance between first and second points will be 1, 2nd and 3rd will be 2, 3rd and 4th will be 4 … then back to 1 between 4th and 5th, …

So I wonder if there is a chance you can provide a GetPointAtChordLength(double Length) similar to the GetPointAtLength(double Length) in the rhinocommon C# API ? I suppose the Curve.DivideByLength(double segmentLength) method uses such a method internally ?

Second question, could you explain the principles of the algorithm behind Curve.DivideByLength(double segmentLength) ? Is this a kind of dichotomic search ?

Thanks,
Lionel

NB : I can already do what I want with curve/sphere intersection but this is really slow and I want to speed up my method.

Here is extension method, lets call it DivideByLenghtsA(), taht you can include in your project. It is doing what you are looking for. It uses curve.LengthParameter() method to get curve parameter at particualr length. Subsequent lengths are calcluated from your list of segment-lengths.

    public static List<double> DivideByLenghtsA(this Curve curve, List<double> segmentLenghts, double fractionalTolerance)
    {
        if (curve == null || segmentLenghts == null || segmentLenghts.Count < 1 || fractionalTolerance <= 0) return null;
        //All segmentLenghts must be >0 
        for (int i = 0; i < segmentLenghts.Count; i++) if (segmentLenghts[i] <= 0) return null;
        List<double> crvParameters = new List<double>();
        double curLength = 0;
        int curIndex = 0;
        while (true)
        {
            curLength += segmentLenghts[curIndex];
            double prm;
            if (!curve.LengthParameter(curLength, out prm, fractionalTolerance)) break;
            crvParameters.Add(prm);
            curIndex = ++curIndex % segmentLenghts.Count;
        }
        return crvParameters;            
    }

\

So when you put such extension method in your project you can use it do determine coresponidng points on the curve for examle like this:

        //curve .. some Curve
        //segments .. list of segemnt lengths, List<double>...
        var parameters = curve.DivideByLenghtsA(segments, 0.00000001);
        var points = parameters.Select(p => curve.PointAt(p));
1 Like

Hi @lionpeloux,

Use Curve.DivideEquidistant.

– Dale

Hi Radovan,

Thank you but this is not what I am talking about. Your script does not position the points to the specified chord lengths (or segment length) along the curve, but regarding to the arclength (that is the length along the curve’s path).

Hi Dale,

Ok, this could do the trick but would require to determine a lot of unnecessary point computations as this method works for a single segment length.

I finally end up with this solution :

Let P be a point on the curve. To find next point Q at (chord) distance L from P (that is ||QP|| = L) :

  1. First guess the next position at arclength L from P (that is the lenght of the subcurve between Q0 and P is L)
  2. Then solve (||Q(t*)P||^2 - L^2)^2 = 0 with a Newton’s method (less than 5 steps for each point)
  3. The solution is Q* = Q(t*)