Back to index

salome-smesh  6.5.0
Public Types | Static Public Member Functions
StdMeshers_ProjectionUtils Class Reference

Class encapsulating methods common to Projection algorithms. More...

#include <StdMeshers_ProjectionUtils.hxx>

List of all members.

Public Types

typedef
StdMeshers_ShapeShapeBiDirectionMap 
TShapeShapeMap
typedef
TopTools_IndexedDataMapOfShapeListOfShape 
TAncestorMap
typedef std::map< const
SMDS_MeshNode *, const
SMDS_MeshNode * > 
TNodeNodeMap

Static Public Member Functions

static bool FindSubShapeAssociation (const TopoDS_Shape &theShape1, SMESH_Mesh *theMesh1, const TopoDS_Shape &theShape2, SMESH_Mesh *theMesh2, TShapeShapeMap &theAssociationMap)
 Looks for association of all sub-shapes of two shapes.
static int FindFaceAssociation (const TopoDS_Face &face1, TopoDS_Vertex VV1[2], const TopoDS_Face &face2, TopoDS_Vertex VV2[2], std::list< TopoDS_Edge > &edges1, std::list< TopoDS_Edge > &edges2)
 Find association of edges of faces.
static void InitVertexAssociation (const SMESH_Hypothesis *theHyp, TShapeShapeMap &theAssociationMap)
 Insert vertex association defined by a hypothesis into a map.
static bool InsertAssociation (const TopoDS_Shape &theShape1, const TopoDS_Shape &theShape2, TShapeShapeMap &theAssociationMap)
 Inserts association theShape1 <-> theShape2 to TShapeShapeMap.
static TopoDS_Edge GetEdgeByVertices (SMESH_Mesh *aMesh, const TopoDS_Vertex &V1, const TopoDS_Vertex &V2)
 Finds an edge by its vertices in a main shape of the mesh.
static TopoDS_Face GetNextFace (const TAncestorMap &edgeToFaces, const TopoDS_Edge &edge, const TopoDS_Face &face)
 Return another face sharing an edge.
static TopoDS_Vertex GetNextVertex (const TopoDS_Edge &edge, const TopoDS_Vertex &vertex)
 Return other vertex of an edge.
static std::pair< int,
TopoDS_Edge > 
GetPropagationEdge (SMESH_Mesh *aMesh, const TopoDS_Edge &anEdge, const TopoDS_Edge &fromEdge)
 Return an oriented propagation edge.
static bool FindMatchingNodesOnFaces (const TopoDS_Face &face1, SMESH_Mesh *mesh1, const TopoDS_Face &face2, SMESH_Mesh *mesh2, const TShapeShapeMap &assocMap, TNodeNodeMap &nodeIn2OutMap)
 Find corresponding nodes on two faces.
static TopoDS_Shape OuterShape (const TopoDS_Face &face, TopAbs_ShapeEnum type)
 Return any sub-shape of a face belonging to the outer wire.
static bool MakeComputed (SMESH_subMesh *sm, const int iterationNb=0)
 Check that submeshis is computed and try to compute it if is not.
static int Count (const TopoDS_Shape &shape, const TopAbs_ShapeEnum type, const bool ignoreSame)
 Count nb of sub-shapes.
static void SetEventListener (SMESH_subMesh *subMesh, TopoDS_Shape srcShape, SMESH_Mesh *srcMesh)
 Set event listeners to submesh with projection algo.
static TopoDS_Edge GetBoundaryEdge (const TopoDS_Shape &edgeContainer, const SMESH_Mesh &mesh)
 Return a boundary EDGE of edgeContainer.

Detailed Description

Class encapsulating methods common to Projection algorithms.

Definition at line 74 of file StdMeshers_ProjectionUtils.hxx.


Member Typedef Documentation

typedef TopTools_IndexedDataMapOfShapeListOfShape StdMeshers_ProjectionUtils::TAncestorMap

Definition at line 79 of file StdMeshers_ProjectionUtils.hxx.

typedef std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> StdMeshers_ProjectionUtils::TNodeNodeMap

Definition at line 80 of file StdMeshers_ProjectionUtils.hxx.

Definition at line 78 of file StdMeshers_ProjectionUtils.hxx.


Member Function Documentation

int StdMeshers_ProjectionUtils::Count ( const TopoDS_Shape &  shape,
const TopAbs_ShapeEnum  type,
const bool  ignoreSame 
) [static]

Count nb of sub-shapes.

Parameters:
shape- the shape
type- the type of sub-shapes to count
ignoreSame- if true, use map not to count same shapes, esle use explorer
Return values:
int- the calculated number
Parameters:
shape- the shape
type- the type of sub-shapes to count
Return values:
int- the calculated number

Definition at line 2022 of file StdMeshers_ProjectionUtils.cxx.

{
  if ( ignoreSame ) {
    TopTools_IndexedMapOfShape map;
    TopExp::MapShapes( shape, type, map );
    return map.Extent();
  }
  else {
    int nb = 0;
    for ( TopExp_Explorer exp( shape, type ); exp.More(); exp.Next() )
      ++nb;
    return nb;
  }
}

Here is the caller graph for this function:

int StdMeshers_ProjectionUtils::FindFaceAssociation ( const TopoDS_Face &  face1,
TopoDS_Vertex  VV1[2],
const TopoDS_Face &  face2,
TopoDS_Vertex  VV2[2],
std::list< TopoDS_Edge > &  edges1,
std::list< TopoDS_Edge > &  edges2 
) [static]

Find association of edges of faces.

Parameters:
face1- face 1
VV1- vertices of face 1
face2- face 2
VV2- vertices of face 2 associated with oned of face 1
edges1- out list of edges of face 1
edges2- out list of edges of face 2
Return values:
int- nb of edges in an outer wire in a success case, else zero
Parameters:
face1- face 1
VV1- vertices of face 1
face2- face 2
VV2- vertices of face 2 associated with ones of face 1
edges1- out list of edges of face 1
edges2- out list of edges of face 2
Return values:
int- nb of edges in an outer wire in a success case, else zero

Definition at line 1231 of file StdMeshers_ProjectionUtils.cxx.

{
  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");
      }
    }
    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 ( 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 )
  {
    // 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 OK ? nbEInW1.front() : 0;
}

Here is the call graph for this function:

bool StdMeshers_ProjectionUtils::FindMatchingNodesOnFaces ( const TopoDS_Face &  face1,
SMESH_Mesh *  mesh1,
const TopoDS_Face &  face2,
SMESH_Mesh *  mesh2,
const TShapeShapeMap assocMap,
TNodeNodeMap node1To2Map 
) [static]

Find corresponding nodes on two faces.

Parameters:
face1- the first face
mesh1- mesh containing elements on the first face
face2- the second face
mesh2- mesh containing elements on the second face
assocMap- map associating sub-shapes of the faces
nodeIn2OutMap- map containing found matching nodes
Return values:
bool- is a success
Parameters:
face1- the first face
mesh1- mesh containing elements on the first face
face2- the second face
mesh2- mesh containing elements on the second face
assocMap- map associating sub-shapes of the faces
node1To2Map- map containing found matching nodes
Return values:
bool- is a success

Definition at line 1600 of file StdMeshers_ProjectionUtils.cxx.

