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 <OSD_Parallel.hxx>
20 #include <Precision.hxx>
21 #include <Standard_ErrorHandler.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 <TColgp_Array1OfPnt.hxx>
49 #include <TColgp_Array1OfPnt2d.hxx>
50 #include <TColStd_Array1OfReal.hxx>
51 #include <TColStd_MapOfTransient.hxx>
52 #include <TopTools_HArray1OfShape.hxx>
53 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
55 #include <GCPnts_TangentialDeflection.hxx>
57 IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot)
61 //! Default flag to control parallelization for BRepMesh_IncrementalMesh
62 //! tool returned for Mesh Factory
63 static Standard_Boolean IS_IN_PARALLEL = Standard_False;
67 //=======================================================================
68 //function : Default constructor
70 //=======================================================================
71 BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh()
73 myModified(Standard_False),
78 //=======================================================================
79 //function : Constructor
81 //=======================================================================
82 BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh( const TopoDS_Shape& theShape,
83 const Standard_Real theLinDeflection,
84 const Standard_Boolean isRelative,
85 const Standard_Real theAngDeflection,
86 const Standard_Boolean isInParallel,
87 const Standard_Boolean adaptiveMin)
89 myModified(Standard_False),
92 myParameters.Deflection = theLinDeflection;
93 myParameters.Relative = isRelative;
94 myParameters.Angle = theAngDeflection;
95 myParameters.InParallel = isInParallel;
96 myParameters.AdaptiveMin = adaptiveMin;
102 //=======================================================================
103 //function : Constructor
105 //=======================================================================
106 BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh(const TopoDS_Shape& theShape,
107 const BRepMesh_FastDiscret::Parameters& theParameters)
108 : myParameters(theParameters)
115 //=======================================================================
116 //function : Destructor
118 //=======================================================================
119 BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh()
123 //=======================================================================
126 //=======================================================================
127 void BRepMesh_IncrementalMesh::clear()
129 // the allocator will be alive while the structures are alive
130 Handle(NCollection_BaseAllocator) anAlloc =
131 new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
132 myEdges.Clear(anAlloc);
133 myEdgeDeflection.Clear(anAlloc);
138 //=======================================================================
141 //=======================================================================
142 void BRepMesh_IncrementalMesh::init()
145 myModified = Standard_False;
153 if ( myParameters.Relative )
155 BRepBndLib::Add(myShape, aBox, Standard_False);
163 BRepMesh_ShapeTool::BoxMaxDimension(aBox, myMaxShapeSize);
166 myMesh = new BRepMesh_FastDiscret (aBox, myParameters);
168 myMesh->InitSharedFaces(myShape);
171 //=======================================================================
172 //function : collectFaces
174 //=======================================================================
175 void BRepMesh_IncrementalMesh::collectFaces()
177 Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
178 TopTools_ListOfShape aFaceList(anAlloc);
179 BRepLib::ReverseSortFaces(myShape, aFaceList);
180 TColStd_MapOfTransient aTFaceMap(1, anAlloc);
182 // make array of faces suitable for processing (excluding faces without surface)
183 TopLoc_Location aDummyLoc;
184 TopTools_ListIteratorOfListOfShape aFaceIter(aFaceList);
185 for (; aFaceIter.More(); aFaceIter.Next())
187 const TopoDS_Face& aFace = TopoDS::Face(aFaceIter.Value());
188 const Handle(TopoDS_TShape)& aTFace = aFace.TShape();
189 if (!aTFaceMap.Add (aTFace))
190 continue; // already processed
192 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aDummyLoc);
196 myFaces.Append(aFace);
200 //=======================================================================
203 //=======================================================================
204 void BRepMesh_IncrementalMesh::Perform()
214 //=======================================================================
215 //function : update()
217 //=======================================================================
218 void BRepMesh_IncrementalMesh::update()
221 TopExp_Explorer aExplorer(myShape, TopAbs_EDGE);
222 for (; aExplorer.More(); aExplorer.Next())
224 const TopoDS_Edge& aEdge = TopoDS::Edge(aExplorer.Current());
225 if(!BRep_Tool::IsGeometric(aEdge))
232 NCollection_Vector<TopoDS_Face>::Iterator aFaceIt(myFaces);
233 for (; aFaceIt.More(); aFaceIt.Next())
234 update(aFaceIt.Value());
237 OSD_Parallel::ForEach(myFaces.begin(), myFaces.end(), *myMesh, !myParameters.InParallel);
243 //=======================================================================
244 //function : discretizeFreeEdges
246 //=======================================================================
247 void BRepMesh_IncrementalMesh::discretizeFreeEdges()
249 TopExp_Explorer aExplorer(myShape ,TopAbs_EDGE, TopAbs_FACE);
250 for (; aExplorer.More(); aExplorer.Next())
252 const TopoDS_Edge& aEdge = TopoDS::Edge(aExplorer.Current());
253 if(!BRep_Tool::IsGeometric(aEdge))
256 TopLoc_Location aLoc;
257 Standard_Real aEdgeDeflection = edgeDeflection(aEdge);
258 Handle(Poly_Polygon3D) aPoly3D = BRep_Tool::Polygon3D(aEdge, aLoc);
259 if (!aPoly3D.IsNull() && aPoly3D->Deflection() < 1.1 * aEdgeDeflection)
262 BRepAdaptor_Curve aCurve(aEdge);
263 GCPnts_TangentialDeflection aDiscret(aCurve, aCurve.FirstParameter(),
264 aCurve.LastParameter(), myParameters.Angle, aEdgeDeflection, 2,
265 Precision::PConfusion(), myParameters.MinSize);
267 Standard_Integer aNodesNb = aDiscret.NbPoints();
268 TColgp_Array1OfPnt aNodes (1, aNodesNb);
269 TColStd_Array1OfReal aUVNodes(1, aNodesNb);
270 for (Standard_Integer i = 1; i <= aNodesNb; ++i)
272 aNodes (i) = aDiscret.Value(i);
273 aUVNodes(i) = aDiscret.Parameter(i);
276 aPoly3D = new Poly_Polygon3D(aNodes, aUVNodes);
277 aPoly3D->Deflection(myParameters.Deflection);
279 BRep_Builder aBuilder;
280 aBuilder.UpdateEdge(aEdge, aPoly3D);
284 //=======================================================================
285 //function : edgeDeflection
287 //=======================================================================
288 Standard_Real BRepMesh_IncrementalMesh::edgeDeflection(
289 const TopoDS_Edge& theEdge)
291 const Standard_Real* pDef = myEdgeDeflection.Seek(theEdge);
295 Standard_Real aEdgeDeflection;
296 if ( myParameters.Relative )
298 Standard_Real aScale;
299 aEdgeDeflection = BRepMesh_ShapeTool::RelativeEdgeDeflection(theEdge,
300 myParameters.Deflection, myMaxShapeSize, aScale);
303 aEdgeDeflection = myParameters.Deflection;
305 myEdgeDeflection.Bind(theEdge, aEdgeDeflection);
306 return aEdgeDeflection;
309 //=======================================================================
310 //function : faceDeflection
312 //=======================================================================
313 Standard_Real BRepMesh_IncrementalMesh::faceDeflection(
314 const TopoDS_Face& theFace)
316 if ( !myParameters.Relative )
317 return myParameters.Deflection;
319 Standard_Integer aEdgesNb = 0;
320 Standard_Real aFaceDeflection = 0.;
322 TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
323 for (; aEdgeIt.More(); aEdgeIt.Next(), ++aEdgesNb)
325 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
326 aFaceDeflection += edgeDeflection(aEdge);
329 return (aEdgesNb == 0) ? myParameters.Deflection : (aFaceDeflection / aEdgesNb);
332 //=======================================================================
333 //function : update(edge)
335 //=======================================================================
336 void BRepMesh_IncrementalMesh::update(const TopoDS_Edge& theEdge)
338 if (!myEdges.IsBound(theEdge))
339 myEdges.Bind(theEdge, BRepMesh::DMapOfTriangulationBool(3, myEdges.Allocator()));
341 Standard_Real aEdgeDeflection = edgeDeflection(theEdge);
342 // Check that triangulation relies to face of the given shape.
343 const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces =
344 myMesh->SharedFaces();
346 const TopTools_ListOfShape& aSharedFaces =
347 aMapOfSharedFaces.FindFromKey(theEdge);
349 TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces);
350 for (; aSharedFaceIt.More(); aSharedFaceIt.Next())
352 TopLoc_Location aLoc;
353 const TopoDS_Face& aFace = TopoDS::Face(aSharedFaceIt.Value());
354 const Handle(Poly_Triangulation)& aFaceTriangulation =
355 BRep_Tool::Triangulation(aFace, aLoc);
357 if (aFaceTriangulation.IsNull())
360 Standard_Boolean isConsistent = Standard_False;
361 const Handle(Poly_PolygonOnTriangulation)& aPolygon =
362 BRep_Tool::PolygonOnTriangulation(theEdge, aFaceTriangulation, aLoc);
364 if (!aPolygon.IsNull())
366 isConsistent = aPolygon->Deflection() < 1.1 * aEdgeDeflection &&
367 aPolygon->HasParameters();
371 myModified = Standard_True;
372 BRepMesh_ShapeTool::NullifyEdge(theEdge, aFaceTriangulation, aLoc);
376 myEdges(theEdge).Bind(aFaceTriangulation, isConsistent);
380 //=======================================================================
381 //function : isToBeMeshed
383 //=======================================================================
384 Standard_Boolean BRepMesh_IncrementalMesh::toBeMeshed(
385 const TopoDS_Face& theFace,
386 const Standard_Boolean isWithCheck)
388 TopLoc_Location aLoc;
389 const Handle(Poly_Triangulation)& aTriangulation =
390 BRep_Tool::Triangulation(theFace, aLoc);
392 if (aTriangulation.IsNull())
393 return Standard_True;
397 Standard_Real aFaceDeflection = faceDeflection(theFace);
398 if (aTriangulation->Deflection() < 1.1 * aFaceDeflection)
400 Standard_Boolean isEdgesConsistent = Standard_True;
401 TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
402 for (; aEdgeIt.More() && isEdgesConsistent; aEdgeIt.Next())
404 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
405 if (!myEdges.IsBound(aEdge))
408 BRepMesh::DMapOfTriangulationBool& aTriMap = myEdges(aEdge);
409 isEdgesConsistent &= aTriMap.IsBound(aTriangulation) &&
410 aTriMap(aTriangulation);
413 if (isEdgesConsistent)
415 // #25080: check that indices of links forming triangles are in range.
416 Standard_Boolean isTriangulationConsistent = Standard_True;
417 const Standard_Integer aNodesNb = aTriangulation->NbNodes();
418 const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles();
419 Standard_Integer i = aTriangles.Lower();
420 for (; i <= aTriangles.Upper() && isTriangulationConsistent; ++i)
422 const Poly_Triangle& aTriangle = aTriangles(i);
423 Standard_Integer n[3];
424 aTriangle.Get(n[0], n[1], n[2]);
425 for (Standard_Integer j = 0; j < 3 && isTriangulationConsistent; ++j)
426 isTriangulationConsistent = (n[j] >= 1 && n[j] <= aNodesNb);
429 if (isTriangulationConsistent)
430 return Standard_False;
436 TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
437 for (; aEdgeIt.More(); aEdgeIt.Next())
439 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
440 BRepMesh_ShapeTool::NullifyEdge(aEdge, aTriangulation, aLoc);
443 BRepMesh_ShapeTool::NullifyFace(theFace);
444 return Standard_True;
447 //=======================================================================
448 //function : update(face)
450 //=======================================================================
451 void BRepMesh_IncrementalMesh::update(const TopoDS_Face& theFace)
453 if (!toBeMeshed(theFace, Standard_True))
456 myModified = Standard_True;
457 Standard_Integer aStatus = myMesh->Add(theFace);
460 if (aStatus != BRepMesh_ReMesh)
463 BRepMesh::MapOfShape aUsedFaces;
464 aUsedFaces.Add(theFace);
466 const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces =
467 myMesh->SharedFaces();
469 TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
470 for (; aEdgeIt.More(); aEdgeIt.Next())
472 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
473 if (aMapOfSharedFaces.FindIndex(aEdge) == 0)
476 const TopTools_ListOfShape& aSharedFaces = aMapOfSharedFaces.FindFromKey(aEdge);
477 TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces);
478 for (; aSharedFaceIt.More(); aSharedFaceIt.Next())
480 const TopoDS_Face& aFace = TopoDS::Face(aSharedFaceIt.Value());
481 if (aUsedFaces.Contains(aFace))
484 aUsedFaces.Add(aFace);
485 toBeMeshed(aFace, Standard_False);
487 myStatus |= myMesh->Add(aFace);
492 //=======================================================================
495 //=======================================================================
496 void BRepMesh_IncrementalMesh::commit()
498 NCollection_Vector<TopoDS_Face>::Iterator aFaceIt(myFaces);
499 for (; aFaceIt.More(); aFaceIt.Next())
500 commitEdges(aFaceIt.Value());
502 discretizeFreeEdges();
505 //=======================================================================
506 //function : commitEdges
508 //=======================================================================
509 void BRepMesh_IncrementalMesh::commitEdges(const TopoDS_Face& theFace)
511 TopoDS_Face aFace = theFace;
512 aFace.Orientation(TopAbs_FORWARD);
514 Handle(BRepMesh_FaceAttribute) aFaceAttribute;
515 if (!myMesh->GetFaceAttribute(aFace, aFaceAttribute))
518 if (!aFaceAttribute->IsValid())
520 myStatus |= aFaceAttribute->GetStatus();
524 TopLoc_Location aLoc;
525 Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLoc);
527 if (aTriangulation.IsNull())
534 // Store discretization of edges
535 BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = aFaceAttribute->ChangeInternalEdges();
536 BRepMesh::DMapOfShapePairOfPolygon::Iterator aEdgeIt(*aInternalEdges);
537 for (; aEdgeIt.More(); aEdgeIt.Next())
539 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Key());
540 const BRepMesh_PairOfPolygon& aPolyPair = aEdgeIt.Value();
541 const Handle(Poly_PolygonOnTriangulation)& aPolygon1 = aPolyPair.First();
542 const Handle(Poly_PolygonOnTriangulation)& aPolygon2 = aPolyPair.Last();
544 if (aPolygon1 == aPolygon2)
545 BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aTriangulation, aLoc);
547 BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aPolygon2, aTriangulation, aLoc);
550 catch (Standard_Failure)
552 myStatus |= BRepMesh_Failure;
556 //=======================================================================
559 //=======================================================================
560 Standard_Integer BRepMesh_IncrementalMesh::Discret(
561 const TopoDS_Shape& theShape,
562 const Standard_Real theDeflection,
563 const Standard_Real theAngle,
564 BRepMesh_DiscretRoot* &theAlgo)
566 BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh();
567 anAlgo->ChangeParameters().Deflection = theDeflection;
568 anAlgo->ChangeParameters().Angle = theAngle;
569 anAlgo->ChangeParameters().InParallel = IS_IN_PARALLEL;
570 anAlgo->SetShape (theShape);
572 return 0; // no error
575 //=======================================================================
576 //function : IsParallelDefault
578 //=======================================================================
579 Standard_Boolean BRepMesh_IncrementalMesh::IsParallelDefault()
581 return IS_IN_PARALLEL;
584 //=======================================================================
587 //=======================================================================
588 void BRepMesh_IncrementalMesh::SetParallelDefault(
589 const Standard_Boolean theInParallel)
591 IS_IN_PARALLEL = theInParallel;
594 //! Export Mesh Plugin entry function
595 DISCRETPLUGIN(BRepMesh_IncrementalMesh)