Find span index given domain

I have an [overly complex] workflow where I generate a polycurve, and encode a relative distance to another curve into a UserDictionary. I sample the segments of the polycurve at the endpoints of the spans, and store this in an array. Later, I use various methods to get parameters along the curve, which don’t always relate to the spans.

Is there a way to determine which span contains a parameter? I want to know this, as for each parameter I use a Rhino.Geometry.Interpolator to find what the “interpolated value” is based on the originally sampled values. The challenge is the interpolator works best with things like PolylineCurve, where the domain is some thing like " 4.60" for the parameter 60% of the way from along the fifth segment. In this case I need to come up with a normalized domain (where something like 4.6 would mean the point 60% along the parameter space in the fifth span…)

Probably there is a cleaner way to do this. I don’t want to split the original curve, though that might be the easier way. These curves have sometimes 15k - 20k spans, so I am afraid the segments will be heavier than the spans (maybe not).

currently doing this by splitting the curves, and storing the computed values as an Interval in the userdictionary. But its pretty heavy. You can always tell its too heavy as you will get an access violation error(meaning, someone else’s code broke).

Hi Wes,

Is this what you want?

PolyCurve poly_curve = ...;
Point3d test_point = ...;
double t;
if (poly_curve.ClosestPoint(test_point, out t))
{
  int segment_index = poly_curve.SegmentIndex(t);
  if (segment_index >= 0 && segment_index < poly_curve.SegmentCount)
  {
    // TODO...
  }
}

– Dale

I am looking for the span index I think, as the segments might have multiple spans? The only way I saw to do it was to

double t;
poly_curve.ClosestPoint(test_point, out t);

int span;
for(int i=0;i<curve.SpanCount;i++)
{
  if(curve.SpanDomain(i).IncludesParameter(t))
  {
    span = i;
    break;
  }
}

And that seems like a lot of code to do 20k times.

Maybe I can open up the question more. I want to sample the distances between two nurbs curves periodically, and store this information in a vector. Later, I will create points along the second curve, and I would like to get an interpolated value of its distance based on the vector I stored before. At this point I can’t easily test that distance, as the curves have been joined, etc. The concept works well for polylinecurves, as there domain structure seems to match the Interpolator class usage well. But its not working well here, with nurbscurves.

Why do you need the span index? I don’t understand what knowing this will get you?

But to answer your question:

If you were using the Rhino C++ SDK, you could use ON_Curve::GetSpanVectorIndex, which returns the span vector index given an evaluation parameter. But this function isn’t available in RhinoCommon.

The best you can is something like the following:

PolyCurve curve = ...
Point3d point = ...

// Get the parameter on the polycurve that is closest to the point
double curve_t;
if (curve.ClosestPoint(point, out curve_t))
{
  // Get the segment index at the parameter
  int segment_index = curve.SegmentIndex(curve_t);
  if (segment_index >= 0 && segment_index < curve.SegmentCount)
  {
    // Get the segment curve
    Curve segment = curve.SegmentCurve(segment_index);
          
    // Convert the parameter to a segment parameter
    double segment_t = curve.SegmentCurveParameter(curve_t);

    // Find the span that includes the segment parameter.
    // Note, not all curves have non-empty, smooth (c-infinity) spans.
    int span_index = -1;
    for (int i = 0; i < segment.SpanCount; i++)
    {
      if (segment.Domain.IncludesParameter(segment_t))
      {
        span_index = i;
        break;
      }
    }

    if (span_index >= 0)
    {
      // TODO...
    }
  }
}

Helpful?

– Dale

Yes that is what I ended up trying; but in then end a more top down approach won out. I am now just storing the domains that I sample distance at in the userdict as well, and using those directly.