{
  SMESHDS_Mesh* meshDS1 = mesh1->GetMeshDS();
  SMESHDS_Mesh* meshDS2 = mesh2->GetMeshDS();
  
  SMESH_MesherHelper helper1( *mesh1 );
  SMESH_MesherHelper helper2( *mesh2 );

  // Get corresponding submeshes and roughly check match of meshes

  SMESHDS_SubMesh * SM2 = meshDS2->MeshElements( face2 );
  SMESHDS_SubMesh * SM1 = meshDS1->MeshElements( face1 );
  if ( !SM2 || !SM1 )
    RETURN_BAD_RESULT("Empty submeshes");
  if ( SM2->NbNodes()    != SM1->NbNodes() ||
       SM2->NbElements() != SM1->NbElements() )
    RETURN_BAD_RESULT("Different meshes on corresponding faces "
                      << meshDS1->ShapeToIndex( face1 ) << " and "
                      << meshDS2->ShapeToIndex( face2 ));
  if ( SM2->NbElements() == 0 )
    RETURN_BAD_RESULT("Empty submeshes");

  helper1.SetSubShape( face1 );
  helper2.SetSubShape( face2 );
  if ( helper1.HasSeam() != helper2.HasSeam() )
    RETURN_BAD_RESULT("Different faces' geometry");

  // Data to call SMESH_MeshEditor::FindMatchingNodes():

  // 1. Nodes of corresponding links:

  // get 2 matching edges, try to find not seam ones
  TopoDS_Edge edge1, edge2, seam1, seam2, anyEdge1, anyEdge2;
  TopExp_Explorer eE( OuterShape( face2, TopAbs_WIRE ), TopAbs_EDGE );
  do {
    // edge 2
    TopoDS_Edge e2 = TopoDS::Edge( eE.Current() );
    eE.Next();
    // edge 1
    if ( !assocMap.IsBound( e2, /*is2nd=*/true ))
      RETURN_BAD_RESULT("Association not found for edge " << meshDS2->ShapeToIndex( e2 ));
    TopoDS_Edge e1 = TopoDS::Edge( assocMap( e2, /*is2nd=*/true ));
    if ( !helper1.IsSubShape( e1, face1 ))
      RETURN_BAD_RESULT("Wrong association, edge " << meshDS1->ShapeToIndex( e1 ) <<
                        " 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 );
    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();
      const SMDS_MeshNode* n2 = eSM2->GetNodes()->next();
      nodesOfFaces = ( n1->GetInverseElementIterator(SMDSAbs_Face)->more() &&
                       n2->GetInverseElementIterator(SMDSAbs_Face)->more() );
    }
    if ( nodesOfFaces )
    {
      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;
  }
  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 ));
  if ( !assocMap.IsBound( V2, /*is2nd=*/true ))
    RETURN_BAD_RESULT("Association not found for vertex " << meshDS2->ShapeToIndex( V2 ));
  TopoDS_Vertex V1 = TopoDS::Vertex( assocMap( V2, /*is2nd=*/true ));

  // nodes on vertices
  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;
  vector< const SMDS_MeshNode*> eNode1( 2, nullNode );
  vector< const SMDS_MeshNode*> eNode2( 2, nullNode );
  if ( hasNodesOnEdge )
  {
    int nbNodeToGet = 1;
    if ( helper1.IsClosedEdge( edge1 ) || helper2.IsClosedEdge( edge2 ) )
      nbNodeToGet = 2;
    for ( int is2 = 0; is2 < 2; ++is2 )
    {
      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 );
    }
  }
  else // 0020338 - nb segments == 1
  {
    // get 2 other matching vertices
    V2 = TopExp::LastVertex( TopoDS::Edge( edge2 ));
    if ( !assocMap.IsBound( V2, /*is2nd=*/true ))
      RETURN_BAD_RESULT("Association not found for vertex " << meshDS2->ShapeToIndex( V2 ));
    V1 = TopoDS::Vertex( assocMap( V2, /*is2nd=*/true ));

    // 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

  set<const SMDS_MeshElement*> Elems1, Elems2;
  for ( int is2 = 0; is2 < 2; ++is2 )
  {
    set<const SMDS_MeshElement*> & elems = is2 ? Elems2 : Elems1;
    SMESHDS_SubMesh*                  sm = is2 ? SM2 : SM1;
    SMESH_MesherHelper*           helper = is2 ? &helper2 : &helper1;
    const TopoDS_Face &             face = is2 ? face2 : face1;
    SMDS_ElemIteratorPtr eIt = sm->GetElements();

    if ( !helper->IsRealSeam( is2 ? edge2 : edge1 ))
    {
      while ( eIt->more() ) elems.insert( eIt->next() );
    }
    else
    {
      // the only suitable edge is seam, i.e. it is a sphere.
      // FindMatchingNodes() will not know which way to go from any edge.
      // So we ignore all faces having nodes on edges or vertices except
      // one of faces sharing current start nodes

      // find a face to keep
      const SMDS_MeshElement* faceToKeep = 0;
      const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1;
      const SMDS_MeshNode* eNode = is2 ? eNode2[0] : eNode1[0];
      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");
      notInSet.insert( f1 );

      const SMDS_MeshElement* f2 =
        SMESH_MeshEditor::FindFaceInSet( vNode, eNode, inSet, notInSet );
      if ( !f2 ) RETURN_BAD_RESULT("The second face on seam not found");

      // select a face with less UV of vNode
      const SMDS_MeshNode* notSeamNode[2] = {0, 0};
      for ( int iF = 0; iF < 2; ++iF ) {
        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->getshapeId() ))
            notSeamNode[ iF ] = node;
        }
      }
      gp_Pnt2d uv1 = helper->GetNodeUV( face, vNode, notSeamNode[0] );
      gp_Pnt2d uv2 = helper->GetNodeUV( face, vNode, notSeamNode[1] );
      if ( uv1.X() + uv1.Y() > uv2.X() + uv2.Y() )
        faceToKeep = f2;
      else
        faceToKeep = f1;

      // fill elem set
      elems.insert( faceToKeep );
      while ( eIt->more() ) {
        const SMDS_MeshElement* f = eIt->next();
        int nbNodes = f->NbNodes();
        if ( f->IsQuadratic() )
          nbNodes /= 2;
        bool onBnd = false;
        for ( int i = 0; !onBnd && i < nbNodes; ++i ) {
          const SMDS_MeshNode* node = f->GetNode( i );
          onBnd = ( node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE);
        }
        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 ) % nbNodes );
        f1 = SMESH_MeshEditor::FindFaceInSet( n1, n2, inSet, notInSet );
        if ( f1 )
          elems.insert( f1 );
      }
    } // case on a sphere
  } // loop on 2 faces

  //  int quadFactor = (*Elems1.begin())->IsQuadratic() ? 2 : 1;

  node1To2Map.clear();
  int res = SMESH_MeshEditor::FindMatchingNodes( Elems1, Elems2,
                                                 vNode1, vNode2,
                                                 eNode1[0], eNode2[0],
                                                 node1To2Map);
  if ( res != SMESH_MeshEditor::SEW_OK )
    RETURN_BAD_RESULT("FindMatchingNodes() result " << res );

  // On a sphere, add matching nodes on the edge

  if ( helper1.IsRealSeam( edge1 ))
  {
    // sort nodes on edges by param on edge
    map< double, const SMDS_MeshNode* > u2nodesMaps[2];
    for ( int is2 = 0; is2 < 2; ++is2 )
    {
      TopoDS_Edge &     edge  = is2 ? edge2 : edge1;
      SMESHDS_Mesh *    smDS  = is2 ? meshDS2 : meshDS1;
      SMESHDS_SubMesh* edgeSM = smDS->MeshElements( edge );
      map< double, const SMDS_MeshNode* > & pos2nodes = u2nodesMaps[ is2 ];

      SMDS_NodeIteratorPtr nIt = edgeSM->GetNodes();
      while ( nIt->more() ) {
        const SMDS_MeshNode* node = nIt->next();
        const SMDS_EdgePosition* pos =
          static_cast<const SMDS_EdgePosition*>(node->GetPosition());
        pos2nodes.insert( make_pair( pos->GetUParameter(), node ));
      }
      if ( pos2nodes.size() != edgeSM->NbNodes() )
        RETURN_BAD_RESULT("Equal params of nodes on edge "
                          << smDS->ShapeToIndex( edge ) << " of face " << is2 );
    }
    if ( u2nodesMaps[0].size() != u2nodesMaps[1].size() )
      RETURN_BAD_RESULT("Different nb of new nodes on edges or wrong params");

    // compare edge orientation
    double u1 = helper1.GetNodeU( edge1, vNode1 );
    double u2 = helper2.GetNodeU( edge2, vNode2 );
    bool isFirst1 = ( u1 < u2nodesMaps[0].begin()->first );
    bool isFirst2 = ( u2 < u2nodesMaps[1].begin()->first );
    bool reverse ( isFirst1 != isFirst2 );

    // associate matching nodes
    map< double, const SMDS_MeshNode* >::iterator u_Node1, u_Node2, end1;
    map< double, const SMDS_MeshNode* >::reverse_iterator uR_Node2;
    u_Node1 = u2nodesMaps[0].begin();
    u_Node2 = u2nodesMaps[1].begin();
    uR_Node2 = u2nodesMaps[1].rbegin();
    end1 = u2nodesMaps[0].end();
    for ( ; u_Node1 != end1; ++u_Node1 ) {
      const SMDS_MeshNode* n1 = u_Node1->second;
      const SMDS_MeshNode* n2 = ( reverse ? (uR_Node2++)->second : (u_Node2++)->second );
      node1To2Map.insert( make_pair( n1, n2 ));
    }

    // associate matching nodes on the last vertices
    V2 = TopExp::LastVertex( TopoDS::Edge( edge2 ));
    if ( !assocMap.IsBound( V2, /*is2nd=*/true ))
      RETURN_BAD_RESULT("Association not found for vertex " << meshDS2->ShapeToIndex( V2 ));
    V1 = TopoDS::Vertex( assocMap( V2, /*is2nd=*/true ));
    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 ));
  }

