0030520: VIS - IVtkTools_ShapePicker::GetPickPosition() returns incorrect point
[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
92efcf78 24IMPLEMENT_STANDARD_RTTIEXT(IVtkOCC_ShapePickerAlgo,IVtk_IShapePickerAlgo)
25
913a4c4a 26// Handle implementation
ec357c5c 27
913a4c4a 28
29//================================================================
30// Function : Constructor
31// Purpose :
32//================================================================
33IVtkOCC_ShapePickerAlgo::IVtkOCC_ShapePickerAlgo() :
34myViewerSelector (new IVtkOCC_ViewerSelector())
35{ }
36
37//================================================================
38// Function : Destructor
39// Purpose :
40//================================================================
41IVtkOCC_ShapePickerAlgo::~IVtkOCC_ShapePickerAlgo()
42{ }
43
44//================================================================
45// Function : SetView
46// Purpose :
47//================================================================
48void IVtkOCC_ShapePickerAlgo::SetView (const IVtk_IView::Handle& theView)
49{
50 myView = theView;
913a4c4a 51}
52
53//================================================================
54// Function : GetSelectionModes
55// Purpose :
56//================================================================
57IVtk_SelectionModeList IVtkOCC_ShapePickerAlgo::GetSelectionModes (
58 const IVtk_IShape::Handle& theShape) const
59{
60 IVtk_SelectionModeList aRes;
61
c04c30b3 62 if (! theShape.IsNull())
913a4c4a 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//================================================================
91void IVtkOCC_ShapePickerAlgo::SetSelectionMode (const IVtk_IShape::Handle& theShape,
92 const IVtk_SelectionMode theMode,
93 const bool theIsTurnOn)
94{
c04c30b3 95 if (theShape.IsNull())
913a4c4a 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);
f751596e 126 myViewerSelector->AddSelectionToObject (aSelObj, aNewSelection);
913a4c4a 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.
f751596e 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);
913a4c4a 141 case SelectMgr_TOU_Partial:
142 {
143 if (aSelObj->HasTransformation())
144 {
f751596e 145 myViewerSelector->RebuildObjectsTree();
913a4c4a 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//================================================================
177void 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//================================================================
194bool 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//================================================================
211bool 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//================================================================
233bool 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//================================================================
249const IVtk_ShapeIdList& IVtkOCC_ShapePickerAlgo::ShapesPicked() const
250{
251 return myShapesPicked;
252}
253
254//================================================================
255// Function : SubShapesPicked
256// Purpose :
257//================================================================
258void IVtkOCC_ShapePickerAlgo::SubShapesPicked (const IVtk_IdType theId, IVtk_ShapeIdList& theShapeList) const
259{
260 if (mySubShapesPicked.IsBound (theId))
261 {
a2f76b15 262 theShapeList = mySubShapesPicked (theId);
913a4c4a 263 }
264}
265
266//================================================================
267// Function : clearPicked
268// Purpose : Internal method, resets picked data
269//================================================================
270void IVtkOCC_ShapePickerAlgo::clearPicked()
271{
1e756cb9 272 myTopPickedPoint.SetCoord (RealLast(), RealLast(), RealLast());
913a4c4a 273 myShapesPicked.Clear();
274 mySubShapesPicked.Clear();
275}
276
277//================================================================
278// Function : NbPicked
279// Purpose : Get number of picked entities.
280//================================================================
281int IVtkOCC_ShapePickerAlgo::NbPicked()
282{
283 return myShapesPicked.Extent();
284}
285
286//================================================================
287// Function : processPicked
288// Purpose :
289//================================================================
290bool IVtkOCC_ShapePickerAlgo::processPicked()
291{
292 Standard_Integer aNbPicked = myViewerSelector->NbPicked();
1e756cb9 293
913a4c4a 294 Handle(StdSelect_BRepOwner) anEntityOwner;
295 Handle(Message_Messenger) anOutput = Message::DefaultMessenger();
296
1e756cb9 297 bool isTop = true;
913a4c4a 298 for (Standard_Integer aDetectIt = 1; aDetectIt <= aNbPicked; aDetectIt++)
299 {
300 // ViewerSelector detects sensitive entities under the mouse
301 // and for each entity returns its entity owner.
302 // StdSelect_BRepOwner instance holds corresponding sub-shape (TopoDS_Shape)
303 // and in general entity owners have a pointer to SelectableObject that can tell us
304 // what is the top-level TopoDS_Shape.
305 anEntityOwner = Handle(StdSelect_BRepOwner)::DownCast (myViewerSelector->Picked (aDetectIt));
306 if (!anEntityOwner.IsNull())
307 {
308 Handle(IVtkOCC_SelectableObject) aSelectable =
309 Handle(IVtkOCC_SelectableObject)::DownCast (anEntityOwner->Selectable());
310
c04c30b3 311 if (aSelectable.IsNull())
913a4c4a 312 {
313 anOutput << "Error: EntityOwner having null SelectableObject picked!";
314 continue;
315 }
316
317 Handle(IVtkOCC_Shape) aSelShape = aSelectable->GetShape();
c04c30b3 318 if (aSelShape.IsNull())
913a4c4a 319 {
320 anOutput << "Error: SelectableObject with null OccShape pointer picked!";
321 continue;
322 }
323
324 IVtk_IdType aTopLevelId = aSelShape->GetId();
325 myShapesPicked.Append (aTopLevelId);
1e756cb9 326 if (isTop)
327 {
328 isTop = false;
329 myTopPickedPoint = myViewerSelector->PickedPoint (aDetectIt);
330 }
913a4c4a 331
332 // Now try to guess if it's the top-level shape itself or just a sub-shape picked
333 TopoDS_Shape aTopLevelShape = aSelShape->GetShape();
334 TopoDS_Shape aSubShape = anEntityOwner->Shape();
335 if (aTopLevelShape.IsNull())
336 {
337 anOutput << "Error: OccShape with null top-level TopoDS_Shape picked!";
338 continue;
339 }
340 if (aSubShape.IsNull())
341 {
342 anOutput << "Error: EntityOwner with null TopoDS_Shape picked!";
343 continue;
344 }
345
346 if (!aSubShape.IsSame (aTopLevelShape))
347 {
348 IVtk_IdType aSubId = aSelShape->GetSubShapeId (aSubShape);
349
350 if (!mySubShapesPicked.IsBound (aTopLevelId))
351 {
352 const IVtk_ShapeIdList aList;
353 mySubShapesPicked.Bind (aTopLevelId, aList);
354 }
355 // Order of selected sub-shapes
356 mySubShapesPicked (aTopLevelId).Append (aSubId);
357 }
358 }
359 }
360
361 return !myShapesPicked.IsEmpty();
362}
a2f76b15 363
364//============================================================================
365// Method: RemoveSelectableActor
366// Purpose: Remove selectable object from the picker (from internal maps).
367//============================================================================
368void IVtkOCC_ShapePickerAlgo::RemoveSelectableObject(const IVtk_IShape::Handle& theShape)
369{
370 clearPicked();
371 // Get shape implementation from shape interface.
372 Handle(IVtkOCC_Shape) aShapeImpl =
373 Handle(IVtkOCC_Shape)::DownCast(theShape);
374
375 // Get selectable object from the shape implementation.
376 Handle(IVtkOCC_SelectableObject) aSelObj =
377 Handle(IVtkOCC_SelectableObject)::DownCast(aShapeImpl->GetSelectableObject());
378
379 myViewerSelector->RemoveSelectableObject(aSelObj);
380 myViewerSelector->Clear();
381 aShapeImpl->SetSelectableObject(NULL);
382}