+SMDSAbs_ElementType SMESH_Mesh::GetElementType( const smIdType id, const bool iselem )
+{
+ return _meshDS->GetElementType( id, iselem );
+}
+
+//=============================================================================
+/*!
+ * \brief Convert group on geometry into standalone group
+ */
+//=============================================================================
+
+SMESH_Group* SMESH_Mesh::ConvertToStandalone ( int theGroupID )
+{
+ SMESH_Group* aGroup = 0;
+ std::map < int, SMESH_Group * >::iterator itg = _mapGroup.find( theGroupID );
+ if ( itg == _mapGroup.end() )
+ return aGroup;
+
+ SMESH_Group* anOldGrp = (*itg).second;
+ if ( !anOldGrp || !anOldGrp->GetGroupDS() )
+ return aGroup;
+ SMESHDS_GroupBase* anOldGrpDS = anOldGrp->GetGroupDS();
+
+ // create new standalone group
+ aGroup = new SMESH_Group (theGroupID, this, anOldGrpDS->GetType(), anOldGrp->GetName() );
+ _mapGroup[theGroupID] = aGroup;
+
+ SMESHDS_Group* aNewGrpDS = dynamic_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
+ GetMeshDS()->RemoveGroup( anOldGrpDS );
+ GetMeshDS()->AddGroup( aNewGrpDS );
+
+ // add elements (or nodes) into new created group
+ SMDS_ElemIteratorPtr anItr = anOldGrpDS->GetElements();
+ while ( anItr->more() )
+ aNewGrpDS->Add( (anItr->next())->GetID() );
+
+ // set color
+ aNewGrpDS->SetColor( anOldGrpDS->GetColor() );
+
+ // remove old group
+ delete anOldGrp;
+
+ return aGroup;
+}
+
+//=============================================================================
+/*!
+ * \brief remove submesh order from Mesh
+ */
+//=============================================================================
+
+void SMESH_Mesh::ClearMeshOrder()
+{
+ _subMeshOrder.clear();
+}
+
+//=============================================================================
+/*!
+ * \brief remove submesh order from Mesh
+ */
+//=============================================================================
+
+void SMESH_Mesh::SetMeshOrder(const TListOfListOfInt& theOrder )
+{
+ _subMeshOrder = theOrder;
+}
+
+//=============================================================================
+/*!
+ * \brief return submesh order if any
+ */
+//=============================================================================
+
+const TListOfListOfInt& SMESH_Mesh::GetMeshOrder() const
+{
+ return _subMeshOrder;
+}
+
+//=============================================================================
+/*!
+ * \brief fill _mapAncestors
+ */
+//=============================================================================
+
+void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
+{
+ int desType, ancType;
+ if ( !theShape.IsSame( GetShapeToMesh()) && theShape.ShapeType() == TopAbs_COMPOUND )
+ {
+ // a geom group is added. Insert it into lists of ancestors before
+ // the first ancestor more complex than group members
+ TopoDS_Iterator subIt( theShape );
+ if ( !subIt.More() ) return;
+ int memberType = subIt.Value().ShapeType();
+ for ( desType = TopAbs_VERTEX; desType >= memberType; desType-- )
+ for (TopExp_Explorer des( theShape, TopAbs_ShapeEnum( desType )); des.More(); des.Next())
+ {
+ if ( !_mapAncestors.Contains( des.Current() )) continue;// issue 0020982
+ TopTools_ListOfShape& ancList = _mapAncestors.ChangeFromKey( des.Current() );
+ TopTools_ListIteratorOfListOfShape ancIt (ancList);
+ while ( ancIt.More() && ancIt.Value().ShapeType() >= memberType )
+ ancIt.Next();
+ if ( ancIt.More() ) ancList.InsertBefore( theShape, ancIt );
+ else ancList.Append( theShape );
+ }
+ }
+ else // else added for 52457: Addition of hypotheses is 8 time longer than meshing
+ {
+ for ( desType = TopAbs_VERTEX; desType > TopAbs_COMPOUND; desType-- )
+ for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- )
+ TopExp::MapShapesAndAncestors ( theShape,
+ (TopAbs_ShapeEnum) desType,
+ (TopAbs_ShapeEnum) ancType,
+ _mapAncestors );
+ }
+ // visit COMPOUNDs inside a COMPOUND that are not reachable by TopExp_Explorer
+ if ( theShape.ShapeType() == TopAbs_COMPOUND )
+ {
+ TopoDS_Iterator sIt(theShape);
+ if ( sIt.More() && sIt.Value().ShapeType() == TopAbs_COMPOUND )
+ for ( ; sIt.More(); sIt.Next() )
+ if ( sIt.Value().ShapeType() == TopAbs_COMPOUND )
+ fillAncestorsMap( sIt.Value() );
+ }
+}
+
+//=============================================================================
+/*!
+ * \brief sort submeshes according to stored mesh order
+ * \param theListToSort in out list to be sorted
+ * \return FALSE if nothing sorted
+ */
+//=============================================================================
+
+bool SMESH_Mesh::SortByMeshOrder(std::vector<SMESH_subMesh*>& theListToSort) const
+{
+ if ( _subMeshOrder.empty() || theListToSort.size() < 2 )
+ return true;
+
+
+ // collect all ordered sub-meshes in smVec as pointers
+ // and get their positions within theListToSort
+
+ std::vector<SMESH_subMesh*> smVec;
+ typedef std::vector<SMESH_subMesh*>::iterator TPosInList;
+ std::map< size_t, size_t > sortedPos; // index in theListToSort to order
+ TPosInList smBeg = theListToSort.begin(), smEnd = theListToSort.end();
+ TListOfListOfInt::const_iterator listIdsIt = _subMeshOrder.begin();
+ bool needSort = false;
+ for( ; listIdsIt != _subMeshOrder.end(); listIdsIt++)
+ {
+ const TListOfInt& listOfId = *listIdsIt;
+ // convert sm ids to sm's
+ smVec.clear();
+ TListOfInt::const_iterator idIt = listOfId.begin();
+ for ( ; idIt != listOfId.end(); idIt++ )
+ {
+ if ( SMESH_subMesh * sm = GetSubMeshContaining( *idIt ))
+ {
+ smVec.push_back( sm );
+ if ( sm->GetSubMeshDS() && sm->GetSubMeshDS()->IsComplexSubmesh() )
+ {
+ smVec.reserve( smVec.size() + sm->GetSubMeshDS()->NbSubMeshes() );
+ SMESHDS_SubMeshIteratorPtr smdsIt = sm->GetSubMeshDS()->GetSubMeshIterator();
+ while ( smdsIt->more() )
+ {
+ const SMESHDS_SubMesh* smDS = smdsIt->next();
+ if (( sm = GetSubMeshContaining( smDS->GetID() )))
+ smVec.push_back( sm );
+ }
+ }
+ }
+ }
+ // find smVec items in theListToSort
+ for ( size_t i = 0; i < smVec.size(); ++i )
+ {
+ TPosInList smPos = find( smBeg, smEnd, smVec[i] ); // position in theListToSort
+ if ( smPos != smEnd )
+ {
+ size_t posInList = std::distance( smBeg, smPos );
+ size_t order = sortedPos.size();
+ sortedPos.insert( std::make_pair( posInList, order ));
+ if ( posInList != order )
+ needSort = true;
+ }
+ }
+ }
+ if ( ! needSort )
+ return false;
+
+ // set sm of sortedPos from theListToSort to front of orderedSM
+ // and the rest of theListToSort to orderedSM end
+
+ std::vector<SMESH_subMesh*> orderedSM;
+ orderedSM.reserve( theListToSort.size() );
+ orderedSM.resize( sortedPos.size() );
+
+ size_t iPrev = 0;
+ sortedPos.insert( std::make_pair( theListToSort.size(), sortedPos.size() ));
+ for ( const auto & pos_order : sortedPos )
+ {
+ const size_t& posInList = pos_order.first;
+ const size_t& order = pos_order.second;
+ if ( order < sortedPos.size() - 1 )
+ orderedSM[ order ] = theListToSort[ posInList ];
+
+ if ( iPrev < posInList )
+ orderedSM.insert( orderedSM.end(),
+ theListToSort.begin() + iPrev,
+ theListToSort.begin() + posInList );
+ iPrev = posInList + 1;
+ }
+
+ theListToSort.swap( orderedSM );
+
+ return true;
+}
+
+//================================================================================
+/*!
+ * \brief Return true if given order of sub-meshes is OK
+ */
+//================================================================================
+
+bool SMESH_Mesh::IsOrderOK( const SMESH_subMesh* smBefore,
+ const SMESH_subMesh* smAfter ) const
+{
+ TListOfListOfInt::const_iterator listIdsIt = _subMeshOrder.begin();
+ for( ; listIdsIt != _subMeshOrder.end(); listIdsIt++)
+ {
+ const TListOfInt& listOfId = *listIdsIt;
+ int iB = -1, iA = -1, i = 0;
+ for ( TListOfInt::const_iterator id = listOfId.begin(); id != listOfId.end(); ++id, ++i )
+ {
+ if ( *id == smBefore->GetId() )
+ {
+ iB = i;
+ if ( iA > -1 )
+ return iB < iA;
+ }
+ else if ( *id == smAfter->GetId() )
+ {
+ iA = i;
+ if ( iB > -1 )
+ return iB < iA;
+ }
+ }
+ }
+ return true; // no order imposed to given sub-meshes
+}
+
+//=============================================================================
+/*!
+ * \brief sort submeshes according to stored mesh order
+ * \param theListToSort in out list to be sorted
+ * \return FALSE if nothing sorted
+ */
+//=============================================================================
+
+void SMESH_Mesh::getAncestorsSubMeshes (const TopoDS_Shape& theSubShape,
+ std::vector< SMESH_subMesh* >& theSubMeshes) const