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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <BRepMesh_IncrementalMesh.hxx>
19 #include <Precision.hxx>
20 #include <Standard_Mutex.hxx>
22 #include <BRepMesh_FaceChecker.hxx>
23 #include <BRepMesh_ShapeTool.hxx>
24 #include <BRepMesh_Edge.hxx>
25 #include <BRepMesh_PluginMacro.hxx>
27 #include <Bnd_Box.hxx>
28 #include <BRep_Builder.hxx>
29 #include <BRep_Tool.hxx>
30 #include <BRepTools.hxx>
31 #include <BRepLib.hxx>
32 #include <BRepBndLib.hxx>
33 #include <BRepAdaptor_Curve.hxx>
35 #include <Poly_Triangulation.hxx>
36 #include <Poly_Polygon3D.hxx>
37 #include <Poly_PolygonOnTriangulation.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Face.hxx>
42 #include <TopoDS_Shape.hxx>
45 #include <TopExp_Explorer.hxx>
47 #include <TopTools_ListIteratorOfListOfShape.hxx>
48 #include <TopTools_MutexForShapeProvider.hxx>
49 #include <TColgp_Array1OfPnt.hxx>
50 #include <TColStd_Array1OfReal.hxx>
51 #include <TopTools_HArray1OfShape.hxx>
53 #include <GCPnts_TangentialDeflection.hxx>
56 // paralleling using Intel TBB
57 #include <tbb/parallel_for_each.h>
62 //! Default flag to control parallelization for BRepMesh_IncrementalMesh
63 //! tool returned for Mesh Factory
64 static Standard_Boolean IS_IN_PARALLEL = Standard_False;
67 IMPLEMENT_STANDARD_HANDLE (BRepMesh_IncrementalMesh, BRepMesh_DiscretRoot)
68 IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IncrementalMesh, BRepMesh_DiscretRoot)
70 //=======================================================================
71 //function : Default constructor
73 //=======================================================================
74 BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh()
75 : myRelative (Standard_False),
76 myInParallel (Standard_False)
80 //=======================================================================
81 //function : Constructor
83 //=======================================================================
84 BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh(
85 const TopoDS_Shape& theShape,
86 const Standard_Real theDeflection,
87 const Standard_Real theAngle,
88 const Standard_Boolean theRelative,
89 const Standard_Boolean theInParallel)
90 : myRelative (theRelative),
91 myInParallel(theInParallel)
93 myDeflection = theDeflection;
100 //=======================================================================
101 //function : Destructor
103 //=======================================================================
104 BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh()
108 //=======================================================================
111 //=======================================================================
112 void BRepMesh_IncrementalMesh::init()
115 myModified = Standard_False;
117 myEdgeDeflection.Clear();
118 mySharedFaces.Clear();
123 if (!isCorrectPolyData())
124 BRepTools::Clean(myShape);
127 BRepBndLib::Add(myShape, aBox, Standard_False);
136 BRepMesh_ShapeTool::BoxMaxDimension(aBox, myMaxShapeSize);
137 TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, mySharedFaces);
139 myMesher = new BRepMesh_FastDiscret(myDeflection, myAngle, aBox,
140 Standard_True, Standard_True, myRelative, Standard_True, myInParallel);
143 //=======================================================================
144 //function : isCorrectPolyData
146 //=======================================================================
147 Standard_Boolean BRepMesh_IncrementalMesh::isCorrectPolyData()
151 BRepMesh_FaceChecker aFaceChecker(myInParallel);
156 // check faces in parallel threads using TBB
157 tbb::parallel_for_each(myFaces.begin(), myFaces.end(), aFaceChecker);
162 std::vector<TopoDS_Face>::iterator aFaceIt = myFaces.begin();
163 for (; aFaceIt != myFaces.end(); aFaceIt++)
164 aFaceChecker(*aFaceIt);
169 return aFaceChecker.IsValid();
172 //=======================================================================
173 //function : collectFaces
175 //=======================================================================
176 void BRepMesh_IncrementalMesh::collectFaces()
178 TopTools_ListOfShape aFaceList;
179 BRepLib::ReverseSortFaces(myShape, aFaceList);
180 TopTools_MapOfShape aFaceMap;
181 myFaces.reserve(aFaceList.Extent());
183 // make array of faces suitable for processing (excluding faces without surface)
184 TopLoc_Location aDummyLoc;
185 const TopLoc_Location aEmptyLoc;
186 TopTools_ListIteratorOfListOfShape aFaceIter(aFaceList);
187 for (; aFaceIter.More(); aFaceIter.Next())
189 TopoDS_Shape aFaceNoLoc = aFaceIter.Value();
190 aFaceNoLoc.Location(aEmptyLoc);
191 if (!aFaceMap.Add (aFaceNoLoc))
192 continue; // already processed
194 TopoDS_Face aFace = TopoDS::Face(aFaceIter.Value());
195 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aDummyLoc);
199 myFaces.push_back(aFace);
203 //=======================================================================
206 //=======================================================================
207 void BRepMesh_IncrementalMesh::Perform()
211 if (myMesher.IsNull())
217 //=======================================================================
218 //function : update()
220 //=======================================================================
221 void BRepMesh_IncrementalMesh::update()
224 TopExp_Explorer aExplorer(myShape, TopAbs_EDGE);
225 for (; aExplorer.More(); aExplorer.Next())
227 const TopoDS_Edge& aEdge = TopoDS::Edge(aExplorer.Current());
228 if(!BRep_Tool::IsGeometric(aEdge))
235 std::vector<TopoDS_Face>::iterator aFaceIt(myFaces.begin());
236 for (; aFaceIt != myFaces.end(); aFaceIt++)
243 myMesher->CreateMutexesForSubShapes(myShape, TopAbs_EDGE);
244 tbb::parallel_for_each(myFaces.begin(), myFaces.end(), *myMesher);
245 myMesher->RemoveAllMutexes();
250 for (aFaceIt = myFaces.begin(); aFaceIt != myFaces.end(); aFaceIt++)
251 myMesher->Process(*aFaceIt);
256 discretizeFreeEdges();
259 //=======================================================================
260 //function : discretizeFreeEdges
262 //=======================================================================
263 void BRepMesh_IncrementalMesh::discretizeFreeEdges()
265 TopExp_Explorer aExplorer(myShape ,TopAbs_EDGE, TopAbs_FACE);
266 for (; aExplorer.More(); aExplorer.Next())
268 const TopoDS_Edge& aEdge = TopoDS::Edge(aExplorer.Current());
269 if(!BRep_Tool::IsGeometric(aEdge))
272 TopLoc_Location aLoc;
273 Standard_Real aEdgeDeflection = edgeDeflection(aEdge);
274 Handle(Poly_Polygon3D) aPoly3D = BRep_Tool::Polygon3D(aEdge, aLoc);
275 if (!aPoly3D.IsNull() && aPoly3D->Deflection() < 1.1 * aEdgeDeflection)
278 BRepAdaptor_Curve aCurve(aEdge);
279 GCPnts_TangentialDeflection aDiscret(aCurve, aCurve.FirstParameter(),
280 aCurve.LastParameter(), myAngle, aEdgeDeflection, 2);
282 Standard_Integer aNodesNb = aDiscret.NbPoints();
283 TColgp_Array1OfPnt aNodes (1, aNodesNb);
284 TColStd_Array1OfReal aUVNodes(1, aNodesNb);
285 for (Standard_Integer i = 1; i <= aNodesNb; ++i)
287 aNodes (i) = aDiscret.Value(i);
288 aUVNodes(i) = aDiscret.Parameter(i);
291 aPoly3D = new Poly_Polygon3D(aNodes, aUVNodes);
292 aPoly3D->Deflection(myDeflection);
294 BRep_Builder aBuilder;
295 aBuilder.UpdateEdge(aEdge, aPoly3D);
299 //=======================================================================
300 //function : edgeDeflection
302 //=======================================================================
303 Standard_Real BRepMesh_IncrementalMesh::edgeDeflection(
304 const TopoDS_Edge& theEdge)
306 if (myEdgeDeflection.IsBound(theEdge))
307 return myEdgeDeflection(theEdge);
309 Standard_Real aEdgeDeflection;
312 Standard_Real aScale;
313 aEdgeDeflection = BRepMesh_ShapeTool::RelativeEdgeDeflection(theEdge,
314 myDeflection, myMaxShapeSize, aScale);
317 aEdgeDeflection = myDeflection;
319 myEdgeDeflection.Bind(theEdge, aEdgeDeflection);
320 return aEdgeDeflection;
323 //=======================================================================
324 //function : faceDeflection
326 //=======================================================================
327 Standard_Real BRepMesh_IncrementalMesh::faceDeflection(
328 const TopoDS_Face& theFace)
333 Standard_Integer aEdgesNb = 0;
334 Standard_Real aFaceDeflection = 0.;
336 TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
337 for (; aEdgeIt.More(); aEdgeIt.Next(), ++aEdgesNb)
339 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
340 aFaceDeflection += edgeDeflection(aEdge);
343 return (aEdgesNb == 0) ? myDeflection : (aFaceDeflection / aEdgesNb);
346 //=======================================================================
347 //function : update(edge)
349 //=======================================================================
350 void BRepMesh_IncrementalMesh::update(const TopoDS_Edge& theEdge)
352 Standard_Integer aPolyIndex = 1;
353 Standard_Real aEdgeDeflection = edgeDeflection(theEdge);
354 Handle(Poly_PolygonOnTriangulation) aPolygon;
357 TopLoc_Location aLoc;
358 Handle(Poly_Triangulation) aTriangulation;
359 BRep_Tool::PolygonOnTriangulation(theEdge, aPolygon,
360 aTriangulation, aLoc, aPolyIndex++);
362 if (!aTriangulation.IsNull() && !aPolygon.IsNull())
364 if (aPolygon->Deflection() < 1.1 * aEdgeDeflection)
367 myModified = Standard_True;
368 BRepMesh_ShapeTool::NullifyEdge(theEdge, aTriangulation, aLoc);
371 if (!myEmptyEdges.IsBound(theEdge))
372 myEmptyEdges.Bind(theEdge, BRepMeshCol::MapOfTriangulation());
374 myEmptyEdges(theEdge).Add(aTriangulation);
376 while (!aPolygon.IsNull());
379 //=======================================================================
380 //function : isToBeMeshed
382 //=======================================================================
383 Standard_Boolean BRepMesh_IncrementalMesh::toBeMeshed(
384 const TopoDS_Face& theFace,
385 const Standard_Boolean isWithCheck)
387 TopLoc_Location aLoc;
388 Handle(Poly_Triangulation) aTriangulation =
389 BRep_Tool::Triangulation(theFace, aLoc);
391 if (aTriangulation.IsNull())
392 return Standard_True;
396 Standard_Real aFaceDeflection = faceDeflection(theFace);
397 if (aTriangulation->Deflection() < 1.1 * aFaceDeflection)
399 Standard_Boolean isEdgesConsistent = Standard_True;
400 TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
401 for (; aEdgeIt.More() && isEdgesConsistent; aEdgeIt.Next())
403 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
404 if (!myEmptyEdges.IsBound(aEdge))
407 isEdgesConsistent &= myEmptyEdges(aEdge).Contains(aTriangulation);
410 if (isEdgesConsistent)
411 return Standard_False;
416 TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
417 for (; aEdgeIt.More(); aEdgeIt.Next())
419 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
420 BRepMesh_ShapeTool::NullifyEdge(aEdge, aTriangulation, aLoc);
423 BRepMesh_ShapeTool::NullifyFace(theFace);
424 return Standard_True;
427 //=======================================================================
428 //function : update(face)
430 //=======================================================================
431 void BRepMesh_IncrementalMesh::update(const TopoDS_Face& theFace)
433 if (!toBeMeshed(theFace, Standard_True))
436 myModified = Standard_True;
437 myMesher->Add(theFace, mySharedFaces);
439 BRepMesh_Status aStatus = myMesher->CurrentFaceStatus();
440 myStatus |= (Standard_Integer)aStatus;
441 if (aStatus != BRepMesh_ReMesh)
444 BRepMeshCol::MapOfShape aUsedFaces;
445 aUsedFaces.Add(theFace);
447 TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
448 for (; aEdgeIt.More(); aEdgeIt.Next())
450 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
451 if (mySharedFaces.FindIndex(aEdge) == 0)
454 const TopTools_ListOfShape& aSharedFaces = mySharedFaces.FindFromKey(aEdge);
455 TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces);
456 for (; aSharedFaceIt.More(); aSharedFaceIt.Next())
458 const TopoDS_Face& aFace = TopoDS::Face(aSharedFaceIt.Value());
459 if (aUsedFaces.Contains(aFace))
462 aUsedFaces.Add(aFace);
463 toBeMeshed(aFace, Standard_False);
465 myMesher->Add(aFace, mySharedFaces);
466 myStatus |= (Standard_Integer)myMesher->CurrentFaceStatus();
471 //=======================================================================
474 //=======================================================================
475 Standard_Integer BRepMesh_IncrementalMesh::Discret(
476 const TopoDS_Shape& theShape,
477 const Standard_Real theDeflection,
478 const Standard_Real theAngle,
479 BRepMesh_PDiscretRoot& theAlgo)
481 BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh();
482 anAlgo->SetDeflection(theDeflection);
483 anAlgo->SetAngle (theAngle);
484 anAlgo->SetShape (theShape);
485 anAlgo->SetParallel (IS_IN_PARALLEL);
487 return 0; // no error
490 //=======================================================================
491 //function : IsParallelDefault
493 //=======================================================================
494 Standard_Boolean BRepMesh_IncrementalMesh::IsParallelDefault()
497 return IS_IN_PARALLEL;
499 // no alternative parallelization yet - flag has no meaning
500 return Standard_False;
504 //=======================================================================
507 //=======================================================================
508 void BRepMesh_IncrementalMesh::SetParallelDefault(
509 const Standard_Boolean theInParallel)
511 IS_IN_PARALLEL = theInParallel;
514 //! Export Mesh Plugin entry function
515 DISCRETPLUGIN(BRepMesh_IncrementalMesh)