Salome HOME
fix SHAPERSTUDY bugs
[modules/smesh.git] / src / SMESH_I / SMESH_Mesh_i.cxx
index aa25d7d07ad1551bb8ccc519d24a3cd2f06dae0f..7789606dd65bbdba49fdfb07e945935d1362c750 100644 (file)
@@ -270,6 +270,16 @@ void SMESH_Mesh_i::ReplaceShape(GEOM::GEOM_Object_ptr theNewGeom)
   if (geomClient->Find(S, aIOR)) {
     geomClient->RemoveShapeFromBuffer(aIOR);
   }
+  // clear buffer also for sub-groups
+  const std::set<SMESHDS_GroupBase*>& groups = _impl->GetMeshDS()->GetGroups();
+  std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
+  for (; g != groups.end(); ++g)
+    if (const SMESHDS_GroupOnGeom* group = dynamic_cast<SMESHDS_GroupOnGeom*>(*g))
+    {
+      const TopoDS_Shape& s = group->GetShape();
+      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();
@@ -2076,59 +2086,69 @@ enum { ONLY_IF_CHANGED, IS_BREAK_LINK, MAIN_TRANSFORMED };
 TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData, int how )
 {
   TopoDS_Shape newShape;
+  SALOMEDS::SObject_wrap groupSO;
 
   if ( how == IS_BREAK_LINK )
   {
     SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( groupData._smeshObject );
-    SALOMEDS::SObject_wrap geomRefSO, geomSO;
+    SALOMEDS::SObject_wrap geomRefSO;
     if ( !meshSO->_is_nil() &&
-         meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
-         geomRefSO->ReferencedObject( geomSO.inout() ))
+         meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.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();
+      geomRefSO->ReferencedObject( groupSO.inout() );
     }
   }
   else
   {
     // get geom group
-    SALOMEDS::SObject_wrap groupSO = SMESH_Gen_i::getStudyServant()->FindObjectID( groupData._groupEntry.c_str() );
-    if ( !groupSO->_is_nil() )
+    groupSO = _gen_i->getStudyServant()->FindObjectID( groupData._groupEntry.c_str() );
+  }
+
+  if ( groupSO->_is_nil() )
+    return newShape;
+
+  CORBA::Object_var      groupObj = _gen_i->SObjectToObject( groupSO );
+  GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj );
+  if ( geomGroup->_is_nil() )
+    return newShape;
+
+  // get indices of group items
+  set<int> curIndices;
+  GEOM::GEOM_Gen_var               geomGen = _gen_i->GetGeomEngine( geomGroup );
+  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] );
+
+  bool sameIndices = ( groupData._indices == curIndices );
+  if ( how == ONLY_IF_CHANGED && sameIndices )
+    return newShape; // group not changed
+
+  newShape = _gen_i->GeomObjectToShape( geomGroup );
+
+  if ( !newShape.IsNull() && ids->length() > 0 )
+  {
+    if ( !sameIndices || !_impl->GetMeshDS()->IsGroupOfSubShapes( newShape ))
     {
-      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<int> curIndices;
-      GEOM::GEOM_Gen_var               geomGen = _gen_i->GetGeomEngine( geomGroup );
-      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 ( 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;
+      GEOM_Client*    geomClient = _gen_i->GetShapeReader();
       CORBA::String_var groupIOR = geomGen->GetStringFromIOR( geomGroup );
       geomClient->RemoveShapeFromBuffer( groupIOR.in() );
       newShape = _gen_i->GeomObjectToShape( geomGroup );
     }
   }
-  if ( newShape.IsNull() ) {
+  else
+  {
     // geom group becomes empty - return empty compound
     TopoDS_Compound compound;
     BRep_Builder().MakeCompound(compound);
     newShape = compound;
   }
+
+  // update data
+  CORBA::String_var entry = geomGroup->GetStudyEntry();
+  groupData._groupEntry = entry.in();
+  groupData._indices = curIndices;
+
   return newShape;
 }
 
@@ -2318,7 +2338,7 @@ void SMESH_Mesh_i::CheckGeomModif( bool isBreakLink )
 
   SMESHDS_Mesh * meshDS = _impl->GetMeshDS();
 
-  // store data of groups on geometry
+  // store data of groups on geometry including new TopoDS_Shape's
   std::vector< TGroupOnGeomData > groupsData;
   const std::set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
   groupsData.reserve( groups.size() );
@@ -2356,17 +2376,22 @@ void SMESH_Mesh_i::CheckGeomModif( bool isBreakLink )
           geom = gog->GetShape();
         }
       }
-      if ( !geom->_is_nil() )
+      if ( old2newShapeMap.IsBound( group->GetShape() ))
       {
-        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 );
+        groupsData.back()._shape = old2newShapeMap( group->GetShape() );
       }
-      else if ( old2newShapeMap.IsBound( group->GetShape() ))
+      else if ( !geom->_is_nil() )
       {
-        groupsData.back()._shape = old2newShapeMap( group->GetShape() );
+        groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
+        if ( meshDS->ShapeToIndex( groupsData.back()._shape ) > 0 )
+        {
+          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 );
       }
+      
     }
   }
   // store assigned hypotheses
@@ -2379,7 +2404,7 @@ 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
+  std::multimap< 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();
@@ -2413,19 +2438,43 @@ void SMESH_Mesh_i::CheckGeomModif( bool isBreakLink )
   }
 
   // re-add shapes (compounds) of geom groups
+  typedef std::map< std::vector< int >, TGeomGroupData* > TIndices2GroupData;
+  TIndices2GroupData ii2grData;
+  std::vector< int > ii;
   std::map< int, int > old2newIDs; // group IDs
