X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_FaceSide.cxx;h=37bc6c346792d2ccbb0e37dae0ed57c9e389019c;hp=87af665b6af086270441b6ae5b2c3345bf2e1cdc;hb=20c126bc220757c06b5576f71ed6f34ae85e3e40;hpb=b6fe67a04f6b63b1d1b09c333ca140fa2be79ff8 diff --git a/src/StdMeshers/StdMeshers_FaceSide.cxx b/src/StdMeshers/StdMeshers_FaceSide.cxx index 87af665b6..37bc6c346 100644 --- a/src/StdMeshers/StdMeshers_FaceSide.cxx +++ b/src/StdMeshers/StdMeshers_FaceSide.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2012 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 @@ -62,14 +62,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 ); } //================================================================================ @@ -80,38 +82,40 @@ 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 ); - myEdgeID.resize( nbEdges ); - myC2d.resize( nbEdges ); + myEdge.resize ( nbEdges ); + myEdgeID.resize ( nbEdges ); + myC2d.resize ( nbEdges ); myC3dAdaptor.resize( nbEdges ); - myFirst.resize( nbEdges ); - myLast.resize( nbEdges ); - myNormPar.resize( nbEdges ); + myFirst.resize ( nbEdges ); + myLast.resize ( nbEdges ); + myNormPar.resize ( nbEdges ); myEdgeLength.resize( nbEdges ); - myIsUniform.resize( nbEdges, true ); - myLength = 0; - myNbPonits = myNbSegments = 0; - myMesh = theMesh; + myIsUniform.resize ( nbEdges, true ); + myLength = 0; + myNbPonits = myNbSegments = 0; + myProxyMesh = theProxyMesh; myMissingVertexNodes = false; - myIgnoreMediumNodes = theIgnoreMediumNodes; - myDefaultPnt2d = gp_Pnt2d( 1e+100, 1e+100 ); + 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(); + 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; + int i = theIsForward ? index : nbEdges-index-1; myEdgeLength[i] = SMESH_Algo::EdgeLength( *edge ); if ( myEdgeLength[i] < DBL_MIN ) nbDegen++; myLength += myEdgeLength[i]; @@ -126,7 +130,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(); @@ -136,6 +140,7 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, myNbPonits += nbN; myNbSegments += sm->NbElements(); } + // TopExp::FirstVertex() and TopExp::LastVertex() return NULL from INTERNAL edge vExp.Initialize( *edge ); if ( vExp.Value().Orientation() == TopAbs_REVERSED ) vExp.Next(); @@ -144,7 +149,7 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, else myMissingVertexNodes = true; - // check if edge has non-uniform parametrization (issue 0020705) + // check if the edge has a non-uniform parametrization (issue 0020705) if ( !myC2d[i].IsNull() && myEdgeLength[i] > DBL_MIN) { Geom2dAdaptor_Curve A2dC( myC2d[i], @@ -155,15 +160,19 @@ StdMeshers_FaceSide::StdMeshers_FaceSide(const TopoDS_Face& theFace, double d4 = GCPnts_AbscissaPoint::Length( A2dC, myFirst[i], p4 ); //cout<<"len = "<MeshElements( myEdge[i] ); - if ( !sm ) continue; - vector< pair< double, const SMDS_MeshNode*> > u2nodeVec; - u2nodeVec.reserve( sm->NbNodes() ); - SMDS_NodeIteratorPtr nItr = sm->GetNodes(); - double paramSize = myLast[i] - myFirst[i]; - double r = myNormPar[i] - prevNormPar; - if ( !myIsUniform[i] ) - 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 ); - double aLenU = GCPnts_AbscissaPoint::Length - ( const_cast( myC3dAdaptor[i]), myFirst[i], u ); - if ( myEdgeLength[i] < aLenU ) // nonregression test "3D_mesh_NETGEN/G6" + if ( const SMESHDS_SubMesh* sm = myProxyMesh->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() ) { - u2nodeVec.clear(); - break; + 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 )); } - double normPar = prevNormPar + r*aLenU/myEdgeLength[i]; - 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[i], node, 0, ¶mOK ); - - // paramSize is signed so orientation is taken into account - double normPar = prevNormPar + r * ( u - myFirst[i] ) / paramSize; - u2nodeVec.push_back( make_pair( normPar, node )); - } - u2node.insert( u2nodeVec.begin(), u2nodeVec.end() ); + 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 ( i+1 == myEdge.size() ) { + 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 )); } - } - if ( u2node.size() != myNbPonits ) { + } // loop on myEdge's + + if ( u2node.size() + nbProxyNodes != myNbPonits && + u2node.size() + nbProxyNodes != NbPoints( /*update=*/true )) + { MESSAGE("Wrong node parameters on edges, u2node.size():" <& 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; - const SMDS_EdgePosition* epos = - dynamic_cast(uvPt.node->GetPosition()); - if (( myNormPar[ EdgeIndex ] < uvPt.normParam ) || - ( epos && uvPt.node->getshapeId() != myEdgeID[ EdgeIndex ])) // for myMissingVertexNodes + for ( size_t iE = 0; iE < myEdge.size(); ++iE ) + { + if ( proxySubMesh[ iE ] ) // copy data from a proxy sub-mesh { - 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; +} //================================================================================ /*! @@ -448,7 +587,7 @@ void StdMeshers_FaceSide::Reverse() reverse( myEdge ); reverse( myEdgeID ); reverse( myC2d ); - reverse( myC3dAdaptor ); + //reverse( myC3dAdaptor ); reverse( myFirst ); reverse( myLast ); reverse( myNormPar ); @@ -460,6 +599,127 @@ void StdMeshers_FaceSide::Reverse() myNormPar[nbEdges-1]=1.; myPoints.clear(); myFalsePoints.clear(); + for ( size_t i = 0; i < myEdge.size(); ++i ) + reverseProxySubmesh( myEdge[i] ); + } + for ( size_t i = 0; i < myEdge.size(); ++i ) + { + 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 ); } } @@ -546,7 +806,6 @@ BRepAdaptor_CompCurve* StdMeshers_FaceSide::GetCurve3d() const return new BRepAdaptor_CompCurve( aWire ); } - //================================================================================ /*! * \brief Return 2D point by normalized parameter @@ -580,21 +839,50 @@ gp_Pnt2d StdMeshers_FaceSide::Value2d(double U) const 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); +} + //================================================================================ /*! * \brief Return wires of a face as StdMeshers_FaceSide's */ //================================================================================ -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, 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 ); @@ -633,14 +921,16 @@ TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace, } StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, wireEdges, &theMesh, - /*isForward=*/true, 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); + /*isForward=*/true, theIgnoreMediumNodes, + theProxyMesh ); wires.push_back( StdMeshers_FaceSidePtr( wire )); internalEdges.pop_back(); }