dca1ebf01f397e546496ec6f518b2c922b179a2e
[occt.git] / src / IVtkOCC / IVtkOCC_ShapePickerAlgo.cxx
1 // Created on: 2011-10-14 
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 <IVtk_Types.hxx>
17 #include <IVtkOCC_ShapePickerAlgo.hxx>
18 #include <IVtkOCC_Shape.hxx>
19 #include <IVtkOCC_SelectableObject.hxx>
20 #include <Message.hxx>
21 #include <Message_Messenger.hxx>
22 #include <StdSelect_BRepOwner.hxx>
23
24 IMPLEMENT_STANDARD_RTTIEXT(IVtkOCC_ShapePickerAlgo,IVtk_IShapePickerAlgo)
25
26 // Handle implementation
27
28
29 //================================================================
30 // Function : Constructor
31 // Purpose  : 
32 //================================================================
33 IVtkOCC_ShapePickerAlgo::IVtkOCC_ShapePickerAlgo() :
34 myViewerSelector (new IVtkOCC_ViewerSelector())
35 { }
36
37 //================================================================
38 // Function : Destructor
39 // Purpose  : 
40 //================================================================
41 IVtkOCC_ShapePickerAlgo::~IVtkOCC_ShapePickerAlgo()
42 { }
43
44 //================================================================
45 // Function : SetView
46 // Purpose  :
47 //================================================================
48 void IVtkOCC_ShapePickerAlgo::SetView (const IVtk_IView::Handle& theView)
49 {
50   myView = theView;
51 }
52
53 //================================================================
54 // Function : GetSelectionModes
55 // Purpose  :
56 //================================================================
57 IVtk_SelectionModeList IVtkOCC_ShapePickerAlgo::GetSelectionModes (
58                                   const IVtk_IShape::Handle& theShape) const
59 {
60   IVtk_SelectionModeList aRes;
61
62   if (! theShape.IsNull())
63   {
64     // Get shape implementation from shape interface.
65     Handle(IVtkOCC_Shape) aShapeImpl = Handle(IVtkOCC_Shape)::DownCast(theShape);
66
67     // Get selectable object from the shape implementation.
68     Handle(IVtkOCC_SelectableObject) aSelObj = 
69       Handle(IVtkOCC_SelectableObject)::DownCast(aShapeImpl->GetSelectableObject());
70
71     if (!aSelObj.IsNull())
72     {
73       IVtk_SelectionMode aSelMode;
74       for (aSelMode = SM_Shape; aSelMode <= SM_Compound; aSelMode = (IVtk_SelectionMode)(aSelMode + 1))
75       {
76         if (myViewerSelector->IsActive (aSelObj, aSelMode))
77         {
78           aRes.Append (aSelMode);
79         }
80       }
81     }
82   }
83
84   return aRes;
85 }
86
87 //================================================================
88 // Function : SetSelectionMode
89 // Purpose  :
90 //================================================================
91 void IVtkOCC_ShapePickerAlgo::SetSelectionMode (const IVtk_IShape::Handle& theShape,
92                                                 const IVtk_SelectionMode theMode,
93                                                 const bool theIsTurnOn)
94 {
95   if (theShape.IsNull())
96   {
97     return;
98   }
99
100   // TODO: treatment for mode == -1 - deactivate the shape...
101   // Is this really needed? The picker and all selection classes
102   // are destroyed when shapes are deactivated...
103
104   // Get shape implementation from shape interface.
105   Handle(IVtkOCC_Shape) aShapeImpl = 
106     Handle(IVtkOCC_Shape)::DownCast(theShape);
107
108   // Get selectable object from the shape implementation.
109   Handle(IVtkOCC_SelectableObject) aSelObj = 
110     Handle(IVtkOCC_SelectableObject)::DownCast(aShapeImpl->GetSelectableObject());
111
112   if (theIsTurnOn)
113   {
114     // If there is no selectable object then create a new one for this shape.
115     if (aSelObj.IsNull())
116     {
117       aSelObj = new IVtkOCC_SelectableObject (aShapeImpl);
118     }
119
120     // If the selectable object has no selection in the given mode
121     if (!aSelObj->HasSelection (theMode))
122     {
123       // then create a new selection in the given mode for this object (shape).
124       Handle(SelectMgr_Selection) aNewSelection = new SelectMgr_Selection (theMode); 
125       aSelObj->AddSelection (aNewSelection, theMode);
126       myViewerSelector->AddSelectionToObject (aSelObj, aNewSelection);
127     }
128
129     // Update the selection for the given mode according to its status.
130     const Handle(SelectMgr_Selection)& aSel = aSelObj->Selection (theMode);
131
132     switch (aSel->UpdateStatus())
133     {
134       case SelectMgr_TOU_Full:
135         // Recompute the sensitive primitives which correspond to the mode.
136         myViewerSelector->RemoveSelectionOfObject (aSelObj, aSelObj->Selection (theMode));
137         aSelObj->RecomputePrimitives (theMode);
138         myViewerSelector->AddSelectionToObject (aSelObj, aSelObj->Selection (theMode));
139         myViewerSelector->RebuildObjectsTree();
140         myViewerSelector->RebuildSensitivesTree (aSelObj);
141       case SelectMgr_TOU_Partial:
142         {
143           if (aSelObj->HasTransformation())
144           {
145             myViewerSelector->RebuildObjectsTree();
146           }
147           break;
148         }
149       default:
150         break;
151     }
152     // Set status of the selection to "nothing to update".
153     aSel->UpdateStatus (SelectMgr_TOU_None);
154
155     // Activate the selection in the viewer selector.
156     myViewerSelector->Activate (aSelObj->Selection (theMode));
157
158   }
159   else
160   { // turn off the selection mode
161
162     if (!aSelObj.IsNull())
163     {
164       if (aSelObj->HasSelection (theMode))
165       {
166         const Handle(SelectMgr_Selection)& aSel = aSelObj->Selection (theMode);
167         myViewerSelector->Deactivate (aSel);
168       }
169     }
170   }
171 }
172
173 //================================================================
174 // Function : SetSelectionMode
175 // Purpose  :
176 //================================================================
177 void IVtkOCC_ShapePickerAlgo::SetSelectionMode (const IVtk_ShapePtrList& theShapes,
178                                                 const IVtk_SelectionMode theMode,
179                                                 const bool /*theIsTurnOn*/)
180 {
181   IVtk_IShape::Handle aShape;
182   IVtk_ShapePtrList::Iterator anIt (theShapes);
183   for (; anIt.More(); anIt.Next())
184   {
185     aShape = anIt.Value();
186     SetSelectionMode (aShape, theMode);
187   }
188 }
189
190 //================================================================
191 // Function : Pick
192 // Purpose  :
193 //================================================================
194 bool IVtkOCC_ShapePickerAlgo::Pick (const double theX, const double theY)
195 {
196   clearPicked();
197
198   // Calling OCCT algortihm
199   myViewerSelector->Pick ((Standard_Integer)theX,
200                           (Standard_Integer)theY,
201                           myView);
202
203   // Fill the results
204   return processPicked();
205 }
206
207 //================================================================
208 // Function : Pick
209 // Purpose  :
210 //================================================================
211 bool IVtkOCC_ShapePickerAlgo::Pick (const double theXMin,
212                                     const double theYMin,
213                                     const double theXMax,
214                                     const double theYMax)
215 {
216   clearPicked();
217
218   // Calling OCCT algortihm
219   myViewerSelector->Pick ((Standard_Integer)theXMin,
220                           (Standard_Integer)theYMin,
221                           (Standard_Integer)theXMax,
222                           (Standard_Integer)theYMax,
223                           myView);
224
225   // Fill the results
226   return processPicked();
227 }
228
229 //================================================================
230 // Function : Pick
231 // Purpose  :
232 //================================================================
233 bool IVtkOCC_ShapePickerAlgo::Pick (double** thePoly,
234                                     const int theNbPoints)
235 {
236   clearPicked();
237
238   // Calling OCCT algortihm
239   myViewerSelector->Pick (thePoly, theNbPoints, myView);
240
241   // Fill the results
242   return processPicked();
243 }
244
245 //================================================================
246 // Function : ShapesPicked
247 // Purpose  :
248 //================================================================
249 const IVtk_ShapeIdList& IVtkOCC_ShapePickerAlgo::ShapesPicked() const
250 {
251   return myShapesPicked;
252 }
253
254 //================================================================
255 // Function : SubShapesPicked
256 // Purpose  :
257 //================================================================
258 void IVtkOCC_ShapePickerAlgo::SubShapesPicked (const IVtk_IdType theId, IVtk_ShapeIdList& theShapeList) const
259 {
260   if (mySubShapesPicked.IsBound (theId))
261   {
262     theShapeList = mySubShapesPicked (theId);
263   }
264 }
265
266 //================================================================
267 // Function : clearPicked
268 // Purpose  : Internal method, resets picked data
269 //================================================================
270 void IVtkOCC_ShapePickerAlgo::clearPicked()
271 {
272   myShapesPicked.Clear();
273   mySubShapesPicked.Clear();
274 }
275
276 //================================================================
277 // Function : NbPicked
278 // Purpose  : Get number of picked entities.
279 //================================================================
280 int IVtkOCC_ShapePickerAlgo::NbPicked()
281 {
282   return myShapesPicked.Extent();
283 }
284
285 //================================================================
286 // Function : processPicked
287 // Purpose  :
288 //================================================================
289 bool IVtkOCC_ShapePickerAlgo::processPicked()
290 {
291   Standard_Integer aNbPicked =  myViewerSelector->NbPicked();
292   Handle(StdSelect_BRepOwner) anEntityOwner;
293   Handle(Message_Messenger) anOutput = Message::DefaultMessenger();
294
295   for (Standard_Integer aDetectIt = 1; aDetectIt <= aNbPicked; aDetectIt++)
296   {
297     // ViewerSelector detects sensitive entities under the mouse
298     // and for each entity returns its entity owner.
299     // StdSelect_BRepOwner instance holds corresponding sub-shape (TopoDS_Shape)
300     // and in general entity owners have a pointer to SelectableObject that can tell us
301     // what is the top-level TopoDS_Shape.
302     anEntityOwner = Handle(StdSelect_BRepOwner)::DownCast (myViewerSelector->Picked (aDetectIt));
303     if (!anEntityOwner.IsNull())
304     {
305       Handle(IVtkOCC_SelectableObject) aSelectable =
306         Handle(IVtkOCC_SelectableObject)::DownCast (anEntityOwner->Selectable());
307
308       if (aSelectable.IsNull())
309       {
310         anOutput << "Error: EntityOwner having null SelectableObject picked!";
311         continue;
312       }
313
314       Handle(IVtkOCC_Shape) aSelShape = aSelectable->GetShape();
315       if (aSelShape.IsNull())
316       {
317         anOutput << "Error: SelectableObject with null OccShape pointer picked!";
318         continue;
319       }
320
321       IVtk_IdType aTopLevelId = aSelShape->GetId();
322       myShapesPicked.Append (aTopLevelId);
323
324       // Now try to guess if it's the top-level shape itself or just a sub-shape picked
325       TopoDS_Shape aTopLevelShape = aSelShape->GetShape();
326       TopoDS_Shape aSubShape      = anEntityOwner->Shape();
327       if (aTopLevelShape.IsNull())
328       {
329         anOutput << "Error: OccShape with null top-level TopoDS_Shape picked!";
330         continue;
331       }
332       if (aSubShape.IsNull())
333       {
334         anOutput << "Error: EntityOwner with null TopoDS_Shape picked!";
335         continue;
336       }
337
338       if (!aSubShape.IsSame (aTopLevelShape))
339       {
340         IVtk_IdType aSubId = aSelShape->GetSubShapeId (aSubShape);
341
342         if (!mySubShapesPicked.IsBound (aTopLevelId))
343         {
344           const IVtk_ShapeIdList aList;
345           mySubShapesPicked.Bind (aTopLevelId, aList);
346         }
347         // Order of selected sub-shapes
348         mySubShapesPicked (aTopLevelId).Append (aSubId);
349       }
350     }
351   }
352
353   return !myShapesPicked.IsEmpty();
354 }
355
356 //============================================================================
357 //  Method: RemoveSelectableActor
358 // Purpose: Remove selectable object from the picker (from internal maps).
359 //============================================================================
360 void IVtkOCC_ShapePickerAlgo::RemoveSelectableObject(const IVtk_IShape::Handle& theShape)
361 {
362   clearPicked();
363   // Get shape implementation from shape interface.
364   Handle(IVtkOCC_Shape) aShapeImpl =
365     Handle(IVtkOCC_Shape)::DownCast(theShape);
366
367   // Get selectable object from the shape implementation.
368   Handle(IVtkOCC_SelectableObject) aSelObj =
369     Handle(IVtkOCC_SelectableObject)::DownCast(aShapeImpl->GetSelectableObject());
370
371   myViewerSelector->RemoveSelectableObject(aSelObj);
372   myViewerSelector->Clear();
373   aShapeImpl->SetSelectableObject(NULL);
374 }