1 // SALOME VTKViewer : build VTK viewer into Salome desktop
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
29 #include "SVTK_Renderer.h"
31 #include "SVTK_Trihedron.h"
32 #include "SVTK_CubeAxesActor2D.h"
33 #include "SVTK_RectPicker.h"
35 #include "SALOME_Actor.h"
36 #include "VTKViewer_Actor.h"
37 #include "VTKViewer_Transform.h"
38 #include "VTKViewer_Utilities.h"
40 #include <vtkCamera.h>
41 #include <vtkRenderer.h>
42 #include <vtkTextProperty.h>
43 #include <vtkObjectFactory.h>
44 #include <vtkCallbackCommand.h>
46 #include <vtkPicker.h>
47 #include <vtkPointPicker.h>
48 #include <vtkCellPicker.h>
50 #include <vtkProperty.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(vtkRenderer::New()),
68 myEventCallbackCommand(vtkCallbackCommand::New()),
69 myPointPicker(vtkPointPicker::New()),
70 myCellPicker(vtkCellPicker::New()),
71 myPointRectPicker(SVTK_RectPicker::New()),
72 myCellRectPicker(SVTK_RectPicker::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 myPointRectPicker->Delete();
88 myPointRectPicker->PickFromListOn();
90 myCellRectPicker->Delete();
91 myCellRectPicker->PickFromListOn();
92 myCellRectPicker->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 myTrihedron->Delete();
109 myCubeAxes->Delete();
110 myEventCallbackCommand->Delete();
112 myTrihedron->AddToRender(GetDevice());
113 GetDevice()->AddViewProp(GetCubeAxes());
115 myBndBox[0] = myBndBox[2] = myBndBox[4] = 0;
116 myBndBox[1] = myBndBox[3] = myBndBox[5] = myTrihedron->GetSize();
118 myCubeAxes->SetBounds(myBndBox);
119 myCubeAxes->SetCamera(GetDevice()->GetActiveCamera());
121 myCubeAxes->SetLabelFormat("%6.4g");
122 myCubeAxes->SetFlyModeToOuterEdges(); // ENK remarks: it must bee
123 myCubeAxes->SetFontFactor(0.8);
124 myCubeAxes->SetCornerOffset(0);
125 myCubeAxes->SetScaling(0);
126 myCubeAxes->SetNumberOfLabels(5);
127 myCubeAxes->VisibilityOff();
128 myCubeAxes->SetTransform(GetTransform());
130 vtkTextProperty* aTextProp = vtkTextProperty::New();
131 aTextProp->SetColor(1, 1, 1);
132 aTextProp->ShadowOn();
133 myCubeAxes->SetAxisTitleTextProperty(aTextProp);
134 myCubeAxes->SetAxisLabelTextProperty(aTextProp);
137 GetDevice()->GetActiveCamera()->ParallelProjectionOn();
138 GetDevice()->LightFollowCameraOn();
139 GetDevice()->TwoSidedLightingOn();
141 myEventCallbackCommand->SetClientData(this);
142 myEventCallbackCommand->SetCallback(SVTK_Renderer::ProcessEvents);
143 GetDevice()->AddObserver(vtkCommand::ConfigureEvent,
144 myEventCallbackCommand.GetPointer(),
146 GetDevice()->AddObserver(vtkCommand::ResetCameraEvent,
147 myEventCallbackCommand.GetPointer(),
149 GetDevice()->AddObserver(vtkCommand::ResetCameraClippingRangeEvent,
150 myEventCallbackCommand.GetPointer(),
160 vtkActorCollection* anActors = GetDevice()->GetActors();
161 vtkActorCollection* anActors2 = vtkActorCollection::New();
163 anActors->InitTraversal();
164 while(vtkActor* anAct = anActors->GetNextActor()){
165 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
166 anActors2->AddItem(anActor);
170 anActors2->InitTraversal();
171 while(vtkActor* anAct = anActors2->GetNextActor()){
172 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
173 RemoveActor(anActor);
182 Main process event method
186 ::ProcessEvents(vtkObject* vtkNotUsed(theObject),
187 unsigned long theEvent,
189 void* vtkNotUsed(theCallData))
191 SVTK_Renderer* self = reinterpret_cast<SVTK_Renderer*>(theClientData);
194 case vtkCommand::ConfigureEvent:
197 case vtkCommand::ResetCameraEvent:
200 case vtkCommand::ResetCameraClippingRangeEvent:
201 self->OnResetClippingRange();
207 \return renderer's device
213 return myDevice.GetPointer();
221 ::Initialize(vtkRenderWindowInteractor* theInteractor,
222 SVTK_Selector* theSelector)
224 myInteractor = theInteractor;
225 mySelector = theSelector;
226 SetSelectionTolerance();
230 Publishes pointed actor into the renderer
234 ::AddActor(VTKViewer_Actor* theActor)
236 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(theActor)){
237 anActor->SetInteractor(myInteractor);
238 anActor->SetTransform(GetTransform());
239 anActor->SetSelector(mySelector.GetPointer());
241 anActor->SetPointPicker(myPointPicker.GetPointer());
242 anActor->SetCellPicker(myCellPicker.GetPointer());
244 anActor->SetPointRectPicker(myPointRectPicker.GetPointer());
245 anActor->SetCellRectPicker(myCellRectPicker.GetPointer());
247 anActor->SetPreHighlightProperty(myPreHighlightProperty.GetPointer());
248 anActor->SetHighlightProperty(myHighlightProperty.GetPointer());
250 anActor->AddToRender(GetDevice());
256 Removes pointed actor from the renderer
260 ::RemoveActor(VTKViewer_Actor* theActor)
262 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(theActor)){
263 // Order of the calls are important because VTKViewer_Actor::RemoveFromRender
264 // can leads do destruction of the actor
265 anActor->SetInteractor(NULL);
266 anActor->SetTransform(NULL);
267 anActor->SetSelector(NULL);
269 anActor->SetPointPicker(NULL);
270 anActor->SetCellPicker(NULL);
272 anActor->SetPointRectPicker(NULL);
273 anActor->SetCellRectPicker(NULL);
275 anActor->SetPreHighlightProperty(NULL);
276 anActor->SetHighlightProperty(NULL);
278 anActor->RemoveFromRender(GetDevice());
284 Get special container that keeps scaling of the scene
290 return myTransform.GetPointer();
294 Allows to get a scale that is applied on the whole scene
298 ::GetScale( double theScale[3] )
300 myTransform->GetMatrixScale( theScale );
304 Allows to apply a scale on the whole scene
308 ::SetScale( double theScale[3] )
310 myTransform->SetMatrixScale( theScale[0], theScale[1], theScale[2] );
315 Applies color and size (PointSize and LineWidth) of primitives in selection mode
319 ::SetSelectionProp(const double& theRed,
320 const double& theGreen,
321 const double& theBlue,
324 myHighlightProperty->SetColor( theRed, theGreen, theBlue );
325 myHighlightProperty->SetLineWidth( theWidth );
326 myHighlightProperty->SetPointSize( theWidth );
330 Applies color and size (PointSize and LineWidth) of primitives in preselection mode
334 ::SetPreselectionProp(const double& theRed,
335 const double& theGreen,
336 const double& theBlue,
339 myPreHighlightProperty->SetColor( theRed, theGreen, theBlue );
340 myPreHighlightProperty->SetLineWidth( theWidth );
341 myPreHighlightProperty->SetPointSize( theWidth );
345 Setup requested tolerance for the picking
349 ::SetSelectionTolerance(const double& theTolNodes,
350 const double& theTolCell,
351 const double& theTolObjects)
353 myPointPicker->SetTolerance( theTolNodes );
354 myCellPicker->SetTolerance( theTolCell );
356 myPointRectPicker->SetTolerance( theTolNodes );
357 myCellRectPicker->SetTolerance( theTolCell );
359 mySelector->SetTolerance( theTolObjects );
363 /*! If parameter theIsForcedUpdate is true, recalculate parameters for
364 * trihedron and cube axes, even if trihedron and cube axes is invisible.
369 CheckBndBox(const vtkFloatingPointType theBounds[6])
371 if(theBounds[0] > -VTK_LARGE_FLOAT && theBounds[1] < VTK_LARGE_FLOAT &&
372 theBounds[2] > -VTK_LARGE_FLOAT && theBounds[3] < VTK_LARGE_FLOAT &&
373 theBounds[4] > -VTK_LARGE_FLOAT && theBounds[5] < VTK_LARGE_FLOAT)
379 Adjusts size of actors
385 bool aTDisplayed = IsTrihedronDisplayed();
386 bool aCDisplayed = IsCubeAxesDisplayed();
388 vtkFloatingPointType aNewBndBox[6];
389 aNewBndBox[ 0 ] = aNewBndBox[ 2 ] = aNewBndBox[ 4 ] = VTK_LARGE_FLOAT;
390 aNewBndBox[ 1 ] = aNewBndBox[ 3 ] = aNewBndBox[ 5 ] = -VTK_LARGE_FLOAT;
392 int aVisibleNum = myTrihedron->GetVisibleActorCount(GetDevice());
395 myTrihedron->VisibilityOff();
398 myCubeAxes->VisibilityOff();
400 // if the new trihedron size have sufficient difference, then apply the value
401 vtkFloatingPointType aSize = myTrihedron->GetSize();
402 if ( IsTrihedronRelative() )
404 ComputeTrihedronSize(GetDevice(),aSize,aSize,myTrihedronSize);
405 myTrihedron->SetSize(aSize);
408 myTrihedron->SetSize( myTrihedronSize );
410 // iterate through displayed objects and set size if necessary
411 vtkActorCollection* anActors = GetDevice()->GetActors();
412 anActors->InitTraversal();
413 while(vtkActor* anAct = anActors->GetNextActor()){
414 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
415 if(anActor->IsResizable())
416 anActor->SetSize(0.5*aSize);
417 if(anActor->GetVisibility() && !anActor->IsInfinitive()){
418 vtkFloatingPointType *aBounds = anActor->GetBounds();
419 if(CheckBndBox(aBounds))
420 for(int i = 0; i < 5; i = i + 2){
421 if(aBounds[i] < aNewBndBox[i])
422 aNewBndBox[i] = aBounds[i];
423 if(aBounds[i+1] > aNewBndBox[i+1])
424 aNewBndBox[i+1] = aBounds[i+1];
431 myTrihedron->VisibilityOn();
434 myCubeAxes->VisibilityOn();
437 double aSize = myTrihedron->GetSize();
438 aNewBndBox[0] = aNewBndBox[2] = aNewBndBox[4] = 0;
439 aNewBndBox[1] = aNewBndBox[3] = aNewBndBox[5] = aSize;
442 if(CheckBndBox(aNewBndBox)){
443 for(int i = 0; i < 6; i++)
444 myBndBox[i] = aNewBndBox[i];
445 myCubeAxes->SetBounds(myBndBox);
453 Adjusts size of actors
460 ::ResetCameraClippingRange(GetDevice());
464 Set size of the trihedron
465 \param theSize - new size
466 \param theRelative - if it is true, then size is mesured in percents from bounding box of the scene,
467 otherwise - in viewer units
471 ::SetTrihedronSize(vtkFloatingPointType theSize, const bool theRelative)
473 if(myTrihedronSize != theSize || myIsTrihedronRelative != theRelative){
474 myTrihedronSize = theSize;
475 myIsTrihedronRelative = theRelative;
481 \return size of the trihedron in percents from bounding box of the scene
485 ::GetTrihedronSize() const
487 return myTrihedronSize;
491 \return true if the size of the trihedron is relative
495 ::IsTrihedronRelative() const
497 return myIsTrihedronRelative;
501 \return trihedron control
507 return myTrihedron.GetPointer();
511 \return true if trihedron is displayed
515 ::IsTrihedronDisplayed()
517 return myTrihedron->GetVisibility() == VTKViewer_Trihedron::eOn;
521 Toggle trihedron visibility
527 if(IsTrihedronDisplayed())
528 myTrihedron->VisibilityOff();
530 myTrihedron->VisibilityOn();
534 Adjust size of the trihedron to the bounding box of the scene
538 ::OnAdjustTrihedron()
544 \return graduated rules control
546 SVTK_CubeAxesActor2D*
550 return myCubeAxes.GetPointer();
554 \return true if graduated rules displayed
558 ::IsCubeAxesDisplayed()
560 return myCubeAxes->GetVisibility() == 1;
564 Toggle graduated rules visibility
570 if(IsCubeAxesDisplayed())
571 myCubeAxes->VisibilityOff();
573 myCubeAxes->VisibilityOn();
577 Adjust size of the graduated rules to the bounding box of the scene
587 Sets camera into predefined state
593 int aTrihedronIsVisible = IsTrihedronDisplayed();
594 int aCubeAxesIsVisible = IsCubeAxesDisplayed();
596 myTrihedron->SetVisibility( VTKViewer_Trihedron::eOnlyLineOn );
597 myCubeAxes->SetVisibility(0);
599 ::ResetCamera(GetDevice(),true);
600 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
601 aCamera->SetPosition(1,-1,1);
602 aCamera->SetViewUp(0,0,1);
603 ::ResetCamera(GetDevice(),true);
605 if(aTrihedronIsVisible)
606 myTrihedron->VisibilityOn();
608 myTrihedron->VisibilityOff();
610 if(aCubeAxesIsVisible)
611 myCubeAxes->VisibilityOn();
613 myCubeAxes->VisibilityOff();
615 static vtkFloatingPointType aCoeff = 3.0;
616 aCamera->SetParallelScale(aCoeff*aCamera->GetParallelScale());
620 Fit all presentation in the scene into the window
626 int aTrihedronWasVisible = false;
627 int aCubeAxesWasVisible = false;
629 aTrihedronWasVisible = IsTrihedronDisplayed();
630 if(aTrihedronWasVisible)
631 myTrihedron->VisibilityOff();
633 aCubeAxesWasVisible = IsCubeAxesDisplayed();
634 if(aCubeAxesWasVisible)
635 myCubeAxes->VisibilityOff();
637 if(myTrihedron->GetVisibleActorCount(GetDevice())){
638 myTrihedron->VisibilityOff();
639 myCubeAxes->VisibilityOff();
640 ::ResetCamera(GetDevice());
642 myTrihedron->SetVisibility(VTKViewer_Trihedron::eOnlyLineOn);
643 myCubeAxes->SetVisibility(2);
644 ::ResetCamera(GetDevice(),true);
647 if(aTrihedronWasVisible)
648 myTrihedron->VisibilityOn();
650 myTrihedron->VisibilityOff();
652 if(aCubeAxesWasVisible)
653 myCubeAxes->VisibilityOn();
655 myCubeAxes->VisibilityOff();
657 ::ResetCameraClippingRange(GetDevice());
661 Reset camera clipping range to adjust the range to the bounding box of the scene
665 ::OnResetClippingRange()
668 ::ResetCameraClippingRange(GetDevice());
672 To reset direction of the camera to front view
678 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
679 aCamera->SetPosition(1,0,0);
680 aCamera->SetViewUp(0,0,1);
681 aCamera->SetFocalPoint(0,0,0);
686 To reset direction of the camera to back view
692 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
693 aCamera->SetPosition(-1,0,0);
694 aCamera->SetViewUp(0,0,1);
695 aCamera->SetFocalPoint(0,0,0);
700 To reset direction of the camera to top view
706 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
707 aCamera->SetPosition(0,0,1);
708 aCamera->SetViewUp(0,1,0);
709 aCamera->SetFocalPoint(0,0,0);
714 To reset direction of the camera to bottom view
720 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
721 aCamera->SetPosition(0,0,-1);
722 aCamera->SetViewUp(0,1,0);
723 aCamera->SetFocalPoint(0,0,0);
728 To reset direction of the camera to left view
734 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
735 aCamera->SetPosition(0,-1,0);
736 aCamera->SetViewUp(0,0,1);
737 aCamera->SetFocalPoint(0,0,0);
742 To reset direction of the camera to right view
748 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
749 aCamera->SetPosition(0,1,0);
750 aCamera->SetViewUp(0,0,1);
751 aCamera->SetFocalPoint(0,0,0);