Problem
Imagine you have a 3D point, now you want to pick all the objects that are underneath it.
Solution
You can use CRhinoPickContext
to build your own object picker. For more details on CRhinoPickContext
, see rhinoSdkPick.h. With the CRhinoPickContext
class, you can define the rules for picking. For example, you can specify a picking style (point, window, crossing). You can also specify a filter so you only pick the types of objects you want. The most important part is to define a pick chord, which starts on near clipping plane and ends on far clipping plane.
After you have created the CRhinoPickContext
object and filled out its parameters, call CRhinoDoc::PickObjects
. This function goes through the list of eligible objects and intersects them with the pick frustum. If they hit the frustum in an acceptable manner, the object is added to a pick list passed in by the caller.
Here is a simple example of a function that might work for you:
static int MyObjectPicker( CRhinoDoc& doc, CRhinoView* view, POINT point, CRhinoObjRefArray& pick_list )
{
if( 0 == view )
return 0;
CRhinoPickContext pick_context;
pick_context.m_view = view;
pick_context.m_pick_style = CRhinoPickContext::point_pick;
CRhinoViewport& active_vp = view->ActiveViewport();
switch( active_vp.DisplayMode() )
{
case ON::shaded_display:
case ON::renderpreview_display:
pick_context.m_pick_mode = CRhinoPickContext::shaded_pick;
break;
}
int pick_count = 0;
if( active_vp.GetPickXform(point.x, point.y, pick_context.m_pick_region.m_xform) )
{
// adds objects to pick_list - does not change any status
active_vp.VP().GetFrustumLine( point.x, point.y, pick_context.m_pick_line );
pick_context.UpdateClippingPlanes();
pick_count = doc.PickObjects( pick_context, pick_list );
}
return pick_count;
}
And, here is a sample of its use:
CRhinoCommand::result CCommandTest::RunCommand( const CRhinoCommandContext& context )
{
CRhinoGetPoint gp;
gp.GetPoint();
if( gp.CommandResult() != CRhinoCommand::success )
return gp.CommandResult();
CRhinoView* view = gp.View();
if( 0 == view )
return failure;
ON_Xform w2s;
view->ActiveViewport().VP().GetXform( ON::world_cs, ON::screen_cs, w2s );
ON_3dPoint pt3d = gp.Point();
pt3d.Transform( w2s );
POINT pt2d;
pt2d.x = (int)pt3d.x;
pt2d.y = (int)pt3d.y;
CRhinoObjRefArray pick_list;
int pick_count = MyObjectPicker( context.m_doc, view, pt2d, pick_list );
for( int i = 0; i < pick_count; i++ )
{
const CRhinoObject* obj = pick_list[i].Object();
if( obj )
obj->Select( true, true, true );
}
context.m_doc.Redraw();
return CRhinoCommand::success;
}