0024219: Strange if-statement in BrepMesh_IncrementalMesh
[occt.git] / src / BRepMesh / BRepMesh_IncrementalMesh.cxx
1 // Created on: 1995-06-20
2 // Created by: Stagiaire Alain JOURDAIN
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <BRepMesh_IncrementalMesh.ixx>
18
19 #include <BRepMesh.hxx>
20 #include <BRepMesh_Edge.hxx>
21 #include <BRepMesh_Triangle.hxx>
22 #include <BRepMesh_FastDiscretFace.hxx>
23 #include <BRepMesh_PluginMacro.hxx>
24
25 #include <Bnd_Box.hxx>
26 #include <BRep_Builder.hxx>
27 #include <BRep_Tool.hxx>
28 #include <BRepLib.hxx>
29 #include <BRepBndLib.hxx>
30 #include <BRepAdaptor_Curve.hxx>
31 #include <GCPnts_TangentialDeflection.hxx>
32 #include <Precision.hxx>
33 #include <TopExp.hxx>
34 #include <TopExp_Explorer.hxx>
35 #include <TopAbs.hxx>
36 #include <TopTools_ListIteratorOfListOfShape.hxx>
37 #include <TopTools_MutexForShapeProvider.hxx>
38 #include <TColgp_Array1OfPnt.hxx>
39 #include <TColStd_Array1OfReal.hxx>
40 #include <TopoDS_Shape.hxx>
41 #include <TopoDS_Face.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS.hxx>
44 #include <TopTools_HArray1OfShape.hxx>
45 #include <Poly_Triangulation.hxx>
46 #include <Poly_Polygon3D.hxx>
47 #include <Poly_PolygonOnTriangulation.hxx>
48
49 #include <vector>
50
51 #ifdef HAVE_TBB
52   // paralleling using Intel TBB
53   #include <tbb/parallel_for_each.h>
54 #endif
55
56 namespace
57 {
58   //! Default flag to control parallelization for BRepMesh_IncrementalMesh
59   //! tool returned for Mesh Factory
60   static Standard_Boolean IS_IN_PARALLEL = Standard_False;
61 };
62
63 //=======================================================================
64 //function : BRepMesh_IncrementalMesh
65 //purpose  : 
66 //=======================================================================
67 BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh() 
68 : myRelative (Standard_False),
69   myInParallel (Standard_False),
70   myModified (Standard_False),
71   myStatus (0)
72 {
73   mymapedge.Clear();
74   myancestors.Clear();
75 }
76
77 //=======================================================================
78 //function : BRepMesh_IncrementalMesh
79 //purpose  : 
80 //=======================================================================
81 BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh (const TopoDS_Shape& theShape,
82                                                     const Standard_Real theDeflection,
83                                                     const Standard_Boolean theRelative,
84                                                     const Standard_Real theAngle,
85                                                                                                         const Standard_Boolean theInParallel)
86 : myRelative (theRelative),
87   myInParallel (theInParallel),
88   myModified (Standard_False),
89   myStatus (0)
90 {
91   mymapedge.Clear();
92   myancestors.Clear();
93   myDeflection = theDeflection;
94   myAngle = theAngle;
95   myShape = theShape;
96
97   //
98   Perform();
99 }
100
101 //=======================================================================
102 //function : ~
103 //purpose  : 
104 //=======================================================================
105 BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh() 
106 {
107 }
108
109 //=======================================================================
110 //function : SetParallel
111 //purpose  :
112 //=======================================================================
113 void BRepMesh_IncrementalMesh::SetParallel (const Standard_Boolean theInParallel)
114 {
115   myInParallel = theInParallel;
116 }
117
118 //=======================================================================
119 //function : IsParallel
120 //purpose  :
121 //=======================================================================
122 Standard_Boolean BRepMesh_IncrementalMesh::IsParallel() const
123 {
124   return myInParallel;
125 }
126
127 //=======================================================================
128 //function : Init
129 //purpose  : 
130 //=======================================================================
131 void BRepMesh_IncrementalMesh::Init() 
132 {
133   myModified=Standard_False;
134   mymapedge.Clear();
135   myancestors.Clear();
136 }
137
138 //=======================================================================
139 //function : SetRelative
140 //purpose  : 
141 //=======================================================================
142 void BRepMesh_IncrementalMesh::SetRelative(const Standard_Boolean theFlag)
143 {
144   myRelative=theFlag;
145 }
146
147 //=======================================================================
148 //function : Relative
149 //purpose  : 
150 //=======================================================================
151 Standard_Boolean BRepMesh_IncrementalMesh::Relative()const
152 {
153   return myRelative;
154 }
155
156 //=======================================================================
157 //function : IsModified
158 //purpose  : 
159 //=======================================================================
160 Standard_Boolean BRepMesh_IncrementalMesh::IsModified() const
161 {
162   return myModified;
163 }
164
165 //=======================================================================
166 //function : Perform
167 //purpose  : 
168 //=======================================================================
169 void BRepMesh_IncrementalMesh::Perform()
170 {
171   Bnd_Box aBox;
172   //
173   SetDone();
174   //
175   Init(); 
176   //
177   BRepBndLib::Add(myShape, aBox);
178   myBox = aBox;
179   //
180   if (!myMesh.IsNull()) {
181     myMesh.Nullify();
182   }
183   //
184   myMesh = new BRepMesh_FastDiscret(myDeflection,
185                                     myAngle,
186                                     aBox,
187                                     Standard_True,
188                                     Standard_True,
189                                     myRelative,
190                                     Standard_True);
191   //
192   Update(myShape);
193 }
194
195 //=======================================================================
196 //function : GetStatus
197 //purpose  : 
198 //=======================================================================
199 Standard_Integer BRepMesh_IncrementalMesh::GetStatusFlags() const
200 {
201   return myStatus;
202 }
203
204 //=======================================================================
205 //function : Update(shape)
206 //purpose  : Builds the incremental mesh of the shape
207 //=======================================================================
208 void BRepMesh_IncrementalMesh::Update(const TopoDS_Shape& S)
209 {
210   myModified = Standard_False;
211   TopExp_Explorer ex;
212
213   //AGV 080407: Since version 6.2.0 there would be exception without this check
214   if (myBox.IsVoid())
215     return;
216
217   TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, myancestors);
218   
219   BRepMesh_FastDiscret::BoxMaxDimension(myBox, mydtotale);
220   
221   for (ex.Init(S, TopAbs_EDGE); ex.More(); ex.Next()) {
222     if(BRep_Tool::IsGeometric(TopoDS::Edge(ex.Current()))) {
223       Update(TopoDS::Edge(ex.Current()));
224     }
225   }
226
227   // get list of faces
228   std::vector<TopoDS_Face> aFaces;
229   {
230     TopTools_ListOfShape aFaceList;
231     BRepLib::ReverseSortFaces (S, aFaceList);
232     TopTools_MapOfShape aFaceMap;
233     aFaces.reserve (aFaceList.Extent());
234
235     // make array of faces suitable for processing (excluding faces without surface)
236     TopLoc_Location aDummyLoc;
237     const TopLoc_Location anEmptyLoc;
238     for (TopTools_ListIteratorOfListOfShape aFaceIter (aFaceList); aFaceIter.More(); aFaceIter.Next())
239     {
240       TopoDS_Shape aFaceNoLoc = aFaceIter.Value();
241       aFaceNoLoc.Location (anEmptyLoc);
242       if (!aFaceMap.Add (aFaceNoLoc))
243         continue; // already processed
244
245       TopoDS_Face aFace = TopoDS::Face (aFaceIter.Value());
246       const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (aFace, aDummyLoc);
247       if (aSurf.IsNull())
248         continue;
249
250       Update (aFace);
251       aFaces.push_back (aFace);
252     }
253   }
254
255   if (myInParallel)
256   {
257   #ifdef HAVE_TBB
258     myMesh->CreateMutexesForSubShapes(S, TopAbs_EDGE);
259     // mesh faces in parallel threads using TBB
260     tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *myMesh.operator->());
261   #else
262     // alternative parallelization not yet available
263     for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
264       myMesh->Process (*it);
265   #endif
266     myMesh->RemoveAllMutexes();
267   }
268   else
269   {
270     for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
271       myMesh->Process (*it);
272   }
273
274   // maillage des edges non contenues dans les faces :
275   Standard_Real f, l, defedge;
276   Standard_Integer i, nbNodes;
277   TopLoc_Location L;
278   Standard_Real cdef = 1.;
279   ex.Init(S ,TopAbs_EDGE, TopAbs_FACE);
280
281   while (ex.More()) {
282     const TopoDS_Edge& E = TopoDS::Edge(ex.Current());
283
284     if(!BRep_Tool::IsGeometric(E)) {
285       ex.Next();
286       continue;
287     }
288
289     if (myRelative) 
290       defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection, 
291                                                              mydtotale, cdef);
292     else 
293       defedge = myDeflection;
294     
295     Handle(Poly_Polygon3D) P3D = BRep_Tool::Polygon3D(E, L);
296     Standard_Boolean maill = Standard_False;
297     if (P3D.IsNull()) {
298       maill = Standard_True;
299     }
300     else if (P3D->Deflection() > 1.1*defedge) {
301       maill = Standard_True;
302     }
303     if (maill) {
304       BRepAdaptor_Curve C(E);
305       f = C.FirstParameter();
306       l = C.LastParameter();
307       
308       GCPnts_TangentialDeflection TD(C, f, l, myAngle, defedge, 2);
309       nbNodes = TD.NbPoints();
310       
311       TColgp_Array1OfPnt Nodes(1, nbNodes);
312       TColStd_Array1OfReal UVNodes(1, nbNodes);
313       for ( i = 1; i <= nbNodes; i++) {
314         Nodes(i) = TD.Value(i);
315         UVNodes(i) = TD.Parameter(i);
316       }
317       
318       BRep_Builder B;
319       Handle(Poly_Polygon3D) P = new Poly_Polygon3D(Nodes, UVNodes);
320       P->Deflection(myDeflection);
321       B.UpdateEdge(E, P);
322     }
323
324     ex.Next();
325   }
326 }
327
328 //=======================================================================
329 //function : Update(edge)
330 //purpose  : Locate a correct discretisation if it exists
331 //           Set no one otherwise
332 //=======================================================================
333 void BRepMesh_IncrementalMesh::Update(const TopoDS_Edge& E)
334 {
335   TopLoc_Location l;
336   Standard_Integer i = 1;
337   Handle(Poly_Triangulation) T, TNull;
338   Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
339   Standard_Boolean found = Standard_False;
340   Standard_Real defedge = Precision::Confusion();
341   Standard_Real cdef = 1.;
342   BRep_Builder B;
343   Standard_Boolean defined = Standard_False;
344   
345   do {
346     BRep_Tool::PolygonOnTriangulation(E, Poly, T, l, i);
347     i++;
348     if (!T.IsNull() && !Poly.IsNull())
349     {
350       if (!defined)
351       {
352         if (myRelative) 
353           defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection, 
354                                                                  mydtotale, cdef);
355         else
356           defedge = myDeflection;
357
358         mymapedge.Bind(E, defedge);
359         defined = Standard_True;
360       }
361       if (Poly->Deflection() <= 1.1 * defedge)
362       {
363         found = Standard_True;
364       }
365       else
366       {
367         myModified = Standard_True;
368         B.UpdateEdge(E, NullPoly, T, l);
369       }
370     }
371   } while (!Poly.IsNull());
372
373   if (!found) myMap.Add(E);
374 }
375
376
377 //=======================================================================
378 //function : Update(face)
379 //purpose  : If the face is not correctly triangulated, or if one of its
380 //           edges is to be discretisated correctly, the triangulation
381 //           of this face is built.
382 //=======================================================================
383 void  BRepMesh_IncrementalMesh::Update(const TopoDS_Face& F)
384 {
385   TopLoc_Location l;
386   Handle(Geom_Surface) SS = BRep_Tool::Surface(F, l);
387   if (SS.IsNull()) return;
388
389   //Standard_Integer i;
390   Standard_Boolean WillBeTriangulated = Standard_False;
391   Handle(Poly_Triangulation) T, TNull;
392   T = BRep_Tool::Triangulation(F, l);
393   Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
394
395   BRep_Builder B;
396   TopExp_Explorer ex;
397   
398   Standard_Real defedge, defface, cdef = 1.;
399   Standard_Integer nbEdge = 0;
400   if (myRelative) {
401     defface = 0.;
402     
403     for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
404       const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
405       nbEdge++;
406       if (mymapedge.IsBound(edge)) {
407         defedge = mymapedge(edge);
408       }
409       else 
410         defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(edge, myDeflection, mydtotale, cdef);
411       defface = defface + defedge;
412     }
413     if (nbEdge != 0) defface = defface / nbEdge;
414     else             defface = myDeflection;
415   }
416   else
417     defface = myDeflection;
418
419   if (!T.IsNull())
420   {
421     if (T->Deflection() <= 1.1 * defface)
422     {
423       for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next())
424       {
425         const TopoDS_Shape& anEdge = ex.Current();
426         Poly = BRep_Tool::PolygonOnTriangulation(TopoDS::Edge(anEdge), T, l);
427
428         if (Poly.IsNull() || myMap.Contains(anEdge))
429         {
430           // Triangulation is built but edge hasn't representation on it.
431           WillBeTriangulated = Standard_True;
432           break;
433         }
434       }
435     }
436     else
437     {
438       WillBeTriangulated = Standard_True;
439     }
440   }
441
442   if (WillBeTriangulated || T.IsNull()) {
443     myModified = Standard_True;
444     if (!T.IsNull()) {
445       for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
446         B.UpdateEdge(TopoDS::Edge(ex.Current()), NullPoly, T, l);
447         myMap.Remove(ex.Current());
448       }
449       B.UpdateFace(F, TNull);
450     }
451     myMesh->Add(F, myancestors);
452     myStatus |= (Standard_Integer)(myMesh->CurrentFaceStatus());
453     if (myMesh->CurrentFaceStatus() == BRepMesh_ReMesh) {
454 #ifdef DEB_MESH
455       cout << " face remaillee + finement que prevu."<< endl;
456 #endif
457
458       Standard_Integer index;
459       
460       TopTools_MapOfShape MShape;
461       MShape.Add(F);
462
463       TopoDS_Iterator ex(F),ex2;
464       for (; ex.More(); ex.Next()) {
465         const TopoDS_Shape& aWire = ex.Value();
466         if (aWire.ShapeType() != TopAbs_WIRE)
467           continue;
468         TopoDS_Iterator exW(aWire);
469         for(; exW.More(); exW.Next()) {
470           const TopoDS_Edge& edge = TopoDS::Edge(exW.Value());
471           index = myancestors.FindIndex(edge);
472           if (index != 0) {
473             const TopTools_ListOfShape& L = myancestors.FindFromKey(edge);
474
475             TopTools_ListIteratorOfListOfShape it(L);
476
477             for (; it.More(); it.Next()) {
478               TopoDS_Face F2 = TopoDS::Face(it.Value());
479               if (!MShape.Contains(F2)) {
480                 MShape.Add(F2);
481                 T = BRep_Tool::Triangulation(F2, l);      
482                 if (!T.IsNull()) {
483 #ifdef DEB_MESH
484                   cout <<"triangulation a refaire" <<endl;
485 #endif
486                   for (ex2.Initialize(F2); ex2.More(); ex2.Next()) {
487                     const TopoDS_Shape& aWire2 = ex2.Value();
488                     if (aWire2.ShapeType() != TopAbs_WIRE)
489                       continue;
490                     TopoDS_Iterator exW2(aWire2);
491                     for(; exW2.More(); exW2.Next()) {
492                       TopoDS_Edge E2 = TopoDS::Edge(exW2.Value());
493                       B.UpdateEdge(E2, NullPoly, T, l);
494                     }
495                   }
496                   B.UpdateFace(F2, TNull);
497                   myMesh->Add(F2, myancestors);
498                 }
499               }
500             }
501           }
502         }
503       }
504     }
505   }
506 }
507
508
509 //=======================================================================
510 //function : Discret
511 //purpose  :
512 //=======================================================================
513 Standard_Integer BRepMesh_IncrementalMesh::Discret (const TopoDS_Shape&    theShape,
514                                                     const Standard_Real    theDeflection,
515                                                     const Standard_Real    theAngle,
516                                                     BRepMesh_PDiscretRoot& theAlgo)
517 {
518   BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh();
519   anAlgo->SetDeflection (theDeflection);
520   anAlgo->SetAngle (theAngle);
521   anAlgo->SetShape (theShape);
522   anAlgo->SetParallel (IS_IN_PARALLEL);
523   theAlgo = anAlgo;
524   return 0; // no error
525 }
526
527 //=======================================================================
528 //function : IsParallelDefault
529 //purpose  :
530 //=======================================================================
531 Standard_Boolean BRepMesh_IncrementalMesh::IsParallelDefault()
532 {
533 #ifdef HAVE_TBB
534   return IS_IN_PARALLEL;
535 #else
536   // no alternative parallelization yet - flag has no meaning
537   return Standard_False;
538 #endif
539 }
540
541 //=======================================================================
542 //function : Discret
543 //purpose  :
544 //=======================================================================
545 void BRepMesh_IncrementalMesh::SetParallelDefault (const Standard_Boolean theInParallel)
546 {
547   IS_IN_PARALLEL = theInParallel;
548 }
549
550 //! Export Mesh Plugin entry function
551 DISCRETPLUGIN(BRepMesh_IncrementalMesh)