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 <TopTools_HArray1OfShape.hxx>
52 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
54 #include <GCPnts_TangentialDeflection.hxx>
56 IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot)
60 //! Default flag to control parallelization for BRepMesh_IncrementalMesh
61 //! tool returned for Mesh Factory
62 static Standard_Boolean IS_IN_PARALLEL = Standard_False;
66 //=======================================================================
67 //function : Default constructor
69 //=======================================================================
70 BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh()
72 myModified(Standard_False),
77 //=======================================================================
78 //function : Constructor
80 //=======================================================================
81 BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh( const TopoDS_Shape& theShape,
82 const Standard_Real theLinDeflection,
83 const Standard_Boolean isRelative,
84 const Standard_Real theAngDeflection,
85 const Standard_Boolean isInParallel,
86 const Standard_Boolean adaptiveMin)
88 myModified(Standard_False),
91 myParameters.Deflection = theLinDeflection;
92 myParameters.Relative = isRelative;
93 myParameters.Angle = theAngDeflection;
94 myParameters.InParallel = isInParallel;
95 myParameters.AdaptiveMin = adaptiveMin;
101 //=======================================================================
102 //function : Constructor
104 //=======================================================================
105 BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh(const TopoDS_Shape& theShape,
106 const BRepMesh_FastDiscret::Parameters& theParameters)
107 : myParameters(theParameters)
114 //=======================================================================
115 //function : Destructor
117 //=======================================================================
118 BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh()
122 //=======================================================================
125 //=======================================================================
126 void BRepMesh_IncrementalMesh::clear()
129 myEdgeDeflection.Clear();
134 //=======================================================================
137 //=======================================================================
138 void BRepMesh_IncrementalMesh::init()
141 myModified = Standard_False;
149 BRepBndLib::Add(myShape, aBox, Standard_False);
157 BRepMesh_ShapeTool::BoxMaxDimension(aBox, myMaxShapeSize);
159 myMesh = new BRepMesh_FastDiscret (aBox, myParameters);
161 myMesh->InitSharedFaces(myShape);
164 //=======================================================================
165 //function : collectFaces
167 //=======================================================================
168 void BRepMesh_IncrementalMesh::collectFaces()
170 TopTools_ListOfShape aFaceList;
171 BRepLib::ReverseSortFaces(myShape, aFaceList);
172 TopTools_MapOfShape aFaceMap;
174 // make array of faces suitable for processing (excluding faces without surface)
175 TopLoc_Location aDummyLoc;
176 const TopLoc_Location aEmptyLoc;
177 TopTools_ListIteratorOfListOfShape aFaceIter(aFaceList);
178 for (; aFaceIter.More(); aFaceIter.Next())
180 TopoDS_Shape aFaceNoLoc = aFaceIter.Value();
181 aFaceNoLoc.Location(aEmptyLoc);
182 if (!aFaceMap.Add (aFaceNoLoc))
183 continue; // already processed
185 TopoDS_Face aFace = TopoDS::Face(aFaceIter.Value());
186 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aDummyLoc);
190 myFaces.Append(aFace);
194 //=======================================================================
197 //=======================================================================
198 void BRepMesh_IncrementalMesh::Perform()
208 //=======================================================================
209 //function : update()
211 //=======================================================================
212 void BRepMesh_IncrementalMesh::update()
215 TopExp_Explorer aExplorer(myShape, TopAbs_EDGE);
216 for (; aExplorer.More(); aExplorer.Next())
218 const TopoDS_Edge& aEdge = TopoDS::Edge(aExplorer.Current());
219 if(!BRep_Tool::IsGeometric(aEdge))
226 NCollection_Vector<TopoDS_Face>::Iterator aFaceIt(myFaces);
227 for (; aFaceIt.More(); aFaceIt.Next())
228 update(aFaceIt.Value());
231 OSD_Parallel::ForEach(myFaces.begin(), myFaces.end(), *myMesh, !myParameters.InParallel);
237 //=======================================================================
238 //function : discretizeFreeEdges
240 //=======================================================================
241 void BRepMesh_IncrementalMesh::discretizeFreeEdges()
243 TopExp_Explorer aExplorer(myShape ,TopAbs_EDGE, TopAbs_FACE);
244 for (; aExplorer.More(); aExplorer.Next())
246 const TopoDS_Edge& aEdge = TopoDS::Edge(aExplorer.Current());
247 if(!BRep_Tool::IsGeometric(aEdge))
250 TopLoc_Location aLoc;
251 Standard_Real aEdgeDeflection = edgeDeflection(aEdge);
252 Handle(Poly_Polygon3D) aPoly3D = BRep_Tool::Polygon3D(aEdge, aLoc);
253 if (!aPoly3D.IsNull() && aPoly3D->Deflection() < 1.1 * aEdgeDeflection)
256 BRepAdaptor_Curve aCurve(aEdge);
257 GCPnts_TangentialDeflection aDiscret(aCurve, aCurve.FirstParameter(),
258 aCurve.LastParameter(), myParameters.Angle, aEdgeDeflection, 2,
259 Precision::PConfusion(), myParameters.MinSize);
261 Standard_Integer aNodesNb = aDiscret.NbPoints();
262 TColgp_Array1OfPnt aNodes (1, aNodesNb);
263 TColStd_Array1OfReal aUVNodes(1, aNodesNb);
264 for (Standard_Integer i = 1; i <= aNodesNb; ++i)
266 aNodes (i) = aDiscret.Value(i);
267 aUVNodes(i) = aDiscret.Parameter(i);
270 aPoly3D = new Poly_Polygon3D(aNodes, aUVNodes);
271 aPoly3D->Deflection(myParameters.Deflection);
273 BRep_Builder aBuilder;
274 aBuilder.UpdateEdge(aEdge, aPoly3D);
278 //=======================================================================
279 //function : edgeDeflection
281 //=======================================================================
282 Standard_Real BRepMesh_IncrementalMesh::edgeDeflection(
283 const TopoDS_Edge& theEdge)
285 if (myEdgeDeflection.IsBound(theEdge))
286 return myEdgeDeflection(theEdge);
288 Standard_Real aEdgeDeflection;
289 if ( myParameters.Relative )
291 Standard_Real aScale;
292 aEdgeDeflection = BRepMesh_ShapeTool::RelativeEdgeDeflection(theEdge,
293 myParameters.Deflection, myMaxShapeSize, aScale);
296 aEdgeDeflection = myParameters.Deflection;
298 myEdgeDeflection.Bind(theEdge, aEdgeDeflection);
299 return aEdgeDeflection;
302 //=======================================================================
303 //function : faceDeflection
305 //=======================================================================
306 Standard_Real BRepMesh_IncrementalMesh::faceDeflection(
307 const TopoDS_Face& theFace)
309 if ( !myParameters.Relative )
310 return myParameters.Deflection;
312 Standard_Integer aEdgesNb = 0;
313 Standard_Real aFaceDeflection = 0.;
315 TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
316 for (; aEdgeIt.More(); aEdgeIt.Next(), ++aEdgesNb)
318 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
319 aFaceDeflection += edgeDeflection(aEdge);
322 return (aEdgesNb == 0) ? myParameters.Deflection : (aFaceDeflection / aEdgesNb);
325 //=======================================================================
326 //function : update(edge)
328 //=======================================================================
329 void BRepMesh_IncrementalMesh::update(const TopoDS_Edge& theEdge)
331 if (!myEdges.IsBound(theEdge))
332 myEdges.Bind(theEdge, BRepMesh::DMapOfTriangulationBool());
334 Standard_Real aEdgeDeflection = edgeDeflection(theEdge);
335 // Check that triangulation relies to face of the given shape.
336 const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces =
337 myMesh->SharedFaces();
339 const TopTools_ListOfShape& aSharedFaces =
340 aMapOfSharedFaces.FindFromKey(theEdge);
342 TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces);
343 for (; aSharedFaceIt.More(); aSharedFaceIt.Next())
345 TopLoc_Location aLoc;
346 const TopoDS_Face& aFace = TopoDS::Face(aSharedFaceIt.Value());
347 const Handle(Poly_Triangulation)& aFaceTriangulation =
348 BRep_Tool::Triangulation(aFace, aLoc);
350 if (aFaceTriangulation.IsNull())
353 Standard_Boolean isConsistent = Standard_False;
354 const Handle(Poly_PolygonOnTriangulation)& aPolygon =
355 BRep_Tool::PolygonOnTriangulation(theEdge, aFaceTriangulation, aLoc);
357 if (!aPolygon.IsNull())
359 isConsistent = aPolygon->Deflection() < 1.1 * aEdgeDeflection &&
360 aPolygon->HasParameters();
364 myModified = Standard_True;
365 BRepMesh_ShapeTool::NullifyEdge(theEdge, aFaceTriangulation, aLoc);
369 myEdges(theEdge).Bind(aFaceTriangulation, isConsistent);
373 //=======================================================================
374 //function : isToBeMeshed
376 //=======================================================================
377 Standard_Boolean BRepMesh_IncrementalMesh::toBeMeshed(
378 const TopoDS_Face& theFace,
379 const Standard_Boolean isWithCheck)
381 TopLoc_Location aLoc;
382 const Handle(Poly_Triangulation)& aTriangulation =
383 BRep_Tool::Triangulation(theFace, aLoc);
385 if (aTriangulation.IsNull())
386 return Standard_True;
390 Standard_Real aFaceDeflection = faceDeflection(theFace);
391 if (aTriangulation->Deflection() < 1.1 * aFaceDeflection)
393 Standard_Boolean isEdgesConsistent = Standard_True;
394 TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
395 for (; aEdgeIt.More() && isEdgesConsistent; aEdgeIt.Next())
397 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
398 if (!myEdges.IsBound(aEdge))
401 BRepMesh::DMapOfTriangulationBool& aTriMap = myEdges(aEdge);
402 isEdgesConsistent &= aTriMap.IsBound(aTriangulation) &&
403 aTriMap(aTriangulation);
406 if (isEdgesConsistent)
408 // #25080: check that indices of links forming triangles are in range.
409 Standard_Boolean isTriangulationConsistent = Standard_True;
410 const Standard_Integer aNodesNb = aTriangulation->NbNodes();
411 const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles();
412 Standard_Integer i = aTriangles.Lower();
413 for (; i <= aTriangles.Upper() && isTriangulationConsistent; ++i)
415 const Poly_Triangle& aTriangle = aTriangles(i);
416 Standard_Integer n[3];
417 aTriangle.Get(n[0], n[1], n[2]);
418 for (Standard_Integer j = 0; j < 3 && isTriangulationConsistent; ++j)
419 isTriangulationConsistent = (n[j] >= 1 && n[j] <= aNodesNb);
422 if (isTriangulationConsistent)
423 return Standard_False;
429 TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
430 for (; aEdgeIt.More(); aEdgeIt.Next())
432 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
433 BRepMesh_ShapeTool::NullifyEdge(aEdge, aTriangulation, aLoc);
436 BRepMesh_ShapeTool::NullifyFace(theFace);
437 return Standard_True;
440 //=======================================================================
441 //function : update(face)
443 //=======================================================================
444 void BRepMesh_IncrementalMesh::update(const TopoDS_Face& theFace)
446 if (!toBeMeshed(theFace, Standard_True))
449 myModified = Standard_True;
450 Standard_Integer aStatus = myMesh->Add(theFace);
453 if (aStatus != BRepMesh_ReMesh)
456 BRepMesh::MapOfShape aUsedFaces;
457 aUsedFaces.Add(theFace);
459 const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces =
460 myMesh->SharedFaces();
462 TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
463 for (; aEdgeIt.More(); aEdgeIt.Next())
465 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
466 if (aMapOfSharedFaces.FindIndex(aEdge) == 0)
469 const TopTools_ListOfShape& aSharedFaces = aMapOfSharedFaces.FindFromKey(aEdge);
470 TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces);
471 for (; aSharedFaceIt.More(); aSharedFaceIt.Next())
473 const TopoDS_Face& aFace = TopoDS::Face(aSharedFaceIt.Value());
474 if (aUsedFaces.Contains(aFace))
477 aUsedFaces.Add(aFace);
478 toBeMeshed(aFace, Standard_False);
480 myStatus |= myMesh->Add(aFace);
485 //=======================================================================
488 //=======================================================================
489 void BRepMesh_IncrementalMesh::commit()
491 NCollection_Vector<TopoDS_Face>::Iterator aFaceIt(myFaces);
492 for (; aFaceIt.More(); aFaceIt.Next())
493 commitEdges(aFaceIt.Value());
495 discretizeFreeEdges();
498 //=======================================================================
499 //function : commitEdges
501 //=======================================================================
502 void BRepMesh_IncrementalMesh::commitEdges(const TopoDS_Face& theFace)
504 TopoDS_Face aFace = theFace;
505 aFace.Orientation(TopAbs_FORWARD);
507 Handle(BRepMesh_FaceAttribute) aFaceAttribute;
508 if (!myMesh->GetFaceAttribute(aFace, aFaceAttribute))
511 if (!aFaceAttribute->IsValid())
513 myStatus |= aFaceAttribute->GetStatus();
517 TopLoc_Location aLoc;
518 Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLoc);
520 if (aTriangulation.IsNull())
527 // Store discretization of edges
528 BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = aFaceAttribute->ChangeInternalEdges();
529 BRepMesh::DMapOfShapePairOfPolygon::Iterator aEdgeIt(*aInternalEdges);
530 for (; aEdgeIt.More(); aEdgeIt.Next())
532 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Key());
533 const BRepMesh_PairOfPolygon& aPolyPair = aEdgeIt.Value();
534 const Handle(Poly_PolygonOnTriangulation)& aPolygon1 = aPolyPair.First();
535 const Handle(Poly_PolygonOnTriangulation)& aPolygon2 = aPolyPair.Last();
537 if (aPolygon1 == aPolygon2)
538 BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aTriangulation, aLoc);
540 BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aPolygon2, aTriangulation, aLoc);
543 catch (Standard_Failure)
545 myStatus |= BRepMesh_Failure;
549 //=======================================================================
552 //=======================================================================
553 Standard_Integer BRepMesh_IncrementalMesh::Discret(
554 const TopoDS_Shape& theShape,
555 const Standard_Real theDeflection,
556 const Standard_Real theAngle,
557 BRepMesh_DiscretRoot* &theAlgo)
559 BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh();
560 anAlgo->ChangeParameters().Deflection = theDeflection;
561 anAlgo->ChangeParameters().Angle = theAngle;
562 anAlgo->ChangeParameters().InParallel = IS_IN_PARALLEL;
563 anAlgo->SetShape (theShape);
565 return 0; // no error
568 //=======================================================================
569 //function : IsParallelDefault
571 //=======================================================================
572 Standard_Boolean BRepMesh_IncrementalMesh::IsParallelDefault()
574 return IS_IN_PARALLEL;
577 //=======================================================================
580 //=======================================================================
581 void BRepMesh_IncrementalMesh::SetParallelDefault(
582 const Standard_Boolean theInParallel)
584 IS_IN_PARALLEL = theInParallel;
587 //! Export Mesh Plugin entry function
588 DISCRETPLUGIN(BRepMesh_IncrementalMesh)