// don't know why this condition is usually true :(
//   if ( node1To2Map.size() * quadFactor < SM1->NbNodes() )
//     MESSAGE("FindMatchingNodes() found too few node pairs starting from nodes ("
//             << vNode1->GetID() << " - " << eNode1[0]->GetID() << ") ("
//             << vNode2->GetID() << " - " << eNode2[0]->GetID() << "):"
//             << node1To2Map.size() * quadFactor << " < " << SM1->NbNodes());
  
  return true;
}

Here is the call graph for this function:

bool StdMeshers_ProjectionUtils::FindSubShapeAssociation ( const TopoDS_Shape &  theShape1,
SMESH_Mesh *  theMesh1,
const TopoDS_Shape &  theShape2,
SMESH_Mesh *  theMesh2,
TShapeShapeMap theMap 
) [static]

Looks for association of all sub-shapes of two shapes.

Parameters:
theShape1- shape 1
theMesh1- mesh built on shape 1
theShape2- shape 2
theMesh2- mesh built on shape 2
theAssociation- association map to be filled that may contain association of one or two pairs of vertices
Return values:
bool- true if association found
Parameters:
theShape1- target shape
theMesh1- mesh built on shape 1
theShape2- source shape
theMesh2- mesh built on shape 2
theAssociation- association map to be filled that may contain association of one or two pairs of vertices
Return values:
bool- true if association found

Definition at line 431 of file StdMeshers_ProjectionUtils.cxx.

