Salome HOME
refs #1327: debug of scaling operations
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_OCCDisplayer.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include "HYDROGUI_OCCDisplayer.h"
20
21 #include "HYDROGUI_DataModel.h"
22 #include "HYDROGUI_Module.h"
23 #include "HYDROGUI_Tool2.h"
24 #include <HYDROGUI_ShapeImage.h>
25 #include <HYDROGUI_ShapeBathymetry.h>
26 #include <HYDROGUI_ShapeLandCoverMap.h>
27 #include "HYDROGUI_Operation.h"
28 #include "HYDROGUI_DataObject.h"
29 #include "HYDROGUI_ZLayers.h"
30
31 #include <HYDROData_Bathymetry.h>
32 #include <HYDROData_Image.h>
33 #include <HYDROData_LandCoverMap.h>
34 #include <HYDROData_StricklerTable.h>
35
36 #include <AIS_InteractiveContext.hxx>
37 #include <AIS_ListIteratorOfListOfInteractive.hxx>
38 #include <AIS_ListOfInteractive.hxx>
39 #include <AIS_ColorScale.hxx>
40
41 #include <TColStd_SequenceOfInteger.hxx>
42
43 #include <LightApp_Application.h>
44 #include <SUIT_Study.h>
45
46 #include <OCCViewer_ViewManager.h>
47 #include <OCCViewer_ViewModel.h>
48 #include <OCCViewer_ViewWindow.h>
49 #include <OCCViewer_ViewPort3d.h>
50
51 HYDROGUI_OCCDisplayer::HYDROGUI_OCCDisplayer( HYDROGUI_Module* theModule )
52 : HYDROGUI_AbstractDisplayer( theModule )
53 {
54   myToUpdateColorScale = false;
55 }
56
57 HYDROGUI_OCCDisplayer::~HYDROGUI_OCCDisplayer()
58 {
59 }
60
61 void HYDROGUI_OCCDisplayer::SetToUpdate( const HYDROData_SequenceOfObjects& theObjs,
62                                          const int                          theViewerId )
63 {
64   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
65   if( !aViewer )
66     return;
67
68   for ( int i = 1, n = theObjs.Length(); i <= n; i++ )
69   {
70     Handle(HYDROData_Entity) anObj = theObjs.Value( i );
71     if( anObj.IsNull() )
72       continue;
73
74     HYDROGUI_Shape* anObjShape = module()->getObjectShape( (size_t)aViewer, anObj );
75     if ( !anObjShape )
76       continue;
77     
78     anObjShape->setIsToUpdate( true );
79   }
80 }
81
82 int HYDROGUI_OCCDisplayer::AddPreviewZLayer( OCCViewer_ViewManager* theMgr )
83 {
84   int aLayer = -1;
85   OCCViewer_Viewer* aViewer = theMgr->getOCCViewer();
86   if ( !aViewer )
87     return aLayer;
88
89   aLayer = CreateTopZLayer( aViewer->getViewer3d() );
90   
91   // Hilight presentation should be on top
92   Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
93   if( !aCtx.IsNull() ) {
94     int aTopLayer = CreateTopZLayer( aViewer->getViewer3d() );
95     if ( aTopLayer > 0 ) {
96       UpdateZLayersOfHilightPresentationsOfDisplayedObjects( aCtx, aTopLayer );
97     }
98   }
99
100   return aLayer;
101 }
102
103 void HYDROGUI_OCCDisplayer::RemoveZLayer( OCCViewer_ViewManager* theMgr,
104                                           const int theLayer )
105 {
106   if ( theLayer < 0 )
107     return;
108
109   OCCViewer_Viewer* aViewer = theMgr->getOCCViewer();
110   if ( !aViewer )
111     return;
112
113   // Get existing Z layers
114   TColStd_SequenceOfInteger anExistingZLayers;
115   aViewer->getViewer3d()->GetAllZLayers( anExistingZLayers );
116   int aNbLayers = anExistingZLayers.Length();
117   
118   if ( theLayer < aNbLayers )
119     aViewer->getViewer3d()->RemoveZLayer( theLayer );
120 }
121
122 void HYDROGUI_OCCDisplayer::EraseAll( const int theViewerId )
123 {
124   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
125   if( !aViewer )
126     return;
127
128   module()->removeViewShapes( (size_t)aViewer );
129   UpdateColorScale( aViewer );
130 }
131
132 void HYDROGUI_OCCDisplayer::Erase( const HYDROData_SequenceOfObjects& theObjs,
133                                    const int                          theViewerId )
134 {
135   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
136   if( !aViewer )
137     return;
138
139   for ( int i = 1, n = theObjs.Length(); i <= n; i++ )
140   {
141     Handle(HYDROData_Entity) anObj = theObjs.Value( i );
142     if( anObj.IsNull() )
143       continue;
144
145     module()->removeObjectShape( (size_t)aViewer, anObj );
146   }
147   aViewer->update();
148   if ( !module()->isLandCoversScalarMapModeOn( (size_t)aViewer ) ) {
149     UpdateColorScale( aViewer );
150   }
151 }
152
153 HYDROGUI_Shape* HYDROGUI_OCCDisplayer::createShape( const int                             theViewerId,
154                                                     const Handle(AIS_InteractiveContext)& theContext,
155                                                     const Handle(HYDROData_Entity)&       theObject )
156 {
157   HYDROGUI_Shape* aResShape = NULL;
158   if ( theContext.IsNull() || theObject.IsNull() )
159     return aResShape;
160
161   if ( !HYDROGUI_Tool::IsObjectHasPresentation( theObject, OCCViewer_Viewer::Type() ) )
162     return aResShape;
163
164   if( theObject->IsKind( STANDARD_TYPE( HYDROData_Image ) ) )
165     aResShape = new HYDROGUI_ShapeImage( theContext, Handle(HYDROData_Image)::DownCast( theObject ) );
166   else if( theObject->IsKind( STANDARD_TYPE( HYDROData_Bathymetry ) ) )
167     aResShape = new HYDROGUI_ShapeBathymetry( this, theContext, Handle(HYDROData_Bathymetry)::DownCast( theObject ) );
168   else if( theObject->IsKind( STANDARD_TYPE( HYDROData_LandCoverMap ) ) ) {
169     bool isScalarMode = module()->isLandCoversScalarMapModeOn( theViewerId );
170     aResShape = new HYDROGUI_ShapeLandCoverMap( this, theContext, Handle(HYDROData_LandCoverMap)::DownCast( theObject ), -1, isScalarMode );
171   }
172   else
173     aResShape = new HYDROGUI_Shape( theContext, theObject );
174
175   module()->setObjectShape( theViewerId, theObject, aResShape );
176
177   return aResShape;
178 }
179
180 void HYDROGUI_OCCDisplayer::Display( const HYDROData_SequenceOfObjects& theObjs,
181                                      const int                          theViewerId,
182                                      const bool                         theIsForced,
183                                      const bool theDoFitAll )
184 {
185   // Get OCC viewer by id
186   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
187   if( !aViewer )
188     return;
189
190   // Get interactive context
191   Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
192   if( aCtx.IsNull() )
193     return;
194
195   // Get the document
196   Handle(HYDROData_Document) aDoc = HYDROData_Document::Document( module()->getStudyId() );
197   if ( !aDoc )
198     return;
199   
200   // Assign Z layer indexes to the objects
201   aDoc->Show( theObjs );
202
203   // Sort objects by display order ( needed for Z layers assignment only )
204   HYDROData_SequenceOfObjects anUnorderedToDisplay = theObjs;
205   HYDROData_SequenceOfObjects anOrderedToDisplay;
206   HYDROData_SequenceOfObjects anAllOrderedObjects = aDoc->GetObjectsLayerOrder();
207
208   HYDROData_SequenceOfObjects::Iterator anAllOrderedIter( anAllOrderedObjects );
209   for ( ; anAllOrderedIter.More(); anAllOrderedIter.Next() ) {
210     QString anOrderedEntry = 
211       HYDROGUI_DataObject::dataObjectEntry( anAllOrderedIter.Value() );
212     
213     HYDROData_SequenceOfObjects::Iterator aToDisplayIter( anUnorderedToDisplay );
214     for ( ; aToDisplayIter.More(); aToDisplayIter.Next() ) {
215       Handle(HYDROData_Entity) anObjToDisplay = aToDisplayIter.Value();
216       QString anEntry = HYDROGUI_DataObject::dataObjectEntry( anObjToDisplay );
217       if ( anEntry == anOrderedEntry ) {
218         anOrderedToDisplay.Prepend( anObjToDisplay );
219         anUnorderedToDisplay.Remove( aToDisplayIter );
220         break;
221       }
222     }
223   }
224   
225   // Get 3d viewer
226   Handle(V3d_Viewer) aViewer3d = aViewer->getViewer3d();
227
228   // Display objects:
229   HYDROGUI_ZLayersIterator aZLayersIt( aViewer->getViewer3d() );
230   if ( !aZLayersIt.More() ) {
231     aZLayersIt.Next();
232   }
233
234   // 1. Display the ordered objects:
235   HYDROData_SequenceOfObjects::Iterator anOrderedIter( anOrderedToDisplay );
236   for ( ; anOrderedIter.More(); anOrderedIter.Next() ) {
237     Handle(HYDROData_Entity) anObj = anOrderedIter.Value();
238     if ( Display( anObj, aViewer, theIsForced ) ) {
239       // set Z layer ( one Z layer for each ordered object )
240       int aZLayerId = aZLayersIt.LayerId();
241       SetZLayer( aViewer, anObj, aZLayerId );
242       SetZLayerSettings( aViewer3d, aZLayerId, true );
243       aZLayersIt.Next();
244     }
245   }
246
247   // 2. Display the unordered objects:
248   bool isDisplayed = false;
249   int anUnorderedZLayerId = aZLayersIt.LayerId();
250   HYDROData_SequenceOfObjects::Iterator anUnorderedIter( anUnorderedToDisplay );
251   for ( ; anUnorderedIter.More(); anUnorderedIter.Next() ) {
252     Handle(HYDROData_Entity) anObj = anUnorderedIter.Value();
253     if ( Display( anObj, aViewer, theIsForced) ) {
254       // set Z layer ( one Z layer for all unordered objects )
255       SetZLayer( aViewer, anObj, anUnorderedZLayerId );
256       if ( !isDisplayed ) {
257         SetZLayerSettings( aViewer3d, anUnorderedZLayerId, false );
258       }
259       isDisplayed = true;
260     }
261   }
262   
263   // 3. Update the top Z layer index
264   if ( isDisplayed ) {
265     aZLayersIt.Next();
266   }
267
268   // Update Z layer of the active operation
269   int aPreviewZLayerId = aZLayersIt.LayerId();
270
271   HYDROGUI_Module* aModule = module();
272   SUIT_Operation* anOp = aModule->activeOperation();
273   HYDROGUI_Operation* aHOp = anOp ? dynamic_cast<HYDROGUI_Operation*>( anOp ) : 0;
274   if ( aHOp && aHOp->getPreviewZLayer() >= 0 ) {
275     aHOp->updatePreviewZLayer( aPreviewZLayerId );
276     aZLayersIt.Next();
277   }
278
279   // Update Z layer of hilight presentations
280   int aHilightLayer = aZLayersIt.TopLayer();
281   UpdateZLayersOfHilightPresentationsOfDisplayedObjects( aCtx, aHilightLayer );
282
283   // Fit all / update selection
284   if ( theDoFitAll ) {
285     OCCViewer_ViewManager* aViewManager
286       = ::qobject_cast<OCCViewer_ViewManager*>( aViewer->getViewManager() );
287     if ( aViewManager ) {
288       OCCViewer_ViewWindow* aViewWindow = 
289         ::qobject_cast<OCCViewer_ViewWindow*>( aViewManager->getActiveView() );
290       if ( aViewWindow ) {
291         aViewWindow->onFitAll();
292       }
293     }
294   } 
295   else if ( !aCtx.IsNull() ) { // TODO: determine if this code is necessary (added as a fix for issue# 359)
296     aCtx->UpdateSelected();
297   }
298
299   UpdateColorScale( aViewer );
300 }
301
302 void HYDROGUI_OCCDisplayer::purgeObjects( const int theViewerId )
303 {
304   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
305   if( !aViewer )
306     return;
307
308   Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
309   if( aCtx.IsNull() )
310     return;
311
312   AIS_ListOfInteractive aDisplayedObjects;
313   aCtx->DisplayedObjects( aDisplayedObjects );
314
315   AIS_ListIteratorOfListOfInteractive aListIter( aDisplayedObjects );
316   for ( ; aListIter.More(); aListIter.Next() )
317   {
318     Handle(AIS_InteractiveObject) aPrsObj = aListIter.Value();
319     if ( aPrsObj.IsNull() )
320       continue;
321
322     Handle(HYDROData_Entity) anOwnerObj = 
323       Handle(HYDROData_Entity)::DownCast( aPrsObj->GetOwner() );
324     if ( !anOwnerObj.IsNull() && anOwnerObj->IsRemoved() )
325       module()->removeObjectShape( (size_t)aViewer, anOwnerObj );
326   }
327 }
328
329 QString HYDROGUI_OCCDisplayer::GetType() const
330 {
331   return OCCViewer_Viewer::Type();
332 }
333
334 bool HYDROGUI_OCCDisplayer::Display( const Handle(HYDROData_Entity)& theObject,
335                                      const OCCViewer_Viewer* theViewer,
336                                      const bool theIsForced )
337 {
338   bool aRes = false;
339
340   if ( theObject.IsNull() || theObject->IsRemoved() || !theViewer ) {
341     return aRes;
342   }
343
344   // Get interactive context
345   Handle(AIS_InteractiveContext) aCtx = theViewer->getAISContext();
346   if( aCtx.IsNull() ) {
347     return aRes;
348   }
349
350   // Viewer id
351   size_t aViewerId = (size_t)theViewer;
352
353   // Object shape 
354   HYDROGUI_Shape* anObjShape = module()->getObjectShape( aViewerId, theObject );
355   // create if needed
356   if ( !anObjShape ) {
357     anObjShape = createShape( aViewerId, aCtx, theObject );
358     if ( anObjShape ) {
359       anObjShape->setIsToUpdate( true );
360     }
361   }
362   
363   // Process the shape
364   if ( anObjShape ) {
365     // update if needed
366     if ( anObjShape->getIsToUpdate() || theIsForced ) {
367       anObjShape->update( false, false );
368     }
369
370     // Set visibility
371     bool anIsVisible = module()->isObjectVisible( aViewerId, theObject );
372     anObjShape->setVisible( anIsVisible, false );
373
374     aRes = true;
375   }
376
377   return aRes;
378 }
379
380 void HYDROGUI_OCCDisplayer::SetZLayer( const OCCViewer_Viewer* theViewer,
381                                        const Handle(HYDROData_Entity)& theObject, 
382                                        const int theZLayerId )
383 {
384   if ( !theViewer /*|| ( theZLayerId < 0 )*/ ) {
385     return;
386   }
387   
388   // Get interactive context
389   Handle(AIS_InteractiveContext) aCtx = theViewer->getAISContext();
390   if( aCtx.IsNull() ) {
391     return;
392   }
393
394   // Get viewer id
395   size_t aViewerId = (size_t)theViewer;
396
397   // Get object shape 
398   HYDROGUI_Shape* anObjShape = module()->getObjectShape( aViewerId, theObject );
399
400   // Set Z layer
401   if ( anObjShape ) {
402     aCtx->SetZLayer( anObjShape->getAISObject(), theZLayerId );
403   }
404 }
405
406 void HYDROGUI_OCCDisplayer::SetToUpdateColorScale()
407 {
408   myToUpdateColorScale = true;
409 }
410
411 void HYDROGUI_OCCDisplayer::UpdateColorScale( const OCCViewer_Viewer* theViewer )
412 {
413   if( !myToUpdateColorScale || !theViewer )
414     return;
415   
416   OCCViewer_ViewWindow* aWnd = dynamic_cast<OCCViewer_ViewWindow*>( theViewer->getViewManager()->getActiveView() );
417   Handle(V3d_View) aView = aWnd->getViewPort()->getView();
418       
419   int aViewerId = (size_t)theViewer;//TODO: check if viewer id is correct
420   bool isLandCoverColoringOn = module()->isLandCoversScalarMapModeOn( aViewerId );
421     
422   QList<HYDROGUI_Shape*> aLandCoverMapShapes = module()->getObjectShapes( aViewerId, KIND_LAND_COVER_MAP );
423   QList<HYDROGUI_Shape*> aBathShapes = module()->getObjectShapes( aViewerId, KIND_BATHYMETRY );
424
425   bool isDisplayColorScale = !aBathShapes.empty() || isLandCoverColoringOn;
426
427   Standard_Real aColorScaleMin = 0, aColorScaleMax = 1;
428
429   // Get range
430   Handle(HYDROData_StricklerTable) aTable;
431   QStringList aTableTypes;
432   if ( isLandCoverColoringOn ) {
433     aTable = module()->getLandCoverColoringTable( aViewerId );
434     if ( !aTable.IsNull() ) {
435       // TODO: non-empty title leads to buggy behaviour
436       // aColorScaleTitle = TCollection_ExtendedString( aTable->GetName().toLatin1().constData() );
437       aTable->GetCoefficientRange( aColorScaleMin, aColorScaleMax );
438       aTableTypes = aTable->GetTypes();
439     }
440   } else {
441     Standard_Real aMin, aMax;
442     bool isFirst = true;
443     foreach( HYDROGUI_Shape* aShape, aBathShapes )
444     {
445       HYDROGUI_ShapeBathymetry* aBathShape = dynamic_cast<HYDROGUI_ShapeBathymetry*>( aShape );
446       if( !aBathShape || !aBathShape->isVisible() )
447         continue;
448
449       aBathShape->GetRange( aMin, aMax );
450
451       if( isFirst || aMin < aColorScaleMin )
452         aColorScaleMin = aMin;
453       if( isFirst || aMax > aColorScaleMax )
454         aColorScaleMax = aMax;
455
456       isFirst = false;
457     }
458   }
459
460   Handle(AIS_ColorScale) aColorScale = GetColorScale( aViewerId );
461   Handle(AIS_InteractiveContext) aCtx = theViewer->getAISContext();
462   if( isDisplayColorScale )
463   {
464     if( !aColorScale.IsNull() )
465     {
466       // Set color scale title
467       TCollection_ExtendedString aColorScaleTitle = ""; //TODO
468       aColorScale->SetTitle( aColorScaleTitle );
469       
470       // Set color scale range
471       aColorScale->SetRange( aColorScaleMin, aColorScaleMax );
472       
473       aColorScale->SetToUpdate();
474
475       if ( !isLandCoverColoringOn ) {
476         foreach( HYDROGUI_Shape* aShape, aBathShapes ) {
477           HYDROGUI_ShapeBathymetry* aBathShape = dynamic_cast<HYDROGUI_ShapeBathymetry*>( aShape );
478           if( !aBathShape || !aBathShape->isVisible() )
479             continue;
480
481           aBathShape->UpdateWithColorScale( aColorScale );
482         }
483       }
484       
485       if ( !aCtx.IsNull()/* && !aCtx->IsDisplayed( aColorScale ) */) {
486         if ( !aCtx->IsDisplayed( aColorScale ) ) {
487           aCtx->Display( aColorScale, Standard_False );
488         }
489
490         aCtx->Update( aColorScale );
491       }
492     }
493   }
494   else
495   {
496     if ( !aCtx.IsNull() && aCtx->IsDisplayed( aColorScale ) ) {
497       aCtx->Erase( aColorScale );
498     }
499   }
500
501   foreach( HYDROGUI_Shape* aShape, aLandCoverMapShapes ) {
502     HYDROGUI_ShapeLandCoverMap* aLandCoverMapShape = 
503       dynamic_cast<HYDROGUI_ShapeLandCoverMap*>( aShape );
504
505     if ( !aLandCoverMapShape || !aLandCoverMapShape->isVisible() ) {
506       continue;
507     }
508     
509     Handle(HYDROData_LandCoverMap) aLandCoverMap = 
510       Handle(HYDROData_LandCoverMap)::DownCast( aLandCoverMapShape->getObject() );
511
512     if ( aLandCoverMap.IsNull() ) {
513       continue;
514     }
515     
516     bool isScalarMode = aLandCoverMapShape->isScalarMapModeEnabled();
517     if( isScalarMode != isLandCoverColoringOn )
518     {
519       aLandCoverMapShape->setScalarMapModeEnabled( isLandCoverColoringOn );
520       theViewer->getAISContext()->Redisplay( aLandCoverMapShape->getAISObject() );
521     }
522   }
523   
524   myToUpdateColorScale = false;
525 }
526
527 Handle(AIS_ColorScale) HYDROGUI_OCCDisplayer::GetColorScale( const int theViewerId )
528 {
529   Handle(AIS_ColorScale) aColorScale;
530
531   aColorScale = myColorScales.value( theViewerId, aColorScale );
532   if ( aColorScale.IsNull() ) {
533     // Create color scale
534     aColorScale = new AIS_ColorScale();
535
536     // Set properties
537     Standard_Integer anXPos = 50; //TODO
538     Standard_Integer anYPos = 100; //TODO
539     Standard_Integer aWidth = 100; //TODO
540     Standard_Integer aHeight = 350; //TODO
541     
542     Standard_Integer aTextHeight = 14; //TODO
543     Standard_Integer aNbIntervals = 20; //TODO
544
545     aColorScale->SetTransformPersistence( Graphic3d_TMF_2d, gp_Pnt( -1, -1, 0 ) );
546     
547     aColorScale->SetXPosition( anXPos );
548     aColorScale->SetYPosition( anYPos );
549     aColorScale->SetSize( aWidth, aHeight );
550
551     aColorScale->SetTextHeight( aTextHeight );
552     aColorScale->SetNumberOfIntervals( aNbIntervals );
553
554     // Put into the map
555     myColorScales.insert( theViewerId, aColorScale );
556   }
557
558   return aColorScale;
559 }