1 // SALOME OBJECT : implementation of interactive object visualization for OCC and VTK viewers
3 // Copyright (C) 2003 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
24 // File : SALOME_Actor.cxx
25 // Author : Nicolas REJNERI
30 \class SALOME_Actor SALOME_Actor.h
31 \brief Abstract class of SALOME Objects in VTK.
35 #include "SALOME_Actor.h"
37 #include "VTKViewer_Transform.h"
38 #include "VTKViewer_TransformFilter.h"
39 #include "VTKViewer_GeometryFilter.h"
40 #include "SVTK_RectPicker.h"
42 #include "SVTK_Actor.h"
47 #include <vtkPicker.h>
48 #include <vtkPointPicker.h>
49 #include <vtkCellPicker.h>
50 #include <vtkRenderer.h>
51 #include <vtkPolyData.h>
52 #include <vtkObjectFactory.h>
53 #include <vtkDataSetMapper.h>
54 #include <vtkPolyDataMapper.h>
55 #include <vtkProperty.h>
56 #include <vtkOutlineSource.h>
58 #include <vtkInteractorStyle.h>
59 #include <vtkRenderWindowInteractor.h>
60 #include <vtkPassThroughFilter.h>
62 #include <TColStd_MapOfInteger.hxx>
63 #include <TColStd_IndexedMapOfInteger.hxx>
73 int SALOME_POINT_SIZE = 5;
74 int SALOME_LINE_WIDTH = 3;
79 GetEdgeId(SALOME_Actor* theActor,
84 if (vtkCell* aPickedCell = theActor->GetElemCell(theObjId)) {
85 vtkFloatingPointType aPickPosition[3];
86 thePicker->GetPickPosition(aPickPosition);
87 vtkFloatingPointType aMinDist = 1000000.0, aDist = 0;
88 for (int i = 0, iEnd = aPickedCell->GetNumberOfEdges(); i < iEnd; i++){
89 if(vtkLine* aLine = vtkLine::SafeDownCast(aPickedCell->GetEdge(i))){
91 vtkFloatingPointType pcoords[3], closestPoint[3], weights[3];
92 aLine->EvaluatePosition(aPickPosition,closestPoint,subId,pcoords,aDist,weights);
93 if (aDist < aMinDist) {
105 CheckDimensionId(Selection_Mode theMode,
106 SALOME_Actor *theActor,
113 return ( theActor->GetObjDimension( theObjId ) == 1 );
115 return ( theActor->GetObjDimension( theObjId ) == 2 );
116 case VolumeSelection:
117 return ( theActor->GetObjDimension( theObjId ) == 3 );
125 vtkStandardNewMacro(SALOME_Actor);
134 mySelectionMode(ActorSelection),
135 myPreHighlightActor(SVTK_Actor::New()),
136 myHighlightActor(SVTK_Actor::New()),
137 myOutline(vtkOutlineSource::New()),
138 myOutlineActor(VTKViewer_Actor::New())
140 myPreHighlightActor->Delete();
141 myPreHighlightActor->Initialize();
142 myPreHighlightActor->PickableOff();
143 myPreHighlightActor->SetVisibility( false );
145 myHighlightActor->Delete();
146 myHighlightActor->Initialize();
147 myHighlightActor->PickableOff();
148 myHighlightActor->SetVisibility( false );
152 vtkPolyDataMapper* anOutlineMapper = vtkPolyDataMapper::New();
153 anOutlineMapper->SetInput(myOutline->GetOutput());
155 myOutlineActor->Delete();
156 myOutlineActor->SetMapper( anOutlineMapper );
157 anOutlineMapper->Delete();
159 myOutlineActor->PickableOff();
160 myOutlineActor->DragableOff();
161 myOutlineActor->GetProperty()->SetColor(1.0,0.0,0.0);
162 myOutlineActor->GetProperty()->SetAmbient(1.0);
163 myOutlineActor->GetProperty()->SetDiffuse(0.0);
164 myOutlineActor->SetVisibility( false );
176 \return true if the SALOME_Actor has a reference to SALOME_InteractiveObject
182 return !myIO.IsNull();
186 \return correspoinding reference to SALOME_InteractiveObject
188 const Handle(SALOME_InteractiveObject)&
196 Sets reference to SALOME_InteractiveObject
197 \param theIO - new SALOME_InteractiveObject
201 ::setIO(const Handle(SALOME_InteractiveObject)& theIO)
207 Sets name the SALOME_Actor
208 \param theName - new name
212 ::setName(const char* theName)
215 myIO->setName(theName);
216 Superclass::setName(theName);
221 Publishes the actor in all its internal devices
225 ::AddToRender(vtkRenderer* theRenderer)
227 Superclass::AddToRender(theRenderer);
229 myRenderer = theRenderer;
231 theRenderer->AddActor( myPreHighlightActor.GetPointer() );
232 theRenderer->AddActor( myHighlightActor.GetPointer() );
233 theRenderer->AddActor( myOutlineActor.GetPointer() );
237 Removes the actor from all its internal devices
241 ::RemoveFromRender(vtkRenderer* theRenderer)
243 Superclass::RemoveFromRender(theRenderer);
245 theRenderer->RemoveActor( myPreHighlightActor.GetPointer() );
246 theRenderer->RemoveActor( myHighlightActor.GetPointer() );
247 theRenderer->RemoveActor( myOutlineActor.GetPointer() );
251 \return reference on renderer where it is published
261 Sets interactor in order to use vtkInteractorObserver devices
262 \param theInteractor - new interactor
266 ::SetInteractor(vtkRenderWindowInteractor* theInteractor)
268 myInteractor = theInteractor;
272 Put a request to redraw the view
278 myInteractor->CreateTimer(VTKI_TIMER_UPDATE);
282 Apply view transformation
283 \param theTransform - transformation
287 ::SetTransform(VTKViewer_Transform* theTransform)
289 Superclass::SetTransform(theTransform);
291 myPreHighlightActor->SetTransform(theTransform);
292 myHighlightActor->SetTransform(theTransform);
293 myOutlineActor->SetTransform(theTransform);
297 Apply additional position
301 ::SetPosition(vtkFloatingPointType _arg1,
302 vtkFloatingPointType _arg2,
303 vtkFloatingPointType _arg3)
305 Superclass::SetPosition(_arg1,_arg2,_arg3);
307 myPreHighlightActor->SetPosition(_arg1,_arg2,_arg3);
308 myHighlightActor->SetPosition(_arg1,_arg2,_arg3);
309 myOutlineActor->SetPosition(_arg1,_arg2,_arg3);
313 Apply additional position
317 ::SetPosition(vtkFloatingPointType _arg[3])
319 SetPosition(_arg[0],_arg[1],_arg[2]);
324 \param theVisibility - new visibility state
328 ::SetVisibility( int theVisibility )
330 Superclass::SetVisibility( theVisibility );
332 myOutlineActor->SetVisibility( theVisibility && isHighlighted() && !hasHighlight() );
334 myPreHighlightActor->SetVisibility( theVisibility && myIsPreselected );
336 if(mySelector.GetPointer() && hasIO()){
337 if(mySelector->SelectionMode() != ActorSelection){
338 int aHasIndex = mySelector->HasIndex( getIO() );
339 myHighlightActor->SetVisibility( theVisibility && isHighlighted() && aHasIndex);
345 Set selector in order to the actor at any time can restore current selection
346 \param theSelector - new selector
350 ::SetSelector(SVTK_Selector* theSelector)
352 mySelector = theSelector;
356 To map current selection to VTK representation
360 ::Highlight(bool theIsHighlight)
362 mySelectionMode = mySelector->SelectionMode();
363 myHighlightActor->SetVisibility( false );
364 myOutlineActor->SetVisibility( false );
366 if(mySelector.GetPointer()){
367 if(mySelectionMode != ActorSelection){
368 TColStd_IndexedMapOfInteger aMapIndex;
369 mySelector->GetIndex( getIO(), aMapIndex );
370 switch( mySelectionMode ){
372 myHighlightActor->GetProperty()->SetRepresentationToPoints();
373 myHighlightActor->MapPoints( this, aMapIndex );
375 case EdgeOfCellSelection:
376 myHighlightActor->GetProperty()->SetRepresentationToWireframe();
377 myHighlightActor->MapEdge( this, aMapIndex );
382 case VolumeSelection:
383 myHighlightActor->GetProperty()->SetRepresentationToSurface();
384 myHighlightActor->MapCells( this, aMapIndex );
387 myHighlightActor->SetVisibility( GetVisibility() && theIsHighlight );
391 highlight(theIsHighlight);
395 Updates visibility of the highlight devices
399 ::highlight(bool theIsHighlight)
401 vtkFloatingPointType aBounds[6];
402 GetInput()->GetBounds(aBounds);
403 myOutline->SetBounds(aBounds);
404 myOutlineActor->SetVisibility( GetVisibility() && theIsHighlight );
406 Superclass::highlight(theIsHighlight);
411 To process prehighlight (called from SVTK_InteractorStyle)
415 ::PreHighlight(vtkInteractorStyle *theInteractorStyle,
416 SVTK_SelectionEvent* theSelectionEvent,
419 if ( !GetPickable() )
422 vtkRenderer *aRenderer = theInteractorStyle->GetCurrentRenderer();
424 myPreHighlightActor->SetVisibility( false );
425 bool anIsPreselected = myIsPreselected;
427 Selection_Mode aSelectionMode = theSelectionEvent->mySelectionMode;
428 bool anIsChanged = (mySelectionMode != aSelectionMode);
430 vtkFloatingPointType x = theSelectionEvent->myX;
431 vtkFloatingPointType y = theSelectionEvent->myY;
432 vtkFloatingPointType z = 0.0;
434 if( !theIsHighlight ) {
435 SetPreSelected( false );
436 vtkActorCollection* theActors = aRenderer->GetActors();
437 theActors->InitTraversal();
438 while( vtkActor *ac = theActors->GetNextActor() )
439 if( SALOME_Actor* anActor = SALOME_Actor::SafeDownCast( ac ) )
440 if( anActor->hasIO() && myIO->isSame( anActor->getIO() ) )
441 anActor->SetPreSelected( false );
444 switch(aSelectionMode){
447 myPointPicker->Pick( x, y, z, aRenderer );
449 int aVtkId = myPointPicker->GetPointId();
450 if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId, true ) ) {
451 int anObjId = GetNodeObjId( aVtkId );
452 myIsPreselected = (anObjId >= 0);
454 const TColStd_IndexedMapOfInteger& aMapIndex = myPreHighlightActor->GetMapIndex();
455 int anExtent = aMapIndex.Extent();
456 anIsChanged |= (anExtent == 0 || anExtent > 0 && anObjId != aMapIndex(1));
458 TColStd_IndexedMapOfInteger aMapIndex;
459 aMapIndex.Add( anObjId );
461 myPreHighlightActor->GetProperty()->SetRepresentationToPoints();
462 myPreHighlightActor->MapPoints( this, aMapIndex );
464 myPreHighlightActor->SetVisibility( true );
472 case VolumeSelection:
474 myCellPicker->Pick( x, y, z, aRenderer );
476 int aVtkId = myCellPicker->GetCellId();
477 if ( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) && hasIO() ) {
478 int anObjId = GetElemObjId (aVtkId );
479 if ( anObjId >= 0 ) {
480 myIsPreselected = CheckDimensionId(aSelectionMode,this,anObjId);
482 const TColStd_IndexedMapOfInteger& aMapIndex = myPreHighlightActor->GetMapIndex();
483 int anExtent = aMapIndex.Extent();
484 anIsChanged |= (anExtent == 0 || anExtent > 0 && anObjId != aMapIndex(1));
486 TColStd_IndexedMapOfInteger aMapIndex;
487 aMapIndex.Add( anObjId );
489 myPreHighlightActor->GetProperty()->SetRepresentationToSurface();
490 myPreHighlightActor->MapCells( this, aMapIndex );
492 myPreHighlightActor->SetVisibility( true );
498 case EdgeOfCellSelection:
500 myCellPicker->Pick( x, y, z, aRenderer );
502 int aVtkId = myCellPicker->GetCellId();
503 if ( aVtkId >= 0 && mySelector->IsValid( this, aVtkId )) {
504 int anObjId = GetElemObjId( aVtkId );
505 if ( anObjId >= 0 ) {
506 int anEdgeId = GetEdgeId(this,myCellPicker.GetPointer(),anObjId);
507 myIsPreselected = anEdgeId < 0;
509 const TColStd_IndexedMapOfInteger& aMapIndex = myPreHighlightActor->GetMapIndex();
510 int anExtent = aMapIndex.Extent();
511 anIsChanged |= (anExtent == 0);
512 anIsChanged |= (anExtent == 2 && (anObjId != aMapIndex(1) || anEdgeId != aMapIndex(2)));
514 TColStd_IndexedMapOfInteger aMapIndex;
515 aMapIndex.Add( anObjId );
516 aMapIndex.Add( anEdgeId );
518 myPreHighlightActor->GetProperty()->SetRepresentationToWireframe();
519 myPreHighlightActor->MapEdge( this, aMapIndex );
521 myPreHighlightActor->SetVisibility( true );
527 case ActorSelection :
529 if( !mySelector->IsSelected( myIO ) ) {
530 SetPreSelected( true );
532 vtkActorCollection* theActors = aRenderer->GetActors();
533 theActors->InitTraversal();
534 while( vtkActor *anAct = theActors->GetNextActor() ) {
536 if( SALOME_Actor* anActor = SALOME_Actor::SafeDownCast( anAct ) )
537 if( anActor->hasIO() && myIO->isSame( anActor->getIO() ) )
538 anActor->SetPreSelected( true );
547 mySelectionMode = aSelectionMode;
548 anIsChanged |= (anIsPreselected != myIsPreselected);
554 To process highlight (called from SVTK_InteractorStyle)
558 ::Highlight(vtkInteractorStyle *theInteractorStyle,
559 SVTK_SelectionEvent* theSelectionEvent,
562 if ( !GetPickable() )
565 myOutlineActor->SetVisibility( false );
566 myHighlightActor->SetVisibility( false );
568 vtkRenderer *aRenderer = theInteractorStyle->GetCurrentRenderer();
570 Selection_Mode aSelectionMode = theSelectionEvent->mySelectionMode;
571 bool anIsShift = theSelectionEvent->myIsShift;
572 if( !anIsShift || !theIsHighlight ) {
573 mySelector->RemoveIObject( this );
576 if ( !theIsHighlight )
579 vtkFloatingPointType x = theSelectionEvent->myX;
580 vtkFloatingPointType y = theSelectionEvent->myY;
581 vtkFloatingPointType z = 0.0;
583 if( !theSelectionEvent->myIsRectangle ) {
584 switch(aSelectionMode){
585 case NodeSelection: {
586 myPointPicker->Pick( x, y, z, aRenderer );
588 int aVtkId = myPointPicker->GetPointId();
589 if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId, true ) ) {
590 int anObjId = GetNodeObjId( aVtkId );
592 mySelector->AddOrRemoveIndex( myIO, anObjId, anIsShift );
593 mySelector->AddIObject( this );
601 case VolumeSelection:
603 myCellPicker->Pick( x, y, z, aRenderer );
605 int aVtkId = myCellPicker->GetCellId();
606 if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) ) {
607 int anObjId = GetElemObjId( aVtkId );
609 if ( CheckDimensionId(aSelectionMode,this,anObjId) ) {
610 mySelector->AddOrRemoveIndex( myIO, anObjId, anIsShift );
611 mySelector->AddIObject( this );
617 case EdgeOfCellSelection:
619 myCellPicker->Pick( x, y, z, aRenderer );
621 int aVtkId = myCellPicker->GetCellId();
622 if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) ) {
623 int anObjId = GetElemObjId( aVtkId );
625 int anEdgeId = GetEdgeId(this,myCellPicker.GetPointer(),anObjId);
627 mySelector->AddOrRemoveIndex( myIO, anObjId, false );
628 mySelector->AddOrRemoveIndex( myIO, anEdgeId, true );
629 mySelector->AddIObject( this );
635 case ActorSelection :
637 if( mySelector->IsSelected( myIO ) && anIsShift )
638 mySelector->RemoveIObject( this );
640 mySelector->AddIObject( this );
648 vtkFloatingPointType xLast = theSelectionEvent->myLastX;
649 vtkFloatingPointType yLast = theSelectionEvent->myLastY;
650 vtkFloatingPointType zLast = 0.0;
652 vtkFloatingPointType x1 = x < xLast ? x : xLast;
653 vtkFloatingPointType y1 = y < yLast ? y : yLast;
654 vtkFloatingPointType z1 = z < zLast ? z : zLast;
655 vtkFloatingPointType x2 = x > xLast ? x : xLast;
656 vtkFloatingPointType y2 = y > yLast ? y : yLast;
657 vtkFloatingPointType z2 = z > zLast ? z : zLast;
659 switch(aSelectionMode){
660 case NodeSelection: {
661 myPointRectPicker->InitializePickList();
662 myPointRectPicker->AddPickList(this);
663 myPointRectPicker->Pick( x1, y1, z1, x2, y2, z2, aRenderer );
665 const SVTK_RectPicker::TVectorIdsMap& aVectorIdsMap = myPointRectPicker->GetPointIdsMap();
666 SVTK_RectPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
667 TColStd_MapOfInteger anIndexes;
668 if(aMapIter != aVectorIdsMap.end()){
669 const SVTK_RectPicker::TVectorIds& aVectorIds = aMapIter->second;
670 vtkIdType anEnd = aVectorIds.size();
671 for(vtkIdType anId = 0; anId < anEnd; anId++ ) {
672 int aPointId = aVectorIds[anId];
673 if( aPointId >= 0 && mySelector->IsValid( this, aPointId, true ) ) {
674 int anObjId = GetNodeObjId( aPointId );
675 anIndexes.Add( anObjId );
680 if( !anIndexes.IsEmpty() ) {
681 mySelector->AddOrRemoveIndex( myIO, anIndexes, anIsShift );
682 mySelector->AddIObject( this );
686 mySelector->RemoveIObject( this );
690 case ActorSelection :
692 vtkFloatingPointType aPnt[3];
693 vtkFloatingPointType* aBounds = GetBounds();
695 bool anIsPicked = true;
696 for( int i = 0; i <= 1; i++ ) {
697 for( int j = 2; j <= 3; j++ ) {
698 for( int k = 4; k <= 5; k++ ) {
699 aRenderer->SetWorldPoint( aBounds[ i ], aBounds[ j ], aBounds[ k ], 1.0 );
700 aRenderer->WorldToDisplay();
701 aRenderer->GetDisplayPoint( aPnt );
703 if( aPnt[0] < x1 || aPnt[0] > x2 || aPnt[1] < y1 || aPnt[1] > y2 ) {
712 mySelector->AddIObject(this);
719 case VolumeSelection:
721 myCellRectPicker->InitializePickList();
722 myCellRectPicker->AddPickList(this);
723 myCellRectPicker->Pick( x1, y1, z1, x2, y2, z2, aRenderer );
725 const SVTK_RectPicker::TVectorIdsMap& aVectorIdsMap = myCellRectPicker->GetCellIdsMap();
726 SVTK_RectPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
727 TColStd_MapOfInteger anIndexes;
728 if(aMapIter != aVectorIdsMap.end()){
729 const SVTK_RectPicker::TVectorIds& aVectorIds = aMapIter->second;
730 vtkIdType anEnd = aVectorIds.size();
731 for(vtkIdType anId = 0; anId < anEnd; anId++ ) {
732 int aCellId = aVectorIds[anId];
733 if ( !mySelector->IsValid( this, aCellId ) )
736 int anObjId = GetElemObjId( aCellId );
738 if ( CheckDimensionId(aSelectionMode,this,anObjId) ) {
739 anIndexes.Add(anObjId);
743 mySelector->AddOrRemoveIndex( myIO, anIndexes, anIsShift );
744 mySelector->AddIObject( this );
751 mySelectionMode = aSelectionMode;
757 To set up a picker for nodal selection (initialized by SVTK_Renderer::AddActor)
758 \param thePointPicker - new picker
762 ::SetPointPicker(vtkPointPicker* thePointPicker)
764 myPointPicker = thePointPicker;
768 To set up a picker for cell selection (initialized by SVTK_Renderer::AddActor)
769 \param theCellPicker - new picker
773 ::SetCellPicker(vtkCellPicker* theCellPicker)
775 myCellPicker = theCellPicker;
779 To set up a picker for point rectangle selection (initialized by SVTK_Renderer::AddActor)
780 \param theRectPicker - new picker
784 ::SetPointRectPicker(SVTK_RectPicker* theRectPicker)
786 myPointRectPicker = theRectPicker;
790 To set up a picker for cell rectangle selection (initialized by SVTK_Renderer::AddActor)
791 \param theRectPicker - new picker
795 ::SetCellRectPicker(SVTK_RectPicker* theRectPicker)
797 myCellRectPicker = theRectPicker;
801 To set up a prehighlight property (initialized by SVTK_Renderer::AddActor)
805 ::SetPreHighlightProperty(vtkProperty* theProperty)
807 myPreHighlightActor->SetProperty(theProperty);
811 To set up a highlight property (initialized by SVTK_Renderer::AddActor)
815 ::SetHighlightProperty(vtkProperty* theProperty)
817 myHighlightActor->SetProperty(theProperty);