0024530: TKMesh - remove unused package IntPoly
[occt.git] / src / BRepMesh / BRepMesh_IncrementalMesh.cxx
... / ...
CommitLineData
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
9// under the terms of the GNU Lesser General Public 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
56namespace
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//=======================================================================
67BRepMesh_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//=======================================================================
81BRepMesh_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//=======================================================================
105BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh()
106{
107}
108
109//=======================================================================
110//function : SetParallel
111//purpose :
112//=======================================================================
113void BRepMesh_IncrementalMesh::SetParallel (const Standard_Boolean theInParallel)
114{
115 myInParallel = theInParallel;
116}
117
118//=======================================================================
119//function : IsParallel
120//purpose :
121//=======================================================================
122Standard_Boolean BRepMesh_IncrementalMesh::IsParallel() const
123{
124 return myInParallel;
125}
126
127//=======================================================================
128//function : Init
129//purpose :
130//=======================================================================
131void BRepMesh_IncrementalMesh::Init()
132{
133 myModified=Standard_False;
134 mymapedge.Clear();
135 myancestors.Clear();
136}
137
138//=======================================================================
139//function : SetRelative
140//purpose :
141//=======================================================================
142void BRepMesh_IncrementalMesh::SetRelative(const Standard_Boolean theFlag)
143{
144 myRelative=theFlag;
145}
146
147//=======================================================================
148//function : Relative
149//purpose :
150//=======================================================================
151Standard_Boolean BRepMesh_IncrementalMesh::Relative()const
152{
153 return myRelative;
154}
155
156//=======================================================================
157//function : IsModified
158//purpose :
159//=======================================================================
160Standard_Boolean BRepMesh_IncrementalMesh::IsModified() const
161{
162 return myModified;
163}
164
165//=======================================================================
166//function : Perform
167//purpose :
168//=======================================================================
169void 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//=======================================================================
199Standard_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//=======================================================================
208void 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//=======================================================================
333void 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//=======================================================================
378void 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//=======================================================================
501Standard_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//=======================================================================
519Standard_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//=======================================================================
533void BRepMesh_IncrementalMesh::SetParallelDefault (const Standard_Boolean theInParallel)
534{
535 IS_IN_PARALLEL = theInParallel;
536}
537
538//! Export Mesh Plugin entry function
539DISCRETPLUGIN(BRepMesh_IncrementalMesh)