1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
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
23 // SALOME VTKViewer : build VTK viewer into Salome desktop
27 #include "SVTK_Renderer.h"
29 #include "SVTK_Trihedron.h"
30 #include "SVTK_CubeAxesActor2D.h"
31 #include "SVTK_AreaPicker.h"
33 #include "SALOME_Actor.h"
34 #include "VTKViewer_Actor.h"
35 #include "VTKViewer_Algorithm.h"
36 #include "VTKViewer_Transform.h"
37 #include "VTKViewer_Utilities.h"
38 #include "VTKViewer_OpenGLRenderer.h"
40 #include <vtkCamera.h>
41 #include <vtkTextProperty.h>
42 #include <vtkObjectFactory.h>
43 #include <vtkCallbackCommand.h>
45 #include <vtkPicker.h>
46 #include <vtkPointPicker.h>
47 #include <vtkCellPicker.h>
49 #include <vtkProperty.h>
50 #include <vtkProp3DCollection.h>
52 // undefining min and max because CASCADE's defines them and
53 // it clashes with std::min(), std::max() included in utilities.h
58 vtkStandardNewMacro(SVTK_Renderer);
65 myDevice(VTKViewer_OpenGLRenderer::New()),
68 myEventCallbackCommand(vtkCallbackCommand::New()),
69 myPointPicker(vtkPointPicker::New()),
70 myCellPicker(vtkCellPicker::New()),
71 myPointAreaPicker(SVTK_AreaPicker::New()),
72 myCellAreaPicker(SVTK_AreaPicker::New()),
73 myPreHighlightProperty(vtkProperty::New()),
74 myHighlightProperty(vtkProperty::New()),
75 myTransform(VTKViewer_Transform::New()),
76 myCubeAxes(SVTK_CubeAxesActor2D::New()),
77 myTrihedron(SVTK_Trihedron::New()),
79 myIsTrihedronRelative(true)
82 myTransform->Delete();
84 myPointPicker->Delete();
85 myCellPicker->Delete();
87 myPointAreaPicker->Delete();
88 myPointAreaPicker->PickFromListOn();
90 myCellAreaPicker->Delete();
91 myCellAreaPicker->PickFromListOn();
92 myCellAreaPicker->PickPointsOff();
94 //SetPreselectionProp();
95 myPreHighlightProperty->Delete();
96 myPreHighlightProperty->SetColor(0,1,1);
97 myPreHighlightProperty->SetPointSize(SALOME_POINT_SIZE+2);
98 myPreHighlightProperty->SetLineWidth(SALOME_LINE_WIDTH+2);
99 myPreHighlightProperty->SetRepresentationToPoints();
101 //SetSelectionProp();
102 myHighlightProperty->Delete();
103 myHighlightProperty->SetColor(1,1,0);
104 myHighlightProperty->SetPointSize(SALOME_POINT_SIZE+2);
105 myHighlightProperty->SetLineWidth(SALOME_LINE_WIDTH+2);
106 myHighlightProperty->SetRepresentationToPoints();
108 // Bug 0020123, note 0005217 - Problem with zoom
109 GetDevice()->SetNearClippingPlaneTolerance( 0.00001 );
111 myTrihedron->Delete();
112 myCubeAxes->Delete();
113 myEventCallbackCommand->Delete();
115 myTrihedron->AddToRender(GetDevice());
116 GetDevice()->AddViewProp(GetCubeAxes());
118 myBndBox[0] = myBndBox[2] = myBndBox[4] = 0;
119 myBndBox[1] = myBndBox[3] = myBndBox[5] = myTrihedron->GetSize();
121 myCubeAxes->SetBounds(myBndBox);
122 myCubeAxes->SetCamera(GetDevice()->GetActiveCamera());
124 myCubeAxes->SetLabelFormat("%6.4g");
125 myCubeAxes->SetFlyModeToOuterEdges(); // ENK remarks: it must bee
126 myCubeAxes->SetFontFactor(0.8);
127 myCubeAxes->SetCornerOffset(0);
128 myCubeAxes->SetScaling(0);
129 myCubeAxes->SetNumberOfLabels(5);
130 myCubeAxes->VisibilityOff();
131 myCubeAxes->SetTransform(GetTransform());
133 vtkTextProperty* aTextProp = vtkTextProperty::New();
134 aTextProp->SetColor(1, 1, 1);
135 aTextProp->ShadowOn();
136 myCubeAxes->SetAxisTitleTextProperty(aTextProp);
137 myCubeAxes->SetAxisLabelTextProperty(aTextProp);
140 GetDevice()->GetActiveCamera()->ParallelProjectionOn();
141 GetDevice()->LightFollowCameraOn();
142 GetDevice()->TwoSidedLightingOn();
144 myEventCallbackCommand->SetClientData(this);
145 myEventCallbackCommand->SetCallback(SVTK_Renderer::ProcessEvents);
146 GetDevice()->AddObserver(vtkCommand::ConfigureEvent,
147 myEventCallbackCommand.GetPointer(),
149 GetDevice()->AddObserver(vtkCommand::ResetCameraEvent,
150 myEventCallbackCommand.GetPointer(),
152 GetDevice()->AddObserver(vtkCommand::ResetCameraClippingRangeEvent,
153 myEventCallbackCommand.GetPointer(),
163 VTK::ActorCollectionCopy aCopy(GetDevice()->GetActors());
164 vtkActorCollection* anActors = aCopy.GetActors();
165 vtkActorCollection* anActors2 = vtkActorCollection::New();
167 anActors->InitTraversal();
168 while(vtkActor* anAct = anActors->GetNextActor()){
169 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
170 anActors2->AddItem(anActor);
174 anActors2->InitTraversal();
175 while(vtkActor* anAct = anActors2->GetNextActor()){
176 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
177 RemoveActor(anActor);
186 Main process event method
190 ::ProcessEvents(vtkObject* vtkNotUsed(theObject),
191 unsigned long theEvent,
193 void* vtkNotUsed(theCallData))
195 SVTK_Renderer* self = reinterpret_cast<SVTK_Renderer*>(theClientData);
198 case vtkCommand::ConfigureEvent:
201 case vtkCommand::ResetCameraEvent:
204 case vtkCommand::ResetCameraClippingRangeEvent:
205 self->OnResetClippingRange();
211 \return renderer's device
217 return myDevice.GetPointer();
225 ::Initialize(vtkRenderWindowInteractor* theInteractor,
226 SVTK_Selector* theSelector)
228 myInteractor = theInteractor;
229 mySelector = theSelector;
230 SetSelectionTolerance();
234 Publishes pointed actor into the renderer
238 ::AddActor(VTKViewer_Actor* theActor, bool theIsAdjustActors)
240 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(theActor)){
241 anActor->SetInteractor(myInteractor);
242 anActor->SetTransform(GetTransform());
243 anActor->SetSelector(mySelector.GetPointer());
245 anActor->SetPointPicker(myPointPicker.GetPointer());
246 anActor->SetCellPicker(myCellPicker.GetPointer());
248 anActor->SetPointAreaPicker(myPointAreaPicker.GetPointer());
249 anActor->SetCellAreaPicker(myCellAreaPicker.GetPointer());
251 anActor->SetPreHighlightProperty(myPreHighlightProperty.GetPointer());
252 anActor->SetHighlightProperty(myHighlightProperty.GetPointer());
254 anActor->AddToRender(GetDevice());
255 anActor->UpdateNameActors();
257 if(theIsAdjustActors)
263 Removes pointed actor from the renderer
267 ::RemoveActor(VTKViewer_Actor* theActor, bool theIsAdjustActors)
269 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(theActor)){
270 // Order of the calls are important because VTKViewer_Actor::RemoveFromRender
271 // can leads do destruction of the actor
272 anActor->SetInteractor(NULL);
273 anActor->SetTransform(NULL);
274 anActor->SetSelector(NULL);
276 anActor->SetPointPicker(NULL);
277 anActor->SetCellPicker(NULL);
279 anActor->SetPointAreaPicker(NULL);
280 anActor->SetCellAreaPicker(NULL);
282 anActor->SetPreHighlightProperty(NULL);
283 anActor->SetHighlightProperty(NULL);
285 anActor->RemoveFromRender(GetDevice());
287 while ( int i = myPointPicker->GetProp3Ds()->IsItemPresent( theActor ))
288 myPointPicker->GetProp3Ds()->RemoveItem( i-1 );
289 while ( int i = myCellPicker->GetProp3Ds()->IsItemPresent( theActor ))
290 myCellPicker->GetProp3Ds()->RemoveItem( i-1 );
292 while ( int i = myPointPicker->GetActors()->IsItemPresent( theActor ))
293 myPointPicker->GetActors()->RemoveItem( i-1 );
294 while ( int i = myCellPicker->GetActors()->IsItemPresent( theActor ))
295 myCellPicker->GetActors()->RemoveItem( i-1 );
297 if(theIsAdjustActors)
303 Get special container that keeps scaling of the scene
309 return myTransform.GetPointer();
313 Allows to get a scale that is applied on the whole scene
317 ::GetScale( double theScale[3] )
319 myTransform->GetMatrixScale( theScale );
323 Allows to apply a scale on the whole scene
327 ::SetScale( double theScale[3] )
329 myTransform->SetMatrixScale( theScale[0], theScale[1], theScale[2] );
332 VTK::ActorCollectionCopy aCopy(GetDevice()->GetActors());
333 vtkActorCollection* anActors = aCopy.GetActors();
334 anActors->InitTraversal();
335 while(vtkActor* anAct = anActors->GetNextActor())
336 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct))
337 if(anActor->isHighlighted() && !anActor->IsInfinitive())
338 anActor->highlight(true);
342 Applies color and size (PointSize and LineWidth) of primitives in selection mode
346 ::SetSelectionProp(const double& theRed,
347 const double& theGreen,
348 const double& theBlue,
351 myHighlightProperty->SetColor( theRed, theGreen, theBlue );
352 myHighlightProperty->SetLineWidth( theWidth );
353 myHighlightProperty->SetPointSize( theWidth );
357 Applies color and size (PointSize and LineWidth) of primitives in preselection mode
361 ::SetPreselectionProp(const double& theRed,
362 const double& theGreen,
363 const double& theBlue,
366 myPreHighlightProperty->SetColor( theRed, theGreen, theBlue );
367 myPreHighlightProperty->SetLineWidth( theWidth );
368 myPreHighlightProperty->SetPointSize( theWidth );
372 Setup requested tolerance for the picking
376 ::SetSelectionTolerance(const double& theTolNodes,
377 const double& theTolCell,
378 const double& theTolObjects)
380 myPointPicker->SetTolerance( theTolNodes );
381 myCellPicker->SetTolerance( theTolCell );
383 myPointAreaPicker->SetTolerance( theTolNodes );
384 myCellAreaPicker->SetTolerance( theTolCell );
386 mySelector->SetTolerance( theTolObjects );
390 /*! If parameter theIsForcedUpdate is true, recalculate parameters for
391 * trihedron and cube axes, even if trihedron and cube axes is invisible.
396 CheckBndBox(const double theBounds[6])
398 if(theBounds[0] > -VTK_LARGE_FLOAT && theBounds[1] < VTK_LARGE_FLOAT &&
399 theBounds[2] > -VTK_LARGE_FLOAT && theBounds[3] < VTK_LARGE_FLOAT &&
400 theBounds[4] > -VTK_LARGE_FLOAT && theBounds[5] < VTK_LARGE_FLOAT)
406 Adjusts size of actors
412 bool aTDisplayed = IsTrihedronDisplayed();
413 bool aCDisplayed = IsCubeAxesDisplayed();
415 double aNewBndBox[6];
416 aNewBndBox[ 0 ] = aNewBndBox[ 2 ] = aNewBndBox[ 4 ] = VTK_LARGE_FLOAT;
417 aNewBndBox[ 1 ] = aNewBndBox[ 3 ] = aNewBndBox[ 5 ] = -VTK_LARGE_FLOAT;
419 int aVisibleNum = myTrihedron->GetVisibleActorCount(GetDevice());
422 myTrihedron->VisibilityOff();
425 myCubeAxes->VisibilityOff();
427 // if the new trihedron size have sufficient difference, then apply the value
428 double aSize = myTrihedron->GetSize();
429 if ( IsTrihedronRelative() )
431 ComputeTrihedronSize(GetDevice(),aSize,aSize,myTrihedronSize);
432 myTrihedron->SetSize(aSize);
435 myTrihedron->SetSize( myTrihedronSize );
437 // iterate through displayed objects and set size if necessary
438 VTK::ActorCollectionCopy aCopy(GetDevice()->GetActors());
439 vtkActorCollection* anActors = aCopy.GetActors();
440 anActors->InitTraversal();
441 while(vtkActor* anAct = anActors->GetNextActor()){
442 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
443 if(anActor->IsResizable())
444 anActor->SetSize(0.5*aSize);
445 if(anActor->GetVisibility() && !anActor->IsInfinitive()){
446 double *aBounds = anActor->GetBounds();
447 if(CheckBndBox(aBounds))
448 for(int i = 0; i < 5; i = i + 2){
449 if(aBounds[i] < aNewBndBox[i])
450 aNewBndBox[i] = aBounds[i];
451 if(aBounds[i+1] > aNewBndBox[i+1])
452 aNewBndBox[i+1] = aBounds[i+1];
459 myTrihedron->VisibilityOn();
462 myCubeAxes->VisibilityOn();
465 double aSize = myTrihedron->GetSize();
466 aNewBndBox[0] = aNewBndBox[2] = aNewBndBox[4] = 0;
467 aNewBndBox[1] = aNewBndBox[3] = aNewBndBox[5] = aSize;
470 if(CheckBndBox(aNewBndBox)){
471 for(int i = 0; i < 6; i++)
472 myBndBox[i] = aNewBndBox[i];
473 myCubeAxes->SetBounds(myBndBox);
481 Adjusts size of actors
488 ::ResetCameraClippingRange(GetDevice());
492 Set size of the trihedron
493 \param theSize - new size
494 \param theRelative - if it is true, then size is mesured in percents from bounding box of the scene,
495 otherwise - in viewer units
499 ::SetTrihedronSize(double theSize, const bool theRelative)
501 if(myTrihedronSize != theSize || myIsTrihedronRelative != theRelative){
502 myTrihedronSize = theSize;
503 myIsTrihedronRelative = theRelative;
509 \return size of the trihedron in percents from bounding box of the scene
513 ::GetTrihedronSize() const
515 return myTrihedronSize;
519 \return true if the size of the trihedron is relative
523 ::IsTrihedronRelative() const
525 return myIsTrihedronRelative;
529 \return trihedron control
535 return myTrihedron.GetPointer();
539 \return true if trihedron is displayed
543 ::IsTrihedronDisplayed()
545 return myTrihedron->GetVisibility() == VTKViewer_Trihedron::eOn;
549 Toggle trihedron visibility
555 if(IsTrihedronDisplayed())
556 myTrihedron->VisibilityOff();
558 myTrihedron->VisibilityOn();
562 Set trihedron visibility
566 ::SetTrihedronVisibility( const bool show ) {
568 myTrihedron->VisibilityOn();
570 myTrihedron->VisibilityOff();
574 Adjust size of the trihedron to the bounding box of the scene
578 ::OnAdjustTrihedron()
584 \return graduated rules control
586 SVTK_CubeAxesActor2D*
590 return myCubeAxes.GetPointer();
594 \return true if graduated rules displayed
598 ::IsCubeAxesDisplayed()
600 return myCubeAxes->GetVisibility() == 1;
604 Toggle graduated rules visibility
610 if(IsCubeAxesDisplayed())
611 myCubeAxes->VisibilityOff();
613 myCubeAxes->VisibilityOn();
617 Adjust size of the graduated rules to the bounding box of the scene
627 Sets camera into predefined state
633 int aTrihedronIsVisible = IsTrihedronDisplayed();
634 int aCubeAxesIsVisible = IsCubeAxesDisplayed();
636 myTrihedron->SetVisibility( VTKViewer_Trihedron::eOnlyLineOn );
637 myCubeAxes->SetVisibility(0);
639 ::ResetCamera(GetDevice(),true);
640 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
641 aCamera->SetPosition(1,-1,1);
642 aCamera->SetViewUp(0,0,1);
643 ::ResetCamera(GetDevice(),true);
645 if(aTrihedronIsVisible)
646 myTrihedron->VisibilityOn();
648 myTrihedron->VisibilityOff();
650 if(aCubeAxesIsVisible)
651 myCubeAxes->VisibilityOn();
653 myCubeAxes->VisibilityOff();
655 static double aCoeff = 3.0;
656 aCamera->SetParallelScale(aCoeff*aCamera->GetParallelScale());
660 Fit all presentation in the scene into the window
666 int aTrihedronWasVisible = false;
667 int aCubeAxesWasVisible = false;
669 aTrihedronWasVisible = IsTrihedronDisplayed();
670 if(aTrihedronWasVisible)
671 myTrihedron->VisibilityOff();
673 aCubeAxesWasVisible = IsCubeAxesDisplayed();
674 if(aCubeAxesWasVisible)
675 myCubeAxes->VisibilityOff();
677 if(myTrihedron->GetVisibleActorCount(GetDevice())){
678 myTrihedron->VisibilityOff();
679 myCubeAxes->VisibilityOff();
680 ::ResetCamera(GetDevice());
682 myTrihedron->SetVisibility(VTKViewer_Trihedron::eOnlyLineOn);
683 myCubeAxes->SetVisibility(2);
684 ::ResetCamera(GetDevice(),true);
687 if(aTrihedronWasVisible)
688 myTrihedron->VisibilityOn();
690 myTrihedron->VisibilityOff();
692 if(aCubeAxesWasVisible)
693 myCubeAxes->VisibilityOn();
695 myCubeAxes->VisibilityOff();
697 ::ResetCameraClippingRange(GetDevice());
701 Reset camera clipping range to adjust the range to the bounding box of the scene
705 ::OnResetClippingRange()
708 ::ResetCameraClippingRange(GetDevice());
712 To reset direction of the camera to front view
718 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
719 aCamera->SetPosition(1,0,0);
720 aCamera->SetViewUp(0,0,1);
721 aCamera->SetFocalPoint(0,0,0);
726 To reset direction of the camera to back view
732 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
733 aCamera->SetPosition(-1,0,0);
734 aCamera->SetViewUp(0,0,1);
735 aCamera->SetFocalPoint(0,0,0);
740 To reset direction of the camera to top view
746 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
747 aCamera->SetPosition(0,0,1);
748 aCamera->SetViewUp(0,1,0);
749 aCamera->SetFocalPoint(0,0,0);
754 To reset direction of the camera to bottom view
760 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
761 aCamera->SetPosition(0,0,-1);
762 aCamera->SetViewUp(0,1,0);
763 aCamera->SetFocalPoint(0,0,0);
768 To reset direction of the camera to left view
774 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
775 aCamera->SetPosition(0,-1,0);
776 aCamera->SetViewUp(0,0,1);
777 aCamera->SetFocalPoint(0,0,0);
783 To rotate view 90 degrees clockwise
789 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
791 aCamera->OrthogonalizeViewUp();
795 To rotate view 90 degrees counterclockwise
799 ::onAntiClockWiseView()
801 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
803 aCamera->OrthogonalizeViewUp();
807 To reset direction of the camera to right view
813 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
814 aCamera->SetPosition(0,1,0);
815 aCamera->SetViewUp(0,0,1);
816 aCamera->SetFocalPoint(0,0,0);