+ Unexpect aCatch(SalomeException);
+ DriverDAT_W_SMDS_Mesh myWriter;
+ myWriter.SetFile( file );
+ myWriter.SetMesh( meshPart ? (SMESHDS_Mesh*) meshPart : _myMeshDS );
+ myWriter.SetMeshId(_id);
+ myWriter.Perform();
+}
+
+//================================================================================
+/*!
+ * \brief Export the mesh to an UNV file
+ */
+//================================================================================
+
+void SMESH_Mesh::ExportUNV(const char * file,
+ const SMESHDS_Mesh* meshPart) throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ DriverUNV_W_SMDS_Mesh myWriter;
+ myWriter.SetFile( file );
+ myWriter.SetMesh( meshPart ? (SMESHDS_Mesh*) meshPart : _myMeshDS );
+ myWriter.SetMeshId(_id);
+ // myWriter.SetGroups(_mapGroup);
+
+ if ( !meshPart )
+ {
+ for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
+ SMESH_Group* aGroup = it->second;
+ SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
+ if ( aGroupDS ) {
+ string aGroupName = aGroup->GetName();
+ aGroupDS->SetStoreName( aGroupName.c_str() );
+ myWriter.AddGroup( aGroupDS );
+ }
+ }
+ }
+ myWriter.Perform();
+}
+
+//================================================================================
+/*!
+ * \brief Export the mesh to an STL file
+ */
+//================================================================================
+
+void SMESH_Mesh::ExportSTL(const char * file,
+ const bool isascii,
+ const SMESHDS_Mesh* meshPart) throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ DriverSTL_W_SMDS_Mesh myWriter;
+ myWriter.SetFile( file );
+ myWriter.SetIsAscii( isascii );
+ myWriter.SetMesh( meshPart ? (SMESHDS_Mesh*) meshPart : _myMeshDS);
+ myWriter.SetMeshId(_id);
+ myWriter.Perform();
+}
+
+//================================================================================
+/*!
+ * \brief Export the mesh to the CGNS file
+ */
+//================================================================================
+
+void SMESH_Mesh::ExportCGNS(const char * file,
+ const SMESHDS_Mesh* meshDS,
+ const char * meshName)
+{
+ int res = Driver_Mesh::DRS_FAIL;
+#ifdef WITH_CGNS
+ DriverCGNS_Write myWriter;
+ myWriter.SetFile( file );
+ myWriter.SetMesh( const_cast<SMESHDS_Mesh*>( meshDS ));
+ myWriter.SetMeshName( SMESH_Comment("Mesh_") << meshDS->GetPersistentId());
+ if ( meshName && meshName[0] )
+ myWriter.SetMeshName( meshName );
+ res = myWriter.Perform();
+#endif
+ if ( res != Driver_Mesh::DRS_OK )
+ throw SALOME_Exception("Export failed");
+}
+
+//================================================================================
+/*!
+ * \brief Export the mesh to a GMF file
+ */
+//================================================================================
+
+void SMESH_Mesh::ExportGMF(const char * file,
+ const SMESHDS_Mesh* meshDS,
+ bool withRequiredGroups)
+{
+ DriverGMF_Write myWriter;
+ myWriter.SetFile( file );
+ myWriter.SetMesh( const_cast<SMESHDS_Mesh*>( meshDS ));
+ myWriter.SetExportRequiredGroups( withRequiredGroups );
+
+ myWriter.Perform();
+}
+
+//================================================================================
+/*!
+ * \brief Return a ratio of "compute cost" of computed sub-meshes to the whole
+ * "compute cost".
+ */
+//================================================================================
+
+double SMESH_Mesh::GetComputeProgress() const
+{
+ double totalCost = 1e-100, computedCost = 0;
+ const SMESH_subMesh* curSM = _gen->GetCurrentSubMesh();
+
+ // get progress of a current algo
+ TColStd_MapOfInteger currentSubIds;
+ if ( curSM )
+ if ( SMESH_Algo* algo = curSM->GetAlgo() )
+ {
+ int algoNotDoneCost = 0, algoDoneCost = 0;
+ const std::vector<SMESH_subMesh*>& smToCompute = algo->SubMeshesToCompute();
+ for ( size_t i = 0; i < smToCompute.size(); ++i )
+ {
+ if ( smToCompute[i]->IsEmpty() || smToCompute.size() == 1 )
+ algoNotDoneCost += smToCompute[i]->GetComputeCost();
+ else
+ algoDoneCost += smToCompute[i]->GetComputeCost();
+ currentSubIds.Add( smToCompute[i]->GetId() );
+ }
+ double rate = 0;
+ try
+ {
+ OCC_CATCH_SIGNALS;
+ rate = algo->GetProgress();
+ }
+ catch (...) {
+#ifdef _DEBUG_
+ cerr << "Exception in " << algo->GetName() << "::GetProgress()" << endl;
+#endif
+ }
+ if ( 0. < rate && rate < 1.001 )
+ {
+ computedCost += rate * ( algoDoneCost + algoNotDoneCost );
+ }
+ else
+ {
+ rate = algo->GetProgressByTic();
+ computedCost += algoDoneCost + rate * algoNotDoneCost;
+ }
+ // cout << "rate: "<<rate << " algoNotDoneCost: " << algoNotDoneCost << endl;
+ }
+
+ // get cost of already treated sub-meshes
+ if ( SMESH_subMesh* mainSM = GetSubMeshContaining( 1 ))
+ {
+ SMESH_subMeshIteratorPtr smIt = mainSM->getDependsOnIterator(/*includeSelf=*/true);
+ while ( smIt->more() )
+ {
+ const SMESH_subMesh* sm = smIt->next();
+ const int smCost = sm->GetComputeCost();
+ totalCost += smCost;
+ if ( !currentSubIds.Contains( sm->GetId() ) )
+ {
+ if (( !sm->IsEmpty() ) ||
+ ( sm->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE &&
+ !sm->DependsOn( curSM ) ))
+ computedCost += smCost;
+ }
+ }
+ }
+ // cout << "Total: " << totalCost
+ // << " computed: " << computedCost << " progress: " << computedCost / totalCost
+ // << " nbElems: " << GetMeshDS()->GetMeshInfo().NbElements() << endl;
+ return computedCost / totalCost;
+}
+
+//================================================================================
+/*!
+ * \brief Return number of nodes in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbNodes() const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->NbNodes();
+}
+
+//================================================================================
+/*!
+ * \brief Return number of edges of given order in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::Nb0DElements() const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().Nb0DElements();
+}
+
+//================================================================================
+/*!
+ * \brief Return number of edges of given order in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbEdges(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbEdges(order);
+}
+
+//================================================================================
+/*!
+ * \brief Return number of faces of given order in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbFaces(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbFaces(order);
+}
+
+//================================================================================
+/*!
+ * \brief Return the number of faces in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbTriangles(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbTriangles(order);
+}
+
+//================================================================================
+/*!
+ * \brief Return number of biquadratic triangles in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbBiQuadTriangles() const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbBiQuadTriangles();
+}
+
+//================================================================================
+/*!
+ * \brief Return the number nodes faces in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbQuadrangles(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbQuadrangles(order);
+}
+
+//================================================================================
+/*!
+ * \brief Return number of biquadratic quadrangles in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbBiQuadQuadrangles() const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbBiQuadQuadrangles();
+}
+
+//================================================================================
+/*!
+ * \brief Return the number of polygonal faces in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbPolygons(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbPolygons(order);
+}
+
+//================================================================================
+/*!
+ * \brief Return number of volumes of given order in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbVolumes(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbVolumes(order);
+}
+
+//================================================================================
+/*!
+ * \brief Return number of tetrahedrons of given order in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbTetras(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbTetras(order);
+}
+
+//================================================================================
+/*!
+ * \brief Return number of hexahedrons of given order in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbHexas(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbHexas(order);
+}
+
+//================================================================================
+/*!
+ * \brief Return number of triquadratic hexahedrons in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbTriQuadraticHexas() const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbTriQuadHexas();
+}
+
+//================================================================================
+/*!
+ * \brief Return number of pyramids of given order in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbPyramids(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbPyramids(order);
+}
+
+//================================================================================
+/*!
+ * \brief Return number of prisms (penthahedrons) of given order in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbPrisms(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbPrisms(order);
+}
+
+//================================================================================
+/*!
+ * \brief Return number of hexagonal prisms in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbHexagonalPrisms() const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbHexPrisms();
+}
+
+//================================================================================
+/*!
+ * \brief Return number of polyhedrons in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbPolyhedrons() const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbPolyhedrons();
+}
+
+//================================================================================
+/*!
+ * \brief Return number of ball elements in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbBalls() const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->GetMeshInfo().NbBalls();
+}
+
+//================================================================================
+/*!
+ * \brief Return number of submeshes in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbSubMesh() const throw(SALOME_Exception)
+{
+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->NbSubMesh();
+}
+
+//================================================================================
+/*!
+ * \brief Returns number of meshes in the Study, that is supposed to be
+ * equal to SMESHDS_Document::NbMeshes()
+ */
+//================================================================================
+
+int SMESH_Mesh::NbMeshes() const // nb meshes in the Study
+{
+ return _myDocument->NbMeshes();
+}
+
+//=======================================================================
+//function : IsNotConformAllowed
+//purpose : check if a hypothesis alowing notconform mesh is present
+//=======================================================================
+
+bool SMESH_Mesh::IsNotConformAllowed() const
+{
+ if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed");
+
+ static SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" ));
+ return GetHypothesis( _myMeshDS->ShapeToMesh(), filter, false );
+}
+
+//=======================================================================
+//function : IsMainShape
+//purpose :
+//=======================================================================
+
+bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
+{
+ return theShape.IsSame(_myMeshDS->ShapeToMesh() );
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
+ const char* theName,
+ int& theId,
+ const TopoDS_Shape& theShape,
+ const SMESH_PredicatePtr& thePredicate)
+{
+ if (_mapGroup.count(_groupId))
+ return NULL;
+ theId = _groupId;
+ SMESH_Group* aGroup = new SMESH_Group (theId, this, theType, theName, theShape, thePredicate);
+ GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
+ _mapGroup[_groupId++] = aGroup;
+ return aGroup;
+}
+
+//================================================================================
+/*!
+ * \brief Creates a group based on an existing SMESHDS group. Group ID should be unique
+ */
+//================================================================================
+
+SMESH_Group* SMESH_Mesh::AddGroup (SMESHDS_GroupBase* groupDS) throw(SALOME_Exception)
+{
+ if ( !groupDS )
+ throw SALOME_Exception(LOCALIZED ("SMESH_Mesh::AddGroup(): NULL SMESHDS_GroupBase"));
+
+ map <int, SMESH_Group*>::iterator i_g = _mapGroup.find( groupDS->GetID() );
+ if ( i_g != _mapGroup.end() && i_g->second )
+ {
+ if ( i_g->second->GetGroupDS() == groupDS )
+ return i_g->second;
+ else
+ throw SALOME_Exception(LOCALIZED ("SMESH_Mesh::AddGroup() wrong ID of SMESHDS_GroupBase"));
+ }
+ SMESH_Group* aGroup = new SMESH_Group (groupDS);
+ _mapGroup[ groupDS->GetID() ] = aGroup;
+ GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
+
+ _groupId = 1 + _mapGroup.rbegin()->first;
+
+ return aGroup;
+}
+
+
+//================================================================================
+/*!
+ * \brief Creates SMESH_Groups for not wrapped SMESHDS_Groups
+ * \retval bool - true if new SMESH_Groups have been created
+ *
+ */
+//================================================================================
+
+bool SMESH_Mesh::SynchronizeGroups()
+{
+ const size_t nbGroups = _mapGroup.size();
+ const set<SMESHDS_GroupBase*>& groups = _myMeshDS->GetGroups();
+ set<SMESHDS_GroupBase*>::const_iterator gIt = groups.begin();
+ for ( ; gIt != groups.end(); ++gIt )
+ {
+ SMESHDS_GroupBase* groupDS = (SMESHDS_GroupBase*) *gIt;
+ _groupId = groupDS->GetID();
+ if ( !_mapGroup.count( _groupId ))
+ _mapGroup[_groupId] = new SMESH_Group( groupDS );
+ }
+ if ( !_mapGroup.empty() )
+ _groupId = _mapGroup.rbegin()->first + 1;
+
+ return nbGroups < _mapGroup.size();
+}
+
+//================================================================================
+/*!
+ * \brief Return iterator on all existing groups
+ */
+//================================================================================
+
+SMESH_Mesh::GroupIteratorPtr SMESH_Mesh::GetGroups() const
+{
+ typedef map <int, SMESH_Group *> TMap;
+ return GroupIteratorPtr( new SMDS_mapIterator<TMap>( _mapGroup ));
+}
+
+//=============================================================================
+/*!
+ * \brief Return a group by ID
+ */
+//=============================================================================
+
+SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
+{
+ if (_mapGroup.find(theGroupID) == _mapGroup.end())
+ return NULL;
+ return _mapGroup[theGroupID];
+}
+
+
+//=============================================================================
+/*!
+ * \brief Return IDs of all groups
+ */
+//=============================================================================
+
+list<int> SMESH_Mesh::GetGroupIds() const
+{
+ list<int> anIds;
+ for ( map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
+ anIds.push_back( it->first );
+
+ return anIds;
+}
+
+//================================================================================
+/*!
+ * \brief Set a caller of methods at level of CORBA API implementation.
+ * The set upCaller will be deleted by SMESH_Mesh
+ */
+//================================================================================
+
+void SMESH_Mesh::SetCallUp( TCallUp* upCaller )
+{
+ if ( _callUp ) delete _callUp;
+ _callUp = upCaller;
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+bool SMESH_Mesh::RemoveGroup( const int theGroupID )
+{
+ if (_mapGroup.find(theGroupID) == _mapGroup.end())
+ return false;
+ GetMeshDS()->RemoveGroup( _mapGroup[theGroupID]->GetGroupDS() );
+ delete _mapGroup[theGroupID];
+ _mapGroup.erase (theGroupID);
+ if (_callUp)
+ _callUp->RemoveGroup( theGroupID );
+ return true;
+}
+
+//=======================================================================
+//function : GetAncestors
+//purpose : return list of ancestors of theSubShape in the order
+// that lower dimention shapes come first.
+//=======================================================================
+
+const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
+{
+ if ( _mapAncestors.Contains( theS ) )
+ return _mapAncestors.FindFromKey( theS );
+
+ static TopTools_ListOfShape emptyList;
+ return emptyList;
+}
+
+//=======================================================================
+//function : Dump
+//purpose : dumps contents of mesh to stream [ debug purposes ]
+//=======================================================================
+
+ostream& SMESH_Mesh::Dump(ostream& save)
+{
+ int clause = 0;
+ save << "========================== Dump contents of mesh ==========================" << endl << endl;
+ save << ++clause << ") Total number of nodes: \t" << NbNodes() << endl;
+ save << ++clause << ") Total number of edges: \t" << NbEdges() << endl;
+ save << ++clause << ") Total number of faces: \t" << NbFaces() << endl;
+ save << ++clause << ") Total number of polygons: \t" << NbPolygons() << endl;
+ save << ++clause << ") Total number of volumes: \t" << NbVolumes() << endl;
+ save << ++clause << ") Total number of polyhedrons:\t" << NbPolyhedrons() << endl << endl;
+ for ( int isQuadratic = 0; isQuadratic < 2; ++isQuadratic )
+ {
+ string orderStr = isQuadratic ? "quadratic" : "linear";
+ SMDSAbs_ElementOrder order = isQuadratic ? ORDER_QUADRATIC : ORDER_LINEAR;
+
+ save << ++clause << ") Total number of " << orderStr << " edges:\t" << NbEdges(order) << endl;
+ save << ++clause << ") Total number of " << orderStr << " faces:\t" << NbFaces(order) << endl;
+ if ( NbFaces(order) > 0 ) {
+ int nb3 = NbTriangles(order);
+ int nb4 = NbQuadrangles(order);
+ save << clause << ".1) Number of " << orderStr << " triangles: \t" << nb3 << endl;
+ save << clause << ".2) Number of " << orderStr << " quadrangles:\t" << nb4 << endl;
+ if ( nb3 + nb4 != NbFaces(order) ) {
+ map<int,int> myFaceMap;
+ SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
+ while( itFaces->more( ) ) {
+ int nbNodes = itFaces->next()->NbNodes();
+ if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
+ myFaceMap[ nbNodes ] = 0;
+ myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
+ }
+ save << clause << ".3) Faces in detail: " << endl;
+ map <int,int>::iterator itF;
+ for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
+ save << "--> nb nodes: " << itF->first << " - nb elemens:\t" << itF->second << endl;
+ }
+ }
+ save << ++clause << ") Total number of " << orderStr << " volumes:\t" << NbVolumes(order) << endl;
+ if ( NbVolumes(order) > 0 ) {
+ int nb8 = NbHexas(order);
+ int nb4 = NbTetras(order);
+ int nb5 = NbPyramids(order);
+ int nb6 = NbPrisms(order);
+ save << clause << ".1) Number of " << orderStr << " hexahedrons: \t" << nb8 << endl;
+ save << clause << ".2) Number of " << orderStr << " tetrahedrons:\t" << nb4 << endl;
+ save << clause << ".3) Number of " << orderStr << " prisms: \t" << nb6 << endl;
+ save << clause << ".4) Number of " << orderStr << " pyramids: \t" << nb5 << endl;
+ if ( nb8 + nb4 + nb5 + nb6 != NbVolumes(order) ) {
+ map<int,int> myVolumesMap;
+ SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
+ while( itVolumes->more( ) ) {
+ int nbNodes = itVolumes->next()->NbNodes();
+ if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
+ myVolumesMap[ nbNodes ] = 0;
+ myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
+ }
+ save << clause << ".5) Volumes in detail: " << endl;
+ map <int,int>::iterator itV;
+ for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
+ save << "--> nb nodes: " << itV->first << " - nb elemens:\t" << itV->second << endl;
+ }
+ }
+ save << endl;
+ }
+ save << "===========================================================================" << endl;
+ return save;
+}
+
+//=======================================================================
+//function : GetElementType
+//purpose : Returns type of mesh element with certain id
+//=======================================================================
+
+SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem )
+{
+ return _myMeshDS->GetElementType( id, iselem );
+}
+
+//=============================================================================
+/*!
+ * \brief Convert group on geometry into standalone group
+ */
+//=============================================================================
+
+SMESH_Group* SMESH_Mesh::ConvertToStandalone ( int theGroupID )
+{
+ SMESH_Group* aGroup = 0;
+ 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;
+ vector<SMESH_subMesh*> onlyOrderedList, smVec;
+
+ // collect all ordered submeshes in one list as pointers
+ // and get their positions within theListToSort
+ typedef vector<SMESH_subMesh*>::iterator TPosInList;
+ 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 ) {
+ onlyOrderedList.push_back( smVec[i] );
+ sortedPos[ distance( smBeg, smPos )] = smPos;
+ }
+ }
+ }
+ if (onlyOrderedList.size() < 2)
+ return res;
+ res = true;
+
+ vector<SMESH_subMesh*>::iterator onlyBIt = onlyOrderedList.begin();
+ vector<SMESH_subMesh*>::iterator onlyEIt = onlyOrderedList.end();
+
+ // iterate on ordered sub-meshes and insert them in detected positions
+ 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 );