0024023: Revamp the OCCT Handle -- general
[occt.git] / src / IVtkOCC / IVtkOCC_ShapePickerAlgo.cxx
CommitLineData
913a4c4a 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// Handle implementation
ec357c5c 25
913a4c4a 26
27//================================================================
28// Function : Constructor
29// Purpose :
30//================================================================
31IVtkOCC_ShapePickerAlgo::IVtkOCC_ShapePickerAlgo() :
32myViewerSelector (new IVtkOCC_ViewerSelector())
33{ }
34
35//================================================================
36// Function : Destructor
37// Purpose :
38//================================================================
39IVtkOCC_ShapePickerAlgo::~IVtkOCC_ShapePickerAlgo()
40{ }
41
42//================================================================
43// Function : SetView
44// Purpose :
45//================================================================
46void IVtkOCC_ShapePickerAlgo::SetView (const IVtk_IView::Handle& theView)
47{
48 myView = theView;
913a4c4a 49}
50
51//================================================================
52// Function : GetSelectionModes
53// Purpose :
54//================================================================
55IVtk_SelectionModeList IVtkOCC_ShapePickerAlgo::GetSelectionModes (
56 const IVtk_IShape::Handle& theShape) const
57{
58 IVtk_SelectionModeList aRes;
59
c04c30b3 60 if (! theShape.IsNull())
913a4c4a 61 {
62 // Get shape implementation from shape interface.
63 Handle(IVtkOCC_Shape) aShapeImpl = Handle(IVtkOCC_Shape)::DownCast(theShape);
64
65 // Get selectable object from the shape implementation.
66 Handle(IVtkOCC_SelectableObject) aSelObj =
67 Handle(IVtkOCC_SelectableObject)::DownCast(aShapeImpl->GetSelectableObject());
68
69 if (!aSelObj.IsNull())
70 {
71 IVtk_SelectionMode aSelMode;
72 for (aSelMode = SM_Shape; aSelMode <= SM_Compound; aSelMode = (IVtk_SelectionMode)(aSelMode + 1))
73 {
74 if (myViewerSelector->IsActive (aSelObj, aSelMode))
75 {
76 aRes.Append (aSelMode);
77 }
78 }
79 }
80 }
81
82 return aRes;
83}
84
85//================================================================
86// Function : SetSelectionMode
87// Purpose :
88//================================================================
89void IVtkOCC_ShapePickerAlgo::SetSelectionMode (const IVtk_IShape::Handle& theShape,
90 const IVtk_SelectionMode theMode,
91 const bool theIsTurnOn)
92{
c04c30b3 93 if (theShape.IsNull())
913a4c4a 94 {
95 return;
96 }
97
98 // TODO: treatment for mode == -1 - deactivate the shape...
99 // Is this really needed? The picker and all selection classes
100 // are destroyed when shapes are deactivated...
101
102 // Get shape implementation from shape interface.
103 Handle(IVtkOCC_Shape) aShapeImpl =
104 Handle(IVtkOCC_Shape)::DownCast(theShape);
105
106 // Get selectable object from the shape implementation.
107 Handle(IVtkOCC_SelectableObject) aSelObj =
108 Handle(IVtkOCC_SelectableObject)::DownCast(aShapeImpl->GetSelectableObject());
109
110 if (theIsTurnOn)
111 {
112 // If there is no selectable object then create a new one for this shape.
113 if (aSelObj.IsNull())
114 {
115 aSelObj = new IVtkOCC_SelectableObject (aShapeImpl);
116 }
117
118 // If the selectable object has no selection in the given mode
119 if (!aSelObj->HasSelection (theMode))
120 {
121 // then create a new selection in the given mode for this object (shape).
122 Handle(SelectMgr_Selection) aNewSelection = new SelectMgr_Selection (theMode);
123 aSelObj->AddSelection (aNewSelection, theMode);
f751596e 124 myViewerSelector->AddSelectionToObject (aSelObj, aNewSelection);
913a4c4a 125 }
126
127 // Update the selection for the given mode according to its status.
128 const Handle(SelectMgr_Selection)& aSel = aSelObj->Selection (theMode);
129
130 switch (aSel->UpdateStatus())
131 {
132 case SelectMgr_TOU_Full:
133 // Recompute the sensitive primitives which correspond to the mode.
f751596e 134 myViewerSelector->RemoveSelectionOfObject (aSelObj, aSelObj->Selection (theMode));
135 aSelObj->RecomputePrimitives (theMode);
136 myViewerSelector->AddSelectionToObject (aSelObj, aSelObj->Selection (theMode));
137 myViewerSelector->RebuildObjectsTree();
138 myViewerSelector->RebuildSensitivesTree (aSelObj);
913a4c4a 139 case SelectMgr_TOU_Partial:
140 {
141 if (aSelObj->HasTransformation())
142 {
f751596e 143 myViewerSelector->RebuildObjectsTree();
913a4c4a 144 }
145 break;
146 }
147 default:
148 break;
149 }
150 // Set status of the selection to "nothing to update".
151 aSel->UpdateStatus (SelectMgr_TOU_None);
152
153 // Activate the selection in the viewer selector.
154 myViewerSelector->Activate (aSelObj->Selection (theMode));
155
156 }
157 else
158 { // turn off the selection mode
159
160 if (!aSelObj.IsNull())
161 {
162 if (aSelObj->HasSelection (theMode))
163 {
164 const Handle(SelectMgr_Selection)& aSel = aSelObj->Selection (theMode);
165 myViewerSelector->Deactivate (aSel);
166 }
167 }
168 }
169}
170
171//================================================================
172// Function : SetSelectionMode
173// Purpose :
174//================================================================
175void IVtkOCC_ShapePickerAlgo::SetSelectionMode (const IVtk_ShapePtrList& theShapes,
176 const IVtk_SelectionMode theMode,
177 const bool /*theIsTurnOn*/)
178{
179 IVtk_IShape::Handle aShape;
180 IVtk_ShapePtrList::Iterator anIt (theShapes);
181 for (; anIt.More(); anIt.Next())
182 {
183 aShape = anIt.Value();
184 SetSelectionMode (aShape, theMode);
185 }
186}
187
188//================================================================
189// Function : Pick
190// Purpose :
191//================================================================
192bool IVtkOCC_ShapePickerAlgo::Pick (const double theX, const double theY)
193{
194 clearPicked();
195
196 // Calling OCCT algortihm
197 myViewerSelector->Pick ((Standard_Integer)theX,
198 (Standard_Integer)theY,
199 myView);
200
201 // Fill the results
202 return processPicked();
203}
204
205//================================================================
206// Function : Pick
207// Purpose :
208//================================================================
209bool IVtkOCC_ShapePickerAlgo::Pick (const double theXMin,
210 const double theYMin,
211 const double theXMax,
212 const double theYMax)
213{
214 clearPicked();
215
216 // Calling OCCT algortihm
217 myViewerSelector->Pick ((Standard_Integer)theXMin,
218 (Standard_Integer)theYMin,
219 (Standard_Integer)theXMax,
220 (Standard_Integer)theYMax,
221 myView);
222
223 // Fill the results
224 return processPicked();
225}
226
227//================================================================
228// Function : Pick
229// Purpose :
230//================================================================
231bool IVtkOCC_ShapePickerAlgo::Pick (double** thePoly,
232 const int theNbPoints)
233{
234 clearPicked();
235
236 // Calling OCCT algortihm
237 myViewerSelector->Pick (thePoly, theNbPoints, myView);
238
239 // Fill the results
240 return processPicked();
241}
242
243//================================================================
244// Function : ShapesPicked
245// Purpose :
246//================================================================
247const IVtk_ShapeIdList& IVtkOCC_ShapePickerAlgo::ShapesPicked() const
248{
249 return myShapesPicked;
250}
251
252//================================================================
253// Function : SubShapesPicked
254// Purpose :
255//================================================================
256void IVtkOCC_ShapePickerAlgo::SubShapesPicked (const IVtk_IdType theId, IVtk_ShapeIdList& theShapeList) const
257{
258 if (mySubShapesPicked.IsBound (theId))
259 {
260 // Need non-const this to call the map's operator[]
261 IVtkOCC_ShapePickerAlgo* that = const_cast< IVtkOCC_ShapePickerAlgo* >(this);
262 theShapeList = that->mySubShapesPicked (theId);
263 }
264}
265
266//================================================================
267// Function : clearPicked
268// Purpose : Internal method, resets picked data
269//================================================================
270void IVtkOCC_ShapePickerAlgo::clearPicked()
271{
272 myShapesPicked.Clear();
273 mySubShapesPicked.Clear();
274}
275
276//================================================================
277// Function : NbPicked
278// Purpose : Get number of picked entities.
279//================================================================
280int IVtkOCC_ShapePickerAlgo::NbPicked()
281{
282 return myShapesPicked.Extent();
283}
284
285//================================================================
286// Function : processPicked
287// Purpose :
288//================================================================
289bool 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
c04c30b3 308 if (aSelectable.IsNull())
913a4c4a 309 {
310 anOutput << "Error: EntityOwner having null SelectableObject picked!";
311 continue;
312 }
313
314 Handle(IVtkOCC_Shape) aSelShape = aSelectable->GetShape();
c04c30b3 315 if (aSelShape.IsNull())
913a4c4a 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}