From: eap Date: Tue, 22 Mar 2022 13:31:40 +0000 (+0300) Subject: bos #29395 EDF 25009 - import1D2D mesh fails X-Git-Tag: V9_9_0a2~5 X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=commitdiff_plain;h=b881b9c7b9c1c2f4d5245d5ffd17eea91b46f26e bos #29395 EDF 25009 - import1D2D mesh fails --- diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx index 44d92ef4d..a8a20c46c 100644 --- a/src/Controls/SMESH_Controls.cxx +++ b/src/Controls/SMESH_Controls.cxx @@ -4453,9 +4453,12 @@ SMDSAbs_ElementType ElementsOnShape::GetType() const void ElementsOnShape::SetTolerance (const double theToler) { - if (myToler != theToler) { + if (myToler != theToler) + { myToler = theToler; - SetShape(myShape, myType); + TopoDS_Shape s = myShape; + myShape.Nullify(); + SetShape( s, myType ); } } diff --git a/src/SMESH/SMESH_MesherHelper.cxx b/src/SMESH/SMESH_MesherHelper.cxx index 1dcc5b064..5621cc34b 100644 --- a/src/SMESH/SMESH_MesherHelper.cxx +++ b/src/SMESH/SMESH_MesherHelper.cxx @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -875,6 +876,51 @@ GeomAPI_ProjectPointOnSurf& SMESH_MesherHelper::GetProjector(const TopoDS_Face& return *( i_proj->second ); } +//======================================================================= +//function : GetProjector +//purpose : Return projector initialized by given face, which is returned +//======================================================================= + +GeomAPI_ProjectPointOnSurf& SMESH_MesherHelper::GetProjector(const TopoDS_Face& F, + double tol ) const +{ + Handle(Geom_Surface) surface = BRep_Tool::Surface( F ); + int faceID = GetMeshDS()->ShapeToIndex( F ); + TID2ProjectorOnSurf& i2proj = const_cast< TID2ProjectorOnSurf&>( myFace2Projector ); + TID2ProjectorOnSurf::iterator i_proj = i2proj.find( faceID ); + if ( i_proj == i2proj.end() ) + { + if ( tol == 0 ) tol = BRep_Tool::Tolerance( F ); + double U1, U2, V1, V2; + surface->Bounds(U1, U2, V1, V2); + GeomAPI_ProjectPointOnSurf* proj = new GeomAPI_ProjectPointOnSurf(); + proj->Init( surface, U1, U2, V1, V2, tol ); + i_proj = i2proj.insert( make_pair( faceID, proj )).first; + } + return *( i_proj->second ); +} + +//======================================================================= +//function : GetPCProjector +//purpose : Return projector initialized by given EDGE +//======================================================================= + +GeomAPI_ProjectPointOnCurve& SMESH_MesherHelper::GetPCProjector(const TopoDS_Edge& E ) const +{ + int edgeID = GetMeshDS()->ShapeToIndex( E ); + TID2ProjectorOnCurve& i2proj = const_cast< TID2ProjectorOnCurve&>( myEdge2Projector ); + TID2ProjectorOnCurve::iterator i_proj = i2proj.insert( make_pair( edgeID, nullptr )).first; + if ( !i_proj->second ) + { + double f,l; + Handle(Geom_Curve) curve = BRep_Tool::Curve( E,f,l ); + i_proj->second = new GeomAPI_ProjectPointOnCurve(); + i_proj->second->Init( curve, f, l ); + } + GeomAPI_ProjectPointOnCurve* projector = i_proj->second; + return *projector; +} + //======================================================================= //function : GetSurface //purpose : Return a cached ShapeAnalysis_Surface of a FACE @@ -1121,27 +1167,17 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge& E, { setPosOnShapeValidity( shapeID, false ); // u incorrect, project the node to the curve - int edgeID = GetMeshDS()->ShapeToIndex( E ); - TID2ProjectorOnCurve& i2proj = const_cast< TID2ProjectorOnCurve&>( myEdge2Projector ); - TID2ProjectorOnCurve::iterator i_proj = - i2proj.insert( make_pair( edgeID, (GeomAPI_ProjectPointOnCurve*) 0 )).first; - if ( !i_proj->second ) - { - i_proj->second = new GeomAPI_ProjectPointOnCurve(); - i_proj->second->Init( curve, f, l ); - } - GeomAPI_ProjectPointOnCurve* projector = i_proj->second; - projector->Perform( nodePnt ); - if ( projector->NbPoints() < 1 ) - { - MESSAGE( "SMESH_MesherHelper::CheckNodeU() failed to project" ); - return false; - } - Standard_Real U = projector->LowerDistanceParameter(); - u = double( U ); - curvPnt = curve->Value( u ); - dist = nodePnt.Distance( curvPnt ); + //GeomAPI_ProjectPointOnCurve& projector = GetPCProjector( E ); -- bug in OCCT-7.5.3p1 + GeomAdaptor_Curve curveAd( curve, f, l ); + ShapeAnalysis_Curve projector; + dist = projector.Project( curveAd, nodePnt, tol, curvPnt, u, false ); + // if ( projector.NbPoints() < 1 ) + // { + // MESSAGE( "SMESH_MesherHelper::CheckNodeU() failed to project" ); + // return false; + // } if ( distXYZ ) { + curvPnt = curve->Value( u ); curvPnt.Transform( loc ); distXYZ[0] = dist; distXYZ[1] = curvPnt.X(); distXYZ[2] = curvPnt.Y(); distXYZ[3]=curvPnt.Z(); @@ -1154,7 +1190,7 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge& E, // store the fixed U on the edge if ( myShape.IsSame(E) && shapeID == myShapeID && myFixNodeParameters ) const_cast(n)->SetPosition - ( SMDS_PositionPtr( new SMDS_EdgePosition( U ))); + ( SMDS_PositionPtr( new SMDS_EdgePosition( u ))); } else if ( fabs( u ) > numeric_limits::min() ) { diff --git a/src/SMESH/SMESH_MesherHelper.hxx b/src/SMESH/SMESH_MesherHelper.hxx index 82d242ec2..0a4bd8b0d 100644 --- a/src/SMESH/SMESH_MesherHelper.hxx +++ b/src/SMESH/SMESH_MesherHelper.hxx @@ -554,11 +554,20 @@ public: bool GetNodeUVneedInFaceNode(const TopoDS_Face& F = TopoDS_Face()) const; /*! - * \brief Return projector initialized by given face without location, which is returned + * \brief Return projector initialized by given face without location */ GeomAPI_ProjectPointOnSurf& GetProjector(const TopoDS_Face& F, TopLoc_Location& loc, - double tol=0 ) const; + double tol=0 ) const; + /*! + * \brief Return projector initialized by given face + */ + GeomAPI_ProjectPointOnSurf& GetProjector(const TopoDS_Face& F, + double tol=0 ) const; + /*! + * \brief Return projector initialized by given EDGE + */ + GeomAPI_ProjectPointOnCurve& GetPCProjector(const TopoDS_Edge& E ) const; /*! * \brief Return a cached ShapeAnalysis_Surface of a FACE */ diff --git a/src/StdMeshers/StdMeshers_Import_1D2D.cxx b/src/StdMeshers/StdMeshers_Import_1D2D.cxx index f4586c979..890084da3 100644 --- a/src/StdMeshers/StdMeshers_Import_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_Import_1D2D.cxx @@ -201,7 +201,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & gp_Pnt p; gp_Vec du, dv; // BRepClass_FaceClassifier is most time consuming, so minimize its usage - const double clsfTol = 10 * BRep_Tool::Tolerance( geomFace ); + const double clsfTol = 1e2 * BRep_Tool::MaxTolerance( geomFace, TopAbs_VERTEX ); BRepTopAdaptor_FClass2d classifier( geomFace, clsfTol ); //Brimless_FaceClassifier classifier; Bnd_B2d bndBox2d; Bnd_Box bndBox3d; @@ -274,7 +274,6 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & double minGroupTol = Precision::Infinite(); SMESH::Controls::ElementsOnShape onEdgeClassifier; - if ( helper.HasSeam() ) { TopoDS_Compound edgesCompound; BRep_Builder builder; @@ -316,8 +315,9 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & // another idea: try to use max tol of all edges //const double clsfTol = 10 * BRep_Tool::Tolerance( geomFace ); // 0.1 * groupTol; - if ( helper.HasSeam() ) - onEdgeClassifier.SetMesh( srcMesh->GetMeshDS() ); + onEdgeClassifier.SetMesh( srcMesh->GetMeshDS() ); + onEdgeClassifier.SetTolerance( groupTol / 10 ); + SMDS_ElemIteratorPtr srcElems = srcGroup->GetElements(); while ( srcElems->more() ) // loop on group contents @@ -373,15 +373,18 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & { // find out if node lies on the surface of theShape gp_XY uv( Precision::Infinite(), 0 ); - isOut = ( !helper.CheckNodeUV( geomFace, node, uv, groupTol, /*force=*/true ) || - bndBox2d.IsOut( uv )); + bool isOutBox = true; + isOut = (! helper.CheckNodeUV( geomFace, node, uv, groupTol, /*force=*/true ) || + ( isOutBox = bndBox2d.IsOut( uv ))); //int iCoo; if ( !isOut && !isIn ) // classify { nodeState[i] = classifier.Perform( uv ); //classifier.Perform( geomFace, uv, clsfTol ); //nodeState[i] = classifier.State(); isOut = ( nodeState[i] == TopAbs_OUT ); - if ( isOut && helper.IsOnSeam( uv ) && onEdgeClassifier.IsSatisfy( node->GetID() )) + if (( isOut ) && + ( !isOutBox || helper.IsOnSeam( uv )) && + onEdgeClassifier.IsSatisfy( node->GetID() )) { // uv.SetCoord( iCoo, helper.GetOtherParam( uv.Coord( iCoo ))); // classifier.Perform( geomFace, uv, clsfTol ); @@ -396,7 +399,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & newNode = tgtMesh->AddNode( nXYZ.X(), nXYZ.Y(), nXYZ.Z()); tgtMesh->SetNodeOnFace( newNode, shapeID, uv.X(), uv.Y() ); nbCreatedNodes++; - if ( newNode->GetID() >= (int) isNodeIn.size() ) + if ( newNode->GetID() >= (smIdType) isNodeIn.size() ) { isNodeIn.push_back( false ); // allow allocate more than newNode->GetID() isNodeIn.resize( newNode->GetID() + 1, false ); @@ -565,7 +568,6 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & // the imported mesh is valid if all external links (encountered once) // lie on geom edges subShapeIDs.erase( shapeID ); // to contain edges and vertices only - double u, f, l; for ( link2Nb = linkCount.begin(); link2Nb != linkCount.end(); ++link2Nb) { const TLink& link = (*link2Nb).first; @@ -580,17 +582,12 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & const SMDS_MeshNode* n = is1stN ? link.node1() : link.node2(); if ( !subShapeIDs.count( n->getshapeId() )) // n is assigned to FACE { - for ( size_t iE = 0; iE < edges.size(); ++iE ) - if ( helper.CheckNodeU( edges[iE], n, u=0, projTol, /*force=*/true )) - { - BRep_Tool::Range(edges[iE],f,l); - if ( Abs(u-f) < 2 * faceTol || Abs(u-l) < 2 * faceTol ) - // duplicated node on vertex - return error("Source elements overlap one another"); - tgtFaceSM->RemoveNode( n ); - tgtMesh->SetNodeOnEdge( n, edges[iE], u ); - break; - } + TopoDS_Shape edge; + if ( onEdgeClassifier.IsSatisfy( n, &edge )) + { + tgtFaceSM->RemoveNode( n ); + tgtMesh->SetNodeOnEdge( n, TopoDS::Edge(edge), /*u=*/0 ); + } nodesOnBoundary = subShapeIDs.count( n->getshapeId()); } if ( nodesOnBoundary ) @@ -638,6 +635,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & { edge = tgtMesh->AddEdge( newNodes[0], newNodes[1], link._medium ); + double u; TopoDS_Edge geomEdge = TopoDS::Edge(bndShapes.back()); helper.CheckNodeU( geomEdge, link._medium, u, projTol, /*force=*/true ); tgtFaceSM->RemoveNode( link._medium ); @@ -710,6 +708,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & TUNodeList nodesOnSeam; double u = helper.GetNodeU( seamEdge, vertNode ); nodesOnSeam.push_back( make_pair( u, vertNode )); + size_t nbNodesOnSeam = 1; TUNodeList::iterator u2nIt = nodesOnSeam.begin(); for ( ; u2nIt != nodesOnSeam.end(); ++u2nIt ) { @@ -723,8 +722,9 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & { const SMDS_MeshNode* n = face->GetNode( i ); if ( n == startNode || !checkedNodes.insert( n ).second ) continue; - if ( helper.CheckNodeU( seamEdge, n, u=0, projTol, /*force=*/true )) - nodesOnSeam.push_back( make_pair( u, n )); + helper.CheckNodeU( seamEdge, n, u=0, projTol, /*force=*/true ); + nodesOnSeam.push_back( make_pair( u, n )); + ++nbNodesOnSeam; } } } @@ -733,6 +733,15 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & map< double, const SMDS_MeshNode* > u2nodeMap; for ( u2nIt = nodesOnSeam.begin(); u2nIt != nodesOnSeam.end(); ++u2nIt ) u2nodeMap.insert( u2nodeMap.end(), *u2nIt ); + if ( u2nodeMap.size() != nbNodesOnSeam ) // problem with parameters on EDGE + { + // sort nodes by distance from seamVertex + gp_Pnt vertPnt = SMESH_NodeXYZ( vertNode ); + u2nodeMap.clear(); + for ( u2nIt = nodesOnSeam.begin(); u2nIt != nodesOnSeam.end(); ++u2nIt ) + u2nodeMap.insert + ({ vertPnt.SquareDistance( SMESH_NodeXYZ( u2nIt->second )), u2nIt->second }); + } // create edges {