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