{
  // 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() ) {
    TopoDS_Shape group1, group2;
    if ( theShape1.ShapeType() == TopAbs_COMPOUND ) {
      group1 = theShape1;
      group2 = FindGroupContaining( theShape2, theMesh2, group1 );
    }
    else if ( theShape2.ShapeType() == TopAbs_COMPOUND ) {
      group2 = theShape2;
      group1 = FindGroupContaining( theShape1, theMesh1, group2 );
    }
    if ( group1.IsNull() || group2.IsNull() )
      RETURN_BAD_RESULT("Different shape types");
    // Associate compounds
    return FindSubShapeAssociation(group1, theMesh1, group2, theMesh2, theMap );
  }

  // ============
  // 2) Is partner?
  // ============
  bool partner = theShape1.IsPartner( theShape2 );
  TopTools_DataMapIteratorOfDataMapOfShapeShape vvIt( theMap._map1to2 );
  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 );
      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() )
  {
    //======================================================================
    // 3) HAS initial vertex association
    //======================================================================
    switch ( theShape1.ShapeType() ) {
      // ----------------------------------------------------------------------
    case TopAbs_EDGE: { // TopAbs_EDGE
      // ----------------------------------------------------------------------
      if ( theMap.Extent() != 2 )
        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] );
      int i1 = 0, i2 = 0;
      if ( theMap.IsBound( VV1[ i1 ] )) i1 = 1;
      if ( theMap.IsBound( VV2[ i2 ] )) i2 = 1;
      InsertAssociation( VV1[ i1 ], VV2[ i2 ], theMap );
      InsertAssociation( theShape1, theShape2, theMap );
      return true;
    }
      // ----------------------------------------------------------------------
    case TopAbs_FACE: { // TopAbs_FACE
      // ----------------------------------------------------------------------
      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
      int nbEdges = 0;
      TopExp_Explorer exp ( face1, TopAbs_EDGE );
      for ( ; VV2[ 1 ].IsNull() && exp.More(); exp.Next(), ++nbEdges ) {
        TopExp::Vertices( TopoDS::Edge( exp.Current() ), VV1[0], VV1[1] );
        if ( theMap.IsBound( VV1[0] ) ) {
          VV2[ 0 ] = TopoDS::Vertex( theMap( VV1[0] ));
          if ( theMap.IsBound( VV1[1] ) && !VV1[0].IsSame( VV1[1] ))
            VV2[ 1 ] = TopoDS::Vertex( theMap( VV1[1] ));
        }
      }
      if ( VV2[ 1 ].IsNull() ) { // 2 bound vertices not found
        if ( nbEdges > 1 ) {
          RETURN_BAD_RESULT("2 bound vertices not found" );
        } else {
          VV2[ 1 ] = VV2[ 0 ];
        }
      }
      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 );

      list< TopoDS_Edge >::iterator eIt1 = edges1.begin();
      list< TopoDS_Edge >::iterator eIt2 = edges2.begin();
      for ( ; eIt1 != edges1.end(); ++eIt1, ++eIt2 )
      {
        InsertAssociation( *eIt1, *eIt2, theMap );
        VV1[0] = TopExp::FirstVertex( *eIt1, true );
        VV2[0] = TopExp::FirstVertex( *eIt2, true );
        InsertAssociation( VV1[0], VV2[0], theMap );
      }
      InsertAssociation( theShape1, theShape2, theMap );
      return true;
    }
      // ----------------------------------------------------------------------
    case TopAbs_SHELL: // TopAbs_SHELL, TopAbs_SOLID
    case TopAbs_SOLID: {
      // ----------------------------------------------------------------------
      TopoDS_Vertex VV1[2], VV2[2];
      // 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() ) {
        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] ));
          if ( theMap.IsBound( VV1[1] ) && !VV1[0].IsSame( VV1[1] ))
            VV2[ 1 ] = TopoDS::Vertex( theMap( VV1[1] ));
        }
      }
      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");

      // 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();
      else
        isSubOfMain = theMesh1->GetMeshDS()->ShapeToIndex( theShape1 );
      TAncestorMap e2f1, e2f2;
      const TAncestorMap& edgeToFace1 = isSubOfMain ? theMesh1->GetAncestorMap() : e2f1;
      const TAncestorMap& edgeToFace2 = isSubOfMain ? theMesh2->GetAncestorMap() : e2f2;
      if (!isSubOfMain) {
        TopExp::MapShapesAndAncestors( theShape1, TopAbs_EDGE, TopAbs_FACE, e2f1 );
        TopExp::MapShapesAndAncestors( theShape2, TopAbs_EDGE, TopAbs_FACE, e2f2 );
        if ( !edgeToFace1.Contains( edge1 ))
          RETURN_BAD_RESULT("edge1 does not belong to theShape1");
        if ( !edgeToFace2.Contains( edge2 ))
          RETURN_BAD_RESULT("edge2 does not belong to theShape2");
      }
      //
      // Look for 2 corresponing faces:
      //
      TopoDS_Shape F1, F2;

      // get a face sharing edge1 (F1)
      TopoDS_Shape FF2[2];
      TopTools_ListIteratorOfListOfShape ancestIt1( edgeToFace1.FindFromKey( edge1 ));
      for ( ; F1.IsNull() && ancestIt1.More(); ancestIt1.Next() )
        if ( ancestIt1.Value().ShapeType() == TopAbs_FACE )
          F1 = ancestIt1.Value().Oriented( TopAbs_FORWARD );
      if ( F1.IsNull() )
        RETURN_BAD_RESULT(" Face1 not found");

      // get 2 faces sharing edge2 (one of them is F2)
      TopTools_ListIteratorOfListOfShape ancestIt2( edgeToFace2.FindFromKey( edge2 ));
      for ( int i = 0; FF2[1].IsNull() && ancestIt2.More(); ancestIt2.Next() )
        if ( ancestIt2.Value().ShapeType() == TopAbs_FACE )
          FF2[ i++ ] = ancestIt2.Value().Oriented( TopAbs_FORWARD );

      // get oriented edge1 and edge2 from F1 and FF2[0]
      for ( exp.Init( F1, TopAbs_EDGE ); exp.More(); exp.Next() )
        if ( edge1.IsSame( exp.Current() )) {
          edge1 = TopoDS::Edge( exp.Current() );
          break;
        }
      for ( exp.Init( FF2[ 0 ], TopAbs_EDGE ); exp.More(); exp.Next() )
        if ( edge2.IsSame( exp.Current() )) {
          edge2 = TopoDS::Edge( exp.Current() );
          break;
        }

      // compare first vertices of edge1 and edge2
      TopExp::Vertices( edge1, VV1[0], VV1[1], true );
      TopExp::Vertices( edge2, VV2[0], VV2[1], true );
      F2 = FF2[ 0 ]; // (F2 !)
      if ( !VV1[ 0 ].IsSame( theMap( VV2[ 0 ], /*is2=*/true))) {
        edge2.Reverse();
        if ( FF2[ 1 ].IsNull() )
          F2.Reverse();
        else
          F2 = FF2[ 1 ];
      }

      TopTools_MapOfShape boundEdges;

      // 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 ));
      FE2.push_back( make_pair( TopoDS::Face( F2 ), edge2 ));
      for ( fe1 = FE1.begin(), fe2 = FE2.begin(); fe1 != FE1.end(); ++fe1, ++fe2 )
      {
        const TopoDS_Face& face1 = fe1->first;
        if ( theMap.IsBound( face1 ) ) continue;
        const TopoDS_Face& face2 = fe2->first;
        edge1 = fe1->second;
        edge2 = fe2->second;
        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");
        InsertAssociation( face1, face2, theMap ); // 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 );  // 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 ); // assoc vertices
          MESSAGE("Assoc vertex " << theMesh1->GetMeshDS()->ShapeToIndex( VV1[0] )<<
                  " to "          << theMesh2->GetMeshDS()->ShapeToIndex( VV2[0] ));

          // add adjacent faces to process
          TopoDS_Face nextFace1 = GetNextFace( edgeToFace1, *eIt1, face1 );
          TopoDS_Face nextFace2 = GetNextFace( edgeToFace2, *eIt2, face2 );
          if ( !nextFace1.IsNull() && !nextFace2.IsNull() ) {
            FE1.push_back( make_pair( nextFace1, *eIt1 ));
            FE2.push_back( make_pair( nextFace2, *eIt2 ));
          }
        }
      }
      InsertAssociation( theShape1, theShape2, theMap );
      return true;
    }
      // ----------------------------------------------------------------------
    case TopAbs_COMPOUND: { // GROUP
      // ----------------------------------------------------------------------
      // Maybe groups contain only one member
      TopoDS_Iterator it1( theShape1 ), it2( theShape2 );
      TopAbs_ShapeEnum memberType = it1.Value().ShapeType();
      int nbMembers = Count( theShape1, memberType, true );
      if ( nbMembers == 0 ) return true;
      if ( nbMembers == 1 ) {
        return FindSubShapeAssociation( it1.Value(), theMesh1, it2.Value(), theMesh2, theMap );
      }
      // Try to make shells of faces
      //
      BRep_Builder builder;
      TopoDS_Shell shell1, shell2;
      builder.MakeShell(shell1); builder.MakeShell(shell2);
      if ( memberType == TopAbs_FACE ) {
        // just add faces of groups to shells
        for (; it1.More(); it1.Next(), it2.Next() )
          builder.Add( shell1, it1.Value() ), builder.Add( shell2, it2.Value() );
      }
      else if ( memberType == TopAbs_EDGE ) {
        // Try to add faces sharing more than one edge of a group or
        // sharing all its vertices with the group
        TopTools_IndexedMapOfShape groupVertices[2];
        TopExp::MapShapes( theShape1, TopAbs_VERTEX, groupVertices[0]);
        TopExp::MapShapes( theShape2, TopAbs_VERTEX, groupVertices[1]);
        //
        TopTools_MapOfShape groupEdges[2], addedFaces[2];
        bool hasInitAssoc = (!theMap.IsEmpty()), initAssocOK = !hasInitAssoc;
        for (; it1.More(); it1.Next(), it2.Next() ) {
          groupEdges[0].Add( it1.Value() );
          groupEdges[1].Add( it2.Value() );
          if ( !initAssocOK ) {
            // for shell association there must be an edge with both vertices bound
            TopoDS_Vertex v1, v2;
            TopExp::Vertices( TopoDS::Edge( it1.Value().Oriented(TopAbs_FORWARD)), v1, v2 );
            initAssocOK = ( theMap.IsBound( v1 ) && theMap.IsBound( v2 ));
          }
        }
        for (int is2ndGroup = 0; initAssocOK && is2ndGroup < 2; ++is2ndGroup) {
          const TopoDS_Shape& group = is2ndGroup ? theShape2: theShape1;
          SMESH_Mesh*         mesh  = is2ndGroup ? theMesh2 : theMesh1;
          TopoDS_Shell&       shell = is2ndGroup ? shell2   : shell1;
          for ( TopoDS_Iterator it( group ); it.More(); it.Next() ) {
            const TopoDS_Edge& edge = TopoDS::Edge( it.Value() );
            TopoDS_Face face;
            for ( int iF = 0; iF < 2; ++iF ) { // loop on 2 faces sharing edge
              face = GetNextFace(mesh->GetAncestorMap(), edge, face);
              if ( !face.IsNull() ) {
                int nbGroupEdges = 0;
                for ( TopExp_Explorer f( face, TopAbs_EDGE ); f.More(); f.Next())
                  if ( groupEdges[ is2ndGroup ].Contains( f.Current() ))
                    if ( ++nbGroupEdges > 1 )
                      break;
                bool add = (nbGroupEdges > 1 || Count( face, TopAbs_EDGE, true ) == 1 );
                if ( !add ) {
                  add = true;
                  for ( TopExp_Explorer v( face, TopAbs_VERTEX ); add && v.More(); v.Next())
                    add = groupVertices[ is2ndGroup ].Contains( v.Current() );
                }
                if ( add && addedFaces[ is2ndGroup ].Add( face ))
                  builder.Add( shell, face );
              }
            }
          }
        }
      } else {
        RETURN_BAD_RESULT("Unexpected group type");
      }
      // Associate shells
      //
      int nbFaces1 = Count( shell1, TopAbs_FACE, 0 );
      int nbFaces2 = Count( shell2, TopAbs_FACE, 0 );
      if ( nbFaces1 != nbFaces2 )
        RETURN_BAD_RESULT("Different nb of faces found for shells");
      if ( nbFaces1 > 0 ) {
        bool ok = false;
        if ( nbFaces1 == 1 ) {
          TopoDS_Shape F1 = TopoDS_Iterator( shell1 ).Value();
          TopoDS_Shape F2 = TopoDS_Iterator( shell2 ).Value();
          ok = FindSubShapeAssociation( F1, theMesh1, F2, theMesh2, theMap );
        }
        else {
          ok = FindSubShapeAssociation(shell1, theMesh1, shell2, theMesh2, theMap );
        }
        // Check if all members are mapped 
        if ( ok ) {
          TopTools_MapOfShape boundMembers[2];
          TopoDS_Iterator mIt;
          for ( mIt.Initialize( theShape1 ); mIt.More(); mIt.Next())
            if ( theMap.IsBound( mIt.Value() )) {
              boundMembers[0].Add( mIt.Value() );
              boundMembers[1].Add( theMap( mIt.Value() ));
            }
          if ( boundMembers[0].Extent() != nbMembers ) {
            // make compounds of not bound members
            TopoDS_Compound comp[2];
            for ( int is2ndGroup = 0; is2ndGroup < 2; ++is2ndGroup ) {
              builder.MakeCompound( comp[is2ndGroup] );
              for ( mIt.Initialize( is2ndGroup ? theShape2:theShape1 ); mIt.More(); mIt.Next())
                if ( ! boundMembers[ is2ndGroup ].Contains( mIt.Value() ))
                  builder.Add( comp[ is2ndGroup ], mIt.Value() );
            }
            // check if theMap contains initial association for the comp's
            bool hasInitialAssoc = false;
            if ( memberType == TopAbs_EDGE ) {
              for ( TopExp_Explorer v( comp[0], TopAbs_VERTEX ); v.More(); v.Next())
                if ( theMap.IsBound( v.Current() )) {
                  hasInitialAssoc = true;
                  break;
                }
            }
            if ( hasInitialAssoc == bool( !theMap.IsEmpty() ))
              ok = FindSubShapeAssociation( comp[0], theMesh1, comp[1], theMesh2, theMap );
            else {
              TShapeShapeMap tmpMap;
              ok = FindSubShapeAssociation( comp[0], theMesh1, comp[1], theMesh2, tmpMap );
              if ( ok ) {
                TopTools_DataMapIteratorOfDataMapOfShapeShape mapIt( tmpMap._map1to2 );
                for ( ; mapIt.More(); mapIt.Next() )
                  theMap.Bind( mapIt.Key(), mapIt.Value());
              }
            }
          }
        }
        return ok;
      }
      // Each edge of an edge group is shared by own faces
      // ------------------------------------------------------------------
      //
      // map vertices to edges sharing them, avoid doubling edges in lists
      TopTools_DataMapOfShapeListOfShape v2e[2];
      for (int isFirst = 0; isFirst < 2; ++isFirst ) {
        const TopoDS_Shape& group = isFirst ? theShape1 : theShape2;
        TopTools_DataMapOfShapeListOfShape& veMap = v2e[ isFirst ? 0 : 1 ];
        TopTools_MapOfShape addedEdges;
        for ( TopExp_Explorer e( group, TopAbs_EDGE ); e.More(); e.Next() ) {
          const TopoDS_Shape& edge = e.Current();
          if ( addedEdges.Add( edge )) {
            for ( TopExp_Explorer v( edge, TopAbs_VERTEX ); v.More(); v.Next()) {
              const TopoDS_Shape& vertex = v.Current();
              if ( !veMap.IsBound( vertex )) {
                TopTools_ListOfShape l;
                veMap.Bind( vertex, l );
              }
              veMap( vertex ).Append( edge );
            }
          }
        }   
      }
      while ( !v2e[0].IsEmpty() )
      {
        // find a bound vertex
        TopoDS_Vertex V[2];
        TopTools_DataMapIteratorOfDataMapOfShapeListOfShape v2eIt( v2e[0] );
        for ( ; v2eIt.More(); v2eIt.Next())
          if ( theMap.IsBound( v2eIt.Key() )) {
            V[0] = TopoDS::Vertex( v2eIt.Key() );
            V[1] = TopoDS::Vertex( theMap( V[0] ));
            break;
          }
        if ( V[0].IsNull() )
          RETURN_BAD_RESULT("No more bound vertices");

        while ( !V[0].IsNull() && v2e[0].IsBound( V[0] )) {
          TopTools_ListOfShape& edges0 = v2e[0]( V[0] );
          TopTools_ListOfShape& edges1 = v2e[1]( V[1] );
          int nbE0 = edges0.Extent(), nbE1 = edges1.Extent();
          if ( nbE0 != nbE1 )
            RETURN_BAD_RESULT("Different nb of edges: "<< nbE0 << " != " << nbE1);

          if ( nbE0 == 1 )
          {
            TopoDS_Edge e0 = TopoDS::Edge( edges0.First() );
            TopoDS_Edge e1 = TopoDS::Edge( edges1.First() );
            v2e[0].UnBind( V[0] );
            v2e[1].UnBind( V[1] );
            InsertAssociation( e0, e1, theMap );
            MESSAGE("Assoc edge " << theMesh1->GetMeshDS()->ShapeToIndex( e0 )<<
                    " to "        << theMesh2->GetMeshDS()->ShapeToIndex( e1 ));
            V[0] = GetNextVertex( e0, V[0] );
            V[1] = GetNextVertex( e1, V[1] );
            if ( !V[0].IsNull() ) {
              InsertAssociation( V[0], V[1], theMap );
              MESSAGE("Assoc vertex " << theMesh1->GetMeshDS()->ShapeToIndex( V[0] )<<
                      " to "          << theMesh2->GetMeshDS()->ShapeToIndex( V[1] ));
            }
          }
          else if ( nbE0 == 2 )
          {
            // one of edges must have both ends bound
            TopoDS_Vertex v0e0 = GetNextVertex( TopoDS::Edge( edges0.First() ), V[0] );
            TopoDS_Vertex v1e0 = GetNextVertex( TopoDS::Edge( edges0.Last() ),  V[0] );
            TopoDS_Vertex v0e1 = GetNextVertex( TopoDS::Edge( edges1.First() ), V[1] );
            TopoDS_Vertex v1e1 = GetNextVertex( TopoDS::Edge( edges1.Last() ),  V[1] );
            TopoDS_Shape e0b, e1b, e0n, e1n, v1b; // bound and not-bound
            TopoDS_Vertex v0n, v1n;
            if ( theMap.IsBound( v0e0 )) {
              v0n = v1e0; e0b = edges0.First(); e0n = edges0.Last(); v1b = theMap( v0e0 );
            } else if ( theMap.IsBound( v1e0 )) {
              v0n = v0e0; e0n = edges0.First(); e0b = edges0.Last(); v1b = theMap( v1e0 );
            } else {
              RETURN_BAD_RESULT("None of vertices bound");
            }
            if ( v1b.IsSame( v1e1 )) {
              v1n = v0e1; e1n = edges1.First(); e1b = edges1.Last();
            } else {
              v1n = v1e1; e1b = edges1.First(); e1n = edges1.Last();
            }
            InsertAssociation( e0b, e1b, theMap );
            InsertAssociation( e0n, e1n, theMap );
            InsertAssociation( v0n, v1n, theMap );
            MESSAGE("Assoc edge " << theMesh1->GetMeshDS()->ShapeToIndex( e0b )<<
                    " to "        << theMesh2->GetMeshDS()->ShapeToIndex( e1b ));
            MESSAGE("Assoc edge " << theMesh1->GetMeshDS()->ShapeToIndex( e0n )<<
                    " to "        << theMesh2->GetMeshDS()->ShapeToIndex( e1n ));
            MESSAGE("Assoc vertex " << theMesh1->GetMeshDS()->ShapeToIndex( v0n )<<
                    " to "          << theMesh2->GetMeshDS()->ShapeToIndex( v1n ));
            v2e[0].UnBind( V[0] );
            v2e[1].UnBind( V[1] );
            V[0] = v0n;
            V[1] = v1n;
          }
          else {
            RETURN_BAD_RESULT("Not implemented");
          }
        }
      } //while ( !v2e[0].IsEmpty() )
      return true;
    }

    default:
      RETURN_BAD_RESULT("Unexpected shape type");

    } // end switch by shape type
  } // end case of available initial vertex association

  //======================================================================
  // 4) NO INITIAL VERTEX ASSOCIATION
  //======================================================================

  switch ( theShape1.ShapeType() ) {

  case TopAbs_EDGE: {
    // ----------------------------------------------------------------------
    TopoDS_Edge edge1 = TopoDS::Edge( theShape1 );
    TopoDS_Edge edge2 = TopoDS::Edge( theShape2 );
    if ( IsPropagationPossible( theMesh1, theMesh2 ))
    {
      TopoDS_Edge prpEdge = GetPropagationEdge( theMesh1, edge2, edge1 ).second;
      if ( !prpEdge.IsNull() )
      {
        TopoDS_Vertex VV1[2], VV2[2];
        TopExp::Vertices( edge1,   VV1[0], VV1[1], true );
        TopExp::Vertices( prpEdge, VV2[0], VV2[1], true );
        InsertAssociation( VV1[ 0 ], VV2[ 0 ], theMap );
        InsertAssociation( VV1[ 1 ], VV2[ 1 ], theMap );
        if ( VV1[0].IsSame( VV1[1] ) || // one of edges is closed
             VV2[0].IsSame( VV2[1] ) )
        {
          InsertAssociation( edge1, prpEdge, theMap ); // insert with a proper orientation
        }
        InsertAssociation( theShape1, theShape2, theMap );
        return true; // done
      }
    }
    if ( SMESH_MesherHelper::IsClosedEdge( edge1 ) &&
         SMESH_MesherHelper::IsClosedEdge( edge2 ))
    {
      // TODO: find out a proper orientation (is it possible?)
      InsertAssociation( edge1, edge2, theMap ); // insert with a proper orientation
      InsertAssociation( TopExp::FirstVertex(edge1), TopExp::FirstVertex(edge2),
                         theMap );
      InsertAssociation( theShape1, theShape2, theMap );
      return true; // done
    }
    break; // try by vertex closeness
  }

  case TopAbs_FACE: {
    // ----------------------------------------------------------------------
    if ( IsPropagationPossible( theMesh1, theMesh2 )) // try by propagation in one mesh
    {
      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 ));
      // find out if any edge of face2 is a propagation edge of outer edge1
      map<int,TopoDS_Edge> propag_edges; // use map to find the closest propagation edge
      for ( TopExp_Explorer exp( face2, TopAbs_EDGE ); exp.More(); exp.Next() ) {
        edge2 = TopoDS::Edge( exp.Current() );
        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
      {
        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");
        // 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);
          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();
        list< TopoDS_Edge >::iterator eIt2 = edges2.begin();
        for ( ; eIt1 != edges1.end(); ++eIt1, ++eIt2 )
        {
          InsertAssociation( *eIt1, *eIt2, theMap );
          VV1[0] = TopExp::FirstVertex( *eIt1, true );
          VV2[0] = TopExp::FirstVertex( *eIt2, true );
          InsertAssociation( VV1[0], VV2[0], theMap );
        }
        InsertAssociation( theShape1, theShape2, theMap );
        return true;
      }
    }
    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 of theShape1
      TopoDS_Edge E = GetBoundaryEdge( theShape1, *theMesh1 );
      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 );
        InsertAssociation( VV1[1], VV2[1], theMap );
        return FindSubShapeAssociation( theShape1, theMesh1, theShape2, theMesh2, theMap);
      }
    }
    break; // try by vertex closeness
  }
  default:;
  }

  // 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");

  if ( vMap1.Extent() == 1 ) {
    InsertAssociation( vMap1(1), vMap2(1), theMap );
    if ( theShape1.ShapeType() == TopAbs_EDGE ) {
      InsertAssociation( theShape1, theShape2, theMap );
      return true;
    }
    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 );
        InsertAssociation( VV1[1], VV1[1], theMap );
        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];
  for ( int i = 1; i <= vMap1.Extent(); ++i ) {
    box[ 0 ].Add( BRep_Tool::Pnt ( TopoDS::Vertex( vMap1( i ))));
    box[ 1 ].Add( BRep_Tool::Pnt ( TopoDS::Vertex( vMap2( i ))));
  }

  gp_Pnt gc[2]; // box center
  double x0,y0,z0, x1,y1,z1;
  box[0].Get( x0,y0,z0, x1,y1,z1 );
  gc[0] = 0.5 * ( gp_XYZ( x0,y0,z0 ) + gp_XYZ( x1,y1,z1 ));
  box[1].Get( x0,y0,z0, x1,y1,z1 );
  gc[1] = 0.5 * ( gp_XYZ( x0,y0,z0 ) + gp_XYZ( x1,y1,z1 ));

  // 1 -> 2
  gp_Vec vec01( gc[0], gc[1] );
  double scale = sqrt( box[1].SquareExtent() / box[0].SquareExtent() );

  // Find 2 closest vertices

  // get 2 linked vertices of shape 1 not belonging to an inner wire of a face
  TopoDS_Shape edge = getOuterEdge( theShape1, *theMesh1 );
  if ( edge.IsNull() || edge.ShapeType() != TopAbs_EDGE )
    RETURN_BAD_RESULT("Edge not found");

  TopExp::Vertices( TopoDS::Edge( edge.Oriented(TopAbs_FORWARD)), VV1[0], VV1[1]);
  if ( VV1[0].IsSame( VV1[1] ))
    RETURN_BAD_RESULT("Only closed edges");

  // find vertices closest to 2 linked vertices of shape 1
  for ( int i1 = 0; i1 < 2; ++i1 )
  {
    double dist2 = DBL_MAX;
    gp_Pnt p1 = BRep_Tool::Pnt( VV1[ i1 ]);
    p1.Translate( vec01 );
    p1.Scale( gc[1], scale );
    for ( int i2 = 1; i2 <= vMap2.Extent(); ++i2 )
    {
      TopoDS_Vertex V2 = TopoDS::Vertex( vMap2( i2 ));
      gp_Pnt p2 = BRep_Tool::Pnt ( V2 );
      double d2 = p1.SquareDistance( p2 );
      if ( d2 < dist2 && !V2.IsSame( VV2[ 0 ])) {
        VV2[ i1 ] = V2; dist2 = d2;
      }
    }
  }

  InsertAssociation( VV1[ 0 ], VV2[ 0 ], theMap );
  InsertAssociation( VV1[ 1 ], VV2[ 1 ], theMap );
  MESSAGE("Initial assoc VERT " << theMesh1->GetMeshDS()->ShapeToIndex( VV1[ 0 ] )<<
          " to "                << theMesh2->GetMeshDS()->ShapeToIndex( VV2[ 0 ] )<<
          "\nand         VERT " << theMesh1->GetMeshDS()->ShapeToIndex( VV1[ 1 ] )<<
          " to "                << theMesh2->GetMeshDS()->ShapeToIndex( VV2[ 1 ] ));
  if ( theShape1.ShapeType() == TopAbs_EDGE ) {
    InsertAssociation( theShape1, theShape2, theMap );
    return true;
  }

  return FindSubShapeAssociation( theShape1, theMesh1, theShape2, theMesh2, theMap );
}

