Salome HOME
Merge ASERIS development.
[modules/gui.git] / src / SVTK / SALOME_Actor.cxx
1 // Copyright (C) 2007-2016  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 <vtkPassThroughFilter.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                     int theObjId,
90                     int& theFirstNodeId,
91                     int& 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   myRenderer(NULL),
177   myInteractor(NULL),
178   mySelectionMode(ActorSelection),
179   myPreHighlightActor(SVTK_Actor::New()),
180   myHighlightActor(SVTK_Actor::New()),
181   myOutline(vtkOutlineSource::New()),
182   myOutlineActor(VTKViewer_Actor::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       TColStd_IndexedMapOfInteger 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_IndexedMapOfIds 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       int aVtkId = myPointPicker->GetPointId();
546       if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId, true ) ) {
547         int anObjId = GetNodeObjId( aVtkId );
548         myIsPreselected = (anObjId >= 0);
549         if(myIsPreselected){
550           const TColStd_IndexedMapOfInteger& aMapIndex = myPreHighlightActor->GetMapIndex();
551           int anExtent = aMapIndex.Extent();
552           anIsChanged |= (anExtent == 0 || (anExtent > 0 && anObjId != aMapIndex(1)));
553           if(anIsChanged){
554             TColStd_IndexedMapOfInteger 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       int aVtkId = myCellPicker->GetCellId();
576       if ( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) && hasIO() ) {
577         int anObjId = GetElemObjId (aVtkId );
578         if ( anObjId >= 0 ) {
579           myIsPreselected = CheckDimensionId(aSelectionMode,this,anObjId);
580           if(myIsPreselected){
581             const TColStd_IndexedMapOfInteger& aMapIndex = myPreHighlightActor->GetMapIndex();
582             int anExtent = aMapIndex.Extent();
583             anIsChanged |= (anExtent == 0 || (anExtent > 0 && anObjId != aMapIndex(1)));
584             if(anIsChanged){
585               TColStd_IndexedMapOfInteger 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       int aVtkId = myCellPicker->GetCellId();
603       if ( aVtkId >= 0 && mySelector->IsValid( this, aVtkId )) {
604         int anObjId = GetElemObjId( aVtkId );
605         if ( anObjId >= 0 ) {
606           int aFNId, aSNId;
607           int anEdgeId = GetEdgeAndNodesId(this,myCellPicker.GetPointer(),anObjId,aFNId,aSNId);
608           myIsPreselected = anEdgeId < 0;
609           if(myIsPreselected){
610             int aFNObjId = GetNodeObjId( aFNId );
611             int aSNObjId = GetNodeObjId( aSNId );
612             const SVTK_IndexedMapOfIds& aMapIds = myPreHighlightActor->GetMapCompositeIndex();
613             int 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_IndexedMapOfIds aMapIds;
618               SVTK_ListOfInteger 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   double x = theSelectionEvent->myX;
687   double y = theSelectionEvent->myY;
688
689   if( theSelectionEvent->myIsRectangle || theSelectionEvent->myIsPolygon ) {
690     double xLast = theSelectionEvent->myLastX;
691     double yLast = theSelectionEvent->myLastY;
692
693     double x1 = x < xLast ? x : xLast;
694     double y1 = y < yLast ? y : yLast;
695     double x2 = x > xLast ? x : xLast;
696     double y2 = y > yLast ? y : yLast;
697
698     switch(aSelectionMode){
699     case NodeSelection: {
700
701       SVTK::TPickLimiter aPickLimiter( myPointAreaPicker, this );
702       if ( theSelectionEvent->myIsRectangle )
703         myPointAreaPicker->Pick( x1, y1, x2, y2, aRenderer, SVTK_AreaPicker::RectangleMode );
704       else if( theSelectionEvent->myIsPolygon )
705         myPointAreaPicker->Pick( theSelectionEvent->myPolygonPoints, aRenderer, SVTK_AreaPicker::PolygonMode );
706
707       const SVTK_AreaPicker::TVectorIdsMap& aVectorIdsMap = myPointAreaPicker->GetPointIdsMap();
708       SVTK_AreaPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
709       TColStd_MapOfInteger anIndexes;
710       if(aMapIter != aVectorIdsMap.end()){
711         const SVTK_AreaPicker::TVectorIds& aVectorIds = aMapIter->second;
712         vtkIdType anEnd = aVectorIds.size();
713         for(vtkIdType anId = 0; anId < anEnd; anId++ ) {
714           int aPointId = aVectorIds[anId];
715           if( aPointId >= 0 && mySelector->IsValid( this, aPointId, true ) ) {
716             int anObjId = GetNodeObjId( aPointId );
717             anIndexes.Add( anObjId );
718           }
719         }
720       }
721       
722       if ( hasIO() ) {
723         if( !anIndexes.IsEmpty() ) {
724           mySelector->AddOrRemoveIndex( myIO, anIndexes, anIsShift );
725           mySelector->AddIObject( this );
726           anIndexes.Clear();
727         }
728         else if ( !anIsShift )
729           mySelector->RemoveIObject( this );
730       }
731       break;
732     }
733     case ActorSelection :
734     {
735       double aPnt[3];
736       double* aBounds = GetBounds();
737
738       bool anIsPicked = true;
739       for( int i = 0; i <= 1; i++ ) {
740         for( int j = 2; j <= 3; j++ ) {
741           for( int k = 4; k <= 5; k++ ) {
742             aRenderer->SetWorldPoint( aBounds[ i ], aBounds[ j ], aBounds[ k ], 1.0 );
743             aRenderer->WorldToDisplay();
744             aRenderer->GetDisplayPoint( aPnt );
745             bool anIsPointInSelection;
746             if( theSelectionEvent->myIsRectangle )
747               anIsPointInSelection =  aPnt[0] > x1 && aPnt[0] < x2 && aPnt[1] > y1 && aPnt[1] < y2;
748             else if( theSelectionEvent->myIsPolygon )
749               anIsPointInSelection = myPointAreaPicker->isPointInPolygon( QPoint( aPnt[0], aPnt[1] ),
750                                                                           theSelectionEvent->myPolygonPoints );
751
752             if( !anIsPointInSelection ) {
753                 anIsPicked = false;
754                 break;
755             }
756           }
757         }
758       }
759
760       if ( hasIO() ) {
761         if( anIsPicked && mySelector->IsSelected( myIO ) && anIsShift )
762           mySelector->RemoveIObject( this );
763         else if ( anIsPicked ){
764           mySelector->AddIObject( this );
765         }
766       }
767
768       break;
769     }
770     case CellSelection: 
771     case EdgeSelection:
772     case FaceSelection:
773     case VolumeSelection: 
774     case Elem0DSelection:        
775     case BallSelection: 
776     {
777       SVTK::TPickLimiter aPickLimiter( myCellAreaPicker, this );
778       if( theSelectionEvent->myIsRectangle )
779         myCellAreaPicker->Pick( x1, y1, x2, y2, aRenderer, SVTK_AreaPicker::RectangleMode );
780       else if( theSelectionEvent->myIsPolygon )
781         myCellAreaPicker->Pick( theSelectionEvent->myPolygonPoints, aRenderer, SVTK_AreaPicker::PolygonMode );
782
783       const SVTK_AreaPicker::TVectorIdsMap& aVectorIdsMap = myCellAreaPicker->GetCellIdsMap();
784       SVTK_AreaPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
785       TColStd_MapOfInteger anIndexes;
786       if(aMapIter != aVectorIdsMap.end()){
787         const SVTK_AreaPicker::TVectorIds& aVectorIds = aMapIter->second;
788         vtkIdType anEnd = aVectorIds.size();
789         for(vtkIdType anId = 0; anId < anEnd; anId++ ) {
790           int aCellId = aVectorIds[anId];
791           if ( !mySelector->IsValid( this, aCellId ) )
792             continue;
793
794           int anObjId = GetElemObjId( aCellId );
795           if( anObjId != -1 )
796             if ( CheckDimensionId(aSelectionMode,this,anObjId) ) {
797               anIndexes.Add(anObjId);
798             }
799         }
800       }
801       
802       if ( hasIO() ) {
803         if( !anIndexes.IsEmpty() ) {
804           mySelector->AddOrRemoveIndex( myIO, anIndexes, anIsShift );
805           mySelector->AddIObject( this );
806           anIndexes.Clear();
807         }
808         else if ( !anIsShift )
809           mySelector->RemoveIObject( this );
810       }
811       break;
812     }
813     case EdgeOfCellSelection:
814     {
815       SVTK::TPickLimiter aPickLimiter( myCellAreaPicker, this );
816       if( theSelectionEvent->myIsRectangle )
817         myCellAreaPicker->Pick( x1, y1, x2, y2, aRenderer, SVTK_AreaPicker::RectangleMode );
818       else if( theSelectionEvent->myIsPolygon )
819         myCellAreaPicker->Pick( theSelectionEvent->myPolygonPoints, aRenderer, SVTK_AreaPicker::PolygonMode );
820
821       const SVTK_AreaPicker::TVectorIdsMap& aVectorIdsMap = myCellAreaPicker->GetCellIdsMap();
822       SVTK_AreaPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
823       SVTK_IndexedMapOfIds anIndexes;
824       if(aMapIter != aVectorIdsMap.end()){
825         const SVTK_AreaPicker::TVectorIds& aVectorIds = aMapIter->second;
826         vtkIdType anEnd = aVectorIds.size();
827         for(vtkIdType anId = 0; anId < anEnd; anId++ ) {
828           int aCellId = aVectorIds[anId];
829           if ( !mySelector->IsValid( this, aCellId ) )
830             continue;
831
832           int anObjId = GetElemObjId( aCellId );
833           if( anObjId != -1 ) {
834             int aFNId, aSNId;
835             int anEdgeId = GetEdgeAndNodesId(this,myCellPicker.GetPointer(),anObjId,aFNId,aSNId);
836             if( anEdgeId < 0 ) {
837               SVTK_ListOfInteger aCompositeID;
838               aCompositeID.push_back( GetNodeObjId( aFNId ) );
839               aCompositeID.push_back( GetNodeObjId( aSNId ) );
840               anIndexes.Add( aCompositeID );
841             }
842           }
843         }
844       }
845
846       if ( hasIO() ) {
847         if( !anIndexes.IsEmpty() ) {
848           mySelector->AddOrRemoveCompositeIndex( myIO, anIndexes, anIsShift );
849           mySelector->AddIObject( this );
850           anIndexes.Clear();
851         }
852         else if ( !anIsShift )
853           mySelector->RemoveIObject( this );
854       }
855     }
856     default:
857       break;
858     }
859   }
860   else {
861     switch(aSelectionMode){
862     case NodeSelection: {
863       SVTK::TPickLimiter aPickLimiter( myPointPicker, this );
864       myPointPicker->Pick( x, y, 0.0, aRenderer );
865
866       int aVtkId = myPointPicker->GetPointId();
867       if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId, true ) ) {
868         int anObjId = GetNodeObjId( aVtkId );
869         if( hasIO() && anObjId >= 0 ) {
870           mySelector->AddOrRemoveIndex( myIO, anObjId, anIsShift );
871           mySelector->AddIObject( this );
872         }
873       }
874       break;
875     }
876     case CellSelection:
877     case EdgeSelection:
878     case FaceSelection:
879     case VolumeSelection:
880     case Elem0DSelection:
881     case BallSelection:
882     {
883       SVTK::TPickLimiter aPickLimiter( myCellPicker, this );
884       myCellPicker->Pick( x, y, 0.0, aRenderer );
885
886       int aVtkId = myCellPicker->GetCellId();
887       if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) ) {
888         int anObjId = GetElemObjId( aVtkId );
889         if( anObjId >= 0 ) {
890           if ( hasIO() && CheckDimensionId(aSelectionMode,this,anObjId) ) {
891             mySelector->AddOrRemoveIndex( myIO, anObjId, anIsShift );
892             mySelector->AddIObject( this );
893           }
894         }
895       }
896       break;
897     }
898     case EdgeOfCellSelection:
899     {
900       SVTK::TPickLimiter aPickLimiter( myCellPicker, this );
901       myCellPicker->Pick( x, y, 0.0, aRenderer );
902
903       int aVtkId = myCellPicker->GetCellId();
904       if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) ) {
905         int anObjId = GetElemObjId( aVtkId );
906         if( anObjId >= 0 ) {
907           int aFNId, aSNId;
908           int anEdgeId = GetEdgeAndNodesId(this,myCellPicker.GetPointer(),anObjId,aFNId,aSNId);
909           if( hasIO() && anEdgeId < 0 ) {
910             SVTK_ListOfInteger aCompositeID;
911             aCompositeID.push_back( GetNodeObjId( aFNId ) );
912             aCompositeID.push_back( GetNodeObjId( aSNId ) );
913             mySelector->AddOrRemoveCompositeIndex( myIO, aCompositeID, anIsShift );
914             mySelector->AddIObject( this );
915           }
916         }
917       }
918       break;
919     }
920     case ActorSelection :
921     {
922       if ( hasIO() ) {
923         if( mySelector->IsSelected( myIO ) && anIsShift )
924           mySelector->RemoveIObject( this );
925         else {
926           mySelector->AddIObject( this );
927         }
928       }
929       break;
930     }
931     default:
932       break;
933     }
934   }
935
936   mySelectionMode = aSelectionMode;
937
938   return true;
939 }
940
941 /*!
942   To get flag of displaying of name actor
943   \return flag to display or not to display name actor
944 */
945 bool
946 SALOME_Actor
947 ::IsDisplayNameActor() const
948 {
949   return myIsDisplayNameActor;
950 }
951
952 /*!
953   To set flag of displaying of name actor
954   \param theIsDisplayNameActor flag to display or not to display name actor
955 */
956 void
957 SALOME_Actor
958 ::SetIsDisplayNameActor(bool theIsDisplayNameActor)
959 {
960   SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
961   bool isShowGroupNames = aResourceMgr->booleanValue("VTKViewer", "show_group_names", false);
962   myIsDisplayNameActor = theIsDisplayNameActor && isShowGroupNames;
963   UpdateNameActors();
964 }
965
966 /*!
967   To set text of name actor
968   \param theText - text of name actor
969 */
970 void
971 SALOME_Actor
972 ::SetNameActorText(const char* theText)
973 {
974   myNameActor->SetText(theText);
975 }
976
977 /*!
978   To set offset of name actor
979   \param theOffset - offset of name actor
980 */
981 void
982 SALOME_Actor
983 ::SetNameActorOffset(double theOffset[2])
984 {
985   myNameActor->SetOffset(theOffset);
986 }
987
988 /*!
989   To get size of name actor
990   \param theRenderer - renderer
991   \param theSize - size of name actor
992 */
993 void
994 SALOME_Actor
995 ::GetNameActorSize(vtkRenderer* theRenderer, double theSize[2]) const
996 {
997   myNameActor->GetSize(theRenderer, theSize);
998 }
999
1000 /*!
1001   Update visibility of name actors
1002 */
1003 void
1004 SALOME_Actor
1005 ::UpdateNameActors()
1006 {
1007   if( vtkRenderer* aRenderer = GetRenderer() )
1008   {
1009     double anOffset[2] = { 0, 0 };
1010     VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
1011     vtkActorCollection* aCollection = aCopy.GetActors();
1012     for( int anIndex = 0, aNbItems = aCollection->GetNumberOfItems(); anIndex < aNbItems; anIndex++ )
1013     {
1014       if( SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>( aCollection->GetItemAsObject( anIndex ) ) )
1015       {
1016         if( anActor->IsDisplayNameActor() )
1017         {
1018           anActor->SetNameActorOffset( anOffset );
1019           if( anActor->GetVisibility() )
1020           {
1021             double aSize[2];
1022             anActor->GetNameActorSize( aRenderer, aSize );
1023             anOffset[0] = anOffset[0] + aSize[0];
1024             anOffset[1] = anOffset[1] + aSize[1];
1025           }
1026         }
1027       }
1028     }
1029   }
1030   myNameActor->SetVisibility( GetVisibility() && IsDisplayNameActor() );
1031 }
1032
1033 /*!
1034   To set up a picker for nodal selection (initialized by SVTK_Renderer::AddActor)
1035   \param thePointPicker - new picker
1036 */
1037 void
1038 SALOME_Actor
1039 ::SetPointPicker(vtkPointPicker* thePointPicker) 
1040 {
1041   myPointPicker = thePointPicker;
1042 }
1043
1044 /*!
1045   To set up a picker for cell selection (initialized by SVTK_Renderer::AddActor)
1046   \param theCellPicker - new picker
1047 */
1048 void
1049 SALOME_Actor
1050 ::SetCellPicker(vtkCellPicker* theCellPicker) 
1051 {
1052   myCellPicker = theCellPicker;
1053 }
1054
1055 /*!
1056   To set up a picker for point rectangle or polygonal selection (initialized by SVTK_Renderer::AddActor)
1057   \param theAreaPicker - new picker
1058 */
1059 void
1060 SALOME_Actor
1061 ::SetPointAreaPicker(SVTK_AreaPicker* theAreaPicker)
1062 {
1063   myPointAreaPicker = theAreaPicker;
1064 }
1065
1066 /*!
1067   To set up a picker for cell rectangle of polygonal selection (initialized by SVTK_Renderer::AddActor)
1068   \param theAreaPicker - new picker
1069 */
1070 void
1071 SALOME_Actor
1072 ::SetCellAreaPicker(SVTK_AreaPicker* theAreaPicker)
1073 {
1074   myCellAreaPicker = theAreaPicker;
1075 }
1076
1077 /*!
1078   To find a gravity center of object
1079   \param theObjId - identification of object
1080 */
1081 double*
1082 SALOME_Actor
1083 ::GetGravityCenter( int theObjId )
1084 {
1085   double* result = new double[3];
1086   for( int i = 0; i < 3; i++ )
1087     result[i]= 0.0;
1088
1089   vtkPoints* points = GetElemCell( theObjId )->GetPoints();
1090   int nbPoints = points->GetNumberOfPoints();
1091
1092   if( nbPoints <= 0 )
1093     return NULL;
1094
1095   for( int i = 0; i < nbPoints; i++ )
1096   {
1097     double* aPoint = points->GetPoint(i);
1098     result[0] += aPoint[0];
1099     result[1] += aPoint[1];
1100     result[2] += aPoint[2];
1101   }
1102   result[0] = result[0] / nbPoints;
1103   result[1] = result[1] / nbPoints;
1104   result[2] = result[2] / nbPoints;
1105
1106   return result;
1107 }
1108
1109 /*!
1110   To set up a prehighlight property (initialized by SVTK_Renderer::AddActor)
1111 */
1112 void
1113 SALOME_Actor
1114 ::SetPreHighlightProperty(vtkProperty* theProperty) 
1115 {
1116   myPreHighlightActor->SetProperty(theProperty);
1117 }
1118
1119 /*!
1120   To set up a highlight property (initialized by SVTK_Renderer::AddActor)
1121 */
1122 void
1123 SALOME_Actor
1124 ::SetHighlightProperty(vtkProperty* theProperty) 
1125 {
1126   myHighlightActor->SetProperty(theProperty);
1127 }
1128
1129 /*!
1130   Set standard point marker
1131   \param theMarkerType type of the marker
1132   \param theMarkerScale scale of the marker
1133 */
1134 void
1135 SALOME_Actor
1136 ::SetMarkerStd( VTK::MarkerType theMarkerType, VTK::MarkerScale theMarkerScale )
1137 {
1138   myPreHighlightActor->SetMarkerStd( theMarkerType, theMarkerScale );
1139   myHighlightActor->SetMarkerStd( theMarkerType, theMarkerScale );
1140 }
1141
1142 /*!
1143   Set custom point marker
1144   \param theMarkerId id of the marker texture
1145   \param theMarkerTexture marker texture
1146 */
1147 void
1148 SALOME_Actor
1149 ::SetMarkerTexture( int theMarkerId, VTK::MarkerTexture theMarkerTexture )
1150 {
1151   myPreHighlightActor->SetMarkerTexture( theMarkerId, theMarkerTexture );
1152   myHighlightActor->SetMarkerTexture( theMarkerId, theMarkerTexture );
1153 }
1154
1155 /*!
1156   Get type of the point marker
1157   \return type of the point marker
1158 */
1159 VTK::MarkerType
1160 SALOME_Actor
1161 ::GetMarkerType()
1162 {
1163   return myPreHighlightActor->GetMarkerType();
1164 }
1165
1166 /*!
1167   Get scale of the point marker
1168   \return scale of the point marker
1169 */
1170 VTK::MarkerScale
1171 SALOME_Actor
1172 ::GetMarkerScale()
1173 {
1174   return myPreHighlightActor->GetMarkerScale();
1175 }
1176
1177 /*!
1178   Get texture identifier of the point marker
1179   \return texture identifier of the point marker
1180  */
1181 int
1182 SALOME_Actor
1183 ::GetMarkerTexture()
1184 {
1185   return myPreHighlightActor->GetMarkerTexture();
1186 }