Rhinocommon opposite of NormalizedLengthParameter

So is there an opposite function to Curve.NormalizedLengthParameter.

We have a point on a curve as a parameter in the domain of the curve,
and want to get a normalized arc length parameter back from this curve and parameter.

Right now we are using:
double nParam = InCurve.Curve.GetLength(new Interval(InCurve.Curve.Domain.Min, parameterInCurve)) / InCurve.Curve.GetLength();

Which works, just wanting to know if we really have to code this by hand? or am I missing a function to do this somewhere?

Thanks.

Gordon J.

1 Like

Hi @gordon,

If you have curve parameter, which fall within a curve’s domain, and you want it’s normalized form, then use Interval.NormalizedParameterAt.

Likewise, if you have a normalized parameter and you want to convert it to a curve parameter, then use Interval.ParameterAt.

A Python example:

import Rhino
import rhinoscriptsyntax as rs

obj_id = rs.GetObject("Select curve")
if rs.IsCurve(obj_id):
    crv = rs.coercecurve(obj_id)
    dom = crv.Domain
    t = (dom.Max + dom.Min) * 0.5
    nt = dom.NormalizedParameterAt(t)
    print 'Normalized parameter: ', nt
    ct = dom.ParameterAt(nt)
    print 'Curve parameter: ', ct

Does this help?

– Dale

So I am looking to get from a curve parameter to a normalized arc length value and back again.

you example above is:
parameter to normalized domain parameter and back.
Which is a different thing.

Hi @gordon,

If you have a parameter (of any kind) and you want it normalized, then use the technique I show above.

To get the parameter of the point on the curve that is a prescribed arc length from the start of the curve, then use Curve.NormalizedLengthParameter.

I guess I need more information on what you are trying to do - sorry.

– Dale

using System.Collections.Generic;
using Rhino;
using Rhino.Commands;
using Rhino.Geometry;

namespace ArcLengthReverse
{
    public class ArcLengthReverseCommand : Command
    {
        public ArcLengthReverseCommand()
        {
            // Rhino only creates one instance of each command class defined in a
            // plug-in, so it is safe to store a refence in a static property.
            Instance = this;
        }

        ///<summary>The only instance of this command.</summary>
        public static ArcLengthReverseCommand Instance
        {
            get; private set;
        }

        ///<returns>The command name as it appears on the Rhino command line.</returns>
        public override string EnglishName
        {
            get { return "ArcLengthReverseCommand"; }
        }

        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            List<Point3d> curvePoints=new List<Point3d>{new Point3d(0,0,0),new Point3d(0,9,0),new Point3d(0,10,0)};

            Curve testcrv = new PolylineCurve(curvePoints);
            doc.Objects.AddCurve(testcrv);

            Point3d testPoint = new Point3d(0, 5, 0);
            doc.Objects.AddPoint(testPoint);

            //-----------------------------------------------
            // getting to the Domain Normalized Value and back again.

            // a test point half way up this curve 
            testcrv.ClosestPoint(testPoint, out double crvParam);

            // the parameter for this test point is 0.5555555555555555
            RhinoApp.WriteLine($"The parameter on this curve at 0,5,0 = {crvParam}");

            double normalizedDomainValue = testcrv.Domain.NormalizedParameterAt(crvParam);
            // normalized domain value = 0.2777777777777777    (not 0.5)
            RhinoApp.WriteLine($"Domain Normalized Value = {normalizedDomainValue}");

            // and back again = 0.5555555555555555
            double backparam = testcrv.Domain.ParameterAt(normalizedDomainValue);
            RhinoApp.WriteLine($"param on curve back out {backparam}");

            // and back to the original point:
            Point3d pointOnCrv = testcrv.PointAt(backparam);
            RhinoApp.WriteLine($"Point y = {pointOnCrv.Y}");


            //---------------------------------------------------
            // getting to the Normalized Arc Length Value and back again.

            // a test point half way up this curve 
            testcrv.ClosestPoint(testPoint, out double crvParam1);

            // the parameter for this test point is 0.5555555555555555
            RhinoApp.WriteLine($"The parameter on this curve at 0,5,0 = {crvParam1}");

            // Question revolves around this line:
            double normalizedArcLengthValue = testcrv.GetLength(new Interval(testcrv.Domain.Min,crvParam1))/testcrv.GetLength();
            // normalized ArcLength Value = 0.5  !!! (Half way along the curve so want 0.5, got it correctly here.)
            RhinoApp.WriteLine($"Normalized ArcLength Value = {normalizedArcLengthValue}");

            // and back again = 0.5555555555555555
            testcrv.NormalizedLengthParameter(normalizedArcLengthValue,out double backparam1);
            RhinoApp.WriteLine($"param on curve back out {backparam1}");

            // and back to the original point:
            Point3d pointOnCrv1 = testcrv.PointAt(backparam1);
            RhinoApp.WriteLine($"Point y = {pointOnCrv1.Y}");


            doc.Views.Redraw();

            return Result.Success;
        }
    }
}

So we have the functions for normalized domain and back is:
double normalizedDomainValue = testcrv.Domain.NormalizedParameterAt(crvParam);
double backparam = testcrv.Domain.ParameterAt(normalizedDomainValue);

But normalized arc length and back is missing a function: (as far as I can see.)
double normalizedArcLengthValue = testcrv.GetLength(new Interval(testcrv.Domain.Min,crvParam1))/testcrv.GetLength();
testcrv.NormalizedLengthParameter(normalizedArcLengthValue,out double backparam1);

For the Normalized arc length version of this it has always been a little confusing.

I want a function that take a crv param and returns a Normalized Arc Length Parameter from that curve parameter.
And we always make the mistake from its name that curve.NormalizedLengthParameter(double t, out double s); would do this,
but it is actually the function for the other way around function.
NormalizedLengthParameter take a normalized parameter and returns a crv parameter.
And there is no reverse function of this built in.

Which brings us back to:
double normalizedArcLengthValue = testcrv.GetLength(new Interval(testcrv.Domain.Min,crvParam1))/testcrv.GetLength();

So am looking for something like:
double arclengthValue=testcrv.NormalizedArcLengthParameterAt(crvParam);

Hi @gordon,

There isn’t a function to do this. But you can calculate it yourself if needed.

// Convert the arc-length parameter to a normalized parameter
var sub_domain = new Interval(curve.Domain.Min, t1);
var sub_length = curve.GetLength(sub_domain);
var length = curve.GetLength();
var s1 = sub_length / length;
RhinoApp.WriteLine($"Arc-length parameter = {t1}, normalized parameter = {s1} (+/- {ftol})");

TestGordon.cs (3.0 KB)

– Dale