0022627: Change OCCT memory management defaults
[occt.git] / src / BRepMesh / BRepMesh_IncrementalMesh.cxx
CommitLineData
7fd59977 1// File: BRepMesh_IncrementalMesh.cxx
2// Created: Tue Jun 20 10:34:51 1995
3// Author: Stagiaire Alain JOURDAIN
4// <ajo@phobox>
5
6
7#include <BRepMesh_IncrementalMesh.ixx>
8
9#include <BRepMesh.hxx>
10#include <BRepMesh_Edge.hxx>
11#include <BRepMesh_Triangle.hxx>
12#include <BRepMesh_FastDiscretFace.hxx>
0b97567d 13#include <BRepMesh_PluginMacro.hxx>
7fd59977 14
15#include <Bnd_Box.hxx>
16#include <BRep_Builder.hxx>
17#include <BRep_Tool.hxx>
18#include <BRepLib.hxx>
19#include <BRepBndLib.hxx>
20#include <BRepAdaptor_Curve.hxx>
21#include <GCPnts_TangentialDeflection.hxx>
22#include <Precision.hxx>
23#include <TopExp.hxx>
24#include <TopExp_Explorer.hxx>
25#include <TopAbs.hxx>
26#include <TopTools_ListIteratorOfListOfShape.hxx>
27#include <TColgp_Array1OfPnt.hxx>
28#include <TColStd_Array1OfReal.hxx>
29#include <TopoDS_Shape.hxx>
30#include <TopoDS_Face.hxx>
31#include <TopoDS_Edge.hxx>
32#include <TopoDS.hxx>
33#include <TopTools_HArray1OfShape.hxx>
34#include <Poly_Triangulation.hxx>
35#include <Poly_Polygon3D.hxx>
36#include <Poly_PolygonOnTriangulation.hxx>
37
38#include <vector>
39
7fd59977 40#ifdef HAVE_TBB
0b97567d
K
41 // paralleling using Intel TBB
42 #include <tbb/parallel_for_each.h>
7fd59977 43#endif
44
0b97567d
K
45namespace
46{
47 //! Default flag to control parallelization for BRepMesh_IncrementalMesh
48 //! tool returned for Mesh Factory
49 static Standard_Boolean IS_IN_PARALLEL = Standard_False;
50};
51
7fd59977 52//=======================================================================
53//function : BRepMesh_IncrementalMesh
54//purpose :
55//=======================================================================
56BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh()
0b97567d
K
57: myRelative (Standard_False),
58 myInParallel (Standard_False),
59 myModified (Standard_False),
60 myStatus (0)
7fd59977 61{
62 mymapedge.Clear();
63 myancestors.Clear();
64}
65
66//=======================================================================
67//function : BRepMesh_IncrementalMesh
68//purpose :
69//=======================================================================
0b97567d
K
70BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh (const TopoDS_Shape& theShape,
71 const Standard_Real theDeflection,
72 const Standard_Boolean theRelative,
73 const Standard_Real theAngle)
74: myRelative (theRelative),
75 myInParallel (Standard_False),
76 myModified (Standard_False),
77 myStatus (0)
7fd59977 78{
79 mymapedge.Clear();
80 myancestors.Clear();
0b97567d
K
81 myDeflection = theDeflection;
82 myAngle = theAngle;
83 myShape = theShape;
84
7fd59977 85 //
0b97567d 86 Perform();
7fd59977 87}
88
89//=======================================================================
90//function : ~
91//purpose :
92//=======================================================================
93BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh()
94{
95}
96
0b97567d
K
97//=======================================================================
98//function : SetParallel
99//purpose :
100//=======================================================================
101void BRepMesh_IncrementalMesh::SetParallel (const Standard_Boolean theInParallel)
102{
103 myInParallel = theInParallel;
104}
105
106//=======================================================================
107//function : IsParallel
108//purpose :
109//=======================================================================
110Standard_Boolean BRepMesh_IncrementalMesh::IsParallel() const
111{
112 return myInParallel;
113}
114
7fd59977 115//=======================================================================
116//function : Init
117//purpose :
118//=======================================================================
119void BRepMesh_IncrementalMesh::Init()
120{
121 myModified=Standard_False;
122 mymapedge.Clear();
123 myancestors.Clear();
124}
125
126//=======================================================================
127//function : SetRelative
128//purpose :
129//=======================================================================
130void BRepMesh_IncrementalMesh::SetRelative(const Standard_Boolean theFlag)
131{
132 myRelative=theFlag;
133}
134
135//=======================================================================
136//function : Relative
137//purpose :
138//=======================================================================
139Standard_Boolean BRepMesh_IncrementalMesh::Relative()const
140{
141 return myRelative;
142}
143
144//=======================================================================
145//function : IsModified
146//purpose :
147//=======================================================================
148Standard_Boolean BRepMesh_IncrementalMesh::IsModified() const
149{
150 return myModified;
151}
152
153//=======================================================================
154//function : Perform
155//purpose :
156//=======================================================================
157void BRepMesh_IncrementalMesh::Perform()
158{
159 Bnd_Box aBox;
160 //
161 SetDone();
162 //
163 Init();
164 //
165 BRepBndLib::Add(myShape, aBox);
8e3006e4 166 myBox = aBox;
7fd59977 167 //
8e3006e4
O
168 if (!myMesh.IsNull()) {
169 myMesh.Nullify();
170 }
7fd59977 171 //
8e3006e4
O
172 myMesh = new BRepMesh_FastDiscret(myDeflection,
173 myAngle,
174 aBox,
175 Standard_True,
176 Standard_True,
177 myRelative,
178 Standard_True);
7fd59977 179 //
8e3006e4 180 Update(myShape);
7fd59977 181}
182
8e3006e4 183//=======================================================================
d51c7072 184//function : GetStatus
8e3006e4
O
185//purpose :
186//=======================================================================
d51c7072 187Standard_Integer BRepMesh_IncrementalMesh::GetStatusFlags() const
8e3006e4 188{
d51c7072 189 return myStatus;
8e3006e4 190}
7fd59977 191
192//=======================================================================
193//function : Update(shape)
194//purpose : Builds the incremental mesh of the shape
195//=======================================================================
196void BRepMesh_IncrementalMesh::Update(const TopoDS_Shape& S)
7fd59977 197{
198 myModified = Standard_False;
199 TopExp_Explorer ex;
200
7fd59977 201 //AGV 080407: Since version 6.2.0 there would be exception without this check
202 if (myBox.IsVoid())
203 return;
0d36f7e4
O
204
205 TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, myancestors);
7fd59977 206
2b59653e 207 BRepMesh_FastDiscret::BoxMaxDimension(myBox, mydtotale);
7fd59977 208
209 for (ex.Init(S, TopAbs_EDGE); ex.More(); ex.Next()) {
210 if(BRep_Tool::IsGeometric(TopoDS::Edge(ex.Current()))) {
211 Update(TopoDS::Edge(ex.Current()));
212 }
213 }
214
215 // get list of faces
7fd59977 216 std::vector<TopoDS_Face> aFaces;
7fd59977 217 {
ca0db031
K
218 TopTools_ListOfShape aFaceList;
219 BRepLib::ReverseSortFaces (S, aFaceList);
220 TopTools_MapOfShape aFaceMap;
221 aFaces.reserve (aFaceList.Extent());
7fd59977 222
ca0db031
K
223 // make array of faces suitable for processing (excluding faces without surface)
224 TopLoc_Location aDummyLoc;
225 const TopLoc_Location anEmptyLoc;
226 for (TopTools_ListIteratorOfListOfShape aFaceIter (aFaceList); aFaceIter.More(); aFaceIter.Next())
227 {
228 TopoDS_Shape aFaceNoLoc = aFaceIter.Value();
229 aFaceNoLoc.Location (anEmptyLoc);
230 if (!aFaceMap.Add (aFaceNoLoc))
231 continue; // already processed
232
233 TopoDS_Face aFace = TopoDS::Face (aFaceIter.Value());
234 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (aFace, aDummyLoc);
235 if (aSurf.IsNull())
236 continue;
237
238 Update (aFace);
239 aFaces.push_back (aFace);
240 }
7fd59977 241 }
242
0b97567d
K
243 if (myInParallel)
244 {
245 #ifdef HAVE_TBB
246 // mesh faces in parallel threads using TBB
7fd59977 247 tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *myMesh.operator->());
0b97567d
K
248 #else
249 // alternative parallelization not yet available
250 for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
251 myMesh->Process (*it);
252 #endif
253 }
7fd59977 254 else
0b97567d
K
255 {
256 for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
257 myMesh->Process (*it);
258 }
7fd59977 259
260 // maillage des edges non contenues dans les faces :
261 Standard_Real f, l, defedge;
262 Standard_Integer i, nbNodes;
263 TopLoc_Location L;
2b59653e 264 Standard_Real cdef = 1.;
7fd59977 265 ex.Init(S ,TopAbs_EDGE, TopAbs_FACE);
266
267 while (ex.More()) {
268 const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
269
270 if(!BRep_Tool::IsGeometric(E)) {
271 ex.Next();
272 continue;
273 }
274
2b59653e
E
275 if (myRelative)
276 defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection,
277 mydtotale, cdef);
278 else
279 defedge = myDeflection;
7fd59977 280
281 Handle(Poly_Polygon3D) P3D = BRep_Tool::Polygon3D(E, L);
282 Standard_Boolean maill = Standard_False;
283 if (P3D.IsNull()) {
284 maill = Standard_True;
285 }
286 else if (P3D->Deflection() > 1.1*defedge) {
287 maill = Standard_True;
288 }
289 if (maill) {
290 BRepAdaptor_Curve C(E);
291 f = C.FirstParameter();
292 l = C.LastParameter();
293
294 GCPnts_TangentialDeflection TD(C, f, l, myAngle, defedge, 2);
295 nbNodes = TD.NbPoints();
296
297 TColgp_Array1OfPnt Nodes(1, nbNodes);
298 TColStd_Array1OfReal UVNodes(1, nbNodes);
299 for ( i = 1; i <= nbNodes; i++) {
2b59653e
E
300 Nodes(i) = TD.Value(i);
301 UVNodes(i) = TD.Parameter(i);
7fd59977 302 }
303
304 BRep_Builder B;
305 Handle(Poly_Polygon3D) P = new Poly_Polygon3D(Nodes, UVNodes);
306 P->Deflection(myDeflection);
307 B.UpdateEdge(E, P);
308 }
309
310 ex.Next();
311 }
0b97567d
K
312}
313
7fd59977 314//=======================================================================
315//function : Update(edge)
316//purpose : Locate a correct discretisation if it exists
317// Set no one otherwise
318//=======================================================================
319void BRepMesh_IncrementalMesh::Update(const TopoDS_Edge& E)
320{
321 TopLoc_Location l;
322 Standard_Integer i = 1;
323 Handle(Poly_Triangulation) T, TNull;
324 Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
325 Standard_Boolean found = Standard_False;
326 Standard_Real defedge;
2b59653e 327 Standard_Real cdef = 1.;
7fd59977 328 BRep_Builder B;
329 Standard_Boolean defined = Standard_False;
330
331 do {
332 BRep_Tool::PolygonOnTriangulation(E, Poly, T, l, i);
333 i++;
334 if (!T.IsNull() && !Poly.IsNull()) {
335 if (!defined) {
2b59653e
E
336 if (myRelative)
337 defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection,
338 mydtotale, cdef);
339 else
340 defedge = myDeflection;
341 mymapedge.Bind(E, defedge);
342 defined = Standard_True;
7fd59977 343 }
344 if ((!myRelative && Poly->Deflection() <= 1.1*defedge) ||
2b59653e
E
345 (myRelative && Poly->Deflection() <= 1.1*defedge))
346 found = Standard_True;
7fd59977 347 else {
2b59653e
E
348 myModified = Standard_True;
349 B.UpdateEdge(E, NullPoly, T, l);
7fd59977 350 }
351 }
352 } while (!Poly.IsNull());
353
354 if (!found) myMap.Add(E);
355}
356
357
358//=======================================================================
359//function : Update(face)
360//purpose : If the face is not correctly triangulated, or if one of its
361// edges is to be discretisated correctly, the triangulation
362// of this face is built.
363//=======================================================================
364void BRepMesh_IncrementalMesh::Update(const TopoDS_Face& F)
365{
366 TopLoc_Location l;
367 Handle(Geom_Surface) SS = BRep_Tool::Surface(F, l);
368 if (SS.IsNull()) return;
369
370 //Standard_Integer i;
371 Standard_Boolean WillBeTriangulated = Standard_False;
372 Handle(Poly_Triangulation) T, TNull;
373 T = BRep_Tool::Triangulation(F, l);
374 Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
375
376 BRep_Builder B;
377 TopExp_Explorer ex;
378
2b59653e 379 Standard_Real defedge, defface, cdef = 1.;
7fd59977 380 Standard_Integer nbEdge = 0;
381 if (myRelative) {
382 defface = 0.;
383
384 for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
385 const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
386 nbEdge++;
387 if (mymapedge.IsBound(edge)) {
2b59653e 388 defedge = mymapedge(edge);
7fd59977 389 }
2b59653e
E
390 else
391 defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(edge, myDeflection, mydtotale, cdef);
7fd59977 392 defface = defface + defedge;
393 }
394 if (nbEdge != 0) defface = defface / nbEdge;
395 else defface = myDeflection;
396 }
397 else
398 defface = myDeflection;
399
400 if (!T.IsNull()) {
401 if ((!myRelative && T->Deflection() <= 1.1*defface) ||
2b59653e
E
402 (myRelative && T->Deflection() <= 1.1*defface)) {
403 for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
404 const TopoDS_Shape& E = ex.Current();
405 Poly = BRep_Tool::PolygonOnTriangulation(TopoDS::Edge(E), T, l);
406 if (Poly.IsNull() || myMap.Contains(E)) {
407 WillBeTriangulated = Standard_True;
408 // cas un peu special. la triangulation est bonne, mais
409 // l'edge n'a pas de representation polygonalisee sur celle-ci.
410 break;
411 }
7fd59977 412 }
413 }
414 else WillBeTriangulated = Standard_True;
415 }
416
417 if (WillBeTriangulated || T.IsNull()) {
418 myModified = Standard_True;
419 if (!T.IsNull()) {
420 for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
2b59653e
E
421 B.UpdateEdge(TopoDS::Edge(ex.Current()), NullPoly, T, l);
422 myMap.Remove(ex.Current());
7fd59977 423 }
424 B.UpdateFace(F, TNull);
425 }
0d36f7e4 426 myMesh->Add(F, myancestors);
d51c7072 427 myStatus |= (Standard_Integer)(myMesh->CurrentFaceStatus());
7fd59977 428 if (myMesh->CurrentFaceStatus() == BRepMesh_ReMesh) {
429#ifdef DEB_MESH
430 cout << " face remaillee + finement que prevu."<< endl;
431#endif
432
433 Standard_Integer index;
0d36f7e4 434
7fd59977 435 TopTools_MapOfShape MShape;
436 MShape.Add(F);
437
438 TopoDS_Iterator ex(F),ex2;
439 for (; ex.More(); ex.Next()) {
440 const TopoDS_Shape& aWire = ex.Value();
441 if (aWire.ShapeType() != TopAbs_WIRE)
442 continue;
443 TopoDS_Iterator exW(aWire);
444 for(; exW.More(); exW.Next()) {
445 const TopoDS_Edge& edge = TopoDS::Edge(exW.Value());
446 index = myancestors.FindIndex(edge);
447 if (index != 0) {
448 const TopTools_ListOfShape& L = myancestors.FindFromKey(edge);
449
450 TopTools_ListIteratorOfListOfShape it(L);
451
452 for (; it.More(); it.Next()) {
453 TopoDS_Face F2 = TopoDS::Face(it.Value());
454 if (!MShape.Contains(F2)) {
455 MShape.Add(F2);
456 T = BRep_Tool::Triangulation(F2, l);
457 if (!T.IsNull()) {
458#ifdef DEB_MESH
459 cout <<"triangulation a refaire" <<endl;
460#endif
461 for (ex2.Initialize(F2); ex2.More(); ex2.Next()) {
462 const TopoDS_Shape& aWire2 = ex2.Value();
463 if (aWire2.ShapeType() != TopAbs_WIRE)
464 continue;
465 TopoDS_Iterator exW2(aWire2);
466 for(; exW2.More(); exW2.Next()) {
467 TopoDS_Edge E2 = TopoDS::Edge(exW2.Value());
468 B.UpdateEdge(E2, NullPoly, T, l);
469 }
470 }
471 B.UpdateFace(F2, TNull);
0d36f7e4 472 myMesh->Add(F2, myancestors);
7fd59977 473 }
474 }
475 }
476 }
477 }
478 }
479 }
480 }
481}
0b97567d
K
482
483//=======================================================================
484//function : Discret
485//purpose :
486//=======================================================================
487Standard_Integer BRepMesh_IncrementalMesh::Discret (const TopoDS_Shape& theShape,
488 const Standard_Real theDeflection,
489 const Standard_Real theAngle,
490 BRepMesh_PDiscretRoot& theAlgo)
491{
492 BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh();
493 anAlgo->SetDeflection (theDeflection);
494 anAlgo->SetAngle (theAngle);
495 anAlgo->SetShape (theShape);
496 anAlgo->SetParallel (IS_IN_PARALLEL);
497 theAlgo = anAlgo;
498 return 0; // no error
499}
500
501//=======================================================================
502//function : IsParallelDefault
503//purpose :
504//=======================================================================
505Standard_Boolean BRepMesh_IncrementalMesh::IsParallelDefault()
506{
507#ifdef HAVE_TBB
508 return IS_IN_PARALLEL;
509#else
510 // no alternative parallelization yet - flag has no meaning
511 return Standard_False;
512#endif
513}
514
515//=======================================================================
516//function : Discret
517//purpose :
518//=======================================================================
519void BRepMesh_IncrementalMesh::SetParallelDefault (const Standard_Boolean theInParallel)
520{
521 IS_IN_PARALLEL = theInParallel;
522}
523
524//! Export Mesh Plugin entry function
525DISCRETPLUGIN(BRepMesh_IncrementalMesh)