CRhinoCommand::result CCommandSamplePrePostSelect::RunCommand( const CRhinoCommandContext& context )
{
  double dValue = m_dValue;
  int nValue = m_nValue;

  CRhinoGetObject go;
  go.SetGeometryFilter( CRhinoGetObject::curve_object );
  go.EnableGroupSelect( TRUE );
  go.EnableSubObjectSelect( FALSE );

  /*int d_option_index =*/ go.AddCommandOptionNumber( 
      RHCMDOPTNAME(L"Double"), &dValue, L"Double value", FALSE, 1.0, 99.9 );

  /*int n_option_index =*/ go.AddCommandOptionInteger( 
      RHCMDOPTNAME(L"Integer"), &nValue, L"Integer value", 1, 99 );

  bool bHavePreselectedObjects = false;

  for( ;; )
  {
    CRhinoGet::result res = go.GetObjects( 1, 0 );

    if( res == CRhinoGet::option )
    {
      go.EnablePreSelect( FALSE );
      go.EnableAlreadySelectedObjectSelect( true );
      go.EnableClearObjectsOnEntry( false );
      go.EnableDeselectAllBeforePostSelect( false );
      go.EnableUnselectObjectsOnExit( false );
      continue;
    }

    else if( res != CRhinoGet::object )
      return CRhinoCommand::cancel;

    if( go.ObjectsWerePreSelected() )
    {
      bHavePreselectedObjects = true;
      go.EnablePreSelect( FALSE );
      go.EnableAlreadySelectedObjectSelect( true );
      go.EnableClearObjectsOnEntry( false );
      go.EnableDeselectAllBeforePostSelect( false );
      go.EnableUnselectObjectsOnExit( false );
      continue;
    }

    break;
  }

  if( bHavePreselectedObjects )
  {
    // Normally, pre-selected objects will remain selected, when a
    // command finishes, and post-selected objects will be unselected.
    // This this way of picking, it is possible to have a combination
    // of pre-selected and post-selected. So, to make sure everything
    // "looks the same", lets unselect everything before finishing
    // the command.
    for( int i = 0; i < go.ObjectCount(); i++ )
    {
      const CRhinoObject* object = go.Object(i).Object();
      if( 0 != object )
        object->Select( false );
    }
    context.m_doc.Redraw();
  }

  int object_count = go.ObjectCount();
  m_dValue = dValue;
  m_nValue = nValue;

  RhinoApp().Print( L"Select object count = %d\n", object_count );
  RhinoApp().Print( L"Value of double = %f\n", m_dValue );
  RhinoApp().Print( L"Value of integer = %d\n", m_nValue );

  return CRhinoCommand::success;
}
CRhinoCommand::result CCommandSampleOrientOnSrf::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() != CRhinoCommand::success )
    return go.CommandResult();

  // Point to orient from
  CRhinoGetPoint gp;
  gp.SetCommandPrompt( L"Point to orient from" );
  gp.GetPoint();
  if( gp.CommandResult() != CRhinoCommand::success )
    return gp.CommandResult();

  // Define source plane
  CRhinoView* view = gp.View();
  if( 0 == view )
  {
    view = RhinoApp().ActiveView();
    if( 0 == view )
      return CRhinoCommand::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() != CRhinoCommand::success )
    return gs.CommandResult();

  const CRhinoObjRef& ref = gs.Object(0);
  // Get selected surface object
  const CRhinoObject* obj = ref.Object();
  if( 0 == obj )
    return CRhinoCommand::failure;
  // Get selected surface (face)
  const ON_BrepFace* face = ref.Face();
  if( 0 == face )
    return CRhinoCommand::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() != CRhinoCommand::success )
    return gp.CommandResult();

  // Do transformation
  CRhinoCommand::result rc = CRhinoCommand::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.CreateFromFrame( 
            target_plane.origin, 
            target_plane.xaxis, 
            -target_plane.zaxis 
            );

      // 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 = CRhinoCommand::success;
    }
  }

	return rc;
}