+
+//=============================================================================
+/*!
+ * \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()
+{
+ _mySubMeshOrder.clear();
+}
+
+//=============================================================================
+/*!
+ * \brief remove submesh order from Mesh
+ */
+//=============================================================================
+
+void SMESH_Mesh::SetMeshOrder(const TListOfListOfInt& theOrder )
+{
+ _mySubMeshOrder = theOrder;
+}
+
+//=============================================================================
+/*!
+ * \brief return submesh order if any
+ */
+//=============================================================================
+
+const TListOfListOfInt& SMESH_Mesh::GetMeshOrder() const
+{
+ return _mySubMeshOrder;
+}
+
+//=============================================================================
+/*!
+ * \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 ( !_mySubMeshOrder.size() || theListToSort.size() < 2)
+ return true;
+
+ bool res = false;
+ std::vector<SMESH_subMesh*> onlyOrderedList, smVec;
+
+ // collect all ordered submeshes in one list as pointers
+ // and get their positions within theListToSort
+ typedef std::vector<SMESH_subMesh*>::iterator TPosInList;
+ std::map< int, TPosInList > sortedPos;
+ TPosInList smBeg = theListToSort.begin(), smEnd = theListToSort.end();
+ TListOfListOfInt::const_iterator listIdsIt = _mySubMeshOrder.begin();
+ for( ; listIdsIt != _mySubMeshOrder.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() )
+ {
+ 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] );
+ if ( smPos != smEnd ) {
+ sortedPos[ std::distance( smBeg, smPos )] = smPos;
+ if ( sortedPos.size() > onlyOrderedList.size() )
+ onlyOrderedList.push_back( smVec[i] );
+ }
+ }
+ }
+ if (onlyOrderedList.size() < 2)
+ return res;
+ res = true;
+
+ std::vector<SMESH_subMesh*>::iterator onlyBIt = onlyOrderedList.begin();
+ std::vector<SMESH_subMesh*>::iterator onlyEIt = onlyOrderedList.end();
+
+ // iterate on ordered sub-meshes and insert them in detected positions
+ std::map< int, TPosInList >::iterator i_pos = sortedPos.begin();
+ for ( ; onlyBIt != onlyEIt; ++onlyBIt, ++i_pos )
+ *(i_pos->second) = *onlyBIt;
+
+ return res;
+}
+
+//================================================================================
+/*!
+ * \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 = _mySubMeshOrder.begin();
+ for( ; listIdsIt != _mySubMeshOrder.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
+{
+ theSubMeshes.clear();
+ TopTools_ListIteratorOfListOfShape it( GetAncestors( theSubShape ));
+ for (; it.More(); it.Next() )
+ if ( SMESH_subMesh* sm = GetSubMeshContaining( it.Value() ))
+ theSubMeshes.push_back(sm);
+
+ // sort submeshes according to stored mesh order
+ SortByMeshOrder( theSubMeshes );
+}