Here is the call graph for this function:

TopoDS_Edge StdMeshers_ProjectionUtils::GetBoundaryEdge ( const TopoDS_Shape &  edgeContainer,
const SMESH_Mesh &  mesh 
) [static]

Return a boundary EDGE of edgeContainer.

Definition at line 2045 of file StdMeshers_ProjectionUtils.cxx.

{
  TopTools_IndexedMapOfShape facesOfEdgeContainer, facesNearEdge;
  TopExp::MapShapes( edgeContainer, TopAbs_FACE, facesOfEdgeContainer );

  if ( !facesOfEdgeContainer.IsEmpty() ) 
    for ( TopExp_Explorer exp(edgeContainer, TopAbs_EDGE); exp.More(); exp.Next() )
    {
      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 TopoDS_Edge();
}
TopoDS_Edge StdMeshers_ProjectionUtils::GetEdgeByVertices ( SMESH_Mesh *  theMesh,
const TopoDS_Vertex &  theV1,
const TopoDS_Vertex &  theV2 
) [static]

Finds an edge by its vertices in a main shape of the mesh.

Parameters:
aMesh- the mesh
V1- vertex 1
V2- vertex 2
Return values:
TopoDS_Edge- found edge

Definition at line 1442 of file StdMeshers_ProjectionUtils.cxx.

{
  if ( theMesh && !theV1.IsNull() && !theV2.IsNull() )
  {
    TopTools_ListIteratorOfListOfShape ancestorIt( theMesh->GetAncestors( theV1 ));
    for ( ; ancestorIt.More(); ancestorIt.Next() )
      if ( ancestorIt.Value().ShapeType() == TopAbs_EDGE )
        for ( TopExp_Explorer expV ( ancestorIt.Value(), TopAbs_VERTEX );
              expV.More();
              expV.Next() )
          if ( theV2.IsSame( expV.Current() ))
            return TopoDS::Edge( ancestorIt.Value() );
  }
  return TopoDS_Edge();
}
TopoDS_Face StdMeshers_ProjectionUtils::GetNextFace ( const TAncestorMap edgeToFaces,
const TopoDS_Edge &  edge,
const TopoDS_Face &  face 
) [static]

Return another face sharing an edge.

Parameters:
edgeToFaces- data map of descendants to ancestors
edgeToFaces- data map of descendants to ancestors
edge- edge
face- face
Return values:
TopoDS_Face- found face

Definition at line 1470 of file StdMeshers_ProjectionUtils.cxx.

{
//   if ( !edge.IsNull() && !face.IsNull() && edgeToFaces.Contains( edge ))
  if ( !edge.IsNull() && edgeToFaces.Contains( edge )) // PAL16202
  {
    TopTools_ListIteratorOfListOfShape ancestorIt( edgeToFaces.FindFromKey( edge ));
    for ( ; ancestorIt.More(); ancestorIt.Next() )
      if ( ancestorIt.Value().ShapeType() == TopAbs_FACE &&
           !face.IsSame( ancestorIt.Value() ))
        return TopoDS::Face( ancestorIt.Value() );
  }
  return TopoDS_Face();
}
TopoDS_Vertex StdMeshers_ProjectionUtils::GetNextVertex ( const TopoDS_Edge &  edge,
const TopoDS_Vertex &  vertex 
) [static]

Return other vertex of an edge.

Definition at line 1492 of file StdMeshers_ProjectionUtils.cxx.

{
  TopoDS_Vertex vF,vL;
  TopExp::Vertices(edge,vF,vL);
  if ( vF.IsSame( vL ))
    return TopoDS_Vertex();
  return vertex.IsSame( vF ) ? vL : vF; 
}
pair< int, TopoDS_Edge > StdMeshers_ProjectionUtils::GetPropagationEdge ( SMESH_Mesh *  aMesh,
const TopoDS_Edge &  theEdge,
const TopoDS_Edge &  fromEdge 
) [static]

Return an oriented propagation edge.

Return a propagation edge.

Parameters:
aMesh- mesh
fromEdge- start edge for propagation
Return values:
pair<int,TopoDS_Edge>- propagation step and found edge
Parameters:
aMesh- mesh
theEdge- edge to find by propagation
fromEdge- start edge for propagation
Return values:
pair<int,TopoDS_Edge>- propagation step and found edge

Definition at line 1513 of file StdMeshers_ProjectionUtils.cxx.

{
  TopTools_IndexedMapOfShape aChain;
  int step = 0;

  // List of edges, added to chain on the previous cycle pass
  TopTools_ListOfShape listPrevEdges;
  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;

    // Find the next portion of edges
    TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
    for (; itE.More(); itE.Next()) {
      TopoDS_Shape anE = itE.Value();

      // Iterate on faces, having edge <anE>
      TopTools_ListIteratorOfListOfShape itA (aMesh->GetAncestors(anE));
      for (; itA.More(); itA.Next()) {
        TopoDS_Shape aW = itA.Value();

        // There are objects of different type among the ancestors of edge
        if (aW.ShapeType() == TopAbs_WIRE) {
          TopoDS_Shape anOppE;

          BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
          Standard_Integer nb = 1, found = 0;
          TopTools_Array1OfShape anEdges (1,4);
          for (; aWE.More(); aWE.Next(), nb++) {
            if (nb > 4) {
              found = 0;
              break;
            }
            anEdges(nb) = aWE.Current();
            if (anEdges(nb).IsSame(anE)) found = nb;
          }

          if (nb == 5 && found > 0) {
            // Quadrangle face found, get an opposite edge
            Standard_Integer opp = found + 2;
            if (opp > 4) opp -= 4;
            anOppE = anEdges(opp);

            // add anOppE to aChain if ...
            if (!aChain.Contains(anOppE)) { // ... anOppE is not in aChain
              // Add found edge to the chain oriented so that to
              // have it co-directed with a forward MainEdge
              TopAbs_Orientation ori = anE.Orientation();
              if ( anEdges(opp).Orientation() == anEdges(found).Orientation() )
                ori = TopAbs::Reverse( ori );
              anOppE.Orientation( ori );
              if ( anOppE.IsSame( theEdge ))
                return make_pair( step, TopoDS::Edge( anOppE ));
              aChain.Add(anOppE);
              listCurEdges.Append(anOppE);
            }
          } // if (nb == 5 && found > 0)
        } // if (aF.ShapeType() == TopAbs_WIRE)
      } // for (; itF.More(); itF.Next())
    } // for (; itE.More(); itE.Next())

    listPrevEdges = listCurEdges;
  } // while (listPrevEdges.Extent() > 0)

  return make_pair( INT_MAX, TopoDS_Edge());
}
void StdMeshers_ProjectionUtils::InitVertexAssociation ( const SMESH_Hypothesis *  theHyp,
TShapeShapeMap theAssociationMap 
) [static]

