From c4d4c3be32adf37c4ff99664205b4f15e1560674 Mon Sep 17 00:00:00 2001 From: eap Date: Fri, 24 Jan 2020 21:36:13 +0300 Subject: [PATCH] Fix exception at Break Link after shaper group modification Scenario: - Create a mesh on a box with sub-mesh on a group - Modify group in shaper - Switch to SMESH and Break Link ==> SIGSEGV --- src/SMESHGUI/SMESHGUI_ComputeDlg.cxx | 2 +- src/SMESHGUI/SMESHGUI_GroupDlg.cxx | 2 ++ src/SMESH_I/SMESH_Mesh_i.cxx | 41 +++++++++++++++++++++++++--- src/SMESH_I/SMESH_subMesh_i.hxx | 1 + 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx index 660838ddb..b5720d797 100644 --- a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx @@ -1280,7 +1280,7 @@ void SMESHGUI_BaseComputeOp::onPublishShape() // look for myMainShape in the table for ( int r = 0, nr = table()->rowCount(); r < nr; ++r ) { if ( table()->item( r, COL_SHAPEID )->text() == "1" ) { - if ( so->_is_nil() ) { + if ( !so->_is_nil() ) { CORBA::String_var name = so->GetName(); CORBA::String_var entry = so->GetID(); QString shapeText = QString("%1 (%2)").arg( name.in() ).arg( entry.in() ); diff --git a/src/SMESHGUI/SMESHGUI_GroupDlg.cxx b/src/SMESHGUI/SMESHGUI_GroupDlg.cxx index 62666c97f..0da119054 100644 --- a/src/SMESHGUI/SMESHGUI_GroupDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_GroupDlg.cxx @@ -1083,6 +1083,8 @@ bool SMESHGUI_GroupDlg::onApply() GEOM::GEOM_Object_var aMeshShape = myMesh->GetShapeToMesh(); GEOM::GEOM_Object_wrap aGroupVar = op->CreateGroup(aMeshShape, aGroupType); + if ( aGroupVar->_is_nil() ) + return false; op->UnionList(aGroupVar, myGeomObjects); if (op->IsDone()) { diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index c65fc0e25..8b2fe347f 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -2002,8 +2002,7 @@ void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj, return; // group indices GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( theGeomObj ); - GEOM::GEOM_IGroupOperations_ptr groupOp = - geomGen->GetIGroupOperations(); + GEOM::GEOM_IGroupOperations_ptr groupOp = geomGen->GetIGroupOperations(); GEOM::ListOfLong_var ids = groupOp->GetObjects( theGeomObj ); // store data @@ -2347,6 +2346,8 @@ void SMESH_Mesh_i::CheckGeomModif( bool isBreakLink ) ids2Hyps.push_back( make_pair( meshDS->ShapeToIndex( s ), hyps )); } + 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 ) @@ -2354,6 +2355,11 @@ void SMESH_Mesh_i::CheckGeomModif( bool isBreakLink ) 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 @@ -2374,9 +2380,15 @@ void SMESH_Mesh_i::CheckGeomModif( bool isBreakLink ) } // 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 ) { + 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() ) { @@ -2387,7 +2399,9 @@ void SMESH_Mesh_i::CheckGeomModif( bool isBreakLink ) 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 )); } } @@ -2396,7 +2410,11 @@ void SMESH_Mesh_i::CheckGeomModif( bool isBreakLink ) { if ( !sameTopology && ids2Hyps[i].first != 1 ) continue; // assign only global hypos - const TopoDS_Shape& s = meshDS->IndexToShape( ids2Hyps[i].first ); + 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 ) @@ -2430,6 +2448,21 @@ void SMESH_Mesh_i::CheckGeomModif( bool isBreakLink ) g->GetGroupDS()->SetColor( data._color ); } + std::map< int, int >::iterator o2n = old2newIDs.begin(); + for ( ; o2n != old2newIDs.end(); ++o2n ) + { + int newID = o2n->second, oldID = o2n->first; + if ( !_mapSubMesh.count( oldID )) + continue; + _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); + _mapSubMesh_i [ newID ]->changeLocalId( newID ); + } + // update _mapSubMesh std::map::iterator i_sm = _mapSubMesh.begin(); for ( ; i_sm != _mapSubMesh.end(); ++i_sm ) diff --git a/src/SMESH_I/SMESH_subMesh_i.hxx b/src/SMESH_I/SMESH_subMesh_i.hxx index f782031e6..0af1debff 100644 --- a/src/SMESH_I/SMESH_subMesh_i.hxx +++ b/src/SMESH_I/SMESH_subMesh_i.hxx @@ -123,6 +123,7 @@ protected: void changeLocalId(int localId) { _localId = localId; } friend void SMESH_Mesh_i::CheckGeomGroupModif(); + friend void SMESH_Mesh_i::CheckGeomModif(bool); SMESH_PreMeshInfo* _preMeshInfo; // mesh info before full loading from study file -- 2.39.2