mirror of
https://git.salome-platform.org/gitpub/modules/smesh.git
synced 2024-11-12 00:29:17 +05:00
22772: EDF 8916 SMESH: Issue with a quadrangle mesh
Consider edges on period boundary as seam ones
This commit is contained in:
parent
e16f6412db
commit
65efd98e77
@ -242,40 +242,44 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh)
|
|||||||
for ( TopExp_Explorer eF( aSh, TopAbs_FACE ); eF.More(); eF.Next() )
|
for ( TopExp_Explorer eF( aSh, TopAbs_FACE ); eF.More(); eF.Next() )
|
||||||
{
|
{
|
||||||
const TopoDS_Face& face = TopoDS::Face( eF.Current() );
|
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() ||
|
for (TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next())
|
||||||
// surface->IsUClosed() || surface->IsVClosed() )
|
|
||||||
{
|
{
|
||||||
//while ( surface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface )))
|
// look for a "seam" edge, actually an edge on period boundary
|
||||||
//surface = Handle(Geom_RectangularTrimmedSurface)::DownCast( surface )->BasisSurface();
|
const TopoDS_Edge& edge = TopoDS::Edge( exp.Current() );
|
||||||
|
if ( myParIndex )
|
||||||
for (TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next())
|
|
||||||
{
|
{
|
||||||
// look for a seam edge
|
bool isSeam = BRep_Tool::IsClosed( edge, face );
|
||||||
TopoDS_Edge edge = TopoDS::Edge( exp.Current() );
|
if ( !isSeam )
|
||||||
if ( BRep_Tool::IsClosed( edge, face )) {
|
{
|
||||||
// initialize myPar1, myPar2 and myParIndex
|
|
||||||
gp_Pnt2d uv1, uv2;
|
gp_Pnt2d uv1, uv2;
|
||||||
BRep_Tool::UVPoints( edge, face, 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);
|
isSeam = ( Abs( uv1.Coord(1) - myPar1[0] ) < Precision::PConfusion() ||
|
||||||
edge.Reverse();
|
Abs( uv1.Coord(1) - myPar2[0] ) < Precision::PConfusion() );
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
else {
|
else if ( dv < Precision::PConfusion() )
|
||||||
double v1 = uv1.Coord(2);
|
{
|
||||||
edge.Reverse();
|
isSeam = ( Abs( uv1.Coord(2) - myPar1[1] ) < Precision::PConfusion() ||
|
||||||
BRep_Tool::UVPoints( edge, face, uv1, uv2 );
|
Abs( uv1.Coord(2) - myPar2[1] ) < Precision::PConfusion() );
|
||||||
double v2 = uv1.Coord(2);
|
|
||||||
myParIndex |= V_periodic;
|
|
||||||
myPar1[1] = Min( v1, v2 );
|
|
||||||
myPar2[1] = Max( v1, v2 );
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if ( isSeam )
|
||||||
|
{
|
||||||
// store seam shape indices, negative if shape encounters twice
|
// store seam shape indices, negative if shape encounters twice
|
||||||
int edgeID = meshDS->ShapeToIndex( edge );
|
int edgeID = meshDS->ShapeToIndex( edge );
|
||||||
mySeamShapeIds.insert( IsSeamShape( edgeID ) ? -edgeID : edgeID );
|
mySeamShapeIds.insert( IsSeamShape( edgeID ) ? -edgeID : edgeID );
|
||||||
@ -284,27 +288,12 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh)
|
|||||||
mySeamShapeIds.insert( IsSeamShape( vertexID ) ? -vertexID : vertexID );
|
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 )
|
// look for a degenerated edge
|
||||||
{
|
if ( SMESH_Algo::isDegenerated( edge )) {
|
||||||
BRepAdaptor_Surface surf( face, false );
|
myDegenShapeIds.insert( meshDS->ShapeToIndex( edge ));
|
||||||
if ( surf.IsUPeriodic() || surf.IsUClosed() ) {
|
for ( TopExp_Explorer v( edge, TopAbs_VERTEX ); v.More(); v.Next() )
|
||||||
myParIndex |= U_periodic;
|
myDegenShapeIds.insert( meshDS->ShapeToIndex( v.Current() ));
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2541,6 +2530,75 @@ bool SMESH_MesherHelper::IsStructured( SMESH_subMesh* faceSM )
|
|||||||
return true;
|
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
|
* \brief Find out elements orientation on a geometrical face
|
||||||
|
@ -117,6 +117,11 @@ class SMESH_EXPORT SMESH_MesherHelper
|
|||||||
*/
|
*/
|
||||||
static bool IsStructured( SMESH_subMesh* faceSM );
|
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
|
* \brief Returns true if given node is medium
|
||||||
* \param n - node to check
|
* \param n - node to check
|
||||||
|
@ -920,79 +920,24 @@ namespace {
|
|||||||
//================================================================================
|
//================================================================================
|
||||||
|
|
||||||
void fixDistortedFaces( SMESH_MesherHelper& helper,
|
void fixDistortedFaces( SMESH_MesherHelper& helper,
|
||||||
TSideVector& )
|
TSideVector& tgtWires )
|
||||||
{
|
{
|
||||||
// Detect bad faces
|
SMESH_subMesh* faceSM = helper.GetMesh()->GetSubMesh( helper.GetSubShape() );
|
||||||
|
|
||||||
bool haveBadFaces = false;
|
if ( helper.IsDistorted2D( faceSM ))
|
||||||
|
|
||||||
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 )
|
|
||||||
{
|
{
|
||||||
SMESH_MeshEditor editor( helper.GetMesh() );
|
SMESH_MeshEditor editor( helper.GetMesh() );
|
||||||
|
SMESHDS_SubMesh* smDS = faceSM->GetSubMeshDS();
|
||||||
|
const TopoDS_Face& F = TopoDS::Face( faceSM->GetSubShape() );
|
||||||
|
|
||||||
TIDSortedElemSet faces;
|
TIDSortedElemSet faces;
|
||||||
|
SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
|
||||||
for ( faceIt = smDS->GetElements(); faceIt->more(); )
|
for ( faceIt = smDS->GetElements(); faceIt->more(); )
|
||||||
faces.insert( faces.end(), faceIt->next() );
|
faces.insert( faces.end(), faceIt->next() );
|
||||||
|
|
||||||
// choose smoothing algo
|
// choose smoothing algo
|
||||||
//SMESH_MeshEditor:: SmoothMethod algo = SMESH_MeshEditor::CENTROIDAL;
|
//SMESH_MeshEditor:: SmoothMethod algo = SMESH_MeshEditor::CENTROIDAL;
|
||||||
bool isConcaveBoundary = false;
|
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 )
|
for ( size_t iW = 0; iW < tgtWires.size() && !isConcaveBoundary; ++iW )
|
||||||
{
|
{
|
||||||
TopoDS_Edge prevEdge = tgtWires[iW]->Edge( tgtWires[iW]->NbEdges() - 1 );
|
TopoDS_Edge prevEdge = tgtWires[iW]->Edge( tgtWires[iW]->NbEdges() - 1 );
|
||||||
|
Loading…
Reference in New Issue
Block a user