6c8582b37e3dfa15a9d86293bd4cd049752e8bb7
[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       if (!defined) {
350         if (myRelative) 
351           defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(E, myDeflection, 
352                                                                  mydtotale, cdef);
353         else 
354           defedge = myDeflection;
355         mymapedge.Bind(E, defedge);
356         defined = Standard_True;
357       }
358       if ((!myRelative && Poly->Deflection() <= 1.1*defedge) ||
359           (myRelative && Poly->Deflection() <= 1.1*defedge)) 
360         found = Standard_True;
361       else {
362         myModified = Standard_True;
363         B.UpdateEdge(E, NullPoly, T, l);
364       }
365     }
366   } while (!Poly.IsNull());
367
368   if (!found) myMap.Add(E);
369 }
370
371
372 //=======================================================================
373 //function : Update(face)
374 //purpose  : If the face is not correctly triangulated, or if one of its
375 //           edges is to be discretisated correctly, the triangulation
376 //           of this face is built.
377 //=======================================================================
378 void  BRepMesh_IncrementalMesh::Update(const TopoDS_Face& F)
379 {
380   TopLoc_Location l;
381   Handle(Geom_Surface) SS = BRep_Tool::Surface(F, l);
382   if (SS.IsNull()) return;
383
384   //Standard_Integer i;
385   Standard_Boolean WillBeTriangulated = Standard_False;
386   Handle(Poly_Triangulation) T, TNull;
387   T = BRep_Tool::Triangulation(F, l);
388   Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
389
390   BRep_Builder B;
391   TopExp_Explorer ex;
392   
393   Standard_Real defedge, defface, cdef = 1.;
394   Standard_Integer nbEdge = 0;
395   if (myRelative) {
396     defface = 0.;
397     
398     for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
399       const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
400       nbEdge++;
401       if (mymapedge.IsBound(edge)) {
402         defedge = mymapedge(edge);
403       }
404       else 
405         defedge = BRepMesh_FastDiscret::RelativeEdgeDeflection(edge, myDeflection, mydtotale, cdef);
406       defface = defface + defedge;
407     }
408     if (nbEdge != 0) defface = defface / nbEdge;
409     else             defface = myDeflection;
410   }
411   else
412     defface = myDeflection;
413
414   if (!T.IsNull()) {
415     if ((!myRelative && T->Deflection() <= 1.1*defface) ||
416         (myRelative && T->Deflection() <= 1.1*defface)) {
417       for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
418         const TopoDS_Shape& E = ex.Current();
419         Poly = BRep_Tool::PolygonOnTriangulation(TopoDS::Edge(E), T, l);
420         if (Poly.IsNull() || myMap.Contains(E)) {
421           WillBeTriangulated = Standard_True;
422           // cas un peu special. la triangulation est bonne, mais
423           // l'edge n'a pas de representation polygonalisee sur celle-ci.
424           break;
425         }
426       }
427     } 
428     else WillBeTriangulated = Standard_True;
429   }
430
431   if (WillBeTriangulated || T.IsNull()) {
432     myModified = Standard_True;
433     if (!T.IsNull()) {
434       for (ex.Init(F, TopAbs_EDGE); ex.More(); ex.Next()) {
435         B.UpdateEdge(TopoDS::Edge(ex.Current()), NullPoly, T, l);
436         myMap.Remove(ex.Current());
437       }
438       B.UpdateFace(F, TNull);
439     }
440     myMesh->Add(F, myancestors);
441     myStatus |= (Standard_Integer)(myMesh->CurrentFaceStatus());
442     if (myMesh->CurrentFaceStatus() == BRepMesh_ReMesh) {
443 #ifdef DEB_MESH
444       cout << " face remaillee + finement que prevu."<< endl;
445 #endif
446
447       Standard_Integer index;
448       
449       TopTools_MapOfShape MShape;
450       MShape.Add(F);
451
452       TopoDS_Iterator ex(F),ex2;
453       for (; ex.More(); ex.Next()) {
454         const TopoDS_Shape& aWire = ex.Value();
455         if (aWire.ShapeType() != TopAbs_WIRE)
456           continue;
457         TopoDS_Iterator exW(aWire);
458         for(; exW.More(); exW.Next()) {
459           const TopoDS_Edge& edge = TopoDS::Edge(exW.Value());
460           index = myancestors.FindIndex(edge);
461           if (index != 0) {
462             const TopTools_ListOfShape& L = myancestors.FindFromKey(edge);
463           
464             TopTools_ListIteratorOfListOfShape it(L);
465           
466             for (; it.More(); it.Next()) {
467               TopoDS_Face F2 = TopoDS::Face(it.Value());
468               if (!MShape.Contains(F2)) {
469                 MShape.Add(F2);
470                 T = BRep_Tool::Triangulation(F2, l);      
471                 if (!T.IsNull()) {
472 #ifdef DEB_MESH
473                   cout <<"triangulation a refaire" <<endl;
474 #endif
475                   for (ex2.Initialize(F2); ex2.More(); ex2.Next()) {
476                     const TopoDS_Shape& aWire2 = ex2.Value();
477                     if (aWire2.ShapeType() != TopAbs_WIRE)
478                       continue;
479                     TopoDS_Iterator exW2(aWire2);
480                     for(; exW2.More(); exW2.Next()) {
481                       TopoDS_Edge E2 = TopoDS::Edge(exW2.Value());
482                       B.UpdateEdge(E2, NullPoly, T, l);
483                     }
484                   }
485                   B.UpdateFace(F2, TNull);
486                   myMesh->Add(F2, myancestors);
487                 }
488               }
489             }
490           }
491         }
492       }      
493     }
494   }
495 }
496
497 //=======================================================================
498 //function : Discret
499 //purpose  :
500 //=======================================================================
501 Standard_Integer BRepMesh_IncrementalMesh::Discret (const TopoDS_Shape&    theShape,
502                                                     const Standard_Real    theDeflection,
503                                                     const Standard_Real    theAngle,
504                                                     BRepMesh_PDiscretRoot& theAlgo)
505 {
506   BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh();
507   anAlgo->SetDeflection (theDeflection);
508   anAlgo->SetAngle (theAngle);
509   anAlgo->SetShape (theShape);
510   anAlgo->SetParallel (IS_IN_PARALLEL);
511   theAlgo = anAlgo;
512   return 0; // no error
513 }
514
515 //=======================================================================
516 //function : IsParallelDefault
517 //purpose  :
518 //=======================================================================
519 Standard_Boolean BRepMesh_IncrementalMesh::IsParallelDefault()
520 {
521 #ifdef HAVE_TBB
522   return IS_IN_PARALLEL;
523 #else
524   // no alternative parallelization yet - flag has no meaning
525   return Standard_False;
526 #endif
527 }
528
529 //=======================================================================
530 //function : Discret
531 //purpose  :
532 //=======================================================================
533 void BRepMesh_IncrementalMesh::SetParallelDefault (const Standard_Boolean theInParallel)
534 {
535   IS_IN_PARALLEL = theInParallel;
536 }
537
538 //! Export Mesh Plugin entry function
539 DISCRETPLUGIN(BRepMesh_IncrementalMesh)