Insert vertex association defined by a hypothesis into a map.

Parameters:
theHyp- hypothesis
theAssociationMap- association map
theTargetShape- the shape theHyp assigned to

Definition at line 1378 of file StdMeshers_ProjectionUtils.cxx.

{
  string hypName = theHyp->GetName();
  if ( hypName == "ProjectionSource1D" ) {
    const StdMeshers_ProjectionSource1D * hyp =
      static_cast<const StdMeshers_ProjectionSource1D*>( theHyp );
    if ( hyp->HasVertexAssociation() )
      InsertAssociation( hyp->GetTargetVertex(),hyp->GetSourceVertex(),theAssociationMap );
  }
  else if ( hypName == "ProjectionSource2D" ) {
    const StdMeshers_ProjectionSource2D * hyp =
      static_cast<const StdMeshers_ProjectionSource2D*>( theHyp );
    if ( hyp->HasVertexAssociation() ) {
      InsertAssociation( hyp->GetTargetVertex(1),hyp->GetSourceVertex(1),theAssociationMap);
      InsertAssociation( hyp->GetTargetVertex(2),hyp->GetSourceVertex(2),theAssociationMap);
    }
  }
  else if ( hypName == "ProjectionSource3D" ) {
    const StdMeshers_ProjectionSource3D * hyp =
      static_cast<const StdMeshers_ProjectionSource3D*>( theHyp );
    if ( hyp->HasVertexAssociation() ) {
      InsertAssociation( hyp->GetTargetVertex(1),hyp->GetSourceVertex(1),theAssociationMap);
      InsertAssociation( hyp->GetTargetVertex(2),hyp->GetSourceVertex(2),theAssociationMap);
    }
  }
}
bool StdMeshers_ProjectionUtils::InsertAssociation ( const TopoDS_Shape &  theShape1,
const TopoDS_Shape &  theShape2,
TShapeShapeMap theAssociationMap 
) [static]

