0030345: Mesh, BRepMesh_CurveTessellator - GCPnts_TangentialDeflection throws Standar...
[occt.git] / src / BRepMesh / BRepMesh_EdgeDiscret.cxx
CommitLineData
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//=======================================================================
33BRepMesh_EdgeDiscret::BRepMesh_EdgeDiscret ()
34{
35}
36
37//=======================================================================
38// Function: Destructor
39// Purpose :
40//=======================================================================
41BRepMesh_EdgeDiscret::~BRepMesh_EdgeDiscret ()
42{
43}
44
45//=======================================================================
46// Function: CreateFreeEdgeTessellator
47// Purpose :
48//=======================================================================
49Handle(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//=======================================================================
60Handle(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//=======================================================================
75Handle(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//=======================================================================
86Standard_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//=======================================================================
108void 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//=======================================================================
181Standard_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//=======================================================================
225void 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//=======================================================================
281void 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}