Offsetting Curves on Surfaces
Windows only
Problem
You are using the RhinoOffsetCurveOnSrf
function to offset a curve which was interpolated on a cylindrical surface. The problem is that the results do not seem to match those of Rhino’s OffsetCrvOnSrf
command. That is, the offset curve does not extend to the edges of the surfaces. Why is this?
Solution
After calculating the offset curve, the OffsetCrvOnSrf
command extends both ends of that curve to the surface edge using RhinoExtendCrvOnSrf
. Below is an sample of how you can do this using the SDK…
Sample
CRhinoCommand::result CCommandTest::RunCommand( const CRhinoCommandContext& context ) { // Select curve on surface CRhinoGetObject gc; gc.SetCommandPrompt( L"Select curve on surface" ); gc.SetGeometryFilter( CRhinoGetObject::curve_object ); gc.GetObjects( 1, 1 ); if( gc.CommandResult() != CRhinoCommand::success ) return gc.CommandResult(); // Validate curve const ON_Curve* crv = gc.Object(0).Curve(); if( 0 == crv ) return CRhinoCommand::failure; // Select base surface CRhinoGetObject gs; gs.SetCommandPrompt( L"Select base surface" ); gs.SetGeometryFilter( CRhinoGetObject::surface_object ); gs.EnablePreSelect( false ); gs.EnableDeselectAllBeforePostSelect( false ); gs.GetObjects( 1, 1 ); if( gs.CommandResult() != CRhinoCommand::success ) return gs.CommandResult(); // Validate face const ON_BrepFace* face = gs.Object(0).Face(); if( 0 == face ) return CRhinoCommand::failure; // Validate brep const ON_Brep* brep = face->Brep(); if( 0 == brep ) return CRhinoCommand::failure; // Specify offset distance CRhinoGetNumber gd; gd.SetCommandPrompt( L"Offset distance" ); gd.SetDefaultNumber( 1.0 ); gd.GetNumber(); if( gd.CommandResult() != CRhinoCommand::success ) return gd.CommandResult(); double dist = gd.Number(); // Do offset curve on surface double tol = context.m_doc.AbsoluteTolerance(); ON_SimpleArray<ON_Curve*> offset_curves; CRhinoCommand::result cmdrc = RhinoOffsetCurveOnSrf( crv, brep, face->m_face_index, dist, tol, offset_curves ); if( cmdrc == CRhinoCommand::success ) { int i = 0; ON_SimpleArray<const ON_Curve*> curves_to_join; curves_to_join.Append( offset_curves.Count(), offset_curves.Array() ); // Try joining the offset curves ON_SimpleArray<ON_Curve*> joined_curves; BOOL rc = RhinoMergeCurves( curves_to_join, joined_curves, 2.0 * tol, TRUE ); for( i = 0; i < curves_to_join.Count(); i++ ) curves_to_join[i] = 0; if( rc ) { for( i = 0; i < joined_curves.Count(); i++ ) { ON_Curve* pC = joined_curves[i]; if( pC ) { // Extend both ends to edge of the surface if( !pC->IsClosed() ) RhinoExtendCrvOnSrf( *face, pC ); // Add to document CRhinoCurveObject* crv_obj = new CRhinoCurveObject(); crv_obj->SetCurve( pC ); context.m_doc.AddObject( crv_obj ); joined_curves[i] = 0; } } // Do not leak memory for( i = 0; i < offset_curves.Count(); i++ ) { if( offset_curves[i] ) { delete offset_curves[i]; offset_curves[i] = 0; } } } else { for( i = 0; i < offset_curves.Count(); i++) { ON_Curve* pC = offset_curves[i]; if( pC ) { // Extend both ends to edge of the surface if( !pC->IsClosed() ) RhinoExtendCrvOnSrf( *face, pC ); // Add to document CRhinoCurveObject* crv_obj = new CRhinoCurveObject(); crv_obj->SetCurve( pC ); context.m_doc.AddObject( crv_obj ); offset_curves[i] = 0; } } } } context.m_doc.Redraw(); return CRhinoCommand::success; }