From 65efd98e778a48079e58b3c73b85608d48bcb40a Mon Sep 17 00:00:00 2001 From: eap Date: Fri, 10 Oct 2014 20:59:37 +0400 Subject: [PATCH] 22772: EDF 8916 SMESH: Issue with a quadrangle mesh Consider edges on period boundary as seam ones --- src/SMESH/SMESH_MesherHelper.cxx | 150 ++++++++++++++------ src/SMESH/SMESH_MesherHelper.hxx | 5 + src/StdMeshers/StdMeshers_Projection_2D.cxx | 67 +-------- 3 files changed, 115 insertions(+), 107 deletions(-) diff --git a/src/SMESH/SMESH_MesherHelper.cxx b/src/SMESH/SMESH_MesherHelper.cxx index e89a75f56..4449efbce 100644 --- a/src/SMESH/SMESH_MesherHelper.cxx +++ b/src/SMESH/SMESH_MesherHelper.cxx @@ -242,40 +242,44 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh) for ( TopExp_Explorer eF( aSh, TopAbs_FACE ); eF.More(); eF.Next() ) { const TopoDS_Face& face = TopoDS::Face( eF.Current() ); + BRepAdaptor_Surface surf( face, false ); + if ( surf.IsUPeriodic() || surf.IsUClosed() ) { + myParIndex |= U_periodic; + myPar1[0] = surf.FirstUParameter(); + myPar2[0] = surf.LastUParameter(); + } + if ( surf.IsVPeriodic() || surf.IsVClosed() ) { + myParIndex |= V_periodic; + myPar1[1] = surf.FirstVParameter(); + myPar2[1] = surf.LastVParameter(); + } - // if ( surface->IsUPeriodic() || surface->IsVPeriodic() || - // surface->IsUClosed() || surface->IsVClosed() ) + for (TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next()) { - //while ( surface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface ))) - //surface = Handle(Geom_RectangularTrimmedSurface)::DownCast( surface )->BasisSurface(); - - for (TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next()) + // look for a "seam" edge, actually an edge on period boundary + const TopoDS_Edge& edge = TopoDS::Edge( exp.Current() ); + if ( myParIndex ) { - // look for a seam edge - TopoDS_Edge edge = TopoDS::Edge( exp.Current() ); - if ( BRep_Tool::IsClosed( edge, face )) { - // initialize myPar1, myPar2 and myParIndex + bool isSeam = BRep_Tool::IsClosed( edge, face ); + if ( !isSeam ) + { gp_Pnt2d uv1, uv2; BRep_Tool::UVPoints( edge, face, uv1, uv2 ); - if ( Abs( uv1.Coord(1) - uv2.Coord(1) ) < Abs( uv1.Coord(2) - uv2.Coord(2) )) + const double du = Abs( uv1.Coord(1) - uv2.Coord(1) ); + const double dv = Abs( uv1.Coord(2) - uv2.Coord(2) ); + if ( du < Precision::PConfusion() ) { - double u1 = uv1.Coord(1); - edge.Reverse(); - BRep_Tool::UVPoints( edge, face, uv1, uv2 ); - double u2 = uv1.Coord(1); - myParIndex |= U_periodic; - myPar1[0] = Min( u1, u2 ); - myPar2[0] = Max( u1, u2 ); + isSeam = ( Abs( uv1.Coord(1) - myPar1[0] ) < Precision::PConfusion() || + Abs( uv1.Coord(1) - myPar2[0] ) < Precision::PConfusion() ); } - else { - double v1 = uv1.Coord(2); - edge.Reverse(); - BRep_Tool::UVPoints( edge, face, uv1, uv2 ); - double v2 = uv1.Coord(2); - myParIndex |= V_periodic; - myPar1[1] = Min( v1, v2 ); - myPar2[1] = Max( v1, v2 ); + else if ( dv < Precision::PConfusion() ) + { + isSeam = ( Abs( uv1.Coord(2) - myPar1[1] ) < Precision::PConfusion() || + Abs( uv1.Coord(2) - myPar2[1] ) < Precision::PConfusion() ); } + } + if ( isSeam ) + { // store seam shape indices, negative if shape encounters twice int edgeID = meshDS->ShapeToIndex( edge ); mySeamShapeIds.insert( IsSeamShape( edgeID ) ? -edgeID : edgeID ); @@ -284,27 +288,12 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh) mySeamShapeIds.insert( IsSeamShape( vertexID ) ? -vertexID : vertexID ); } } - - // look for a degenerated edge - if ( SMESH_Algo::isDegenerated( edge )) { - myDegenShapeIds.insert( meshDS->ShapeToIndex( edge )); - for ( TopExp_Explorer v( edge, TopAbs_VERTEX ); v.More(); v.Next() ) - myDegenShapeIds.insert( meshDS->ShapeToIndex( v.Current() )); - } } - if ( !myDegenShapeIds.empty() && !myParIndex ) - { - BRepAdaptor_Surface surf( face, false ); - if ( surf.IsUPeriodic() || surf.IsUClosed() ) { - myParIndex |= U_periodic; - myPar1[0] = surf.FirstUParameter(); - myPar2[0] = surf.LastUParameter(); - } - else if ( surf.IsVPeriodic() || surf.IsVClosed() ) { - myParIndex |= V_periodic; - myPar1[1] = surf.FirstVParameter(); - myPar2[1] = surf.LastVParameter(); - } + // look for a degenerated edge + if ( SMESH_Algo::isDegenerated( edge )) { + myDegenShapeIds.insert( meshDS->ShapeToIndex( edge )); + for ( TopExp_Explorer v( edge, TopAbs_VERTEX ); v.More(); v.Next() ) + myDegenShapeIds.insert( meshDS->ShapeToIndex( v.Current() )); } } } @@ -2541,6 +2530,75 @@ bool SMESH_MesherHelper::IsStructured( SMESH_subMesh* faceSM ) return true; } +//======================================================================= +//function : IsDistorted2D +//purpose : Return true if 2D mesh on FACE is ditorted +//======================================================================= + +bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM ) +{ + if ( !faceSM || faceSM->GetSubShape().ShapeType() != TopAbs_FACE ) + return false; + + bool haveBadFaces = false; + + SMESH_MesherHelper helper( *faceSM->GetFather() ); + helper.SetSubShape( faceSM->GetSubShape() ); + + const TopoDS_Face& F = TopoDS::Face( faceSM->GetSubShape() ); + SMESHDS_SubMesh* smDS = helper.GetMeshDS()->MeshElements( F ); + if ( !smDS || smDS->NbElements() == 0 ) return false; + + SMDS_ElemIteratorPtr faceIt = smDS->GetElements(); + double prevArea2D = 0; + vector< const SMDS_MeshNode* > nodes; + vector< gp_XY > uv; + while ( faceIt->more() && !haveBadFaces ) + { + const SMDS_MeshElement* face = faceIt->next(); + + // get nodes + nodes.resize( face->NbCornerNodes() ); + SMDS_MeshElement::iterator n = face->begin_nodes(); + for ( size_t i = 0; i < nodes.size(); ++n, ++i ) + nodes[ i ] = *n; + + // avoid elems on degenarate shapes as UV on them can be wrong + if ( helper.HasDegeneratedEdges() ) + { + bool isOnDegen = false; + for ( size_t i = 0; ( i < nodes.size() && !isOnDegen ); ++i ) + isOnDegen = helper.IsDegenShape( nodes[ i ]->getshapeId() ); + if ( isOnDegen ) + continue; + } + // prepare to getting UVs + const SMDS_MeshNode* inFaceNode = 0; + if ( helper.HasSeam() ) + for ( size_t i = 0; ( i < nodes.size() && !inFaceNode ); ++i ) + if ( !helper.IsSeamShape( nodes[ i ]->getshapeId() )) + inFaceNode = nodes[ i ]; + + // get UVs + uv.resize( nodes.size() ); + for ( size_t i = 0; i < nodes.size(); ++i ) + uv[ i ] = helper.GetNodeUV( F, nodes[ i ], inFaceNode ); + + // compare orientation of triangles + for ( int iT = 0, nbT = nodes.size()-2; iT < nbT; ++iT ) + { + gp_XY v1 = uv[ iT+1 ] - uv[ 0 ]; + gp_XY v2 = uv[ iT+2 ] - uv[ 0 ]; + double area2D = v2 ^ v1; + if (( haveBadFaces = ( area2D * prevArea2D < 0 ))) + break; + prevArea2D = area2D; + } + } + + return haveBadFaces; +} + //================================================================================ /*! * \brief Find out elements orientation on a geometrical face diff --git a/src/SMESH/SMESH_MesherHelper.hxx b/src/SMESH/SMESH_MesherHelper.hxx index 3e67d1364..430e6f374 100644 --- a/src/SMESH/SMESH_MesherHelper.hxx +++ b/src/SMESH/SMESH_MesherHelper.hxx @@ -117,6 +117,11 @@ class SMESH_EXPORT SMESH_MesherHelper */ static bool IsStructured( SMESH_subMesh* faceSM ); + /*! + * \brief Return true if 2D mesh on FACE is distored + */ + static bool IsDistorted2D( SMESH_subMesh* faceSM ); + /*! * \brief Returns true if given node is medium * \param n - node to check diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx index 78c16a4eb..9db5ee4c3 100644 --- a/src/StdMeshers/StdMeshers_Projection_2D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_2D.cxx @@ -920,79 +920,24 @@ namespace { //================================================================================ void fixDistortedFaces( SMESH_MesherHelper& helper, - TSideVector& ) + TSideVector& tgtWires ) { - // Detect bad faces + SMESH_subMesh* faceSM = helper.GetMesh()->GetSubMesh( helper.GetSubShape() ); - bool haveBadFaces = false; - - const TopoDS_Face& F = TopoDS::Face( helper.GetSubShape() ); - SMESHDS_SubMesh* smDS = helper.GetMeshDS()->MeshElements( F ); - if ( !smDS || smDS->NbElements() == 0 ) return; - - SMDS_ElemIteratorPtr faceIt = smDS->GetElements(); - double prevArea2D = 0; - vector< const SMDS_MeshNode* > nodes; - vector< gp_XY > uv; - while ( faceIt->more() && !haveBadFaces ) - { - const SMDS_MeshElement* face = faceIt->next(); - - // get nodes - nodes.resize( face->NbCornerNodes() ); - SMDS_MeshElement::iterator n = face->begin_nodes(); - for ( size_t i = 0; i < nodes.size(); ++n, ++i ) - nodes[ i ] = *n; - - // avoid elems on degenarate shapes as UV on them can be wrong - if ( helper.HasDegeneratedEdges() ) - { - bool isOnDegen = false; - for ( size_t i = 0; ( i < nodes.size() && !isOnDegen ); ++i ) - isOnDegen = helper.IsDegenShape( nodes[ i ]->getshapeId() ); - if ( isOnDegen ) - continue; - } - // prepare to getting UVs - const SMDS_MeshNode* inFaceNode = 0; - if ( helper.HasSeam() ) - for ( size_t i = 0; ( i < nodes.size() && !inFaceNode ); ++i ) - if ( !helper.IsSeamShape( nodes[ i ]->getshapeId() )) - inFaceNode = nodes[ i ]; - - // get UVs - uv.resize( nodes.size() ); - for ( size_t i = 0; i < nodes.size(); ++i ) - uv[ i ] = helper.GetNodeUV( F, nodes[ i ], inFaceNode ); - - // compare orientation of triangles - for ( int iT = 0, nbT = nodes.size()-2; iT < nbT; ++iT ) - { - gp_XY v1 = uv[ iT+1 ] - uv[ 0 ]; - gp_XY v2 = uv[ iT+2 ] - uv[ 0 ]; - double area2D = v2 ^ v1; - if (( haveBadFaces = ( area2D * prevArea2D < 0 ))) - break; - prevArea2D = area2D; - } - } - - // Fix faces - - if ( haveBadFaces ) + if ( helper.IsDistorted2D( faceSM )) { SMESH_MeshEditor editor( helper.GetMesh() ); + SMESHDS_SubMesh* smDS = faceSM->GetSubMeshDS(); + const TopoDS_Face& F = TopoDS::Face( faceSM->GetSubShape() ); TIDSortedElemSet faces; + SMDS_ElemIteratorPtr faceIt = smDS->GetElements(); for ( faceIt = smDS->GetElements(); faceIt->more(); ) faces.insert( faces.end(), faceIt->next() ); // choose smoothing algo //SMESH_MeshEditor:: SmoothMethod algo = SMESH_MeshEditor::CENTROIDAL; bool isConcaveBoundary = false; - TError err; - TSideVector tgtWires = - StdMeshers_FaceSide::GetFaceWires( F, *helper.GetMesh(),/*skipMediumNodes=*/0, err); for ( size_t iW = 0; iW < tgtWires.size() && !isConcaveBoundary; ++iW ) { TopoDS_Edge prevEdge = tgtWires[iW]->Edge( tgtWires[iW]->NbEdges() - 1 );