X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_FaceSide.cxx;h=b543928dcabd653c2e7adfda7f4f26fca61b11c5;hp=7719b4f6e799628d4678b0d3d5f9110e835e3ced;hb=faaf2eee1d5badc5647a3d17140edc1067f8293f;hpb=0635c9fc80f67d1e5dc0e94ec85f487286a92070 diff --git a/src/StdMeshers/StdMeshers_FaceSide.cxx b/src/StdMeshers/StdMeshers_FaceSide.cxx index 7719b4f6e..b543928dc 100644 --- a/src/StdMeshers/StdMeshers_FaceSide.cxx +++ b/src/StdMeshers/StdMeshers_FaceSide.cxx @@ -1,25 +1,25 @@ -// Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE // -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. // -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// SMESH SMESH : implementaion of SMESH idl descriptions + // File : StdMeshers_FaceSide.hxx // Created : Wed Jan 31 18:41:25 2007 // Author : Edward AGAPOV (eap) @@ -31,24 +31,27 @@ #include "SMDS_MeshNode.hxx" #include "SMESHDS_Mesh.hxx" #include "SMESHDS_SubMesh.hxx" -//#include "SMESH_Algo.hxx" +#include "SMESH_Algo.hxx" #include "SMESH_Mesh.hxx" -#include "SMESH_MeshEditor.hxx" +#include "SMESH_MesherHelper.hxx" #include "SMESH_ComputeError.hxx" #include "SMESH_Block.hxx" #include #include -#include #include #include +#include +#include #include #include +#include #include #include #include #include +#include #include "utilities.h" @@ -60,14 +63,16 @@ */ //================================================================================ -StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, - const TopoDS_Edge& theEdge, - SMESH_Mesh* theMesh, - const bool theIsForward, - const bool theIgnoreMediumNodes) +StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, + const TopoDS_Edge& theEdge, + SMESH_Mesh* theMesh, + const bool theIsForward, + const bool theIgnoreMediumNodes, + SMESH_ProxyMesh::Ptr theProxyMesh) { list edges(1,theEdge); - *this = StdMeshers_FaceSide( theFace, edges, theMesh, theIsForward, theIgnoreMediumNodes ); + *this = StdMeshers_FaceSide( theFace, edges, theMesh, theIsForward, + theIgnoreMediumNodes, theProxyMesh ); } //================================================================================ @@ -78,37 +83,45 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, */ //================================================================================ -StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, - list& theEdges, - SMESH_Mesh* theMesh, - const bool theIsForward, - const bool theIgnoreMediumNodes) +StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, + list& theEdges, + SMESH_Mesh* theMesh, + const bool theIsForward, + const bool theIgnoreMediumNodes, + SMESH_ProxyMesh::Ptr theProxyMesh) { int nbEdges = theEdges.size(); - myEdge.resize( nbEdges ); - myC2d.resize( nbEdges ); - myFirst.resize( nbEdges ); - myLast.resize( nbEdges ); - myNormPar.resize( nbEdges ); - myLength = 0; - myNbPonits = myNbSegments = 0; - myMesh = theMesh; + myEdge.resize ( nbEdges ); + myEdgeID.resize ( nbEdges ); + myC2d.resize ( nbEdges ); + myC3dAdaptor.resize( nbEdges ); + myFirst.resize ( nbEdges ); + myLast.resize ( nbEdges ); + myNormPar.resize ( nbEdges ); + myEdgeLength.resize( nbEdges ); + myIsUniform.resize ( nbEdges, true ); + myLength = 0; + myNbPonits = myNbSegments = 0; + myProxyMesh = theProxyMesh; myMissingVertexNodes = false; - myIgnoreMediumNodes = theIgnoreMediumNodes; + myIgnoreMediumNodes = theIgnoreMediumNodes; + myDefaultPnt2d = gp_Pnt2d( 1e+100, 1e+100 ); + if ( !myProxyMesh ) myProxyMesh.reset( new SMESH_ProxyMesh( *theMesh )); if ( nbEdges == 0 ) return; - SMESHDS_Mesh* meshDS = theMesh->GetMeshDS(); - vector len( nbEdges ); + SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS(); int nbDegen = 0; list::iterator edge = theEdges.begin(); + TopoDS_Iterator vExp; for ( int index = 0; edge != theEdges.end(); ++index, ++edge ) { - int i = theIsForward ? index : nbEdges - index - 1; - len[i] = SMESH_Algo::EdgeLength( *edge ); - if ( len[i] < DBL_MIN ) nbDegen++; - myLength += len[i]; + int i = theIsForward ? index : nbEdges-index-1; + myEdgeLength[i] = SMESH_Algo::EdgeLength( *edge ); + if ( myEdgeLength[i] < DBL_MIN ) nbDegen++; + myLength += myEdgeLength[i]; myEdge[i] = *edge; + myEdgeID[i] = meshDS->ShapeToIndex( *edge ); if ( !theIsForward ) myEdge[i].Reverse(); if ( theFace.IsNull() ) @@ -118,7 +131,7 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, if ( myEdge[i].Orientation() == TopAbs_REVERSED ) std::swap( myFirst[i], myLast[i] ); - if ( SMESHDS_SubMesh* sm = meshDS->MeshElements( *edge )) { + if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( *edge )) { int nbN = sm->NbNodes(); if ( theIgnoreMediumNodes ) { SMDS_ElemIteratorPtr elemIt = sm->GetElements(); @@ -128,16 +141,48 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, myNbPonits += nbN; myNbSegments += sm->NbElements(); } - if ( SMESH_Algo::VertexNode( TopExp::FirstVertex( *edge, 1), meshDS )) + + // TopExp::FirstVertex() and TopExp::LastVertex() return NULL from INTERNAL edge + vExp.Initialize( *edge ); + if ( vExp.Value().Orientation() == TopAbs_REVERSED ) vExp.Next(); + if ( SMESH_Algo::VertexNode( TopoDS::Vertex( vExp.Value()), meshDS )) myNbPonits += 1; // for the first end else myMissingVertexNodes = true; - } - if ( SMESH_Algo::VertexNode( TopExp::LastVertex( theEdges.back(), 1), meshDS )) - myNbPonits++; // for the last end - else - myMissingVertexNodes = true; + // check if the edge has a non-uniform parametrization (issue 0020705) + if ( !myC2d[i].IsNull() && myEdgeLength[i] > DBL_MIN) + { + Geom2dAdaptor_Curve A2dC( myC2d[i], + std::min( myFirst[i], myLast[i] ), + std::max( myFirst[i], myLast[i] )); + double p2 = myFirst[i]+(myLast[i]-myFirst[i])/2., p4 = myFirst[i]+(myLast[i]-myFirst[i])/4.; + double d2 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p2 ); + double d4 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p4 ); + //cout<<"len = "<GetSubMesh( myEdge[iE] )) + { + vector< pair< double, const SMDS_MeshNode*> > u2nodeVec; + u2nodeVec.reserve( sm->NbNodes() ); + SMDS_NodeIteratorPtr nItr = sm->GetNodes(); + double paramSize = myLast[iE] - myFirst[iE]; + double r = myNormPar[iE] - prevNormPar; + helper.SetSubShape( myEdge[iE] ); + helper.ToFixNodeParameters( true ); + if ( !myIsUniform[iE] ) + while ( nItr->more() ) + { + const SMDS_MeshNode* node = nItr->next(); + if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge )) + continue; + double u = helper.GetNodeU( myEdge[iE], node, 0, ¶mOK ); + double aLenU = GCPnts_AbscissaPoint::Length + ( const_cast( myC3dAdaptor[iE]), myFirst[iE], u ); + if ( myEdgeLength[iE] < aLenU ) // nonregression test "3D_mesh_NETGEN/G6" + { + u2nodeVec.clear(); + break; + } + double normPar = prevNormPar + r*aLenU/myEdgeLength[iE]; + u2nodeVec.push_back( make_pair( normPar, node )); + } + nItr = sm->GetNodes(); + if ( u2nodeVec.empty() ) + while ( nItr->more() ) + { + const SMDS_MeshNode* node = nItr->next(); + if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge )) + continue; + double u = helper.GetNodeU( myEdge[iE], node, 0, ¶mOK ); + + // paramSize is signed so orientation is taken into account + double normPar = prevNormPar + r * ( u - myFirst[iE] ) / paramSize; + u2nodeVec.push_back( make_pair( normPar, node )); + } + for ( size_t j = 0; j < u2nodeVec.size(); ++j ) + u2node.insert( u2node.end(), u2nodeVec[j] ); + } + + // Put 2nd vertex node for a last edge + if ( iE+1 == myEdge.size() ) { + node = SMESH_Algo::VertexNode( VV[1], meshDS ); if ( !node ) { MESSAGE(" NO NODE on VERTEX" ); return myPoints; } - u2node.insert( make_pair( 1., node )); + u2node.insert( u2node.end(), make_pair( 1., node )); } + } // loop on myEdge's - // put internal nodes - SMESHDS_SubMesh* sm = meshDS->MeshElements( myEdge[i] ); - if ( !sm ) continue; - SMDS_NodeIteratorPtr nItr = sm->GetNodes(); - double paramSize = myLast[i] - myFirst[i], r = myNormPar[i] - prevNormPar; - while ( nItr->more() ) { - const SMDS_MeshNode* node = nItr->next(); - if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge )) - continue; - const SMDS_EdgePosition* epos = - static_cast(node->GetPosition().get()); - double u = epos->GetUParameter(); - // paramSize is signed so orientation is taken into account - double normPar = prevNormPar + r * ( u - myFirst[i] ) / paramSize; -#ifdef _DEBUG_ - if ( normPar > 1 || normPar < 0) { - dump("DEBUG"); - MESSAGE ( "WRONG normPar: "<& StdMeshers_FaceSide::GetUVPtStruct(bool isXConst, // fill array of UVPtStruct - vector* points = const_cast*>( &myPoints ); - points->resize( myNbPonits ); + UVPtStructVec& points = const_cast< UVPtStructVec& >( myPoints ); + points.resize( myNbPonits ); - int EdgeIndex = 0; - double prevNormPar = 0, paramSize = myNormPar[ EdgeIndex ]; + int iPt = 0; + double prevNormPar = 0, paramSize = myNormPar[ 0 ]; map< double, const SMDS_MeshNode*>::iterator u_node = u2node.begin(); - for (int i = 0 ; u_node != u2node.end(); ++u_node, ++i ) { - UVPtStruct & uvPt = (*points)[i]; - uvPt.node = u_node->second; - uvPt.x = uvPt.y = uvPt.normParam = u_node->first; - if ( isXConst ) uvPt.x = constValue; - else uvPt.y = constValue; - if ( myNormPar[ EdgeIndex ] < uvPt.normParam ) { - prevNormPar = myNormPar[ EdgeIndex ]; - ++EdgeIndex; -#ifdef _DEBUG_ - if ( EdgeIndex >= myEdge.size() ) { - dump("DEBUG"); - MESSAGE ( "WRONg EdgeIndex " << 1+EdgeIndex - << " myNormPar.size()="<MeshElements( myEdge[i] )) + { + SMDS_NodeIteratorPtr nItr = sm->GetNodes(); + double paramSize = myLast[i] - myFirst[i]; + double r = myNormPar[i] - prevNormPar; + helper.SetSubShape( myEdge[i] ); + helper.ToFixNodeParameters( true ); + while ( nItr->more() ) + { + const SMDS_MeshNode* node = nItr->next(); + if ( myIgnoreMediumNodes && SMESH_MeshEditor::IsMedium( node, SMDSAbs_Edge )) + continue; + double u = helper.GetNodeU( myEdge[i], node, 0, ¶mOK ); + + // paramSize is signed so orientation is taken into account + double normPar = prevNormPar + r * ( u - myFirst[i] ) / paramSize; + u2node.insert( u2node.end(), make_pair( normPar, node )); + } + } + + // Put 2nd vertex node for a last edge + if ( i+1 == myEdge.size() ) { + node = SMESH_Algo::VertexNode( VV[1], meshDS ); + if ( !node ) { + return resultNodes; + } + u2node.insert( u2node.end(), make_pair( 1., node )); + } + } + + // Fill the result vector + + if ( u2node.size() == myNbPonits ) + { + resultNodes.reserve( u2node.size() ); + map< double, const SMDS_MeshNode*>::iterator u2n = u2node.begin(); + for ( ; u2n != u2node.end(); ++u2n ) + resultNodes.push_back( u2n->second ); + } + } + else + { + resultNodes.resize( myPoints.size() ); + for ( size_t i = 0; i < myPoints.size(); ++i ) + resultNodes[i] = myPoints[i].node; + } + + return resultNodes; +} //================================================================================ /*! @@ -356,20 +676,173 @@ void StdMeshers_FaceSide::Reverse() int nbEdges = myEdge.size(); for ( int i = nbEdges-1; i >= 0; --i ) { std::swap( myFirst[i], myLast[i] ); - myEdge[i].Reverse(); + if ( !myEdge[i].IsNull() ) + myEdge[i].Reverse(); if ( i > 0 ) // at the first loop 1. is overwritten myNormPar[i] = 1 - myNormPar[i-1]; } if ( nbEdges > 1 ) { reverse( myEdge ); + reverse( myEdgeID ); reverse( myC2d ); + //reverse( myC3dAdaptor ); reverse( myFirst ); reverse( myLast ); reverse( myNormPar ); + reverse( myEdgeLength ); + reverse( myIsUniform ); + } + if ( nbEdges > 0 ) + { + myNormPar[nbEdges-1]=1.; + if ( !myEdge[0].IsNull() ) + { + for ( size_t i = 0; i < myEdge.size(); ++i ) + reverseProxySubmesh( myEdge[i] ); + myPoints.clear(); + myFalsePoints.clear(); + } + else + { + for ( size_t i = 0; i < myPoints.size(); ++i ) + { + UVPtStruct & uvPt = myPoints[i]; + uvPt.normParam = 1 - uvPt.normParam; + uvPt.x = 1 - uvPt.x; + uvPt.y = 1 - uvPt.y; + } + reverse( myPoints ); + + for ( size_t i = 0; i < myFalsePoints.size(); ++i ) + { + UVPtStruct & uvPt = myFalsePoints[i]; + uvPt.normParam = 1 - uvPt.normParam; + uvPt.x = 1 - uvPt.x; + uvPt.y = 1 - uvPt.y; + } + reverse( myFalsePoints ); + } + } + for ( size_t i = 0; i < myEdge.size(); ++i ) + { + if ( myEdge[i].IsNull() ) continue; // for a side on points only + double fp,lp; + Handle(Geom_Curve) C3d = BRep_Tool::Curve(myEdge[i],fp,lp); + if ( !C3d.IsNull() ) + myC3dAdaptor[i].Load( C3d, fp,lp ); + } +} + +//======================================================================= +//function : SetIgnoreMediumNodes +//purpose : Make ignore medium nodes +//======================================================================= + +void StdMeshers_FaceSide::SetIgnoreMediumNodes(bool toIgnore) +{ + if ( myIgnoreMediumNodes != toIgnore ) + { + myIgnoreMediumNodes = toIgnore; + + if ( !myPoints.empty() ) + { + UVPtStructVec newPoints; + newPoints.reserve( myPoints.size()/2 + 1 ); + for ( size_t i = 0; i < myPoints.size(); i += 2 ) + newPoints.push_back( myPoints[i] ); + + myPoints.swap( newPoints ); + } + else + { + NbPoints( /*update=*/true ); + } + } +} + +//======================================================================= +//function : NbPoints +//purpose : Return nb nodes on edges and vertices (+1 to be == GetUVPtStruct().size() ) +// Call it with update == true if mesh of this side can be recomputed +// since creation of this side +//======================================================================= + +int StdMeshers_FaceSide::NbPoints(const bool update) const +{ + if ( !myPoints.empty() ) + return myPoints.size(); + + // if ( !myFalsePoints.empty() ) + // return myFalsePoints.size(); + + if ( update && myEdge.size() > 0 ) + { + StdMeshers_FaceSide* me = (StdMeshers_FaceSide*) this; + me->myNbPonits = 0; + me->myNbSegments = 0; + me->myMissingVertexNodes = false; + + for ( int i = 0; i < NbEdges(); ++i ) + { + TopoDS_Vertex v1 = SMESH_MesherHelper::IthVertex( 0, myEdge[i] ); + if ( SMESH_Algo::VertexNode( v1, myProxyMesh->GetMeshDS() )) + me->myNbPonits += 1; // for the first end + else + me->myMissingVertexNodes = true; + + if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( Edge(i) )) { + int nbN = sm->NbNodes(); + if ( myIgnoreMediumNodes ) { + SMDS_ElemIteratorPtr elemIt = sm->GetElements(); + if ( elemIt->more() && elemIt->next()->IsQuadratic() ) + nbN -= sm->NbElements(); + } + me->myNbPonits += nbN; + me->myNbSegments += sm->NbElements(); + } + } + TopoDS_Vertex v1 = SMESH_MesherHelper::IthVertex( 1, Edge( NbEdges()-1 )); + if ( SMESH_Algo::VertexNode( v1, myProxyMesh->GetMeshDS() )) + me->myNbPonits++; // for the last end + else + me->myMissingVertexNodes = true; + } + return myNbPonits; +} + +//======================================================================= +//function : NbSegments +//purpose : Return nb edges +// Call it with update == true if mesh of this side can be recomputed +// since creation of this side +//======================================================================= + +int StdMeshers_FaceSide::NbSegments(const bool update) const +{ + return NbPoints( update ), myNbSegments; +} + +//================================================================================ +/*! + * \brief Reverse UVPtStructVec if a proxy sub-mesh of E + */ +//================================================================================ + +void StdMeshers_FaceSide::reverseProxySubmesh( const TopoDS_Edge& E ) +{ + if ( !myProxyMesh ) return; + if ( const SMESH_ProxyMesh::SubMesh* sm = myProxyMesh->GetProxySubMesh( E )) + { + UVPtStructVec& edgeUVPtStruct = (UVPtStructVec& ) sm->GetUVPtStructVec(); + for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i ) + { + UVPtStruct & uvPt = edgeUVPtStruct[i]; + uvPt.normParam = 1 - uvPt.normParam; + uvPt.x = 1 - uvPt.x; + uvPt.y = 1 - uvPt.y; + } + reverse( edgeUVPtStruct ); } - myNormPar[nbEdges-1]=1.; - myPoints.clear(); - myFalsePoints.clear(); } //================================================================================ @@ -443,14 +916,15 @@ BRepAdaptor_CompCurve* StdMeshers_FaceSide::GetCurve3d() const if ( myEdge.empty() ) return 0; -// if ( myEdge.size() == 1 ) -// return new BRepAdaptor_Curve( myEdge[0] ); - TopoDS_Wire aWire; BRep_Builder aBuilder; aBuilder.MakeWire(aWire); for ( int i=0; iValue( myFirst[i] * ( 1 - r ) + myLast[i] * r ); + + double par = myFirst[i] * ( 1 - r ) + myLast[i] * r; + + // check parametrization of curve + if( !myIsUniform[i] ) + { + double aLen3dU = r * myEdgeLength[i] * ( myFirst[i]>myLast[i] ? -1. : 1.); + GCPnts_AbscissaPoint AbPnt + ( const_cast( myC3dAdaptor[i]), aLen3dU, myFirst[i] ); + if( AbPnt.IsDone() ) { + par = AbPnt.Parameter(); + } + } + return myC2d[ i ]->Value(par); + + } + else if ( !myPoints.empty() ) + { + int i = U * double( myPoints.size()-1 ); + while ( i > 0 && myPoints[ i ].normParam > U ) + --i; + while ( i+1 < myPoints.size() && myPoints[ i+1 ].normParam < U ) + ++i; + double r = (( U - myPoints[ i ].normParam ) / + ( myPoints[ i+1 ].normParam - myPoints[ i ].normParam )); + return ( myPoints[ i ].UV() * ( 1 - r ) + + myPoints[ i+1 ].UV() * r ); } - return gp_Pnt2d( 1e+100, 1e+100 ); + return myDefaultPnt2d; +} + +//================================================================================ +/*! + * \brief Return XYZ by normalized parameter + * \param U - normalized parameter value + * \retval gp_Pnt - point + */ +//================================================================================ + +gp_Pnt StdMeshers_FaceSide::Value3d(double U) const +{ + int i = EdgeIndex( U ); + double prevU = i ? myNormPar[ i-1 ] : 0; + double r = ( U - prevU )/ ( myNormPar[ i ] - prevU ); + + double par = myFirst[i] * ( 1 - r ) + myLast[i] * r; + + // check parametrization of curve + if( !myIsUniform[i] ) + { + double aLen3dU = r * myEdgeLength[i] * ( myFirst[i]>myLast[i] ? -1. : 1.); + GCPnts_AbscissaPoint AbPnt + ( const_cast( myC3dAdaptor[i]), aLen3dU, myFirst[i] ); + if( AbPnt.IsDone() ) { + par = AbPnt.Parameter(); + } + } + return myC3dAdaptor[ i ].Value(par); } //================================================================================ @@ -479,52 +1008,105 @@ gp_Pnt2d StdMeshers_FaceSide::Value2d(double U) const */ //================================================================================ -TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace, - SMESH_Mesh & theMesh, - const bool theIgnoreMediumNodes, - TError & theError) +TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace, + SMESH_Mesh & theMesh, + const bool theIgnoreMediumNodes, + TError & theError, + SMESH_ProxyMesh::Ptr theProxyMesh) { - TopoDS_Vertex V1; - list< TopoDS_Edge > edges; + list< TopoDS_Edge > edges, internalEdges; list< int > nbEdgesInWires; - int nbWires = SMESH_Block::GetOrderedEdges (theFace, V1, edges, nbEdgesInWires); + int nbWires = SMESH_Block::GetOrderedEdges (theFace, edges, nbEdgesInWires); // split list of all edges into separate wires TSideVector wires( nbWires ); list< int >::iterator nbE = nbEdgesInWires.begin(); - list< TopoDS_Edge >::iterator from, to; - from = to = edges.begin(); - for ( int iW = 0; iW < nbWires; ++iW ) + list< TopoDS_Edge >::iterator from = edges.begin(), to = from; + for ( int iW = 0; iW < nbWires; ++iW, ++nbE ) { - std::advance( to, *nbE++ ); + std::advance( to, *nbE ); + if ( *nbE == 0 ) // Issue 0020676 + { + --nbWires; + --iW; + wires.resize( nbWires ); + continue; + } list< TopoDS_Edge > wireEdges( from, to ); // assure that there is a node on the first vertex // as StdMeshers_FaceSide::GetUVPtStruct() requires - while ( !SMESH_Algo::VertexNode( TopExp::FirstVertex( wireEdges.front(), true), - theMesh.GetMeshDS())) + if ( wireEdges.front().Orientation() != TopAbs_INTERNAL ) // Issue 0020676 { - wireEdges.splice(wireEdges.end(), wireEdges, - wireEdges.begin(), ++wireEdges.begin()); - if ( from->IsSame( wireEdges.front() )) { - theError = TError - ( new SMESH_ComputeError(COMPERR_BAD_INPUT_MESH,"No nodes on vertices")); - return TSideVector(0); + while ( !SMESH_Algo::VertexNode( TopExp::FirstVertex( wireEdges.front(), true), + theMesh.GetMeshDS())) + { + wireEdges.splice(wireEdges.end(), wireEdges, + wireEdges.begin(), ++wireEdges.begin()); + if ( from->IsSame( wireEdges.front() )) { + theError = TError + ( new SMESH_ComputeError(COMPERR_BAD_INPUT_MESH,"No nodes on vertices")); + return TSideVector(0); + } } } - // find out side orientation, which is important if there are several wires (PAL19080) - bool isForward = true; - if ( nbWires > 1 ) { - TopExp_Explorer e( theFace, TopAbs_EDGE ); - while ( ! e.Current().IsSame( wireEdges.back() )) - e.Next(); - isForward = ( e.Current().Orientation() == wireEdges.back().Orientation() ); + else if ( *nbE > 1 ) // Issue 0020676 (Face_pb_netgen.brep) - several internal edges in a wire + { + internalEdges.splice( internalEdges.end(), wireEdges, ++wireEdges.begin(), wireEdges.end()); } StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, wireEdges, &theMesh, - isForward, theIgnoreMediumNodes); + /*isForward=*/true, theIgnoreMediumNodes, + theProxyMesh ); wires[ iW ] = StdMeshers_FaceSidePtr( wire ); from = to; } + while ( !internalEdges.empty() ) + { + StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, internalEdges.back(), &theMesh, + /*isForward=*/true, theIgnoreMediumNodes, + theProxyMesh ); + wires.push_back( StdMeshers_FaceSidePtr( wire )); + internalEdges.pop_back(); + } return wires; } +//================================================================================ +/*! + * \brief Return 1st vertex of the i-the edge + */ +//================================================================================ + +TopoDS_Vertex StdMeshers_FaceSide::FirstVertex(int i) const +{ + TopoDS_Vertex v; + if ( i < NbEdges() ) + { + v = myEdge[i].Orientation() <= TopAbs_REVERSED ? // FORWARD || REVERSED + TopExp::FirstVertex( myEdge[i], 1 ) : + TopoDS::Vertex( TopoDS_Iterator( myEdge[i] ).Value() ); + } + return v; +} + +//================================================================================ +/*! + * \brief Return last vertex of the i-the edge + */ +//================================================================================ + +TopoDS_Vertex StdMeshers_FaceSide::LastVertex(int i) const +{ + TopoDS_Vertex v; + if ( i < NbEdges() ) + { + const TopoDS_Edge& edge = i<0 ? myEdge[ NbEdges() + i ] : myEdge[i]; + if ( edge.Orientation() <= TopAbs_REVERSED ) // FORWARD || REVERSED + v = TopExp::LastVertex( edge, 1 ); + else + for ( TopoDS_Iterator vIt( edge ); vIt.More(); vIt.Next() ) + v = TopoDS::Vertex( vIt.Value() ); + } + return v; +} +