1 // Copyright (C) 2007-2008 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
22 // SALOME VTKViewer : build VTK viewer into Salome desktop
28 #include "SVTK_Renderer.h"
30 #include "SVTK_Trihedron.h"
31 #include "SVTK_CubeAxesActor2D.h"
32 #include "SVTK_RectPicker.h"
34 #include "SALOME_Actor.h"
35 #include "VTKViewer_Actor.h"
36 #include "VTKViewer_Transform.h"
37 #include "VTKViewer_Utilities.h"
39 #include <vtkCamera.h>
40 #include <vtkRenderer.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(vtkRenderer::New()),
67 myEventCallbackCommand(vtkCallbackCommand::New()),
68 myPointPicker(vtkPointPicker::New()),
69 myCellPicker(vtkCellPicker::New()),
70 myPointRectPicker(SVTK_RectPicker::New()),
71 myCellRectPicker(SVTK_RectPicker::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 myPointRectPicker->Delete();
87 myPointRectPicker->PickFromListOn();
89 myCellRectPicker->Delete();
90 myCellRectPicker->PickFromListOn();
91 myCellRectPicker->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 myTrihedron->Delete();
108 myCubeAxes->Delete();
109 myEventCallbackCommand->Delete();
111 myTrihedron->AddToRender(GetDevice());
112 GetDevice()->AddViewProp(GetCubeAxes());
114 myBndBox[0] = myBndBox[2] = myBndBox[4] = 0;
115 myBndBox[1] = myBndBox[3] = myBndBox[5] = myTrihedron->GetSize();
117 myCubeAxes->SetBounds(myBndBox);
118 myCubeAxes->SetCamera(GetDevice()->GetActiveCamera());
120 myCubeAxes->SetLabelFormat("%6.4g");
121 myCubeAxes->SetFlyModeToOuterEdges(); // ENK remarks: it must bee
122 myCubeAxes->SetFontFactor(0.8);
123 myCubeAxes->SetCornerOffset(0);
124 myCubeAxes->SetScaling(0);
125 myCubeAxes->SetNumberOfLabels(5);
126 myCubeAxes->VisibilityOff();
127 myCubeAxes->SetTransform(GetTransform());
129 vtkTextProperty* aTextProp = vtkTextProperty::New();
130 aTextProp->SetColor(1, 1, 1);
131 aTextProp->ShadowOn();
132 myCubeAxes->SetAxisTitleTextProperty(aTextProp);
133 myCubeAxes->SetAxisLabelTextProperty(aTextProp);
136 GetDevice()->GetActiveCamera()->ParallelProjectionOn();
137 GetDevice()->LightFollowCameraOn();
138 GetDevice()->TwoSidedLightingOn();
140 myEventCallbackCommand->SetClientData(this);
141 myEventCallbackCommand->SetCallback(SVTK_Renderer::ProcessEvents);
142 GetDevice()->AddObserver(vtkCommand::ConfigureEvent,
143 myEventCallbackCommand.GetPointer(),
145 GetDevice()->AddObserver(vtkCommand::ResetCameraEvent,
146 myEventCallbackCommand.GetPointer(),
148 GetDevice()->AddObserver(vtkCommand::ResetCameraClippingRangeEvent,
149 myEventCallbackCommand.GetPointer(),
159 vtkActorCollection* anActors = GetDevice()->GetActors();
160 vtkActorCollection* anActors2 = vtkActorCollection::New();
162 anActors->InitTraversal();
163 while(vtkActor* anAct = anActors->GetNextActor()){
164 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
165 anActors2->AddItem(anActor);
169 anActors2->InitTraversal();
170 while(vtkActor* anAct = anActors2->GetNextActor()){
171 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
172 RemoveActor(anActor);
181 Main process event method
185 ::ProcessEvents(vtkObject* vtkNotUsed(theObject),
186 unsigned long theEvent,
188 void* vtkNotUsed(theCallData))
190 SVTK_Renderer* self = reinterpret_cast<SVTK_Renderer*>(theClientData);
193 case vtkCommand::ConfigureEvent:
196 case vtkCommand::ResetCameraEvent:
199 case vtkCommand::ResetCameraClippingRangeEvent:
200 self->OnResetClippingRange();
206 \return renderer's device
212 return myDevice.GetPointer();
220 ::Initialize(vtkRenderWindowInteractor* theInteractor,
221 SVTK_Selector* theSelector)
223 myInteractor = theInteractor;
224 mySelector = theSelector;
225 SetSelectionTolerance();
229 Publishes pointed actor into the renderer
233 ::AddActor(VTKViewer_Actor* theActor)
235 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(theActor)){
236 anActor->SetInteractor(myInteractor);
237 anActor->SetTransform(GetTransform());
238 anActor->SetSelector(mySelector.GetPointer());
240 anActor->SetPointPicker(myPointPicker.GetPointer());
241 anActor->SetCellPicker(myCellPicker.GetPointer());
243 anActor->SetPointRectPicker(myPointRectPicker.GetPointer());
244 anActor->SetCellRectPicker(myCellRectPicker.GetPointer());
246 anActor->SetPreHighlightProperty(myPreHighlightProperty.GetPointer());
247 anActor->SetHighlightProperty(myHighlightProperty.GetPointer());
249 anActor->AddToRender(GetDevice());
255 Removes pointed actor from the renderer
259 ::RemoveActor(VTKViewer_Actor* theActor)
261 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(theActor)){
262 // Order of the calls are important because VTKViewer_Actor::RemoveFromRender
263 // can leads do destruction of the actor
264 anActor->SetInteractor(NULL);
265 anActor->SetTransform(NULL);
266 anActor->SetSelector(NULL);
268 anActor->SetPointPicker(NULL);
269 anActor->SetCellPicker(NULL);
271 anActor->SetPointRectPicker(NULL);
272 anActor->SetCellRectPicker(NULL);
274 anActor->SetPreHighlightProperty(NULL);
275 anActor->SetHighlightProperty(NULL);
277 anActor->RemoveFromRender(GetDevice());
283 Get special container that keeps scaling of the scene
289 return myTransform.GetPointer();
293 Allows to get a scale that is applied on the whole scene
297 ::GetScale( double theScale[3] )
299 myTransform->GetMatrixScale( theScale );
303 Allows to apply a scale on the whole scene
307 ::SetScale( double theScale[3] )
309 myTransform->SetMatrixScale( theScale[0], theScale[1], theScale[2] );
312 vtkActorCollection* anActors = GetDevice()->GetActors();
313 anActors->InitTraversal();
314 while(vtkActor* anAct = anActors->GetNextActor())
315 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct))
316 if(anActor->isHighlighted() && !anActor->IsInfinitive())
317 anActor->highlight(true);
321 Applies color and size (PointSize and LineWidth) of primitives in selection mode
325 ::SetSelectionProp(const double& theRed,
326 const double& theGreen,
327 const double& theBlue,
330 myHighlightProperty->SetColor( theRed, theGreen, theBlue );
331 myHighlightProperty->SetLineWidth( theWidth );
332 myHighlightProperty->SetPointSize( theWidth );
336 Applies color and size (PointSize and LineWidth) of primitives in preselection mode
340 ::SetPreselectionProp(const double& theRed,
341 const double& theGreen,
342 const double& theBlue,
345 myPreHighlightProperty->SetColor( theRed, theGreen, theBlue );
346 myPreHighlightProperty->SetLineWidth( theWidth );
347 myPreHighlightProperty->SetPointSize( theWidth );
351 Setup requested tolerance for the picking
355 ::SetSelectionTolerance(const double& theTolNodes,
356 const double& theTolCell,
357 const double& theTolObjects)
359 myPointPicker->SetTolerance( theTolNodes );
360 myCellPicker->SetTolerance( theTolCell );
362 myPointRectPicker->SetTolerance( theTolNodes );
363 myCellRectPicker->SetTolerance( theTolCell );
365 mySelector->SetTolerance( theTolObjects );
369 /*! If parameter theIsForcedUpdate is true, recalculate parameters for
370 * trihedron and cube axes, even if trihedron and cube axes is invisible.
375 CheckBndBox(const vtkFloatingPointType theBounds[6])
377 if(theBounds[0] > -VTK_LARGE_FLOAT && theBounds[1] < VTK_LARGE_FLOAT &&
378 theBounds[2] > -VTK_LARGE_FLOAT && theBounds[3] < VTK_LARGE_FLOAT &&
379 theBounds[4] > -VTK_LARGE_FLOAT && theBounds[5] < VTK_LARGE_FLOAT)
385 Adjusts size of actors
391 bool aTDisplayed = IsTrihedronDisplayed();
392 bool aCDisplayed = IsCubeAxesDisplayed();
394 vtkFloatingPointType aNewBndBox[6];
395 aNewBndBox[ 0 ] = aNewBndBox[ 2 ] = aNewBndBox[ 4 ] = VTK_LARGE_FLOAT;
396 aNewBndBox[ 1 ] = aNewBndBox[ 3 ] = aNewBndBox[ 5 ] = -VTK_LARGE_FLOAT;
398 int aVisibleNum = myTrihedron->GetVisibleActorCount(GetDevice());
401 myTrihedron->VisibilityOff();
404 myCubeAxes->VisibilityOff();
406 // if the new trihedron size have sufficient difference, then apply the value
407 vtkFloatingPointType aSize = myTrihedron->GetSize();
408 if ( IsTrihedronRelative() )
410 ComputeTrihedronSize(GetDevice(),aSize,aSize,myTrihedronSize);
411 myTrihedron->SetSize(aSize);
414 myTrihedron->SetSize( myTrihedronSize );
416 // iterate through displayed objects and set size if necessary
417 vtkActorCollection* anActors = GetDevice()->GetActors();
418 anActors->InitTraversal();
419 while(vtkActor* anAct = anActors->GetNextActor()){
420 if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
421 if(anActor->IsResizable())
422 anActor->SetSize(0.5*aSize);
423 if(anActor->GetVisibility() && !anActor->IsInfinitive()){
424 vtkFloatingPointType *aBounds = anActor->GetBounds();
425 if(CheckBndBox(aBounds))
426 for(int i = 0; i < 5; i = i + 2){
427 if(aBounds[i] < aNewBndBox[i])
428 aNewBndBox[i] = aBounds[i];
429 if(aBounds[i+1] > aNewBndBox[i+1])
430 aNewBndBox[i+1] = aBounds[i+1];
437 myTrihedron->VisibilityOn();
440 myCubeAxes->VisibilityOn();
443 double aSize = myTrihedron->GetSize();
444 aNewBndBox[0] = aNewBndBox[2] = aNewBndBox[4] = 0;
445 aNewBndBox[1] = aNewBndBox[3] = aNewBndBox[5] = aSize;
448 if(CheckBndBox(aNewBndBox)){
449 for(int i = 0; i < 6; i++)
450 myBndBox[i] = aNewBndBox[i];
451 myCubeAxes->SetBounds(myBndBox);
459 Adjusts size of actors
466 ::ResetCameraClippingRange(GetDevice());
470 Set size of the trihedron
471 \param theSize - new size
472 \param theRelative - if it is true, then size is mesured in percents from bounding box of the scene,
473 otherwise - in viewer units
477 ::SetTrihedronSize(vtkFloatingPointType theSize, const bool theRelative)
479 if(myTrihedronSize != theSize || myIsTrihedronRelative != theRelative){
480 myTrihedronSize = theSize;
481 myIsTrihedronRelative = theRelative;
487 \return size of the trihedron in percents from bounding box of the scene
491 ::GetTrihedronSize() const
493 return myTrihedronSize;
497 \return true if the size of the trihedron is relative
501 ::IsTrihedronRelative() const
503 return myIsTrihedronRelative;
507 \return trihedron control
513 return myTrihedron.GetPointer();
517 \return true if trihedron is displayed
521 ::IsTrihedronDisplayed()
523 return myTrihedron->GetVisibility() == VTKViewer_Trihedron::eOn;
527 Toggle trihedron visibility
533 if(IsTrihedronDisplayed())
534 myTrihedron->VisibilityOff();
536 myTrihedron->VisibilityOn();
540 Adjust size of the trihedron to the bounding box of the scene
544 ::OnAdjustTrihedron()
550 \return graduated rules control
552 SVTK_CubeAxesActor2D*
556 return myCubeAxes.GetPointer();
560 \return true if graduated rules displayed
564 ::IsCubeAxesDisplayed()
566 return myCubeAxes->GetVisibility() == 1;
570 Toggle graduated rules visibility
576 if(IsCubeAxesDisplayed())
577 myCubeAxes->VisibilityOff();
579 myCubeAxes->VisibilityOn();
583 Adjust size of the graduated rules to the bounding box of the scene
593 Sets camera into predefined state
599 int aTrihedronIsVisible = IsTrihedronDisplayed();
600 int aCubeAxesIsVisible = IsCubeAxesDisplayed();
602 myTrihedron->SetVisibility( VTKViewer_Trihedron::eOnlyLineOn );
603 myCubeAxes->SetVisibility(0);
605 ::ResetCamera(GetDevice(),true);
606 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
607 aCamera->SetPosition(1,-1,1);
608 aCamera->SetViewUp(0,0,1);
609 ::ResetCamera(GetDevice(),true);
611 if(aTrihedronIsVisible)
612 myTrihedron->VisibilityOn();
614 myTrihedron->VisibilityOff();
616 if(aCubeAxesIsVisible)
617 myCubeAxes->VisibilityOn();
619 myCubeAxes->VisibilityOff();
621 static vtkFloatingPointType aCoeff = 3.0;
622 aCamera->SetParallelScale(aCoeff*aCamera->GetParallelScale());
626 Fit all presentation in the scene into the window
632 int aTrihedronWasVisible = false;
633 int aCubeAxesWasVisible = false;
635 aTrihedronWasVisible = IsTrihedronDisplayed();
636 if(aTrihedronWasVisible)
637 myTrihedron->VisibilityOff();
639 aCubeAxesWasVisible = IsCubeAxesDisplayed();
640 if(aCubeAxesWasVisible)
641 myCubeAxes->VisibilityOff();
643 if(myTrihedron->GetVisibleActorCount(GetDevice())){
644 myTrihedron->VisibilityOff();
645 myCubeAxes->VisibilityOff();
646 ::ResetCamera(GetDevice());
648 myTrihedron->SetVisibility(VTKViewer_Trihedron::eOnlyLineOn);
649 myCubeAxes->SetVisibility(2);
650 ::ResetCamera(GetDevice(),true);
653 if(aTrihedronWasVisible)
654 myTrihedron->VisibilityOn();
656 myTrihedron->VisibilityOff();
658 if(aCubeAxesWasVisible)
659 myCubeAxes->VisibilityOn();
661 myCubeAxes->VisibilityOff();
663 ::ResetCameraClippingRange(GetDevice());
667 Reset camera clipping range to adjust the range to the bounding box of the scene
671 ::OnResetClippingRange()
674 ::ResetCameraClippingRange(GetDevice());
678 To reset direction of the camera to front view
684 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
685 aCamera->SetPosition(1,0,0);
686 aCamera->SetViewUp(0,0,1);
687 aCamera->SetFocalPoint(0,0,0);
692 To reset direction of the camera to back view
698 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
699 aCamera->SetPosition(-1,0,0);
700 aCamera->SetViewUp(0,0,1);
701 aCamera->SetFocalPoint(0,0,0);
706 To reset direction of the camera to top view
712 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
713 aCamera->SetPosition(0,0,1);
714 aCamera->SetViewUp(0,1,0);
715 aCamera->SetFocalPoint(0,0,0);
720 To reset direction of the camera to bottom view
726 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
727 aCamera->SetPosition(0,0,-1);
728 aCamera->SetViewUp(0,1,0);
729 aCamera->SetFocalPoint(0,0,0);
734 To reset direction of the camera to left view
740 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
741 aCamera->SetPosition(0,-1,0);
742 aCamera->SetViewUp(0,0,1);
743 aCamera->SetFocalPoint(0,0,0);
748 To reset direction of the camera to right view
754 vtkCamera* aCamera = GetDevice()->GetActiveCamera();
755 aCamera->SetPosition(0,1,0);
756 aCamera->SetViewUp(0,0,1);
757 aCamera->SetFocalPoint(0,0,0);