From ceb418e13f0e2e8aa7fa8e86346e6904cd7465f8 Mon Sep 17 00:00:00 2001 From: oan Date: Fri, 26 Sep 2014 16:31:27 +0400 Subject: [PATCH] 0023106: BRepMesh_IncrementalMesh returns wrong status Fix compilation errors on Linux platform Squeeze compilation warnings on Linux Fix regressions Back RemoveFaceAttribute for further reasons Fix retrieving of polygon by index Fix applying of location Test case for issue CR23106 Fix memory leak regression 'test bugs vis bug79' occurred due to incorrect memory cleaning of inherited objects by MMgtRaw::Free through BRepMesh_IEdgeTool; Replace BRepMesh_PDiscretRoot by pure pointer to BRepMesh_DiscretRoot; Fix IVtkOCC_ShapeMesher. --- adm/UDLIST | 2 +- src/BRepMesh/BRepMesh.cdl | 6 +- src/BRepMesh/BRepMesh_Collections.hxx | 5 +- src/BRepMesh/BRepMesh_Delaun.cxx | 57 +- src/BRepMesh/BRepMesh_Delaun.hxx | 10 +- src/BRepMesh/BRepMesh_DiscretFactory.cxx | 6 +- src/BRepMesh/BRepMesh_Edge.hxx | 111 +- .../BRepMesh_EdgeParameterProvider.cxx | 89 + .../BRepMesh_EdgeParameterProvider.hxx | 69 + .../BRepMesh_EdgeTessellationExtractor.cxx | 59 + .../BRepMesh_EdgeTessellationExtractor.hxx | 87 + src/BRepMesh/BRepMesh_EdgeTessellator.cxx | 217 ++ src/BRepMesh/BRepMesh_EdgeTessellator.hxx | 88 + src/BRepMesh/BRepMesh_FaceAttribute.cxx | 146 +- src/BRepMesh/BRepMesh_FaceAttribute.hxx | 388 ++- src/BRepMesh/BRepMesh_FastDiscret.cxx | 2193 ++++++--------- src/BRepMesh/BRepMesh_FastDiscret.hxx | 373 ++- src/BRepMesh/BRepMesh_FastDiscretFace.cxx | 2342 +++++++---------- src/BRepMesh/BRepMesh_FastDiscretFace.hxx | 142 +- src/BRepMesh/BRepMesh_IEdgeTool.cxx | 19 + src/BRepMesh/BRepMesh_IEdgeTool.hxx | 46 + src/BRepMesh/BRepMesh_IncrementalMesh.cxx | 171 +- src/BRepMesh/BRepMesh_IncrementalMesh.hxx | 34 +- src/BRepMesh/BRepMesh_PluginMacro.hxx | 10 +- src/BRepMesh/BRepMesh_ShapeTool.cxx | 106 +- src/BRepMesh/BRepMesh_ShapeTool.hxx | 80 +- src/BRepMesh/BRepMesh_Vertex.hxx | 4 +- src/BRepMesh/BRepMesh_WireChecker.cxx | 24 +- src/BRepMesh/BRepMesh_WireChecker.hxx | 8 +- src/BRepMesh/FILES | 8 + src/IVtkOCC/IVtkOCC_ShapeMesher.cxx | 1 - src/MeshTest/MeshTest.cxx | 142 +- src/MeshTest/MeshTest_DrawableMesh.cxx | 114 +- src/MeshTest/MeshTest_DrawableMesh.hxx | 38 +- src/MeshTest/MeshTest_PluginCommands.cxx | 2 +- src/XBRepMesh/FILES | 2 + src/XBRepMesh/XBRepMesh.cdl | 31 - src/XBRepMesh/XBRepMesh.cxx | 11 +- src/XBRepMesh/XBRepMesh.hxx | 39 + src/XSDRAWSTLVRML/XSDRAWSTLVRML_ToVRML.cxx | 212 +- tests/bugs/mesh/bug23106 | 29 + 41 files changed, 3926 insertions(+), 3595 deletions(-) create mode 100644 src/BRepMesh/BRepMesh_EdgeParameterProvider.cxx create mode 100644 src/BRepMesh/BRepMesh_EdgeParameterProvider.hxx create mode 100644 src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx create mode 100644 src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx create mode 100644 src/BRepMesh/BRepMesh_EdgeTessellator.cxx create mode 100644 src/BRepMesh/BRepMesh_EdgeTessellator.hxx create mode 100644 src/BRepMesh/BRepMesh_IEdgeTool.cxx create mode 100644 src/BRepMesh/BRepMesh_IEdgeTool.hxx create mode 100644 src/XBRepMesh/FILES delete mode 100644 src/XBRepMesh/XBRepMesh.cdl create mode 100644 src/XBRepMesh/XBRepMesh.hxx create mode 100755 tests/bugs/mesh/bug23106 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