Salome HOME
Fix exception at Break Link after shaper group modification
authoreap <eap@opencascade.com>
Fri, 24 Jan 2020 18:36:13 +0000 (21:36 +0300)
committereap <eap@opencascade.com>
Fri, 24 Jan 2020 18:36:13 +0000 (21:36 +0300)
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
src/SMESHGUI/SMESHGUI_GroupDlg.cxx
src/SMESH_I/SMESH_Mesh_i.cxx
src/SMESH_I/SMESH_subMesh_i.hxx

index 660838d..b5720d7 100644 (file)
@@ -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() );
index 62666c9..0da1190 100644 (file)
@@ -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()) {
index c65fc0e..8b2fe34 100644 (file)
@@ -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>, 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<int> 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<TGeomGroupData>::iterator data = _geomGroupData.begin();
   for ( ; data != _geomGroupData.end(); ++data )
   {
+    int oldID = 0;
+    std::map< std::set<int>, 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<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
     for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
index f782031..0af1deb 100644 (file)
@@ -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