X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MesherHelper.cxx;h=bdd3584513c3f5a1090004a3629b3128938ad1c7;hb=bcfa36bbd041d724ff56560fb606261235d5f9e1;hp=6dda8f79b7aa0ac0fa817156a90de1fab38cee00;hpb=cb88fa5e41e060e23f5a15f1149bff8e983c4824;p=modules%2Fsmesh.git diff --git a/src/SMESH/SMESH_MesherHelper.cxx b/src/SMESH/SMESH_MesherHelper.cxx index 6dda8f79b..bdd358451 100644 --- a/src/SMESH/SMESH_MesherHelper.cxx +++ b/src/SMESH/SMESH_MesherHelper.cxx @@ -242,34 +242,39 @@ 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() ); - TopLoc_Location loc; - Handle(Geom_Surface) surface = BRep_Tool::Surface( face, loc ); // if ( surface->IsUPeriodic() || surface->IsVPeriodic() || // surface->IsUClosed() || surface->IsVClosed() ) { //while ( surface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface ))) //surface = Handle(Geom_RectangularTrimmedSurface)::DownCast( surface )->BasisSurface(); - GeomAdaptor_Surface surf( surface ); for (TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next()) { // look for a seam edge - const TopoDS_Edge& edge = TopoDS::Edge( exp.Current() ); + TopoDS_Edge edge = TopoDS::Edge( exp.Current() ); if ( BRep_Tool::IsClosed( edge, face )) { // initialize myPar1, myPar2 and myParIndex 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) )) { + double u1 = uv1.Coord(1); + edge.Reverse(); + BRep_Tool::UVPoints( edge, face, uv1, uv2 ); + double u2 = uv1.Coord(1); myParIndex |= U_periodic; - myPar1[0] = surf.FirstUParameter(); - myPar2[0] = surf.LastUParameter(); + myPar1[0] = Min( u1, u2 ); + myPar2[0] = Max( u1, u2 ); } 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] = surf.FirstVParameter(); - myPar2[1] = surf.LastVParameter(); + myPar1[1] = Min( v1, v2 ); + myPar2[1] = Max( v1, v2 ); } // store seam shape indices, negative if shape encounters twice int edgeID = meshDS->ShapeToIndex( edge ); @@ -287,13 +292,15 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh) myDegenShapeIds.insert( meshDS->ShapeToIndex( v.Current() )); } } - if ( !myDegenShapeIds.empty() && !myParIndex ) { - if ( surface->IsUPeriodic() || surface->IsUClosed() ) { + 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 ( surface->IsVPeriodic() || surface->IsVClosed() ) { + else if ( surf.IsVPeriodic() || surf.IsVClosed() ) { myParIndex |= V_periodic; myPar1[1] = surf.FirstVParameter(); myPar2[1] = surf.LastVParameter(); @@ -513,8 +520,8 @@ gp_Pnt2d SMESH_MesherHelper::GetUVOnSeam( const gp_Pnt2d& uv1, const gp_Pnt2d& u double p1 = uv1.Coord( i ); double dp1 = Abs( p1-myPar1[i-1]), dp2 = Abs( p1-myPar2[i-1]); if ( myParIndex == i || - dp1 < ( myPar2[i-1] - myPar2[i-1] ) / 100. || - dp2 < ( myPar2[i-1] - myPar2[i-1] ) / 100. ) + dp1 < ( myPar2[i-1] - myPar1[i-1] ) / 100. || + dp2 < ( myPar2[i-1] - myPar1[i-1] ) / 100. ) { double p2 = uv2.Coord( i ); double p1Alt = ( dp1 < dp2 ) ? myPar2[i-1] : myPar1[i-1]; @@ -544,7 +551,7 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face& F, { // node has position on face const SMDS_FacePosition* fpos = - static_cast(n->GetPosition()); + static_cast( Pos ); uv.SetCoord(fpos->GetUParameter(),fpos->GetVParameter()); if ( check ) uvOK = CheckNodeUV( F, n, uv.ChangeCoord(), 10*MaxTolerance( F )); @@ -555,7 +562,7 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face& F, // corresponding edge from face, get pcurve for this // edge and retrieve value from this pcurve const SMDS_EdgePosition* epos = - static_cast(n->GetPosition()); + static_cast( Pos ); int edgeID = n->getshapeId(); TopoDS_Edge E = TopoDS::Edge(GetMeshDS()->IndexToShape(edgeID)); double f, l, u = epos->GetUParameter(); @@ -1200,10 +1207,11 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetCentralNode(const SMDS_MeshNode* n1, } else // ( force3d || F.IsNull() ) { - P = ( SMESH_TNodeXYZ( n1 ) + - SMESH_TNodeXYZ( n2 ) + - SMESH_TNodeXYZ( n3 ) + - SMESH_TNodeXYZ( n4 ) ) / 4; + P = calcTFI (0.5, 0.5, + SMESH_TNodeXYZ(n1), SMESH_TNodeXYZ(n2), + SMESH_TNodeXYZ(n3), SMESH_TNodeXYZ(n4), + SMESH_TNodeXYZ(n12), SMESH_TNodeXYZ(n23), + SMESH_TNodeXYZ(n34), SMESH_TNodeXYZ(n41)); centralNode = meshDS->AddNode( P.X(), P.Y(), P.Z() ); if ( !F.IsNull() ) // force3d @@ -1435,6 +1443,7 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1, catch ( Standard_Failure& f ) { // issue 22502 / a node is on VERTEX not belonging to E + // issue 22568 / both nodes are on non-connected VERTEXes return getMediumNodeOnComposedWire(n1,n2,force3d); } } @@ -1455,7 +1464,6 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1, if ( myParIndex & U_periodic ) uv[1].SetCoord( 1, uv[0].Coord( 1 )); else uv[1].SetCoord( 2, uv[0].Coord( 2 )); } - TopLoc_Location loc; Handle(Geom_Surface) S = BRep_Tool::Surface(F,loc); gp_XY UV = GetMiddleUV( S, uv[0], uv[1] ); @@ -1534,67 +1542,108 @@ const SMDS_MeshNode* SMESH_MesherHelper::getMediumNodeOnComposedWire(const SMDS_ const SMDS_MeshNode* n2, bool force3d) { - gp_Pnt middle = 0.5 * XYZ(n1) + 0.5 * XYZ(n2); + SMESH_TNodeXYZ p1( n1 ), p2( n2 ); + gp_Pnt middle = 0.5 * p1 + 0.5 * p2; SMDS_MeshNode* n12 = AddNode( middle.X(), middle.Y(), middle.Z() ); // To find position on edge and 3D position for n12, // project to 2 edges and select projection most close to - double u = 0, distMiddleProj = Precision::Infinite(), distXYZ[4]; - int iOkEdge = 0; - TopoDS_Edge edges[2]; + TopoDS_Edge bestEdge; + double u = 0, distMiddleProj = Precision::Infinite(), distXYZ[4], f,l; + + // get shapes under the nodes + TopoDS_Shape shape[2]; + int nbShapes = 0; 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; + TopoDS_Shape S = GetSubShapeByNode( n, GetMeshDS() ); + if ( !S.IsNull() ) + shape[ nbShapes++ ] = S; + } + // get EDGEs + vector< TopoDS_Shape > edges; + for ( int iS = 0; iS < nbShapes; ++iS ) + { + switch ( shape[iS].ShapeType() ) { + case TopAbs_EDGE: + { + edges.push_back( shape[iS] ); + break; + } + case TopAbs_VERTEX: + { + TopoDS_Shape edge; + if ( nbShapes == 2 && iS==0 && shape[1-iS].ShapeType() == TopAbs_VERTEX ) + edge = GetCommonAncestor( shape[iS], shape[1-iS], *myMesh, TopAbs_EDGE ); - // 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 ); - CheckNodeU( edge, n12, foundU, 2*BRep_Tool::Tolerance(edge), /*force=*/true, distXYZ ); - if ( distXYZ[0] < node2MiddleDist ) + if ( edge.IsNull() ) + { + PShapeIteratorPtr eIt = GetAncestors( shape[iS], *myMesh, TopAbs_EDGE ); + while( const TopoDS_Shape* e = eIt->next() ) + edges.push_back( *e ); + } + break; + } + case TopAbs_FACE: { - distMiddleProj = distXYZ[0]; - u = foundU; - iOkEdge = is2nd; + if ( nbShapes == 1 || shape[1-iS].ShapeType() < TopAbs_EDGE ) + for ( TopExp_Explorer e( shape[iS], TopAbs_EDGE ); e.More(); e.Next() ) + edges.push_back( e.Current() ); + break; + } + default: + continue; } } - if ( Precision::IsInfinite( distMiddleProj )) + // project to get U of projection and distance from middle to projection + for ( size_t iE = 0; iE < edges.size(); ++iE ) { - // 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 + const TopoDS_Edge& edge = TopoDS::Edge( edges[ iE ]); + distXYZ[0] = distMiddleProj; + double testU = 0; + CheckNodeU( edge, n12, testU, 2 * BRep_Tool::Tolerance(edge), /*force=*/true, distXYZ ); + if ( distXYZ[0] < distMiddleProj ) { - double f,l, u0 = GetNodeU( edges[0], n1 ); - BRep_Tool::Range( edges[0],f,l ); - u = ( fabs(u0-f) < fabs(u0-l) ) ? f : l; + distMiddleProj = distXYZ[0]; + u = testU; + bestEdge = edge; } - 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() ); } - - //if ( mySetElemOnShape ) node is not elem! + // { + // // 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; + // } + + if ( !bestEdge.IsNull() ) { - int edgeID = GetMeshDS()->ShapeToIndex( edges[iOkEdge] ); - if ( edgeID != n12->getshapeId() ) - GetMeshDS()->UnSetNodeOnShape( n12 ); - GetMeshDS()->SetNodeOnEdge(n12, edgeID, u); + // move n12 to position of a successfull projection + //double tol = BRep_Tool::Tolerance(edges[ iOkEdge ]); + if ( !force3d /*&& distMiddleProj > 2*tol*/ ) + { + TopLoc_Location loc; + Handle(Geom_Curve) curve = BRep_Tool::Curve( bestEdge,loc,f,l ); + gp_Pnt p = curve->Value( u ).Transformed( loc ); + GetMeshDS()->MoveNode( n12, p.X(), p.Y(), p.Z() ); + } + //if ( mySetElemOnShape ) node is not elem! + { + int edgeID = GetMeshDS()->ShapeToIndex( bestEdge ); + if ( edgeID != n12->getshapeId() ) + GetMeshDS()->UnSetNodeOnShape( n12 ); + GetMeshDS()->SetNodeOnEdge(n12, edgeID, u); + } } myTLinkNodeMap.insert( make_pair( SMESH_TLink(n1,n2), n12 )); @@ -2279,11 +2328,12 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2 while ( ++u_n != sortedBaseNN.end() && !isNodeInSubMesh( u_n->second, faceSubMesh )); sortedBaseNN.erase( sortedBaseNN.begin(), u_n ); } - if ( u_n = --sortedBaseNN.end(), !isNodeInSubMesh( u_n->second, faceSubMesh )) - { - while ( u_n != sortedBaseNN.begin() && !isNodeInSubMesh( (--u_n)->second, faceSubMesh )); - sortedBaseNN.erase( ++u_n, sortedBaseNN.end() ); - } + if ( !sortedBaseNN.empty() ) + if ( u_n = --sortedBaseNN.end(), !isNodeInSubMesh( u_n->second, faceSubMesh )) + { + while ( u_n != sortedBaseNN.begin() && !isNodeInSubMesh( (--u_n)->second, faceSubMesh )); + sortedBaseNN.erase( ++u_n, sortedBaseNN.end() ); + } if ( sortedBaseNN.empty() ) continue; } @@ -2300,7 +2350,7 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2 u2nn->second.push_back( u_n->second ); } } - if ( theParam2ColumnMap.empty() ) + if ( theParam2ColumnMap.size() < 2 ) return false; } @@ -2683,23 +2733,22 @@ double SMESH_MesherHelper::MaxTolerance( const TopoDS_Shape& shape ) */ //================================================================================ -double SMESH_MesherHelper::GetAngle( const TopoDS_Edge & theE1, - const TopoDS_Edge & theE2, - const TopoDS_Face & theFace) +double SMESH_MesherHelper::GetAngle( const TopoDS_Edge & theE1, + const TopoDS_Edge & theE2, + const TopoDS_Face & theFace, + const TopoDS_Vertex & theCommonV, + gp_Vec* theFaceNormal) { double angle = 1e100; try { - TopoDS_Vertex vCommon; - if ( !TopExp::CommonVertex( theE1, theE2, vCommon )) - return angle; double f,l; Handle(Geom_Curve) c1 = BRep_Tool::Curve( theE1, f,l ); Handle(Geom_Curve) c2 = BRep_Tool::Curve( theE2, f,l ); Handle(Geom2d_Curve) c2d1 = BRep_Tool::CurveOnSurface( theE1, theFace, f,l ); Handle(Geom_Surface) surf = BRep_Tool::Surface( theFace ); - double p1 = BRep_Tool::Parameter( vCommon, theE1 ); - double p2 = BRep_Tool::Parameter( vCommon, theE2 ); + double p1 = BRep_Tool::Parameter( theCommonV, theE1 ); + double p2 = BRep_Tool::Parameter( theCommonV, theE2 ); if ( c1.IsNull() || c2.IsNull() ) return angle; gp_XY uv = c2d1->Value( p1 ).XY(); @@ -2708,10 +2757,10 @@ double SMESH_MesherHelper::GetAngle( const TopoDS_Edge & theE1, gp_Vec vec1, vec2, vecRef = du ^ dv; int nbLoops = 0; double p1tmp = p1; - while ( vecRef.SquareMagnitude() < std::numeric_limits::min() ) + while ( vecRef.SquareMagnitude() < 1e-25 ) { double dp = ( l - f ) / 1000.; - p1tmp += dp * (( Abs( p1 - f ) > Abs( p1 - l )) ? +1. : -1.); + p1tmp += dp * (( Abs( p1 - f ) > Abs( p1 - l )) ? -1. : +1.); uv = c2d1->Value( p1tmp ).XY(); surf->D1( uv.X(), uv.Y(), p, du, dv ); vecRef = du ^ dv; @@ -2725,16 +2774,33 @@ double SMESH_MesherHelper::GetAngle( const TopoDS_Edge & theE1, } if ( theFace.Orientation() == TopAbs_REVERSED ) vecRef.Reverse(); + if ( theFaceNormal ) *theFaceNormal = vecRef; + c1->D1( p1, p, vec1 ); c2->D1( p2, p, vec2 ); - TopoDS_Face F = theFace; - if ( F.Orientation() == TopAbs_INTERNAL ) - F.Orientation( TopAbs_FORWARD ); + // TopoDS_Face F = theFace; + // if ( F.Orientation() == TopAbs_INTERNAL ) + // F.Orientation( TopAbs_FORWARD ); if ( theE1.Orientation() /*GetSubShapeOri( F, theE1 )*/ == TopAbs_REVERSED ) vec1.Reverse(); if ( theE2.Orientation() /*GetSubShapeOri( F, theE2 )*/ == TopAbs_REVERSED ) vec2.Reverse(); angle = vec1.AngleWithRef( vec2, vecRef ); + + if ( Abs ( angle ) >= 0.99 * M_PI ) + { + BRep_Tool::Range( theE1, f, l ); + p1 += 1e-7 * ( p1-f < l-p1 ? +1. : -1. ); + c1->D1( p1, p, vec1 ); + if ( theE1.Orientation() == TopAbs_REVERSED ) + vec1.Reverse(); + BRep_Tool::Range( theE2, f, l ); + p2 += 1e-7 * ( p2-f < l-p2 ? +1. : -1. ); + c2->D1( p2, p, vec2 ); + if ( theE2.Orientation() == TopAbs_REVERSED ) + vec2.Reverse(); + angle = vec1.AngleWithRef( vec2, vecRef ); + } } catch (...) { @@ -3550,7 +3616,7 @@ namespace { // Structures used by FixQuadraticElements() } else if ( _faces.size() > 1 ) // not found, set NULL by the first face { - _faces.insert( ++_faces.begin(), 0 ); + _faces.insert( ++_faces.begin(), (QFace*) 0 ); } } //================================================================================ @@ -4093,9 +4159,11 @@ namespace { // Structures used by FixQuadraticElements() //BRepClass3d_SolidClassifier solidClassifier( shape ); TIDSortedElemSet checkedVols, movedNodes; - for ( faceIt.ReInit(); faceIt.More(); faceIt.Next() ) // loop on FACEs of a SOLID + //for ( faceIt.ReInit(); faceIt.More(); faceIt.Next() ) // loop on FACEs of a SOLID + for ( size_t iF = 0; iF < concaveFaces.size(); ++iF ) // loop on concave FACEs { - const TopoDS_Shape& face = faceIt.Current(); + //const TopoDS_Shape& face = faceIt.Current(); + const TopoDS_Shape& face = concaveFaces[ iF ]; SMESHDS_SubMesh* faceSM = meshDS->MeshElements( face ); if ( !faceSM ) continue; @@ -4110,11 +4178,16 @@ namespace { // Structures used by FixQuadraticElements() if ( !vertexSM ) continue; nodeIt = vertexSM->GetNodes(); } + // get ids of sub-shapes of the FACE + set< int > subIDs; + SMESH_subMeshIteratorPtr smIt = + theHelper.GetMesh()->GetSubMesh( face )->getDependsOnIterator(/*includeSelf=*/true); + while ( smIt->more() ) + subIDs.insert( smIt->next()->GetId() ); // find suspicious volumes adjacent to the FACE vector< const SMDS_MeshNode* > nOnFace( 4 ); const SMDS_MeshNode* nInSolid; - //vector< const SMDS_MeshElement* > intersectedFaces; while ( nodeIt->more() ) { const SMDS_MeshNode* n = nodeIt->next(); @@ -4136,8 +4209,10 @@ namespace { // Structures used by FixQuadraticElements() n = *volNode; if ( n->GetPosition()->GetDim() == 3 ) nInSolid = n; - else + else if ( subIDs.count( n->getshapeId() )) nOnFace.push_back( n ); + else + nInSolid = n; } if ( !nInSolid || nOnFace.size() != nbN - 1 ) continue;