0021006: EDF 1546 SMESH : Convert To Quadratic fails

+  const SMDS_MeshNode* getMediumNodeOnComposedWire(const SMDS_MeshNode* n1,
+                                                   const SMDS_MeshNode* n2,
+                                                   bool                 force3d);
This commit is contained in:
eap 2010-09-28 11:29:20 +00:00
parent 195a4bb6ec
commit 56d3c935a8
2 changed files with 98 additions and 12 deletions

View File

@ -356,7 +356,7 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face& F,
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 ) if ( check )
uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), BRep_Tool::Tolerance( F )); uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), 2*BRep_Tool::Tolerance( F ));
} }
else if(Pos->GetTypeOfPosition()==SMDS_TOP_EDGE) else if(Pos->GetTypeOfPosition()==SMDS_TOP_EDGE)
{ {
@ -375,7 +375,7 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face& F,
else else
uv.SetCoord(0.,0.); uv.SetCoord(0.,0.);
if ( check || !validU ) if ( check || !validU )
uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), BRep_Tool::Tolerance( E ),/*force=*/ !validU ); uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), 2*BRep_Tool::Tolerance( E ),/*force=*/ !validU );
// 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 ) )
@ -479,7 +479,7 @@ bool SMESH_MesherHelper::CheckNodeUV(const TopoDS_Face& F,
if ( !loc.IsIdentity() ) nodePnt.Transform( loc.Transformation().Inverted() ); if ( !loc.IsIdentity() ) nodePnt.Transform( loc.Transformation().Inverted() );
if ( Precision::IsInfinite( uv.X() ) || if ( Precision::IsInfinite( uv.X() ) ||
Precision::IsInfinite( uv.Y() ) || Precision::IsInfinite( uv.Y() ) ||
nodePnt.Distance( surface->Value( uv.X(), uv.Y() )) > 2*tol ) nodePnt.Distance( surface->Value( uv.X(), uv.Y() )) > tol )
{ {
// uv incorrect, project the node to surface // uv incorrect, project the node to surface
GeomAPI_ProjectPointOnSurf& projector = GetProjector( F, loc, tol ); GeomAPI_ProjectPointOnSurf& projector = GetProjector( F, loc, tol );
@ -492,7 +492,7 @@ bool SMESH_MesherHelper::CheckNodeUV(const TopoDS_Face& F,
Quantity_Parameter U,V; Quantity_Parameter U,V;
projector.LowerDistanceParameters(U,V); projector.LowerDistanceParameters(U,V);
uv.SetCoord( U,V ); uv.SetCoord( U,V );
if ( nodePnt.Distance( surface->Value( U, V )) > 2*tol ) if ( nodePnt.Distance( surface->Value( U, V )) > tol )
{ {
MESSAGE( "SMESH_MesherHelper::CheckNodeUV(), invalid projection" ); MESSAGE( "SMESH_MesherHelper::CheckNodeUV(), invalid projection" );
return false; return false;
@ -632,7 +632,7 @@ double SMESH_MesherHelper::GetNodeU(const TopoDS_Edge& E,
if ( !force && pos->GetTypeOfPosition()==SMDS_TOP_EDGE ) if ( !force && pos->GetTypeOfPosition()==SMDS_TOP_EDGE )
force = ( GetMeshDS()->ShapeToIndex( E ) != pos->GetShapeId() ); force = ( GetMeshDS()->ShapeToIndex( E ) != pos->GetShapeId() );
*check = CheckNodeU( E, n, param, tol, force ); *check = CheckNodeU( E, n, param, 2*tol, force );
} }
return param; return param;
} }
@ -647,7 +647,8 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge& E,
const SMDS_MeshNode* n, const SMDS_MeshNode* n,
double& u, double& u,
const double tol, const double tol,
const bool force) const const bool force,
double* distance) const
{ {
if ( force || !myOkNodePosShapes.count( n->GetPosition()->GetShapeId() )) if ( force || !myOkNodePosShapes.count( n->GetPosition()->GetShapeId() ))
{ {
@ -666,7 +667,9 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge& E,
{ {
gp_Pnt nodePnt = SMESH_MeshEditor::TNodeXYZ( n ); gp_Pnt nodePnt = SMESH_MeshEditor::TNodeXYZ( n );
if ( !loc.IsIdentity() ) nodePnt.Transform( loc.Transformation().Inverted() ); if ( !loc.IsIdentity() ) nodePnt.Transform( loc.Transformation().Inverted() );
if ( nodePnt.Distance( curve->Value( u )) > tol ) double dist = nodePnt.Distance( curve->Value( u ));
if ( distance ) *distance = dist;
if ( dist > tol )
{ {
// u incorrect, project the node to the curve // u incorrect, project the node to the curve
GeomAPI_ProjectPointOnCurve projector( nodePnt, curve, f, l ); GeomAPI_ProjectPointOnCurve projector( nodePnt, curve, f, l );
@ -677,7 +680,9 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge& E,
} }
Quantity_Parameter U = projector.LowerDistanceParameter(); Quantity_Parameter U = projector.LowerDistanceParameter();
u = double( U ); u = double( U );
if ( nodePnt.Distance( curve->Value( U )) > tol ) dist = nodePnt.Distance( curve->Value( U ));
if ( distance ) *distance = dist;
if ( dist > tol )
{ {
MESSAGE( "SMESH_MesherHelper::CheckNodeU(), invalid projection" ); MESSAGE( "SMESH_MesherHelper::CheckNodeU(), invalid projection" );
return false; return false;
@ -768,6 +773,11 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1,
} }
else if (edgeID>0 || shapeType == TopAbs_EDGE) else if (edgeID>0 || shapeType == TopAbs_EDGE)
{ {
if ( Pos1->GetTypeOfPosition()==SMDS_TOP_EDGE &&
Pos2->GetTypeOfPosition()==SMDS_TOP_EDGE &&
Pos1->GetShapeId() != Pos2->GetShapeId() ) // issue 0021006
return getMediumNodeOnComposedWire(n1,n2,force3d);
if( myShape.IsNull() ) if( myShape.IsNull() )
E = TopoDS::Edge(meshDS->IndexToShape(edgeID)); E = TopoDS::Edge(meshDS->IndexToShape(edgeID));
else { else {
@ -835,13 +845,13 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1,
if ( !F.IsNull() ) if ( !F.IsNull() )
{ {
gp_XY UV = ( uv[0] + uv[1] ) / 2.; gp_XY UV = ( uv[0] + uv[1] ) / 2.;
CheckNodeUV( F, n12, UV, BRep_Tool::Tolerance( F ), /*force=*/true); CheckNodeUV( F, n12, UV, 2*BRep_Tool::Tolerance( F ), /*force=*/true);
meshDS->SetNodeOnFace(n12, faceID, UV.X(), UV.Y() ); meshDS->SetNodeOnFace(n12, faceID, UV.X(), UV.Y() );
} }
else if ( !E.IsNull() ) else if ( !E.IsNull() )
{ {
double U = ( u[0] + u[1] ) / 2.; double U = ( u[0] + u[1] ) / 2.;
CheckNodeU( E, n12, U, BRep_Tool::Tolerance( E ), /*force=*/true); CheckNodeU( E, n12, U, 2*BRep_Tool::Tolerance( E ), /*force=*/true);
meshDS->SetNodeOnEdge(n12, edgeID, U); meshDS->SetNodeOnEdge(n12, edgeID, U);
} }
else if ( myShapeID > 0 ) else if ( myShapeID > 0 )
@ -852,6 +862,78 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1,
return n12; return n12;
} }
//================================================================================
/*!
* \brief Makes a medium node if nodes reside different edges
*/
//================================================================================
const SMDS_MeshNode* SMESH_MesherHelper::getMediumNodeOnComposedWire(const SMDS_MeshNode* n1,
const SMDS_MeshNode* n2,
bool force3d)
{
gp_Pnt middle = 0.5 * XYZ(n1) + 0.5 * XYZ(n2);
SMDS_MeshNode* n12 = AddNode( middle.X(), middle.Y(), middle.Z() );
// To find position on edge and 3D position for n12,
// project <middle> to 2 edges and select projection most close to <middle>
double u = 0, distMiddleProj = Precision::Infinite();
int iOkEdge = 0;
TopoDS_Edge edges[2];
for ( int is2nd = 0; is2nd < 2; ++is2nd )
{
// get an edge
const SMDS_MeshNode* n = is2nd ? n2 : n1;
TopoDS_Shape shape = GetSubShapeByNode( n, GetMeshDS() );
if ( shape.IsNull() || shape.ShapeType() != TopAbs_EDGE )
continue;
// project to get U of projection and distance from middle to projection
TopoDS_Edge edge = edges[ is2nd ] = TopoDS::Edge( shape );
double node2MiddleDist = middle.Distance( XYZ(n) );
double foundU = GetNodeU( edge, n ), foundDist = node2MiddleDist;
CheckNodeU( edge, n12, foundU, 2*BRep_Tool::Tolerance(edge), /*force=*/true, &foundDist );
if ( foundDist < node2MiddleDist )
{
distMiddleProj = foundDist;
u = foundU;
iOkEdge = is2nd;
}
}
if ( Precision::IsInfinite( distMiddleProj ))
{
// both projections failed; set n12 on the edge of n1 with U of a common vertex
TopoDS_Vertex vCommon;
if ( TopExp::CommonVertex( edges[0], edges[1], vCommon ))
u = BRep_Tool::Parameter( vCommon, edges[0] );
else
{
double f,l, u0 = GetNodeU( edges[0], n1 );
BRep_Tool::Range( edges[0],f,l );
u = ( fabs(u0-f) < fabs(u0-l) ) ? f : l;
}
iOkEdge = 0;
distMiddleProj = 0;
}
// move n12 to position of a successfull projection
double tol = BRep_Tool::Tolerance(edges[ iOkEdge ]);
if ( !force3d && distMiddleProj > 2*tol )
{
TopLoc_Location loc; double f,l;
Handle(Geom_Curve) curve = BRep_Tool::Curve( edges[iOkEdge],loc,f,l );
gp_Pnt p = curve->Value( u );
GetMeshDS()->MoveNode( n12, p.X(), p.Y(), p.Z() );
}
GetMeshDS()->SetNodeOnEdge(n12, edges[iOkEdge], u);
myTLinkNodeMap.insert( make_pair( SMESH_TLink(n1,n2), n12 ));
return n12;
}
//======================================================================= //=======================================================================
//function : AddNode //function : AddNode
//purpose : Creates a node //purpose : Creates a node
@ -2291,7 +2373,7 @@ namespace { // Structures used by FixQuadraticElements()
return _OK; return _OK;
} }
} } //namespace
//======================================================================= //=======================================================================
/*! /*!

View File

@ -298,7 +298,8 @@ public:
const SMDS_MeshNode* n, const SMDS_MeshNode* n,
double& u, double& u,
const double tol, const double tol,
const bool force=false) const; const bool force=false,
double* distance=0) const;
/*! /*!
* \brief Return middle UV taking in account surface period * \brief Return middle UV taking in account surface period
*/ */
@ -453,6 +454,9 @@ protected:
*/ */
gp_Pnt2d GetUVOnSeam( const gp_Pnt2d& uv1, const gp_Pnt2d& uv2 ) const; gp_Pnt2d GetUVOnSeam( const gp_Pnt2d& uv1, const gp_Pnt2d& uv2 ) const;
const SMDS_MeshNode* getMediumNodeOnComposedWire(const SMDS_MeshNode* n1,
const SMDS_MeshNode* n2,
bool force3d);
private: private:
// Forbiden copy constructor // Forbiden copy constructor