X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH_I%2FSMESH_Mesh_i.cxx;h=83dd619f53811d17a53e4c6a04929af442c62bac;hp=f4a7000d3e3d83b0ac43088c284ed32f3dd9ef9c;hb=e350ffef91f9c13e43046073a96f6c75f96a1c17;hpb=cd3124ccaae98a4788a5ed13ab4877803e0e0bc1 diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index f4a7000d3..83dd619f5 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -23,7 +23,7 @@ // File : SMESH_Mesh_i.cxx // Author : Paul RASCLE, EDF // Module : SMESH -// + #include "SMESH_Mesh_i.hxx" #include "SMESH_Filter_i.hxx" @@ -37,6 +37,7 @@ #include "DriverMED_R_SMESHDS_Mesh.h" #include "DriverMED_W_SMESHDS_Mesh.h" #include "SMDS_VolumeTool.hxx" +#include "SMDS_ElemIterator.hxx" #include "SMESHDS_Command.hxx" #include "SMESHDS_CommandType.hxx" #include "SMESHDS_GroupOnGeom.hxx" @@ -64,10 +65,14 @@ #include #include #include +#include #include #include +#include +#include // STL Includes +#include #include #include #include @@ -84,7 +89,9 @@ using SMESH::TPythonDump; int SMESH_Mesh_i::myIdGenerator = 0; - +//To disable automatic genericobj management, the following line should be commented. +//Otherwise, it should be uncommented. Refer to KERNEL_SRC/src/SALOMEDSImpl/SALOMEDSImpl_AttributeIOR.cxx +#define WITHGENERICOBJ //============================================================================= /*! @@ -93,8 +100,8 @@ int SMESH_Mesh_i::myIdGenerator = 0; //============================================================================= SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA, - SMESH_Gen_i* gen_i, - CORBA::Long studyId ) + SMESH_Gen_i* gen_i, + CORBA::Long studyId ) : SALOME::GenericObj_i( thePOA ) { MESSAGE("SMESH_Mesh_i"); @@ -113,17 +120,43 @@ SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA, SMESH_Mesh_i::~SMESH_Mesh_i() { INFOS("~SMESH_Mesh_i"); - map::iterator it; - for ( it = _mapGroups.begin(); it != _mapGroups.end(); it++ ) { - SMESH_GroupBase_i* aGroup = dynamic_cast( SMESH_Gen_i::GetServant( it->second ).in() ); - if ( aGroup ) { - // this method is colled from destructor of group (PAL6331) + + // destroy groups + map::iterator itGr; + for (itGr = _mapGroups.begin(); itGr != _mapGroups.end(); itGr++) { + SMESH_GroupBase_i* aGroup = dynamic_cast(SMESH_Gen_i::GetServant(itGr->second).in()); + if (aGroup) { + // this method is called from destructor of group (PAL6331) //_impl->RemoveGroup( aGroup->GetLocalID() ); - +#ifdef WITHGENERICOBJ aGroup->Destroy(); +#endif } } _mapGroups.clear(); + +#ifdef WITHGENERICOBJ + // destroy submeshes + map::iterator itSM; + for ( itSM = _mapSubMeshIor.begin(); itSM != _mapSubMeshIor.end(); itSM++ ) { + SMESH_subMesh_i* aSubMesh = dynamic_cast(SMESH_Gen_i::GetServant(itSM->second).in()); + if (aSubMesh) { + aSubMesh->Destroy(); + } + } + _mapSubMeshIor.clear(); + + // destroy hypotheses + map::iterator itH; + for ( itH = _mapHypo.begin(); itH != _mapHypo.end(); itH++ ) { + SMESH_Hypothesis_i* aHypo = dynamic_cast(SMESH_Gen_i::GetServant(itH->second).in()); + if (aHypo) { + aHypo->Destroy(); + } + } + _mapHypo.clear(); +#endif + delete _impl; } @@ -203,6 +236,7 @@ void SMESH_Mesh_i::Clear() throw (SALOME::SALOME_Exception) Unexpect aCatch(SALOME_SalomeException); try { _impl->Clear(); + CheckGeomGroupModif(); // issue 20145 } catch(SALOME_Exception & S_ex) { THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM); @@ -309,7 +343,7 @@ SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName ) char* SMESH_Mesh_i::GetVersionString(SMESH::MED_VERSION version, CORBA::Short nbDigits) { - std::string ver = DriverMED_W_SMESHDS_Mesh::GetVersionString(MED::EVersion(version), + string ver = DriverMED_W_SMESHDS_Mesh::GetVersionString(MED::EVersion(version), nbDigits); return CORBA::string_dup( ver.c_str() ); } @@ -467,6 +501,9 @@ SMESH_Hypothesis::Hypothesis_Status status = _impl->AddHypothesis(myLocSubShape, hypId); if ( !SMESH_Hypothesis::IsStatusFatal(status) ) { _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( myHyp ); +#ifdef WITHGENERICOBJ + _mapHypo[hypId]->Register(); +#endif // assure there is a corresponding submesh if ( !_impl->IsMainShape( myLocSubShape )) { int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape ); @@ -519,41 +556,40 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aS */ //============================================================================= -SMESH_Hypothesis::Hypothesis_Status SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject, - SMESH::SMESH_Hypothesis_ptr anHyp) +SMESH_Hypothesis::Hypothesis_Status +SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject, + SMESH::SMESH_Hypothesis_ptr anHyp) { - if(MYDEBUG) MESSAGE("removeHypothesis()"); - // **** proposer liste de subShape (selection multiple) + if(MYDEBUG) MESSAGE("removeHypothesis()"); + // **** proposer liste de subShape (selection multiple) + + if (CORBA::is_nil(aSubShapeObject) && HasShapeToMesh()) + THROW_SALOME_CORBA_EXCEPTION("bad subShape reference", SALOME::BAD_PARAM); - if (CORBA::is_nil(aSubShapeObject) && HasShapeToMesh()) - THROW_SALOME_CORBA_EXCEPTION("bad subShape reference", - SALOME::BAD_PARAM); + SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp); + if (CORBA::is_nil(myHyp)) + THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference", SALOME::BAD_PARAM); - SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp); - if (CORBA::is_nil(myHyp)) - THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference", - SALOME::BAD_PARAM); + SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK; + try + { + TopoDS_Shape myLocSubShape; + //use PseudoShape in case if mesh has no shape + if(HasShapeToMesh()) + myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject); + else + myLocSubShape = _impl->GetShapeToMesh(); - SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK; - try - { - TopoDS_Shape myLocSubShape; - //use PseudoShape in case if mesh has no shape - if(HasShapeToMesh()) - myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject); - else - myLocSubShape = _impl->GetShapeToMesh(); - - int hypId = myHyp->GetId(); - status = _impl->RemoveHypothesis(myLocSubShape, hypId); - if ( !SMESH_Hypothesis::IsStatusFatal(status) ) - _mapHypo.erase( hypId ); - } - catch(SALOME_Exception & S_ex) - { - THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM); - } - return status; + int hypId = myHyp->GetId(); + status = _impl->RemoveHypothesis(myLocSubShape, hypId); +// if ( !SMESH_Hypothesis::IsStatusFatal(status) ) EAP: hyp can be used on many subshapes +// _mapHypo.erase( hypId ); + } + catch(SALOME_Exception & S_ex) + { + THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM); + } + return status; } //============================================================================= @@ -563,19 +599,20 @@ SMESH_Hypothesis::Hypothesis_Status SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Ob //============================================================================= SMESH::ListOfHypothesis * - SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShapeObject) + SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShapeObject) throw(SALOME::SALOME_Exception) { Unexpect aCatch(SALOME_SalomeException); if (MYDEBUG) MESSAGE("GetHypothesisList"); - if (CORBA::is_nil(aSubShapeObject)) - THROW_SALOME_CORBA_EXCEPTION("bad subShape reference", - SALOME::BAD_PARAM); + if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShapeObject)) + THROW_SALOME_CORBA_EXCEPTION("bad subShape reference", SALOME::BAD_PARAM); SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis(); try { TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject); + if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() ) + myLocSubShape = _impl->GetShapeToMesh(); const list& aLocalList = _impl->GetHypothesisList( myLocSubShape ); int i = 0, n = aLocalList.size(); aList->length( n ); @@ -583,7 +620,7 @@ throw(SALOME::SALOME_Exception) for ( list::const_iterator anIt = aLocalList.begin(); i < n && anIt != aLocalList.end(); anIt++ ) { SMESHDS_Hypothesis* aHyp = (SMESHDS_Hypothesis*)(*anIt); if ( _mapHypo.find( aHyp->GetID() ) != _mapHypo.end() ) - aList[i++] = SMESH::SMESH_Hypothesis::_narrow( _mapHypo[aHyp->GetID()] ); + aList[i++] = SMESH::SMESH_Hypothesis::_narrow( _mapHypo[aHyp->GetID()] ); } aList->length( i ); @@ -601,14 +638,14 @@ throw(SALOME::SALOME_Exception) */ //============================================================================= SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShapeObject, - const char* theName ) + const char* theName ) throw(SALOME::SALOME_Exception) { Unexpect aCatch(SALOME_SalomeException); MESSAGE("SMESH_Mesh_i::GetSubMesh"); if (CORBA::is_nil(aSubShapeObject)) THROW_SALOME_CORBA_EXCEPTION("bad subShape reference", - SALOME::BAD_PARAM); + SALOME::BAD_PARAM); SMESH::SMESH_subMesh_var subMesh; SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow(_this()); @@ -618,6 +655,9 @@ SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShap //Get or Create the SMESH_subMesh object implementation int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape ); + if ( !subMeshId && ! _impl->GetMeshDS()->IsGroupOfSubShapes( myLocSubShape )) + THROW_SALOME_CORBA_EXCEPTION("not sub-shape of the main shape", SALOME::BAD_PARAM); + subMesh = getSubMesh( subMeshId ); // create a new subMesh object servant if there is none for the shape @@ -662,7 +702,10 @@ void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh ) long aTag = SMESH_Gen_i::GetRefOnShapeTag(); SALOMEDS::SObject_var anObj, aRef; if ( anSO->FindSubObject( aTag, anObj ) && anObj->ReferencedObject( aRef ) ) - aSubShapeObject = GEOM::GEOM_Object::_narrow( aRef->GetObject() ); + aSubShapeObject = GEOM::GEOM_Object::_narrow( aRef->GetObject() ); + +// if ( aSubShapeObject->_is_nil() ) // not published shape (IPAL13617) +// aSubShapeObject = theSubMesh->GetSubShape(); aStudy->NewBuilder()->RemoveObjectWithChildren( anSO ); @@ -1570,7 +1613,7 @@ TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData) CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO ); if ( CORBA::is_nil( groupObj )) return newShape; GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj ); - + // get indices of group items set curIndices; GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine(); @@ -1596,13 +1639,24 @@ TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData) if ( newShape.IsNull() ) { // geom group becomes empty - return empty compound TopoDS_Compound compound; - BRep_Builder builder; - builder.MakeCompound(compound); + BRep_Builder().MakeCompound(compound); newShape = compound; } return newShape; } +namespace { + //============================================================================= + /*! + * \brief Storage of shape and index used in CheckGeomGroupModif() + */ + //============================================================================= + struct TIndexedShape { + int _index; + TopoDS_Shape _shape; + TIndexedShape( int i, const TopoDS_Shape& s ):_index(i), _shape(s) {} + }; +} //============================================================================= /*! * \brief Update objects depending on changed geom groups @@ -1641,19 +1695,12 @@ void SMESH_Mesh_i::CheckGeomGroupModif() if ( processedGroup ) { // update group indices list::iterator data2 = data; - for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) - data->_indices = data2->_indices; + for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) {} + data->_indices = data2->_indices; } // Update SMESH objects according to new GEOM group contents - SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject ); - if ( !mesh->_is_nil() ) // -------------- MESH ---------------------------- - { - // TODO - continue; - } - SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject ); if ( !submesh->_is_nil() ) // -------------- Sub mesh --------------------- { @@ -1697,7 +1744,129 @@ void SMESH_Mesh_i::CheckGeomGroupModif() } continue; } - } + + SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject ); + if ( !mesh->_is_nil() ) // -------------- MESH ---------------------------- + { + // Remove groups and submeshes basing on removed sub-shapes + + TopTools_MapOfShape newShapeMap; + TopoDS_Iterator shapeIt( newShape ); + for ( ; shapeIt.More(); shapeIt.Next() ) + newShapeMap.Add( shapeIt.Value() ); + + SMESHDS_Mesh* meshDS = _impl->GetMeshDS(); + for ( shapeIt.Initialize( meshDS->ShapeToMesh() ); shapeIt.More(); shapeIt.Next() ) + { + if ( newShapeMap.Contains( shapeIt.Value() )) + continue; + TopTools_IndexedMapOfShape oldShapeMap; + TopExp::MapShapes( shapeIt.Value(), oldShapeMap ); + for ( int i = 1; i <= oldShapeMap.Extent(); ++i ) + { + const TopoDS_Shape& oldShape = oldShapeMap(i); + int oldInd = meshDS->ShapeToIndex( oldShape ); + // -- submeshes -- + map::iterator i_smIor = _mapSubMeshIor.find( oldInd ); + if ( i_smIor != _mapSubMeshIor.end() ) { + RemoveSubMesh( i_smIor->second ); // one submesh per shape index + } + // --- groups --- + map::iterator i_grp = _mapGroups.begin(); + for ( ; i_grp != _mapGroups.end(); ++i_grp ) + { + // check if a group bases on oldInd shape + SMESHDS_GroupOnGeom* grpOnGeom = 0; + if ( ::SMESH_Group* g = _impl->GetGroup( i_grp->first )) + grpOnGeom = dynamic_cast( g->GetGroupDS() ); + if ( grpOnGeom && oldShape.IsSame( grpOnGeom->GetShape() )) + { // remove + RemoveGroup( i_grp->second ); // several groups can base on same shape + i_grp = _mapGroups.begin(); // _mapGroups changed - restart iteration + } + } + } + } + // Reassign hypotheses and update groups after setting the new shape to mesh + + // collect anassigned hypotheses + typedef list< pair< TIndexedShape, list > > TShapeHypList; + list ::const_iterator hypIt; + TShapeHypList assignedHyps; + for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i ) + { + const TopoDS_Shape& oldShape = meshDS->IndexToShape(i); + list hyps = meshDS->GetHypothesis( oldShape );// copy + if ( !hyps.empty() ) { + assignedHyps.push_back( make_pair( TIndexedShape(i,oldShape), hyps )); + for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt ) + _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID()); + } + } + // collect shapes supporting groups + typedef list < pair< TIndexedShape, SMDSAbs_ElementType > > TShapeTypeList; + TShapeTypeList groupData; + const set& groups = meshDS->GetGroups(); + set::const_iterator grIt = groups.begin(); + for ( ; grIt != groups.end(); ++grIt ) + { + if ( SMESHDS_GroupOnGeom* gog = dynamic_cast( *grIt )) + groupData.push_back + ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType())); + } + // set new shape to mesh -> DS of submeshes and geom groups is deleted + _impl->ShapeToMesh( newShape ); + + // reassign hypotheses + TShapeHypList::iterator indS_hyps = assignedHyps.begin(); + for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps ) + { + TIndexedShape& geom = indS_hyps->first; + list& hyps = indS_hyps->second; + int oldID = geom._index; + int newID = meshDS->ShapeToIndex( geom._shape ); + if ( !newID ) + continue; + if ( oldID == 1 ) { // main shape + newID = 1; + geom._shape = newShape; + } + for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt ) + _impl->AddHypothesis( geom._shape, (*hypIt)->GetID()); + // care of submeshes + SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape ); + if ( newID != oldID ) { + _mapSubMesh [ newID ] = newSubmesh; + _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ]; + _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ]; + _mapSubMesh. erase(oldID); + _mapSubMesh_i. erase(oldID); + _mapSubMeshIor.erase(oldID); + _mapSubMesh_i [ newID ]->changeLocalId( newID ); + } + } + // recreate groups + TShapeTypeList::iterator geomType = groupData.begin(); + for ( ; geomType != groupData.end(); ++geomType ) + { + const TIndexedShape& geom = geomType->first; + int oldID = geom._index; + if ( _mapGroups.find( oldID ) == _mapGroups.end() ) + continue; + // get group name + SALOMEDS::SObject_var groupSO = _gen_i->ObjectToSObject( study,_mapGroups[oldID] ); + CORBA::String_var name = groupSO->GetName(); + // update + SMESH_GroupBase_i* group_i = SMESH::DownCast(_mapGroups[oldID] ); + int newID; + if ( group_i && _impl->AddGroup( geomType->second, name.in(), newID, geom._shape )) + group_i->changeLocalId( newID ); + } + + break; // everything has been updated + + } // update mesh + } // loop on group data // Update icons @@ -1725,7 +1894,6 @@ void SMESH_Mesh_i::CheckGeomGroupModif() //============================================================================= /*! * \brief Create standalone group instead if group on geometry - * */ //============================================================================= @@ -1782,8 +1950,8 @@ SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupOnGe _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup ); // register CORBA object for persistence - //int nextId = _gen_i->RegisterObject( aGroup ); - //if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId); + /*int nextId =*/ _gen_i->RegisterObject( aGroup ); + builder->SetIOR( aGroupSO, _gen_i->GetORB()->object_to_string( aGroup ) ); return aGroup._retn(); @@ -1845,20 +2013,37 @@ void SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh, GEOM::GEOM_Object_ptr theSubShapeObject ) { MESSAGE("SMESH_Mesh_i::removeSubMesh()"); - if ( theSubMesh->_is_nil() || theSubShapeObject->_is_nil() ) + if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ ) return; - try { - SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject ); - for ( int i = 0, n = aHypList->length(); i < n; i++ ) { - removeHypothesis( theSubShapeObject, aHypList[i] ); + if ( theSubShapeObject->_is_nil() ) // not published shape (IPAL13617) + { + CORBA::Long shapeId = theSubMesh->GetId(); + if ( _mapSubMesh.find( shapeId ) != _mapSubMesh.end()) + { + TopoDS_Shape S = _mapSubMesh[ shapeId ]->GetSubShape(); + if ( !S.IsNull() ) + { + list hyps = _impl->GetHypothesisList( S ); + list::const_iterator hyp = hyps.begin(); + for ( ; hyp != hyps.end(); ++hyp ) + _impl->RemoveHypothesis(S, (*hyp)->GetID()); + } } } - catch( const SALOME::SALOME_Exception& ) { - INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!"); + else + { + try { + SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject ); + for ( int i = 0, n = aHypList->length(); i < n; i++ ) { + removeHypothesis( theSubShapeObject, aHypList[i] ); + } + } + catch( const SALOME::SALOME_Exception& ) { + INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!"); + } + removeGeomGroupData( theSubShapeObject ); } - removeGeomGroupData( theSubShapeObject ); - int subMeshId = theSubMesh->GetId(); _mapSubMesh.erase(subMeshId); @@ -1965,14 +2150,14 @@ throw(SALOME::SALOME_Exception) aLog[indexLog].coords.length(rnum); aLog[indexLog].indexes.length(inum); for(int i = 0; i < rnum; i++){ - aLog[indexLog].coords[i] = *ir; - //MESSAGE(" "<ClearLog(); } //============================================================================= @@ -2077,6 +2262,19 @@ SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer() return aMesh._retn(); } +//================================================================================ +/*! + * \brief Return true if the mesh has been edited since a last total re-compute + * and those modifications may prevent successful partial re-compute + */ +//================================================================================ + +CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard() throw(SALOME::SALOME_Exception) +{ + Unexpect aCatch(SALOME_SalomeException); + return _impl->HasModificationsToDiscard(); +} + //============================================================================= /*! * @@ -2111,7 +2309,7 @@ CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED() return _impl->HasDuplicatedGroupNamesMED(); } -void SMESH_Mesh_i::PrepareForWriting (const char* file) +void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite) { TCollection_AsciiString aFullName ((char*)file); OSD_Path aPath (aFullName); @@ -2120,8 +2318,10 @@ void SMESH_Mesh_i::PrepareForWriting (const char* file) // existing filesystem node if (aFile.KindOfFile() == OSD_FILE) { if (aFile.IsWriteable()) { - aFile.Reset(); - aFile.Remove(); + if (overwrite) { + aFile.Reset(); + aFile.Remove(); + } if (aFile.Failed()) { TCollection_AsciiString msg ("File "); msg += aFullName + " cannot be replaced."; @@ -2152,15 +2352,16 @@ void SMESH_Mesh_i::PrepareForWriting (const char* file) } } -void SMESH_Mesh_i::ExportToMED (const char* file, - CORBA::Boolean auto_groups, - SMESH::MED_VERSION theVersion) +void SMESH_Mesh_i::ExportToMEDX (const char* file, + CORBA::Boolean auto_groups, + SMESH::MED_VERSION theVersion, + CORBA::Boolean overwrite) throw(SALOME::SALOME_Exception) { Unexpect aCatch(SALOME_SalomeException); // Perform Export - PrepareForWriting(file); + PrepareForWriting(file, overwrite); const char* aMeshName = "Mesh"; SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy(); if ( !aStudy->_is_nil() ) { @@ -2169,20 +2370,20 @@ void SMESH_Mesh_i::ExportToMED (const char* file, aMeshName = aMeshSO->GetName(); // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes if ( !aStudy->GetProperties()->IsLocked() ) - { - SALOMEDS::GenericAttribute_var anAttr; - SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder(); - SALOMEDS::AttributeExternalFileDef_var aFileName; - anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef"); - aFileName = SALOMEDS::AttributeExternalFileDef::_narrow(anAttr); - ASSERT(!aFileName->_is_nil()); + { + SALOMEDS::GenericAttribute_var anAttr; + SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder(); + SALOMEDS::AttributeExternalFileDef_var aFileName; + anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef"); + aFileName = SALOMEDS::AttributeExternalFileDef::_narrow(anAttr); + ASSERT(!aFileName->_is_nil()); aFileName->SetValue(file); SALOMEDS::AttributeFileType_var aFileType; anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType"); aFileType = SALOMEDS::AttributeFileType::_narrow(anAttr); ASSERT(!aFileType->_is_nil()); aFileType->SetValue("FICHIERMED"); - } + } } } // Update Python script @@ -2192,17 +2393,25 @@ void SMESH_Mesh_i::ExportToMED (const char* file, // check names of groups checkGroupNames(); - TPythonDump() << _this() << ".ExportToMED( '" - << file << "', " << auto_groups << ", " << theVersion << " )"; + TPythonDump() << _this() << ".ExportToMEDX( r'" + << file << "', " << auto_groups << ", " << theVersion << ", " << overwrite << " )"; _impl->ExportMED( file, aMeshName, auto_groups, theVersion ); } +void SMESH_Mesh_i::ExportToMED (const char* file, + CORBA::Boolean auto_groups, + SMESH::MED_VERSION theVersion) + throw(SALOME::SALOME_Exception) +{ + ExportToMEDX(file,auto_groups,theVersion,true); +} + void SMESH_Mesh_i::ExportMED (const char* file, - CORBA::Boolean auto_groups) + CORBA::Boolean auto_groups) throw(SALOME::SALOME_Exception) { - ExportToMED(file,auto_groups,SMESH::MED_V2_1); + ExportToMEDX(file,auto_groups,SMESH::MED_V2_1,true); } void SMESH_Mesh_i::ExportDAT (const char *file) @@ -2213,7 +2422,7 @@ void SMESH_Mesh_i::ExportDAT (const char *file) // Update Python script // check names of groups checkGroupNames(); - TPythonDump() << _this() << ".ExportDAT( '" << file << "' )"; + TPythonDump() << _this() << ".ExportDAT( r'" << file << "' )"; // Perform Export PrepareForWriting(file); @@ -2228,7 +2437,7 @@ void SMESH_Mesh_i::ExportUNV (const char *file) // Update Python script // check names of groups checkGroupNames(); - TPythonDump() << _this() << ".ExportUNV( '" << file << "' )"; + TPythonDump() << _this() << ".ExportUNV( r'" << file << "' )"; // Perform Export PrepareForWriting(file); @@ -2243,7 +2452,7 @@ void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii) // Update Python script // check names of groups checkGroupNames(); - TPythonDump() << _this() << ".ExportSTL( '" << file << "', " << isascii << " )"; + TPythonDump() << _this() << ".ExportSTL( r'" << file << "', " << isascii << " )"; // Perform Export PrepareForWriting(file); @@ -2283,7 +2492,18 @@ CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception) CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception) { Unexpect aCatch(SALOME_SalomeException); - return NbEdges() + NbFaces() + NbVolumes(); + return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes(); +} + +//============================================================================= +/*! + * + */ +//============================================================================= +CORBA::Long SMESH_Mesh_i::Nb0DElements()throw (SALOME::SALOME_Exception) +{ + Unexpect aCatch(SALOME_SalomeException); + return _impl->Nb0DElements(); } //============================================================================= @@ -2448,7 +2668,7 @@ CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception) //============================================================================= char* SMESH_Mesh_i::Dump() { - std::ostringstream os; + ostringstream os; _impl->Dump( os ); return CORBA::string_dup( os.str().c_str() ); } @@ -2581,6 +2801,21 @@ SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const boo return ( SMESH::ElementType )_impl->GetElementType( id, iselem ); } +//============================================================================= +/*! + * + */ +//============================================================================= + +SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id ) + throw (SALOME::SALOME_Exception) +{ + const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id); + if ( !e ) + THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM ); + + return ( SMESH::EntityType ) e->GetEntityType(); +} //============================================================================= /*! @@ -3006,6 +3241,57 @@ CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id) return elem->NbFaces(); } +//======================================================================= +//function : GetElemFaceNodes +//purpose : Returns nodes of given face (counted from zero) for given element. +//======================================================================= + +SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long elemId, + CORBA::Short faceIndex) +{ + SMESH::long_array_var aResult = new SMESH::long_array(); + if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() ) + { + if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(elemId) ) + { + SMDS_VolumeTool vtool( elem ); + if ( faceIndex < vtool.NbFaces() ) + { + aResult->length( vtool.NbFaceNodes( faceIndex )); + const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex ); + for ( int i = 0; i < aResult->length(); ++i ) + aResult[ i ] = nn[ i ]->GetID(); + } + } + } + return aResult._retn(); +} + +//======================================================================= +//function : FindElementByNodes +//purpose : Returns an element based on all given nodes. +//======================================================================= + +CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes) +{ + CORBA::Long elemID(0); + if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() ) + { + vector< const SMDS_MeshNode * > nn( nodes.length() ); + for ( int i = 0; i < nodes.length(); ++i ) + if ( !( nn[i] = mesh->FindNode( nodes[i] ))) + return elemID; + + const SMDS_MeshElement* elem = mesh->FindElement( nn ); + if ( !elem && ( _impl->NbEdges( ORDER_QUADRATIC ) || + _impl->NbFaces( ORDER_QUADRATIC ) || + _impl->NbVolumes( ORDER_QUADRATIC ))) + elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true ); + + if ( elem ) elemID = CORBA::Long( elem->GetID() ); + } + return elemID; +} //============================================================================= /*! @@ -3264,3 +3550,498 @@ SMESH::string_array* SMESH_Mesh_i::GetLastParameters() } return aResult._retn(); } + +//======================================================================= +//function : GetTypes +//purpose : Returns types of elements it contains +//======================================================================= + +SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes() +{ + SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType; + + types->length( 4 ); + int nbTypes = 0; + if (_impl->NbEdges()) + types[nbTypes++] = SMESH::EDGE; + if (_impl->NbFaces()) + types[nbTypes++] = SMESH::FACE; + if (_impl->NbVolumes()) + types[nbTypes++] = SMESH::VOLUME; + if (_impl->Nb0DElements()) + types[nbTypes++] = SMESH::ELEM0D; + types->length( nbTypes ); + + return types._retn(); +} + +//============================================================================= +/*! + * \brief Returns statistic of mesh elements + */ +//============================================================================= +SMESH::long_array* SMESH_Mesh_i::GetMeshInfo() +{ + SMESH::long_array_var aRes = new SMESH::long_array(); + aRes->length(SMESH::Entity_Last); + for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++) + aRes[i] = 0; + SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS(); + if (!aMeshDS) + return aRes._retn(); + const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo(); + for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++) + aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i); + return aRes._retn(); +} + +//============================================================================= +/*! + * \brief Collect statistic of mesh elements given by iterator + */ +//============================================================================= +void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr, + SMESH::long_array& theInfo) +{ + if (!theItr) return; + while (theItr->more()) + theInfo[ theItr->next()->GetEntityType() ]++; +} + +//============================================================================= +/*! + * \brief mapping of mesh dimension into shape type + */ +//============================================================================= +static TopAbs_ShapeEnum shapeTypeByDim(const int theDim) +{ + TopAbs_ShapeEnum aType = TopAbs_SOLID; + switch ( theDim ) { + case 0: aType = TopAbs_VERTEX; break; + case 1: aType = TopAbs_EDGE; break; + case 2: aType = TopAbs_FACE; break; + case 3: + default:aType = TopAbs_SOLID; break; + } + return aType; +} + +//============================================================================= +/*! + * \brief Internal structure used to find concurent submeshes + * + * It represents a pair < submesh, concurent dimension >, where + * 'concurrent dimension' is dimension of shape where the submesh can concurent + * with another submesh. In other words, it is dimension of a hypothesis assigned + * to submesh. + */ +//============================================================================= + +class SMESH_DimHyp +{ + public: + //! fileds + int _dim; //!< a dimension the algo can build (concurrent dimension) + int _ownDim; //!< dimension of shape of _subMesh (>=_dim) + TopTools_MapOfShape _shapeMap; + SMESH_subMesh* _subMesh; + list _hypothesises; //!< algo is first, then its parameters + + //! Constructors + SMESH_DimHyp(const SMESH_subMesh* theSubMesh, + const int theDim, + const TopoDS_Shape& theShape) + { + _subMesh = (SMESH_subMesh*)theSubMesh; + SetShape( theDim, theShape ); + } + + //! set shape + void SetShape(const int theDim, + const TopoDS_Shape& theShape) + { + _dim = theDim; + _ownDim = (int)SMESH_Gen::GetShapeDim(theShape); + if (_dim >= _ownDim) + _shapeMap.Add( theShape ); + else { + TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) ); + for( ; anExp.More(); anExp.Next() ) + _shapeMap.Add( anExp.Current() ); + } + } + + //! Check sharing of sub shapes + static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck, + const TopTools_MapOfShape& theToFind, + const TopAbs_ShapeEnum theType) + { + bool isShared = false; + TopTools_MapIteratorOfMapOfShape anItr( theToCheck ); + for (; !isShared && anItr.More(); anItr.Next() ) { + const TopoDS_Shape aSubSh = anItr.Key(); + // check for case when concurrent dimensions are same + isShared = theToFind.Contains( aSubSh ); + // check for subshape with concurrent dimension + TopExp_Explorer anExp( aSubSh, theType ); + for ( ; !isShared && anExp.More(); anExp.Next() ) + isShared = theToFind.Contains( anExp.Current() ); + } + return isShared; + } + + //! check algorithms + static bool checkAlgo(const SMESHDS_Hypothesis* theA1, + const SMESHDS_Hypothesis* theA2) + { + if ( theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO || + theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ) + return false; // one of the hypothesis is not algorithm + // check algorithm names (should be equal) + return strcmp( theA1->GetName(), theA2->GetName() ) == 0; + } + + + //! Check if subshape hypotheses are concurrent + bool IsConcurrent(const SMESH_DimHyp* theOther) const + { + if ( _subMesh == theOther->_subMesh ) + return false; // same subshape - should not be + + // if ( == && + // any of the two submeshes is not on COMPOUND shape ) + // -> no concurrency + bool meIsCompound = (_subMesh->GetSubMeshDS() && _subMesh->GetSubMeshDS()->IsComplexSubmesh()); + bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() && theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh()); + if ( (_ownDim == _dim || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound)) + return false; + +// bool checkSubShape = ( _dim >= theOther->_dim ) +// ? isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(theOther->_dim) ) +// : isShareSubShapes( theOther->_shapeMap, _shapeMap, shapeTypeByDim(_dim) ) ; + bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim)); + if ( !checkSubShape ) + return false; + + // check algorithms to be same + if (!checkAlgo( _hypothesises.front(), theOther->_hypothesises.front() )) + return true; // different algorithms + + // check hypothesises for concurrence (skip first as algorithm) + int nbSame = 0; + // pointers should be same, becase it is referenes from mesh hypothesis partition + list ::const_iterator hypIt = _hypothesises.begin(); + list ::const_iterator otheEndIt = theOther->_hypothesises.end(); + for ( hypIt++ /*skip first as algo*/; hypIt != _hypothesises.end(); hypIt++ ) + if ( find( theOther->_hypothesises.begin(), otheEndIt, *hypIt ) != otheEndIt ) + nbSame++; + // the submeshes are concurrent if their algorithms has different parameters + return nbSame != theOther->_hypothesises.size() - 1; + } + +}; // end of SMESH_DimHyp + +typedef list TDimHypList; + +static void addDimHypInstance(const int theDim, + const TopoDS_Shape& theShape, + const SMESH_Algo* theAlgo, + const SMESH_subMesh* theSubMesh, + const list & theHypList, + TDimHypList* theDimHypListArr ) +{ + TDimHypList& listOfdimHyp = theDimHypListArr[theDim]; + if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) { + SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape ); + listOfdimHyp.push_back( dimHyp ); + } + + SMESH_DimHyp* dimHyp = listOfdimHyp.back(); + dimHyp->_hypothesises.push_front(theAlgo); + list ::const_iterator hypIt = theHypList.begin(); + for( ; hypIt != theHypList.end(); hypIt++ ) + dimHyp->_hypothesises.push_back( *hypIt ); +} + +static void findConcurrents(const SMESH_DimHyp* theDimHyp, + const TDimHypList& theListOfDimHyp, + TListOfInt& theListOfConcurr ) +{ + TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin(); + for ( ; rIt != theListOfDimHyp.rend(); rIt++ ) { + const SMESH_DimHyp* curDimHyp = *rIt; + if ( curDimHyp == theDimHyp ) + break; // meet own dimHyp pointer in same dimension + else if ( theDimHyp->IsConcurrent( curDimHyp ) ) + if ( find( theListOfConcurr.begin(), + theListOfConcurr.end(), + curDimHyp->_subMesh->GetId() ) == theListOfConcurr.end() ) + theListOfConcurr.push_back( curDimHyp->_subMesh->GetId() ); + } +} + +static void unionLists(TListOfInt& theListOfId, + TListOfListOfInt& theListOfListOfId, + const int theIndx ) +{ + TListOfListOfInt::iterator it = theListOfListOfId.begin(); + for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) { + if ( i < theIndx ) + continue; //skip already treated lists + // check if other list has any same submesh object + TListOfInt& otherListOfId = *it; + if ( find_first_of( theListOfId.begin(), theListOfId.end(), + otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() ) + continue; + + // union two lists (from source into target) + TListOfInt::iterator it2 = otherListOfId.begin(); + for ( ; it2 != otherListOfId.end(); it2++ ) { + if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() ) + theListOfId.push_back(*it2); + } + // clear source list + otherListOfId.clear(); + } +} + +//! free memory allocated for dimension-hypothesis objects +static void removeDimHyps( TDimHypList* theArrOfList ) +{ + for (int i = 0; i < 4; i++ ) { + TDimHypList& listOfdimHyp = theArrOfList[i]; + TDimHypList::const_iterator it = listOfdimHyp.begin(); + for ( ; it != listOfdimHyp.end(); it++ ) + delete (*it); + } +} + +//============================================================================= +/*! + * \brief Return submesh objects list in meshing order + */ +//============================================================================= + +SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder() +{ + SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array(); + + SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS(); + if ( !aMeshDS ) + return aResult._retn(); + + ::SMESH_Mesh& mesh = GetImpl(); + TListOfListOfInt anOrder = mesh.GetMeshOrder(); // is there already defined order? + if ( !anOrder.size() ) { + + // collect submeshes detecting concurrent algorithms and hypothesises + TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension + + map::iterator i_sm = _mapSubMesh.begin(); + for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) { + ::SMESH_subMesh* sm = (*i_sm).second; + // shape of submesh + const TopoDS_Shape& aSubMeshShape = sm->GetSubShape(); + + // list of assigned hypothesises + const list & hypList = mesh.GetHypothesisList(aSubMeshShape); + // Find out dimensions where the submesh can be concurrent. + // We define the dimensions by algo of each of hypotheses in hypList + list ::const_iterator hypIt = hypList.begin(); + for( ; hypIt != hypList.end(); hypIt++ ) { + SMESH_Algo* anAlgo = 0; + const SMESH_Hypothesis* hyp = dynamic_cast(*hypIt); + if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO ) + // hyp it-self is algo + anAlgo = (SMESH_Algo*)dynamic_cast(hyp); + else { + // try to find algorithm with help of subshapes + TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) ); + for ( ; !anAlgo && anExp.More(); anExp.Next() ) + anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() ); + } + if (!anAlgo) + continue; // no assigned algorithm to current submesh + + int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp) + // the submesh can concurrent at (or lower dims if !anAlgo->NeedDescretBoundary()) + + // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm + for ( int j = anAlgo->NeedDescretBoundary() ? dim : 1, jn = dim; j <= jn; j++ ) + addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr ); + } + } // end iterations on submesh + + // iterate on created dimension-hypotheses and check for concurrents + for ( int i = 0; i < 4; i++ ) { + const list& listOfDimHyp = dimHypListArr[i]; + // check for concurrents in own and other dimensions (step-by-step) + TDimHypList::const_iterator dhIt = listOfDimHyp.begin(); + for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) { + const SMESH_DimHyp* dimHyp = *dhIt; + TListOfInt listOfConcurr; + // looking for concurrents and collect into own list + for ( int j = i; j < 4; j++ ) + findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr ); + // check if any concurrents found + if ( listOfConcurr.size() > 0 ) { + // add own submesh to list of concurrent + listOfConcurr.push_front( dimHyp->_subMesh->GetId() ); + anOrder.push_back( listOfConcurr ); + } + } + } + + removeDimHyps(dimHypListArr); + + // now, minimise the number of concurrent groups + // Here we assume that lists of submhes can has same submesh + // in case of multi-dimension algorithms, as result + // list with common submesh have to be union into one list + int listIndx = 0; + TListOfListOfInt::iterator listIt = anOrder.begin(); + for(; listIt != anOrder.end(); listIt++, listIndx++ ) + unionLists( *listIt, anOrder, listIndx + 1 ); + } + // convert submesh ids into interface instances + // and dump command into python + convertMeshOrder( anOrder, aResult, true ); + + return aResult._retn(); +} + +//============================================================================= +/*! + * \brief find common submeshes with given submesh + * \param theSubMeshList list of already collected submesh to check + * \param theSubMesh given submesh to intersect with other + * \param theCommonSubMeshes collected common submeshes + */ +//============================================================================= + +static void findCommonSubMesh + (list& theSubMeshList, + const SMESH_subMesh* theSubMesh, + set& theCommon ) +{ + if ( !theSubMesh ) + return; + list::const_iterator it = theSubMeshList.begin(); + for ( ; it != theSubMeshList.end(); it++ ) + theSubMesh->FindIntersection( *it, theCommon ); + theSubMeshList.push_back( theSubMesh ); + //theCommon.insert( theSubMesh ); +} + +//============================================================================= +/*! + * \brief Set submesh object order + * \param theSubMeshArray submesh array order + */ +//============================================================================= + +::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray) +{ + bool res = false; + ::SMESH_Mesh& mesh = GetImpl(); + + TPythonDump aPythonDump; // prevent dump of called methods + aPythonDump << "isDone = " << _this() << ".SetMeshOrder( [ "; + + TListOfListOfInt subMeshOrder; + for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ ) + { + const SMESH::submesh_array& aSMArray = theSubMeshArray[i]; + TListOfInt subMeshIds; + aPythonDump << "[ "; + // Collect subMeshes which should be clear + // do it list-by-list, because modification of submesh order + // take effect between concurrent submeshes only + set subMeshToClear; + list subMeshList; + for ( int j = 0, jn = aSMArray.length(); j < jn; j++ ) + { + const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]); + if ( j > 0 ) + aPythonDump << ", "; + aPythonDump << subMesh; + subMeshIds.push_back( subMesh->GetId() ); + // detect common parts of submeshes + if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() ) + findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear ); + } + aPythonDump << " ]"; + subMeshOrder.push_back( subMeshIds ); + + // clear collected submeshes + set::iterator clrIt = subMeshToClear.begin(); + for ( ; clrIt != subMeshToClear.end(); clrIt++ ) { + SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt; + if ( sm ) + sm->ComputeStateEngine( SMESH_subMesh::CLEAN ); + // ClearSubMesh( *clrIt ); + } + } + aPythonDump << " ])"; + + mesh.SetMeshOrder( subMeshOrder ); + res = true; + + return res; +} + +//============================================================================= +/*! + * \brief Convert submesh ids into submesh interfaces + */ +//============================================================================= + +void SMESH_Mesh_i::convertMeshOrder +(const TListOfListOfInt& theIdsOrder, + SMESH::submesh_array_array& theResOrder, + const bool theIsDump) +{ + int nbSet = theIdsOrder.size(); + TPythonDump aPythonDump; // prevent dump of called methods + if ( theIsDump ) + aPythonDump << "[ "; + theResOrder.length(nbSet); + TListOfListOfInt::const_iterator it = theIdsOrder.begin(); + int listIndx = 0; + for( ; it != theIdsOrder.end(); it++ ) { + // translate submesh identificators into submesh objects + // takeing into account real number of concurrent lists + const TListOfInt& aSubOrder = (*it); + if (!aSubOrder.size()) + continue; + if ( theIsDump ) + aPythonDump << "[ "; + // convert shape indeces into interfaces + SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array(); + aResSubSet->length(aSubOrder.size()); + TListOfInt::const_iterator subIt = aSubOrder.begin(); + for( int j = 0; subIt != aSubOrder.end(); subIt++ ) { + if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() ) + continue; + SMESH::SMESH_subMesh_var subMesh = + SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] ); + if ( theIsDump ) { + if ( j > 0 ) + aPythonDump << ", "; + aPythonDump << subMesh; + } + aResSubSet[ j++ ] = subMesh; + } + if ( theIsDump ) + aPythonDump << " ]"; + theResOrder[ listIndx++ ] = aResSubSet; + } + // correct number of lists + theResOrder.length( listIndx ); + + if ( theIsDump ) { + // finilise python dump + aPythonDump << " ]"; + aPythonDump << " = " << _this() << ".GetMeshOrder()"; + } +}