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