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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
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_PassThroughFilter.h"
40 #include "VTKViewer_GeometryFilter.h"
41 #include "SVTK_RectPicker.h"
43 #include "SVTK_Actor.h"
48 #include <vtkPicker.h>
49 #include <vtkPointPicker.h>
50 #include <vtkCellPicker.h>
51 #include <vtkRenderer.h>
52 #include <vtkPolyData.h>
53 #include <vtkObjectFactory.h>
54 #include <vtkDataSetMapper.h>
55 #include <vtkPolyDataMapper.h>
56 #include <vtkProperty.h>
57 #include <vtkOutlineSource.h>
59 #include <vtkInteractorStyle.h>
60 #include <vtkRenderWindowInteractor.h>
62 #include <TColStd_MapOfInteger.hxx>
63 #include <TColStd_IndexedMapOfInteger.hxx>
73 int SALOME_POINT_SIZE = 5;
74 int SALOME_LINE_WIDTH = 3;
76 //----------------------------------------------------------------------------
80 GetEdgeId(SALOME_Actor* theActor,
85 if (vtkCell* aPickedCell = theActor->GetElemCell(theObjId)) {
86 float aPickPosition[3];
87 thePicker->GetPickPosition(aPickPosition);
88 float aMinDist = 1000000.0, aDist = 0;
89 for (int i = 0, iEnd = aPickedCell->GetNumberOfEdges(); i < iEnd; i++){
90 if(vtkLine* aLine = vtkLine::SafeDownCast(aPickedCell->GetEdge(i))){
91 int subId; float 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 //----------------------------------------------------------------------------
126 vtkStandardNewMacro(SALOME_Actor);
129 //----------------------------------------------------------------------------
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 );
168 //----------------------------------------------------------------------------
174 //----------------------------------------------------------------------------
179 return !myIO.IsNull();
182 const Handle(SALOME_InteractiveObject)&
191 ::setIO(const Handle(SALOME_InteractiveObject)& theIO)
198 ::setName(const char* theName)
201 myIO->setName(theName);
202 Superclass::setName(theName);
206 //----------------------------------------------------------------------------
209 ::AddToRender(vtkRenderer* theRenderer)
211 Superclass::AddToRender(theRenderer);
213 myRenderer = theRenderer;
215 theRenderer->AddActor( myPreHighlightActor.GetPointer() );
216 theRenderer->AddActor( myHighlightActor.GetPointer() );
217 theRenderer->AddActor( myOutlineActor.GetPointer() );
222 ::RemoveFromRender(vtkRenderer* theRenderer)
224 Superclass::RemoveFromRender(theRenderer);
226 theRenderer->RemoveActor( myPreHighlightActor.GetPointer() );
227 theRenderer->RemoveActor( myHighlightActor.GetPointer() );
228 theRenderer->RemoveActor( myOutlineActor.GetPointer() );
239 //----------------------------------------------------------------------------
242 ::SetInteractor(vtkRenderWindowInteractor* theInteractor)
244 myInteractor = theInteractor;
251 myInteractor->CreateTimer(VTKI_TIMER_UPDATE);
255 //----------------------------------------------------------------------------
258 ::SetTransform(VTKViewer_Transform* theTransform)
260 Superclass::SetTransform(theTransform);
262 myPreHighlightActor->SetTransform(theTransform);
263 myHighlightActor->SetTransform(theTransform);
264 myOutlineActor->SetTransform(theTransform);
270 ::SetPosition(float _arg1, float _arg2, float _arg3)
272 Superclass::SetPosition(_arg1,_arg2,_arg3);
274 myPreHighlightActor->SetPosition(_arg1,_arg2,_arg3);
275 myHighlightActor->SetPosition(_arg1,_arg2,_arg3);
276 myOutlineActor->SetPosition(_arg1,_arg2,_arg3);
282 ::SetPosition(float _arg[3])
284 SetPosition(_arg[0],_arg[1],_arg[2]);
288 //----------------------------------------------------------------
291 ::SetVisibility( int theVisibility )
293 Superclass::SetVisibility( theVisibility );
295 myOutlineActor->SetVisibility( theVisibility && isHighlighted() && !hasHighlight() );
297 myPreHighlightActor->SetVisibility( theVisibility && myIsPreselected );
299 if(mySelector.GetPointer() && hasIO()){
300 if(mySelector->SelectionMode() != ActorSelection){
301 int aHasIndex = mySelector->HasIndex( getIO() );
302 myHighlightActor->SetVisibility( theVisibility && isHighlighted() && aHasIndex);
308 //----------------------------------------------------------------
311 ::SetSelector(SVTK_Selector* theSelector)
313 mySelector = theSelector;
318 ::Highlight(bool theIsHighlight)
320 mySelectionMode = mySelector->SelectionMode();
321 myHighlightActor->SetVisibility( false );
322 myOutlineActor->SetVisibility( false );
324 if(mySelector.GetPointer()){
325 if(mySelectionMode != ActorSelection){
326 TColStd_IndexedMapOfInteger aMapIndex;
327 mySelector->GetIndex( getIO(), aMapIndex );
328 switch( mySelectionMode ){
330 myHighlightActor->GetProperty()->SetRepresentationToPoints();
331 myHighlightActor->MapPoints( this, aMapIndex );
333 case EdgeOfCellSelection:
334 myHighlightActor->GetProperty()->SetRepresentationToWireframe();
335 myHighlightActor->MapEdge( this, aMapIndex );
340 case VolumeSelection:
341 myHighlightActor->GetProperty()->SetRepresentationToSurface();
342 myHighlightActor->MapCells( this, aMapIndex );
345 myHighlightActor->SetVisibility( GetVisibility() && theIsHighlight );
349 highlight(theIsHighlight);
354 ::highlight(bool theIsHighlight)
357 GetInput()->GetBounds(aBounds);
358 myOutline->SetBounds(aBounds);
359 myOutlineActor->SetVisibility( GetVisibility() && theIsHighlight );
361 Superclass::highlight(theIsHighlight);
365 //----------------------------------------------------------------
368 ::PreHighlight(vtkInteractorStyle *theInteractorStyle,
369 SVTK_SelectionEvent* theSelectionEvent,
372 vtkRenderer *aRenderer = theInteractorStyle->GetCurrentRenderer();
374 myPreHighlightActor->SetVisibility( false );
375 bool anIsPreselected = myIsPreselected;
377 Selection_Mode aSelectionMode = theSelectionEvent->mySelectionMode;
378 bool anIsChanged = (mySelectionMode != aSelectionMode);
380 float x = theSelectionEvent->myX;
381 float y = theSelectionEvent->myY;
384 if( !theIsHighlight ) {
385 SetPreSelected( false );
386 vtkActorCollection* theActors = aRenderer->GetActors();
387 theActors->InitTraversal();
388 while( vtkActor *ac = theActors->GetNextActor() )
389 if( SALOME_Actor* anActor = SALOME_Actor::SafeDownCast( ac ) )
390 if( anActor->hasIO() && myIO->isSame( anActor->getIO() ) )
391 anActor->SetPreSelected( false );
394 switch(aSelectionMode){
397 myPointPicker->Pick( x, y, z, aRenderer );
399 int aVtkId = myPointPicker->GetPointId();
400 if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId, true ) ) {
401 int anObjId = GetNodeObjId( aVtkId );
402 myIsPreselected = (anObjId >= 0);
404 const TColStd_IndexedMapOfInteger& aMapIndex = myPreHighlightActor->GetMapIndex();
405 int anExtent = aMapIndex.Extent();
406 anIsChanged |= (anExtent == 0 || anExtent > 0 && anObjId != aMapIndex(1));
408 TColStd_IndexedMapOfInteger aMapIndex;
409 aMapIndex.Add( anObjId );
411 myPreHighlightActor->GetProperty()->SetRepresentationToPoints();
412 myPreHighlightActor->MapPoints( this, aMapIndex );
414 myPreHighlightActor->SetVisibility( true );
422 case VolumeSelection:
424 myCellPicker->Pick( x, y, z, aRenderer );
426 int aVtkId = myCellPicker->GetCellId();
427 if ( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) && hasIO() ) {
428 int anObjId = GetElemObjId (aVtkId );
429 if ( anObjId >= 0 ) {
430 myIsPreselected = CheckDimensionId(aSelectionMode,this,anObjId);
432 const TColStd_IndexedMapOfInteger& aMapIndex = myPreHighlightActor->GetMapIndex();
433 int anExtent = aMapIndex.Extent();
434 anIsChanged |= (anExtent == 0 || anExtent > 0 && anObjId != aMapIndex(1));
436 TColStd_IndexedMapOfInteger aMapIndex;
437 aMapIndex.Add( anObjId );
439 myPreHighlightActor->GetProperty()->SetRepresentationToSurface();
440 myPreHighlightActor->MapCells( this, aMapIndex );
442 myPreHighlightActor->SetVisibility( true );
448 case EdgeOfCellSelection:
450 myCellPicker->Pick( x, y, z, aRenderer );
452 int aVtkId = myCellPicker->GetCellId();
453 if ( aVtkId >= 0 && mySelector->IsValid( this, aVtkId )) {
454 int anObjId = GetElemObjId( aVtkId );
455 if ( anObjId >= 0 ) {
456 int anEdgeId = GetEdgeId(this,myCellPicker.GetPointer(),anObjId);
457 myIsPreselected = anEdgeId < 0;
459 const TColStd_IndexedMapOfInteger& aMapIndex = myPreHighlightActor->GetMapIndex();
460 int anExtent = aMapIndex.Extent();
461 anIsChanged |= (anExtent == 0);
462 anIsChanged |= (anExtent == 2 && (anObjId != aMapIndex(1) || anEdgeId != aMapIndex(2)));
464 TColStd_IndexedMapOfInteger aMapIndex;
465 aMapIndex.Add( anObjId );
466 aMapIndex.Add( anEdgeId );
468 myPreHighlightActor->GetProperty()->SetRepresentationToWireframe();
469 myPreHighlightActor->MapEdge( this, aMapIndex );
471 myPreHighlightActor->SetVisibility( true );
477 case ActorSelection :
479 if( !mySelector->IsSelected( myIO ) ) {
480 SetPreSelected( true );
482 vtkActorCollection* theActors = aRenderer->GetActors();
483 theActors->InitTraversal();
484 while( vtkActor *anAct = theActors->GetNextActor() ) {
486 if( SALOME_Actor* anActor = SALOME_Actor::SafeDownCast( anAct ) )
487 if( anActor->hasIO() && myIO->isSame( anActor->getIO() ) )
488 anActor->SetPreSelected( true );
497 mySelectionMode = aSelectionMode;
498 anIsChanged |= (anIsPreselected != myIsPreselected);
504 //----------------------------------------------------------------
507 ::Highlight(vtkInteractorStyle *theInteractorStyle,
508 SVTK_SelectionEvent* theSelectionEvent,
511 myOutlineActor->SetVisibility( false );
512 myHighlightActor->SetVisibility( false );
514 vtkRenderer *aRenderer = theInteractorStyle->GetCurrentRenderer();
516 Selection_Mode aSelectionMode = theSelectionEvent->mySelectionMode;
517 bool anIsShift = theSelectionEvent->myIsShift;
519 mySelector->RemoveIObject( this );
522 float x = theSelectionEvent->myX;
523 float y = theSelectionEvent->myY;
526 if( !theSelectionEvent->myIsRectangle ) {
527 switch(aSelectionMode){
528 case NodeSelection: {
529 myPointPicker->Pick( x, y, z, aRenderer );
531 int aVtkId = myPointPicker->GetPointId();
532 if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId, true ) ) {
533 int anObjId = GetNodeObjId( aVtkId );
535 mySelector->AddOrRemoveIndex( myIO, anObjId, anIsShift );
536 mySelector->AddIObject( this );
544 case VolumeSelection:
546 myCellPicker->Pick( x, y, z, aRenderer );
548 int aVtkId = myCellPicker->GetCellId();
549 if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) ) {
550 int anObjId = GetElemObjId( aVtkId );
552 if ( CheckDimensionId(aSelectionMode,this,anObjId) ) {
553 mySelector->AddOrRemoveIndex( myIO, anObjId, anIsShift );
554 mySelector->AddIObject( this );
560 case EdgeOfCellSelection:
562 myCellPicker->Pick( x, y, z, aRenderer );
564 int aVtkId = myCellPicker->GetCellId();
565 if( aVtkId >= 0 && mySelector->IsValid( this, aVtkId ) ) {
566 int anObjId = GetElemObjId( aVtkId );
568 int anEdgeId = GetEdgeId(this,myCellPicker.GetPointer(),anObjId);
570 mySelector->AddOrRemoveIndex( myIO, anObjId, false );
571 mySelector->AddOrRemoveIndex( myIO, anEdgeId, true );
572 mySelector->AddIObject( this );
578 case ActorSelection :
580 if( mySelector->IsSelected( myIO ) && anIsShift )
581 mySelector->RemoveIObject( this );
583 mySelector->AddIObject( this );
591 float xLast = theSelectionEvent->myLastX;
592 float yLast = theSelectionEvent->myLastY;
595 float x1 = x < xLast ? x : xLast;
596 float y1 = y < yLast ? y : yLast;
597 float z1 = z < zLast ? z : zLast;
598 float x2 = x > xLast ? x : xLast;
599 float y2 = y > yLast ? y : yLast;
600 float z2 = z > zLast ? z : zLast;
602 switch(aSelectionMode){
603 case NodeSelection: {
604 myPointRectPicker->InitializePickList();
605 myPointRectPicker->AddPickList(this);
606 myPointRectPicker->Pick( x1, y1, z1, x2, y2, z2, aRenderer );
608 const SVTK_RectPicker::TVectorIdsMap& aVectorIdsMap = myPointRectPicker->GetPointIdsMap();
609 SVTK_RectPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
610 TColStd_MapOfInteger anIndexes;
611 if(aMapIter != aVectorIdsMap.end()){
612 const SVTK_RectPicker::TVectorIds& aVectorIds = aMapIter->second;
613 vtkIdType anEnd = aVectorIds.size();
614 SVTK_RectPicker::TVectorIds::const_iterator anIdIter = aVectorIds.begin();
615 for(vtkIdType anId = 0; anId < anEnd; anId++ ) {
616 int aPointId = aVectorIds[anId];
617 if( aPointId >= 0 && mySelector->IsValid( this, aPointId, true ) ) {
618 int anObjId = GetNodeObjId( aPointId );
619 anIndexes.Add( anObjId );
624 if( !anIndexes.IsEmpty() ) {
625 mySelector->AddOrRemoveIndex( myIO, anIndexes, anIsShift );
626 mySelector->AddIObject( this );
630 mySelector->RemoveIObject( this );
634 case ActorSelection :
637 float* aBounds = GetBounds();
639 bool anIsPicked = true;
640 for( int i = 0; i <= 1; i++ ) {
641 for( int j = 2; j <= 3; j++ ) {
642 for( int k = 4; k <= 5; k++ ) {
643 aRenderer->SetWorldPoint( aBounds[ i ], aBounds[ j ], aBounds[ k ], 1.0 );
644 aRenderer->WorldToDisplay();
645 aRenderer->GetDisplayPoint( aPnt );
647 if( aPnt[0] < x1 || aPnt[0] > x2 || aPnt[1] < y1 || aPnt[1] > y2 ) {
656 mySelector->AddIObject(this);
663 case VolumeSelection:
665 myCellRectPicker->InitializePickList();
666 myCellRectPicker->AddPickList(this);
667 myCellRectPicker->Pick( x1, y1, z1, x2, y2, z2, aRenderer );
669 const SVTK_RectPicker::TVectorIdsMap& aVectorIdsMap = myCellRectPicker->GetCellIdsMap();
670 SVTK_RectPicker::TVectorIdsMap::const_iterator aMapIter = aVectorIdsMap.find(this);
671 TColStd_MapOfInteger anIndexes;
672 if(aMapIter != aVectorIdsMap.end()){
673 const SVTK_RectPicker::TVectorIds& aVectorIds = aMapIter->second;
674 vtkIdType anEnd = aVectorIds.size();
675 SVTK_RectPicker::TVectorIds::const_iterator anIdIter = aVectorIds.begin();
676 for(vtkIdType anId = 0; anId < anEnd; anId++ ) {
677 int aCellId = aVectorIds[anId];
678 if ( !mySelector->IsValid( this, aCellId ) )
681 int anObjId = GetElemObjId( aCellId );
683 if ( CheckDimensionId(aSelectionMode,this,anObjId) ) {
684 anIndexes.Add(anObjId);
688 mySelector->AddOrRemoveIndex( myIO, anIndexes, anIsShift );
689 mySelector->AddIObject( this );
696 mySelectionMode = aSelectionMode;
701 //----------------------------------------------------------------------------
704 ::SetPointPicker(vtkPointPicker* thePointPicker)
706 myPointPicker = thePointPicker;
711 ::SetCellPicker(vtkCellPicker* theCellPicker)
713 myCellPicker = theCellPicker;
718 ::SetPointRectPicker(SVTK_RectPicker* theRectPicker)
720 myPointRectPicker = theRectPicker;
725 ::SetCellRectPicker(SVTK_RectPicker* theRectPicker)
727 myCellRectPicker = theRectPicker;
730 //----------------------------------------------------------------------------
733 ::SetPreHighlightProperty(vtkProperty* theProperty)
735 myPreHighlightActor->SetProperty(theProperty);
740 ::SetHighlightProperty(vtkProperty* theProperty)
742 myHighlightActor->SetProperty(theProperty);