X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_ProjectionUtils.cxx;h=94714a25551a3949b4e0ef4e0074b86071a504e8;hb=43db13f33a1d75fae36db8f06fa378ed7906a332;hp=fbbe297cfc9854f79d97f3e59eb07f13bcd03fc0;hpb=14dd470a5db504fa5956b906a806cd47e505dc12;p=modules%2Fsmesh.git diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx index fbbe297cf..94714a255 100644 --- a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx +++ b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx @@ -1,24 +1,25 @@ -// Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE // -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. // -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + // SMESH SMESH : idl implementation based on 'SMESH' unit's calsses // File : StdMeshers_ProjectionUtils.cxx // Created : Fri Oct 27 10:24:28 2006 @@ -34,15 +35,15 @@ #include "SMESH_Block.hxx" #include "SMESH_Gen.hxx" #include "SMESH_Hypothesis.hxx" -#include "SMESH_IndexedDataMapOfShapeIndexedMapOfShape.hxx" #include "SMESH_Mesh.hxx" -#include "SMESH_MeshEditor.hxx" +#include "SMESH_MesherHelper.hxx" #include "SMESH_subMesh.hxx" #include "SMESH_subMeshEventListener.hxx" #include "SMDS_EdgePosition.hxx" #include "utilities.h" +#include #include #include #include @@ -52,6 +53,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -60,20 +64,22 @@ #include #include #include -#include -#include + +#include using namespace std; #define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; } -#define SHOW_VERTEX(v,msg) // { \ -// if ( v.IsNull() ) cout << msg << " NULL SHAPE" << endl; \ -// else if (v.ShapeType() == TopAbs_VERTEX) {\ -// gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( v ));\ -// cout << msg << (v).TShape().operator->()<<" ( " <()<ShapeToIndex(S), theMeshDS[1]->ShapeToIndex(S) ); + return long(S.TShape().operator->()); + } + //================================================================================ /*! * \brief Write shape for debug purposes @@ -113,31 +127,24 @@ namespace { */ //================================================================================ - void Reverse( list< TopoDS_Edge > & edges, const int nbEdges ) + void Reverse( list< TopoDS_Edge > & edges, const int nbEdges, const int firstEdge=0) { SHOW_LIST("BEFORE REVERSE", edges); list< TopoDS_Edge >::iterator eIt = edges.begin(); - if ( edges.size() == nbEdges ) - { - edges.reverse(); - } - else // reverse only the given nb of edges + std::advance( eIt, firstEdge ); + list< TopoDS_Edge >::iterator eBackIt = eIt; + for ( int i = 0; i < nbEdges; ++i, ++eBackIt ) + eBackIt->Reverse(); // reverse edge + // reverse list + --eBackIt; + while ( eIt != eBackIt ) { - // look for the last edge to be reversed - list< TopoDS_Edge >::iterator eBackIt = edges.begin(); - for ( int i = 1; i < nbEdges; ++i ) - ++eBackIt; - // reverse - while ( eIt != eBackIt ) { - std::swap( *eIt, *eBackIt ); - SHOW_LIST("# AFTER SWAP", edges) + std::swap( *eIt, *eBackIt ); + SHOW_LIST("# AFTER SWAP", edges) if ( (++eIt) != eBackIt ) --eBackIt; - } } - for ( eIt = edges.begin(); eIt != edges.end(); ++eIt ) - eIt->Reverse(); SHOW_LIST("ATFER REVERSE", edges) } @@ -300,11 +307,7 @@ namespace { if ( gr1It.Value().ShapeType() == TopAbs_FACE ) { // find a boundary edge of group1 to start from - TopoDS_Shape bndEdge; - TopExp_Explorer edgeExp1( theGroup1, TopAbs_EDGE ); - for ( ; bndEdge.IsNull() && edgeExp1.More(); edgeExp1.Next()) - if ( HERE::IsBoundaryEdge( TopoDS::Edge( edgeExp1.Current()), theGroup1, theMesh )) - bndEdge = edgeExp1.Current(); + TopoDS_Shape bndEdge = StdMeshers_ProjectionUtils::GetBoundaryEdge( theGroup1, theMesh ); if ( bndEdge.IsNull() ) return false; @@ -348,11 +351,73 @@ namespace { return true; } + //================================================================================ + /*! + * \brief Return true if uv position of the vIndex-th vertex of edge on face is close + * enough to given uv + */ + //================================================================================ + + bool sameVertexUV( const TopoDS_Edge& edge, + const TopoDS_Face& face, + const int& vIndex, + const gp_Pnt2d& uv, + const double& tol2d ) + { + TopoDS_Vertex VV[2]; + TopExp::Vertices( edge, VV[0], VV[1], true); + gp_Pnt2d v1UV = BRep_Tool::Parameters( VV[vIndex], face); + double dist2d = v1UV.Distance( uv ); + return dist2d < tol2d; + } + + //================================================================================ + /*! + * \brief Returns an EDGE suitable for search of initial vertex association + */ + //================================================================================ + + TopoDS_Shape getOuterEdge( const TopoDS_Shape theShape1, SMESH_Mesh& mesh ) + { + TopoDS_Shape edge; + if ( theShape1.ShapeType() == TopAbs_COMPOUND ) + { + TopoDS_Iterator it( theShape1 ); + if ( it.Value().ShapeType() == TopAbs_FACE ) // group of FACEs + { + // look for a boundary EDGE of a group + edge = StdMeshers_ProjectionUtils::GetBoundaryEdge( theShape1, mesh ); + if ( !edge.IsNull() ) + return edge; + } + } + edge = theShape1; + TopExp_Explorer expF( theShape1, TopAbs_FACE ), expE; + if ( expF.More() ) { + for ( ; expF.More(); expF.Next() ) { + edge.Nullify(); + TopoDS_Shape wire = + StdMeshers_ProjectionUtils::OuterShape( TopoDS::Face( expF.Current() ), TopAbs_WIRE ); + for ( expE.Init( wire, TopAbs_EDGE ); edge.IsNull() && expE.More(); expE.Next() ) + if ( !SMESH_MesherHelper::IsClosedEdge( TopoDS::Edge( expE.Current() ))) + edge = expE.Current(); + if ( !edge.IsNull() ) + break; + } + } else if (edge.ShapeType() != TopAbs_EDGE) { // no faces + edge.Nullify(); + for ( expE.Init( theShape1, TopAbs_EDGE ); edge.IsNull() && expE.More(); expE.Next() ) + if ( !SMESH_MesherHelper::IsClosedEdge( TopoDS::Edge( expE.Current() ))) + edge = expE.Current(); + } + return edge; + } + } // namespace //======================================================================= /*! - * \brief Looks for association of all subshapes of two shapes + * \brief Looks for association of all sub-shapes of two shapes * \param theShape1 - shape 1 * \param theMesh1 - mesh built on shape 1 * \param theShape2 - shape 2 @@ -369,8 +434,31 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the SMESH_Mesh* theMesh2, TShapeShapeMap & theMap) { + // Structure of this long function is following + // 1) Group->group projection: theShape1 is a group member, + // theShape2 is a group. We find a group theShape1 is in and recall self. + // 2) Accosiate same shapes with different location (partners). + // 3) If vertex association is given, perform accosiation according to shape type: + // switch ( ShapeType ) { + // case TopAbs_EDGE: + // case ...: + // } + // 4) else try to accosiate in different ways: + // a) accosiate shapes by propagation and other simple cases + // switch ( ShapeType ) { + // case TopAbs_EDGE: + // case ...: + // } + // b) find association of a couple of vertices and recall self. + // + + theMeshDS[0] = theMesh1->GetMeshDS(); // debug + theMeshDS[1] = theMesh2->GetMeshDS(); + + // ================================================================================= + // 1) Is it the case of associating a group member -> another group? (PAL16202, 16203) + // ================================================================================= if ( theShape1.ShapeType() != theShape2.ShapeType() ) { - // is it the case of a group member -> another group? (PAL16202, 16203) TopoDS_Shape group1, group2; if ( theShape1.ShapeType() == TopAbs_COMPOUND ) { group1 = theShape1; @@ -387,10 +475,35 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the } bool bidirect = ( !theShape1.IsSame( theShape2 )); + + // ============ + // 2) Is partner? + // ============ + bool partner = theShape1.IsPartner( theShape2 ); + TopTools_DataMapIteratorOfDataMapOfShapeShape vvIt( theMap ); + for ( ; partner && vvIt.More(); vvIt.Next() ) + partner = vvIt.Key().IsPartner( vvIt.Value() ); + + if ( partner ) // Same shape with different location + { + // recursively associate all sub-shapes of theShape1 and theShape2 + typedef list< pair< TopoDS_Shape, TopoDS_Shape > > TShapePairsList; + TShapePairsList shapesQueue( 1, make_pair( theShape1, theShape2 )); + TShapePairsList::iterator s1_s2 = shapesQueue.begin(); + for ( ; s1_s2 != shapesQueue.end(); ++s1_s2 ) + { + InsertAssociation( s1_s2->first, s1_s2->second, theMap, bidirect); + TopoDS_Iterator s1It( s1_s2->first), s2It( s1_s2->second ); + for ( ; s1It.More(); s1It.Next(), s2It.Next() ) + shapesQueue.push_back( make_pair( s1It.Value(), s2It.Value() )); + } + return true; + } + if ( !theMap.IsEmpty() ) { //====================================================================== - // HAS initial vertex association + // 3) HAS initial vertex association //====================================================================== switch ( theShape1.ShapeType() ) { // ---------------------------------------------------------------------- @@ -400,6 +513,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the RETURN_BAD_RESULT("Wrong map extent " << theMap.Extent() ); TopoDS_Edge edge1 = TopoDS::Edge( theShape1 ); TopoDS_Edge edge2 = TopoDS::Edge( theShape2 ); + if ( edge1.Orientation() >= TopAbs_INTERNAL ) edge1.Orientation( TopAbs_FORWARD ); + if ( edge2.Orientation() >= TopAbs_INTERNAL ) edge2.Orientation( TopAbs_FORWARD ); TopoDS_Vertex VV1[2], VV2[2]; TopExp::Vertices( edge1, VV1[0], VV1[1] ); TopExp::Vertices( edge2, VV2[0], VV2[1] ); @@ -415,6 +530,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the // ---------------------------------------------------------------------- TopoDS_Face face1 = TopoDS::Face( theShape1 ); TopoDS_Face face2 = TopoDS::Face( theShape2 ); + if ( face1.Orientation() >= TopAbs_INTERNAL ) face1.Orientation( TopAbs_FORWARD ); + if ( face2.Orientation() >= TopAbs_INTERNAL ) face2.Orientation( TopAbs_FORWARD ); TopoDS_Vertex VV1[2], VV2[2]; // find a not closed edge of face1 both vertices of which are associated @@ -462,6 +579,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the TopExp_Explorer exp ( theShape1, TopAbs_EDGE ); for ( ; VV2[ 1 ].IsNull() && exp.More(); exp.Next() ) { edge1 = TopoDS::Edge( exp.Current() ); + if ( edge1.Orientation() >= TopAbs_INTERNAL ) edge1.Orientation( TopAbs_FORWARD ); TopExp::Vertices( edge1 , VV1[0], VV1[1] ); if ( theMap.IsBound( VV1[0] )) { VV2[ 0 ] = TopoDS::Vertex( theMap( VV1[0] )); @@ -476,7 +594,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the if ( edge2.IsNull() ) RETURN_BAD_RESULT("GetEdgeByVertices() failed"); - // build map of edge to faces if shapes are not subshapes of main ones + // build map of edge to faces if shapes are not sub-shapes of main ones bool isSubOfMain = false; if ( SMESHDS_SubMesh * sm = theMesh1->GetMeshDS()->MeshElements( theShape1 )) isSubOfMain = !sm->IsComplexSubmesh(); @@ -539,7 +657,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the TopTools_MapOfShape boundEdges; - // association of face subshapes and neighbour faces + // association of face sub-shapes and neighbour faces list< pair < TopoDS_Face, TopoDS_Edge > > FE1, FE2; list< pair < TopoDS_Face, TopoDS_Edge > >::iterator fe1, fe2; FE1.push_back( make_pair( TopoDS::Face( F1 ), edge1 )); @@ -625,7 +743,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the if ( !initAssocOK ) { // for shell association there must be an edge with both vertices bound TopoDS_Vertex v1, v2; - TopExp::Vertices( TopoDS::Edge( it1.Value()), v1, v2 ); + TopExp::Vertices( TopoDS::Edge( it1.Value().Oriented(TopAbs_FORWARD)), v1, v2 ); initAssocOK = ( theMap.IsBound( v1 ) && theMap.IsBound( v2 )); } } @@ -828,7 +946,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the } // end case of available initial vertex association //====================================================================== - // NO INITIAL VERTEX ASSOCIATION + // 4) NO INITIAL VERTEX ASSOCIATION //====================================================================== switch ( theShape1.ShapeType() ) { @@ -856,7 +974,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the return true; // done } } - if ( IsClosedEdge( edge1 ) && IsClosedEdge( edge2 )) + if ( SMESH_MesherHelper::IsClosedEdge( edge1 ) && + SMESH_MesherHelper::IsClosedEdge( edge2 )) { // TODO: find out a proper orientation (is it possible?) InsertAssociation( edge1, edge2, theMap, bidirect); // insert with a proper orientation @@ -874,6 +993,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the { TopoDS_Face face1 = TopoDS::Face(theShape1); TopoDS_Face face2 = TopoDS::Face(theShape2); + if ( face1.Orientation() >= TopAbs_INTERNAL ) face1.Orientation( TopAbs_FORWARD ); + if ( face2.Orientation() >= TopAbs_INTERNAL ) face2.Orientation( TopAbs_FORWARD ); TopoDS_Edge edge1, edge2; // get outer edge of theShape1 edge1 = TopoDS::Edge( OuterShape( face1, TopAbs_EDGE )); @@ -884,6 +1005,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the pair step_edge = GetPropagationEdge( theMesh1, edge2, edge1 ); if ( !step_edge.second.IsNull() ) { // propagation found propag_edges.insert( step_edge ); + if ( step_edge.first == 1 ) break; // most close found } } if ( !propag_edges.empty() ) // propagation found @@ -895,13 +1017,14 @@ 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"); - 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 ) { - // 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); + Reverse(edges2, nbE); + if ( nbE != 2 ) // 2 degen edges of 4 (issue 0021144) + edges2.splice( edges2.end(), edges2, edges2.begin()); } // store association list< TopoDS_Edge >::iterator eIt1 = edges1.begin(); @@ -927,15 +1050,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the if ( AssocGroupsByPropagation( theShape1, theShape2, *theMesh1, theMap )) return true; - // find a boundary edge for theShape1 - TopoDS_Edge E; - for(TopExp_Explorer exp(theShape1, TopAbs_EDGE); exp.More(); exp.Next() ) { - E = TopoDS::Edge( exp.Current() ); - if ( IsBoundaryEdge( E, theShape1, *theMesh1 )) - break; - else - E.Nullify(); - } + // find a boundary edge of theShape1 + TopoDS_Edge E = GetBoundaryEdge( theShape1, *theMesh1 ); if ( E.IsNull() ) break; // try by vertex closeness @@ -993,12 +1109,13 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the default:; } - // Find association by closeness of vertices - // ------------------------------------------ + // 4.b) Find association by closeness of vertices + // ---------------------------------------------- TopTools_IndexedMapOfShape vMap1, vMap2; TopExp::MapShapes( theShape1, TopAbs_VERTEX, vMap1 ); TopExp::MapShapes( theShape2, TopAbs_VERTEX, vMap2 ); + TopoDS_Vertex VV1[2], VV2[2]; if ( vMap1.Extent() != vMap2.Extent() ) RETURN_BAD_RESULT("Different nb of vertices"); @@ -1012,6 +1129,32 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the return FindSubShapeAssociation( theShape1, theMesh1, theShape2, theMesh2, theMap); } + // Try to associate by common vertices of an edge + for ( int i = 1; i <= vMap1.Extent(); ++i ) + { + const TopoDS_Shape& v1 = vMap1(i); + if ( vMap2.Contains( v1 )) + { + // find an egde sharing v1 and sharing at the same time another common vertex + PShapeIteratorPtr edgeIt = SMESH_MesherHelper::GetAncestors( v1, *theMesh1, TopAbs_EDGE); + bool edgeFound = false; + while ( edgeIt->more() && !edgeFound ) + { + TopoDS_Edge edge = TopoDS::Edge( edgeIt->next()->Oriented(TopAbs_FORWARD)); + TopExp::Vertices(edge, VV1[0], VV1[1]); + if ( !VV1[0].IsSame( VV1[1] )) + edgeFound = ( vMap2.Contains( VV1[ v1.IsSame(VV1[0]) ? 1:0])); + } + if ( edgeFound ) + { + InsertAssociation( VV1[0], VV1[0], theMap, bidirect ); + InsertAssociation( VV1[1], VV1[1], theMap, bidirect ); + if (FindSubShapeAssociation( theShape1, theMesh1, theShape2, theMesh2, theMap )) + return true; + } + } + } + // Find transformation to make the shapes be of similar size at same location Bnd_Box box[2]; @@ -1033,30 +1176,12 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the // Find 2 closest vertices - TopoDS_Vertex VV1[2], VV2[2]; // get 2 linked vertices of shape 1 not belonging to an inner wire of a face - TopoDS_Shape edge = theShape1; - TopExp_Explorer expF( theShape1, TopAbs_FACE ), expE; - if ( expF.More() ) { - for ( ; expF.More(); expF.Next() ) { - edge.Nullify(); - TopoDS_Shape wire = OuterShape( TopoDS::Face( expF.Current() ), TopAbs_WIRE ); - for ( expE.Init( wire, TopAbs_EDGE ); edge.IsNull() && expE.More(); expE.Next() ) - if ( !IsClosedEdge( TopoDS::Edge( expE.Current() ))) - edge = expE.Current(); - if ( !edge.IsNull() ) - break; - } - } else if (edge.ShapeType() != TopAbs_EDGE) { // no faces - edge.Nullify(); - for ( expE.Init( theShape1, TopAbs_EDGE ); edge.IsNull() && expE.More(); expE.Next() ) - if ( !IsClosedEdge( TopoDS::Edge( expE.Current() ))) - edge = expE.Current(); - } + TopoDS_Shape edge = getOuterEdge( theShape1, *theMesh1 ); if ( edge.IsNull() || edge.ShapeType() != TopAbs_EDGE ) RETURN_BAD_RESULT("Edge not found"); - TopExp::Vertices( TopoDS::Edge( edge ), VV1[0], VV1[1]); + TopExp::Vertices( TopoDS::Edge( edge.Oriented(TopAbs_FORWARD)), VV1[0], VV1[1]); if ( VV1[0].IsSame( VV1[1] )) RETURN_BAD_RESULT("Only closed edges"); @@ -1105,68 +1230,146 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the */ //================================================================================ -int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face& face1, - TopoDS_Vertex VV1[2], - const TopoDS_Face& face2, - TopoDS_Vertex VV2[2], +int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face& face1, + TopoDS_Vertex VV1[2], + const TopoDS_Face& face2, + TopoDS_Vertex VV2[2], list< TopoDS_Edge > & edges1, list< TopoDS_Edge > & edges2) { - edges1.clear(); - edges2.clear(); - - list< int > nbVInW1, nbVInW2; - if ( SMESH_Block::GetOrderedEdges( face1, VV1[0], edges1, nbVInW1) != - SMESH_Block::GetOrderedEdges( face2, VV2[0], edges2, nbVInW2) ) - RETURN_BAD_RESULT("Different number of wires in faces "); - - if ( nbVInW1.front() != nbVInW2.front() ) - RETURN_BAD_RESULT("Different number of edges in faces: " << - nbVInW1.front() << " != " << nbVInW2.front()); - - // Define if we need to reverse one of wires to make edges in lists match each other - - bool reverse = false; - - 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 ))) { - bool KO = true; // belongs to none - if ( nbVInW1.size() > 1 ) { // several wires - eBackIt = edges1.begin(); - for ( int i = 1; i < nbVInW1.front(); ++i ) ++eBackIt; - KO = !VV1[1].IsSame( TopExp::FirstVertex( *eBackIt, true )); + bool OK = false; + list< int > nbEInW1, nbEInW2; + int i_ok_wire_algo = -1; + for ( int outer_wire_algo = 0; outer_wire_algo < 2 && !OK; ++outer_wire_algo ) + { + edges1.clear(); + edges2.clear(); + + if ( SMESH_Block::GetOrderedEdges( face1, VV1[0], edges1, nbEInW1, outer_wire_algo) != + SMESH_Block::GetOrderedEdges( face2, VV2[0], edges2, nbEInW2, outer_wire_algo) ) + CONT_BAD_RESULT("Different number of wires in faces "); + + if ( nbEInW1 != nbEInW2 ) + CONT_BAD_RESULT("Different number of edges in faces: " << + nbEInW1.front() << " != " << nbEInW2.front()); + + i_ok_wire_algo = outer_wire_algo; + + // Define if we need to reverse one of wires to make edges in lists match each other + + bool reverse = false; + + list< TopoDS_Edge >::iterator edgeIt; + if ( !VV1[1].IsSame( TopExp::LastVertex( edges1.front(), true ))) { + reverse = true; + edgeIt = --edges1.end(); + // check if the second vertex belongs to the first or last edge in the wire + if ( !VV1[1].IsSame( TopExp::FirstVertex( *edgeIt, true ))) { + bool KO = true; // belongs to none + if ( nbEInW1.size() > 1 ) { // several wires + edgeIt = edges1.begin(); + std::advance( edgeIt, nbEInW1.front()-1 ); + KO = !VV1[1].IsSame( TopExp::FirstVertex( *edgeIt, true )); + } + if ( KO ) + CONT_BAD_RESULT("GetOrderedEdges() failed"); } - if ( KO ) - RETURN_BAD_RESULT("GetOrderedEdges() failed"); } - } - 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 - if ( nbVInW2.size() > 1 ) { // several wires - eBackIt = edges2.begin(); - for ( int i = 1; i < nbVInW2.front(); ++i ) ++eBackIt; - KO = !VV2[1].IsSame( TopExp::FirstVertex( *eBackIt, true )); + edgeIt = --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( *edgeIt, true ))) { + bool KO = true; // belongs to none + if ( nbEInW2.size() > 1 ) { // several wires + edgeIt = edges2.begin(); + std::advance( edgeIt, nbEInW2.front()-1 ); + KO = !VV2[1].IsSame( TopExp::FirstVertex( *edgeIt, true )); + } + if ( KO ) + CONT_BAD_RESULT("GetOrderedEdges() failed"); } - if ( KO ) - RETURN_BAD_RESULT("GetOrderedEdges() failed"); } - } - if ( reverse ) + if ( reverse ) + { + Reverse( edges2 , nbEInW2.front()); + if (( VV1[1].IsSame( TopExp::LastVertex( edges1.front(), true ))) != + ( VV2[1].IsSame( TopExp::LastVertex( edges2.front(), true )))) + CONT_BAD_RESULT("GetOrderedEdges() failed"); + } + OK = true; + + } // loop algos getting an outer wire + + // Try to orient all (if !OK) or only internal wires (issue 0020996) by UV similarity + if (( !OK || nbEInW1.size() > 1 ) && i_ok_wire_algo > -1 ) { - Reverse( edges2 , nbVInW2.front()); - if (( VV1[1].IsSame( TopExp::LastVertex( edges1.front(), true ))) != - ( VV2[1].IsSame( TopExp::LastVertex( edges2.front(), true )))) - RETURN_BAD_RESULT("GetOrderedEdges() failed"); + // Check that Vec(VV1[0],VV1[1]) in 2D on face1 is the same + // as Vec(VV2[0],VV2[1]) on face2 + double vTol = BRep_Tool::Tolerance( VV1[0] ); + BRepAdaptor_Surface surface1( face1, false ); + double vTolUV = + surface1.UResolution( vTol ) + surface1.VResolution( vTol ); // let's be tolerant + gp_Pnt2d v0f1UV = BRep_Tool::Parameters( VV1[0], face1 ); + gp_Pnt2d v0f2UV = BRep_Tool::Parameters( VV2[0], face2 ); + gp_Pnt2d v1f1UV = BRep_Tool::Parameters( VV1[1], face1 ); + gp_Pnt2d v1f2UV = BRep_Tool::Parameters( VV2[1], face2 ); + gp_Vec2d v01f1Vec( v0f1UV, v1f1UV ); + gp_Vec2d v01f2Vec( v0f2UV, v1f2UV ); + if ( Abs( v01f1Vec.X()-v01f2Vec.X()) < vTolUV && + Abs( v01f1Vec.Y()-v01f2Vec.Y()) < vTolUV ) + { + if ( !OK /*i_ok_wire_algo != 1*/ ) + { + edges1.clear(); + edges2.clear(); + SMESH_Block::GetOrderedEdges( face1, VV1[0], edges1, nbEInW1, i_ok_wire_algo); + SMESH_Block::GetOrderedEdges( face2, VV2[0], edges2, nbEInW2, i_ok_wire_algo); + } + gp_XY dUV = v0f2UV.XY() - v0f1UV.XY(); // UV shift between 2 faces + // skip edges of the outer wire (if the outer wire is OK) + list< int >::iterator nbEInW = nbEInW1.begin(); + list< TopoDS_Edge >::iterator edge1Beg = edges1.begin(), edge2Beg = edges2.begin(); + if ( OK ) + { + for ( int i = 0; i < *nbEInW; ++i ) + ++edge1Beg, ++edge2Beg; + ++nbEInW; + } + for ( ; nbEInW != nbEInW1.end(); ++nbEInW ) // loop on wires + { + // reach an end of edges of a current wire + list< TopoDS_Edge >::iterator edge1End = edge1Beg, edge2End = edge2Beg; + for ( int i = 0; i < *nbEInW; ++i ) + ++edge1End, ++edge2End; + // rotate edges2 untill coincident with edges1 in 2D + v0f1UV = BRep_Tool::Parameters( TopExp::FirstVertex(*edge1Beg,true), face1 ); + v1f1UV = BRep_Tool::Parameters( TopExp::LastVertex (*edge1Beg,true), face1 ); + v0f1UV.ChangeCoord() += dUV; + v1f1UV.ChangeCoord() += dUV; + int i = *nbEInW; + while ( --i > 0 && !sameVertexUV( *edge2Beg, face2, 0, v0f1UV, vTolUV )) + edges2.splice( edge2End, edges2, edge2Beg++ ); // move edge2Beg to place before edge2End + if ( sameVertexUV( *edge2Beg, face2, 0, v0f1UV, vTolUV )) + { + if ( nbEInW == nbEInW1.begin() ) + OK = true; // OK is for the first wire + // reverse edges2 if needed + if ( !sameVertexUV( *edge2Beg, face2, 1, v1f1UV, vTolUV )) + { + Reverse( edges2 , *nbEInW, distance( edges2.begin(),edge2Beg )); + // set correct edge2End + edge2End = edges2.begin(); + std::advance( edge2End, std::accumulate( nbEInW1.begin(), nbEInW, *nbEInW)); + } + } + // prepare to the next wire loop + edge1Beg = edge1End, edge2Beg = edge2End; + } + } } - return nbVInW2.front(); + + return OK ? nbEInW1.front() : 0; } //======================================================================= @@ -1219,8 +1422,8 @@ bool StdMeshers_ProjectionUtils::InsertAssociation( const TopoDS_Shape& theShape const bool theBidirectional) { if ( !theShape1.IsNull() && !theShape2.IsNull() ) { - SHOW_VERTEX(theShape1,"Assoc "); - SHOW_VERTEX(theShape2," to "); + SHOW_SHAPE(theShape1,"Assoc "); + SHOW_SHAPE(theShape2," to "); bool isNew = ( theAssociationMap.Bind( theShape1, theShape2 )); if ( theBidirectional ) theAssociationMap.Bind( theShape2, theShape1 ); @@ -1232,44 +1435,6 @@ bool StdMeshers_ProjectionUtils::InsertAssociation( const TopoDS_Shape& theShape return false; } -//======================================================================= -//function : IsSubShape -//purpose : -//======================================================================= - -bool StdMeshers_ProjectionUtils::IsSubShape( const TopoDS_Shape& shape, - SMESH_Mesh* aMesh ) -{ - if ( shape.IsNull() || !aMesh ) - return false; - return - aMesh->GetMeshDS()->ShapeToIndex( shape ) || - // PAL16202 - shape.ShapeType() == TopAbs_COMPOUND && aMesh->GetMeshDS()->IsGroupOfSubShapes( shape ); -} - -//======================================================================= -//function : IsSubShape -//purpose : -//======================================================================= - -bool StdMeshers_ProjectionUtils::IsSubShape( const TopoDS_Shape& shape, - const TopoDS_Shape& mainShape ) -{ - if ( !shape.IsNull() && !mainShape.IsNull() ) - { - for ( TopExp_Explorer exp( mainShape, shape.ShapeType()); - exp.More(); - exp.Next() ) - if ( shape.IsSame( exp.Current() )) - return true; - } - SCRUTE((shape.IsNull())); - SCRUTE((mainShape.IsNull())); - return false; -} - - //======================================================================= /*! * \brief Finds an edge by its vertices in a main shape of the mesh @@ -1355,7 +1520,7 @@ StdMeshers_ProjectionUtils::GetPropagationEdge( SMESH_Mesh* aMesh, const TopoDS_Edge& theEdge, const TopoDS_Edge& fromEdge) { - SMESH_IndexedMapOfShape aChain; + TopTools_IndexedMapOfShape aChain; int step = 0; // List of edges, added to chain on the previous cycle pass @@ -1431,7 +1596,7 @@ StdMeshers_ProjectionUtils::GetPropagationEdge( SMESH_Mesh* aMesh, * \param mesh1 - mesh containing elements on the first face * \param face2 - the second face * \param mesh2 - mesh containing elements on the second face - * \param assocMap - map associating subshapes of the faces + * \param assocMap - map associating sub-shapes of the faces * \param node1To2Map - map containing found matching nodes * \retval bool - is a success */ @@ -1485,9 +1650,9 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, 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 )) + if ( !helper1.IsSubShape( e1, face1 )) RETURN_BAD_RESULT("Wrong association, edge " << meshDS1->ShapeToIndex( e1 ) << - " isn't a subshape of face " << meshDS1->ShapeToIndex( face1 )); + " isn't a sub-shape of face " << meshDS1->ShapeToIndex( face1 )); // check that there are nodes on edges SMESHDS_SubMesh * eSM1 = meshDS1->MeshElements( e1 ); SMESHDS_SubMesh * eSM2 = meshDS2->MeshElements( e2 ); @@ -1543,7 +1708,7 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, if ( hasNodesOnEdge ) { int nbNodeToGet = 1; - if ( IsClosedEdge( edge1 ) || IsClosedEdge( edge2 ) ) + if ( helper1.IsClosedEdge( edge1 ) || helper2.IsClosedEdge( edge2 ) ) nbNodeToGet = 2; for ( int is2 = 0; is2 < 2; ++is2 ) { @@ -1631,7 +1796,7 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, const SMDS_MeshElement* f = ( iF ? f2 : f1 ); for ( int i = 0; !notSeamNode[ iF ] && i < f->NbNodes(); ++i ) { const SMDS_MeshNode* node = f->GetNode( i ); - if ( !helper->IsSeamShape( node->GetPosition()->GetShapeId() )) + if ( !helper->IsSeamShape( node->getshapeId() )) notSeamNode[ iF ] = node; } } @@ -1664,7 +1829,7 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, 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 ); + const SMDS_MeshNode* n2 = faceToKeep->GetNode(( i+1 ) % nbNodes ); f1 = SMESH_MeshEditor::FindFaceInSet( n1, n2, inSet, notInSet ); if ( f1 ) elems.insert( f1 ); @@ -1699,7 +1864,7 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, while ( nIt->more() ) { const SMDS_MeshNode* node = nIt->next(); const SMDS_EdgePosition* pos = - static_cast(node->GetPosition().get()); + static_cast(node->GetPosition()); pos2nodes.insert( make_pair( pos->GetUParameter(), node )); } if ( pos2nodes.size() != edgeSM->NbNodes() ) @@ -1751,25 +1916,12 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, return true; } -//================================================================================ -/*! - * \brief Check if the first and last vertices of an edge are the same - * \param anEdge - the edge to check - * \retval bool - true if same - */ -//================================================================================ - -bool StdMeshers_ProjectionUtils::IsClosedEdge( const TopoDS_Edge& anEdge ) -{ - return TopExp::FirstVertex( anEdge ).IsSame( TopExp::LastVertex( anEdge )); -} - //================================================================================ /*! - * \brief Return any subshape of a face belonging to the outer wire + * \brief Return any sub-shape of a face belonging to the outer wire * \param face - the face - * \param type - type of subshape to return - * \retval TopoDS_Shape - the found subshape + * \param type - type of sub-shape to return + * \retval TopoDS_Shape - the found sub-shape */ //================================================================================ @@ -1802,7 +1954,7 @@ bool StdMeshers_ProjectionUtils::MakeComputed(SMESH_subMesh * sm, const int iter SMESH_Mesh* mesh = sm->GetFather(); SMESH_Gen* gen = mesh->GetGen(); - SMESH_Algo* algo = gen->GetAlgo( *mesh, sm->GetSubShape() ); + SMESH_Algo* algo = sm->GetAlgo(); if ( !algo ) { if ( sm->GetSubShape().ShapeType() != TopAbs_COMPOUND ) @@ -1866,9 +2018,9 @@ bool StdMeshers_ProjectionUtils::MakeComputed(SMESH_subMesh * sm, const int iter //================================================================================ /*! - * \brief Count nb of subshapes + * \brief Count nb of sub-shapes * \param shape - the shape - * \param type - the type of subshapes to count + * \param type - the type of sub-shapes to count * \retval int - the calculated number */ //================================================================================ @@ -1892,33 +2044,35 @@ int StdMeshers_ProjectionUtils::Count(const TopoDS_Shape& shape, //================================================================================ /*! - * \brief Return true if edge is a boundary of edgeContainer + * \brief Return a boundary EDGE of edgeContainer */ //================================================================================ -bool StdMeshers_ProjectionUtils::IsBoundaryEdge(const TopoDS_Edge& edge, - const TopoDS_Shape& edgeContainer, - SMESH_Mesh& mesh) +TopoDS_Edge StdMeshers_ProjectionUtils::GetBoundaryEdge(const TopoDS_Shape& edgeContainer, + const SMESH_Mesh& mesh) { TopTools_IndexedMapOfShape facesOfEdgeContainer, facesNearEdge; TopExp::MapShapes( edgeContainer, TopAbs_FACE, facesOfEdgeContainer ); - const TopTools_ListOfShape& EAncestors = mesh.GetAncestors(edge); - TopTools_ListIteratorOfListOfShape itea(EAncestors); - for(; itea.More(); itea.Next()) { - if( itea.Value().ShapeType() == TopAbs_FACE && - facesOfEdgeContainer.Contains( itea.Value() )) + if ( !facesOfEdgeContainer.IsEmpty() ) + for ( TopExp_Explorer exp(edgeContainer, TopAbs_EDGE); exp.More(); exp.Next() ) { - facesNearEdge.Add( itea.Value() ); - if ( facesNearEdge.Extent() > 1 ) - return false; + const TopoDS_Edge& edge = TopoDS::Edge( exp.Current() ); + facesNearEdge.Clear(); + PShapeIteratorPtr faceIt = SMESH_MesherHelper::GetAncestors( edge, mesh, TopAbs_FACE ); + while ( const TopoDS_Shape* face = faceIt->next() ) + if ( facesOfEdgeContainer.Contains( *face )) + if ( facesNearEdge.Add( *face ) && facesNearEdge.Extent() > 1 ) + break; + if ( facesNearEdge.Extent() == 1 ) + return edge; } - } - return ( facesNearEdge.Extent() == 1 ); + + return TopoDS_Edge(); } -namespace { +namespace { // Definition of event listeners SMESH_subMeshEventListener* GetSrcSubMeshListener(); @@ -1931,8 +2085,8 @@ namespace { struct HypModifWaiter: SMESH_subMeshEventListener { - HypModifWaiter():SMESH_subMeshEventListener(0){} // won't be deleted by submesh - + HypModifWaiter():SMESH_subMeshEventListener(false,// won't be deleted by submesh + "StdMeshers_ProjectionUtils::HypModifWaiter") {} void ProcessEvent(const int event, const int eventType, SMESH_subMesh* subMesh, EventListenerData*, const SMESH_Hypothesis*) { @@ -1942,9 +2096,7 @@ namespace { // 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() )) + if ( SMESH_Algo* algo = subMesh->GetAlgo() ) algo->SetEventListener( subMesh ); } } @@ -1966,7 +2118,8 @@ namespace { //================================================================================ SMESH_subMeshEventListener* GetSrcSubMeshListener() { - static SMESH_subMeshEventListener srcListener(0); // won't be deleted by submesh + static SMESH_subMeshEventListener srcListener(false, // won't be deleted by submesh + "StdMeshers_ProjectionUtils::SrcSubMeshListener"); return &srcListener; } } @@ -1985,7 +2138,7 @@ void StdMeshers_ProjectionUtils::SetEventListener(SMESH_subMesh* subMesh, SMESH_Mesh* srcMesh) { // Set listener that resets an event listener on source submesh when - // "ProjectionSource*D" hypothesis is modified + // "ProjectionSource*D" hypothesis is modified since source shape can be changed subMesh->SetEventListener( GetHypModifWaiter(),0,subMesh); // Set an event listener to submesh of the source shape @@ -2000,18 +2153,21 @@ void StdMeshers_ProjectionUtils::SetEventListener(SMESH_subMesh* subMesh, if ( srcShapeSM->GetSubMeshDS() && srcShapeSM->GetSubMeshDS()->IsComplexSubmesh() ) { // source shape is a group - TopExp_Explorer it(srcShapeSM->GetSubShape(), // explore the group into subshapes... + TopExp_Explorer it(srcShapeSM->GetSubShape(), // explore the group into sub-shapes... subMesh->GetSubShape().ShapeType()); // ...of target shape type for (; it.More(); it.Next()) { SMESH_subMesh* srcSM = srcMesh->GetSubMesh( it.Current() ); - SMESH_subMeshEventListenerData* data = - srcSM->GetEventListenerData(GetSrcSubMeshListener()); - if ( data ) - data->mySubMeshes.push_back( subMesh ); - else - data = SMESH_subMeshEventListenerData::MakeData( subMesh ); - subMesh->SetEventListener ( GetSrcSubMeshListener(), data, srcSM ); + if ( srcSM != subMesh ) + { + SMESH_subMeshEventListenerData* data = + srcSM->GetEventListenerData(GetSrcSubMeshListener()); + if ( data ) + data->mySubMeshes.push_back( subMesh ); + else + data = SMESH_subMeshEventListenerData::MakeData( subMesh ); + subMesh->SetEventListener ( GetSrcSubMeshListener(), data, srcSM ); + } } } else