-  std::list<TGeomGroupData>::iterator data = _geomGroupData.begin();
-  for ( ; data != _geomGroupData.end(); ++data )
+  std::list<TGeomGroupData>::iterator dataIt = _geomGroupData.begin();
+  for ( ; dataIt != _geomGroupData.end(); ++dataIt )
   {
+    TGeomGroupData* data = &(*dataIt);
+    ii.reserve( data->_indices.size() );
+    ii.assign( data->_indices.begin(), data->_indices.end() );
+    TIndices2GroupData::iterator ii2gd = ii2grData.insert( std::make_pair( ii, data )).first;
+    if ( ii2gd->second != data )
+    {
+      data->_groupEntry = ii2gd->second->_groupEntry;
+      data->_indices    = ii2gd->second->_indices;
+      continue;
+    }
+    const int  oldNbSub = data->_indices.size();
+    const int soleOldID = oldNbSub == 1 ? *data->_indices.begin() : 0;
     int oldID = 0;
-    std::map< std::set<int>, int >::iterator ii2i = ii2iMap.find( data->_indices );
+    std::multimap< std::set<int>, int >::iterator ii2i = ii2iMap.find( data->_indices );
     if ( ii2i != ii2iMap.end() )
+    {
       oldID = ii2i->second;
+      ii2iMap.erase( ii2i );
+    }
+    if ( !oldID && oldNbSub == 1 )
+      oldID = soleOldID;
+    if ( old2newIDs.count( oldID ))
+      continue;
+
+    int how = ( isBreakLink || !sameTopology ) ? IS_BREAK_LINK : MAIN_TRANSFORMED;
+    newShape = newGroupShape( *data, how );
 
-    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
+      if ( oldNbSub > 1 && meshDS->ShapeToIndex( newShape ) > 0 ) // group reduced to one sub-shape
       {
         TopoDS_Compound compound;
         BRep_Builder().MakeCompound( compound );
@@ -2433,33 +2482,31 @@ void SMESH_Mesh_i::CheckGeomModif( bool isBreakLink )
         newShape = compound;
       }
       int newID = _impl->GetSubMesh( newShape )->GetId();
-      if ( oldID && oldID != newID )
+      if ( oldID /*&& oldID != newID*/ )
         old2newIDs.insert( std::make_pair( oldID, newID ));
+      if ( oldNbSub == 1 )
+        old2newIDs.insert( std::make_pair( soleOldID, newID ));
     }
   }
 
   // re-assign hypotheses
   for ( size_t i = 0; i < ids2Hyps.size(); ++i )
   {
-    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;
+    else if ( !sameTopology && sID != 1 )
+      continue;
     const TopoDS_Shape& s = meshDS->IndexToShape( sID );
-    const THypList&  hyps = ids2Hyps[i].second;
+    if ( s.IsNull() )
+      continue;
+    const THypList& hyps = ids2Hyps[i].second;
     THypList::const_iterator h = hyps.begin();
     for ( ; h != hyps.end(); ++h )
       _impl->AddHypothesis( s, (*h)->GetID() );
   }
 
-  if ( !sameTopology )
-  {
-    // remove invalid study sub-objects
-    CheckGeomGroupModif();
-  }
-  else
   {
     // restore groups on geometry
     for ( size_t i = 0; i < groupsData.size(); ++i )
@@ -2481,23 +2528,26 @@ 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 )
+    if ( !sameTopology )
     {
-      int newID = o2n->second, oldID = o2n->first;
-      if ( !_mapSubMesh.count( oldID ))
-        continue;
-      if ( newID > 0 )
+      std::map< int, int >::iterator o2n = old2newIDs.begin();
+      for ( ; o2n != old2newIDs.end(); ++o2n )
       {
-        _mapSubMesh   [ newID ] = _impl->GetSubMeshContaining( newID );
-        _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
-        _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
+        int newID = o2n->second, oldID = o2n->first;
+        if ( newID == oldID || !_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 );
       }
-      _mapSubMesh.   erase(oldID);
-      _mapSubMesh_i. erase(oldID);
-      _mapSubMeshIor.erase(oldID);
-      if ( newID > 0 )
-        _mapSubMesh_i [ newID ]->changeLocalId( newID );
     }
 
     // update _mapSubMesh
@@ -2506,6 +2556,12 @@ void SMESH_Mesh_i::CheckGeomModif( bool isBreakLink )
       i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first ));
   }
 
+  if ( !sameTopology )
+  {
+    // remove invalid study sub-objects
+    CheckGeomGroupModif();
+  }
+
   _gen_i->UpdateIcons( me );
 
   if ( !isBreakLink && isShaper )
@@ -2584,13 +2640,18 @@ void SMESH_Mesh_i::CheckGeomGroupModif()
   {
     SMESH::SMESH_GroupBase_ptr group = i_gr->second;
     ++i_gr;
-    SALOMEDS::SObject_wrap        groupSO = _gen_i->ObjectToSObject( group ), refSO;
+    SALOMEDS::SObject_wrap        groupSO = _gen_i->ObjectToSObject( group ), refSO, geomSO;
     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() );
+      isValidGeom = ( ! GEOM::GEOM_Object_var( onGeom->GetShape() )->_is_nil() &&
+                      ! groupSO->_is_nil() &&
+                      groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ) &&
+                      refSO->ReferencedObject( geomSO.inout() ) &&
+                      ! geomSO->_is_nil());
+      isValidGeom = ( isValidGeom && !CORBA::is_nil( CORBA::Object_var( geomSO->GetObject() )));
     }
     else if ( !onFilt->_is_nil() )
     {