a19ee169203ae36fefb4ba1431711c90073108bc
[occt.git] / src / RWMesh / RWMesh_FaceIterator.cxx
1 // Copyright (c) 2017-2019 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <RWMesh_FaceIterator.hxx>
15
16 #include <BRepAdaptor_Surface.hxx>
17 #include <BRep_Tool.hxx>
18 #include <TopExp.hxx>
19 #include <TopoDS.hxx>
20 #include <XCAFDoc_ShapeTool.hxx>
21 #include <XCAFPrs.hxx>
22
23 // =======================================================================
24 // function : RWMesh_FaceIterator
25 // purpose  :
26 // =======================================================================
27 RWMesh_FaceIterator::RWMesh_FaceIterator (const TDF_Label&       theLabel,
28                                           const TopLoc_Location& theLocation,
29                                           const Standard_Boolean theToMapColors,
30                                           const XCAFPrs_Style&   theStyle)
31 : myDefStyle (theStyle),
32   myToMapColors (theToMapColors),
33   mySLTool  (1, 1e-12),
34   myHasNormals (false),
35   myIsMirrored (false),
36   myHasFaceColor (false)
37 {
38   TopoDS_Shape aShape;
39   if (!XCAFDoc_ShapeTool::GetShape (theLabel, aShape)
40    ||  aShape.IsNull())
41   {
42     return;
43   }
44
45   aShape.Location (theLocation);
46   myFaceIter.Init (aShape, TopAbs_FACE);
47
48   if (theToMapColors)
49   {
50     dispatchStyles (theLabel, theLocation, theStyle);
51   }
52
53   Next();
54 }
55
56 // =======================================================================
57 // function : RWMesh_FaceIterator
58 // purpose  :
59 // =======================================================================
60 RWMesh_FaceIterator::RWMesh_FaceIterator (const TopoDS_Shape&  theShape,
61                                           const XCAFPrs_Style& theStyle)
62 : myDefStyle (theStyle),
63   myToMapColors (true),
64   mySLTool  (1, 1e-12),
65   myHasNormals (false),
66   myIsMirrored (false),
67   myHasFaceColor (false)
68 {
69   if (theShape.IsNull())
70   {
71     return;
72   }
73
74   myFaceIter.Init (theShape, TopAbs_FACE);
75   Next();
76 }
77
78 // =======================================================================
79 // function : dispatchStyles
80 // purpose  :
81 // =======================================================================
82 void RWMesh_FaceIterator::dispatchStyles (const TDF_Label&       theLabel,
83                                           const TopLoc_Location& theLocation,
84                                           const XCAFPrs_Style&   theStyle)
85 {
86   TopLoc_Location aDummyLoc;
87   XCAFPrs_IndexedDataMapOfShapeStyle aStyles;
88   XCAFPrs::CollectStyleSettings (theLabel, aDummyLoc, aStyles);
89
90   Standard_Integer aNbTypes[TopAbs_SHAPE] = {};
91   for (Standard_Integer aTypeIter = TopAbs_FACE; aTypeIter >= TopAbs_COMPOUND; --aTypeIter)
92   {
93     if (aTypeIter != TopAbs_FACE
94      && aNbTypes[aTypeIter] == 0)
95     {
96       continue;
97     }
98
99     for (XCAFPrs_IndexedDataMapOfShapeStyle::Iterator aStyleIter (aStyles); aStyleIter.More(); aStyleIter.Next())
100     {
101       const TopoDS_Shape&    aKeyShape     = aStyleIter.Key();
102       const TopAbs_ShapeEnum aKeyShapeType = aKeyShape.ShapeType();
103       if (aTypeIter == TopAbs_FACE)
104       {
105         ++aNbTypes[aKeyShapeType];
106       }
107       if (aTypeIter != aKeyShapeType)
108       {
109         continue;
110       }
111
112       XCAFPrs_Style aCafStyle = aStyleIter.Value();
113       if (!aCafStyle.IsSetColorCurv()
114          && theStyle.IsSetColorCurv())
115       {
116         aCafStyle.SetColorCurv (theStyle.GetColorCurv());
117       }
118       if (!aCafStyle.IsSetColorSurf()
119          && theStyle.IsSetColorSurf())
120       {
121         aCafStyle.SetColorSurf (theStyle.GetColorSurfRGBA());
122       }
123       if (aCafStyle.Material().IsNull()
124        && !theStyle.Material().IsNull())
125       {
126         aCafStyle.SetMaterial (theStyle.Material());
127       }
128
129       TopoDS_Shape aKeyShapeLocated = aKeyShape.Located (theLocation);
130       if (aKeyShapeType == TopAbs_FACE)
131       {
132         myStyles.Bind (aKeyShapeLocated, aCafStyle);
133       }
134       else
135       {
136         for (TopExp_Explorer aFaceIter (aKeyShapeLocated, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
137         {
138           if (!myStyles.IsBound (aFaceIter.Current()))
139           {
140             myStyles.Bind (aFaceIter.Current(), aCafStyle);
141           }
142         }
143       }
144     }
145   }
146 }
147
148 // =======================================================================
149 // function : normal
150 // purpose  :
151 // =======================================================================
152 gp_Dir RWMesh_FaceIterator::normal (Standard_Integer theNode) const
153 {
154   gp_Dir aNormal (gp::DZ());
155   if (myPolyTriang->HasNormals())
156   {
157     Graphic3d_Vec3 aNormVec3;
158     myPolyTriang->Normal (theNode, aNormVec3);
159     if (aNormVec3.Modulus() != 0.0f)
160     {
161       aNormal.SetCoord (aNormVec3.x(), aNormVec3.y(), aNormVec3.z());
162     }
163   }
164   else if (myHasNormals
165         && myPolyTriang->HasUVNodes())
166   {
167     const gp_XY anUV = myPolyTriang->UVNode (theNode).XY();
168     mySLTool.SetParameters (anUV.X(), anUV.Y());
169     if (mySLTool.IsNormalDefined())
170     {
171       aNormal = mySLTool.Normal();
172     }
173   }
174   return aNormal;
175 }
176
177 // =======================================================================
178 // function : Next
179 // purpose  :
180 // =======================================================================
181 void RWMesh_FaceIterator::Next()
182 {
183   for (; myFaceIter.More(); myFaceIter.Next())
184   {
185     myFace       = TopoDS::Face (myFaceIter.Current());
186     myPolyTriang = BRep_Tool::Triangulation (myFace, myFaceLocation);
187     myTrsf       = myFaceLocation.Transformation();
188     if (myPolyTriang.IsNull()
189      || myPolyTriang->NbTriangles() == 0)
190     {
191       resetFace();
192       continue;
193     }
194
195     initFace();
196     myFaceIter.Next();
197     return;
198   }
199
200   resetFace();
201 }
202
203 // =======================================================================
204 // function : initFace
205 // purpose  :
206 // =======================================================================
207 void RWMesh_FaceIterator::initFace()
208 {
209   myHasNormals   = false;
210   myHasFaceColor = false;
211   myIsMirrored   = myTrsf.VectorialPart().Determinant() < 0.0;
212   if (myPolyTriang->HasNormals())
213   {
214     myHasNormals = true;
215   }
216   if (myPolyTriang->HasUVNodes() && !myHasNormals)
217   {
218     TopoDS_Face aFaceFwd = TopoDS::Face (myFace.Oriented (TopAbs_FORWARD));
219     aFaceFwd.Location (TopLoc_Location());
220     TopLoc_Location aLoc;
221     if (!BRep_Tool::Surface (aFaceFwd, aLoc).IsNull())
222     {
223       myFaceAdaptor.Initialize (aFaceFwd, false);
224       mySLTool.SetSurface (myFaceAdaptor);
225       myHasNormals = true;
226     }
227   }
228   if (!myToMapColors)
229   {
230     return;
231   }
232
233   if (!myStyles.Find (myFace, myFaceStyle))
234   {
235     myFaceStyle = myDefStyle;
236   }
237
238   if (!myFaceStyle.Material().IsNull())
239   {
240     myHasFaceColor = true;
241     myFaceColor = myFaceStyle.Material()->BaseColor();
242   }
243   else if (myFaceStyle.IsSetColorSurf())
244   {
245     myHasFaceColor = true;
246     myFaceColor = myFaceStyle.GetColorSurfRGBA();
247   }
248 }