020461: EDF 1102 GHS3DPLUGIN: Bad detection of volumes with Ghs3d mesh

SMESH_MesherHelper:

-  void SetCheckNodePosition(bool toCheck) { myCheckNodePos = toCheck; }
   /*!
+   * \brief Check and fix node UV on a face
+   *  \retval bool - false if UV is bad and could not be fixed
+   */
+  bool CheckNodeUV(const TopoDS_Face&   F,
+                   const SMDS_MeshNode* n,
+                   gp_XY&               uv,
+                   const double         tol) const;

-  bool            myCheckNodePos;
+  std::set< int > myOkNodePosShapes;
This commit is contained in:
eap 2009-10-02 16:20:31 +00:00
parent 72ca340bff
commit 6510081be2
3 changed files with 107 additions and 77 deletions

View File

@ -7689,7 +7689,6 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
SMESH_subMesh* sm = smIt->next(); SMESH_subMesh* sm = smIt->next();
if ( SMESHDS_SubMesh *smDS = sm->GetSubMeshDS() ) { if ( SMESHDS_SubMesh *smDS = sm->GetSubMeshDS() ) {
aHelper.SetSubShape( sm->GetSubShape() ); aHelper.SetSubShape( sm->GetSubShape() );
if ( !theForce3d) aHelper.SetCheckNodePosition(true);
nbCheckedElems += convertElemToQuadratic(smDS, aHelper, theForce3d); nbCheckedElems += convertElemToQuadratic(smDS, aHelper, theForce3d);
} }
} }

View File

