1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // SALOME SALOMEGUI : implementation of desktop and GUI kernel
23 // File : SALOME_Selection.cxx
24 // Author : Nicolas REJNERI
28 #include "SVTK_SelectorDef.h"
30 #include <VTKViewer_Filter.h>
32 #include "SALOME_Actor.h"
34 #include <SUIT_Session.h>
35 #include <SUIT_ResourceMgr.h>
37 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
38 #include <TColStd_IndexedMapOfInteger.hxx>
40 #include <vtkCallbackCommand.h>
41 #include <vtkActorCollection.h>
42 #include <vtkCellPicker.h>
46 Find first SALOME_Actor from the end of actors collection
50 GetLastSALOMEActor(vtkActorCollection* theCollection)
53 for (int i = theCollection->GetNumberOfItems() - 1; i >= 0; i--) {
54 if (SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(theCollection->GetItemAsObject(i)))
64 \return new SVTK_Selector
70 return new SVTK_SelectorDef();
78 myPicker(vtkPicker::New()),
79 myCellPicker(vtkCellPicker::New())
81 mySelectionMode = ActorSelection;
84 myCellPicker->Delete();
96 To invoke selectionChanged signals
100 ::StartPickCallback()
102 this->InvokeEvent(vtkCommand::StartPickEvent,NULL);
106 To invoke selectionChanged signals
112 this->InvokeEvent(vtkCommand::EndPickEvent,NULL);
116 To change current Selection_Mode (as outside effect, it invokes selectionChange signal)
120 ::SetSelectionMode(Selection_Mode theMode)
122 if(mySelectionMode != theMode){
123 mySelectionMode = theMode;
124 myMapIOSubIndex.clear();
125 this->EndPickCallback();
138 myMapIOSubIndex.clear();
142 \return true if the SALOME_InteractiveObject presents into selection
146 ::IsSelected(const Handle(SALOME_InteractiveObject)& theIO) const
148 return !theIO.IsNull() && (myIObjects.find(theIO) != myIObjects.end());
152 \return true if the SALOME_Actor presents into selection
156 ::IsSelected(SALOME_Actor* theActor) const
158 const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
159 return IsSelected(anIO) && myIO2Actors.find(anIO) != myIO2Actors.end();
163 \return corresponding SALOME_Actor for SALOME_InteractiveObject
164 \param theIO - SALOME_InteractiveObject
168 ::GetActor(const Handle(SALOME_InteractiveObject)& theIO) const
170 TIO2Actors::const_iterator anIter = myIO2Actors.find(theIO);
171 if(anIter != myIO2Actors.end())
172 return anIter->second.GetPointer();
177 Adds SALOME_InteractiveObject into selection
178 \param theIO - SALOME_InteractiveObject
182 ::AddIObject(const Handle(SALOME_InteractiveObject)& theIO)
184 if(!IsSelected(theIO)){
185 myIObjects.insert(theIO);
192 Adds SALOME_Actor into selection
193 \param theActor - SALOME_Actor
197 ::AddIObject(SALOME_Actor* theActor)
199 const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
201 bool anIsIOBound = IsSelected(anIO);
203 myIObjects.insert(anIO);
205 bool anIsActorBound = myIO2Actors.find(anIO) != myIO2Actors.end();
207 myIO2Actors[anIO] = theActor;
209 return !anIsIOBound || !anIsActorBound;
213 Removes SALOME_InteractiveObject from selection
214 \param theIO - SALOME_InteractiveObject
218 ::RemoveIObject(const Handle(SALOME_InteractiveObject)& theIO)
220 bool anIsIOBound = myIObjects.find(theIO) != myIObjects.end();
222 myIObjects.erase(theIO);
223 myIO2Actors.erase(theIO);
224 myMapIOSubIndex.erase(theIO);
230 Removes SALOME_Actor from selection
231 \param theActor - SALOME_Actor
235 ::RemoveIObject(SALOME_Actor* theActor)
237 const Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
239 bool anIsActorBound = myIO2Actors.find(anIO) != myIO2Actors.end();
241 myIO2Actors.erase(anIO);
243 return RemoveIObject(anIO) || anIsActorBound;
247 \return list of all SALOME_InteractiveObject presenting in selection
251 ::StoredIObjects() const
253 myIObjectList.Clear();
254 TIObjects::const_iterator anIter = myIObjects.begin();
255 TIObjects::const_iterator anIterEnd = myIObjects.end();
256 for(; anIter != anIterEnd; anIter++)
257 myIObjectList.Append(*anIter);
259 return myIObjectList;
263 \return number of selected objects
267 ::IObjectCount() const
269 return myIObjects.size();
273 \return true if the SALOME_InteractiveObject has a subselection
274 \param theIO - SALOME_InteractiveObject
278 ::HasIndex( const Handle(SALOME_InteractiveObject)& theIO) const
280 return myMapIOSubIndex.find(theIO) != myMapIOSubIndex.end();
284 Gets indices of subselection for SALOME_InteractiveObject
285 \param theIO - SALOME_InteractiveObject
289 ::GetIndex( const Handle(SALOME_InteractiveObject)& theIO,
290 TColStd_IndexedMapOfInteger& theIndex)
292 TMapIOSubIndex::const_iterator anIter = myMapIOSubIndex.find(theIO);
293 if(anIter != myMapIOSubIndex.end())
294 theIndex = anIter->second.myMap;
300 \return true if the index presents in subselection
301 \param theIO - SALOME_InteractiveObject
302 \param theIndex - index
306 ::IsIndexSelected(const Handle(SALOME_InteractiveObject)& theIO,
309 TMapIOSubIndex::const_iterator anIter = myMapIOSubIndex.find(theIO);
310 if(anIter != myMapIOSubIndex.end()){
311 const TColStd_IndexedMapOfInteger& aMapIndex = anIter->second.myMap;
312 return aMapIndex.Contains( theIndex ) == Standard_True;
318 static bool removeIndex(TColStd_IndexedMapOfInteger& theMapIndex, const int theIndex)
320 int anId = theMapIndex.FindIndex(theIndex); // i==0 if Index is not in the MapIndex
322 // only the last key can be removed
323 int aLastId = theMapIndex.FindKey(theMapIndex.Extent());
325 theMapIndex.RemoveLast();
327 TColStd_IndexedMapOfInteger aNewMap;
328 aNewMap.ReSize(theMapIndex.Extent()-1);
329 for(int j = 1; j <= theMapIndex.Extent(); j++){
330 int anIndex = theMapIndex(j);
331 if ( anIndex != theIndex )
332 aNewMap.Add( anIndex );
334 theMapIndex = aNewMap;
341 Changes indices of subselection for SALOME_InteractiveObject
342 \param theIO - SALOME_InteractiveObject
343 \param theIndices - indices
344 \param theIsModeShift - if it is false, then map will be cleared before indices are added
348 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
349 const TColStd_IndexedMapOfInteger& theIndices,
352 TMapIOSubIndex::iterator aMapIter = myMapIOSubIndex.find(theIO);
353 if(aMapIter == myMapIOSubIndex.end()){
354 TIndexedMapOfInteger anEmpty;
355 aMapIter = myMapIOSubIndex.
356 insert(TMapIOSubIndex::value_type(theIO,anEmpty)).first;
358 TColStd_IndexedMapOfInteger& aMapIndex = aMapIter->second.myMap;
363 for(int i = 1, iEnd = theIndices.Extent(); i <= iEnd; i++)
364 aMapIndex.Add(theIndices(i));
366 if(aMapIndex.IsEmpty()) {
367 myMapIOSubIndex.erase(theIO);
376 Changes indices of subselection for SALOME_InteractiveObject
377 \param theIO - SALOME_InteractiveObject
378 \param theIndices - indices
379 \param theIsModeShift - if it is false, then map will be cleared before indices are added
383 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
384 const TColStd_MapOfInteger& theIndices,
387 TMapIOSubIndex::iterator aMapIter = myMapIOSubIndex.find(theIO);
388 if(aMapIter == myMapIOSubIndex.end()){
389 TIndexedMapOfInteger anEmpty;
390 aMapIter = myMapIOSubIndex.
391 insert(TMapIOSubIndex::value_type(theIO,anEmpty)).first;
393 TColStd_IndexedMapOfInteger& aMapIndex = aMapIter->second.myMap;
398 TColStd_MapIteratorOfMapOfInteger anIter(theIndices);
399 for(; anIter.More(); anIter.Next())
400 aMapIndex.Add(anIter.Key());
402 if(aMapIndex.IsEmpty()) {
403 myMapIOSubIndex.erase(theIO);
412 Changes indices of subselection for SALOME_InteractiveObject
413 \param theIO - SALOME_InteractiveObject
414 \param theIndex - index
415 \param theIsModeShift - if it is false, then map will be cleared before indices are added
419 ::AddOrRemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
423 TMapIOSubIndex::iterator anIter = myMapIOSubIndex.find(theIO);
424 if(anIter == myMapIOSubIndex.end()){
425 TIndexedMapOfInteger anEmpty;
426 anIter = myMapIOSubIndex.
427 insert(TMapIOSubIndex::value_type(theIO,anEmpty)).first;
429 TColStd_IndexedMapOfInteger& aMapIndex = anIter->second.myMap;
431 bool anIsConatains = aMapIndex.Contains( theIndex ) == Standard_True;
433 removeIndex( aMapIndex, theIndex );
435 if ( !theIsModeShift )
438 if ( !anIsConatains )
439 aMapIndex.Add( theIndex );
441 if ( aMapIndex.IsEmpty() )
442 myMapIOSubIndex.erase( theIO );
449 Removes index of subselection for SALOME_InteractiveObject
450 \param theIO - SALOME_InteractiveObject
451 \param theIndex - index
455 ::RemoveIndex( const Handle(SALOME_InteractiveObject)& theIO,
458 if(IsIndexSelected(theIO,theIndex)){
459 TMapIOSubIndex::iterator anIter = myMapIOSubIndex.find(theIO);
460 TColStd_IndexedMapOfInteger& aMapIndex = anIter->second.myMap;
461 removeIndex(aMapIndex,theIndex);
466 Clears all indices of subselection
472 myMapIOSubIndex.clear();
476 To apply a filter on the selection
477 \param theFilter - new filter
481 ::SetFilter(const Handle(VTKViewer_Filter)& theFilter)
483 myFilters.insert(TFilters::value_type(theFilter->GetId(),theFilter));
487 \return true if filter with given number is applyed
488 \param theId - filter id
492 ::IsFilterPresent(const TFilterID theId) const
494 return myFilters.find(theId) != myFilters.end();
498 To remove a filter from the selection
499 \param theId - filter id
503 ::RemoveFilter(const TFilterID theId)
505 if(IsFilterPresent(theId))
506 myFilters.erase(theId);
510 \return true if the index satisfy installed filters
511 \param theActor - actor
512 \param theId - filter id
513 \param theIsNode - whether it is node
517 ::IsValid(SALOME_Actor* theActor,
518 const TFilterID theId,
519 const bool theIsNode) const
521 TFilters::const_iterator anIter = myFilters.begin();
522 for(; anIter != myFilters.end(); ++anIter){
523 const Handle(VTKViewer_Filter)& aFilter = anIter->second;
524 if(theIsNode == aFilter->IsNodeFilter() &&
525 !aFilter->IsValid(theActor,theId))
532 \return filter by it's id
533 \param theId - filter id
535 Handle(VTKViewer_Filter)
537 ::GetFilter(const TFilterID theId) const
539 TFilters::const_iterator anIter = myFilters.find(theId);
540 if(anIter != myFilters.end()){
541 const Handle(VTKViewer_Filter)& aFilter = anIter->second;
544 return Handle(VTKViewer_Filter)();
549 ::Pick(const SVTK_SelectionEvent* theEvent, vtkRenderer* theRenderer) const
551 bool anAdvancedSelectionAlgorithm = true;
552 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
554 anAdvancedSelectionAlgorithm = aResourceMgr->booleanValue( "VTKViewer", "use_advanced_selection_algorithm", true );
556 SALOME_Actor* anActor = NULL;
557 vtkActorCollection* aListActors = NULL;
558 if ( anAdvancedSelectionAlgorithm ) {
559 myCellPicker->Pick(theEvent->myX,
564 aListActors = myCellPicker->GetActors();
565 anActor = GetLastSALOMEActor(aListActors);
569 myPicker->Pick(theEvent->myX,
573 aListActors = myPicker->GetActors();
574 anActor = GetLastSALOMEActor(aListActors);
582 ::SetTolerance(const double& theTolerance)
584 myPicker->SetTolerance(theTolerance);
585 myCellPicker->SetTolerance(theTolerance);