0022735: Data races in BRepMesh working in parallel mode
[occt.git] / src / BRepMesh / BRepMesh_IncrementalMesh.cxx
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>
13 #include <BRepMesh_PluginMacro.hxx>
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
40 #ifdef HAVE_TBB
41   // paralleling using Intel TBB
42   #include <tbb/parallel_for_each.h>
43 #endif
44
45 namespace
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
52 //=======================================================================
53 //function : BRepMesh_IncrementalMesh
54 //purpose  : 
55 //=======================================================================
56 BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh() 
57 : myRelative (Standard_False),
58   myInParallel (Standard_False),
59   myModified (Standard_False),
60   myStatus (0)
61 {
62   mymapedge.Clear();
63   myancestors.Clear();
64 }
65
66 //=======================================================================
67 //function : BRepMesh_IncrementalMesh
68 //purpose  : 
69 //=======================================================================
70 BRepMesh_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)
78 {
79   mymapedge.Clear();
80   myancestors.Clear();
81   myDeflection = theDeflection;
82   myAngle = theAngle;
83   myShape = theShape;
84
85   //
86   Perform();
87 }
88
89 //=======================================================================
90 //function : ~
91 //purpose  : 
92 //=======================================================================
93 BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh() 
94 {
95 }
96
97 //=======================================================================
98 //function : SetParallel
99 //purpose  :
100 //=======================================================================
101 void BRepMesh_IncrementalMesh::SetParallel (const Standard_Boolean theInParallel)
102 {
103   myInParallel = theInParallel;
104 }
105
106 //=======================================================================
107 //function : IsParallel
108 //purpose  :
109 //=======================================================================
110 Standard_Boolean BRepMesh_IncrementalMesh::IsParallel() const
111 {
112   return myInParallel;
113 }
114
115 //=======================================================================
116 //function : Init
117 //purpose  : 
118 //=======================================================================
119 void BRepMesh_IncrementalMesh::Init() 
120 {
121   myModified=Standard_False;
122   mymapedge.Clear();
123   myancestors.Clear();
124 }
125
126 //=======================================================================
127 //function : SetRelative
128 //purpose  : 
129 //=======================================================================
130 void BRepMesh_IncrementalMesh::SetRelative(const Standard_Boolean theFlag)
131 {
132   myRelative=theFlag;
133 }
134
135 //=======================================================================
136 //function : Relative
137 //purpose  : 
138 //=======================================================================
139 Standard_Boolean BRepMesh_IncrementalMesh::Relative()const
140 {
141   return myRelative;
142 }
143
144 //=======================================================================
145 //function : IsModified
146 //purpose  : 
147 //=======================================================================
148 Standard_Boolean BRepMesh_IncrementalMesh::IsModified() const
149 {
150   return myModified;
151 }
152
153 //=======================================================================
154 //function : Perform
155 //purpose  : 
156 //=======================================================================
157 void BRepMesh_IncrementalMesh::Perform()
158 {
159   Bnd_Box aBox;
160   //
161   SetDone();
162   //
163   Init(); 
164   //
165   BRepBndLib::Add(myShape, aBox);
166   myBox = aBox;
167   //
168   if (!myMesh.IsNull()) {
169     myMesh.Nullify();
170   }
171   //
172   myMesh = new BRepMesh_FastDiscret(myDeflection,
173                                     myAngle,
174                                     aBox,
175                                     Standard_True,
176                                     Standard_True,
177                                     myRelative,
178                                     Standard_True);
179   //
180   Update(myShape);
181 }
182
183 //=======================================================================
184 //function : GetStatus
185 //purpose  : 
186 //=======================================================================
187 Standard_Integer BRepMesh_IncrementalMesh::GetStatusFlags() const
188 {
189   return myStatus;
190 }
191
192 //=======================================================================
193 //function : Update(shape)
194 //purpose  : Builds the incremental mesh of the shape
195 //=======================================================================
196 void BRepMesh_IncrementalMesh::Update(const TopoDS_Shape& S)
197 {
198   myModified = Standard_False;
199   TopExp_Explorer ex;
200
201   //AGV 080407: Since version 6.2.0 there would be exception without this check
202   if (myBox.IsVoid())
203     return;
204
205   TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, myancestors);
206   
207   BRepMesh_FastDiscret::BoxMaxDimension(myBox, mydtotale);
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
216   std::vector<TopoDS_Face> aFaces;
217   {
218     TopTools_ListOfShape aFaceList;
219     BRepLib::ReverseSortFaces (S, aFaceList);
220     TopTools_MapOfShape aFaceMap;
221     aFaces.reserve (aFaceList.Extent());
222
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     }
241   }
242
243   if (myInParallel)
244   {
245   #ifdef HAVE_TBB
246     // mesh faces in parallel threads using TBB
247     tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *myMesh.operator->());
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   }
254   else
255   {
256     for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
257       myMesh->Process (*it);
258   }
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;
264   Standard_Real cdef = 1.;
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
275     if (myRelative) 
276       defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection, 
277                                                              mydtotale, cdef);
278     else 
279       defedge = myDeflection;
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++) {
300         Nodes(i) = TD.Value(i);
301         UVNodes(i) = TD.Parameter(i);
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   }
312 }
313
314 //=======================================================================
315 //function : Update(edge)
316 //purpose  : Locate a correct discretisation if it exists
317 //           Set no one otherwise
318 //=======================================================================
319 void 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;
327   Standard_Real cdef = 1.;
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) {
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;
343       }
344       if ((!myRelative && Poly->Deflection() <= 1.1*defedge) ||
345           (myRelative && Poly->Deflection() <= 1.1*defedge)) 
346         found = Standard_True;
347       else {
348         myModified = Standard_True;
349         B.UpdateEdge(E, NullPoly, T, l);
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 //=======================================================================
364 void  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   
379   Standard_Real defedge, defface, cdef = 1.;
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)) {
388         defedge = mymapedge(edge);
389       }
390       else 
391         defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(edge, myDeflection, mydtotale, cdef);
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) ||
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         }
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()) {
421         B.UpdateEdge(TopoDS::Edge(ex.Current()), NullPoly, T, l);
422         myMap.Remove(ex.Current());
423       }
424       B.UpdateFace(F, TNull);
425     }
426     myMesh->Add(F, myancestors);
427     myStatus |= (Standard_Integer)(myMesh->CurrentFaceStatus());
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;
434       
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);
472                   myMesh->Add(F2, myancestors);
473                 }
474               }
475             }
476           }
477         }
478       }      
479     }
480   }
481 }
482
483 //=======================================================================
484 //function : Discret
485 //purpose  :
486 //=======================================================================
487 Standard_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 //=======================================================================
505 Standard_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 //=======================================================================
519 void BRepMesh_IncrementalMesh::SetParallelDefault (const Standard_Boolean theInParallel)
520 {
521   IS_IN_PARALLEL = theInParallel;
522 }
523
524 //! Export Mesh Plugin entry function
525 DISCRETPLUGIN(BRepMesh_IncrementalMesh)