Salome HOME
be595d23a983300fce1a56781c8fcdb0560f93d6
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_Shape.cxx
1 // Copyright (C) 2007-2013  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.
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
25 #include <AIS_Drawer.hxx>
26
27 #include <BRepBuilderAPI_MakeEdge.hxx>
28 #include <BRepBuilderAPI_MakeWire.hxx>
29 #include <BRepBuilderAPI_MakeFace.hxx>
30
31 #include <gp_Pnt.hxx>
32
33 #include <Graphic3d_AspectFillArea3d.hxx>
34 #include <Graphic3d_MaterialAspect.hxx>
35
36 #include <TopoDS_Wire.hxx>
37 #include <TopoDS_Face.hxx>
38
39 #include <Precision.hxx>
40
41 #include <Prs3d_ShadingAspect.hxx>
42 #include <Prs3d_LineAspect.hxx>
43 #include <Prs3d_IsoAspect.hxx>
44
45 #include <QColor>
46
47 HYDROGUI_Shape::HYDROGUI_Shape( const Handle(AIS_InteractiveContext)& theContext )
48 : myContext( theContext ),
49   myIsHighlight( false ),
50   myZIndex( 0.0 ),
51   myFillingColor( Qt::green ),
52   myBorderColor( Qt::black ),
53   myHighlightColor( Qt::white )
54 {
55 }
56
57 HYDROGUI_Shape::~HYDROGUI_Shape()
58 {
59   erase();
60
61   if ( !myShape.IsNull() )
62     myShape.Nullify();
63 }
64
65 void HYDROGUI_Shape::display()
66 {
67   if ( !myContext || myShape.IsNull() )
68     return;
69
70   myContext->Display( myShape );
71 }
72
73 void HYDROGUI_Shape::erase()
74 {
75   if ( !myContext || myShape.IsNull() )
76     return;
77
78   myContext->Erase( myShape );
79 }
80
81 void HYDROGUI_Shape::highlight( bool theIsHighlight )
82 {
83   if ( myIsHighlight == theIsHighlight )
84     return;
85
86   myIsHighlight = theIsHighlight;
87
88   if ( !myContext || myShape.IsNull() )
89     return;
90
91   colorShapeBorder( getActiveColor() );
92   myContext->Display( myShape );
93 }
94
95 bool HYDROGUI_Shape::isHighlighted() const
96 {
97   return myIsHighlight;
98 }
99
100 void HYDROGUI_Shape::setPath( const QPainterPath& thePath,
101                               const bool          theToDisplay )
102 {
103   myPath = thePath;
104   buildShape();
105   updateShape( theToDisplay );
106 }
107
108 QPainterPath HYDROGUI_Shape::getPath() const
109 {
110   return myPath;
111 }
112
113 void HYDROGUI_Shape::setZIndex( const double theZIndex,
114                                 const bool   theToDisplay )
115 {
116   myZIndex = theZIndex;
117   buildShape();
118   updateShape( theToDisplay );
119 }
120
121 double HYDROGUI_Shape::getZIndex() const
122 {
123   return myZIndex;
124 }
125
126 void HYDROGUI_Shape::setFillingColor( const QColor& theColor,
127                                       const bool    theToDisplay )
128 {
129   myFillingColor = theColor;
130   updateShape( theToDisplay );
131 }
132
133 QColor HYDROGUI_Shape::getFillingColor() const
134 {
135   return myFillingColor;
136 }
137
138 void HYDROGUI_Shape::setBorderColor( const QColor& theColor,
139                                      const bool    theToDisplay )
140 {
141   myBorderColor = theColor;
142   updateShape( theToDisplay );
143 }
144
145 QColor HYDROGUI_Shape::getBorderColor() const
146 {
147   return myBorderColor;
148 }
149
150 void HYDROGUI_Shape::setHighlightColor( const QColor& theColor )
151 {
152   myHighlightColor = theColor;
153 }
154
155 QColor HYDROGUI_Shape::getHighlightColor() const
156 {
157   return myHighlightColor;
158 }
159
160 void HYDROGUI_Shape::makeEdge( BRepBuilderAPI_MakeWire& theWireBuilder,
161                                gp_Pnt&                  theFirstPoint,
162                                gp_Pnt&                  theLastPoint ) const
163 {
164   BRepBuilderAPI_MakeEdge anEdgeBuilder( theFirstPoint, theLastPoint );
165   anEdgeBuilder.Build();
166   if ( anEdgeBuilder.IsDone() )
167   {
168     TopoDS_Edge anEdge = anEdgeBuilder;
169     theWireBuilder.Add( anEdge );
170   }
171 }
172
173 void HYDROGUI_Shape::makeWire( BRepBuilderAPI_MakeFace& theFaceBuilder,
174                                BRepBuilderAPI_MakeWire& theWireBuilder,
175                                bool&                    theIsComposed ) const
176 {
177   theWireBuilder.Build();
178   if ( theWireBuilder.IsDone() )
179   {
180     TopoDS_Wire aBuildedWire = theWireBuilder;
181     if ( theIsComposed )
182     {
183       theFaceBuilder.Add( aBuildedWire );
184     }
185     else
186     {
187       theFaceBuilder = BRepBuilderAPI_MakeFace( aBuildedWire, true );
188
189       theFaceBuilder.Build();
190       theIsComposed = theFaceBuilder.IsDone();
191     }
192   }
193
194   theWireBuilder = BRepBuilderAPI_MakeWire();
195 }
196
197 void HYDROGUI_Shape::buildShape()
198 {
199   // Erase previously created shape
200   erase();
201
202   if ( myPath.isEmpty() )
203     return;
204
205   BRepBuilderAPI_MakeFace aFaceBuilder;
206   BRepBuilderAPI_MakeWire aWireBuilder;
207
208   // Build new shape from path
209   bool anIsComposed = false;
210   bool anIsStarted = false;
211   gp_Pnt aStartPoint( 0, 0, myZIndex );
212   gp_Pnt aPrevPoint(  0, 0, myZIndex );
213
214   for ( int i = 0; i < myPath.elementCount(); ++i )
215   {
216     const QPainterPath::Element& aPathElem = myPath.elementAt( i );
217
218     gp_Pnt aCurPoint( aPathElem.x, aPathElem.y, myZIndex );
219     switch ( aPathElem.type )
220     {
221       case QPainterPath::LineToElement:
222       {
223         // Just build the edge
224         makeEdge( aWireBuilder, aPrevPoint, aCurPoint );
225         break;
226       }
227       case QPainterPath::CurveToElement:
228       {
229         // TODO
230         break;
231       }
232       case QPainterPath::MoveToElement:
233       {
234         if ( anIsStarted )
235         {
236           // Compose face
237           if ( !aStartPoint.IsEqual( aPrevPoint, Precision::Confusion() ) )
238           {
239             //Close wire
240             makeEdge( aWireBuilder, aPrevPoint, aStartPoint );
241           }
242
243           // Make face wiyth edge
244           makeWire( aFaceBuilder, aWireBuilder, anIsComposed );
245         }
246
247         anIsStarted = true;
248         aStartPoint = aCurPoint;
249         break;
250       }
251       default:
252         break;
253     }
254
255     aPrevPoint = aCurPoint;
256   }
257
258   makeWire( aFaceBuilder, aWireBuilder, anIsComposed );
259
260   TopoDS_Face aResShape;
261
262   aFaceBuilder.Build();
263   if ( aFaceBuilder.IsDone() )
264     aResShape = aFaceBuilder;
265
266   myShape = new AIS_Shape( aResShape );
267
268   myShape->SetTransparency( 0 );
269   myShape->SetDisplayMode( AIS_Shaded );
270
271   // Init default params for shape
272   const Handle(AIS_Drawer)& anAttributes = myShape->Attributes();
273   if ( !anAttributes.IsNull() )
274   {
275     Handle(Prs3d_IsoAspect) anIsoAspect = anAttributes->UIsoAspect();
276     if ( !anIsoAspect.IsNull() )
277       anIsoAspect->SetNumber( 0 );
278     
279     anIsoAspect = anAttributes->VIsoAspect();
280     if ( !anIsoAspect.IsNull() )
281       anIsoAspect->SetNumber( 0 );
282
283     Handle(Prs3d_ShadingAspect) aShadingAspect = anAttributes->ShadingAspect();
284     if ( !aShadingAspect.IsNull() )
285     {
286       Graphic3d_MaterialAspect aMatAspect;
287           aMatAspect.SetAmbient( 1 );
288           aMatAspect.SetDiffuse( 0 );
289         
290           aShadingAspect->Aspect()->SetFrontMaterial( aMatAspect );
291           aShadingAspect->Aspect()->SetBackMaterial( aMatAspect );
292     }
293   }
294 }
295
296 void HYDROGUI_Shape::updateShape( const bool theIsForce )
297 {
298   if ( myShape.IsNull() )
299     return;
300
301   const Handle(AIS_Drawer)& anAttributes = myShape->Attributes();
302   if ( !anAttributes.IsNull() )
303   {
304     // Coloring face filling
305     Handle(Prs3d_ShadingAspect) aShadingAspect = anAttributes->ShadingAspect();
306     if ( !aShadingAspect.IsNull() )
307     {
308       Quantity_Color aFillingColor( getQuantityColorVal( myFillingColor.red() ), 
309                                     getQuantityColorVal( myFillingColor.green() ),
310                                     getQuantityColorVal( myFillingColor.blue() ),
311                                     Quantity_TOC_RGB );
312
313       aShadingAspect->SetColor( aFillingColor );
314       aShadingAspect->SetTransparency( 1 - getQuantityColorVal( myFillingColor.alpha() ) );
315     }
316
317     // Coloring borders
318     colorShapeBorder( getActiveColor() );
319   }
320
321   if ( !theIsForce || !myContext )
322     return;
323   
324   myContext->Display( myShape );
325 }
326
327 QColor HYDROGUI_Shape::getActiveColor() const
328 {
329   return isHighlighted() ? myHighlightColor : myBorderColor;
330 }
331
332 double HYDROGUI_Shape::getQuantityColorVal( const int theColorVal )
333 {
334   return theColorVal == 0 ? 0 : ( (double)theColorVal / 255 );
335 }
336
337 void HYDROGUI_Shape::colorShapeBorder( const QColor& theColor )
338 {
339   if ( myShape.IsNull() )
340     return;
341
342   const Handle(AIS_Drawer)& anAttributes = myShape->Attributes();
343   if ( anAttributes.IsNull() )
344     return;
345
346   if ( theColor.alpha() == 0 )
347   {
348     anAttributes->SetFaceBoundaryDraw( false );
349   }
350   else
351   {
352     Quantity_Color aBorderColor( getQuantityColorVal( theColor.red() ), 
353                                  getQuantityColorVal( theColor.green() ),
354                                  getQuantityColorVal( theColor.blue() ),
355                                  Quantity_TOC_RGB );
356
357     anAttributes->SetFaceBoundaryDraw( true );
358
359     Handle(Prs3d_LineAspect) aBoundaryAspect = anAttributes->FaceBoundaryAspect();
360     if ( !aBoundaryAspect.IsNull() )
361     {
362       aBoundaryAspect->SetColor( aBorderColor );
363     }
364   }
365 }
366
367