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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : VTKViewer_ViewFrame.cxx
25 // Author : Nicolas REJNERI
29 #include "VTKViewer_ViewFrame.h"
30 #include "VTKViewer_Utilities.h"
31 #include "VTKViewer_Trihedron.h"
32 #include "VTKViewer_RenderWindow.h"
33 #include "VTKViewer_RenderWindowInteractor.h"
34 #include "VTKViewer_InteractorStyleSALOME.h"
35 #include "VTKViewer_Algorithm.h"
36 #include "VTKViewer_Functor.h"
37 #include "VTKViewer_Prs.h"
39 #include "SALOME_Actor.h"
40 #include "SALOME_Transform.h"
41 #include "SALOME_TransformFilter.h"
42 #include "SALOME_GeometryFilter.h"
44 #include "QAD_Settings.h"
45 #include "QAD_Config.h"
46 #include "QAD_Application.h"
47 #include "QAD_Desktop.h"
48 #include "SALOME_Selection.h"
49 #include "SALOME_InteractiveObject.hxx"
51 #include "utilities.h"
55 #include <qcolordialog.h>
56 #include <qfiledialog.h>
57 #include <qapplication.h>
61 #include <vtkCamera.h>
62 #include <vtkRenderer.h>
63 #include <vtkTransform.h>
64 #include <vtkActorCollection.h>
66 #include <TColStd_IndexedMapOfInteger.hxx>
73 VTKViewer_ViewFrame::VTKViewer_ViewFrame(QWidget* parent, const char* name)
74 : QAD_ViewFrame(parent, name)
76 m_ViewUp[0] = 0; m_ViewUp[1] = 0; m_ViewUp[2] = -1;
77 m_ViewNormal[0] = 0; m_ViewNormal[1] = 0; m_ViewNormal[2] = 1;
78 m_Triedron = VTKViewer_Trihedron::New();
79 m_Transform = SALOME_Transform::New();
80 //m_Renderer = VTKViewer_Renderer::New() ;
81 m_Renderer = vtkRenderer::New() ;
83 m_Triedron->AddToRender(m_Renderer);
87 void VTKViewer_ViewFrame::InitialSetup() {
88 m_RW = new VTKViewer_RenderWindow(this, "RenderWindow");
89 m_RW->getRenderWindow()->AddRenderer(m_Renderer);
91 m_Renderer->GetActiveCamera()->ParallelProjectionOn();
92 m_Renderer->LightFollowCameraOn();
93 m_Renderer->TwoSidedLightingOn();
95 // Set BackgroundColor
96 QString BgrColorRed = QAD_CONFIG->getSetting("VTKViewer:BackgroundColorRed");
97 QString BgrColorGreen = QAD_CONFIG->getSetting("VTKViewer:BackgroundColorGreen");
98 QString BgrColorBlue = QAD_CONFIG->getSetting("VTKViewer:BackgroundColorBlue");
100 if( !BgrColorRed.isEmpty() && !BgrColorGreen.isEmpty() && !BgrColorBlue.isEmpty() )
101 m_Renderer->SetBackground( BgrColorRed.toInt()/255., BgrColorGreen.toInt()/255., BgrColorBlue.toInt()/255. );
103 m_Renderer->SetBackground( 0, 0, 0 );
105 // Create an interactor.
106 m_RWInteractor = VTKViewer_RenderWindowInteractor::New();
107 m_RWInteractor->SetRenderWindow(m_RW->getRenderWindow());
109 VTKViewer_InteractorStyleSALOME* RWS = VTKViewer_InteractorStyleSALOME::New();
110 m_RWInteractor->SetInteractorStyle(RWS);
113 m_RWInteractor->setGUIWindow(m_RW);
114 RWS->setGUIWindow(m_RW);
116 m_RWInteractor->Initialize();
117 m_RWInteractor->setViewFrame(this);
118 RWS->setTriedron(m_Triedron);
119 RWS->setViewFrame(this);
120 //SRN: additional initialization, to init CurrentRenderer of vtkInteractorStyle
121 RWS->FindPokedRenderer(0, 0);
123 setCentralWidget( m_RW );
127 VTKViewer_ViewFrame::~VTKViewer_ViewFrame() {
128 // In order to ensure that the interactor unregisters
129 // this RenderWindow, we assign a NULL RenderWindow to
130 // it before deleting it.
131 m_RWInteractor->SetRenderWindow(NULL) ;
132 m_RWInteractor->Delete() ;
134 m_Transform->Delete() ;
136 m_Renderer->RemoveAllProps();
137 // NRI : BugID 1137: m_Renderer->Delete() ;
138 m_Triedron->Delete();
139 INFOS("VTKViewer_ViewFrame::~VTKViewer_ViewFrame()");
143 Returns widget containing 3D-Viewer
145 QWidget* VTKViewer_ViewFrame::getViewWidget(){
149 bool VTKViewer_ViewFrame::isTrihedronDisplayed(){
150 return m_Triedron->GetVisibility() == VTKViewer_Trihedron::eOn;
153 bool VTKViewer_ViewFrame::ComputeTrihedronSize( double& theNewSize, double& theSize )
155 // calculating diagonal of visible props of the renderer
157 m_Triedron->VisibilityOff();
158 if ( ::ComputeVisiblePropBounds( m_Renderer, bnd ) == 0 )
160 bnd[ 1 ] = bnd[ 3 ] = bnd[ 5 ] = 100;
161 bnd[ 0 ] = bnd[ 2 ] = bnd[ 100 ] = 0;
163 m_Triedron->VisibilityOn();
165 static bool CalcByDiag = false;
168 aLength = sqrt( ( bnd[1]-bnd[0])*(bnd[1]-bnd[0] )+
169 ( bnd[3]-bnd[2])*(bnd[3]-bnd[2] )+
170 ( bnd[5]-bnd[4])*(bnd[5]-bnd[4] ) );
174 aLength = bnd[ 1 ]-bnd[ 0 ];
175 aLength = max( ( bnd[ 3 ] - bnd[ 2 ] ),aLength );
176 aLength = max( ( bnd[ 5 ] - bnd[ 4 ] ),aLength );
179 static float aSizeInPercents = 105;
180 QString aSetting = QAD_CONFIG->getSetting( "Viewer:TrihedronSize" );
181 if ( !aSetting.isEmpty() )
182 aSizeInPercents = aSetting.toFloat();
184 static float EPS_SIZE = 5.0E-3;
185 theSize = m_Triedron->GetSize();
186 theNewSize = aLength * aSizeInPercents / 100.0;
188 // if the new trihedron size have sufficient difference, then apply the value
189 return fabs( theNewSize - theSize) > theSize * EPS_SIZE ||
190 fabs( theNewSize-theSize ) > theNewSize * EPS_SIZE;
193 double VTKViewer_ViewFrame::GetTrihedronSize() const
195 return m_Triedron->GetSize();
198 void VTKViewer_ViewFrame::AdjustTrihedrons( const bool forcedUpdate )
200 if ( !isTrihedronDisplayed() && !forcedUpdate )
203 int aVisibleNum = m_Triedron->GetVisibleActorCount( m_Renderer );
204 if ( aVisibleNum || forcedUpdate )
206 // if the new trihedron size have sufficient difference, then apply the value
207 double aNewSize = 100, anOldSize;
208 if ( ComputeTrihedronSize( aNewSize, anOldSize ) || forcedUpdate )
210 m_Triedron->SetSize( aNewSize );
211 // itearte throuh displayed objects and set size if necessary
213 vtkActorCollection* anActors = getRenderer()->GetActors();
214 anActors->InitTraversal();
215 while( vtkActor* anActor = anActors->GetNextActor() )
217 if( SALOME_Actor* aSActor = SALOME_Actor::SafeDownCast( anActor ) )
219 if ( aSActor->IsResizable() )
220 aSActor->SetSize( 0.5 * aNewSize );
226 ::ResetCameraClippingRange(m_Renderer);
229 void VTKViewer_ViewFrame::onAdjustTrihedron()
231 AdjustTrihedrons( false );
235 Display/hide Trihedron
237 void VTKViewer_ViewFrame::onViewTrihedron(){
238 if(!m_Triedron) return;
239 if(isTrihedronDisplayed())
240 m_Triedron->VisibilityOff();
242 m_Triedron->VisibilityOn();
248 Provides top projection of the active view
250 void VTKViewer_ViewFrame::onViewTop(){
251 vtkCamera* camera = m_Renderer->GetActiveCamera();
252 camera->SetPosition(0,0,1);
253 camera->SetViewUp(0,1,0);
254 camera->SetFocalPoint(0,0,0);
259 Provides bottom projection of the active view
261 void VTKViewer_ViewFrame::onViewBottom(){
262 vtkCamera* camera = m_Renderer->GetActiveCamera();
263 camera->SetPosition(0,0,-1);
264 camera->SetViewUp(0,1,0);
265 camera->SetFocalPoint(0,0,0);
270 Provides left projection of the active view
272 void VTKViewer_ViewFrame::onViewLeft(){
273 vtkCamera* camera = m_Renderer->GetActiveCamera();
274 camera->SetPosition(0,-1,0);
275 camera->SetViewUp(0,0,1);
276 camera->SetFocalPoint(0,0,0);
281 Provides right projection of the active view
283 void VTKViewer_ViewFrame::onViewRight(){
284 vtkCamera* camera = m_Renderer->GetActiveCamera();
285 camera->SetPosition(0,1,0);
286 camera->SetViewUp(0,0,1);
287 camera->SetFocalPoint(0,0,0);
292 Provides back projection of the active view
294 void VTKViewer_ViewFrame::onViewBack(){
295 vtkCamera* camera = m_Renderer->GetActiveCamera();
296 camera->SetPosition(-1,0,0);
297 camera->SetViewUp(0,0,1);
298 camera->SetFocalPoint(0,0,0);
303 Provides front projection of the active view
305 void VTKViewer_ViewFrame::onViewFront(){
306 vtkCamera* camera = m_Renderer->GetActiveCamera();
307 camera->SetPosition(1,0,0);
308 camera->SetViewUp(0,0,1);
309 camera->SetFocalPoint(0,0,0);
314 Fits all objects in the active view
316 void VTKViewer_ViewFrame::onViewFitAll(){
317 m_RWInteractor->GetInteractorStyleSALOME()->ViewFitAll();
322 Reset the active view
324 void VTKViewer_ViewFrame::onViewReset(){
325 int aTriedronIsVisible = isTrihedronDisplayed();
326 m_Triedron->SetVisibility(VTKViewer_Trihedron::eOnlyLineOn);
327 ::ResetCamera(m_Renderer,true);
328 vtkCamera* aCamera = m_Renderer->GetActiveCamera();
329 aCamera->SetPosition(1,-1,1);
330 aCamera->SetViewUp(0,0,1);
331 ::ResetCamera(m_Renderer,true);
332 if(aTriedronIsVisible) m_Triedron->VisibilityOn();
333 else m_Triedron->VisibilityOff();
334 static float aCoeff = 3.0;
335 aCamera->SetParallelScale(aCoeff*aCamera->GetParallelScale());
340 Rotates the active view
342 void VTKViewer_ViewFrame::onViewRotate(){
343 m_RWInteractor->GetInteractorStyleSALOME()->startRotate();
347 Sets a new center of the active view
349 void VTKViewer_ViewFrame::onViewGlobalPan(){
350 if(m_Triedron->GetVisibleActorCount(m_Renderer))
351 m_RWInteractor->GetInteractorStyleSALOME()->startGlobalPan();
355 Zooms the active view
357 void VTKViewer_ViewFrame::onViewZoom(){
358 m_RWInteractor->GetInteractorStyleSALOME()->startZoom();
362 Moves the active view
364 void VTKViewer_ViewFrame::onViewPan(){
365 m_RWInteractor->GetInteractorStyleSALOME()->startPan();
369 Fits all obejcts within a rectangular area of the active view
371 void VTKViewer_ViewFrame::onViewFitArea(){
372 m_RWInteractor->GetInteractorStyleSALOME()->startFitArea();
376 Set background of the viewport
378 void VTKViewer_ViewFrame::setBackgroundColor( const QColor& color)
381 m_Renderer->SetBackground( color.red()/255., color.green()/255., color.blue()/255. );
385 Returns background of the viewport
387 QColor VTKViewer_ViewFrame::backgroundColor() const
391 m_Renderer->GetBackground(backint);
392 return QColorDialog::getColor ( QColor(int(backint[0]*255), int(backint[1]*255), int(backint[2]*255)), NULL );
394 return QMainWindow::backgroundColor();
398 void VTKViewer_ViewFrame::SetSelectionMode( Selection_Mode mode )
400 m_RWInteractor->SetSelectionMode( mode );
403 void VTKViewer_ViewFrame::rename( const Handle(SALOME_InteractiveObject)& IObject, QString newName )
405 m_RWInteractor->rename(IObject, newName);
408 void VTKViewer_ViewFrame::unHighlightAll()
410 m_RWInteractor->unHighlightAll();
413 void VTKViewer_ViewFrame::highlight( const Handle(SALOME_InteractiveObject)& IObject,
417 QAD_Study* ActiveStudy = QAD_Application::getDesktop()->getActiveStudy();
418 SALOME_Selection* Sel = SALOME_Selection::Selection( ActiveStudy->getSelection() );
419 m_RWInteractor->highlight(IObject, highlight, update);
421 if(Sel->HasIndex(IObject) && IObject->hasEntry()){
422 TColStd_IndexedMapOfInteger MapIndex;
423 Sel->GetIndex(IObject,MapIndex);
424 using namespace SALOME::VTK;
425 const char* anEntry = IObject->getEntry();
426 vtkActorCollection* aCollection = getRenderer()->GetActors();
427 if(SALOME_Actor* anActor = Find<SALOME_Actor>(aCollection,TIsSameEntry<SALOME_Actor>(anEntry))){
428 switch (Sel->SelectionMode()) {
430 m_RWInteractor->highlightPoint(MapIndex,anActor,highlight,update);
432 case EdgeOfCellSelection:
433 m_RWInteractor->highlightEdge(MapIndex,anActor,highlight,update);
438 case VolumeSelection:
439 m_RWInteractor->highlightCell(MapIndex,anActor,highlight,update);
444 m_RWInteractor->unHighlightSubSelection();
448 bool VTKViewer_ViewFrame::isInViewer( const Handle(SALOME_InteractiveObject)& IObject )
450 return m_RWInteractor->isInViewer( IObject );
453 bool VTKViewer_ViewFrame::isVisible( const Handle(SALOME_InteractiveObject)& IObject )
455 return m_RWInteractor->isVisible( IObject );
458 void VTKViewer_ViewFrame::setPopupServer( QAD_Application* App )
460 m_RW->setPopupServer( App );
464 Handle(SALOME_InteractiveObject) VTKViewer_ViewFrame::FindIObject(const char* theEntry)
466 using namespace SALOME::VTK;
467 SALOME_Actor* anActor =
468 Find<SALOME_Actor>(getRenderer()->GetActors(),
469 TIsSameEntry<SALOME_Actor>(theEntry));
471 return anActor->getIO();
473 return Handle(SALOME_InteractiveObject)();
477 void VTKViewer_ViewFrame::Display(const Handle(SALOME_InteractiveObject)& theIObject, bool update)
479 QAD_Study* aStudy = QAD_Application::getDesktop()->getActiveStudy();
480 SALOME_Selection* aSel = SALOME_Selection::Selection(aStudy->getSelection());
482 m_RWInteractor->Display(theIObject,false);
483 aSel->AddIObject(theIObject,false);
490 struct TDisplayAction{
491 SALOME_Selection* mySel;
492 Handle(SALOME_InteractiveObject) myIO;
493 TDisplayAction(SALOME_Selection* theSel,
494 Handle(SALOME_InteractiveObject) theIO):
495 mySel(theSel), myIO(theIO)
497 void operator()(SALOME_Actor* theActor){
498 theActor->SetVisibility(true);
499 mySel->AddIObject(myIO,false);
503 void VTKViewer_ViewFrame::DisplayOnly(const Handle(SALOME_InteractiveObject)& theIObject)
505 QAD_Study* aStudy = QAD_Application::getDesktop()->getActiveStudy();
506 SALOME_Selection* aSel = SALOME_Selection::Selection(aStudy->getSelection());
508 aSel->ClearIObjects();
509 m_RWInteractor->EraseAll();
511 using namespace SALOME::VTK;
512 ForEachIf<SALOME_Actor>(getRenderer()->GetActors(),
513 TIsSameIObject<SALOME_Actor>(theIObject),
514 TDisplayAction(aSel,theIObject));
520 struct TEraseAction: TDisplayAction{
521 VTKViewer_RenderWindowInteractor* myRWInteractor;
522 TEraseAction(SALOME_Selection* theSel,
523 Handle(SALOME_InteractiveObject) theIO,
524 VTKViewer_RenderWindowInteractor* theRWInteractor):
525 TDisplayAction(theSel,theIO),
526 myRWInteractor(theRWInteractor)
528 void operator()(SALOME_Actor* theActor){
529 myRWInteractor->Erase(myIO,false);
530 mySel->RemoveIObject(myIO,false);
534 void VTKViewer_ViewFrame::Erase(const Handle(SALOME_InteractiveObject)& theIObject, bool update)
536 QAD_Study* aStudy = QAD_Application::getDesktop()->getActiveStudy();
537 SALOME_Selection* aSel = SALOME_Selection::Selection(aStudy->getSelection());
539 using namespace SALOME::VTK;
540 ForEachIf<SALOME_Actor>(getRenderer()->GetActors(),
541 TIsSameIObject<SALOME_Actor>(theIObject),
542 TEraseAction(aSel,theIObject,m_RWInteractor));
549 void VTKViewer_ViewFrame::DisplayAll()
551 m_RWInteractor->DisplayAll();
555 void VTKViewer_ViewFrame::EraseAll()
557 m_RWInteractor->EraseAll();
561 void VTKViewer_ViewFrame::Repaint(bool theUpdateTrihedron)
563 if (theUpdateTrihedron) onAdjustTrihedron();
567 void VTKViewer_ViewFrame::GetScale(double theScale[3]){
568 m_Transform->GetScale(theScale);
571 void VTKViewer_ViewFrame::SetScale(double theScale[3]){
572 m_Transform->SetScale(theScale[0], theScale[1], theScale[2]);
573 m_RWInteractor->Render();
577 void VTKViewer_ViewFrame::InsertActor( SALOME_Actor* theActor, bool theMoveInternalActors ){
578 theActor->AddToRender(m_Renderer);
579 theActor->SetTransform(m_Transform);
580 if(theMoveInternalActors)
581 m_RWInteractor->MoveInternalActors();
584 void VTKViewer_ViewFrame::AddActor( SALOME_Actor* theActor, bool theUpdate /*=false*/ ){
585 InsertActor(theActor);
590 void VTKViewer_ViewFrame::RemoveActor( SALOME_Actor* theActor, bool theUpdate /*=false*/ ){
591 theActor->RemoveFromRender(m_Renderer);
596 void VTKViewer_ViewFrame::MoveActor(SALOME_Actor* theActor)
598 RemoveActor(theActor);
599 InsertActor(theActor,true);
602 //==========================================================
604 * VTKViewer_ViewFrame::Display
605 * Display presentation
607 //==========================================================
608 void VTKViewer_ViewFrame::Display( const SALOME_VTKPrs* prs )
610 // try do downcast object
611 const VTKViewer_Prs* aVTKPrs = dynamic_cast<const VTKViewer_Prs*>( prs );
612 if ( !aVTKPrs || aVTKPrs->IsNull() )
615 vtkActorCollection* actors = aVTKPrs->GetObjects();
619 actors->InitTraversal();
621 while( ( actor = actors->GetNextActor() ) )
623 SALOME_Actor* salomeActor = SALOME_Actor::SafeDownCast( actor );
626 // just display the object
627 m_RWInteractor->Display( salomeActor, false );
628 if ( salomeActor->IsSetCamera() )
629 salomeActor->SetCamera( getRenderer()->GetActiveCamera() );
634 //==========================================================
636 * VTKViewer_ViewFrame::Erase
639 //==========================================================
640 void VTKViewer_ViewFrame::Erase( const SALOME_VTKPrs* prs, const bool forced )
642 // try do downcast object
643 const VTKViewer_Prs* aVTKPrs = dynamic_cast<const VTKViewer_Prs*>( prs );
644 if ( !aVTKPrs || aVTKPrs->IsNull() )
647 vtkActorCollection* actors = aVTKPrs->GetObjects();
651 actors->InitTraversal();
653 while( ( actor = actors->GetNextActor() ) ) {
654 SALOME_Actor* salomeActor = SALOME_Actor::SafeDownCast( actor );
656 // just erase the object
657 m_RWInteractor->Erase( salomeActor, forced );
662 //==========================================================
664 * VTKViewer_ViewFrame::CreatePrs
665 * Create presentation by entry
667 //==========================================================
668 SALOME_Prs* VTKViewer_ViewFrame::CreatePrs( const char* entry )
670 VTKViewer_Prs* prs = new VTKViewer_Prs();
672 vtkActorCollection* theActors = m_Renderer->GetActors();
673 theActors->InitTraversal();
675 while( ( ac = theActors->GetNextActor() ) ) {
676 SALOME_Actor* anActor = SALOME_Actor::SafeDownCast( ac );
677 if ( anActor && anActor->hasIO() && !strcmp( anActor->getIO()->getEntry(), entry ) ) {
678 prs->AddObject( ac );
685 //==========================================================
687 * VTKViewer_ViewFrame::BeforeDisplay
688 * Axiluary method called before displaying of objects
690 //==========================================================
691 void VTKViewer_ViewFrame::BeforeDisplay( SALOME_Displayer* d )
693 d->BeforeDisplay( this, SALOME_VTKViewType() );
696 //==========================================================
698 * VTKViewer_ViewFrame::AfterDisplay
699 * Axiluary method called after displaying of objects
701 //==========================================================
702 void VTKViewer_ViewFrame::AfterDisplay( SALOME_Displayer* d )
704 d->AfterDisplay( this, SALOME_VTKViewType() );