developer:sdksamples:nurbscurvelength


Problem Calculating the Lengths of NURBS Curves

Developer: C++
Summary: Discusses a problem when trying to calculate the length of a NURBS curve using the Rhino SDK.

Question

I am having problems determining the length of an ON_NurbsCurve created by calling ON_Curve::GetNurbForm. When I test the following block of code, I only get the length of the ON_Curve object, not the ON_NurbsCurve object. What am I doing wrong?

CRhinoCommand::result CCommandFooBar::RunCommand( const CRhinoCommandContext& context )
{
  CRhinoGetObject go;
  go.SetCommandPrompt( L"Select curve" );
  go.SetGeometryFilter( CRhinoGetObject::curve_object );
  go.GetObjects( 1, 1 );
  if( go.CommandResult() != success )
    return go.CommandResult();
 
  const ON_Curve* curve = go.Object(0).Curve();
  if( 0 == curve )
    return failure;
 
  double curve_length = 0.0;
  if( curve->GetLength(&curve_length) )
    RhinoApp().Print( L"ON_Curve::GetLength() = %g\n", curve_length );
 
  ON_NurbsCurve nurbs_curve;
  if( curve->GetNurbForm(nurbs_curve) )
  {
    double nurbs_curve_length = 0.0;
    if( nurbs_curve.GetLength(&nurbs_curve_length) )
      RhinoApp().Print( L"ON_NurbsCurve::GetLength() = %g\n", nurbs_curve_length );
  }
 
  return success;
}

Answer

There is nothing wrong with your code. Rather, you've exposed a flaw in Microsoft Visual C++ 2005 and they way it deals with stack variables with modified vtables. The problem might sound complicated, but the solution is rather easy. Just make a simple function that you can pass your ON_NurbsCurve object to that will calculate the curve length for you. For example, the function below should work for most developers:

BOOL ON_NurbsCurve_GetLength(
        const ON_NurbsCurve& curve,
        double* length,
        double fractional_tolerance = 1.0e-8,
        const ON_Interval* sub_domain = NULL
        )
{
  return curve.GetLength( length, fractional_tolerance, sub_domain );
}

Then, your code sample would look like this:

CRhinoCommand::result CCommandFooBar::RunCommand( const CRhinoCommandContext& context )
{
  CRhinoGetObject go;
  go.SetCommandPrompt( L"Select curve" );
  go.SetGeometryFilter( CRhinoGetObject::curve_object );
  go.GetObjects( 1, 1 );
  if( go.CommandResult() != success )
    return go.CommandResult();
 
  const ON_Curve* curve = go.Object(0).Curve();
  if( 0 == curve )
    return failure;
 
  double curve_length = 0.0;
  if( curve->GetLength(&curve_length) )
    RhinoApp().Print( L"ON_Curve::GetLength() = %g\n", curve_length );
 
  ON_NurbsCurve nurbs_curve;
  if( curve->GetNurbForm(nurbs_curve) )
  {
    double nurbs_curve_length = 0.0;
    if( ON_NurbsCurve_GetLength(nurbs_curve, &nurbs_curve_length) )
      RhinoApp().Print( L"ON_NurbsCurve::GetLength() = %g\n", nurbs_curve_length );
  }
 
  return success;
}


developer/sdksamples/nurbscurvelength.txt · Last modified: 2010/09/28 15:02 by dale Driven by DokuWiki Recent changes RSS feed

 © 1997-2012 

McNeel North America Europe Latin AmericaAsia