Orienting Objects on Surfaces
Windows only
Overview
Rhino orients objects onto a surface by defining a rotation transformation. With the Rhino C/C++ SDK, you define transformations with the ON_Xform
class. See opennurbs_xform.h for details. The transformation that is defined rotates objects from one plane to another. The source plane is defined from the active view’s construction plane and a user-selected base point. The target plane is defined by the location the user picks on the surface.
Sample
The following sample code demonstrates how to orient objects on a surface.
NOTE: This sample does not contain all of the options available in the Rhino command, nor does it show the objects transforming dynamically, but it is a good example on how to build the transformation.
CRhinoCommand::result CCommandTest::RunCommand( const CRhinoCommandContext& context )
{
// Select objects to orient
CRhinoGetObject go;
go.SetCommandPrompt( L"Select objects to orient" );
go.EnableSubObjectSelect( FALSE );
go.EnableGroupSelect( TRUE );
go.GetObjects( 1, 0 );
if( go.CommandResult() != success )
return go.CommandResult();
// Point to orient from
CRhinoGetPoint gp;
gp.SetCommandPrompt( L"Point to orient from" );
gp.GetPoint();
if( gp.CommandResult() != success )
return gp.CommandResult();
// Define source plane
CRhinoView* view = gp.View();
if( 0 == view )
{
view = RhinoApp().ActiveView();
if( 0 == view )
return failure;
}
ON_Plane source_plane( view->Viewport().ConstructionPlane().m_plane );
source_plane.SetOrigin( gp.Point() );
// Surface to orient on
CRhinoGetObject gs;
gs.SetCommandPrompt( L"Surface to orient on" );
gs.SetGeometryFilter( CRhinoGetObject::surface_object );
gs.EnableSubObjectSelect( TRUE );
gs.EnableDeselectAllBeforePostSelect( false );
gs.EnableOneByOnePostSelect();
gs.GetObjects( 1, 1 );
if( gs.CommandResult() != success )
return gs.CommandResult();
const CRhinoObjRef& ref = gs.Object(0);
// Get selected surface object
const CRhinoObject* obj = ref.Object();
if( 0 == obj )
return failure;
// Get selected surface (face)
const ON_BrepFace* face = ref.Face();
if( 0 == face )
return failure;
// Unselect surface
obj->Select( false );
// Point on surface to orient to
gp.SetCommandPrompt( L"Point on surface to orient to" );
gp.Constrain( *face );
gp.GetPoint();
if( gp.CommandResult() != success )
return gp.CommandResult();
// Do transformation
CRhinoCommand::result rc = failure;
double u = 0.0, v = 0.0;
if( face->GetClosestPoint(gp.Point(), &u, &v) )
{
ON_Plane target_plane;
if( face->FrameAt(u, v, target_plane) )
{
// If the face orientation is opposite
// of natural surface orientation, then
// flip the plane's zaxis.
if( face->m_bRev )
{
target_plane.yaxis.Reverse();
target_plane.zaxis.Reverse();
target_plane.UpdateEquation();
}
// Build transformation
ON_Xform xform;
xform.Rotation( source_plane, target_plane );
// Do the transformation. In this example,
// we will copy the original objects
bool bDeleteOriginal = false;
int i;
for( i = 0; i < go.ObjectCount(); i++ )
context.m_doc.TransformObject( go.Object(i), xform, bDeleteOriginal );
context.m_doc.Redraw();
rc = success;
}
}
return rc;
}