0022564: BRepMesh_Classifier improvements
[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   myStatus(0)
57 {
58   mymapedge.Clear();
59   myancestors.Clear();
60 }
61
62 //=======================================================================
63 //function : BRepMesh_IncrementalMesh
64 //purpose  : 
65 //=======================================================================
66
67 BRepMesh_IncrementalMesh::
68 BRepMesh_IncrementalMesh(const TopoDS_Shape& S,
69                          const Standard_Real D,
70                          const Standard_Boolean Rel,
71                          const Standard_Real Ang) :
72                          myRelative(Rel),
73                          myModified(Standard_False),
74                          myStatus(0)
75 {
76   mymapedge.Clear();
77   myancestors.Clear();
78   myDeflection = D;
79   myAngle = Ang;
80   myShape = S;
81   
82   //
83   Perform(); 
84 }
85
86 //=======================================================================
87 //function : ~
88 //purpose  : 
89 //=======================================================================
90 BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh() 
91 {
92 }
93
94 //=======================================================================
95 //function : Init
96 //purpose  : 
97 //=======================================================================
98 void BRepMesh_IncrementalMesh::Init() 
99 {
100   myModified=Standard_False;
101   mymapedge.Clear();
102   myancestors.Clear();
103 }
104
105 //=======================================================================
106 //function : SetRelative
107 //purpose  : 
108 //=======================================================================
109 void BRepMesh_IncrementalMesh::SetRelative(const Standard_Boolean theFlag)
110 {
111   myRelative=theFlag;
112 }
113
114 //=======================================================================
115 //function : Relative
116 //purpose  : 
117 //=======================================================================
118 Standard_Boolean BRepMesh_IncrementalMesh::Relative()const
119 {
120   return myRelative;
121 }
122
123 //=======================================================================
124 //function : IsModified
125 //purpose  : 
126 //=======================================================================
127 Standard_Boolean BRepMesh_IncrementalMesh::IsModified() const
128 {
129   return myModified;
130 }
131
132 //=======================================================================
133 //function : Perform
134 //purpose  : 
135 //=======================================================================
136 void BRepMesh_IncrementalMesh::Perform()
137 {
138   Bnd_Box aBox;
139   //
140   SetDone();
141   //
142   Init(); 
143   //
144   BRepBndLib::Add(myShape, aBox);
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 //function : GetStatus
164 //purpose  : 
165 //=======================================================================
166 Standard_Integer BRepMesh_IncrementalMesh::GetStatusFlags() const
167 {
168   return myStatus;
169 }
170
171 //=======================================================================
172 //function : Update(shape)
173 //purpose  : Builds the incremental mesh of the shape
174 //=======================================================================
175 void BRepMesh_IncrementalMesh::Update(const TopoDS_Shape& S)
176                                   
177 {
178   myModified = Standard_False;
179   TopExp_Explorer ex;
180
181   //AGV 080407: Since version 6.2.0 there would be exception without this check
182   if (myBox.IsVoid())
183     return;
184   
185   BRepMesh_FastDiscret::BoxMaxDimension(myBox, mydtotale);
186   
187   for (ex.Init(S, TopAbs_EDGE); ex.More(); ex.Next()) {
188     if(BRep_Tool::IsGeometric(TopoDS::Edge(ex.Current()))) {
189       Update(TopoDS::Edge(ex.Current()));
190     }
191   }
192
193   // get list of faces
194   TopTools_ListOfShape LF;
195   BRepLib::ReverseSortFaces(S,LF);
196
197   // make array of faces suitable for processing (excluding faces without surface)
198   std::vector<TopoDS_Face> aFaces;
199   for (TopTools_ListIteratorOfListOfShape it(LF); it.More(); it.Next()) 
200   {
201     TopoDS_Face F = TopoDS::Face(it.Value());
202
203     TopLoc_Location L1;
204     const Handle(Geom_Surface)& Surf = BRep_Tool::Surface(F, L1);
205     if(Surf.IsNull())
206       continue;
207     
208     Update (F);
209     aFaces.push_back (F);
210   }
211
212   // mesh faces in parallel threads using TBB
213 #ifdef HAVE_TBB
214   if (Standard::IsReentrant())
215     tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *myMesh.operator->());
216   else
217 #endif
218   for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
219     myMesh->Process (*it);
220
221   // maillage des edges non contenues dans les faces :
222   Standard_Real f, l, defedge;
223   Standard_Integer i, nbNodes;
224   TopLoc_Location L;
225   Standard_Real cdef = 1.;
226   ex.Init(S ,TopAbs_EDGE, TopAbs_FACE);
227
228   while (ex.More()) {
229     const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
230
231     if(!BRep_Tool::IsGeometric(E)) {
232       ex.Next();
233       continue;
234     }
235
236     if (myRelative) 
237       defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection, 
238                                                              mydtotale, cdef);
239     else 
240       defedge = myDeflection;
241     
242     Handle(Poly_Polygon3D) P3D = BRep_Tool::Polygon3D(E, L);
243     Standard_Boolean maill = Standard_False;
244     if (P3D.IsNull()) {
245       maill = Standard_True;
246     }
247     else if (P3D->Deflection() > 1.1*defedge) {
248       maill = Standard_True;
249     }
250     if (maill) {
251       BRepAdaptor_Curve C(E);
252       f = C.FirstParameter();
253       l = C.LastParameter();
254       
255       GCPnts_TangentialDeflection TD(C, f, l, myAngle, defedge, 2);
256       nbNodes = TD.NbPoints();
257       
258       TColgp_Array1OfPnt Nodes(1, nbNodes);
259       TColStd_Array1OfReal UVNodes(1, nbNodes);
260       for ( i = 1; i <= nbNodes; i++) {
261         Nodes(i) = TD.Value(i);
262         UVNodes(i) = TD.Parameter(i);
263       }
264       
265       BRep_Builder B;
266       Handle(Poly_Polygon3D) P = new Poly_Polygon3D(Nodes, UVNodes);
267       P->Deflection(myDeflection);
268       B.UpdateEdge(E, P);
269     }
270
271     ex.Next();
272   }
273 }    
274 //=======================================================================
275 //function : Update(edge)
276 //purpose  : Locate a correct discretisation if it exists
277 //           Set no one otherwise
278 //=======================================================================
279 void BRepMesh_IncrementalMesh::Update(const TopoDS_Edge& E)
280 {
281   TopLoc_Location l;
282   Standard_Integer i = 1;
283   Handle(Poly_Triangulation) T, TNull;
284   Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
285   Standard_Boolean found = Standard_False;
286   Standard_Real defedge;
287   Standard_Real cdef = 1.;
288   BRep_Builder B;
289   Standard_Boolean defined = Standard_False;
290   
291   do {
292     BRep_Tool::PolygonOnTriangulation(E, Poly, T, l, i);
293     i++;
294     if (!T.IsNull() && !Poly.IsNull()) {
295       if (!defined) {
296         if (myRelative) 
297           defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection, 
298                                                                  mydtotale, cdef);
299         else 
300           defedge = myDeflection;
301         mymapedge.Bind(E, defedge);
302         defined = Standard_True;
303       }
304       if ((!myRelative && Poly->Deflection() <= 1.1*defedge) ||
305           (myRelative && Poly->Deflection() <= 1.1*defedge)) 
306         found = Standard_True;
307       else {
308         myModified = Standard_True;
309         B.UpdateEdge(E, NullPoly, T, l);
310       }
311     }
312   } while (!Poly.IsNull());
313
314   if (!found) myMap.Add(E);
315 }
316
317
318 //=======================================================================
319 //function : Update(face)
320 //purpose  : If the face is not correctly triangulated, or if one of its
321 //           edges is to be discretisated correctly, the triangulation
322 //           of this face is built.
323 //=======================================================================
324 void  BRepMesh_IncrementalMesh::Update(const TopoDS_Face& F)
325 {
326   TopLoc_Location l;
327   Handle(Geom_Surface) SS = BRep_Tool::Surface(F, l);
328   if (SS.IsNull()) return;
329
330   //Standard_Integer i;
331   Standard_Boolean WillBeTriangulated = Standard_False;
332   Handle(Poly_Triangulation) T, TNull;
333   T = BRep_Tool::Triangulation(F, l);
334   Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
335
336   BRep_Builder B;
337   TopExp_Explorer ex;
338   
339   Standard_Real defedge, defface, cdef = 1.;
340   Standard_Integer nbEdge = 0;
341   if (myRelative) {
342     defface = 0.;
343     
344     for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
345       const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
346       nbEdge++;
347       if (mymapedge.IsBound(edge)) {
348         defedge = mymapedge(edge);
349       }
350       else 
351         defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(edge, myDeflection, mydtotale, cdef);
352       defface = defface + defedge;
353     }
354     if (nbEdge != 0) defface = defface / nbEdge;
355     else             defface = myDeflection;
356   }
357   else
358     defface = myDeflection;
359
360   if (!T.IsNull()) {
361     if ((!myRelative && T->Deflection() <= 1.1*defface) ||
362         (myRelative && T->Deflection() <= 1.1*defface)) {
363       for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
364         const TopoDS_Shape& E = ex.Current();
365         Poly = BRep_Tool::PolygonOnTriangulation(TopoDS::Edge(E), T, l);
366         if (Poly.IsNull() || myMap.Contains(E)) {
367           WillBeTriangulated = Standard_True;
368           // cas un peu special. la triangulation est bonne, mais
369           // l'edge n'a pas de representation polygonalisee sur celle-ci.
370           break;
371         }
372       }
373     } 
374     else WillBeTriangulated = Standard_True;
375   }
376
377   if (WillBeTriangulated || T.IsNull()) {
378     myModified = Standard_True;
379     if (!T.IsNull()) {
380       for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
381         B.UpdateEdge(TopoDS::Edge(ex.Current()), NullPoly, T, l);
382         myMap.Remove(ex.Current());
383       }
384       B.UpdateFace(F, TNull);
385     }
386     myMesh->Add(F);
387     myStatus |= (Standard_Integer)(myMesh->CurrentFaceStatus());
388     if (myMesh->CurrentFaceStatus() == BRepMesh_ReMesh) {
389 #ifdef DEB_MESH
390       cout << " face remaillee + finement que prevu."<< endl;
391 #endif
392
393       Standard_Integer index;
394       if( myancestors.Extent() < 1 )
395         TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,myancestors);
396
397       TopTools_MapOfShape MShape;
398       MShape.Add(F);
399
400       TopoDS_Iterator ex(F),ex2;
401       for (; ex.More(); ex.Next()) {
402         const TopoDS_Shape& aWire = ex.Value();
403         if (aWire.ShapeType() != TopAbs_WIRE)
404           continue;
405         TopoDS_Iterator exW(aWire);
406         for(; exW.More(); exW.Next()) {
407           const TopoDS_Edge& edge = TopoDS::Edge(exW.Value());
408           index = myancestors.FindIndex(edge);
409           if (index != 0) {
410             const TopTools_ListOfShape& L = myancestors.FindFromKey(edge);
411           
412             TopTools_ListIteratorOfListOfShape it(L);
413           
414             for (; it.More(); it.Next()) {
415               TopoDS_Face F2 = TopoDS::Face(it.Value());
416               if (!MShape.Contains(F2)) {
417                 MShape.Add(F2);
418                 T = BRep_Tool::Triangulation(F2, l);      
419                 if (!T.IsNull()) {
420 #ifdef DEB_MESH
421                   cout <<"triangulation a refaire" <<endl;
422 #endif
423                   for (ex2.Initialize(F2); ex2.More(); ex2.Next()) {
424                     const TopoDS_Shape& aWire2 = ex2.Value();
425                     if (aWire2.ShapeType() != TopAbs_WIRE)
426                       continue;
427                     TopoDS_Iterator exW2(aWire2);
428                     for(; exW2.More(); exW2.Next()) {
429                       TopoDS_Edge E2 = TopoDS::Edge(exW2.Value());
430                       B.UpdateEdge(E2, NullPoly, T, l);
431                     }
432                   }
433                   B.UpdateFace(F2, TNull);
434                   myMesh->Add(F2);
435                 }
436               }
437             }
438           }
439         }
440       }      
441     }
442   }
443 }