0026106: BRepMesh - revision of data model
[occt.git] / src / BRepMesh / BRepMesh_ModelPostProcessor.cxx
1 // Created on: 2016-07-04
2 // Copyright (c) 2016 OPEN CASCADE SAS
3 // Created by: Oleg AGASHIN
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <BRepMesh_ModelPostProcessor.hxx>
17 #include <BRepMesh_ShapeTool.hxx>
18 #include <IMeshData_Model.hxx>
19 #include <IMeshData_Edge.hxx>
20 #include <IMeshData_PCurve.hxx>
21 #include <OSD_Parallel.hxx>
22
23 namespace
24 {
25   //! Commits 3D polygons and polygons on triangulations for corresponding edges.
26   class PolygonCommitter
27   {
28   public:
29     //! Constructor
30     PolygonCommitter(const Handle(IMeshData_Model)& theModel)
31       : myModel(theModel)
32     {
33     }
34
35     //! Main functor.
36     void operator()(const Standard_Integer theEdgeIndex) const
37     {
38       const IMeshData::IEdgeHandle& aDEdge = myModel->GetEdge(theEdgeIndex);
39       if (aDEdge->IsFree())
40       {
41         if (!aDEdge->IsSet(IMeshData_Reused))
42         {
43           commitPolygon3D(aDEdge);
44         }
45       }
46       else
47       {
48         commitPolygons(aDEdge);
49       }
50     }
51
52   private:
53
54     //! Commits 3d polygon to topological edge
55     void commitPolygon3D(const IMeshData::IEdgeHandle& theDEdge) const
56     {
57       const IMeshData::ICurveHandle& aCurve = theDEdge->GetCurve();
58
59       TColgp_Array1OfPnt   aNodes  (1, aCurve->ParametersNb());
60       TColStd_Array1OfReal aUVNodes(1, aCurve->ParametersNb());
61       for (Standard_Integer i = 1; i <= aCurve->ParametersNb(); ++i)
62       {
63         aNodes  (i) = aCurve->GetPoint    (i - 1);
64         aUVNodes(i) = aCurve->GetParameter(i - 1);
65       }
66
67       Handle(Poly_Polygon3D) aPoly3D = new Poly_Polygon3D(aNodes, aUVNodes);
68       aPoly3D->Deflection(theDEdge->GetDeflection());
69
70       BRepMesh_ShapeTool::UpdateEdge(theDEdge->GetEdge(), aPoly3D);
71     }
72
73     //! Commits all polygons on triangulations correspondent to the given edge.
74     void commitPolygons(const IMeshData::IEdgeHandle& theDEdge) const
75     {
76       // Collect pcurves associated with the given edge on the specific surface.
77       IMeshData::IDMapOfIFacePtrsListOfIPCurves aMapOfPCurves;
78       for (Standard_Integer aPCurveIt = 0; aPCurveIt < theDEdge->PCurvesNb(); ++aPCurveIt)
79       {
80         const IMeshData::IPCurveHandle& aPCurve   = theDEdge->GetPCurve(aPCurveIt);
81         const IMeshData::IFacePtr&      aDFacePtr = aPCurve->GetFace();
82         const IMeshData::IFaceHandle    aDFace    = aDFacePtr;
83         if (aDFace->IsSet(IMeshData_Failure) ||
84             aDFace->IsSet(IMeshData_Reused))
85         {
86           continue;
87         }
88
89         if (!aMapOfPCurves.Contains(aDFacePtr))
90         {
91           aMapOfPCurves.Add(aDFacePtr, IMeshData::ListOfIPCurves());
92         }
93
94         IMeshData::ListOfIPCurves& aPCurves = aMapOfPCurves.ChangeFromKey(aDFacePtr);
95         aPCurves.Append(aPCurve);
96       }
97
98       // Commit polygons related to separate face.
99       const TopoDS_Edge& aEdge = theDEdge->GetEdge();
100       IMeshData::IDMapOfIFacePtrsListOfIPCurves::Iterator aPolygonIt(aMapOfPCurves);
101       for (; aPolygonIt.More(); aPolygonIt.Next())
102       {
103         const TopoDS_Face& aFace = aPolygonIt.Key()->GetFace();
104
105         TopLoc_Location aLoc;
106         const Handle(Poly_Triangulation)& aTriangulation =
107           BRep_Tool::Triangulation(aFace, aLoc);
108
109         if (!aTriangulation.IsNull())
110         {
111           const IMeshData::ListOfIPCurves& aPCurves = aPolygonIt.Value();
112           if (aPCurves.Size() == 2)
113           {
114             BRepMesh_ShapeTool::UpdateEdge(
115               aEdge,
116               collectPolygon(aPCurves.First(), theDEdge->GetDeflection()),
117               collectPolygon(aPCurves.Last (), theDEdge->GetDeflection()),
118               aTriangulation, aLoc);
119           }
120           else
121           {
122             BRepMesh_ShapeTool::UpdateEdge(
123               aEdge,
124               collectPolygon(aPCurves.First(), theDEdge->GetDeflection()),
125               aTriangulation, aLoc);
126           }
127         }
128       }
129     }
130
131     //! Collects polygonal data for the given pcurve
132     Handle(Poly_PolygonOnTriangulation) collectPolygon(
133       const IMeshData::IPCurveHandle& thePCurve,
134       const Standard_Real             theDeflection) const
135     {
136       TColStd_Array1OfInteger aNodes (1, thePCurve->ParametersNb());
137       TColStd_Array1OfReal    aParams(1, thePCurve->ParametersNb());
138       for (Standard_Integer i = 1; i <= thePCurve->ParametersNb(); ++i)
139       {
140         aNodes (i) = thePCurve->GetIndex    (i - 1);
141         aParams(i) = thePCurve->GetParameter(i - 1);
142       }
143
144       Handle(Poly_PolygonOnTriangulation) aPolygon = 
145         new Poly_PolygonOnTriangulation(aNodes, aParams);
146
147       aPolygon->Deflection(theDeflection);
148       return aPolygon;
149     }
150
151   private:
152
153     Handle(IMeshData_Model) myModel;
154   };
155 }
156
157 //=======================================================================
158 // Function: Constructor
159 // Purpose : 
160 //=======================================================================
161 BRepMesh_ModelPostProcessor::BRepMesh_ModelPostProcessor()
162 {
163 }
164
165 //=======================================================================
166 // Function: Destructor
167 // Purpose : 
168 //=======================================================================
169 BRepMesh_ModelPostProcessor::~BRepMesh_ModelPostProcessor()
170 {
171 }
172
173 //=======================================================================
174 // Function: Perform
175 // Purpose : 
176 //=======================================================================
177 Standard_Boolean BRepMesh_ModelPostProcessor::Perform(
178   const Handle(IMeshData_Model)& theModel,
179   const IMeshTools_Parameters&   /*theParameters*/)
180 {
181   if (theModel.IsNull())
182   {
183     return Standard_False;
184   }
185
186   // TODO: Force single threaded solution due to data races on edges sharing the same TShape
187   OSD_Parallel::For(0, theModel->EdgesNb(), PolygonCommitter(theModel), Standard_True/*!theParameters.InParallel*/);
188   return Standard_True;
189 }