Salome HOME
refs #514: add 'Cursor for specific operations' section into preferences of HYDRO...
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_Shape.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_Shape.h>
24 #include <HYDROGUI_Tool.h>
25 #include <HYDROData_Channel.h>
26 #include <HYDROData_Document.h>
27 #include <HYDROData_DummyObject3D.h>
28 #include <HYDROData_ImmersibleZone.h>
29 #include <HYDROData_Obstacle.h>
30 #include <HYDROData_PolylineXY.h>
31 #include <HYDROData_Polyline3D.h>
32 #include <HYDROData_Profile.h>
33 #include <HYDROData_ShapesGroup.h>
34 #include <HYDROData_Stream.h>
35 #include <HYDROData_Zone.h>
36
37 #include <AIS_Shape.hxx>
38 #include <BRep_Builder.hxx>
39 #include <BRepBuilderAPI_MakeFace.hxx>
40 #include <Graphic3d_AspectFillArea3d.hxx>
41 #include <Prs3d_IsoAspect.hxx>
42 #include <Prs3d_ShadingAspect.hxx>
43 #include <TopoDS.hxx>
44 #include <TopoDS_Face.hxx>
45 #include <TopoDS_Wire.hxx>
46 #include <TopExp_Explorer.hxx>
47
48 HYDROGUI_Shape::HYDROGUI_Shape( const Handle(AIS_InteractiveContext)& theContext,
49                                 const Handle(HYDROData_Entity)&       theObject,
50                                 const int                             theZLayer )
51 : myContext( theContext ),
52   myObject( theObject ),
53   myZLayer( theZLayer ),
54   myIsHighlight( false ),
55   myFillingColor( Qt::transparent ),
56   myBorderColor( Qt::black ),
57   myHighlightColor( Qt::white ),
58   myIsToUpdate( false ),
59   myIsVisible( true ),
60   myDisplayMode( AIS_Shaded )
61 {
62 }
63
64 HYDROGUI_Shape::~HYDROGUI_Shape()
65 {
66   erase( false );
67
68   if ( !myShape.IsNull() )
69     myShape.Nullify();
70 }
71
72 Handle(AIS_InteractiveContext) HYDROGUI_Shape::getContext() const
73 {
74   return myContext;
75 }
76
77 Handle(HYDROData_Entity) HYDROGUI_Shape::getObject() const
78 {
79   return myObject;
80 }
81
82 TopoDS_Shape HYDROGUI_Shape::getTopoShape() const
83 {
84   return myTopoShape;
85 }
86
87 bool HYDROGUI_Shape::getIsToUpdate() const
88 {
89   return myIsToUpdate;
90 }
91
92 void HYDROGUI_Shape::setIsToUpdate( bool theState )
93 {
94   myIsToUpdate = theState;
95 }
96
97 bool HYDROGUI_Shape::isVisible() const
98 {
99   return myIsVisible;
100 }
101
102 Handle(AIS_InteractiveObject) HYDROGUI_Shape::getAISObject() const
103 {
104   return myShape;
105 }
106
107 void HYDROGUI_Shape::display( const bool theIsUpdateViewer )
108 {
109   if ( myContext.IsNull() || myShape.IsNull() || !isVisible() )
110     return;
111
112   displayShape( theIsUpdateViewer );
113 }
114
115 void HYDROGUI_Shape::erase( const bool theIsUpdateViewer )
116 {
117   if ( myContext.IsNull() || myShape.IsNull() )
118     return;
119
120   myContext->Erase( myShape, theIsUpdateViewer );
121 }
122
123 void HYDROGUI_Shape::update( bool isUpdateViewer,
124                              bool isDeactivateSelection )
125
126 {
127   setIsToUpdate( false );
128
129   if ( myContext.IsNull() )
130     return;
131
132   // Try to retrieve information from object
133   if ( !myObject.IsNull() )
134   {
135     Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myObject->Label() );
136   
137     if ( myObject->IsKind( STANDARD_TYPE(HYDROData_ImmersibleZone) ) )
138     {
139       Handle(HYDROData_ImmersibleZone) aZoneObj =
140         Handle(HYDROData_ImmersibleZone)::DownCast( myObject );
141
142       TopoDS_Shape aZoneShape = aZoneObj->GetTopShape();
143       if ( !aZoneShape.IsNull() ) {
144         if ( aZoneShape.ShapeType() == TopAbs_FACE ) {
145           TopoDS_Face aZoneFace = TopoDS::Face( aZoneShape );
146           setFace( aZoneFace, false, false, "" );
147         } else {
148           myTopoShape = aZoneShape;
149           //TODO: myDisplayMode = myTextureFileName.isEmpty() ? AIS_Shaded : AIS_Shaded+2;
150           myDisplayMode = AIS_Shaded;
151
152           buildShape();
153           updateShape( false, false );
154         }
155       }
156
157       QColor aFillingColor = aZoneObj->GetFillingColor();
158       QColor aBorderColor = aZoneObj->GetBorderColor();
159
160       setFillingColor( aFillingColor, false, false );
161       setBorderColor( aBorderColor, false, false );
162     }
163     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_PolylineXY) ) )
164     {
165       Handle(HYDROData_PolylineXY) aPolyline =
166         Handle(HYDROData_PolylineXY)::DownCast( myObject );
167
168       TopoDS_Shape aPolylineShape = aPolyline->GetShape();
169
170       if ( !aPolylineShape.IsNull() ) {
171         if ( aPolylineShape.ShapeType() == TopAbs_WIRE ) {
172           TopoDS_Wire aPolylineWire = TopoDS::Wire( aPolylineShape );
173           setWire( aPolylineWire, false, false );  
174         } else {
175           myTopoShape = aPolylineShape;
176           // Set shading mode to avoid that hilight presentation is equal to "normal" object presentation.
177           // Note that hilight presentation is always to be on top ( i.e. in the top Z layer ).
178           myDisplayMode = AIS_Shaded;
179
180           buildShape();
181           updateShape( false, false );
182         }
183       }
184
185       QColor aWireColor = aPolyline->GetWireColor();
186       setBorderColor( aWireColor, false, false );
187     }
188     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_Polyline3D) ) )
189     {
190       Handle(HYDROData_Polyline3D) aPolyline =
191         Handle(HYDROData_Polyline3D)::DownCast( myObject );
192
193       TopoDS_Shape aPolylineShape = aPolyline->GetShape3D();
194
195       if ( !aPolylineShape.IsNull() ) {
196         if ( aPolylineShape.ShapeType() == TopAbs_WIRE ) {
197           TopoDS_Wire aPolylineWire = TopoDS::Wire( aPolylineShape );
198           setWire( aPolylineWire, false, false );  
199         } else {
200           myTopoShape = aPolylineShape;
201           // Set shading mode to avoid that hilight presentation is equal to "normal" object presentation.
202           // Note that hilight presentation is always to be on top ( i.e. in the top Z layer ).
203           myDisplayMode = AIS_Shaded;
204
205           buildShape();
206           updateShape( false, false );
207         }
208       }
209
210       QColor aWireColor = aPolyline->GetBorderColor();
211       setBorderColor( aWireColor, false, false );
212     }
213     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_Zone) ) )
214     {
215       Handle(HYDROData_Zone) aZone =
216         Handle(HYDROData_Zone)::DownCast( myObject );
217
218       TopoDS_Face aZoneFace = TopoDS::Face( aZone->GetShape() );
219
220       setFace( aZoneFace, false, false, "" );
221       if (aZone->IsMergingNeed() && aZone->GetMergeType() == HYDROData_Zone::Merge_UNKNOWN )
222       {
223         // Red color for a zone with bathymetry conflict
224         setFillingColor( Qt::red );
225       }
226       else
227       {
228                 // Set the filling color for zone
229                 setFillingColor( aZone->GetColor(HYDROData_ImmersibleZone::DefaultFillingColor()) );
230       }
231     }
232     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_Profile) ) )
233     {
234       Handle(HYDROData_Profile) aProfile =
235         Handle(HYDROData_Profile)::DownCast( myObject );
236
237       TopoDS_Wire aProfileWire;
238
239       if ( aProfile->IsValid() ) {
240         TopoDS_Shape aProfileShape = aProfile->GetShape3D();
241
242         if ( !aProfileShape.IsNull() && 
243              aProfileShape.ShapeType() == TopAbs_WIRE ) {
244           aProfileWire = TopoDS::Wire( aProfileShape );
245         }
246       }
247
248       setWire( aProfileWire, false, false );  
249
250       QColor aWireColor = aProfile->GetBorderColor();
251       setBorderColor( aWireColor, false, false );
252     }
253     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_Stream) ) ||
254               myObject->IsKind( STANDARD_TYPE(HYDROData_Channel) ) ||
255               myObject->IsKind( STANDARD_TYPE(HYDROData_Obstacle) ) )
256     {
257       Handle(HYDROData_Object) aGeomObject =
258         Handle(HYDROData_Object)::DownCast( myObject );
259
260       TopoDS_Shape anObjShape = aGeomObject->GetTopShape();
261
262       setShape( anObjShape, false, false );
263
264       QColor aFillingColor = aGeomObject->GetFillingColor();
265       QColor aBorderColor = aGeomObject->GetBorderColor();
266
267       setFillingColor( aFillingColor, false, false );
268       setBorderColor( aBorderColor, false, false );
269     }
270     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_DummyObject3D) ) )
271     {
272       Handle(HYDROData_DummyObject3D) anObject3D =
273         Handle(HYDROData_DummyObject3D)::DownCast( myObject );
274       TopoDS_Shape aShape3D = anObject3D->GetShape();
275
276       setShape( aShape3D, false, false );
277
278       QColor aFillingColor = anObject3D->GetFillingColor();
279       QColor aBorderColor = anObject3D->GetBorderColor();
280
281       setFillingColor( aFillingColor, false, false );
282       setBorderColor( aBorderColor, false, false );
283     }
284     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_ShapesGroup) ) )
285     {
286       Handle(HYDROData_ShapesGroup) aShapesGroup =
287         Handle(HYDROData_ShapesGroup)::DownCast( myObject );
288
289       TopTools_SequenceOfShape aShapes;
290       aShapesGroup->GetShapes( aShapes );
291
292       TopoDS_Compound aCompound;
293       BRep_Builder aCompoundBuilder;
294       aCompoundBuilder.MakeCompound( aCompound );
295
296       for ( int i = 1, n = aShapes.Length(); i <= n; ++i )
297       {
298         const TopoDS_Shape& aShape = aShapes.Value( i );
299         aCompoundBuilder.Add( aCompound, aShape );
300       }
301
302       setShape( aCompound, false, false );  
303     }
304   }
305  
306   if ( myShape.IsNull() || !isVisible() )
307     return;
308
309   displayShape( isUpdateViewer );
310
311   if (isDeactivateSelection)
312     myContext->Deactivate(myShape);
313 }
314
315 void HYDROGUI_Shape::setVisible( const bool theState,
316                                  const bool theIsUpdateViewer )
317 {
318   myIsVisible = theState;
319
320   if ( myShape.IsNull() )
321     return;
322
323   if ( ( myIsVisible && myContext->IsDisplayed( myShape ) ) ||
324        ( !myIsVisible && !myContext->IsDisplayed( myShape ) ) )
325     return;
326
327   if ( myIsVisible ) {
328     displayShape( theIsUpdateViewer );
329   }
330   else
331     myContext->Erase( myShape, theIsUpdateViewer );
332 }
333
334 void HYDROGUI_Shape::highlight( bool theIsHighlight, bool isUpdateViewer )
335 {
336   if ( myIsHighlight == theIsHighlight )
337     return;
338
339   myIsHighlight = theIsHighlight;
340
341   if ( myContext.IsNull() || myShape.IsNull() )
342     return;
343
344   colorShapeBorder( getActiveColor() );
345   displayShape( isUpdateViewer );
346 }
347
348 bool HYDROGUI_Shape::isHighlighted() const
349 {
350   return myIsHighlight;
351 }
352
353 void HYDROGUI_Shape::setWire( const TopoDS_Wire& theWire,
354                               const bool         theToDisplay,
355                               const bool         theIsUpdateViewer )
356 {
357   myTopoShape = theWire;
358   // To avoid that hilight presentation is equal to "normal" object presentation.
359   // Note that hilight presentation is always to be on top ( i.e. in the top Z layer ).
360   myDisplayMode = AIS_Shaded;
361
362   buildShape();
363   updateShape( theToDisplay, theIsUpdateViewer );
364 }
365
366 void HYDROGUI_Shape::setFaces( const TopoDS_Compound& theWires,
367                                const bool             theToDisplay,
368                                const bool             theIsUpdateViewer )
369 {
370   TopExp_Explorer anExp( theWires, TopAbs_WIRE );
371   TopoDS_Compound aCompound;
372   BRep_Builder aBuilder;
373     aBuilder.MakeCompound( aCompound );
374
375   for ( ; anExp.More(); anExp.Next() ) {
376     TopoDS_Wire aWire = TopoDS::Wire( anExp.Current() );
377     if ( aWire.IsNull() ) {
378       continue;
379     }
380
381     BRepBuilderAPI_MakeFace aMakeFace( aWire, Standard_True );
382     aMakeFace.Build();
383     if( aMakeFace.IsDone() ) {
384       aBuilder.Add( aCompound, aMakeFace.Face() );
385     }
386   }
387
388   myTopoShape = aCompound;
389   myDisplayMode = AIS_Shaded;
390
391   buildShape();
392   updateShape( theToDisplay, theIsUpdateViewer );
393 }
394
395 void HYDROGUI_Shape::setFace( const TopoDS_Wire& theWire,
396                               const bool         theToDisplay,
397                               const bool         theIsUpdateViewer,
398                               const QString&     theTextureFileName )
399 {
400   BRepBuilderAPI_MakeFace aFaceBuilder( theWire, Standard_True );
401   aFaceBuilder.Build();
402   if( aFaceBuilder.IsDone() )
403   {
404     TopoDS_Face aFace = aFaceBuilder.Face();
405     setFace( aFace, theToDisplay, theIsUpdateViewer, theTextureFileName );
406   }
407 }
408
409 void HYDROGUI_Shape::setFace( const TopoDS_Face& theFace,
410                               const bool         theToDisplay,
411                               const bool         theIsUpdateViewer,
412                               const QString&     theTextureFileName )
413 {
414   myTopoShape = theFace;
415   myDisplayMode = theTextureFileName.isEmpty() ? AIS_Shaded : AIS_Shaded+2;
416   //Note: AIS_Shaded+2 is the same as AIS_ExactHLR
417   //TODO: it would be more suitable to use TexturedShape mode from GEOM_AISShape
418
419   buildShape();
420   updateShape( theToDisplay, theIsUpdateViewer );
421 }
422
423 void HYDROGUI_Shape::setShape( const TopoDS_Shape& theShape,
424                                const bool          theToDisplay,
425                                const bool          theIsUpdateViewer )
426 {
427   myTopoShape = theShape;
428   myDisplayMode = AIS_Shaded;
429
430   buildShape();
431   updateShape( theToDisplay, theIsUpdateViewer );
432 }
433
434 void HYDROGUI_Shape::setFillingColor( const QColor& theColor,
435                                       const bool    theToDisplay,
436                                       const bool    theIsUpdateViewer )
437 {
438   myFillingColor = theColor;
439   updateShape( theToDisplay, theIsUpdateViewer );
440 }
441
442 QColor HYDROGUI_Shape::getFillingColor() const
443 {
444   return myFillingColor;
445 }
446
447 void HYDROGUI_Shape::setBorderColor( const QColor& theColor,
448                                      const bool    theToDisplay,
449                                      const bool    theIsUpdateViewer )
450 {
451   myBorderColor = theColor;
452   updateShape( theToDisplay, theIsUpdateViewer );
453 }
454
455 QColor HYDROGUI_Shape::getBorderColor() const
456 {
457   return myBorderColor;
458 }
459
460 void HYDROGUI_Shape::setHighlightColor( const QColor& theColor )
461 {
462   myHighlightColor = theColor;
463 }
464
465 QColor HYDROGUI_Shape::getHighlightColor() const
466 {
467   return myHighlightColor;
468 }
469
470 void HYDROGUI_Shape::setZLayer( const int theZLayer )
471 {
472   if ( myZLayer == theZLayer )
473     return;
474
475   myZLayer = theZLayer;
476   if ( !myShape.IsNull() && isVisible() && !myContext.IsNull() && myZLayer >= 0 )
477     myContext->SetZLayer( myShape, myZLayer );
478 }
479
480 Handle_AIS_InteractiveObject HYDROGUI_Shape::createShape() const
481 {
482   if( myTopoShape.IsNull() )
483     return Handle_AIS_InteractiveObject();
484   else
485     return new AIS_Shape( myTopoShape );
486 }
487
488 void HYDROGUI_Shape::buildShape()
489 {
490   // Erase previously created shape
491   erase();
492
493   myShape = createShape();
494   if( myShape.IsNull() )
495     return;
496
497   Handle_AIS_Shape anAISShape = Handle_AIS_Shape::DownCast( myShape );
498   if( !anAISShape.IsNull() )
499     anAISShape ->SetHLRAngleAndDeviation( 0.001 );
500
501   if ( !myObject.IsNull() )
502     myShape->SetOwner( myObject );
503
504   myShape->SetTransparency( 0 );
505   myShape->SetDisplayMode( (AIS_DisplayMode)myDisplayMode );
506
507     // Init default params for shape
508   const Handle(AIS_Drawer)& anAttributes = myShape->Attributes();
509   if ( !anAttributes.IsNull() )
510   {
511     Handle(Prs3d_IsoAspect) anIsoAspect = anAttributes->UIsoAspect();
512     if ( !anIsoAspect.IsNull() ) {
513       anIsoAspect->SetNumber( 0 );
514       anAttributes->SetUIsoAspect( anIsoAspect );
515     }
516       
517     anIsoAspect = anAttributes->VIsoAspect();
518     if ( !anIsoAspect.IsNull() ) {
519       anIsoAspect->SetNumber( 0 );
520       anAttributes->SetVIsoAspect( anIsoAspect );
521     }
522
523     if ( myDisplayMode == AIS_Shaded )
524     {
525       Handle(Prs3d_ShadingAspect) aShadingAspect = anAttributes->ShadingAspect();
526       if ( !aShadingAspect.IsNull() )
527       {
528         Graphic3d_MaterialAspect aMatAspect( Graphic3d_NOM_PLASTIC );
529         //aMatAspect.SetAmbient( 1 );
530         //aMatAspect.SetDiffuse( 0 );
531
532         aShadingAspect->Aspect()->SetFrontMaterial( aMatAspect );
533         aShadingAspect->Aspect()->SetBackMaterial( aMatAspect );
534       }
535     }
536     else if ( myDisplayMode == AIS_WireFrame )
537     {
538       anAttributes->SetWireDraw( true );
539     }
540   }
541 }
542
543 void HYDROGUI_Shape::updateShape( const bool theToDisplay,
544                                   const bool theIsUpdateViewer )
545 {
546   if ( myShape.IsNull() )
547     return;
548
549   const Handle(AIS_Drawer)& anAttributes = myShape->Attributes();
550   if ( !anAttributes.IsNull() )
551   {
552     if ( myDisplayMode == AIS_Shaded )
553     {
554       // Coloring face filling
555       Handle(Prs3d_ShadingAspect) aShadingAspect = anAttributes->ShadingAspect();
556       if ( !aShadingAspect.IsNull() )
557       {
558         Quantity_Color aFillingColor( getQuantityColorVal( myFillingColor.red() ), 
559                                       getQuantityColorVal( myFillingColor.green() ),
560                                       getQuantityColorVal( myFillingColor.blue() ),
561                                       Quantity_TOC_RGB );
562
563         aShadingAspect->SetColor( aFillingColor );
564         aShadingAspect->SetTransparency( 1 - getQuantityColorVal( myFillingColor.alpha() ) );
565       }
566     }
567     else if ( myDisplayMode == AIS_WireFrame )
568     {
569     }
570
571     // Coloring borders
572     colorShapeBorder( getActiveColor() );
573   }
574
575   if ( !theToDisplay || !isVisible() || myContext.IsNull() )
576     return;
577   
578   displayShape( theIsUpdateViewer );
579 }
580
581 void HYDROGUI_Shape::displayShape( const bool theIsUpdateViewer )
582 {
583   myContext->Display( myShape, Standard_False );
584
585   if ( myZLayer >= 0 )
586     myContext->SetZLayer( myShape, myZLayer );
587
588   myContext->UpdateCurrentViewer();
589 }
590
591 QColor HYDROGUI_Shape::getActiveColor() const
592 {
593   return isHighlighted() ? myHighlightColor : myBorderColor;
594 }
595
596 double HYDROGUI_Shape::getQuantityColorVal( const int theColorVal )
597 {
598   return theColorVal == 0 ? 0 : ( (double)theColorVal / 255 );
599 }
600
601 void HYDROGUI_Shape::colorShapeBorder( const QColor& theColor )
602 {
603   if ( myShape.IsNull() )
604     return;
605
606   const Handle(AIS_Drawer)& anAttributes = myShape->Attributes();
607   if ( anAttributes.IsNull() )
608     return;
609
610   Quantity_Color aBorderColor( getQuantityColorVal( theColor.red() ), 
611                                getQuantityColorVal( theColor.green() ),
612                                getQuantityColorVal( theColor.blue() ),
613                                Quantity_TOC_RGB );
614   
615   if( !myTopoShape.IsNull() )
616   {
617     if ( myTopoShape.ShapeType() == TopAbs_WIRE ) // Note that we display polylines in shaded mode
618     {
619       myShape->SetColor( aBorderColor );
620     }
621     else if ( myDisplayMode == AIS_Shaded )
622     {
623       if ( theColor.alpha() == 0 )
624       {
625         anAttributes->SetFaceBoundaryDraw( false );
626       }
627       else
628       {
629         anAttributes->SetFaceBoundaryDraw( true );
630   
631         Handle(Prs3d_LineAspect) aBoundaryAspect = anAttributes->FaceBoundaryAspect();
632         if ( !aBoundaryAspect.IsNull() )
633         {
634           aBoundaryAspect->SetColor( aBorderColor );
635           anAttributes->SetFaceBoundaryAspect( aBoundaryAspect );
636         }
637         Handle(Prs3d_LineAspect) aWireAspect = anAttributes->WireAspect();
638         if ( !aWireAspect.IsNull() )
639         {
640           aWireAspect->SetColor( aBorderColor );
641           anAttributes->SetWireAspect( aWireAspect );
642         }
643       }
644     }
645     else if ( myDisplayMode == AIS_WireFrame )
646     {
647       myShape->SetColor( aBorderColor );
648     }
649   }
650 }
651
652 void HYDROGUI_Shape::setDisplayMode( int theDisplayMode )
653 {
654   myDisplayMode = theDisplayMode;
655 }