|
'Snapping
to Grid' implies confining the mouse input to a pre-defined
3D planar grid. This feature is extensively used in various
applications typically in situations where the user is required
to create a drawing or a sketch. In this article we will
learn how to enable this feature in your HOOPS based application
using the utility class HSnapGrid which
is provided with HOOPS/MVO.
Let
us take a simple operation - creating a sphere. We will
take the default implementation of the operator (HOpCreateSphere
in MVO) and
enhance it to provide the 'snap to grid' feature.
1.
Define the Snap-Grid.
Create a member object pointer of class HSnapGrid
as
below.
class HOpCreateSphereSnap : public HBaseOperator
{
...
protected:
bool m_bSnapToGrid; /*Indicates if in snap mode*/
HSnapGrid * m_pSnapGrid; /*To display a grid and snap moves to it */
HC_KEY m_ScratchSeg; /*Scratch segment for drawing temporary geometry*/
...
}
Define
the plane and intervals for the grid. The example below
defines a grid which lies in XY plane and has unit interval
along both the axes.
HOpCreateSphereSnap::HOpCreateSphereSnap (HBaseView* view, int DoRepeat, int DoCapture, bool SnapToGrid) :
HBaseOperator(view, DoRepeat, DoCapture)
{
...
if( m_bSnapToGrid )
{
// create a grid object with grid along XY plane
m_pSnapGrid = new HSnapGrid(view);
HPoint origin(0, 0, 0);
HPoint ref1(1, 0, 0);
HPoint ref2(0, 1, 0);
m_pSnapGrid->Create(origin, ref1, ref2, 0, 0);
// create a scratch area for highlighting snapped point
HC_Open_Segment_By_Key(m_pView->GetConstructionKey());
m_ScratchSeg = HC_KOpen_Segment("scratch segment");
HC_Flush_Geometry(".");
HC_Set_Visibility("everything = off, markers = on");
HC_Set_Color("markers = blue");
HC_Close_Segment();
HC_Close_Segment();
m_pView->Update();
}
}
Remember
to destroy the HSnapGrid object in the destructor.
Using this object we can snap any mouse input point on to
the grid.
2.
Identify the mouse input functions.
From the HOpCreateSphere.h we find following functions
which provides with a mouse input.
virtual int OnNoButtonDownAndMove(HEventInfo &event);
virtual int OnLButtonDown(HEventInfo &event);
virtual int OnLButtonDownAndMove(HEventInfo &event);
virtual int OnLButtonUp(HEventInfo &event);
Each of this function recieves the mouse input location
through the HEventInfo parameter. In the next step,
we are going to convert this mouse location to the nearest
point on the grid.
3.
Use HSnapGrid object to snap mouse input to nearest
point on the grid.
The function HSnapGrid::GetSnappedXXX takes a point
and returns the snapped point. OnLButtonDown function
below shows an example.
int HOpCreateSphereSnap::OnLButtonDown(HEventInfo &event)
{
...
if( m_bSnapToGrid )
{
// get the world pos point and snap it
HPoint this_pt = event.GetMouseWorldPos();
m_pSnapGrid->GetSnappedWorldPos( this_pt );
// highlight the snapped location
HC_Open_Segment_By_Key(m_ScratchSeg);
HC_Flush_Geometry(".");
HC_Insert_Marker(this_pt.x, this_pt.y, this_pt.z);
HC_Close_Segment();
// reset the event with the snapped point
event.SetWorldPos(event.GetType(), this_pt, event.GetFlags());
}
...
}
How
is it done?
The input location is projected onto the view plane.
A ray is the created with the help of this point and original
input location. The intersection of this ray and the grid
plane gives a point on the grid plane. Finally this point
is snapped to its closed grid point and returned. To display
the grid, HSnapGrid uses HOOPS' Insert_Grid
api.
Advanced
Grid Manipulation
Various other methods of HSnapGrid allows the
programmer to control various aspects of the grid. HSnapGrid::GetGridSegment
returns the segment key in which the grid geometry is inserted.
The programmer can set various attributes of this segment
to set the display of the grid. Also, one can set the grid
to be displayed on top by using the api HSnapGrid::SetOnTop.
Fig.
1: The mouse point snapped on to the grid for input
as the center of the sphere

Fig. 2: The mouse point snapped on to the grid for
second input as a point on the sphere.

Fig.
3: The output sphere.

|