1 // Copyright (C) 2007-2013 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.
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>
51 // undefining min and max because CASCADE's defines them and
52 // it clashes with std::min(), std::max() included in utilities.h
57 vtkStandardNewMacro(SVTK_Renderer);
64 myDevice(VTKViewer_OpenGLRenderer::New()),
67 myEventCallbackCommand(vtkCallbackCommand::New()),
68 myPointPicker(vtkPointPicker::New()),
69 myCellPicker(vtkCellPicker::New()),
70 myPointAreaPicker(SVTK_AreaPicker::New()),
71 myCellAreaPicker(SVTK_AreaPicker::New()),
72 myPreHighlightProperty(vtkProperty::New()),
73 myHighlightProperty(vtkProperty::New()),
74 myTransform(VTKViewer_Transform::New()),
75 myCubeAxes(SVTK_CubeAxesActor2D::New()),
76 myTrihedron(SVTK_Trihedron::New()),
78 myIsTrihedronRelative(true)
81 myTransform->Delete();
83 myPointPicker->Delete();
84 myCellPicker->Delete();
86 myPointAreaPicker->Delete();
87 myPointAreaPicker->PickFromListOn();
89 myCellAreaPicker->Delete();
90 myCellAreaPicker->PickFromListOn();
91 myCellAreaPicker->PickPointsOff();
93 //SetPreselectionProp();
94 myPreHighlightProperty->Delete();
95 myPreHighlightProperty->SetColor(0,1,1);
96 myPreHighlightProperty->SetPointSize(SALOME_POINT_SIZE+2);
97 myPreHighlightProperty->SetLineWidth(SALOME_LINE_WIDTH+2);
98 myPreHighlightProperty->SetRepresentationToPoints();
100 //SetSelectionProp();
101 myHighlightProperty->Delete();
102 myHighlightProperty->SetColor(1,1,0);
103 myHighlightProperty->SetPointSize(SALOME_POINT_SIZE+2);
104 myHighlightProperty->SetLineWidth(SALOME_LINE_WIDTH+2);
105 myHighlightProperty->SetRepresentationToPoints();
107 // Bug 0020123, note 0005217 - Problem with zoom
108 GetDevice()->SetNearClippingPlaneTolerance( 0.00001 );
110 myTrihedron->Delete();
111 myCubeAxes->Delete();
112 myEventCallbackCommand->Delete();
114 myTrihedron->AddToRender(GetDevice());
115 GetDevice()->AddViewProp(GetCubeAxes());
117 myBndBox[0] = myBndBox[2] = myBndBox[4] = 0;
118 myBndBox[1] = myBndBox[3] = myBndBox[5] = myTrihedron->GetSize();
120 myCubeAxes->SetBounds(myBndBox);
121 myCubeAxes->SetCamera(GetDevice()->GetActiveCamera());
123 myCubeAxes->SetLabelFormat("%6.4g");
124 myCubeAxes->SetFlyModeToOuterEdges(); // ENK remarks: it must bee
125 myCubeAxes->SetFontFactor(0.8);
126 myCubeAxes->SetCornerOffset(0);
127 myCubeAxes->SetScaling(0);
128 myCubeAxes->SetNumberOfLabels(5);
129 myCubeAxes->VisibilityOff();
130 myCubeAxes->SetTransform(GetTransform());
132 vtkTextProperty* aTextProp = vtkTextProperty::New();
133 aTextProp->SetColor(1, 1, 1);
134 aTextProp->ShadowOn();
135 myCubeAxes->SetAxisTitleTextProperty(aTextProp);
136 myCubeAxes->SetAxisLabelTextProperty(aTextProp);
139 GetDevice()->GetActiveCamera()->ParallelProjectionOn();
140 GetDevice()->LightFollowCameraOn();
141 GetDevice()->TwoSidedLightingOn();
143 myEventCallbackCommand->SetClientData(this);
144 myEventCallbackCommand->SetCallback(SVTK_Renderer::ProcessEvents);
145 GetDevice()->AddObserver(vtkCommand::ConfigureEvent,
146 myEventCallbackCommand.GetPointer(),
148 GetDevice()->AddObserver(vtkCommand::ResetCameraEvent,
149 myEventCallbackCommand.GetPointer(),
151 GetDevice()->AddObserver(vtkCommand::ResetCameraClippingRangeEvent,
152 myEventCallbackCommand.GetPointer(),
162 VTK::ActorCollectionCopy aCopy(GetDevice()->GetActors());
163 vtkActorCollection* anActors = aCopy.GetActors();
164 vtkActorCollection* anActors2 = vtkActorCollection::New();
166 anActors->InitTraversal();
167 while(vtkActor* anAct = anActors->GetNextActor()){
168 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
169 anActors2->AddItem(anActor);
173 anActors2->InitTraversal();
174 while(vtkActor* anAct = anActors2->GetNextActor()){
175 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
176 RemoveActor(anActor);
185 Main process event method
189 ::ProcessEvents(vtkObject* vtkNotUsed(theObject),
190 unsigned long theEvent,
192 void* vtkNotUsed(theCallData))
194 SVTK_Renderer* self = reinterpret_cast<SVTK_Renderer*>(theClientData);
197 case vtkCommand::ConfigureEvent:
200 case vtkCommand::ResetCameraEvent:
203 case vtkCommand::ResetCameraClippingRangeEvent:
204 self->OnResetClippingRange();
210 \return renderer's device
216 return myDevice.GetPointer();
224 ::Initialize(vtkRenderWindowInteractor* theInteractor,
225 SVTK_Selector* theSelector)
227 myInteractor = theInteractor;
228 mySelector = theSelector;
229 SetSelectionTolerance();
233 Publishes pointed actor into the renderer
237 ::AddActor(VTKViewer_Actor* theActor, bool theIsAdjustActors)
239 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(theActor)){
240 anActor->SetInteractor(myInteractor);
241 anActor->SetTransform(GetTransform());
242 anActor->SetSelector(mySelector.GetPointer());
244 anActor->SetPointPicker(myPointPicker.GetPointer());
245 anActor->SetCellPicker(myCellPicker.GetPointer());
247 anActor->SetPointAreaPicker(myPointAreaPicker.GetPointer());
248 anActor->SetCellAreaPicker(myCellAreaPicker.GetPointer());
250 anActor->SetPreHighlightProperty(myPreHighlightProperty.GetPointer());
251 anActor->SetHighlightProperty(myHighlightProperty.GetPointer());
253 anActor->AddToRender(GetDevice());
254 anActor->UpdateNameActors();
256 if(theIsAdjustActors)
262 Removes pointed actor from the renderer
266 ::RemoveActor(VTKViewer_Actor* theActor, bool theIsAdjustActors)
268 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(theActor)){
269 // Order of the calls are important because VTKViewer_Actor::RemoveFromRender
270 // can leads do destruction of the actor
271 anActor->SetInteractor(NULL);
272 anActor->SetTransform(NULL);
273 anActor->SetSelector(NULL);
275 anActor->SetPointPicker(NULL);
276 anActor->SetCellPicker(NULL);
278 anActor->SetPointAreaPicker(NULL);
279 anActor->SetCellAreaPicker(NULL);
281 anActor->SetPreHighlightProperty(NULL);
282 anActor->SetHighlightProperty(NULL);
284 anActor->RemoveFromRender(GetDevice());
286 if(theIsAdjustActors)
292 Get special container that keeps scaling of the scene
298 return myTransform.GetPointer();
302 Allows to get a scale that is applied on the whole scene
306 ::GetScale( double theScale[3] )
308 myTransform->GetMatrixScale( theScale );
312 Allows to apply a scale on the whole scene
316 ::SetScale( double theScale[3] )
318 myTransform->SetMatrixScale( theScale[0], theScale[1], theScale[2] );
321 VTK::ActorCollectionCopy aCopy(GetDevice()->GetActors());
322 vtkActorCollection* anActors = aCopy.GetActors();
323 anActors->InitTraversal();
324 while(vtkActor* anAct = anActors->GetNextActor())
325 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct))
326 if(anActor->isHighlighted() && !anActor->IsInfinitive())
327 anActor->highlight(true);
331 Applies color and size (PointSize and LineWidth) of primitives in selection mode
335 ::SetSelectionProp(const double& theRed,
336 const double& theGreen,
337 const double& theBlue,
340 myHighlightProperty->SetColor( theRed, theGreen, theBlue );
341 myHighlightProperty->SetLineWidth( theWidth );
342 myHighlightProperty->SetPointSize( theWidth );
346 Applies color and size (PointSize and LineWidth) of primitives in preselection mode
350 ::SetPreselectionProp(const double& theRed,
351 const double& theGreen,
352 const double& theBlue,
355 myPreHighlightProperty->SetColor( theRed, theGreen, theBlue );
356 myPreHighlightProperty->SetLineWidth( theWidth );
357 myPreHighlightProperty->SetPointSize( theWidth );
361 Setup requested tolerance for the picking
365 ::SetSelectionTolerance(const double& theTolNodes,
366 const double& theTolCell,
367 const double& theTolObjects)
369 myPointPicker->SetTolerance( theTolNodes );
370 myCellPicker->SetTolerance( theTolCell );
372 myPointAreaPicker->SetTolerance( theTolNodes );
373 myCellAreaPicker->SetTolerance( theTolCell );
375 mySelector->SetTolerance( theTolObjects );
379 /*! If parameter theIsForcedUpdate is true, recalculate parameters for
380 * trihedron and cube axes, even if trihedron and cube axes is invisible.
385 CheckBndBox(const double theBounds[6])
387 if(theBounds[0] > -VTK_LARGE_FLOAT && theBounds[1] < VTK_LARGE_FLOAT &&
388 theBounds[2] > -VTK_LARGE_FLOAT && theBounds[3] < VTK_LARGE_FLOAT &&
389 theBounds[4] > -VTK_LARGE_FLOAT && theBounds[5] < VTK_LARGE_FLOAT)
395 Adjusts size of actors
401 bool aTDisplayed = IsTrihedronDisplayed();
402 bool aCDisplayed = IsCubeAxesDisplayed();
404 double aNewBndBox[6];
405 aNewBndBox[ 0 ] = aNewBndBox[ 2 ] = aNewBndBox[ 4 ] = VTK_LARGE_FLOAT;
406 aNewBndBox[ 1 ] = aNewBndBox[ 3 ] = aNewBndBox[ 5 ] = -VTK_LARGE_FLOAT;
408 int aVisibleNum = myTrihedron->GetVisibleActorCount(GetDevice());
411 myTrihedron->VisibilityOff();
414 myCubeAxes->VisibilityOff();
416 // if the new trihedron size have sufficient difference, then apply the value
417 double aSize = myTrihedron->GetSize();
418 if ( IsTrihedronRelative() )
420 ComputeTrihedronSize(GetDevice(),aSize,aSize,myTrihedronSize);
421 myTrihedron->SetSize(aSize);
424 myTrihedron->SetSize( myTrihedronSize );
426 // iterate through displayed objects and set size if necessary
427 VTK::ActorCollectionCopy aCopy(GetDevice()->GetActors());
428 vtkActorCollection* anActors = aCopy.GetActors();
429 anActors->InitTraversal();
430 while(vtkActor* anAct = anActors->GetNextActor()){
431 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
432 if(anActor->IsResizable())
433 anActor->SetSize(0.5*aSize);
434 if(anActor->GetVisibility() && !anActor->IsInfinitive()){
435 double *aBounds = anActor->GetBounds();
436 if(CheckBndBox(aBounds))
437 for(int i = 0; i < 5; i = i + 2){
438 if(aBounds[i] < aNewBndBox[i])
439 aNewBndBox[i] = aBounds[i];
440 if(aBounds[i+1] > aNewBndBox[i+1])
441 aNewBndBox[i+1] = aBounds[i+1];
448 myTrihedron->VisibilityOn();
451 myCubeAxes->VisibilityOn();
454 double aSize = myTrihedron->GetSize();
455 aNewBndBox[0] = aNewBndBox[2] = aNewBndBox[4] = 0;
456 aNewBndBox[1] = aNewBndBox[3] = aNewBndBox[5] = aSize;
459 if(CheckBndBox(aNewBndBox)){
460 for(int i = 0; i < 6; i++)
461 myBndBox[i] = aNewBndBox[i];
462 myCubeAxes->SetBounds(myBndBox);
470 Adjusts size of actors
477 ::ResetCameraClippingRange(GetDevice());
481 Set size of the trihedron
482 \param theSize - new size
483 \param theRelative - if it is true, then size is mesured in percents from bounding box of the scene,
484 otherwise - in viewer units
488 ::SetTrihedronSize(double theSize, const bool theRelative)
490 if(myTrihedronSize != theSize || myIsTrihedronRelative != theRelative){
491 myTrihedronSize = theSize;
492 myIsTrihedronRelative = theRelative;
498 \return size of the trihedron in percents from bounding box of the scene
502 ::GetTrihedronSize() const
504 return myTrihedronSize;
508 \return true if the size of the trihedron is relative
512 ::IsTrihedronRelative() const
514 return myIsTrihedronRelative;
518 \return trihedron control
524 return myTrihedron.GetPointer();
528 \return true if trihedron is displayed
532 ::IsTrihedronDisplayed()
534 return myTrihedron->GetVisibility() == VTKViewer_Trihedron::eOn;
538 Toggle trihedron visibility
544 if(IsTrihedronDisplayed())
545 myTrihedron->VisibilityOff();
547 myTrihedron->VisibilityOn();
551 Adjust size of the trihedron to the bounding box of the scene
555 ::OnAdjustTrihedron()
561 \return graduated rules control
563 SVTK_CubeAxesActor2D*
567 return myCubeAxes.GetPointer();
571 \return true if graduated rules displayed
575 ::IsCubeAxesDisplayed()
577 return myCubeAxes->GetVisibility() == 1;
581 Toggle graduated rules visibility
587 if(IsCubeAxesDisplayed())
588 myCubeAxes->VisibilityOff();
590 myCubeAxes->VisibilityOn();
594 Adjust size of the graduated rules to the bounding box of the scene
604 Sets camera into predefined state
610 int aTrihedronIsVisible = IsTrihedronDisplayed();
611 int aCubeAxesIsVisible = IsCubeAxesDisplayed();
613 myTrihedron->SetVisibility( VTKViewer_Trihedron::eOnlyLineOn );
614 myCubeAxes->SetVisibility(0);
616 ::ResetCamera(GetDevice(),true);
617 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
618 aCamera->SetPosition(1,-1,1);
619 aCamera->SetViewUp(0,0,1);
620 ::ResetCamera(GetDevice(),true);
622 if(aTrihedronIsVisible)
623 myTrihedron->VisibilityOn();
625 myTrihedron->VisibilityOff();
627 if(aCubeAxesIsVisible)
628 myCubeAxes->VisibilityOn();
630 myCubeAxes->VisibilityOff();
632 static double aCoeff = 3.0;
633 aCamera->SetParallelScale(aCoeff*aCamera->GetParallelScale());
637 Fit all presentation in the scene into the window
643 int aTrihedronWasVisible = false;
644 int aCubeAxesWasVisible = false;
646 aTrihedronWasVisible = IsTrihedronDisplayed();
647 if(aTrihedronWasVisible)
648 myTrihedron->VisibilityOff();
650 aCubeAxesWasVisible = IsCubeAxesDisplayed();
651 if(aCubeAxesWasVisible)
652 myCubeAxes->VisibilityOff();
654 if(myTrihedron->GetVisibleActorCount(GetDevice())){
655 myTrihedron->VisibilityOff();
656 myCubeAxes->VisibilityOff();
657 ::ResetCamera(GetDevice());
659 myTrihedron->SetVisibility(VTKViewer_Trihedron::eOnlyLineOn);
660 myCubeAxes->SetVisibility(2);
661 ::ResetCamera(GetDevice(),true);
664 if(aTrihedronWasVisible)
665 myTrihedron->VisibilityOn();
667 myTrihedron->VisibilityOff();
669 if(aCubeAxesWasVisible)
670 myCubeAxes->VisibilityOn();
672 myCubeAxes->VisibilityOff();
674 ::ResetCameraClippingRange(GetDevice());
678 Reset camera clipping range to adjust the range to the bounding box of the scene
682 ::OnResetClippingRange()
685 ::ResetCameraClippingRange(GetDevice());
689 To reset direction of the camera to front view
695 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
696 aCamera->SetPosition(1,0,0);
697 aCamera->SetViewUp(0,0,1);
698 aCamera->SetFocalPoint(0,0,0);
703 To reset direction of the camera to back view
709 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
710 aCamera->SetPosition(-1,0,0);
711 aCamera->SetViewUp(0,0,1);
712 aCamera->SetFocalPoint(0,0,0);
717 To reset direction of the camera to top view
723 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
724 aCamera->SetPosition(0,0,1);
725 aCamera->SetViewUp(0,1,0);
726 aCamera->SetFocalPoint(0,0,0);
731 To reset direction of the camera to bottom view
737 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
738 aCamera->SetPosition(0,0,-1);
739 aCamera->SetViewUp(0,1,0);
740 aCamera->SetFocalPoint(0,0,0);
745 To reset direction of the camera to left view
751 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
752 aCamera->SetPosition(0,-1,0);
753 aCamera->SetViewUp(0,0,1);
754 aCamera->SetFocalPoint(0,0,0);
760 To rotate view 90 degrees clockwise
766 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
768 aCamera->OrthogonalizeViewUp();
772 To rotate view 90 degrees counterclockwise
776 ::onAntiClockWiseView()
778 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
780 aCamera->OrthogonalizeViewUp();
784 To reset direction of the camera to right view
790 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
791 aCamera->SetPosition(0,1,0);
792 aCamera->SetViewUp(0,0,1);
793 aCamera->SetFocalPoint(0,0,0);