74cb77ca3127e60693bf67fa3fca14d7ce063530
[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   TopTools_ListOfShape LF;
217   BRepLib::ReverseSortFaces(S,LF);
218
219   // make array of faces suitable for processing (excluding faces without surface)
220   std::vector<TopoDS_Face> aFaces;
221   for (TopTools_ListIteratorOfListOfShape it(LF); it.More(); it.Next()) 
222   {
223     TopoDS_Face F = TopoDS::Face(it.Value());
224
225     TopLoc_Location L1;
226     const Handle(Geom_Surface)& Surf = BRep_Tool::Surface(F, L1);
227     if(Surf.IsNull())
228       continue;
229     
230     Update (F);
231     aFaces.push_back (F);
232   }
233
234   if (myInParallel)
235   {
236   #ifdef HAVE_TBB
237     // mesh faces in parallel threads using TBB
238     tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *myMesh.operator->());
239   #else
240     // alternative parallelization not yet available
241     for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
242       myMesh->Process (*it);
243   #endif
244   }
245   else
246   {
247     for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
248       myMesh->Process (*it);
249   }
250
251   // maillage des edges non contenues dans les faces :
252   Standard_Real f, l, defedge;
253   Standard_Integer i, nbNodes;
254   TopLoc_Location L;
255   Standard_Real cdef = 1.;
256   ex.Init(S ,TopAbs_EDGE, TopAbs_FACE);
257
258   while (ex.More()) {
259     const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
260
261     if(!BRep_Tool::IsGeometric(E)) {
262       ex.Next();
263       continue;
264     }
265
266     if (myRelative) 
267       defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection, 
268                                                              mydtotale, cdef);
269     else 
270       defedge = myDeflection;
271     
272     Handle(Poly_Polygon3D) P3D = BRep_Tool::Polygon3D(E, L);
273     Standard_Boolean maill = Standard_False;
274     if (P3D.IsNull()) {
275       maill = Standard_True;
276     }
277     else if (P3D->Deflection() > 1.1*defedge) {
278       maill = Standard_True;
279     }
280     if (maill) {
281       BRepAdaptor_Curve C(E);
282       f = C.FirstParameter();
283       l = C.LastParameter();
284       
285       GCPnts_TangentialDeflection TD(C, f, l, myAngle, defedge, 2);
286       nbNodes = TD.NbPoints();
287       
288       TColgp_Array1OfPnt Nodes(1, nbNodes);
289       TColStd_Array1OfReal UVNodes(1, nbNodes);
290       for ( i = 1; i <= nbNodes; i++) {
291         Nodes(i) = TD.Value(i);
292         UVNodes(i) = TD.Parameter(i);
293       }
294       
295       BRep_Builder B;
296       Handle(Poly_Polygon3D) P = new Poly_Polygon3D(Nodes, UVNodes);
297       P->Deflection(myDeflection);
298       B.UpdateEdge(E, P);
299     }
300
301     ex.Next();
302   }
303 }
304
305 //=======================================================================
306 //function : Update(edge)
307 //purpose  : Locate a correct discretisation if it exists
308 //           Set no one otherwise
309 //=======================================================================
310 void BRepMesh_IncrementalMesh::Update(const TopoDS_Edge& E)
311 {
312   TopLoc_Location l;
313   Standard_Integer i = 1;
314   Handle(Poly_Triangulation) T, TNull;
315   Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
316   Standard_Boolean found = Standard_False;
317   Standard_Real defedge;
318   Standard_Real cdef = 1.;
319   BRep_Builder B;
320   Standard_Boolean defined = Standard_False;
321   
322   do {
323     BRep_Tool::PolygonOnTriangulation(E, Poly, T, l, i);
324     i++;
325     if (!T.IsNull() && !Poly.IsNull()) {
326       if (!defined) {
327         if (myRelative) 
328           defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection, 
329                                                                  mydtotale, cdef);
330         else 
331           defedge = myDeflection;
332         mymapedge.Bind(E, defedge);
333         defined = Standard_True;
334       }
335       if ((!myRelative && Poly->Deflection() <= 1.1*defedge) ||
336           (myRelative && Poly->Deflection() <= 1.1*defedge)) 
337         found = Standard_True;
338       else {
339         myModified = Standard_True;
340         B.UpdateEdge(E, NullPoly, T, l);
341       }
342     }
343   } while (!Poly.IsNull());
344
345   if (!found) myMap.Add(E);
346 }
347
348
349 //=======================================================================
350 //function : Update(face)
351 //purpose  : If the face is not correctly triangulated, or if one of its
352 //           edges is to be discretisated correctly, the triangulation
353 //           of this face is built.
354 //=======================================================================
355 void  BRepMesh_IncrementalMesh::Update(const TopoDS_Face& F)
356 {
357   TopLoc_Location l;
358   Handle(Geom_Surface) SS = BRep_Tool::Surface(F, l);
359   if (SS.IsNull()) return;
360
361   //Standard_Integer i;
362   Standard_Boolean WillBeTriangulated = Standard_False;
363   Handle(Poly_Triangulation) T, TNull;
364   T = BRep_Tool::Triangulation(F, l);
365   Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
366
367   BRep_Builder B;
368   TopExp_Explorer ex;
369   
370   Standard_Real defedge, defface, cdef = 1.;
371   Standard_Integer nbEdge = 0;
372   if (myRelative) {
373     defface = 0.;
374     
375     for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
376       const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
377       nbEdge++;
378       if (mymapedge.IsBound(edge)) {
379         defedge = mymapedge(edge);
380       }
381       else 
382         defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(edge, myDeflection, mydtotale, cdef);
383       defface = defface + defedge;
384     }
385     if (nbEdge != 0) defface = defface / nbEdge;
386     else             defface = myDeflection;
387   }
388   else
389     defface = myDeflection;
390
391   if (!T.IsNull()) {
392     if ((!myRelative && T->Deflection() <= 1.1*defface) ||
393         (myRelative && T->Deflection() <= 1.1*defface)) {
394       for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
395         const TopoDS_Shape& E = ex.Current();
396         Poly = BRep_Tool::PolygonOnTriangulation(TopoDS::Edge(E), T, l);
397         if (Poly.IsNull() || myMap.Contains(E)) {
398           WillBeTriangulated = Standard_True;
399           // cas un peu special. la triangulation est bonne, mais
400           // l'edge n'a pas de representation polygonalisee sur celle-ci.
401           break;
402         }
403       }
404     } 
405     else WillBeTriangulated = Standard_True;
406   }
407
408   if (WillBeTriangulated || T.IsNull()) {
409     myModified = Standard_True;
410     if (!T.IsNull()) {
411       for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
412         B.UpdateEdge(TopoDS::Edge(ex.Current()), NullPoly, T, l);
413         myMap.Remove(ex.Current());
414       }
415       B.UpdateFace(F, TNull);
416     }
417     myMesh->Add(F, myancestors);
418     myStatus |= (Standard_Integer)(myMesh->CurrentFaceStatus());
419     if (myMesh->CurrentFaceStatus() == BRepMesh_ReMesh) {
420 #ifdef DEB_MESH
421       cout << " face remaillee + finement que prevu."<< endl;
422 #endif
423
424       Standard_Integer index;
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, myancestors);
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)