dd3763e0914faaad7eecea6099221d3251375a7f
[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   if (aBox.IsVoid() == Standard_False)
144   {
145     myBox = aBox;
146   //
147     if (!myMesh.IsNull()) {
148       myMesh.Nullify();
149     }
150   //
151     myMesh = new BRepMesh_FastDiscret(myDeflection,
152                                       myAngle,
153                                       aBox,
154                                       Standard_True,
155                                       Standard_True,
156                                       myRelative,
157                                       Standard_True);
158   //
159     Update(myShape);
160   }
161 }
162
163
164 //=======================================================================
165 //function : Update(shape)
166 //purpose  : Builds the incremental mesh of the shape
167 //=======================================================================
168 void BRepMesh_IncrementalMesh::Update(const TopoDS_Shape& S)
169                                   
170 {
171   myModified = Standard_False;
172   TopExp_Explorer ex;
173
174   Standard_Real TXmin, TYmin, TZmin, TXmax, TYmax, TZmax;
175   Standard_Real dx, dy, dz;
176
177   //AGV 080407: Since version 6.2.0 there would be exception without this check
178   if (myBox.IsVoid())
179     return;
180   
181   myBox.Get(TXmin, TYmin, TZmin, TXmax, TYmax, TZmax);
182   dx = TXmax-TXmin;
183   dy = TYmax-TYmin;
184   dz = TZmax-TZmin;
185   mydtotale = dx;
186   if (dy > mydtotale) mydtotale = dy;
187   if (dz > mydtotale) mydtotale = dz;
188   
189   for (ex.Init(S, TopAbs_EDGE); ex.More(); ex.Next()) {
190     if(BRep_Tool::IsGeometric(TopoDS::Edge(ex.Current()))) {
191       Update(TopoDS::Edge(ex.Current()));
192     }
193   }
194
195   // get list of faces
196   TopTools_ListOfShape LF;
197   BRepLib::ReverseSortFaces(S,LF);
198
199   // make array of faces suitable for processing (excluding faces without surface)
200   std::vector<TopoDS_Face> aFaces;
201   for (TopTools_ListIteratorOfListOfShape it(LF); it.More(); it.Next()) 
202   {
203     TopoDS_Face F = TopoDS::Face(it.Value());
204
205     TopLoc_Location L1;
206     const Handle(Geom_Surface)& Surf = BRep_Tool::Surface(F, L1);
207     if(Surf.IsNull())
208       continue;
209     
210     Update (F);
211     aFaces.push_back (F);
212   }
213
214   // mesh faces in parallel threads using TBB
215 #ifdef HAVE_TBB
216   if (Standard::IsReentrant())
217     tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *myMesh.operator->());
218   else
219 #endif
220   for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
221     myMesh->Process (*it);
222
223   // maillage des edges non contenues dans les faces :
224   Standard_Real f, l, defedge;
225   Standard_Integer i, nbNodes;
226   TopLoc_Location L;
227   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
228   ex.Init(S ,TopAbs_EDGE, TopAbs_FACE);
229
230   while (ex.More()) {
231     const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
232
233     if(!BRep_Tool::IsGeometric(E)) {
234       ex.Next();
235       continue;
236     }
237
238     if (myRelative) {
239       Bnd_Box B;
240       BRepBndLib::Add(E, B);
241       B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
242       dx = aXmax-aXmin;
243       dy = aYmax-aYmin;
244       dz = aZmax-aZmin;
245       defedge = dx;
246       if (defedge < dy) defedge = dy;
247       if (defedge < dz) defedge = dz;
248       // ajustement par rapport a la taille totale:
249       Standard_Real cdef = mydtotale/(2*defedge);
250       if (cdef < 0.5) cdef = 0.5;
251       if (cdef > 2.) cdef = 2.;
252       defedge = cdef * defedge * myDeflection;
253     }
254     else defedge = myDeflection;
255     
256     Handle(Poly_Polygon3D) P3D = BRep_Tool::Polygon3D(E, L);
257     Standard_Boolean maill = Standard_False;
258     if (P3D.IsNull()) {
259       maill = Standard_True;
260     }
261     else if (P3D->Deflection() > 1.1*defedge) {
262       maill = Standard_True;
263     }
264     if (maill) {
265       BRepAdaptor_Curve C(E);
266       f = C.FirstParameter();
267       l = C.LastParameter();
268       
269       GCPnts_TangentialDeflection TD(C, f, l, myAngle, defedge, 2);
270       nbNodes = TD.NbPoints();
271       
272       TColgp_Array1OfPnt Nodes(1, nbNodes);
273       TColStd_Array1OfReal UVNodes(1, nbNodes);
274       for ( i = 1; i <= nbNodes; i++) {
275         Nodes(i) = TD.Value(i);
276         UVNodes(i) = TD.Parameter(i);
277       }
278       
279       BRep_Builder B;
280       Handle(Poly_Polygon3D) P = new Poly_Polygon3D(Nodes, UVNodes);
281       P->Deflection(myDeflection);
282       B.UpdateEdge(E, P);
283     }
284
285     ex.Next();
286   }
287 }    
288 //=======================================================================
289 //function : Update(edge)
290 //purpose  : Locate a correct discretisation if it exists
291 //           Set no one otherwise
292 //=======================================================================
293 void BRepMesh_IncrementalMesh::Update(const TopoDS_Edge& E)
294 {
295   TopLoc_Location l;
296   Standard_Integer i = 1;
297   Handle(Poly_Triangulation) T, TNull;
298   Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
299   Standard_Boolean found = Standard_False;
300   Standard_Real defedge;
301   BRep_Builder B;
302   Standard_Boolean defined = Standard_False;
303   
304   do {
305     BRep_Tool::PolygonOnTriangulation(E, Poly, T, l, i);
306     i++;
307     if (!T.IsNull() && !Poly.IsNull()) {
308       if (!defined) {
309         if (myRelative) {
310           Bnd_Box aBox;
311           BRepBndLib::Add(E, aBox);
312           Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, dx, dy, dz;
313           aBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
314           dx = aXmax-aXmin;
315           dy = aYmax-aYmin;
316           dz = aZmax-aZmin;
317           defedge = dx;
318           if (defedge < dy) defedge = dy;
319           if (defedge < dz) defedge = dz;
320           // ajustement par rapport a la taille totale:
321           Standard_Real cdef = mydtotale/(2*defedge);
322           if (cdef < 0.5) cdef = 0.5;
323           if (cdef > 2.) cdef = 2.;
324           defedge = cdef * defedge * myDeflection;
325         }
326         else defedge = myDeflection;
327         mymapedge.Bind(E, defedge);
328         defined = Standard_True;
329       }
330       if ((!myRelative && Poly->Deflection() <= 1.1*defedge) ||
331           (myRelative && Poly->Deflection() <= 1.1*defedge)) 
332         found = Standard_True;
333       else {
334         myModified = Standard_True;
335         B.UpdateEdge(E, NullPoly, T, l);
336       }
337     }
338   } while (!Poly.IsNull());
339
340   if (!found) myMap.Add(E);
341 }
342
343
344 //=======================================================================
345 //function : Update(face)
346 //purpose  : If the face is not correctly triangulated, or if one of its
347 //           edges is to be discretisated correctly, the triangulation
348 //           of this face is built.
349 //=======================================================================
350 void  BRepMesh_IncrementalMesh::Update(const TopoDS_Face& F)
351 {
352   TopLoc_Location l;
353   Handle(Geom_Surface) SS = BRep_Tool::Surface(F, l);
354   if (SS.IsNull()) return;
355
356   //Standard_Integer i;
357   Standard_Boolean WillBeTriangulated = Standard_False;
358   Handle(Poly_Triangulation) T, TNull;
359   T = BRep_Tool::Triangulation(F, l);
360   Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
361
362   BRep_Builder B;
363   TopExp_Explorer ex;
364   
365   Standard_Real defedge, defface;
366   Standard_Integer nbEdge = 0;
367   if (myRelative) {
368     defface = 0.;
369     
370     for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
371       const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
372       nbEdge++;
373       if (mymapedge.IsBound(edge)) {
374         defedge = mymapedge(edge);
375       }
376       else {
377         Bnd_Box aBox;
378         BRepBndLib::Add(edge, aBox);
379         Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, dx, dy, dz;
380         aBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
381         dx = aXmax-aXmin;
382         dy = aYmax-aYmin;
383         dz = aZmax-aZmin;
384         defedge = dx;
385         if (defedge < dy) defedge = dy;
386         if (defedge < dz) defedge = dz;
387         // ajustement par rapport a la taille totale:
388         Standard_Real cdef = mydtotale/(2*defedge);
389         if (cdef < 0.5) cdef = 0.5;
390         if (cdef > 2.) cdef = 2.;
391         defedge = cdef * defedge * myDeflection;
392       }
393       defface = defface + defedge;
394     }
395     if (nbEdge != 0) defface = defface / nbEdge;
396     else             defface = myDeflection;
397   }
398   else
399     defface = myDeflection;
400
401   if (!T.IsNull()) {
402     if ((!myRelative && T->Deflection() <= 1.1*defface) ||
403         (myRelative && T->Deflection() <= 1.1*defface)) {
404       for (ex.Init(F, TopAbs_EDGE);
405            ex.More();
406            ex.Next()) {
407         const TopoDS_Shape& E = ex.Current();
408         Poly = BRep_Tool::PolygonOnTriangulation(TopoDS::Edge(E), T, l);
409         if (Poly.IsNull() || myMap.Contains(E)) {
410           WillBeTriangulated = Standard_True;
411           // cas un peu special. la triangulation est bonne, mais
412           // l'edge n'a pas de representation polygonalisee sur celle-ci.
413           break;
414         }
415       }
416     } 
417     else WillBeTriangulated = Standard_True;
418   }
419
420   if (WillBeTriangulated || T.IsNull()) {
421     myModified = Standard_True;
422     if (!T.IsNull()) {
423       for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
424         B.UpdateEdge(TopoDS::Edge(ex.Current()), NullPoly, T, l);
425         myMap.Remove(ex.Current());
426       }
427       B.UpdateFace(F, TNull);
428     }
429     myMesh->Add(F);
430     if (myMesh->CurrentFaceStatus() == BRepMesh_ReMesh) {
431 #ifdef DEB_MESH
432       cout << " face remaillee + finement que prevu."<< endl;
433 #endif
434
435       Standard_Integer index;
436       if( myancestors.Extent() < 1 )
437         TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,myancestors);
438
439       TopTools_MapOfShape MShape;
440       MShape.Add(F);
441
442       TopoDS_Iterator ex(F),ex2;
443       for (; ex.More(); ex.Next()) {
444         const TopoDS_Shape& aWire = ex.Value();
445         if (aWire.ShapeType() != TopAbs_WIRE)
446           continue;
447         TopoDS_Iterator exW(aWire);
448         for(; exW.More(); exW.Next()) {
449           const TopoDS_Edge& edge = TopoDS::Edge(exW.Value());
450           index = myancestors.FindIndex(edge);
451           if (index != 0) {
452             const TopTools_ListOfShape& L = myancestors.FindFromKey(edge);
453           
454             TopTools_ListIteratorOfListOfShape it(L);
455           
456             for (; it.More(); it.Next()) {
457               TopoDS_Face F2 = TopoDS::Face(it.Value());
458               if (!MShape.Contains(F2)) {
459                 MShape.Add(F2);
460                 T = BRep_Tool::Triangulation(F2, l);      
461                 if (!T.IsNull()) {
462 #ifdef DEB_MESH
463                   cout <<"triangulation a refaire" <<endl;
464 #endif
465                   for (ex2.Initialize(F2); ex2.More(); ex2.Next()) {
466                     const TopoDS_Shape& aWire2 = ex2.Value();
467                     if (aWire2.ShapeType() != TopAbs_WIRE)
468                       continue;
469                     TopoDS_Iterator exW2(aWire2);
470                     for(; exW2.More(); exW2.Next()) {
471                       TopoDS_Edge E2 = TopoDS::Edge(exW2.Value());
472                       B.UpdateEdge(E2, NullPoly, T, l);
473                     }
474                   }
475                   B.UpdateFace(F2, TNull);
476                   myMesh->Add(F2);
477                 }
478               }
479             }
480           }
481         }
482       }      
483     }
484   }
485 }