7bd071ed |
1 | // Created on: 2016-04-19 |
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_EdgeDiscret.hxx> |
17 | #include <BRepMesh_Deflection.hxx> |
18 | #include <IMeshData_Model.hxx> |
19 | #include <IMeshData_Edge.hxx> |
20 | #include <IMeshData_Face.hxx> |
21 | #include <IMeshData_PCurve.hxx> |
22 | #include <TopExp.hxx> |
23 | #include <BRepMesh_ShapeTool.hxx> |
24 | #include <BRepMesh_EdgeTessellationExtractor.hxx> |
25 | #include <IMeshData_ParametersListArrayAdaptor.hxx> |
26 | #include <BRepMesh_CurveTessellator.hxx> |
27 | #include <OSD_Parallel.hxx> |
28 | |
29 | //======================================================================= |
30 | // Function: Constructor |
31 | // Purpose : |
32 | //======================================================================= |
33 | BRepMesh_EdgeDiscret::BRepMesh_EdgeDiscret () |
34 | { |
35 | } |
36 | |
37 | //======================================================================= |
38 | // Function: Destructor |
39 | // Purpose : |
40 | //======================================================================= |
41 | BRepMesh_EdgeDiscret::~BRepMesh_EdgeDiscret () |
42 | { |
43 | } |
44 | |
45 | //======================================================================= |
46 | // Function: CreateFreeEdgeTessellator |
47 | // Purpose : |
48 | //======================================================================= |
49 | Handle(IMeshTools_CurveTessellator) BRepMesh_EdgeDiscret::CreateEdgeTessellator( |
50 | const IMeshData::IEdgeHandle& theDEdge, |
51 | const IMeshTools_Parameters& theParameters) |
52 | { |
53 | return new BRepMesh_CurveTessellator(theDEdge, theParameters); |
54 | } |
55 | |
56 | //======================================================================= |
57 | // Function: CreateEdgeTessellator |
58 | // Purpose : |
59 | //======================================================================= |
60 | Handle(IMeshTools_CurveTessellator) BRepMesh_EdgeDiscret::CreateEdgeTessellator( |
61 | const IMeshData::IEdgeHandle& theDEdge, |
62 | const TopAbs_Orientation theOrientation, |
63 | const IMeshData::IFaceHandle& theDFace, |
64 | const IMeshTools_Parameters& theParameters) |
65 | { |
66 | return theDEdge->GetSameParam() ? |
67 | new BRepMesh_CurveTessellator(theDEdge, theParameters) : |
68 | new BRepMesh_CurveTessellator(theDEdge, theOrientation, theDFace, theParameters); |
69 | } |
70 | |
71 | //======================================================================= |
72 | // Function: CreateEdgeTessellationExtractor |
73 | // Purpose : |
74 | //======================================================================= |
75 | Handle(IMeshTools_CurveTessellator) BRepMesh_EdgeDiscret::CreateEdgeTessellationExtractor( |
76 | const IMeshData::IEdgeHandle& theDEdge, |
77 | const IMeshData::IFaceHandle& theDFace) |
78 | { |
79 | return new BRepMesh_EdgeTessellationExtractor(theDEdge, theDFace); |
80 | } |
81 | |
82 | //======================================================================= |
83 | // Function: Perform |
84 | // Purpose : |
85 | //======================================================================= |
86 | Standard_Boolean BRepMesh_EdgeDiscret::Perform ( |
87 | const Handle (IMeshData_Model)& theModel, |
88 | const IMeshTools_Parameters& theParameters) |
89 | { |
90 | myModel = theModel; |
91 | myParameters = theParameters; |
92 | |
93 | if (myModel.IsNull()) |
94 | { |
95 | return Standard_False; |
96 | } |
97 | |
98 | OSD_Parallel::For (0, myModel->EdgesNb (), *this, !myParameters.InParallel); |
99 | |
100 | myModel.Nullify(); // Do not hold link to model. |
101 | return Standard_True; |
102 | } |
103 | |
104 | //======================================================================= |
105 | // Function: process |
106 | // Purpose : |
107 | //======================================================================= |
108 | void BRepMesh_EdgeDiscret::process (const Standard_Integer theEdgeIndex) const |
109 | { |
110 | const IMeshData::IEdgeHandle& aDEdge = myModel->GetEdge (theEdgeIndex); |
111 | BRepMesh_Deflection::ComputeDeflection (aDEdge, myModel->GetMaxSize (), myParameters); |
112 | |
113 | Handle (IMeshTools_CurveTessellator) aEdgeTessellator; |
114 | if (!aDEdge->IsFree ()) |
115 | { |
116 | // Iterate over pcurves and check deflection on corresponding face. |
117 | Standard_Real aMinDeflection = RealLast (); |
118 | Standard_Integer aMinPCurveIndex = -1; |
119 | for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb (); ++aPCurveIt) |
120 | { |
121 | const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve (aPCurveIt); |
122 | const Standard_Real aTmpDeflection = checkExistingPolygonAndUpdateStatus(aDEdge, aPCurve); |
123 | if (aTmpDeflection < aMinDeflection) |
124 | { |
125 | // Identify pcurve with the smallest deflection in order to |
126 | // retrieve polygon that represents the most smooth discretization. |
127 | aMinDeflection = aTmpDeflection; |
128 | aMinPCurveIndex = aPCurveIt; |
129 | } |
130 | |
131 | BRepMesh_ShapeTool::CheckAndUpdateFlags (aDEdge, aPCurve); |
132 | } |
133 | |
134 | if (aMinPCurveIndex != -1) |
135 | { |
136 | aDEdge->SetDeflection (aMinDeflection); |
137 | const IMeshData::IFaceHandle aDFace = aDEdge->GetPCurve(aMinPCurveIndex)->GetFace(); |
138 | aEdgeTessellator = CreateEdgeTessellationExtractor(aDEdge, aDFace); |
139 | } |
140 | else |
141 | { |
142 | const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(0); |
143 | const IMeshData::IFaceHandle aDFace = aPCurve->GetFace(); |
144 | aEdgeTessellator = BRepMesh_EdgeDiscret::CreateEdgeTessellator( |
145 | aDEdge, aPCurve->GetOrientation(), aDFace, myParameters); |
146 | } |
147 | } |
148 | else |
149 | { |
150 | TopLoc_Location aLoc; |
151 | const Handle (Poly_Polygon3D)& aPoly3D = BRep_Tool::Polygon3D (aDEdge->GetEdge (), aLoc); |
152 | if (!aPoly3D.IsNull ()) |
153 | { |
154 | if (aPoly3D->HasParameters () && |
155 | aPoly3D->Deflection () < 1.1 * aDEdge->GetDeflection ()) |
156 | { |
157 | // Edge already has suitable 3d polygon. |
158 | aDEdge->SetStatus(IMeshData_Reused); |
159 | return; |
160 | } |
161 | else |
162 | { |
163 | aDEdge->SetStatus(IMeshData_Outdated); |
164 | } |
165 | } |
166 | |
167 | aEdgeTessellator = CreateEdgeTessellator(aDEdge, myParameters); |
168 | } |
169 | |
170 | Tessellate3d (aDEdge, aEdgeTessellator, Standard_True); |
171 | if (!aDEdge->IsFree()) |
172 | { |
173 | Tessellate2d(aDEdge, Standard_True); |
174 | } |
175 | } |
176 | |
177 | //======================================================================= |
178 | // Function: checkExistingPolygonAndUpdateStatus |
179 | // Purpose : |
180 | //======================================================================= |
181 | Standard_Real BRepMesh_EdgeDiscret::checkExistingPolygonAndUpdateStatus( |
182 | const IMeshData::IEdgeHandle& theDEdge, |
183 | const IMeshData::IPCurveHandle& thePCurve) const |
184 | { |
185 | const TopoDS_Edge& aEdge = theDEdge->GetEdge (); |
186 | const TopoDS_Face& aFace = thePCurve->GetFace ()->GetFace (); |
187 | |
188 | TopLoc_Location aLoc; |
189 | const Handle (Poly_Triangulation)& aFaceTriangulation = |
190 | BRep_Tool::Triangulation (aFace, aLoc); |
191 | |
192 | Standard_Real aDeflection = RealLast (); |
193 | if (aFaceTriangulation.IsNull()) |
194 | { |
195 | return aDeflection; |
196 | } |
197 | |
198 | const Handle (Poly_PolygonOnTriangulation)& aPolygon = |
199 | BRep_Tool::PolygonOnTriangulation (aEdge, aFaceTriangulation, aLoc); |
200 | |
201 | if (!aPolygon.IsNull ()) |
202 | { |
203 | Standard_Boolean isConsistent = aPolygon->HasParameters () && |
204 | aPolygon->Deflection () < 1.1 * theDEdge->GetDeflection (); |
205 | |
206 | if (!isConsistent) |
207 | { |
208 | // Nullify edge data and mark discrete pcurve to |
209 | // notify necessity to mesh the entire face. |
210 | theDEdge->SetStatus(IMeshData_Outdated); |
211 | } |
212 | else |
213 | { |
214 | aDeflection = aPolygon->Deflection(); |
215 | } |
216 | } |
217 | |
218 | return aDeflection; |
219 | } |
220 | |
221 | //======================================================================= |
222 | // Function: Tessellate3d |
223 | // Purpose : |
224 | //======================================================================= |
225 | void BRepMesh_EdgeDiscret::Tessellate3d( |
226 | const IMeshData::IEdgeHandle& theDEdge, |
227 | const Handle (IMeshTools_CurveTessellator)& theTessellator, |
228 | const Standard_Boolean theUpdateEnds) |
229 | { |
230 | // Create 3d polygon. |
231 | const IMeshData::ICurveHandle& aCurve = theDEdge->GetCurve(); |
232 | |
233 | const TopoDS_Edge& aEdge = theDEdge->GetEdge(); |
234 | TopoDS_Vertex aFirstVertex, aLastVertex; |
235 | TopExp::Vertices(aEdge, aFirstVertex, aLastVertex); |
236 | |
237 | if(aFirstVertex.IsNull() || aLastVertex.IsNull()) |
238 | return; |
239 | |
240 | if (theUpdateEnds) |
241 | { |
242 | gp_Pnt aPoint; |
243 | Standard_Real aParam; |
244 | theTessellator->Value(1, aPoint, aParam); |
245 | aCurve->AddPoint(BRep_Tool::Pnt(aFirstVertex), aParam); |
246 | } |
247 | |
248 | if (!theDEdge->GetDegenerated()) |
249 | { |
250 | for (Standard_Integer i = 2; i < theTessellator->PointsNb(); ++i) |
251 | { |
252 | gp_Pnt aPoint; |
253 | Standard_Real aParam; |
254 | if (!theTessellator->Value(i, aPoint, aParam)) |
255 | continue; |
256 | |
257 | if (theUpdateEnds) |
258 | { |
259 | aCurve->AddPoint(aPoint, aParam); |
260 | } |
261 | else |
262 | { |
263 | aCurve->InsertPoint(aCurve->ParametersNb() - 1, aPoint, aParam); |
264 | } |
265 | } |
266 | } |
267 | |
268 | if (theUpdateEnds) |
269 | { |
270 | gp_Pnt aPoint; |
271 | Standard_Real aParam; |
272 | theTessellator->Value(theTessellator->PointsNb(), aPoint, aParam); |
273 | aCurve->AddPoint(BRep_Tool::Pnt(aLastVertex), aParam); |
274 | } |
275 | } |
276 | |
277 | //======================================================================= |
278 | // Function: Tessellate2d |
279 | // Purpose : |
280 | //======================================================================= |
281 | void BRepMesh_EdgeDiscret::Tessellate2d( |
282 | const IMeshData::IEdgeHandle& theDEdge, |
283 | const Standard_Boolean theUpdateEnds) |
284 | { |
285 | const IMeshData::ICurveHandle& aCurve = theDEdge->GetCurve(); |
286 | for (Standard_Integer aPCurveIt = 0; aPCurveIt < theDEdge->PCurvesNb(); ++aPCurveIt) |
287 | { |
288 | const IMeshData::IPCurveHandle& aPCurve = theDEdge->GetPCurve(aPCurveIt); |
289 | const IMeshData::IFaceHandle aDFace = aPCurve->GetFace(); |
290 | IMeshData::ICurveArrayAdaptorHandle aCurveArray(new IMeshData::ICurveArrayAdaptor(aCurve)); |
291 | BRepMesh_EdgeParameterProvider<IMeshData::ICurveArrayAdaptorHandle> aProvider( |
292 | theDEdge, aPCurve->GetOrientation(), aDFace, aCurveArray); |
293 | |
294 | const Handle(Adaptor2d_HCurve2d)& aGeomPCurve = aProvider.GetPCurve(); |
295 | |
296 | Standard_Integer aParamIdx, aParamNb; |
297 | if (theUpdateEnds) |
298 | { |
299 | aParamIdx = 0; |
300 | aParamNb = aCurve->ParametersNb(); |
301 | } |
302 | else |
303 | { |
304 | aParamIdx = 1; |
305 | aParamNb = aCurve->ParametersNb() - 1; |
306 | } |
307 | |
308 | for (; aParamIdx < aParamNb; ++aParamIdx) |
309 | { |
310 | const Standard_Real aParam = aProvider.Parameter(aParamIdx, aCurve->GetPoint(aParamIdx)); |
311 | |
312 | gp_Pnt2d aPoint2d; |
313 | aGeomPCurve->D0(aParam, aPoint2d); |
314 | if (theUpdateEnds) |
315 | { |
316 | aPCurve->AddPoint(aPoint2d, aParam); |
317 | } |
318 | else |
319 | { |
320 | aPCurve->InsertPoint(aPCurve->ParametersNb() - 1, aPoint2d, aParam); |
321 | } |
322 | } |
323 | } |
324 | } |