5abbf982b49c7815abbcb5421f0c7609883ab032
[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   BRepMesh_FastDiscret::BoxMaxDimension(myBox, mydtotale);
206   
207   for (ex.Init(S, TopAbs_EDGE); ex.More(); ex.Next()) {
208     if(BRep_Tool::IsGeometric(TopoDS::Edge(ex.Current()))) {
209       Update(TopoDS::Edge(ex.Current()));
210     }
211   }
212
213   // get list of faces
214   TopTools_ListOfShape LF;
215   BRepLib::ReverseSortFaces(S,LF);
216
217   // make array of faces suitable for processing (excluding faces without surface)
218   std::vector<TopoDS_Face> aFaces;
219   for (TopTools_ListIteratorOfListOfShape it(LF); it.More(); it.Next()) 
220   {
221     TopoDS_Face F = TopoDS::Face(it.Value());
222
223     TopLoc_Location L1;
224     const Handle(Geom_Surface)& Surf = BRep_Tool::Surface(F, L1);
225     if(Surf.IsNull())
226       continue;
227     
228     Update (F);
229     aFaces.push_back (F);
230   }
231
232   if (myInParallel)
233   {
234   #ifdef HAVE_TBB
235     // mesh faces in parallel threads using TBB
236     tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *myMesh.operator->());
237   #else
238     // alternative parallelization not yet available
239     for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
240       myMesh->Process (*it);
241   #endif
242   }
243   else
244   {
245     for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
246       myMesh->Process (*it);
247   }
248
249   // maillage des edges non contenues dans les faces :
250   Standard_Real f, l, defedge;
251   Standard_Integer i, nbNodes;
252   TopLoc_Location L;
253   Standard_Real cdef = 1.;
254   ex.Init(S ,TopAbs_EDGE, TopAbs_FACE);
255
256   while (ex.More()) {
257     const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
258
259     if(!BRep_Tool::IsGeometric(E)) {
260       ex.Next();
261       continue;
262     }
263
264     if (myRelative) 
265       defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection, 
266                                                              mydtotale, cdef);
267     else 
268       defedge = myDeflection;
269     
270     Handle(Poly_Polygon3D) P3D = BRep_Tool::Polygon3D(E, L);
271     Standard_Boolean maill = Standard_False;
272     if (P3D.IsNull()) {
273       maill = Standard_True;
274     }
275     else if (P3D->Deflection() > 1.1*defedge) {
276       maill = Standard_True;
277     }
278     if (maill) {
279       BRepAdaptor_Curve C(E);
280       f = C.FirstParameter();
281       l = C.LastParameter();
282       
283       GCPnts_TangentialDeflection TD(C, f, l, myAngle, defedge, 2);
284       nbNodes = TD.NbPoints();
285       
286       TColgp_Array1OfPnt Nodes(1, nbNodes);
287       TColStd_Array1OfReal UVNodes(1, nbNodes);
288       for ( i = 1; i <= nbNodes; i++) {
289         Nodes(i) = TD.Value(i);
290         UVNodes(i) = TD.Parameter(i);
291       }
292       
293       BRep_Builder B;
294       Handle(Poly_Polygon3D) P = new Poly_Polygon3D(Nodes, UVNodes);
295       P->Deflection(myDeflection);
296       B.UpdateEdge(E, P);
297     }
298
299     ex.Next();
300   }
301 }
302
303 //=======================================================================
304 //function : Update(edge)
305 //purpose  : Locate a correct discretisation if it exists
306 //           Set no one otherwise
307 //=======================================================================
308 void BRepMesh_IncrementalMesh::Update(const TopoDS_Edge& E)
309 {
310   TopLoc_Location l;
311   Standard_Integer i = 1;
312   Handle(Poly_Triangulation) T, TNull;
313   Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
314   Standard_Boolean found = Standard_False;
315   Standard_Real defedge;
316   Standard_Real cdef = 1.;
317   BRep_Builder B;
318   Standard_Boolean defined = Standard_False;
319   
320   do {
321     BRep_Tool::PolygonOnTriangulation(E, Poly, T, l, i);
322     i++;
323     if (!T.IsNull() && !Poly.IsNull()) {
324       if (!defined) {
325         if (myRelative) 
326           defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection, 
327                                                                  mydtotale, cdef);
328         else 
329           defedge = myDeflection;
330         mymapedge.Bind(E, defedge);
331         defined = Standard_True;
332       }
333       if ((!myRelative && Poly->Deflection() <= 1.1*defedge) ||
334           (myRelative && Poly->Deflection() <= 1.1*defedge)) 
335         found = Standard_True;
336       else {
337         myModified = Standard_True;
338         B.UpdateEdge(E, NullPoly, T, l);
339       }
340     }
341   } while (!Poly.IsNull());
342
343   if (!found) myMap.Add(E);
344 }
345
346
347 //=======================================================================
348 //function : Update(face)
349 //purpose  : If the face is not correctly triangulated, or if one of its
350 //           edges is to be discretisated correctly, the triangulation
351 //           of this face is built.
352 //=======================================================================
353 void  BRepMesh_IncrementalMesh::Update(const TopoDS_Face& F)
354 {
355   TopLoc_Location l;
356   Handle(Geom_Surface) SS = BRep_Tool::Surface(F, l);
357   if (SS.IsNull()) return;
358
359   //Standard_Integer i;
360   Standard_Boolean WillBeTriangulated = Standard_False;
361   Handle(Poly_Triangulation) T, TNull;
362   T = BRep_Tool::Triangulation(F, l);
363   Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
364
365   BRep_Builder B;
366   TopExp_Explorer ex;
367   
368   Standard_Real defedge, defface, cdef = 1.;
369   Standard_Integer nbEdge = 0;
370   if (myRelative) {
371     defface = 0.;
372     
373     for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
374       const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
375       nbEdge++;
376       if (mymapedge.IsBound(edge)) {
377         defedge = mymapedge(edge);
378       }
379       else 
380         defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(edge, myDeflection, mydtotale, cdef);
381       defface = defface + defedge;
382     }
383     if (nbEdge != 0) defface = defface / nbEdge;
384     else             defface = myDeflection;
385   }
386   else
387     defface = myDeflection;
388
389   if (!T.IsNull()) {
390     if ((!myRelative && T->Deflection() <= 1.1*defface) ||
391         (myRelative && T->Deflection() <= 1.1*defface)) {
392       for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
393         const TopoDS_Shape& E = ex.Current();
394         Poly = BRep_Tool::PolygonOnTriangulation(TopoDS::Edge(E), T, l);
395         if (Poly.IsNull() || myMap.Contains(E)) {
396           WillBeTriangulated = Standard_True;
397           // cas un peu special. la triangulation est bonne, mais
398           // l'edge n'a pas de representation polygonalisee sur celle-ci.
399           break;
400         }
401       }
402     } 
403     else WillBeTriangulated = Standard_True;
404   }
405
406   if (WillBeTriangulated || T.IsNull()) {
407     myModified = Standard_True;
408     if (!T.IsNull()) {
409       for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
410         B.UpdateEdge(TopoDS::Edge(ex.Current()), NullPoly, T, l);
411         myMap.Remove(ex.Current());
412       }
413       B.UpdateFace(F, TNull);
414     }
415     myMesh->Add(F);
416     myStatus |= (Standard_Integer)(myMesh->CurrentFaceStatus());
417     if (myMesh->CurrentFaceStatus() == BRepMesh_ReMesh) {
418 #ifdef DEB_MESH
419       cout << " face remaillee + finement que prevu."<< endl;
420 #endif
421
422       Standard_Integer index;
423       if( myancestors.Extent() < 1 )
424         TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,myancestors);
425
426       TopTools_MapOfShape MShape;
427       MShape.Add(F);
428
429       TopoDS_Iterator ex(F),ex2;
430       for (; ex.More(); ex.Next()) {
431         const TopoDS_Shape& aWire = ex.Value();
432         if (aWire.ShapeType() != TopAbs_WIRE)
433           continue;
434         TopoDS_Iterator exW(aWire);
435         for(; exW.More(); exW.Next()) {
436           const TopoDS_Edge& edge = TopoDS::Edge(exW.Value());
437           index = myancestors.FindIndex(edge);
438           if (index != 0) {
439             const TopTools_ListOfShape& L = myancestors.FindFromKey(edge);
440           
441             TopTools_ListIteratorOfListOfShape it(L);
442           
443             for (; it.More(); it.Next()) {
444               TopoDS_Face F2 = TopoDS::Face(it.Value());
445               if (!MShape.Contains(F2)) {
446                 MShape.Add(F2);
447                 T = BRep_Tool::Triangulation(F2, l);      
448                 if (!T.IsNull()) {
449 #ifdef DEB_MESH
450                   cout <<"triangulation a refaire" <<endl;
451 #endif
452                   for (ex2.Initialize(F2); ex2.More(); ex2.Next()) {
453                     const TopoDS_Shape& aWire2 = ex2.Value();
454                     if (aWire2.ShapeType() != TopAbs_WIRE)
455                       continue;
456                     TopoDS_Iterator exW2(aWire2);
457                     for(; exW2.More(); exW2.Next()) {
458                       TopoDS_Edge E2 = TopoDS::Edge(exW2.Value());
459                       B.UpdateEdge(E2, NullPoly, T, l);
460                     }
461                   }
462                   B.UpdateFace(F2, TNull);
463                   myMesh->Add(F2);
464                 }
465               }
466             }
467           }
468         }
469       }      
470     }
471   }
472 }
473
474 //=======================================================================
475 //function : Discret
476 //purpose  :
477 //=======================================================================
478 Standard_Integer BRepMesh_IncrementalMesh::Discret (const TopoDS_Shape&    theShape,
479                                                     const Standard_Real    theDeflection,
480                                                     const Standard_Real    theAngle,
481                                                     BRepMesh_PDiscretRoot& theAlgo)
482 {
483   BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh();
484   anAlgo->SetDeflection (theDeflection);
485   anAlgo->SetAngle (theAngle);
486   anAlgo->SetShape (theShape);
487   anAlgo->SetParallel (IS_IN_PARALLEL);
488   theAlgo = anAlgo;
489   return 0; // no error
490 }
491
492 //=======================================================================
493 //function : IsParallelDefault
494 //purpose  :
495 //=======================================================================
496 Standard_Boolean BRepMesh_IncrementalMesh::IsParallelDefault()
497 {
498 #ifdef HAVE_TBB
499   return IS_IN_PARALLEL;
500 #else
501   // no alternative parallelization yet - flag has no meaning
502   return Standard_False;
503 #endif
504 }
505
506 //=======================================================================
507 //function : Discret
508 //purpose  :
509 //=======================================================================
510 void BRepMesh_IncrementalMesh::SetParallelDefault (const Standard_Boolean theInParallel)
511 {
512   IS_IN_PARALLEL = theInParallel;
513 }
514
515 //! Export Mesh Plugin entry function
516 DISCRETPLUGIN(BRepMesh_IncrementalMesh)