Inserts association theShape1 <-> theShape2 to TShapeShapeMap.

Parameters:
theShape1- target shape
theShape2- source shape
theAssociationMap- association map
theBidirectional- if false, inserts theShape1 -> theShape2 association
Return values:
bool- true if there was no association for these shapes before
Parameters:
theShape1- target shape
theShape2- source shape
theAssociationMap- association map
Return values:
bool- true if there was no association for these shapes before

Definition at line 1416 of file StdMeshers_ProjectionUtils.cxx.

{
  if ( !theShape1.IsNull() && !theShape2.IsNull() ) {
    SHOW_SHAPE(theShape1,"Assoc ");
    SHOW_SHAPE(theShape2," to ");
    bool isNew = ( theAssociationMap.Bind( theShape1, theShape2 ));
    return isNew;
  }
  else {
    throw SALOME_Exception("StdMeshers_ProjectionUtils: attempt to associate NULL shape");
  }
  return false;
}

Here is the call graph for this function:

bool StdMeshers_ProjectionUtils::MakeComputed ( SMESH_subMesh *  sm,
const int  iterationNb = 0 
) [static]

Check that submeshis is computed and try to compute it if is not.

Check that submesh is computed and try to compute it if is not.

Parameters:
sm- submesh to compute
iterationNb- int used to stop infinite recursive call
Return values:
bool- true if computed

