X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_FaceSide.cxx;h=b0d36a59ccb5bd25c9f7aa58a6a9006e4b6e2605;hp=3fd0305636b9a9c3b8208d154a12aca4055c249d;hb=70c33e5f83059e589c93b7818348e3c003eaec4d;hpb=0e017d4c87d670c01e72c0b4858ffcb9e47aa9ba diff --git a/src/StdMeshers/StdMeshers_FaceSide.cxx b/src/StdMeshers/StdMeshers_FaceSide.cxx index 3fd030563..b0d36a59c 100644 --- a/src/StdMeshers/StdMeshers_FaceSide.cxx +++ b/src/StdMeshers/StdMeshers_FaceSide.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2016 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 @@ -56,12 +56,14 @@ #include "utilities.h" +using namespace std; + //================================================================================ /*! * \brief Constructor of a side of one edge * \param theFace - the face * \param theEdge - the edge - */ + */ //================================================================================ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, @@ -69,11 +71,15 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, SMESH_Mesh* theMesh, const bool theIsForward, const bool theIgnoreMediumNodes, + SMESH_MesherHelper* theFaceHelper, SMESH_ProxyMesh::Ptr theProxyMesh) { - list edges(1,theEdge); - *this = StdMeshers_FaceSide( theFace, edges, theMesh, theIsForward, - theIgnoreMediumNodes, theProxyMesh ); + std::list edges(1,theEdge); + StdMeshers_FaceSide tmp( theFace, edges, theMesh, theIsForward, + theIgnoreMediumNodes, theFaceHelper, theProxyMesh ); + *this = tmp; + + tmp.myHelper = NULL; } //================================================================================ @@ -82,12 +88,13 @@ 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, - SMESH_ProxyMesh::Ptr theProxyMesh) +StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, + const std::list& theEdges, + SMESH_Mesh* theMesh, + const bool theIsForward, + const bool theIgnoreMediumNodes, + SMESH_MesherHelper* theFaceHelper, + SMESH_ProxyMesh::Ptr theProxyMesh) { int nbEdges = theEdges.size(); myEdge.resize ( nbEdges ); @@ -106,14 +113,19 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, myMissingVertexNodes = false; myIgnoreMediumNodes = theIgnoreMediumNodes; myDefaultPnt2d = gp_Pnt2d( 1e+100, 1e+100 ); + myHelper = NULL; if ( !myProxyMesh ) myProxyMesh.reset( new SMESH_ProxyMesh( *theMesh )); + if ( theFaceHelper && theFaceHelper->GetSubShape() == myFace ) + { + myHelper = new SMESH_MesherHelper( * myProxyMesh->GetMesh() ); + myHelper->CopySubShapeInfo( *theFaceHelper ); + } if ( nbEdges == 0 ) return; SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS(); int nbDegen = 0; - list::iterator edge = theEdges.begin(); - TopoDS_Iterator vExp; + std::list::const_iterator edge = theEdges.begin(); for ( int index = 0; edge != theEdges.end(); ++index, ++edge ) { int i = theIsForward ? index : nbEdges-index-1; @@ -143,18 +155,25 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, double 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 = "<& StdMeshers_FaceSide::GetUVPtStruct(bool isXConst, if ( u2nodeVec.empty() ) for ( size_t i = 0; i < nodes.size(); ++i ) { - double u = helper.GetNodeU( myEdge[iE], nodes[i], 0, ¶mOK ); + double u = eHelper.GetNodeU( myEdge[iE], nodes[i], 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, nodes[i] )); @@ -402,31 +451,40 @@ const vector& StdMeshers_FaceSide::GetUVPtStruct(bool isXConst, } } // loop on myEdge's - if ( u2node.empty() ) return myPoints; - // Add 2nd VERTEX node for a last EDGE + if ( !proxySubMesh.back() ) { + if ( u2node.empty() ) return myPoints; + const SMDS_MeshNode* node; - if ( IsClosed() ) + if ( IsClosed() && !proxySubMesh[0] ) node = u2node.begin()->second; else { node = VertexNode( iE ); - while ( !node && iE > 0 ) - node = VertexNode( --iE ); - if ( !node ) - return myPoints; + if ( myProxyMesh->GetMesh()->HasModificationsToDiscard() ) + while ( !node && iE > 1 ) // check intermediate VERTEXes + node = VertexNode( --iE ); + } + if ( node ) + { + if ( u2node.rbegin()->second == node && + !fHelper.IsRealSeam ( node->getshapeId() ) && + !fHelper.IsDegenShape( node->getshapeId() )) + u2node.erase( --u2node.end() ); + + u2node.insert( u2node.end(), make_pair( 1., node )); } - if ( u2node.rbegin()->second == node ) - u2node.erase( --u2node.end() ); - u2node.insert( u2node.end(), make_pair( 1., node )); } - if ( u2node.size() + nbProxyNodes != myNbPonits && - u2node.size() + nbProxyNodes != NbPoints( /*update=*/true )) + if ((int) u2node.size() + nbProxyNodes != myNbPonits && + (int) u2node.size() + nbProxyNodes != NbPoints( /*update=*/true )) + { + return myPoints; + } + if (( u2node.size() > 0 ) && + ( u2node.begin()->first < 0 || u2node.rbegin()->first > 1 )) { - MESSAGE("Wrong node parameters on edges, u2node.size():" - <& StdMeshers_FaceSide::GetUVPtStruct(bool isXConst, if ( proxySubMesh[ iE ] ) // copy data from a proxy sub-mesh { const UVPtStructVec& edgeUVPtStruct = proxySubMesh[iE]->GetUVPtStructVec(); - std::copy( edgeUVPtStruct.begin(), edgeUVPtStruct.end(), & points[iPt] ); + UVPtStruct* pointsPtr = & points[iPt]; + std::copy( edgeUVPtStruct.begin(), edgeUVPtStruct.end(), pointsPtr ); // check orientation double du1 = edgeUVPtStruct.back().param - edgeUVPtStruct[0].param; double du2 = myLast[iE] - myFirst[iE]; if ( du1 * du2 < 0 ) { - std::reverse( & points[iPt], & points[iPt + edgeUVPtStruct.size()]); + std::reverse( pointsPtr, pointsPtr + edgeUVPtStruct.size()); for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i ) - points[iPt+i].normParam = 1. - points[iPt+i].normParam; + pointsPtr[i].normParam = 1. - pointsPtr[i].normParam; } // update normalized params if ( myEdge.size() > 1 ) { - for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i, ++iPt ) + for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i ) { - UVPtStruct & uvPt = points[iPt]; + UVPtStruct & uvPt = pointsPtr[i]; uvPt.normParam = prevNormPar + uvPt.normParam * paramSize; uvPt.x = uvPt.y = uvPt.normParam; } - --iPt; // to point to the 1st VERTEX of the next EDGE + iPt += edgeUVPtStruct.size() - 1; // to point to the 1st VERTEX of the next EDGE + } + // update UV on a seam EDGE + if ( fHelper.IsRealSeam( myEdgeID[ iE ])) + { + // check if points lye on the EDGE + const UVPtStruct& pm = edgeUVPtStruct[ edgeUVPtStruct.size()/2 ]; + gp_Pnt pNode = SMESH_TNodeXYZ( pm.node ); + gp_Pnt pCurv = myC3dAdaptor[ iE ].Value( pm.param ); + double tol = BRep_Tool::Tolerance( myEdge[ iE ]) * 10; + bool isPointOnEdge = ( pNode.SquareDistance( pCurv ) < tol * tol ); + if ( isPointOnEdge ) + for ( size_t i = 0; i < edgeUVPtStruct.size(); ++i ) + pointsPtr[i].SetUV( myC2d[ iE ]->Value( pointsPtr[i].param ).XY() ); } } else @@ -469,7 +541,7 @@ const vector& StdMeshers_FaceSide::GetUVPtStruct(bool isXConst, for ( ; u_node != u2node.end(); ++u_node, ++iPt ) { if ( myNormPar[ iE ]-eps < u_node->first ) - break; // u_node is at VERTEX of the next EDGE + break; // u_node is at VERTEX of the next EDGE UVPtStruct & uvPt = points[iPt]; uvPt.node = u_node->second; @@ -507,9 +579,9 @@ const vector& StdMeshers_FaceSide::GetUVPtStruct(bool isXConst, // set if ( isXConst ) - for ( iPt = 0; iPt < points.size(); ++iPt ) points[ iPt ].x = constValue; + for ( iPt = 0; iPt < (int)points.size(); ++iPt ) points[ iPt ].x = constValue; else - for ( iPt = 0; iPt < points.size(); ++iPt ) points[ iPt ].y = constValue; + for ( iPt = 0; iPt < (int)points.size(); ++iPt ) points[ iPt ].y = constValue; } // if ( myPoints.empty()) @@ -528,8 +600,8 @@ const vector& StdMeshers_FaceSide::SimulateUVPtStruct(int nbSeg, bool isXConst, double constValue) const { - if ( myFalsePoints.empty() ) { - + if ( myFalsePoints.empty() ) + { if ( NbEdges() == 0 ) return myFalsePoints; vector* points = const_cast*>( &myFalsePoints ); @@ -537,28 +609,29 @@ const vector& StdMeshers_FaceSide::SimulateUVPtStruct(int nbSeg, int EdgeIndex = 0; double prevNormPar = 0, paramSize = myNormPar[ EdgeIndex ]; - for (int i = 0 ; i < myFalsePoints.size(); ++i ) { + gp_Pnt2d p; + for ( size_t i = 0 ; i < myFalsePoints.size(); ++i ) + { double normPar = double(i) / double(nbSeg); UVPtStruct & uvPt = (*points)[i]; uvPt.node = 0; uvPt.x = uvPt.y = uvPt.param = uvPt.normParam = normPar; if ( isXConst ) uvPt.x = constValue; else uvPt.y = constValue; - if ( myNormPar[ EdgeIndex ] < normPar ) { + if ( myNormPar[ EdgeIndex ] < normPar ) + { prevNormPar = myNormPar[ EdgeIndex ]; ++EdgeIndex; paramSize = myNormPar[ EdgeIndex ] - prevNormPar; } double r = ( normPar - prevNormPar )/ paramSize; uvPt.param = myFirst[EdgeIndex] * ( 1 - r ) + myLast[EdgeIndex] * r; - if ( !myC2d[ EdgeIndex ].IsNull() ) { - gp_Pnt2d p = myC2d[ EdgeIndex ]->Value( uvPt.param ); - uvPt.u = p.X(); - uvPt.v = p.Y(); - } - else { - uvPt.u = uvPt.v = 1e+100; - } + if ( !myC2d[ EdgeIndex ].IsNull() ) + p = myC2d[ EdgeIndex ]->Value( uvPt.param ); + else + p = Value2d( normPar ); + uvPt.u = p.X(); + uvPt.v = p.Y(); } } return myFalsePoints; @@ -576,15 +649,16 @@ std::vector StdMeshers_FaceSide::GetOrderedNodes(int theEd { if ( NbEdges() == 0 ) return resultNodes; - SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS(); - SMESH_MesherHelper helper(*myProxyMesh->GetMesh()); + //SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS(); + SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() ); + SMESH_MesherHelper& fHelper = * FaceHelper(); bool paramOK = true; // Sort nodes of all edges putting them into a map - map< double, const SMDS_MeshNode*> u2node; - vector nodes; - set vertexNodes; + map< double, const SMDS_MeshNode*> u2node; + vector nodes; + set vertexNodes; int iE = 0, iEnd = myEdge.size(); if ( theEdgeInd >= 0 ) { @@ -607,7 +681,9 @@ std::vector StdMeshers_FaceSide::GetOrderedNodes(int theEd // Add 1st vertex node of a current EDGE const SMDS_MeshNode* node = VertexNode( iE ); if ( node ) { // nodes on internal vertices may be missing - if ( vertexNodes.insert( node ).second ) + if ( vertexNodes.insert( node ).second || + fHelper.IsRealSeam ( node->getshapeId() ) || + fHelper.IsDegenShape( node->getshapeId() )) u2node.insert( make_pair( prevNormPar, node )); } else if ( iE == 0 ) @@ -633,11 +709,11 @@ std::vector StdMeshers_FaceSide::GetOrderedNodes(int theEd { double paramSize = myLast[iE] - myFirst[iE]; double r = myNormPar[iE] - prevNormPar; - helper.SetSubShape( myEdge[iE] ); - helper.ToFixNodeParameters( true ); + eHelper.SetSubShape( myEdge[iE] ); + eHelper.ToFixNodeParameters( true ); for ( size_t i = 0; i < nodes.size(); ++i ) { - double u = helper.GetNodeU( myEdge[iE], nodes[i], 0, ¶mOK ); + double u = eHelper.GetNodeU( myEdge[iE], nodes[i], 0, ¶mOK ); // paramSize is signed so orientation is taken into account double normPar = prevNormPar + r * ( u - myFirst[iE] ) / paramSize; u2node.insert( u2node.end(), make_pair( normPar, nodes[i] )); @@ -661,20 +737,26 @@ std::vector StdMeshers_FaceSide::GetOrderedNodes(int theEd if ( !node ) return resultNodes; } - if ( u2node.rbegin()->second == node ) + if ( u2node.rbegin()->second == node && + !fHelper.IsRealSeam ( node->getshapeId() ) && + !fHelper.IsDegenShape( node->getshapeId() )) u2node.erase( --u2node.end() ); + u2node.insert( u2node.end(), make_pair( 1., node )); } // Fill the result vector - if ( u2node.size() == myNbPonits ) + if ( theEdgeInd < 0 && + (int) u2node.size() != myNbPonits && + (int) u2node.size() != NbPoints( /*update=*/true )) { - resultNodes.reserve( u2node.size() ); - map< double, const SMDS_MeshNode*>::iterator u2n = u2node.begin(); - for ( ; u2n != u2node.end(); ++u2n ) - resultNodes.push_back( u2n->second ); + u2node.clear(); } + resultNodes.reserve( u2node.size() ); + map< double, const SMDS_MeshNode*>::iterator u2n = u2node.begin(); + for ( ; u2n != u2node.end(); ++u2n ) + resultNodes.push_back( u2n->second ); } else { @@ -708,16 +790,15 @@ bool StdMeshers_FaceSide::GetEdgeNodes(size_t i, if ( inlude1stVertex ) { - const SMDS_MeshNode* n0 = VertexNode( i ); - if ( !n0 ) return false; - nodes.push_back( n0 ); + if ( const SMDS_MeshNode* n0 = VertexNode( i )) + nodes.push_back( n0 ); } if ( sm && ( sm->NbElements() > 0 || sm->NbNodes() > 0 )) { if ( mesh->HasModificationsToDiscard() ) // check nb of nodes on the EDGE sub-mesh { - int iQuad = sm->GetElements()->next()->IsQuadratic(); + int iQuad = sm->NbElements() ? sm->GetElements()->next()->IsQuadratic() : 0; int nbExpect = sm->NbElements() - 1 + iQuad * sm->NbElements(); if ( nbExpect != sm->NbNodes() ) // some nodes are moved from the EDGE by MergeNodes() { @@ -765,9 +846,8 @@ bool StdMeshers_FaceSide::GetEdgeNodes(size_t i, if ( inludeLastVertex ) { - const SMDS_MeshNode* n1 = VertexNode( i+1 ); - if ( !n1 ) return false; - nodes.push_back( n1 ); + if ( const SMDS_MeshNode* n1 = VertexNode( i+1 )) + nodes.push_back( n1 ); } return true; } @@ -796,7 +876,7 @@ const SMDS_MeshNode* StdMeshers_FaceSide::VertexNode(std::size_t i, bool* isMove n = SMESH_Algo::VertexNode( V, sm, myProxyMesh->GetMesh(), /*checkV=*/false ); if (( !n ) && - (( i > 0 && i < NbEdges() ) || IsClosed() )) + (( i > 0 && (int) i < NbEdges() ) || IsClosed() )) { iE = SMESH_MesherHelper::WrapIndex( int(i)-1, NbEdges() ); sm = myProxyMesh->GetMeshDS()->MeshElements( myEdgeID[ iE ]); @@ -944,27 +1024,43 @@ int StdMeshers_FaceSide::NbPoints(const bool update) const me->myNbSegments = 0; me->myMissingVertexNodes = false; + vector nodes; for ( int i = 0; i < NbEdges(); ++i ) { - if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( Edge(i) )) { - int nbN = sm->NbNodes(); - if ( sm->NbElements() > 0 ) { - nbN = sm->NbElements() - 1; // nodes can be moved to other shapes by MergeNodes() - if ( !myIgnoreMediumNodes && - sm->GetElements()->next()->IsQuadratic() ) - nbN += sm->NbElements(); + if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( Edge(i) )) + { + if ( sm->NbNodes() == sm->NbElements()-1 || sm->NbElements() == 0 ) + { + me->myNbPonits += sm->NbNodes(); + if ( myIgnoreMediumNodes && sm->IsQuadratic() ) + me->myNbPonits -= sm->NbElements(); + } + else // nodes can be moved to other shapes by MergeNodes() + { + nodes.clear(); + GetEdgeNodes( i, nodes, /*v1=*/false, /*v2=*/false ); + me->myNbPonits += nodes.size(); } - me->myNbPonits += nbN; me->myNbSegments += sm->NbElements(); } } + SMESH_MesherHelper* helper = FaceHelper(); + std::set< const SMDS_MeshNode* > vNodes; - for ( int i = 0; i <= NbEdges(); ++i ) + const int nbV = NbEdges() + !IsClosed(); + for ( int i = 0; i < nbV; ++i ) if ( const SMDS_MeshNode* n = VertexNode( i )) - vNodes.insert( n ); + { + if ( !vNodes.insert( n ).second && + ( helper->IsRealSeam ( n->getshapeId() ) || + helper->IsDegenShape( n->getshapeId() ))) + me->myNbPonits++; + } else + { me->myMissingVertexNodes = true; + } me->myNbPonits += vNodes.size(); if ( IsClosed() ) @@ -1020,7 +1116,7 @@ void StdMeshers_FaceSide::dump(const char* msg) const if (msg) MESSAGE ( std::endl << msg ); MESSAGE_BEGIN ("NB EDGES: "<< myEdge.size() ); MESSAGE_ADD ( "nbPoints: "<()<() - << " V2: " << TopExp::LastVertex( myEdge[i], 1).TShape().operator->() ); + << " V2: " << TopExp::LastVertex( myEdge[i], 1).TShape().operator->() ); } MESSAGE_ADD ( "\tC2d: "); - + if (myC2d[i].IsNull()) { MESSAGE_ADD ( "NULL" ); } else { MESSAGE_ADD ( myC2d[i].operator->() ); } - + MESSAGE_ADD ( "\tF: "< 0 && myPoints[ i ].normParam > U ) --i; - while ( i+1 < myPoints.size() && myPoints[ i+1 ].normParam < U ) + while ( i+1 < (int)myPoints.size() && myPoints[ i+1 ].normParam < U ) ++i; double r = (( U - myPoints[ i ].normParam ) / ( myPoints[ i+1 ].normParam - myPoints[ i ].normParam )); @@ -1155,7 +1251,7 @@ gp_Pnt StdMeshers_FaceSide::Value3d(double U) const // check parametrization of curve if( !myIsUniform[i] ) { - double aLen3dU = r * myEdgeLength[i] * ( myFirst[i]>myLast[i] ? -1. : 1.); + double aLen3dU = r * myEdgeLength[i] * ( myFirst[i] > myLast[i] ? -1. : 1. ); GCPnts_AbscissaPoint AbPnt ( const_cast( myC3dAdaptor[i]), aLen3dU, myFirst[i] ); if( AbPnt.IsDone() ) { @@ -1175,9 +1271,14 @@ TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace, SMESH_Mesh & theMesh, const bool theIgnoreMediumNodes, TError & theError, + SMESH_MesherHelper* theFaceHelper, SMESH_ProxyMesh::Ptr theProxyMesh, const bool theCheckVertexNodes) { + SMESH_MesherHelper helper( theMesh ); + if ( theFaceHelper && theFaceHelper->GetSubShape() == theFace ) + helper.CopySubShapeInfo( *theFaceHelper ); + list< TopoDS_Edge > edges, internalEdges; list< int > nbEdgesInWires; int nbWires = SMESH_Block::GetOrderedEdges (theFace, edges, nbEdgesInWires); @@ -1221,7 +1322,7 @@ TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace, StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, wireEdges, &theMesh, /*isForward=*/true, theIgnoreMediumNodes, - theProxyMesh ); + &helper, theProxyMesh ); wires[ iW ] = StdMeshers_FaceSidePtr( wire ); from = to; } @@ -1229,7 +1330,7 @@ TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace, { StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, internalEdges.back(), &theMesh, /*isForward=*/true, theIgnoreMediumNodes, - theProxyMesh ); + &helper, theProxyMesh ); wires.push_back( StdMeshers_FaceSidePtr( wire )); internalEdges.pop_back(); } @@ -1285,3 +1386,20 @@ bool StdMeshers_FaceSide::IsClosed() const { return myEdge.empty() ? false : FirstVertex().IsSame( LastVertex() ); } + +//================================================================================ +/*! + * \brief Return a helper initialized with the FACE + */ +//================================================================================ + +SMESH_MesherHelper* StdMeshers_FaceSide::FaceHelper() const +{ + StdMeshers_FaceSide* me = const_cast< StdMeshers_FaceSide* >( this ); + if ( !myHelper && myProxyMesh ) + { + me->myHelper = new SMESH_MesherHelper( *myProxyMesh->GetMesh() ); + me->myHelper->SetSubShape( myFace ); + } + return me->myHelper; +}