mirror of
https://git.salome-platform.org/gitpub/modules/smesh.git
synced 2025-01-13 18:20:34 +05:00
0021422: EDF 1963 SMESH: Viscous layer algorithm fails in some cases
1) fix getting node UV on a periodic FACE 2) enable inflation along a seam edge 3) force shrinking on a FACE at relatively thin layers
This commit is contained in:
parent
2daf574775
commit
02024c6589
@ -225,12 +225,13 @@ namespace VISCOUS
|
|||||||
return determinant > 1e-100;
|
return determinant > 1e-100;
|
||||||
}
|
}
|
||||||
bool IsForward(const gp_XY& tgtUV,
|
bool IsForward(const gp_XY& tgtUV,
|
||||||
|
const SMDS_MeshNode* smoothedNode,
|
||||||
const TopoDS_Face& face,
|
const TopoDS_Face& face,
|
||||||
SMESH_MesherHelper& helper,
|
SMESH_MesherHelper& helper,
|
||||||
const double refSign) const
|
const double refSign) const
|
||||||
{
|
{
|
||||||
gp_XY prevUV = helper.GetNodeUV( face, _nPrev );
|
gp_XY prevUV = helper.GetNodeUV( face, _nPrev, smoothedNode );
|
||||||
gp_XY nextUV = helper.GetNodeUV( face, _nNext );
|
gp_XY nextUV = helper.GetNodeUV( face, _nNext, smoothedNode );
|
||||||
gp_Vec2d v1( tgtUV, prevUV ), v2( tgtUV, nextUV );
|
gp_Vec2d v1( tgtUV, prevUV ), v2( tgtUV, nextUV );
|
||||||
double d = v1 ^ v2;
|
double d = v1 ^ v2;
|
||||||
return d*refSign > 1e-100;
|
return d*refSign > 1e-100;
|
||||||
@ -1104,7 +1105,25 @@ bool _ViscousBuilder::findFacesWithLayers()
|
|||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
_sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, facesWOL[0] )); break;
|
helper.SetSubShape( facesWOL[0] );
|
||||||
|
if ( helper.IsRealSeam( vInd )) // inflate along a seam edge?
|
||||||
|
{
|
||||||
|
TopoDS_Shape seamEdge;
|
||||||
|
PShapeIteratorPtr eIt = helper.GetAncestors(vertex, *_mesh, TopAbs_EDGE);
|
||||||
|
while ( eIt->more() && seamEdge.IsNull() )
|
||||||
|
{
|
||||||
|
const TopoDS_Shape* e = eIt->next();
|
||||||
|
if ( helper.IsRealSeam( *e ) )
|
||||||
|
seamEdge = *e;
|
||||||
|
}
|
||||||
|
if ( !seamEdge.IsNull() )
|
||||||
|
{
|
||||||
|
_sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, seamEdge ));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_sdVec[i]._shrinkShape2Shape.insert( make_pair( vInd, facesWOL[0] ));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
@ -2053,10 +2072,12 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
|
|||||||
TGeomID sInd = data._edges[ iBeg ]->_nodes[0]->getshapeId();
|
TGeomID sInd = data._edges[ iBeg ]->_nodes[0]->getshapeId();
|
||||||
|
|
||||||
if ( data._edges[ iBeg ]->IsOnEdge() )
|
if ( data._edges[ iBeg ]->IsOnEdge() )
|
||||||
{ // try a simple solution on an analytic EDGE
|
|
||||||
if ( !smoothAnalyticEdge( data, iBeg, iEnd, surface, F, helper ))
|
|
||||||
{
|
{
|
||||||
dumpFunction(SMESH_Comment("smooth")<<data._index << "_Ed"<<sInd <<"_InfStep"<<nbSteps);
|
dumpFunction(SMESH_Comment("smooth")<<data._index << "_Ed"<<sInd <<"_InfStep"<<nbSteps);
|
||||||
|
|
||||||
|
// try a simple solution on an analytic EDGE
|
||||||
|
if ( !smoothAnalyticEdge( data, iBeg, iEnd, surface, F, helper ))
|
||||||
|
{
|
||||||
// smooth on EDGE's
|
// smooth on EDGE's
|
||||||
int step = 0;
|
int step = 0;
|
||||||
do {
|
do {
|
||||||
@ -2069,9 +2090,8 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
|
|||||||
}
|
}
|
||||||
while ( moved && step++ < 5 );
|
while ( moved && step++ < 5 );
|
||||||
//cout << " NB STEPS: " << step << endl;
|
//cout << " NB STEPS: " << step << endl;
|
||||||
|
|
||||||
dumpFunctionEnd();
|
|
||||||
}
|
}
|
||||||
|
dumpFunctionEnd();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2327,21 +2347,35 @@ bool _ViscousBuilder::smoothAnalyticEdge( _SolidData& data,
|
|||||||
data._edges[i]->_pos.back() = newPos;
|
data._edges[i]->_pos.back() = newPos;
|
||||||
SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( data._edges[i]->_nodes.back() );
|
SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( data._edges[i]->_nodes.back() );
|
||||||
tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
|
tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
|
||||||
|
dumpMove( tgtNode );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gp_XY uv0 = helper.GetNodeUV( F, data._edges[iFrom]->_2neibors->_nodes[0]);
|
gp_XY uv0 = helper.GetNodeUV( F, data._edges[iFrom]->_2neibors->_nodes[0]);
|
||||||
gp_XY uv1 = helper.GetNodeUV( F, data._edges[iTo-1]->_2neibors->_nodes[1]);
|
gp_XY uv1 = helper.GetNodeUV( F, data._edges[iTo-1]->_2neibors->_nodes[1]);
|
||||||
|
if ( data._edges[iFrom]->_2neibors->_nodes[0] ==
|
||||||
|
data._edges[iTo-1]->_2neibors->_nodes[1] ) // closed edge
|
||||||
|
{
|
||||||
|
int iPeriodic = helper.GetPeriodicIndex();
|
||||||
|
if ( iPeriodic == 1 || iPeriodic == 2 )
|
||||||
|
{
|
||||||
|
uv1.SetCoord( iPeriodic, helper.GetOtherParam( uv1.Coord( iPeriodic )));
|
||||||
|
if ( uv0.Coord( iPeriodic ) > uv1.Coord( iPeriodic ))
|
||||||
|
std::swap( uv0, uv1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const gp_XY rangeUV = uv1 - uv0;
|
||||||
for ( int i = iFrom; i < iTo; ++i )
|
for ( int i = iFrom; i < iTo; ++i )
|
||||||
{
|
{
|
||||||
double r = len[i-iFrom] / len.back();
|
double r = len[i-iFrom] / len.back();
|
||||||
gp_XY newUV = uv0 * ( 1. - r ) + uv1 * r;
|
gp_XY newUV = uv0 + r * rangeUV;
|
||||||
data._edges[i]->_pos.back().SetCoord( newUV.X(), newUV.Y(), 0 );
|
data._edges[i]->_pos.back().SetCoord( newUV.X(), newUV.Y(), 0 );
|
||||||
|
|
||||||
gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() );
|
gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() );
|
||||||
SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( data._edges[i]->_nodes.back() );
|
SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( data._edges[i]->_nodes.back() );
|
||||||
tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
|
tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
|
||||||
|
dumpMove( tgtNode );
|
||||||
|
|
||||||
SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
|
SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
|
||||||
pos->SetUParameter( newUV.X() );
|
pos->SetUParameter( newUV.X() );
|
||||||
@ -2388,6 +2422,7 @@ bool _ViscousBuilder::smoothAnalyticEdge( _SolidData& data,
|
|||||||
gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() );
|
gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() );
|
||||||
SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( data._edges[i]->_nodes.back() );
|
SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( data._edges[i]->_nodes.back() );
|
||||||
tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
|
tgtNode->setXYZ( newPos.X(), newPos.Y(), newPos.Z() );
|
||||||
|
dumpMove( tgtNode );
|
||||||
|
|
||||||
SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
|
SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
|
||||||
pos->SetUParameter( newUV.X() );
|
pos->SetUParameter( newUV.X() );
|
||||||
@ -3329,7 +3364,6 @@ bool _ViscousBuilder::shrink()
|
|||||||
_SolidData& data = *f2sd->second;
|
_SolidData& data = *f2sd->second;
|
||||||
TNode2Edge& n2eMap = data._n2eMap;
|
TNode2Edge& n2eMap = data._n2eMap;
|
||||||
const TopoDS_Face& F = TopoDS::Face( getMeshDS()->IndexToShape( f2sd->first ));
|
const TopoDS_Face& F = TopoDS::Face( getMeshDS()->IndexToShape( f2sd->first ));
|
||||||
const bool reverse = ( data._reversedFaceIds.count( f2sd->first ));
|
|
||||||
|
|
||||||
Handle(Geom_Surface) surface = BRep_Tool::Surface(F);
|
Handle(Geom_Surface) surface = BRep_Tool::Surface(F);
|
||||||
|
|
||||||
@ -3357,12 +3391,15 @@ bool _ViscousBuilder::shrink()
|
|||||||
// Find out face orientation
|
// Find out face orientation
|
||||||
double refSign = 1;
|
double refSign = 1;
|
||||||
const set<TGeomID> ignoreShapes;
|
const set<TGeomID> ignoreShapes;
|
||||||
|
bool isOkUV;
|
||||||
if ( !smoothNodes.empty() )
|
if ( !smoothNodes.empty() )
|
||||||
{
|
{
|
||||||
gp_XY uv = helper.GetNodeUV( F, smoothNodes[0] );
|
|
||||||
vector<_Simplex> simplices;
|
vector<_Simplex> simplices;
|
||||||
getSimplices( smoothNodes[0], simplices, ignoreShapes );
|
getSimplices( smoothNodes[0], simplices, ignoreShapes );
|
||||||
if ( simplices[0].IsForward(uv, F, helper,refSign) != (!reverse))
|
helper.GetNodeUV( F, simplices[0]._nPrev, 0, &isOkUV ); // fix UV of silpmex nodes
|
||||||
|
helper.GetNodeUV( F, simplices[0]._nNext, 0, &isOkUV );
|
||||||
|
gp_XY uv = helper.GetNodeUV( F, smoothNodes[0], 0, &isOkUV );
|
||||||
|
if ( !simplices[0].IsForward(uv, smoothNodes[0], F, helper,refSign) )
|
||||||
refSign = -1;
|
refSign = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3411,7 +3448,6 @@ bool _ViscousBuilder::shrink()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create _SmoothNode's on face F
|
// Create _SmoothNode's on face F
|
||||||
bool isOkUV;
|
|
||||||
vector< _SmoothNode > nodesToSmooth( smoothNodes.size() );
|
vector< _SmoothNode > nodesToSmooth( smoothNodes.size() );
|
||||||
{
|
{
|
||||||
dumpFunction(SMESH_Comment("beforeShrinkFace")<<f2sd->first); // debug
|
dumpFunction(SMESH_Comment("beforeShrinkFace")<<f2sd->first); // debug
|
||||||
@ -3465,8 +3501,6 @@ bool _ViscousBuilder::shrink()
|
|||||||
shrinked |= lEdges[i]->SetNewLength2d( surface,F,helper );
|
shrinked |= lEdges[i]->SetNewLength2d( surface,F,helper );
|
||||||
}
|
}
|
||||||
dumpFunctionEnd();
|
dumpFunctionEnd();
|
||||||
if ( !shrinked )
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Move nodes on EDGE's
|
// Move nodes on EDGE's
|
||||||
set< _Shrinker1D* >::iterator shr = eShri1D.begin();
|
set< _Shrinker1D* >::iterator shr = eShri1D.begin();
|
||||||
@ -3498,6 +3532,9 @@ bool _ViscousBuilder::shrink()
|
|||||||
}
|
}
|
||||||
if ( badNb > 0 )
|
if ( badNb > 0 )
|
||||||
return error(SMESH_Comment("Can't shrink 2D mesh on face ") << f2sd->first );
|
return error(SMESH_Comment("Can't shrink 2D mesh on face ") << f2sd->first );
|
||||||
|
|
||||||
|
if ( !shrinked )
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// No wrongly shaped faces remain; final smooth. Set node XYZ.
|
// No wrongly shaped faces remain; final smooth. Set node XYZ.
|
||||||
// First, find out a needed quality of smoothing (high for quadrangles only)
|
// First, find out a needed quality of smoothing (high for quadrangles only)
|
||||||
@ -3517,7 +3554,7 @@ bool _ViscousBuilder::shrink()
|
|||||||
highQuality = ( *nbNodesSet.begin() == 4 );
|
highQuality = ( *nbNodesSet.begin() == 4 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ( int st = highQuality ? 8 : 3; st; --st )
|
for ( int st = highQuality ? 10 : 3; st; --st )
|
||||||
{
|
{
|
||||||
dumpFunction(SMESH_Comment("shrinkFace")<<f2sd->first<<"_st"<<++smooStep); // debug
|
dumpFunction(SMESH_Comment("shrinkFace")<<f2sd->first<<"_st"<<++smooStep); // debug
|
||||||
for ( unsigned i = 0; i < nodesToSmooth.size(); ++i )
|
for ( unsigned i = 0; i < nodesToSmooth.size(); ++i )
|
||||||
@ -3527,7 +3564,7 @@ bool _ViscousBuilder::shrink()
|
|||||||
// Set an event listener to clear FACE sub-mesh together with SOLID sub-mesh
|
// Set an event listener to clear FACE sub-mesh together with SOLID sub-mesh
|
||||||
_SrinkShapeListener::ToClearSubMeshWithSolid( sm, data._solid );
|
_SrinkShapeListener::ToClearSubMeshWithSolid( sm, data._solid );
|
||||||
|
|
||||||
}// loop on FACES to srink mesh on
|
} // loop on FACES to srink mesh on
|
||||||
|
|
||||||
|
|
||||||
// Replace source nodes by target nodes in shrinked mesh edges
|
// Replace source nodes by target nodes in shrinked mesh edges
|
||||||
@ -3822,18 +3859,18 @@ bool _SmoothNode::Smooth(int& badNb,
|
|||||||
// compute new UV for the node
|
// compute new UV for the node
|
||||||
gp_XY newPos (0,0);
|
gp_XY newPos (0,0);
|
||||||
for ( unsigned i = 0; i < _simplices.size(); ++i )
|
for ( unsigned i = 0; i < _simplices.size(); ++i )
|
||||||
newPos += helper.GetNodeUV( face, _simplices[i]._nPrev );
|
newPos += helper.GetNodeUV( face, _simplices[i]._nPrev, _node );
|
||||||
newPos /= _simplices.size();
|
newPos /= _simplices.size();
|
||||||
|
|
||||||
// count quality metrics (orientation) of triangles around the node
|
// count quality metrics (orientation) of triangles around the node
|
||||||
int nbOkBefore = 0;
|
int nbOkBefore = 0;
|
||||||
gp_XY tgtUV = helper.GetNodeUV( face, _node );
|
gp_XY tgtUV = helper.GetNodeUV( face, _node );
|
||||||
for ( unsigned i = 0; i < _simplices.size(); ++i )
|
for ( unsigned i = 0; i < _simplices.size(); ++i )
|
||||||
nbOkBefore += _simplices[i].IsForward( tgtUV, face, helper, refSign );
|
nbOkBefore += _simplices[i].IsForward( tgtUV, _node, face, helper, refSign );
|
||||||
|
|
||||||
int nbOkAfter = 0;
|
int nbOkAfter = 0;
|
||||||
for ( unsigned i = 0; i < _simplices.size(); ++i )
|
for ( unsigned i = 0; i < _simplices.size(); ++i )
|
||||||
nbOkAfter += _simplices[i].IsForward( newPos, face, helper, refSign );
|
nbOkAfter += _simplices[i].IsForward( newPos, _node, face, helper, refSign );
|
||||||
|
|
||||||
if ( nbOkAfter < nbOkBefore )
|
if ( nbOkAfter < nbOkBefore )
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
Reference in New Issue
Block a user