Salome HOME
Merge remote-tracking branch 'origin/BR_LAND_COVER' into BR_v14_rc
[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_Tool.h"
24 #include <HYDROGUI_ShapeImage.h>
25 #include <HYDROGUI_ShapeBathymetry.h>
26 #include <HYDROGUI_ShapeLandCover.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_LandCover.h>
33 #include <HYDROData_StricklerTable.h>
34
35 #include <AIS_InteractiveContext.hxx>
36 #include <AIS_ListIteratorOfListOfInteractive.hxx>
37 #include <AIS_ListOfInteractive.hxx>
38
39 #include <Aspect_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_LandCover ) ) ) {
169     bool isScalarMode = module()->isLandCoversScalarMapModeOn( theViewerId );
170     aResShape = new HYDROGUI_ShapeLandCover( this, theContext, Handle_HYDROData_LandCover::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*> aLandCoverShapes = module()->getObjectShapes( aViewerId, KIND_LAND_COVER );
423   QList<HYDROGUI_Shape*> aBathShapes = module()->getObjectShapes( aViewerId, KIND_BATHYMETRY );
424
425   bool isDisplayColorScale = !aBathShapes.empty() || isLandCoverColoringOn;
426   Standard_Real anXPos = 0.05; //TODO
427   Standard_Real anYPos = 0.1; //TODO
428   Standard_Real aWidth = 0.2; //TODO
429   Standard_Real aHeight = 0.5; //TODO
430   Standard_Integer aTextHeight = 14; //TODO
431   Standard_Integer aNbIntervals = 20; //TODO
432   TCollection_ExtendedString aColorScaleTitle = "";//TODO
433
434   Standard_Real aColorScaleMin = 0, aColorScaleMax = 1;
435
436   // Get range
437   Handle(HYDROData_StricklerTable) aTable;
438   TColStd_SequenceOfExtendedString aTableTypes;
439   if ( isLandCoverColoringOn ) {
440     aTable = module()->getLandCoverColoringTable( aViewerId );
441     if ( !aTable.IsNull() ) {
442       // TODO: non-empty title leads to buggy behaviour
443       // aColorScaleTitle = TCollection_ExtendedString( aTable->GetName().toLatin1().constData() );
444       aTable->GetCoefficientRange( aColorScaleMin, aColorScaleMax );
445       aTableTypes = aTable->GetTypes();
446     }
447   } else {
448     Standard_Real aMin, aMax;
449     bool isFirst = true;
450     foreach( HYDROGUI_Shape* aShape, aBathShapes )
451     {
452       HYDROGUI_ShapeBathymetry* aBathShape = dynamic_cast<HYDROGUI_ShapeBathymetry*>( aShape );
453       if( !aBathShape || !aBathShape->isVisible() )
454         continue;
455
456       aBathShape->GetRange( aMin, aMax );
457
458       if( isFirst || aMin < aColorScaleMin )
459         aColorScaleMin = aMin;
460       if( isFirst || aMax > aColorScaleMax )
461         aColorScaleMax = aMax;
462
463       isFirst = false;
464     }
465   }
466
467   Handle(Aspect_ColorScale) aColorScale;
468   if( isDisplayColorScale )
469   {
470     aColorScale = aView->ColorScale();
471     if( !aColorScale.IsNull() )
472     {
473       aColorScale->SetXPosition( anXPos );
474       aColorScale->SetYPosition( anYPos );
475       aColorScale->SetWidth( aWidth );
476       aColorScale->SetHeight( aHeight );
477
478       aColorScale->SetTextHeight( aTextHeight );
479       aColorScale->SetNumberOfIntervals( aNbIntervals );
480
481       aColorScale->SetTitle( aColorScaleTitle );
482       aColorScale->SetRange( aColorScaleMin, aColorScaleMax );
483
484       if ( !isLandCoverColoringOn ) {
485         foreach( HYDROGUI_Shape* aShape, aBathShapes ) {
486           HYDROGUI_ShapeBathymetry* aBathShape = dynamic_cast<HYDROGUI_ShapeBathymetry*>( aShape );
487           if( !aBathShape || !aBathShape->isVisible() )
488             continue;
489
490           aBathShape->UpdateWithColorScale( aColorScale );
491         }
492       }
493     }
494     if( !aView->ColorScaleIsDisplayed() )
495       aView->ColorScaleDisplay();
496   }
497   else
498   {
499     if( aView->ColorScaleIsDisplayed() )
500       aView->ColorScaleErase();
501   }
502
503   foreach( HYDROGUI_Shape* aShape, aLandCoverShapes ) {
504     HYDROGUI_ShapeLandCover* aLandCoverShape = 
505       dynamic_cast<HYDROGUI_ShapeLandCover*>( aShape );
506
507     if ( !aLandCoverShape || !aLandCoverShape->isVisible() ) {
508       continue;
509     }
510     
511     Handle(HYDROData_LandCover) aLandCover = 
512       Handle(HYDROData_LandCover)::DownCast( aLandCoverShape->getObject() );
513
514     if ( aLandCover.IsNull() ) {
515       continue;
516     }
517     
518     QColor aUndefinedColor( Qt::gray );
519     QColor aColor = isLandCoverColoringOn ? aUndefinedColor : aLandCover->GetFillingColor();
520     
521     if ( isLandCoverColoringOn && !aTable.IsNull() ) {
522       TCollection_ExtendedString aStricklerType = 
523         aLandCover->GetStricklerType().toLatin1().constData();
524      
525       if ( aTable->HasType( aStricklerType ) ) {
526         double aStricklerCoeff = aTable->Get( aStricklerType, 0 );
527         Quantity_Color aShapeColor;
528         if ( aColorScale->FindColor( aStricklerCoeff, aShapeColor ) ) {
529           aColor = QColor( aShapeColor.Red() * 255, 
530                            aShapeColor.Green() * 255,
531                            aShapeColor.Blue() * 255 );
532         }
533       }
534     }
535     
536     aLandCoverShape->setFillingColor( aColor, true, true );
537     aLandCoverShape->setScalarMapModeEnabled( isLandCoverColoringOn );
538     theViewer->getAISContext()->Redisplay( aLandCoverShape->getAISObject() );
539   }
540
541   myToUpdateColorScale = false;
542 }