diff --git a/adm/UDLIST b/adm/UDLIST index c0ca7321ea..1e9c93a464 100644 --- a/adm/UDLIST +++ b/adm/UDLIST @@ -182,7 +182,7 @@ p TopOpeBRepBuild p TopOpeBRepDS p TopOpeBRepTool p TopTrans -p XBRepMesh +n XBRepMesh t TKBO t TKBool t TKFeat diff --git a/src/BRepMesh/BRepMesh.cdl b/src/BRepMesh/BRepMesh.cdl index e53dbc9601..088351178a 100644 --- a/src/BRepMesh/BRepMesh.cdl +++ b/src/BRepMesh/BRepMesh.cdl @@ -54,8 +54,6 @@ is imported Circle from BRepMesh; imported DiscretRoot from BRepMesh; imported DiscretFactory from BRepMesh; - -- - pointer PDiscretRoot to DiscretRoot from BRepMesh; imported ShapeTool from BRepMesh; imported Collections from BRepMesh; @@ -66,6 +64,10 @@ is imported WireInterferenceChecker from BRepMesh; imported EdgeChecker from BRepMesh; imported FaceChecker from BRepMesh; + imported EdgeParameterProvider from BRepMesh; + imported IEdgeTool from BRepMesh; + imported EdgeTessellationExtractor from BRepMesh; + imported EdgeTessellator from BRepMesh; primitive PluginEntryType; diff --git a/src/BRepMesh/BRepMesh_Collections.hxx b/src/BRepMesh/BRepMesh_Collections.hxx index eb613ca694..13a818d89e 100644 --- a/src/BRepMesh/BRepMesh_Collections.hxx +++ b/src/BRepMesh/BRepMesh_Collections.hxx @@ -40,6 +40,7 @@ #include #include #include +#include #include @@ -48,7 +49,6 @@ class TopoDS_Shape; class TopoDS_Face; class TopoDS_Edge; class TopoDS_Vertex; -class BRepMesh_FaceAttribute; class Handle_BRepMesh_FaceAttribute; class BRepMesh_VertexInspector; class BRepMesh_CircleInspector; @@ -132,6 +132,9 @@ namespace BRepMeshCol //! Handles typedef N_HANDLE HMapOfInteger; + typedef N_HANDLE HIMapOfInteger; + typedef N_HANDLE HDMapOfShapePairOfPolygon; + typedef N_HANDLE HDMapOfIntegerPnt; typedef N_HANDLE HClassifier; typedef N_HANDLE HBndBox2dTree; typedef N_HANDLE HArray1OfSegments; diff --git a/src/BRepMesh/BRepMesh_Delaun.cxx b/src/BRepMesh/BRepMesh_Delaun.cxx index aa628f9f2d..654783414b 100644 --- a/src/BRepMesh/BRepMesh_Delaun.cxx +++ b/src/BRepMesh/BRepMesh_Delaun.cxx @@ -75,10 +75,9 @@ namespace { //function : BRepMesh_Delaun //purpose : Creates the triangulation with an empty Mesh data structure //======================================================================= -BRepMesh_Delaun::BRepMesh_Delaun( BRepMeshCol::Array1OfVertexOfDelaun& theVertices, - const Standard_Boolean isPositive ) -: myIsPositiveOrientation( isPositive ), - myCircles( theVertices.Length(), new NCollection_IncAllocator() ) +BRepMesh_Delaun::BRepMesh_Delaun( + BRepMeshCol::Array1OfVertexOfDelaun& theVertices) +: myCircles( theVertices.Length(), new NCollection_IncAllocator() ) { if ( theVertices.Length() > 2 ) { @@ -92,11 +91,10 @@ BRepMesh_Delaun::BRepMesh_Delaun( BRepMeshCol::Array1OfVertexOfDelaun& theVertic //function : BRepMesh_Delaun //purpose : Creates the triangulation with and existent Mesh data structure //======================================================================= -BRepMesh_Delaun::BRepMesh_Delaun( const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh, - BRepMeshCol::Array1OfVertexOfDelaun& theVertices, - const Standard_Boolean isPositive ) - : myIsPositiveOrientation( isPositive ), - myCircles( theVertices.Length(), theOldMesh->Allocator() ) +BRepMesh_Delaun::BRepMesh_Delaun( + const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh, + BRepMeshCol::Array1OfVertexOfDelaun& theVertices) + : myCircles( theVertices.Length(), theOldMesh->Allocator() ) { myMeshData = theOldMesh; if ( theVertices.Length() > 2 ) @@ -107,11 +105,10 @@ BRepMesh_Delaun::BRepMesh_Delaun( const Handle( BRepMesh_DataStructureOfDelaun ) //function : BRepMesh_Delaun //purpose : Creates the triangulation with and existent Mesh data structure //======================================================================= -BRepMesh_Delaun::BRepMesh_Delaun( const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh, - BRepMeshCol::Array1OfInteger& theVertexIndices, - const Standard_Boolean isPositive ) - : myIsPositiveOrientation( isPositive ), - myCircles( theVertexIndices.Length(), theOldMesh->Allocator() ) +BRepMesh_Delaun::BRepMesh_Delaun( + const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh, + BRepMeshCol::Array1OfInteger& theVertexIndices) + : myCircles( theVertexIndices.Length(), theOldMesh->Allocator() ) { myMeshData = theOldMesh; if ( theVertexIndices.Length() > 2 ) @@ -199,14 +196,6 @@ void BRepMesh_Delaun::superMesh( const Bnd_Box2d& theBox ) mySupVert[2] = myMeshData->AddNode( BRepMesh_Vertex( aMaxX + aDelta, aMinY - aDeltaMin, BRepMesh_Free ) ); - if ( !myIsPositiveOrientation ) - { - Standard_Integer aTmp; - aTmp = mySupVert[1]; - mySupVert[1] = mySupVert[2]; - mySupVert[2] = aTmp; - } - Standard_Integer e[3]; Standard_Boolean o[3]; for (Standard_Integer aNodeId = 0; aNodeId < 3; ++aNodeId) @@ -354,13 +343,6 @@ void BRepMesh_Delaun::createTriangles ( const Standard_Integer theVer continue; } - Standard_Boolean isSensOK; - if ( myIsPositiveOrientation ) - isSensOK = ( aDist12 > 0. && aDist23 > 0.); - else - isSensOK = ( aDist12 < 0. && aDist23 < 0.); - - BRepMesh_Edge aFirstLink( aNodes[1], aNodes[0], BRepMesh_Free ); BRepMesh_Edge aLastLink ( aNodes[2], aNodes[1], BRepMesh_Free ); @@ -369,7 +351,8 @@ void BRepMesh_Delaun::createTriangles ( const Standard_Integer theVer isPositive ? anEdgeId : -anEdgeId, myMeshData->AddLink( aLastLink ) }; - if ( isSensOK ) + Standard_Boolean isSensOK = (aDist12 > 0. && aDist23 > 0.); + if (isSensOK) { Standard_Integer anEdges[3]; Standard_Boolean anEdgesOri[3]; @@ -935,8 +918,7 @@ Standard_Integer BRepMesh_Delaun::findNextPolygonLink( { // Find the next link having the greatest angle // respect to a direction of a reference one - Standard_Real aMaxAngle = myIsPositiveOrientation ? - RealFirst() : RealLast(); + Standard_Real aMaxAngle = RealFirst(); Standard_Integer aNextLinkId = 0; BRepMeshCol::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( thePivotNode ) ); @@ -996,11 +978,8 @@ Standard_Integer BRepMesh_Delaun::findNextPolygonLink( } } - if ( ( myIsPositiveOrientation && anAngle <= aMaxAngle ) || - (!myIsPositiveOrientation && anAngle >= aMaxAngle ) ) - { + if (anAngle <= aMaxAngle) continue; - } Standard_Boolean isCheckEndPoints = ( anOtherNode != theFirstNode ); @@ -1802,12 +1781,8 @@ void BRepMesh_Delaun::meshSimplePolygon( BRepMeshCol::SequenceOfInteger& thePoly Standard_Real aDist = aRefEdgeDir ^ aDistanceDir; Standard_Real aAngle = Abs( aRefEdgeDir.Angle(aDistanceDir) ); Standard_Real anAbsDist = Abs( aDist ); - if ( ( anAbsDist < Precision ) || - ( myIsPositiveOrientation && aDist < 0. ) || - (!myIsPositiveOrientation && aDist > 0. ) ) - { + if (anAbsDist < Precision || aDist < 0.) continue; - } if ( ( anAbsDist >= aMinDist ) && ( aAngle <= aOptAngle || aAngle > AngDeviation90Deg ) ) diff --git a/src/BRepMesh/BRepMesh_Delaun.hxx b/src/BRepMesh/BRepMesh_Delaun.hxx index ae6da815af..e6484a1663 100755 --- a/src/BRepMesh/BRepMesh_Delaun.hxx +++ b/src/BRepMesh/BRepMesh_Delaun.hxx @@ -40,18 +40,15 @@ public: DEFINE_STANDARD_ALLOC //! Creates the triangulation with an empty Mesh data structure. - Standard_EXPORT BRepMesh_Delaun (BRepMeshCol::Array1OfVertexOfDelaun& theVertices, - const Standard_Boolean isPositive = Standard_True); + Standard_EXPORT BRepMesh_Delaun (BRepMeshCol::Array1OfVertexOfDelaun& theVertices); //! Creates the triangulation with an existent Mesh data structure. Standard_EXPORT BRepMesh_Delaun (const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh, - BRepMeshCol::Array1OfVertexOfDelaun& theVertices, - const Standard_Boolean isPositive = Standard_True); + BRepMeshCol::Array1OfVertexOfDelaun& theVertices); //! Creates the triangulation with an existant Mesh data structure. Standard_EXPORT BRepMesh_Delaun (const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh, - BRepMeshCol::Array1OfInteger& theVertexIndices, - const Standard_Boolean isPositive = Standard_True); + BRepMeshCol::Array1OfInteger& theVertexIndices); //! Initializes the triangulation with an array of vertices. Standard_EXPORT void Init (BRepMeshCol::Array1OfVertexOfDelaun& theVertices); @@ -307,7 +304,6 @@ private: private: Handle(BRepMesh_DataStructureOfDelaun) myMeshData; - Standard_Boolean myIsPositiveOrientation; BRepMesh_CircleTool myCircles; Standard_Integer mySupVert[3]; BRepMesh_Triangle mySupTrian; diff --git a/src/BRepMesh/BRepMesh_DiscretFactory.cxx b/src/BRepMesh/BRepMesh_DiscretFactory.cxx index 8e727bd6a4..bc4e7d7d3e 100644 --- a/src/BRepMesh/BRepMesh_DiscretFactory.cxx +++ b/src/BRepMesh/BRepMesh_DiscretFactory.cxx @@ -18,7 +18,7 @@ #include #include #include -#include +#include namespace { @@ -145,7 +145,7 @@ Standard_Boolean BRepMesh_DiscretFactory::SetDefault( } // try to create dummy tool - BRepMesh_PDiscretRoot anInstancePtr = NULL; + BRepMesh_DiscretRoot* anInstancePtr = NULL; Standard_Integer anErr = aFunc (TopoDS_Shape(), 0.001, 0.1, anInstancePtr); if (anErr != 0 || anInstancePtr == NULL) { @@ -174,7 +174,7 @@ Handle(BRepMesh_DiscretRoot) BRepMesh_DiscretFactory::Discret( const Standard_Real theAngle) { Handle(BRepMesh_DiscretRoot) aDiscretRoot; - BRepMesh_PDiscretRoot anInstancePtr = NULL; + BRepMesh_DiscretRoot* anInstancePtr = NULL; if (myPluginEntry != NULL) { // use plugin diff --git a/src/BRepMesh/BRepMesh_Edge.hxx b/src/BRepMesh/BRepMesh_Edge.hxx index 603c4cc498..5a46ebbb74 100644 --- a/src/BRepMesh/BRepMesh_Edge.hxx +++ b/src/BRepMesh/BRepMesh_Edge.hxx @@ -19,28 +19,26 @@ #include #include -//! Light weighted structure representing link of the mesh. -class BRepMesh_Edge +//! Light weighted structure representing simple link. +class BRepMesh_OrientedEdge { public: DEFINE_STANDARD_ALLOC - + //! Default constructor. - Standard_EXPORT BRepMesh_Edge() - : myFirstNode (-1), - myLastNode (-1), - myMovability(BRepMesh_Deleted) + Standard_EXPORT BRepMesh_OrientedEdge() + : myFirstNode(-1), + myLastNode(-1) { } - //! Contructs a link beetween two vertices. - Standard_EXPORT BRepMesh_Edge(const Standard_Integer theFirstNode, - const Standard_Integer theLastNode, - const BRepMesh_DegreeOfFreedom theMovability) - : myFirstNode (theFirstNode), - myLastNode (theLastNode), - myMovability(theMovability) + //! Constructs a link between two vertices. + Standard_EXPORT BRepMesh_OrientedEdge( + const Standard_Integer theFirstNode, + const Standard_Integer theLastNode) + : myFirstNode(theFirstNode), + myLastNode(theLastNode) { } @@ -55,49 +53,88 @@ public: { return myLastNode; } - + + //! Returns hash code for this edge. + //! @param theUpper upper index in the container. + //! @return hash code. + Standard_EXPORT Standard_Integer HashCode(const Standard_Integer theUpper) const + { + return ::HashCode(myFirstNode + myLastNode, theUpper); + } + + //! Checks this and other edge for equality. + //! @param theOther edge to be checked against this one. + //! @retrun TRUE if edges have the same orientation, FALSE if not. + inline Standard_Boolean IsEqual(const BRepMesh_OrientedEdge& theOther) const + { + return (myFirstNode == theOther.myFirstNode && myLastNode == theOther.myLastNode); + } + + //! Alias for IsEqual. + Standard_Boolean operator ==(const BRepMesh_OrientedEdge& Other) const + { + return IsEqual(Other); + } + +private: + + Standard_Integer myFirstNode; + Standard_Integer myLastNode; +}; + +//! Light weighted structure representing link of the mesh. +class BRepMesh_Edge : public BRepMesh_OrientedEdge +{ +public: + + //! Default constructor. + Standard_EXPORT BRepMesh_Edge() + : BRepMesh_OrientedEdge(), + myMovability(BRepMesh_Deleted) + { + } + + //! Constructs a link between two vertices. + Standard_EXPORT BRepMesh_Edge( + const Standard_Integer theFirstNode, + const Standard_Integer theLastNode, + const BRepMesh_DegreeOfFreedom theMovability) + : BRepMesh_OrientedEdge(theFirstNode, theLastNode), + myMovability(theMovability) + { + } + //! Returns movability flag of the Link. inline BRepMesh_DegreeOfFreedom Movability() const { return myMovability; } - + //! Sets movability flag of the Link. //! \param theMovability flag to be set. inline void SetMovability(const BRepMesh_DegreeOfFreedom theMovability) { myMovability = theMovability; } - - //! Returns hash code for this edge. - //! \param theUpper upper index in the container. - //! \return hash code. - Standard_EXPORT Standard_Integer HashCode(const Standard_Integer theUpper) const - { - return ::HashCode(myFirstNode + myLastNode, theUpper); - } - + //! Checks if the given edge and this one have the same orientation. //! \param theOther edge to be checked against this one. //! \retrun TRUE if edges have the same orientation, FALSE if not. inline Standard_Boolean IsSameOrientation(const BRepMesh_Edge& theOther) const { - return (myFirstNode == theOther.myFirstNode && myLastNode == theOther.myLastNode); + return BRepMesh_OrientedEdge::IsEqual(theOther); } - + //! Checks for equality with another edge. //! \param theOther edge to be checked against this one. //! \return TRUE if equal, FALSE if not. inline Standard_Boolean IsEqual(const BRepMesh_Edge& theOther) const { - if (myMovability == BRepMesh_Deleted || - theOther.myMovability == BRepMesh_Deleted) - { + if (myMovability == BRepMesh_Deleted || theOther.myMovability == BRepMesh_Deleted) return Standard_False; - } - return IsSameOrientation(theOther) || - (myFirstNode == theOther.myLastNode && myLastNode == theOther.myFirstNode); + return IsSameOrientation(theOther) || + (FirstNode() == theOther.LastNode() && LastNode() == theOther.FirstNode()); } //! Alias for IsEqual. @@ -108,11 +145,15 @@ public: private: - Standard_Integer myFirstNode; - Standard_Integer myLastNode; BRepMesh_DegreeOfFreedom myMovability; }; +inline Standard_Integer HashCode(const BRepMesh_OrientedEdge& theEdge, + const Standard_Integer theUpper) +{ + return theEdge.HashCode(theUpper); +} + inline Standard_Integer HashCode(const BRepMesh_Edge& theEdge, const Standard_Integer theUpper) { diff --git a/src/BRepMesh/BRepMesh_EdgeParameterProvider.cxx b/src/BRepMesh/BRepMesh_EdgeParameterProvider.cxx new file mode 100644 index 0000000000..927795635d --- /dev/null +++ b/src/BRepMesh/BRepMesh_EdgeParameterProvider.cxx @@ -0,0 +1,89 @@ +// Created on: 2014-08-13 +// Created by: Oleg AGASHIN +// Copyright (c) 2011-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include +#include +#include +#include +#include +#include + +//======================================================================= +//function : Constructor +//purpose : +//======================================================================= +BRepMesh_EdgeParameterProvider::BRepMesh_EdgeParameterProvider( + const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace, + const Handle(TColStd_HArray1OfReal)& theParameters) + : myParameters(theParameters), + myIsSameParam(BRep_Tool::SameParameter(theEdge)), + myScale(1.) +{ + if (myIsSameParam) + return; + + // Extract actual parametric values + Standard_Real aLastParam; + BRep_Tool::Range(theEdge, theFace, myFirstParam, aLastParam); + + myFoundParam = myCurParam = myFirstParam; + + // Extract parameters stored in polygon + myOldFirstParam = + myParameters->Value(myParameters->Lower()); + + const Standard_Real aOldLastParam = + myParameters->Value(myParameters->Upper()); + + // Calculate scale factor between actual and stored parameters + if ((myOldFirstParam != myFirstParam || aOldLastParam != aLastParam) && + myOldFirstParam != aOldLastParam) + { + myScale = (aLastParam - myFirstParam) / + (aOldLastParam - myOldFirstParam); + } + + BRepAdaptor_Curve aCOnS(theEdge, theFace); + myProjector.Initialize(aCOnS, aCOnS.FirstParameter(), + aCOnS.LastParameter(), Precision::PConfusion()); +} + +//======================================================================= +//function : Parameter +//purpose : +//======================================================================= +Standard_Real BRepMesh_EdgeParameterProvider::Parameter( + const Standard_Integer theIndex, + const gp_Pnt& thePoint3d) +{ + if (myIsSameParam) + return myParameters->Value(theIndex); + + // Use scaled + Standard_Real aPrevParam = myCurParam; + myCurParam = myFirstParam + myScale * + (myParameters->Value(theIndex) - myOldFirstParam); + + myFoundParam += (myCurParam - aPrevParam); + + myProjector.Perform(thePoint3d, myFoundParam); + if (myProjector.IsDone()) + myFoundParam = myProjector.Point().Parameter(); + + return myFoundParam; +} diff --git a/src/BRepMesh/BRepMesh_EdgeParameterProvider.hxx b/src/BRepMesh/BRepMesh_EdgeParameterProvider.hxx new file mode 100644 index 0000000000..1a250db71f --- /dev/null +++ b/src/BRepMesh/BRepMesh_EdgeParameterProvider.hxx @@ -0,0 +1,69 @@ +// Created on: 2014-08-13 +// Created by: Oleg AGASHIN +// Copyright (c) 2011-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepMesh_EdgeParameterProvider_HeaderFile +#define _BRepMesh_EdgeParameterProvider_HeaderFile + +#include +#include +#include +#include + +class gp_Pnt; +class TopoDS_Edge; +class TopoDS_Face; +class TColStd_HArray1OfReal; + +//! Auxiliary class provides correct parameters +//! on curve regarding SameParameter flag. +class BRepMesh_EdgeParameterProvider +{ +public: + + DEFINE_STANDARD_ALLOC + + //! Constructor. + //! @param theEdge edge which parameters should be processed. + //! @param theFace face the parametric values are defined for. + //! @param theParameters parameters corresponded to discretization points. + BRepMesh_EdgeParameterProvider( + const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace, + const Handle(TColStd_HArray1OfReal)& theParameters); + + //! Returns parameter according to SameParameter flag of the edge. + //! If SameParameter is TRUE returns value from parameters w/o changes, + //! elsewhere scales initial parameter and tries to determine resulting + //! value using projection of the corresponded 3D point on PCurve. + Standard_Real Parameter(const Standard_Integer theIndex, + const gp_Pnt& thePoint3d); + +private: + + Handle(TColStd_HArray1OfReal) myParameters; + + Standard_Boolean myIsSameParam; + Standard_Real myFirstParam; + + Standard_Real myOldFirstParam; + Standard_Real myScale; + + Standard_Real myCurParam; + Standard_Real myFoundParam; + + Extrema_LocateExtPC myProjector; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx new file mode 100644 index 0000000000..89ab5dc981 --- /dev/null +++ b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx @@ -0,0 +1,59 @@ +// Created on: 2014-08-13 +// Created by: Oleg AGASHIN +// Copyright (c) 2011-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include +#include +#include + +IMPLEMENT_STANDARD_HANDLE (BRepMesh_EdgeTessellationExtractor, BRepMesh_IEdgeTool) +IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_EdgeTessellationExtractor, BRepMesh_IEdgeTool) + +//======================================================================= +//function : Constructor +//purpose : +//======================================================================= +BRepMesh_EdgeTessellationExtractor::BRepMesh_EdgeTessellationExtractor( + const TopoDS_Edge& theEdge, + const Handle(Geom2d_Curve)& thePCurve, + const TopoDS_Face& theFace, + const Handle(Poly_Triangulation)& theTriangulation, + const Handle(Poly_PolygonOnTriangulation)& thePolygon, + const TopLoc_Location& theLocation) + : myProvider(theEdge, theFace, thePolygon->Parameters()), + myPCurve(thePCurve), + myNodes(theTriangulation->Nodes()), + myIndices(thePolygon->Nodes()), + myLoc(theLocation) +{ +} + +//======================================================================= +//function : Value +//purpose : +//======================================================================= +void BRepMesh_EdgeTessellationExtractor::Value( + const Standard_Integer theIndex, + Standard_Real& theParameter, + gp_Pnt& thePoint, + gp_Pnt2d& theUV) +{ + const gp_Pnt& theRefPnt = myNodes(myIndices(theIndex)); + thePoint = BRepMesh_ShapeTool::UseLocation(theRefPnt, myLoc); + + theParameter = myProvider.Parameter(theIndex, thePoint); + theUV = myPCurve->Value(theParameter); +} diff --git a/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx new file mode 100644 index 0000000000..b150005a82 --- /dev/null +++ b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx @@ -0,0 +1,87 @@ +// Created on: 2014-08-13 +// Created by: Oleg AGASHIN +// Copyright (c) 2011-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepMesh_EdgeTessellationExtractor_HeaderFile +#define _BRepMesh_EdgeTessellationExtractor_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Poly_Triangulation; +class Poly_PolygonOnTriangulation; +class TopoDS_Edge; +class TopoDS_Face; + +//! Auxiliary class implements functionality retrieving tessellated +//! representation of an edge stored in polygon. +class BRepMesh_EdgeTessellationExtractor : public BRepMesh_IEdgeTool +{ +public: + + //! Constructor. + //! Initializes extractor. + BRepMesh_EdgeTessellationExtractor( + const TopoDS_Edge& theEdge, + const Handle(Geom2d_Curve)& thePCurve, + const TopoDS_Face& theFace, + const Handle(Poly_Triangulation)& theTriangulation, + const Handle(Poly_PolygonOnTriangulation)& thePolygon, + const TopLoc_Location& theLocation); + + //! Returns number of dicretization points. + virtual Standard_Integer NbPoints() const + { + return myIndices.Length(); + } + + //! Returns parameters of solution with the given index. + //! @param theIndex index of tessellation point. + //! @param theParameter parameters on PCurve corresponded to the solution. + //! @param thePoint tessellation point. + //! @param theUV coordinates of tessellation point in parametric space of face. + virtual void Value(const Standard_Integer theIndex, + Standard_Real& theParameter, + gp_Pnt& thePoint, + gp_Pnt2d& theUV); + + DEFINE_STANDARD_RTTI(BRepMesh_EdgeTessellationExtractor) + +private: + + //! Assignment operator. + void operator =(const BRepMesh_EdgeTessellationExtractor& /*theOther*/) + { + } + +private: + + BRepMesh_EdgeParameterProvider myProvider; + const Handle(Geom2d_Curve)& myPCurve; + const TColgp_Array1OfPnt& myNodes; + const TColStd_Array1OfInteger& myIndices; + const TopLoc_Location myLoc; +}; + +DEFINE_STANDARD_HANDLE(BRepMesh_EdgeTessellationExtractor, BRepMesh_IEdgeTool) + +#endif diff --git a/src/BRepMesh/BRepMesh_EdgeTessellator.cxx b/src/BRepMesh/BRepMesh_EdgeTessellator.cxx new file mode 100644 index 0000000000..2347a2840f --- /dev/null +++ b/src/BRepMesh/BRepMesh_EdgeTessellator.cxx @@ -0,0 +1,217 @@ +// Created on: 2014-08-13 +// Created by: Oleg AGASHIN +// Copyright (c) 2011-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +IMPLEMENT_STANDARD_HANDLE (BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool) +IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool) + +//======================================================================= +//function : Constructor +//purpose : +//======================================================================= +BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator( + const TopoDS_Edge& theEdge, + const Handle(BRepMesh_FaceAttribute)& theFaceAttribute, + const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces, + const Standard_Real theLinDeflection, + const Standard_Real theAngDeflection) + : mySurface(theFaceAttribute->Surface()) +{ + Standard_Real aPreciseAngDef = 0.5 * theAngDeflection; + Standard_Real aPreciseLinDef = 0.5 * theLinDeflection; + if (theEdge.Orientation() == TopAbs_INTERNAL) + aPreciseLinDef *= 0.5; + + mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef; + + Standard_Boolean isSameParam = BRep_Tool::SameParameter(theEdge); + if (isSameParam) + myCOnS.Initialize(theEdge); + else + myCOnS.Initialize(theEdge, theFaceAttribute->Face()); + + TopLoc_Location aLoc; + const GeomAbs_CurveType aCurveType = myCOnS.GetType(); + Standard_Integer aMinPntNb = (aCurveType == GeomAbs_Circle) ? 4 : 2; //OCC287 + + // Get range on 2d curve + Standard_Real aFirstParam, aLastParam; + BRep_Tool::Range(theEdge, theFaceAttribute->Face(), aFirstParam, aLastParam); + myTool = new BRepMesh_GeomTool(myCOnS, aFirstParam, aLastParam, + aPreciseLinDef, aPreciseAngDef, aMinPntNb); + + if (aCurveType == GeomAbs_BSplineCurve) + { + // TODO: remove this code block when #24959 is fixed + const Standard_Integer aNbInt = myCOnS.NbIntervals(GeomAbs_C1); + if ( aNbInt > 0 ) + { + TColStd_Array1OfReal anIntervals( 1, aNbInt + 1 ); + myCOnS.Intervals(anIntervals, GeomAbs_C1); + for (Standard_Integer aIntIt = 1; aIntIt <= aNbInt; ++aIntIt) + { + const Standard_Real& aStartInt = anIntervals.Value( aIntIt ); + const Standard_Real& anEndInt = anIntervals.Value( aIntIt + 1 ); + + BRepMesh_GeomTool aDetalizator(myCOnS, aStartInt, anEndInt, + aPreciseLinDef, aPreciseAngDef, aMinPntNb); + + Standard_Integer aNbAddNodes = aDetalizator.NbPoints(); + for ( Standard_Integer aNodeIt = 1; aNodeIt <= aNbAddNodes; ++aNodeIt ) + { + Standard_Real aParam; + gp_Pnt aPoint3d; + gp_Pnt2d aPoint2d; + aDetalizator.Value( aNodeIt, mySurface, aParam, aPoint3d, aPoint2d ); + myTool->AddPoint( aPoint3d, aParam, Standard_False ); + } + } + } + } + + // PTv, chl/922/G9, Take into account internal vertices + // it is necessary for internal edges, which do not split other edges, by their vertex + TopExp_Explorer aVertexIt(theEdge, TopAbs_VERTEX); + for (; aVertexIt.More(); aVertexIt.Next()) + { + const TopoDS_Vertex& aVertex = TopoDS::Vertex(aVertexIt.Current()); + if (aVertex.Orientation() != TopAbs_INTERNAL) + continue; + + myTool->AddPoint(BRep_Tool::Pnt(aVertex), + BRep_Tool::Parameter(aVertex, theEdge), Standard_True); + } + + Standard_Integer aNodesNb = myTool->NbPoints(); + //Check deflection in 2d space for improvement of edge tesselation. + if( isSameParam && aNodesNb > 1) + { + const TopTools_ListOfShape& aSharedFaces = theMapOfSharedFaces.FindFromKey(theEdge); + TopTools_ListIteratorOfListOfShape aFaceIt(aSharedFaces); + for (; aFaceIt.More(); aFaceIt.Next()) + { + TopLoc_Location aLoc; + const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Value()); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc); + + if (aSurf->IsInstance(STANDARD_TYPE(Geom_Plane))) + continue; + + Standard_Real aF, aL; + Handle(Geom2d_Curve) aCurve2d = BRep_Tool::CurveOnSurface(theEdge, aFace, aF, aL); + if ( Abs(aF - aFirstParam) > Precision::PConfusion() || + Abs(aL - aLastParam ) > Precision::PConfusion() ) + { + continue; + } + + aNodesNb = myTool->NbPoints(); + TColStd_Array1OfReal aParamArray(1, aNodesNb); + for (Standard_Integer i = 1; i <= aNodesNb; ++i) + { + gp_Pnt2d aTmpUV; + gp_Pnt aTmpPnt; + Standard_Real aParam; + myTool->Value(i, mySurface, aParam, aTmpPnt, aTmpUV); + aParamArray.SetValue(i, aParam); + } + + for (Standard_Integer i = 1; i < aNodesNb; ++i) + splitSegment(aSurf, aCurve2d, aParamArray(i), aParamArray(i + 1), 1); + } + } +} + +//======================================================================= +//function : Value +//purpose : +//======================================================================= +void BRepMesh_EdgeTessellator::Value(const Standard_Integer theIndex, + Standard_Real& theParameter, + gp_Pnt& thePoint, + gp_Pnt2d& theUV) +{ + myTool->Value(theIndex, mySurface, theParameter, thePoint, theUV); +} + +//======================================================================= +//function : splitSegment +//purpose : +//======================================================================= +void BRepMesh_EdgeTessellator::splitSegment( + const Handle(Geom_Surface)& theSurf, + const Handle(Geom2d_Curve)& theCurve2d, + const Standard_Real theFirst, + const Standard_Real theLast, + const Standard_Integer theNbIter) +{ + // limit iteration depth + if(theNbIter > 10) + return; + + gp_Pnt2d uvf, uvl, uvm; + gp_Pnt P3dF, P3dL, midP3d, midP3dFromSurf; + Standard_Real midpar; + + if(Abs(theLast - theFirst) < 2 * Precision::PConfusion()) + return; + + theCurve2d->D0(theFirst, uvf); + theCurve2d->D0(theLast, uvl); + + P3dF = theSurf->Value(uvf.X(), uvf.Y()); + P3dL = theSurf->Value(uvl.X(), uvl.Y()); + + if(P3dF.SquareDistance(P3dL) < mySquareEdgeDef) + return; + + uvm = gp_Pnt2d((uvf.XY() + uvl.XY())*0.5); + midP3dFromSurf = theSurf->Value(uvm.X(), uvm.Y()); + + gp_XYZ aVec = P3dL.XYZ() - P3dF.XYZ(); + aVec.Normalize(); + + gp_XYZ Vec1 = midP3dFromSurf.XYZ() - P3dF.XYZ(); + Standard_Real aModulus = Vec1.Dot(aVec); + gp_XYZ aProj = aVec * aModulus; + gp_XYZ aDist = Vec1 - aProj; + + if(aDist.SquareModulus() < mySquareEdgeDef) + return; + + midpar = (theFirst + theLast) * 0.5; + myCOnS.D0(midpar, midP3d); + myTool->AddPoint(midP3d, midpar, Standard_False); + + splitSegment(theSurf, theCurve2d, theFirst, midpar, theNbIter + 1); + splitSegment(theSurf, theCurve2d, midpar, theLast, theNbIter + 1); +} diff --git a/src/BRepMesh/BRepMesh_EdgeTessellator.hxx b/src/BRepMesh/BRepMesh_EdgeTessellator.hxx new file mode 100644 index 0000000000..d64bf6705a --- /dev/null +++ b/src/BRepMesh/BRepMesh_EdgeTessellator.hxx @@ -0,0 +1,88 @@ +// Created on: 2014-08-13 +// Created by: Oleg AGASHIN +// Copyright (c) 2011-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepMesh_EdgeTessellator_HeaderFile +#define _BRepMesh_EdgeTessellator_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Geom_Surface; +class Geom2d_Curve; +class TopoDS_Edge; +class BRepAdaptor_HSurface; +class TopTools_IndexedDataMapOfShapeListOfShape; + +//! Auxiliary class implements functionality producing tessellated +//! representation of an edge based on edge geometry. +class BRepMesh_EdgeTessellator : public BRepMesh_IEdgeTool +{ +public: + + //! Constructor. + //! Automatically performs tessellation of the edge according to the + //! given parameters. + BRepMesh_EdgeTessellator( + const TopoDS_Edge& theEdge, + const Handle(BRepMesh_FaceAttribute)& theFaceAttribute, + const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces, + const Standard_Real theLinDeflection, + const Standard_Real theAngDeflection); + + //! Returns number of dicretization points. + virtual Standard_Integer NbPoints() const + { + return myTool->NbPoints(); + } + + //! Returns parameters of solution with the given index. + //! @param theIndex index of tessellation point. + //! @param theParameter parameters on PCurve corresponded to the solution. + //! @param thePoint tessellation point. + //! @param theUV coordinates of tessellation point in parametric space of face. + virtual void Value(const Standard_Integer theIndex, + Standard_Real& theParameter, + gp_Pnt& thePoint, + gp_Pnt2d& theUV); + + DEFINE_STANDARD_RTTI(BRepMesh_EdgeTessellator) + +private: + + //! + void splitSegment(const Handle(Geom_Surface)& theSurf, + const Handle(Geom2d_Curve)& theCurve2d, + const Standard_Real theFirst, + const Standard_Real theLast, + const Standard_Integer theNbIter); + +private: + N_HANDLE myTool; + Handle(BRepAdaptor_HSurface) mySurface; + BRepAdaptor_Curve myCOnS; + Standard_Real mySquareEdgeDef; +}; + +DEFINE_STANDARD_HANDLE(BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool) + +#endif diff --git a/src/BRepMesh/BRepMesh_FaceAttribute.cxx b/src/BRepMesh/BRepMesh_FaceAttribute.cxx index 0ce1d9ce37..716f3e04e6 100644 --- a/src/BRepMesh/BRepMesh_FaceAttribute.cxx +++ b/src/BRepMesh/BRepMesh_FaceAttribute.cxx @@ -13,16 +13,154 @@ // commercial license or contractual agreement. #include +#include +#include +#include +#include +#include IMPLEMENT_STANDARD_HANDLE (BRepMesh_FaceAttribute, Standard_Transient) IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FaceAttribute, Standard_Transient) //======================================================================= -//function : BRepMesh_FaceAttribute +//function : Constructor //purpose : //======================================================================= -BRepMesh_FaceAttribute::BRepMesh_FaceAttribute(): - mydefface(0.), myumin(0.), myumax(0.), myvmin(0.), myvmax(0.), - mydeltaX(1.), mydeltaY(1.), myminX(0.), myminY(0.) +BRepMesh_FaceAttribute::BRepMesh_FaceAttribute( + const TopoDS_Face& theFace, + BRepMeshCol::DMapOfVertexInteger& theBoundaryVertices, + BRepMeshCol::DMapOfIntegerPnt& theBoundaryPoints) + : myDefFace (0.), + myUMin (0.), + myUMax (0.), + myVMin (0.), + myVMax (0.), + myDeltaX (1.), + myDeltaY (1.), + myStatus (BRepMesh_NoError), + myBoundaryVertices(theBoundaryVertices), + myBoundaryPoints (theBoundaryPoints), + myAllocator (new NCollection_IncAllocator(64000)) { + myVertexEdgeMap = new BRepMeshCol::IMapOfInteger; + myInternalEdges = new BRepMeshCol::DMapOfShapePairOfPolygon; + mySurfacePoints = new BRepMeshCol::DMapOfIntegerPnt; + myClassifier = new BRepMesh_Classifier; + + myFace = theFace; + BRepTools::Update(myFace); + myFace.Orientation(TopAbs_FORWARD); + + BRepAdaptor_Surface aSurfAdaptor(myFace, Standard_False); + mySurface = new BRepAdaptor_HSurface(aSurfAdaptor); + + ResetStructure(); +} + +//======================================================================= +//function : Destructor +//purpose : +//======================================================================= +BRepMesh_FaceAttribute::~BRepMesh_FaceAttribute() +{ + clearLocal(); + + mySurfaceVertices.Clear(); + mySurfacePoints->Clear(); + + myClassifier.Nullify(); + myAllocator.Nullify(); +} + +//======================================================================= +//function : clearLocal +//purpose : +//======================================================================= +void BRepMesh_FaceAttribute::clearLocal() +{ + myStructure.Nullify(); + + myLocation2D.Clear(); + myVertexEdgeMap->Clear(); + myInternalEdges->Clear(); + + myAllocator->Reset(Standard_False); +} + +//======================================================================= +//function : ResetStructure +//purpose : +//======================================================================= +Handle(BRepMesh_DataStructureOfDelaun)& BRepMesh_FaceAttribute::ResetStructure() +{ + clearLocal(); + myStructure = new BRepMesh_DataStructureOfDelaun(myAllocator); + + BRepTools::UVBounds(myFace, myUMin, myUMax, myVMin, myVMax); + Standard_Real aTolU = ToleranceU(); + Standard_Real aTolV = ToleranceV(); + + myStructure->Data().SetCellSize(14.0 * aTolU, 14.0 * aTolV); + myStructure->Data().SetTolerance(aTolU, aTolV); + return myStructure; +} + +//======================================================================= +//function : computeParametricTolerance +//purpose : +//======================================================================= +Standard_Real BRepMesh_FaceAttribute::computeParametricTolerance( + const Standard_Real theFirstParam, + const Standard_Real theLastParam) const +{ + const Standard_Real aDeflectionUV = 1.e-05; + return Max(Precision::PConfusion(), (theLastParam - theFirstParam) * aDeflectionUV); +} + +//======================================================================= +//function : getVertexIndex +//purpose : +//======================================================================= +Standard_Boolean BRepMesh_FaceAttribute::getVertexIndex( + const TopoDS_Vertex& theVertex, + Standard_Integer& theVertexIndex) const +{ + if (myBoundaryVertices.IsBound(theVertex)) + theVertexIndex = myBoundaryVertices.Find(theVertex); + else if (mySurfaceVertices.IsBound(theVertex)) + theVertexIndex = mySurfaceVertices.Find(theVertex); + else + return Standard_False; + + return Standard_True; +} + +//======================================================================= +//function : AddNode +//purpose : +//======================================================================= +void BRepMesh_FaceAttribute::AddNode( + const Standard_Integer theIndex, + const gp_XY& theUV, + const BRepMesh_DegreeOfFreedom theMovability, + Standard_Integer& theNodeIndex, + Standard_Integer& theNodeOnEdgeIndex) +{ + BRepMesh_Vertex aNode(theUV, theIndex, theMovability); + theNodeIndex = myStructure->AddNode(aNode); + theNodeOnEdgeIndex = myVertexEdgeMap->FindIndex(theNodeIndex); + if (theNodeOnEdgeIndex == 0) + theNodeOnEdgeIndex = myVertexEdgeMap->Add(theNodeIndex); +} + +//======================================================================= +//function : Scale +//purpose : +//======================================================================= +gp_XY BRepMesh_FaceAttribute::Scale(const gp_XY& thePoint2d, + const Standard_Boolean isToFaceBasis) +{ + return isToFaceBasis ? + gp_XY((thePoint2d.X() - myUMin) / myDeltaX, (thePoint2d.Y() - myVMin) / myDeltaY) : + gp_XY(thePoint2d.X() * myDeltaX + myUMin, thePoint2d.Y() * myDeltaY + myVMin); } diff --git a/src/BRepMesh/BRepMesh_FaceAttribute.hxx b/src/BRepMesh/BRepMesh_FaceAttribute.hxx index bd856b38d7..94d9068426 100644 --- a/src/BRepMesh/BRepMesh_FaceAttribute.hxx +++ b/src/BRepMesh/BRepMesh_FaceAttribute.hxx @@ -15,83 +15,341 @@ #define _BRepMesh_FaceAttribute_HeaderFile #include -#include -#include #include +#include +#include +#include +#include +#include -//! auxiliary class for FastDiscret and FastDiscretFace classes
+class BRepAdaptor_HSurface; + +//! Auxiliary class for FastDiscret and FastDiscretFace classes. class BRepMesh_FaceAttribute : public Standard_Transient { public: - Standard_EXPORT BRepMesh_FaceAttribute(); + //! Constructor. + //! @param theFace face the attribute is created for. + //! Used for default initialization. Attribute keeps reference + //! to the source face with forward orientation. + //! @param theBoundaryVertices shared map of shape vertices. + //! @param theBoundaryPoints shared discretization points of shape boundaries. + Standard_EXPORT BRepMesh_FaceAttribute( + const TopoDS_Face& theFace, + BRepMeshCol::DMapOfVertexInteger& theBoundaryVertices, + BRepMeshCol::DMapOfIntegerPnt& theBoundaryPoints); + + //! Destructor. + virtual ~BRepMesh_FaceAttribute(); + +public: //! @name main geometrical properties. + + //! Returns face's surface. + inline const Handle(BRepAdaptor_HSurface)& Surface() const + { + return mySurface; + } + + //! Returns forward oriented face to be used for calculations. + inline const TopoDS_Face& Face() const + { + return myFace; + } + + //! Returns U tolerance of face calculated regarding its parameters. + inline Standard_Real ToleranceU() const + { + return computeParametricTolerance(myUMin, myUMax); + } + + //! Returns V tolerance of face calculated regarding its parameters. + inline Standard_Real ToleranceV() const + { + return computeParametricTolerance(myVMin, myVMax); + } + + //! Gives face deflection parameter. + inline Standard_Real GetDefFace() const + { + return myDefFace; + } + + //! Sets face deflection. + inline void SetDefFace(const Standard_Real theDefFace) + { + myDefFace = theDefFace; + } + + //! Gives minimal value in U domain. + inline Standard_Real GetUMin() const + { + return myUMin; + } + + //! Sets minimal value in U domain. + inline void SetUMin(const Standard_Real theUMin) + { + myUMin = theUMin; + } + + //! Gives minimal value in V domain. + inline Standard_Real GetVMin() const + { + return myVMin; + } + + //! Sets minimal value in V domain. + inline void SetVMin(const Standard_Real theVMin) + { + myVMin = theVMin; + } + + //! Gives maximal value in U domain. + inline Standard_Real GetUMax() const + { + return myUMax; + } + + //! Sets maximal value in U domain. + inline void SetUMax(const Standard_Real theUMax) + { + myUMax = theUMax; + } + + //! Gives maximal value in V domain. + inline Standard_Real GetVMax() const + { + return myVMax; + } + + //! Sets maximal value in V domain. + inline void SetVMax(const Standard_Real theVMax) + { + myVMax = theVMax; + } + + //! Gives value of step in U domain. + inline Standard_Real GetDeltaX() const + { + return myDeltaX; + } + + //! Sets value of step in U domain. + inline void SetDeltaX(const Standard_Real theDeltaX) + { + myDeltaX = theDeltaX; + } + + //! Gives value of step in V domain. + inline Standard_Real GetDeltaY() const + { + return myDeltaY; + } + + //! Sets value of step in V domain. + inline void SetDeltaY(const Standard_Real theDeltaY) + { + myDeltaY = theDeltaY; + } + + //! Sets set of status flags for this face. + inline Standard_Integer GetStatus() const + { + return myStatus; + } + + //! Sets status flag for this face. + inline void SetStatus(const BRepMesh_Status theStatus) + { + myStatus |= theStatus; + } + + //! Returns TRUE in case if computed data is valid. + inline Standard_Boolean IsValid() const + { + return (myStatus == BRepMesh_NoError || myStatus == BRepMesh_ReMesh); + } + +public: //! @name auxiliary structures + + //! Clear all face attribute. + Standard_EXPORT void Clear(); + + //! Resets mesh data structure. + //! @returns reset data structure. + Standard_EXPORT Handle(BRepMesh_DataStructureOfDelaun)& ResetStructure(); + + //! Gives reference to map of internal edges of face. + inline BRepMeshCol::HDMapOfShapePairOfPolygon& ChangeInternalEdges() + { + return myInternalEdges; + } + + //! Gives reference to map of 2D points of discretization. + inline BRepMeshCol::DMapOfIntegerListOfXY& ChangeLocation2D() + { + return myLocation2D; + } + + //! Gives reference to map of 3D points of discretization. + inline BRepMeshCol::HDMapOfIntegerPnt& ChangeSurfacePoints() + { + return mySurfacePoints; + } + + //! Gives reference on map of (vertex, edge) pairs of face. + inline BRepMeshCol::HIMapOfInteger& ChangeVertexEdgeMap() + { + return myVertexEdgeMap; + } + + //! Gives Delaunay data structure. + inline Handle(BRepMesh_DataStructureOfDelaun)& ChangeStructure() + { + return myStructure; + } + + //! Returns classifier. + inline BRepMeshCol::HClassifier& ChangeClassifier() + { + return myClassifier; + } + +public: //! @name Point/Vertex/Node manipulators + + //! Gives the number of different locations in 3D space. + inline Standard_Integer LastPointId() const + { + return myBoundaryPoints.Extent() + mySurfacePoints->Extent(); + } + + //! Gives the 3D location of the vertex. + inline const gp_Pnt& GetPoint(const BRepMesh_Vertex& theVertex) const + { + return GetPoint(theVertex.Location3d()); + } + + //! Gives the 3D location of the vertex. + inline const gp_Pnt& GetPoint(const Standard_Integer theIndex) const + { + if (theIndex > myBoundaryPoints.Extent()) + return mySurfacePoints->Find(theIndex); + + return myBoundaryPoints(theIndex); + } + + //! Returns index of the given vertex if it exists in cache, + //! elsewhere adds it to cache and returns cached index. + //! @param theVertexExplorer template parameter intended to transfer + //! parameters of vertex to method. Explorer class can implement different + //! approaches of extraction of target parameters. + //! @param isFillEdgeVertices if TRUE adds vertex to shared map of + //! edges vertices, elsewhere adds it map of face vertices. + template + Standard_Integer GetVertexIndex( + const HVertexExplorer& theVertexExplorer, + const Standard_Boolean isFillEdgeVertices = Standard_False) + { + const TopoDS_Vertex& aVertex = theVertexExplorer->Vertex(); + Standard_Integer aNewVertexIndex = 0; + if (getVertexIndex(aVertex, aNewVertexIndex)) + return aNewVertexIndex; + + if (!theVertexExplorer->IsSameUV() || + !getVertexIndex(theVertexExplorer->SameVertex(), aNewVertexIndex)) + { + aNewVertexIndex = LastPointId() + 1; + + BRepMeshCol::DMapOfIntegerPnt& aPointsMap = isFillEdgeVertices ? + myBoundaryPoints : *mySurfacePoints; + + aPointsMap.Bind(aNewVertexIndex, theVertexExplorer->Point()); + } + + BRepMeshCol::DMapOfVertexInteger& aVertexMap = isFillEdgeVertices ? + myBoundaryVertices : mySurfaceVertices; + + aVertexMap.Bind(aVertex, aNewVertexIndex); + + return aNewVertexIndex; + } + + //! Adds node with the given parameters to mesh. + //! @param theIndex index of 3D point corresponded to the node. + //! @param theUV node position. + //! @param theMovability movability of a node. + //! @param theNodeIndex index of vertex in mesh structure. + //! @param theNodeOnEdgeIndex ordered index of node on the boundary. + Standard_EXPORT void AddNode(const Standard_Integer theIndex, + const gp_XY& theUV, + const BRepMesh_DegreeOfFreedom theMovability, + Standard_Integer& theNodeIndex, + Standard_Integer& theNodeOnEdgeIndex); + +public: //! @name Auxiliary methods - inline Standard_Real& GetDefFace() - { - return mydefface; - } - - inline Standard_Real& GetUMin() - { - return myumin; - } - - inline Standard_Real& GetVMin() - { - return myvmin; - } - - inline Standard_Real& GetUMax() - { - return myumax; - } - - inline Standard_Real& GetVMax() - { - return myvmax; - } - - inline Standard_Real& GetDeltaX() - { - return mydeltaX; - } - - inline Standard_Real& GetDeltaY() - { - return mydeltaY; - } - - inline Standard_Real& GetMinX() - { - return myminX; - } - - inline Standard_Real& GetMinY() - { - return myminY; - } - - inline BRepMeshCol::HClassifier& GetClassifier() - { - return myclassifier; - } - + //! Scales the given point from real parametric space + //! to face basis and otherwise. + //! @param thePoint2d point to be scaled. + //! @param isToFaceBasis if TRUE converts point to face basis, + //! otherwise performs reverse conversion. + //! @return scaled point. + Standard_EXPORT gp_XY Scale(const gp_XY& thePoint2d, + const Standard_Boolean isToFaceBasis); DEFINE_STANDARD_RTTI(BRepMesh_FaceAttribute) -private: +private: - Standard_Real mydefface; - Standard_Real myumin; - Standard_Real myumax; - Standard_Real myvmin; - Standard_Real myvmax; - Standard_Real mydeltaX; - Standard_Real mydeltaY; - Standard_Real myminX; - Standard_Real myminY; - BRepMeshCol::HClassifier myclassifier; + //! Assignment operator. + void operator =(const BRepMesh_FaceAttribute& /*theOther*/) + { + } + + //! Computes parametric tolerance of a face regarding the given limits. + Standard_Real computeParametricTolerance( + const Standard_Real theFirstParam, + const Standard_Real theLastParam) const; + + //! Clears internal data structures local to face. + void clearLocal(); + + //! Returns index of the given vertex if it exists in cache. + //! @param theVertex vertex which index should be retrieved. + //! @param theVertexIndex index of the given vertex. + //! @return TRUE if cached value is found, FALSE elsewhere. + Standard_EXPORT Standard_Boolean getVertexIndex( + const TopoDS_Vertex& theVertex, + Standard_Integer& theVertexIndex) const; + +private: + + Standard_Real myDefFace; //!< Restore face deflection + Standard_Real myUMin; //!< Describes minimal value in U domain + Standard_Real myUMax; //!< Describes maximal value in U domain + Standard_Real myVMin; //!< Describes minimal value in V domain + Standard_Real myVMax; //!< Describes maximal value in V domain + Standard_Real myDeltaX; + Standard_Real myDeltaY; + Standard_Integer myStatus; + + BRepMeshCol::DMapOfVertexInteger& myBoundaryVertices; + BRepMeshCol::DMapOfIntegerPnt& myBoundaryPoints; + + TopoDS_Face myFace; + Handle(BRepAdaptor_HSurface) mySurface; + BRepMeshCol::DMapOfVertexInteger mySurfaceVertices; + BRepMeshCol::HDMapOfIntegerPnt mySurfacePoints; + + BRepMeshCol::DMapOfIntegerListOfXY myLocation2D; + BRepMeshCol::HIMapOfInteger myVertexEdgeMap; + BRepMeshCol::HDMapOfShapePairOfPolygon myInternalEdges; + + Handle(BRepMesh_DataStructureOfDelaun) myStructure; + BRepMeshCol::HClassifier myClassifier; + BRepMeshCol::Allocator myAllocator; }; DEFINE_STANDARD_HANDLE(BRepMesh_FaceAttribute, Standard_Transient) diff --git a/src/BRepMesh/BRepMesh_FastDiscret.cxx b/src/BRepMesh/BRepMesh_FastDiscret.cxx index 87ca40a802..ba76f40996 100644 --- a/src/BRepMesh/BRepMesh_FastDiscret.cxx +++ b/src/BRepMesh/BRepMesh_FastDiscret.cxx @@ -23,7 +23,10 @@ #include #include #include -#include +#include +#include +#include +#include #include #include @@ -33,7 +36,6 @@ #include #include #include -#include #include #include @@ -46,7 +48,6 @@ #include #include -#include #include #include #include @@ -54,7 +55,6 @@ #include #include -#include #include #include @@ -85,25 +85,24 @@ IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscret, Standard_Transient) //function : BRepMesh_FastDiscret //purpose : //======================================================================= -BRepMesh_FastDiscret::BRepMesh_FastDiscret(const Standard_Real theDefle, - const Standard_Real theAngl, - const Bnd_Box& theBox, - const Standard_Boolean theWithShare, - const Standard_Boolean theInshape, - const Standard_Boolean theRelative, - const Standard_Boolean theShapetrigu, - const Standard_Boolean isInParallel) +BRepMesh_FastDiscret::BRepMesh_FastDiscret( + const Standard_Real theDefle, + const Standard_Real theAngl, + const Bnd_Box& theBox, + const Standard_Boolean theWithShare, + const Standard_Boolean theInshape, + const Standard_Boolean theRelative, + const Standard_Boolean theShapetrigu, + const Standard_Boolean isInParallel) : myAngle (theAngl), myDeflection (theDefle), myWithShare (theWithShare), myInParallel (isInParallel), - myNbLocat (0), myRelative (theRelative), myShapetrigu (theShapetrigu), myInshape (theInshape) { - myAllocator = new NCollection_IncAllocator(64000); - if(myRelative) + if ( myRelative ) BRepMesh_ShapeTool::BoxMaxDimension(theBox, myDtotale); } @@ -111,7 +110,6 @@ BRepMesh_FastDiscret::BRepMesh_FastDiscret(const Standard_Real theDefle, //function : BRepMesh_FastDiscret //purpose : //======================================================================= - BRepMesh_FastDiscret::BRepMesh_FastDiscret(const TopoDS_Shape& theShape, const Standard_Real theDefle, const Standard_Real theAngl, @@ -125,64 +123,53 @@ BRepMesh_FastDiscret::BRepMesh_FastDiscret(const TopoDS_Shape& theShape, myDeflection (theDefle), myWithShare (theWithShare), myInParallel (isInParallel), - myNbLocat (0), myRelative (theRelative), myShapetrigu (theShapetrigu), myInshape (theInshape) { - myAllocator = new NCollection_IncAllocator(64000); - if(myRelative) + if ( myRelative ) BRepMesh_ShapeTool::BoxMaxDimension(theBox, myDtotale); + Perform(theShape); } //======================================================================= -//function : SetParallel -//purpose : +//function : InitSharedFaces +//purpose : //======================================================================= -void BRepMesh_FastDiscret::SetParallel (const Standard_Boolean theInParallel) +void BRepMesh_FastDiscret::InitSharedFaces(const TopoDS_Shape& theShape) { - myInParallel = theInParallel; -} - -//======================================================================= -//function : IsParallel -//purpose : -//======================================================================= -Standard_Boolean BRepMesh_FastDiscret::IsParallel() const -{ - return myInParallel; + TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, mySharedFaces); } //======================================================================= //function : Perform(shape) //purpose : //======================================================================= - void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape) { - TopTools_IndexedDataMapOfShapeListOfShape anAncestors; - TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, anAncestors); + InitSharedFaces(theShape); + std::vector aFaces; - for (TopExp_Explorer ex(theShape, TopAbs_FACE); ex.More(); ex.Next()) { - TopoDS_Face aF = TopoDS::Face(ex.Current()); - Add(aF, anAncestors); - aFaces.push_back(aF); + TopExp_Explorer anExplorer(theShape, TopAbs_FACE); + for (; anExplorer.More(); anExplorer.Next()) + { + const TopoDS_Face& aFace = TopoDS::Face(anExplorer.Current()); + Add(aFace); + aFaces.push_back(aFace); } #ifdef HAVE_TBB - if (myInParallel) + if ( myInParallel ) { - CreateMutexesForSubShapes(theShape, TopAbs_EDGE); - // mesh faces in parallel threads using TBB - tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *this); - RemoveAllMutexes(); + tbb::parallel_for_each(aFaces.begin(), aFaces.end(), *this); } else { #endif - for (std::vector::iterator it(aFaces.begin()); it != aFaces.end(); it++) - Process (*it); + std::vector::const_iterator anIt(aFaces.begin()); + for (; anIt != aFaces.end(); anIt++) + Process(*anIt); #ifdef HAVE_TBB } #endif @@ -193,1438 +180,798 @@ void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape) //function : Process //purpose : //======================================================================= - void BRepMesh_FastDiscret::Process(const TopoDS_Face& theFace) const { - //cout << "START face " << theFace.TShape().operator->() << endl << flush; - Handle(BRepMesh_FaceAttribute) fattribute; - if ( GetFaceAttribute (theFace, fattribute) ) + Handle(BRepMesh_FaceAttribute) anAttribute; + if (GetFaceAttribute(theFace, anAttribute)) { - BRepMesh_FastDiscretFace aTool (GetAngle(), WithShare()); - aTool.Add (theFace, fattribute, GetMapOfDefEdge(), myMutexProvider); + try + { + OCC_CATCH_SIGNALS + + BRepMesh_FastDiscretFace aTool(GetAngle(), WithShare()); + aTool.Add(anAttribute); + } + catch (Standard_Failure) + { + anAttribute->SetStatus(BRepMesh_Failure); + } } - //cout << "END face " << theFace.TShape().operator->() << endl << flush; } //======================================================================= //function : Add(face) //purpose : //======================================================================= - -#define MESH_FAILURE(theface) \ -{ \ - myFacestate = BRepMesh_Failure; \ - myNottriangulated.Append(theface); \ - return; \ -} - -void BRepMesh_FastDiscret::Add(const TopoDS_Face& theface, - const TopTools_IndexedDataMapOfShapeListOfShape& theAncestors) +Standard_Integer BRepMesh_FastDiscret::Add(const TopoDS_Face& theFace) { -#ifndef DEB_MESH try { OCC_CATCH_SIGNALS -#endif - TopoDS_Face face = theface; - BRepTools::Update(face); - face.Orientation(TopAbs_FORWARD); - myStructure.Nullify(); - Handle(NCollection_IncAllocator) anAlloc = Handle(NCollection_IncAllocator)::DownCast(myAllocator); - anAlloc->Reset(Standard_False); - myStructure=new BRepMesh_DataStructureOfDelaun(anAlloc); - Standard_Real aUmin, aVmin, aUmax, aVmax; - BRepTools::UVBounds (theface, aUmin, aUmax, aVmin, aVmax); - Standard_Real aTolU = Max( Precision::PConfusion(), (aUmax - aUmin) * UVDEFLECTION ); - Standard_Real aTolV = Max( Precision::PConfusion(), (aVmax - aVmin) * UVDEFLECTION ); - myStructure->Data().SetCellSize ( 14 * aTolU, 14 * aTolV ); - myStructure->Data().SetTolerance( aTolU, aTolV ); - - BRepAdaptor_Surface BS(face, Standard_False); - Handle(BRepAdaptor_HSurface) gFace = new BRepAdaptor_HSurface(BS); - - GeomAbs_SurfaceType thetype; - thetype = BS.GetType(); - - gp_Pnt2d uvFirst, uvLast; - - Handle(Poly_Triangulation) T; - TopLoc_Location loc; - - if (!myWithShare) { - myVertices.Clear(); - myEdges.Clear(); - } - - myVemap.Clear(); - myLocation2d.Clear(); - myInternaledges.Clear(); - - Standard_Integer i; - i = 1; - - Standard_Real defedge, defface; - Standard_Integer nbEdge = 0; - Standard_Real savangle = myAngle; - Standard_Real cdef; - Standard_Real maxdef = 2.* BRepMesh_ShapeTool::MaxFaceTolerance(theface); - defface = 0.; - - if (!myRelative) defface = Max(myDeflection, maxdef); - - BRepMeshCol::SequenceOfReal aFSeq, aLSeq; - TColGeom2d_SequenceOfCurve aCSeq; - TopTools_SequenceOfShape aShSeq; - - TopoDS_Iterator exW(face); - - for (; exW.More(); exW.Next()) { - const TopoDS_Shape& aWire = exW.Value(); - if (aWire.ShapeType() != TopAbs_WIRE) - continue; - TopoDS_Iterator ex(aWire); - for(; ex.More(); ex.Next()) { - const TopoDS_Edge& edge = TopoDS::Edge(ex.Value()); - nbEdge++; - if (!myMapdefle.IsBound(edge)) { - if (myRelative) { - if (myEdges.IsBound(edge)) { - const BRepMesh_PairOfPolygon& pair = myEdges.Find(edge); - const Handle(Poly_PolygonOnTriangulation)& P = pair.First(); - defedge = P->Deflection(); - } - else { - defedge = BRepMesh_ShapeTool::RelativeEdgeDeflection(edge, - myDeflection, myDtotale, cdef); - - myAngle = savangle * cdef; - } - defface = defface + defedge; - defface = Max(maxdef, defface); - } - else defedge = myDeflection; - - defedge = Max(maxdef, defedge); - defedge = Max(UVDEFLECTION , defedge); - myMapdefle.Bind(edge, defedge); - } - else{ - defedge = myMapdefle(edge); - if (myRelative) {defface = defface + defedge; defface = Max(maxdef, defface);} - } - Standard_Real f1,l1; - Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(edge, face, f1, l1); - if (C.IsNull()) continue; - - aFSeq.Append(f1); - aLSeq.Append(l1); - aCSeq.Append(C); - aShSeq.Append(edge); - Add(edge, face, gFace, C, theAncestors, defedge, f1, l1); - myAngle = savangle; - } - } - - if (nbEdge == 0 || myVemap.Extent() < 3) - { - MESH_FAILURE(theface); - } - - if (myRelative ) defface = defface / nbEdge; - else defface = myDeflection; - - if (myWithShare) defface = Max(maxdef, defface); - - T = BRep_Tool::Triangulation(face, loc); - - if (!myShapetrigu || T.IsNull()) { - - Standard_Real xCur, yCur; - Standard_Real maxX, minX, maxY, minY; - minX=minY=1.e100; - maxX=maxY=-1.e100; - - Standard_Integer ipn = 0; - Standard_Integer i1 =1; - for (i1 = 1; i1 <= myVemap.Extent(); i1++) { - const BRepMesh_Vertex& aV = myStructure->GetNode(myVemap.FindKey(i1)); - ipn++; - xCur=aV.Coord().X(); - yCur=aV.Coord().Y(); - minX=Min(xCur, minX); - maxX=Max(xCur, maxX); - minY=Min(yCur, minY); - maxY=Max(yCur, maxY); - } - Standard_Real myumin = minX; - Standard_Real myumax = maxX; - Standard_Real myvmin = minY; - Standard_Real myvmax = maxY; - - const Standard_Real umin = BS.FirstUParameter(); - const Standard_Real umax = BS.LastUParameter(); - const Standard_Real vmin = BS.FirstVParameter(); - const Standard_Real vmax = BS.LastVParameter(); - - if (myumin < umin || myumax > umax) + // Initialize face attributes + myAttribute.Nullify(); + GetFaceAttribute(theFace, myAttribute); + if (myAttribute.IsNull()) { - if (BS.IsUPeriodic()) + myAttribute = new BRepMesh_FaceAttribute(theFace, + myBoundaryVertices, myBoundaryPoints); + + myAttributes.Bind(theFace, myAttribute); + } + + myStructure = myAttribute->ResetStructure(); + myVertexEdgeMap = myAttribute->ChangeVertexEdgeMap(); + myInternalEdges = myAttribute->ChangeInternalEdges(); + + if (!myWithShare) + { + myEdges.Clear(); + myBoundaryVertices.Clear(); + myBoundaryPoints.Clear(); + } + + Standard_Real defedge; + Standard_Integer nbEdge = 0; + Standard_Real savangle = myAngle; + Standard_Real cdef; + Standard_Real maxdef = 2.* BRepMesh_ShapeTool::MaxFaceTolerance(theFace); + + Standard_Real defface = 0.; + if (!myRelative) + defface = Max(myDeflection, maxdef); + + N_SEQUENCE aPCurves; + N_SEQUENCE aFaceEdges; + + const TopoDS_Face& aFace = myAttribute->Face(); + const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); + TopExp_Explorer aWireIt(aFace, TopAbs_WIRE); + for (; aWireIt.More(); aWireIt.Next()) + { + TopExp_Explorer aEdgeIt(aWireIt.Current(), TopAbs_EDGE); + for (; aEdgeIt.More(); aEdgeIt.Next(), ++nbEdge) { - if ((myumax - myumin) > (umax - umin)) + const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current()); + if (!myMapdefle.IsBound(aEdge)) { - myumax = myumin + (umax - umin); - } - } - else - { - if (umin > myumin) myumin = umin; - if (umax < myumax) myumax = umax; - } - } - - if (myvmin < vmin || myvmax > vmax) - { - if (BS.IsVPeriodic()) - { - if ((myvmax - myvmin) > (vmax - vmin)) - { - myvmax = myvmin + (vmax - vmin); - } - } - else - { - if (vmin > myvmin) myvmin = vmin; - if (vmax < myvmax) myvmax = vmax; - } - } - - // fast verification of the validity of calculated limits. If wrong, - // sure a problem of pcurve. - if (thetype == GeomAbs_BezierSurface && - (myumin < -0.5 || myumax > 1.5 || myvmin < -0.5 || myvmax > 1.5)) - { - MESH_FAILURE(theface); - } - - //define parameters for correct parametrics - - Standard_Real deltaX = 1.0; - Standard_Real deltaY = 1.0; - Standard_Integer nbVertices = myVemap.Extent(); - const Standard_Real tolclass = Precision::PConfusion(); //0.03*Max(myumax-myumin, myvmax-myvmin); - - BRepMeshCol::HClassifier classifier = new BRepMesh_Classifier; - { - BRepMesh_WireChecker aDFaceChecker(face, - tolclass, myInternaledges, myVemap, myStructure, - myumin, myumax, myvmin, myvmax, myInParallel); - aDFaceChecker.ReCompute(classifier); - - myFacestate = aDFaceChecker.Status(); - if (myFacestate == BRepMesh_SelfIntersectingWire) - { - Standard_Integer nbmaill = 0; - Standard_Real eps = Precision::Confusion(); - while (nbmaill < 5 && myFacestate != BRepMesh_ReMesh) - { - nbmaill++; - - //clear the structure of links - myStructure.Nullify(); - myStructure = new BRepMesh_DataStructureOfDelaun(anAlloc); - - myVemap.Clear(); - myLocation2d.Clear(); - myInternaledges.Clear(); - - Standard_Integer j1; - for(j1 = 1; j1 <= aShSeq.Length(); j1++) + if (myRelative) { - const TopoDS_Edge& edge = TopoDS::Edge(aShSeq.Value(j1)); - if (myEdges.IsBound(edge)) + if (myEdges.IsBound(aEdge)) { - myEdges.UnBind(edge); - myInternaledges.UnBind(edge); - } - } - - - for( j1 = 1; j1 <= aShSeq.Length(); j1++) - { - const TopoDS_Edge& edge = TopoDS::Edge(aShSeq.Value(j1)); - defedge = myMapdefle(edge) / 3.; - defedge = Max(defedge, eps); - myMapdefle.Bind(edge, defedge); - const Handle(Geom2d_Curve)& C = aCSeq.Value(j1); - Add(edge, face, gFace, C, theAncestors, defedge, aFSeq.Value(j1), aLSeq.Value(j1)); - } - - aDFaceChecker.ReCompute(classifier); - if (aDFaceChecker.Status() == BRepMesh_NoError) - { - myFacestate = BRepMesh_ReMesh; - } - nbVertices = myVemap.Extent(); - } - } - } - - if (myFacestate != BRepMesh_NoError && myFacestate != BRepMesh_ReMesh) - { - myNottriangulated.Append(face); - classifier.Nullify(); - return; - } - - // try to find the real length: - // akm (bug OCC16) : We must calculate these measures in non-singular - // parts of face. Let's try to compute average value of three - // (umin, (umin+umax)/2, umax), and respectively for v. - // vvvvv - Standard_Real longu = 0.0, longv = 0.0; //, last , first; - gp_Pnt P11, P12, P21, P22, P31, P32; - - Standard_Real du = (myumax-myumin)/20; - Standard_Real dv = (myvmax-myvmin)/20; - Standard_Real dfuave=(myumin+myumax)/2, dfucur; - Standard_Real dfvave=(myvmin+myvmax)/2, dfvcur; - // U loop - BS.D0 (myumin, myvmin, P11); - BS.D0 (myumin, dfvave, P21); - BS.D0 (myumin, myvmax, P31); - for (i1=1, dfucur=myumin+du; i1 <= 20; i1++, dfucur+=du) { - BS.D0 (dfucur, myvmin, P12); - BS.D0 (dfucur, dfvave, P22); - BS.D0 (dfucur, myvmax, P32); - longu += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) ); - P11 = P12; - P21 = P22; - P31 = P32; - } - // V loop - BS.D0(myumin, myvmin, P11); - BS.D0(dfuave, myvmin, P21); - BS.D0(myumax, myvmin, P31); - for (i1=1, dfvcur=myvmin+dv; i1 <= 20; i1++, dfvcur+=dv) { - BS.D0 (myumin, dfvcur, P12); - BS.D0 (dfuave, dfvcur, P22); - BS.D0 (myumax, dfvcur, P32); - longv += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) ); - P11 = P12; - P21 = P22; - P31 = P32; - } - longu /= 3.; - longv /= 3.; - // akm (bug OCC16) ^^^^^ - - if (longu <= 1.e-16 || longv <= 1.e-16) { - //yes, it is seen!! -#ifdef DEB_MESH_CHRONO - chMaillEdges.Stop(); - MESH_CHRONO_TSTOP(thetype); -#endif - MESH_FAILURE(theface); - } - - - if (thetype == GeomAbs_Torus) { - gp_Torus Tor = BS.Torus(); - Standard_Real r = Tor.MinorRadius(), R = Tor.MajorRadius(); - Standard_Real Du, Dv;//, pasu, pasv; - - Dv = Max(1.0e0 - (defface/r),0.0e0) ; - Standard_Real oldDv = 2.0 * ACos (Dv); - oldDv = Min(oldDv, myAngle); - Dv = 0.9*oldDv; //TWOTHIRD * oldDv; - Dv = oldDv; - - Standard_Integer nbV = Max((Standard_Integer)((myvmax-myvmin)/Dv), 2); - Dv = (myvmax-myvmin)/(nbV+1); - - Standard_Real ru = R + r; - if (ru > 1.e-16) { - Du = Max(1.0e0 - (defface/ru),0.0e0); - Du = (2.0 * ACos (Du)); - Du = Min(Du, myAngle); - Standard_Real aa = sqrt(Du*Du + oldDv*oldDv); - if(aa < gp::Resolution()) - return; - - Du = Du * Min(oldDv, Du) / aa; - } - else Du = Dv; - - Standard_Integer nbU = Max((Standard_Integer)((myumax-myumin)/Du), 2); - nbU = Max(nbU, (Standard_Integer)(nbV*(myumax-myumin)*R/((myvmax-myvmin)*r)/5.)); - - Du = (myumax-myumin)/(nbU+1); - //-- DeltaX and DeltaY are chosen so that to avoid "jumping" - //-- of points on the grid - deltaX = Du; - deltaY = Dv; - } - else if (thetype == GeomAbs_Cylinder) { - /*Standard_Real aMax = Max(myumax,myvmax); - deltaX = 0.01; //1./aMax; //0.01; - deltaY = 1.0;*/ - gp_Cylinder Cyl = BS.Cylinder(); - Standard_Real R = Cyl.Radius(); - // Calculate parameters for iteration in U direction - Standard_Real Du = 1.0 - (defface/R); - if (Du < 0.0) Du = 0.0; - Du = 2.0 * ACos (Du); - if (Du > GetAngle()) Du = GetAngle(); - deltaX = Du/longv; - deltaY = 1.; - } - else { - deltaX = (myumax-myumin)/longu; - deltaY = (myvmax-myvmin)/longv; - } - - if(!myMapattrib.IsBound(theface)) - { - Handle(BRepMesh_FaceAttribute) aFA = new BRepMesh_FaceAttribute(); - aFA->GetDefFace() = defface; - aFA->GetUMax() = myumax; - aFA->GetVMax() = myvmax; - aFA->GetUMin() = myumin; - aFA->GetVMin() = myvmin; - aFA->GetDeltaX() = deltaX; - aFA->GetDeltaY() = deltaY; - aFA->GetMinX() = minX; - aFA->GetMinY() = minY; - aFA->GetClassifier() = classifier; - myMapattrib.Bind(theface, aFA); - } - - //Standard_Integer nbVertices = myVemap.Extent(); - T = new Poly_Triangulation(nbVertices, 1, Standard_True); - TColgp_Array1OfPnt& Nodes = T->ChangeNodes(); - TColgp_Array1OfPnt2d& Nodes2d = T->ChangeUVNodes(); - - Standard_Integer index; - for (i = 1; i <= nbVertices; i++) { - index = myVemap.FindKey(i); - Nodes(i) = Pnt(index); - Nodes2d(i).SetXY(Vertex(index).Coord()); - } - BRepMesh_ShapeTool::AddInFace(face, T); - - BRepMeshCol::DMapOfShapePairOfPolygon::Iterator It(myInternaledges); - for (; It.More(); It.Next()) - { - const TopoDS_Edge& aEdge = TopoDS::Edge(It.Key()); - const BRepMesh_PairOfPolygon& pair = It.Value(); - const Handle(Poly_PolygonOnTriangulation)& NOD1 = pair.First(); - const Handle(Poly_PolygonOnTriangulation)& NOD2 = pair.Last(); - if ( NOD1 == NOD2 ) - BRepMesh_ShapeTool::UpdateEdge(aEdge, NOD1, T, loc); - else - BRepMesh_ShapeTool::UpdateEdge(aEdge, NOD1, NOD2, T, loc); - } - } - -#ifndef DEB_MESH - } - catch(Standard_Failure) - { - MESH_FAILURE(theface); - } -#endif // DEB_MESH - myStructure.Nullify(); -} - -//======================================================================= -//function : splitSegment -//purpose : -//======================================================================= -static void splitSegment( BRepMesh_GeomTool& theGT, - const Handle(Geom_Surface)& theSurf, - const Handle(Geom2d_Curve)& theCurve2d, - const BRepAdaptor_Curve& theBAC, - const Standard_Real theSquareEDef, - const Standard_Real theFirst, - const Standard_Real theLast, - const Standard_Integer theNbIter) -{ - //limit ineration depth - if(theNbIter > 10) - return; - gp_Pnt2d uvf, uvl, uvm; - gp_Pnt P3dF, P3dL, midP3d, midP3dFromSurf; - Standard_Real midpar; - - if(Abs(theLast - theFirst) < 2*Precision::PConfusion()) - return; - - theCurve2d->D0(theFirst, uvf); - theCurve2d->D0(theLast, uvl); - - P3dF = theSurf->Value(uvf.X(), uvf.Y()); - P3dL = theSurf->Value(uvl.X(), uvl.Y()); - - if(P3dF.SquareDistance(P3dL) < theSquareEDef) - return; - - uvm = gp_Pnt2d((uvf.XY() + uvl.XY())*0.5); - midP3dFromSurf = theSurf->Value(uvm.X(), uvm.Y()); - - gp_XYZ aVec = P3dL.XYZ()-P3dF.XYZ(); - aVec.Normalize(); - - gp_XYZ Vec1 = midP3dFromSurf.XYZ() - P3dF.XYZ(); - Standard_Real aModulus = Vec1.Dot(aVec); - gp_XYZ aProj = aVec*aModulus; - gp_XYZ aDist = Vec1 - aProj; - - if(aDist.SquareModulus() < theSquareEDef) - return; - - midpar = (theFirst + theLast) * 0.5; - theBAC.D0(midpar, midP3d); - theGT.AddPoint(midP3d, midpar, Standard_False); - - splitSegment(theGT, theSurf, theCurve2d, theBAC, theSquareEDef, theFirst, midpar, theNbIter+1); - splitSegment(theGT, theSurf, theCurve2d, theBAC, theSquareEDef, midpar, theLast, theNbIter+1); -} - -//======================================================================= -//function : Add -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::Add( const TopoDS_Edge& theEdge, - const TopoDS_Face& theFace, - const Handle(BRepAdaptor_HSurface)& theGFace, - const Handle(Geom2d_Curve)& theC2d, - const TopTools_IndexedDataMapOfShapeListOfShape& theAncestors, - const Standard_Real theDefEdge, - const Standard_Real theFirst, - const Standard_Real theLast) -{ - const TopAbs_Orientation orEdge = theEdge.Orientation(); - if (orEdge == TopAbs_EXTERNAL) return; - - const Standard_Boolean isEdgeBound = myEdges.IsBound(theEdge); - - if (!isEdgeBound) - { - if (Update(theEdge, theFace, theC2d, theDefEdge, theFirst, theLast)) - { - return; - } - } - - TopoDS_Vertex pBegin, pEnd; - TopExp::Vertices(theEdge, pBegin, pEnd); - if (pBegin.IsNull() || pEnd.IsNull()) - { - return; - } - - Standard_Real wFirst, wLast; - BRep_Tool::Range(theEdge, theFace, wFirst, wLast); - - gp_Pnt2d uvFirst, uvLast; - BRep_Tool::UVPoints(theEdge, theFace, uvFirst, uvLast); - - const Standard_Boolean sameUV = uvFirst.IsEqual(uvLast, Precision::PConfusion()); - - //Control vertexes tolerances - gp_Pnt pFirst = theGFace->Value(uvFirst.X(), uvFirst.Y()); - gp_Pnt pLast = theGFace->Value(uvLast.X(), uvLast.Y()); - - Standard_Real mindist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(pBegin)), - pLast.Distance(BRep_Tool::Pnt(pEnd))); - - if(mindist < BRep_Tool::Tolerance(pBegin) || - mindist < BRep_Tool::Tolerance(pEnd) ) mindist = theDefEdge; - - // control of degenerated non-coded edges. - - Standard_Boolean degener = BRep_Tool::Degenerated(theEdge); - - if (!degener) - { - if (pBegin.IsSame(pEnd)) - { - // calculation of the length of the edge in 3D - Standard_Real longueur = 0.0; - Standard_Real du = (wLast-wFirst)/20; - gp_Pnt P1, P2; - BRepAdaptor_Curve BC(theEdge); - BC.D0(wFirst, P1); - Standard_Real tolV = BRep_Tool::Tolerance(pBegin); - Standard_Real tolV2 = 1.2*tolV; - for (Standard_Integer l = 1; l <= 20; l++) { - BC.D0(wFirst + l*du, P2); - longueur += P1.Distance(P2); - if (longueur > tolV2) break; - P1 = P2; - } - - if (longueur < tolV2) - { - degener = Standard_True; - } - } - } - - // Correct UV points - if (sameUV) - { - // 1. is it really sameUV without being degenerated - gp_Pnt2d uvF, uvL; - theC2d->D0(theFirst, uvF); - theC2d->D0(theLast, uvL); - if (!uvFirst.IsEqual(uvF, Precision::PConfusion())) - { - uvFirst = uvF; - } - if (!uvLast.IsEqual(uvL, Precision::PConfusion())) - { - uvLast = uvL; - } - } - - gp_XY theUV; - - // Process first vertex - Standard_Integer ipf; - if (myVertices.IsBound(pBegin)) - { - ipf = myVertices.Find(pBegin); - } - else - { - if (sameUV && myVertices.IsBound(pEnd)) - { - ipf = myVertices.Find(pEnd); - } - else - { - myNbLocat++; - ipf = myNbLocat; - myLocation3d.Bind(ipf, BRep_Tool::Pnt(pBegin)); - } - myVertices.Bind(pBegin, ipf); - } - - Handle(BRepMesh_FaceAttribute) aFaceAttribute; - GetFaceAttribute ( theFace, aFaceAttribute ); - theUV = BRepMesh_ShapeTool::FindUV(ipf, uvFirst, - pBegin, mindist, aFaceAttribute, theGFace, myLocation2d); - - BRepMesh_Vertex vf(theUV, ipf, BRepMesh_Frontier); - Standard_Integer ivf = myStructure->AddNode(vf); - - // Process last vertex - Standard_Integer ipl; - if (pEnd.IsSame(pBegin)) - { - ipl = ipf; - } - else - { - if (myVertices.IsBound(pEnd)) - { - ipl = myVertices.Find(pEnd); - } - else - { - if (sameUV) - { - ipl = ipf; - } - else - { - myNbLocat++; - ipl = myNbLocat; - myLocation3d.Bind(ipl, BRep_Tool::Pnt(pEnd)); - } - myVertices.Bind(pEnd,ipl); - } - } - - theUV = BRepMesh_ShapeTool::FindUV(ipl, uvLast, - pEnd, mindist, aFaceAttribute, theGFace, myLocation2d); - - BRepMesh_Vertex vl(theUV, ipl, BRepMesh_Frontier); - Standard_Integer ivl= myStructure->AddNode(vl); - - Standard_Integer isvf = myVemap.FindIndex(ivf); - if (isvf == 0) isvf = myVemap.Add(ivf); - Standard_Integer isvl = myVemap.FindIndex(ivl); - if (isvl == 0) isvl = myVemap.Add(ivl); - - Standard_Real otherdefedge = 0.5*theDefEdge; - gp_Pnt2d uv; - BRepMesh_Vertex v2; - gp_Pnt P3d; - - Handle(Poly_PolygonOnTriangulation) P1; - - if (!isEdgeBound) - { - Handle(Poly_PolygonOnTriangulation) P2; - - if (degener) - { - // creation anew: - TColStd_Array1OfInteger Nodes(1, 2), NodInStruct(1, 2); - TColStd_Array1OfReal Param(1, 2); - - NodInStruct(1) = ipf; - Nodes(1) = isvf; - Param(1) = wFirst; - - NodInStruct(2) = ipl; - Nodes(2) = isvl; - Param(2) = wLast; - - P1 = new Poly_PolygonOnTriangulation(Nodes, Param); - P2 = new Poly_PolygonOnTriangulation(NodInStruct, Param); - } - else - { - if (orEdge == TopAbs_INTERNAL) otherdefedge *= 0.5; - - BRepAdaptor_Curve cons; - Standard_Boolean isSameParam = BRep_Tool::SameParameter(theEdge); - if (isSameParam) - { - cons.Initialize(theEdge); - } - else - { - cons.Initialize(theEdge, theFace); - } - - TopLoc_Location L; - Standard_Integer nbpmin = 2; - const GeomAbs_CurveType aCurveType = cons.GetType(); - if ( aCurveType == GeomAbs_Circle ) - nbpmin = 4; //OCC287 - - BRepMesh_GeomTool GT(cons, wFirst, wLast, otherdefedge, 0.5 * myAngle, nbpmin); - - if ( aCurveType == GeomAbs_BSplineCurve ) - { - const Standard_Integer aNbInt = cons.NbIntervals( GeomAbs_C1 ); - if ( aNbInt > 0 ) - { - TColStd_Array1OfReal anIntervals( 1, aNbInt + 1 ); - cons.Intervals( anIntervals, GeomAbs_C1 ); - for ( Standard_Integer aIntIt = 1; aIntIt <= aNbInt; ++aIntIt ) - { - const Standard_Real& aStartInt = anIntervals.Value( aIntIt ); - const Standard_Real& anEndInt = anIntervals.Value( aIntIt + 1 ); - - BRepMesh_GeomTool aDetalizator( cons, aStartInt, anEndInt, - otherdefedge, 0.5 * myAngle, nbpmin ); - - Standard_Integer aNbAddNodes = aDetalizator.NbPoints(); - for ( Standard_Integer aNodeIt = 1; aNodeIt <= aNbAddNodes; ++aNodeIt ) - { - Standard_Real aParam; - gp_Pnt aPoint3d; - gp_Pnt2d aPoint2d; - aDetalizator.Value( aNodeIt, theGFace, aParam, aPoint3d, aPoint2d ); - GT.AddPoint( aPoint3d, aParam, Standard_False ); - } - } - } - } - - // PTv, chl/922/G9, Take into account internal vertices - // it is necessary for internal edges, which do not split other edges, by their vertex - TopoDS_Iterator exV(theEdge); - for ( ; exV.More(); exV.Next() ) - { - TopoDS_Vertex aIntV = TopoDS::Vertex(exV.Value()); - if ( aIntV.Orientation() == TopAbs_INTERNAL ) - GT.AddPoint(BRep_Tool::Pnt(aIntV), - BRep_Tool::Parameter(aIntV, theEdge), - Standard_True); - } - - Standard_Integer i; - Standard_Integer nbnodes = GT.NbPoints(); - //Check deflection in 2d space for improvement of edge tesselation. - if( isSameParam && nbnodes > 1) - { - Standard_Real aSquareEdgeDef = otherdefedge * otherdefedge; - const TopTools_ListOfShape& lf = theAncestors.FindFromKey(theEdge); - TopTools_ListIteratorOfListOfShape itl(lf); - for (; itl.More(); itl.Next()) { - const TopoDS_Face& aFace = TopoDS::Face (itl.Value()); - - TopLoc_Location aLoc; - Standard_Real aF, aL; - Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc); - const Handle(Standard_Type)& aType = aSurf->DynamicType(); - if(aType == STANDARD_TYPE(Geom_Plane)) - continue; - Handle(Geom2d_Curve) aCurve2d = BRep_Tool::CurveOnSurface(theEdge, aFace, aF, aL); - if(Abs(aF-wFirst)>Precision::PConfusion()||Abs(aL-wLast)>Precision::PConfusion()) - continue; - - gp_Pnt2d uvf; - Standard_Real parf; - nbnodes = GT.NbPoints(); - TColStd_Array1OfReal aParamArray(1, nbnodes); - for (i = 1; i <= nbnodes; i++) - { - GT.Value(i, theGFace, parf, P3d, uvf); - aParamArray.SetValue(i, parf); - } - for (i = 1; i < nbnodes; i++) - { - splitSegment(GT, aSurf, aCurve2d, cons, aSquareEdgeDef, aParamArray(i), aParamArray(i+1), 1); - } - } - } - - // Creation of polygons on triangulation: - Standard_Real puv; - nbnodes = GT.NbPoints(); - - TColStd_Array1OfInteger Nodes(1, nbnodes); - TColStd_Array1OfInteger NodInStruct(1, nbnodes); - TColStd_Array1OfReal Param(1, nbnodes); - - // processing of the 1st point: - Nodes(1) = isvf; - NodInStruct(1) = ipf; - Param(1) = wFirst; - - // last point: - Nodes(nbnodes) = isvl; - NodInStruct(nbnodes) = ipl; - Param(nbnodes) = wLast; - - if(nbnodes > 2) - { - Standard_Integer iv2; - for (i = 2; i < GT.NbPoints(); i++) - { - // Record 3d point - GT.Value(i, theGFace, puv, P3d, uv); - myNbLocat++; - myLocation3d.Bind(myNbLocat, P3d); - NodInStruct(i) = myNbLocat; - // Record 2d point - v2.Initialize(uv.Coord(), myNbLocat, BRepMesh_OnCurve); - iv2=myStructure->AddNode(v2); - - Standard_Integer isv = myVemap.FindIndex(iv2); - if (isv == 0) isv = myVemap.Add(iv2); - Nodes(i) = isv; - NodInStruct(i) = myNbLocat; - Param(i) = puv; - - if (orEdge == TopAbs_FORWARD) - myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Frontier)); - else if (orEdge == TopAbs_REVERSED) - myStructure->AddLink(BRepMesh_Edge(iv2, ivf, BRepMesh_Frontier)); - else if (orEdge == TopAbs_INTERNAL) - myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Fixed)); - ivf = iv2; - } - } - - P1 = new Poly_PolygonOnTriangulation(Nodes, Param); - P2 = new Poly_PolygonOnTriangulation(NodInStruct, Param); - } - - P2->Deflection(otherdefedge); - BRepMesh_PairOfPolygon pair; - pair.Append(P2); - myEdges.Bind(theEdge, pair); - - if (ivf != ivl) { - if (orEdge == TopAbs_FORWARD) - myStructure->AddLink(BRepMesh_Edge(ivf, ivl, BRepMesh_Frontier)); - else if (orEdge == TopAbs_REVERSED) - myStructure->AddLink(BRepMesh_Edge(ivl, ivf, BRepMesh_Frontier)); - else if (orEdge == TopAbs_INTERNAL) - myStructure->AddLink(BRepMesh_Edge(ivf, ivl, BRepMesh_Fixed)); - } - - - } - // If this Edge has been already checked and it is not degenerated, - // the points of the polygon calculated at the first check are retrieved : - else - { - if (degener) - { - // Create 2d polygon for degenerated edge - TColStd_Array1OfInteger Nodes(1, 2); - TColStd_Array1OfReal PPar(1, 2); - - Nodes(1) = isvf; - PPar(1) = wFirst; - - Nodes(2) = isvl; - PPar(2) = wLast; - - P1 = new Poly_PolygonOnTriangulation(Nodes, PPar); - } - else - { - // retrieve the polygone: - const BRepMesh_PairOfPolygon& pair = myEdges.Find(theEdge); - const Handle(Poly_PolygonOnTriangulation)& P = pair.First(); - const TColStd_Array1OfInteger& NOD = P->Nodes(); - Handle(TColStd_HArray1OfReal) Par = P->Parameters(); - - // creation anew: - const Standard_Integer nbnodes = NOD.Length(); - TColStd_Array1OfInteger Nodes(1, nbnodes); - TColStd_Array1OfReal PPar(1, nbnodes); - Standard_Integer iv2; - - Nodes(1) = isvf; - PPar(1) = wFirst; - - Nodes(nbnodes) = isvl; - PPar(nbnodes) = wLast; - - if (nbnodes > 2) - { - Standard_Integer i; - if (BRep_Tool::SameParameter(theEdge)) - { - for (i = 2; i < nbnodes; i++) - { - const Standard_Real puv = Par->Value(i); - theC2d->D0(puv, uv); - v2.Initialize(uv.Coord(), NOD(i), BRepMesh_OnCurve); - iv2 = myStructure->AddNode(v2); - - Standard_Integer isv = myVemap.FindIndex(iv2); - if (isv == 0) isv = myVemap.Add(iv2); - Nodes(i) = isv; - PPar(i) = puv; - - if (orEdge==TopAbs_FORWARD) - myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Frontier)); - else if (orEdge == TopAbs_REVERSED) - myStructure->AddLink(BRepMesh_Edge(iv2, ivf, BRepMesh_Frontier)); - else if (orEdge == TopAbs_INTERNAL) - myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Fixed)); - - ivf = iv2; - } - } - else - { - const Standard_Real wFold = Par->Value(Par->Lower()); - const Standard_Real wLold = Par->Value(Par->Upper()); - - Standard_Real wKoef = 1.; - if ((wFold != wFirst || wLold != wLast) && wLold != wFold) - { - wKoef = (wLast - wFirst) / (wLold - wFold); - } - - BRepAdaptor_Curve cons(theEdge, theFace); - Extrema_LocateExtPC pcos; - pcos.Initialize(cons, cons.FirstParameter(), - cons.LastParameter(), Precision::PConfusion()); - - Standard_Real wPrev; - Standard_Real wCur = wFirst; - Standard_Real wCurFound = wFirst; - for (i = 2; i < nbnodes; i++) - { - P3d = myLocation3d(NOD(i)); - // Record 2d point - wPrev = wCur; - wCur = wFirst + wKoef*(Par->Value(i) - wFold); - wCurFound += (wCur - wPrev); - pcos.Perform(P3d, wCurFound); - if (pcos.IsDone()) wCurFound = pcos.Point().Parameter(); - theC2d->D0(wCurFound, uv); - v2.Initialize(uv.Coord(), NOD(i), BRepMesh_OnCurve); - iv2 = myStructure->AddNode(v2); - - Standard_Integer isv = myVemap.FindIndex(iv2); - if (isv == 0) isv = myVemap.Add(iv2); - Nodes(i) = isv; - PPar(i) = wCurFound; - - if (orEdge==TopAbs_FORWARD) - myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Frontier)); - else if (orEdge == TopAbs_REVERSED) - myStructure->AddLink(BRepMesh_Edge(iv2, ivf, BRepMesh_Frontier)); - else if (orEdge == TopAbs_INTERNAL) - myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Fixed)); - - ivf = iv2; - } - } - } - - P1 = new Poly_PolygonOnTriangulation(Nodes, PPar); - - if (ivf != ivl) { - if (orEdge == TopAbs_FORWARD) - myStructure->AddLink(BRepMesh_Edge(ivf, ivl, BRepMesh_Frontier)); - else if (orEdge == TopAbs_REVERSED) - myStructure->AddLink(BRepMesh_Edge(ivl, ivf, BRepMesh_Frontier)); - else if (orEdge == TopAbs_INTERNAL) - myStructure->AddLink(BRepMesh_Edge(ivf, ivl, BRepMesh_Fixed)); - } - } - } - - P1->Deflection(theDefEdge); - if (myInternaledges.IsBound(theEdge)) - { - BRepMesh_PairOfPolygon& pair = myInternaledges.ChangeFind(theEdge); - if (orEdge == TopAbs_REVERSED) - pair.Append(P1); - else - pair.Prepend(P1); - } - else - { - BRepMesh_PairOfPolygon pair1; - pair1.Append(P1); - myInternaledges.Bind(theEdge, pair1); - } -} - - -//======================================================================= -//function : Update(edge) -//purpose : -//======================================================================= -Standard_Boolean BRepMesh_FastDiscret::Update(const TopoDS_Edge& theEdge, - const TopoDS_Face& theFace, - const Handle(Geom2d_Curve)& theC2d, - const Standard_Real theDefEdge, - const Standard_Real theFirst, - const Standard_Real theLast) -{ - TopLoc_Location Loc; - Handle(Poly_Triangulation) T; - Handle(Poly_PolygonOnTriangulation) Poly, NullPoly; - - Standard_Integer i = 1; - Standard_Boolean found = Standard_False; - do - { - BRep_Tool::PolygonOnTriangulation(theEdge,Poly,T,Loc,i); - i++; - if (!found && !T.IsNull() && T->HasUVNodes() && - !Poly.IsNull() && Poly->HasParameters()) - { - if (Poly->Deflection() <= 1.1*theDefEdge) - { - // 2d vertex indices - TopAbs_Orientation orEdge = theEdge.Orientation(); - Standard_Integer iv1, iv2, ivl; - Standard_Integer isv1, isv, isvl; - - // Get range on 2d curve - Standard_Real wFirst, wLast; - BRep_Tool::Range(theEdge, theFace, wFirst, wLast); - - // Get end points on 2d curve - gp_Pnt2d uvFirst, uvLast; - BRep_Tool::UVPoints(theEdge, theFace, uvFirst, uvLast); - - // Get vertices - TopoDS_Vertex pBegin, pEnd; - TopExp::Vertices(theEdge,pBegin,pEnd); - - const Standard_Boolean sameUV = - uvFirst.IsEqual(uvLast, Precision::PConfusion()); - - //Controle vertice tolerances - BRepAdaptor_Surface BS(theFace, Standard_False); - Handle(BRepAdaptor_HSurface) gFace = new BRepAdaptor_HSurface(BS); - - - gp_Pnt pFirst = gFace->Value(uvFirst.X(), uvFirst.Y()); - gp_Pnt pLast = gFace->Value(uvLast.X(), uvLast.Y()); - - Standard_Real mindist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(pBegin)), - pLast.Distance(BRep_Tool::Pnt(pEnd))); - - if (mindist < BRep_Tool::Tolerance(pBegin) || - mindist < BRep_Tool::Tolerance(pEnd) ) mindist = theDefEdge; - - if (sameUV) - { - // 1. is it really sameUV without being degenerated - gp_Pnt2d uvF, uvL; - theC2d->D0(theFirst, uvF); - theC2d->D0(theLast, uvL); - if (!uvFirst.IsEqual(uvF, Precision::PConfusion())) { - uvFirst = uvF; - } - if (!uvLast.IsEqual(uvL, Precision::PConfusion())) { - uvLast = uvL; - } - } - - const TColgp_Array1OfPnt& Nodes = T->Nodes(); - const TColStd_Array1OfInteger& Indices = Poly->Nodes(); - Handle(TColStd_HArray1OfReal) Param = Poly->Parameters(); - - const Standard_Integer nbnodes = Indices.Length(); - TColStd_Array1OfInteger NewNodes(1, nbnodes); - TColStd_Array1OfInteger NewNodInStruct(1, nbnodes); - - gp_Pnt P3d; - gp_XY theUV; - - // Process first vertex - Standard_Integer ipf; - if (myVertices.IsBound(pBegin)) - { - ipf = myVertices.Find(pBegin); - } - else - { - if (sameUV && myVertices.IsBound(pEnd)) - { - ipf = myVertices.Find(pEnd); - } - else - { - P3d = Nodes(Indices(1)); - if (!Loc.IsIdentity()) - P3d.Transform(Loc.Transformation()); - myNbLocat++; - myLocation3d.Bind(myNbLocat,P3d); - ipf = myNbLocat; - } - myVertices.Bind(pBegin,ipf); - } - NewNodInStruct(1) = ipf; - - Handle(BRepMesh_FaceAttribute) aFaceAttribute; - GetFaceAttribute ( theFace, aFaceAttribute ); - theUV = BRepMesh_ShapeTool::FindUV(ipf, uvFirst, - pBegin, mindist, aFaceAttribute, gFace, myLocation2d); - - BRepMesh_Vertex vf(theUV,ipf,BRepMesh_Frontier); - iv1 = myStructure->AddNode(vf); - isv1 = myVemap.FindIndex(iv1); - if (isv1 == 0) isv1 = myVemap.Add(iv1); - NewNodes(1) = isv1; - - // Process last vertex - Standard_Integer ipl; - if (pEnd.IsSame(pBegin)) - { - ipl = ipf; - } - else - { - if (myVertices.IsBound(pEnd)) - { - ipl = myVertices.Find(pEnd); - } - else - { - if (sameUV) - { - ipl = ipf; - ivl = iv1; + const BRepMesh_PairOfPolygon& aPair = myEdges.Find(aEdge); + const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First(); + defedge = aPolygon->Deflection(); } else { - myNbLocat++; - myLocation3d.Bind(myNbLocat,Nodes(Indices(nbnodes)).Transformed(Loc.Transformation())); - ipl = myNbLocat; + defedge = BRepMesh_ShapeTool::RelativeEdgeDeflection( + aEdge, myDeflection, myDtotale, cdef); + + myAngle = savangle * cdef; } - myVertices.Bind(pEnd,ipl); - } - } - NewNodInStruct(nbnodes) = ipl; - theUV = BRepMesh_ShapeTool::FindUV(ipl, uvLast, - pEnd, mindist, aFaceAttribute, gFace, myLocation2d); - BRepMesh_Vertex vl(theUV,ipl,BRepMesh_Frontier); - - ivl = myStructure->AddNode(vl); - isvl = myVemap.FindIndex(ivl); - if (isvl == 0) isvl = myVemap.Add(ivl); - - NewNodes(nbnodes) = isvl; - - gp_Pnt2d uv; - BRepMesh_Vertex v; - - if (BRep_Tool::SameParameter(theEdge)) - { - for (i = 2; i < Indices.Length(); i++) - { - // Record 3d point - P3d = Nodes(Indices(i)); - if (!Loc.IsIdentity()) - P3d.Transform(Loc.Transformation()); - myNbLocat++; - myLocation3d.Bind(myNbLocat, P3d); - NewNodInStruct(i) = myNbLocat; - // Record 2d point - uv = theC2d->Value(Param->Value(i)); - v.Initialize(uv.Coord(), myNbLocat, BRepMesh_Frontier); - iv2 = myStructure->AddNode(v); - isv = myVemap.FindIndex(iv2); - if (isv == 0) isv = myVemap.Add(iv2); - NewNodes(i) = isv; - - //add links - if (orEdge == TopAbs_FORWARD) - myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Frontier)); - else if (orEdge == TopAbs_REVERSED) - myStructure->AddLink(BRepMesh_Edge(iv2,iv1,BRepMesh_Frontier)); - else if (orEdge == TopAbs_INTERNAL) - myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Fixed)); - iv1 = iv2; + defface += defedge; + defface = Max(maxdef, defface); } - - // last point - if (iv1 != ivl) { - if (orEdge == TopAbs_FORWARD) - myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Frontier)); - else if (orEdge == TopAbs_REVERSED) - myStructure->AddLink(BRepMesh_Edge(ivl,iv1,BRepMesh_Frontier)); - else if (orEdge == TopAbs_INTERNAL) - myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Fixed)); - } - - - } - else - { - const Standard_Real wFold = Param->Value(Param->Lower()); - const Standard_Real wLold = Param->Value(Param->Upper()); - - Standard_Real wKoef = 1.; - if ((wFold != wFirst || wLold != wLast) && wLold != wFold) - { - wKoef = (wLast - wFirst) / (wLold - wFold); - } - - BRepAdaptor_Curve cons(theEdge, theFace); - Extrema_LocateExtPC pcos; - pcos.Initialize(cons, cons.FirstParameter(), - cons.LastParameter(), Precision::PConfusion()); - - Standard_Real wPrev; - Standard_Real wCur = wFirst; - Standard_Real wCurFound = wFirst; - for (i = 2; i < Indices.Length(); i++) - { - // Record 3d point - P3d = Nodes(Indices(i)); - if (!Loc.IsIdentity()) - P3d.Transform(Loc.Transformation()); - myNbLocat++; - myLocation3d.Bind(myNbLocat, P3d); - NewNodInStruct(i) = myNbLocat; - // Record 2d point - wPrev = wCur; - wCur = wFirst + wKoef*(Param->Value(i) - wFold); - wCurFound += (wCur - wPrev); - pcos.Perform(P3d, wCurFound); - if (pcos.IsDone()) wCurFound = pcos.Point().Parameter(); - theC2d->D0(wCurFound, uv); - v.Initialize(uv.Coord(), myNbLocat, BRepMesh_Frontier); - iv2 = myStructure->AddNode(v); - isv = myVemap.FindIndex(iv2); - if (isv == 0) isv = myVemap.Add(iv2); - NewNodes(i) = isv; - - - //add links - if (orEdge == TopAbs_FORWARD) - myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Frontier)); - else if (orEdge == TopAbs_REVERSED) - myStructure->AddLink(BRepMesh_Edge(iv2,iv1,BRepMesh_Frontier)); - else if (orEdge == TopAbs_INTERNAL) - myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Fixed)); - iv1 = iv2; - } - - // last point - if (iv1 != ivl) { - if (orEdge == TopAbs_FORWARD) - myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Frontier)); - else if (orEdge == TopAbs_REVERSED) - myStructure->AddLink(BRepMesh_Edge(ivl,iv1,BRepMesh_Frontier)); - else if (orEdge == TopAbs_INTERNAL) - myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Fixed)); - } - } - - Handle(Poly_PolygonOnTriangulation) P1 = - new Poly_PolygonOnTriangulation(NewNodes, Param->Array1()); - P1->Deflection(theDefEdge); - if (myInternaledges.IsBound(theEdge)) - { - BRepMesh_PairOfPolygon& pair = myInternaledges.ChangeFind(theEdge); - if (theEdge.Orientation() == TopAbs_REVERSED) - pair.Append(P1); else - pair.Prepend(P1); + { + defedge = myDeflection; + } + + defedge = Max(maxdef, defedge); + defedge = Max(UVDEFLECTION, defedge); + myMapdefle.Bind(aEdge, defedge); } else { - BRepMesh_PairOfPolygon pair1; - pair1.Append(P1); - myInternaledges.Bind(theEdge, pair1); + defedge = myMapdefle(aEdge); + if ( myRelative ) + { + defface += defedge; + defface = Max(maxdef, defface); + } } - - Handle(Poly_PolygonOnTriangulation) P2 = - new Poly_PolygonOnTriangulation(NewNodInStruct, Param->Array1()); - P2->Deflection(theDefEdge); - BRepMesh_PairOfPolygon pair; - pair.Append(P2); - myEdges.Bind(theEdge, pair); - - found = Standard_True; + + Standard_Real aFirstParam, aLastParam; + Handle(Geom2d_Curve) aCurve2d = + BRep_Tool::CurveOnSurface(aEdge, aFace, aFirstParam, aLastParam); + + if (aCurve2d.IsNull()) + continue; + + EdgePCurve aPCurve = { aCurve2d, aFirstParam, aLastParam }; + aPCurves.Append(aPCurve); + aFaceEdges.Append(aEdge); + + add(aEdge, aPCurve, defedge); + myAngle = savangle; + } + } + + if ( nbEdge == 0 || myVertexEdgeMap->Extent() < 3 ) + { + myAttribute->SetStatus(BRepMesh_Failure); + return myAttribute->GetStatus(); + } + + if ( myRelative ) + { + defface = defface / nbEdge; + } + else + { + defface = myDeflection; + } + + if ( myWithShare ) + defface = Max(maxdef, defface); + + TopLoc_Location aLoc; + Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLoc); + + if (!myShapetrigu || aTriangulation.IsNull()) + { + Standard_Real xCur, yCur; + Standard_Real maxX, minX, maxY, minY; + + minX = minY = 1.e100; + maxX = maxY =-1.e100; + + Standard_Integer ipn = 0; + Standard_Integer i1 = 1; + for ( i1 = 1; i1 <= myVertexEdgeMap->Extent(); ++i1 ) + { + const BRepMesh_Vertex& aVertex = myStructure->GetNode(myVertexEdgeMap->FindKey(i1)); + + ++ipn; + + xCur = aVertex.Coord().X(); + yCur = aVertex.Coord().Y(); + + minX = Min(xCur, minX); + maxX = Max(xCur, maxX); + minY = Min(yCur, minY); + maxY = Max(yCur, maxY); + } + + Standard_Real myumin = minX; + Standard_Real myumax = maxX; + Standard_Real myvmin = minY; + Standard_Real myvmax = maxY; + + const Standard_Real umin = gFace->FirstUParameter(); + const Standard_Real umax = gFace->LastUParameter(); + const Standard_Real vmin = gFace->FirstVParameter(); + const Standard_Real vmax = gFace->LastVParameter(); + + if (myumin < umin || myumax > umax) + { + if (gFace->IsUPeriodic()) + { + if ((myumax - myumin) > (umax - umin)) + myumax = myumin + (umax - umin); + } + else + { + if (umin > myumin) + myumin = umin; + + if (umax < myumax) + myumax = umax; + } + } + + if (myvmin < vmin || myvmax > vmax) + { + if (gFace->IsVPeriodic()) + { + if ((myvmax - myvmin) > (vmax - vmin)) + myvmax = myvmin + (vmax - vmin); + } + else + { + if ( vmin > myvmin ) + myvmin = vmin; + + if (vmax < myvmax) + myvmax = vmax; + } + } + + GeomAbs_SurfaceType aSurfType = gFace->GetType(); + // Fast verification of the validity of calculated limits. + // If wrong, sure a problem of pcurve. + if (aSurfType == GeomAbs_BezierSurface && + (myumin < -0.5 || myumax > 1.5 || myvmin < -0.5 || myvmax > 1.5) ) + { + myAttribute->SetStatus(BRepMesh_Failure); + return myAttribute->GetStatus(); + } + + //define parameters for correct parametrics + Standard_Real deltaX = 1.0; + Standard_Real deltaY = 1.0; + + { + BRepMeshCol::HClassifier& aClassifier = myAttribute->ChangeClassifier(); + BRepMesh_WireChecker aDFaceChecker(aFace, Precision::PConfusion(), + myInternalEdges, myVertexEdgeMap, myStructure, + myumin, myumax, myvmin, myvmax, myInParallel ); + + aDFaceChecker.ReCompute(aClassifier); + BRepMesh_Status aCheckStatus = aDFaceChecker.Status(); + + if (aCheckStatus == BRepMesh_SelfIntersectingWire) + { + Standard_Integer nbmaill = 0; + Standard_Real eps = Precision::Confusion(); + while (nbmaill < 5 && aCheckStatus != BRepMesh_ReMesh) + { + ++nbmaill; + + // Clear the structure of links + myStructure = myAttribute->ResetStructure(); + + + for (Standard_Integer j = 1; j <= aFaceEdges.Length(); ++j) + { + const TopoDS_Edge& anEdge = aFaceEdges(j); + if (myEdges.IsBound(anEdge)) + myEdges.UnBind(anEdge); + + defedge = Max(myMapdefle(anEdge) / 3.0, eps); + myMapdefle.Bind(anEdge, defedge); + + add(anEdge, aPCurves(j), defedge); + } + + aDFaceChecker.ReCompute(aClassifier); + if (aDFaceChecker.Status() == BRepMesh_NoError) + aCheckStatus = BRepMesh_ReMesh; + } + } + + myAttribute->SetStatus(aCheckStatus); + if (!myAttribute->IsValid()) + //RemoveFaceAttribute(theFace); + return myAttribute->GetStatus(); + } + + // try to find the real length: + // akm (bug OCC16) : We must calculate these measures in non-singular + // parts of face. Let's try to compute average value of three + // (umin, (umin+umax)/2, umax), and respectively for v. + // vvvvv + Standard_Real longu = 0.0, longv = 0.0; //, last , first; + gp_Pnt P11, P12, P21, P22, P31, P32; + + Standard_Real du = 0.05 * ( myumax - myumin ); + Standard_Real dv = 0.05 * ( myvmax - myvmin ); + Standard_Real dfuave = 0.5 * ( myumin + myumax ); + Standard_Real dfvave = 0.5 * ( myvmin + myvmax ); + Standard_Real dfucur, dfvcur; + + // U loop + gFace->D0(myumin, myvmin, P11); + gFace->D0(myumin, dfvave, P21); + gFace->D0(myumin, myvmax, P31); + for (i1=1, dfucur=myumin+du; i1 <= 20; i1++, dfucur+=du) + { + gFace->D0(dfucur, myvmin, P12); + gFace->D0(dfucur, dfvave, P22); + gFace->D0(dfucur, myvmax, P32); + longu += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) ); + P11 = P12; + P21 = P22; + P31 = P32; + } + + // V loop + gFace->D0(myumin, myvmin, P11); + gFace->D0(dfuave, myvmin, P21); + gFace->D0(myumax, myvmin, P31); + for (i1=1, dfvcur=myvmin+dv; i1 <= 20; i1++, dfvcur+=dv) + { + gFace->D0(myumin, dfvcur, P12); + gFace->D0(dfuave, dfvcur, P22); + gFace->D0(myumax, dfvcur, P32); + longv += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) ); + P11 = P12; + P21 = P22; + P31 = P32; + } + + longu /= 3.; + longv /= 3.; + // akm (bug OCC16) ^^^^^ + + if (longu <= 1.e-16 || longv <= 1.e-16) + { + //yes, it is seen!! + myAttribute->SetStatus(BRepMesh_Failure); + return myAttribute->GetStatus(); + } + + + if (aSurfType == GeomAbs_Torus) + { + gp_Torus Tor = gFace->Torus(); + Standard_Real r = Tor.MinorRadius(), R = Tor.MajorRadius(); + Standard_Real Du, Dv;//, pasu, pasv; + + Dv = Max(1.0e0 - (defface/r),0.0e0) ; + Standard_Real oldDv = 2.0 * ACos (Dv); + oldDv = Min(oldDv, myAngle); + Dv = 0.9*oldDv; //TWOTHIRD * oldDv; + Dv = oldDv; + + Standard_Integer nbV = Max((Standard_Integer)((myvmax-myvmin)/Dv), 2); + Dv = (myvmax-myvmin)/(nbV+1); + + Standard_Real ru = R + r; + if ( ru > 1.e-16 ) + { + Du = Max(1.0e0 - (defface/ru),0.0e0); + Du = (2.0 * ACos (Du)); + Du = Min(Du, myAngle); + Standard_Real aa = sqrt(Du*Du + oldDv*oldDv); + + if (aa < gp::Resolution()) + return myAttribute->GetStatus(); + + Du = Du * Min(oldDv, Du) / aa; + } + else + { + Du = Dv; + } + + Standard_Integer nbU = Max((Standard_Integer)((myumax-myumin)/Du), 2); + nbU = Max(nbU, (Standard_Integer)(nbV*(myumax-myumin)*R/((myvmax-myvmin)*r)/5.)); + + Du = (myumax-myumin)/(nbU+1); + //-- DeltaX and DeltaY are chosen so that to avoid "jumping" + //-- of points on the grid + deltaX = Du; + deltaY = Dv; + } + else if (aSurfType == GeomAbs_Cylinder) + { + gp_Cylinder Cyl = gFace->Cylinder(); + Standard_Real R = Cyl.Radius(); + + // Calculate parameters for iteration in U direction + Standard_Real Du = 1.0 - (defface/R); + if (Du < 0.0) + Du = 0.0; + + Du = 2.0 * ACos (Du); + if (Du > GetAngle()) + Du = GetAngle(); + + deltaX = Du / longv; + deltaY = 1.; } else { - BRepMesh_ShapeTool::NullifyEdge(theEdge, T, Loc); - BRepMesh_ShapeTool::NullifyFace(theFace); + deltaX = (myumax-myumin)/longu; + deltaY = (myvmax-myvmin)/longv; } + + // Restore face attribute + myAttribute->SetDefFace(defface); + myAttribute->SetUMax(myumax); + myAttribute->SetVMax(myvmax); + myAttribute->SetUMin(myumin); + myAttribute->SetVMin(myvmin); + myAttribute->SetDeltaX(deltaX); + myAttribute->SetDeltaY(deltaY); } - else if (!T.IsNull() && !T->HasUVNodes()) + } + catch(Standard_Failure) + { + myAttribute->SetStatus(BRepMesh_Failure); + } + + return myAttribute->GetStatus(); +} + +//======================================================================= +//function : addLinkToMesh +//purpose : +//======================================================================= +void BRepMesh_FastDiscret::addLinkToMesh( + const Standard_Integer theFirstNodeId, + const Standard_Integer theLastNodeId, + const TopAbs_Orientation theOrientation) +{ + if (theOrientation == TopAbs_FORWARD) + myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Frontier)); + else if (theOrientation == TopAbs_REVERSED) + myStructure->AddLink(BRepMesh_Edge(theLastNodeId, theFirstNodeId, BRepMesh_Frontier)); + else if (theOrientation == TopAbs_INTERNAL) + myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Fixed)); +} + +//======================================================================= +//function : getEdgeAttributes +//purpose : +//======================================================================= +Standard_Boolean BRepMesh_FastDiscret::getEdgeAttributes( + const TopoDS_Edge& theEdge, + const BRepMesh_FastDiscret::EdgePCurve& thePCurve, + const Standard_Real theDefEdge, + BRepMesh_FastDiscret::EdgeAttributes& theAttributes) const +{ + EdgeAttributes& aEAttr = theAttributes; + + // Get vertices + TopExp::Vertices(theEdge, aEAttr.FirstVertex, aEAttr.LastVertex); + if (aEAttr.FirstVertex.IsNull() || aEAttr.LastVertex.IsNull()) + return Standard_False; + + // Get range on 2d curve + const TopoDS_Face& aFace = myAttribute->Face(); + BRep_Tool::Range(theEdge, aFace, aEAttr.FirstParam, aEAttr.LastParam); + + // Get end points on 2d curve + BRep_Tool::UVPoints(theEdge, aFace, aEAttr.FirstUV, aEAttr.LastUV); + + aEAttr.IsSameUV = + aEAttr.FirstUV.IsEqual(aEAttr.LastUV, Precision::PConfusion()); + + //Control tolerance of vertices + const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); + gp_Pnt pFirst = gFace->Value(aEAttr.FirstUV.X(), aEAttr.FirstUV.Y()); + gp_Pnt pLast = gFace->Value(aEAttr.LastUV.X(), aEAttr.LastUV.Y()); + + aEAttr.MinDist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(aEAttr.FirstVertex)), + pLast .Distance(BRep_Tool::Pnt(aEAttr.LastVertex))); + + if (aEAttr.MinDist < BRep_Tool::Tolerance(aEAttr.FirstVertex) || + aEAttr.MinDist < BRep_Tool::Tolerance(aEAttr.LastVertex)) + { + aEAttr.MinDist = theDefEdge; + } + + if (aEAttr.IsSameUV) + { + // 1. is it really sameUV without being degenerated + gp_Pnt2d uvF, uvL; + thePCurve.Curve2d->D0(thePCurve.FirstParam, uvF); + thePCurve.Curve2d->D0(thePCurve.LastParam, uvL); + + if (!aEAttr.FirstUV.IsEqual(uvF, Precision::PConfusion())) + aEAttr.FirstUV = uvF; + + if (!aEAttr.LastUV.IsEqual(uvL, Precision::PConfusion())) + aEAttr.LastUV = uvL; + } + + return Standard_True; +} + +//======================================================================= +//function : registerEdgeVertices +//purpose : +//======================================================================= +void BRepMesh_FastDiscret::registerEdgeVertices( + BRepMesh_FastDiscret::EdgeAttributes& theAttributes, + Standard_Integer& ipf, + Standard_Integer& ivf, + Standard_Integer& isvf, + Standard_Integer& ipl, + Standard_Integer& ivl, + Standard_Integer& isvl) +{ + EdgeAttributes& aEAttr = theAttributes; + if (aEAttr.FirstVExtractor.IsNull()) + { + // Use edge geometry to produce tesselation. + aEAttr.FirstVExtractor = + new TopoDSVExplorer(aEAttr.FirstVertex, aEAttr.IsSameUV, aEAttr.LastVertex); + } + + if (aEAttr.LastVExtractor.IsNull()) + { + // Use edge geometry to produce tesselation. + aEAttr.LastVExtractor = + new TopoDSVExplorer(aEAttr.LastVertex, aEAttr.IsSameUV, aEAttr.FirstVertex); + } + + gp_XY aTmpUV; + // Process first vertex + ipf = myAttribute->GetVertexIndex(aEAttr.FirstVExtractor, Standard_True); + aTmpUV = BRepMesh_ShapeTool::FindUV(ipf, aEAttr.FirstUV, aEAttr.FirstVertex, + aEAttr.MinDist, myAttribute); + + myAttribute->AddNode(ipf, aTmpUV, BRepMesh_Frontier, ivf, isvf); + + // Process last vertex + ipl = aEAttr.LastVertex.IsSame(aEAttr.FirstVertex) ? ipf : + myAttribute->GetVertexIndex(aEAttr.LastVExtractor, Standard_True); + aTmpUV = BRepMesh_ShapeTool::FindUV(ipl, aEAttr.LastUV, aEAttr.LastVertex, + aEAttr.MinDist, myAttribute); + + myAttribute->AddNode(ipl, aTmpUV, BRepMesh_Frontier, ivl, isvl); +} + +//======================================================================= +//function : add +//purpose : +//======================================================================= +void BRepMesh_FastDiscret::add( + const TopoDS_Edge& theEdge, + const BRepMesh_FastDiscret::EdgePCurve& thePCurve, + const Standard_Real theDefEdge) +{ + const TopAbs_Orientation orEdge = theEdge.Orientation(); + if (orEdge == TopAbs_EXTERNAL) + return; + + EdgeAttributes aEAttr; + if (!getEdgeAttributes(theEdge, thePCurve, theDefEdge, aEAttr)) + return; + + if (!myEdges.IsBound(theEdge)) + { + update(theEdge, thePCurve.Curve2d, theDefEdge, aEAttr); + return; + } + + Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl; + registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl); + + // If this Edge has been already checked and it is not degenerated, + // the points of the polygon calculated at the first check are retrieved : + + // retrieve the polygone: + const BRepMesh_PairOfPolygon& aPair = myEdges.Find(theEdge); + const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First(); + const TColStd_Array1OfInteger& aNodes = aPolygon->Nodes(); + Handle(TColStd_HArray1OfReal) aParams = aPolygon->Parameters(); + + // creation anew: + const Standard_Integer aNodesNb = aNodes.Length(); + TColStd_Array1OfInteger aNewNodes (1, aNodesNb); + TColStd_Array1OfReal aNewParams(1, aNodesNb); + + aNewNodes (1) = isvf; + aNewParams(1) = aEAttr.FirstParam; + + aNewNodes (aNodesNb) = isvl; + aNewParams(aNodesNb) = aEAttr.LastParam; + + const TopoDS_Face& aFace = myAttribute->Face(); + if (!BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace)) + { + BRepMesh_EdgeParameterProvider aProvider(theEdge, aFace, aParams); + for (Standard_Integer i = 2; i < aNodesNb; ++i) { - BRepMesh_ShapeTool::NullifyEdge(theEdge, T, Loc); - BRepMesh_ShapeTool::NullifyFace(theFace); + const Standard_Integer aPointId = aNodes(i); + gp_Pnt& aPnt = myBoundaryPoints(aPointId); + + const Standard_Real aParam = aProvider.Parameter(i, aPnt); + gp_Pnt2d aUV = thePCurve.Curve2d->Value(aParam); + + Standard_Integer iv2, isv; + myAttribute->AddNode(aPointId, aUV.Coord(), BRepMesh_OnCurve, iv2, isv); + + aNewNodes (i) = isv; + aNewParams(i) = aParam; + + addLinkToMesh(ivf, iv2, orEdge); + ivf = iv2; } + + // last point + if (ivf != ivl) + addLinkToMesh(ivf, ivl, orEdge); } - while (!Poly.IsNull()); - return found; + Handle(Poly_PolygonOnTriangulation) P1 = + new Poly_PolygonOnTriangulation(aNewNodes, aNewParams); + + storePolygon(theEdge, P1, theDefEdge); } //======================================================================= -//function : output -//purpose : +//function : update(edge) +//purpose : //======================================================================= -Standard_Integer BRepMesh_FastDiscret::NbTriangles() const +void BRepMesh_FastDiscret::update( + const TopoDS_Edge& theEdge, + const Handle(Geom2d_Curve)& theC2d, + const Standard_Real theDefEdge, + BRepMesh_FastDiscret::EdgeAttributes& theAttributes) { - return myStructure->NbElements(); -} + EdgeAttributes& aEAttr = theAttributes; -//======================================================================= -//function : Triangle -//purpose : -//======================================================================= + const TopoDS_Face& aFace = myAttribute->Face(); + Handle(BRepMesh_IEdgeTool) aEdgeTool; + // Try to find existing tessellation. + for (Standard_Integer i = 1; aEdgeTool.IsNull(); ++i) + { + TopLoc_Location aLoc; + Handle(Poly_Triangulation) aTriangulation; + Handle(Poly_PolygonOnTriangulation) aPolygon; + BRep_Tool::PolygonOnTriangulation(theEdge, aPolygon, aTriangulation, aLoc, i); -const BRepMesh_Triangle& BRepMesh_FastDiscret::Triangle - (const Standard_Integer Index) const -{ - return myStructure->GetElement(Index); -} + if (aPolygon.IsNull()) + break; -//======================================================================= -//function : NbEdges -//purpose : -//======================================================================= + if (aTriangulation.IsNull() || !aPolygon->HasParameters()) + continue; -Standard_Integer BRepMesh_FastDiscret::NbEdges() const -{ - return myStructure->NbLinks(); -} + if (aPolygon->Deflection() > 1.1 * theDefEdge) + continue; -//======================================================================= -//function : Edge -//purpose : -//======================================================================= + const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes(); + const TColStd_Array1OfInteger& aIndices = aPolygon->Nodes(); + Handle(TColStd_HArray1OfReal) aParams = aPolygon->Parameters(); -const BRepMesh_Edge& BRepMesh_FastDiscret::Edge(const Standard_Integer Index) const -{ - return myStructure->GetLink(Index); -} + aEAttr.FirstVExtractor = new PolyVExplorer(aEAttr.FirstVertex, + aEAttr.IsSameUV, aEAttr.LastVertex, aIndices(1), aNodes, aLoc); -//======================================================================= -//function : NbVertices -//purpose : -//======================================================================= + aEAttr.LastVExtractor = new PolyVExplorer(aEAttr.LastVertex, + aEAttr.IsSameUV, aEAttr.FirstVertex, aIndices(aIndices.Length()), aNodes, aLoc); -Standard_Integer BRepMesh_FastDiscret::NbVertices() const -{ - return myStructure->NbNodes(); -} - -//======================================================================= -//function : Vertex -//purpose : -//======================================================================= - -const BRepMesh_Vertex& BRepMesh_FastDiscret::Vertex - (const Standard_Integer Index) const -{ - return myStructure->GetNode(Index); -} - -//======================================================================= -//function : Pnt -//purpose : -//======================================================================= - -const gp_Pnt& BRepMesh_FastDiscret::Pnt(const Standard_Integer Index) const -{ - return myLocation3d(myStructure->GetNode(Index).Location3d()); -} - -//======================================================================= -//function : VerticesOfDomain -//purpose : -//======================================================================= - -void BRepMesh_FastDiscret::VerticesOfDomain(BRepMeshCol::MapOfInteger& Indices) const -{ - Indices.Clear(); - - // recuperate from the map of edges. - const BRepMeshCol::MapOfInteger& edmap = myStructure->LinksOfDomain(); - - // iterator on edges. - BRepMeshCol::MapOfInteger::Iterator iter(edmap); - - Standard_Integer ind_edge; - for (iter.Reset(); iter.More(); iter.Next()) { - ind_edge = iter.Key(); - const BRepMesh_Edge& Ed = Edge(ind_edge); - Indices.Add(Ed.FirstNode()); - Indices.Add(Ed.LastNode()); + aEdgeTool = new BRepMesh_EdgeTessellationExtractor(theEdge, theC2d, + aFace, aTriangulation, aPolygon, aLoc); } + + if (aEdgeTool.IsNull()) + { + aEdgeTool = new BRepMesh_EdgeTessellator(theEdge, myAttribute, + mySharedFaces, theDefEdge, myAngle); + } + + Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl; + registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl); + + TopAbs_Orientation orEdge = theEdge.Orientation(); + Handle(Poly_PolygonOnTriangulation) P1, P2; + if (BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace)) + { + const Standard_Integer aNodesNb = 2; + TColStd_Array1OfInteger aNewNodes (1, aNodesNb); + TColStd_Array1OfInteger aNewNodInStruct(1, aNodesNb); + TColStd_Array1OfReal aNewParams (1, aNodesNb); + + aNewNodInStruct(1) = ipf; + aNewNodes (1) = isvf; + aNewParams (1) = aEAttr.FirstParam; + + aNewNodInStruct(aNodesNb) = ipl; + aNewNodes (aNodesNb) = isvl; + aNewParams (aNodesNb) = aEAttr.LastParam; + + P1 = new Poly_PolygonOnTriangulation(aNewNodes, aNewParams); + P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams); + } + else + { + const Standard_Integer aNodesNb = aEdgeTool->NbPoints(); + TColStd_Array1OfInteger aNewNodes (1, aNodesNb); + TColStd_Array1OfInteger aNewNodInStruct(1, aNodesNb); + TColStd_Array1OfReal aNewParams (1, aNodesNb); + + aNewNodInStruct(1) = ipf; + aNewNodes (1) = isvf; + aNewParams (1) = aEAttr.FirstParam; + + aNewNodInStruct(aNodesNb) = ipl; + aNewNodes (aNodesNb) = isvl; + aNewParams (aNodesNb) = aEAttr.LastParam; + + Standard_Integer aLastPointId = myAttribute->LastPointId(); + for (Standard_Integer i = 2; i < aNodesNb; ++i) + { + gp_Pnt aPnt; + gp_Pnt2d aUV; + Standard_Real aParam; + aEdgeTool->Value(i, aParam, aPnt, aUV); + myBoundaryPoints.Bind(++aLastPointId, aPnt); + + Standard_Integer iv2, isv; + myAttribute->AddNode(aLastPointId, aUV.Coord(), BRepMesh_Frontier, iv2, isv); + + aNewNodInStruct(i) = aLastPointId; + aNewNodes (i) = isv; + aNewParams (i) = aParam; + + addLinkToMesh(ivf, iv2, orEdge); + ivf = iv2; + } + + P1 = new Poly_PolygonOnTriangulation(aNewNodes, aNewParams); + P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams); + } + + // last point + if (ivf != ivl) + addLinkToMesh(ivf, ivl, orEdge); + + storePolygon(theEdge, P1, theDefEdge); + storePolygonSharedData(theEdge, P2, theDefEdge); } -BRepMesh_Status BRepMesh_FastDiscret::CurrentFaceStatus() const +//======================================================================= +//function : storeInternalPolygon +//purpose : +//======================================================================= +void BRepMesh_FastDiscret::storePolygon( + const TopoDS_Edge& theEdge, + Handle(Poly_PolygonOnTriangulation)& thePolygon, + const Standard_Real theDeflection) { - return myFacestate; + thePolygon->Deflection(theDeflection); + if (myInternalEdges->IsBound(theEdge)) + { + BRepMesh_PairOfPolygon& aPair = myInternalEdges->ChangeFind(theEdge); + if (theEdge.Orientation() == TopAbs_REVERSED) + aPair.Append(thePolygon); + else + aPair.Prepend(thePolygon); + + return; + } + + BRepMesh_PairOfPolygon aPair; + aPair.Append(thePolygon); + myInternalEdges->Bind(theEdge, aPair); +} + +//======================================================================= +//function : storePolygonSharedData +//purpose : +//======================================================================= +void BRepMesh_FastDiscret::storePolygonSharedData( + const TopoDS_Edge& theEdge, + Handle(Poly_PolygonOnTriangulation)& thePolygon, + const Standard_Real theDeflection) +{ + thePolygon->Deflection(theDeflection); + BRepMesh_PairOfPolygon aPair; + aPair.Append(thePolygon); + myEdges.Bind(theEdge, aPair); } //======================================================================= //function : GetFaceAttribute //purpose : //======================================================================= - -Standard_Boolean BRepMesh_FastDiscret::GetFaceAttribute(const TopoDS_Face& theFace, - Handle(BRepMesh_FaceAttribute)& theFattrib) const +Standard_Boolean BRepMesh_FastDiscret::GetFaceAttribute( + const TopoDS_Face& theFace, + Handle(BRepMesh_FaceAttribute)& theAttribute ) const { - if(myMapattrib.IsBound(theFace)) + if (myAttributes.IsBound(theFace)) { - theFattrib = myMapattrib(theFace); + theAttribute = myAttributes(theFace); return Standard_True; } + return Standard_False; } @@ -1632,28 +979,8 @@ Standard_Boolean BRepMesh_FastDiscret::GetFaceAttribute(const TopoDS_Face& //function : RemoveFaceAttribute //purpose : //======================================================================= - void BRepMesh_FastDiscret::RemoveFaceAttribute(const TopoDS_Face& theFace) { - if(myMapattrib.IsBound(theFace)) - myMapattrib.UnBind(theFace); -} - -//======================================================================= -//function : CreateMutexesForSubShapes -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::CreateMutexesForSubShapes(const TopoDS_Shape& theShape, - const TopAbs_ShapeEnum theType) -{ - myMutexProvider.CreateMutexesForSubShapes(theShape, theType); -} - -//======================================================================= -//function : RemoveAllMutexes -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::RemoveAllMutexes() -{ - myMutexProvider.RemoveAllMutexes(); + if (myAttributes.IsBound(theFace)) + myAttributes.UnBind(theFace); } diff --git a/src/BRepMesh/BRepMesh_FastDiscret.hxx b/src/BRepMesh/BRepMesh_FastDiscret.hxx index 245fa604c0..35b02f6ef0 100644 --- a/src/BRepMesh/BRepMesh_FastDiscret.hxx +++ b/src/BRepMesh/BRepMesh_FastDiscret.hxx @@ -31,16 +31,19 @@ #include #include #include +#include +#include +#include +#include +#include class BRepMesh_DataStructureOfDelaun; class Bnd_Box; class TopoDS_Shape; class TopoDS_Face; -class TopTools_IndexedDataMapOfShapeListOfShape; class TopoDS_Edge; class BRepAdaptor_HSurface; class Geom2d_Curve; -class TopoDS_Vertex; class BRepMesh_Edge; class BRepMesh_Vertex; class gp_Pnt; @@ -86,16 +89,17 @@ public: const Standard_Boolean shapetrigu = Standard_False, const Standard_Boolean isInParallel = Standard_False); - //! Build triangulation on the whole shape
+ //! Build triangulation on the whole shape. Standard_EXPORT void Perform(const TopoDS_Shape& shape); - //! Record a face for further processing.
- Standard_EXPORT void Add(const TopoDS_Face& face, - const TopTools_IndexedDataMapOfShapeListOfShape& ancestor) ; + //! Record a face for further processing. + //! @return status flags collected during discretization + //! of boundaries of the given face. + Standard_EXPORT Standard_Integer Add(const TopoDS_Face& face); - //! Triangulate a face previously recorded for
- //! processing by call to Add(). Can be executed in
- //! parallel threads.
+ //! Triangulate a face previously recorded for + //! processing by call to Add(). Can be executed in + //! parallel threads. Standard_EXPORT void Process(const TopoDS_Face& face) const; void operator ()(const TopoDS_Face& face) const @@ -103,82 +107,22 @@ public: Process(face); } - Standard_EXPORT BRepMesh_Status CurrentFaceStatus() const; - //! Request algorithm to launch in multiple threads
//! to improve performance (should be supported by plugin).
- Standard_EXPORT void SetParallel(const Standard_Boolean theInParallel); + inline void SetParallel(const Standard_Boolean theInParallel) + { + myInParallel = theInParallel; + } //! Returns the multi-threading usage flag.
- Standard_EXPORT Standard_Boolean IsParallel() const; - - //! Creates mutexes for each sub-shape of type theType in theShape.
- //! Used to avoid data races.
- Standard_EXPORT void CreateMutexesForSubShapes(const TopoDS_Shape& theShape, - const TopAbs_ShapeEnum theType); - - //! Removes all created mutexes
- Standard_EXPORT void RemoveAllMutexes(); - - //! Gives the number of built triangles.
- Standard_EXPORT Standard_Integer NbTriangles() const; - - //! Gives the triangle of .
- Standard_EXPORT const BRepMesh_Triangle& Triangle(const Standard_Integer Index) const; - - //! Gives the number of built Edges
- Standard_EXPORT Standard_Integer NbEdges() const; - - //! Gives the edge of index .
- Standard_EXPORT const BRepMesh_Edge& Edge(const Standard_Integer Index) const; - - //! Gives the number of built Vertices.
- Standard_EXPORT Standard_Integer NbVertices() const; - - //! Gives the vertex of .
- Standard_EXPORT const BRepMesh_Vertex& Vertex(const Standard_Integer Index) const; - - //! Gives the nodes of triangle with the given index. - Standard_EXPORT void TriangleNodes(const Standard_Integer theIndex, - Standard_Integer (&theNodes)[3]) const + inline Standard_Boolean IsParallel() const { - myStructure->ElementNodes(Triangle(theIndex), theNodes); + return myInParallel; } - - //! Gives the location3d of the vertex of .
- Standard_EXPORT const gp_Pnt& Pnt(const Standard_Integer Index) const; - + //! Gives the list of indices of the vertices
Standard_EXPORT void VerticesOfDomain(BRepMeshCol::MapOfInteger& Indices) const; - //! Gives the list of indices of the edges
- inline void EdgesOfDomain(BRepMeshCol::MapOfInteger& Indices) const - { - Indices = myStructure->LinksOfDomain(); - } - - //! Gives the list of indices of the triangles
- inline void TrianglesOfDomain(BRepMeshCol::MapOfInteger& Indices) const - { - Indices = myStructure->ElementsOfDomain(); - } - - //! Gives the number of different location in 3d space. - //! It is different of the number of vertices if there - //! is more than one surface.
- //! Even for one surface, the number can be different - //! if an edge is shared.
- inline Standard_Integer NbPoint3d() const - { - return myNbLocat; - } - - //! Gives the 3d space location of the vertex .
- inline const gp_Pnt& Point3d(const Standard_Integer Index) const - { - return myLocation3d(Index); - } - //! returns the deflection value.
inline Standard_Real GetDeflection() const { @@ -206,82 +150,227 @@ public: return myShapetrigu; } - //! returns the face deflection value.
- Standard_EXPORT Standard_Boolean GetFaceAttribute(const TopoDS_Face& face,Handle(BRepMesh_FaceAttribute)& fattrib) const; + Standard_EXPORT void InitSharedFaces(const TopoDS_Shape& theShape); - //! remove face attribute as useless to free locate memory
- Standard_EXPORT void RemoveFaceAttribute(const TopoDS_Face& face); - - inline const TopTools_DataMapOfShapeReal& GetMapOfDefEdge() const + inline const TopTools_IndexedDataMapOfShapeListOfShape& SharedFaces() const { - return myMapdefle; + return mySharedFaces; } + //! Gives face attribute. + Standard_EXPORT Standard_Boolean GetFaceAttribute + ( const TopoDS_Face& theFace, Handle(BRepMesh_FaceAttribute)& theAttribute ) const; + + //! Remove face attribute as useless to free locate memory. + Standard_EXPORT void RemoveFaceAttribute( const TopoDS_Face& theFace ); + + //! Returns number of boundary 3d points. + inline Standard_Integer NbBoundaryPoints() const + { + return myBoundaryPoints.Extent(); + } DEFINE_STANDARD_RTTI(BRepMesh_FastDiscret) -private: - - void Add(const TopoDS_Edge& edge, - const TopoDS_Face& face, - const Handle(BRepAdaptor_HSurface)& S, - const Handle(Geom2d_Curve)& C, - const TopTools_IndexedDataMapOfShapeListOfShape& ancestor, - const Standard_Real defedge, - const Standard_Real first, - const Standard_Real last); - - void Add(const TopoDS_Vertex& theVert, - const TopoDS_Face& face, - const Handle(BRepAdaptor_HSurface)& S); - - Standard_Boolean Update(const TopoDS_Edge& Edge, - const TopoDS_Face& Face, - const Handle(Geom2d_Curve)& C, - const Standard_Real defedge, - const Standard_Real first, - const Standard_Real last); - - void InternalVertices(const Handle(BRepAdaptor_HSurface)& caro, - BRepMeshCol::ListOfVertex& inter, - const Standard_Real defedge, - const BRepMeshCol::HClassifier& classifier); - - Standard_Real Control(const Handle(BRepAdaptor_HSurface)& caro, - const Standard_Real defface, - BRepMeshCol::ListOfVertex& inter, - BRepMeshCol::ListOfInteger& badTri, - BRepMeshCol::ListOfInteger& nulTri, - BRepMesh_Delaun& trigu, - const Standard_Boolean isfirst); - - void AddInShape(const TopoDS_Face& face, - const Standard_Real defedge); +private: + + //! Auxiliary class used to extract geometrical parameters of TopoDS_Vertex. + class TopoDSVExplorer + { + public: + TopoDSVExplorer( + const TopoDS_Vertex& theVertex, + const Standard_Boolean isSameUV, + const TopoDS_Vertex& theSameVertex) + : myVertex(theVertex), + myIsSameUV(isSameUV), + mySameVertex(theSameVertex) + { + } + + const TopoDS_Vertex& Vertex() const + { + return myVertex; + } + + Standard_Boolean IsSameUV() const + { + return myIsSameUV; + } + + const TopoDS_Vertex& SameVertex() const + { + return mySameVertex; + } + + virtual gp_Pnt Point() const + { + return BRep_Tool::Pnt(myVertex); + } + + private: + + void operator =(const TopoDSVExplorer& /*theOther*/) + { + } + + private: + const TopoDS_Vertex& myVertex; + Standard_Boolean myIsSameUV; + const TopoDS_Vertex& mySameVertex; + }; + + + //! Auxiliary class used to extract polygonal parameters of TopoDS_Vertex. + class PolyVExplorer : public TopoDSVExplorer + { + public: + PolyVExplorer( + const TopoDS_Vertex& theVertex, + const Standard_Boolean isSameUV, + const TopoDS_Vertex& theSameVertex, + const Standard_Integer theVertexIndex, + const TColgp_Array1OfPnt& thePolygon, + const TopLoc_Location& theLoc) + : TopoDSVExplorer(theVertex, isSameUV, theSameVertex), + myVertexIndex(theVertexIndex), + myPolygon(thePolygon), + myLoc(theLoc) + { + } + + virtual gp_Pnt Point() const + { + return BRepMesh_ShapeTool::UseLocation(myPolygon(myVertexIndex), myLoc); + } + + private: + + void operator =(const PolyVExplorer& /*theOther*/) + { + } + + private: + Standard_Integer myVertexIndex; + const TColgp_Array1OfPnt& myPolygon; + const TopLoc_Location myLoc; + }; + + //! Structure keeps common parameters of edge + //! used for tessellation. + struct EdgeAttributes + { + TopoDS_Vertex FirstVertex; + TopoDS_Vertex LastVertex; + + Standard_Real FirstParam; + Standard_Real LastParam; + + gp_Pnt2d FirstUV; + gp_Pnt2d LastUV; + + Standard_Boolean IsSameUV; + Standard_Real MinDist; + + N_HANDLE FirstVExtractor; + N_HANDLE LastVExtractor; + }; + + //! Structure keeps geometrical parameters of edge's PCurve. + //! Used for caching. + struct EdgePCurve + { + Handle(Geom2d_Curve) Curve2d; + Standard_Real FirstParam; + Standard_Real LastParam; + }; + + //! Fills structure of by attributes of the given edge. + //! @return TRUE on success, FALSE elsewhere. + Standard_Boolean getEdgeAttributes( + const TopoDS_Edge& theEdge, + const EdgePCurve& thePCurve, + const Standard_Real theDefEdge, + EdgeAttributes& theAttributes) const; + + //! Registers end vertices of the edge in mesh data + //! structure of currently processed face. + void registerEdgeVertices( + EdgeAttributes& theAttributes, + Standard_Integer& ipf, + Standard_Integer& ivf, + Standard_Integer& isvf, + Standard_Integer& ipl, + Standard_Integer& ivl, + Standard_Integer& isvl); + + //! Adds tessellated representation of the given edge to + //! mesh data structure of currently processed face. + void add(const TopoDS_Edge& theEdge, + const EdgePCurve& theCurve2D, + const Standard_Real theEdgeDeflection); + + //! Updates tessellated representation of the given edge. + //! If edge already has a polygon which deflection satisfies + //! the given value, retrieves tessellation from polygon. + //! Computes tessellation using edge's geometry elsewhere. + void update( + const TopoDS_Edge& theEdge, + const Handle(Geom2d_Curve)& theCurve2D, + const Standard_Real theEdgeDeflection, + EdgeAttributes& theAttributes); + + //! Adds new link to the mesh data structure. + //! Movability of the link and order of nodes depend on orientation parameter. + void addLinkToMesh(const Standard_Integer theFirstNodeId, + const Standard_Integer theLastNodeId, + const TopAbs_Orientation theOrientation); + + //! Stores polygonal model of the given edge. + //! @param theEdge edge which polygonal model is stored. + //! @param thePolygon polygonal model of the edge. + //! @param theDeflection deflection with which polygonalization is performed. + //! This value is stored inside the polygon. + void storePolygon( + const TopoDS_Edge& theEdge, + Handle(Poly_PolygonOnTriangulation)& thePolygon, + const Standard_Real theDeflection); + + //! Caches polygonal model of the given edge to be used in further. + //! @param theEdge edge which polygonal data is stored. + //! @param thePolygon shared polygonal data of the edge. + //! @param theDeflection deflection with which polygonalization is performed. + //! This value is stored inside the polygon. + void storePolygonSharedData( + const TopoDS_Edge& theEdge, + Handle(Poly_PolygonOnTriangulation)& thePolygon, + const Standard_Real theDeflection); private: - Standard_Real myAngle; - Standard_Real myDeflection; - Standard_Real myDtotale; - Standard_Boolean myWithShare; - Standard_Boolean myInParallel; - BRepMeshCol::DMapOfVertexInteger myVertices; - BRepMeshCol::DMapOfShapePairOfPolygon myEdges; - BRepMeshCol::DMapOfShapePairOfPolygon myInternaledges; - Standard_Integer myNbLocat; - BRepMeshCol::DMapOfIntegerPnt myLocation3d; - Handle_BRepMesh_DataStructureOfDelaun myStructure; - BRepMeshCol::DMapOfFaceAttribute myMapattrib; - TColStd_IndexedMapOfInteger myVemap; - BRepMeshCol::DMapOfIntegerListOfXY myLocation2d; - Standard_Boolean myRelative; - Standard_Boolean myShapetrigu; - Standard_Boolean myInshape; - BRepMesh_Status myFacestate; - TopTools_DataMapOfShapeReal myMapdefle; - TopTools_ListOfShape myNottriangulated; - BRepMeshCol::Allocator myAllocator; - TopTools_MutexForShapeProvider myMutexProvider; + TopoDS_Face myFace; + Standard_Real myAngle; + Standard_Real myDeflection; + Standard_Real myDtotale; + Standard_Boolean myWithShare; + Standard_Boolean myInParallel; + BRepMeshCol::DMapOfShapePairOfPolygon myEdges; + BRepMeshCol::DMapOfFaceAttribute myAttributes; + Standard_Boolean myRelative; + Standard_Boolean myShapetrigu; + Standard_Boolean myInshape; + TopTools_DataMapOfShapeReal myMapdefle; + + // Data shared for whole shape + BRepMeshCol::DMapOfVertexInteger myBoundaryVertices; + BRepMeshCol::DMapOfIntegerPnt myBoundaryPoints; + + // Fast access to attributes of current face + Handle(BRepMesh_FaceAttribute) myAttribute; + Handle(BRepMesh_DataStructureOfDelaun) myStructure; + BRepMeshCol::HIMapOfInteger myVertexEdgeMap; + BRepMeshCol::HDMapOfShapePairOfPolygon myInternalEdges; + TopTools_IndexedDataMapOfShapeListOfShape mySharedFaces; }; DEFINE_STANDARD_HANDLE(BRepMesh_FastDiscret, Standard_Transient) diff --git a/src/BRepMesh/BRepMesh_FastDiscretFace.cxx b/src/BRepMesh/BRepMesh_FastDiscretFace.cxx index b2e5f208ff..949f26a7ac 100644 --- a/src/BRepMesh/BRepMesh_FastDiscretFace.cxx +++ b/src/BRepMesh/BRepMesh_FastDiscretFace.cxx @@ -15,7 +15,6 @@ #include #include -#include #include #include #include @@ -30,7 +29,6 @@ #include #include -#include #include #include #include @@ -56,7 +54,7 @@ #include #include -#define UVDEFLECTION 1.e-05 +#include IMPLEMENT_STANDARD_HANDLE (BRepMesh_FastDiscretFace, Standard_Transient) IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscretFace, Standard_Transient) @@ -92,6 +90,52 @@ static Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_ return (n? (result / (Standard_Real) n) : -1.); } +namespace { + + //! Auxiliary class used to extract geometrical parameters of fixed TopoDS_Vertex. + class FixedVExplorer + { + public: + + DEFINE_STANDARD_ALLOC + + FixedVExplorer(const TopoDS_Vertex& theVertex) + : myVertex(theVertex) + { + } + + const TopoDS_Vertex& Vertex() const + { + return myVertex; + } + + Standard_Boolean IsSameUV() const + { + return Standard_False; + } + + TopoDS_Vertex SameVertex() const + { + return TopoDS_Vertex(); + } + + virtual gp_Pnt Point() const + { + return BRep_Tool::Pnt(myVertex); + } + + private: + + void operator =(const FixedVExplorer& /*theOther*/) + { + } + + private: + const TopoDS_Vertex& myVertex; + }; +} + + //======================================================================= //function : BRepMesh_FastDiscretFace //purpose : @@ -99,7 +143,7 @@ static Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_ BRepMesh_FastDiscretFace::BRepMesh_FastDiscretFace (const Standard_Real theAngle, const Standard_Boolean theWithShare) : - myAngle(theAngle), myWithShare(theWithShare), myNbLocat(0), + myAngle(theAngle), myWithShare(theWithShare), myInternalVerticesMode(Standard_True) { myAllocator = new NCollection_IncAllocator(64000); @@ -109,446 +153,188 @@ BRepMesh_FastDiscretFace::BRepMesh_FastDiscretFace //function : Add(face) //purpose : //======================================================================= - -void BRepMesh_FastDiscretFace::Add(const TopoDS_Face& theFace, - const Handle(BRepMesh_FaceAttribute)& theAttrib, - const TopTools_DataMapOfShapeReal& theMapDefle, - const TopTools_MutexForShapeProvider& theMutexProvider) +void BRepMesh_FastDiscretFace::Add(const Handle(BRepMesh_FaceAttribute)& theAttribute) { -#ifndef DEB_MESH - try + if (!theAttribute->IsValid()) + return; + + myAttribute = theAttribute; + myStructure = myAttribute->ChangeStructure(); + myVertexEdgeMap = myAttribute->ChangeVertexEdgeMap(); + myClassifier = myAttribute->ChangeClassifier(); + mySurfacePoints = myAttribute->ChangeSurfacePoints(); + + Standard_Real aTolU = myAttribute->ToleranceU(); + Standard_Real aTolV = myAttribute->ToleranceV(); + Standard_Real uCellSize = 14.0 * aTolU; + Standard_Real vCellSize = 14.0 * aTolV; + + const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); + GeomAbs_SurfaceType thetype = gFace->GetType(); + + Standard_Integer i = 1; + + //////////////////////////////////////////////////////////// + //add internal vertices after self-intersection check + Standard_Integer nbVertices = 0; + if ( myInternalVerticesMode ) { - OCC_CATCH_SIGNALS -#endif - TopoDS_Face face = theFace; - TopLoc_Location loc; + TopExp_Explorer anExplorer(myAttribute->Face(), TopAbs_VERTEX, TopAbs_EDGE); + for ( ; anExplorer.More(); anExplorer.Next() ) + add(TopoDS::Vertex(anExplorer.Current())); + nbVertices = myVertexEdgeMap->Extent(); + } - const Handle(Poly_Triangulation)& aFaceTrigu = BRep_Tool::Triangulation(face, loc); - if ( aFaceTrigu.IsNull() ) - return; + // essai de determination de la longueur vraie: + // akm (bug OCC16) : We must calculate these measures in non-singular + // parts of face. Let`s try to compute average value of three + // (umin, (umin+umax)/2, umax), and respectively for v. + // vvvvv + //Standard_Real longu = 0.0, longv = 0.0; //, last , first; + //gp_Pnt P11, P12, P21, P22, P31, P32; - myAttrib = theAttrib; - face.Orientation(TopAbs_FORWARD); - myStructure.Nullify(); - Handle(NCollection_IncAllocator) anAlloc = Handle(NCollection_IncAllocator)::DownCast(myAllocator); - anAlloc->Reset(Standard_False); - myStructure=new BRepMesh_DataStructureOfDelaun(anAlloc); - - Standard_Real umax = myAttrib->GetUMax(); - Standard_Real umin = myAttrib->GetUMin(); - Standard_Real vmax = myAttrib->GetVMax(); - Standard_Real vmin = myAttrib->GetVMin(); + const Standard_Real deltaX = myAttribute->GetDeltaX(); + const Standard_Real deltaY = myAttribute->GetDeltaY(); - Standard_Real aTolU = Max( Precision::PConfusion(), (umax - umin) * UVDEFLECTION ); - Standard_Real aTolV = Max( Precision::PConfusion(), (vmax - vmin) * UVDEFLECTION ); - Standard_Real uCellSize = 14 * aTolU; - Standard_Real vCellSize = 14 * aTolV; + BRepMeshCol::Array1OfInteger tabvert_corr(1, nbVertices); - myStructure->Data().SetCellSize ( uCellSize, vCellSize ); - myStructure->Data().SetTolerance( aTolU, aTolV ); + // Check the necessity to fill the map of parameters + const Standard_Boolean useUVParam = (thetype == GeomAbs_Torus || + thetype == GeomAbs_BezierSurface || + thetype == GeomAbs_BSplineSurface); + myUParam.Clear(); + myVParam.Clear(); + BRepMesh_VertexTool aMoveNodes(nbVertices, myAllocator); - BRepAdaptor_Surface BS(face, Standard_False); - Handle(BRepAdaptor_HSurface) gFace = new BRepAdaptor_HSurface(BS); - - GeomAbs_SurfaceType thetype; - thetype = BS.GetType(); - - TopAbs_Orientation orFace = face.Orientation(); + aMoveNodes.SetCellSize ( uCellSize / deltaX, vCellSize / deltaY); + aMoveNodes.SetTolerance( aTolU / deltaX, aTolV / deltaY); - if (!myWithShare) - myVertices.Clear(); + for ( i = 1; i <= myStructure->NbNodes(); ++i ) + { + const BRepMesh_Vertex& v = myStructure->GetNode(i); + gp_XY aPnt2d = v.Coord(); - myListver.Clear(); - myVemap.Clear(); - myLocation2d.Clear(); - myInternaledges.Clear(); + if (useUVParam) + { + myUParam.Add(aPnt2d.X()); + myVParam.Add(aPnt2d.Y()); + } - Standard_Integer i = 1; - Standard_Integer ipn = 0; - - TopoDS_Iterator exW(face); - for (; exW.More(); exW.Next()) { - const TopoDS_Shape& aWire = exW.Value(); - if (aWire.ShapeType() != TopAbs_WIRE) + aPnt2d = myAttribute->Scale(aPnt2d, Standard_True); + BRepMesh_Vertex v_new(aPnt2d, v.Location3d(), v.Movability()); + const BRepMeshCol::ListOfInteger& alist = myStructure->LinksConnectedTo(i); + aMoveNodes.Add(v_new, alist); + tabvert_corr(i) = i; + } + myStructure->ReplaceNodes(aMoveNodes); + + Standard_Boolean rajout = + (thetype == GeomAbs_Sphere || thetype == GeomAbs_Torus); + + BRepMesh_Delaun trigu(myStructure, tabvert_corr); + + //removed all free edges from triangulation + const Standard_Integer nbLinks = myStructure->NbLinks(); + for( i = 1; i <= nbLinks; i++ ) + { + if( myStructure->ElementsConnectedTo(i).Extent() < 1 ) + { + BRepMesh_Edge& anEdge = (BRepMesh_Edge&)trigu.GetEdge(i); + if ( anEdge.Movability() == BRepMesh_Deleted ) continue; - TopoDS_Iterator ex(aWire); - for(; ex.More(); ex.Next()) { - const TopoDS_Edge& edge = TopoDS::Edge(ex.Value()); - if(edge.IsNull()) - continue; - RestoreStructureFromTriangulation(edge, face, gFace, aFaceTrigu, - theMapDefle(edge), loc, theMutexProvider); - } + + anEdge.SetMovability(BRepMesh_Free); + myStructure->RemoveLink(i); } - - //////////////////////////////////////////////////////////// - //add internal vertices after self-intersection check - Standard_Integer nbVertices = 0; - if(myInternalVerticesMode) { - for(TopExp_Explorer ex(face,TopAbs_VERTEX ,TopAbs_EDGE); ex.More(); ex.Next()) { - const TopoDS_Vertex& aVert = TopoDS::Vertex(ex.Current()); - Add(aVert,face,gFace); - } - nbVertices = myVemap.Extent(); - } - - // essai de determination de la longueur vraie: - // akm (bug OCC16) : We must calculate these measures in non-singular - // parts of face. Let`s try to compute average value of three - // (umin, (umin+umax)/2, umax), and respectively for v. - // vvvvv - //Standard_Real longu = 0.0, longv = 0.0; //, last , first; - //gp_Pnt P11, P12, P21, P22, P31, P32; - - Standard_Real deltaX = myAttrib->GetDeltaX(); - Standard_Real deltaY = myAttrib->GetDeltaY(); - - BRepMeshCol::Array1OfInteger tabvert_corr(1, nbVertices); - gp_Pnt2d p2d; - - // Check the necessity to fill the map of parameters - const Standard_Boolean useUVParam = (thetype == GeomAbs_Torus || - thetype == GeomAbs_BezierSurface || - thetype == GeomAbs_BSplineSurface); - myUParam.Clear(); - myVParam.Clear(); - - BRepMesh_VertexTool aMoveNodes(myVemap.Extent(), myAllocator); - - aMoveNodes.SetCellSize ( uCellSize / deltaX, vCellSize / deltaY); - aMoveNodes.SetTolerance( aTolU / deltaX, aTolV / deltaY); - - for (i = 1; i <= myStructure->NbNodes(); i++) - { - const BRepMesh_Vertex& v = myStructure->GetNode(i); - p2d = v.Coord(); - if (useUVParam) { - myUParam.Add(p2d.X()); - myVParam.Add(p2d.Y()); - } - gp_XY res; - res.SetCoord((p2d.X() - umin ) / deltaX, - (p2d.Y() - vmin ) / deltaY); - BRepMesh_Vertex v_new(res,v.Location3d(),v.Movability()); - const BRepMeshCol::ListOfInteger& alist = myStructure->LinksConnectedTo(i); - aMoveNodes.Add(v_new, alist); - tabvert_corr(i) = i; - } - myStructure->ReplaceNodes(aMoveNodes); - - Standard_Boolean rajout; - - BRepMeshCol::HClassifier& classifier = theAttrib->GetClassifier(); - - switch (thetype) - { - case GeomAbs_Sphere: - case GeomAbs_Torus: - rajout = Standard_True; - break; - default: - rajout = Standard_False; - } - - BRepMesh_Delaun trigu(myStructure, tabvert_corr, orFace==TopAbs_FORWARD); - - //removed all free edges from triangulation - Standard_Integer nbLinks = myStructure->NbLinks(); - for( i = 1; i <= nbLinks; i++ ) - { - if( myStructure->ElementsConnectedTo(i).Extent() < 1 ) - { - BRepMesh_Edge& anEdge = (BRepMesh_Edge&)trigu.GetEdge(i); - if ( anEdge.Movability() == BRepMesh_Deleted ) - continue; - - anEdge.SetMovability(BRepMesh_Free); - myStructure->RemoveLink(i); - } - } - - Standard_Boolean isaline; - isaline = ((umax-umin) < UVDEFLECTION) || ((vmax-vmin) < UVDEFLECTION); - - Standard_Real aDef = -1; - if (!isaline && myStructure->ElementsOfDomain().Extent() > 0) { - BRepMeshCol::ListOfInteger badTri, nulTri; - - if(!rajout) - { - aDef = Control(gFace, theAttrib->GetDefFace(), myListver, badTri, nulTri, trigu, Standard_True); - if( aDef > theAttrib->GetDefFace() || aDef < 0.) - rajout = Standard_True; - } - - if(!rajout) { - if(useUVParam) { - if(BS.IsUClosed()) { - if(myVParam.Extent() > 2) { - rajout = Standard_True; - } - } - if(BS.IsVClosed()) { - if(myUParam.Extent() > 2) { - rajout = Standard_True; - } - } - } - } - - if(rajout){ - InternalVertices(gFace, myListver, theAttrib->GetDefFace(), classifier); - - if (myListver.Extent() > 0) { - BRepMeshCol::Array1OfVertexOfDelaun verttab(1, myListver.Extent()); - BRepMeshCol::ListOfVertex::Iterator itVer(myListver); - ipn = 1; - for (; itVer.More(); itVer.Next()) - verttab(ipn++) = itVer.Value(); - trigu.AddVertices(verttab); - } - //control internal points - BRepMeshCol::ListOfVertex vvlist; - aDef = Control(gFace, theAttrib->GetDefFace(), vvlist, badTri, nulTri, trigu, Standard_False); - myListver.Append(vvlist); - } - } - - //modify myStructure back - aMoveNodes.SetCellSize ( uCellSize, vCellSize ); - aMoveNodes.SetTolerance( aTolU , aTolV ); - for (i = 1; i <= myStructure->NbNodes(); i++) - { - const BRepMesh_Vertex& v = myStructure->GetNode(i); - p2d = v.Coord(); - gp_XY res; - res.SetCoord(p2d.X() * deltaX + umin, p2d.Y() * deltaY + vmin); - BRepMesh_Vertex v_new(res,v.Location3d(),v.Movability()); - const BRepMeshCol::ListOfInteger& alist = myStructure->LinksConnectedTo(i); - aMoveNodes.Add(v_new, alist); - } - myStructure->ReplaceNodes(aMoveNodes); - - AddInShape(face, (aDef < 0.0)? theAttrib->GetDefFace() : aDef, theMutexProvider); -#ifndef DEB_MESH } - catch(Standard_Failure) + + const Standard_Real umax = myAttribute->GetUMax(); + const Standard_Real umin = myAttribute->GetUMin(); + const Standard_Real vmax = myAttribute->GetVMax(); + const Standard_Real vmin = myAttribute->GetVMin(); + + Standard_Boolean isaline = + ((umax - umin) < Precision::PConfusion() || + (vmax - vmin) < Precision::PConfusion()); + + Standard_Real aDef = -1; + if ( !isaline && myStructure->ElementsOfDomain().Extent() > 0 ) { - BRepMesh_ShapeTool::NullifyFace(theFace); + BRepMeshCol::ListOfVertex aNewVertices; + if ( !rajout ) + { + aDef = control(aNewVertices, trigu, Standard_True); + + if( aDef > myAttribute->GetDefFace() || aDef < 0.) + rajout = Standard_True; + } + + if ( !rajout && useUVParam ) + { + if ( myVParam.Extent() > 2 && + (gFace->IsUClosed() || + gFace->IsVClosed())) + { + rajout = Standard_True; + } + } + + if ( rajout ) + { + insertInternalVertices(aNewVertices, trigu); + + //control internal points + aDef = control(aNewVertices, trigu, Standard_False); + } } -#endif // DEB_MESH - myStructure.Nullify(); - myAttrib.Nullify(); + + //modify myStructure back + aMoveNodes.SetCellSize ( uCellSize, vCellSize ); + aMoveNodes.SetTolerance( aTolU , aTolV ); + + for ( i = 1; i <= myStructure->NbNodes(); ++i ) + { + const BRepMesh_Vertex& v = myStructure->GetNode(i); + gp_XY aPnt2d = myAttribute->Scale(v.Coord(), Standard_False); + BRepMesh_Vertex v_new(aPnt2d, v.Location3d(), v.Movability()); + const BRepMeshCol::ListOfInteger& alist = myStructure->LinksConnectedTo(i); + aMoveNodes.Add(v_new, alist); + + // Register internal nodes used in triangulation + if (!alist.IsEmpty() && myVertexEdgeMap->FindIndex(i) == 0) + myVertexEdgeMap->Add(i); + } + myStructure->ReplaceNodes(aMoveNodes); + + if (!(aDef < 0.)) + myAttribute->SetDefFace(aDef); } //======================================================================= -//function : RestoreStructureFromTriangulation(edge) -//purpose : Restore structure of Delaun from triangulation on face +//function : addVerticesToMesh +//purpose : //======================================================================= -Standard_Boolean BRepMesh_FastDiscretFace::RestoreStructureFromTriangulation - (const TopoDS_Edge& theEdge, - const TopoDS_Face& theFace, - const Handle(BRepAdaptor_HSurface)& theSurf, - const Handle(Poly_Triangulation)& theTrigu, - const Standard_Real theDefEdge, - const TopLoc_Location& theLoc, - const TopTools_MutexForShapeProvider& theMutexProvider) +Standard_Boolean BRepMesh_FastDiscretFace::addVerticesToMesh( + const BRepMeshCol::ListOfVertex& theVertices, + BRepMesh_Delaun& theMeshBuilder) { - // 2d vertex indices - TopAbs_Orientation orEdge = theEdge.Orientation(); - // Get end points on 2d curve - gp_Pnt2d uvFirst, uvLast; - // oan: changes for right restoring of triangulation data from face & edges - Handle(Poly_PolygonOnTriangulation) Poly; + if (theVertices.IsEmpty()) + return Standard_False; - { - // lock mutex during querying data from edge curves to prevent parallel change of the same data - Standard_Mutex* aMutex = theMutexProvider.GetMutex(theEdge); - Standard_Mutex::Sentry aSentry (aMutex); - - Poly = BRep_Tool::PolygonOnTriangulation(theEdge, theTrigu, theLoc); - if (Poly.IsNull() || !Poly->HasParameters()) - return Standard_False; - - BRep_Tool::UVPoints(theEdge, theFace, uvFirst, uvLast); - } - - // Get vertices - TopoDS_Vertex pBegin, pEnd; - TopExp::Vertices(theEdge,pBegin,pEnd); - - const Standard_Boolean sameUV = - uvFirst.IsEqual(uvLast, Precision::PConfusion()); - - const TColgp_Array1OfPnt2d& UVNodes = theTrigu->UVNodes(); - const TColgp_Array1OfPnt& Nodes = theTrigu->Nodes(); - const TColStd_Array1OfInteger& Indices = Poly->Nodes(); - - const Standard_Integer nbnodes = Indices.Length(); - TColStd_Array1OfInteger NewNodes(1, nbnodes); - - gp_Pnt P3d; - gp_XY anUV; - - // Process first vertex - Standard_Integer ipf; - if (myVertices.IsBound(pBegin)) - { - ipf = myVertices.Find(pBegin); - } - else - { - if (sameUV && myVertices.IsBound(pEnd)) - { - ipf = myVertices.Find(pEnd); - } - else - { - P3d = Nodes(Indices(1)); - if (!theLoc.IsIdentity()) - P3d.Transform(theLoc.Transformation()); - myNbLocat++; - myLocation3d.Bind(myNbLocat, P3d); - ipf = myNbLocat; - } - myVertices.Bind(pBegin,ipf); - } - - //Controle vertice tolerances - gp_Pnt pFirst = theSurf->Value(uvFirst.X(), uvFirst.Y()); - gp_Pnt pLast = theSurf->Value(uvLast.X(), uvLast.Y()); - - Standard_Real mindist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(pBegin)), - pLast.Distance(BRep_Tool::Pnt(pEnd))); - - if (mindist < BRep_Tool::Tolerance(pBegin) || - mindist < BRep_Tool::Tolerance(pEnd) ) mindist = theDefEdge; - - anUV = BRepMesh_ShapeTool::FindUV(ipf, uvFirst, - pBegin, mindist, myAttrib, theSurf, myLocation2d); - - Standard_Integer iv1, isv1; - BRepMesh_Vertex vf(anUV, ipf, BRepMesh_Frontier); - iv1 = myStructure->AddNode(vf); - isv1 = myVemap.FindIndex(iv1); - if (isv1 == 0) - isv1 = myVemap.Add(iv1); - NewNodes(1) = isv1; - - // Process last vertex - Standard_Integer ipl, ivl; - if (pEnd.IsSame(pBegin)) - { - ipl = ipf; - } - else - { - if (myVertices.IsBound(pEnd)) - { - ipl = myVertices.Find(pEnd); - } - else - { - if (sameUV) - { - ipl = ipf; - ivl = iv1; - } - else - { - P3d = Nodes(Indices(nbnodes)); - if (!theLoc.IsIdentity()) - P3d.Transform(theLoc.Transformation()); - myNbLocat++; - myLocation3d.Bind(myNbLocat, P3d); - ipl = myNbLocat; - } - myVertices.Bind(pEnd,ipl); - } - } - - anUV = BRepMesh_ShapeTool::FindUV(ipl, uvLast, - pEnd, mindist, myAttrib, theSurf, myLocation2d); - - BRepMesh_Vertex vl(anUV, ipl, BRepMesh_Frontier); - - Standard_Integer isvl; - ivl = myStructure->AddNode(vl); - isvl = myVemap.FindIndex(ivl); - if (isvl == 0) - isvl = myVemap.Add(ivl); - NewNodes(nbnodes) = isvl; - - BRepMesh_Vertex v; - - Standard_Integer i; - for (i = 2; i < nbnodes; i++) - { - // Record 3d point - P3d = Nodes(Indices(i)); - if (!theLoc.IsIdentity()) - P3d.Transform(theLoc.Transformation()); - myNbLocat++; - myLocation3d.Bind(myNbLocat, P3d); - - // Record 2d point - anUV = UVNodes(Indices(i)).Coord(); - - Standard_Integer iv2, isv; - v.Initialize(anUV, myNbLocat, BRepMesh_Frontier); - iv2 = myStructure->AddNode(v); - isv = myVemap.FindIndex(iv2); - if (isv == 0) - isv = myVemap.Add(iv2); - NewNodes(i) = isv; - - //add links - if (orEdge == TopAbs_FORWARD) - myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Frontier)); - else if (orEdge == TopAbs_REVERSED) - myStructure->AddLink(BRepMesh_Edge(iv2,iv1,BRepMesh_Frontier)); - else if (orEdge == TopAbs_INTERNAL) - myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Fixed)); - iv1 = iv2; - } - - // last point - if (iv1 != ivl) { - if (orEdge == TopAbs_FORWARD) - myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Frontier)); - else if (orEdge == TopAbs_REVERSED) - myStructure->AddLink(BRepMesh_Edge(ivl,iv1,BRepMesh_Frontier)); - else if (orEdge == TopAbs_INTERNAL) - myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Fixed)); - } - - Handle(Poly_PolygonOnTriangulation) P1 = - new Poly_PolygonOnTriangulation(NewNodes, Poly->Parameters()->Array1()); - P1->Deflection(theDefEdge); - if (myInternaledges.IsBound(theEdge)) - { - BRepMesh_PairOfPolygon& pair = myInternaledges.ChangeFind(theEdge); - if (theEdge.Orientation() == TopAbs_REVERSED) - pair.Append(P1); - else - pair.Prepend(P1); - } - else - { - BRepMesh_PairOfPolygon pair1; - pair1.Append(P1); - myInternaledges.Bind(theEdge, pair1); - } + BRepMeshCol::Array1OfVertexOfDelaun aArrayOfNewVertices(1, theVertices.Extent()); + BRepMeshCol::ListOfVertex::Iterator aVertexIt(theVertices); + for (Standard_Integer aVertexId = 0; aVertexIt.More(); aVertexIt.Next()) + aArrayOfNewVertices(++aVertexId) = aVertexIt.Value(); + theMeshBuilder.AddVertices(aArrayOfNewVertices); return Standard_True; } //======================================================================= -//function : InternalVertices +//function : insertInternalVertices //purpose : //======================================================================= - static void filterParameters(const BRepMeshCol::IMapOfReal& theParams, const Standard_Real theMinDist, const Standard_Real theFilterDist, @@ -585,7 +371,7 @@ static void filterParameters(const BRepMeshCol::IMapOfReal& theParams, //add last point if required if(aParamArray(anInitLen)-theParams(aParamLength) > theMinDist) { - aParamTmp.Append(aParamArray(anInitLen)); + aParamTmp.Append(aParamArray(anInitLen)); aParamLength++; } @@ -643,1084 +429,784 @@ static void filterParameters(const BRepMeshCol::IMapOfReal& theParams, } } -void BRepMesh_FastDiscretFace::InternalVertices(const Handle(BRepAdaptor_HSurface)& theCaro, - BRepMeshCol::ListOfVertex& theInternalV, - const Standard_Real theDefFace, - const BRepMeshCol::HClassifier& theClassifier) +void BRepMesh_FastDiscretFace::insertInternalVertices( + BRepMeshCol::ListOfVertex& theNewVertices, + BRepMesh_Delaun& theMeshBuilder) { - BRepMesh_Vertex newV; - gp_Pnt2d p2d; - gp_Pnt p3d; + const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); + switch (gFace->GetType()) + { + case GeomAbs_Sphere: + insertInternalVerticesSphere(theNewVertices); + break; + + case GeomAbs_Cylinder: + insertInternalVerticesCylinder(theNewVertices); + break; + + case GeomAbs_Cone: + insertInternalVerticesCone(theNewVertices); + break; + + case GeomAbs_Torus: + insertInternalVerticesTorus(theNewVertices); + break; + + case GeomAbs_BezierSurface: + case GeomAbs_BSplineSurface: + insertInternalVerticesBSpline(theNewVertices); + break; + + default: + insertInternalVerticesOther(theNewVertices); + break; + } - // work following the type of surface - const BRepAdaptor_Surface& BS = *(BRepAdaptor_Surface*)&(theCaro->Surface()); - GeomAbs_SurfaceType thetype = theCaro->GetType(); - - Standard_Real umax = myAttrib->GetUMax(); - Standard_Real umin = myAttrib->GetUMin(); - Standard_Real vmax = myAttrib->GetVMax(); - Standard_Real vmin = myAttrib->GetVMin(); - Standard_Real deltaX = myAttrib->GetDeltaX(); - Standard_Real deltaY = myAttrib->GetDeltaY(); - - if (thetype == GeomAbs_Sphere) - { - gp_Sphere S = BS.Sphere(); - const Standard_Real R = S.Radius(); - - // Calculate parameters for iteration in V direction - Standard_Real Dv = 1.0 - (theDefFace/R); - if (Dv < 0.0) Dv = 0.0; - Standard_Real oldDv = 2.0 * ACos (Dv); - Dv = .7 * oldDv; //.7 ~= sqrt(2.) - Dv is hypotenuse of triangle when oldDv is legs - const Standard_Real sv = vmax - vmin; - Dv = sv/((Standard_Integer)(sv/Dv) + 1); - const Standard_Real pasvmax = vmax-Dv*0.5; - - //Du can be defined from relation: 2*r*Sin(Du/2) = 2*R*Sin(Dv/2), r = R*Cos(v) - //here approximate relation r*Du = R*Dv is used - - Standard_Real Du, pasu, pasv; //, ru; - const Standard_Real su = umax-umin; - Standard_Boolean Shift = Standard_False; - for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) - { - // Calculate parameters for iteration in U direction - // 1.-.365*pasv*pasv is simple approximation of Cos(pasv) - // with condition that it gives ~.1 when pasv = pi/2 - Du = Dv/(1.-.365*pasv*pasv); - Du = su/((Standard_Integer)(su/Du) + 1); - Shift = !Shift; - const Standard_Real d = (Shift)? Du*.5 : 0.; - const Standard_Real pasumax = umax-Du*0.5 + d; - for (pasu = umin + Du - d; pasu < pasumax; pasu += Du) - { - if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN) - { - // Record 3d point -#ifdef DEB_MESH_CHRONO - D0Internal++; -#endif - ElSLib::D0(pasu, pasv, S, p3d); - myNbLocat++; - myLocation3d.Bind(myNbLocat, p3d); - // Record 2d point - p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY); - newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free); - theInternalV.Append(newV); - } - } - } - } - else if (thetype == GeomAbs_Cylinder) - { - gp_Cylinder S = BS.Cylinder(); - const Standard_Real R = S.Radius(); - - // Calculate parameters for iteration in U direction - Standard_Real Du = 1.0 - (theDefFace/R); - if (Du < 0.0) Du = 0.0; - Du = 2.0 * ACos (Du); - if (Du > myAngle) Du = myAngle; - const Standard_Real su = umax - umin; - const Standard_Integer nbU = (Standard_Integer)(su/Du); - Du = su/(nbU+1); - - // Calculate parameters for iteration in V direction - const Standard_Real sv = vmax - vmin; - Standard_Integer nbV = (Standard_Integer)( nbU*sv/(su*R) ); - nbV = Min(nbV, 100*nbU); - Standard_Real Dv = sv/(nbV+1); - - Standard_Real pasu, pasv, pasvmax = vmax-Dv*0.5, pasumax = umax-Du*0.5; - for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) { - for (pasu = umin + Du; pasu < pasumax; pasu += Du) { - if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN) - { - // Record 3d point - ElSLib::D0(pasu, pasv, S, p3d); - myNbLocat++; - myLocation3d.Bind(myNbLocat, p3d); - // Record 2d point - p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY); - newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free); - theInternalV.Append(newV); - } - } - } - } - else if (thetype == GeomAbs_Cone) - { - Standard_Real R, RefR, SAng; - gp_Cone C = BS.Cone(); - RefR = C.RefRadius(); - SAng = C.SemiAngle(); - R = Max(Abs(RefR+vmin*Sin(SAng)), Abs(RefR+vmax*Sin(SAng))); - Standard_Real Du, Dv, pasu, pasv; - Du = Max(1.0e0 - (theDefFace/R),0.0e0); - Du = (2.0 * ACos (Du)); - Standard_Integer nbU = (Standard_Integer) ( (umax-umin)/Du ); - Standard_Integer nbV = (Standard_Integer) ( nbU*(vmax-vmin)/((umax-umin)*R) ); - Du = (umax-umin)/(nbU+1); - Dv = (vmax-vmin)/(nbV+1); - - Standard_Real pasvmax = vmax-Dv*0.5, pasumax = umax-Du*0.5; - for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) { - for (pasu = umin + Du; pasu < pasumax; pasu += Du) { - if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN) - { - // Record 3d point - ElSLib::D0(pasu, pasv, C, p3d); - myNbLocat++; - myLocation3d.Bind(myNbLocat, p3d); - // Record 2d point - p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY); - newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free); - theInternalV.Append(newV); - } - } - } - } - else if (thetype == GeomAbs_Torus) - { - gp_Torus T = BS.Torus(); - - Standard_Boolean insert; - Standard_Integer i, j, ParamULength, ParamVLength; - Standard_Real pp, pasu, pasv; - Standard_Real r = T.MinorRadius(), R = T.MajorRadius(); - - BRepMeshCol::SequenceOfReal ParamU, ParamV; - - Standard_Real Du, Dv;//, pasu, pasv; - Dv = Max(1.0e0 - (theDefFace/r),0.0e0) ; - Standard_Real oldDv = 2.0 * ACos (Dv); - oldDv = Min(oldDv, myAngle); - Dv = 0.9*oldDv; //TWOTHIRD * oldDv; - Dv = oldDv; - - Standard_Integer nbV = Max((Standard_Integer)((vmax-vmin)/Dv), 2); - Dv = (vmax-vmin)/(nbV+1); - Standard_Real ru = R + r; - if (ru > 1.e-16) - { - Du = 2.0 * ACos(Max(1.0 - (theDefFace/ru),0.0)); - if (myAngle < Du) Du = myAngle; - Standard_Real aa = sqrt(Du*Du + oldDv*oldDv); - if(aa < gp::Resolution()) - return; - Du *= Min(oldDv, Du) / aa; - } - else Du = Dv; - - Standard_Integer nbU = Max((Standard_Integer)((umax-umin)/Du), 2); - nbU = Max(nbU , (int)(nbV*(umax-umin)*R/((vmax-vmin)*r)/5.)); - Du = (umax-umin)/(nbU+1); - - if (R < r) - { - // As the points of edges are returned. - // in this case, the points are not representative. - - //-- Choose DeltaX and DeltaY so that to avoid skipping points on the grid - for (i = 0; i <= nbU; i++) ParamU.Append(umin + i* Du); - }//R r - { - //--ofv: U - // Number of mapped U parameters - const Standard_Integer LenU = myUParam.Extent(); - // Fill array of U parameters - TColStd_Array1OfReal Up(1,LenU); - for (j = 1; j <= LenU; j++) Up(j) = myUParam(j); - - // Calculate DU, leave array of parameters - Standard_Real aDU = FUN_CalcAverageDUV(Up,LenU); - aDU = Max(aDU, Abs(umax - umin) / (Standard_Real) nbU / 2.); - Standard_Real dUstd = Abs(umax - umin) / (Standard_Real) LenU; - if (aDU > dUstd) dUstd = aDU; - // Add U parameters - for (j = 1; j <= LenU; j++) - { - pp = Up(j); - insert = Standard_True; - ParamULength = ParamU.Length(); - for (i = 1; i <= ParamULength && insert; i++) - { - insert = (Abs(ParamU.Value(i)-pp) > (0.5*dUstd)); - } - if (insert) ParamU.Append(pp); - } - } - - //--ofv: V - // Number of mapped V parameters - const Standard_Integer LenV = myVParam.Extent(); - // Fill array of V parameters - TColStd_Array1OfReal Vp(1,LenV); - for (j = 1; j <= LenV; j++) Vp(j) = myVParam(j); - // Calculate DV, sort array of parameters - Standard_Real aDV = FUN_CalcAverageDUV(Vp,LenV); - aDV = Max(aDV, Abs(vmax - vmin) / (Standard_Real) nbV / 2.); - - Standard_Real dVstd = Abs(vmax - vmin) / (Standard_Real) LenV; - if (aDV > dVstd) dVstd = aDV; - // Add V parameters - for (j = 1; j <= LenV; j++) - { - pp = Vp(j); - - insert = Standard_True; - ParamVLength = ParamV.Length(); - for (i = 1; i <= ParamVLength && insert; i++) - { - insert = (Abs(ParamV.Value(i)-pp) > (dVstd*2./3.)); - } - if (insert) ParamV.Append(pp); - } - - Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length(); - Standard_Real uminnew = umin+deltaY*0.1; - Standard_Real vminnew = vmin+deltaX*0.1; - Standard_Real umaxnew = umax-deltaY*0.1; - Standard_Real vmaxnew = vmax-deltaX*0.1; - - for (i = 1; i <= Lu; i++) - { - pasu = ParamU.Value(i); - if (pasu >= uminnew && pasu < umaxnew) - { - for (j = 1; j <= Lv; j++) - { - pasv = ParamV.Value(j); - if (pasv >= vminnew && pasv < vmaxnew) - { - if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN) - { - // Record 3d point - ElSLib::D0(pasu, pasv, T, p3d); - myNbLocat++; - myLocation3d.Bind(myNbLocat, p3d); - // Record 2d point - p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY); - newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free); - theInternalV.Append(newV); - } - } - } - } - } - } - else if (thetype == GeomAbs_BezierSurface || thetype == GeomAbs_BSplineSurface) - { - //define resolutions - Standard_Real uRes = BS.UResolution(theDefFace); - Standard_Real vRes = BS.VResolution(theDefFace); - - // Sort and filter sequence of parameters - Standard_Real aMinDu = Precision::PConfusion(); - if(deltaX < 1.) - aMinDu/=deltaX; - - Standard_Real aDuMaxLim = 0.1*(umax-umin); - Standard_Real ddu = Min(aDuMaxLim,Max(0.005*(umax-umin),2.*uRes)); - BRepMeshCol::SequenceOfReal ParamU; - filterParameters(myUParam,aMinDu,ddu,ParamU); - Standard_Integer ParamULength = ParamU.Length(); - - Standard_Real aMinDv = Precision::PConfusion(); - if(deltaY < 1) - aMinDv/=deltaY; - - Standard_Real aDvMaxLim = 0.1*(vmax-vmin); - Standard_Real ddv = Min(aDvMaxLim,Max(0.005*(vmax-vmin),2.*vRes)); - BRepMeshCol::SequenceOfReal ParamV; - filterParameters(myVParam,aMinDv,ddv,ParamV); - Standard_Integer ParamVLength = ParamV.Length(); - - // check intermediate isolines - Handle(Geom_Surface) B; - if (thetype == GeomAbs_BezierSurface) { - B = BS.Bezier(); - } - else { - B = BS.BSpline(); - } - - gp_Pnt P1, P2, PControl; - Standard_Real u, v, dist; - - // precision for compare square distances - double dPreci = Precision::SquareConfusion(); - - // Insert V parameters by deflection criterion - Standard_Integer i,j; - Standard_Real V1, V2, U1, U2; - for (i = 1; i <= ParamULength; i++) { - Handle(Geom_Curve) IsoU = B->UIso(ParamU.Value(i)); - V1 = ParamV.Value(1); - P1 = IsoU->Value(V1); - for (j = 2; j <= ParamVLength;) { - V2 = ParamV.Value(j); - P2 = IsoU->Value(V2); - v = 0.5*(V1+V2); - PControl = IsoU->Value(v); - // 23.03.2010 skl for OCC21645 - change precision for comparison - if( P1.SquareDistance(P2) > dPreci ) { - gp_Lin L (P1, gp_Dir(gp_Vec(P1, P2))); - dist = L.Distance(PControl); - } - else { - dist = P1.Distance(PControl); - } - if (dist > theDefFace) { - // insertion - ParamV.InsertBefore(j, v); - ParamVLength++; - } - else { - //put regular grig for normals - gp_Dir N1(0,0,1),N2(0,0,1); - Standard_Boolean aSt1 = GeomLib::NormEstim(B, gp_Pnt2d(ParamU.Value(i),V1), Precision::Confusion(), N1); - Standard_Boolean aSt2 = GeomLib::NormEstim(B, gp_Pnt2d(ParamU.Value(i),v), Precision::Confusion(), N2); - - Standard_Real anAngle1 = N2.Angle(N1); - if(aSt1 < 1 && aSt2 < 1 && anAngle1 > myAngle ) { - // insertion - ParamV.InsertBefore(j, v); - ParamVLength++; - } - else { - V1 = V2; - P1 = P2; - j++; - } - } - } - } - - for (i = 2; i < ParamVLength; i++) { - v = ParamV.Value(i); - Handle(Geom_Curve) IsoV = B->VIso(v); - U1 = ParamU.Value(1); - P1 = IsoV->Value(U1); - for (j = 2; j <= ParamULength;) { - U2 = ParamU.Value(j); - P2 = IsoV->Value(U2); - u = 0.5*(U1+U2); - PControl = IsoV->Value(u); - // 23.03.2010 skl for OCC21645 - change precision for comparison - if( P1.SquareDistance(P2) > dPreci ) { - gp_Lin L (P1, gp_Dir(gp_Vec(P1, P2))); - dist = L.Distance(PControl); - } - else { - dist = P1.Distance(PControl); - } - if (dist > theDefFace) { - // insertion - ParamU.InsertBefore(j, u); - ParamULength++; - } - else { - //check normal - //put regular grig for normals - gp_Dir N1(0,0,1),N2(0,0,1); - Standard_Boolean aSt1 = GeomLib::NormEstim(B, gp_Pnt2d(U1,v), Precision::Confusion(), N1); - Standard_Boolean aSt2 = GeomLib::NormEstim(B, gp_Pnt2d(u,v), Precision::Confusion(), N2); - - Standard_Real anAngle1 = N2.Angle(N1); - if(aSt1 < 1 && aSt2 < 1 && anAngle1 > myAngle) { - // insertion - ParamU.InsertBefore(j, u); - ParamULength++; - } - else { - U1 = U2; - P1 = P2; - if (j < ParamULength) { - // Classify intersection point - if (theClassifier->Perform(gp_Pnt2d(U1, v)) == TopAbs_IN) - { - // Record 3d point - myNbLocat++; - myLocation3d.Bind(myNbLocat, P1); - // Record 2d point - p2d.SetCoord((U1-umin)/deltaX, (v-vmin)/deltaY); - newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free); - theInternalV.Append(newV); - } - } - j++; - } - } - } - } - } - else { - const Standard_Real anAngle = 0.35; - - Standard_Integer i, j, nbpointsU = 10, nbpointsV = 10; - Adaptor3d_IsoCurve tabu[11], tabv[11]; - - BRepMeshCol::SequenceOfReal ParamU, ParamV; - Standard_Real u, v, du, dv; - Standard_Integer iu, iv; - Standard_Real f, l; - - du = (umax-umin) / (nbpointsU+1); dv = (vmax-vmin) / (nbpointsV+1); - - for (iu = 0; iu <= nbpointsU; iu++) { - u = umin + iu*du; - tabu[iu].Load(theCaro); - tabu[iu].Load(GeomAbs_IsoU, u); - } - - for (iv = 0; iv <= nbpointsV; iv++) { - v = vmin + iv*dv; - tabv[iv].Load(theCaro); - tabv[iv].Load(GeomAbs_IsoV, v); - } - - Standard_Integer imax = 1, MaxV = 0; - - GCPnts_TangentialDeflection* tabGU = new GCPnts_TangentialDeflection[nbpointsU+1]; - - for (i = 0; i <= nbpointsU; i++) { - f = Max(vmin, tabu[i].FirstParameter()); - l = Min(vmax, tabu[i].LastParameter()); - GCPnts_TangentialDeflection theDeflection(tabu[i], f, l, anAngle, 0.7*theDefFace, 2); - tabGU[i] = theDeflection; - if (tabGU[i].NbPoints() > MaxV) { - MaxV = tabGU[i].NbPoints(); - imax = i; - } - } - - // return table of parameters V: - Standard_Integer NV = tabGU[imax].NbPoints(); - for (i = 1; i <= NV; i++) { - ParamV.Append(tabGU[imax].Parameter(i)); - } - delete [] tabGU; - - imax = 1; - Standard_Integer MaxU = 0; - - GCPnts_TangentialDeflection* tabGV = new GCPnts_TangentialDeflection[nbpointsV+1]; - - for (i = 0; i <= nbpointsV; i++) { - f = Max(umin, tabv[i].FirstParameter()); - l = Min(umax, tabv[i].LastParameter()); - GCPnts_TangentialDeflection thedeflection2(tabv[i], f, l, anAngle, 0.7*theDefFace, 2); - tabGV[i] = thedeflection2; - if (tabGV[i].NbPoints() > MaxU) { - MaxU = tabGV[i].NbPoints(); - imax = i; - } - } - - // return table of parameters U: - Standard_Integer NU = tabGV[imax].NbPoints(); - for (i = 1; i <= NU; i++) { - ParamU.Append(tabGV[imax].Parameter(i)); - } - delete [] tabGV; - - if (ParamU.Length() == 2) { - ParamU.InsertAfter(1, (umax+umin)*0.5); - } - if (ParamV.Length() == 2) { - ParamV.InsertAfter(1, (vmax+vmin)*0.5); - } - - BRepMeshCol::SequenceOfReal InsertV, InsertU; - gp_Pnt P1; - - Adaptor3d_IsoCurve IsoV; - IsoV.Load(theCaro); - - Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length(); - - for (i = 2; i < Lv; i++) { - v = ParamV.Value(i); - IsoV.Load(GeomAbs_IsoV, v); - for (j = 2; j < Lu; j++) { - u = ParamU.Value(j); - if (theClassifier->Perform(gp_Pnt2d(u, v)) == TopAbs_IN) - { - // Record 3d point - P1 = IsoV.Value(u); - myNbLocat++; - myLocation3d.Bind(myNbLocat, P1); - // Record 2d point - p2d.SetCoord((u-umin)/deltaX, (v-vmin)/deltaY); - newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free); - theInternalV.Append(newV); - } - } - } - } -#ifdef DEB_MESH_CHRONO - chInternal.Stop(); -#endif + addVerticesToMesh(theNewVertices, theMeshBuilder); } -/** -* Internal class Couple, moved from MeshData package -*/ - -class BRepMesh_Couple -{ - public: - BRepMesh_Couple() { myI1 = myI2 = 0; } - BRepMesh_Couple(const Standard_Integer I1, - const Standard_Integer I2) - { myI1 = I1; myI2 = I2; } - - Standard_Integer myI1; - Standard_Integer myI2; -}; - -inline Standard_Boolean IsEqual(const BRepMesh_Couple& one, - const BRepMesh_Couple& other) -{ - if (one.myI1 == other.myI1 && - one.myI2 == other.myI2) return Standard_True; - else return Standard_False; -} - -inline Standard_Integer HashCode(const BRepMesh_Couple& one, - const Standard_Integer Upper) -{ - return ::HashCode((one.myI1+one.myI2), Upper); -} - -typedef NCollection_Map BRepMesh_MapOfCouple; - //======================================================================= -//function : Control +//function : insertInternalVerticesSphere //purpose : //======================================================================= -Standard_Real BRepMesh_FastDiscretFace::Control(const Handle(BRepAdaptor_HSurface)& theCaro, - const Standard_Real theDefFace, - BRepMeshCol::ListOfVertex& theInternalV, - BRepMeshCol::ListOfInteger& theBadTriangles, - BRepMeshCol::ListOfInteger& theNulTriangles, - BRepMesh_Delaun& theTrigu, - const Standard_Boolean theIsFirst) +void BRepMesh_FastDiscretFace::insertInternalVerticesSphere( + BRepMeshCol::ListOfVertex& theNewVertices) { - //IMPORTANT: Constants used in calculations - const Standard_Real MinimalArea2d = 1.e-9; - const Standard_Real MinimalSqLength3d = 1.e-12; + const Standard_Real umax = myAttribute->GetUMax(); + const Standard_Real umin = myAttribute->GetUMin(); + const Standard_Real vmax = myAttribute->GetVMax(); + const Standard_Real vmin = myAttribute->GetVMin(); - // Define the number of iterations - Standard_Integer myNbIterations = 11; - const Standard_Integer nbPasses = (theIsFirst? 1 : myNbIterations); + gp_Sphere S = myAttribute->Surface()->Sphere(); + const Standard_Real R = S.Radius(); - // Initialize stop condition - Standard_Boolean allDegenerated = Standard_False; - Standard_Integer nbInserted = 1; + // Calculate parameters for iteration in V direction + Standard_Real Dv = 1.0 - (myAttribute->GetDefFace() / R); + if (Dv < 0.0) Dv = 0.0; + Standard_Real oldDv = 2.0 * ACos(Dv); + Dv = .7 * oldDv; //.7 ~= sqrt(2.) - Dv is hypotenuse of triangle when oldDv is legs + const Standard_Real sv = vmax - vmin; + Dv = sv / ((Standard_Integer)(sv / Dv) + 1); + const Standard_Real pasvmax = vmax - Dv*0.5; - // Create map of links to skip already processed - Standard_Integer nbtriangles; + //Du can be defined from relation: 2*r*Sin(Du/2) = 2*R*Sin(Dv/2), r = R*Cos(v) + //here approximate relation r*Du = R*Dv is used - nbtriangles = myStructure->ElementsOfDomain().Extent(); - if (nbtriangles <= 0) return -1.0; - BRepMesh_MapOfCouple theCouples(3*nbtriangles); - - gp_XY mi2d; - gp_XYZ vecEd1, vecEd2, vecEd3; - gp_Pnt pDef; - Standard_Real dv = 0, defl = 0, maxdef = -1; - Standard_Integer pass = 1, nf = 0, nl = 0; - BRepMesh_Vertex InsVertex; - Standard_Boolean caninsert; - - Standard_Real sqdefface = theDefFace * theDefFace; - - GeomAbs_SurfaceType thetype = theCaro->GetType(); - Handle(Geom_Surface) BSpl; - Standard_Boolean isSpline = Standard_False; - if (thetype == GeomAbs_BezierSurface || thetype == GeomAbs_BSplineSurface) + Standard_Real Du, pasu, pasv; //, ru; + const Standard_Real su = umax - umin; + Standard_Boolean Shift = Standard_False; + for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) { - isSpline = Standard_True; - if (thetype == GeomAbs_BezierSurface) - BSpl = theCaro->Bezier(); - else - BSpl = theCaro->BSpline(); + // Calculate parameters for iteration in U direction + // 1.-.365*pasv*pasv is simple approximation of Cos(pasv) + // with condition that it gives ~.1 when pasv = pi/2 + Du = Dv / (1. - .365*pasv*pasv); + Du = su / ((Standard_Integer)(su / Du) + 1); + Shift = !Shift; + const Standard_Real d = (Shift) ? Du*.5 : 0.; + const Standard_Real pasumax = umax - Du*0.5 + d; + for (pasu = umin + Du - d; pasu < pasumax; pasu += Du) + { + tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), S, theNewVertices); + } + } +} + +//======================================================================= +//function : insertInternalVerticesCylinder +//purpose : +//======================================================================= +void BRepMesh_FastDiscretFace::insertInternalVerticesCylinder( + BRepMeshCol::ListOfVertex& theNewVertices) +{ + const Standard_Real umax = myAttribute->GetUMax(); + const Standard_Real umin = myAttribute->GetUMin(); + const Standard_Real vmax = myAttribute->GetVMax(); + const Standard_Real vmin = myAttribute->GetVMin(); + + gp_Cylinder S = myAttribute->Surface()->Cylinder(); + const Standard_Real R = S.Radius(); + + // Calculate parameters for iteration in U direction + Standard_Real Du = 1.0 - (myAttribute->GetDefFace() / R); + if (Du < 0.0) Du = 0.0; + Du = 2.0 * ACos(Du); + if (Du > myAngle) Du = myAngle; + const Standard_Real su = umax - umin; + const Standard_Integer nbU = (Standard_Integer)(su / Du); + Du = su / (nbU + 1); + + // Calculate parameters for iteration in V direction + const Standard_Real sv = vmax - vmin; + Standard_Integer nbV = (Standard_Integer)(nbU*sv / (su*R)); + nbV = Min(nbV, 100 * nbU); + Standard_Real Dv = sv / (nbV + 1); + + Standard_Real pasu, pasv, pasvmax = vmax - Dv*0.5, pasumax = umax - Du*0.5; + for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) + { + for (pasu = umin + Du; pasu < pasumax; pasu += Du) + { + tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), S, theNewVertices); + } + } +} + +//======================================================================= +//function : insertInternalVerticesCone +//purpose : +//======================================================================= +void BRepMesh_FastDiscretFace::insertInternalVerticesCone( + BRepMeshCol::ListOfVertex& theNewVertices) +{ + const Standard_Real umax = myAttribute->GetUMax(); + const Standard_Real umin = myAttribute->GetUMin(); + const Standard_Real vmax = myAttribute->GetVMax(); + const Standard_Real vmin = myAttribute->GetVMin(); + + Standard_Real R, RefR, SAng; + gp_Cone C = myAttribute->Surface()->Cone(); + RefR = C.RefRadius(); + SAng = C.SemiAngle(); + R = Max(Abs(RefR + vmin*Sin(SAng)), Abs(RefR + vmax*Sin(SAng))); + Standard_Real Du, Dv, pasu, pasv; + Du = Max(1.0e0 - (myAttribute->GetDefFace() / R), 0.0e0); + Du = (2.0 * ACos(Du)); + Standard_Integer nbU = (Standard_Integer)((umax - umin) / Du); + Standard_Integer nbV = (Standard_Integer)(nbU*(vmax - vmin) / ((umax - umin)*R)); + Du = (umax - umin) / (nbU + 1); + Dv = (vmax - vmin) / (nbV + 1); + + Standard_Real pasvmax = vmax - Dv*0.5, pasumax = umax - Du*0.5; + for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) + { + for (pasu = umin + Du; pasu < pasumax; pasu += Du) + { + tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), C, theNewVertices); + } + } +} + +//======================================================================= +//function : insertInternalVerticesTorus +//purpose : +//======================================================================= +void BRepMesh_FastDiscretFace::insertInternalVerticesTorus( + BRepMeshCol::ListOfVertex& theNewVertices) +{ + const Standard_Real umax = myAttribute->GetUMax(); + const Standard_Real umin = myAttribute->GetUMin(); + const Standard_Real vmax = myAttribute->GetVMax(); + const Standard_Real vmin = myAttribute->GetVMin(); + const Standard_Real deltaX = myAttribute->GetDeltaX(); + const Standard_Real deltaY = myAttribute->GetDeltaY(); + const Standard_Real aDefFace = myAttribute->GetDefFace(); + + gp_Torus T = myAttribute->Surface()->Torus(); + + Standard_Boolean insert; + Standard_Integer i, j, ParamULength, ParamVLength; + Standard_Real pp, pasu, pasv; + Standard_Real r = T.MinorRadius(), R = T.MajorRadius(); + + BRepMeshCol::SequenceOfReal ParamU, ParamV; + + Standard_Real Du, Dv;//, pasu, pasv; + Dv = Max(1.0e0 - (aDefFace / r), 0.0e0); + Standard_Real oldDv = 2.0 * ACos(Dv); + oldDv = Min(oldDv, myAngle); + Dv = 0.9*oldDv; //TWOTHIRD * oldDv; + Dv = oldDv; + + Standard_Integer nbV = Max((Standard_Integer)((vmax - vmin) / Dv), 2); + Dv = (vmax - vmin) / (nbV + 1); + Standard_Real ru = R + r; + if (ru > 1.e-16) + { + Du = 2.0 * ACos(Max(1.0 - (aDefFace / ru), 0.0)); + if (myAngle < Du) Du = myAngle; + Standard_Real aa = sqrt(Du*Du + oldDv*oldDv); + if (aa < gp::Resolution()) + return; + Du *= Min(oldDv, Du) / aa; + } + else Du = Dv; + + Standard_Integer nbU = Max((Standard_Integer)((umax - umin) / Du), 2); + nbU = Max(nbU, (int)(nbV*(umax - umin)*R / ((vmax - vmin)*r) / 5.)); + Du = (umax - umin) / (nbU + 1); + + if (R < r) + { + // As the points of edges are returned. + // in this case, the points are not representative. + + //-- Choose DeltaX and DeltaY so that to avoid skipping points on the grid + for (i = 0; i <= nbU; i++) ParamU.Append(umin + i* Du); + }//R r + { + //--ofv: U + // Number of mapped U parameters + const Standard_Integer LenU = myUParam.Extent(); + // Fill array of U parameters + TColStd_Array1OfReal Up(1, LenU); + for (j = 1; j <= LenU; j++) Up(j) = myUParam(j); + + // Calculate DU, leave array of parameters + Standard_Real aDU = FUN_CalcAverageDUV(Up, LenU); + aDU = Max(aDU, Abs(umax - umin) / (Standard_Real)nbU / 2.); + Standard_Real dUstd = Abs(umax - umin) / (Standard_Real)LenU; + if (aDU > dUstd) dUstd = aDU; + // Add U parameters + for (j = 1; j <= LenU; j++) + { + pp = Up(j); + insert = Standard_True; + ParamULength = ParamU.Length(); + for (i = 1; i <= ParamULength && insert; i++) + { + insert = (Abs(ParamU.Value(i) - pp) > (0.5*dUstd)); + } + if (insert) ParamU.Append(pp); + } } - NCollection_DataMap aNorMap; - BRepMeshCol::MapOfIntegerInteger aStatMap; + //--ofv: V + // Number of mapped V parameters + const Standard_Integer LenV = myVParam.Extent(); + // Fill array of V parameters + TColStd_Array1OfReal Vp(1, LenV); + for (j = 1; j <= LenV; j++) Vp(j) = myVParam(j); + // Calculate DV, sort array of parameters + Standard_Real aDV = FUN_CalcAverageDUV(Vp, LenV); + aDV = Max(aDV, Abs(vmax - vmin) / (Standard_Real)nbV / 2.); + + Standard_Real dVstd = Abs(vmax - vmin) / (Standard_Real)LenV; + if (aDV > dVstd) dVstd = aDV; + // Add V parameters + for (j = 1; j <= LenV; j++) + { + pp = Vp(j); + + insert = Standard_True; + ParamVLength = ParamV.Length(); + for (i = 1; i <= ParamVLength && insert; i++) + { + insert = (Abs(ParamV.Value(i) - pp) > (dVstd*2. / 3.)); + } + if (insert) ParamV.Append(pp); + } + + Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length(); + Standard_Real uminnew = umin + deltaY*0.1; + Standard_Real vminnew = vmin + deltaX*0.1; + Standard_Real umaxnew = umax - deltaY*0.1; + Standard_Real vmaxnew = vmax - deltaX*0.1; + + for (i = 1; i <= Lu; i++) + { + pasu = ParamU.Value(i); + if (pasu >= uminnew && pasu < umaxnew) + { + for (j = 1; j <= Lv; j++) + { + pasv = ParamV.Value(j); + if (pasv >= vminnew && pasv < vmaxnew) + { + tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), T, theNewVertices); + } + } + } + } +} + +//======================================================================= +//function : insertInternalVerticesBSpline +//purpose : +//======================================================================= +void BRepMesh_FastDiscretFace::insertInternalVerticesBSpline( + BRepMeshCol::ListOfVertex& theNewVertices) +{ + const Standard_Real aRange[2][2] = { + { myAttribute->GetUMax(), myAttribute->GetUMin() }, + { myAttribute->GetVMax(), myAttribute->GetVMin() } + }; + + const Standard_Real aDelta[2] = { + myAttribute->GetDeltaX(), + myAttribute->GetDeltaY() + }; + + const Standard_Real aDefFace = myAttribute->GetDefFace(); + const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); + + BRepMeshCol::SequenceOfReal aParams[2]; + for (Standard_Integer i = 0; i < 2; ++i) + { + Standard_Boolean isU = (i == 0); + Standard_Real aRes = isU ? + gFace->UResolution(aDefFace) : + gFace->VResolution(aDefFace); + + // Sort and filter sequence of parameters + Standard_Real aMinDiff = Precision::PConfusion(); + if (aDelta[i] < 1.) + aMinDiff /= aDelta[i]; + + Standard_Real aRangeDiff = aRange[i][0] - aRange[i][1]; + Standard_Real aDiffMaxLim = 0.1 * aRangeDiff; + Standard_Real aDiff = Min(aDiffMaxLim, Max(0.005 * aRangeDiff, 2. * aRes)); + filterParameters(isU ? myUParam : myVParam, aMinDiff, aDiff, aParams[i]); + } + + // check intermediate isolines + Handle(Geom_Surface) aBSpline; + GeomAbs_SurfaceType aSurfType = gFace->GetType(); + if (aSurfType == GeomAbs_BezierSurface) + aBSpline = gFace->Bezier(); + else if (aSurfType == GeomAbs_BSplineSurface) + aBSpline = gFace->BSpline(); + + // precision for compare square distances + const Standard_Real aPrecision = Precision::Confusion(); + const Standard_Real aSqPrecision = aPrecision * aPrecision; + for (Standard_Integer k = 0; k < 2; ++k) + { + BRepMeshCol::SequenceOfReal& aParams1 = aParams[k]; + BRepMeshCol::SequenceOfReal& aParams2 = aParams[(k + 1) % 2]; + const Standard_Boolean isU = (k == 0); + Standard_Integer aStartIndex, aEndIndex; + if (isU) + { + aStartIndex = 1; + aEndIndex = aParams1.Length(); + } + else + { + aStartIndex = 2; + aEndIndex = aParams1.Length() - 1; + } + + for (Standard_Integer i = aStartIndex; i <= aEndIndex; ++i) + { + const Standard_Real aParam1 = aParams1(i); + Handle(Geom_Curve) aIso = isU ? + aBSpline->UIso(aParam1) : aBSpline->VIso(aParam1); + + Standard_Real aPrevParam2 = aParams2(1); + gp_Pnt aPrevPnt2 = aIso->Value(aPrevParam2); + for (Standard_Integer j = 2; j <= aParams2.Length();) + { + Standard_Real aParam2 = aParams2(j); + gp_Pnt aPnt2 = aIso->Value(aParam2); + Standard_Real aMidParam = 0.5 * (aPrevParam2 + aParam2); + gp_Pnt aMidPnt = aIso->Value(aMidParam); + + // 23.03.2010 skl for OCC21645 - change precision for comparison + Standard_Real aDist; + if (aPrevPnt2.SquareDistance(aPnt2) > aSqPrecision) + { + gp_Lin aLin(aPrevPnt2, gp_Dir(gp_Vec(aPrevPnt2, aPnt2))); + aDist = aLin.Distance(aMidPnt); + } + else + aDist = aPrevPnt2.Distance(aMidPnt); + + if (aDist > aDefFace) + { + // insertion + aParams2.InsertBefore(j, aMidParam); + } + else + { + //put regular grig for normals + gp_Pnt2d aStPnt1, aStPnt2; + if (isU) + { + aStPnt1 = gp_Pnt2d(aParam1, aPrevParam2); + aStPnt2 = gp_Pnt2d(aParam1, aMidParam); + } + else + { + aStPnt1 = gp_Pnt2d(aPrevParam2, aParam1); + aStPnt2 = gp_Pnt2d(aMidParam, aParam1); + } + + gp_Dir N1(0, 0, 1), N2(0, 0, 1); + Standard_Boolean aSt1 = GeomLib::NormEstim(aBSpline, aStPnt1, aPrecision, N1); + Standard_Boolean aSt2 = GeomLib::NormEstim(aBSpline, aStPnt2, aPrecision, N2); + + Standard_Real aAngle = N2.Angle(N1); + if (aSt1 < 1 && aSt2 < 1 && aAngle > myAngle) + { + // insertion + aParams2.InsertBefore(j, aMidParam); + } + else + { + aPrevParam2 = aParam2; + aPrevPnt2 = aPnt2; + + if (!isU && j < aParams2.Length()) + { + // Update point parameter. + aStPnt1.SetX(aPrevParam2); + + // Classify intersection point + if (myClassifier->Perform(aStPnt1) == TopAbs_IN) + { + insertVertex(aPrevPnt2, aStPnt1.Coord(), theNewVertices); + } + } + + ++j; + } + } + } + } + } +} + +//======================================================================= +//function : insertInternalVerticesOther +//purpose : +//======================================================================= +void BRepMesh_FastDiscretFace::insertInternalVerticesOther( + BRepMeshCol::ListOfVertex& theNewVertices) +{ + const Standard_Real aAngle = 0.35; + const Standard_Real aRange[2][2] = { + { myAttribute->GetUMax(), myAttribute->GetUMin() }, + { myAttribute->GetVMax(), myAttribute->GetVMin() } + }; + + const Standard_Real aDefFace = myAttribute->GetDefFace(); + const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); + + BRepMeshCol::SequenceOfReal aParams[2]; + const Standard_Integer aIsoPointsNb = 11; + for (Standard_Integer k = 0; k < 2; ++k) + { + const Standard_Boolean isU = (k == 0); + const GeomAbs_IsoType aIsoType = isU ? GeomAbs_IsoU : GeomAbs_IsoV; + const Standard_Integer aOtherParamsIndex = (k + 1) % 2; + const Standard_Real (&aRange1)[2] = aRange[k]; + const Standard_Real (&aRange2)[2] = aRange[aOtherParamsIndex]; + + GCPnts_TangentialDeflection aDiscretIso[aIsoPointsNb]; + const Standard_Real aStepWidth = (aRange1[0] - aRange1[1]) / aIsoPointsNb; + + // Find the most curved Iso. + Standard_Integer aMaxIndex = 1, aMaxPointsNb = 0; + for (Standard_Integer aIsoIt = 0; aIsoIt < aIsoPointsNb; ++aIsoIt) + { + Standard_Real aParam = aRange1[1] + aIsoIt * aStepWidth; + Adaptor3d_IsoCurve aIso(gFace, aIsoType, aParam); + + Standard_Real aFirstParam = Max(aRange2[1], aIso.FirstParameter()); + Standard_Real aLastParam = Min(aRange2[0], aIso.LastParameter()); + + aDiscretIso[aIsoIt].Initialize(aIso, aFirstParam, aLastParam, + aAngle, 0.7 * aDefFace, 2); + + const Standard_Integer aPointsNb = aDiscretIso[aIsoIt].NbPoints(); + if (aPointsNb > aMaxPointsNb) + { + aMaxPointsNb = aPointsNb; + aMaxIndex = aIsoIt; + } + } + + BRepMeshCol::SequenceOfReal& aParams2 = aParams[aOtherParamsIndex]; + GCPnts_TangentialDeflection& aDIso = aDiscretIso[aMaxIndex]; + for (Standard_Integer i = 1; i <= aMaxPointsNb; ++i) + aParams2.Append(aDIso.Parameter(i)); + + if (aParams2.Length() == 2) + aParams2.InsertAfter(1, 0.5 * (aRange2[1] + aRange2[0])); + } + + Adaptor3d_IsoCurve aIsoV; + aIsoV.Load(gFace); + + const Standard_Integer aUPointsNb = aParams[0].Length(); + const Standard_Integer aVPointsNb = aParams[1].Length(); + for (Standard_Integer i = 2; i < aVPointsNb; ++i) + { + const Standard_Real aV = aParams[1].Value(i); + aIsoV.Load(GeomAbs_IsoV, aV); + + for (Standard_Integer j = 2; j < aUPointsNb; ++j) + { + const Standard_Real aU = aParams[0].Value(j); + + const gp_Pnt2d aNewPoint(aU, aV); + if (myClassifier->Perform(aNewPoint) == TopAbs_IN) + insertVertex(aIsoV.Value(aU), aNewPoint.Coord(), theNewVertices); + } + } +} + +//======================================================================= +//function : control +//purpose : +//======================================================================= +Standard_Real BRepMesh_FastDiscretFace::control( + BRepMeshCol::ListOfVertex& theNewVertices, + BRepMesh_Delaun& theTrigu, + const Standard_Boolean theIsFirst) + +#define CHECK_DEF_AND_INSERT_CURRENT(isSkipped) \ +if (aSqDef > aMaxSqDef) \ + aMaxSqDef = aSqDef; \ + \ +(isSkipped) = Standard_False; \ +if (aSqDef > aSqDefFace) \ +{ \ + (isSkipped) = theIsFirst; \ + if (!(isSkipped)) \ + insertVertex(pDef, mi2d, theNewVertices); \ +} \ + +{ + Standard_Integer aTrianglesNb = myStructure->ElementsOfDomain().Extent(); + if (aTrianglesNb < 1) + return -1.0; + + //IMPORTANT: Constants used in calculations + const Standard_Real MinimalArea2d = 1.e-9; + const Standard_Real MinimalSqLength3d = 1.e-12; + const Standard_Real aSqDefFace = myAttribute->GetDefFace() * myAttribute->GetDefFace(); + + const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); + + Handle(Geom_Surface) aBSpline; + GeomAbs_SurfaceType aSurfType = gFace->GetType(); + if (aSurfType == GeomAbs_BezierSurface) + aBSpline = gFace->Bezier(); + else if (aSurfType == GeomAbs_BSplineSurface) + aBSpline = gFace->BSpline(); + + NCollection_DataMap aNorMap; + BRepMeshCol::MapOfIntegerInteger aStatMap; + NCollection_Map aCouples(3 * aTrianglesNb); // Perform refinement passes - for (; pass <= nbPasses && nbInserted && !allDegenerated; pass++) + // Define the number of iterations + Standard_Integer aIterationsNb = 11; + const Standard_Integer aPassesNb = (theIsFirst ? 1 : aIterationsNb); + // Initialize stop condition + Standard_Real aMaxSqDef = -1.; + Standard_Integer aPass = 1, aInsertedNb = 1; + Standard_Boolean isAllDegenerated = Standard_False; + for (; aPass <= aPassesNb && aInsertedNb && !isAllDegenerated; ++aPass) { - theInternalV.Clear(); - theBadTriangles.Clear(); - + theNewVertices.Clear(); + // Reset stop condition - allDegenerated = Standard_True; - nbInserted = 0; - maxdef = -1.0; + aInsertedNb = 0; + aMaxSqDef = -1.; + isAllDegenerated = Standard_True; - // Do not insert nodes in last pass in non-SharedMode - caninsert = (myWithShare || pass < nbPasses); - - // Read mesh size - nbtriangles = myStructure->ElementsOfDomain().Extent(); - if (nbtriangles <= 0) break; + aTrianglesNb = myStructure->ElementsOfDomain().Extent(); + if (aTrianglesNb < 1) + break; // Iterate on current triangles - BRepMeshCol::MapOfInteger::Iterator triDom; - const BRepMeshCol::MapOfInteger& TriMap = myStructure->ElementsOfDomain(); - triDom.Initialize(TriMap); - Standard_Integer aNbPnt = 0; - Standard_Real umin = myAttrib->GetUMin(); - Standard_Real vmin = myAttrib->GetVMin(); - Standard_Real deltaX = myAttrib->GetDeltaX(); - Standard_Real deltaY = myAttrib->GetDeltaY(); - for (; triDom.More(); triDom.Next()) + const BRepMeshCol::MapOfInteger& aTriangles = myStructure->ElementsOfDomain(); + BRepMeshCol::MapOfInteger::Iterator aTriangleIt(aTriangles); + for (; aTriangleIt.More(); aTriangleIt.Next()) { - Standard_Integer TriId = triDom.Key(); - const BRepMesh_Triangle& curTri=Triangle(TriId); - if (curTri.Movability()==BRepMesh_Deleted) continue; - + const Standard_Integer aTriangleId = aTriangleIt.Key(); + const BRepMesh_Triangle& aCurrentTriangle = myStructure->GetElement(aTriangleId); + + if (aCurrentTriangle.Movability() == BRepMesh_Deleted) + continue; + Standard_Integer v[3]; - myStructure->ElementNodes(curTri, v); + myStructure->ElementNodes(aCurrentTriangle, v); Standard_Integer e[3]; Standard_Boolean o[3]; - curTri.Edges(e, o); - - Standard_Boolean m1 = (Edge(e[0]).Movability() == BRepMesh_Frontier); - Standard_Boolean m2 = (Edge(e[1]).Movability() == BRepMesh_Frontier); - Standard_Boolean m3 = (Edge(e[2]).Movability() == BRepMesh_Frontier); + aCurrentTriangle.Edges(e, o); - const BRepMesh_Vertex& vert1=Vertex(v[0]); - const BRepMesh_Vertex& vert2=Vertex(v[1]); - const BRepMesh_Vertex& vert3=Vertex(v[2]); - - const gp_XYZ& p1=myLocation3d(vert1.Location3d()).Coord(); - const gp_XYZ& p2=myLocation3d(vert2.Location3d()).Coord(); - const gp_XYZ& p3=myLocation3d(vert3.Location3d()).Coord(); - - vecEd1 = p2 - p1; - vecEd2 = p3 - p2; - vecEd3 = p1 - p3; - - // Check for degenerated triangle - if (vecEd1.SquareModulus() < MinimalSqLength3d || - vecEd2.SquareModulus() < MinimalSqLength3d || - vecEd3.SquareModulus() < MinimalSqLength3d) + gp_XY xy[3]; + gp_XYZ p[3]; + Standard_Boolean m[3]; + for (Standard_Integer i = 0; i < 3; ++i) { - theNulTriangles.Append(TriId); - continue; + m[i] = (myStructure->GetLink(e[i]).Movability() == BRepMesh_Frontier); + + const BRepMesh_Vertex& aVertex = myStructure->GetNode(v[i]); + xy[i] = myAttribute->Scale(aVertex.Coord(), Standard_False); + p [i] = myAttribute->GetPoint(aVertex).Coord(); } - allDegenerated = Standard_False; + gp_XYZ aLinkVec[3]; + Standard_Boolean isDegeneratedTri = Standard_False; + for (Standard_Integer i = 0; i < 3 && !isDegeneratedTri; ++i) + { + aLinkVec[i] = p[(i + 1) % 3] - p[i]; + isDegeneratedTri = (aLinkVec[i].SquareModulus() < MinimalSqLength3d); + } - gp_XY xy1(vert1.Coord().X()*deltaX+umin,vert1.Coord().Y()*deltaY+vmin); - gp_XY xy2(vert2.Coord().X()*deltaX+umin,vert2.Coord().Y()*deltaY+vmin); - gp_XY xy3(vert3.Coord().X()*deltaX+umin,vert3.Coord().Y()*deltaY+vmin); + if (isDegeneratedTri) + continue; + + isAllDegenerated = Standard_False; // Check triangle area in 2d - if (Abs((xy2-xy1)^(xy3-xy1)) < MinimalArea2d) - { - theNulTriangles.Append(TriId); + if (Abs((xy[1]-xy[0])^(xy[2]-xy[1])) < MinimalArea2d) continue; - } // Check triangle normal - gp_XYZ normal(vecEd1^vecEd2); - dv = normal.Modulus(); - if (dv < Precision::Confusion()) + gp_Pnt pDef; + Standard_Real aSqDef = -1.; + Standard_Boolean isSkipped = Standard_False; + gp_XYZ normal(aLinkVec[0] ^ aLinkVec[1]); + try + { + OCC_CATCH_SIGNALS + + normal.Normalize(); + + // Check deflection on triangle + gp_XY mi2d = (xy[0] + xy[1] + xy[2]) / 3.0; + gFace->D0(mi2d.X(), mi2d.Y(), pDef); + aSqDef = Abs(normal * (pDef.XYZ() - p[0])); + aSqDef *= aSqDef; + + CHECK_DEF_AND_INSERT_CURRENT(isSkipped); + if (isSkipped) + break; + } + catch (Standard_Failure) { - theNulTriangles.Append(TriId); continue; } - normal /= dv; - // Check deflection on triangle - mi2d = (xy1+xy2+xy3)/3.0; - theCaro->D0(mi2d.X(), mi2d.Y(), pDef); - defl = Abs(normal*(pDef.XYZ()-p1)); - defl = defl*defl; - /*mi2d = (xy1+xy2+xy3)/3.0; - theCaro->D0(mi2d.X(), mi2d.Y(), pDef); - defl = pDef.SquareDistance((p1+p2+p3)/3.);*/ - if (defl > maxdef) maxdef = defl; - if (defl > sqdefface) - { - if (theIsFirst) break; - if (caninsert) - { - // Record new vertex - aNbPnt++; - myNbLocat++; - myLocation3d.Bind(myNbLocat,pDef); - mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY); - InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free); - theInternalV.Append(InsVertex); - } - theBadTriangles.Append(TriId); - } - - if (!m2) // Not a boundary + for (Standard_Integer i = 0; i < 3 && !isSkipped; ++i) { + if (m[i]) // is a boundary + continue; + + Standard_Integer j = (i + 1) % 3; // Check if this link was already processed - if (v[1] < v[2]) { nf = v[1]; nl = v[2]; } else { nf = v[2]; nl = v[1]; } - if (theCouples.Add(BRepMesh_Couple(nf,nl))) + Standard_Integer aFirstVertex, aLastVertex; + if (v[i] < v[j]) + { + aFirstVertex = v[i]; + aLastVertex = v[j]; + } + else + { + aFirstVertex = v[j]; + aLastVertex = v[i]; + } + + if (aCouples.Add(BRepMesh_OrientedEdge(aFirstVertex, aLastVertex))) { // Check deflection on edge 1 - mi2d = (xy2+xy3)*0.5; - theCaro->D0(mi2d.X(), mi2d.Y(), pDef); - gp_Lin L (p2, gp_Vec(p2, p3)); - defl = L.SquareDistance(pDef); - if (defl > maxdef) maxdef = defl; - if (defl > sqdefface) - { - if (theIsFirst) break; - if (caninsert) - { - // Record new vertex - aNbPnt++; - myNbLocat++; - myLocation3d.Bind(myNbLocat,pDef); - mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY); - InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free); - theInternalV.Append(InsVertex); - } - theBadTriangles.Append(TriId); - } + gp_XY mi2d = (xy[i] + xy[j]) * 0.5; + gFace->D0(mi2d.X(), mi2d.Y(), pDef); + gp_Lin aLin(p[i], gp_Vec(p[i], p[j])); + aSqDef = aLin.SquareDistance(pDef); + + CHECK_DEF_AND_INSERT_CURRENT(isSkipped); } } - if (!m3) // Not a boundary - { - // Check if this link was already processed - if (v[0] < v[2]) { nf = v[0]; nl = v[2]; } else { nf = v[2]; nl = v[0]; } - if (theCouples.Add(BRepMesh_Couple(nf,nl))) - { - // Check deflection on edge 2 - mi2d = (xy3+xy1)*0.5; - theCaro->D0(mi2d.X(), mi2d.Y(), pDef); - gp_Lin L (p1, gp_Vec(p1, p3)); - defl = L.SquareDistance(pDef); - if (defl > maxdef) maxdef = defl; - if (defl > sqdefface) - { - if (theIsFirst) break; - if (caninsert) - { - // Record new vertex - aNbPnt++; - myNbLocat++; - myLocation3d.Bind(myNbLocat,pDef); - mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY); - InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free); - theInternalV.Append(InsVertex); - } - theBadTriangles.Append(TriId); - } - } - } + if (isSkipped) + break; - if (!m1) // Not a boundary - { - // Check if this link was already processed - if (v[0] < v[1]) { nf = v[0]; nl = v[1]; } else { nf = v[1]; nl = v[0]; } - if (theCouples.Add(BRepMesh_Couple(nf,nl))) - { - // Check deflection on edge 3 - mi2d = (xy1+xy2)*0.5; - theCaro->D0(mi2d.X(), mi2d.Y(), pDef); - gp_Lin L (p1, gp_Vec(p1, p2)); - defl = L.SquareDistance(pDef); - if (defl > maxdef) maxdef = defl; - if (defl > sqdefface) - { - if (theIsFirst) break; - if (caninsert) - { - // Record new vertex - aNbPnt++; - myNbLocat++; - myLocation3d.Bind(myNbLocat,pDef); - mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY); - InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free); - theInternalV.Append(InsVertex); - } - theBadTriangles.Append(TriId); - } - } - } - //check normal on bsplines - if(theIsFirst && isSpline && !BSpl.IsNull() ) + if (theIsFirst && !aBSpline.IsNull()) { - gp_Dir N1(0,0,1), N2(0,0,1), N3(0,0,1); - Standard_Integer aSt1, aSt2, aSt3; - if(aNorMap.IsBound(v[0])) { - aSt1 = aStatMap.Find(v[0]); - N1 =aNorMap.Find(v[0]); - } - else { - aSt1 = GeomLib::NormEstim(BSpl, gp_Pnt2d(xy1), Precision::Confusion(), N1); - aStatMap.Bind(v[0],aSt1); - aNorMap.Bind(v[0],N1); + gp_Dir N[3] = { gp::DZ(), gp::DZ(), gp::DZ() }; + Standard_Integer aSt[3]; + + for (Standard_Integer i = 0; i < 3; ++i) + { + if (aNorMap.IsBound(v[i])) + { + aSt[i] = aStatMap.Find(v[i]); + N[i] = aNorMap.Find(v[i]); + } + else + { + aSt[i] = GeomLib::NormEstim(aBSpline, gp_Pnt2d(xy[i]), Precision::Confusion(), N[i]); + aStatMap.Bind(v[i], aSt[i]); + aNorMap.Bind(v[i], N[i]); + } } - if(aNorMap.IsBound(v[1])) { - aSt2 = aStatMap.Find(v[1]); - N2 = aNorMap.Find(v[1]); - } - else { - aSt2 = GeomLib::NormEstim(BSpl, gp_Pnt2d(xy2), Precision::Confusion(), N2); - aStatMap.Bind(v[1],aSt2); - aNorMap.Bind(v[1],N2); - } + Standard_Real aAngle[3]; + for (Standard_Integer i = 0; i < 3; ++i) + aAngle[i] = N[(i + 1) % 3].Angle(N[i]); - if(aNorMap.IsBound(v[2])) { - aSt3 = aStatMap.Find(v[2]); - N3 = aNorMap.Find(v[2]); - } - else { - aSt3 = GeomLib::NormEstim(BSpl, gp_Pnt2d(xy3), Precision::Confusion(), N3); - aStatMap.Bind(v[2],aSt3); - aNorMap.Bind(v[2],N3.XYZ()); - } - - Standard_Real anAngle1 = N2.Angle(N1); - Standard_Real anAngle2 = N3.Angle(N2); - Standard_Real anAngle3 = N1.Angle(N3); - if(aSt1 < 1 && aSt2 < 1 && aSt3 < 1 && - (anAngle1 > myAngle || anAngle2 > myAngle || anAngle3 > myAngle)) { - - maxdef = -1; + if (aSt[0] < 1 && aSt[1] < 1 && aSt[2] < 1) + { + if (aAngle[0] > myAngle || aAngle[1] > myAngle || aAngle[2] > myAngle) + { + aMaxSqDef = -1.; break; + } } } } - - if (!theIsFirst && theInternalV.Extent() > 0) - { - BRepMeshCol::Array1OfVertexOfDelaun verttab(1, theInternalV.Extent()); - BRepMeshCol::ListOfVertex::Iterator itVer(theInternalV); - Standard_Integer ipn = 1; - for (; itVer.More(); itVer.Next()) - verttab(ipn++) = itVer.Value(); - - theTrigu.AddVertices(verttab); - nbInserted++; - } + + if (theIsFirst) + continue; + + if (addVerticesToMesh(theNewVertices, theTrigu)) + ++aInsertedNb; } - if (maxdef < 0) - return maxdef; - return Sqrt(maxdef); + return (aMaxSqDef < 0) ? aMaxSqDef : Sqrt(aMaxSqDef); } //======================================================================= -//function : AddInShape +//function : add //purpose : //======================================================================= -void BRepMesh_FastDiscretFace::AddInShape(const TopoDS_Face& theFace, - const Standard_Real theDefFace, - const TopTools_MutexForShapeProvider& theMutexProvider) +void BRepMesh_FastDiscretFace::add(const TopoDS_Vertex& theVertex) { - TopLoc_Location loc = theFace.Location(); - Handle(Poly_Triangulation) TOld = BRep_Tool::Triangulation(theFace, loc); - Handle(Poly_PolygonOnTriangulation) NullPoly; - - BRepMesh_ShapeTool::NullifyFace(theFace); - - try{ - BRepMeshCol::MapOfInteger::Iterator it; - - Standard_Integer i, index; - TopAbs_Orientation orFace = theFace.Orientation(); - - const BRepMeshCol::MapOfInteger& TriMap = myStructure->ElementsOfDomain(); - it.Initialize(TriMap); - - Standard_Integer nTri = TriMap.Extent(); - if (nTri != 0) { - - Poly_Array1OfTriangle Tri(1, nTri); - - i = 1; - - for (; it.More(); it.Next()) - { - const BRepMesh_Triangle& aCurElem = myStructure->GetElement(it.Key()); - - Standard_Integer v[3]; - myStructure->ElementNodes(aCurElem, v); - - Standard_Integer iv1, iv2, iv3; - iv1 = myVemap.FindIndex(v[0]); - if (iv1 == 0) iv1 = myVemap.Add(v[0]); - iv2 = myVemap.FindIndex(v[1]); - if (iv2 == 0) iv2 = myVemap.Add(v[1]); - iv3 = myVemap.FindIndex(v[2]); - if (iv3 == 0) iv3 = myVemap.Add(v[2]); - - if (orFace == TopAbs_REVERSED) Tri(i++).Set(iv1, iv3, iv2); - else Tri(i++).Set(iv1, iv2, iv3); - } - - Standard_Integer nbVertices = myVemap.Extent(); - Handle(Poly_Triangulation) T = new Poly_Triangulation(nbVertices, nTri, Standard_True); - Poly_Array1OfTriangle& Trian = T->ChangeTriangles(); - Trian = Tri; - TColgp_Array1OfPnt& Nodes = T->ChangeNodes(); - TColgp_Array1OfPnt2d& Nodes2d = T->ChangeUVNodes(); - - for (i = 1; i <= nbVertices; i++) { - index = myVemap.FindKey(i); - Nodes(i) = Pnt(index); - Nodes2d(i).SetXY(Vertex(index).Coord()); - } - - T->Deflection(theDefFace); - BRepMesh_ShapeTool::AddInFace(theFace, T); - - // implement polygons on triangulation in the face: - BRepMeshCol::DMapOfShapePairOfPolygon::Iterator It(myInternaledges); - - for (; It.More(); It.Next()) { - const TopoDS_Edge& aEdge = TopoDS::Edge(It.Key()); - const BRepMesh_PairOfPolygon& pair = It.Value(); - const Handle(Poly_PolygonOnTriangulation)& NOD1 = pair.First(); - const Handle(Poly_PolygonOnTriangulation)& NOD2 = pair.Last(); - - // lock mutex to prevent parallel change of the same data - Standard_Mutex* aMutex = theMutexProvider.GetMutex(It.Key()); - Standard_Mutex::Sentry aSentry (aMutex); - - if ( NOD1 == NOD2 ) { - BRepMesh_ShapeTool::NullifyEdge(aEdge, TOld, loc); - BRepMesh_ShapeTool::UpdateEdge(aEdge, NOD1, T, loc); - } - else { - BRepMesh_ShapeTool::NullifyEdge(aEdge, TOld, loc); - BRepMesh_ShapeTool::UpdateEdge(aEdge, NOD1, NOD2, T, loc); - } - } - } - } - - catch(Standard_Failure) - { - // MESH_FAILURE(theFace); - } -} - - -//======================================================================= -//function : Triangle -//purpose : -//======================================================================= - -const BRepMesh_Triangle& BRepMesh_FastDiscretFace::Triangle(const Standard_Integer Index) const -{ - return myStructure->GetElement(Index); -} - -//======================================================================= -//function : NbEdges -//purpose : -//======================================================================= - -/*Standard_Integer BRepMesh_FastDiscretFace::NbEdges() const -{ - return myStructure->NbLinks(); -}*/ - -//======================================================================= -//function : Edge -//purpose : -//======================================================================= - -const BRepMesh_Edge& BRepMesh_FastDiscretFace::Edge(const Standard_Integer Index) const -{ - return myStructure->GetLink(Index); -} - - -//======================================================================= -//function : Vertex -//purpose : -//======================================================================= - -const BRepMesh_Vertex& BRepMesh_FastDiscretFace::Vertex(const Standard_Integer Index) const -{ - return myStructure->GetNode(Index); -} - -//======================================================================= -//function : Pnt -//purpose : -//======================================================================= - -const gp_Pnt& BRepMesh_FastDiscretFace::Pnt(const Standard_Integer Index) const -{ - return myLocation3d(myStructure->GetNode(Index).Location3d()); -} - -static Standard_Boolean GetVertexParameters(const TopoDS_Vertex& theVert, - const TopoDS_Face& theFace, - gp_Pnt2d& thePoint) -{ - TopLoc_Location L; - const Handle(Geom_Surface)& S = BRep_Tool::Surface(theFace,L); - L = L.Predivided(theVert.Location()); - BRep_ListIteratorOfListOfPointRepresentation itpr = - ((*((Handle(BRep_TVertex)*) &theVert.TShape()))->Points()); - // Check first if there are PointRepresentation (case non Manifold) - - while (itpr.More()) { - if (itpr.Value()->IsPointOnSurface(S,L)) { - thePoint.SetCoord(itpr.Value()->Parameter(), - itpr.Value()->Parameter2()); - return Standard_True; - } - itpr.Next(); - } - return Standard_False; -} - -//======================================================================= -//function : Add -//purpose : method intended to add internal myVertices in triangulation. -//======================================================================= -void BRepMesh_FastDiscretFace::Add(const TopoDS_Vertex& theVert, - const TopoDS_Face& theFace, - const Handle(BRepAdaptor_HSurface)& thegFace) -{ - const TopAbs_Orientation anOrient = theVert.Orientation(); - gp_Pnt2d uvXY; - if( anOrient != TopAbs_INTERNAL || !GetVertexParameters(theVert,theFace,uvXY)) + if (theVertex.Orientation() != TopAbs_INTERNAL) return; - Standard_Integer indVert =0; - if (myVertices.IsBound(theVert)) - indVert = myVertices.Find(theVert); - else - { - myNbLocat++; - myLocation3d.Bind(myNbLocat, BRep_Tool::Pnt(theVert)); - indVert = myNbLocat; - myVertices.Bind(theVert, indVert); - } - Standard_Real mindist = BRep_Tool::Tolerance(theVert); - // gp_Pnt2d uvXY = BRep_Tool::Parameters(theVert,theFace); - gp_XY anUV = BRepMesh_ShapeTool::FindUV(indVert, uvXY, - theVert, mindist, myAttrib, thegFace, myLocation2d); - BRepMesh_Vertex vf(anUV, indVert, BRepMesh_Fixed); - Standard_Integer ivff = myStructure->AddNode(vf); - Standard_Integer isvf = myVemap.FindIndex(ivff); - if (isvf == 0) isvf = myVemap.Add(ivff); + try + { + OCC_CATCH_SIGNALS + + gp_Pnt2d aPnt2d = BRep_Tool::Parameters(theVertex, myAttribute->Face()); + + N_HANDLE aFixedVExplorer = new FixedVExplorer(theVertex); + Standard_Integer aIndex = myAttribute->GetVertexIndex(aFixedVExplorer); + gp_XY anUV = BRepMesh_ShapeTool::FindUV(aIndex, aPnt2d, + theVertex, BRep_Tool::Tolerance(theVertex), myAttribute); + + Standard_Integer aTmpId1, aTmpId2; + myAttribute->AddNode(aIndex, anUV, BRepMesh_Fixed, aTmpId1, aTmpId2); + } + catch (Standard_Failure) + { + } } + +//======================================================================= +//function : insertVertex +//purpose : +//======================================================================= +void BRepMesh_FastDiscretFace::insertVertex( + const gp_Pnt& thePnt3d, + const gp_XY& theUV, + BRepMeshCol::ListOfVertex& theVertices) +{ + Standard_Integer aNbLocat = myAttribute->LastPointId(); + mySurfacePoints->Bind(++aNbLocat, thePnt3d); + + gp_XY aPnt2d = myAttribute->Scale(theUV, Standard_True); + BRepMesh_Vertex aVertex(aPnt2d, aNbLocat, BRepMesh_Free); + theVertices.Append(aVertex); +} \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_FastDiscretFace.hxx b/src/BRepMesh/BRepMesh_FastDiscretFace.hxx index bb42352bfc..74fdc90340 100644 --- a/src/BRepMesh/BRepMesh_FastDiscretFace.hxx +++ b/src/BRepMesh/BRepMesh_FastDiscretFace.hxx @@ -26,6 +26,8 @@ #include #include #include +#include +#include class BRepMesh_DataStructureOfDelaun; class BRepMesh_FaceAttribute; @@ -43,83 +45,113 @@ class BRepMesh_Vertex; class gp_Pnt; //! Algorithm to mesh a face with respect of the frontier -//! the deflection and by option the shared components.
+//! the deflection and by option the shared components. class BRepMesh_FastDiscretFace : public Standard_Transient { public: - + Standard_EXPORT BRepMesh_FastDiscretFace(const Standard_Real theAngle, const Standard_Boolean theWithShare = Standard_True); - - Standard_EXPORT void Add(const TopoDS_Face& theFace, - const Handle(BRepMesh_FaceAttribute)& theAttrib, - const TopTools_DataMapOfShapeReal& theMapDefle, - const TopTools_MutexForShapeProvider& theMutexProvider); - - Standard_EXPORT Standard_Real Control(const Handle(BRepAdaptor_HSurface)& theCaro, - const Standard_Real theDefFace, - BRepMeshCol::ListOfVertex& theInternalV, - BRepMeshCol::ListOfInteger& theBadTriangles, - BRepMeshCol::ListOfInteger& theNulTriangles, - BRepMesh_Delaun& theTrigu, - const Standard_Boolean theIsFirst); + + Standard_EXPORT void Add(const Handle(BRepMesh_FaceAttribute)& theAttribute); //! Gives the triangle of .
Standard_EXPORT const BRepMesh_Triangle& Triangle(const Standard_Integer theIndex) const; - //! Gives the edge of index .
- Standard_EXPORT const BRepMesh_Edge& Edge(const Standard_Integer theIndex) const; - - //! Gives the vertex of .
- Standard_EXPORT const BRepMesh_Vertex& Vertex(const Standard_Integer theIndex) const; - - //! Gives the location3d of the vertex of .
- Standard_EXPORT const gp_Pnt& Pnt(const Standard_Integer theIndex) const; - DEFINE_STANDARD_RTTI(BRepMesh_FastDiscretFace) -protected: - - Standard_Boolean RestoreStructureFromTriangulation(const TopoDS_Edge& theEdge, - const TopoDS_Face& theFace, - const Handle(BRepAdaptor_HSurface)& theSurf, - const Handle(Poly_Triangulation)& theTrigu, - const Standard_Real theDefEdge, - const TopLoc_Location& theLoc, - const TopTools_MutexForShapeProvider& theMutexProvider); +private: -private: + void add(const TopoDS_Vertex& theVertex); + + Standard_Real control(BRepMeshCol::ListOfVertex& theNewVertices, + BRepMesh_Delaun& theMeshBuilder, + const Standard_Boolean theIsFirst); + + //! Registers the given nodes in mesh data structure and + //! performs refinement of existing mesh. + //! @param theVertices nodes to be inserted. + //! @param theMeshBuilder initialized tool refining mesh + //! in respect to inserting nodes. + //! @return TRUE if vertices were been inserted, FALSE elewhere. + Standard_Boolean addVerticesToMesh( + const BRepMeshCol::ListOfVertex& theVertices, + BRepMesh_Delaun& theMeshBuilder); + + //! Calculates nodes lying on face's surface and inserts them to a mesh. + //! @param theNewVertices list of vertices to be extended and added to mesh. + //! @param theMeshBuilder initialized tool refining mesh + //! in respect to inserting nodes. + void insertInternalVertices(BRepMeshCol::ListOfVertex& theNewVertices, + BRepMesh_Delaun& theMeshBuilder); + + //! Calculates nodes lying on spherical surface. + //! @param theNewVertices list of vertices to be extended and added to mesh. + void insertInternalVerticesSphere(BRepMeshCol::ListOfVertex& theNewVertices); + + //! Calculates nodes lying on cylindrical surface. + //! @param theNewVertices list of vertices to be extended and added to mesh. + void insertInternalVerticesCylinder(BRepMeshCol::ListOfVertex& theNewVertices); + + //! Calculates nodes lying on conical surface. + //! @param theNewVertices list of vertices to be extended and added to mesh. + void insertInternalVerticesCone(BRepMeshCol::ListOfVertex& theNewVertices); + + //! Calculates nodes lying on toroidal surface. + //! @param theNewVertices list of vertices to be extended and added to mesh. + void insertInternalVerticesTorus(BRepMeshCol::ListOfVertex& theNewVertices); + + //! Calculates nodes lying on Bezier/BSpline surface. + //! @param theNewVertices list of vertices to be extended and added to mesh. + void insertInternalVerticesBSpline(BRepMeshCol::ListOfVertex& theNewVertices); + + //! Calculates nodes lying on custom-type surface. + //! @param theNewVertices list of vertices to be extended and added to mesh. + void insertInternalVerticesOther(BRepMeshCol::ListOfVertex& theNewVertices); - void Add(const TopoDS_Vertex& theVert, - const TopoDS_Face& theFace, - const Handle(BRepAdaptor_HSurface)& theSFace); - - void InternalVertices(const Handle(BRepAdaptor_HSurface)& theCaro, - BRepMeshCol::ListOfVertex& theInternalV, - const Standard_Real theDefFace, - const BRepMeshCol::HClassifier& theClassifier); - - void AddInShape(const TopoDS_Face& theFace, - const Standard_Real theDefFace, - const TopTools_MutexForShapeProvider& theMutexProvider); + //! Template method trying to insert new internal vertex corresponded to + //! the given 2d point. Calculates 3d position analytically using the given + //! surface. + //! @param thePnt2d 2d point to be inserted to the list. + //! @param theAnalyticSurface analytic surface to calculate 3d point. + //! @param[out] theVertices list of vertices to be updated. + template + void tryToInsertAnalyticVertex(const gp_Pnt2d& thePnt2d, + const AnalyticSurface& theAnalyticSurface, + BRepMeshCol::ListOfVertex& theVertices) + { + if (!myClassifier->Perform(thePnt2d) == TopAbs_IN) + return; + + gp_Pnt aPnt; + ElSLib::D0(thePnt2d.X(), thePnt2d.Y(), theAnalyticSurface, aPnt); + insertVertex(aPnt, thePnt2d.Coord(), theVertices); + } + + //! Creates new vertex with the given parameters. + //! @param thePnt3d 3d point corresponded to the vertex. + //! @param theUV UV point corresponded to the vertex. + //! @param[out] theVertices list of vertices to be updated. + void insertVertex(const gp_Pnt& thePnt3d, + const gp_XY& theUV, + BRepMeshCol::ListOfVertex& theVertices); private: + Standard_Real myAngle; Standard_Boolean myWithShare; - BRepMeshCol::DMapOfVertexInteger myVertices; - BRepMeshCol::DMapOfShapePairOfPolygon myInternaledges; - Standard_Integer myNbLocat; - BRepMeshCol::DMapOfIntegerPnt myLocation3d; - Handle_BRepMesh_DataStructureOfDelaun myStructure; - BRepMeshCol::ListOfVertex myListver; - BRepMeshCol::IMapOfInteger myVemap; - BRepMeshCol::DMapOfIntegerListOfXY myLocation2d; - Handle_BRepMesh_FaceAttribute myAttrib; Standard_Boolean myInternalVerticesMode; BRepMeshCol::IMapOfReal myUParam; BRepMeshCol::IMapOfReal myVParam; BRepMeshCol::Allocator myAllocator; + + // Fast access to attributes of current face + Handle(BRepMesh_FaceAttribute) myAttribute; + Handle(BRepMesh_DataStructureOfDelaun) myStructure; + BRepMeshCol::HIMapOfInteger myVertexEdgeMap; + BRepMeshCol::HClassifier myClassifier; + BRepMeshCol::HDMapOfIntegerPnt mySurfacePoints; }; DEFINE_STANDARD_HANDLE (BRepMesh_FastDiscretFace, Standard_Transient) diff --git a/src/BRepMesh/BRepMesh_IEdgeTool.cxx b/src/BRepMesh/BRepMesh_IEdgeTool.cxx new file mode 100644 index 0000000000..c000b517b4 --- /dev/null +++ b/src/BRepMesh/BRepMesh_IEdgeTool.cxx @@ -0,0 +1,19 @@ +// Created on: 2014-08-13 +// Created by: Oleg AGASHIN +// Copyright (c) 2011-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +IMPLEMENT_STANDARD_HANDLE (BRepMesh_IEdgeTool, Standard_Transient) +IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IEdgeTool, Standard_Transient) diff --git a/src/BRepMesh/BRepMesh_IEdgeTool.hxx b/src/BRepMesh/BRepMesh_IEdgeTool.hxx new file mode 100644 index 0000000000..6d7624d5a4 --- /dev/null +++ b/src/BRepMesh/BRepMesh_IEdgeTool.hxx @@ -0,0 +1,46 @@ +// Created on: 2014-08-13 +// Created by: Oleg AGASHIN +// Copyright (c) 2011-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepMesh_IEdgeTool_HeaderFile +#define _BRepMesh_IEdgeTool_HeaderFile + +#include +#include +#include +#include + +//! Interface class providing API for edge tessellation tools. +class BRepMesh_IEdgeTool : public Standard_Transient +{ +public: + //! Returns number of tessellation points. + virtual Standard_Integer NbPoints() const = 0; + + //! Returns parameters of solution with the given index. + //! @param theIndex index of tessellation point. + //! @param theParameter parameters on PCurve corresponded to the solution. + //! @param thePoint tessellation point. + //! @param theUV coordinates of tessellation point in parametric space of face. + virtual void Value(const Standard_Integer theIndex, + Standard_Real& theParameter, + gp_Pnt& thePoint, + gp_Pnt2d& theUV) = 0; + + DEFINE_STANDARD_RTTI(BRepMesh_IEdgeTool) +}; + +DEFINE_STANDARD_HANDLE(BRepMesh_IEdgeTool, Standard_Transient) + +#endif diff --git a/src/BRepMesh/BRepMesh_IncrementalMesh.cxx b/src/BRepMesh/BRepMesh_IncrementalMesh.cxx index e313ce7183..4fd3418fe8 100644 --- a/src/BRepMesh/BRepMesh_IncrementalMesh.cxx +++ b/src/BRepMesh/BRepMesh_IncrementalMesh.cxx @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include @@ -45,10 +45,11 @@ #include #include -#include #include +#include #include #include +#include #include @@ -90,10 +91,10 @@ BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh( : myRelative (isRelative), myInParallel(isInParallel) { - myDeflection = theLinDeflection; - myAngle = theAngDeflection; - myShape = theShape; - + myDeflection = theLinDeflection; + myAngle = theAngDeflection; + myShape = theShape; + Perform(); } @@ -115,7 +116,6 @@ void BRepMesh_IncrementalMesh::init() myModified = Standard_False; myEdgeDeflection.Clear(); - mySharedFaces.Clear(); myFaces.clear(); setDone(); @@ -129,15 +129,16 @@ void BRepMesh_IncrementalMesh::init() if (aBox.IsVoid()) { // Nothing to mesh. - myMesher.Nullify(); + myMesh.Nullify(); return; } BRepMesh_ShapeTool::BoxMaxDimension(aBox, myMaxShapeSize); - TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, mySharedFaces); - myMesher = new BRepMesh_FastDiscret(myDeflection, myAngle, aBox, + myMesh = new BRepMesh_FastDiscret(myDeflection, myAngle, aBox, Standard_True, Standard_True, myRelative, Standard_True, myInParallel); + + myMesh->InitSharedFaces(myShape); } //======================================================================= @@ -208,7 +209,7 @@ void BRepMesh_IncrementalMesh::Perform() { init(); - if (myMesher.IsNull()) + if (myMesh.IsNull()) return; update(); @@ -240,20 +241,18 @@ void BRepMesh_IncrementalMesh::update() #ifdef HAVE_TBB if (myInParallel) { - myMesher->CreateMutexesForSubShapes(myShape, TopAbs_EDGE); - tbb::parallel_for_each(myFaces.begin(), myFaces.end(), *myMesher); - myMesher->RemoveAllMutexes(); + tbb::parallel_for_each(myFaces.begin(), myFaces.end(), *myMesh); } else { #endif for (aFaceIt = myFaces.begin(); aFaceIt != myFaces.end(); aFaceIt++) - myMesher->Process(*aFaceIt); + myMesh->Process(*aFaceIt); #ifdef HAVE_TBB } #endif - discretizeFreeEdges(); + commit(); } //======================================================================= @@ -361,8 +360,11 @@ void BRepMesh_IncrementalMesh::update(const TopoDS_Edge& theEdge) if (!aTriangulation.IsNull() && !aPolygon.IsNull()) { - if (aPolygon->Deflection() < 1.1 * aEdgeDeflection) + if (aPolygon->Deflection() < 1.1 * aEdgeDeflection && + aPolygon->HasParameters()) + { continue; + } myModified = Standard_True; BRepMesh_ShapeTool::NullifyEdge(theEdge, aTriangulation, aLoc); @@ -371,7 +373,8 @@ void BRepMesh_IncrementalMesh::update(const TopoDS_Edge& theEdge) if (!myEmptyEdges.IsBound(theEdge)) myEmptyEdges.Bind(theEdge, BRepMeshCol::MapOfTriangulation()); - myEmptyEdges(theEdge).Add(aTriangulation); + if (!aTriangulation.IsNull()) + myEmptyEdges(theEdge).Add(aTriangulation); } while (!aPolygon.IsNull()); } @@ -404,7 +407,8 @@ Standard_Boolean BRepMesh_IncrementalMesh::toBeMeshed( if (!myEmptyEdges.IsBound(aEdge)) continue; - isEdgesConsistent &= myEmptyEdges(aEdge).Contains(aTriangulation); + BRepMeshCol::MapOfTriangulation& aTriMap = myEmptyEdges(aEdge); + isEdgesConsistent &= !aTriMap.IsEmpty() && !aTriMap.Contains(aTriangulation); } if (isEdgesConsistent) @@ -434,24 +438,26 @@ void BRepMesh_IncrementalMesh::update(const TopoDS_Face& theFace) return; myModified = Standard_True; - myMesher->Add(theFace, mySharedFaces); + Standard_Integer aStatus = myMesh->Add(theFace); - BRepMesh_Status aStatus = myMesher->CurrentFaceStatus(); - myStatus |= (Standard_Integer)aStatus; + myStatus |= aStatus; if (aStatus != BRepMesh_ReMesh) return; BRepMeshCol::MapOfShape aUsedFaces; aUsedFaces.Add(theFace); + const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces = + myMesh->SharedFaces(); + TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE); for (; aEdgeIt.More(); aEdgeIt.Next()) { const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current()); - if (mySharedFaces.FindIndex(aEdge) == 0) + if (aMapOfSharedFaces.FindIndex(aEdge) == 0) continue; - const TopTools_ListOfShape& aSharedFaces = mySharedFaces.FindFromKey(aEdge); + const TopTools_ListOfShape& aSharedFaces = aMapOfSharedFaces.FindFromKey(aEdge); TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces); for (; aSharedFaceIt.More(); aSharedFaceIt.Next()) { @@ -462,12 +468,123 @@ void BRepMesh_IncrementalMesh::update(const TopoDS_Face& theFace) aUsedFaces.Add(aFace); toBeMeshed(aFace, Standard_False); - myMesher->Add(aFace, mySharedFaces); - myStatus |= (Standard_Integer)myMesher->CurrentFaceStatus(); + myStatus |= myMesh->Add(aFace); } } } +//======================================================================= +//function : commit +//purpose : +//======================================================================= +void BRepMesh_IncrementalMesh::commit() +{ + std::vector::iterator aFaceIt(myFaces.begin()); + for (; aFaceIt != myFaces.end(); aFaceIt++) + commitFace(*aFaceIt); + + discretizeFreeEdges(); +} + +//======================================================================= +//function : commitFace +//purpose : +//======================================================================= +void BRepMesh_IncrementalMesh::commitFace(const TopoDS_Face& theFace) +{ + TopoDS_Face aFace = theFace; + aFace.Orientation(TopAbs_FORWARD); + + Handle(BRepMesh_FaceAttribute) aFaceAttribute; + if (!myMesh->GetFaceAttribute(aFace, aFaceAttribute)) + return; + + BRepMesh_ShapeTool::NullifyFace(aFace); + + if (!aFaceAttribute->IsValid()) + { + myStatus |= aFaceAttribute->GetStatus(); + return; + } + + TopLoc_Location aLoc = aFace.Location(); + Handle(Poly_Triangulation) aOldTriangulation = BRep_Tool::Triangulation(aFace, aLoc); + + try + { + OCC_CATCH_SIGNALS + + Handle(BRepMesh_DataStructureOfDelaun)& aStructure = aFaceAttribute->ChangeStructure(); + const BRepMeshCol::MapOfInteger& aTriangles = aStructure->ElementsOfDomain(); + if (aTriangles.IsEmpty()) + return; + + BRepMeshCol::HIMapOfInteger& aVetrexEdgeMap = aFaceAttribute->ChangeVertexEdgeMap(); + + // Store triangles + Standard_Integer aVerticesNb = aVetrexEdgeMap->Extent(); + Standard_Integer aTrianglesNb = aTriangles.Extent(); + Handle(Poly_Triangulation) aNewTriangulation = + new Poly_Triangulation(aVerticesNb, aTrianglesNb, Standard_True); + + Poly_Array1OfTriangle& aPolyTrianges = aNewTriangulation->ChangeTriangles(); + + Standard_Integer aTriangeId = 1; + BRepMeshCol::MapOfInteger::Iterator aTriIt(aTriangles); + for (; aTriIt.More(); aTriIt.Next()) + { + const BRepMesh_Triangle& aCurElem = aStructure->GetElement(aTriIt.Key()); + + Standard_Integer aNode[3]; + aStructure->ElementNodes(aCurElem, aNode); + + Standard_Integer aNodeId[3]; + for (Standard_Integer i = 0; i < 3; ++i) + aNodeId[i] = aVetrexEdgeMap->FindIndex(aNode[i]); + + aPolyTrianges(aTriangeId++).Set(aNodeId[0], aNodeId[1], aNodeId[2]); + } + + // Store mesh nodes + TColgp_Array1OfPnt& aNodes = aNewTriangulation->ChangeNodes(); + TColgp_Array1OfPnt2d& aNodes2d = aNewTriangulation->ChangeUVNodes(); + + for (Standard_Integer i = 1; i <= aVerticesNb; ++i) + { + Standard_Integer aVertexId = aVetrexEdgeMap->FindKey(i); + const BRepMesh_Vertex& aVertex = aStructure->GetNode(aVertexId); + const gp_Pnt& aPoint = aFaceAttribute->GetPoint(aVertex); + + aNodes(i) = aPoint; + aNodes2d(i) = aVertex.Coord(); + } + + aNewTriangulation->Deflection(aFaceAttribute->GetDefFace()); + BRepMesh_ShapeTool::AddInFace(aFace, aNewTriangulation); + + // Store discretization of edges + BRepMeshCol::HDMapOfShapePairOfPolygon& aInternalEdges = aFaceAttribute->ChangeInternalEdges(); + BRepMeshCol::DMapOfShapePairOfPolygon::Iterator aEdgeIt(*aInternalEdges); + for (; aEdgeIt.More(); aEdgeIt.Next()) + { + const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Key()); + const BRepMesh_PairOfPolygon& aPolyPair = aEdgeIt.Value(); + const Handle(Poly_PolygonOnTriangulation)& aPolygon1 = aPolyPair.First(); + const Handle(Poly_PolygonOnTriangulation)& aPolygon2 = aPolyPair.Last(); + + BRepMesh_ShapeTool::NullifyEdge(aEdge, aOldTriangulation, aLoc); + if (aPolygon1 == aPolygon2) + BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aNewTriangulation, aLoc); + else + BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aPolygon2, aNewTriangulation, aLoc); + } + } + catch (Standard_Failure) + { + myStatus |= BRepMesh_Failure; + } +} + //======================================================================= //function : Discret //purpose : @@ -476,7 +593,7 @@ Standard_Integer BRepMesh_IncrementalMesh::Discret( const TopoDS_Shape& theShape, const Standard_Real theDeflection, const Standard_Real theAngle, - BRepMesh_PDiscretRoot& theAlgo) + BRepMesh_DiscretRoot* &theAlgo) { BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh(); anAlgo->SetDeflection(theDeflection); diff --git a/src/BRepMesh/BRepMesh_IncrementalMesh.hxx b/src/BRepMesh/BRepMesh_IncrementalMesh.hxx index 83a044b554..7e53483e47 100644 --- a/src/BRepMesh/BRepMesh_IncrementalMesh.hxx +++ b/src/BRepMesh/BRepMesh_IncrementalMesh.hxx @@ -20,9 +20,7 @@ #include #include #include -#include #include -#include #include #include @@ -116,7 +114,7 @@ public: //! \name plugin API Standard_EXPORT static Standard_Integer Discret(const TopoDS_Shape& theShape, const Standard_Real theLinDeflection, const Standard_Real theAngDeflection, - BRepMesh_PDiscretRoot& theAlgo); + BRepMesh_DiscretRoot* &theAlgo); //! Returns multi-threading usage flag set by default in //! Discret() static method (thus applied only to Mesh Factories). @@ -126,6 +124,11 @@ public: //! \name plugin API //! Discret() static method (thus applied only to Mesh Factories). Standard_EXPORT static void SetParallelDefault(const Standard_Boolean isInParallel); + //! Returns mesh tool storing mesh data. + inline const Handle(BRepMesh_FastDiscret)& Mesh() const + { + return myMesh; + } DEFINE_STANDARD_RTTI(BRepMesh_IncrementalMesh) @@ -183,18 +186,23 @@ private: Standard_Boolean toBeMeshed(const TopoDS_Face& theFace, const Standard_Boolean isWithCheck); + //! Stores mesh to the shape. + void commit(); + + //! Stores mesh to the face. + void commitFace(const TopoDS_Face& theFace); + protected: - Standard_Boolean myRelative; - Standard_Boolean myInParallel; - BRepMeshCol::DMapOfEdgeListOfTriangulation myEmptyEdges; - Handle(BRepMesh_FastDiscret) myMesher; - Standard_Boolean myModified; - TopTools_DataMapOfShapeReal myEdgeDeflection; - TopTools_IndexedDataMapOfShapeListOfShape mySharedFaces; - Standard_Real myMaxShapeSize; - Standard_Integer myStatus; - std::vector myFaces; + Standard_Boolean myRelative; + Standard_Boolean myInParallel; + BRepMeshCol::DMapOfEdgeListOfTriangulation myEmptyEdges; + Handle(BRepMesh_FastDiscret) myMesh; + Standard_Boolean myModified; + TopTools_DataMapOfShapeReal myEdgeDeflection; + Standard_Real myMaxShapeSize; + Standard_Integer myStatus; + std::vector myFaces; }; DEFINE_STANDARD_HANDLE(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot) diff --git a/src/BRepMesh/BRepMesh_PluginMacro.hxx b/src/BRepMesh/BRepMesh_PluginMacro.hxx index 4da575e46b..c2769eed13 100644 --- a/src/BRepMesh/BRepMesh_PluginMacro.hxx +++ b/src/BRepMesh/BRepMesh_PluginMacro.hxx @@ -21,13 +21,13 @@ extern "C" { \ Standard_EXPORT Standard_Integer DISCRETALGO(const TopoDS_Shape& , \ const Standard_Real, \ const Standard_Real, \ - BRepMesh_PDiscretRoot& ); \ + BRepMesh_DiscretRoot* &); \ } \ \ -Standard_Integer DISCRETALGO(const TopoDS_Shape& theShape, \ - const Standard_Real theLinDeflection, \ - const Standard_Real theAngDeflection, \ - BRepMesh_PDiscretRoot& theAlgo) \ +Standard_Integer DISCRETALGO(const TopoDS_Shape& theShape, \ + const Standard_Real theLinDeflection, \ + const Standard_Real theAngDeflection, \ + BRepMesh_DiscretRoot* &theAlgo) \ { \ return name::Discret(theShape, theLinDeflection, \ theAngDeflection, theAlgo); \ diff --git a/src/BRepMesh/BRepMesh_ShapeTool.cxx b/src/BRepMesh/BRepMesh_ShapeTool.cxx index 9a70db7662..38cc71aa2c 100644 --- a/src/BRepMesh/BRepMesh_ShapeTool.cxx +++ b/src/BRepMesh/BRepMesh_ShapeTool.cxx @@ -24,6 +24,8 @@ #include #include #include +#include +#include namespace { //! Auxilary struct to take a tolerance of edge. @@ -108,7 +110,7 @@ Standard_Real BRepMesh_ShapeTool::RelativeEdgeDeflection( return aDefEdge; Bnd_Box aBox; - BRepBndLib::Add(theEdge, aBox); + BRepBndLib::Add(theEdge, aBox, Standard_False); BoxMaxDimension(aBox, aDefEdge); // Adjust resulting value in relation to the total size @@ -126,25 +128,25 @@ Standard_Real BRepMesh_ShapeTool::RelativeEdgeDeflection( //purpose : //======================================================================= gp_XY BRepMesh_ShapeTool::FindUV( - const Standard_Integer theIndexOfPnt3d, - const gp_Pnt2d& thePnt2d, - const TopoDS_Vertex& theVertex, - const Standard_Real theMinDistance, - const Handle(BRepMesh_FaceAttribute)& theFaceAttribute, - const Handle(BRepAdaptor_HSurface)& theSurface, - BRepMeshCol::DMapOfIntegerListOfXY& theLocation2dMap) + const Standard_Integer theIndexOfPnt3d, + const gp_Pnt2d& thePnt2d, + const TopoDS_Vertex& theVertex, + const Standard_Real theMinDistance, + const Handle(BRepMesh_FaceAttribute)& theFaceAttribute) { const gp_XY& aPnt2d = thePnt2d.Coord(); - if (!theLocation2dMap.IsBound(theIndexOfPnt3d)) + BRepMeshCol::DMapOfIntegerListOfXY& aLocation2D = + theFaceAttribute->ChangeLocation2D(); + + if (!aLocation2D.IsBound(theIndexOfPnt3d)) { BRepMeshCol::ListOfXY aPoints2d; aPoints2d.Append(aPnt2d); - theLocation2dMap.Bind(theIndexOfPnt3d, aPoints2d); + aLocation2D.Bind(theIndexOfPnt3d, aPoints2d); return aPnt2d; } - BRepMeshCol::ListOfXY& aPoints2d = - theLocation2dMap.ChangeFind(theIndexOfPnt3d); + BRepMeshCol::ListOfXY& aPoints2d = aLocation2D.ChangeFind(theIndexOfPnt3d); // Find the most closest 2d point to the given one. gp_XY aUV; @@ -166,23 +168,15 @@ gp_XY BRepMesh_ShapeTool::FindUV( Min(2. * BRep_Tool::Tolerance(theVertex), theMinDistance); // Get face limits - Standard_Real aDiffU, aDiffV; - if (theFaceAttribute.IsNull()) - { - aDiffU = theSurface->LastUParameter() - theSurface->FirstUParameter(); - aDiffV = theSurface->LastVParameter() - theSurface->FirstVParameter(); - } - else - { - aDiffU = theFaceAttribute->GetUMax() - theFaceAttribute->GetUMin(); - aDiffV = theFaceAttribute->GetVMax() - theFaceAttribute->GetVMin(); - } + Standard_Real aDiffU = theFaceAttribute->GetUMax() - theFaceAttribute->GetUMin(); + Standard_Real aDiffV = theFaceAttribute->GetVMax() - theFaceAttribute->GetVMin(); const Standard_Real Utol2d = .5 * aDiffU; const Standard_Real Vtol2d = .5 * aDiffV; - const gp_Pnt aPnt1 = theSurface->Value( aUV.X(), aUV.Y()); - const gp_Pnt aPnt2 = theSurface->Value(aPnt2d.X(), aPnt2d.Y()); + const Handle(BRepAdaptor_HSurface)& aSurface = theFaceAttribute->Surface(); + const gp_Pnt aPnt1 = aSurface->Value(aUV.X(), aUV.Y()); + const gp_Pnt aPnt2 = aSurface->Value(aPnt2d.X(), aPnt2d.Y()); //! If selected point is too far from the given one in parametric space //! or their positions in 3d are different, add the given point as unique. @@ -272,3 +266,65 @@ void BRepMesh_ShapeTool::UpdateEdge( aBuilder.UpdateEdge(theEdge, thePolygon1, thePolygon2, theTriangulation, theLocation); } + +//======================================================================= +//function : UseLocation +//purpose : +//======================================================================= +gp_Pnt BRepMesh_ShapeTool::UseLocation(const gp_Pnt& thePnt, + const TopLoc_Location& theLoc) +{ + if (theLoc.IsIdentity()) + return thePnt; + + return thePnt.Transformed(theLoc.Transformation()); +} + +//======================================================================= +//function : IsDegenerated +//purpose : +//======================================================================= +Standard_Boolean BRepMesh_ShapeTool::IsDegenerated( + const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace) +{ + // Get vertices + TopoDS_Vertex pBegin, pEnd; + TopExp::Vertices(theEdge, pBegin, pEnd); + if (pBegin.IsNull() || pEnd.IsNull()) + return Standard_True; + + if (BRep_Tool::Degenerated(theEdge)) + return Standard_True; + + if (!pBegin.IsSame(pEnd)) + return Standard_False; + + Standard_Real wFirst, wLast; + BRep_Tool::Range(theEdge, theFace, wFirst, wLast); + + // calculation of the length of the edge in 3D + Standard_Real longueur = 0.0; + Standard_Real du = (wLast - wFirst) * 0.05; + gp_Pnt P1, P2; + BRepAdaptor_Curve BC(theEdge); + BC.D0(wFirst, P1); + Standard_Real tolV = BRep_Tool::Tolerance(pBegin); + Standard_Real tolV2 = 1.2 * tolV; + + for (Standard_Integer l = 1; l <= 20; ++l) + { + BC.D0(wFirst + l * du, P2); + longueur += P1.Distance(P2); + + if (longueur > tolV2) + break; + + P1 = P2; + } + + if (longueur < tolV2) + return Standard_True; + + return Standard_False; +} diff --git a/src/BRepMesh/BRepMesh_ShapeTool.hxx b/src/BRepMesh/BRepMesh_ShapeTool.hxx index 5c94663d61..9486d21926 100644 --- a/src/BRepMesh/BRepMesh_ShapeTool.hxx +++ b/src/BRepMesh/BRepMesh_ShapeTool.hxx @@ -43,18 +43,18 @@ public: //! Gets the maximum dimension of the given bounding box. //! If the given bounding box is void leaves the resulting value unchanged. - //! \param theBox bounding box to be processed. - //! \param theMaxDimension maximum dimension of the given box. + //! @param theBox bounding box to be processed. + //! @param theMaxDimension maximum dimension of the given box. Standard_EXPORT static void BoxMaxDimension(const Bnd_Box& theBox, Standard_Real& theMaxDimension); //! Returns relative deflection for edge with respect to shape size. - //! \param theEdge edge for which relative deflection should be computed. - //! \param theDeflection absolute deflection. - //! \param theMaxShapeSize maximum size of a shape. - //! \param theAdjustmentCoefficient coefficient of adjustment between maximum + //! @param theEdge edge for which relative deflection should be computed. + //! @param theDeflection absolute deflection. + //! @param theMaxShapeSize maximum size of a shape. + //! @param theAdjustmentCoefficient coefficient of adjustment between maximum //! size of shape and calculated relative deflection. - //! \return relative deflection for the edge. + //! @return relative deflection for the edge. Standard_EXPORT static Standard_Real RelativeEdgeDeflection( const TopoDS_Edge& theEdge, const Standard_Real theDeflection, @@ -63,24 +63,21 @@ public: //! Checks 2d representations of 3d point with the //! given index for equality to avoid duplications. - //! \param theIndexOfPnt3d index of 3d point with which 2d + //! @param theIndexOfPnt3d index of 3d point with which 2d //! representation should be associated. - //! \param thePnt2d 2d representation of the point with the + //! @param thePnt2d 2d representation of the point with the //! given index. - //! \param theVertex vertex corresponded to 3d point with the + //! @param theVertex vertex corresponded to 3d point with the //! given index. Used to extract vertex tolerance in 3d space. - //! \param theMinDistance minimum distance between vertices + //! @param theMinDistance minimum distance between vertices //! regarding which they could be treated as distinct ones. //! This value is defined by mesher using parameters given by //! user in connection with shape metrics. - //! \param theFaceAttribute attributes contining data calculated + //! @param theFaceAttribute attributes contining data calculated //! according to face geomtry and define limits of face in parametric //! space. If defined, will be used instead of surface parameter. - //! \param theSurface surface within which parametric space - //! the 2d point is defined. Supposed to be used in case if face - //! attributes are not defined by the moment of method invocation. - //! \param theLocation2dMap map of 2d representations of 3d points. - //! \return given 2d point in case if 3d poind does not alredy have + //! @param theLocation2dMap map of 2d representations of 3d points. + //! @return given 2d point in case if 3d poind does not alredy have //! the similar representation, otherwice 2d point corresponding to //! existing representation will be returned. Standard_EXPORT static gp_XY FindUV( @@ -88,35 +85,33 @@ public: const gp_Pnt2d& thePnt2d, const TopoDS_Vertex& theVertex, const Standard_Real theMinDistance, - const Handle(BRepMesh_FaceAttribute)& theFaceAttribute, - const Handle(BRepAdaptor_HSurface)& theSurface, - BRepMeshCol::DMapOfIntegerListOfXY& theLocation2dMap); + const Handle(BRepMesh_FaceAttribute)& theFaceAttribute); //! Stores the given triangulation into the given face. - //! \param theFace face to be updated by triangulation. - //! \param theTriangulation triangulation to be stored into the face. + //! @param theFace face to be updated by triangulation. + //! @param theTriangulation triangulation to be stored into the face. Standard_EXPORT static void AddInFace( const TopoDS_Face& theFace, Handle(Poly_Triangulation)& theTriangulation); //! Nullifies triangulation stored in the face. - //! \param theFace face to be updated by null triangulation. + //! @param theFace face to be updated by null triangulation. Standard_EXPORT static void NullifyFace(const TopoDS_Face& theFace); //! Nullifies polygon on triangulation stored in the edge. - //! \param theEdge edge to be updated by null polygon. - //! \param theTriangulation triangulation the given edge is associated to. - //! \param theLocation face location. + //! @param theEdge edge to be updated by null polygon. + //! @param theTriangulation triangulation the given edge is associated to. + //! @param theLocation face location. Standard_EXPORT static void NullifyEdge( const TopoDS_Edge& theEdge, const Handle(Poly_Triangulation)& theTriangulation, const TopLoc_Location& theLocation); //! Updates the given edge by the given tessellated representation. - //! \param theEdge edge to be updated. - //! \param thePolygon tessellated representation of the edge to be stored. - //! \param theTriangulation triangulation the given edge is associated to. - //! \param theLocation face location. + //! @param theEdge edge to be updated. + //! @param thePolygon tessellated representation of the edge to be stored. + //! @param theTriangulation triangulation the given edge is associated to. + //! @param theLocation face location. Standard_EXPORT static void UpdateEdge( const TopoDS_Edge& theEdge, const Handle(Poly_PolygonOnTriangulation)& thePolygon, @@ -124,19 +119,34 @@ public: const TopLoc_Location& theLocation); //! Updates the given seam edge by the given tessellated representations. - //! \param theEdge edge to be updated. - //! \param thePolygon1 tessellated representation corresponding to + //! @param theEdge edge to be updated. + //! @param thePolygon1 tessellated representation corresponding to //! forward direction of the seam edge. - //! \param thePolygon2 tessellated representation corresponding to + //! @param thePolygon2 tessellated representation corresponding to //! reversed direction of the seam edge. - //! \param theTriangulation triangulation the given edge is associated to. - //! \param theLocation face location. + //! @param theTriangulation triangulation the given edge is associated to. + //! @param theLocation face location. Standard_EXPORT static void UpdateEdge( const TopoDS_Edge& theEdge, const Handle(Poly_PolygonOnTriangulation)& thePolygon1, const Handle(Poly_PolygonOnTriangulation)& thePolygon2, const Handle(Poly_Triangulation)& theTriangulation, const TopLoc_Location& theLocation); + + //! Applies location to the given point and return result. + //! @param thePnt point to be transformed. + //! @param theLoc location to be applied. + Standard_EXPORT static gp_Pnt UseLocation(const gp_Pnt& thePnt, + const TopLoc_Location& theLoc); + + //! Checks is the given edge degenerated. + //! Checks geometrical parameters in case if IsDegenerated flag is not set. + //! @param theEdge edge to be checked. + //! @param theFace face within which parametric space edge will be checked + //! for geometrical degenerativity. + Standard_EXPORT static Standard_Boolean IsDegenerated( + const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace); }; #endif diff --git a/src/BRepMesh/BRepMesh_Vertex.hxx b/src/BRepMesh/BRepMesh_Vertex.hxx index 8fc140004a..b288b3d53a 100644 --- a/src/BRepMesh/BRepMesh_Vertex.hxx +++ b/src/BRepMesh/BRepMesh_Vertex.hxx @@ -110,8 +110,8 @@ public: //! \return TRUE if equal, FALSE if not. Standard_EXPORT Standard_Boolean IsEqual(const BRepMesh_Vertex& theOther) const { - if (myMovability != BRepMesh_Deleted || - theOther.myMovability != BRepMesh_Deleted) + if (myMovability == BRepMesh_Deleted || + theOther.myMovability == BRepMesh_Deleted) { return Standard_False; } diff --git a/src/BRepMesh/BRepMesh_WireChecker.cxx b/src/BRepMesh/BRepMesh_WireChecker.cxx index e6d2366d4d..e939050593 100644 --- a/src/BRepMesh/BRepMesh_WireChecker.cxx +++ b/src/BRepMesh/BRepMesh_WireChecker.cxx @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -129,8 +129,8 @@ Standard_Integer BRepMesh_WireChecker::BndBox2dTreeSelector::IndicesNb() const BRepMesh_WireChecker::BRepMesh_WireChecker( const TopoDS_Face& theFace, const Standard_Real theTolUV, - const BRepMeshCol::DMapOfShapePairOfPolygon& theEdges, - const TColStd_IndexedMapOfInteger& theVertexMap, + const BRepMeshCol::HDMapOfShapePairOfPolygon& theEdges, + const BRepMeshCol::HIMapOfInteger& theVertexMap, const Handle(BRepMesh_DataStructureOfDelaun)& theStructure, const Standard_Real theUmin, const Standard_Real theUmax, @@ -151,18 +151,16 @@ BRepMesh_WireChecker::BRepMesh_WireChecker( TopoDS_Face aFace = theFace; aFace.Orientation(TopAbs_FORWARD); - TopoDS_Iterator aFaceExplorer(aFace); + TopExp_Explorer aFaceExplorer(aFace, TopAbs_WIRE); for (; aFaceExplorer.More(); aFaceExplorer.Next()) { - const TopoDS_Shape& aWire = aFaceExplorer.Value(); - if (aWire.ShapeType() != TopAbs_WIRE) - continue; + const TopoDS_Wire& aWire = TopoDS::Wire(aFaceExplorer.Current()); myWiresEdges.push_back(ListOfEdges()); ListOfEdges& aEdges = myWiresEdges.back(); // Start traversing the wires - BRepTools_WireExplorer aWireExplorer(TopoDS::Wire(aWire), aFace); + BRepTools_WireExplorer aWireExplorer(aWire, aFace); for (; aWireExplorer.More(); aWireExplorer.Next()) { const TopoDS_Edge& aEdge = aWireExplorer.Current(); @@ -264,13 +262,13 @@ Standard_Boolean BRepMesh_WireChecker::collectDiscretizedWires( { const TopoDS_Edge& aEdge = aEdgeIt.Value(); TopAbs_Orientation aOrient = aEdge.Orientation(); - if (!myEdges.IsBound(aEdge)) + if (!myEdges->IsBound(aEdge)) continue; // Retrieve polygon // Define the direction for adding points to aSeqPnt2d Standard_Integer aStartId, aEndId, aIncrement; - const BRepMesh_PairOfPolygon& aPair = myEdges.Find(aEdge); + const BRepMesh_PairOfPolygon& aPair = myEdges->Find(aEdge); Handle(Poly_PolygonOnTriangulation) aNOD; if (aOrient == TopAbs_FORWARD) { @@ -288,8 +286,8 @@ Standard_Boolean BRepMesh_WireChecker::collectDiscretizedWires( } const TColStd_Array1OfInteger& aIndices = aNOD->Nodes(); - const Standard_Integer aFirstVertexId = myVertexMap.FindKey(aIndices(aStartId)); - const Standard_Integer aLastVertexId = myVertexMap.FindKey(aIndices(aEndId) ); + const Standard_Integer aFirstVertexId = myVertexMap->FindKey(aIndices(aStartId)); + const Standard_Integer aLastVertexId = myVertexMap->FindKey(aIndices(aEndId) ); if (aFirstVertexId == aLastVertexId && (aEndId - aStartId) == aIncrement) { @@ -320,7 +318,7 @@ Standard_Boolean BRepMesh_WireChecker::collectDiscretizedWires( { Standard_Integer aIndex = ((i == aStartId) ? aFirstVertexId : - myVertexMap.FindKey(aIndices(i))); + myVertexMap->FindKey(aIndices(i))); aSeqPnt2d.Append(gp_Pnt2d(myStructure->GetNode(aIndex).Coord())); } diff --git a/src/BRepMesh/BRepMesh_WireChecker.hxx b/src/BRepMesh/BRepMesh_WireChecker.hxx index 417be93eec..d49259943c 100644 --- a/src/BRepMesh/BRepMesh_WireChecker.hxx +++ b/src/BRepMesh/BRepMesh_WireChecker.hxx @@ -87,8 +87,8 @@ public: Standard_EXPORT BRepMesh_WireChecker( const TopoDS_Face& theFace, const Standard_Real theTolUV, - const BRepMeshCol::DMapOfShapePairOfPolygon& theEdges, - const TColStd_IndexedMapOfInteger& theVertexMap, + const BRepMeshCol::HDMapOfShapePairOfPolygon& theEdges, + const BRepMeshCol::HIMapOfInteger& theVertexMap, const Handle(BRepMesh_DataStructureOfDelaun)& theStructure, const Standard_Real theUmin, const Standard_Real theUmax, @@ -129,8 +129,8 @@ private: private: const Standard_Real myTolUV; - const BRepMeshCol::DMapOfShapePairOfPolygon& myEdges; - const TColStd_IndexedMapOfInteger& myVertexMap; + const BRepMeshCol::HDMapOfShapePairOfPolygon& myEdges; + const BRepMeshCol::HIMapOfInteger& myVertexMap; const Handle(BRepMesh_DataStructureOfDelaun)& myStructure; const Standard_Real myUmin; const Standard_Real myUmax; diff --git a/src/BRepMesh/FILES b/src/BRepMesh/FILES index 7d36164fac..e7c3736d2c 100755 --- a/src/BRepMesh/FILES +++ b/src/BRepMesh/FILES @@ -36,6 +36,14 @@ BRepMesh_EdgeChecker.hxx BRepMesh_FaceChecker.hxx BRepMesh_SelectorOfDataStructureOfDelaun.hxx BRepMesh_SelectorOfDataStructureOfDelaun.cxx +BRepMesh_EdgeParameterProvider.hxx +BRepMesh_EdgeParameterProvider.cxx +BRepMesh_IEdgeTool.hxx +BRepMesh_IEdgeTool.cxx +BRepMesh_EdgeTessellationExtractor.hxx +BRepMesh_EdgeTessellationExtractor.cxx +BRepMesh_EdgeTessellator.hxx +BRepMesh_EdgeTessellator.cxx BRepMesh_FastDiscretFace.hxx BRepMesh_FastDiscretFace.cxx BRepMesh_FastDiscret.hxx diff --git a/src/IVtkOCC/IVtkOCC_ShapeMesher.cxx b/src/IVtkOCC/IVtkOCC_ShapeMesher.cxx index 112d4069e6..737684b5df 100644 --- a/src/IVtkOCC/IVtkOCC_ShapeMesher.cxx +++ b/src/IVtkOCC/IVtkOCC_ShapeMesher.cxx @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/src/MeshTest/MeshTest.cxx b/src/MeshTest/MeshTest.cxx index db6db2eacc..9b92c29156 100644 --- a/src/MeshTest/MeshTest.cxx +++ b/src/MeshTest/MeshTest.cxx @@ -394,36 +394,30 @@ static void MeshStats(const TopoDS_Shape& theSape, static Standard_Integer triangule(Draw_Interpretor& di, Standard_Integer nbarg, const char** argv) { - if (nbarg < 4) return 1; - - Standard_Boolean save = Standard_False; + if (nbarg < 4) + return 1; const char *id1 = argv[2]; - TopoDS_Shape S = DBRep::Get(id1); - if (S.IsNull()) return 1; + TopoDS_Shape aShape = DBRep::Get(id1); + if (aShape.IsNull()) + return 1; + di << argv[1] << " "; - Standard_Real Deflect=Draw::Atof(argv[3]); - if (Deflect<=0.) { - di << " Donner la fleche !" << "\n"; + + Standard_Real aDeflection = Draw::Atof(argv[3]); + if (aDeflection <= 0.) + { + di << " Incorrect value of deflection!" << "\n"; return 1; } - if (nbarg >4) { - save = (Draw::Atoi(argv[4])==1); - } + Handle(MeshTest_DrawableMesh) aDMesh = + new MeshTest_DrawableMesh(aShape, aDeflection); - Standard_Boolean partage=Standard_True; - if (nbarg>5) { - partage=Draw::Atoi(argv[5])==1; - } - - Handle(MeshTest_DrawableMesh) DM = - new MeshTest_DrawableMesh(S,Deflect,partage, save); - - Draw::Set(argv[1],DM); + Draw::Set(argv[1], aDMesh); Standard_Integer nbn, nbl, nbe; - MeshStats(S, nbe, nbl, nbn); + MeshStats(aShape, nbe, nbl, nbn); di<<"(Resultat ("<Mesh()->NbPoint3d(); lepnt++) { - bobo.Add(DM->Mesh()->Point3d(lepnt)); + Bnd_Box aBox; + const Handle(BRepMesh_FastDiscret)& aFastDiscret = aDMesh->Mesher()->Mesh(); + + TopExp_Explorer aFaceIt(aShape, TopAbs_FACE); + for (; aFaceIt.More(); aFaceIt.Next()) + { + const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current()); + + Handle(BRepMesh_FaceAttribute) anAttribute; + if (aFastDiscret->GetFaceAttribute(aFace, anAttribute) && anAttribute->IsValid()) + { + const Standard_Integer aNbPnts = anAttribute->LastPointId(); + for (Standard_Integer i = 1; i < aNbPnts; ++i) + aBox.Add(anAttribute->GetPoint(i)); + } } - Standard_Real x,y,z,X,Y,Z; - bobo.Get(x,y,z,X,Y,Z); - Standard_Real delta=Max(X-x,Max(Y-y,Z-z)); - if (delta>0) delta=Deflect/delta; - di << " Fleche de " << delta << " fois la taille de l''objet." << "\n"; + + Standard_Real aDelta = 0.; + if (!aBox.IsVoid()) + { + Standard_Real x, y, z, X, Y, Z; + aBox.Get(x, y, z, X, Y, Z); + + aDelta = Max(X - x, Max(Y - y, Z - z)); + if (aDelta > 0.0) + aDelta = aDeflection / aDelta; + } + + di << " Ratio between deflection and total shape size is " << aDelta << "\n"; return 0; } @@ -546,36 +560,60 @@ return 0; //function : vertices //purpose : //======================================================================= - -static Standard_Integer vertices (Draw_Interpretor&, Standard_Integer n, const char** a) +static Standard_Integer vertices( + Draw_Interpretor& /*di*/, + Standard_Integer /*argc*/, + const char** /*argv*/) { - if (n < 3) return 1; + return 0; - Handle(MeshTest_DrawableMesh) D = - Handle(MeshTest_DrawableMesh)::DownCast(Draw::Get(a[1])); - if (D.IsNull()) return 1; - TopoDS_Shape S = DBRep::Get(a[2]); - if (S.IsNull()) return 1; + // TODO: OAN re-implement this command according changes in BRepMesh + //if (argc < 3) + // return 1; - TopExp_Explorer ex; - TColStd_SequenceOfInteger& vseq = D->Vertices(); - Handle(BRepMesh_FastDiscret) M = D->Mesh(); + //Handle(MeshTest_DrawableMesh) aDrawableMesh = + // Handle(MeshTest_DrawableMesh)::DownCast(Draw::Get(argv[1])); + //if (aDrawableMesh.IsNull()) + // return 1; - // the faces - for (ex.Init(S,TopAbs_FACE);ex.More();ex.Next()) { - BRepMeshCol::MapOfInteger vtx; - M->VerticesOfDomain(vtx); - for (BRepMeshCol::MapOfInteger::Iterator it(vtx); it.More(); it.Next()) - vseq.Append(it.Key()); - } + //TopoDS_Shape aShape = DBRep::Get(argv[2]); + //if (aShape.IsNull()) + // return 1; + //TColStd_SequenceOfInteger& aVertexSeq = aDrawableMesh->Vertices(); + //Handle(BRepMesh_FastDiscret) aMesh = aDrawableMesh->Mesh(); - // the edges - //for (ex.Init(S,TopAbs_EDGE,TopAbs_FACE);ex.More();ex.Next()) { + //TopExp_Explorer aFaceIt(aShape, TopAbs_FACE); + //for (; aFaceIt.More(); aFaceIt.Next()) + //{ + // const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current()); + + // Handle(BRepMesh_FaceAttribute) aAttribute; + // if (aMesh->GetFaceAttribute(aFace, aAttribute)) + // { + // Handle(BRepMesh_DataStructureOfDelaun) aStructure = aAttribute->EditStructure(); + + // // Recuperate from the map of edges. + // const BRepMeshCol::MapOfInteger& aEdgeMap = aStructure->LinksOfDomain(); + + // // Iterator on edges. + // BRepMeshCol::MapOfInteger aVertices; + // BRepMeshCol::MapOfInteger::Iterator aEdgeIt(aEdgeMap); + // for (; aEdgeIt.More(); aEdgeIt.Next()) + // { + // const BRepMesh_Edge& aEdge = aStructure->GetLink(aEdgeIt.Key()); + // aVertices.Add(aEdge.FirstNode()); + // aVertices.Add(aEdge.LastNode()); + // } + + // BRepMeshCol::MapOfInteger::Iterator anIt(vtx); + // for ( ; anIt.More(); anIt.Next() ) + // aVertexSeq.Append(anIt.Key()); + // } //} - Draw::Repaint(); - return 0; + //Draw::Repaint(); + //return 0; } //======================================================================= @@ -1504,7 +1542,7 @@ void MeshTest::Commands(Draw_Interpretor& theCommands) theCommands.Add("incmesh","incmesh shape deflection [inParallel (0/1) : 0 by default]",__FILE__, incrementalmesh, g); theCommands.Add("MemLeakTest","MemLeakTest",__FILE__, MemLeakTest, g); theCommands.Add("fastdiscret","fastdiscret shape deflection [shared [nbiter]]",__FILE__, fastdiscret, g); - theCommands.Add("mesh","mesh result Shape deflection [save partage]",__FILE__, triangule, g); + theCommands.Add("mesh","mesh result Shape deflection",__FILE__, triangule, g); theCommands.Add("addshape","addshape meshname Shape [deflection]",__FILE__, addshape, g); //theCommands.Add("smooth","smooth meshname",__FILE__, smooth, g); //theCommands.Add("edges","edges mesh shape, highlight the edges",__FILE__,edges, g); diff --git a/src/MeshTest/MeshTest_DrawableMesh.cxx b/src/MeshTest/MeshTest_DrawableMesh.cxx index 75f7ad88f8..68cd1914e8 100644 --- a/src/MeshTest/MeshTest_DrawableMesh.cxx +++ b/src/MeshTest/MeshTest_DrawableMesh.cxx @@ -26,8 +26,7 @@ #include #include #include -#include -#include +#include IMPLEMENT_STANDARD_HANDLE (MeshTest_DrawableMesh, Draw_Drawable3D) IMPLEMENT_STANDARD_RTTIEXT(MeshTest_DrawableMesh, Draw_Drawable3D) @@ -36,9 +35,8 @@ IMPLEMENT_STANDARD_RTTIEXT(MeshTest_DrawableMesh, Draw_Drawable3D) //function : MeshTest_DrawableMesh //purpose : //======================================================================= - -MeshTest_DrawableMesh::MeshTest_DrawableMesh() : -myDeflection(1.), myinshape(Standard_False) +MeshTest_DrawableMesh::MeshTest_DrawableMesh() + : myDeflection(1.) { } @@ -46,56 +44,41 @@ myDeflection(1.), myinshape(Standard_False) //function : MeshTest_DrawableMesh //purpose : //======================================================================= - -MeshTest_DrawableMesh::MeshTest_DrawableMesh(const TopoDS_Shape& S, - const Standard_Real Deflect, - const Standard_Boolean Partage, - const Standard_Boolean inshape) : -myDeflection(Deflect), myinshape(inshape) +MeshTest_DrawableMesh::MeshTest_DrawableMesh(const TopoDS_Shape& theShape, + const Standard_Real theDeflection) + : myDeflection(theDeflection) { - Bnd_Box B; - BRepBndLib::Add(S, B); - - myMesh = new BRepMesh_FastDiscret(S, Deflect, 0.5, B, Partage, inshape); + Add(theShape); } - //======================================================================= //function : MeshTest_DrawableMesh //purpose : //======================================================================= - -MeshTest_DrawableMesh::MeshTest_DrawableMesh(const Handle(BRepMesh_FastDiscret)& Tr): -myDeflection(1.0) +MeshTest_DrawableMesh::MeshTest_DrawableMesh( + const Handle(BRepMesh_IncrementalMesh)& theMesher) + : myDeflection(1.) { - myMesh = Tr; + myMesher = theMesher; + if (!myMesher.IsNull()) + myDeflection = myMesher->Deflection(); } - //======================================================================= //function : MeshTest_DrawableMesh //purpose : //======================================================================= - -void MeshTest_DrawableMesh::Add(const TopoDS_Shape& S) +void MeshTest_DrawableMesh::Add(const TopoDS_Shape& theShape) { - Bnd_Box B; - BRepBndLib::Add(S, B); - - if (myMesh.IsNull()) - myMesh=new BRepMesh_FastDiscret(S, myDeflection, 0.5, B, myinshape); - else - myMesh->Perform(S); -} - -//======================================================================= -//function : AddInShape -//purpose : -//======================================================================= - -void MeshTest_DrawableMesh::AddInShape(const Standard_Boolean inshape) -{ - myinshape = inshape; + if (myMesher.IsNull()) + { + myMesher = new BRepMesh_IncrementalMesh; + myMesher->SetDeflection(myDeflection); + myMesher->SetAngle(0.5); + } + + myMesher->SetShape(theShape); + myMesher->Perform(); } //======================================================================= @@ -172,18 +155,15 @@ void MeshTest_DrawableMesh::DrawOn(Draw_Display& /*D*/) const //function : Copy //purpose : //======================================================================= - Handle(Draw_Drawable3D) MeshTest_DrawableMesh::Copy() const { - Handle(MeshTest_DrawableMesh) D = new MeshTest_DrawableMesh(); - return D; + return new MeshTest_DrawableMesh(myMesher); } //======================================================================= //function : Dump //purpose : //======================================================================= - void MeshTest_DrawableMesh::Dump(Standard_OStream&) const { // Should be reimplemented @@ -239,24 +219,45 @@ void MeshTest_DrawableMesh::Dump(Standard_OStream&) const //function : Whatis //purpose : //======================================================================= - -void MeshTest_DrawableMesh::Whatis(Draw_Interpretor& S) const +void MeshTest_DrawableMesh::Whatis(Draw_Interpretor& theStream) const { - S << " 3d mesh\n"; - S << " - Triangles : " << myMesh->NbTriangles() << "\n"; - S << " - Edges : " << myMesh->NbEdges() << "\n"; - S << " - Vertices : " << myMesh->NbVertices() << "\n"; - S << " - Point3d : " << myMesh->NbPoint3d() << "\n"; + const Handle(BRepMesh_FastDiscret)& aMesh = myMesher->Mesh(); + Standard_Integer aPointsNb = aMesh->NbBoundaryPoints(); + Standard_Integer aTrianglesNb = 0; + Standard_Integer aEdgesNb = 0; + + const TopoDS_Shape& aShape = myMesher->Shape(); + TopExp_Explorer aFaceIt(aShape, TopAbs_FACE); + for (; aFaceIt.More(); aFaceIt.Next()) + { + const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current()); + + Handle(BRepMesh_FaceAttribute) aAtrribure; + if (!aMesh->GetFaceAttribute(aFace, aAtrribure) || !aAtrribure->IsValid()) + continue; + + aPointsNb += aAtrribure->ChangeSurfacePoints()->Extent(); + + Handle(BRepMesh_DataStructureOfDelaun)& aStructure = + aAtrribure->ChangeStructure(); + + aTrianglesNb += aStructure->ElementsOfDomain().Extent(); + aEdgesNb += aStructure->LinksOfDomain().Extent(); + } + + theStream << " 3d mesh\n"; + theStream << " - Triangles : " << aTrianglesNb << "\n"; + theStream << " - Edges : " << aEdgesNb << "\n"; + theStream << " - Point3d : " << aPointsNb << "\n"; } //======================================================================= -//function : Mesh +//function : Mesher //purpose : //======================================================================= - -Handle(BRepMesh_FastDiscret) MeshTest_DrawableMesh::Mesh() const +const Handle(BRepMesh_IncrementalMesh)& MeshTest_DrawableMesh::Mesher() const { - return myMesh; + return myMesher; } @@ -264,7 +265,6 @@ Handle(BRepMesh_FastDiscret) MeshTest_DrawableMesh::Mesh() const //function : Edges //purpose : //======================================================================= - TColStd_SequenceOfInteger& MeshTest_DrawableMesh::Edges() { return myEdges; @@ -275,7 +275,6 @@ TColStd_SequenceOfInteger& MeshTest_DrawableMesh::Edges() //function : Vertices //purpose : //======================================================================= - TColStd_SequenceOfInteger& MeshTest_DrawableMesh::Vertices() { return myVertices; @@ -285,7 +284,6 @@ TColStd_SequenceOfInteger& MeshTest_DrawableMesh::Vertices() //function : Triangles //purpose : //======================================================================= - TColStd_SequenceOfInteger& MeshTest_DrawableMesh::Triangles() { return myTriangles; diff --git a/src/MeshTest/MeshTest_DrawableMesh.hxx b/src/MeshTest/MeshTest_DrawableMesh.hxx index 85bb3ed6da..d190007e0a 100644 --- a/src/MeshTest/MeshTest_DrawableMesh.hxx +++ b/src/MeshTest/MeshTest_DrawableMesh.hxx @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include #include @@ -37,40 +37,38 @@ public: Standard_EXPORT MeshTest_DrawableMesh(); - Standard_EXPORT MeshTest_DrawableMesh(const TopoDS_Shape& S,const Standard_Real Deflect,const Standard_Boolean Partage,const Standard_Boolean InShape = Standard_False); + Standard_EXPORT MeshTest_DrawableMesh(const TopoDS_Shape& theShape, + const Standard_Real theDeflection); - Standard_EXPORT MeshTest_DrawableMesh(const Handle(BRepMesh_FastDiscret)& Tr); + Standard_EXPORT MeshTest_DrawableMesh(const Handle(BRepMesh_IncrementalMesh)& theMesher); - Standard_EXPORT void AddInShape(const Standard_Boolean inshape) ; + Standard_EXPORT void Add(const TopoDS_Shape& theShape); - Standard_EXPORT void Add(const TopoDS_Shape& S) ; + Standard_EXPORT TColStd_SequenceOfInteger& Edges(); - Standard_EXPORT TColStd_SequenceOfInteger& Edges() ; + Standard_EXPORT TColStd_SequenceOfInteger& Vertices(); - Standard_EXPORT TColStd_SequenceOfInteger& Vertices() ; + Standard_EXPORT TColStd_SequenceOfInteger& Triangles(); - Standard_EXPORT TColStd_SequenceOfInteger& Triangles() ; + Standard_EXPORT void DrawOn(Draw_Display& theDisplay) const; - Standard_EXPORT void DrawOn(Draw_Display& dis) const; + Standard_EXPORT virtual Handle_Draw_Drawable3D Copy() const; - Standard_EXPORT virtual Handle_Draw_Drawable3D Copy() const; + Standard_EXPORT virtual void Dump(Standard_OStream& theStream) const; - Standard_EXPORT virtual void Dump(Standard_OStream& S) const; + Standard_EXPORT virtual void Whatis(Draw_Interpretor& theDi) const; - Standard_EXPORT virtual void Whatis(Draw_Interpretor& S) const; - - Standard_EXPORT Handle(BRepMesh_FastDiscret) Mesh() const; + Standard_EXPORT const Handle(BRepMesh_IncrementalMesh)& Mesher() const; DEFINE_STANDARD_RTTI(MeshTest_DrawableMesh) private: - Handle(BRepMesh_FastDiscret) myMesh; - Standard_Real myDeflection; - TColStd_SequenceOfInteger myEdges; - TColStd_SequenceOfInteger myVertices; - TColStd_SequenceOfInteger myTriangles; - Standard_Boolean myinshape; + Handle(BRepMesh_IncrementalMesh) myMesher; + Standard_Real myDeflection; + TColStd_SequenceOfInteger myEdges; + TColStd_SequenceOfInteger myVertices; + TColStd_SequenceOfInteger myTriangles; }; DEFINE_STANDARD_HANDLE(MeshTest_DrawableMesh, Draw_Drawable3D) diff --git a/src/MeshTest/MeshTest_PluginCommands.cxx b/src/MeshTest/MeshTest_PluginCommands.cxx index 1b95c95a55..99b0e0817a 100644 --- a/src/MeshTest/MeshTest_PluginCommands.cxx +++ b/src/MeshTest/MeshTest_PluginCommands.cxx @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/XBRepMesh/FILES b/src/XBRepMesh/FILES new file mode 100644 index 0000000000..c120d50ef9 --- /dev/null +++ b/src/XBRepMesh/FILES @@ -0,0 +1,2 @@ +XBRepMesh.hxx +XBRepMesh.cxx diff --git a/src/XBRepMesh/XBRepMesh.cdl b/src/XBRepMesh/XBRepMesh.cdl deleted file mode 100644 index 428d3d4252..0000000000 --- a/src/XBRepMesh/XBRepMesh.cdl +++ /dev/null @@ -1,31 +0,0 @@ --- Created on: 2008-04-11 --- Created by: Peter KURNEV --- Copyright (c) 2008-2014 OPEN CASCADE SAS --- --- This file is part of Open CASCADE Technology software library. --- --- This library is free software; you can redistribute it and/or modify it under --- the terms of the GNU Lesser General Public License version 2.1 as published --- by the Free Software Foundation, with special exception defined in the file --- OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT --- distribution for complete text of the license and disclaimer of any warranty. --- --- Alternatively, this file may be used under the terms of Open CASCADE --- commercial license or contractual agreement. - -package XBRepMesh - - ---Purpose: - -uses - TopoDS, - BRepMesh - -is - Discret(theShape : Shape from TopoDS; - theDeflection : Real from Standard; - theAngle : Real from Standard; - theAlgo:out PDiscretRoot from BRepMesh) - returns Integer from Standard; - -end XBRepMesh; diff --git a/src/XBRepMesh/XBRepMesh.cxx b/src/XBRepMesh/XBRepMesh.cxx index 051ecb652c..6f76378cd4 100644 --- a/src/XBRepMesh/XBRepMesh.cxx +++ b/src/XBRepMesh/XBRepMesh.cxx @@ -13,7 +13,7 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -#include +#include #include #include @@ -21,10 +21,11 @@ //function : Discret //purpose : //======================================================================= -Standard_Integer XBRepMesh::Discret(const TopoDS_Shape& theShape, - const Standard_Real theDeflection, - const Standard_Real theAngle, - BRepMesh_PDiscretRoot& theAlgo) +Standard_Integer XBRepMesh::Discret( + const TopoDS_Shape& theShape, + const Standard_Real theDeflection, + const Standard_Real theAngle, + BRepMesh_DiscretRoot* &theAlgo) { Standard_Integer iErr; // diff --git a/src/XBRepMesh/XBRepMesh.hxx b/src/XBRepMesh/XBRepMesh.hxx new file mode 100644 index 0000000000..28e32c6ce7 --- /dev/null +++ b/src/XBRepMesh/XBRepMesh.hxx @@ -0,0 +1,39 @@ +// Created on: 2008-04-11 +// Created by: Peter KURNEV +// Copyright (c) 2008-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _XBRepMesh_HeaderFile +#define _XBRepMesh_HeaderFile + +#include +#include +#include +#include + +class TopoDS_Shape; + +class XBRepMesh +{ +public: + + DEFINE_STANDARD_ALLOC + + Standard_EXPORT static Standard_Integer Discret( + const TopoDS_Shape& theShape, + const Standard_Real theDeflection, + const Standard_Real theAngle, + BRepMesh_DiscretRoot* &theAlgo); +}; + +#endif diff --git a/src/XSDRAWSTLVRML/XSDRAWSTLVRML_ToVRML.cxx b/src/XSDRAWSTLVRML/XSDRAWSTLVRML_ToVRML.cxx index 0f775e6485..5aaa2f5a12 100644 --- a/src/XSDRAWSTLVRML/XSDRAWSTLVRML_ToVRML.cxx +++ b/src/XSDRAWSTLVRML/XSDRAWSTLVRML_ToVRML.cxx @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include //ied_modif_for_compil_Nov-20-1998 @@ -63,103 +65,141 @@ Standard_Real& XSDRAWSTLVRML_ToVRML::Deflection () { return myDeflecti //======================================================================= Standard_Boolean XSDRAWSTLVRML_ToVRML::Write - (const TopoDS_Shape& aShape, const Standard_CString filename) const + (const TopoDS_Shape& theShape, const Standard_CString theFileName) const { - filebuf thefile; - ostream TheFileOut(&thefile); + filebuf aFile; + ostream anOut(&aFile); - if (thefile.open(filename,ios::out)) - { + if ( aFile.open(theFileName,ios::out) ) + { + // Creates facets from the shape + // Create (defle : Real from Standard; + // shape : Shape from TopoDS; + // angl : Real from Standard = 0.17; + // withShare : Boolean from Standard = Standard_True; + // inshape : Boolean from Standard = Standard_False; + // relative : Boolean from Standard = Standard_False; + // shapetrigu: Boolean from Standard = Standard_False) + // returns mutable Discret from BRepMesh; - // Creates facets from the shape -// Create (defle : Real from Standard; -// shape : Shape from TopoDS; -// angl : Real from Standard= 0.17; -// withShare : Boolean from Standard=Standard_True; -// inshape : Boolean from Standard=Standard_False; -// relative : Boolean from Standard=Standard_False; -// shapetrigu: Boolean from Standard=Standard_False) -// returns mutable Discret from BRepMesh; - Bnd_Box B; - BRepBndLib::Add(aShape, B); + Bnd_Box aBox; + BRepBndLib::Add(theShape, aBox); - Handle(BRepMesh_FastDiscret) TheDiscret = - new BRepMesh_FastDiscret(aShape, - myDeflection, - 0.17, - B, - Standard_True, - Standard_False, - Standard_True, - Standard_True); + Handle(BRepMesh_FastDiscret) aDiscret = + new BRepMesh_FastDiscret( theShape, + myDeflection, + 0.17, + aBox, + Standard_True, + Standard_False, + Standard_True, + Standard_True ); - Standard_Integer i,j; + // Header of the VRML file + anOut << "#VRML V2.0 utf8" << endl; + anOut << "Group {" << endl; + anOut << " children [ " << endl; + anOut << " NavigationInfo {" << endl; + anOut << " type \"EXAMINE\" " << endl; + anOut << " }," << endl; + anOut << " Shape {" << endl; - // header of the VRML file - TheFileOut << "#VRML V2.0 utf8" << endl; - TheFileOut << "Group {" << endl; - TheFileOut << " children [ " << endl; - TheFileOut << " NavigationInfo {" << endl; - TheFileOut << " type \"EXAMINE\" " << endl; - TheFileOut << " }," << endl; - TheFileOut << "Shape {" << endl; + anOut << " appearance Appearance {" << endl; + anOut << " texture ImageTexture {" << endl; + anOut << " url " << myTexture.ToCString() << endl; + anOut << " }" << endl; + anOut << " material Material {" << endl; + anOut << " diffuseColor " << myDiffuseColorRed << " " + << myDiffuseColorGreen << " " + << myDiffuseColorBlue << " " << endl; + anOut << " emissiveColor " << myEmissiveColorRed << " " + << myEmissiveColorGreen << " " + << myEmissiveColorBlue << " " << endl; + anOut << " transparency " << myTransparency << endl; + anOut << " ambientIntensity " << myAmbientIntensity << " " << endl; + anOut << " specularColor " << mySpecularColorRed << " " + << mySpecularColorGreen << " " + << mySpecularColorBlue << " " << endl; + anOut << " shininess " << myShininess << " " << endl; + anOut << " }" << endl; + anOut << " }" << endl; - TheFileOut << " appearance Appearance {" << endl; - TheFileOut << " texture ImageTexture {" << endl; - TheFileOut << " url " << myTexture.ToCString() << endl; - TheFileOut << " }" << endl; - TheFileOut << " material Material { " << endl; - TheFileOut << " diffuseColor " << myDiffuseColorRed << " " << myDiffuseColorGreen << " " << myDiffuseColorBlue << " " << endl; - TheFileOut << " emissiveColor " << myEmissiveColorRed << " " - << myEmissiveColorGreen << " " << myEmissiveColorBlue << " " << endl; - TheFileOut << " transparency " << myTransparency << endl; - TheFileOut << " ambientIntensity " << myAmbientIntensity << " " << endl; - TheFileOut << " specularColor " << mySpecularColorRed << " " << mySpecularColorGreen << " " << mySpecularColorBlue << " " << endl; - TheFileOut << " shininess " <NbVertices();i++) - { - gp_Pnt TheVertex=TheDiscret->Pnt(i); - TheFileOut << " " - << TheVertex.Coord().X() << " " - << TheVertex.Coord().Y() << " " - << TheVertex.Coord().Z() << "," << endl; - } - TheFileOut << " ]" << endl; - TheFileOut << " }" << endl; - - TheFileOut << " coordIndex [" << endl; - - // retrieves all the triangles in order to draw the facets - for (j=1; j <= TheDiscret->NbTriangles(); j++) - { - Standard_Integer v[3]; - TheDiscret->TriangleNodes(j, v); - - TheFileOut << " " << v[0]-1 << ", " << v[1]-1 << ", " << v[2]-1 << ", -1, " << endl; - } - - TheFileOut << " ]" << endl; - TheFileOut << " solid FALSE" << endl; // it is not a closed solid - TheFileOut << " creaseAngle " << myCreaseAngle << " " << endl; // for smooth shading - TheFileOut << " }" << endl; - TheFileOut << " }" << endl; - TheFileOut << " ]" << endl; - TheFileOut << "} " << endl; - - } - else return Standard_False; // failure when opening file + TopExp_Explorer aFaceIt(theShape, TopAbs_FACE); + for (; aFaceIt.More(); aFaceIt.Next()) + { + Handle(BRepMesh_FaceAttribute) anAttribute; + const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current()); + if (!aDiscret->GetFaceAttribute(aFace, anAttribute) || !anAttribute->IsValid()) + continue; - thefile.close(); + Handle(BRepMesh_DataStructureOfDelaun)& aStructure = + anAttribute->ChangeStructure(); + const Standard_Integer aNbVertices = aStructure->NbNodes(); + for (Standard_Integer i = 1; i <= aNbVertices; ++i) + { + const BRepMesh_Vertex& aVertex = aStructure->GetNode(i); + const gp_Pnt& aPoint = anAttribute->GetPoint(aVertex); + + anOut << " " + << aPoint.Coord().X() << " " + << aPoint.Coord().Y() << " " + << aPoint.Coord().Z() << "," << endl; + } + } + + anOut << " ]" << endl; + anOut << " }" << endl; + anOut << " coordIndex [" << endl; + + // Retrieves all the triangles in order to draw the facets + for (aFaceIt.Init(theShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next()) + { + Handle(BRepMesh_FaceAttribute) anAttribute; + const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current()); + + if (!aDiscret->GetFaceAttribute(aFace, anAttribute) || !anAttribute->IsValid()) + continue; + + Handle(BRepMesh_DataStructureOfDelaun)& aStructure = + anAttribute->ChangeStructure(); + + const Standard_Integer aNbTriangles = aStructure->NbElements(); + for ( Standard_Integer i = 1; i <= aNbTriangles; ++i ) + { + const BRepMesh_Triangle& aTriangle = aStructure->GetElement(i); + + Standard_Integer v[3]; + aStructure->ElementNodes(aTriangle, v); + + anOut << " " + << v[0] - 1 << ", " + << v[1] - 1 << ", " + << v[2] - 1 << ", -1," << endl; + } + } + + anOut << " ]" << endl; + anOut << " solid FALSE" << endl; // it is not a closed solid + anOut << " creaseAngle " << myCreaseAngle << " " << endl; // for smooth shading + anOut << " }" << endl; + anOut << " }" << endl; + anOut << " ]" << endl; + anOut << "}" << endl; + } + else + { + // Failure when opening file + return Standard_False; + } + + aFile.close(); return Standard_True; } diff --git a/tests/bugs/mesh/bug23106 b/tests/bugs/mesh/bug23106 new file mode 100755 index 0000000000..b0b0a140cd --- /dev/null +++ b/tests/bugs/mesh/bug23106 @@ -0,0 +1,29 @@ +puts "========" +puts "OCC23106" +puts "========" +puts "" +########################################### +## BRepMesh_IncrementalMesh returns wrong status +########################################### + +set BugNumber OCC23106 + +restore [locate_data_file bug23106_face_0triangles.brep] result + +incmesh result 0.01 +triangles result + +set tri 0 +set nod 0 + +set tri_info [trinfo result] +regexp { +([-0-9.+eE]+) +triangles} $tri_info full tri +regexp { +([-0-9.+eE]+) +nodes} $tri_info full nod + +if { ${tri} > 0 && ${nod} > 0 } { + puts "${BugNumber} shading: OK" +} else { + puts "${BugNumber} shading: Faulty" +} + +set 3dviewer 1