0025113: Mesh - Progress indication and user break functionality for BRepMesh component
[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->GetCurve()->ParametersNb() == 0)
40         return;
41
42       if (aDEdge->IsFree())
43       {
44         if (!aDEdge->IsSet(IMeshData_Reused))
45         {
46           commitPolygon3D(aDEdge);
47         }
48       }
49       else
50       {
51         commitPolygons(aDEdge);
52       }
53     }
54
55   private:
56
57     //! Commits 3d polygon to topological edge
58     void commitPolygon3D(const IMeshData::IEdgeHandle& theDEdge) const
59     {
60       const IMeshData::ICurveHandle& aCurve = theDEdge->GetCurve();
61
62       TColgp_Array1OfPnt   aNodes  (1, aCurve->ParametersNb());
63       TColStd_Array1OfReal aUVNodes(1, aCurve->ParametersNb());
64       for (Standard_Integer i = 1; i <= aCurve->ParametersNb(); ++i)
65       {
66         aNodes  (i) = aCurve->GetPoint    (i - 1);
67         aUVNodes(i) = aCurve->GetParameter(i - 1);
68       }
69
70       Handle(Poly_Polygon3D) aPoly3D = new Poly_Polygon3D(aNodes, aUVNodes);
71       aPoly3D->Deflection(theDEdge->GetDeflection());
72
73       BRepMesh_ShapeTool::UpdateEdge(theDEdge->GetEdge(), aPoly3D);
74     }
75
76     //! Commits all polygons on triangulations correspondent to the given edge.
77     void commitPolygons(const IMeshData::IEdgeHandle& theDEdge) const
78     {
79       // Collect pcurves associated with the given edge on the specific surface.
80       IMeshData::IDMapOfIFacePtrsListOfIPCurves aMapOfPCurves;
81       for (Standard_Integer aPCurveIt = 0; aPCurveIt < theDEdge->PCurvesNb(); ++aPCurveIt)
82       {
83         const IMeshData::IPCurveHandle& aPCurve   = theDEdge->GetPCurve(aPCurveIt);
84         const IMeshData::IFacePtr&      aDFacePtr = aPCurve->GetFace();
85         const IMeshData::IFaceHandle    aDFace    = aDFacePtr;
86         if (aDFace->IsSet(IMeshData_Failure) ||
87             aDFace->IsSet(IMeshData_Reused))
88         {
89           continue;
90         }
91
92         if (!aMapOfPCurves.Contains(aDFacePtr))
93         {
94           aMapOfPCurves.Add(aDFacePtr, IMeshData::ListOfIPCurves());
95         }
96
97         IMeshData::ListOfIPCurves& aPCurves = aMapOfPCurves.ChangeFromKey(aDFacePtr);
98         aPCurves.Append(aPCurve);
99       }
100
101       // Commit polygons related to separate face.
102       const TopoDS_Edge& aEdge = theDEdge->GetEdge();
103       IMeshData::IDMapOfIFacePtrsListOfIPCurves::Iterator aPolygonIt(aMapOfPCurves);
104       for (; aPolygonIt.More(); aPolygonIt.Next())
105       {
106         const TopoDS_Face& aFace = aPolygonIt.Key()->GetFace();
107
108         TopLoc_Location aLoc;
109         const Handle(Poly_Triangulation)& aTriangulation =
110           BRep_Tool::Triangulation(aFace, aLoc);
111
112         if (!aTriangulation.IsNull())
113         {
114           const IMeshData::ListOfIPCurves& aPCurves = aPolygonIt.Value();
115           if (aPCurves.Size() == 2)
116           {
117             BRepMesh_ShapeTool::UpdateEdge(
118               aEdge,
119               collectPolygon(aPCurves.First(), theDEdge->GetDeflection()),
120               collectPolygon(aPCurves.Last (), theDEdge->GetDeflection()),
121               aTriangulation, aLoc);
122           }
123           else
124           {
125             BRepMesh_ShapeTool::UpdateEdge(
126               aEdge,
127               collectPolygon(aPCurves.First(), theDEdge->GetDeflection()),
128               aTriangulation, aLoc);
129           }
130         }
131       }
132     }
133
134     //! Collects polygonal data for the given pcurve
135     Handle(Poly_PolygonOnTriangulation) collectPolygon(
136       const IMeshData::IPCurveHandle& thePCurve,
137       const Standard_Real             theDeflection) const
138     {
139       TColStd_Array1OfInteger aNodes (1, thePCurve->ParametersNb());
140       TColStd_Array1OfReal    aParams(1, thePCurve->ParametersNb());
141       for (Standard_Integer i = 1; i <= thePCurve->ParametersNb(); ++i)
142       {
143         aNodes (i) = thePCurve->GetIndex    (i - 1);
144         aParams(i) = thePCurve->GetParameter(i - 1);
145       }
146
147       Handle(Poly_PolygonOnTriangulation) aPolygon = 
148         new Poly_PolygonOnTriangulation(aNodes, aParams);
149
150       aPolygon->Deflection(theDeflection);
151       return aPolygon;
152     }
153
154   private:
155
156     Handle(IMeshData_Model) myModel;
157   };
158 }
159
160 //=======================================================================
161 // Function: Constructor
162 // Purpose : 
163 //=======================================================================
164 BRepMesh_ModelPostProcessor::BRepMesh_ModelPostProcessor()
165 {
166 }
167
168 //=======================================================================
169 // Function: Destructor
170 // Purpose : 
171 //=======================================================================
172 BRepMesh_ModelPostProcessor::~BRepMesh_ModelPostProcessor()
173 {
174 }
175
176 //=======================================================================
177 // Function: Perform
178 // Purpose : 
179 //=======================================================================
180 Standard_Boolean BRepMesh_ModelPostProcessor::performInternal(
181   const Handle(IMeshData_Model)& theModel,
182   const IMeshTools_Parameters&   /*theParameters*/,
183   const Message_ProgressRange&   theRange)
184 {
185   (void )theRange;
186   if (theModel.IsNull())
187   {
188     return Standard_False;
189   }
190
191   // TODO: Force single threaded solution due to data races on edges sharing the same TShape
192   OSD_Parallel::For(0, theModel->EdgesNb(), PolygonCommitter(theModel), Standard_True/*!theParameters.InParallel*/);
193   return Standard_True;
194 }