Salome HOME
51be247b74420fcacd6c7fbc45f787a47aa064c8
[modules/gui.git] / src / SVTK / SALOME_Actor.cxx
1 // Copyright (C) 2007-2023  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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, or (at your option) any later version.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SALOME OBJECT : implementation of interactive object visualization for OCC and VTK viewers
24 //  File   : SALOME_Actor.cxx
25 //  Author : Nicolas REJNERI
26
27 /*!
28   \class SALOME_Actor SALOME_Actor.h
29   \brief Abstract class of SALOME Objects in VTK.
30 */
31
32
33 #include "SALOME_Actor.h"
34 #include "SALOME_InteractiveObject.hxx"
35
36 #include "VTKViewer_Algorithm.h"
37 #include "VTKViewer_Transform.h"
38 #include "VTKViewer_TransformFilter.h"
39 #include "VTKViewer_GeometryFilter.h"
40 #include "VTKViewer_FramedTextActor.h"
41 #include "SVTK_AreaPicker.h"
42
43 #include "SVTK_Actor.h"
44
45 #include <SUIT_ResourceMgr.h>
46 #include <SUIT_Session.h>
47
48 // VTK Includes
49 #include <vtkCell.h>
50 #include <vtkLine.h>
51 #include <vtkQuadraticEdge.h>
52 #include <vtkPicker.h>
53 #include <vtkPointPicker.h>
54 #include <vtkCellPicker.h>
55 #include <vtkRenderer.h>
56 #include <vtkPolyData.h>
57 #include <vtkObjectFactory.h>
58 #include <vtkDataSetMapper.h>
59 #include <vtkPolyDataMapper.h>
60 #include <vtkProperty.h>
61 #include <vtkOutlineSource.h>
62 #include <vtkPolygon.h>
63
64 #include <vtkInteractorStyle.h>
65 #include <vtkRenderWindowInteractor.h>
66 #include <vtkPassThrough.h>
67
68 #include <TColStd_MapOfInteger.hxx>
69 #include <TColStd_IndexedMapOfInteger.hxx>
70
71 #include <math.h>
72 #include <QPoint>
73 #include <QVector>
74
75 #if defined __GNUC__
76   #if __GNUC__ == 2
77     #define __GNUC_2__
78   #endif
79 #endif
80
81 int SALOME_POINT_SIZE = 5;
82 int SALOME_LINE_WIDTH = 3;
83
84 namespace
85 {
86   int
87   GetEdgeAndNodesId(SALOME_Actor* theActor,
88                     vtkPicker* thePicker,
89                     vtkIdType theObjId,
90                     vtkIdType& theFirstNodeId,
91                     vtkIdType& theSecondNodeId)
92   {
93     int anEdgeId = 0;
94     if (vtkCell* aPickedCell = theActor->GetElemCell(theObjId)) {
95       double aPickPosition[3];
96       thePicker->GetPickPosition(aPickPosition);
97       double aMinDist = 1000000.0, aDist = 0;
98       vtkCell* aSelEdge;
99       for (int i = 0, iEnd = aPickedCell->GetNumberOfEdges(); i < iEnd; i++){
100         aSelEdge = aPickedCell->GetEdge(i);
101         if(vtkLine::SafeDownCast(aPickedCell->GetEdge(i)) || 
102            vtkQuadraticEdge::SafeDownCast(aPickedCell->GetEdge(i))){
103           int subId;  
104           double pcoords[3], closestPoint[3], weights[3];
105           aSelEdge->EvaluatePosition(aPickPosition,closestPoint,subId,pcoords,aDist,weights);
106           if (aDist < aMinDist) {
107             aMinDist = aDist;
108             anEdgeId = -1 - i;
109             theFirstNodeId = aSelEdge->GetPointId(0);
110             theSecondNodeId = aSelEdge->GetPointId(1);
111           }
112         }
113       }
114     }
115     return anEdgeId;
116   }
117
118   inline
119   bool
120   CheckDimensionId(Selection_Mode theMode, 
121                    SALOME_Actor *theActor, 
122                    vtkIdType theObjId)
123   {
124     switch(theMode) {
125     case CellSelection:
126       return true;
127     case EdgeSelection:
128       return ( theActor->GetObjDimension( theObjId ) == 1 );
129     case FaceSelection:
130       return ( theActor->GetObjDimension( theObjId ) == 2 );
131     case VolumeSelection:
132       return ( theActor->GetObjDimension( theObjId ) == 3 );
133     case Elem0DSelection:        
134       return ((theActor->GetObjDimension( theObjId ) == 0) &&
135                theActor->GetElemCell(theObjId) && 
136               (theActor->GetElemCell(theObjId)->GetCellType() == VTK_VERTEX));
137     case BallSelection:
138       return ((theActor->GetObjDimension( theObjId ) == 0) &&
139                theActor->GetElemCell(theObjId) && 
140               (theActor->GetElemCell(theObjId)->GetCellType() == VTK_POLY_VERTEX));
141
142     };
143     return false;
144   }
145 }
146
147 namespace SVTK
148 {
149   /*!
150     Make picker work with this actor only
151   */
152   TPickLimiter::TPickLimiter(vtkAbstractPicker* picker, SALOME_Actor* actor):myPicker(picker)
153   {
154     myPicker->InitializePickList();
155     myPicker->AddPickList( actor );
156     myPicker->SetPickFromList( true );
157   }
158   /*!
159     Unlimit picking
160   */
161   TPickLimiter::~TPickLimiter()
162   {
163     myPicker->SetPickFromList( false );
164     myPicker->InitializePickList();
165   }
166 }
167
168
169 vtkStandardNewMacro(SALOME_Actor)
170
171 /*!
172   Constructor
173 */
174 SALOME_Actor
175 ::SALOME_Actor():
176   myInteractor(NULL),
177   myRenderer(NULL),
178   mySelectionMode(ActorSelection),
179   myPreHighlightActor(SVTK_Actor::New()),
180   myHighlightActor(SVTK_Actor::New()),
181   myOutlineActor(VTKViewer_Actor::New()),
182   myOutline(vtkOutlineSource::New()),
183   myIsDisplayNameActor(false),
184   myNameActor(VTKViewer_FramedTextActor::New())
185 {
186   myPreHighlightActor->Delete();
187   myPreHighlightActor->Initialize();
188   myPreHighlightActor->PickableOff();
189   myPreHighlightActor->SetVisibility( false );
190   myPreHighlightActor->SetCoincident3DAllowed(true);
191
192   myHighlightActor->Delete();
193   myHighlightActor->Initialize();
194   myHighlightActor->PickableOff();
195   myHighlightActor->SetVisibility( false );
196   myHighlightActor->SetCoincident3DAllowed(true);
197
198   myOutline->Delete();
199
200   vtkPolyDataMapper* anOutlineMapper = vtkPolyDataMapper::New();
201   anOutlineMapper->SetInputConnection(myOutline->GetOutputPort());
202
203   myOutlineActor->Delete();
204   myOutlineActor->SetMapper( anOutlineMapper );
205   anOutlineMapper->Delete();
206
207   myOutlineActor->PickableOff();
208   myOutlineActor->DragableOff();
209   myOutlineActor->GetProperty()->SetColor(1.0,0.0,0.0);
210   myOutlineActor->GetProperty()->SetAmbient(1.0);
211   myOutlineActor->GetProperty()->SetDiffuse(0.0);
212   myOutlineActor->SetVisibility( false );
213
214   // Name actor
215   myNameActor->Delete();
216   myNameActor->SetVisibility(false);
217   myNameActor->SetPickable(false);
218   myNameActor->SetModePosition(VTKViewer_FramedTextActor::TopRight);
219   myNameActor->SetLayoutType(VTKViewer_FramedTextActor::Vertical);
220
221   SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
222
223   QColor aForegroundColor = aResourceMgr->colorValue( "VTKViewer", "group_names_text_color", Qt::white );
224   myNameActor->SetForegroundColor(aForegroundColor.redF(),
225                                   aForegroundColor.greenF(),
226                                   aForegroundColor.blueF());
227
228   double aGroupNamesTransparency = 0.5;
229   aGroupNamesTransparency = aResourceMgr->doubleValue( "VTKViewer", "group_names_transparency", aGroupNamesTransparency );
230   myNameActor->SetTransparency(aGroupNamesTransparency);
231 }
232
233 /*!
234   Destructor
235 */
236 SALOME_Actor
237 ::~SALOME_Actor()
238 {}
239
240
241 /*!
242   \return true if the SALOME_Actor has a reference to SALOME_InteractiveObject
243 */
244 Standard_Boolean 
245 SALOME_Actor
246 ::hasIO() 
247
248   return !myIO.IsNull(); 
249 }
250
251 /*!
252   \return correspoinding reference to SALOME_InteractiveObject
253 */
254 const Handle(SALOME_InteractiveObject)& 
255 SALOME_Actor
256 ::getIO()
257
258   return myIO; 
259 }
260
261 /*!
262   Sets reference to SALOME_InteractiveObject
263   \param theIO - new SALOME_InteractiveObject
264 */
265 void
266 SALOME_Actor
267 ::setIO(const Handle(SALOME_InteractiveObject)& theIO) 
268
269   myIO = theIO; 
270 }
271
272 /*!
273   Sets name the SALOME_Actor
274   \param theName - new name
275 */
276 void
277 SALOME_Actor
278 ::setName(const char* theName)
279 {
280   if(hasIO())   
281     myIO->setName(theName);
282   myNameActor->SetText(theName);
283   Superclass::setName(theName);
284 }
285
286
287 /*!
288   Publishes the actor in all its internal devices
289 */
290 void
291 SALOME_Actor
292 ::AddToRender(vtkRenderer* theRenderer)
293 {
294   Superclass::AddToRender(theRenderer);
295
296   myRenderer = theRenderer;
297
298   myHighlightActor->AddToRender(theRenderer);
299   myPreHighlightActor->AddToRender(theRenderer);
300   theRenderer->AddActor( myOutlineActor.GetPointer() );
301   theRenderer->AddActor( myNameActor.GetPointer() );
302 }
303
304 /*!
305   Removes the actor from all its internal devices
306 */
307 void 
308 SALOME_Actor
309 ::RemoveFromRender(vtkRenderer* theRenderer)
310 {
311   Superclass::RemoveFromRender(theRenderer);
312
313   myHighlightActor->RemoveFromRender(theRenderer);
314   myPreHighlightActor->RemoveFromRender(theRenderer);
315
316   theRenderer->RemoveActor( myPreHighlightActor.GetPointer() );
317   theRenderer->RemoveActor( myHighlightActor.GetPointer() );
318   theRenderer->RemoveActor( myOutlineActor.GetPointer() );
319   theRenderer->RemoveActor( myNameActor.GetPointer() );
320 }
321
322 /*!
323   \return reference on renderer where it is published
324 */
325 vtkRenderer*
326 SALOME_Actor
327 ::GetRenderer()
328 {
329   return myRenderer;
330 }
331
332 /*!
333   Sets interactor in order to use vtkInteractorObserver devices
334   \param theInteractor - new interactor
335 */
336 void
337 SALOME_Actor
338 ::SetInteractor(vtkRenderWindowInteractor* theInteractor)
339 {
340   myInteractor = theInteractor;
341 }
342
343 /*!
344   Put a request to redraw the view 
345 */
346 void
347 SALOME_Actor
348 ::Update()
349 {
350   myInteractor->CreateTimer(VTKI_TIMER_UPDATE);    
351 }
352
353 /*!
354   Apply view transformation
355   \param theTransform - transformation
356 */
357 void
358 SALOME_Actor
359 ::SetTransform(VTKViewer_Transform* theTransform)
360 {
361   Superclass::SetTransform(theTransform);
362
363   myPreHighlightActor->SetTransform(theTransform);
364   myHighlightActor->SetTransform(theTransform);
365   myOutlineActor->SetTransform(theTransform);
366 }
367
368 /*!
369   Apply additional position
370 */
371 void
372 SALOME_Actor
373 ::SetPosition(double _arg1, 
374               double _arg2, 
375               double _arg3)
376 {
377   Superclass::SetPosition(_arg1,_arg2,_arg3);
378
379   myPreHighlightActor->SetPosition(_arg1,_arg2,_arg3);
380   myHighlightActor->SetPosition(_arg1,_arg2,_arg3);
381   myOutlineActor->SetPosition(_arg1,_arg2,_arg3);
382 }
383
384 /*!
385   Apply additional position
386 */
387 void
388 SALOME_Actor
389 ::SetPosition(double _arg[3])
390 {
391   SetPosition(_arg[0],_arg[1],_arg[2]);
392 }
393
394 /*!
395   Shows/hides actor
396   \param theVisibility - new visibility state
397 */
398 void
399 SALOME_Actor
400 ::SetVisibility( int theVisibility )
401 {
402   Superclass::SetVisibility( theVisibility );
403
404   myOutlineActor->SetVisibility( theVisibility && isHighlighted() && !hasHighlight() );
405
406   myPreHighlightActor->SetVisibility( theVisibility && myIsPreselected );
407
408   if(mySelector.GetPointer() && hasIO()){
409     if(mySelector->SelectionMode() != ActorSelection){
410       int aHasIndex = mySelector->HasIndex( getIO() );
411       myHighlightActor->SetVisibility( theVisibility && isHighlighted() && aHasIndex);
412     }
413   }
414
415   UpdateNameActors();
416 }
417
418 /*!
419   Gets know whether the actor should be displayed or not
420 */
421 bool 
422 SALOME_Actor
423 ::ShouldBeDisplayed()
424 {
425   return true;
426 }
427
428 /*!
429   Set selector in order to the actor at any time can restore current selection
430   \param theSelector - new selector
431 */
432 void
433 SALOME_Actor
434 ::SetSelector(SVTK_Selector* theSelector)
435 {
436   mySelector = theSelector;
437 }
438   
439 /*!
440   To map current selection to VTK representation
441 */
442 void
443 SALOME_Actor
444 ::Highlight(bool theIsHighlight)
445 {
446   mySelectionMode = mySelector->SelectionMode();
447   myHighlightActor->SetVisibility( false );
448   myOutlineActor->SetVisibility( false );
449
450   if(mySelector.GetPointer()){
451     if(mySelectionMode != ActorSelection){
452       SVTK_TIndexedMapOfVtkId aMapIndex;
453       mySelector->GetIndex( getIO(), aMapIndex );
454       switch( mySelectionMode ) {
455       case NodeSelection:
456         myHighlightActor->GetProperty()->SetRepresentationToPoints();
457         myHighlightActor->MapPoints( this, aMapIndex );
458         break;
459       case CellSelection:
460       case EdgeSelection:
461       case FaceSelection:
462       case VolumeSelection:
463       case Elem0DSelection: 
464       case BallSelection: 
465         myHighlightActor->GetProperty()->SetRepresentationToSurface();
466         myHighlightActor->MapCells( this, aMapIndex );
467         break;
468       case EdgeOfCellSelection:
469         SVTK_IndexedMapOfVtkIds aMapCompositeIndex;
470         mySelector->GetCompositeIndex( getIO(), aMapCompositeIndex );
471         myHighlightActor->GetProperty()->SetRepresentationToWireframe();
472         myHighlightActor->MapEdge( this, aMapCompositeIndex );
473         break;
474       }
475       myHighlightActor->SetVisibility( GetVisibility() && theIsHighlight );
476     }
477     myHighlightActor->SetMarkerEnabled( mySelectionMode == NodeSelection );
478   }
479
480   highlight(theIsHighlight);
481 }
482
483 /*!
484   Updates visibility of the highlight devices  
485 */
486 void
487 SALOME_Actor
488 ::highlight(bool theIsHighlight)
489 {
490   double aBounds[6];
491   vtkDataSet * aDataSet = GetHighlightedDataSet();
492   aDataSet->GetBounds(aBounds);
493   myOutline->SetBounds(aBounds);
494   myOutline->Update();
495   myOutlineActor->SetVisibility( GetVisibility() && theIsHighlight );
496
497   Superclass::highlight(theIsHighlight);
498 }
499
500
501 /*!
502   To process prehighlight (called from SVTK_InteractorStyle)
503 */
504 bool
505 SALOME_Actor
506 ::PreHighlight(vtkInteractorStyle *theInteractorStyle, 
507                SVTK_SelectionEvent* theSelectionEvent,
508                bool theIsHighlight)
509 {
510   if ( !GetPickable() || !mySelector || !mySelector->IsPreSelectionEnabled() )
511     return false;
512       
513   vtkRenderer *aRenderer = theInteractorStyle->GetCurrentRenderer();
514   //
515   myPreHighlightActor->SetVisibility( false );
516   bool anIsPreselected = myIsPreselected;
517   SetPreSelected( false );
518
519   Selection_Mode aSelectionMode = theSelectionEvent->mySelectionMode;
520   bool anIsChanged = (mySelectionMode != aSelectionMode);
521
522   myPreHighlightActor->SetMarkerEnabled( aSelectionMode == NodeSelection );
523
524   double x = theSelectionEvent->myX;
525   double y = theSelectionEvent->myY;
526   double z = 0.0;
527
528   if( !theIsHighlight ) {
529     if ( hasIO() ) {
530       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
531       vtkActorCollection* theActors = aCopy.GetActors();
532       theActors->InitTraversal();
533       while( vtkActor *ac = theActors->GetNextActor() )
534         if( SALOME_Actor* anActor = SALOME_Actor::SafeDownCast( ac ) )
535           if( anActor->hasIO() && myIO->isSame( anActor->getIO() ) )
536             anActor->SetPreSelected( false );
537     }
538   }else{
539     switch(aSelectionMode) {
540     case NodeSelection: 
541     {
542       SVTK::TPickLimiter aPickLimiter( myPointPicker, this );
543       myPointPicker->Pick( x, y, z, aRenderer );
544       
545       vtkIdType aVtkId = myPointPicker->GetPointId();
546       if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId, true ) ) {
547         vtkIdType anObjId = GetNodeObjId( aVtkId );
548         myIsPreselected = (anObjId >= 0);
549         if(myIsPreselected){
550           const SVTK_TIndexedMapOfVtkId& aMapIndex = myPreHighlightActor->GetMapIndex();
551           vtkIdType anExtent = aMapIndex.Extent();
552           anIsChanged |= (anExtent == 0 || (anExtent > 0 && anObjId != aMapIndex(1)));
553           if(anIsChanged){
554             SVTK_TIndexedMapOfVtkId aMapIndex;
555             aMapIndex.Add( anObjId );
556             
557             myPreHighlightActor->GetProperty()->SetRepresentationToPoints();
558             myPreHighlightActor->MapPoints( this, aMapIndex );
559           }
560           myPreHighlightActor->SetVisibility( true );
561         }
562       }
563       break;
564     }
565     case CellSelection: 
566     case EdgeSelection:
567     case FaceSelection:
568     case VolumeSelection: 
569     case Elem0DSelection:        
570     case BallSelection: 
571     {
572       SVTK::TPickLimiter aPickLimiter( myCellPicker, this );
573       myCellPicker->Pick( x, y, z, aRenderer );
574       
575       vtkIdType aVtkId = myCellPicker->GetCellId();
576       if ( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) && hasIO() ) {
577         vtkIdType anObjId = GetElemObjId (aVtkId );
578         if ( anObjId >= 0 ) {
579           myIsPreselected = CheckDimensionId(aSelectionMode,this,anObjId);
580           if(myIsPreselected){
581             const SVTK_TIndexedMapOfVtkId& aMapIndex = myPreHighlightActor->GetMapIndex();
582             vtkIdType anExtent = aMapIndex.Extent();
583             anIsChanged |= (anExtent == 0 || (anExtent > 0 && anObjId != aMapIndex(1)));
584             if(anIsChanged){
585               SVTK_TIndexedMapOfVtkId aMapIndex;
586               aMapIndex.Add( anObjId );
587               
588               myPreHighlightActor->GetProperty()->SetRepresentationToSurface();
589               myPreHighlightActor->MapCells( this, aMapIndex );
590             }
591             myPreHighlightActor->SetVisibility( true );
592           }
593         }
594       }
595       break;
596     }
597     case EdgeOfCellSelection:
598     {
599       SVTK::TPickLimiter aPickLimiter( myCellPicker, this );
600       myCellPicker->Pick( x, y, z, aRenderer );
601       
602       vtkIdType aVtkId = myCellPicker->GetCellId();
603       if ( aVtkId >= 0 && mySelector->IsValid( this, aVtkId )) {
604         vtkIdType anObjId = GetElemObjId( aVtkId );
605         if ( anObjId >= 0 ) {
606           vtkIdType aFNId, aSNId;
607           int anEdgeId = GetEdgeAndNodesId(this,myCellPicker.GetPointer(),anObjId,aFNId,aSNId);
608           myIsPreselected = anEdgeId < 0;
609           if(myIsPreselected){
610             vtkIdType aFNObjId = GetNodeObjId( aFNId );
611             vtkIdType aSNObjId = GetNodeObjId( aSNId );
612             const SVTK_IndexedMapOfVtkIds& aMapIds = myPreHighlightActor->GetMapCompositeIndex();
613             vtkIdType anExtent = aMapIds.Extent();
614             anIsChanged |= (anExtent == 0 || (anExtent > 0 && aMapIds(1).size() == 2 && 
615                                              (aFNObjId != aMapIds(1)[0] || aSNObjId != aMapIds(1)[1] ) ) );
616             if( anIsChanged ) {
617               SVTK_IndexedMapOfVtkIds aMapIds;
618               SVTK_ListOfVtk aCompositeID;
619               aCompositeID.push_back( aFNObjId );
620               aCompositeID.push_back( aSNObjId );
621               aMapIds.Add( aCompositeID );
622               myPreHighlightActor->GetProperty()->SetRepresentationToWireframe();
623               myPreHighlightActor->MapEdge( this, aMapIds );
624             }
625             myPreHighlightActor->SetVisibility( true );
626           }
627         }
628       }
629       break;
630     }
631     case ActorSelection : 
632     {
633       if( !mySelector->IsSelected( myIO ) ) {
634         SetPreSelected( true );
635
636         if ( hasIO() ) {
637           VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
638           vtkActorCollection* theActors = aCopy.GetActors();
639           theActors->InitTraversal();
640           while( vtkActor *anAct = theActors->GetNextActor() ) {
641             if( anAct != this )
642               if( SALOME_Actor* anActor = SALOME_Actor::SafeDownCast( anAct ) )
643                 if( anActor->hasIO() && myIO->isSame( anActor->getIO() ) )
644                   anActor->SetPreSelected( true );
645           }
646         }
647       }
648     }
649     default:
650       break;
651     }
652   }
653
654   mySelectionMode = aSelectionMode;
655   anIsChanged |= (anIsPreselected != myIsPreselected);
656
657   return anIsChanged;
658 }
659
660 /*!
661   To process highlight (called from SVTK_InteractorStyle)
662 */
663 bool
664 SALOME_Actor
665 ::Highlight(vtkInteractorStyle *theInteractorStyle, 
666             SVTK_SelectionEvent* theSelectionEvent,
667             bool theIsHighlight)
668 {
669   if ( !GetPickable() || !mySelector /*|| !mySelector->IsSelectionEnabled()*/ )
670     return false;
671
672   myOutlineActor->SetVisibility( false );
673   myHighlightActor->SetVisibility( false );
674
675   vtkRenderer *aRenderer = theInteractorStyle->GetCurrentRenderer();
676   //
677   Selection_Mode aSelectionMode = theSelectionEvent->mySelectionMode;
678   bool anIsShift = theSelectionEvent->myIsShift;
679   if( !anIsShift || !theIsHighlight ) {
680     mySelector->RemoveIObject( this );
681   }
682
683   if ( !theIsHighlight )
684     return true;
685
686   if ( !mySelector->IsSelectionEnabled() )
687     return false;
688
689   double x = theSelectionEvent->myX;
690   double y = theSelectionEvent->myY;
691
692   if( theSelectionEvent->myIsRectangle || theSelectionEvent->myIsPolygon ) {
693     double xLast = theSelectionEvent->myLastX;
694     double yLast = theSelectionEvent->myLastY;
695
696     double x1 = x < xLast ? x : xLast;
697     double y1 = y < yLast ? y : yLast;
698     double x2 = x > xLast ? x : xLast;
699     double y2 = y > yLast ? y : yLast;
700
701     switch(aSelectionMode){
702     case NodeSelection: {
703
704       SVTK::TPickLimiter aPickLimiter( myPointAreaPicker, this );
705       if ( theSelectionEvent->myIsRectangle )
706         myPointAreaPicker->Pick( x1, y1, x2, y2, aRenderer, SVTK_AreaPicker::RectangleMode );
707       else if( theSelectionEvent->myIsPolygon )
708         myPointAreaPicker->Pick( theSelectionEvent->myPolygonPoints, aRenderer, SVTK_AreaPicker::PolygonMode );
709
710       const SVTK_AreaPicker::TVectorIdsMap& aVectorIdsMap = myPointAreaPicker->GetPointIdsMap();
711       SVTK_AreaPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
712       SVTK_TVtkIDsMap anIndexes;
713       if(aMapIter != aVectorIdsMap.end()){
714         const SVTK_AreaPicker::TVectorIds& aVectorIds = aMapIter->second;
715         vtkIdType anEnd = (int)aVectorIds.size(); //!< TODO: conversion from size_t to int
716         for(vtkIdType anId = 0; anId < anEnd; anId++ ) {
717           vtkIdType aPointId = aVectorIds[anId];
718           if( aPointId >= 0 && mySelector->IsValid( this, aPointId, true ) ) {
719             vtkIdType anObjId = GetNodeObjId( aPointId );
720             anIndexes.Add( anObjId );
721           }
722         }
723       }
724       
725       if ( hasIO() ) {
726         if( !anIndexes.IsEmpty() ) {
727           mySelector->AddOrRemoveIndex( myIO, anIndexes, anIsShift );
728           mySelector->AddIObject( this );
729           anIndexes.Clear();
730         }
731         else if ( !anIsShift )
732           mySelector->RemoveIObject( this );
733       }
734       break;
735     }
736     case ActorSelection :
737     {
738       double aPnt[3];
739       double* aBounds = GetBounds();
740
741       bool anIsPicked = true;
742       for( int i = 0; i <= 1; i++ ) {
743         for( int j = 2; j <= 3; j++ ) {
744           for( int k = 4; k <= 5; k++ ) {
745             aRenderer->SetWorldPoint( aBounds[ i ], aBounds[ j ], aBounds[ k ], 1.0 );
746             aRenderer->WorldToDisplay();
747             aRenderer->GetDisplayPoint( aPnt );
748             bool anIsPointInSelection = false;
749             if( theSelectionEvent->myIsRectangle )
750               anIsPointInSelection =  aPnt[0] > x1 && aPnt[0] < x2 && aPnt[1] > y1 && aPnt[1] < y2;
751             else if( theSelectionEvent->myIsPolygon )
752               anIsPointInSelection = myPointAreaPicker->isPointInPolygon( QPoint( aPnt[0], aPnt[1] ),
753                                                                           theSelectionEvent->myPolygonPoints );
754
755             if( !anIsPointInSelection ) {
756                 anIsPicked = false;
757                 break;
758             }
759           }
760         }
761       }
762
763       if ( hasIO() ) {
764         if( anIsPicked && mySelector->IsSelected( myIO ) && anIsShift )
765           mySelector->RemoveIObject( this );
766         else if ( anIsPicked ){
767           mySelector->AddIObject( this );
768         }
769       }
770
771       break;
772     }
773     case CellSelection: 
774     case EdgeSelection:
775     case FaceSelection:
776     case VolumeSelection: 
777     case Elem0DSelection:        
778     case BallSelection: 
779     {
780       SVTK::TPickLimiter aPickLimiter( myCellAreaPicker, this );
781       if( theSelectionEvent->myIsRectangle )
782         myCellAreaPicker->Pick( x1, y1, x2, y2, aRenderer, SVTK_AreaPicker::RectangleMode );
783       else if( theSelectionEvent->myIsPolygon )
784         myCellAreaPicker->Pick( theSelectionEvent->myPolygonPoints, aRenderer, SVTK_AreaPicker::PolygonMode );
785
786       const SVTK_AreaPicker::TVectorIdsMap& aVectorIdsMap = myCellAreaPicker->GetCellIdsMap();
787       SVTK_AreaPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
788       SVTK_TVtkIDsMap anIndexes;
789       if(aMapIter != aVectorIdsMap.end()){
790         const SVTK_AreaPicker::TVectorIds& aVectorIds = aMapIter->second;
791         vtkIdType anEnd = (int)aVectorIds.size(); //!< TODO: conversion from size_t to int
792         for(vtkIdType anId = 0; anId < anEnd; anId++ ) {
793           vtkIdType aCellId = aVectorIds[anId];
794           if ( !mySelector->IsValid( this, aCellId ) )
795             continue;
796
797           vtkIdType anObjId = GetElemObjId( aCellId );
798           if( anObjId != -1 )
799             if ( CheckDimensionId(aSelectionMode,this,anObjId) ) {
800               anIndexes.Add(anObjId);
801             }
802         }
803       }
804       
805       if ( hasIO() ) {
806         if( !anIndexes.IsEmpty() ) {
807           mySelector->AddOrRemoveIndex( myIO, anIndexes, anIsShift );
808           mySelector->AddIObject( this );
809           anIndexes.Clear();
810         }
811         else if ( !anIsShift )
812           mySelector->RemoveIObject( this );
813       }
814       break;
815     }
816     case EdgeOfCellSelection:
817     {
818       SVTK::TPickLimiter aPickLimiter( myCellAreaPicker, this );
819       if( theSelectionEvent->myIsRectangle )
820         myCellAreaPicker->Pick( x1, y1, x2, y2, aRenderer, SVTK_AreaPicker::RectangleMode );
821       else if( theSelectionEvent->myIsPolygon )
822         myCellAreaPicker->Pick( theSelectionEvent->myPolygonPoints, aRenderer, SVTK_AreaPicker::PolygonMode );
823
824       const SVTK_AreaPicker::TVectorIdsMap& aVectorIdsMap = myCellAreaPicker->GetCellIdsMap();
825       SVTK_AreaPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
826       SVTK_IndexedMapOfVtkIds anIndexes;
827       if(aMapIter != aVectorIdsMap.end()){
828         const SVTK_AreaPicker::TVectorIds& aVectorIds = aMapIter->second;
829         vtkIdType anEnd = (int)aVectorIds.size(); //!< TODO: conversion from size_t to int
830         for(vtkIdType anId = 0; anId < anEnd; anId++ ) {
831           vtkIdType aCellId = aVectorIds[anId];
832           if ( !mySelector->IsValid( this, aCellId ) )
833             continue;
834
835           vtkIdType anObjId = GetElemObjId( aCellId );
836           if( anObjId != -1 ) {
837             vtkIdType aFNId, aSNId;
838             int anEdgeId = GetEdgeAndNodesId(this,myCellPicker.GetPointer(),anObjId,aFNId,aSNId);
839             if( anEdgeId < 0 ) {
840               SVTK_ListOfVtk aCompositeID;
841               aCompositeID.push_back( GetNodeObjId( aFNId ) );
842               aCompositeID.push_back( GetNodeObjId( aSNId ) );
843               anIndexes.Add( aCompositeID );
844             }
845           }
846         }
847       }
848
849       if ( hasIO() ) {
850         if( !anIndexes.IsEmpty() ) {
851           mySelector->AddOrRemoveCompositeIndex( myIO, anIndexes, anIsShift );
852           mySelector->AddIObject( this );
853           anIndexes.Clear();
854         }
855         else if ( !anIsShift )
856           mySelector->RemoveIObject( this );
857       }
858     }
859     default:
860       break;
861     }
862   }
863   else {
864     switch(aSelectionMode){
865     case NodeSelection: {
866       SVTK::TPickLimiter aPickLimiter( myPointPicker, this );
867       myPointPicker->Pick( x, y, 0.0, aRenderer );
868
869       vtkIdType aVtkId = myPointPicker->GetPointId();
870       if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId, true ) ) {
871         vtkIdType anObjId = GetNodeObjId( aVtkId );
872         if( hasIO() && anObjId >= 0 ) {
873           mySelector->AddOrRemoveIndex( myIO, anObjId, anIsShift );
874           mySelector->AddIObject( this );
875         }
876       }
877       break;
878     }
879     case CellSelection:
880     case EdgeSelection:
881     case FaceSelection:
882     case VolumeSelection:
883     case Elem0DSelection:
884     case BallSelection:
885     {
886       SVTK::TPickLimiter aPickLimiter( myCellPicker, this );
887       myCellPicker->Pick( x, y, 0.0, aRenderer );
888
889       vtkIdType aVtkId = myCellPicker->GetCellId();
890       if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) ) {
891         vtkIdType anObjId = GetElemObjId( aVtkId );
892         if( anObjId >= 0 ) {
893           if ( hasIO() && CheckDimensionId(aSelectionMode,this,anObjId) ) {
894             mySelector->AddOrRemoveIndex( myIO, anObjId, anIsShift );
895             mySelector->AddIObject( this );
896           }
897         }
898       }
899       break;
900     }
901     case EdgeOfCellSelection:
902     {
903       SVTK::TPickLimiter aPickLimiter( myCellPicker, this );
904       myCellPicker->Pick( x, y, 0.0, aRenderer );
905
906       vtkIdType aVtkId = myCellPicker->GetCellId();
907       if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) ) {
908         vtkIdType anObjId = GetElemObjId( aVtkId );
909         if( anObjId >= 0 ) {
910           vtkIdType aFNId, aSNId;
911           int anEdgeId = GetEdgeAndNodesId(this,myCellPicker.GetPointer(),anObjId,aFNId,aSNId);
912           if( hasIO() && anEdgeId < 0 ) {
913             SVTK_ListOfVtk aCompositeID;
914             aCompositeID.push_back( GetNodeObjId( aFNId ) );
915             aCompositeID.push_back( GetNodeObjId( aSNId ) );
916             mySelector->AddOrRemoveCompositeIndex( myIO, aCompositeID, anIsShift );
917             mySelector->AddIObject( this );
918           }
919         }
920       }
921       break;
922     }
923     case ActorSelection :
924     {
925       if ( hasIO() ) {
926         if( mySelector->IsSelected( myIO ) && anIsShift )
927           mySelector->RemoveIObject( this );
928         else {
929           mySelector->AddIObject( this );
930         }
931       }
932       break;
933     }
934     default:
935       break;
936     }
937   }
938
939   mySelectionMode = aSelectionMode;
940
941   return true;
942 }
943
944 /*!
945   To get flag of displaying of name actor
946   \return flag to display or not to display name actor
947 */
948 bool
949 SALOME_Actor
950 ::IsDisplayNameActor() const
951 {
952   return myIsDisplayNameActor;
953 }
954
955 /*!
956   To set flag of displaying of name actor
957   \param theIsDisplayNameActor flag to display or not to display name actor
958 */
959 void
960 SALOME_Actor
961 ::SetIsDisplayNameActor(bool theIsDisplayNameActor)
962 {
963   SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
964   bool isShowGroupNames = aResourceMgr->booleanValue("VTKViewer", "show_group_names", false);
965   myIsDisplayNameActor = theIsDisplayNameActor && isShowGroupNames;
966   UpdateNameActors();
967 }
968
969 /*!
970   To set text of name actor
971   \param theText - text of name actor
972 */
973 void
974 SALOME_Actor
975 ::SetNameActorText(const char* theText)
976 {
977   myNameActor->SetText(theText);
978 }
979
980 /*!
981   To set offset of name actor
982   \param theOffset - offset of name actor
983 */
984 void
985 SALOME_Actor
986 ::SetNameActorOffset(double theOffset[2])
987 {
988   myNameActor->SetOffset(theOffset);
989 }
990
991 /*!
992   To get size of name actor
993   \param theRenderer - renderer
994   \param theSize - size of name actor
995 */
996 void
997 SALOME_Actor
998 ::GetNameActorSize(vtkRenderer* theRenderer, double theSize[2]) const
999 {
1000   myNameActor->GetSize(theRenderer, theSize);
1001 }
1002
1003 /*!
1004   Update visibility of name actors
1005 */
1006 void
1007 SALOME_Actor
1008 ::UpdateNameActors()
1009 {
1010   if( vtkRenderer* aRenderer = GetRenderer() )
1011   {
1012     double anOffset[2] = { 0, 0 };
1013     VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
1014     vtkActorCollection* aCollection = aCopy.GetActors();
1015     for( int anIndex = 0, aNbItems = aCollection->GetNumberOfItems(); anIndex < aNbItems; anIndex++ )
1016     {
1017       if( SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>( aCollection->GetItemAsObject( anIndex ) ) )
1018       {
1019         if( anActor->IsDisplayNameActor() )
1020         {
1021           anActor->SetNameActorOffset( anOffset );
1022           if( anActor->GetVisibility() )
1023           {
1024             double aSize[2];
1025             anActor->GetNameActorSize( aRenderer, aSize );
1026             anOffset[0] = anOffset[0] + aSize[0];
1027             anOffset[1] = anOffset[1] + aSize[1];
1028           }
1029         }
1030       }
1031     }
1032   }
1033   myNameActor->SetVisibility( GetVisibility() && IsDisplayNameActor() );
1034 }
1035
1036 /*!
1037   To set up a picker for nodal selection (initialized by SVTK_Renderer::AddActor)
1038   \param thePointPicker - new picker
1039 */
1040 void
1041 SALOME_Actor
1042 ::SetPointPicker(vtkPointPicker* thePointPicker) 
1043 {
1044   myPointPicker = thePointPicker;
1045 }
1046
1047 /*!
1048   To set up a picker for cell selection (initialized by SVTK_Renderer::AddActor)
1049   \param theCellPicker - new picker
1050 */
1051 void
1052 SALOME_Actor
1053 ::SetCellPicker(vtkCellPicker* theCellPicker) 
1054 {
1055   myCellPicker = theCellPicker;
1056 }
1057
1058 /*!
1059   To set up a picker for point rectangle or polygonal selection (initialized by SVTK_Renderer::AddActor)
1060   \param theAreaPicker - new picker
1061 */
1062 void
1063 SALOME_Actor
1064 ::SetPointAreaPicker(SVTK_AreaPicker* theAreaPicker)
1065 {
1066   myPointAreaPicker = theAreaPicker;
1067 }
1068
1069 /*!
1070   To set up a picker for cell rectangle of polygonal selection (initialized by SVTK_Renderer::AddActor)
1071   \param theAreaPicker - new picker
1072 */
1073 void
1074 SALOME_Actor
1075 ::SetCellAreaPicker(SVTK_AreaPicker* theAreaPicker)
1076 {
1077   myCellAreaPicker = theAreaPicker;
1078 }
1079
1080 /*!
1081   To find a gravity center of object
1082   \param theObjId - identification of object
1083 */
1084 double*
1085 SALOME_Actor
1086 ::GetGravityCenter( int theObjId )
1087 {
1088   double* result = new double[3];
1089   for( int i = 0; i < 3; i++ )
1090     result[i]= 0.0;
1091
1092   vtkPoints* points = GetElemCell( theObjId )->GetPoints();
1093   int nbPoints = points->GetNumberOfPoints();
1094
1095   if( nbPoints <= 0 )
1096     return NULL;
1097
1098   for( int i = 0; i < nbPoints; i++ )
1099   {
1100     double* aPoint = points->GetPoint(i);
1101     result[0] += aPoint[0];
1102     result[1] += aPoint[1];
1103     result[2] += aPoint[2];
1104   }
1105   result[0] = result[0] / nbPoints;
1106   result[1] = result[1] / nbPoints;
1107   result[2] = result[2] / nbPoints;
1108
1109   return result;
1110 }
1111
1112 /*!
1113   To set up a prehighlight property (initialized by SVTK_Renderer::AddActor)
1114 */
1115 void
1116 SALOME_Actor
1117 ::SetPreHighlightProperty(vtkProperty* theProperty) 
1118 {
1119   myPreHighlightActor->SetProperty(theProperty);
1120 }
1121
1122 /*!
1123   To set up a highlight property (initialized by SVTK_Renderer::AddActor)
1124 */
1125 void
1126 SALOME_Actor
1127 ::SetHighlightProperty(vtkProperty* theProperty) 
1128 {
1129   myHighlightActor->SetProperty(theProperty);
1130 }
1131
1132 /*!
1133   Set standard point marker
1134   \param theMarkerType type of the marker
1135   \param theMarkerScale scale of the marker
1136 */
1137 void
1138 SALOME_Actor
1139 ::SetMarkerStd( VTK::MarkerType theMarkerType, VTK::MarkerScale theMarkerScale )
1140 {
1141   myPreHighlightActor->SetMarkerStd( theMarkerType, theMarkerScale );
1142   myHighlightActor->SetMarkerStd( theMarkerType, theMarkerScale );
1143 }
1144
1145 /*!
1146   Set custom point marker
1147   \param theMarkerId id of the marker texture
1148   \param theMarkerTexture marker texture
1149 */
1150 void
1151 SALOME_Actor
1152 ::SetMarkerTexture( int theMarkerId, VTK::MarkerTexture theMarkerTexture )
1153 {
1154   myPreHighlightActor->SetMarkerTexture( theMarkerId, theMarkerTexture );
1155   myHighlightActor->SetMarkerTexture( theMarkerId, theMarkerTexture );
1156 }
1157
1158 /*!
1159   Get type of the point marker
1160   \return type of the point marker
1161 */
1162 VTK::MarkerType
1163 SALOME_Actor
1164 ::GetMarkerType()
1165 {
1166   return myPreHighlightActor->GetMarkerType();
1167 }
1168
1169 /*!
1170   Get scale of the point marker
1171   \return scale of the point marker
1172 */
1173 VTK::MarkerScale
1174 SALOME_Actor
1175 ::GetMarkerScale()
1176 {
1177   return myPreHighlightActor->GetMarkerScale();
1178 }
1179
1180 /*!
1181   Get texture identifier of the point marker
1182   \return texture identifier of the point marker
1183  */
1184 int
1185 SALOME_Actor
1186 ::GetMarkerTexture()
1187 {
1188   return myPreHighlightActor->GetMarkerTexture();
1189 }