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