Salome HOME
refs #497: redesign of HYDRO main menu.
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_VTKPrsDisplayer.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "HYDROGUI_VTKPrsDisplayer.h"
24
25 #include "HYDROGUI_DataModel.h"
26 #include "HYDROGUI_Module.h"
27 #include "HYDROGUI_VTKPrs.h"
28 #include "HYDROGUI_VTKPrsBathymetryDriver.h"
29 #include "HYDROGUI_VTKPrsShapeDriver.h"
30 #include "HYDROGUI_Tool.h"
31
32 #include "HYDROData_Tool.h"
33 #include <SVTK_ViewModel.h>
34 #include <SVTK_ViewWindow.h>
35 #include <SALOME_ListIO.hxx>
36 //#include <SALOME_ListIteratorOfListIO.hxx>
37 #include <SALOME_InteractiveObject.hxx>
38 #include <SUIT_ViewManager.h>
39 #include <SUIT_Accel.h>
40
41 #include <vtkLookupTable.h>
42 #include <vtkRenderer.h>
43 #include <vtkTextProperty.h>
44 #include <vtkWindow.h>
45 #include <vtkActor2DCollection.h>
46
47 #include <QVector>
48
49 #define NB_COLORS 32
50
51 // Saturation of blue
52 //#define HUE_START 0.69 
53 //#define HUE_END   0.41
54 //#define SATURATION_START 1.0 
55 //#define SATURATION_END   0.4
56
57 #define HUE_START 0.7
58 #define HUE_END   0.0 
59 #define SATURATION_START 1.0 
60 #define SATURATION_END   1.0
61
62 HYDROGUI_VTKPrsDisplayer::HYDROGUI_VTKPrsDisplayer( HYDROGUI_Module* theModule )
63 : HYDROGUI_AbstractDisplayer( theModule ), myDriver( NULL ), myShapeDriver( NULL )
64 {
65 }
66
67 HYDROGUI_VTKPrsDisplayer::~HYDROGUI_VTKPrsDisplayer()
68 {
69 }
70
71 void HYDROGUI_VTKPrsDisplayer::SetToUpdate( const HYDROData_SequenceOfObjects& theObjs,
72                                       const int theViewerId )
73 {
74   SVTK_Viewer* aViewer = module()->getVTKViewer( theViewerId );
75   if( !aViewer )
76   {
77     HYDROGUI_VTKPrs* anObjShape;
78     for ( int i = 1, n = theObjs.Length(); i <= n; i++ )
79     {
80       Handle(HYDROData_Entity) anObj = theObjs.Value( i );
81       if( !anObj.IsNull() )
82       {
83         anObjShape = module()->getObjectVTKPrs( (size_t)aViewer, anObj );
84         if ( anObjShape )
85         {
86           anObjShape->setIsToUpdate( true );
87         }
88       }
89     }
90   }
91 }
92
93 void HYDROGUI_VTKPrsDisplayer::DisplayAll( const int theViewerId,
94                                            const bool theIsForced,
95                                            const bool theDoFitAll )
96 {
97   HYDROGUI_AbstractDisplayer::DisplayAll( theViewerId, theIsForced, theDoFitAll );
98
99   bool isEraseScalarBar = true;
100
101   SVTK_Viewer* aViewer = module()->getVTKViewer( theViewerId );
102   if( aViewer )
103   {
104     SALOME_ListIO aListIO;
105     aViewer->GetVisible( aListIO );
106     
107     HYDROGUI_VTKPrs* aPrs;
108     SALOME_ListIteratorOfListIO anIter( aListIO );
109     for( ; anIter.More(); anIter.Next() )
110     {
111       Handle(SALOME_InteractiveObject) aPrsObj = anIter.Value();
112       if ( !aPrsObj.IsNull() )
113       {
114         Handle(HYDROData_Entity) anObj = 
115           module()->getDataModel()->objectByEntry( aPrsObj->getEntry() );
116         aPrs = module()->getObjectVTKPrs( (size_t)aViewer, anObj );
117         if( aPrs->needScalarBar() )
118         {
119           isEraseScalarBar = false;
120           break;
121         }
122       }
123     }
124   }
125
126   if( isEraseScalarBar )
127     EraseScalarBar( theViewerId );
128 }
129
130 void HYDROGUI_VTKPrsDisplayer::EraseAll( const int theViewerId )
131 {
132   SVTK_Viewer* aViewer = module()->getVTKViewer( theViewerId );
133   if( aViewer )
134   {
135     aViewer->EraseAll( 0, true );
136     module()->removeViewVTKPrs( (size_t)aViewer );
137     EraseScalarBar( theViewerId );
138   }
139 }
140
141 void HYDROGUI_VTKPrsDisplayer::EraseScalarBar( const int theViewerId, const bool theIsDelete )
142 {
143   SVTK_Viewer* aViewer = module()->getVTKViewer( theViewerId );
144   if( aViewer )
145   {
146     if ( myScalarBars.contains( (size_t)aViewer ) )
147     {
148       SUIT_ViewManager* aViewMgr = dynamic_cast<SUIT_ViewManager*>( aViewer->getViewManager() );
149       if ( aViewMgr && aViewMgr->getViewsCount() > 0 )
150       {
151         SVTK_ViewWindow* aView = dynamic_cast<SVTK_ViewWindow*>( aViewMgr->getActiveView() );
152         if ( aView )
153         {
154           vtkScalarBarActor* aScalarBar = myScalarBars[ (size_t)aViewer ];
155           if ( aView->getRenderer()->HasViewProp( aScalarBar ) )
156           {
157             aView->getRenderer()->RemoveActor2D( aScalarBar );
158           }
159         }
160       }
161       if ( theIsDelete )
162       {
163         myScalarBars.remove( (size_t)aViewer );
164       }
165     }
166   }
167 }
168
169 void HYDROGUI_VTKPrsDisplayer::Erase( const HYDROData_SequenceOfObjects& theObjs,
170                                 const int theViewerId )
171 {
172   SVTK_Viewer* aViewer = module()->getVTKViewer( theViewerId );
173   if( aViewer )
174   {
175     HYDROGUI_VTKPrs* aPrs;
176     for ( int i = 1, n = theObjs.Length(); i <= n; i++ )
177     {
178       Handle(HYDROData_Entity) anObj = theObjs.Value( i );
179       if( anObj.IsNull() )
180         continue;
181
182       aPrs = module()->getObjectVTKPrs( (size_t)aViewer, anObj );
183       if ( aPrs )
184       {
185         aViewer->Erase( aPrs, true );
186       }
187       if ( anObj->IsRemoved() )
188       {
189         module()->removeObjectVTKPrs( (size_t)aViewer, anObj );
190       }
191     }
192   }
193 }
194
195 void HYDROGUI_VTKPrsDisplayer::Display( const HYDROData_SequenceOfObjects& theObjs,
196                                         const int theViewerId,
197                                         const bool theIsForced,
198                                         const bool theDoFitAll)
199 {
200   SVTK_Viewer* aViewer = module()->getVTKViewer( theViewerId );
201   if( aViewer )
202   {
203     // Hide colors legend bar
204     SVTK_ViewWindow* aView = dynamic_cast<SVTK_ViewWindow*>(
205       aViewer->getViewManager()->getActiveView() );
206     vtkScalarBarActor* aScalarBar = 0;
207     if ( aView )
208     {
209       if ( !myScalarBars.contains( (size_t)aViewer ) )
210       {
211         createScalarBar( (size_t)aViewer );
212       }
213       aScalarBar = myScalarBars[ (size_t)aViewer ];
214
215       if ( aView->getRenderer()->HasViewProp( aScalarBar ) )
216       {
217         aView->getRenderer()->RemoveActor2D( aScalarBar );
218       }
219     }
220
221     // Invalidate global Z range
222     double anInvalidRange[2] = { HYDROGUI_VTKPrs::InvalidZValue(), HYDROGUI_VTKPrs::InvalidZValue() };
223     SetZRange( (size_t)aViewer, anInvalidRange );
224
225     int anInvalidZ = HYDROGUI_VTKPrs::InvalidZValue();
226     bool isChanged = false;
227     bool isScalarBarNeeded = false;
228     HYDROGUI_VTKPrs* aPrs;
229     for ( int i = 1, n = theObjs.Length(); i <= n; i++ )
230     {
231       Handle(HYDROData_Entity) anObj = theObjs.Value( i );
232       if( !anObj.IsNull() )
233       {
234         bool anIsVisible = module()->isObjectVisible( (size_t)aViewer, anObj );
235         aPrs = module()->getObjectVTKPrs( (size_t)aViewer, anObj );
236
237         bool anIsInserted = ( aPrs != 0 );
238         if( anIsVisible && ( !aPrs || aPrs->getIsToUpdate() || theIsForced ) )
239         {
240           // Erase the presentation in the view because of the problem with GEOM_Actor upadting on second SetShape.
241           if ( aPrs )
242           {
243             aViewer->Erase( aPrs, true );
244           }
245           // Update the presentation
246           if( HYDROGUI_VTKPrsDriver* aDriver = getDriver( (size_t)aViewer, anObj ) )
247           {
248             if( aDriver->Update( anObj, aPrs ) && aPrs && !anIsInserted )
249             {
250               module()->setObjectVTKPrs( (size_t)aViewer, anObj, aPrs );
251             }
252           }
253         }
254
255         if( aPrs )
256         {
257           if ( anIsVisible )
258           {
259             if ( aPrs->needScalarBar() )
260             {
261               // Extend the global Z range if necessary
262               double* aGlobalRange = GetZRange( (size_t)aViewer );
263               double* aRange = aPrs->getInternalZRange();
264               bool anIsUpdate = false;
265               if ( aRange[0] < aGlobalRange[0] || ValuesEquals( aGlobalRange[0], anInvalidZ ) )
266               {
267                 aGlobalRange[0] = aRange[0];
268                 anIsUpdate = true;
269               }
270               if ( aRange[1] > aGlobalRange[1] || ValuesEquals( aGlobalRange[1], anInvalidZ ) )
271               {
272                 aGlobalRange[1] = aRange[1];
273                 anIsUpdate = true;
274               }
275
276               if ( anIsUpdate )
277               {
278                 module()->updateVTKZRange( (size_t)aViewer, aGlobalRange );
279               }
280             }
281
282             aViewer->Display( aPrs );
283             isScalarBarNeeded = isScalarBarNeeded || aPrs->needScalarBar();
284
285           }
286           else
287           {
288             aViewer->Erase( aPrs );
289           }
290           isChanged = true;
291         }
292       }
293     }
294
295     if ( aView ) 
296     {
297       if ( isChanged && isScalarBarNeeded && aScalarBar )
298       {
299         // Show colors legend bar
300           aView->getRenderer()->AddActor2D( aScalarBar );
301       }
302
303       // Refresh the view
304       if ( theDoFitAll )
305       {
306         // Repaint is done inside OnFitAll()
307         aView->onAccelAction( SUIT_Accel::ZoomFit );
308       } 
309       else if ( isChanged )
310       {
311         aView->Repaint( true );
312       }
313     }
314   }
315 }
316
317 void HYDROGUI_VTKPrsDisplayer::purgeObjects( const int theViewerId )
318 {
319   bool doEraseScalarBar = false;
320
321   SVTK_Viewer* aViewer = module()->getVTKViewer( theViewerId );
322   if( aViewer )
323   {
324     SALOME_ListIO aListIO;
325     aViewer->GetVisible( aListIO );
326     
327     HYDROGUI_VTKPrs* aPrs;
328     SALOME_ListIteratorOfListIO anIter( aListIO );
329     for( ; anIter.More(); anIter.Next() )
330     {
331       Handle(SALOME_InteractiveObject) aPrsObj = anIter.Value();
332       if ( !aPrsObj.IsNull() )
333       {
334         Handle(HYDROData_Entity) anOwnerObj = 
335           module()->getDataModel()->objectByEntry( aPrsObj->getEntry() );
336         if ( anOwnerObj.IsNull() )
337         {
338           // We found an unknown IO presented in the viewer. 
339           // Remove such an orphan presentation from all the views of the viewer.
340           SUIT_ViewManager* aViewMgr = dynamic_cast<SUIT_ViewManager*>( aViewer->getViewManager() );
341           if ( aViewMgr && aViewMgr->getViewsCount() > 0 )
342           {
343             QVector<SUIT_ViewWindow*> aViews = aViewMgr->getViews();
344             foreach ( SUIT_ViewWindow* aView, aViews )
345             {
346               SVTK_ViewWindow* aVTKView = dynamic_cast<SVTK_ViewWindow*>( aView );
347               if ( aVTKView )
348               {
349                 aVTKView->Erase( aPrsObj, false );
350               }
351             }
352           }
353           // Remove the object presentation from the module's cache
354           module()->removeObjectVTKPrs( (size_t)aViewer, aPrsObj->getEntry() );
355           doEraseScalarBar = true;
356         }
357         else if ( anOwnerObj->IsRemoved() )
358         {
359           aPrs = module()->getObjectVTKPrs( (size_t)aViewer, anOwnerObj );
360           if ( aPrs )
361           {
362             aViewer->Erase( aPrs );
363           }
364           else
365           {
366           }
367           module()->removeObjectVTKPrs( (size_t)aViewer, anOwnerObj );
368           doEraseScalarBar = true;
369         }
370       }
371     }
372
373     if ( doEraseScalarBar )
374     {
375       EraseScalarBar( theViewerId );
376     }
377   }
378 }
379
380 HYDROGUI_VTKPrsDriver* HYDROGUI_VTKPrsDisplayer::getDriver( const int theViewId, const Handle(HYDROData_Entity)& theObj )
381 {
382   HYDROGUI_VTKPrsDriver* aDriver = NULL;
383   ObjectKind aKind = theObj->GetKind();
384   if( theObj->GetKind() == KIND_BATHYMETRY )
385   {
386     if ( !myDriver )
387     {
388       myDriver = new HYDROGUI_VTKPrsBathymetryDriver( myScalarBars[ theViewId ] );
389     }
390     aDriver = myDriver;
391   }
392   else
393   {
394     if ( !myShapeDriver )
395     {
396       myShapeDriver = new HYDROGUI_VTKPrsShapeDriver( myScalarBars[ theViewId ] );
397     }
398     aDriver = myShapeDriver;
399   }
400
401   return aDriver;
402 }
403
404 QString HYDROGUI_VTKPrsDisplayer::GetType() const
405 {
406   return SVTK_Viewer::Type();
407 }
408
409 void HYDROGUI_VTKPrsDisplayer::SetZRange( const int theViewId, double theRange[] )
410 {
411   myScalarBars[ theViewId ]->GetLookupTable()->SetRange( theRange );
412 }
413
414 double* HYDROGUI_VTKPrsDisplayer::GetZRange( const int theViewId ) const
415 {
416   return myScalarBars[ theViewId ]->GetLookupTable()->GetRange();
417 }
418
419 void HYDROGUI_VTKPrsDisplayer::createScalarBar( const int theViewId )
420 {
421   if ( !myScalarBars.contains( theViewId ) )
422   {
423     // The invalid value is used to identify the case when the table range is not initialized yet.
424     double anInvalidValue = HYDROGUI_VTKPrs::InvalidZValue();
425     vtkLookupTable* aTable = vtkLookupTable::New();
426     aTable->SetHueRange( HUE_START, HUE_END );
427     aTable->SetSaturationRange( SATURATION_START, SATURATION_END );
428     aTable->SetTableRange( anInvalidValue, anInvalidValue );
429     aTable->SetValueRange( 1.0, 1.0 );
430     aTable->SetAlphaRange( 1.0, 1.0 );
431     aTable->SetNumberOfColors( NB_COLORS );
432     aTable->Build();
433     vtkSmartPointer<vtkScalarBarActor> aScalarBar = vtkScalarBarActor::New();
434     aScalarBar->SetLookupTable( aTable );
435     aScalarBar->SetNumberOfLabels( NB_COLORS * 0.75 );
436     aScalarBar->SetWidth( aScalarBar->GetWidth() / 1.5 );
437     aScalarBar->SetTextureGridWidth( aScalarBar->GetTextureGridWidth() * 4. );
438     aScalarBar->SetTitle( "  " );
439     // The call of SetTitle() with dummy string is a workaround necessary
440     // to avoid the problem with uninitialized variables in VTK scalar bar actor
441     // which leads to incorrect (very big) size of the VTK scalar bar presentation
442     aTable->Delete();
443     myScalarBars.insert( theViewId, aScalarBar );
444   }
445 }