+
+ //================================================================================
+ /*!
+ * \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, edges, nbEdgesInWire, v1);
+ 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 = HERE::GetBoundaryEdge( theGroup1, theMesh );
+ 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(), /*is2nd=*/true ) &&
+ subshapes2.Contains( ancestIt.Value() ))
+ face2 = ancestIt.Value();
+ }
+ if ( face2.IsNull() )
+ return false;
+
+ HERE::InsertAssociation( face1, face2, theMap);
+ }
+ }
+ }
+ return true;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Return true if uv position of the vIndex-th vertex of edge on face is close
+ * enough to given uv
+ */
+ //================================================================================
+
+ bool sameVertexUV( const TopoDS_Edge& edge,
+ const TopoDS_Face& face,
+ const int& vIndex,
+ const gp_Pnt2d& uv,
+ const double& tol2d )
+ {
+ TopoDS_Vertex VV[2];
+ TopExp::Vertices( edge, VV[0], VV[1], true);
+ gp_Pnt2d v1UV = BRep_Tool::Parameters( VV[vIndex], face);
+ double dist2d = v1UV.Distance( uv );
+ return dist2d < tol2d;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Returns an EDGE suitable for search of initial vertex association
+ */
+ //================================================================================
+
+ bool getOuterEdges( const TopoDS_Shape shape,
+ SMESH_Mesh& mesh,
+ std::list< TopoDS_Edge >& allBndEdges )
+ {
+ if ( shape.ShapeType() == TopAbs_COMPOUND )
+ {
+ TopoDS_Iterator it( shape );
+ if ( it.More() && it.Value().ShapeType() == TopAbs_FACE ) // group of FACEs
+ {
+ // look for a boundary EDGE of a group
+ StdMeshers_ProjectionUtils::GetBoundaryEdge( shape, mesh, &allBndEdges );
+ if ( !allBndEdges.empty() )
+ return true;
+ }
+ }
+ TopExp_Explorer expF( shape, TopAbs_FACE ), expE;
+ if ( expF.More() ) {
+ for ( ; expF.More(); expF.Next() ) {
+ TopoDS_Shape wire =
+ StdMeshers_ProjectionUtils::OuterShape( TopoDS::Face( expF.Current() ), TopAbs_WIRE );
+ for ( expE.Init( wire, TopAbs_EDGE ); expE.More(); expE.Next() )
+ if ( !SMESH_MesherHelper::IsClosedEdge( TopoDS::Edge( expE.Current() )))
+ allBndEdges.push_back( TopoDS::Edge( expE.Current() ));
+ }
+ }
+ else if ( shape.ShapeType() != TopAbs_EDGE) { // no faces
+ for ( expE.Init( shape, TopAbs_EDGE ); expE.More(); expE.Next() )
+ if ( !SMESH_MesherHelper::IsClosedEdge( TopoDS::Edge( expE.Current() )))
+ allBndEdges.push_back( TopoDS::Edge( expE.Current() ));
+ }
+ else if ( shape.ShapeType() == TopAbs_EDGE ) {
+ if ( !SMESH_MesherHelper::IsClosedEdge( TopoDS::Edge( shape )))
+ allBndEdges.push_back( TopoDS::Edge( shape ));
+ }
+ return !allBndEdges.empty();
+ }
+
+} // namespace