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