@ -71,7 +71,7 @@ namespace {
//================================================================================ //================================================================================
SMESH_MesherHelper::SMESH_MesherHelper(SMESH_Mesh& theMesh) SMESH_MesherHelper::SMESH_MesherHelper(SMESH_Mesh& theMesh)
: myMesh(&theMesh), myShapeID(0), myCreateQuadratic(false), myCheckNodePos(false) : myMesh(&theMesh), myShapeID(0), myCreateQuadratic(false)
{ {
mySetElemOnShape = ( ! myMesh->HasShapeToMesh() ); mySetElemOnShape = ( ! myMesh->HasShapeToMesh() );
} }
@ -326,9 +326,8 @@ gp_Pnt2d SMESH_MesherHelper::GetUVOnSeam( const gp_Pnt2d& uv1, const gp_Pnt2d& u
* \param F - the face * \param F - the face
* \param n - the node * \param n - the node
* \param n2 - a node of element being created located inside a face * \param n2 - a node of element being created located inside a face
* \param check - optional flag returing false if found UV are invalid
* \retval gp_XY - resulting UV * \retval gp_XY - resulting UV
*
* Auxilary function called form GetMediumNode()
*/ */
//======================================================================= //=======================================================================
@ -339,37 +338,14 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face& F,
{ {
gp_Pnt2d uv( 1e100, 1e100 ); gp_Pnt2d uv( 1e100, 1e100 );
const SMDS_PositionPtr Pos = n->GetPosition(); const SMDS_PositionPtr Pos = n->GetPosition();
bool uvOK = false;
if(Pos->GetTypeOfPosition()==SMDS_TOP_FACE) if(Pos->GetTypeOfPosition()==SMDS_TOP_FACE)
{ {
// node has position on face // node has position on face
const SMDS_FacePosition* fpos = const SMDS_FacePosition* fpos =
static_cast<const SMDS_FacePosition*>(n->GetPosition().get()); static_cast<const SMDS_FacePosition*>(n->GetPosition().get());
uv.SetCoord(fpos->GetUParameter(),fpos->GetVParameter()); uv.SetCoord(fpos->GetUParameter(),fpos->GetVParameter());
if ( check && *check ) uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), BRep_Tool::Tolerance( F ));
{
// check that uv is correct
TopLoc_Location loc;
Handle(Geom_Surface) surface = BRep_Tool::Surface( F,loc );
double tol = 2 * BRep_Tool::Tolerance( F );
gp_Pnt nodePnt = XYZ( n );
if ( !loc.IsIdentity() ) nodePnt.Transform( loc.Transformation().Inverted() );
if ( nodePnt.Distance( surface->Value( uv.X(), uv.Y() )) > tol ) {
// uv incorrect, project the node to surface
GeomAPI_ProjectPointOnSurf projector( nodePnt, surface, tol );
if ( !projector.IsDone() || projector.NbPoints() < 1 ) {
MESSAGE( "SMESH_MesherHelper::GetNodeUV() failed to project" )
return uv.XY();
}
Quantity_Parameter U,V;
projector.LowerDistanceParameters(U,V);
if ( nodePnt.Distance( surface->Value( U, V )) > tol )
MESSAGE( "SMESH_MesherHelper::GetNodeUV(), invalid projection" );
uv.SetCoord( U,V );
}
else if ( uv.XY().Modulus() > numeric_limits<double>::min() ) {
*check = false; // parameters are OK, do not check further more
}
}
} }
else if(Pos->GetTypeOfPosition()==SMDS_TOP_EDGE) else if(Pos->GetTypeOfPosition()==SMDS_TOP_EDGE)
{ {
@ -383,11 +359,15 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face& F,
double f, l; double f, l;
Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l); Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
uv = C2d->Value( epos->GetUParameter() ); uv = C2d->Value( epos->GetUParameter() );
uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), BRep_Tool::Tolerance( E ));
// for a node on a seam edge select one of UVs on 2 pcurves // for a node on a seam edge select one of UVs on 2 pcurves
if ( n2 && IsSeamShape( edgeID ) ) if ( n2 && IsSeamShape( edgeID ) )
{
uv = GetUVOnSeam( uv, GetNodeUV( F, n2, 0 )); uv = GetUVOnSeam( uv, GetNodeUV( F, n2, 0 ));
}
// adjust uv to period else
{ // adjust uv to period
TopLoc_Location loc; TopLoc_Location loc;
Handle(Geom_Surface) S = BRep_Tool::Surface(F,loc); Handle(Geom_Surface) S = BRep_Tool::Surface(F,loc);
Standard_Boolean isUPeriodic = S->IsUPeriodic(); Standard_Boolean isUPeriodic = S->IsUPeriodic();
@ -401,21 +381,21 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face& F,
uv.SetY( uv.Y() + ShapeAnalysis::AdjustToPeriod(uv.Y(),VF,VL)); uv.SetY( uv.Y() + ShapeAnalysis::AdjustToPeriod(uv.Y(),VF,VL));
} }
} }
}
else if(Pos->GetTypeOfPosition()==SMDS_TOP_VERTEX) else if(Pos->GetTypeOfPosition()==SMDS_TOP_VERTEX)
{ {
if ( int vertexID = n->GetPosition()->GetShapeId() ) { if ( int vertexID = n->GetPosition()->GetShapeId() ) {
bool ok = true;
const TopoDS_Vertex& V = TopoDS::Vertex(GetMeshDS()->IndexToShape(vertexID)); const TopoDS_Vertex& V = TopoDS::Vertex(GetMeshDS()->IndexToShape(vertexID));
try { try {
uv = BRep_Tool::Parameters( V, F ); uv = BRep_Tool::Parameters( V, F );
uvOK = true;
} }
catch (Standard_Failure& exc) { catch (Standard_Failure& exc) {
ok = false;
} }
if ( !ok ) { if ( !uvOK ) {
for ( TopExp_Explorer vert(F,TopAbs_VERTEX); !ok && vert.More(); vert.Next() ) for ( TopExp_Explorer vert(F,TopAbs_VERTEX); !uvOK && vert.More(); vert.Next() )
ok = ( V == vert.Current() ); uvOK = ( V == vert.Current() );
if ( !ok ) { if ( !uvOK ) {
#ifdef _DEBUG_ #ifdef _DEBUG_
MESSAGE ( "SMESH_MesherHelper::GetNodeUV(); Vertex " << vertexID MESSAGE ( "SMESH_MesherHelper::GetNodeUV(); Vertex " << vertexID
<< " not in face " << GetMeshDS()->ShapeToIndex( F ) ); << " not in face " << GetMeshDS()->ShapeToIndex( F ) );
@ -423,14 +403,14 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face& F,
// get UV of a vertex closest to the node // get UV of a vertex closest to the node
double dist = 1e100; double dist = 1e100;
gp_Pnt pn = XYZ( n ); gp_Pnt pn = XYZ( n );
for ( TopExp_Explorer vert(F,TopAbs_VERTEX); !ok && vert.More(); vert.Next() ) { for ( TopExp_Explorer vert(F,TopAbs_VERTEX); !uvOK && vert.More(); vert.Next() ) {
TopoDS_Vertex curV = TopoDS::Vertex( vert.Current() ); TopoDS_Vertex curV = TopoDS::Vertex( vert.Current() );
gp_Pnt p = BRep_Tool::Pnt( curV ); gp_Pnt p = BRep_Tool::Pnt( curV );
double curDist = p.SquareDistance( pn ); double curDist = p.SquareDistance( pn );
if ( curDist < dist ) { if ( curDist < dist ) {
dist = curDist; dist = curDist;
uv = BRep_Tool::Parameters( curV, F ); uv = BRep_Tool::Parameters( curV, F );
if ( dist < DBL_MIN ) break; uvOK = ( dist < DBL_MIN );
} }
} }
} }
@ -454,9 +434,58 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face& F,
uv = GetUVOnSeam( uv, GetNodeUV( F, n2, 0 )); uv = GetUVOnSeam( uv, GetNodeUV( F, n2, 0 ));
} }
} }
if ( check )
*check = uvOK;
return uv.XY(); return uv.XY();
} }
//=======================================================================
/*!
* \brief Check and fix node UV on a face
* \retval bool - false if UV is bad and could not be fixed
*/
//=======================================================================
bool SMESH_MesherHelper::CheckNodeUV(const TopoDS_Face& F,
const SMDS_MeshNode* n,
gp_XY& uv,
const double tol) const
{
if ( !myOkNodePosShapes.count( n->GetPosition()->GetShapeId() ))
{
// check that uv is correct
TopLoc_Location loc;
Handle(Geom_Surface) surface = BRep_Tool::Surface( F,loc );
gp_Pnt nodePnt = XYZ( n );
if ( !loc.IsIdentity() ) nodePnt.Transform( loc.Transformation().Inverted() );
if ( nodePnt.Distance( surface->Value( uv.X(), uv.Y() )) > tol )
{
// uv incorrect, project the node to surface
GeomAPI_ProjectPointOnSurf projector( nodePnt, surface, tol );
if ( !projector.IsDone() || projector.NbPoints() < 1 )
{
MESSAGE( "SMESH_MesherHelper::CheckNodeUV() failed to project" );
return false;
}
Quantity_Parameter U,V;
projector.LowerDistanceParameters(U,V);
if ( nodePnt.Distance( surface->Value( U, V )) > tol )
{
MESSAGE( "SMESH_MesherHelper::CheckNodeUV(), invalid projection" );
return false;
}
uv.SetCoord( U,V );
}
else if ( uv.Modulus() > numeric_limits<double>::min() )
{
((SMESH_MesherHelper*) this)->myOkNodePosShapes.insert( n->GetPosition()->GetShapeId() );
}
}
return true;
}
//======================================================================= //=======================================================================
/*! /*!
* \brief Return middle UV taking in account surface period * \brief Return middle UV taking in account surface period
@ -583,10 +612,12 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1,
F = TopoDS::Face(myShape); F = TopoDS::Face(myShape);
faceID = myShapeID; faceID = myShapeID;
} }
bool uvOK1, uvOK2;
gp_XY p1 = GetNodeUV(F,n1,n2, &uvOK1);
gp_XY p2 = GetNodeUV(F,n2,n1, &uvOK2);
gp_XY p1 = GetNodeUV(F,n1,n2, &myCheckNodePos); if ( uvOK1 && uvOK2 )
gp_XY p2 = GetNodeUV(F,n2,n1, &myCheckNodePos); {
if ( IsDegenShape( Pos1->GetShapeId() )) if ( IsDegenShape( Pos1->GetShapeId() ))
p1.SetCoord( myParIndex, p2.Coord( myParIndex )); p1.SetCoord( myParIndex, p2.Coord( myParIndex ));
else if ( IsDegenShape( Pos2->GetShapeId() )) else if ( IsDegenShape( Pos2->GetShapeId() ))
@ -601,6 +632,7 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1,
myTLinkNodeMap.insert(make_pair(link,n12)); myTLinkNodeMap.insert(make_pair(link,n12));
return n12; return n12;
} }
}
if (edgeID>0 || shapeType == TopAbs_EDGE) { if (edgeID>0 || shapeType == TopAbs_EDGE) {
TopoDS_Edge E; TopoDS_Edge E;
@ -611,8 +643,8 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1,
edgeID = myShapeID; edgeID = myShapeID;
} }
double p1 = GetNodeU(E,n1, &myCheckNodePos); double p1 = GetNodeU(E,n1);
double p2 = GetNodeU(E,n2, &myCheckNodePos); double p2 = GetNodeU(E,n2);
double f,l; double f,l;
Handle(Geom_Curve) C = BRep_Tool::Curve(E, f, l); Handle(Geom_Curve) C = BRep_Tool::Curve(E, f, l);

View File

@ -151,15 +151,6 @@ public:
*/ */
void SetElementsOnShape(bool toSet) { mySetElemOnShape = toSet; } void SetElementsOnShape(bool toSet) { mySetElemOnShape = toSet; }
/*!
* \brief Enable/disable checking of node parameters on shapes while adding elements.
* In case of incorrect parameters mudium node place is computed as the middle
* of two nodes. Default is false.
* NOTE that this flag is reset to "not to check" if check with non-default partameter
* is successful
*/
void SetCheckNodePosition(bool toCheck) { myCheckNodePos = toCheck; }
/*! /*!
* \brief Set shape to make elements on without calling IsQuadraticSubMesh() * \brief Set shape to make elements on without calling IsQuadraticSubMesh()
*/ */
@ -260,6 +251,14 @@ public:
const SMDS_MeshNode* n, const SMDS_MeshNode* n,
const SMDS_MeshNode* inFaceNode=0, const SMDS_MeshNode* inFaceNode=0,
bool* check=0) const; bool* check=0) const;
/*!
* \brief Check and fix node UV on a face
* \retval bool - false if UV is bad and could not be fixed
*/
bool CheckNodeUV(const TopoDS_Face& F,
const SMDS_MeshNode* n,
gp_XY& uv,
const double tol) const;
/*! /*!
* \brief Return middle UV taking in account surface period * \brief Return middle UV taking in account surface period
*/ */
@ -393,7 +392,7 @@ protected:
// to create quadratic elements // to create quadratic elements
bool myCreateQuadratic; bool myCreateQuadratic;
bool mySetElemOnShape; bool mySetElemOnShape;
bool myCheckNodePos; std::set< int > myOkNodePosShapes;
}; };