b94c364282c8655421f5f09e50f2a34f0dedc22f
[occt.git] / src / IVtkTools / IVtkTools_ShapePicker.cxx
1 // Created on: 2011-10-27 
2 // Created by: Roman KOZLOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS 
4 // 
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <IVtkTools_ShapePicker.hxx>
17 #include <IVtkTools_ShapeObject.hxx>
18 #include <IVtkVTK_View.hxx>
19
20 // prevent disabling some MSVC warning messages by VTK headers 
21 #ifdef _MSC_VER
22 #pragma warning(push)
23 #endif
24 #include <vtkCommand.h>
25 #include <vtkObjectFactory.h>
26 #include <vtkRenderer.h>
27 #include <vtkActorCollection.h>
28 #ifdef _MSC_VER
29 #pragma warning(pop)
30 #endif
31
32 //! @class IVtkTools_ShapePicker
33 //! VTK picker implementation for OCCT shapes.
34 //! Can pick either whole shapes or sub-shapes.
35 //! The kind of selectable entities is defined by the current selection mode.
36 //! NOTE: For performance reasons, setRenderer() method should be called in advance,
37 //! before the user starts to select interactively, in order for the OCCT selection
38 //! algorithm to prepare its internal selection data.
39
40 vtkStandardNewMacro(IVtkTools_ShapePicker)
41
42 //============================================================================
43 //  Method: IVtkTools_ShapePicker
44 // Purpose: Constructs the picker with empty renderer and ready for point selection.
45 //============================================================================
46 IVtkTools_ShapePicker::IVtkTools_ShapePicker()
47 : myRenderer (NULL),
48   myIsRectSelection (false)
49 {
50   myOccPickerAlgo = new IVtkOCC_ShapePickerAlgo();
51 }
52
53 //============================================================================
54 //  Method: ~IVtkTools_ShapePicker
55 // Purpose: Destructor
56 //============================================================================
57 IVtkTools_ShapePicker::~IVtkTools_ShapePicker()
58 {
59 }
60
61 //============================================================================
62 //  Method: SetTolerance
63 // Purpose: Setter for tolerance of picking.
64 //============================================================================
65 void IVtkTools_ShapePicker::SetTolerance (float theTolerance )
66 {
67   myTolerance = theTolerance;
68 }
69
70 //============================================================================
71 //  Method: GetTolerance
72 // Purpose: Getter for tolerance of picking.
73 //============================================================================
74 float IVtkTools_ShapePicker::GetTolerance( ) const
75 {
76   return myTolerance;
77 }
78
79 //============================================================================
80 //  Method: convertDisplayToWorld
81 // Purpose: Convert display coordinates to world coordinates
82 //============================================================================
83 bool IVtkTools_ShapePicker::convertDisplayToWorld (vtkRenderer *theRenderer,
84                                                    double theDisplayCoord[3],
85                                                    double theWorldCoord[3])
86 {
87   // Convert the selection point into world coordinates.
88   theRenderer->SetDisplayPoint (theDisplayCoord[0], theDisplayCoord[1], theDisplayCoord[2]);
89   theRenderer->DisplayToWorld();
90
91   double aCoords[4];
92   theRenderer->GetWorldPoint(aCoords);
93   if (aCoords[3] == 0.0)
94   {
95     return false;
96   }
97
98   for (Standard_Integer anI = 0; anI < 3; anI++)
99   {
100     theWorldCoord[anI] = aCoords[anI] / aCoords[3];
101   }
102   
103   return true;
104 }
105
106 //============================================================================
107 // Method:  Pick
108 // Purpose: Pick entities in the given point.
109 //============================================================================
110 int IVtkTools_ShapePicker::Pick (double theX, double theY, double /*theZ*/, vtkRenderer *theRenderer)
111 {
112   double aPos[2] = {theX, theY};
113   myIsRectSelection = false;
114   myIsPolySelection = false;
115   return pick (aPos, theRenderer);
116 }
117
118 //============================================================================
119 //  Method: pick
120 // Purpose: Pick entities in the given rectangle area.
121 //============================================================================
122 int IVtkTools_ShapePicker::Pick (double theXPMin, double theYPMin, double theXPMax, double theYPMax,
123                                  vtkRenderer *theRenderer)
124 {
125   double aPos[4] = {theXPMin, theYPMin, theXPMax, theYPMax};
126   myIsRectSelection = true;
127   myIsPolySelection = false;
128   return pick (aPos, theRenderer);
129 }
130 //============================================================================
131 //  Method: pick
132 // Purpose: Pick entities in the given polygonal area.
133 //============================================================================
134 int IVtkTools_ShapePicker::Pick (double thePoly[][3], const int theNbPoints,
135                                  vtkRenderer *theRenderer)
136 {
137   myIsRectSelection = false;
138   myIsPolySelection = true;
139   return pick ((double*)thePoly, theRenderer, theNbPoints);
140 }
141
142 //============================================================================
143 //  Method: pick
144 // Purpose: Pick entities in the given point or area.
145 //============================================================================
146 int IVtkTools_ShapePicker::pick (double* thePos,
147                                  vtkRenderer *theRenderer,
148                                  const int theNbPoints)
149 {
150  //  Initialize picking process
151   Initialize();
152
153   // Emit StartPickEvent for observer callbacks (if any)
154   InvokeEvent(vtkCommand::StartPickEvent, NULL);
155
156   vtkSmartPointer<vtkRenderer> aRenderer;
157   if (theRenderer == NULL)
158   {
159     aRenderer = myRenderer; // by default use own renderer
160   }
161   else
162   {
163     aRenderer = theRenderer;
164   }
165   doPickImpl (thePos, aRenderer, theNbPoints);
166
167   // Emit EndPickEvent for observer callbacks (if any)
168   InvokeEvent(vtkCommand::EndPickEvent, NULL);
169
170   return myOccPickerAlgo->NbPicked();
171 }
172
173 //============================================================================
174 //  Method: doPickImpl
175 // Purpose: Implementation of picking algorithm.
176 //============================================================================
177 void IVtkTools_ShapePicker::doPickImpl (double* thePos,
178                                         vtkRenderer* theRenderer, 
179                                         const int theNbPoints)
180 {
181   // Make sure the correct renderer is used
182   SetRenderer (theRenderer);
183
184   if (myIsPolySelection)
185   {
186     myOccPickerAlgo->Pick ((double**)thePos, theNbPoints);
187   }
188   else if (myIsRectSelection)
189   {
190     myOccPickerAlgo->Pick (thePos[0], thePos[1], thePos[2], thePos[3]);
191   }
192   else
193   {
194     myOccPickerAlgo->Pick (thePos[0], thePos[1]);
195   }
196 }
197
198 //============================================================================
199 //  Method: SetRenderer
200 // Purpose: Sets the renderer to be used by OCCT selection algorithm
201 //============================================================================
202 void IVtkTools_ShapePicker::SetRenderer (vtkRenderer* theRenderer)
203 {
204   if (theRenderer == myRenderer.GetPointer())
205   {
206     return;
207     // In this case we should not do anything.
208     // In the worth case we need to update picker algorithm (view er selector and projection options)
209     // If any needs this , call myOccPickerAlgo->Modified();
210   }
211
212   myRenderer = theRenderer;
213   IVtkVTK_View::Handle aView = new IVtkVTK_View (myRenderer);
214   myOccPickerAlgo->SetView (aView);
215 }
216
217 //============================================================================
218 //  Method: SetAreaSelection
219 // Purpose: Sets area selection on/off
220 //============================================================================
221 void IVtkTools_ShapePicker::SetAreaSelection (bool theIsOn)
222 {
223   myIsRectSelection = theIsOn;
224 }
225
226 //============================================================================
227 //  Method: GetSelectionModes
228 // Purpose: Get activated selection modes for a shape.
229 //============================================================================
230 IVtk_SelectionModeList IVtkTools_ShapePicker::GetSelectionModes (
231                                               const IVtk_IShape::Handle& theShape) const
232 {
233   return myOccPickerAlgo->GetSelectionModes (theShape);
234 }
235
236 //============================================================================
237 //  Method: GetSelectionModes
238 // Purpose: Get activated selection modes for a shape actor.
239 //============================================================================
240 IVtk_SelectionModeList IVtkTools_ShapePicker::GetSelectionModes (
241                                               vtkActor* theShapeActor) const
242 {
243   IVtk_SelectionModeList aRes;
244   IVtk_IShape::Handle aShape = IVtkTools_ShapeObject::GetOccShape (theShapeActor);
245   if (!aShape.IsNull())
246   {
247     aRes = myOccPickerAlgo->GetSelectionModes (aShape);
248   }
249   return aRes;
250 }
251
252 //============================================================================
253 //  Method: SetSelectionMode
254 // Purpose: Turn on/off a selection mode for a shape.
255 //============================================================================
256 void IVtkTools_ShapePicker::SetSelectionMode (const IVtk_IShape::Handle& theShape,
257                                               const IVtk_SelectionMode   theMode,
258                                               const bool                 theIsTurnOn) const
259 {
260   myOccPickerAlgo->SetSelectionMode (theShape, theMode, theIsTurnOn);
261 }
262
263 //============================================================================
264 //  Method: SetSelectionMode
265 // Purpose: Turn on/off a selection mode for a shape actor.
266 //============================================================================
267 void IVtkTools_ShapePicker::SetSelectionMode (vtkActor*                theShapeActor,
268                                               const IVtk_SelectionMode theMode,
269                                               const bool               theIsTurnOn) const
270 {
271   IVtk_IShape::Handle aShape = IVtkTools_ShapeObject::GetOccShape (theShapeActor);
272   if (!aShape.IsNull())
273   {
274     myOccPickerAlgo->SetSelectionMode (aShape, theMode, theIsTurnOn);
275   }
276 }
277
278 //============================================================================
279 //  Method: SetSelectionMode
280 // Purpose: Sets the current selection mode for all visible shape objects.
281 //============================================================================
282 void IVtkTools_ShapePicker::SetSelectionMode (const IVtk_SelectionMode theMode, 
283                                               const bool               theIsTurnOn) const
284 {
285   if (myRenderer.GetPointer() != NULL)
286   {
287     // Obtain all OccShapes displayed and activate the specified selection mode
288     vtkSmartPointer<vtkActorCollection> anActors = myRenderer->GetActors();
289     anActors->InitTraversal();
290     vtkSmartPointer<vtkActor> anActor = anActors->GetNextActor();
291     while ( anActor.GetPointer() != NULL )
292     {
293       if (anActor->GetPickable() && anActor->GetVisibility())
294       {
295         if (anActor->GetMapper())
296         {
297           IVtk_IShape::Handle aShape = IVtkTools_ShapeObject::GetOccShape (anActor);
298           if (!aShape.IsNull())
299           {
300             myOccPickerAlgo->SetSelectionMode (aShape, theMode, theIsTurnOn);
301           }
302         }
303       }
304       anActor = anActors->GetNextActor();
305     }
306   }
307 }
308
309 //============================================================================
310 //  Method: GetPickedShapesIds
311 // Purpose: Access to the list of top-level shapes picked.
312 //============================================================================
313 IVtk_ShapeIdList IVtkTools_ShapePicker::GetPickedShapesIds (bool theIsAll) const
314 {
315   if (theIsAll || myIsRectSelection )
316   {
317     return myOccPickerAlgo->ShapesPicked();
318   }
319
320   IVtk_ShapeIdList aRes;
321   IVtk_ShapeIdList aPicked = myOccPickerAlgo->ShapesPicked();
322   if (!aPicked.IsEmpty())
323   {
324     aRes.Append (aPicked.First());
325   }
326   return aRes;
327 }
328
329 //============================================================================
330 //  Method: RemoveSelectableActor
331 // Purpose: Remove selectable object from the picker (from internal maps).
332 //============================================================================
333 void IVtkTools_ShapePicker::RemoveSelectableObject(const IVtk_IShape::Handle& theShape)
334 {
335   myOccPickerAlgo->RemoveSelectableObject(theShape);
336 }
337
338 //============================================================================
339 //  Method: RemoveSelectableActor
340 // Purpose: Remove selectable object from the picker (from internal maps).
341 //============================================================================
342 void IVtkTools_ShapePicker::RemoveSelectableActor(vtkActor* theShapeActor)
343 {
344   IVtk_IShape::Handle aShape = IVtkTools_ShapeObject::GetOccShape(theShapeActor);
345   if (!aShape.IsNull())
346   {
347     RemoveSelectableObject(aShape);
348   }
349 }
350
351 //============================================================================
352 //  Method: GetPickedSubShapesIds
353 // Purpose: Access to the list of sub-shapes ids picked.
354 //============================================================================
355 IVtk_ShapeIdList IVtkTools_ShapePicker::GetPickedSubShapesIds (const IVtk_IdType theId, bool theIsAll) const
356 {
357   IVtk_ShapeIdList aRes;
358   if (theIsAll)
359   {
360     myOccPickerAlgo->SubShapesPicked (theId, aRes);
361   }
362   else
363   {
364     IVtk_ShapeIdList aList;
365     myOccPickerAlgo->SubShapesPicked (theId, aList);
366     if (!aList.IsEmpty())
367     {
368       aRes.Append (aList.First());
369     }
370   }
371   return aRes;
372 }
373
374 //============================================================================
375 //  Method: GetPickedActors
376 // Purpose: Access to the list of actors picked.
377 //============================================================================
378 vtkSmartPointer<vtkActorCollection> IVtkTools_ShapePicker::GetPickedActors (bool theIsAll) const
379 {
380   vtkSmartPointer<vtkActorCollection> aRes = vtkSmartPointer<vtkActorCollection>::New();
381   IVtk_ShapeIdList anIds = GetPickedShapesIds (theIsAll);
382   if (myRenderer.GetPointer() != NULL)
383   {
384     // Obtain all actors whose source shape ids are within selected ids.
385     vtkSmartPointer<vtkActorCollection> anActors = myRenderer->GetActors();
386     anActors->InitTraversal();
387     vtkSmartPointer<vtkActor> anActor = anActors->GetNextActor();
388     while ( anActor.GetPointer() != NULL )
389     {
390       if (anActor->GetPickable() && anActor->GetVisibility())
391       {
392         if (anActor->GetMapper())
393         {
394           IVtk_IShape::Handle aShape = IVtkTools_ShapeObject::GetOccShape (anActor);
395           if (!aShape.IsNull())
396           {
397             for (IVtk_ShapeIdList::Iterator anIt (anIds); anIt.More(); anIt.Next())
398             {
399               if (aShape->GetId() == anIt.Value())
400               {
401                 aRes->AddItem (anActor);
402               }
403             }
404           }
405         }
406       }
407       anActor = anActors->GetNextActor();
408     }
409   }
410   return aRes;
411 }