Definition at line 1940 of file StdMeshers_ProjectionUtils.cxx.

{
  if ( iterationNb > 10 )
    RETURN_BAD_RESULT("Infinite recursive projection");
  if ( !sm )
    RETURN_BAD_RESULT("NULL submesh");
  if ( sm->IsMeshComputed() )
    return true;

  SMESH_Mesh* mesh = sm->GetFather();
  SMESH_Gen* gen   = mesh->GetGen();
  SMESH_Algo* algo = sm->GetAlgo();
  if ( !algo )
  {
    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_")
    return gen->Compute( *mesh, sm->GetSubShape() );

  // try to compute source mesh

  const list <const SMESHDS_Hypothesis *> & hyps =
    algo->GetUsedHypothesis( *mesh, sm->GetSubShape() );

  TopoDS_Shape srcShape;
  SMESH_Mesh* srcMesh = 0;
  list <const SMESHDS_Hypothesis*>::const_iterator hIt = hyps.begin();
  for ( ; srcShape.IsNull() && hIt != hyps.end(); ++hIt ) {
    string hypName = (*hIt)->GetName();
    if ( hypName == "ProjectionSource1D" ) {
      const StdMeshers_ProjectionSource1D * hyp =
        static_cast<const StdMeshers_ProjectionSource1D*>( *hIt );
      srcShape = hyp->GetSourceEdge();
      srcMesh = hyp->GetSourceMesh();
    }
    else if ( hypName == "ProjectionSource2D" ) {
      const StdMeshers_ProjectionSource2D * hyp =
        static_cast<const StdMeshers_ProjectionSource2D*>( *hIt );
      srcShape = hyp->GetSourceFace();
      srcMesh = hyp->GetSourceMesh();
    }
    else if ( hypName == "ProjectionSource3D" ) {
      const StdMeshers_ProjectionSource3D * hyp =
        static_cast<const StdMeshers_ProjectionSource3D*>( *hIt );
      srcShape = hyp->GetSource3DShape();
      srcMesh = hyp->GetSourceMesh();
    }
  }
  if ( srcShape.IsNull() ) // no projection source defined
    return gen->Compute( *mesh, sm->GetSubShape() );

  if ( srcShape.IsSame( sm->GetSubShape() ))
    RETURN_BAD_RESULT("Projection from self");
    
  if ( !srcMesh )
    srcMesh = mesh;

  if ( MakeComputed( srcMesh->GetSubMesh( srcShape ), iterationNb + 1 ))
    return gen->Compute( *mesh, sm->GetSubShape() );

  return false;
}
TopoDS_Shape StdMeshers_ProjectionUtils::OuterShape ( const TopoDS_Face &  face,
TopAbs_ShapeEnum  type 
) [static]

Return any sub-shape of a face belonging to the outer wire.

Parameters:
face- the face
type- type of sub-shape to return
Return values:
TopoDS_Shape- the found sub-shape

Definition at line 1922 of file StdMeshers_ProjectionUtils.cxx.

{
  TopExp_Explorer exp( BRepTools::OuterWire( face ), type );
  if ( exp.More() )
    return exp.Current();
  return TopoDS_Shape();
}
void StdMeshers_ProjectionUtils::SetEventListener ( SMESH_subMesh *  subMesh,
TopoDS_Shape  srcShape,
SMESH_Mesh *  srcMesh 
) [static]

Set event listeners to submesh with projection algo.

Parameters:
subMesh- submesh with projection algo
srcShape- source shape
srcMesh- source mesh

Definition at line 2130 of file StdMeshers_ProjectionUtils.cxx.

{
  // Set listener that resets an event listener on source submesh when
  // "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
  if ( !srcShape.IsNull() )
  {
    if ( !srcMesh )
      srcMesh = subMesh->GetFather();

    SMESH_subMesh* srcShapeSM = srcMesh->GetSubMesh( srcShape );

    if ( srcShapeSM != subMesh ) {
      if ( srcShapeSM->GetSubMeshDS() &&
           srcShapeSM->GetSubMeshDS()->IsComplexSubmesh() )
      {  // source shape is a group
        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() );
          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
      {
        subMesh->SetEventListener( GetSrcSubMeshListener(),
                                   SMESH_subMeshEventListenerData::MakeData( subMesh ),
                                   srcShapeSM );
      }
    }
  }
}

Here is the call graph for this function:


The documentation for this class was generated from the following files: