+//=======================================================================
+//function : getSubMeshes
+//purpose : for a submesh on shape to which elements are not bound directly,
+// return submeshes containing elements
+//=======================================================================
+
+typedef list<SMESHDS_SubMesh*> TListOfSubMeshes;
+
+bool getSubMeshes(::SMESH_subMesh* theSubMesh,
+ TListOfSubMeshes& theSubMeshList)
+{
+ int size = theSubMeshList.size();
+
+ SMESH_Mesh* aMesh = theSubMesh->GetFather();
+ SMESHDS_Mesh* aMeshDS = aMesh->GetMeshDS();
+ SMESHDS_SubMesh* aSubMeshDS = theSubMesh->GetSubMeshDS();
+
+ // nodes can be bound to either vertex, edge, face or solid_or_shell
+ TopoDS_Shape aShape = theSubMesh->GetSubShape();
+ switch ( aShape.ShapeType() )
+ {
+ case TopAbs_SOLID: {
+ // add submesh of solid itself
+ aSubMeshDS = aMeshDS->MeshElements( aShape );
+ if ( aSubMeshDS )
+ theSubMeshList.push_back( aSubMeshDS );
+ // and of the first shell
+ TopExp_Explorer exp( aShape, TopAbs_SHELL );
+ if ( exp.More() ) {
+ aSubMeshDS = aMeshDS->MeshElements( exp.Current() );
+ if ( aSubMeshDS )
+ theSubMeshList.push_back( aSubMeshDS );
+ }
+ break;
+ }
+ case TopAbs_WIRE:
+ case TopAbs_COMPOUND:
+ case TopAbs_COMPSOLID: {
+ // call getSubMeshes() for sub-shapes
+ list<TopoDS_Shape> shapeList;
+ shapeList.push_back( aShape );
+ list<TopoDS_Shape>::iterator sh = shapeList.begin();
+ for ( ; sh != shapeList.end(); ++sh ) {
+ for ( TopoDS_Iterator it( *sh ); it.More(); it.Next() ) {
+ if ( ::SMESH_subMesh* aSubMesh = aMesh->GetSubMeshContaining( it.Value() ))
+ getSubMeshes( aSubMesh, theSubMeshList ); // add found submesh or explore deeper
+ else
+ // no submesh for a compound inside compound
+ shapeList.push_back( it.Value() );
+ }
+ }
+ // return only unique submeshes
+ set<SMESHDS_SubMesh*> smSet;
+ TListOfSubMeshes::iterator sm = theSubMeshList.begin();
+ while ( sm != theSubMeshList.end() ) {
+ if ( !smSet.insert( *sm ).second )
+ sm = theSubMeshList.erase( sm );
+ else
+ ++sm;
+ }
+ break;
+ }
+ default:
+ if ( aSubMeshDS )
+ theSubMeshList.push_back( aSubMeshDS );
+ }
+ return size < theSubMeshList.size();
+}
+