0032133: Modeling Data - Restriction of access to internal arrays for Poly_Triangulat...
[occt.git] / src / RWObj / RWObj_TriangulationReader.cxx
1 // Author: Kirill Gavrilov
2 // Copyright (c) 2019 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <RWObj_TriangulationReader.hxx>
16
17 #include <BRep_Builder.hxx>
18 #include <TopoDS.hxx>
19 #include <TopoDS_Iterator.hxx>
20
21 IMPLEMENT_STANDARD_RTTIEXT(RWObj_TriangulationReader, RWObj_Reader)
22
23 //================================================================
24 // Function : addMesh
25 // Purpose  :
26 //================================================================
27 Standard_Boolean RWObj_TriangulationReader::addMesh (const RWObj_SubMesh& theMesh,
28                                                      const RWObj_SubMeshReason theReason)
29 {
30   if (!myToCreateShapes)
31   {
32     return Standard_False;
33   }
34
35   if (Handle(Poly_Triangulation) aTris = GetTriangulation())
36   {
37     myNodes.Clear();
38     myNodesUV.Clear();
39     myNormals.Clear();
40     myTriangles.Clear();
41     if (theMesh.Group != myLastGroupName)
42     {
43       // flush previous group and start a new one
44       if (addSubShape (myLastObjectShape, myLastGroupShape, Standard_False))
45       {
46         if (myShapeReceiver != NULL)
47         {
48           const RWObj_Material* aMaterial = myLastGroupShape.ShapeType() == TopAbs_FACE
49                                         && !myLastFaceMaterial.IsEmpty()
50                                           ? myMaterials.Seek (myLastFaceMaterial)
51                                           : NULL;
52           myShapeReceiver->BindNamedShape (myLastGroupShape, myLastGroupName, aMaterial, Standard_False);
53         }
54       }
55       myLastGroupShape = TopoDS_Shape();
56       myLastGroupName = theMesh.Group;
57     }
58
59     TopoDS_Face aNewFace;
60     BRep_Builder aBuilder;
61     aBuilder.MakeFace (aNewFace, aTris);
62     addSubShape (myLastGroupShape, aNewFace, Standard_True);
63     myLastFaceMaterial = theMesh.Material;
64     if (myShapeReceiver != NULL)
65     {
66       const RWObj_Material* aMaterial = myMaterials.Seek (theMesh.Material);
67       myShapeReceiver->BindNamedShape (aNewFace, "", aMaterial, Standard_False);
68     }
69   }
70
71   if (theReason == RWObj_SubMeshReason_NewObject)
72   {
73     // forced flush at the end of the object
74     if (addSubShape (myLastObjectShape, myLastGroupShape, Standard_False))
75     {
76       if (myShapeReceiver != NULL)
77       {
78         const RWObj_Material* aMaterial = myLastGroupShape.ShapeType() == TopAbs_FACE
79                                           && !myLastFaceMaterial.IsEmpty()
80                                             ? myMaterials.Seek (myLastFaceMaterial)
81                                             : NULL;
82         myShapeReceiver->BindNamedShape (myLastGroupShape, myLastGroupName, aMaterial, Standard_False);
83       }
84     }
85     myLastGroupShape = TopoDS_Shape();
86     myLastGroupName.Clear();
87
88     if (addSubShape (myResultShape, myLastObjectShape, Standard_False))
89     {
90       if (myShapeReceiver != NULL)
91       {
92         myShapeReceiver->BindNamedShape (myLastObjectShape, theMesh.Object, NULL, Standard_True);
93       }
94     }
95     myLastObjectShape = TopoDS_Compound();
96   }
97   return Standard_True;
98 }
99
100 // =======================================================================
101 // function : addSubShape
102 // purpose  :
103 // =======================================================================
104 Standard_Boolean RWObj_TriangulationReader::addSubShape (TopoDS_Shape& theParent,
105                                                          const TopoDS_Shape& theSubShape,
106                                                          const Standard_Boolean theToExpandCompound)
107 {
108   if (theSubShape.IsNull())
109   {
110     return Standard_False;
111   }
112
113   BRep_Builder aBuilder;
114   if (theParent.IsNull()
115    && theToExpandCompound)
116   {
117     theParent = theSubShape;
118     return Standard_True;
119   }
120
121   TopoDS_Compound aComp;
122   if (!theParent.IsNull()
123     && theParent.ShapeType() == TopAbs_COMPOUND)
124   {
125     aComp = TopoDS::Compound (theParent);
126   }
127   else
128   {
129     aBuilder.MakeCompound (aComp);
130     if (!theParent.IsNull())
131     {
132       aBuilder.Add (aComp, theParent);
133     }
134   }
135   aBuilder.Add (aComp, theSubShape);
136   theParent = aComp;
137   return Standard_True;
138 }
139
140 //=============================================================================
141 //function : GetTriangulation
142 //purpose  :
143 //=============================================================================
144 Handle(Poly_Triangulation) RWObj_TriangulationReader::GetTriangulation()
145 {
146   if (myTriangles.IsEmpty())
147   {
148     return Handle(Poly_Triangulation)();
149   }
150
151   const Standard_Boolean hasNormals = myNodes.Length() == myNormals.Length();
152   const Standard_Boolean hasUV      = myNodes.Length() == myNodesUV.Length();
153
154   Handle(Poly_Triangulation) aPoly = new Poly_Triangulation (myNodes.Length(), myTriangles.Length(), hasUV);
155   for (Standard_Integer aNodeIter = 0; aNodeIter < myNodes.Size(); ++aNodeIter)
156   {
157     const gp_Pnt& aNode = myNodes.Value (aNodeIter);
158     aPoly->SetNode (aNodeIter + 1, aNode);
159   }
160   if (hasUV)
161   {
162     for (Standard_Integer aNodeIter = 0; aNodeIter < myNodes.Size(); ++aNodeIter)
163     {
164       const Graphic3d_Vec2& aNode = myNodesUV.Value (aNodeIter);
165       aPoly->SetUVNode (aNodeIter + 1, gp_Pnt2d (aNode.x(), aNode.y()));
166     }
167   }
168   if (hasNormals)
169   {
170     aPoly->AddNormals();
171     Standard_Integer aNbInvalid = 0;
172     for (Standard_Integer aNodeIter = 0; aNodeIter < myNodes.Size(); ++aNodeIter)
173     {
174       const Graphic3d_Vec3& aNorm = myNormals.Value (aNodeIter);
175       const float aMod2 = aNorm.SquareModulus();
176       if (aMod2 > 0.001f)
177       {
178         aPoly->SetNormal (aNodeIter + 1, aNorm);
179       }
180       else
181       {
182         ++aNbInvalid;
183         aPoly->SetNormal (aNodeIter + 1, Graphic3d_Vec3 (0.0f, 0.0f, 1.0f));
184       }
185     }
186     if (aNbInvalid == myNodes.Length())
187     {
188       aPoly->RemoveNormals();
189     }
190   }
191
192   for (Standard_Integer aTriIter = 0; aTriIter < myTriangles.Size(); ++aTriIter)
193   {
194     aPoly->SetTriangle (aTriIter + 1, myTriangles[aTriIter]);
195   }
196
197   return aPoly;
198 }
199
200 //================================================================
201 // Function : ResultShape
202 // Purpose  :
203 //================================================================
204 TopoDS_Shape RWObj_TriangulationReader::ResultShape()
205 {
206   if (!myToCreateShapes)
207   {
208     if (Handle(Poly_Triangulation) aTris = GetTriangulation())
209     {
210       TopoDS_Face aFace;
211       BRep_Builder aBuilder;
212       aBuilder.MakeFace (aFace, aTris);
213       return aFace;
214     }
215     return TopoDS_Shape();
216   }
217
218   if (!myResultShape.IsNull()
219     && myResultShape.ShapeType() == TopAbs_COMPOUND
220     && myResultShape.NbChildren() == 1
221     && myActiveSubMesh.Object.IsEmpty())
222   {
223     TopoDS_Iterator aChildIter (myResultShape);
224     return aChildIter.Value();
225   }
226   return myResultShape;
227 }