-// SMESH SMESH : idl implementation based on 'SMESH' unit's calsses
+// Copyright (C) 2007-2010 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
+//
+// 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.
//
-// Copyright (C) 2003 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 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
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+// 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
//
+// 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
// Author : Edward AGAPOV (eap)
-
-using namespace std;
-
+//
#include "StdMeshers_ProjectionUtils.hxx"
#include "StdMeshers_ProjectionSource1D.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 <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
+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->()<<" ( " <<p.X()<<", "<<p.Y()<<", "<<p.Z()<<" )"<<endl;}\
+#define CONT_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); continue; }
+#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->()<<" ( "<<p.X()<<", "<<p.Y()<<", "<<p.Z()<<" )"<<endl;}\
// else {\
-// cout << msg << " "; TopAbs::Print(v.ShapeType(),cout) <<" "<<(v).TShape().operator->()<<endl;}\
+// cout << msg << " "; TopAbs::Print((v).ShapeType(),cout) <<" "<<(v).TShape().operator->()<<endl;}\
// }
#define SHOW_LIST(msg,l) \
// { \
// cout << endl;\
// }
+#define HERE StdMeshers_ProjectionUtils
+
namespace {
+
+ //================================================================================
+ /*!
+ * \brief Write shape for debug purposes
+ */
+ //================================================================================
+
+ bool _StoreBadShape(const TopoDS_Shape& shape)
+ {
+#ifdef _DEBUG_
+ const char* type[] ={"COMPOUND","COMPSOLID","SOLID","SHELL","FACE","WIRE","EDGE","VERTEX"};
+ BRepTools::Write( shape, SMESH_Comment("/tmp/") << type[shape.ShapeType()] << "_"
+ << shape.TShape().operator->() << ".brep");
+#endif
+ return false;
+ }
+
//================================================================================
/*!
* \brief Reverse order of edges in a list and their orientation
if ( nbEdges == 2 && IsPropagationPossible( theMesh1, theMesh2 ) )
{
list< TopoDS_Edge >::iterator eIt2 = ++edges2.begin(); // 2nd edge of the 2nd face
- TopoDS_Edge edge2 =
- StdMeshers_ProjectionUtils::GetPropagationEdge( theMesh1, *eIt2, edges1.front() ).second;
+ TopoDS_Edge edge2 = HERE::GetPropagationEdge( theMesh1, *eIt2, edges1.front() ).second;
if ( !edge2.IsNull() ) { // propagation found for the second edge
Reverse( edges2, nbEdges );
return true;
}
return TopoDS_Shape();
}
-}
+
+ //================================================================================
+ /*!
+ * \brief Find association of groups at top and bottom of prism
+ */
+ //================================================================================
+
+ bool AssocGroupsByPropagation(const TopoDS_Shape& theGroup1,
+ const TopoDS_Shape& theGroup2,
+ SMESH_Mesh& theMesh,
+ HERE::TShapeShapeMap& theMap)
+ {
+ // If groups are on top and bottom of prism then we can associate
+ // them using "vertical" (or "side") edges and faces of prism since
+ // they connect corresponding vertices and edges of groups.
+
+ TopTools_IndexedMapOfShape subshapes1, subshapes2;
+ TopExp::MapShapes( theGroup1, subshapes1 );
+ TopExp::MapShapes( theGroup2, subshapes2 );
+ TopTools_ListIteratorOfListOfShape ancestIt;
+
+ // Iterate on vertices of group1 to find corresponding vertices in group2
+ // and associate adjacent edges and faces
+
+ TopTools_MapOfShape verticShapes;
+ TopExp_Explorer vExp1( theGroup1, TopAbs_VERTEX );
+ for ( ; vExp1.More(); vExp1.Next() )
+ {
+ const TopoDS_Vertex& v1 = TopoDS::Vertex( vExp1.Current() );
+ if ( theMap.IsBound( v1 )) continue; // already processed
+
+ // Find "vertical" edge ending in v1 and whose other vertex belongs to group2
+ TopoDS_Shape verticEdge, v2;
+ ancestIt.Initialize( theMesh.GetAncestors( v1 ));
+ for ( ; verticEdge.IsNull() && ancestIt.More(); ancestIt.Next() )
+ {
+ if ( ancestIt.Value().ShapeType() != TopAbs_EDGE ) continue;
+ v2 = HERE::GetNextVertex( TopoDS::Edge( ancestIt.Value() ), v1 );
+ if ( subshapes2.Contains( v2 ))
+ verticEdge = ancestIt.Value();
+ }
+ if ( verticEdge.IsNull() )
+ return false;
+
+ HERE::InsertAssociation( v1, v2, theMap);
+
+ // Associate edges by vertical faces sharing the found vertical edge
+ ancestIt.Initialize( theMesh.GetAncestors( verticEdge ) );
+ for ( ; ancestIt.More(); ancestIt.Next() )
+ {
+ if ( ancestIt.Value().ShapeType() != TopAbs_FACE ) continue;
+ if ( !verticShapes.Add( ancestIt.Value() )) continue;
+ const TopoDS_Face& face = TopoDS::Face( ancestIt.Value() );
+
+ // get edges of the face
+ TopoDS_Edge edgeGr1, edgeGr2, verticEdge2;
+ list< TopoDS_Edge > edges; list< int > nbEdgesInWire;
+ SMESH_Block::GetOrderedEdges( face, v1, edges, nbEdgesInWire);
+ if ( nbEdgesInWire.front() != 4 )
+ return _StoreBadShape( face );
+ list< TopoDS_Edge >::iterator edge = edges.begin();
+ if ( verticEdge.IsSame( *edge )) {
+ edgeGr2 = *(++edge);
+ verticEdge2 = *(++edge);
+ edgeGr1 = *(++edge);
+ } else {
+ edgeGr1 = *(edge++);
+ verticEdge2 = *(edge++);
+ edgeGr2 = *(edge++);
+ }
+
+ HERE::InsertAssociation( edgeGr1, edgeGr2.Reversed(), theMap);
+ }
+ }
+
+ // Associate faces
+ TopoDS_Iterator gr1It( theGroup1 );
+ 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();
+ if ( bndEdge.IsNull() )
+ return false;
+
+ list< TopoDS_Shape > edges(1, bndEdge);
+ list< TopoDS_Shape >::iterator edge1 = edges.begin();
+ for ( ; edge1 != edges.end(); ++edge1 )
+ {
+ // there must be one or zero not associated faces between ancestors of edge
+ // belonging to theGroup1
+ TopoDS_Shape face1;
+ ancestIt.Initialize( theMesh.GetAncestors( *edge1 ) );
+ for ( ; ancestIt.More() && face1.IsNull(); ancestIt.Next() ) {
+ if ( ancestIt.Value().ShapeType() == TopAbs_FACE &&
+ !theMap.IsBound( ancestIt.Value() ) &&
+ subshapes1.Contains( ancestIt.Value() ))
+ face1 = ancestIt.Value();
+
+ // add edges of face1 to start searching for adjacent faces from
+ for ( TopExp_Explorer e(face1, TopAbs_EDGE); e.More(); e.Next())
+ if ( !edge1->IsSame( e.Current() ))
+ edges.push_back( e.Current() );
+ }
+ if ( !face1.IsNull() ) {
+ // find the corresponding face of theGroup2
+ TopoDS_Shape edge2 = theMap( *edge1 );
+ TopoDS_Shape face2;
+ ancestIt.Initialize( theMesh.GetAncestors( edge2 ) );
+ for ( ; ancestIt.More() && face2.IsNull(); ancestIt.Next() ) {
+ if ( ancestIt.Value().ShapeType() == TopAbs_FACE &&
+ !theMap.IsBound( ancestIt.Value() ) &&
+ subshapes2.Contains( ancestIt.Value() ))
+ face2 = ancestIt.Value();
+ }
+ if ( face2.IsNull() )
+ return false;
+
+ HERE::InsertAssociation( face1, face2, theMap);
+ }
+ }
+ }
+ return true;
+ }
+
+} // namespace
//=======================================================================
/*!
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 ...:
+ // }
+ // 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.
+ //
+
+ // =================================================================================
+ // 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;
}
bool bidirect = ( !theShape1.IsSame( theShape2 ));
+
+ // ============
+ // 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 subshapes 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() )
{
//======================================================================
case TopAbs_SOLID: {
// ----------------------------------------------------------------------
TopoDS_Vertex VV1[2], VV2[2];
- // find a not closed edge of shape1 both vertices of which are associated
+ // try to find a not closed edge of shape1 both vertices of which are associated
TopoDS_Edge edge1;
TopExp_Explorer exp ( theShape1, TopAbs_EDGE );
for ( ; VV2[ 1 ].IsNull() && exp.More(); exp.Next() ) {
}
if ( VV2[ 1 ].IsNull() ) // 2 bound vertices not found
RETURN_BAD_RESULT("2 bound vertices not found" );
+ // get an edge2 of theShape2 corresponding to edge1
TopoDS_Edge edge2 = GetEdgeByVertices( theMesh2, VV2[ 0 ], VV2[ 1 ]);
if ( edge2.IsNull() )
RETURN_BAD_RESULT("GetEdgeByVertices() failed");
pair<int,TopoDS_Edge> 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
}
break; // try by vertex closeness
}
+ case TopAbs_COMPOUND: {
+ // ----------------------------------------------------------------------
+ if ( IsPropagationPossible( theMesh1, theMesh2 )) {
+
+ // try to accosiate all using propagation
+ 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();
+ }
+ if ( E.IsNull() )
+ break; // try by vertex closeness
+
+ // find association for vertices of edge E
+ TopoDS_Vertex VV1[2], VV2[2];
+ for(TopExp_Explorer eexp(E, TopAbs_VERTEX); eexp.More(); eexp.Next()) {
+ TopoDS_Vertex V1 = TopoDS::Vertex( eexp.Current() );
+ // look for an edge ending in E whose one vertex is in theShape1
+ // and the other, in theShape2
+ const TopTools_ListOfShape& Ancestors = theMesh1->GetAncestors(V1);
+ TopTools_ListIteratorOfListOfShape ita(Ancestors);
+ for(; ita.More(); ita.Next()) {
+ if( ita.Value().ShapeType() != TopAbs_EDGE ) continue;
+ TopoDS_Edge edge = TopoDS::Edge(ita.Value());
+ bool FromShape1 = false;
+ for(TopExp_Explorer expe(theShape1, TopAbs_EDGE); expe.More(); expe.Next() ) {
+ if(edge.IsSame(expe.Current())) {
+ FromShape1 = true;
+ break;
+ }
+ }
+ if(!FromShape1) {
+ // is it an edge between theShape1 and theShape2?
+ TopExp_Explorer expv(edge, TopAbs_VERTEX);
+ TopoDS_Vertex V2 = TopoDS::Vertex( expv.Current() );
+ if(V2.IsSame(V1)) {
+ expv.Next();
+ V2 = TopoDS::Vertex( expv.Current() );
+ }
+ bool FromShape2 = false;
+ for ( expv.Init( theShape2, TopAbs_VERTEX ); expv.More(); expv.Next()) {
+ if ( V2.IsSame( expv.Current() )) {
+ FromShape2 = true;
+ break;
+ }
+ }
+ if ( FromShape2 ) {
+ if ( VV1[0].IsNull() )
+ VV1[0] = V1, VV2[0] = V2;
+ else
+ VV1[1] = V1, VV2[1] = V2;
+ break; // from loop on ancestors of V1
+ }
+ }
+ }
+ }
+ if ( !VV1[1].IsNull() ) {
+ InsertAssociation( VV1[0], VV2[0], theMap, bidirect);
+ InsertAssociation( VV1[1], VV2[1], theMap, bidirect);
+ return FindSubShapeAssociation( theShape1, theMesh1, theShape2, theMesh2, theMap);
+ }
+ }
+ break; // try by vertex closeness
+ }
default:;
}
* \param face1 - face 1
* \param VV1 - vertices of face 1
* \param face2 - face 2
- * \param VV2 - vertices of face 2 associated with oned of face 1
+ * \param VV2 - vertices of face 2 associated with ones of face 1
* \param edges1 - out list of edges of face 1
* \param edges2 - out list of edges of face 2
* \retval int - nb of edges in an outer wire in a success case, else zero
*/
//================================================================================
-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 ");
+ for ( int outer_wire_algo = 0; outer_wire_algo < 2; ++outer_wire_algo )
+ {
+ edges1.clear();
+ edges2.clear();
+
+ if ( SMESH_Block::GetOrderedEdges( face1, VV1[0], edges1, nbVInW1, outer_wire_algo) !=
+ SMESH_Block::GetOrderedEdges( face2, VV2[0], edges2, nbVInW2, outer_wire_algo) )
+ CONT_BAD_RESULT("Different number of wires in faces ");
- if ( nbVInW1.front() != nbVInW2.front() )
- RETURN_BAD_RESULT("Different number of edges in faces: " <<
+ if ( nbVInW1.front() != nbVInW2.front() )
+ CONT_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 ));
+ // 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 ( nbVInW1.size() > 1 ) { // several wires
+ edgeIt = edges1.begin();
+ for ( int i = 1; i < nbVInW1.front(); ++i ) ++edgeIt;
+ 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 ( nbVInW2.size() > 1 ) { // several wires
+ edgeIt = edges2.begin();
+ for ( int i = 1; i < nbVInW2.front(); ++i ) ++edgeIt;
+ KO = !VV2[1].IsSame( TopExp::FirstVertex( *edgeIt, true ));
+ }
+ if ( KO )
+ CONT_BAD_RESULT("GetOrderedEdges() failed");
}
- if ( KO )
- RETURN_BAD_RESULT("GetOrderedEdges() failed");
}
- }
- if ( reverse )
- {
- 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");
+ if ( reverse )
+ {
+ Reverse( edges2 , nbVInW2.front());
+ if (( VV1[1].IsSame( TopExp::LastVertex( edges1.front(), true ))) !=
+ ( VV2[1].IsSame( TopExp::LastVertex( edges2.front(), true ))))
+ CONT_BAD_RESULT("GetOrderedEdges() failed");
+ }
}
return nbVInW2.front();
}
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
// 1. Nodes of corresponding links:
// get 2 matching edges, try to find not seam ones
- TopoDS_Edge edge1, edge2, seam1, seam2;
+ TopoDS_Edge edge1, edge2, seam1, seam2, anyEdge1, anyEdge2;
TopExp_Explorer eE( OuterShape( face2, TopAbs_WIRE ), TopAbs_EDGE );
do {
// edge 2
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 ));
// check that there are nodes on edges
SMESHDS_SubMesh * eSM2 = meshDS2->MeshElements( e2 );
bool nodesOnEdges = ( eSM1 && eSM2 && eSM1->NbNodes() && eSM2->NbNodes() );
// check that the nodes on edges belong to faces
+ // (as NETGEN ignores nodes on the degenerated geom edge)
bool nodesOfFaces = false;
if ( nodesOnEdges ) {
const SMDS_MeshNode* n1 = eSM1->GetNodes()->next();
}
if ( nodesOfFaces )
{
- if ( BRep_Tool::IsClosed( e2, face2 )) {
+ if ( helper2.IsRealSeam( e2 )) {
seam1 = e1; seam2 = e2;
}
else {
edge1 = e1; edge2 = e2;
}
}
+ else {
+ anyEdge1 = e1; anyEdge2 = 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");
+ bool hasNodesOnEdge = (! edge2.IsNull() );
+ if ( !hasNodesOnEdge ) {
+ // 0020338 - nb segments == 1
+ edge1 = anyEdge1; edge2 = anyEdge2;
+ }
// get 2 matching vertices
TopoDS_Vertex V2 = TopExp::FirstVertex( TopoDS::Edge( edge2 ));
const SMDS_MeshNode* nullNode = 0;
vector< const SMDS_MeshNode*> eNode1( 2, nullNode );
vector< const SMDS_MeshNode*> eNode2( 2, nullNode );
- int nbNodeToGet = 1;
- if ( IsClosedEdge( edge1 ) || IsClosedEdge( edge2 ) )
- nbNodeToGet = 2;
- for ( int is2 = 0; is2 < 2; ++is2 )
+ if ( hasNodesOnEdge )
{
- TopoDS_Edge & edge = is2 ? edge2 : edge1;
- SMESHDS_Mesh * smDS = is2 ? meshDS2 : meshDS1;
- SMESHDS_SubMesh* edgeSM = smDS->MeshElements( edge );
- // nodes linked with ones on vertices
- const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1;
- vector< const SMDS_MeshNode*>& eNode = is2 ? eNode2 : eNode1;
- int nbGotNode = 0;
- SMDS_ElemIteratorPtr vElem = vNode->GetInverseElementIterator();
- while ( vElem->more() && nbGotNode != nbNodeToGet ) {
- const SMDS_MeshElement* elem = vElem->next();
- if ( elem->GetType() == SMDSAbs_Edge && edgeSM->Contains( elem ))
- eNode[ nbGotNode++ ] =
- ( elem->GetNode(0) == vNode ) ? elem->GetNode(1) : elem->GetNode(0);
- }
- if ( nbGotNode > 1 ) // sort found nodes by param on edge
+ int nbNodeToGet = 1;
+ if ( IsClosedEdge( edge1 ) || IsClosedEdge( edge2 ) )
+ nbNodeToGet = 2;
+ for ( int is2 = 0; is2 < 2; ++is2 )
{
- SMESH_MesherHelper* helper = is2 ? &helper2 : &helper1;
- double u0 = helper->GetNodeU( edge, eNode[ 0 ]);
- double u1 = helper->GetNodeU( edge, eNode[ 1 ]);
- if ( u0 > u1 ) std::swap( eNode[ 0 ], eNode[ 1 ]);
+ TopoDS_Edge & edge = is2 ? edge2 : edge1;
+ SMESHDS_Mesh * smDS = is2 ? meshDS2 : meshDS1;
+ SMESHDS_SubMesh* edgeSM = smDS->MeshElements( edge );
+ // nodes linked with ones on vertices
+ const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1;
+ vector< const SMDS_MeshNode*>& eNode = is2 ? eNode2 : eNode1;
+ int nbGotNode = 0;
+ SMDS_ElemIteratorPtr vElem = vNode->GetInverseElementIterator(SMDSAbs_Edge);
+ while ( vElem->more() && nbGotNode != nbNodeToGet ) {
+ const SMDS_MeshElement* elem = vElem->next();
+ if ( edgeSM->Contains( elem ))
+ eNode[ nbGotNode++ ] =
+ ( elem->GetNode(0) == vNode ) ? elem->GetNode(1) : elem->GetNode(0);
+ }
+ if ( nbGotNode > 1 ) // sort found nodes by param on edge
+ {
+ SMESH_MesherHelper* helper = is2 ? &helper2 : &helper1;
+ double u0 = helper->GetNodeU( edge, eNode[ 0 ]);
+ double u1 = helper->GetNodeU( edge, eNode[ 1 ]);
+ if ( u0 > u1 ) std::swap( eNode[ 0 ], eNode[ 1 ]);
+ }
+ if ( nbGotNode == 0 )
+ RETURN_BAD_RESULT("Found no nodes on edge " << smDS->ShapeToIndex( edge ) <<
+ " linked to " << vNode );
}
- if ( nbGotNode == 0 )
- RETURN_BAD_RESULT("Found no nodes on edge " << smDS->ShapeToIndex( edge ) <<
- " linked to " << vNode );
+ }
+ else // 0020338 - nb segments == 1
+ {
+ // get 2 other matching vertices
+ V2 = TopExp::LastVertex( TopoDS::Edge( edge2 ));
+ if ( !assocMap.IsBound( V2 ))
+ RETURN_BAD_RESULT("Association not found for vertex " << meshDS2->ShapeToIndex( V2 ));
+ V1 = TopoDS::Vertex( assocMap( V2 ));
+
+ // nodes on vertices
+ eNode1[0] = SMESH_Algo::VertexNode( V1, meshDS1 );
+ eNode2[0] = SMESH_Algo::VertexNode( V2, meshDS2 );
+ if ( !eNode1[0] ) RETURN_BAD_RESULT("No node on vertex #" << meshDS1->ShapeToIndex( V1 ));
+ if ( !eNode2[0] ) RETURN_BAD_RESULT("No node on vertex #" << meshDS2->ShapeToIndex( V2 ));
}
// 2. face sets
const TopoDS_Face & face = is2 ? face2 : face1;
SMDS_ElemIteratorPtr eIt = sm->GetElements();
- if ( !helper->IsSeamShape( is2 ? edge2 : edge1 ))
+ if ( !helper->IsRealSeam( is2 ? edge2 : edge1 ))
{
while ( eIt->more() ) elems.insert( eIt->next() );
}
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 );
// On a sphere, add matching nodes on the edge
- if ( helper1.IsSeamShape( edge1 ))
+ if ( helper1.IsRealSeam( edge1 ))
{
// sort nodes on edges by param on edge
map< double, const SMDS_MeshNode* > u2nodesMaps[2];
SMESH_Gen* gen = mesh->GetGen();
SMESH_Algo* algo = gen->GetAlgo( *mesh, sm->GetSubShape() );
if ( !algo )
- RETURN_BAD_RESULT("No algo assigned to submesh " << sm->GetId());
+ {
+ if ( sm->GetSubShape().ShapeType() != TopAbs_COMPOUND )
+ RETURN_BAD_RESULT("No algo assigned to submesh " << sm->GetId());
+ // group
+ bool computed = true;
+ for ( TopoDS_Iterator grMember( sm->GetSubShape() ); grMember.More(); grMember.Next())
+ if ( SMESH_subMesh* grSub = mesh->GetSubMesh( grMember.Value() ))
+ if ( !MakeComputed( grSub, iterationNb + 1 ))
+ computed = false;
+ return computed;
+ }
string algoType = algo->GetName();
if ( algoType.substr(0, 11) != "Projection_")
if ( !srcMesh )
srcMesh = mesh;
- return MakeComputed( srcMesh->GetSubMesh( srcShape ), iterationNb + 1 );
+ if ( MakeComputed( srcMesh->GetSubMesh( srcShape ), iterationNb + 1 ))
+ return gen->Compute( *mesh, sm->GetSubShape() );
+
+ return false;
}
//================================================================================
- /*!
- * \brief Count nb of subshapes
- * \param shape - the shape
- * \param type - the type of subshapes to count
- * \retval int - the calculated number
- */
+/*!
+ * \brief Count nb of subshapes
+ * \param shape - the shape
+ * \param type - the type of subshapes to count
+ * \retval int - the calculated number
+ */
//================================================================================
int StdMeshers_ProjectionUtils::Count(const TopoDS_Shape& shape,
}
}
+//================================================================================
+/*!
+ * \brief Return true if edge is a boundary of edgeContainer
+ */
+//================================================================================
+
+bool StdMeshers_ProjectionUtils::IsBoundaryEdge(const TopoDS_Edge& edge,
+ const TopoDS_Shape& edgeContainer,
+ 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() ))
+ {
+ facesNearEdge.Add( itea.Value() );
+ if ( facesNearEdge.Extent() > 1 )
+ return false;
+ }
+ }
+ return ( facesNearEdge.Extent() == 1 );
+}
+
+
namespace {
SMESH_subMeshEventListener* GetSrcSubMeshListener();
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
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