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=d4e396cbdfacd0556715d974ba7d7b1d655a9077;hp=016bf658bf9db8be14c9d603d3e8b0a512df6a20;hb=6472eab132825fec572beda8276947593f85ffa1;hpb=09bc0414c91ebabb67c7fe200549044a1854e199 diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index 016bf658b..d4e396cbd 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2019 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 @@ -72,6 +72,7 @@ #include #include #include +#include #include #include #include @@ -113,6 +114,7 @@ SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA, _impl = NULL; _gen_i = gen_i; _id = _idGenerator++; + _nbInvalidHypos= -1; _editor = NULL; _previewEditor = NULL; _preMeshInfo = NULL; @@ -240,7 +242,7 @@ GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh() for ( ; data != _geomGroupData.end(); ++data ) if ( data->_smeshObject->_is_equivalent( _this() )) { - SALOMEDS::SObject_wrap so = SMESH_Gen_i::getStudyServant()->FindObjectID( data->_groupEntry.c_str() ); + SALOMEDS::SObject_wrap so = _gen_i->getStudyServant()->FindObjectID( data->_groupEntry.c_str() ); CORBA::Object_var obj = _gen_i->SObjectToObject( so ); aShapeObj = GEOM::GEOM_Object::_narrow( obj ); break; @@ -254,6 +256,47 @@ GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh() return aShapeObj._retn(); } +//================================================================================ +/*! +* \brief Replaces a shape in the mesh +*/ +//================================================================================ +void SMESH_Mesh_i::ReplaceShape(GEOM::GEOM_Object_ptr theNewGeom) + throw (SALOME::SALOME_Exception) +{ + TopoDS_Shape S = _impl->GetShapeToMesh(); + GEOM_Client* geomClient = _gen_i->GetShapeReader(); + TCollection_AsciiString aIOR; + if (geomClient->Find(S, aIOR)) { + geomClient->RemoveShapeFromBuffer(aIOR); + } + + // update the reference to theNewGeom (needed for correct execution of a dumped python script) + SMESH::SMESH_Mesh_var me = _this(); + SALOMEDS::SObject_wrap aSO = _gen_i->ObjectToSObject( me ); + CORBA::String_var entry = theNewGeom->GetStudyEntry(); + if ( !aSO->_is_nil() ) + { + SALOMEDS::SObject_wrap aShapeRefSO; + if ( aSO->FindSubObject( _gen_i->GetRefOnShapeTag(), aShapeRefSO.inout() )) + { + SALOMEDS::SObject_wrap aShapeSO = _gen_i->getStudyServant()->FindObjectID( entry ); + SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder(); + builder->Addreference( aShapeRefSO, aShapeSO ); + } + } + + // re-assign global hypotheses to the new shape + _mainShapeTick = -1; + CheckGeomModif( true ); + + TPythonDump() << "SHAPERSTUDY.breakLinkForSubElements(salome.ObjectToSObject(" + << me <<".GetMesh()), " << entry.in() << ")"; + + TPythonDump() << me << ".ReplaceShape( " << entry.in() << " )"; + +} + //================================================================================ /*! * \brief Return false if the mesh is not yet fully loaded from the study file @@ -647,6 +690,8 @@ SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr aSubShape, if ( _preMeshInfo ) _preMeshInfo->ForgetOrLoad(); + const int prevNbMeshEnt = _impl->NbNodes() + _impl->GetMeshDS()->NbElements(); + std::string error; SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShape, anHyp, &error ); anErrorText = error.c_str(); @@ -655,7 +700,10 @@ SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr aSubShape, if ( !SMESH_Hypothesis::IsStatusFatal(status) ) { _gen_i->AddHypothesisToShape( mesh, aSubShape, anHyp ); - _gen_i->UpdateIcons( mesh ); + + int newNbMeshEnt = _impl->NbNodes() + _impl->GetMeshDS()->NbElements(); + if ( newNbMeshEnt != prevNbMeshEnt ) + _gen_i->UpdateIcons( mesh ); } if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status ); @@ -772,6 +820,9 @@ SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShape, if (CORBA::is_nil( anHyp )) THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference", SALOME::BAD_PARAM); + if ( _preMeshInfo ) + _preMeshInfo->ForgetOrLoad(); + SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK; try { @@ -955,7 +1006,7 @@ void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh ) // if ( aSubShape->_is_nil() ) // not published shape (IPAL13617) // aSubShape = theSubMesh->GetSubShape(); - SALOMEDS::StudyBuilder_var builder = SMESH_Gen_i::getStudyServant()->NewBuilder(); + SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder(); builder->RemoveObjectWithChildren( anSO ); // Update Python script @@ -1101,6 +1152,10 @@ void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup ) if ( !aGroup ) return; + if ( aGroup->GetMeshServant() != this ) + THROW_SALOME_CORBA_EXCEPTION( "RemoveGroup(): group does not belong to this mesh", + SALOME::BAD_PARAM ); + SALOMEDS::SObject_wrap aGroupSO = _gen_i->ObjectToSObject( theGroup ); if ( !aGroupSO->_is_nil() ) { @@ -1135,6 +1190,11 @@ void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup if ( theGroup->_is_nil() ) return; + SMESH_GroupBase_i* groupImpl = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup ); + if ( !groupImpl || groupImpl->GetMeshServant() != this ) + THROW_SALOME_CORBA_EXCEPTION( "RemoveGroupWithContents(): group does not belong to this mesh", + SALOME::BAD_PARAM); + vector nodeIds; // to remove nodes becoming free bool isNodal = ( theGroup->GetType() == SMESH::NODE ); if ( !isNodal && !theGroup->IsEmpty() ) @@ -1968,9 +2028,8 @@ void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj, if ( groupSO->_is_nil() ) return; // group indices - GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine(); - GEOM::GEOM_IGroupOperations_wrap groupOp = - geomGen->GetIGroupOperations(); + GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( theGeomObj ); + GEOM::GEOM_IGroupOperations_ptr groupOp = geomGen->GetIGroupOperations(); GEOM::ListOfLong_var ids = groupOp->GetObjects( theGeomObj ); // store data @@ -2012,41 +2071,58 @@ void SMESH_Mesh_i::removeGeomGroupData(CORBA::Object_ptr theSmeshObj) * \brief Return new group contents if it has been changed and update group data */ //================================================================================ +enum { ONLY_IF_CHANGED, IS_BREAK_LINK, MAIN_TRANSFORMED }; -TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData) +TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData, int how ) { TopoDS_Shape newShape; - // get geom group - SALOMEDS::SObject_wrap groupSO = SMESH_Gen_i::getStudyServant()->FindObjectID( groupData._groupEntry.c_str() ); - if ( !groupSO->_is_nil() ) + if ( how == IS_BREAK_LINK ) { - 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(); - GEOM::GEOM_IGroupOperations_wrap groupOp = - geomGen->GetIGroupOperations(); - GEOM::ListOfLong_var ids = groupOp->GetObjects( geomGroup ); - for ( CORBA::ULong i = 0; i < ids->length(); ++i ) - curIndices.insert( ids[i] ); - - if ( groupData._indices == curIndices ) - return newShape; // group not changed - - // update data - groupData._indices = curIndices; - - GEOM_Client* geomClient = _gen_i->GetShapeReader(); - if ( !geomClient ) return newShape; - CORBA::String_var groupIOR = geomGen->GetStringFromIOR( geomGroup ); - geomClient->RemoveShapeFromBuffer( groupIOR.in() ); - newShape = _gen_i->GeomObjectToShape( geomGroup ); + SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( groupData._smeshObject ); + SALOMEDS::SObject_wrap geomRefSO, geomSO; + if ( !meshSO->_is_nil() && + meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) && + geomRefSO->ReferencedObject( geomSO.inout() )) + { + CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO ); + GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( geomObj ); + newShape = _gen_i->GeomObjectToShape( geom ); + CORBA::String_var entry = geom->GetStudyEntry(); + groupData._groupEntry = entry.in(); + } + } + else + { + // get geom group + SALOMEDS::SObject_wrap groupSO = SMESH_Gen_i::getStudyServant()->FindObjectID( groupData._groupEntry.c_str() ); + if ( !groupSO->_is_nil() ) + { + 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( geomGroup ); + GEOM::GEOM_IGroupOperations_ptr groupOp = geomGen->GetIGroupOperations(); + GEOM::ListOfLong_var ids = groupOp->GetObjects( geomGroup ); + for ( CORBA::ULong i = 0; i < ids->length(); ++i ) + curIndices.insert( ids[i] ); + + if ( how == ONLY_IF_CHANGED && groupData._indices == curIndices ) + return newShape; // group not changed + + // update data + groupData._indices = curIndices; + + GEOM_Client* geomClient = _gen_i->GetShapeReader(); + if ( !geomClient ) return newShape; + CORBA::String_var groupIOR = geomGen->GetStringFromIOR( geomGroup ); + geomClient->RemoveShapeFromBuffer( groupIOR.in() ); + newShape = _gen_i->GeomObjectToShape( geomGroup ); + } } - if ( newShape.IsNull() ) { // geom group becomes empty - return empty compound TopoDS_Compound compound; @@ -2075,11 +2151,66 @@ namespace struct TGroupOnGeomData { int _oldID; - int _shapeID; + TopoDS_Shape _shape; SMDSAbs_ElementType _type; std::string _name; Quantity_Color _color; + + TGroupOnGeomData( const SMESHDS_GroupOnGeom* group ) + { + _oldID = group->GetID(); + _type = group->GetType(); + _name = group->GetStoreName(); + _color = group->GetColor(); + } }; + + //----------------------------------------------------------------------------- + /*! + * \brief Check if a filter is still valid after geometry removal + */ + bool isValidGeomFilter( SMESH::Filter_var theFilter ) + { + if ( theFilter->_is_nil() ) + return false; + SMESH::Filter::Criteria_var criteria; + theFilter->GetCriteria( criteria.out() ); + + for ( CORBA::ULong iCr = 0; iCr < criteria->length(); ++iCr ) + { + const char* thresholdID = criteria[ iCr ].ThresholdID.in(); + std::string entry; + switch ( criteria[ iCr ].Type ) + { + case SMESH::FT_BelongToGeom: + case SMESH::FT_BelongToPlane: + case SMESH::FT_BelongToCylinder: + case SMESH::FT_BelongToGenSurface: + case SMESH::FT_LyingOnGeom: + entry = thresholdID; + break; + case SMESH::FT_ConnectedElements: + if ( thresholdID ) + { + entry = thresholdID; + break; + } + default: + continue; + } + SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen(); + SALOMEDS::SObject_wrap so = gen->getStudyServant()->FindObjectID( entry.c_str() ); + if ( so->_is_nil() ) + return false; + CORBA::Object_var obj = so->GetObject(); + GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( obj ); + if ( gen->GeomObjectToShape( geom ).IsNull() ) + return false; + + } // loop on criteria + + return true; + } } //============================================================================= @@ -2090,38 +2221,93 @@ namespace */ //============================================================================= -void SMESH_Mesh_i::CheckGeomModif() +void SMESH_Mesh_i::CheckGeomModif( bool isBreakLink ) { + SMESH::SMESH_Mesh_var me = _this(); + GEOM::GEOM_Object_var mainGO = GetShapeToMesh(); + + TPythonDump dumpNothing; // prevent any dump + + //bool removedFromClient = false; + + if ( mainGO->_is_nil() ) // GEOM_Client cleared or geometry removed? (IPAL52735, PAL23636) + { + //removedFromClient = _impl->HasShapeToMesh(); + + // try to find geometry by study reference + SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me ); + SALOMEDS::SObject_wrap geomRefSO, geomSO; + if ( !meshSO->_is_nil() && + meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) && + geomRefSO->ReferencedObject( geomSO.inout() )) + { + CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO ); + mainGO = GEOM::GEOM_Object::_narrow( geomObj ); + } + + if ( mainGO->_is_nil() && // geometry removed ==> + !geomRefSO->_is_nil() ) // remove geom dependent data: sub-meshes etc. + { + // convert geom dependent groups into standalone ones + CheckGeomGroupModif(); + + _impl->ShapeToMesh( TopoDS_Shape() ); + + // remove sub-meshes + std::map::iterator i_sm = _mapSubMeshIor.begin(); + while ( i_sm != _mapSubMeshIor.end() ) + { + SMESH::SMESH_subMesh_ptr sm = i_sm->second; + ++i_sm; + RemoveSubMesh( sm ); + } + // remove all children except groups in the study + SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder(); + SALOMEDS::SObject_wrap so; + for ( CORBA::Long tag = SMESH::Tag_RefOnShape; tag <= SMESH::Tag_LastSubMesh; ++tag ) + if ( meshSO->FindSubObject( tag, so.inout() )) + builder->RemoveObjectWithChildren( so ); + + _gen_i->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED" ); + + return; + } + } + if ( !_impl->HasShapeToMesh() ) return; - GEOM::GEOM_Object_var mainGO = _gen_i->ShapeToGeomObject( _impl->GetShapeToMesh() ); - //if ( mainGO->_is_nil() ) return; // Update after group modification - if ( mainGO->_is_nil() || /* shape was removed from GEOM_Client by newGroupShape() - called by other mesh (IPAL52735) */ - mainGO->GetType() == GEOM_GROUP || + if ( mainGO->GetType() == GEOM_GROUP || // is group or not modified mainGO->GetTick() == _mainShapeTick ) { + int nb = NbNodes() + NbElements(); CheckGeomGroupModif(); + if ( nb != NbNodes() + NbElements() ) // something removed due to hypotheses change + _gen_i->UpdateIcons( me ); return; } - // Update after shape transformation like Translate + // Update after shape modification GEOM_Client* geomClient = _gen_i->GetShapeReader(); if ( !geomClient ) return; - GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine(); + GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( mainGO ); if ( geomGen->_is_nil() ) return; CORBA::String_var ior = geomGen->GetStringFromIOR( mainGO ); geomClient->RemoveShapeFromBuffer( ior.in() ); - // Update data taking into account that + // Update data taking into account that if topology doesn't change // all sub-shapes change but IDs of sub-shapes remain (except for geom groups) - _impl->Clear(); + if ( _preMeshInfo ) + _preMeshInfo->ForgetAllData(); + + + if (isBreakLink) + _impl->Clear(); TopoDS_Shape newShape = _gen_i->GeomObjectToShape( mainGO ); if ( newShape.IsNull() ) return; @@ -2131,23 +2317,58 @@ void SMESH_Mesh_i::CheckGeomModif() SMESHDS_Mesh * meshDS = _impl->GetMeshDS(); // store data of groups on geometry - vector< TGroupOnGeomData > groupsData; - const set& groups = meshDS->GetGroups(); + std::vector< TGroupOnGeomData > groupsData; + const std::set& groups = meshDS->GetGroups(); groupsData.reserve( groups.size() ); - set::const_iterator g = groups.begin(); + TopTools_DataMapOfShapeShape old2newShapeMap; + std::set::const_iterator g = groups.begin(); for ( ; g != groups.end(); ++g ) + { if ( const SMESHDS_GroupOnGeom* group = dynamic_cast< SMESHDS_GroupOnGeom* >( *g )) { - TGroupOnGeomData data; - data._oldID = group->GetID(); - data._shapeID = meshDS->ShapeToIndex( group->GetShape() ); - data._type = group->GetType(); - data._name = group->GetStoreName(); - data._color = group->GetColor(); - groupsData.push_back( data ); + groupsData.push_back( TGroupOnGeomData( group )); + + // get a new shape + SMESH::SMESH_GroupOnGeom_var gog; + std::map::iterator i_grp = _mapGroups.find( group->GetID() ); + if ( i_grp != _mapGroups.end() ) + gog = SMESH::SMESH_GroupOnGeom::_narrow( i_grp->second ); + + GEOM::GEOM_Object_var geom; + if ( !gog->_is_nil() ) + { + if ( isBreakLink ) + { + SALOMEDS::SObject_wrap grpSO = _gen_i->ObjectToSObject( gog ); + SALOMEDS::SObject_wrap geomRefSO, geomSO; + if ( !grpSO->_is_nil() && + grpSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) && + geomRefSO->ReferencedObject( geomSO.inout() )) + { + CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO ); + geom = GEOM::GEOM_Object::_narrow( geomObj ); + } + } + else + { + geom = gog->GetShape(); + } + } + if ( !geom->_is_nil() ) + { + CORBA::String_var ior = geomGen->GetStringFromIOR( geom ); + geomClient->RemoveShapeFromBuffer( ior.in() ); + groupsData.back()._shape = _gen_i->GeomObjectToShape( geom ); + old2newShapeMap.Bind( group->GetShape(), groupsData.back()._shape ); + } + else if ( old2newShapeMap.IsBound( group->GetShape() )) + { + groupsData.back()._shape = old2newShapeMap( group->GetShape() ); + } } + } // store assigned hypotheses - vector< pair< int, THypList > > ids2Hyps; + std::vector< pair< int, THypList > > ids2Hyps; const ShapeToHypothesis & hyps = meshDS->GetHypotheses(); for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() ) { @@ -2156,16 +2377,50 @@ void SMESH_Mesh_i::CheckGeomModif() ids2Hyps.push_back( make_pair( meshDS->ShapeToIndex( s ), hyps )); } - // change shape to mesh + std::map< std::set, int > ii2iMap; // group sub-ids to group id in SMESHDS + + // count shapes excluding compounds corresponding to geom groups int oldNbSubShapes = meshDS->MaxShapeIndex(); + for ( ; oldNbSubShapes > 0; --oldNbSubShapes ) + { + const TopoDS_Shape& s = meshDS->IndexToShape( oldNbSubShapes ); + if ( s.IsNull() || s.ShapeType() != TopAbs_COMPOUND ) + break; + // fill ii2iMap + std::set subIds; + for ( TopoDS_Iterator it( s ); it.More(); it.Next() ) + subIds.insert( meshDS->ShapeToIndex( it.Value() )); + ii2iMap.insert( std::make_pair( subIds, oldNbSubShapes )); + } + + // check if shape topology changes - save shape type per shape ID + std::vector< TopAbs_ShapeEnum > shapeTypes( Max( oldNbSubShapes + 1, 1 )); + for ( int shapeID = oldNbSubShapes; shapeID > 0; --shapeID ) + shapeTypes[ shapeID ] = meshDS->IndexToShape( shapeID ).ShapeType(); + + // change shape to mesh _impl->ShapeToMesh( TopoDS_Shape() ); _impl->ShapeToMesh( newShape ); - // re-add shapes of geom groups - list::iterator data = _geomGroupData.begin(); + // check if shape topology changes - check new shape types + bool sameTopology = ( oldNbSubShapes == meshDS->MaxShapeIndex() ); + for ( int shapeID = oldNbSubShapes; shapeID > 0 && sameTopology; --shapeID ) + { + const TopoDS_Shape& s = meshDS->IndexToShape( shapeID ); + sameTopology = ( !s.IsNull() && s.ShapeType() == shapeTypes[ shapeID ]); + } + + // re-add shapes (compounds) of geom groups + std::map< int, int > old2newIDs; // group IDs + std::list::iterator data = _geomGroupData.begin(); for ( ; data != _geomGroupData.end(); ++data ) { - TopoDS_Shape newShape = newGroupShape( *data ); + int oldID = 0; + std::map< std::set, int >::iterator ii2i = ii2iMap.find( data->_indices ); + if ( ii2i != ii2iMap.end() ) + oldID = ii2i->second; + + TopoDS_Shape newShape = newGroupShape( *data, isBreakLink ? IS_BREAK_LINK : MAIN_TRANSFORMED ); if ( !newShape.IsNull() ) { if ( meshDS->ShapeToIndex( newShape ) > 0 ) // a group reduced to one sub-shape @@ -2175,56 +2430,88 @@ void SMESH_Mesh_i::CheckGeomModif() BRep_Builder().Add( compound, newShape ); newShape = compound; } - _impl->GetSubMesh( newShape ); + int newID = _impl->GetSubMesh( newShape )->GetId(); + if ( oldID && oldID != newID ) + old2newIDs.insert( std::make_pair( oldID, newID )); } } - if ( oldNbSubShapes != meshDS->MaxShapeIndex() ) - THROW_SALOME_CORBA_EXCEPTION( "SMESH_Mesh_i::CheckGeomModif() bug", - SALOME::INTERNAL_ERROR ); // re-assign hypotheses for ( size_t i = 0; i < ids2Hyps.size(); ++i ) { - const TopoDS_Shape& s = meshDS->IndexToShape( ids2Hyps[i].first ); + if ( !sameTopology && ids2Hyps[i].first != 1 ) + continue; // assign only global hypos + int sID = ids2Hyps[i].first; + std::map< int, int >::iterator o2n = old2newIDs.find( sID ); + if ( o2n != old2newIDs.end() ) + sID = o2n->second; + const TopoDS_Shape& s = meshDS->IndexToShape( sID ); const THypList& hyps = ids2Hyps[i].second; THypList::const_iterator h = hyps.begin(); for ( ; h != hyps.end(); ++h ) _impl->AddHypothesis( s, (*h)->GetID() ); } - // restore groups - for ( size_t i = 0; i < groupsData.size(); ++i ) + if ( !sameTopology ) { - const TGroupOnGeomData& data = groupsData[i]; + // remove invalid study sub-objects + CheckGeomGroupModif(); + } + else + { + // restore groups on geometry + for ( size_t i = 0; i < groupsData.size(); ++i ) + { + const TGroupOnGeomData& data = groupsData[i]; + if ( data._shape.IsNull() ) + continue; - map::iterator i2g = _mapGroups.find( data._oldID ); - if ( i2g == _mapGroups.end() ) continue; + std::map::iterator i2g = _mapGroups.find( data._oldID ); + if ( i2g == _mapGroups.end() ) continue; - SMESH_GroupBase_i* gr_i = SMESH::DownCast( i2g->second ); - if ( !gr_i ) continue; + SMESH_GroupBase_i* gr_i = SMESH::DownCast( i2g->second ); + if ( !gr_i ) continue; - int id; - SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), id, - meshDS->IndexToShape( data._shapeID )); - if ( !g ) - { - _mapGroups.erase( i2g ); + SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), data._oldID, data._shape ); + if ( !g ) + _mapGroups.erase( i2g ); + else + g->GetGroupDS()->SetColor( data._color ); } - else + + std::map< int, int >::iterator o2n = old2newIDs.begin(); + for ( ; o2n != old2newIDs.end(); ++o2n ) { - g->GetGroupDS()->SetColor( data._color ); - gr_i->changeLocalId( id ); - _mapGroups[ id ] = i2g->second; - if ( data._oldID != id ) - _mapGroups.erase( i2g ); + int newID = o2n->second, oldID = o2n->first; + if ( !_mapSubMesh.count( oldID )) + continue; + if ( newID > 0 ) + { + _mapSubMesh [ newID ] = _impl->GetSubMeshContaining( newID ); + _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ]; + _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ]; + } + _mapSubMesh. erase(oldID); + _mapSubMesh_i. erase(oldID); + _mapSubMeshIor.erase(oldID); + if ( newID > 0 ) + _mapSubMesh_i [ newID ]->changeLocalId( newID ); } + + // update _mapSubMesh + std::map::iterator i_sm = _mapSubMesh.begin(); + for ( ; i_sm != _mapSubMesh.end(); ++i_sm ) + i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first )); } - // update _mapSubMesh - map::iterator i_sm = _mapSubMesh.begin(); - for ( ; i_sm != _mapSubMesh.end(); ++i_sm ) - i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first )); + _gen_i->UpdateIcons( me ); + if ( !isBreakLink ) + { + SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me ); + if ( !meshSO->_is_nil() ) + _gen_i->SetPixMap(meshSO, "ICON_SMESH_TREE_GEOM_MODIF"); + } } //============================================================================= @@ -2238,6 +2525,98 @@ void SMESH_Mesh_i::CheckGeomModif() void SMESH_Mesh_i::CheckGeomGroupModif() { + // remove sub-meshes referring a removed sub-shapes (if main shape still exists) + SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder(); + GEOM::GEOM_Object_var mainGO = GetShapeToMesh(); + SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( SMESH::SMESH_Mesh_var( _this() )); + if ( !mainGO->_is_nil() && !meshSO->_is_nil() ) + { + SALOMEDS::SObject_wrap rootSO, geomRefSO, geomSO; + for ( CORBA::Long tag = SMESH::Tag_FirstSubMesh; tag <= SMESH::Tag_LastSubMesh; ++tag ) + if ( meshSO->FindSubObject( tag, rootSO.inout() )) + { + int nbValid = 0, nbRemoved = 0; + SALOMEDS::ChildIterator_wrap chItr = _gen_i->getStudyServant()->NewChildIterator( rootSO ); + for ( ; chItr->More(); chItr->Next() ) + { + SALOMEDS::SObject_wrap smSO = chItr->Value(); // sub-mesh SO + if ( !smSO->_is_nil() && + smSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) && + geomRefSO->ReferencedObject( geomSO.inout() )) // find geometry by reference + { + CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO ); + GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( geomObj ); + if ( !geom->_non_existent() ) + { + ++nbValid; + continue; // keep the sub-mesh + } + } + CORBA::Object_var smObj = _gen_i->SObjectToObject( smSO ); + SMESH::SMESH_subMesh_var sm = SMESH::SMESH_subMesh::_narrow( smObj ); + if ( !sm->_is_nil() && !sm->_non_existent() ) + { + GEOM::GEOM_Object_var smGeom = sm->GetSubShape(); + if ( smGeom->_is_nil() ) + { + RemoveSubMesh( sm ); + ++nbRemoved; + } + } + else + { + if ( _preMeshInfo ) + _preMeshInfo->ForgetAllData(); // unknown hypothesis modified + builder->RemoveObjectWithChildren( smSO ); // sub-shape removed before loading SMESH + ++nbRemoved; + } + } + if ( /*nbRemoved > 0 &&*/ nbValid == 0 ) + builder->RemoveObjectWithChildren( rootSO ); + } + } + + // check for removed sub-shapes and convert geom dependent groups into standalone ones + std::map::iterator i_gr = _mapGroups.begin(); + while ( i_gr != _mapGroups.end()) + { + SMESH::SMESH_GroupBase_ptr group = i_gr->second; + ++i_gr; + SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( group ), refSO; + SMESH::SMESH_GroupOnGeom_var onGeom = SMESH::SMESH_GroupOnGeom::_narrow ( group ); + SMESH::SMESH_GroupOnFilter_var onFilt = SMESH::SMESH_GroupOnFilter::_narrow( group ); + bool isValidGeom = false; + if ( !onGeom->_is_nil() ) + { + isValidGeom = ( ! GEOM::GEOM_Object_var( onGeom->GetShape() )->_is_nil() ); + } + else if ( !onFilt->_is_nil() ) + { + isValidGeom = isValidGeomFilter( onFilt->GetFilter() ); + } + else // standalone + { + isValidGeom = ( !groupSO->_is_nil() && + !groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() )); + } + if ( !isValidGeom ) + { + if ( !IsLoaded() || group->IsEmpty() ) + { + RemoveGroup( group ); + } + else if ( !onGeom->_is_nil() || !onFilt->_is_nil() ) + { + SMESH::SMESH_Group_var ( ConvertToStandalone( group )); + } + else // is it possible? + { + builder->RemoveObjectWithChildren( refSO ); + } + } + } + + if ( !_impl->HasShapeToMesh() ) return; CORBA::Long nbEntities = NbNodes() + NbElements(); @@ -2256,7 +2635,7 @@ void SMESH_Mesh_i::CheckGeomGroupModif() bool processedGroup = !it_new.second; TopoDS_Shape& newShape = it_new.first->second; if ( !processedGroup ) - newShape = newGroupShape( *data ); + newShape = newGroupShape( *data, ONLY_IF_CHANGED ); if ( newShape.IsNull() ) continue; // no changes @@ -2384,7 +2763,7 @@ void SMESH_Mesh_i::CheckGeomGroupModif() groupData.push_back ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType())); } - // set new shape to mesh -> DS of sub-meshes and geom groups are deleted + // set new shape to mesh -> DS of sub-meshes and geom groups is deleted _impl->Clear(); _impl->ShapeToMesh( TopoDS_Shape() ); // IPAL52730 _impl->ShapeToMesh( newShape ); @@ -2510,9 +2889,11 @@ SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase // remove reference to geometry SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO); for ( ; chItr->More(); chItr->Next() ) + { // Remove group's child SObject - builder->RemoveObject( chItr->Value() ); - + SALOMEDS::SObject_wrap so = chItr->Value(); + builder->RemoveObject( so ); + } // Update Python script TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this()) << ".ConvertToStandalone( " << aGroupSO << " )"; @@ -2520,9 +2901,9 @@ SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase // change icon of Group on Filter if ( isOnFilter ) { - SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes(); - const int isEmpty = ( elemTypes->length() == 0 ); - if ( !isEmpty ) + // SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes(); + // const int isEmpty = ( elemTypes->length() == 0 ); + // if ( !isEmpty ) { SALOMEDS::GenericAttribute_wrap anAttr = builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" ); @@ -2631,14 +3012,17 @@ bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh, if ( theSubShapeObject->_is_nil() ) // not published shape (IPAL13617) { - if ( _mapSubMesh.find( subMeshId ) != _mapSubMesh.end() && - _mapSubMesh[ subMeshId ]) + SMESH_subMesh* sm; + if (( _mapSubMesh.count( subMeshId )) && + ( sm = _impl->GetSubMeshContaining( subMeshId ))) { - TopoDS_Shape S = _mapSubMesh[ subMeshId ]->GetSubShape(); + TopoDS_Shape S = sm->GetSubShape(); if ( !S.IsNull() ) { list hyps = _impl->GetHypothesisList( S ); isHypChanged = !hyps.empty(); + if ( isHypChanged && _preMeshInfo ) + _preMeshInfo->ForgetOrLoad(); list::const_iterator hyp = hyps.begin(); for ( ; hyp != hyps.end(); ++hyp ) _impl->RemoveHypothesis(S, (*hyp)->GetID()); @@ -2856,40 +3240,55 @@ namespace SMESH_Mesh_i* _mesh; TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {} virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); } - virtual void HypothesisModified (int theHypID) { _mesh->onHypothesisModified( theHypID ); } + virtual void HypothesisModified( int hypID, + bool updIcons) { _mesh->onHypothesisModified( hypID, + updIcons ); } virtual void Load () { _mesh->Load(); } + virtual bool IsLoaded() { return _mesh->IsLoaded(); } }; } //================================================================================ /*! - * \brief callback from _impl to forget not loaded mesh data (issue 0021208) + * \brief callback from _impl to + * 1) forget not loaded mesh data (issue 0021208) + * 2) mark hypothesis as valid */ //================================================================================ -void SMESH_Mesh_i::onHypothesisModified(int theHypID) +void SMESH_Mesh_i::onHypothesisModified(int theHypID, bool theUpdateIcons) { if ( _preMeshInfo ) _preMeshInfo->ForgetOrLoad(); - SMESH::SMESH_Mesh_var mesh = _this(); - _gen_i->UpdateIcons( mesh ); + if ( theUpdateIcons ) + { + SMESH::SMESH_Mesh_var mesh = _this(); + _gen_i->UpdateIcons( mesh ); + } - // mark a hypothesis as valid after edition - SALOMEDS::SComponent_wrap smeshComp = _gen_i->PublishComponent(); - SALOMEDS::SObject_wrap hypRoot; - if ( !smeshComp->_is_nil() && - smeshComp->FindSubObject( _gen_i->GetHypothesisRootTag(), hypRoot.inout() )) + if ( _nbInvalidHypos != 0 ) { - SALOMEDS::ChildIterator_wrap anIter = _gen_i->getStudyServant()->NewChildIterator( hypRoot ); - for ( ; anIter->More(); anIter->Next() ) + // mark a hypothesis as valid after edition + int nbInvalid = 0; + SALOMEDS::SComponent_wrap smeshComp = _gen_i->PublishComponent(); + SALOMEDS::SObject_wrap hypRoot; + if ( !smeshComp->_is_nil() && + smeshComp->FindSubObject( _gen_i->GetHypothesisRootTag(), hypRoot.inout() )) { - SALOMEDS::SObject_wrap hypSO = anIter->Value(); - CORBA::Object_var obj = _gen_i->SObjectToObject( hypSO ); - SMESH::SMESH_Hypothesis_var hyp = SMESH::SMESH_Hypothesis::_narrow( obj ); - if ( !hyp->_is_nil() && hyp->GetId() == theHypID ) - _gen_i->HighLightInvalid( hyp, false ); + SALOMEDS::ChildIterator_wrap anIter = _gen_i->getStudyServant()->NewChildIterator( hypRoot ); + for ( ; anIter->More(); anIter->Next() ) + { + SALOMEDS::SObject_wrap hypSO = anIter->Value(); + CORBA::Object_var obj = _gen_i->SObjectToObject( hypSO ); + SMESH::SMESH_Hypothesis_var hyp = SMESH::SMESH_Hypothesis::_narrow( obj ); + if ( !hyp->_is_nil() && hyp->GetId() == theHypID ) + _gen_i->HighLightInvalid( hyp, false ); + else + nbInvalid += _gen_i->IsInvalid( hypSO ); + } } + _nbInvalidHypos = nbInvalid; } } @@ -3076,9 +3475,9 @@ CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED() void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite) { - SMESH_File aFile( file ); + SMESH_File aFile( file, false ); SMESH_Comment msg; - if (aFile.exists()) { + if ( aFile.exists() ) { // existing filesystem node if ( !aFile.isDirectory() ) { if ( aFile.openForWriting() ) { @@ -4720,8 +5119,9 @@ SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id) if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(id) ) { aResult->length( elem->NbNodes() ); - for ( int i = 0; i < elem->NbNodes(); ++i ) - aResult[ i ] = elem->GetNode( i )->GetID(); + for ( CORBA::ULong i = 0; i < aResult->length(); ++i ) + if ( const SMDS_MeshNode* n = elem->GetNode( i )) + aResult[ i ] = n->GetID(); } } return aResult._retn(); @@ -4837,7 +5237,7 @@ SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long elemId, { if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(elemId) ) { - SMDS_VolumeTool vtool( elem ); + SMDS_VolumeTool vtool( elem, /*skipCentralNodes = */false ); if ( faceIndex < vtool.NbFaces() ) { aResult->length( vtool.NbFaceNodes( faceIndex )); @@ -4851,7 +5251,7 @@ SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long elemId, } //======================================================================= -//function : GetElemFaceNodes +//function : GetFaceNormal //purpose : Returns three components of normal of given mesh face. //======================================================================= @@ -5148,7 +5548,7 @@ void SMESH_Mesh_i::CreateGroupServants() while ( groupIt->more() ) { ::SMESH_Group* group = groupIt->next(); - int anId = group->GetGroupDS()->GetID(); + int anId = group->GetID(); map::iterator it = _mapGroups.find(anId); if ( it != _mapGroups.end() && !CORBA::is_nil( it->second )) @@ -5866,19 +6266,23 @@ class SMESH_DimHyp 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; + return false; // check algorithms to be same - if ( !checkAlgo( this->GetAlgo(), theOther->GetAlgo() )) - return true; // different algorithms -> concurrency ! + const SMESH_Algo* a1 = this->GetAlgo(); + const SMESH_Algo* a2 = theOther->GetAlgo(); + bool isSame = checkAlgo( a1, a2 ); + if ( !isSame ) + { + if ( !a1 || !a2 ) + return false; // pb? + return a1->GetDim() == a2->GetDim(); // different algorithms of same dim -> concurrency ! + } // check hypothesises for concurrence (skip first as algorithm) - int nbSame = 0; + size_t nbSame = 0; // pointers should be same, because it is referened from mesh hypothesis partition list ::const_iterator hypIt = _hypotheses.begin(); list ::const_iterator otheEndIt = theOther->_hypotheses.end(); @@ -5886,7 +6290,7 @@ class SMESH_DimHyp if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt ) nbSame++; // the submeshes are concurrent if their algorithms has different parameters - return nbSame != (int)theOther->_hypotheses.size() - 1; + return nbSame != theOther->_hypotheses.size() - 1; } // Return true if algorithm of this SMESH_DimHyp is used if no @@ -6219,11 +6623,15 @@ TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes() aPythonDump << " ]"; subMeshOrder.push_back( subMeshIds ); - // clear collected submeshes + // clear collected sub-meshes set::iterator clrIt = subMeshToClear.begin(); for ( ; clrIt != subMeshToClear.end(); clrIt++ ) if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt ) + { sm->ComputeStateEngine( SMESH_subMesh::CLEAN ); + if ( SMESH_Algo* algo = sm->GetAlgo() ) // #16748 + sm->AlgoStateEngine( SMESH_subMesh::MODIF_HYP, algo ); // to clear a cached algo + } } aPythonDump << " ])"; @@ -6406,6 +6814,48 @@ const SMDS_MeshElement * SMESH_MeshPartDS::FindElement(int IDelem) const return 0; } // ------------------------------------------------------------------------------------- +bool SMESH_MeshPartDS::HasNumerationHoles() +{ + if ( _meshDS ) return _meshDS->HasNumerationHoles(); + + return ( MinNodeID() != 1 || + MaxNodeID() != NbNodes() || + MinElementID() != 1 || + MaxElementID() != NbElements() ); +} +// ------------------------------------------------------------------------------------- +int SMESH_MeshPartDS::MaxNodeID() const +{ + if ( _meshDS ) return _meshDS->MaxNodeID(); + return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].rbegin())->GetID(); +} +// ------------------------------------------------------------------------------------- +int SMESH_MeshPartDS::MinNodeID() const +{ + if ( _meshDS ) return _meshDS->MinNodeID(); + return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].begin())->GetID(); +} +// ------------------------------------------------------------------------------------- +int SMESH_MeshPartDS::MaxElementID() const +{ + if ( _meshDS ) return _meshDS->MaxElementID(); + int maxID = 0; + for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType ) + if ( !_elements[ iType ].empty() ) + maxID = Max( maxID, (*_elements[ iType ].rbegin())->GetID() ); + return maxID; +} +// ------------------------------------------------------------------------------------- +int SMESH_MeshPartDS::MinElementID() const +{ + if ( _meshDS ) return _meshDS->MinElementID(); + int minID = 0; + for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType ) + if ( !_elements[ iType ].empty() ) + minID = Min( minID, (*_elements[ iType ].begin())->GetID() ); + return minID; +} +// ------------------------------------------------------------------------------------- SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const { if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );