Salome HOME
Merge branch 'occ/shaper2smesh'
[modules/smesh.git] / src / SMESH_I / SMESH_Gen_i.cxx
index 7b403d9aabe014de939e7796469af2285351e8c5..ac0b696007a2f4329b6ecf2b404d421475d5c3e9 100644 (file)
@@ -157,7 +157,7 @@ static int MYDEBUG = 0;
 #endif
 
 // Static variables definition
-GEOM::GEOM_Gen_var      SMESH_Gen_i::myGeomGen = GEOM::GEOM_Gen::_nil();
+GEOM::GEOM_Gen_var      SMESH_Gen_i::myGeomGen;
 CORBA::ORB_var          SMESH_Gen_i::myOrb;
 PortableServer::POA_var SMESH_Gen_i::myPoa;
 SALOME_NamingService*   SMESH_Gen_i::myNS  = NULL;
@@ -258,14 +258,15 @@ SALOME_NamingService* SMESH_Gen_i::GetNS()
  *  Get SALOME_LifeCycleCORBA object
  */
 //=============================================================================
-SALOME_LifeCycleCORBA*  SMESH_Gen_i::GetLCC() {
+
+SALOME_LifeCycleCORBA*  SMESH_Gen_i::GetLCC()
+{
   if ( myLCC == NULL ) {
     myLCC = new SALOME_LifeCycleCORBA( GetNS() );
   }
   return myLCC;
 }
 
-
 //=============================================================================
 /*!
  *  GetGeomEngine [ static ]
@@ -273,18 +274,33 @@ SALOME_LifeCycleCORBA*  SMESH_Gen_i::GetLCC() {
  *  Get GEOM::GEOM_Gen reference
  */
 //=============================================================================
-GEOM::GEOM_Gen_var SMESH_Gen_i::GetGeomEngine() {
-  //CCRT GEOM::GEOM_Gen_var aGeomEngine =
-  //CCRT   GEOM::GEOM_Gen::_narrow( GetLCC()->FindOrLoad_Component("FactoryServer","GEOM") );
-  //CCRT return aGeomEngine._retn();
-  if(CORBA::is_nil(myGeomGen))
-  {
-    Engines::EngineComponent_ptr temp=GetLCC()->FindOrLoad_Component("FactoryServer","GEOM");
-    myGeomGen=GEOM::GEOM_Gen::_narrow(temp);
-  }
+
+GEOM::GEOM_Gen_var SMESH_Gen_i::GetGeomEngine( bool isShaper )
+{
+  Engines::EngineComponent_ptr temp =
+    GetLCC()->FindOrLoad_Component( isShaper ? "FactoryServer" : "FactoryServer",
+                                    isShaper ? "SHAPERSTUDY" : "GEOM" );
+  myGeomGen = GEOM::GEOM_Gen::_narrow( temp );
+
   return myGeomGen;
 }
 
+//=============================================================================
+/*!
+ *  GetGeomEngine [ static ]
+ *
+ *  Get GEOM::GEOM_Gen reference
+ */
+//=============================================================================
+
+GEOM::GEOM_Gen_var SMESH_Gen_i::GetGeomEngine( GEOM::GEOM_Object_ptr go )
+{
+  GEOM::GEOM_Gen_ptr gen;
+  if ( !CORBA::is_nil( go ))
+    gen = go->GetGen();
+  return gen;
+}
+
 //=============================================================================
 /*!
  *  SMESH_Gen_i::SMESH_Gen_i
@@ -687,11 +703,18 @@ void SMESH_Gen_i::UpdateStudy()
     myStudyContext = new StudyContext;
 
   SALOMEDS::Study_var aStudy = getStudyServant();
-  if ( !CORBA::is_nil( aStudy ) ) {
+  if ( !CORBA::is_nil( aStudy ) )
+  {
     SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
+
     SALOMEDS::SComponent_wrap GEOM_var = aStudy->FindComponent( "GEOM" );
     if( !GEOM_var->_is_nil() )
-      aStudyBuilder->LoadWith( GEOM_var, GetGeomEngine() );
+      aStudyBuilder->LoadWith( GEOM_var, GetGeomEngine( /*isShaper=*/false ) );
+
+    GEOM_var = aStudy->FindComponent( "SHAPERSTUDY" );
+    if( !GEOM_var->_is_nil() )
+      aStudyBuilder->LoadWith( GEOM_var, GetGeomEngine( /*isShaper=*/true ) );
+
     // NPAL16168, issue 0020210
     // Let meshes update their data depending on GEOM groups that could change
     CORBA::String_var compDataType = ComponentDataType();
@@ -708,6 +731,63 @@ void SMESH_Gen_i::UpdateStudy()
   }
 }
 
+//================================================================================
+/*!
+ * \brief Return true if mesh has ICON_SMESH_TREE_GEOM_MODIF icon
+ */
+//================================================================================
+
+bool SMESH_Gen_i::isGeomModifIcon( SMESH::SMESH_Mesh_ptr mesh )
+{
+  SALOMEDS::SObject_wrap so = ObjectToSObject( mesh );
+  SALOMEDS::GenericAttribute_wrap attr;
+  if ( ! so->_is_nil() && so->FindAttribute( attr.inout(), "AttributePixMap" ))
+  {
+    SALOMEDS::AttributePixMap_wrap pm = attr;
+    CORBA::String_var             ico = pm->GetPixMap();
+    return ( strcmp( ico.in(), "ICON_SMESH_TREE_GEOM_MODIF" ) == 0 );
+  }
+  return false;
+}
+
+//=================================================================================
+// function : hasObjectInfo()
+// purpose  : shows if module provides information for its objects
+//=================================================================================
+
+bool SMESH_Gen_i::hasObjectInfo()
+{
+  return true;
+}
+
+//=================================================================================
+// function : getObjectInfo()
+// purpose  : returns an information for a given object by its entry
+//=================================================================================
+
+char* SMESH_Gen_i::getObjectInfo( const char* entry )
+{
+  // for a mesh with icon == ICON_SMESH_TREE_GEOM_MODIF show a warning;
+  // for the rest, "module 'SMESH', ID=0:1:2:*"
+
+  SMESH_Comment txt;
+
+  SALOMEDS::SObject_wrap  so = getStudyServant()->FindObjectID( entry );
+  CORBA::Object_var      obj = SObjectToObject( so );
+  SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( obj );
+  if ( isGeomModifIcon( mesh ))
+  {
+    txt << "The geometry was changed and the mesh needs to be recomputed";
+  }
+
+  if ( txt.empty() )
+  {
+    CORBA::String_var compType = ComponentDataType();
+    txt << "module '" << compType << "', ID=" << entry;
+  }
+  return CORBA::string_dup( txt );
+}
+
 //=============================================================================
 /*!
  *  SMESH_Gen_i::GetStudyContext
@@ -749,6 +829,43 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypNam
   return hyp._retn();
 }
 
+//================================================================================
+/*!
+ * \brief Return a hypothesis initialized by given average length.
+ *  \param theHypType - hypothesis type name
+ *  \param theLibName - plugin library name
+ *  \param theAverageLength - average length
+ *  \param theQuadDominated - is quad-dominated flag
+ *  \retval SMESH::SMESH_Hypothesis_ptr - the new hypothesis
+ */
+//================================================================================
+
+SMESH::SMESH_Hypothesis_ptr
+SMESH_Gen_i::CreateHypothesisByAverageLength( const char*    theHypType,
+                                              const char*    theLibName,
+                                              CORBA::Double  theAverageLength,
+                                              CORBA::Boolean theQuadDominated)
+  throw ( SALOME::SALOME_Exception )
+{
+  SMESH::HypInitParams initParams = { ::SMESH_Hypothesis::BY_AVERAGE_LENGTH,
+                                      theAverageLength, theQuadDominated };
+
+  SMESH::SMESH_Hypothesis_var hyp =
+    GetHypothesisParameterValues( theHypType, theLibName,
+                                  SMESH::SMESH_Mesh::_nil(),
+                                  GEOM::GEOM_Object::_nil(),
+                                  initParams );
+  SALOMEDS::SObject_wrap so = PublishHypothesis( hyp );
+
+  TPythonDump() << hyp << " = " << this << ".CreateHypothesisByAverageLength( '"
+                << theHypType << "', '"
+                << theLibName << "', "
+                << theAverageLength << ", "
+                << theQuadDominated << " )";
+
+  return hyp._retn();
+}
+
 //================================================================================
 /*!
  * \brief Return a hypothesis holding parameter values corresponding either to the mesh
@@ -764,14 +881,16 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypNam
 //================================================================================
 
 SMESH::SMESH_Hypothesis_ptr
-SMESH_Gen_i::GetHypothesisParameterValues (const char*           theHypType,
-                                           const char*           theLibName,
-                                           SMESH::SMESH_Mesh_ptr theMesh,
-                                           GEOM::GEOM_Object_ptr theGeom,
-                                           CORBA::Boolean        byMesh)
+SMESH_Gen_i::GetHypothesisParameterValues( const char*                 theHypType,
+                                           const char*                 theLibName,
+                                           SMESH::SMESH_Mesh_ptr       theMesh,
+                                           GEOM::GEOM_Object_ptr       theGeom,
+                                           const SMESH::HypInitParams& theParams)
   throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
+
+  const bool byMesh = ( theParams.way == ::SMESH_Hypothesis::BY_MESH );
   if ( byMesh && CORBA::is_nil( theMesh ) )
     return SMESH::SMESH_Hypothesis::_nil();
   if ( byMesh && CORBA::is_nil( theGeom ) )
@@ -826,17 +945,24 @@ SMESH_Gen_i::GetHypothesisParameterValues (const char*           theHypType,
     if ( hyp->SetParametersByMesh( mesh, shape ))
       return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
   }
-  else {
-    double diagonal = 0;
-    if ( mesh )
-      diagonal = mesh->GetShapeDiagonalSize();
-    else
-      diagonal = ::SMESH_Mesh::GetShapeDiagonalSize( shape );
+  else
+  {
     ::SMESH_Hypothesis::TDefaults dflts;
-    dflts._elemLength = diagonal / myGen.GetBoundaryBoxSegmentation();
-    dflts._nbSegments = myGen.GetDefaultNbSegments();
-    dflts._shape      = &shape;
-    // let the temporary hypothesis initialize it's values
+    dflts._way           = ( ::SMESH_Hypothesis::InitWay) theParams.way;
+    dflts._nbSegments    = myGen.GetDefaultNbSegments();
+    dflts._elemLength    = theParams.averageLength;
+    dflts._quadDominated = theParams.quadDominated;
+    if ( theParams.way == ::SMESH_Hypothesis::BY_GEOM )
+    {
+      if ( mesh )
+        dflts._diagonal  = mesh->GetShapeDiagonalSize();
+      else
+        dflts._diagonal  = ::SMESH_Mesh::GetShapeDiagonalSize( shape );
+      dflts._elemLength  = dflts._diagonal / myGen.GetBoundaryBoxSegmentation();
+      dflts._shape       = &shape;
+    }
+
+    // let the hypothesis initialize it's values
     if ( hyp->SetParametersByDefaults( dflts, mesh ))
       return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
   }
@@ -1949,7 +2075,10 @@ CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
     SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
     ASSERT( meshServant );
     if ( meshServant ) {
-      meshServant->Load();
+      if ( isGeomModifIcon( theMesh ))
+        meshServant->Clear();
+      else
+        meshServant->Load();
       // NPAL16168: "geometrical group edition from a submesh don't modify mesh computation"
       meshServant->CheckGeomModif();
       // get local TopoDS_Shape
@@ -2305,7 +2434,7 @@ SMESH_Gen_i::GetGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
   GEOM::GEOM_Object_wrap geom = FindGeometryByMeshElement(theMesh, theElementID);
   if ( !geom->_is_nil() ) {
     GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh();
-    GEOM::GEOM_Gen_ptr    geomGen   = GetGeomEngine();
+    GEOM::GEOM_Gen_var    geomGen   = GetGeomEngine( geom );
 
     // try to find the corresponding SObject
     SALOMEDS::SObject_wrap SObj = ObjectToSObject( geom.in() );
@@ -2336,7 +2465,7 @@ SMESH_Gen_i::GetGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
         }
       }
     }
-    if ( SObj->_is_nil() ) // publish a new subshape
+    if ( SObj->_is_nil() && !geomGen->_is_nil() ) // publish a new subshape
       SObj = geomGen->AddInStudy( geom, theGeomName, mainShape );
 
     // return only published geometry
@@ -2369,7 +2498,7 @@ SMESH_Gen_i::FindGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", SALOME::BAD_PARAM );
 
   GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh();
-  GEOM::GEOM_Gen_ptr    geomGen   = GetGeomEngine();
+  GEOM::GEOM_Gen_var    geomGen   = GetGeomEngine( mainShape );
 
   // get a core mesh DS
   SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
@@ -2392,7 +2521,7 @@ SMESH_Gen_i::FindGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
           }
           if ( !it->_is_nil() ) {
             for ( it->InitEx(true); it->More(); it->Next() ) {
-              SALOMEDS::SObject_wrap      so = it->Value();
+              SALOMEDS::SObject_wrap     so = it->Value();
               CORBA::Object_var         obj = SObjectToObject( so );
               GEOM::GEOM_Object_var subGeom = GEOM::GEOM_Object::_narrow( obj );
               if ( !subGeom->_is_nil() ) {
@@ -2542,7 +2671,7 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
       continue;
     initImpl->Load();
 
-    // assure that IDs increments by one during iteration
+    // assure that IDs increment by one during iteration
     ::SMESH_Mesh& initLocMesh = initImpl->GetImpl();
     SMESHDS_Mesh*  initMeshDS = initLocMesh.GetMeshDS();
     if ( initMeshDS->MaxNodeID()    > initMeshDS->NbNodes() ||
@@ -2567,6 +2696,9 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
 
     // copy elements
 
+    SMESH::array_of_ElementType_var srcElemTypes = theMeshesArray[i]->GetTypes();
+    if ( srcElemTypes->length() == 1 && srcElemTypes[0] == SMESH::NODE ) // group of nodes
+      continue;
     std::vector< const SMDS_MeshElement* > newElems( initMeshDS->NbElements() + 1, 0 );
     elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::ALL );
     while ( elemIt->more() )
@@ -2986,7 +3118,8 @@ namespace // utils for CopyMeshWithGeom()
 {
   typedef std::map< std::string, std::string >             TStr2StrMap;
   typedef std::map< std::string, std::set< std::string > > TStr2StrSetMap;
-  //typedef std::map< std::set<int>, int >                   TIdSet2IndexMap;
+  typedef std::map< std::set<int>, int >                   TIdSet2IndexMap;
+  typedef std::map< std::string, int >                     TName2IndexMap;
 
   //================================================================================
   /*!
@@ -3004,8 +3137,9 @@ namespace // utils for CopyMeshWithGeom()
 
     TStr2StrMap   myOld2NewEntryMap; // map of study entries
 
-    //GEOM::ListOfGO_var         mySubshapes; // sub-shapes existing in the new geometry
-    //TIdSet2IndexMap            myIds2SubshapeIndex; // to find an existing sub-shape
+    GEOM::ListOfGO_var         mySubshapes; // sub-shapes existing in the new geometry
+    TIdSet2IndexMap            myIds2SubshapeIndex; // to find an existing sub-shape
+    TName2IndexMap             myName2SubshapeIndex; // to find an existing sub-shape by name
 
     bool                       myGIPMapDone;
     GEOM::ListOfListOfLong_var myGIPMap; // filled by GetInPlaceMap()
@@ -3044,16 +3178,18 @@ namespace // utils for CopyMeshWithGeom()
       CORBA::String_var newEntry = newSO->GetID();
       myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ),
                                                 std::string( newEntry.in() )));
+      std::string  newMainEntry = newEntry.in();
 
       SALOMEDS::Study_var            study = myGen_i->getStudyServant();
-      GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine();
+      GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine( mainShapeNew );
       GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
-      GEOM::ListOfGO_var         subShapes = op->GetExistingSubObjects( mainShapeNew,
+      mySubshapes                          = op->GetExistingSubObjects( mainShapeNew,
                                                                         /*groupsOnly=*/false );
-      for ( CORBA::ULong i = 0; i < subShapes->length(); ++i )
+      for ( CORBA::ULong i = 0; i < mySubshapes->length(); ++i )
       {
-        newSO = myGen_i->ObjectToSObject( subShapes[ i ]);
+        newSO = myGen_i->ObjectToSObject( mySubshapes[ i ]);
         SALOMEDS::ChildIterator_wrap anIter = study->NewChildIterator( newSO );
+        bool refFound = false;
         for ( ; anIter->More(); anIter->Next() )
         {
           SALOMEDS::SObject_wrap so = anIter->Value();
@@ -3061,8 +3197,22 @@ namespace // utils for CopyMeshWithGeom()
           {
             oldEntry = oldSO->GetID();
             newEntry = newSO->GetID();
-            myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ),
-                                                      std::string( newEntry.in() )));
+            if (( refFound = ( newMainEntry != oldEntry.in() )))
+              myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ),
+                                                        std::string( newEntry.in() )));
+          }
+        }
+        if ( !refFound )
+        {
+          GEOM::GEOM_Object_var father = mySubshapes[ i ]->GetMainShape();
+          if ( father->_is_equivalent( mainShapeNew ))
+          {
+            GEOM::ListOfLong_var ids = mySubshapes[ i ]->GetSubShapeIndices();
+            std::set< int > idSet( &ids[0] , &ids[0] + ids->length() );
+            myIds2SubshapeIndex.insert( std::make_pair( idSet, i ));
+            CORBA::String_var name = newSO->GetName();
+            if ( name.in()[0] )
+              myName2SubshapeIndex.insert( std::make_pair( name.in(), i ));
           }
         }
       }
@@ -3086,9 +3236,9 @@ namespace // utils for CopyMeshWithGeom()
         return GEOM::GEOM_Object::_duplicate( oldShape ); // shape independent of the old shape
 
       GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh();
-      GEOM::GEOM_Gen_var         geomGen = myGen_i->GetGeomEngine();
+      GEOM::GEOM_Gen_var         geomGen = myGen_i->GetGeomEngine( mainShapeNew );
 
-      // try to find by entry
+      // try to find by entry or name
       if ( myToPublish )
       {
         CORBA::String_var  oldEntry = oldShape->GetStudyEntry();
@@ -3097,6 +3247,22 @@ namespace // utils for CopyMeshWithGeom()
         {
           newShape = getShapeByEntry( o2nID->second );
         }
+        if ( newShape->_is_nil() )
+        {
+          CORBA::String_var name = oldShape->GetName();
+          TName2IndexMap::iterator n2ind = myName2SubshapeIndex.find( name.in() );
+          if ( n2ind != myName2SubshapeIndex.end() )
+          {
+            newShape = GEOM::GEOM_Object::_duplicate( mySubshapes[ n2ind->second ]);
+            GEOM::ListOfLong_var oldIndices = oldShape->GetSubShapeIndices();
+            GEOM::ListOfLong_var newIndices = newShape->GetSubShapeIndices();
+            if ( oldIndices->length() == 0 ||
+                 newIndices->length() == 0 ||
+                 getShapeType( myNewMesh_i, newIndices[0] ) !=
+                 getShapeType( mySrcMesh_i, oldIndices[0] ))
+              newShape = GEOM::GEOM_Object::_nil();
+          }
+        }
       }
 
       if ( newShape->_is_nil() )
@@ -3114,32 +3280,40 @@ namespace // utils for CopyMeshWithGeom()
           newIndices.clear();
           newShape = getInPlace( oldShape );
         }
-        if ( !newIndices.empty() )
+        if ( !newIndices.empty() && newShape->_is_nil() )
         {
-          try
-          {
-            if ( newIndices.size() > 1 || oldShape->GetType() == GEOM_GROUP )
+          // search for a sub-shape with same ids
+          std::set< int > idSet( newIndices.begin(), newIndices.end() );
+          TIdSet2IndexMap::iterator ids2ind = myIds2SubshapeIndex.find( idSet );
+          if ( ids2ind != myIds2SubshapeIndex.end() ) {
+            newShape = GEOM::GEOM_Object::_duplicate( mySubshapes[ ids2ind->second ]);
+          }
+          if ( newShape->_is_nil() )
+            try
             {
-              int groupType = getShapeType( myNewMesh_i, newIndices[0] );
+              // create a new shape
+              if ( newIndices.size() > 1 || oldShape->GetType() == GEOM_GROUP )
+              {
+                int groupType = getShapeType( myNewMesh_i, newIndices[0] );
 
-              GEOM::GEOM_IGroupOperations_wrap grOp = geomGen->GetIGroupOperations();
-              newShape = grOp->CreateGroup( mainShapeNew, groupType );
+                GEOM::GEOM_IGroupOperations_ptr grOp = geomGen->GetIGroupOperations();
+                newShape = grOp->CreateGroup( mainShapeNew, groupType );
 
-              GEOM::ListOfLong_var  newIndicesList = new GEOM::ListOfLong();
-              newIndicesList->length( newIndices.size() );
-              for ( size_t i = 0; i < newIndices.size(); ++i )
-                newIndicesList[ i ] = newIndices[ i ];
-              grOp->UnionIDs( newShape, newIndicesList );
+                GEOM::ListOfLong_var  newIndicesList = new GEOM::ListOfLong();
+                newIndicesList->length( newIndices.size() );
+                for ( size_t i = 0; i < newIndices.size(); ++i )
+                  newIndicesList[ i ] = newIndices[ i ];
+                grOp->UnionIDs( newShape, newIndicesList );
+              }
+              else
+              {
+                GEOM::GEOM_IShapesOperations_wrap shOp = geomGen->GetIShapesOperations();
+                newShape = shOp->GetSubShape( mainShapeNew, newIndices[0] );
+              }
             }
-            else
+            catch (...)
             {
-              GEOM::GEOM_IShapesOperations_wrap shOp = geomGen->GetIShapesOperations();
-              newShape = shOp->GetSubShape( mainShapeNew, newIndices[0] );
             }
-          }
-          catch (...)
-          {
-          }
         }
       }
 
@@ -3284,7 +3458,7 @@ namespace // utils for CopyMeshWithGeom()
 
         GEOM::GEOM_Object_var   mainShapeNew = myNewMesh_i->GetShapeToMesh();
         GEOM::GEOM_Object_var   mainShapeOld = mySrcMesh_i->GetShapeToMesh();
-        GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine();
+        GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine( mainShapeNew );
         GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
         try
         {
@@ -3306,7 +3480,7 @@ namespace // utils for CopyMeshWithGeom()
       GEOM::GEOM_Object_var newShape;
 
       GEOM::GEOM_Object_var   mainShapeNew = myNewMesh_i->GetShapeToMesh();
-      GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine();
+      GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine( mainShapeNew );
       GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
       try
       {
@@ -3989,6 +4163,9 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                                       const char*              theURL,
                                       bool                     isMultiFile )
 {
+  // localizing
+  Kernel_Utils::Localizer loc;
+
   if (!myStudyContext)
     UpdateStudy();
 
@@ -4298,6 +4475,14 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
             aDataset->WriteOnDisk( &meshPersistentId );
             aDataset->CloseOnDisk();
 
+            // Store SMESH_Mesh_i::_mainShapeTick
+            int shapeTick = myImpl->MainShapeTick();
+            aSize[ 0 ] = 1;
+            aDataset = new HDFdataset( "shapeTick", aTopGroup, HDF_INT32, aSize, 1 );
+            aDataset->CreateOnDisk();
+            aDataset->WriteOnDisk( &shapeTick );
+            aDataset->CloseOnDisk();
+
             // write reference on a shape if exists
             SALOMEDS::SObject_wrap myRef;
             bool shapeRefFound = false;
@@ -4973,23 +5158,6 @@ SALOMEDS::TMPFile* SMESH_Gen_i::SaveASCII( SALOMEDS::SComponent_ptr theComponent
   return anAsciiStreamFile._retn();
 }
 
-//=============================================================================
-/*!
- *  SMESH_Gen_i::loadGeomData
- *
- *  Load GEOM module data
- */
-//=============================================================================
-
-void SMESH_Gen_i::loadGeomData( SALOMEDS::SComponent_ptr theCompRoot )
-{
-  if ( theCompRoot->_is_nil() )
-    return;
-
-  SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
-  aStudyBuilder->LoadWith( theCompRoot, GetGeomEngine() );
-}
-
 //=============================================================================
 /*!
  *  SMESH_Gen_i::Load
@@ -5003,14 +5171,10 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                         const char*              theURL,
                         bool                     isMultiFile )
 {
-  //if (!myStudyContext)
-    UpdateStudy();
+  UpdateStudy(); // load geom data
+  Kernel_Utils::Localizer loc;
+
   SALOMEDS::Study_var aStudy = getStudyServant();
-  /*  if( !theComponent->_is_nil() )
-      {
-      if( !aStudy->FindComponent( "GEOM" )->_is_nil() )
-      loadGeomData( aStudy->FindComponent( "GEOM" ) );
-      }*/
 
   // Get temporary files location
   TCollection_AsciiString tmpDir =
@@ -5332,11 +5496,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
             aDataset->CloseOnDisk();
             if ( strlen( refFromFile ) > 0 ) {
               SALOMEDS::SObject_wrap shapeSO = aStudy->FindObjectID( refFromFile );
-
-              // Make sure GEOM data are loaded first
-              //loadGeomData( shapeSO->GetFatherComponent() );
-
-              CORBA::Object_var shapeObject = SObjectToObject( shapeSO );
+              CORBA::Object_var  shapeObject = SObjectToObject( shapeSO );
               if ( !CORBA::is_nil( shapeObject ) ) {
                 aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
                 if ( !aShapeObject->_is_nil() )
@@ -5347,7 +5507,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
           }
 
           // issue 20918. Restore Persistent Id of SMESHDS_Mesh
-          if( aTopGroup->ExistInternalObject( "meshPersistentId" ) )
+          if ( aTopGroup->ExistInternalObject( "meshPersistentId" ) )
           {
             aDataset = new HDFdataset( "meshPersistentId", aTopGroup );
             aDataset->OpenOnDisk();
@@ -5359,6 +5519,16 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
             delete [] meshPersistentId;
           }
 
+          // Restore SMESH_Mesh_i::_mainShapeTick
+          if ( aTopGroup->ExistInternalObject( "shapeTick" ))
+          {
+            aDataset = new HDFdataset( "shapeTick", aTopGroup );
+            aDataset->OpenOnDisk();
+            int* shapeTick = & myNewMeshImpl->MainShapeTick();
+            aDataset->ReadFromDisk( shapeTick );
+            aDataset->CloseOnDisk();
+          }
+
           // Restore file info
           if ( aTopGroup->ExistInternalObject( "file info" ))
           {