X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_ProjectionUtils.cxx;h=1452599ed08ddc7c25eaf5c8c838ff0d43458aa0;hp=2afedd4ce40c5c50128c4b7b0625739afa22f2f6;hb=92f303e8d0ccb645dd38b9dba53721da782cdbab;hpb=512916b107f163a97535d0326008d3edabf6c7ec diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx index 2afedd4ce..1452599ed 100644 --- a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx +++ b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx @@ -40,6 +40,7 @@ #include "SMESH_Mesh.hxx" #include "SMESH_MeshEditor.hxx" #include "SMESH_subMesh.hxx" +#include "SMESH_subMeshEventListener.hxx" #include "SMDS_EdgePosition.hxx" #include "utilities.h" @@ -145,10 +146,11 @@ namespace { * \param edges2 - matching edges of another face * \param theMesh1 - mesh 1 * \param theMesh2 - mesh 2 + * \retval bool - true if association was fixed */ //================================================================================ - void FixAssocByPropagation( const int nbEdges, + bool FixAssocByPropagation( const int nbEdges, list< TopoDS_Edge > & edges1, list< TopoDS_Edge > & edges2, SMESH_Mesh* theMesh1, @@ -158,10 +160,13 @@ namespace { { list< TopoDS_Edge >::iterator eIt2 = ++edges2.begin(); // 2nd edge of the 2nd face TopoDS_Edge edge2 = - StdMeshers_ProjectionUtils::GetPropagationEdge( theMesh1, *eIt2, edges1.front() ); - if ( !edge2.IsNull() ) // propagation found for the second edge + StdMeshers_ProjectionUtils::GetPropagationEdge( theMesh1, *eIt2, edges1.front() ).second; + if ( !edge2.IsNull() ) { // propagation found for the second edge Reverse( edges2, nbEdges ); + return true; + } } + return false; } } @@ -329,15 +334,21 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the list< TopoDS_Edge > edges1, edges2; int nbE = FindFaceAssociation( face1, VV1, face2, VV2, edges1, edges2 ); if ( !nbE ) RETURN_BAD_RESULT("FindFaceAssociation() failed"); - FixAssocByPropagation( nbE, edges1, edges2, theMesh1, theMesh2 ); - InsertAssociation( face1, face2, theMap, bidirect); // assoc faces + MESSAGE("Assoc FACE " << theMesh1->GetMeshDS()->ShapeToIndex( face1 )<< + " to " << theMesh2->GetMeshDS()->ShapeToIndex( face2 )); + if ( nbE == 2 && (edge1.IsSame( edges1.front())) != (edge2.IsSame( edges2.front()))) + { + Reverse( edges2, nbE ); + } list< TopoDS_Edge >::iterator eIt1 = edges1.begin(); list< TopoDS_Edge >::iterator eIt2 = edges2.begin(); for ( ; eIt1 != edges1.end(); ++eIt1, ++eIt2 ) { if ( !boundEdges.Add( *eIt1 )) continue; // already associated InsertAssociation( *eIt1, *eIt2, theMap, bidirect); // assoc edges + MESSAGE("Assoc edge " << theMesh1->GetMeshDS()->ShapeToIndex( *eIt1 )<< + " to " << theMesh2->GetMeshDS()->ShapeToIndex( *eIt2 )); VV1[0] = TopExp::FirstVertex( *eIt1, true ); VV2[0] = TopExp::FirstVertex( *eIt2, true ); InsertAssociation( VV1[0], VV2[0], theMap, bidirect); // assoc vertices @@ -371,7 +382,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the TopoDS_Edge edge2 = TopoDS::Edge( theShape2 ); if ( IsPropagationPossible( theMesh1, theMesh2 )) { - TopoDS_Edge prpEdge = GetPropagationEdge( theMesh1, edge2, edge1 ); + TopoDS_Edge prpEdge = GetPropagationEdge( theMesh1, edge2, edge1 ).second; if ( !prpEdge.IsNull() ) { TopoDS_Vertex VV1[2], VV2[2]; @@ -404,40 +415,46 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the { TopoDS_Face face1 = TopoDS::Face(theShape1); TopoDS_Face face2 = TopoDS::Face(theShape2); + TopoDS_Edge edge1, edge2; // get outer edge of theShape1 - TopoDS_Edge edge1 = TopoDS::Edge( OuterShape( face1, TopAbs_EDGE )); + edge1 = TopoDS::Edge( OuterShape( face1, TopAbs_EDGE )); // find out if any edge of face2 is a propagation edge of outer edge1 + map propag_edges; // use map to find the closest propagation edge for ( TopExp_Explorer exp( face2, TopAbs_EDGE ); exp.More(); exp.Next() ) { - TopoDS_Edge edge2 = TopoDS::Edge( exp.Current() ); - edge2 = GetPropagationEdge( theMesh1, edge2, edge1 ); - if ( !edge2.IsNull() ) // propagation found + edge2 = TopoDS::Edge( exp.Current() ); + pair step_edge = GetPropagationEdge( theMesh1, edge2, edge1 ); + if ( !step_edge.second.IsNull() ) { // propagation found + propag_edges.insert( step_edge ); + } + } + if ( !propag_edges.empty() ) // propagation found + { + edge2 = propag_edges.begin()->second; + TopoDS_Vertex VV1[2], VV2[2]; + TopExp::Vertices( edge1, VV1[0], VV1[1], true ); + TopExp::Vertices( edge2, VV2[0], VV2[1], true ); + list< TopoDS_Edge > edges1, edges2; + int nbE = FindFaceAssociation( face1, VV1, face2, VV2, edges1, edges2 ); + if ( !nbE ) RETURN_BAD_RESULT("FindFaceAssociation() failed"); + if ( nbE == 2 ) // only 2 edges { - TopoDS_Vertex VV1[2], VV2[2]; - TopExp::Vertices( edge1, VV1[0], VV1[1], true ); - TopExp::Vertices( edge2, VV2[0], VV2[1], true ); - list< TopoDS_Edge > edges1, edges2; - int nbE = FindFaceAssociation( face1, VV1, face2, VV2, edges1, edges2 ); - if ( !nbE ) RETURN_BAD_RESULT("FindFaceAssociation() failed"); - if ( nbE == 2 ) // only 2 edges - { - // take care of proper association of propagated edges - bool same1 = edge1.IsSame( edges1.front() ); - bool same2 = edge2.IsSame( edges2.front() ); - if ( same1 != same2 ) - Reverse(edges2, nbE); - } - // store association - list< TopoDS_Edge >::iterator eIt1 = edges1.begin(); - list< TopoDS_Edge >::iterator eIt2 = edges2.begin(); - for ( ; eIt1 != edges1.end(); ++eIt1, ++eIt2 ) - { - InsertAssociation( *eIt1, *eIt2, theMap, bidirect); - VV1[0] = TopExp::FirstVertex( *eIt1, true ); - VV2[0] = TopExp::FirstVertex( *eIt2, true ); - InsertAssociation( VV1[0], VV2[0], theMap, bidirect); - } - return true; + // take care of proper association of propagated edges + bool same1 = edge1.IsSame( edges1.front() ); + bool same2 = edge2.IsSame( edges2.front() ); + if ( same1 != same2 ) + Reverse(edges2, nbE); + } + // store association + list< TopoDS_Edge >::iterator eIt1 = edges1.begin(); + list< TopoDS_Edge >::iterator eIt2 = edges2.begin(); + for ( ; eIt1 != edges1.end(); ++eIt1, ++eIt2 ) + { + InsertAssociation( *eIt1, *eIt2, theMap, bidirect); + VV1[0] = TopExp::FirstVertex( *eIt1, true ); + VV2[0] = TopExp::FirstVertex( *eIt2, true ); + InsertAssociation( VV1[0], VV2[0], theMap, bidirect); } + return true; } } break; // try by vertex closeness @@ -567,6 +584,7 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face& face1, list< TopoDS_Edge >::iterator eBackIt; if ( !VV1[1].IsSame( TopExp::LastVertex( edges1.front(), true ))) { + reverse = true; eBackIt = --edges1.end(); // check if the second vertex belongs to the first or last edge in the wire if ( !VV1[1].IsSame( TopExp::FirstVertex( *eBackIt, true ))) { @@ -579,10 +597,10 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face& face1, if ( KO ) RETURN_BAD_RESULT("GetOrderedEdges() failed"); } - reverse = true; } eBackIt = --edges2.end(); if ( !VV2[1].IsSame( TopExp::LastVertex( edges2.front(), true ))) { + reverse = !reverse; // check if the second vertex belongs to the first or last edge in the wire if ( !VV2[1].IsSame( TopExp::FirstVertex( *eBackIt, true ))) { bool KO = true; // belongs to none @@ -594,7 +612,6 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face& face1, if ( KO ) RETURN_BAD_RESULT("GetOrderedEdges() failed"); } - reverse = !reverse; } if ( reverse ) { @@ -761,23 +778,25 @@ TopoDS_Face StdMeshers_ProjectionUtils::GetNextFace( SMESH_Mesh* mesh, * \param aMesh - mesh * \param theEdge - edge to find by propagation * \param fromEdge - start edge for propagation - * \retval TopoDS_Edge - found edge + * \retval pair - propagation step and found edge */ //================================================================================ -TopoDS_Edge StdMeshers_ProjectionUtils::GetPropagationEdge( SMESH_Mesh* aMesh, - const TopoDS_Edge& theEdge, - const TopoDS_Edge& fromEdge) +pair +StdMeshers_ProjectionUtils::GetPropagationEdge( SMESH_Mesh* aMesh, + const TopoDS_Edge& theEdge, + const TopoDS_Edge& fromEdge) { SMESH_IndexedMapOfShape aChain; - //aChain.Add(fromEdge); + int step = 0; // List of edges, added to chain on the previous cycle pass TopTools_ListOfShape listPrevEdges; - listPrevEdges.Append(fromEdge/*.Oriented( TopAbs_FORWARD )*/); + listPrevEdges.Append(fromEdge); // Collect all edges pass by pass while (listPrevEdges.Extent() > 0) { + step++; // List of edges, added to chain on this cycle pass TopTools_ListOfShape listCurEdges; @@ -822,7 +841,7 @@ TopoDS_Edge StdMeshers_ProjectionUtils::GetPropagationEdge( SMESH_Mesh* a ori = TopAbs::Reverse( ori ); anOppE.Orientation( ori ); if ( anOppE.IsSame( theEdge )) - return TopoDS::Edge( anOppE ); + return make_pair( step, TopoDS::Edge( anOppE )); aChain.Add(anOppE); listCurEdges.Append(anOppE); } @@ -834,7 +853,7 @@ TopoDS_Edge StdMeshers_ProjectionUtils::GetPropagationEdge( SMESH_Mesh* a listPrevEdges = listCurEdges; } // while (listPrevEdges.Extent() > 0) - return TopoDS_Edge(); + return make_pair( INT_MAX, TopoDS_Edge()); } //================================================================================ @@ -887,33 +906,50 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, // 1. Nodes of corresponding links: - // get 2 matching edges, not seam ones - TopoDS_Edge edge1, edge2; + // get 2 matching edges, try to find not seam ones + TopoDS_Edge edge1, edge2, seam1, seam2; TopExp_Explorer eE( OuterShape( face2, TopAbs_WIRE ), TopAbs_EDGE ); do { - edge2 = TopoDS::Edge( eE.Current() ); + // edge 2 + TopoDS_Edge e2 = TopoDS::Edge( eE.Current() ); eE.Next(); - } while ( BRep_Tool::IsClosed( edge2, face2 ) && eE.More()); - if ( !assocMap.IsBound( edge2 )) - RETURN_BAD_RESULT("Association not found for edge " << meshDS2->ShapeToIndex( edge2 )); - edge1 = TopoDS::Edge( assocMap( edge2 )); - if ( !IsSubShape( edge1, face1 )) - RETURN_BAD_RESULT("Wrong association, edge " << meshDS1->ShapeToIndex( edge1 ) << - " isn't a subshape of face " << meshDS1->ShapeToIndex( face1 )); + // edge 1 + if ( !assocMap.IsBound( e2 )) + RETURN_BAD_RESULT("Association not found for edge " << meshDS2->ShapeToIndex( e2 )); + TopoDS_Edge e1 = TopoDS::Edge( assocMap( e2 )); + if ( !IsSubShape( e1, face1 )) + RETURN_BAD_RESULT("Wrong association, edge " << meshDS1->ShapeToIndex( e1 ) << + " isn't a subshape of face " << meshDS1->ShapeToIndex( face1 )); + // check that there are nodes on edges + SMESHDS_SubMesh * eSM1 = meshDS1->MeshElements( e1 ); + SMESHDS_SubMesh * eSM2 = meshDS2->MeshElements( e2 ); + if ( eSM1 && eSM2 && eSM1->NbNodes() > 0 && eSM2->NbNodes() > 0 ) + { + if ( BRep_Tool::IsClosed( e2, face2 )) { + seam1 = e1; seam2 = e2; + } + else { + edge1 = e1; edge2 = e2; + } + } + } while ( edge2.IsNull() && eE.More() ); + // + if ( edge2.IsNull() ) { + edge1 = seam1; edge2 = seam2; + } + if ( edge2.IsNull() ) RETURN_BAD_RESULT("No matching edges with nodes found"); // get 2 matching vertices - TopoDS_Shape V2 = TopExp::FirstVertex( TopoDS::Edge( edge2 )); + TopoDS_Vertex V2 = TopExp::FirstVertex( TopoDS::Edge( edge2 )); if ( !assocMap.IsBound( V2 )) RETURN_BAD_RESULT("Association not found for vertex " << meshDS2->ShapeToIndex( V2 )); - TopoDS_Shape V1 = assocMap( V2 ); + TopoDS_Vertex V1 = TopoDS::Vertex( assocMap( V2 )); // nodes on vertices - SMESHDS_SubMesh * vSM1 = meshDS1->MeshElements( V1 ); - SMESHDS_SubMesh * vSM2 = meshDS2->MeshElements( V2 ); - if ( !vSM1 || !vSM2 || vSM1->NbNodes() != 1 || vSM2->NbNodes() != 1 ) - RETURN_BAD_RESULT("Bad node submesh"); - const SMDS_MeshNode* vNode1 = vSM1->GetNodes()->next(); - const SMDS_MeshNode* vNode2 = vSM2->GetNodes()->next(); + const SMDS_MeshNode* vNode1 = SMESH_Algo::VertexNode( V1, meshDS1 ); + const SMDS_MeshNode* vNode2 = SMESH_Algo::VertexNode( V2, meshDS2 ); + if ( !vNode1 ) RETURN_BAD_RESULT("No node on vertex #" << meshDS1->ShapeToIndex( V1 )); + if ( !vNode2 ) RETURN_BAD_RESULT("No node on vertex #" << meshDS2->ShapeToIndex( V2 )); // nodes on edges linked with nodes on vertices const SMDS_MeshNode* nullNode = 0; @@ -976,12 +1012,12 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, const SMDS_MeshElement* faceToKeep = 0; const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1; const SMDS_MeshNode* eNode = is2 ? eNode2[0] : eNode1[0]; - std::map inSet, notInSet; + TIDSortedElemSet inSet, notInSet; const SMDS_MeshElement* f1 = SMESH_MeshEditor::FindFaceInSet( vNode, eNode, inSet, notInSet ); if ( !f1 ) RETURN_BAD_RESULT("The first face on seam not found"); - SMESH_MeshEditor::Insert( f1, notInSet ); + notInSet.insert( f1 ); const SMDS_MeshElement* f2 = SMESH_MeshEditor::FindFaceInSet( vNode, eNode, inSet, notInSet ); @@ -1019,6 +1055,18 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, if ( !onBnd ) elems.insert( f ); } + // add also faces adjacent to faceToKeep + int nbNodes = faceToKeep->NbNodes(); + if ( faceToKeep->IsQuadratic() ) nbNodes /= 2; + notInSet.insert( f1 ); + notInSet.insert( f2 ); + for ( int i = 0; i < nbNodes; ++i ) { + const SMDS_MeshNode* n1 = faceToKeep->GetNode( i ); + const SMDS_MeshNode* n2 = faceToKeep->GetNode( i+1 ); + f1 = SMESH_MeshEditor::FindFaceInSet( n1, n2, inSet, notInSet ); + if ( f1 ) + elems.insert( f1 ); + } } // case on a sphere } // loop on 2 faces @@ -1082,13 +1130,11 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, V2 = TopExp::LastVertex( TopoDS::Edge( edge2 )); if ( !assocMap.IsBound( V2 )) RETURN_BAD_RESULT("Association not found for vertex " << meshDS2->ShapeToIndex( V2 )); - V1 = assocMap( V2 ); - vSM1 = meshDS1->MeshElements( V1 ); - vSM2 = meshDS2->MeshElements( V2 ); - if ( !vSM1 || !vSM2 || vSM1->NbNodes() != 1 || vSM2->NbNodes() != 1 ) - RETURN_BAD_RESULT("Bad node submesh"); - vNode1 = vSM1->GetNodes()->next(); - vNode2 = vSM2->GetNodes()->next(); + V1 = TopoDS::Vertex( assocMap( V2 )); + vNode1 = SMESH_Algo::VertexNode( V1, meshDS1 ); + vNode2 = SMESH_Algo::VertexNode( V2, meshDS2 ); + if ( !vNode1 ) RETURN_BAD_RESULT("No node on vertex #" << meshDS1->ShapeToIndex( V1 )); + if ( !vNode2 ) RETURN_BAD_RESULT("No node on vertex #" << meshDS2->ShapeToIndex( V2 )); node1To2Map.insert( make_pair( vNode1, vNode2 )); } @@ -1128,7 +1174,7 @@ TopoDS_Shape StdMeshers_ProjectionUtils::OuterShape( const TopoDS_Face& face, //================================================================================ /*! - * \brief Check that submeshis is computed and try to compute it if is not + * \brief Check that submesh is computed and try to compute it if is not * \param sm - submesh to compute * \param iterationNb - int used to stop infinite recursive call * \retval bool - true if computed @@ -1221,21 +1267,87 @@ int StdMeshers_ProjectionUtils::Count(const TopoDS_Shape& shape, } } - // bull shit -// Standard_Real f1,l1, f2,l2; -// BRep_Tool::Range( edge1, f1,l1 ); -// BRep_Tool::Range( edge2, f2,l2 ); -// BRepAdaptor_Curve e1( edge1 ), e2( edge2 ); -// gp_Pnt pf1, pf2; -// gp_Vec dirX1, dirX2; // 1st derivatives -// e1.D1( f1, pf1, dirX1 ); -// e2.D1( f2, pf2, dirX2 ); -// gp_Pnt pm1 = e1.Value( 0.5 * ( f1 + l1 )); -// gp_Pnt pm2 = e2.Value( 0.5 * ( f2 + l2 )); -// gp_Vec dirZ1( pf1, pm1 ), dirZ2( pf2, pm2 ); -// gp_Trsf trsf; -// gp_Ax3 fromSys( pf1, dirZ1, dirX1 ), toSys( pf2, dirZ2, dirX2 ); -// trsf.SetTransformation( fromSys, toSys ); -// dirX1.Transform( trsf ); -// bool reverse = ( dirX1 * dirX2 < 0 ); -// if ( reverse ) edge2.Reverse(); +namespace { + + SMESH_subMeshEventListener* GetSrcSubMeshListener(); + + //================================================================================ + /*! + * \brief Listener that resets an event listener on source submesh when + * "ProjectionSource*D" hypothesis is modified + */ + //================================================================================ + + struct HypModifWaiter: SMESH_subMeshEventListener + { + HypModifWaiter():SMESH_subMeshEventListener(0){} // won't be deleted by submesh + + void ProcessEvent(const int event, const int eventType, SMESH_subMesh* subMesh, + EventListenerData*, const SMESH_Hypothesis*) + { + if ( event == SMESH_subMesh::MODIF_HYP && + eventType == SMESH_subMesh::ALGO_EVENT) + { + // delete current source listener + subMesh->DeleteEventListener( GetSrcSubMeshListener() ); + // let algo set a new one + SMESH_Gen* gen = subMesh->GetFather()->GetGen(); + if ( SMESH_Algo* algo = gen->GetAlgo( *subMesh->GetFather(), + subMesh->GetSubShape() )) + algo->SetEventListener( subMesh ); + } + } + }; + //================================================================================ + /*! + * \brief return static HypModifWaiter + */ + //================================================================================ + + SMESH_subMeshEventListener* GetHypModifWaiter() { + static HypModifWaiter aHypModifWaiter; + return &aHypModifWaiter; + } + //================================================================================ + /*! + * \brief return static listener for source shape submeshes + */ + //================================================================================ + + SMESH_subMeshEventListener* GetSrcSubMeshListener() { + static SMESH_subMeshEventListener srcListener(0); // won't be deleted by submesh + return &srcListener; + } +} + +//================================================================================ +/*! + * \brief Set event listeners to submesh with projection algo + * \param subMesh - submesh with projection algo + * \param srcShape - source shape + * \param srcMesh - source mesh + */ +//================================================================================ + +void StdMeshers_ProjectionUtils::SetEventListener(SMESH_subMesh* subMesh, + TopoDS_Shape srcShape, + SMESH_Mesh* srcMesh) +{ + // Set listener that resets an event listener on source submesh when + // "ProjectionSource*D" hypothesis is modified + subMesh->SetEventListener( GetHypModifWaiter(),0,subMesh); + + // Set an event listener to submesh of the source shape + if ( !srcShape.IsNull() ) + { + if ( !srcMesh ) + srcMesh = subMesh->GetFather(); + + SMESH_subMesh* srcShapeSM = srcMesh->GetSubMesh( srcShape ); + + if ( srcShapeSM != subMesh ) + subMesh->SetEventListener( GetSrcSubMeshListener(), + SMESH_subMeshEventListenerData::MakeData( subMesh ), + srcShapeSM ); + } +}