Salome HOME
load mesh from study before Compute and PreCompute
[modules/smesh.git] / src / SMESH_I / SMESH_Gen_i.cxx
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : SMESH_Gen_i.cxx
23 //  Author : Paul RASCLE, EDF
24 //  Module : SMESH
25
26 #include <TopExp.hxx>
27 #include <TopExp_Explorer.hxx>
28 #include <TopoDS.hxx>
29 #include <TopoDS_Iterator.hxx>
30 #include <TopoDS_Compound.hxx>
31 #include <TopoDS_CompSolid.hxx>
32 #include <TopoDS_Solid.hxx>
33 #include <TopoDS_Shell.hxx>
34 #include <TopoDS_Face.hxx>
35 #include <TopoDS_Wire.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Vertex.hxx>
38 #include <TopoDS_Shape.hxx>
39 #include <TopTools_MapOfShape.hxx>
40 #include <TopTools_IndexedMapOfShape.hxx>
41 #include <TopTools_ListOfShape.hxx>
42 #include <TopTools_ListIteratorOfListOfShape.hxx>
43 #include <gp_Pnt.hxx>
44 #include <BRep_Tool.hxx>
45 #include <TCollection_AsciiString.hxx>
46 #include <OSD.hxx>
47
48 #include "Utils_CorbaException.hxx"
49
50 #include "utilities.h"
51 #include <fstream>
52 #include <stdio.h>
53
54 #ifdef WNT
55  #include <windows.h>
56  #include <process.h>
57 #else
58  #include <dlfcn.h>
59 #endif
60
61 #ifdef WNT
62  #define LibHandle HMODULE
63  #define LoadLib( name ) LoadLibrary( name )
64  #define GetProc GetProcAddress
65  #define UnLoadLib( handle ) FreeLibrary( handle );
66 #else
67  #define LibHandle void*
68  #define LoadLib( name ) dlopen( name, RTLD_LAZY )
69  #define GetProc dlsym
70  #define UnLoadLib( handle ) dlclose( handle );
71 #endif
72
73 #include <HDFOI.hxx>
74
75 #include "SMESH_Gen_i.hxx"
76 #include "SMESH_Mesh_i.hxx"
77 #include "SMESH_Hypothesis_i.hxx"
78 #include "SMESH_Algo_i.hxx"
79 #include "SMESH_Group_i.hxx"
80 #include "SMESH_PythonDump.hxx"
81 #include "SMESH_PreMeshInfo.hxx"
82
83 #include "SMESHDS_Document.hxx"
84 #include "SMESHDS_Group.hxx"
85 #include "SMESHDS_GroupOnGeom.hxx"
86 #include "SMESH_Mesh.hxx"
87 #include "SMESH_Hypothesis.hxx"
88 #include "SMESH_Group.hxx"
89 #include "SMESH_MeshEditor.hxx"
90
91 #include "SMDS_EdgePosition.hxx"
92 #include "SMDS_FacePosition.hxx"
93 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
94 #include "SMDS_SetIterator.hxx"
95 #include "SMDS_SpacePosition.hxx"
96 #include "SMDS_VertexPosition.hxx"
97
98 #include CORBA_SERVER_HEADER(SMESH_Group)
99 #include CORBA_SERVER_HEADER(SMESH_Filter)
100 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
101
102 #include "DriverMED_W_SMESHDS_Mesh.h"
103 #include "DriverMED_R_SMESHDS_Mesh.h"
104 #ifdef WITH_CGNS
105 #include "DriverCGNS_Read.hxx"
106 #endif
107
108 #include "SALOMEDS_Tool.hxx"
109 #include "SALOME_NamingService.hxx"
110 #include "SALOME_LifeCycleCORBA.hxx"
111 #include "Utils_SINGLETON.hxx"
112 #include "OpUtil.hxx"
113
114 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
115 #include CORBA_CLIENT_HEADER(SALOME_Session)
116
117 #include "GEOM_Client.hxx"
118 #include "Utils_ExceptHandlers.hxx"
119 #include "memoire.h"
120 #include "Basics_Utils.hxx"
121
122 #include <map>
123
124 using namespace std;
125 using SMESH::TPythonDump;
126
127 #define NUM_TMP_FILES 2
128
129 #ifdef _DEBUG_
130 static int MYDEBUG = 0;
131 #else
132 static int MYDEBUG = 0;
133 #endif
134
135 // Static variables definition
136 GEOM::GEOM_Gen_var      SMESH_Gen_i::myGeomGen = GEOM::GEOM_Gen::_nil();
137 CORBA::ORB_var          SMESH_Gen_i::myOrb;
138 PortableServer::POA_var SMESH_Gen_i::myPoa;
139 SALOME_NamingService*   SMESH_Gen_i::myNS  = NULL;
140 SALOME_LifeCycleCORBA*  SMESH_Gen_i::myLCC = NULL;
141 SMESH_Gen_i*            SMESH_Gen_i::mySMESHGen = NULL;
142
143
144 const int nbElemPerDiagonal = 10;
145
146 //=============================================================================
147 /*!
148  *  GetServant [ static ]
149  *
150  *  Get servant of the CORBA object
151  */
152 //=============================================================================
153
154 PortableServer::ServantBase_var SMESH_Gen_i::GetServant( CORBA::Object_ptr theObject )
155 {
156   if( CORBA::is_nil( theObject ) || CORBA::is_nil( GetPOA() ) )
157     return NULL;
158   try {
159     PortableServer::Servant aServant = GetPOA()->reference_to_servant( theObject );
160     return aServant;
161   }
162   catch (...) {
163     INFOS( "GetServant - Unknown exception was caught!!!" );
164     return NULL;
165   }
166 }
167
168 //=============================================================================
169 /*!
170  *  SObjectToObject [ static ]
171  *
172  *  Get CORBA object corresponding to the SALOMEDS::SObject
173  */
174 //=============================================================================
175
176 CORBA::Object_var SMESH_Gen_i::SObjectToObject( SALOMEDS::SObject_ptr theSObject )
177 {
178   SALOMEDS::GenericAttribute_var anAttr;
179   CORBA::Object_var anObj;
180   if ( !theSObject->_is_nil() ) {
181     try {
182       if( theSObject->FindAttribute( anAttr, "AttributeIOR" ) ) {
183         SALOMEDS::AttributeIOR_var anIOR  = SALOMEDS::AttributeIOR::_narrow( anAttr );
184         CORBA::String_var aValue = anIOR->Value();
185         if( strcmp( aValue, "" ) != 0 )
186           anObj = GetORB()->string_to_object( aValue );
187         }
188     }
189     catch( ... ) {
190       INFOS( "SObjectToObject - Unknown exception was caught!!!" );
191     }
192   }
193   return anObj;
194 }
195
196 //=============================================================================
197 /*!
198  *  GetNS [ static ]
199  *
200  *  Get SALOME_NamingService object
201  */
202 //=============================================================================
203
204 SALOME_NamingService* SMESH_Gen_i::GetNS()
205 {
206   if ( myNS == NULL ) {
207     myNS = SINGLETON_<SALOME_NamingService>::Instance();
208     ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting());
209     myNS->init_orb( GetORB() );
210   }
211   return myNS;
212 }
213
214 //=============================================================================
215 /*!
216  *  GetLCC [ static ]
217  *
218  *  Get SALOME_LifeCycleCORBA object
219  */
220 //=============================================================================
221 SALOME_LifeCycleCORBA*  SMESH_Gen_i::GetLCC() {
222   if ( myLCC == NULL ) {
223     myLCC = new SALOME_LifeCycleCORBA( GetNS() );
224   }
225   return myLCC;
226 }
227
228
229 //=============================================================================
230 /*!
231  *  GetGeomEngine [ static ]
232  *
233  *  Get GEOM::GEOM_Gen reference
234  */
235 //=============================================================================
236 GEOM::GEOM_Gen_ptr SMESH_Gen_i::GetGeomEngine() {
237   //CCRT GEOM::GEOM_Gen_var aGeomEngine =
238   //CCRT   GEOM::GEOM_Gen::_narrow( GetLCC()->FindOrLoad_Component("FactoryServer","GEOM") );
239   //CCRT return aGeomEngine._retn();
240   if(CORBA::is_nil(myGeomGen))
241   {
242     Engines::EngineComponent_ptr temp=GetLCC()->FindOrLoad_Component("FactoryServer","GEOM");
243     myGeomGen=GEOM::GEOM_Gen::_narrow(temp);
244   }
245   return myGeomGen;
246 }
247
248 //=============================================================================
249 /*!
250  *  SMESH_Gen_i::SMESH_Gen_i
251  *
252  *  Default constructor: not for use
253  */
254 //=============================================================================
255
256 SMESH_Gen_i::SMESH_Gen_i()
257 {
258   INFOS( "SMESH_Gen_i::SMESH_Gen_i : default constructor" );
259 }
260
261 //=============================================================================
262 /*!
263  *  SMESH_Gen_i::SMESH_Gen_i
264  *
265  *  Standard constructor, used with Container
266  */
267 //=============================================================================
268
269 SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr            orb,
270                           PortableServer::POA_ptr   poa,
271                           PortableServer::ObjectId* contId,
272                           const char*               instanceName,
273                           const char*               interfaceName )
274      : Engines_Component_i( orb, poa, contId, instanceName, interfaceName )
275 {
276   MESSAGE( "SMESH_Gen_i::SMESH_Gen_i : standard constructor" );
277
278   myOrb = CORBA::ORB::_duplicate(orb);
279   myPoa = PortableServer::POA::_duplicate(poa);
280
281   _thisObj = this ;
282   _id = myPoa->activate_object( _thisObj );
283
284   myIsEmbeddedMode = false;
285   myShapeReader = NULL;  // shape reader
286   mySMESHGen = this;
287   myIsHistoricalPythonDump = true;
288   myToForgetMeshDataOnHypModif = false;
289
290   // set it in standalone mode only
291   //OSD::SetSignal( true );
292
293   // 0020605: EDF 1190 SMESH: Display performance. 80 seconds for 52000 cells.
294   // find out mode (embedded or standalone) here else
295   // meshes created before calling SMESH_Client::GetSMESHGen(), which calls
296   // SMESH_Gen_i::SetEmbeddedMode(), have wrong IsEmbeddedMode flag
297   if ( SALOME_NamingService* ns = GetNS() )
298   {
299     CORBA::Object_var obj = ns->Resolve( "/Kernel/Session" );
300     SALOME::Session_var session = SALOME::Session::_narrow( obj ) ;
301     if ( !session->_is_nil() )
302     {
303       CORBA::String_var str_host = session->getHostname();
304       CORBA::Long        s_pid = session->getPID();
305       string my_host = Kernel_Utils::GetHostname();
306 #ifdef WNT
307       long    my_pid = (long)_getpid();
308 #else
309       long    my_pid = (long) getpid();
310 #endif
311       SetEmbeddedMode( s_pid == my_pid && my_host == str_host.in() );
312     }
313   }
314 }
315
316 //=============================================================================
317 /*!
318  *  SMESH_Gen_i::~SMESH_Gen_i
319  *
320  *  Destructor
321  */
322 //=============================================================================
323
324 SMESH_Gen_i::~SMESH_Gen_i()
325 {
326   MESSAGE( "SMESH_Gen_i::~SMESH_Gen_i" );
327
328   // delete hypothesis creators
329   map<string, GenericHypothesisCreator_i*>::iterator itHyp;
330   for (itHyp = myHypCreatorMap.begin(); itHyp != myHypCreatorMap.end(); itHyp++)
331   {
332     delete (*itHyp).second;
333   }
334   myHypCreatorMap.clear();
335
336   // Clear study contexts data
337   map<int, StudyContext*>::iterator it;
338   for ( it = myStudyContextMap.begin(); it != myStudyContextMap.end(); ++it ) {
339     delete it->second;
340   }
341   myStudyContextMap.clear();
342   // delete shape reader
343   if ( !myShapeReader )
344     delete myShapeReader;
345 }
346
347 //=============================================================================
348 /*!
349  *  SMESH_Gen_i::createHypothesis
350  *
351  *  Create hypothesis of given type
352  */
353 //=============================================================================
354 SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName,
355                                                           const char* theLibName)
356      throw (SALOME::SALOME_Exception)
357 {
358   /* It's Need to tranlate lib name for WIN32 or X platform */
359   char* aPlatformLibName = 0;
360   if ( theLibName && theLibName[0] != '\0'  )
361   {
362     int libNameLen = strlen(theLibName);
363     //check for old format "libXXXXXXX.so"
364     if (libNameLen > 7 &&
365         !strncmp( theLibName, "lib", 3 ) &&
366         !strcmp( theLibName+libNameLen-3, ".so" ))
367     {
368       //the old format
369 #ifdef WNT
370       aPlatformLibName = new char[libNameLen - 1];
371       aPlatformLibName[0] = '\0';
372       aPlatformLibName = strncat( aPlatformLibName, theLibName+3, libNameLen-6  );
373       aPlatformLibName = strcat( aPlatformLibName, ".dll" );
374       aPlatformLibName[libNameLen - 2] = '\0';
375 #else
376       aPlatformLibName = new char[ libNameLen + 1];
377       aPlatformLibName[0] = '\0';
378       aPlatformLibName = strcat( aPlatformLibName, theLibName );
379       aPlatformLibName[libNameLen] = '\0';
380 #endif
381     }
382     else
383     {
384       //try to use new format
385 #ifdef WNT
386       aPlatformLibName = new char[ libNameLen + 5 ];
387       aPlatformLibName[0] = '\0';
388       aPlatformLibName = strcat( aPlatformLibName, theLibName );
389       aPlatformLibName = strcat( aPlatformLibName, ".dll" );
390 #else
391       aPlatformLibName = new char[ libNameLen + 7 ];
392       aPlatformLibName[0] = '\0';
393       aPlatformLibName = strcat( aPlatformLibName, "lib" );
394       aPlatformLibName = strcat( aPlatformLibName, theLibName );
395       aPlatformLibName = strcat( aPlatformLibName, ".so" );
396 #endif
397     }
398   }
399
400
401   Unexpect aCatch(SALOME_SalomeException);
402   if(MYDEBUG) MESSAGE( "Create Hypothesis <" << theHypName << "> from " << aPlatformLibName/*theLibName*/);
403
404   // create a new hypothesis object servant
405   SMESH_Hypothesis_i* myHypothesis_i = 0;
406   SMESH::SMESH_Hypothesis_var hypothesis_i;
407
408   try
409   {
410     // check, if creator for this hypothesis type already exists
411     if (myHypCreatorMap.find(string(theHypName)) == myHypCreatorMap.end())
412     {
413       // load plugin library
414       if(MYDEBUG) MESSAGE("Loading server meshers plugin library ...");
415       LibHandle libHandle = LoadLib( aPlatformLibName/*theLibName*/ );
416       if (!libHandle)
417       {
418         // report any error, if occured
419 #ifndef WNT
420         const char* anError = dlerror();
421         throw(SALOME_Exception(anError));
422 #else
423         throw(SALOME_Exception(LOCALIZED( "Can't load server meshers plugin library" )));
424 #endif
425       }
426
427       // get method, returning hypothesis creator
428       if(MYDEBUG) MESSAGE("Find GetHypothesisCreator() method ...");
429       typedef GenericHypothesisCreator_i* (*GetHypothesisCreator)(const char* theHypName);
430       GetHypothesisCreator procHandle =
431         (GetHypothesisCreator)GetProc( libHandle, "GetHypothesisCreator" );
432       if (!procHandle)
433       {
434         throw(SALOME_Exception(LOCALIZED("bad hypothesis plugin library")));
435         UnLoadLib(libHandle);
436       }
437
438       // get hypothesis creator
439       if(MYDEBUG) MESSAGE("Get Hypothesis Creator for " << theHypName);
440       GenericHypothesisCreator_i* aCreator = procHandle(theHypName);
441       if (!aCreator)
442       {
443         throw(SALOME_Exception(LOCALIZED("no such a hypothesis in this plugin")));
444       }
445
446       // map hypothesis creator to a hypothesis name
447       myHypCreatorMap[string(theHypName)] = aCreator;
448     }
449
450     // create a new hypothesis object, store its ref. in studyContext
451     if(MYDEBUG) MESSAGE("Create Hypothesis " << theHypName);
452     myHypothesis_i =
453       myHypCreatorMap[string(theHypName)]->Create(myPoa, GetCurrentStudyID(), &myGen);
454     myHypothesis_i->SetLibName(aPlatformLibName/*theLibName*/); // for persistency assurance
455   }
456   catch (SALOME_Exception& S_ex)
457   {
458     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
459   }
460
461   if ( aPlatformLibName )
462     delete[] aPlatformLibName;
463
464   if (!myHypothesis_i)
465     return hypothesis_i._retn();
466
467   // activate the CORBA servant of hypothesis
468   hypothesis_i = SMESH::SMESH_Hypothesis::_narrow( myHypothesis_i->_this() );
469   int nextId = RegisterObject( hypothesis_i );
470   if(MYDEBUG) MESSAGE( "Add hypo to map with id = "<< nextId );
471
472   return hypothesis_i._retn();
473 }
474
475 //=============================================================================
476 /*!
477  *  SMESH_Gen_i::createMesh
478  *
479  *  Create empty mesh on shape
480  */
481 //=============================================================================
482 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh()
483      throw ( SALOME::SALOME_Exception )
484 {
485   Unexpect aCatch(SALOME_SalomeException);
486   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::createMesh" );
487
488   // Get or create the GEOM_Client instance
489   try {
490     // create a new mesh object servant, store it in a map in study context
491     SMESH_Mesh_i* meshServant = new SMESH_Mesh_i( GetPOA(), this, GetCurrentStudyID() );
492     // create a new mesh object
493     MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode);
494     meshServant->SetImpl( myGen.CreateMesh( GetCurrentStudyID(), myIsEmbeddedMode ));
495
496     // activate the CORBA servant of Mesh
497     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( meshServant->_this() );
498     int nextId = RegisterObject( mesh );
499     if(MYDEBUG) MESSAGE( "Add mesh to map with id = "<< nextId);
500     return mesh._retn();
501   }
502   catch (SALOME_Exception& S_ex) {
503     THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
504   }
505   return SMESH::SMESH_Mesh::_nil();
506 }
507
508 //=============================================================================
509 /*!
510  *  SMESH_Gen_i::GetShapeReader
511  *
512  *  Get shape reader
513  */
514 //=============================================================================
515 GEOM_Client* SMESH_Gen_i::GetShapeReader()
516 {
517   // create shape reader if necessary
518   if ( !myShapeReader )
519     myShapeReader = new GEOM_Client(GetContainerRef());
520   ASSERT( myShapeReader );
521   return myShapeReader;
522 }
523
524 //=============================================================================
525 /*!
526  *  SMESH_Gen_i::SetGeomEngine
527  *
528  *  Set GEOM::GEOM_Gen reference
529  */
530 //=============================================================================
531 //GEOM::GEOM_Gen_ptr SMESH_Gen_i::SetGeomEngine( const char* containerLoc )
532 void SMESH_Gen_i::SetGeomEngine( GEOM::GEOM_Gen_ptr geomcompo )
533 {
534   //Engines::Component_ptr temp=GetLCC()->FindOrLoad_Component(containerLoc,"GEOM");
535   //myGeomGen=GEOM::GEOM_Gen::_narrow(temp);
536   myGeomGen=GEOM::GEOM_Gen::_duplicate(geomcompo);
537   //return myGeomGen;
538 }
539
540 //=============================================================================
541 /*!
542  *  SMESH_Gen_i::SetEmbeddedMode
543  *
544  *  Set current mode
545  */
546 //=============================================================================
547
548 void SMESH_Gen_i::SetEmbeddedMode( CORBA::Boolean theMode )
549 {
550   myIsEmbeddedMode = theMode;
551   MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode);
552
553   if ( !myIsEmbeddedMode ) {
554     //PAL10867: disable signals catching with "noexcepthandler" option
555     char* envNoCatchSignals = getenv("NOT_INTERCEPT_SIGNALS");
556     if (!envNoCatchSignals || !atoi(envNoCatchSignals))
557     {
558       bool raiseFPE;
559 #ifdef _DEBUG_
560       raiseFPE = true;
561       char* envDisableFPE = getenv("DISABLE_FPE");
562       if (envDisableFPE && atoi(envDisableFPE))
563         raiseFPE = false;
564 #else
565       raiseFPE = false;
566 #endif
567       OSD::SetSignal( raiseFPE );
568     }
569     // else OSD::SetSignal() is called in GUI
570   }
571 }
572
573 //=============================================================================
574 /*!
575  *  SMESH_Gen_i::IsEmbeddedMode
576  *
577  *  Get current mode
578  */
579 //=============================================================================
580
581 CORBA::Boolean SMESH_Gen_i::IsEmbeddedMode()
582 {
583   return myIsEmbeddedMode;
584 }
585
586 //=============================================================================
587 /*!
588  *  SMESH_Gen_i::SetCurrentStudy
589  *
590  *  Set current study
591  */
592 //=============================================================================
593
594 void SMESH_Gen_i::SetCurrentStudy( SALOMEDS::Study_ptr theStudy )
595 {
596   int curStudyId = GetCurrentStudyID();
597   myCurrentStudy = SALOMEDS::Study::_duplicate( theStudy );
598   // create study context, if it doesn't exist and set current study
599   int studyId = GetCurrentStudyID();
600   if ( myStudyContextMap.find( studyId ) == myStudyContextMap.end() ) {
601     myStudyContextMap[ studyId ] = new StudyContext;
602   }
603
604   // myCurrentStudy may be nil
605   if ( !CORBA::is_nil( myCurrentStudy ) ) {
606     SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
607     if( !myCurrentStudy->FindComponent( "GEOM" )->_is_nil() )
608       aStudyBuilder->LoadWith( myCurrentStudy->FindComponent( "GEOM" ), GetGeomEngine() );
609
610     // NPAL16168, issue 0020210
611     // Let meshes update their data depending on GEOM groups that could change
612     if ( curStudyId != studyId )
613     {
614       //SALOMEDS::SComponent_var me =  PublishComponent( myCurrentStudy );
615       SALOMEDS::SComponent_var me = SALOMEDS::SComponent::_narrow
616         ( myCurrentStudy->FindComponent( ComponentDataType() ) );
617       if ( !me->_is_nil() ) {
618         SALOMEDS::ChildIterator_var anIter = myCurrentStudy->NewChildIterator( me );
619         for ( ; anIter->More(); anIter->Next() ) {
620           SALOMEDS::SObject_var so = anIter->Value();
621           CORBA::Object_var    ior = SObjectToObject( so );
622           if ( SMESH_Mesh_i*  mesh = SMESH::DownCast<SMESH_Mesh_i*>( ior ))
623             mesh->CheckGeomGroupModif();
624         }
625       }
626     }
627   }
628 }
629
630 //=============================================================================
631 /*!
632  *  SMESH_Gen_i::GetCurrentStudy
633  *
634  *  Get current study
635  */
636 //=============================================================================
637
638 SALOMEDS::Study_ptr SMESH_Gen_i::GetCurrentStudy()
639 {
640   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetCurrentStudy: study Id = " << GetCurrentStudyID() );
641   return SALOMEDS::Study::_duplicate( myCurrentStudy );
642 }
643
644 //=============================================================================
645 /*!
646  *  SMESH_Gen_i::GetCurrentStudyContext
647  *
648  *  Get current study context
649  */
650 //=============================================================================
651 StudyContext* SMESH_Gen_i::GetCurrentStudyContext()
652 {
653   if ( !CORBA::is_nil( myCurrentStudy ) &&
654       myStudyContextMap.find( GetCurrentStudyID() ) != myStudyContextMap.end() )
655     return myStudyContextMap[ myCurrentStudy->StudyId() ];
656   else
657     return 0;
658 }
659
660 //=============================================================================
661 /*!
662  *  SMESH_Gen_i::CreateHypothesis
663  *
664  *  Create hypothesis/algorothm of given type and publish it in the study
665  */
666 //=============================================================================
667
668 SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypName,
669                                                            const char* theLibName )
670      throw ( SALOME::SALOME_Exception )
671 {
672   Unexpect aCatch(SALOME_SalomeException);
673   // Create hypothesis/algorithm
674   SMESH::SMESH_Hypothesis_var hyp = this->createHypothesis( theHypName, theLibName );
675
676   // Publish hypothesis/algorithm in the study
677   if ( CanPublishInStudy( hyp ) ) {
678     SALOMEDS::SObject_var aSO = PublishHypothesis( myCurrentStudy, hyp );
679     if ( !aSO->_is_nil() ) {
680       // Update Python script
681       TPythonDump() << aSO << " = " << this << ".CreateHypothesis('"
682                     << theHypName << "', '" << theLibName << "')";
683     }
684   }
685
686   return hyp._retn();
687 }
688
689 //================================================================================
690 /*!
691  * \brief Return a hypothesis holding parameter values corresponding either to the mesh
692  * existing on the given geometry or to size of the geometry.
693  *  \param theHypType - hypothesis type name
694  *  \param theLibName - plugin library name
695  *  \param theMesh - The mesh of interest
696  *  \param theGeom - The shape to get parameter values from
697  *  \retval SMESH::SMESH_Hypothesis_ptr - The returned hypothesis may be the one existing
698  *     in a study and used to compute the mesh, or a temporary one created just to pass
699  *     parameter values
700  */
701 //================================================================================
702
703 SMESH::SMESH_Hypothesis_ptr
704 SMESH_Gen_i::GetHypothesisParameterValues (const char*           theHypType,
705                                            const char*           theLibName,
706                                            SMESH::SMESH_Mesh_ptr theMesh,
707                                            GEOM::GEOM_Object_ptr theGeom,
708                                            CORBA::Boolean        byMesh)
709   throw ( SALOME::SALOME_Exception )
710 {
711   Unexpect aCatch(SALOME_SalomeException);
712   if ( byMesh && CORBA::is_nil( theMesh ) )
713     return SMESH::SMESH_Hypothesis::_nil();
714   if ( byMesh && CORBA::is_nil( theGeom ) )
715     return SMESH::SMESH_Hypothesis::_nil();
716
717   // -----------------------------------------------
718   // find hypothesis used to mesh theGeom
719   // -----------------------------------------------
720
721   // get mesh and shape
722   SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
723   TopoDS_Shape shape = GeomObjectToShape( theGeom );
724   if ( byMesh && ( !meshServant || meshServant->NbNodes()==0 || shape.IsNull() ))
725     return SMESH::SMESH_Hypothesis::_nil();
726   ::SMESH_Mesh* mesh = meshServant ? &meshServant->GetImpl() : (::SMESH_Mesh*)0;
727
728   // create a temporary hypothesis to know its dimention
729   SMESH::SMESH_Hypothesis_var tmpHyp = this->createHypothesis( theHypType, theLibName );
730   SMESH_Hypothesis_i* hypServant = SMESH::DownCast<SMESH_Hypothesis_i*>( tmpHyp );
731   if ( !hypServant )
732     return SMESH::SMESH_Hypothesis::_nil();
733   ::SMESH_Hypothesis* hyp = hypServant->GetImpl();
734
735   if ( byMesh ) {
736     // look for a hypothesis of theHypType used to mesh the shape
737     if ( myGen.GetShapeDim( shape ) == hyp->GetDim() )
738     {
739       // check local shape
740       SMESH::ListOfHypothesis_var aHypList = theMesh->GetHypothesisList( theGeom );
741       int nbLocalHyps = aHypList->length();
742       for ( int i = 0; i < nbLocalHyps; i++ )
743         if ( strcmp( theHypType, aHypList[i]->GetName() ) == 0 ) // FOUND local!
744           return SMESH::SMESH_Hypothesis::_duplicate( aHypList[i] );
745       // check super shapes
746       TopTools_ListIteratorOfListOfShape itShape( mesh->GetAncestors( shape ));
747       while ( nbLocalHyps == 0 && itShape.More() ) {
748         GEOM::GEOM_Object_ptr geomObj = ShapeToGeomObject( itShape.Value() );
749         if ( ! CORBA::is_nil( geomObj )) {
750           SMESH::ListOfHypothesis_var aHypList = theMesh->GetHypothesisList( geomObj );
751           nbLocalHyps = aHypList->length();
752           for ( int i = 0; i < nbLocalHyps; i++ )
753             if ( strcmp( theHypType, aHypList[i]->GetName() ) == 0 ) // FOUND global!
754               return SMESH::SMESH_Hypothesis::_duplicate( aHypList[i] );
755         }
756         itShape.Next();
757       }
758     }
759
760     // let the temporary hypothesis find out somehow parameter values by mesh
761     if ( hyp->SetParametersByMesh( mesh, shape ))
762       return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
763   }
764   else {
765     double diagonal = 0;
766     if ( mesh )
767       diagonal = mesh->GetShapeDiagonalSize();
768     else
769       diagonal = ::SMESH_Mesh::GetShapeDiagonalSize( shape );
770     ::SMESH_Hypothesis::TDefaults dflts;
771     dflts._elemLength = diagonal / myGen.GetBoundaryBoxSegmentation();
772     dflts._nbSegments = myGen.GetDefaultNbSegments();
773     dflts._shape      = &shape;
774     // let the temporary hypothesis initialize it's values
775     if ( hyp->SetParametersByDefaults( dflts, mesh ))
776       return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
777   }
778
779   return SMESH::SMESH_Hypothesis::_nil();
780 }
781
782 //=============================================================================
783 /*!
784  * Sets number of segments per diagonal of boundary box of geometry by which
785  * default segment length of appropriate 1D hypotheses is defined
786  */
787 //=============================================================================
788
789 void SMESH_Gen_i::SetBoundaryBoxSegmentation( CORBA::Long theNbSegments )
790   throw ( SALOME::SALOME_Exception )
791 {
792   if ( theNbSegments > 0 )
793     myGen.SetBoundaryBoxSegmentation( int( theNbSegments ));
794   else
795     THROW_SALOME_CORBA_EXCEPTION( "non-positive number of segments", SALOME::BAD_PARAM );
796 }
797 //=============================================================================
798   /*!
799    * \brief Sets default number of segments per edge
800    */
801 //=============================================================================
802 void SMESH_Gen_i::SetDefaultNbSegments(CORBA::Long theNbSegments)
803   throw ( SALOME::SALOME_Exception )
804 {
805   if ( theNbSegments > 0 )
806     myGen.SetDefaultNbSegments( int(theNbSegments) );
807   else
808     THROW_SALOME_CORBA_EXCEPTION( "non-positive number of segments", SALOME::BAD_PARAM );
809 }
810
811 //=============================================================================
812 /*!
813   Set an option value
814 */
815 //=============================================================================
816
817 void SMESH_Gen_i::SetOption(const char* name, const char* value)
818 {
819   if ( name && value && strlen( value ) > 0 )
820   {
821     string msgToGUI; 
822     if ( strcmp(name, "historical_python_dump") == 0 )
823     {
824       myIsHistoricalPythonDump = ( value[0] == '1' || toupper(value[0]) == 'T' ); // 1 || true
825       msgToGUI = "preferences:SMESH:historical_python_dump:";
826       msgToGUI += myIsHistoricalPythonDump ? "true" : "false";
827     }
828     else if ( strcmp(name, "forget_mesh_on_hyp_modif") == 0 )
829     {
830       myToForgetMeshDataOnHypModif = ( value[0] == '1' || toupper(value[0]) == 'T' ); // 1 || true
831       msgToGUI = "preferences:SMESH:forget_mesh_on_hyp_modif:";
832       msgToGUI += myToForgetMeshDataOnHypModif ? "true" : "false";
833     }
834
835     // update preferences in case if SetOption() is invoked from python console
836     if ( !msgToGUI.empty() )
837     {
838       CORBA::Object_var obj = SMESH_Gen_i::GetNS()->Resolve( "/Kernel/Session" );
839       SALOME::Session_var session = SALOME::Session::_narrow( obj );
840       if ( !CORBA::is_nil( session ) )
841         session->emitMessageOneWay(msgToGUI.c_str());
842     }
843   }
844 }
845
846 //=============================================================================
847 /*!
848   Return an option value
849 */
850 //=============================================================================
851
852 char* SMESH_Gen_i::GetOption(const char* name)
853 {
854   if ( name )
855   {
856     if ( strcmp(name, "historical_python_dump") == 0 )
857     {
858       return CORBA::string_dup( myIsHistoricalPythonDump ? "true" : "false" );
859     }
860     if ( strcmp(name, "forget_mesh_on_hyp_modif") == 0 )
861     {
862       return CORBA::string_dup( myToForgetMeshDataOnHypModif ? "true" : "false" );
863     }
864   }
865   return CORBA::string_dup( "" );
866 }
867
868 //=============================================================================
869 /*!
870  *  SMESH_Gen_i::CreateMesh
871  *
872  *  Create empty mesh on a shape and publish it in the study
873  */
874 //=============================================================================
875
876 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObject )
877      throw ( SALOME::SALOME_Exception )
878 {
879   Unexpect aCatch(SALOME_SalomeException);
880   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMesh" );
881   // create mesh
882   SMESH::SMESH_Mesh_var mesh = this->createMesh();
883   // set shape
884   SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
885   ASSERT( meshServant );
886   meshServant->SetShape( theShapeObject );
887
888   // publish mesh in the study
889   if ( CanPublishInStudy( mesh ) ) {
890     SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
891     aStudyBuilder->NewCommand();  // There is a transaction
892     SALOMEDS::SObject_var aSO = PublishMesh( myCurrentStudy, mesh.in() );
893     aStudyBuilder->CommitCommand();
894     if ( !aSO->_is_nil() ) {
895       // Update Python script
896       TPythonDump() << aSO << " = " << this << ".CreateMesh(" << theShapeObject << ")";
897     }
898   }
899
900   return mesh._retn();
901 }
902
903 //=============================================================================
904 /*!
905  *  SMESH_Gen_i::CreateEmptyMesh
906  *
907  *  Create empty mesh
908  */
909 //=============================================================================
910
911 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateEmptyMesh()
912      throw ( SALOME::SALOME_Exception )
913 {
914   Unexpect aCatch(SALOME_SalomeException);
915   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMesh" );
916   // create mesh
917   SMESH::SMESH_Mesh_var mesh = this->createMesh();
918
919   // publish mesh in the study
920   if ( CanPublishInStudy( mesh ) ) {
921     SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
922     aStudyBuilder->NewCommand();  // There is a transaction
923     SALOMEDS::SObject_var aSO = PublishMesh( myCurrentStudy, mesh.in() );
924     aStudyBuilder->CommitCommand();
925     if ( !aSO->_is_nil() ) {
926       // Update Python script
927       TPythonDump() << aSO << " = " << this << ".CreateEmptyMesh()";
928     }
929   }
930
931   return mesh._retn();
932 }
933
934 //=============================================================================
935 /*!
936  *  SMESH_Gen_i::CreateMeshFromUNV
937  *
938  *  Create mesh and import data from UNV file
939  */
940 //=============================================================================
941
942 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName )
943   throw ( SALOME::SALOME_Exception )
944 {
945   Unexpect aCatch(SALOME_SalomeException);
946   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMeshesFromUNV" );
947
948   SMESH::SMESH_Mesh_var aMesh = createMesh();
949   string aFileName;
950   // publish mesh in the study
951   if ( CanPublishInStudy( aMesh ) ) {
952     SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
953     aStudyBuilder->NewCommand();  // There is a transaction
954     SALOMEDS::SObject_var aSO = PublishMesh( myCurrentStudy, aMesh.in(), aFileName.c_str() );
955     aStudyBuilder->CommitCommand();
956     if ( !aSO->_is_nil() ) {
957       // Update Python script
958       TPythonDump() << aSO << " = smeshgen.CreateMeshesFromUNV(r'" << theFileName << "')";
959     }
960   }
961
962   SMESH_Mesh_i* aServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( aMesh ).in() );
963   ASSERT( aServant );
964   aServant->ImportUNVFile( theFileName );
965
966   // Dump creation of groups
967   SMESH::ListOfGroups_var groups = aServant->GetGroups();
968
969   aServant->GetImpl().GetMeshDS()->Modified();
970   return aMesh._retn();
971 }
972
973 //=============================================================================
974 /*!
975  *  SMESH_Gen_i::CreateMeshFromMED
976  *
977  *  Create mesh and import data from MED file
978  */
979 //=============================================================================
980
981 SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMEDorSAUV( const char* theFileName,
982                                                            SMESH::DriverMED_ReadStatus& theStatus,
983                                                            const char* theCommandNameForPython,
984                                                            const char* theFileNameForPython)
985 {
986   // Retrieve mesh names from the file
987   DriverMED_R_SMESHDS_Mesh myReader;
988   myReader.SetFile( theFileName );
989   myReader.SetMeshId( -1 );
990   Driver_Mesh::Status aStatus;
991   list<string> aNames = myReader.GetMeshNames(aStatus);
992   SMESH::mesh_array_var aResult = new SMESH::mesh_array();
993   theStatus = (SMESH::DriverMED_ReadStatus)aStatus;
994
995   { // open a new scope to make aPythonDump die before PythonDump in SMESH_Mesh::GetGroups()
996
997   // Python Dump
998   TPythonDump aPythonDump;
999   aPythonDump << "([";
1000
1001   if (theStatus == SMESH::DRS_OK) {
1002     SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
1003     aStudyBuilder->NewCommand();  // There is a transaction
1004     aResult->length( aNames.size() );
1005     int i = 0;
1006
1007     // Iterate through all meshes and create mesh objects
1008     for ( list<string>::iterator it = aNames.begin(); it != aNames.end(); it++ ) {
1009       // Python Dump
1010       if (i > 0) aPythonDump << ", ";
1011
1012       // create mesh
1013       SMESH::SMESH_Mesh_var mesh = createMesh();
1014
1015       // publish mesh in the study
1016       SALOMEDS::SObject_var aSO;
1017       if ( CanPublishInStudy( mesh ) )
1018         aSO = PublishMesh( myCurrentStudy, mesh.in(), (*it).c_str() );
1019       if ( !aSO->_is_nil() ) {
1020         // Python Dump
1021         aPythonDump << aSO;
1022       } else {
1023         // Python Dump
1024         aPythonDump << "mesh_" << i;
1025       }
1026
1027       // Read mesh data (groups are published automatically by ImportMEDFile())
1028       SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
1029       ASSERT( meshServant );
1030       SMESH::DriverMED_ReadStatus status1 =
1031         meshServant->ImportMEDFile( theFileName, (*it).c_str() );
1032       if (status1 > theStatus)
1033         theStatus = status1;
1034
1035       aResult[i++] = SMESH::SMESH_Mesh::_duplicate( mesh );
1036       meshServant->GetImpl().GetMeshDS()->Modified();
1037     }
1038     aStudyBuilder->CommitCommand();
1039   }
1040
1041   // Update Python script
1042   aPythonDump << "], status) = " << this << "." << theCommandNameForPython << "(r'" << theFileNameForPython << "')";
1043   }
1044   // Dump creation of groups
1045   for ( int i = 0; i < aResult->length(); ++i )
1046     SMESH::ListOfGroups_var groups = aResult[ i ]->GetGroups();
1047
1048   return aResult._retn();
1049 }
1050
1051 SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char* theFileName,
1052                                                      SMESH::DriverMED_ReadStatus& theStatus)
1053      throw ( SALOME::SALOME_Exception )
1054 {
1055   Unexpect aCatch(SALOME_SalomeException);
1056   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMeshFromMED" );
1057   SMESH::mesh_array* result = CreateMeshesFromMEDorSAUV(theFileName, theStatus, "CreateMeshesFromMED", theFileName);
1058   return result;
1059 }
1060
1061 //=============================================================================
1062 /*!
1063  *  SMESH_Gen_i::CreateMeshFromSAUV
1064  *
1065  *  Create mesh and import data from SAUV file
1066  */
1067 //=============================================================================
1068
1069 SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromSAUV( const char* theFileName,
1070                                                       SMESH::DriverMED_ReadStatus& theStatus)
1071      throw ( SALOME::SALOME_Exception )
1072 {
1073   Unexpect aCatch(SALOME_SalomeException);
1074   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMeshFromSAUV" );
1075   std::string sauvfilename(theFileName);
1076   std::string medfilename(theFileName);
1077   medfilename += ".med";
1078   std::string cmd;
1079 #ifdef WNT
1080   cmd = "%PYTHONBIN% ";
1081 #else
1082   cmd = "python ";
1083 #endif
1084   cmd += "-c \"";
1085   cmd += "from medutilities import convert ; convert(r'" + sauvfilename + "', 'GIBI', 'MED', 1, r'" + medfilename + "')";
1086   cmd += "\"";
1087   system(cmd.c_str());
1088   SMESH::mesh_array* result = CreateMeshesFromMEDorSAUV(medfilename.c_str(), theStatus, "CreateMeshesFromSAUV", sauvfilename.c_str());
1089 #ifdef WNT
1090   cmd = "%PYTHONBIN% ";
1091 #else
1092   cmd = "python ";
1093 #endif
1094   cmd += "-c \"";
1095   cmd += "from medutilities import my_remove ; my_remove(r'" + medfilename + "')";
1096   cmd += "\"";
1097   system(cmd.c_str());
1098   return result;
1099 }
1100
1101 //=============================================================================
1102 /*!
1103  *  SMESH_Gen_i::CreateMeshFromSTL
1104  *
1105  *  Create mesh and import data from STL file
1106  */
1107 //=============================================================================
1108
1109 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromSTL( const char* theFileName )
1110   throw ( SALOME::SALOME_Exception )
1111 {
1112   Unexpect aCatch(SALOME_SalomeException);
1113   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMeshesFromSTL" );
1114
1115   SMESH::SMESH_Mesh_var aMesh = createMesh();
1116   string aFileName;
1117   // publish mesh in the study
1118   if ( CanPublishInStudy( aMesh ) ) {
1119     SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
1120     aStudyBuilder->NewCommand();  // There is a transaction
1121     SALOMEDS::SObject_var aSO = PublishInStudy
1122       ( myCurrentStudy, SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() );
1123     aStudyBuilder->CommitCommand();
1124     if ( !aSO->_is_nil() ) {
1125       // Update Python script
1126       TPythonDump() << aSO << " = " << this << ".CreateMeshesFromSTL(r'" << theFileName << "')";
1127     }
1128   }
1129
1130   SMESH_Mesh_i* aServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( aMesh ).in() );
1131   ASSERT( aServant );
1132   aServant->ImportSTLFile( theFileName );
1133   aServant->GetImpl().GetMeshDS()->Modified();
1134   return aMesh._retn();
1135 }
1136
1137 //================================================================================
1138 /*!
1139  * \brief Create meshes and import data from the CGSN file
1140  */
1141 //================================================================================
1142
1143 SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromCGNS( const char* theFileName,
1144                                                       SMESH::DriverMED_ReadStatus& theStatus)
1145   throw ( SALOME::SALOME_Exception )
1146 {
1147   Unexpect aCatch(SALOME_SalomeException);
1148
1149   SMESH::mesh_array_var aResult = new SMESH::mesh_array();
1150
1151 #ifdef WITH_CGNS
1152   // Retrieve nb meshes from the file
1153   DriverCGNS_Read myReader;
1154   myReader.SetFile( theFileName );
1155   Driver_Mesh::Status aStatus;
1156   int nbMeshes = myReader.GetNbMeshes(aStatus);
1157   theStatus = (SMESH::DriverMED_ReadStatus)aStatus;
1158
1159   aResult->length( nbMeshes );
1160
1161   { // open a new scope to make aPythonDump die before PythonDump in SMESH_Mesh::GetGroups()
1162
1163     // Python Dump
1164     TPythonDump aPythonDump;
1165     aPythonDump << "([";
1166
1167     if (theStatus == SMESH::DRS_OK)
1168     {
1169       SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
1170       aStudyBuilder->NewCommand();  // There is a transaction
1171
1172       int i = 0;
1173
1174       // Iterate through all meshes and create mesh objects
1175       for ( ; i < nbMeshes; ++i )
1176       {
1177         // Python Dump
1178         if (i > 0) aPythonDump << ", ";
1179
1180         // create mesh
1181         SMESH::SMESH_Mesh_var mesh = createMesh();
1182         aResult[i] = SMESH::SMESH_Mesh::_duplicate( mesh );
1183
1184         // Read mesh data (groups are published automatically by ImportMEDFile())
1185         SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
1186         ASSERT( meshServant );
1187         string meshName;
1188         SMESH::DriverMED_ReadStatus status1 =
1189           meshServant->ImportCGNSFile( theFileName, i, meshName );
1190         if (status1 > theStatus)
1191           theStatus = status1;
1192
1193         meshServant->GetImpl().GetMeshDS()->Modified();
1194         // publish mesh in the study
1195         SALOMEDS::SObject_var aSO;
1196         if ( CanPublishInStudy( mesh ) )
1197           aSO = PublishMesh( myCurrentStudy, mesh.in(), meshName.c_str() );
1198
1199         // Python Dump
1200         if ( !aSO->_is_nil() )
1201           aPythonDump << aSO;
1202         else
1203           aPythonDump << "mesh_" << i;
1204       }
1205       aStudyBuilder->CommitCommand();
1206     }
1207
1208     aPythonDump << "], status) = " << this << ".CreateMeshesFromCGNS(r'" << theFileName << "')";
1209   }
1210   // Dump creation of groups
1211   for ( int i = 0; i < aResult->length(); ++i )
1212     SMESH::ListOfGroups_var groups = aResult[ i ]->GetGroups();
1213 #else
1214   THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
1215 #endif
1216
1217   return aResult._retn();
1218 }
1219
1220 //=============================================================================
1221 /*!
1222  *  SMESH_Gen_i::IsReadyToCompute
1223  *
1224  *  Returns true if mesh contains enough data to be computed
1225  */
1226 //=============================================================================
1227
1228 CORBA::Boolean SMESH_Gen_i::IsReadyToCompute( SMESH::SMESH_Mesh_ptr theMesh,
1229                                               GEOM::GEOM_Object_ptr theShapeObject )
1230   throw ( SALOME::SALOME_Exception )
1231 {
1232   Unexpect aCatch(SALOME_SalomeException);
1233   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IsReadyToCompute" );
1234
1235   if ( CORBA::is_nil( theShapeObject ) )
1236     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
1237                                   SALOME::BAD_PARAM );
1238
1239   if ( CORBA::is_nil( theMesh ) )
1240     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
1241                                   SALOME::BAD_PARAM );
1242
1243   try {
1244     // get mesh servant
1245     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
1246     ASSERT( meshServant );
1247     if ( meshServant ) {
1248       // get local TopoDS_Shape
1249       TopoDS_Shape myLocShape = GeomObjectToShape( theShapeObject );
1250       // call implementation
1251       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
1252       return myGen.CheckAlgoState( myLocMesh, myLocShape );
1253     }
1254   }
1255   catch ( SALOME_Exception& S_ex ) {
1256     INFOS( "catch exception "<< S_ex.what() );
1257   }
1258   return false;
1259 }
1260
1261 //================================================================================
1262 /*!
1263  * \brief  Find SObject for an algo
1264  */
1265 //================================================================================
1266
1267 SALOMEDS::SObject_ptr SMESH_Gen_i::GetAlgoSO(const ::SMESH_Algo* algo)
1268 {
1269   if ( algo ) {
1270     if ( !myCurrentStudy->_is_nil() ) {
1271       // find algo in the study
1272       SALOMEDS::SComponent_var father = SALOMEDS::SComponent::_narrow
1273         ( myCurrentStudy->FindComponent( ComponentDataType() ) );
1274       if ( !father->_is_nil() ) {
1275         SALOMEDS::ChildIterator_var itBig = myCurrentStudy->NewChildIterator( father );
1276         for ( ; itBig->More(); itBig->Next() ) {
1277           SALOMEDS::SObject_var gotBranch = itBig->Value();
1278           if ( gotBranch->Tag() == GetAlgorithmsRootTag() ) {
1279             SALOMEDS::ChildIterator_var algoIt = myCurrentStudy->NewChildIterator( gotBranch );
1280             for ( ; algoIt->More(); algoIt->Next() ) {
1281               SALOMEDS::SObject_var algoSO = algoIt->Value();
1282               CORBA::Object_var     algoIOR = SObjectToObject( algoSO );
1283               if ( !CORBA::is_nil( algoIOR )) {
1284                 SMESH_Hypothesis_i* impl = SMESH::DownCast<SMESH_Hypothesis_i*>( algoIOR );
1285                 if ( impl && impl->GetImpl() == algo )
1286                   return algoSO._retn();
1287               }
1288             } // loop on algo SO's
1289             break;
1290           } // if algo tag
1291         } // SMESH component iterator
1292       }
1293     }
1294   }
1295   return SALOMEDS::SObject::_nil();
1296 }
1297
1298 //================================================================================
1299 /*!
1300  * \brief Return errors of mesh computation
1301  */
1302 //================================================================================
1303
1304 SMESH::compute_error_array* SMESH_Gen_i::GetComputeErrors( SMESH::SMESH_Mesh_ptr theMesh,
1305                                                            GEOM::GEOM_Object_ptr theSubObject )
1306   throw ( SALOME::SALOME_Exception )
1307 {
1308   Unexpect aCatch(SALOME_SalomeException);
1309   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetComputeErrors()" );
1310
1311   if ( CORBA::is_nil( theSubObject ) && theMesh->HasShapeToMesh())
1312     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM );
1313
1314   if ( CORBA::is_nil( theMesh ) )
1315     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM );
1316
1317   SMESH::compute_error_array_var error_array = new SMESH::compute_error_array;
1318   try {
1319     if ( SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh ))
1320     {
1321       TopoDS_Shape shape;
1322       if(theMesh->HasShapeToMesh())
1323         shape = GeomObjectToShape( theSubObject );
1324       else
1325         shape = SMESH_Mesh::PseudoShape();
1326
1327       ::SMESH_Mesh& mesh = meshServant->GetImpl();
1328
1329       error_array->length( mesh.GetMeshDS()->MaxShapeIndex() );
1330       int nbErr = 0;
1331
1332       SMESH_subMesh *sm = mesh.GetSubMesh(shape);
1333       const bool includeSelf = true, complexShapeFirst = true;
1334       SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(includeSelf,
1335                                                                complexShapeFirst);
1336       while ( smIt->more() )
1337       {
1338         sm = smIt->next();
1339         if ( sm->GetSubShape().ShapeType() == TopAbs_VERTEX )
1340           break;
1341         SMESH_ComputeErrorPtr error = sm->GetComputeError();
1342         if ( error && !error->IsOK() && error->myAlgo )
1343         {
1344           SMESH::ComputeError & errStruct = error_array[ nbErr++ ];
1345           errStruct.code       = -( error->myName < 0 ? error->myName + 1: error->myName ); // -1 -> 0
1346           errStruct.comment    = error->myComment.c_str();
1347           errStruct.subShapeID = sm->GetId();
1348           SALOMEDS::SObject_var algoSO = GetAlgoSO( error->myAlgo );
1349           if ( !algoSO->_is_nil() )
1350             errStruct.algoName = algoSO->GetName();
1351           else
1352             errStruct.algoName = error->myAlgo->GetName();
1353           errStruct.hasBadMesh = !error->myBadElements.empty();
1354         }
1355       }
1356       error_array->length( nbErr );
1357     }
1358   }
1359   catch ( SALOME_Exception& S_ex ) {
1360     INFOS( "catch exception "<< S_ex.what() );
1361   }
1362
1363   return error_array._retn();
1364 }
1365
1366 //
1367 //================================================================================
1368 /*!
1369  * \brief Return mesh elements preventing computation of a subshape
1370  */
1371 //================================================================================
1372
1373 SMESH::MeshPreviewStruct*
1374 SMESH_Gen_i::GetBadInputElements( SMESH::SMESH_Mesh_ptr theMesh,
1375                                   CORBA::Short          theSubShapeID )
1376   throw ( SALOME::SALOME_Exception )
1377 {
1378   Unexpect aCatch(SALOME_SalomeException);
1379   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetBadInputElements()" );
1380
1381   if ( CORBA::is_nil( theMesh ) )
1382     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM );
1383
1384   SMESH::MeshPreviewStruct_var result = new SMESH::MeshPreviewStruct;
1385   try {
1386     // mesh servant
1387     if ( SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh ))
1388     {
1389       // mesh implementation
1390       ::SMESH_Mesh& mesh = meshServant->GetImpl();
1391       // submesh by subshape id
1392       if ( SMESH_subMesh * sm = mesh.GetSubMeshContaining( theSubShapeID ))
1393       {
1394         // compute error
1395         SMESH_ComputeErrorPtr error = sm->GetComputeError();
1396         if ( error && !error->myBadElements.empty())
1397         {
1398           typedef map<const SMDS_MeshElement*, int > TNode2LocalIDMap;
1399           typedef TNode2LocalIDMap::iterator         TNodeLocalID;
1400
1401           // get nodes of elements and count elements
1402           TNode2LocalIDMap mapNode2LocalID;
1403           list< TNodeLocalID > connectivity;
1404           int i, nbElements = 0, nbConnNodes = 0;
1405
1406           list<const SMDS_MeshElement*>::iterator elemIt  = error->myBadElements.begin();
1407           list<const SMDS_MeshElement*>::iterator elemEnd = error->myBadElements.end();
1408           for ( ; elemIt != elemEnd; ++elemIt, ++nbElements )
1409           {
1410             SMDS_ElemIteratorPtr nIt = (*elemIt)->nodesIterator();
1411             while ( nIt->more() )
1412               connectivity.push_back
1413                 ( mapNode2LocalID.insert( make_pair( nIt->next(), ++nbConnNodes)).first );
1414           }
1415           // fill node coords and assign local ids to the nodes
1416           int nbNodes = mapNode2LocalID.size();
1417           result->nodesXYZ.length( nbNodes );
1418           TNodeLocalID node2ID = mapNode2LocalID.begin();
1419           for ( i = 0; i < nbNodes; ++i, ++node2ID ) {
1420             node2ID->second = i;
1421             const SMDS_MeshNode* node = (const SMDS_MeshNode*) node2ID->first;
1422             result->nodesXYZ[i].x = node->X();
1423             result->nodesXYZ[i].y = node->Y();
1424             result->nodesXYZ[i].z = node->Z();
1425           }
1426           // fill connectivity
1427           result->elementConnectivities.length( nbConnNodes );
1428           list< TNodeLocalID >::iterator connIt = connectivity.begin();
1429           for ( i = 0; i < nbConnNodes; ++i, ++connIt ) {
1430             result->elementConnectivities[i] = (*connIt)->second;
1431           }
1432           // fill element types
1433           result->elementTypes.length( nbElements );
1434           for ( i = 0, elemIt = error->myBadElements.begin(); i <nbElements; ++i, ++elemIt )
1435           {
1436             const SMDS_MeshElement* elem = *elemIt;
1437             result->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) elem->GetType();
1438             result->elementTypes[i].isPoly           = elem->IsPoly();
1439             result->elementTypes[i].nbNodesInElement = elem->NbNodes();
1440           }
1441         }
1442       }
1443     }
1444   }
1445   catch ( SALOME_Exception& S_ex ) {
1446     INFOS( "catch exception "<< S_ex.what() );
1447   }
1448
1449   return result._retn();
1450 }
1451
1452 //================================================================================
1453 /*!
1454  * \brief Returns errors of hypotheses definintion
1455  * \param theMesh - the mesh
1456  * \param theSubObject - the main or sub- shape
1457  * \retval SMESH::algo_error_array* - sequence of errors
1458  */
1459 //================================================================================
1460
1461 SMESH::algo_error_array* SMESH_Gen_i::GetAlgoState( SMESH::SMESH_Mesh_ptr theMesh,
1462                                                     GEOM::GEOM_Object_ptr theSubObject )
1463       throw ( SALOME::SALOME_Exception )
1464 {
1465   Unexpect aCatch(SALOME_SalomeException);
1466   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetAlgoState()" );
1467
1468   if ( CORBA::is_nil( theSubObject ) && theMesh->HasShapeToMesh())
1469     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM );
1470
1471   if ( CORBA::is_nil( theMesh ) )
1472     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM );
1473
1474   SMESH::algo_error_array_var error_array = new SMESH::algo_error_array;
1475   try {
1476     SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
1477     ASSERT( meshServant );
1478     if ( meshServant ) {
1479       TopoDS_Shape myLocShape;
1480       if(theMesh->HasShapeToMesh())
1481         myLocShape = GeomObjectToShape( theSubObject );
1482       else
1483         myLocShape = SMESH_Mesh::PseudoShape();
1484
1485       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
1486       list< ::SMESH_Gen::TAlgoStateError > error_list;
1487       list< ::SMESH_Gen::TAlgoStateError >::iterator error;
1488       // call ::SMESH_Gen::GetAlgoState()
1489       myGen.GetAlgoState( myLocMesh, myLocShape, error_list );
1490       error_array->length( error_list.size() );
1491       int i = 0;
1492       for ( error = error_list.begin(); error != error_list.end(); ++error )
1493       {
1494         // fill AlgoStateError structure
1495         SMESH::AlgoStateError & errStruct = error_array[ i++ ];
1496         errStruct.state        = SMESH_Mesh_i::ConvertHypothesisStatus( error->_name );
1497         errStruct.algoDim      = error->_algoDim;
1498         errStruct.isGlobalAlgo = error->_isGlobalAlgo;
1499         errStruct.algoName     = "";
1500         SALOMEDS::SObject_var algoSO = GetAlgoSO( error->_algo );
1501         if ( !algoSO->_is_nil() )
1502           errStruct.algoName   = algoSO->GetName();
1503       }
1504     }
1505   }
1506   catch ( SALOME_Exception& S_ex ) {
1507     INFOS( "catch exception "<< S_ex.what() );
1508   }
1509   return error_array._retn();
1510 }
1511
1512 //=============================================================================
1513 /*!
1514  *  SMESH_Gen_i::GetSubShapesId
1515  *
1516  *  Get sub-shapes unique ID's list
1517  */
1518 //=============================================================================
1519
1520 SMESH::long_array* SMESH_Gen_i::GetSubShapesId( GEOM::GEOM_Object_ptr theMainShapeObject,
1521                                             const SMESH::object_array& theListOfSubShapeObject )
1522      throw ( SALOME::SALOME_Exception )
1523 {
1524   Unexpect aCatch(SALOME_SalomeException);
1525   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetSubShapesId" );
1526
1527   SMESH::long_array_var shapesId = new SMESH::long_array;
1528   set<int> setId;
1529
1530   if ( CORBA::is_nil( theMainShapeObject ) )
1531     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
1532                                   SALOME::BAD_PARAM );
1533
1534   try
1535     {
1536       TopoDS_Shape myMainShape = GeomObjectToShape(theMainShapeObject);
1537       TopTools_IndexedMapOfShape myIndexToShape;
1538       TopExp::MapShapes(myMainShape,myIndexToShape);
1539
1540       for ( int i = 0; i < theListOfSubShapeObject.length(); i++ )
1541         {
1542           GEOM::GEOM_Object_var aShapeObject
1543             = GEOM::GEOM_Object::_narrow(theListOfSubShapeObject[i]);
1544           if ( CORBA::is_nil( aShapeObject ) )
1545             THROW_SALOME_CORBA_EXCEPTION ("bad shape object reference", \
1546                                         SALOME::BAD_PARAM );
1547
1548           TopoDS_Shape locShape  = GeomObjectToShape(aShapeObject);
1549           for (TopExp_Explorer exp(locShape,TopAbs_FACE); exp.More(); exp.Next())
1550             {
1551               const TopoDS_Face& F = TopoDS::Face(exp.Current());
1552               setId.insert(myIndexToShape.FindIndex(F));
1553               if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(F));
1554             }
1555           for (TopExp_Explorer exp(locShape,TopAbs_EDGE); exp.More(); exp.Next())
1556             {
1557               const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1558               setId.insert(myIndexToShape.FindIndex(E));
1559               if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(E));
1560             }
1561           for (TopExp_Explorer exp(locShape,TopAbs_VERTEX); exp.More(); exp.Next())
1562             {
1563               const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
1564               setId.insert(myIndexToShape.FindIndex(V));
1565               if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(V));
1566             }
1567         }
1568       shapesId->length(setId.size());
1569       set<int>::iterator iind;
1570       int i=0;
1571       for (iind = setId.begin(); iind != setId.end(); iind++)
1572         {
1573           if(MYDEBUG) SCRUTE((*iind));
1574           shapesId[i] = (*iind);
1575           if(MYDEBUG) SCRUTE(shapesId[i]);
1576           i++;
1577         }
1578     }
1579   catch (SALOME_Exception& S_ex)
1580     {
1581       THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
1582     }
1583
1584   return shapesId._retn();
1585 }
1586
1587 //=============================================================================
1588 /*!
1589  *  SMESH_Gen_i::Compute
1590  *
1591  *  Compute mesh on a shape
1592  */
1593 //=============================================================================
1594
1595 CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
1596                                      GEOM::GEOM_Object_ptr theShapeObject )
1597      throw ( SALOME::SALOME_Exception )
1598 {
1599   MEMOSTAT;
1600   Unexpect aCatch(SALOME_SalomeException);
1601   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Compute" );
1602
1603   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
1604     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
1605                                   SALOME::BAD_PARAM );
1606
1607   if ( CORBA::is_nil( theMesh ) )
1608     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
1609                                   SALOME::BAD_PARAM );
1610
1611   // Update Python script
1612   TPythonDump() << "isDone = " << this << ".Compute( "
1613                 << theMesh << ", " << theShapeObject << ")";
1614
1615   try {
1616     // get mesh servant
1617     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
1618     meshServant->Load();
1619     ASSERT( meshServant );
1620     if ( meshServant ) {
1621       // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
1622       meshServant->CheckGeomGroupModif();
1623       // get local TopoDS_Shape
1624       TopoDS_Shape myLocShape;
1625       if(theMesh->HasShapeToMesh())
1626         myLocShape = GeomObjectToShape( theShapeObject );
1627       else
1628         myLocShape = SMESH_Mesh::PseudoShape();
1629       // call implementation compute
1630       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
1631 #ifdef WITH_SMESH_CANCEL_COMPUTE
1632       myGen.PrepareCompute( myLocMesh, myLocShape);
1633 #endif
1634       bool ok = myGen.Compute( myLocMesh, myLocShape);
1635       meshServant->CreateGroupServants(); // algos can create groups (issue 0020918)
1636       myLocMesh.GetMeshDS()->Modified();
1637       return ok;
1638     }
1639   }
1640   catch ( std::bad_alloc ) {
1641     INFOS( "Compute(): lack of memory" );
1642   }
1643   catch ( SALOME_Exception& S_ex ) {
1644     INFOS( "Compute(): catch exception "<< S_ex.what() );
1645   }
1646   catch ( ... ) {
1647     INFOS( "Compute(): unknown exception " );
1648   }
1649   return false;
1650 }
1651
1652 //=============================================================================
1653 /*!
1654  *  SMESH_Gen_i::CancelCompute
1655  *
1656  *  Cancel Compute mesh on a shape
1657  */
1658 //=============================================================================
1659
1660 void SMESH_Gen_i::CancelCompute( SMESH::SMESH_Mesh_ptr theMesh,
1661                                  GEOM::GEOM_Object_ptr theShapeObject )
1662 {
1663 #ifdef WITH_SMESH_CANCEL_COMPUTE
1664   SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
1665   ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
1666   TopoDS_Shape myLocShape;
1667   if(theMesh->HasShapeToMesh())
1668     myLocShape = GeomObjectToShape( theShapeObject );
1669   else
1670     myLocShape = SMESH_Mesh::PseudoShape();
1671   myGen.CancelCompute( myLocMesh, myLocShape);
1672 #endif
1673 }
1674
1675 //=============================================================================
1676 /*!
1677  *  SMESH_Gen_i::Precompute
1678  *
1679  *  Compute mesh as preview till indicated dimension on shape
1680  */
1681 //=============================================================================
1682
1683 SMESH::MeshPreviewStruct* SMESH_Gen_i::Precompute( SMESH::SMESH_Mesh_ptr theMesh,
1684                                                    GEOM::GEOM_Object_ptr theShapeObject,
1685                                                    SMESH::Dimension      theDimension,
1686                                                    SMESH::long_array&    theShapesId)
1687      throw ( SALOME::SALOME_Exception )
1688 {
1689   Unexpect aCatch(SALOME_SalomeException);
1690   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Precompute" );
1691
1692   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
1693     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
1694                                   SALOME::BAD_PARAM );
1695
1696   if ( CORBA::is_nil( theMesh ) )
1697     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
1698                                   SALOME::BAD_PARAM );
1699
1700   SMESH::MeshPreviewStruct_var result = new SMESH::MeshPreviewStruct;
1701   try {
1702     // get mesh servant
1703     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
1704     meshServant->Load();
1705     ASSERT( meshServant );
1706     if ( meshServant ) {
1707       // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
1708       meshServant->CheckGeomGroupModif();
1709       // get local TopoDS_Shape
1710       TopoDS_Shape myLocShape;
1711       if(theMesh->HasShapeToMesh())
1712         myLocShape = GeomObjectToShape( theShapeObject );
1713       else
1714         return result._retn();;
1715
1716       // call implementation compute
1717       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
1718       TSetOfInt shapeIds;
1719       ::MeshDimension aDim = (MeshDimension)theDimension;
1720       if ( myGen.Compute( myLocMesh, myLocShape, false, aDim, &shapeIds ) )
1721       {
1722         int nbShapeId = shapeIds.size();
1723         theShapesId.length( nbShapeId );
1724         // iterates on shapes and collect mesh entities into mesh preview
1725         TSetOfInt::const_iterator idIt = shapeIds.begin();
1726         TSetOfInt::const_iterator idEnd = shapeIds.end();
1727         std::map< int, int > mapOfShIdNb;
1728         std::set< SMESH_TLink > setOfEdge;
1729         std::list< SMDSAbs_ElementType > listOfElemType;
1730         typedef map<const SMDS_MeshElement*, int > TNode2LocalIDMap;
1731         typedef TNode2LocalIDMap::iterator         TNodeLocalID;
1732         TNode2LocalIDMap mapNode2LocalID;
1733         list< TNodeLocalID > connectivity;
1734         int i, nbConnNodes = 0;
1735         std::set< const SMESH_subMesh* > setOfVSubMesh;
1736         // iterates on shapes
1737         for ( ; idIt != idEnd; idIt++ )
1738         {
1739           if ( mapOfShIdNb.find( *idIt ) != mapOfShIdNb.end() )
1740             continue;
1741           SMESH_subMesh* sm = myLocMesh.GetSubMeshContaining(*idIt);
1742           if ( !sm || !sm->IsMeshComputed() )
1743             continue;
1744
1745           const TopoDS_Shape& aSh = sm->GetSubShape();
1746           const int shDim = myGen.GetShapeDim( aSh );
1747           if ( shDim < 1 || shDim > theDimension )
1748             continue;
1749
1750           mapOfShIdNb[ *idIt ] = 0;
1751           theShapesId[ mapOfShIdNb.size() - 1 ] = *idIt;
1752
1753           SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
1754           if ( !smDS ) continue;
1755
1756           if ( theDimension == SMESH::DIM_2D )
1757           {
1758             SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
1759             while ( faceIt->more() )
1760             {
1761               const SMDS_MeshElement* face = faceIt->next();
1762               int aNbNode = face->NbNodes();
1763               if ( aNbNode > 4 )
1764                 aNbNode /= 2; // do not take into account additional middle nodes
1765
1766               SMDS_MeshNode* node1 = (SMDS_MeshNode*)face->GetNode( 0 );
1767               for ( int nIndx = 0; nIndx < aNbNode; nIndx++ )
1768               {
1769                 SMDS_MeshNode* node2 = (SMDS_MeshNode*)face->GetNode( nIndx+1 < aNbNode ? nIndx+1 : 0 );
1770                 if ( setOfEdge.insert( SMESH_TLink ( node1, node2 ) ).second )
1771                 {
1772                   listOfElemType.push_back( SMDSAbs_Edge );
1773                   connectivity.push_back
1774                     ( mapNode2LocalID.insert( make_pair( node1, ++nbConnNodes)).first );
1775                   connectivity.push_back
1776                     ( mapNode2LocalID.insert( make_pair( node2, ++nbConnNodes)).first );
1777                 }
1778                 node1 = node2;
1779               }
1780             }
1781           }
1782           else if ( theDimension == SMESH::DIM_1D )
1783           {
1784             SMDS_NodeIteratorPtr nodeIt = smDS->GetNodes();
1785             while ( nodeIt->more() )
1786             {
1787               listOfElemType.push_back( SMDSAbs_Node );
1788               connectivity.push_back
1789                 ( mapNode2LocalID.insert( make_pair( nodeIt->next(), ++nbConnNodes)).first );
1790             }
1791             // add corner nodes by first vertex from edge
1792             SMESH_subMeshIteratorPtr edgeSmIt =
1793               sm->getDependsOnIterator(/*includeSelf*/false,
1794                                        /*complexShapeFirst*/false);
1795             while ( edgeSmIt->more() )
1796             {
1797               SMESH_subMesh* vertexSM = edgeSmIt->next();
1798               // check that vertex is not already treated
1799               if ( !setOfVSubMesh.insert( vertexSM ).second )
1800                 continue;
1801               if ( vertexSM->GetSubShape().ShapeType() != TopAbs_VERTEX )
1802                 continue;
1803
1804               const SMESHDS_SubMesh* vertexSmDS = vertexSM->GetSubMeshDS();
1805               SMDS_NodeIteratorPtr nodeIt = vertexSmDS->GetNodes();
1806               while ( nodeIt->more() )
1807               {
1808                 listOfElemType.push_back( SMDSAbs_Node );
1809                 connectivity.push_back
1810                   ( mapNode2LocalID.insert( make_pair( nodeIt->next(), ++nbConnNodes)).first );
1811               }
1812             }
1813           }
1814         }
1815
1816         // fill node coords and assign local ids to the nodes
1817         int nbNodes = mapNode2LocalID.size();
1818         result->nodesXYZ.length( nbNodes );
1819         TNodeLocalID node2ID = mapNode2LocalID.begin();
1820         for ( i = 0; i < nbNodes; ++i, ++node2ID ) {
1821           node2ID->second = i;
1822           const SMDS_MeshNode* node = (const SMDS_MeshNode*) node2ID->first;
1823           result->nodesXYZ[i].x = node->X();
1824           result->nodesXYZ[i].y = node->Y();
1825           result->nodesXYZ[i].z = node->Z();
1826         }
1827         // fill connectivity
1828         result->elementConnectivities.length( nbConnNodes );
1829         list< TNodeLocalID >::iterator connIt = connectivity.begin();
1830         for ( i = 0; i < nbConnNodes; ++i, ++connIt ) {
1831           result->elementConnectivities[i] = (*connIt)->second;
1832         }
1833
1834         // fill element types
1835         result->elementTypes.length( listOfElemType.size() );
1836         std::list< SMDSAbs_ElementType >::const_iterator typeIt = listOfElemType.begin();
1837         std::list< SMDSAbs_ElementType >::const_iterator typeEnd = listOfElemType.end();
1838         for ( i = 0; typeIt != typeEnd; ++i, ++typeIt )
1839         {
1840           SMDSAbs_ElementType elemType = *typeIt;
1841           result->elementTypes[i].SMDS_ElementType = (SMESH::ElementType)elemType;
1842           result->elementTypes[i].isPoly           = false;
1843           result->elementTypes[i].nbNodesInElement = elemType == SMDSAbs_Edge ? 2 : 1;
1844         }
1845
1846         // correct number of shapes
1847         theShapesId.length( mapOfShIdNb.size() );
1848       }
1849     }
1850   }
1851   catch ( std::bad_alloc ) {
1852     INFOS( "Precompute(): lack of memory" );
1853   }
1854   catch ( SALOME_Exception& S_ex ) {
1855     INFOS( "Precompute(): catch exception "<< S_ex.what() );
1856   }
1857   catch ( ... ) {
1858     INFOS( "Precompute(): unknown exception " );
1859   }
1860   return result._retn();
1861 }
1862
1863
1864 //=============================================================================
1865 /*!
1866  *  SMESH_Gen_i::Evaluate
1867  *
1868  *  Evaluate mesh on a shape
1869  */
1870 //=============================================================================
1871
1872 SMESH::long_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
1873                                          GEOM::GEOM_Object_ptr theShapeObject)
1874 //                                     SMESH::long_array& theNbElems)
1875      throw ( SALOME::SALOME_Exception )
1876 {
1877   Unexpect aCatch(SALOME_SalomeException);
1878   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Evaluate" );
1879
1880   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
1881     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
1882                                   SALOME::BAD_PARAM );
1883
1884   if ( CORBA::is_nil( theMesh ) )
1885     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
1886                                   SALOME::BAD_PARAM );
1887
1888   SMESH::long_array_var nbels = new SMESH::long_array;
1889   nbels->length(SMESH::Entity_Last);
1890   int i = SMESH::Entity_Node;
1891   for (; i < SMESH::Entity_Last; i++)
1892     nbels[i] = 0;
1893
1894   // Update Python script
1895   TPythonDump() << "theNbElems = " << this << ".Evaluate( "
1896                 << theMesh << ", " << theShapeObject << ")";
1897
1898   try {
1899     // get mesh servant
1900     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
1901     ASSERT( meshServant );
1902     if ( meshServant ) {
1903       // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
1904       meshServant->CheckGeomGroupModif();
1905       // get local TopoDS_Shape
1906       TopoDS_Shape myLocShape;
1907       if(theMesh->HasShapeToMesh())
1908         myLocShape = GeomObjectToShape( theShapeObject );
1909       else
1910         myLocShape = SMESH_Mesh::PseudoShape();
1911       // call implementation compute
1912       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
1913       MapShapeNbElems aResMap;
1914       /*CORBA::Boolean ret =*/ myGen.Evaluate( myLocMesh, myLocShape, aResMap);
1915       MapShapeNbElemsItr anIt = aResMap.begin();
1916       for(; anIt!=aResMap.end(); anIt++) {
1917         const vector<int>& aVec = (*anIt).second;
1918         for(i = SMESH::Entity_Node; i < aVec.size(); i++) {
1919           int nbElem = aVec[i];
1920           if ( nbElem < 0 ) // algo failed, check that it has reported a message
1921           {
1922             SMESH_subMesh* sm = anIt->first;
1923             SMESH_ComputeErrorPtr& error = sm->GetComputeError();
1924             const SMESH_Algo* algo = myGen.GetAlgo( myLocMesh, sm->GetSubShape());
1925             if ( (algo && !error.get()) || error->IsOK() )
1926               error.reset( new SMESH_ComputeError( COMPERR_ALGO_FAILED,"Failed to evaluate",algo));
1927           }
1928           else
1929           {
1930             nbels[i] += aVec[i];
1931           }
1932         }
1933       }
1934       return nbels._retn();
1935     }
1936   }
1937   catch ( std::bad_alloc ) {
1938     INFOS( "Evaluate(): lack of memory" );
1939   }
1940   catch ( SALOME_Exception& S_ex ) {
1941     INFOS( "Evaluate(): catch exception "<< S_ex.what() );
1942   }
1943   catch ( ... ) {
1944     INFOS( "Evaluate(): unknown exception " );
1945   }
1946
1947   return nbels._retn();
1948 }
1949
1950 //================================================================================
1951 /*!
1952  * \brief Return geometrical object the given element is built on
1953  *  \param theMesh - the mesh the element is in
1954  *  \param theElementID - the element ID
1955  *  \param theGeomName - the name of the result geom object if it is not yet published
1956  *  \retval GEOM::GEOM_Object_ptr - the found or just published geom object
1957  */
1958 //================================================================================
1959
1960 GEOM::GEOM_Object_ptr
1961 SMESH_Gen_i::GetGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
1962                                        CORBA::Long            theElementID,
1963                                        const char*            theGeomName)
1964   throw ( SALOME::SALOME_Exception )
1965 {
1966   Unexpect aCatch(SALOME_SalomeException);
1967
1968   GEOM::GEOM_Object_var geom = FindGeometryByMeshElement(theMesh, theElementID);
1969   if ( !geom->_is_nil() ) {
1970     GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh();
1971     GEOM::GEOM_Gen_ptr    geomGen   = GetGeomEngine();
1972
1973     // try to find the corresponding SObject
1974     SALOMEDS::SObject_var SObj = ObjectToSObject( myCurrentStudy, geom.in() );
1975     if ( SObj->_is_nil() ) // submesh can be not found even if published
1976     {
1977       // try to find published submesh
1978       GEOM::ListOfLong_var list = geom->GetSubShapeIndices();
1979       if ( !geom->IsMainShape() && list->length() == 1 ) {
1980         SALOMEDS::SObject_var mainSO = ObjectToSObject( myCurrentStudy, mainShape );
1981         SALOMEDS::ChildIterator_var it;
1982         if ( !mainSO->_is_nil() )
1983           it = myCurrentStudy->NewChildIterator( mainSO );
1984         if ( !it->_is_nil() ) {
1985           for ( it->InitEx(true); SObj->_is_nil() && it->More(); it->Next() ) {
1986             GEOM::GEOM_Object_var subGeom =
1987               GEOM::GEOM_Object::_narrow( SObjectToObject( it->Value() ));
1988             if ( !subGeom->_is_nil() ) {
1989               GEOM::ListOfLong_var subList = subGeom->GetSubShapeIndices();
1990               if ( subList->length() == 1 && list[0] == subList[0] ) {
1991                 SObj = it->Value();
1992                 geom = subGeom;
1993               }
1994             }
1995           }
1996         }
1997       }
1998     }
1999     if ( SObj->_is_nil() ) // publish a new subshape
2000       SObj = geomGen->AddInStudy( myCurrentStudy, geom, theGeomName, mainShape );
2001
2002     // return only published geometry
2003     if ( !SObj->_is_nil() )
2004       return geom._retn();
2005   }
2006   return GEOM::GEOM_Object::_nil();
2007 }
2008
2009 //================================================================================
2010 /*!
2011  * \brief Return geometrical object the given element is built on.
2012  *  \param theMesh - the mesh the element is in
2013  *  \param theElementID - the element ID
2014  *  \retval GEOM::GEOM_Object_ptr - the found geom object
2015  */
2016 //================================================================================
2017
2018 GEOM::GEOM_Object_ptr
2019 SMESH_Gen_i::FindGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
2020                                         CORBA::Long            theElementID)
2021   throw ( SALOME::SALOME_Exception )
2022 {
2023   Unexpect aCatch(SALOME_SalomeException);
2024   if ( CORBA::is_nil( theMesh ) )
2025     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", SALOME::BAD_PARAM );
2026
2027   GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh();
2028   GEOM::GEOM_Gen_ptr    geomGen   = GetGeomEngine();
2029
2030   // get a core mesh DS
2031   SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
2032   if ( meshServant && !geomGen->_is_nil() && !mainShape->_is_nil() )
2033   {
2034     ::SMESH_Mesh & mesh = meshServant->GetImpl();
2035     SMESHDS_Mesh* meshDS = mesh.GetMeshDS();
2036     // find the element in mesh
2037     if ( const SMDS_MeshElement * elem = meshDS->FindElement( theElementID ) ) {
2038       // find a shape id by the element
2039       if ( int shapeID = ::SMESH_MeshEditor( &mesh ).FindShape( elem )) {
2040         // get a geom object by the shape id
2041         GEOM::GEOM_Object_var geom = ShapeToGeomObject( meshDS->IndexToShape( shapeID ));
2042         if ( geom->_is_nil() ) {
2043           // try to find a published sub-shape
2044           SALOMEDS::SObject_var mainSO = ObjectToSObject( myCurrentStudy, mainShape );
2045           SALOMEDS::ChildIterator_var it;
2046           if ( !mainSO->_is_nil() )
2047             it = myCurrentStudy->NewChildIterator( mainSO );
2048           if ( !it->_is_nil() ) {
2049             for ( it->InitEx(true); it->More(); it->Next() ) {
2050               GEOM::GEOM_Object_var subGeom =
2051                 GEOM::GEOM_Object::_narrow( SObjectToObject( it->Value() ));
2052               if ( !subGeom->_is_nil() ) {
2053                 GEOM::ListOfLong_var subList = subGeom->GetSubShapeIndices();
2054                 if ( subList->length() == 1 && shapeID == subList[0] ) {
2055                   geom = subGeom;
2056                   break;
2057                 }
2058               }
2059             }
2060           }
2061         }
2062         if ( geom->_is_nil() ) {
2063           // explode
2064           GEOM::GEOM_IShapesOperations_var op =
2065             geomGen->GetIShapesOperations( GetCurrentStudyID() );
2066           if ( !op->_is_nil() )
2067             geom = op->GetSubShape( mainShape, shapeID );
2068         }
2069         if ( !geom->_is_nil() ) {
2070           GeomObjectToShape( geom ); // let geom client remember the found shape
2071           return geom._retn();
2072         }
2073       }
2074     }
2075   }
2076   return GEOM::GEOM_Object::_nil();
2077 }
2078
2079 //================================================================================
2080 /*!
2081  *  SMESH_Gen_i::Concatenate
2082  *
2083  *  Concatenate the given meshes into one mesh
2084  */
2085 //================================================================================
2086
2087 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::Concatenate(const SMESH::mesh_array& theMeshesArray,
2088                                                CORBA::Boolean           theUniteIdenticalGroups,
2089                                                CORBA::Boolean           theMergeNodesAndElements,
2090                                                CORBA::Double            theMergeTolerance)
2091   throw ( SALOME::SALOME_Exception )
2092 {
2093   return ConcatenateCommon(theMeshesArray,
2094                            theUniteIdenticalGroups,
2095                            theMergeNodesAndElements,
2096                            theMergeTolerance,
2097                            false);
2098 }
2099
2100 //================================================================================
2101 /*!
2102  *  SMESH_Gen_i::ConcatenateWithGroups
2103  *
2104  *  Concatenate the given meshes into one mesh
2105  *  Create the groups of all elements from initial meshes
2106  */
2107 //================================================================================
2108
2109 SMESH::SMESH_Mesh_ptr
2110 SMESH_Gen_i::ConcatenateWithGroups(const SMESH::mesh_array& theMeshesArray,
2111                                    CORBA::Boolean           theUniteIdenticalGroups,
2112                                    CORBA::Boolean           theMergeNodesAndElements,
2113                                    CORBA::Double            theMergeTolerance)
2114   throw ( SALOME::SALOME_Exception )
2115 {
2116   return ConcatenateCommon(theMeshesArray,
2117                            theUniteIdenticalGroups,
2118                            theMergeNodesAndElements,
2119                            theMergeTolerance,
2120                            true);
2121 }
2122
2123 //================================================================================
2124 /*!
2125  *  SMESH_Gen_i::ConcatenateCommon
2126  *
2127  *  Concatenate the given meshes into one mesh
2128  */
2129 //================================================================================
2130
2131 SMESH::SMESH_Mesh_ptr
2132 SMESH_Gen_i::ConcatenateCommon(const SMESH::mesh_array& theMeshesArray,
2133                                CORBA::Boolean           theUniteIdenticalGroups,
2134                                CORBA::Boolean           theMergeNodesAndElements,
2135                                CORBA::Double            theMergeTolerance,
2136                                CORBA::Boolean           theCommonGroups)
2137   throw ( SALOME::SALOME_Exception )
2138 {
2139   typedef map<int, int> TIDsMap;
2140   typedef list<SMESH::SMESH_Group_var> TListOfNewGroups;
2141   typedef map< pair<string, SMESH::ElementType>, TListOfNewGroups > TGroupsMap;
2142   typedef std::set<SMESHDS_GroupBase*> TGroups;
2143
2144   TPythonDump* pPythonDump = new TPythonDump;
2145   TPythonDump& aPythonDump = *pPythonDump; // prevent dump of called methods
2146
2147   // create mesh
2148   SMESH::SMESH_Mesh_var aNewMesh = CreateEmptyMesh();
2149
2150   SMESHDS_Mesh* aNewMeshDS = 0;
2151   if ( !aNewMesh->_is_nil() ) {
2152     SMESH_Mesh_i* aNewImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( aNewMesh ).in() );
2153     if ( aNewImpl ) {
2154       ::SMESH_Mesh& aLocMesh = aNewImpl->GetImpl();
2155       aNewMeshDS = aLocMesh.GetMeshDS();
2156
2157       TGroupsMap aGroupsMap;
2158       TListOfNewGroups aListOfNewGroups;
2159       SMESH_MeshEditor aNewEditor = ::SMESH_MeshEditor(&aLocMesh);
2160       SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
2161
2162       // loop on meshes
2163       for ( int i = 0; i < theMeshesArray.length(); i++) {
2164         SMESH::SMESH_Mesh_var anInitMesh = theMeshesArray[i];
2165         if ( !anInitMesh->_is_nil() ) {
2166           SMESH_Mesh_i* anInitImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( anInitMesh ).in() );
2167           if ( anInitImpl ) {
2168             ::SMESH_Mesh& aInitLocMesh = anInitImpl->GetImpl();
2169             SMESHDS_Mesh* anInitMeshDS = aInitLocMesh.GetMeshDS();
2170
2171             TIDsMap nodesMap;
2172             TIDsMap elemsMap;
2173
2174             // loop on elements of mesh
2175             SMDS_ElemIteratorPtr itElems = anInitMeshDS->elementsIterator();
2176             const SMDS_MeshElement* anElem = 0;
2177             const SMDS_MeshElement* aNewElem = 0;
2178             int anElemNbNodes = 0;
2179
2180             int anNbNodes   = 0;
2181             int anNbEdges   = 0;
2182             int anNbFaces   = 0;
2183             int anNbVolumes = 0;
2184
2185             SMESH::long_array_var anIDsNodes   = new SMESH::long_array();
2186             SMESH::long_array_var anIDsEdges   = new SMESH::long_array();
2187             SMESH::long_array_var anIDsFaces   = new SMESH::long_array();
2188             SMESH::long_array_var anIDsVolumes = new SMESH::long_array();
2189
2190             if( theCommonGroups ) {
2191               anIDsNodes->length(   anInitMeshDS->NbNodes()   );
2192               anIDsEdges->length(   anInitMeshDS->NbEdges()   );
2193               anIDsFaces->length(   anInitMeshDS->NbFaces()   );
2194               anIDsVolumes->length( anInitMeshDS->NbVolumes() );
2195             }
2196
2197             for ( int j = 0; itElems->more(); j++) {
2198               anElem = itElems->next();
2199               SMDSAbs_ElementType anElemType = anElem->GetType();
2200               anElemNbNodes = anElem->NbNodes();
2201               std::vector<const SMDS_MeshNode*> aNodesArray (anElemNbNodes);
2202
2203               // loop on nodes of element
2204               const SMDS_MeshNode* aNode = 0;
2205               const SMDS_MeshNode* aNewNode = 0;
2206               SMDS_ElemIteratorPtr itNodes = anElem->nodesIterator();
2207
2208               for ( int k = 0; itNodes->more(); k++) {
2209                 aNode = static_cast<const SMDS_MeshNode*>(itNodes->next());
2210                 if ( nodesMap.find(aNode->GetID()) == nodesMap.end() ) {
2211                   aNewNode = aNewMeshDS->AddNode(aNode->X(), aNode->Y(), aNode->Z());
2212                   nodesMap.insert( make_pair(aNode->GetID(), aNewNode->GetID()) );
2213                   if( theCommonGroups )
2214                     anIDsNodes[anNbNodes++] = aNewNode->GetID();
2215                 }
2216                 else
2217                   aNewNode = aNewMeshDS->FindNode( nodesMap.find(aNode->GetID())->second );
2218                 aNodesArray[k] = aNewNode;
2219               }//nodes loop
2220
2221               // creates a corresponding element on existent nodes in new mesh
2222               if ( anElem->IsPoly() && anElemType == SMDSAbs_Volume )
2223                 {
2224                   const SMDS_VtkVolume* aVolume =
2225                     dynamic_cast<const SMDS_VtkVolume*> (anElem);
2226                   if ( aVolume ) {
2227                     aNewElem = aNewMeshDS->AddPolyhedralVolume(aNodesArray,
2228                                                                aVolume->GetQuantities());
2229                     elemsMap.insert(make_pair(anElem->GetID(), aNewElem->GetID()));
2230                     if( theCommonGroups )
2231                       anIDsVolumes[anNbVolumes++] = aNewElem->GetID();
2232                   }
2233                 }
2234               else {
2235
2236                 aNewElem = aNewEditor.AddElement(aNodesArray,
2237                                                  anElemType,
2238                                                  anElem->IsPoly());
2239                 elemsMap.insert(make_pair(anElem->GetID(), aNewElem->GetID()));
2240                 if( theCommonGroups ) {
2241                   if( anElemType == SMDSAbs_Edge )
2242                     anIDsEdges[anNbEdges++] = aNewElem->GetID();
2243                   else if( anElemType == SMDSAbs_Face )
2244                     anIDsFaces[anNbFaces++] = aNewElem->GetID();
2245                   else if( anElemType == SMDSAbs_Volume )
2246                     anIDsVolumes[anNbVolumes++] = aNewElem->GetID();
2247                 }
2248               }
2249             }//elems loop
2250
2251             // copy orphan nodes
2252             SMDS_NodeIteratorPtr  itNodes = anInitMeshDS->nodesIterator();
2253             while ( itNodes->more() )
2254             {
2255               const SMDS_MeshNode* aNode = itNodes->next();
2256               if ( aNode->NbInverseElements() == 0 )
2257               {
2258                 const SMDS_MeshNode* aNewNode =
2259                   aNewMeshDS->AddNode(aNode->X(), aNode->Y(), aNode->Z());
2260                 nodesMap.insert( make_pair(aNode->GetID(), aNewNode->GetID()) );
2261                 if( theCommonGroups )
2262                   anIDsNodes[anNbNodes++] = aNewNode->GetID();
2263               }
2264             }
2265
2266
2267             aListOfGroups = anInitImpl->GetGroups();
2268             SMESH::SMESH_GroupBase_ptr aGroup;
2269
2270             // loop on groups of mesh
2271             SMESH::long_array_var anInitIDs = new SMESH::long_array();
2272             SMESH::long_array_var anNewIDs = new SMESH::long_array();
2273             SMESH::SMESH_Group_var aNewGroup;
2274
2275             SMESH::ElementType aGroupType;
2276             CORBA::String_var aGroupName;
2277             if ( theCommonGroups ) {
2278               for(aGroupType=SMESH::NODE;aGroupType<=SMESH::VOLUME;aGroupType=(SMESH::ElementType)(aGroupType+1)) {
2279                 string str = "Gr";
2280                 SALOMEDS::SObject_var aMeshSObj = ObjectToSObject( myCurrentStudy, anInitMesh );
2281                 if(aMeshSObj)
2282                   str += aMeshSObj->GetName();
2283                 str += "_";
2284
2285                 int anLen = 0;
2286
2287                 switch(aGroupType) {
2288                 case SMESH::NODE:
2289                   str += "Nodes";
2290                   anIDsNodes->length(anNbNodes);
2291                   anLen = anNbNodes;
2292                   break;
2293                 case SMESH::EDGE:
2294                   str += "Edges";
2295                   anIDsEdges->length(anNbEdges);
2296                   anLen = anNbEdges;
2297                   break;
2298                 case SMESH::FACE:
2299                   str += "Faces";
2300                   anIDsFaces->length(anNbFaces);
2301                   anLen = anNbFaces;
2302                   break;
2303                 case SMESH::VOLUME:
2304                   str += "Volumes";
2305                   anIDsVolumes->length(anNbVolumes);
2306                   anLen = anNbVolumes;
2307                   break;
2308                 default:
2309                   break;
2310                 }
2311
2312                 if(anLen) {
2313                   aGroupName = str.c_str();
2314
2315                   // add a new group in the mesh
2316                   aNewGroup = aNewImpl->CreateGroup(aGroupType, aGroupName);
2317
2318                   switch(aGroupType) {
2319                   case SMESH::NODE:
2320                     aNewGroup->Add( anIDsNodes );
2321                     break;
2322                   case SMESH::EDGE:
2323                     aNewGroup->Add( anIDsEdges );
2324                     break;
2325                   case SMESH::FACE:
2326                     aNewGroup->Add( anIDsFaces );
2327                     break;
2328                   case SMESH::VOLUME:
2329                     aNewGroup->Add( anIDsVolumes );
2330                     break;
2331                   default:
2332                     break;
2333                   }
2334
2335                   aListOfNewGroups.clear();
2336                   aListOfNewGroups.push_back(aNewGroup);
2337                   aGroupsMap.insert(make_pair( make_pair(aGroupName, aGroupType), aListOfNewGroups ));
2338                 }
2339               }
2340             }
2341
2342             // check that current group name and type don't have identical ones in union mesh
2343             for (int i = 0; i < aListOfGroups->length(); i++) {
2344               aGroup = aListOfGroups[i];
2345               aListOfNewGroups.clear();
2346               aGroupType = aGroup->GetType();
2347               aGroupName = aGroup->GetName();
2348
2349               TGroupsMap::iterator anIter = aGroupsMap.find(make_pair(aGroupName, aGroupType));
2350
2351               // convert a list of IDs
2352               anInitIDs = aGroup->GetListOfID();
2353               anNewIDs->length(anInitIDs->length());
2354               if ( aGroupType == SMESH::NODE )
2355                 for (int j = 0; j < anInitIDs->length(); j++) {
2356                   anNewIDs[j] = nodesMap.find(anInitIDs[j])->second;
2357                 }
2358               else
2359                 for (int j = 0; j < anInitIDs->length(); j++) {
2360                   anNewIDs[j] = elemsMap.find(anInitIDs[j])->second;
2361                 }
2362
2363               // check that current group name and type don't have identical ones in union mesh
2364               if ( anIter == aGroupsMap.end() ) {
2365                 // add a new group in the mesh
2366                 aNewGroup = aNewImpl->CreateGroup(aGroupType, aGroupName);
2367                 // add elements into new group
2368                 aNewGroup->Add( anNewIDs );
2369
2370                 aListOfNewGroups.push_back(aNewGroup);
2371                 aGroupsMap.insert(make_pair( make_pair(aGroupName, aGroupType), aListOfNewGroups ));
2372               }
2373
2374               else if ( theUniteIdenticalGroups ) {
2375                 // unite identical groups
2376                 TListOfNewGroups& aNewGroups = anIter->second;
2377                 aNewGroups.front()->Add( anNewIDs );
2378               }
2379
2380               else {
2381                 // rename identical groups
2382                 aNewGroup = aNewImpl->CreateGroup(aGroupType, aGroupName);
2383                 aNewGroup->Add( anNewIDs );
2384
2385                 TListOfNewGroups& aNewGroups = anIter->second;
2386                 string aNewGroupName;
2387                 if (aNewGroups.size() == 1) {
2388                   aNewGroupName = string(aGroupName) + "_1";
2389                   aNewGroups.front()->SetName(aNewGroupName.c_str());
2390                 }
2391                 char aGroupNum[128];
2392                 sprintf(aGroupNum, "%u", aNewGroups.size()+1);
2393                 aNewGroupName = string(aGroupName) + "_" + string(aGroupNum);
2394                 aNewGroup->SetName(aNewGroupName.c_str());
2395                 aNewGroups.push_back(aNewGroup);
2396               }
2397             }//groups loop
2398           }
2399         }
2400       }//meshes loop
2401
2402       if (theMergeNodesAndElements) {
2403         // merge nodes
2404         TIDSortedNodeSet aMeshNodes; // no input nodes
2405         SMESH_MeshEditor::TListOfListOfNodes aGroupsOfNodes;
2406         aNewEditor.FindCoincidentNodes( aMeshNodes, theMergeTolerance, aGroupsOfNodes );
2407         aNewEditor.MergeNodes( aGroupsOfNodes );
2408         // merge elements
2409         aNewEditor.MergeEqualElements();
2410       }
2411     }
2412   }
2413
2414   // Update Python script
2415   aPythonDump << aNewMesh << " = " << this;
2416   if( !theCommonGroups )
2417     aPythonDump << ".Concatenate(";
2418   else
2419     aPythonDump << ".ConcatenateWithGroups(";
2420   aPythonDump << "[";
2421   for ( int i = 0; i < theMeshesArray.length(); i++) {
2422     if (i > 0) aPythonDump << ", ";
2423     aPythonDump << theMeshesArray[i];
2424   }
2425   aPythonDump << "], ";
2426   aPythonDump << theUniteIdenticalGroups << ", "
2427               << theMergeNodesAndElements << ", "
2428               << theMergeTolerance << ")";
2429
2430   delete pPythonDump; // enable python dump from GetGroups()
2431
2432   // 0020577: EDF 1164 SMESH: Bad dump of concatenate with create common groups
2433   if ( !aNewMesh->_is_nil() )
2434   {
2435     SMESH::ListOfGroups_var groups = aNewMesh->GetGroups();
2436   }
2437
2438   // IPAL21468 Change icon of compound because it need not be computed.
2439   SALOMEDS::SObject_var aMeshSObj = ObjectToSObject( myCurrentStudy, aNewMesh );
2440   if( !aMeshSObj->_is_nil() ) {
2441     SALOMEDS::GenericAttribute_var anAttr;
2442     SALOMEDS::StudyBuilder_var aBuilder = myCurrentStudy->NewBuilder();
2443     anAttr = aBuilder->FindOrCreateAttribute( aMeshSObj,"AttributePixMap" );
2444     SALOMEDS::AttributePixMap_var aPixmap = SALOMEDS::AttributePixMap::_narrow(anAttr);
2445     aPixmap->SetPixMap("ICON_SMESH_TREE_MESH");
2446   }
2447   if (aNewMeshDS)
2448     aNewMeshDS->Modified();
2449   return aNewMesh._retn();
2450 }
2451
2452 //================================================================================
2453 /*!
2454  * \brief Create a mesh by copying a part of another mesh
2455  *  \param meshPart - a part of mesh to copy
2456  *  \param toCopyGroups - to create in the new mesh groups
2457  *                        the copied elements belongs to
2458  *  \param toKeepIDs - to preserve IDs of the copied elements or not
2459  *  \retval SMESH::SMESH_Mesh_ptr - the new mesh
2460  */
2461 //================================================================================
2462
2463 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
2464                                             const char*               meshName,
2465                                             CORBA::Boolean            toCopyGroups,
2466                                             CORBA::Boolean            toKeepIDs)
2467 {
2468   Unexpect aCatch(SALOME_SalomeException);
2469
2470   TPythonDump* pyDump = new TPythonDump; // prevent dump from CreateMesh()
2471
2472   // 1. Get source mesh
2473
2474   if ( CORBA::is_nil( meshPart ))
2475     THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM );
2476
2477   SMESH::SMESH_Mesh_var srcMesh = meshPart->GetMesh();
2478   SMESH_Mesh_i*       srcMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( srcMesh );
2479   if ( !srcMesh_i )
2480     THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM );
2481
2482   SMESHDS_Mesh* srcMeshDS = srcMesh_i->GetImpl().GetMeshDS();
2483
2484   // 2. Make a new mesh
2485
2486   SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil());
2487   SMESH_Mesh_i*       newMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( newMesh );
2488   if ( !newMesh_i )
2489     THROW_SALOME_CORBA_EXCEPTION( "can't create a mesh", SALOME::INTERNAL_ERROR );
2490   SALOMEDS::SObject_var meshSO = ObjectToSObject(myCurrentStudy, newMesh );
2491   if ( !meshSO->_is_nil() )
2492   {
2493     SetName( meshSO, meshName, "Mesh" );
2494     SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
2495   }
2496   SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS();
2497   ::SMESH_MeshEditor editor( &newMesh_i->GetImpl() );
2498
2499   // 3. Get elements to copy
2500
2501   SMDS_ElemIteratorPtr srcElemIt; SMDS_NodeIteratorPtr srcNodeIt;
2502   TIDSortedElemSet srcElems;
2503   SMESH::array_of_ElementType_var srcElemTypes = meshPart->GetTypes();
2504   if ( SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
2505   {
2506     srcElemIt = srcMeshDS->elementsIterator();
2507     srcNodeIt = srcMeshDS->nodesIterator();
2508   }
2509   else
2510   {
2511     SMESH::long_array_var ids = meshPart->GetIDs();
2512     if ( srcElemTypes->length() == 1 && srcElemTypes[0] == SMESH::NODE ) // group of nodes
2513     {
2514       for (int i=0; i < ids->length(); i++)
2515         if ( const SMDS_MeshElement * elem = srcMeshDS->FindNode( ids[i] ))
2516           srcElems.insert( elem );
2517     }
2518     else
2519     {
2520       for (int i=0; i < ids->length(); i++)
2521         if ( const SMDS_MeshElement * elem = srcMeshDS->FindElement( ids[i] ))
2522           srcElems.insert( elem );
2523     }
2524     if ( srcElems.empty() )
2525       return newMesh._retn();
2526
2527     typedef SMDS_SetIterator< SMDS_pElement, TIDSortedElemSet::const_iterator > ElIter;
2528     srcElemIt = SMDS_ElemIteratorPtr( new ElIter( srcElems.begin(), srcElems.end() ));
2529   }
2530
2531   // 4. Copy elements
2532
2533   typedef map<SMDS_pElement, SMDS_pElement, TIDCompare> TE2EMap;
2534   TE2EMap e2eMapByType[ SMDSAbs_NbElementTypes ];
2535   TE2EMap& n2nMap = e2eMapByType[ SMDSAbs_Node ];
2536   int iN;
2537   const SMDS_MeshNode *nSrc, *nTgt;
2538   vector< const SMDS_MeshNode* > nodes;
2539   while ( srcElemIt->more() )
2540   {
2541     const SMDS_MeshElement * elem = srcElemIt->next();
2542     nodes.resize( elem->NbNodes());
2543     SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
2544     if ( toKeepIDs ) {
2545       for ( iN = 0; nIt->more(); ++iN )
2546       {
2547         nSrc = static_cast<const SMDS_MeshNode*>( nIt->next() );
2548         nTgt = newMeshDS->FindNode( nSrc->GetID());
2549         if ( !nTgt )
2550           nTgt = newMeshDS->AddNodeWithID( nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID());
2551         nodes[ iN ] = nTgt;
2552       }
2553     }
2554     else {
2555       for ( iN = 0; nIt->more(); ++iN )
2556       {
2557         nSrc = static_cast<const SMDS_MeshNode*>( nIt->next() );
2558         TE2EMap::iterator n2n = n2nMap.insert( make_pair( nSrc, SMDS_pNode(0) )).first;
2559         if ( !n2n->second )
2560           n2n->second = newMeshDS->AddNode( nSrc->X(), nSrc->Y(), nSrc->Z() );
2561         nodes[ iN ] = (const SMDS_MeshNode*) n2n->second;
2562       }
2563     }
2564     if ( elem->GetType() != SMDSAbs_Node )
2565     {
2566       int ID = toKeepIDs ? elem->GetID() : 0;
2567       const SMDS_MeshElement * newElem;
2568       if ( elem->GetEntityType() == SMDSEntity_Polyhedra )
2569         newElem = editor.GetMeshDS()->
2570           AddPolyhedralVolumeWithID( nodes,
2571                                      static_cast<const SMDS_VtkVolume*>(elem)->GetQuantities(),
2572                                      elem->GetID());
2573       else
2574         newElem = editor.AddElement( nodes,elem->GetType(),elem->IsPoly(),ID);
2575
2576       if ( toCopyGroups && !toKeepIDs )
2577         e2eMapByType[ elem->GetType() ].insert( make_pair( elem, newElem ));
2578     }
2579   }
2580
2581   // 4(b). Copy free nodes
2582
2583   if ( srcNodeIt && srcMeshDS->NbNodes() != newMeshDS->NbNodes() )
2584   {
2585     while ( srcNodeIt->more() )
2586     {
2587       nSrc = srcNodeIt->next();
2588       if ( nSrc->NbInverseElements() == 0 )
2589       {
2590         if ( toKeepIDs )
2591           nTgt = newMeshDS->AddNodeWithID( nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID());
2592         else
2593           n2nMap[ nSrc ] = newMeshDS->AddNode( nSrc->X(), nSrc->Y(), nSrc->Z() );
2594       }
2595     }
2596   }
2597
2598   // 5. Copy groups
2599
2600   int nbNewGroups = 0;
2601   if ( toCopyGroups )
2602   {
2603     SMESH_Mesh::GroupIteratorPtr gIt = srcMesh_i->GetImpl().GetGroups();
2604     while ( gIt->more() )
2605     {
2606       SMESH_Group* group = gIt->next();
2607       const SMESHDS_GroupBase* groupDS = group->GetGroupDS();
2608
2609       // Check group type. We copy nodal groups containing nodes of copied element
2610       SMDSAbs_ElementType groupType = groupDS->GetType();
2611       if ( groupType != SMDSAbs_Node &&
2612            newMeshDS->GetMeshInfo().NbElements( groupType ) == 0 )
2613         continue; // group type differs from types of meshPart
2614
2615       // Find copied elements in the group
2616       vector< const SMDS_MeshElement* > groupElems;
2617       SMDS_ElemIteratorPtr eIt = groupDS->GetElements();
2618       if ( toKeepIDs )
2619       {
2620         const SMDS_MeshElement* foundElem;
2621         if ( groupType == SMDSAbs_Node )
2622         {
2623           while ( eIt->more() )
2624             if (( foundElem = newMeshDS->FindNode( eIt->next()->GetID() )))
2625               groupElems.push_back( foundElem );
2626         }
2627         else
2628         {
2629           while ( eIt->more() )
2630             if (( foundElem = newMeshDS->FindElement( eIt->next()->GetID() )))
2631               groupElems.push_back( foundElem );
2632         }
2633       }
2634       else
2635       {
2636         TE2EMap & e2eMap = e2eMapByType[ groupDS->GetType() ];
2637         if ( e2eMap.empty() ) continue;
2638         int minID = e2eMap.begin()->first->GetID();
2639         int maxID = e2eMap.rbegin()->first->GetID();
2640         TE2EMap::iterator e2e;
2641         while ( eIt->more() && groupElems.size() < e2eMap.size())
2642         {
2643           const SMDS_MeshElement* e = eIt->next();
2644           if ( e->GetID() < minID || e->GetID() > maxID ) continue;
2645           if ((e2e = e2eMap.find( e )) != e2eMap.end())
2646             groupElems.push_back( e2e->second );
2647         }
2648       }
2649       // Make a new group
2650       if ( !groupElems.empty() )
2651       {
2652         SMESH::SMESH_Group_var newGroupObj =
2653           newMesh->CreateGroup( SMESH::ElementType(groupType), group->GetName() );
2654         if ( SMESH_GroupBase_i* newGroup_i = SMESH::DownCast<SMESH_GroupBase_i*>( newGroupObj))
2655         {
2656           SMESHDS_GroupBase * newGroupDS = newGroup_i->GetGroupDS();
2657           SMDS_MeshGroup& smdsGroup = ((SMESHDS_Group*)newGroupDS)->SMDSGroup();
2658           for ( unsigned i = 0; i < groupElems.size(); ++i )
2659             smdsGroup.Add( groupElems[i] );
2660
2661           nbNewGroups++;
2662         }
2663       }
2664     }
2665   }
2666
2667   newMeshDS->Modified();
2668
2669   *pyDump << newMesh << " = " << this
2670           << ".CopyMesh( " << meshPart << ", "
2671           << "'" << meshName << "', "
2672           << toCopyGroups << ", "
2673           << toKeepIDs << ")";
2674
2675   delete pyDump; pyDump = 0; // allow dump in GetGroups()
2676
2677   if ( nbNewGroups > 0 ) // dump created groups
2678     SMESH::ListOfGroups_var groups = newMesh->GetGroups();
2679
2680   return newMesh._retn();
2681 }
2682
2683 //================================================================================
2684 /*!
2685  *  SMESH_Gen_i::GetMEDVersion
2686  *
2687  *  Get MED version of the file by its name
2688  */
2689 //================================================================================
2690 CORBA::Boolean SMESH_Gen_i::GetMEDVersion(const char* theFileName,
2691                                           SMESH::MED_VERSION& theVersion)
2692 {
2693   theVersion = SMESH::MED_V2_1;
2694   MED::EVersion aVersion = MED::GetVersionId( theFileName );
2695   switch( aVersion ) {
2696     case MED::eV2_1     : theVersion = SMESH::MED_V2_1; return true;
2697     case MED::eV2_2     : theVersion = SMESH::MED_V2_2; return true;
2698     case MED::eVUnknown : return false;
2699   }
2700   return false;
2701 }
2702
2703 //================================================================================
2704 /*!
2705  *  SMESH_Gen_i::GetMeshNames
2706  *
2707  *  Get names of meshes defined in file with the specified name
2708  */
2709 //================================================================================
2710 SMESH::string_array* SMESH_Gen_i::GetMeshNames(const char* theFileName)
2711 {
2712   SMESH::string_array_var aResult = new SMESH::string_array();
2713   MED::PWrapper aMed = MED::CrWrapper( theFileName );
2714   MED::TErr anErr;
2715   MED::TInt aNbMeshes = aMed->GetNbMeshes( &anErr );
2716   if( anErr >= 0 ) {
2717     aResult->length( aNbMeshes );
2718     for( MED::TInt i = 0; i < aNbMeshes; i++ ) {
2719       MED::PMeshInfo aMeshInfo = aMed->GetPMeshInfo( i+1 );
2720       aResult[i] = CORBA::string_dup( aMeshInfo->GetName().c_str() );
2721     }
2722   }
2723   return aResult._retn();
2724 }
2725
2726 //=============================================================================
2727 /*!
2728  *  SMESH_Gen_i::Save
2729  *
2730  *  Save SMESH module's data
2731  */
2732 //=============================================================================
2733 SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
2734                                       const char*              theURL,
2735                                       bool                     isMultiFile )
2736 {
2737   INFOS( "SMESH_Gen_i::Save" );
2738
2739   //  ASSERT( theComponent->GetStudy()->StudyId() == myCurrentStudy->StudyId() )
2740   // san -- in case <myCurrentStudy> differs from theComponent's study,
2741   // use that of the component
2742   if ( myCurrentStudy->_is_nil() ||
2743     theComponent->GetStudy()->StudyId() != myCurrentStudy->StudyId() )
2744     SetCurrentStudy( theComponent->GetStudy() );
2745
2746   // Store study contents as a set of python commands
2747   SavePython(myCurrentStudy);
2748
2749   StudyContext* myStudyContext = GetCurrentStudyContext();
2750
2751   // Declare a byte stream
2752   SALOMEDS::TMPFile_var aStreamFile;
2753
2754   // Obtain a temporary dir
2755   TCollection_AsciiString tmpDir =
2756     ( isMultiFile ) ? TCollection_AsciiString( ( char* )theURL ) : ( char* )SALOMEDS_Tool::GetTmpDir().c_str();
2757
2758   // Create a sequence of files processed
2759   SALOMEDS::ListOfFileNames_var aFileSeq = new SALOMEDS::ListOfFileNames;
2760   aFileSeq->length( NUM_TMP_FILES );
2761
2762   TCollection_AsciiString aStudyName( "" );
2763   if ( isMultiFile )
2764     aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( myCurrentStudy->URL() ).c_str() );
2765
2766   // Set names of temporary files
2767   TCollection_AsciiString filename =
2768     aStudyName + TCollection_AsciiString( "_SMESH.hdf" );        // for SMESH data itself
2769   TCollection_AsciiString meshfile =
2770     aStudyName + TCollection_AsciiString( "_SMESH_Mesh.med" );   // for mesh data to be stored in MED file
2771   aFileSeq[ 0 ] = CORBA::string_dup( filename.ToCString() );
2772   aFileSeq[ 1 ] = CORBA::string_dup( meshfile.ToCString() );
2773   filename = tmpDir + filename;
2774   meshfile = tmpDir + meshfile;
2775
2776   HDFfile*    aFile;
2777   HDFdataset* aDataset;
2778   HDFgroup*   aTopGroup;
2779   HDFgroup*   aGroup;
2780   HDFgroup*   aSubGroup;
2781   HDFgroup*   aSubSubGroup;
2782   hdf_size    aSize[ 1 ];
2783
2784
2785   //Remove the files if they exist: BugID: 11225
2786 #ifndef WNT /* unix functionality */
2787   TCollection_AsciiString cmd("rm -f \"");
2788 #else /* windows */
2789   TCollection_AsciiString cmd("del /F \"");
2790 #endif
2791
2792   cmd+=filename;
2793   cmd+="\" \"";
2794   cmd+=meshfile;
2795   cmd+="\"";
2796   system(cmd.ToCString());
2797
2798   // MED writer to be used by storage process
2799   DriverMED_W_SMESHDS_Mesh myWriter;
2800   myWriter.SetFile( meshfile.ToCString() );
2801
2802   // IMP issue 20918
2803   // SetStoreName() to groups before storing hypotheses to let them refer to
2804   // groups using "store name", which is "Group <group_persistent_id>"
2805   {
2806     SALOMEDS::ChildIterator_var itBig = myCurrentStudy->NewChildIterator( theComponent );
2807     for ( ; itBig->More(); itBig->Next() ) {
2808       SALOMEDS::SObject_var gotBranch = itBig->Value();
2809       if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) {
2810         CORBA::Object_var anObject = SObjectToObject( gotBranch );
2811         if ( !CORBA::is_nil( anObject ) ) {
2812           SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ;
2813           if ( !myMesh->_is_nil() ) {
2814             myMesh->Load(); // load from study file if not yet done
2815             TPythonDump pd; // not to dump GetGroups()
2816             SMESH::ListOfGroups_var groups = myMesh->GetGroups();
2817             pd << ""; // to avoid optimizing pd out
2818             for ( int i = 0; i < groups->length(); ++i )
2819             {
2820               SMESH_GroupBase_i* grImpl = SMESH::DownCast<SMESH_GroupBase_i*>( groups[i]);
2821               if ( grImpl )
2822               {
2823                 CORBA::String_var objStr = GetORB()->object_to_string( grImpl->_this() );
2824                 int anId = myStudyContext->findId( string( objStr.in() ) );
2825                 char grpName[ 30 ];
2826                 sprintf( grpName, "Group %d", anId );
2827                 SMESHDS_GroupBase* aGrpBaseDS = grImpl->GetGroupDS();
2828                 aGrpBaseDS->SetStoreName( grpName );
2829               }
2830             }
2831           }
2832         }
2833       }
2834     }
2835   }
2836
2837   // Write data
2838   // ---> create HDF file
2839   aFile = new HDFfile( (char*) filename.ToCString() );
2840   aFile->CreateOnDisk();
2841
2842   // --> iterator for top-level objects
2843   SALOMEDS::ChildIterator_var itBig = myCurrentStudy->NewChildIterator( theComponent );
2844   for ( ; itBig->More(); itBig->Next() ) {
2845     SALOMEDS::SObject_var gotBranch = itBig->Value();
2846
2847     // --> hypotheses root branch (only one for the study)
2848     if ( gotBranch->Tag() == GetHypothesisRootTag() ) {
2849       // create hypotheses root HDF group
2850       aTopGroup = new HDFgroup( "Hypotheses", aFile );
2851       aTopGroup->CreateOnDisk();
2852
2853       // iterator for all hypotheses
2854       SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( gotBranch );
2855       for ( ; it->More(); it->Next() ) {
2856         SALOMEDS::SObject_var mySObject = it->Value();
2857         CORBA::Object_var anObject = SObjectToObject( mySObject );
2858         if ( !CORBA::is_nil( anObject ) ) {
2859           SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject );
2860           if ( !myHyp->_is_nil() ) {
2861             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
2862             if ( myImpl ) {
2863               string hypname = string( myHyp->GetName() );
2864               string libname = string( myHyp->GetLibName() );
2865               // BUG SWP13062
2866               // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for
2867               // WNT and ".so" for X-system) must be deleted
2868               int libname_len = libname.length();
2869 #ifdef WNT
2870               if( libname_len > 4 )
2871                 libname.resize( libname_len - 4 );
2872 #else
2873               // PAL17753 (Regresion: missing hypothesis in restored study)
2874               // "lib" also should be removed from the beginning
2875               //if( libname_len > 3 )
2876                 //libname.resize( libname_len - 3 );
2877               if( libname_len > 6 )
2878                 libname = libname.substr( 3, libname_len - 3 - 3 );
2879 #endif
2880               CORBA::String_var objStr = GetORB()->object_to_string( anObject );
2881               int    id      = myStudyContext->findId( string( objStr.in() ) );
2882               string hypdata = string( myImpl->SaveTo() );
2883
2884               // for each hypothesis create HDF group basing on its id
2885               char hypGrpName[30];
2886               sprintf( hypGrpName, "Hypothesis %d", id );
2887               aGroup = new HDFgroup( hypGrpName, aTopGroup );
2888               aGroup->CreateOnDisk();
2889               // --> type name of hypothesis
2890               aSize[ 0 ] = hypname.length() + 1;
2891               aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 );
2892               aDataset->CreateOnDisk();
2893               aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) );
2894               aDataset->CloseOnDisk();
2895               // --> server plugin library name of hypothesis
2896               aSize[ 0 ] = libname.length() + 1;
2897               aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 );
2898               aDataset->CreateOnDisk();
2899               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
2900               aDataset->CloseOnDisk();
2901               // --> persistent data of hypothesis
2902               aSize[ 0 ] = hypdata.length() + 1;
2903               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
2904               aDataset->CreateOnDisk();
2905               aDataset->WriteOnDisk( ( char* )( hypdata.c_str() ) );
2906               aDataset->CloseOnDisk();
2907               // close hypothesis HDF group
2908               aGroup->CloseOnDisk();
2909             }
2910           }
2911         }
2912       }
2913       // close hypotheses root HDF group
2914       aTopGroup->CloseOnDisk();
2915     }
2916     // --> algorithms root branch (only one for the study)
2917     else if ( gotBranch->Tag() == GetAlgorithmsRootTag() ) {
2918       // create algorithms root HDF group
2919       aTopGroup = new HDFgroup( "Algorithms", aFile );
2920       aTopGroup->CreateOnDisk();
2921
2922       // iterator for all algorithms
2923       SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( gotBranch );
2924       for ( ; it->More(); it->Next() ) {
2925         SALOMEDS::SObject_var mySObject = it->Value();
2926         CORBA::Object_var anObject = SObjectToObject( mySObject );
2927         if ( !CORBA::is_nil( anObject ) ) {
2928           SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject );
2929           if ( !myHyp->_is_nil() ) {
2930             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
2931             if ( myImpl ) {
2932               string hypname = string( myHyp->GetName() );
2933               string libname = string( myHyp->GetLibName() );
2934               // BUG SWP13062
2935               // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for
2936               // WNT and ".so" for X-system) must be deleted
2937               int libname_len = libname.length();
2938 #ifdef WNT
2939               if( libname_len > 4 )
2940                 libname.resize( libname_len - 4 );
2941 #else
2942               // PAL17753 (Regresion: missing hypothesis in restored study)
2943               // "lib" also should be removed from the beginning
2944               //if( libname_len > 3 )
2945                 //libname.resize( libname_len - 3 );
2946               if( libname_len > 6 )
2947                 libname = libname.substr( 3, libname_len - 3 - 3 );
2948 #endif
2949               CORBA::String_var objStr = GetORB()->object_to_string( anObject );
2950               int    id      = myStudyContext->findId( string( objStr.in() ) );
2951               string hypdata = string( myImpl->SaveTo() );
2952
2953               // for each algorithm create HDF group basing on its id
2954               char hypGrpName[30];
2955               sprintf( hypGrpName, "Algorithm %d", id );
2956               aGroup = new HDFgroup( hypGrpName, aTopGroup );
2957               aGroup->CreateOnDisk();
2958               // --> type name of algorithm
2959               aSize[0] = hypname.length() + 1;
2960               aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 );
2961               aDataset->CreateOnDisk();
2962               aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) );
2963               aDataset->CloseOnDisk();
2964               // --> server plugin library name of hypothesis
2965               aSize[0] = libname.length() + 1;
2966               aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 );
2967               aDataset->CreateOnDisk();
2968               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
2969               aDataset->CloseOnDisk();
2970               // --> persistent data of algorithm
2971               aSize[0] = hypdata.length() + 1;
2972               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
2973               aDataset->CreateOnDisk();
2974               aDataset->WriteOnDisk( ( char* )( hypdata.c_str() ) );
2975               aDataset->CloseOnDisk();
2976               // close algorithm HDF group
2977               aGroup->CloseOnDisk();
2978             }
2979           }
2980         }
2981       }
2982       // close algorithms root HDF group
2983       aTopGroup->CloseOnDisk();
2984     }
2985     // --> mesh objects roots branches
2986     else if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) {
2987       CORBA::Object_var anObject = SObjectToObject( gotBranch );
2988       if ( !CORBA::is_nil( anObject ) ) {
2989         SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ;
2990         if ( !myMesh->_is_nil() ) {
2991           SMESH_Mesh_i* myImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( myMesh ).in() );
2992           if ( myImpl ) {
2993             CORBA::String_var objStr = GetORB()->object_to_string( anObject );
2994             int id = myStudyContext->findId( string( objStr.in() ) );
2995             ::SMESH_Mesh& myLocMesh = myImpl->GetImpl();
2996             SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS();
2997             bool hasShape = myLocMesh.HasShapeToMesh();
2998
2999             // for each mesh open the HDF group basing on its id
3000             char meshGrpName[ 30 ];
3001             sprintf( meshGrpName, "Mesh %d", id );
3002             aTopGroup = new HDFgroup( meshGrpName, aFile );
3003             aTopGroup->CreateOnDisk();
3004
3005             // --> put dataset to hdf file which is a flag that mesh has data
3006             string strHasData = "0";
3007             // check if the mesh is not empty
3008             if ( mySMESHDSMesh->NbNodes() > 0 ) {
3009               // write mesh data to med file
3010               myWriter.SetMesh( mySMESHDSMesh );
3011               myWriter.SetMeshId( id );
3012               strHasData = "1";
3013             }
3014             aSize[ 0 ] = strHasData.length() + 1;
3015             aDataset = new HDFdataset( "Has data", aTopGroup, HDF_STRING, aSize, 1 );
3016             aDataset->CreateOnDisk();
3017             aDataset->WriteOnDisk( ( char* )( strHasData.c_str() ) );
3018             aDataset->CloseOnDisk();
3019
3020             // ouv : NPAL12872
3021             // for each mesh open the HDF group basing on its auto color parameter
3022             char meshAutoColorName[ 30 ];
3023             sprintf( meshAutoColorName, "AutoColorMesh %d", id );
3024             int anAutoColor[1];
3025             anAutoColor[0] = myImpl->GetAutoColor();
3026             aSize[ 0 ] = 1;
3027             aDataset = new HDFdataset( meshAutoColorName, aTopGroup, HDF_INT32, aSize, 1 );
3028             aDataset->CreateOnDisk();
3029             aDataset->WriteOnDisk( anAutoColor );
3030             aDataset->CloseOnDisk();
3031
3032             // issue 0020693. Store _isModified flag
3033             int isModified = myLocMesh.GetIsModified();
3034             aSize[ 0 ] = 1;
3035             aDataset = new HDFdataset( "_isModified", aTopGroup, HDF_INT32, aSize, 1 );
3036             aDataset->CreateOnDisk();
3037             aDataset->WriteOnDisk( &isModified );
3038             aDataset->CloseOnDisk();
3039
3040             // issue 20918. Store Persistent Id of SMESHDS_Mesh
3041             int meshPersistentId = mySMESHDSMesh->GetPersistentId();
3042             aSize[ 0 ] = 1;
3043             aDataset = new HDFdataset( "meshPersistentId", aTopGroup, HDF_INT32, aSize, 1 );
3044             aDataset->CreateOnDisk();
3045             aDataset->WriteOnDisk( &meshPersistentId );
3046             aDataset->CloseOnDisk();
3047
3048             // write reference on a shape if exists
3049             SALOMEDS::SObject_var myRef;
3050             bool shapeRefFound = false;
3051             bool found = gotBranch->FindSubObject( GetRefOnShapeTag(), myRef );
3052             if ( found ) {
3053               SALOMEDS::SObject_var myShape;
3054               bool ok = myRef->ReferencedObject( myShape );
3055               if ( ok ) {
3056                 shapeRefFound = (! CORBA::is_nil( myShape->GetObject() ));
3057                 string myRefOnObject = myShape->GetID();
3058                 if ( shapeRefFound && myRefOnObject.length() > 0 ) {
3059                   aSize[ 0 ] = myRefOnObject.length() + 1;
3060                   aDataset = new HDFdataset( "Ref on shape", aTopGroup, HDF_STRING, aSize, 1 );
3061                   aDataset->CreateOnDisk();
3062                   aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3063                   aDataset->CloseOnDisk();
3064                 }
3065               }
3066             }
3067
3068             // write applied hypotheses if exist
3069             SALOMEDS::SObject_var myHypBranch;
3070             found = gotBranch->FindSubObject( GetRefOnAppliedHypothesisTag(), myHypBranch );
3071             if ( found && !shapeRefFound && hasShape) { // remove applied hyps
3072               myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( myHypBranch );
3073             }
3074             if ( found && (shapeRefFound || !hasShape) ) {
3075               aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup );
3076               aGroup->CreateOnDisk();
3077
3078               SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( myHypBranch );
3079               int hypNb = 0;
3080               for ( ; it->More(); it->Next() ) {
3081                 SALOMEDS::SObject_var mySObject = it->Value();
3082                 SALOMEDS::SObject_var myRefOnHyp;
3083                 bool ok = mySObject->ReferencedObject( myRefOnHyp );
3084                 if ( ok ) {
3085                   // san - it is impossible to recover applied hypotheses
3086                   //       using their entries within Load() method,
3087                   // for there are no AttributeIORs in the study when Load() is working.
3088                   // Hence, it is better to store persistent IDs of hypotheses as references to them
3089
3090                   //string myRefOnObject = myRefOnHyp->GetID();
3091                   CORBA::Object_var anObject = SObjectToObject( myRefOnHyp );
3092                   CORBA::String_var objStr = GetORB()->object_to_string( anObject );
3093                   int id = myStudyContext->findId( string( objStr.in() ) );
3094                   //if ( myRefOnObject.length() > 0 ) {
3095                   //aSize[ 0 ] = myRefOnObject.length() + 1;
3096                   char hypName[ 30 ], hypId[ 30 ];
3097                   sprintf( hypName, "Hyp %d", ++hypNb );
3098                   sprintf( hypId, "%d", id );
3099                   aSize[ 0 ] = strlen( hypId ) + 1;
3100                   aDataset = new HDFdataset( hypName, aGroup, HDF_STRING, aSize, 1 );
3101                   aDataset->CreateOnDisk();
3102                   //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3103                   aDataset->WriteOnDisk( hypId );
3104                   aDataset->CloseOnDisk();
3105                   //}
3106                 }
3107               }
3108               aGroup->CloseOnDisk();
3109             }
3110
3111             // write applied algorithms if exist
3112             SALOMEDS::SObject_var myAlgoBranch;
3113             found = gotBranch->FindSubObject( GetRefOnAppliedAlgorithmsTag(), myAlgoBranch );
3114             if ( found && !shapeRefFound && hasShape) { // remove applied algos
3115               myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( myAlgoBranch );
3116             }
3117             if ( found && (shapeRefFound || !hasShape)) {
3118               aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
3119               aGroup->CreateOnDisk();
3120
3121               SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( myAlgoBranch );
3122               int algoNb = 0;
3123               for ( ; it->More(); it->Next() ) {
3124                 SALOMEDS::SObject_var mySObject = it->Value();
3125                 SALOMEDS::SObject_var myRefOnAlgo;
3126                 bool ok = mySObject->ReferencedObject( myRefOnAlgo );
3127                 if ( ok ) {
3128                   // san - it is impossible to recover applied algorithms
3129                   //       using their entries within Load() method,
3130                   // for there are no AttributeIORs in the study when Load() is working.
3131                   // Hence, it is better to store persistent IDs of algorithms as references to them
3132
3133                   //string myRefOnObject = myRefOnAlgo->GetID();
3134                   CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo );
3135                   CORBA::String_var objStr = GetORB()->object_to_string( anObject );
3136                   int id = myStudyContext->findId( string( objStr.in() ) );
3137                   //if ( myRefOnObject.length() > 0 ) {
3138                   //aSize[ 0 ] = myRefOnObject.length() + 1;
3139                   char algoName[ 30 ], algoId[ 30 ];
3140                   sprintf( algoName, "Algo %d", ++algoNb );
3141                   sprintf( algoId, "%d", id );
3142                   aSize[ 0 ] = strlen( algoId ) + 1;
3143                   aDataset = new HDFdataset( algoName, aGroup, HDF_STRING, aSize, 1 );
3144                   aDataset->CreateOnDisk();
3145                   //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3146                   aDataset->WriteOnDisk( algoId );
3147                   aDataset->CloseOnDisk();
3148                   //}
3149                 }
3150               }
3151               aGroup->CloseOnDisk();
3152             }
3153
3154             // --> submesh objects sub-branches
3155
3156             for ( int i = GetSubMeshOnVertexTag(); i <= GetSubMeshOnCompoundTag(); i++ ) {
3157               SALOMEDS::SObject_var mySubmeshBranch;
3158               found = gotBranch->FindSubObject( i, mySubmeshBranch );
3159
3160               if ( found ) // check if there is shape reference in submeshes
3161               {
3162                 bool hasShapeRef = false;
3163                 SALOMEDS::ChildIterator_var itSM =
3164                   myCurrentStudy->NewChildIterator( mySubmeshBranch );
3165                 for ( ; itSM->More(); itSM->Next() ) {
3166                   SALOMEDS::SObject_var mySubRef, myShape, mySObject = itSM->Value();
3167                   if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef ))
3168                     mySubRef->ReferencedObject( myShape );
3169                   if ( !CORBA::is_nil( myShape ) && !CORBA::is_nil( myShape->GetObject() ))
3170                     hasShapeRef = true;
3171                   else
3172                   { // remove one submesh
3173                     if ( shapeRefFound )
3174                     { // unassign hypothesis
3175                       SMESH::SMESH_subMesh_var mySubMesh =
3176                         SMESH::SMESH_subMesh::_narrow( SObjectToObject( mySObject ));
3177                       if ( !mySubMesh->_is_nil() ) {
3178                         int shapeID = mySubMesh->GetId();
3179                         TopoDS_Shape S = mySMESHDSMesh->IndexToShape( shapeID );
3180                         const list<const SMESHDS_Hypothesis*>& hypList =
3181                           mySMESHDSMesh->GetHypothesis( S );
3182                         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
3183                         while ( hyp != hypList.end() ) {
3184                           int hypID = (*hyp++)->GetID(); // goto next hyp here because
3185                           myLocMesh.RemoveHypothesis( S, hypID ); // hypList changes here
3186                         }
3187                       }
3188                     }
3189                     myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( mySObject );
3190                   }
3191                 } // loop on submeshes of a type
3192                 if ( !shapeRefFound || !hasShapeRef ) { // remove the whole submeshes branch
3193                   myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( mySubmeshBranch );
3194                   found = false;
3195                 }
3196               }  // end check if there is shape reference in submeshes
3197               if ( found ) {
3198                 char name_meshgroup[ 30 ];
3199                 if ( i == GetSubMeshOnVertexTag() )
3200                   strcpy( name_meshgroup, "SubMeshes On Vertex" );
3201                 else if ( i == GetSubMeshOnEdgeTag() )
3202                   strcpy( name_meshgroup, "SubMeshes On Edge" );
3203                 else if ( i == GetSubMeshOnWireTag() )
3204                   strcpy( name_meshgroup, "SubMeshes On Wire" );
3205                 else if ( i == GetSubMeshOnFaceTag() )
3206                   strcpy( name_meshgroup, "SubMeshes On Face" );
3207                 else if ( i == GetSubMeshOnShellTag() )
3208                   strcpy( name_meshgroup, "SubMeshes On Shell" );
3209                 else if ( i == GetSubMeshOnSolidTag() )
3210                   strcpy( name_meshgroup, "SubMeshes On Solid" );
3211                 else if ( i == GetSubMeshOnCompoundTag() )
3212                   strcpy( name_meshgroup, "SubMeshes On Compound" );
3213
3214                 // for each type of submeshes create container HDF group
3215                 aGroup = new HDFgroup( name_meshgroup, aTopGroup );
3216                 aGroup->CreateOnDisk();
3217
3218                 // iterator for all submeshes of given type
3219                 SALOMEDS::ChildIterator_var itSM = myCurrentStudy->NewChildIterator( mySubmeshBranch );
3220                 for ( ; itSM->More(); itSM->Next() ) {
3221                   SALOMEDS::SObject_var mySObject = itSM->Value();
3222                   CORBA::Object_var anSubObject = SObjectToObject( mySObject );
3223                   if ( !CORBA::is_nil( anSubObject ))
3224                   {
3225                     SMESH::SMESH_subMesh_var mySubMesh = SMESH::SMESH_subMesh::_narrow( anSubObject ) ;
3226                     CORBA::String_var objStr = GetORB()->object_to_string( anSubObject );
3227                     int subid = myStudyContext->findId( string( objStr.in() ) );
3228
3229                     // for each mesh open the HDF group basing on its id
3230                     char submeshGrpName[ 30 ];
3231                     sprintf( submeshGrpName, "SubMesh %d", subid );
3232                     aSubGroup = new HDFgroup( submeshGrpName, aGroup );
3233                     aSubGroup->CreateOnDisk();
3234
3235                     // write reference on a shape, already checked if it exists
3236                     SALOMEDS::SObject_var mySubRef, myShape;
3237                     if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef ))
3238                       mySubRef->ReferencedObject( myShape );
3239                     string myRefOnObject = myShape->GetID();
3240                     if ( myRefOnObject.length() > 0 ) {
3241                       aSize[ 0 ] = myRefOnObject.length() + 1;
3242                       aDataset = new HDFdataset( "Ref on shape", aSubGroup, HDF_STRING, aSize, 1 );
3243                       aDataset->CreateOnDisk();
3244                       aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3245                       aDataset->CloseOnDisk();
3246                     }
3247
3248                     // write applied hypotheses if exist
3249                     SALOMEDS::SObject_var mySubHypBranch;
3250                     found = mySObject->FindSubObject( GetRefOnAppliedHypothesisTag(), mySubHypBranch );
3251                     if ( found ) {
3252                       aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup );
3253                       aSubSubGroup->CreateOnDisk();
3254
3255                       SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( mySubHypBranch );
3256                       int hypNb = 0;
3257                       for ( ; it->More(); it->Next() ) {
3258                         SALOMEDS::SObject_var mySubSObject = it->Value();
3259                         SALOMEDS::SObject_var myRefOnHyp;
3260                         bool ok = mySubSObject->ReferencedObject( myRefOnHyp );
3261                         if ( ok ) {
3262                           //string myRefOnObject = myRefOnHyp->GetID();
3263                           CORBA::Object_var anObject = SObjectToObject( myRefOnHyp );
3264                           CORBA::String_var objStr = GetORB()->object_to_string( anObject );
3265                           int id = myStudyContext->findId( string( objStr.in() ) );
3266                           //if ( myRefOnObject.length() > 0 ) {
3267                           //aSize[ 0 ] = myRefOnObject.length() + 1;
3268                           char hypName[ 30 ], hypId[ 30 ];
3269                           sprintf( hypName, "Hyp %d", ++hypNb );
3270                           sprintf( hypId, "%d", id );
3271                           aSize[ 0 ] = strlen( hypId ) + 1;
3272                           aDataset = new HDFdataset( hypName, aSubSubGroup, HDF_STRING, aSize, 1 );
3273                           aDataset->CreateOnDisk();
3274                           //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3275                           aDataset->WriteOnDisk( hypId );
3276                           aDataset->CloseOnDisk();
3277                           //}
3278                         }
3279                       }
3280                       aSubSubGroup->CloseOnDisk();
3281                     }
3282
3283                     // write applied algorithms if exist
3284                     SALOMEDS::SObject_var mySubAlgoBranch;
3285                     found = mySObject->FindSubObject( GetRefOnAppliedAlgorithmsTag(), mySubAlgoBranch );
3286                     if ( found ) {
3287                       aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup );
3288                       aSubSubGroup->CreateOnDisk();
3289
3290                       SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( mySubAlgoBranch );
3291                       int algoNb = 0;
3292                       for ( ; it->More(); it->Next() ) {
3293                         SALOMEDS::SObject_var mySubSObject = it->Value();
3294                         SALOMEDS::SObject_var myRefOnAlgo;
3295                         bool ok = mySubSObject->ReferencedObject( myRefOnAlgo );
3296                         if ( ok ) {
3297                           //string myRefOnObject = myRefOnAlgo->GetID();
3298                           CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo );
3299                           CORBA::String_var objStr = GetORB()->object_to_string( anObject );
3300                           int id = myStudyContext->findId( string( objStr.in() ) );
3301                           //if ( myRefOnObject.length() > 0 ) {
3302                           //aSize[ 0 ] = myRefOnObject.length() + 1;
3303                           char algoName[ 30 ], algoId[ 30 ];
3304                           sprintf( algoName, "Algo %d", ++algoNb );
3305                           sprintf( algoId, "%d", id );
3306                           aSize[ 0 ] = strlen( algoId ) + 1;
3307                           aDataset = new HDFdataset( algoName, aSubSubGroup, HDF_STRING, aSize, 1 );
3308                           aDataset->CreateOnDisk();
3309                           //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3310                           aDataset->WriteOnDisk( algoId );
3311                           aDataset->CloseOnDisk();
3312                           //}
3313                         }
3314                       }
3315                       aSubSubGroup->CloseOnDisk();
3316                     }
3317                     // close submesh HDF group
3318                     aSubGroup->CloseOnDisk();
3319                   }
3320                 }
3321                 // close container of submeshes by type HDF group
3322                 aGroup->CloseOnDisk();
3323               }
3324             }
3325             // All sub-meshes will be stored in MED file
3326             // .. will NOT (PAL 12992)
3327             //if ( shapeRefFound )
3328             //myWriter.AddAllSubMeshes();
3329
3330             // store submesh order if any
3331             const TListOfListOfInt& theOrderIds = myLocMesh.GetMeshOrder();
3332             if ( theOrderIds.size() ) {
3333               char order_list[ 30 ];
3334               strcpy( order_list, "Mesh Order" );
3335               // count number of submesh ids
3336               int nbIDs = 0;
3337               TListOfListOfInt::const_iterator idIt = theOrderIds.begin();
3338               for ( ; idIt != theOrderIds.end(); idIt++ )
3339                 nbIDs += (*idIt).size();
3340               // number of values = number of IDs +
3341               //                    number of lists (for separators) - 1
3342               int* smIDs = new int [ nbIDs + theOrderIds.size() - 1 ];
3343               idIt = theOrderIds.begin();
3344               for ( int i = 0; idIt != theOrderIds.end(); idIt++ ) {
3345                 const TListOfInt& idList = *idIt;
3346                 if (idIt != theOrderIds.begin()) // not first list
3347                   smIDs[ i++ ] = -1/* *idList.size()*/; // separator between lists
3348                 // dump submesh ids from current list
3349                 TListOfInt::const_iterator id_smId = idList.begin();
3350                 for( ; id_smId != idList.end(); id_smId++ )
3351                   smIDs[ i++ ] = *id_smId;
3352               }
3353               // write HDF group
3354               aSize[ 0 ] = nbIDs + theOrderIds.size() - 1;
3355
3356               aDataset = new HDFdataset( order_list, aTopGroup, HDF_INT32, aSize, 1 );
3357               aDataset->CreateOnDisk();
3358               aDataset->WriteOnDisk( smIDs );
3359               aDataset->CloseOnDisk();
3360               //
3361               delete[] smIDs;
3362             }
3363
3364             // groups root sub-branch
3365             SALOMEDS::SObject_var myGroupsBranch;
3366             for ( int i = GetNodeGroupsTag(); i <= Get0DElementsGroupsTag(); i++ ) {
3367               found = gotBranch->FindSubObject( i, myGroupsBranch );
3368               if ( found ) {
3369                 char name_group[ 30 ];
3370                 if ( i == GetNodeGroupsTag() )
3371                   strcpy( name_group, "Groups of Nodes" );
3372                 else if ( i == GetEdgeGroupsTag() )
3373                   strcpy( name_group, "Groups of Edges" );
3374                 else if ( i == GetFaceGroupsTag() )
3375                   strcpy( name_group, "Groups of Faces" );
3376                 else if ( i == GetVolumeGroupsTag() )
3377                   strcpy( name_group, "Groups of Volumes" );
3378                 else if ( i == Get0DElementsGroupsTag() )
3379                   strcpy( name_group, "Groups of 0D Elements" );
3380
3381                 aGroup = new HDFgroup( name_group, aTopGroup );
3382                 aGroup->CreateOnDisk();
3383
3384                 SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( myGroupsBranch );
3385                 for ( ; it->More(); it->Next() ) {
3386                   SALOMEDS::SObject_var mySObject = it->Value();
3387                   CORBA::Object_var aSubObject = SObjectToObject( mySObject );
3388                   if ( !CORBA::is_nil( aSubObject ) ) {
3389                     SMESH_GroupBase_i* myGroupImpl =
3390                       dynamic_cast<SMESH_GroupBase_i*>( GetServant( aSubObject ).in() );
3391                     if ( !myGroupImpl )
3392                       continue;
3393                     SMESHDS_GroupBase* aGrpBaseDS = myGroupImpl->GetGroupDS();
3394                     if ( !aGrpBaseDS )
3395                       continue;
3396
3397                     CORBA::String_var objStr = GetORB()->object_to_string( aSubObject );
3398                     int anId = myStudyContext->findId( string( objStr.in() ) );
3399
3400                     // For each group, create a dataset named "Group <group_persistent_id>"
3401                     // and store the group's user name into it
3402                     const char* grpName = aGrpBaseDS->GetStoreName();
3403                     char* aUserName = myGroupImpl->GetName();
3404                     aSize[ 0 ] = strlen( aUserName ) + 1;
3405
3406                     aDataset = new HDFdataset( grpName, aGroup, HDF_STRING, aSize, 1 );
3407                     aDataset->CreateOnDisk();
3408                     aDataset->WriteOnDisk( aUserName );
3409                     aDataset->CloseOnDisk();
3410
3411                     // ouv : NPAL12872
3412                     // For each group, create a dataset named "Group <group_persistent_id> Color"
3413                     // and store the group's color into it
3414                     char grpColorName[ 30 ];
3415                     sprintf( grpColorName, "ColorGroup %d", anId );
3416                     SALOMEDS::Color aColor = myGroupImpl->GetColor();
3417                     double anRGB[3];
3418                     anRGB[ 0 ] = aColor.R;
3419                     anRGB[ 1 ] = aColor.G;
3420                     anRGB[ 2 ] = aColor.B;
3421                     aSize[ 0 ] = 3;
3422                     aDataset = new HDFdataset( grpColorName, aGroup, HDF_FLOAT64, aSize, 1 );
3423                     aDataset->CreateOnDisk();
3424                     aDataset->WriteOnDisk( anRGB );
3425                     aDataset->CloseOnDisk();
3426
3427                     // Pass SMESHDS_Group to MED writer
3428                     SMESHDS_Group* aGrpDS = dynamic_cast<SMESHDS_Group*>( aGrpBaseDS );
3429                     if ( aGrpDS )
3430                       myWriter.AddGroup( aGrpDS );
3431
3432                     // write reference on a shape if exists
3433                     SMESHDS_GroupOnGeom* aGeomGrp =
3434                       dynamic_cast<SMESHDS_GroupOnGeom*>( aGrpBaseDS );
3435                     if ( aGeomGrp ) {
3436                       SALOMEDS::SObject_var mySubRef, myShape;
3437                       if (mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef ) &&
3438                           mySubRef->ReferencedObject( myShape ) &&
3439                           !CORBA::is_nil( myShape->GetObject() ))
3440                       {
3441                         string myRefOnObject = myShape->GetID();
3442                         if ( myRefOnObject.length() > 0 ) {
3443                           char aRefName[ 30 ];
3444                           sprintf( aRefName, "Ref on shape %d", anId);
3445                           aSize[ 0 ] = myRefOnObject.length() + 1;
3446                           aDataset = new HDFdataset(aRefName, aGroup, HDF_STRING, aSize, 1);
3447                           aDataset->CreateOnDisk();
3448                           aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3449                           aDataset->CloseOnDisk();
3450                         }
3451                       }
3452                       else // shape ref is invalid:
3453                       {
3454                         // save a group on geometry as ordinary group
3455                         myWriter.AddGroup( aGeomGrp );
3456                       }
3457                     }
3458                     else if ( SMESH_GroupOnFilter_i* aFilterGrp_i = 
3459                               dynamic_cast<SMESH_GroupOnFilter_i*>( myGroupImpl ))
3460                     {
3461                       std::string str = aFilterGrp_i->FilterToString();
3462                       std::string hdfGrpName = "Filter " + SMESH_Comment(anId);
3463                       aSize[ 0 ] = str.length() + 1;
3464                       aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup, HDF_STRING, aSize, 1);
3465                       aDataset->CreateOnDisk();
3466                       aDataset->WriteOnDisk( ( char* )( str.c_str() ) );
3467                       aDataset->CloseOnDisk();
3468                     }
3469                   }
3470                 }
3471                 aGroup->CloseOnDisk();
3472               }
3473             } // loop on groups
3474
3475             if ( strcmp( strHasData.c_str(), "1" ) == 0 )
3476             {
3477               // Flush current mesh information into MED file
3478               myWriter.Perform();
3479
3480               // save info on nb of elements
3481               SMESH_PreMeshInfo::SaveToFile( myImpl, id, aFile );
3482
3483               // maybe a shape was deleted in the study
3484               if ( !shapeRefFound && !mySMESHDSMesh->ShapeToMesh().IsNull() && hasShape) {
3485                 TopoDS_Shape nullShape;
3486                 myLocMesh.ShapeToMesh( nullShape ); // remove shape referring data
3487               }
3488
3489               if ( !mySMESHDSMesh->SubMeshes().empty() )
3490               {
3491                 // Store submeshes
3492                 // ----------------
3493                 aGroup = new HDFgroup( "Submeshes", aTopGroup );
3494                 aGroup->CreateOnDisk();
3495
3496                 // each element belongs to one or none submesh,
3497                 // so for each node/element, we store a submesh ID
3498
3499                 // Make maps of submesh IDs of elements sorted by element IDs
3500                 typedef int TElemID;
3501                 typedef int TSubMID;
3502                 map< TElemID, TSubMID > eId2smId, nId2smId;
3503                 map< TElemID, TSubMID >::iterator hint; // insertion to map is done before hint
3504                 const map<int,SMESHDS_SubMesh*>& aSubMeshes = mySMESHDSMesh->SubMeshes();
3505                 map<int,SMESHDS_SubMesh*>::const_iterator itSubM ( aSubMeshes.begin() );
3506                 SMDS_NodeIteratorPtr itNode;
3507                 SMDS_ElemIteratorPtr itElem;
3508                 for ( itSubM = aSubMeshes.begin(); itSubM != aSubMeshes.end() ; itSubM++ )
3509                 {
3510                   TSubMID          aSubMeID = itSubM->first;
3511                   SMESHDS_SubMesh* aSubMesh = itSubM->second;
3512                   if ( aSubMesh->IsComplexSubmesh() )
3513                     continue; // submesh containing other submeshs
3514                   // nodes
3515                   hint = nId2smId.begin(); // optimize insertion basing on increasing order of elem Ids in submesh
3516                   for ( itNode = aSubMesh->GetNodes(); itNode->more(); ++hint)
3517                     hint = nId2smId.insert( hint, make_pair( itNode->next()->GetID(), aSubMeID ));
3518                   // elements
3519                   hint = eId2smId.begin();
3520                   for ( itElem = aSubMesh->GetElements(); itElem->more(); ++hint)
3521                     hint = eId2smId.insert( hint, make_pair( itElem->next()->GetID(), aSubMeID ));
3522                 }
3523
3524                 // Care of elements that are not on submeshes
3525                 if ( mySMESHDSMesh->NbNodes() != nId2smId.size() ) {
3526                   for ( itNode = mySMESHDSMesh->nodesIterator(); itNode->more(); )
3527                     /*  --- stl_map.h says : */
3528                     /*  A %map relies on unique keys and thus a %pair is only inserted if its */
3529                     /*  first element (the key) is not already present in the %map.           */
3530                     nId2smId.insert( make_pair( itNode->next()->GetID(), 0 ));
3531                 }
3532                 int nbElems = mySMESHDSMesh->NbEdges() + mySMESHDSMesh->NbFaces() + mySMESHDSMesh->NbVolumes();
3533                 if ( nbElems != eId2smId.size() ) {
3534                   for ( itElem = mySMESHDSMesh->elementsIterator(); itElem->more(); )
3535                     eId2smId.insert( make_pair( itElem->next()->GetID(), 0 ));
3536                 }
3537
3538                 // Store submesh IDs
3539                 for ( int isNode = 0; isNode < 2; ++isNode )
3540                 {
3541                   map< TElemID, TSubMID >& id2smId = isNode ? nId2smId : eId2smId;
3542                   if ( id2smId.empty() ) continue;
3543                   map< TElemID, TSubMID >::const_iterator id_smId = id2smId.begin();
3544                   // make and fill array of submesh IDs
3545                   int* smIDs = new int [ id2smId.size() ];
3546                   for ( int i = 0; id_smId != id2smId.end(); ++id_smId, ++i )
3547                     smIDs[ i ] = id_smId->second;
3548                   // write HDF group
3549                   aSize[ 0 ] = id2smId.size();
3550                   string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
3551                   aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_INT32, aSize, 1 );
3552                   aDataset->CreateOnDisk();
3553                   aDataset->WriteOnDisk( smIDs );
3554                   aDataset->CloseOnDisk();
3555                   //
3556                   delete[] smIDs;
3557                 }
3558
3559                 aGroup->CloseOnDisk();
3560
3561                 // Store node positions on sub-shapes (SMDS_Position):
3562                 // ----------------------------------------------------
3563
3564                 aGroup = new HDFgroup( "Node Positions", aTopGroup );
3565                 aGroup->CreateOnDisk();
3566
3567                 // in aGroup, create 5 datasets to contain:
3568                 // "Nodes on Edges" - ID of node on edge
3569                 // "Edge positions" - U parameter on node on edge
3570                 // "Nodes on Faces" - ID of node on face
3571                 // "Face U positions" - U parameter of node on face
3572                 // "Face V positions" - V parameter of node on face
3573
3574                 // Find out nb of nodes on edges and faces
3575                 // Collect corresponing sub-meshes
3576                 int nbEdgeNodes = 0, nbFaceNodes = 0;
3577                 list<SMESHDS_SubMesh*> aEdgeSM, aFaceSM;
3578                 // loop on SMESHDS_SubMesh'es
3579                 for ( itSubM = aSubMeshes.begin(); itSubM != aSubMeshes.end() ; itSubM++ )
3580                 {
3581                   SMESHDS_SubMesh* aSubMesh = (*itSubM).second;
3582                   if ( aSubMesh->IsComplexSubmesh() )
3583                     continue; // submesh containing other submeshs
3584                   int nbNodes = aSubMesh->NbNodes();
3585                   if ( nbNodes == 0 ) continue;
3586
3587                   int aShapeID = (*itSubM).first;
3588                   if ( aShapeID < 1 || aShapeID > mySMESHDSMesh->MaxShapeIndex() )
3589                     continue;
3590                   int aShapeType = mySMESHDSMesh->IndexToShape( aShapeID ).ShapeType();
3591                   // write only SMDS_FacePosition and SMDS_EdgePosition
3592                   switch ( aShapeType ) {
3593                   case TopAbs_FACE:
3594                     nbFaceNodes += nbNodes;
3595                     aFaceSM.push_back( aSubMesh );
3596                     break;
3597                   case TopAbs_EDGE:
3598                     nbEdgeNodes += nbNodes;
3599                     aEdgeSM.push_back( aSubMesh );
3600                     break;
3601                   default:
3602                     continue;
3603                   }
3604                 }
3605                 // Treat positions on edges or faces
3606                 for ( int onFace = 0; onFace < 2; onFace++ )
3607                 {
3608                   // Create arrays to store in datasets
3609                   int iNode = 0, nbNodes = ( onFace ? nbFaceNodes : nbEdgeNodes );
3610                   if (!nbNodes) continue;
3611                   int* aNodeIDs = new int [ nbNodes ];
3612                   double* aUPos = new double [ nbNodes ];
3613                   double* aVPos = ( onFace ? new double[ nbNodes ] : 0 );
3614
3615                   // Fill arrays
3616                   // loop on sub-meshes
3617                   list<SMESHDS_SubMesh*> * pListSM = ( onFace ? &aFaceSM : &aEdgeSM );
3618                   list<SMESHDS_SubMesh*>::iterator itSM = pListSM->begin();
3619                   for ( ; itSM != pListSM->end(); itSM++ )
3620                   {
3621                     SMESHDS_SubMesh* aSubMesh = (*itSM);
3622
3623                     SMDS_NodeIteratorPtr itNode = aSubMesh->GetNodes();
3624                     // loop on nodes in aSubMesh
3625                     while ( itNode->more() )
3626                     {
3627                       //node ID
3628                       const SMDS_MeshNode* node = itNode->next();
3629                       aNodeIDs [ iNode ] = node->GetID();
3630
3631                       // Position
3632                       const SMDS_PositionPtr pos = node->GetPosition();
3633                       if ( onFace ) { // on FACE
3634                         const SMDS_FacePosition* fPos =
3635                           dynamic_cast<const SMDS_FacePosition*>( pos );
3636                         if ( fPos ) {
3637                           aUPos[ iNode ] = fPos->GetUParameter();
3638                           aVPos[ iNode ] = fPos->GetVParameter();
3639                           iNode++;
3640                         }
3641                         else
3642                           nbNodes--;
3643                       }
3644                       else { // on EDGE
3645                         const SMDS_EdgePosition* ePos =
3646                           dynamic_cast<const SMDS_EdgePosition*>( pos );
3647                         if ( ePos ) {
3648                           aUPos[ iNode ] = ePos->GetUParameter();
3649                           iNode++;
3650                         }
3651                         else
3652                           nbNodes--;
3653                       }
3654                     } // loop on nodes in aSubMesh
3655                   } // loop on sub-meshes
3656
3657                   // Write datasets
3658                   if ( nbNodes )
3659                   {
3660                     aSize[ 0 ] = nbNodes;
3661                     // IDS
3662                     string aDSName( onFace ? "Nodes on Faces" : "Nodes on Edges");
3663                     aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_INT32, aSize, 1 );
3664                     aDataset->CreateOnDisk();
3665                     aDataset->WriteOnDisk( aNodeIDs );
3666                     aDataset->CloseOnDisk();
3667
3668                     // U Positions
3669                     aDSName = ( onFace ? "Face U positions" : "Edge positions");
3670                     aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_FLOAT64, aSize, 1);
3671                     aDataset->CreateOnDisk();
3672                     aDataset->WriteOnDisk( aUPos );
3673                     aDataset->CloseOnDisk();
3674                     // V Positions
3675                     if ( onFace ) {
3676                       aDataset = new HDFdataset( "Face V positions", aGroup, HDF_FLOAT64, aSize, 1);
3677                       aDataset->CreateOnDisk();
3678                       aDataset->WriteOnDisk( aVPos );
3679                       aDataset->CloseOnDisk();
3680                     }
3681                   }
3682                   delete [] aNodeIDs;
3683                   delete [] aUPos;
3684                   if ( aVPos ) delete [] aVPos;
3685
3686                 } // treat positions on edges or faces
3687
3688                 // close "Node Positions" group
3689                 aGroup->CloseOnDisk();
3690
3691               } // if ( there are submeshes in SMESHDS_Mesh )
3692             } // if ( hasData )
3693
3694             // close mesh HDF group
3695             aTopGroup->CloseOnDisk();
3696           }
3697         }
3698       }
3699     }
3700   }
3701
3702   // close HDF file
3703   aFile->CloseOnDisk();
3704   delete aFile;
3705
3706   // Convert temporary files to stream
3707   aStreamFile = SALOMEDS_Tool::PutFilesToStream( tmpDir.ToCString(), aFileSeq.in(), isMultiFile );
3708
3709   // Remove temporary files and directory
3710   if ( !isMultiFile )
3711     SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
3712
3713   INFOS( "SMESH_Gen_i::Save() completed" );
3714   return aStreamFile._retn();
3715 }
3716
3717 //=============================================================================
3718 /*!
3719  *  SMESH_Gen_i::SaveASCII
3720  *
3721  *  Save SMESH module's data in ASCII format
3722  */
3723 //=============================================================================
3724
3725 SALOMEDS::TMPFile* SMESH_Gen_i::SaveASCII( SALOMEDS::SComponent_ptr theComponent,
3726                                            const char*              theURL,
3727                                            bool                     isMultiFile ) {
3728   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::SaveASCII" );
3729   SALOMEDS::TMPFile_var aStreamFile = Save( theComponent, theURL, isMultiFile );
3730   return aStreamFile._retn();
3731
3732   //after usual saving needs to encipher binary to text string
3733   //Any binary symbol will be represent as "|xx" () hexadecimal format number
3734   int size = aStreamFile.in().length();
3735   _CORBA_Octet* buffer = new _CORBA_Octet[size*3+1];
3736   for ( int i = 0; i < size; i++ )
3737     sprintf( (char*)&(buffer[i*3]), "|%02x", aStreamFile[i] );
3738
3739   buffer[size * 3] = '\0';
3740
3741   SALOMEDS::TMPFile_var anAsciiStreamFile = new SALOMEDS::TMPFile(size*3, size*3, buffer, 1);
3742
3743   return anAsciiStreamFile._retn();
3744 }
3745
3746 //=============================================================================
3747 /*!
3748  *  SMESH_Gen_i::loadGeomData
3749  *
3750  *  Load GEOM module data
3751  */
3752 //=============================================================================
3753
3754 void SMESH_Gen_i::loadGeomData( SALOMEDS::SComponent_ptr theCompRoot )
3755 {
3756   if ( theCompRoot->_is_nil() )
3757     return;
3758
3759   SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow( theCompRoot->GetStudy() );
3760   if ( aStudy->_is_nil() )
3761     return;
3762
3763   SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
3764   aStudyBuilder->LoadWith( theCompRoot, GetGeomEngine() );
3765 }
3766
3767 //=============================================================================
3768 /*!
3769  *  SMESH_Gen_i::Load
3770  *
3771  *  Load SMESH module's data
3772  */
3773 //=============================================================================
3774
3775 bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
3776                         const SALOMEDS::TMPFile& theStream,
3777                         const char*              theURL,
3778                         bool                     isMultiFile )
3779 {
3780   INFOS( "SMESH_Gen_i::Load" );
3781
3782   if ( myCurrentStudy->_is_nil() ||
3783        theComponent->GetStudy()->StudyId() != myCurrentStudy->StudyId() )
3784     SetCurrentStudy( theComponent->GetStudy() );
3785
3786   /*  if( !theComponent->_is_nil() )
3787       {
3788       //SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow( theComponent->GetStudy() );
3789       if( !myCurrentStudy->FindComponent( "GEOM" )->_is_nil() )
3790       loadGeomData( myCurrentStudy->FindComponent( "GEOM" ) );
3791       }*/
3792
3793   StudyContext* myStudyContext = GetCurrentStudyContext();
3794
3795   // Get temporary files location
3796   TCollection_AsciiString tmpDir =
3797     isMultiFile ? TCollection_AsciiString( ( char* )theURL ) : ( char* )SALOMEDS_Tool::GetTmpDir().c_str();
3798
3799     INFOS( "THE URL++++++++++++++" )
3800     INFOS( theURL );
3801     INFOS( "THE TMP PATH+++++++++" );
3802     INFOS( tmpDir );
3803
3804   // Convert the stream into sequence of files to process
3805   SALOMEDS::ListOfFileNames_var aFileSeq = SALOMEDS_Tool::PutStreamToFiles( theStream,
3806                                                                             tmpDir.ToCString(),
3807                                                                             isMultiFile );
3808   TCollection_AsciiString aStudyName( "" );
3809   if ( isMultiFile )
3810     aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( myCurrentStudy->URL() ).c_str() );
3811
3812   // Set names of temporary files
3813   TCollection_AsciiString filename = tmpDir + aStudyName + TCollection_AsciiString( "_SMESH.hdf" );
3814   TCollection_AsciiString meshfile = tmpDir + aStudyName + TCollection_AsciiString( "_SMESH_Mesh.med" );
3815
3816   int size;
3817   HDFfile*    aFile;
3818   HDFdataset* aDataset;
3819   HDFgroup*   aTopGroup;
3820   HDFgroup*   aGroup;
3821   HDFgroup*   aSubGroup;
3822   HDFgroup*   aSubSubGroup;
3823
3824   // Read data
3825   // ---> open HDF file
3826   aFile = new HDFfile( (char*) filename.ToCString() );
3827   try {
3828     aFile->OpenOnDisk( HDF_RDONLY );
3829   }
3830   catch ( HDFexception ) {
3831     INFOS( "Load(): " << filename << " not found!" );
3832     return false;
3833   }
3834
3835   TPythonDump pd; // prevent dump during loading
3836
3837   // DriverMED_R_SMESHDS_Mesh myReader;
3838   // myReader.SetFile( meshfile.ToCString() );
3839
3840   // For PAL13473 ("Repetitive mesh") implementation.
3841   // New dependencies between SMESH objects are established:
3842   // now hypotheses can refer to meshes, shapes and other hypotheses.
3843   // To keep data consistent, the following order of data restoration
3844   // imposed:
3845   // 1. Create hypotheses
3846   // 2. Create all meshes
3847   // 3. Load hypotheses' data
3848   // 4. All the rest
3849
3850   list< pair< SMESH_Hypothesis_i*, string > >    hypDataList;
3851   list< pair< SMESH_Mesh_i*,       HDFgroup* > > meshGroupList;
3852
3853   // get total number of top-level groups
3854   int aNbGroups = aFile->nInternalObjects();
3855   if ( aNbGroups > 0 ) {
3856     // --> in first turn we should read&create hypotheses
3857     if ( aFile->ExistInternalObject( "Hypotheses" ) ) {
3858       // open hypotheses root HDF group
3859       aTopGroup = new HDFgroup( "Hypotheses", aFile );
3860       aTopGroup->OpenOnDisk();
3861
3862       // get number of hypotheses
3863       int aNbObjects = aTopGroup->nInternalObjects();
3864       for ( int j = 0; j < aNbObjects; j++ ) {
3865         // try to identify hypothesis
3866         char hypGrpName[ HDF_NAME_MAX_LEN+1 ];
3867         aTopGroup->InternalObjectIndentify( j, hypGrpName );
3868
3869         if ( string( hypGrpName ).substr( 0, 10 ) == string( "Hypothesis" ) ) {
3870           // open hypothesis group
3871           aGroup = new HDFgroup( hypGrpName, aTopGroup );
3872           aGroup->OpenOnDisk();
3873
3874           // --> get hypothesis id
3875           int    id = atoi( string( hypGrpName ).substr( 10 ).c_str() );
3876           string hypname;
3877           string libname;
3878           string hypdata;
3879
3880           // get number of datasets
3881           int aNbSubObjects = aGroup->nInternalObjects();
3882           for ( int k = 0; k < aNbSubObjects; k++ ) {
3883             // identify dataset
3884             char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ];
3885             aGroup->InternalObjectIndentify( k, name_of_subgroup );
3886             // --> get hypothesis name
3887             if ( strcmp( name_of_subgroup, "Name"  ) == 0 ) {
3888               aDataset = new HDFdataset( name_of_subgroup, aGroup );
3889               aDataset->OpenOnDisk();
3890               size = aDataset->GetSize();
3891               char* hypname_str = new char[ size ];
3892               aDataset->ReadFromDisk( hypname_str );
3893               hypname = string( hypname_str );
3894               delete [] hypname_str;
3895               aDataset->CloseOnDisk();
3896             }
3897             // --> get hypothesis plugin library name
3898             if ( strcmp( name_of_subgroup, "LibName"  ) == 0 ) {
3899               aDataset = new HDFdataset( name_of_subgroup, aGroup );
3900               aDataset->OpenOnDisk();
3901               size = aDataset->GetSize();
3902               char* libname_str = new char[ size ];
3903               aDataset->ReadFromDisk( libname_str );
3904               if(MYDEBUG) SCRUTE( libname_str );
3905               libname = string( libname_str );
3906               delete [] libname_str;
3907               aDataset->CloseOnDisk();
3908             }
3909             // --> get hypothesis data
3910             if ( strcmp( name_of_subgroup, "Data"  ) == 0 ) {
3911               aDataset = new HDFdataset( name_of_subgroup, aGroup );
3912               aDataset->OpenOnDisk();
3913               size = aDataset->GetSize();
3914               char* hypdata_str = new char[ size ];
3915               aDataset->ReadFromDisk( hypdata_str );
3916               hypdata = string( hypdata_str );
3917               delete [] hypdata_str;
3918               aDataset->CloseOnDisk();
3919             }
3920           }
3921           // close hypothesis HDF group
3922           aGroup->CloseOnDisk();
3923
3924           // --> restore hypothesis from data
3925           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
3926             if(MYDEBUG) MESSAGE("VSR - load hypothesis : id = " << id <<
3927                                 ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
3928             SMESH::SMESH_Hypothesis_var myHyp;
3929
3930             try { // protect persistence mechanism against exceptions
3931               myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() );
3932             }
3933             catch (...) {
3934               INFOS( "Exception during hypothesis creation" );
3935             }
3936
3937             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
3938             if ( myImpl ) {
3939               // myImpl->LoadFrom( hypdata.c_str() );
3940               hypDataList.push_back( make_pair( myImpl, hypdata ));
3941               string iorString = GetORB()->object_to_string( myHyp );
3942               int newId = myStudyContext->findId( iorString );
3943               myStudyContext->mapOldToNew( id, newId );
3944             }
3945             else
3946               if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
3947           }
3948         }
3949       }
3950       // close hypotheses root HDF group
3951       aTopGroup->CloseOnDisk();
3952       aTopGroup = 0;
3953     }
3954
3955     // --> then we should read&create algorithms
3956     if ( aFile->ExistInternalObject( "Algorithms" ) ) {
3957       // open algorithms root HDF group
3958       aTopGroup = new HDFgroup( "Algorithms", aFile );
3959       aTopGroup->OpenOnDisk();
3960
3961       // get number of algorithms
3962       int aNbObjects = aTopGroup->nInternalObjects();
3963       for ( int j = 0; j < aNbObjects; j++ ) {
3964         // try to identify algorithm
3965         char hypGrpName[ HDF_NAME_MAX_LEN+1 ];
3966         aTopGroup->InternalObjectIndentify( j, hypGrpName );
3967
3968         if ( string( hypGrpName ).substr( 0, 9 ) == string( "Algorithm" ) ) {
3969           // open algorithm group
3970           aGroup = new HDFgroup( hypGrpName, aTopGroup );
3971           aGroup->OpenOnDisk();
3972
3973           // --> get algorithm id
3974           int    id = atoi( string( hypGrpName ).substr( 9 ).c_str() );
3975           string hypname;
3976           string libname;
3977           string hypdata;
3978
3979           // get number of datasets
3980           int aNbSubObjects = aGroup->nInternalObjects();
3981           for ( int k = 0; k < aNbSubObjects; k++ ) {
3982             // identify dataset
3983             char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ];
3984             aGroup->InternalObjectIndentify( k, name_of_subgroup );
3985             // --> get algorithm name
3986             if ( strcmp( name_of_subgroup, "Name"  ) == 0 ) {
3987               aDataset = new HDFdataset( name_of_subgroup, aGroup );
3988               aDataset->OpenOnDisk();
3989               size = aDataset->GetSize();
3990               char* hypname_str = new char[ size ];
3991               aDataset->ReadFromDisk( hypname_str );
3992               hypname = string( hypname_str );
3993               delete [] hypname_str;
3994               aDataset->CloseOnDisk();
3995             }
3996             // --> get algorithm plugin library name
3997             if ( strcmp( name_of_subgroup, "LibName"  ) == 0 ) {
3998               aDataset = new HDFdataset( name_of_subgroup, aGroup );
3999               aDataset->OpenOnDisk();
4000               size = aDataset->GetSize();
4001               char* libname_str = new char[ size ];
4002               aDataset->ReadFromDisk( libname_str );
4003               if(MYDEBUG) SCRUTE( libname_str );
4004               libname = string( libname_str );
4005               delete [] libname_str;
4006               aDataset->CloseOnDisk();
4007             }
4008             // --> get algorithm data
4009             if ( strcmp( name_of_subgroup, "Data"  ) == 0 ) {
4010               aDataset = new HDFdataset( name_of_subgroup, aGroup );
4011               aDataset->OpenOnDisk();
4012               size = aDataset->GetSize();
4013               char* hypdata_str = new char[ size ];
4014               aDataset->ReadFromDisk( hypdata_str );
4015               if(MYDEBUG) SCRUTE( hypdata_str );
4016               hypdata = string( hypdata_str );
4017               delete [] hypdata_str;
4018               aDataset->CloseOnDisk();
4019             }
4020           }
4021           // close algorithm HDF group
4022           aGroup->CloseOnDisk();
4023
4024           // --> restore algorithm from data
4025           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
4026             if(MYDEBUG) MESSAGE("VSR - load algo : id = " << id <<
4027                                 ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
4028             SMESH::SMESH_Hypothesis_var myHyp;
4029
4030             try { // protect persistence mechanism against exceptions
4031               myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() );
4032             }
4033             catch (...) {
4034               INFOS( "Exception during hypothesis creation" );
4035             }
4036
4037             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
4038             if ( myImpl ) {
4039               //myImpl->LoadFrom( hypdata.c_str() );
4040               hypDataList.push_back( make_pair( myImpl, hypdata ));
4041               string iorString = GetORB()->object_to_string( myHyp );
4042               int newId = myStudyContext->findId( iorString );
4043               myStudyContext->mapOldToNew( id, newId );
4044             }
4045             else
4046               if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
4047           }
4048         }
4049       }
4050       // close algorithms root HDF group
4051       aTopGroup->CloseOnDisk();
4052       aTopGroup = 0;
4053     }
4054
4055     // --> the rest groups should be meshes
4056     for ( int i = 0; i < aNbGroups; i++ ) {
4057       // identify next group
4058       char meshName[ HDF_NAME_MAX_LEN+1 ];
4059       aFile->InternalObjectIndentify( i, meshName );
4060
4061       if ( string( meshName ).substr( 0, 4 ) == string( "Mesh" ) ) {
4062         // --> get mesh id
4063         int id = atoi( string( meshName ).substr( 4 ).c_str() );
4064         if ( id <= 0 )
4065           continue;
4066
4067         // open mesh HDF group
4068         aTopGroup = new HDFgroup( meshName, aFile );
4069         aTopGroup->OpenOnDisk();
4070
4071         // get number of child HDF objects
4072         int aNbObjects = aTopGroup->nInternalObjects();
4073         if ( aNbObjects > 0 ) {
4074           // create mesh
4075           if(MYDEBUG) MESSAGE( "VSR - load mesh : id = " << id );
4076           SMESH::SMESH_Mesh_var myNewMesh = this->createMesh();
4077           SMESH_Mesh_i* myNewMeshImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( myNewMesh ).in() );
4078           if ( !myNewMeshImpl )
4079             continue;
4080           meshGroupList.push_back( make_pair( myNewMeshImpl, aTopGroup ));
4081
4082           string iorString = GetORB()->object_to_string( myNewMesh );
4083           int newId = myStudyContext->findId( iorString );
4084           myStudyContext->mapOldToNew( id, newId );
4085
4086           // ouv : NPAL12872
4087           // try to read and set auto color flag
4088           char aMeshAutoColorName[ 30 ];
4089           sprintf( aMeshAutoColorName, "AutoColorMesh %d", id);
4090           if( aTopGroup->ExistInternalObject( aMeshAutoColorName ) )
4091           {
4092             aDataset = new HDFdataset( aMeshAutoColorName, aTopGroup );
4093             aDataset->OpenOnDisk();
4094             size = aDataset->GetSize();
4095             int* anAutoColor = new int[ size ];
4096             aDataset->ReadFromDisk( anAutoColor );
4097             aDataset->CloseOnDisk();
4098             myNewMeshImpl->GetImpl().SetAutoColor( (bool)anAutoColor[0] );
4099           }
4100
4101           // try to read and set reference to shape
4102           GEOM::GEOM_Object_var aShapeObject;
4103           if ( aTopGroup->ExistInternalObject( "Ref on shape" ) ) {
4104             // load mesh "Ref on shape" - it's an entry to SObject
4105             aDataset = new HDFdataset( "Ref on shape", aTopGroup );
4106             aDataset->OpenOnDisk();
4107             size = aDataset->GetSize();
4108             char* refFromFile = new char[ size ];
4109             aDataset->ReadFromDisk( refFromFile );
4110             aDataset->CloseOnDisk();
4111             if ( strlen( refFromFile ) > 0 ) {
4112               SALOMEDS::SObject_var shapeSO = myCurrentStudy->FindObjectID( refFromFile );
4113
4114               // Make sure GEOM data are loaded first
4115               //loadGeomData( shapeSO->GetFatherComponent() );
4116
4117               CORBA::Object_var shapeObject = SObjectToObject( shapeSO );
4118               if ( !CORBA::is_nil( shapeObject ) ) {
4119                 aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
4120                 if ( !aShapeObject->_is_nil() )
4121                   myNewMeshImpl->SetShape( aShapeObject );
4122               }
4123             }
4124           }
4125
4126           // issue 0020693. Restore _isModified flag
4127           if( aTopGroup->ExistInternalObject( "_isModified" ) )
4128           {
4129             aDataset = new HDFdataset( "_isModified", aTopGroup );
4130             aDataset->OpenOnDisk();
4131             size = aDataset->GetSize();
4132             int* isModified = new int[ size ];
4133             aDataset->ReadFromDisk( isModified );
4134             aDataset->CloseOnDisk();
4135             myNewMeshImpl->GetImpl().SetIsModified( bool(*isModified));
4136           }
4137
4138           // issue 20918. Restore Persistent Id of SMESHDS_Mesh
4139           if( aTopGroup->ExistInternalObject( "meshPersistentId" ) )
4140           {
4141             aDataset = new HDFdataset( "meshPersistentId", aTopGroup );
4142             aDataset->OpenOnDisk();
4143             size = aDataset->GetSize();
4144             int* meshPersistentId = new int[ size ];
4145             aDataset->ReadFromDisk( meshPersistentId );
4146             aDataset->CloseOnDisk();
4147             myNewMeshImpl->GetImpl().GetMeshDS()->SetPersistentId( *meshPersistentId );
4148           }
4149         }
4150       }
4151     } // reading MESHes
4152
4153     // As all object that can be referred by hypothesis are created,
4154     // we can restore hypothesis data
4155
4156     list< pair< SMESH_Hypothesis_i*, string > >::iterator hyp_data;
4157     for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data )
4158     {
4159       SMESH_Hypothesis_i* hyp  = hyp_data->first;
4160       string &            data = hyp_data->second;
4161       hyp->LoadFrom( data.c_str() );
4162     }
4163
4164     // Restore the rest mesh data
4165
4166     list< pair< SMESH_Mesh_i*, HDFgroup* > >::iterator meshi_group;
4167     for ( meshi_group = meshGroupList.begin(); meshi_group != meshGroupList.end(); ++meshi_group )
4168     {
4169       aTopGroup                   = meshi_group->second;
4170       SMESH_Mesh_i* myNewMeshImpl = meshi_group->first;
4171       //::SMESH_Mesh& myLocMesh     = myNewMeshImpl->GetImpl();
4172       //SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS();
4173
4174       GEOM::GEOM_Object_var aShapeObject = myNewMeshImpl->GetShapeToMesh();
4175       bool hasData = false;
4176
4177       // get mesh old id
4178       string iorString = GetORB()->object_to_string( myNewMeshImpl->_this() );
4179       int newId = myStudyContext->findId( iorString );
4180       int id = myStudyContext->getOldId( newId );
4181
4182       // try to find mesh data dataset
4183       if ( aTopGroup->ExistInternalObject( "Has data" ) ) {
4184         // load mesh "has data" flag
4185         aDataset = new HDFdataset( "Has data", aTopGroup );
4186         aDataset->OpenOnDisk();
4187         size = aDataset->GetSize();
4188         char* strHasData = new char[ size ];
4189         aDataset->ReadFromDisk( strHasData );
4190         aDataset->CloseOnDisk();
4191         if ( strcmp( strHasData, "1") == 0 ) {
4192           // read mesh data from MED file
4193           // myReader.SetMesh( mySMESHDSMesh );
4194           // myReader.SetMeshId( id );
4195           // myReader.Perform();
4196           hasData = true;
4197         }
4198       }
4199
4200       // Try to get applied ALGORITHMS (mesh is not cleared by algo addition because
4201       // nodes and elements are not yet put into sub-meshes)
4202       if ( aTopGroup->ExistInternalObject( "Applied Algorithms" ) ) {
4203         aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
4204         aGroup->OpenOnDisk();
4205         // get number of applied algorithms
4206         int aNbSubObjects = aGroup->nInternalObjects();
4207         if(MYDEBUG) MESSAGE( "VSR - number of applied algos " << aNbSubObjects );
4208         for ( int j = 0; j < aNbSubObjects; j++ ) {
4209           char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4210           aGroup->InternalObjectIndentify( j, name_dataset );
4211           // check if it is an algorithm
4212           if ( string( name_dataset ).substr( 0, 4 ) == string( "Algo" ) ) {
4213             aDataset = new HDFdataset( name_dataset, aGroup );
4214             aDataset->OpenOnDisk();
4215             size = aDataset->GetSize();
4216             char* refFromFile = new char[ size ];
4217             aDataset->ReadFromDisk( refFromFile );
4218             aDataset->CloseOnDisk();
4219             // san - it is impossible to recover applied algorithms using their entries within Load() method
4220             //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
4221             //CORBA::Object_var hypObject = SObjectToObject( hypSO );
4222             int id = atoi( refFromFile );
4223             string anIOR = myStudyContext->getIORbyOldId( id );
4224             if ( !anIOR.empty() ) {
4225               CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
4226               if ( !CORBA::is_nil( hypObject ) ) {
4227                 SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
4228                 if ( !anHyp->_is_nil() && (!aShapeObject->_is_nil()
4229                                            || !myNewMeshImpl->HasShapeToMesh()) )
4230                   myNewMeshImpl->addHypothesis( aShapeObject, anHyp );
4231               }
4232             }
4233           }
4234         }
4235         aGroup->CloseOnDisk();
4236       }
4237
4238       // try to get applied hypotheses
4239       if ( aTopGroup->ExistInternalObject( "Applied Hypotheses" ) ) {
4240         aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup );
4241         aGroup->OpenOnDisk();
4242         // get number of applied hypotheses
4243         int aNbSubObjects = aGroup->nInternalObjects();
4244         for ( int j = 0; j < aNbSubObjects; j++ ) {
4245           char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4246           aGroup->InternalObjectIndentify( j, name_dataset );
4247           // check if it is a hypothesis
4248           if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) {
4249             aDataset = new HDFdataset( name_dataset, aGroup );
4250             aDataset->OpenOnDisk();
4251             size = aDataset->GetSize();
4252             char* refFromFile = new char[ size ];
4253             aDataset->ReadFromDisk( refFromFile );
4254             aDataset->CloseOnDisk();
4255             // san - it is impossible to recover applied hypotheses using their entries within Load() method
4256             //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
4257             //CORBA::Object_var hypObject = SObjectToObject( hypSO );
4258             int id = atoi( refFromFile );
4259             string anIOR = myStudyContext->getIORbyOldId( id );
4260             if ( !anIOR.empty() ) {
4261               CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
4262               if ( !CORBA::is_nil( hypObject ) ) {
4263                 SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
4264                 if ( !anHyp->_is_nil() && (!aShapeObject->_is_nil()
4265                                            || !myNewMeshImpl->HasShapeToMesh()) )
4266                   myNewMeshImpl->addHypothesis( aShapeObject, anHyp );
4267               }
4268             }
4269           }
4270         }
4271         aGroup->CloseOnDisk();
4272       }
4273
4274       // --> try to find SUB-MESHES containers for each type of submesh
4275       for ( int j = GetSubMeshOnVertexTag(); j <= GetSubMeshOnCompoundTag(); j++ ) {
4276         char name_meshgroup[ 30 ];
4277         if ( j == GetSubMeshOnVertexTag() )
4278           strcpy( name_meshgroup, "SubMeshes On Vertex" );
4279         else if ( j == GetSubMeshOnEdgeTag() )
4280           strcpy( name_meshgroup, "SubMeshes On Edge" );
4281         else if ( j == GetSubMeshOnWireTag() )
4282           strcpy( name_meshgroup, "SubMeshes On Wire" );
4283         else if ( j == GetSubMeshOnFaceTag() )
4284           strcpy( name_meshgroup, "SubMeshes On Face" );
4285         else if ( j == GetSubMeshOnShellTag() )
4286           strcpy( name_meshgroup, "SubMeshes On Shell" );
4287         else if ( j == GetSubMeshOnSolidTag() )
4288           strcpy( name_meshgroup, "SubMeshes On Solid" );
4289         else if ( j == GetSubMeshOnCompoundTag() )
4290           strcpy( name_meshgroup, "SubMeshes On Compound" );
4291
4292         // try to get submeshes container HDF group
4293         if ( aTopGroup->ExistInternalObject( name_meshgroup ) ) {
4294           // open submeshes containers HDF group
4295           aGroup = new HDFgroup( name_meshgroup, aTopGroup );
4296           aGroup->OpenOnDisk();
4297
4298           // get number of submeshes
4299           int aNbSubMeshes = aGroup->nInternalObjects();
4300           for ( int k = 0; k < aNbSubMeshes; k++ ) {
4301             // identify submesh
4302             char name_submeshgroup[ HDF_NAME_MAX_LEN+1 ];
4303             aGroup->InternalObjectIndentify( k, name_submeshgroup );
4304             if ( string( name_submeshgroup ).substr( 0, 7 ) == string( "SubMesh" )  ) {
4305               // --> get submesh id
4306               int subid = atoi( string( name_submeshgroup ).substr( 7 ).c_str() );
4307               if ( subid <= 0 )
4308                 continue;
4309               // open submesh HDF group
4310               aSubGroup = new HDFgroup( name_submeshgroup, aGroup );
4311               aSubGroup->OpenOnDisk();
4312
4313               // try to read and set reference to subshape
4314               GEOM::GEOM_Object_var aSubShapeObject;
4315               SMESH::SMESH_subMesh_var aSubMesh;
4316
4317               if ( aSubGroup->ExistInternalObject( "Ref on shape" ) ) {
4318                 // load submesh "Ref on shape" - it's an entry to SObject
4319                 aDataset = new HDFdataset( "Ref on shape", aSubGroup );
4320                 aDataset->OpenOnDisk();
4321                 size = aDataset->GetSize();
4322                 char* refFromFile = new char[ size ];
4323                 aDataset->ReadFromDisk( refFromFile );
4324                 aDataset->CloseOnDisk();
4325                 if ( strlen( refFromFile ) > 0 ) {
4326                   SALOMEDS::SObject_var subShapeSO = myCurrentStudy->FindObjectID( refFromFile );
4327                   CORBA::Object_var subShapeObject = SObjectToObject( subShapeSO );
4328                   if ( !CORBA::is_nil( subShapeObject ) ) {
4329                     aSubShapeObject = GEOM::GEOM_Object::_narrow( subShapeObject );
4330                     if ( !aSubShapeObject->_is_nil() )
4331                       aSubMesh = SMESH::SMESH_subMesh::_duplicate
4332                         ( myNewMeshImpl->createSubMesh( aSubShapeObject ) );
4333                     if ( aSubMesh->_is_nil() )
4334                       continue;
4335                     string iorSubString = GetORB()->object_to_string( aSubMesh );
4336                     int newSubId = myStudyContext->findId( iorSubString );
4337                     myStudyContext->mapOldToNew( subid, newSubId );
4338                   }
4339                 }
4340               }
4341
4342               if ( aSubMesh->_is_nil() )
4343                 continue;
4344
4345               // try to get applied algorithms
4346               if ( aSubGroup->ExistInternalObject( "Applied Algorithms" ) ) {
4347                 // open "applied algorithms" HDF group
4348                 aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup );
4349                 aSubSubGroup->OpenOnDisk();
4350                 // get number of applied algorithms
4351                 int aNbSubObjects = aSubSubGroup->nInternalObjects();
4352                 for ( int l = 0; l < aNbSubObjects; l++ ) {
4353                   char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4354                   aSubSubGroup->InternalObjectIndentify( l, name_dataset );
4355                   // check if it is an algorithm
4356                   if ( string( name_dataset ).substr( 0, 4 ) == string( "Algo" ) ) {
4357                     aDataset = new HDFdataset( name_dataset, aSubSubGroup );
4358                     aDataset->OpenOnDisk();
4359                     size = aDataset->GetSize();
4360                     char* refFromFile = new char[ size ];
4361                     aDataset->ReadFromDisk( refFromFile );
4362                     aDataset->CloseOnDisk();
4363
4364                     int id = atoi( refFromFile );
4365                     string anIOR = myStudyContext->getIORbyOldId( id );
4366                     if ( !anIOR.empty() ) {
4367                       CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
4368                       if ( !CORBA::is_nil( hypObject ) ) {
4369                         SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
4370                         if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
4371                           myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
4372                       }
4373                     }
4374                   }
4375                 }
4376                 // close "applied algorithms" HDF group
4377                 aSubSubGroup->CloseOnDisk();
4378               }
4379
4380               // try to get applied hypotheses
4381               if ( aSubGroup->ExistInternalObject( "Applied Hypotheses" ) ) {
4382                 // open "applied hypotheses" HDF group
4383                 aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup );
4384                 aSubSubGroup->OpenOnDisk();
4385                 // get number of applied hypotheses
4386                 int aNbSubObjects = aSubSubGroup->nInternalObjects();
4387                 for ( int l = 0; l < aNbSubObjects; l++ ) {
4388                   char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4389                   aSubSubGroup->InternalObjectIndentify( l, name_dataset );
4390                   // check if it is a hypothesis
4391                   if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) {
4392                     aDataset = new HDFdataset( name_dataset, aSubSubGroup );
4393                     aDataset->OpenOnDisk();
4394                     size = aDataset->GetSize();
4395                     char* refFromFile = new char[ size ];
4396                     aDataset->ReadFromDisk( refFromFile );
4397                     aDataset->CloseOnDisk();
4398
4399                     int id = atoi( refFromFile );
4400                     string anIOR = myStudyContext->getIORbyOldId( id );
4401                     if ( !anIOR.empty() ) {
4402                       CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
4403                       if ( !CORBA::is_nil( hypObject ) ) {
4404                         SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
4405                         if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
4406                           myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
4407                       }
4408                     }
4409                   }
4410                 }
4411                 // close "APPLIED HYPOTHESES" hdf group
4412                 aSubSubGroup->CloseOnDisk();
4413               }
4414
4415               // close SUB-MESH hdf group
4416               aSubGroup->CloseOnDisk();
4417             }
4418           }
4419           // close SUB-MESHES containers hdf group
4420           aGroup->CloseOnDisk();
4421         }
4422       }
4423
4424       // try to get GROUPS
4425       for ( int ii = GetNodeGroupsTag(); ii <= Get0DElementsGroupsTag(); ii++ ) {
4426         char name_group[ 30 ];
4427         if ( ii == GetNodeGroupsTag() )
4428           strcpy( name_group, "Groups of Nodes" );
4429         else if ( ii == GetEdgeGroupsTag() )
4430           strcpy( name_group, "Groups of Edges" );
4431         else if ( ii == GetFaceGroupsTag() )
4432           strcpy( name_group, "Groups of Faces" );
4433         else if ( ii == GetVolumeGroupsTag() )
4434           strcpy( name_group, "Groups of Volumes" );
4435         else if ( ii == Get0DElementsGroupsTag() )
4436           strcpy( name_group, "Groups of 0D Elements" );
4437
4438         if ( aTopGroup->ExistInternalObject( name_group ) ) {
4439           aGroup = new HDFgroup( name_group, aTopGroup );
4440           aGroup->OpenOnDisk();
4441           // get number of groups
4442           int aNbSubObjects = aGroup->nInternalObjects();
4443           for ( int j = 0; j < aNbSubObjects; j++ ) {
4444             char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4445             aGroup->InternalObjectIndentify( j, name_dataset );
4446             // check if it is an group
4447             if ( string( name_dataset ).substr( 0, 5 ) == string( "Group" ) ) {
4448               // --> get group id
4449               int subid = atoi( string( name_dataset ).substr( 5 ).c_str() );
4450               if ( subid <= 0 )
4451                 continue;
4452               aDataset = new HDFdataset( name_dataset, aGroup );
4453               aDataset->OpenOnDisk();
4454
4455               // Retrieve actual group name
4456               size = aDataset->GetSize();
4457               char* nameFromFile = new char[ size ];
4458               aDataset->ReadFromDisk( nameFromFile );
4459               aDataset->CloseOnDisk();
4460
4461               // Try to find a shape reference
4462               TopoDS_Shape aShape;
4463               char aRefName[ 30 ];
4464               sprintf( aRefName, "Ref on shape %d", subid);
4465               if ( aGroup->ExistInternalObject( aRefName ) ) {
4466                 // load mesh "Ref on shape" - it's an entry to SObject
4467                 aDataset = new HDFdataset( aRefName, aGroup );
4468                 aDataset->OpenOnDisk();
4469                 size = aDataset->GetSize();
4470                 char* refFromFile = new char[ size ];
4471                 aDataset->ReadFromDisk( refFromFile );
4472                 aDataset->CloseOnDisk();
4473                 if ( strlen( refFromFile ) > 0 ) {
4474                   SALOMEDS::SObject_var shapeSO = myCurrentStudy->FindObjectID( refFromFile );
4475                   CORBA::Object_var shapeObject = SObjectToObject( shapeSO );
4476                   if ( !CORBA::is_nil( shapeObject ) ) {
4477                     aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
4478                     if ( !aShapeObject->_is_nil() )
4479                       aShape = GeomObjectToShape( aShapeObject );
4480                   }
4481                 }
4482               }
4483               // Try to read a filter of SMESH_GroupOnFilter
4484               SMESH::Filter_var filter;
4485               SMESH_PredicatePtr predicate;
4486               std::string hdfGrpName = "Filter " + SMESH_Comment(subid);
4487               if ( aGroup->ExistInternalObject( hdfGrpName.c_str() ))
4488               {
4489                 aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup );
4490                 aDataset->OpenOnDisk();
4491                 size = aDataset->GetSize();
4492                 char* persistStr = new char[ size ];
4493                 aDataset->ReadFromDisk( persistStr );
4494                 aDataset->CloseOnDisk();
4495                 if ( strlen( persistStr ) > 0 ) {
4496                   filter = SMESH_GroupOnFilter_i::StringToFilter( persistStr );
4497                   predicate = SMESH_GroupOnFilter_i::GetPredicate( filter );
4498                 }
4499               }
4500
4501               // Create group servant
4502               SMESH::ElementType type = (SMESH::ElementType)(ii - GetNodeGroupsTag() + 1);
4503               SMESH::SMESH_GroupBase_var aNewGroup = SMESH::SMESH_GroupBase::_duplicate
4504                 ( myNewMeshImpl->createGroup( type, nameFromFile, aShape, predicate ) );
4505               // Obtain a SMESHDS_Group object
4506               if ( aNewGroup->_is_nil() )
4507                 continue;
4508
4509               string iorSubString = GetORB()->object_to_string( aNewGroup );
4510               int newSubId = myStudyContext->findId( iorSubString );
4511               myStudyContext->mapOldToNew( subid, newSubId );
4512
4513               SMESH_GroupBase_i* aGroupImpl = SMESH::DownCast< SMESH_GroupBase_i*>( aNewGroup );
4514               if ( !aGroupImpl )
4515                 continue;
4516
4517               if ( SMESH_GroupOnFilter_i* aFilterGroup =
4518                    dynamic_cast< SMESH_GroupOnFilter_i*>( aGroupImpl ))
4519                 aFilterGroup->SetFilter( filter );
4520
4521               SMESHDS_GroupBase* aGroupBaseDS = aGroupImpl->GetGroupDS();
4522               if ( !aGroupBaseDS )
4523                 continue;
4524
4525               aGroupBaseDS->SetStoreName( name_dataset );
4526
4527               // ouv : NPAL12872
4528               // Read color of the group
4529               char aGroupColorName[ 30 ];
4530               sprintf( aGroupColorName, "ColorGroup %d", subid);
4531               if ( aGroup->ExistInternalObject( aGroupColorName ) )
4532               {
4533                 aDataset = new HDFdataset( aGroupColorName, aGroup );
4534                 aDataset->OpenOnDisk();
4535                 size = aDataset->GetSize();
4536                 double* anRGB = new double[ size ];
4537                 aDataset->ReadFromDisk( anRGB );
4538                 aDataset->CloseOnDisk();
4539                 Quantity_Color aColor( anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB );
4540                 aGroupBaseDS->SetColor( aColor );
4541               }
4542
4543               // Fill group with contents from MED file
4544               // SMESHDS_Group* aGrp = dynamic_cast<SMESHDS_Group*>( aGroupBaseDS );
4545               // if ( aGrp )
4546               //   myReader.GetGroup( aGrp );
4547             }
4548           }
4549           aGroup->CloseOnDisk();
4550         }
4551       } // reading GROUPs
4552
4553       // instead of reading mesh data, we read only brief information of all
4554       // objects: mesh, groups, sub-meshes (issue 0021208 )
4555       if ( hasData )
4556       {
4557         SMESH_PreMeshInfo::LoadFromFile( myNewMeshImpl, id,
4558                                          meshfile.ToCString(), filename.ToCString(),
4559                                          !isMultiFile );
4560       }
4561
4562       // read Sub-Mesh ORDER if any
4563       if( aTopGroup->ExistInternalObject( "Mesh Order" ) ) {
4564         aDataset = new HDFdataset( "Mesh Order", aTopGroup );
4565         aDataset->OpenOnDisk();
4566         size = aDataset->GetSize();
4567         int* smIDs = new int[ size ];
4568         aDataset->ReadFromDisk( smIDs );
4569         aDataset->CloseOnDisk();
4570         TListOfListOfInt anOrderIds;
4571         anOrderIds.push_back( TListOfInt() );
4572         for ( int i = 0; i < size; i++ )
4573           if ( smIDs[ i ] < 0 ) // is separator
4574             anOrderIds.push_back( TListOfInt() );
4575           else
4576             anOrderIds.back().push_back(smIDs[ i ]);
4577
4578         myNewMeshImpl->GetImpl().SetMeshOrder( anOrderIds );
4579       }
4580     } // loop on meshes
4581
4582     // update hyps needing full mesh data restored (issue 20918)
4583     for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data )
4584     {
4585       SMESH_Hypothesis_i* hyp  = hyp_data->first;
4586       hyp->UpdateAsMeshesRestored();
4587     }
4588
4589     // notify algos on completed restoration to set sub-mesh event listeners
4590     for ( meshi_group = meshGroupList.begin(); meshi_group != meshGroupList.end(); ++meshi_group )
4591     {
4592       SMESH_Mesh_i* myNewMeshImpl = meshi_group->first;
4593       ::SMESH_Mesh& myLocMesh     = myNewMeshImpl->GetImpl();
4594
4595       TopoDS_Shape myLocShape;
4596       if(myLocMesh.HasShapeToMesh())
4597         myLocShape = myLocMesh.GetShapeToMesh();
4598       else
4599         myLocShape = SMESH_Mesh::PseudoShape();
4600
4601       myLocMesh.GetSubMesh(myLocShape)->
4602         ComputeStateEngine (SMESH_subMesh::SUBMESH_RESTORED);
4603     }
4604
4605     // close mesh group
4606     if(aTopGroup)
4607       aTopGroup->CloseOnDisk();
4608   }
4609   // close HDF file
4610   aFile->CloseOnDisk();
4611   delete aFile;
4612
4613   // Remove temporary files created from the stream
4614   // if ( !isMultiFile )
4615   //   SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
4616
4617   pd << ""; // prevent optimizing pd out
4618
4619   INFOS( "SMESH_Gen_i::Load completed" );
4620   return true;
4621 }
4622
4623 //=============================================================================
4624 /*!
4625  *  SMESH_Gen_i::LoadASCII
4626  *
4627  *  Load SMESH module's data in ASCII format
4628  */
4629 //=============================================================================
4630
4631 bool SMESH_Gen_i::LoadASCII( SALOMEDS::SComponent_ptr theComponent,
4632                              const SALOMEDS::TMPFile& theStream,
4633                              const char*              theURL,
4634                              bool                     isMultiFile ) {
4635   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LoadASCII" );
4636   return Load( theComponent, theStream, theURL, isMultiFile );
4637
4638   //before call main ::Load method it's need for decipher text format to
4639   //binary ( "|xx" => x' )
4640   int size = theStream.length();
4641   if ( int((size / 3 )*3) != size ) //error size of buffer
4642     return false;
4643
4644   int real_size = int(size / 3);
4645
4646   _CORBA_Octet* buffer = new _CORBA_Octet[real_size];
4647   char tmp[3];
4648   tmp[2]='\0';
4649   int c = -1;
4650   for ( int i = 0; i < real_size; i++ )
4651   {
4652     memcpy( &(tmp[0]), &(theStream[i*3+1]), 2 );
4653     sscanf( tmp, "%x", &c );
4654     sprintf( (char*)&(buffer[i]), "%c", (char)c );
4655   }
4656
4657   SALOMEDS::TMPFile_var aRealStreamFile = new SALOMEDS::TMPFile(real_size, real_size, buffer, 1);
4658
4659   return Load( theComponent, *(aRealStreamFile._retn()), theURL, isMultiFile );
4660 }
4661
4662 //=============================================================================
4663 /*!
4664  *  SMESH_Gen_i::Close
4665  *
4666  *  Clears study-connected data when it is closed
4667  */
4668 //=============================================================================
4669
4670 void SMESH_Gen_i::Close( SALOMEDS::SComponent_ptr theComponent )
4671 {
4672   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Close" );
4673
4674   // set correct current study
4675   SALOMEDS::Study_var study = theComponent->GetStudy();
4676   if ( study->StudyId() != GetCurrentStudyID())
4677     SetCurrentStudy( study );
4678
4679   // Clear study contexts data
4680   int studyId = GetCurrentStudyID();
4681   if ( myStudyContextMap.find( studyId ) != myStudyContextMap.end() ) {
4682     delete myStudyContextMap[ studyId ];
4683     myStudyContextMap.erase( studyId );
4684   }
4685
4686   // delete SMESH_Mesh's
4687 //   See bug IPAL19437.
4688 //
4689 //   StudyContextStruct* context = myGen.GetStudyContext( studyId );
4690 //   map< int, SMESH_Mesh* >::iterator i_mesh = context->mapMesh.begin();
4691 //   for ( ; i_mesh != context->mapMesh.end(); ++i_mesh ) {
4692 //     printf( "--------------------------- SMESH_Gen_i::Close, delete aGroup = %p \n", i_mesh->second );
4693 //     delete i_mesh->second;
4694 //   }
4695
4696
4697   // delete SMESHDS_Mesh's
4698   // it's too long on big meshes
4699 //   if ( context->myDocument ) {
4700 //     delete context->myDocument;
4701 //     context->myDocument = 0;
4702 //   }
4703
4704   // remove the tmp files meshes are loaded from
4705   SMESH_PreMeshInfo::RemoveStudyFiles_TMP_METHOD( theComponent );
4706
4707   myCurrentStudy = SALOMEDS::Study::_nil();
4708   return;
4709 }
4710
4711 //=============================================================================
4712 /*!
4713  *  SMESH_Gen_i::ComponentDataType
4714  *
4715  *  Get component data type
4716  */
4717 //=============================================================================
4718
4719 char* SMESH_Gen_i::ComponentDataType()
4720 {
4721   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::ComponentDataType" );
4722   return CORBA::string_dup( "SMESH" );
4723 }
4724
4725
4726 //=============================================================================
4727 /*!
4728  *  SMESH_Gen_i::IORToLocalPersistentID
4729  *
4730  *  Transform data from transient form to persistent
4731  */
4732 //=============================================================================
4733
4734 char* SMESH_Gen_i::IORToLocalPersistentID( SALOMEDS::SObject_ptr /*theSObject*/,
4735                                            const char*           IORString,
4736                                            CORBA::Boolean        /*isMultiFile*/,
4737                                            CORBA::Boolean        /*isASCII*/ )
4738 {
4739   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IORToLocalPersistentID" );
4740   StudyContext* myStudyContext = GetCurrentStudyContext();
4741
4742   if ( myStudyContext && strcmp( IORString, "" ) != 0 ) {
4743     int anId = myStudyContext->findId( IORString );
4744     if ( anId ) {
4745       if(MYDEBUG) MESSAGE( "VSR " << anId )
4746       char strId[ 20 ];
4747       sprintf( strId, "%d", anId );
4748       return  CORBA::string_dup( strId );
4749     }
4750   }
4751   return CORBA::string_dup( "" );
4752 }
4753
4754 //=============================================================================
4755 /*!
4756  *  SMESH_Gen_i::LocalPersistentIDToIOR
4757  *
4758  *  Transform data from persistent form to transient
4759  */
4760 //=============================================================================
4761
4762 char* SMESH_Gen_i::LocalPersistentIDToIOR( SALOMEDS::SObject_ptr /*theSObject*/,
4763                                            const char*           aLocalPersistentID,
4764                                            CORBA::Boolean        /*isMultiFile*/,
4765                                            CORBA::Boolean        /*isASCII*/ )
4766 {
4767   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LocalPersistentIDToIOR(): id = " << aLocalPersistentID );
4768   StudyContext* myStudyContext = GetCurrentStudyContext();
4769
4770   if ( myStudyContext && strcmp( aLocalPersistentID, "" ) != 0 ) {
4771     int anId = atoi( aLocalPersistentID );
4772     return CORBA::string_dup( myStudyContext->getIORbyOldId( anId ).c_str() );
4773   }
4774   return CORBA::string_dup( "" );
4775 }
4776
4777 //=======================================================================
4778 //function : RegisterObject
4779 //purpose  :
4780 //=======================================================================
4781
4782 int SMESH_Gen_i::RegisterObject(CORBA::Object_ptr theObject)
4783 {
4784   StudyContext* myStudyContext = GetCurrentStudyContext();
4785   if ( myStudyContext && !CORBA::is_nil( theObject )) {
4786     CORBA::String_var iorString = GetORB()->object_to_string( theObject );
4787     return myStudyContext->addObject( string( iorString.in() ) );
4788   }
4789   return 0;
4790 }
4791
4792 //================================================================================
4793 /*!
4794  * \brief Return id of registered object
4795   * \param theObject - the Object
4796   * \retval int - Object id
4797  */
4798 //================================================================================
4799
4800 CORBA::Long SMESH_Gen_i::GetObjectId(CORBA::Object_ptr theObject)
4801 {
4802   StudyContext* myStudyContext = GetCurrentStudyContext();
4803   if ( myStudyContext && !CORBA::is_nil( theObject )) {
4804     string iorString = GetORB()->object_to_string( theObject );
4805     return myStudyContext->findId( iorString );
4806   }
4807   return 0;
4808 }
4809
4810 //=============================================================================
4811 /*!
4812  *  SMESH_Gen_i::SetName
4813  *
4814  *  Set a new object name
4815  */
4816 //=============================================================================
4817 void SMESH_Gen_i::SetName(const char* theIOR,
4818                           const char* theName)
4819 {
4820   if ( theIOR && strcmp( theIOR, "" ) ) {
4821     CORBA::Object_var anObject = GetORB()->string_to_object( theIOR );
4822     SALOMEDS::SObject_var aSO = ObjectToSObject( myCurrentStudy, anObject );
4823     if ( !aSO->_is_nil() ) {
4824       SetName( aSO, theName );
4825     }
4826   }
4827 }
4828
4829 int SMESH_Gen_i::GetCurrentStudyID()
4830 {
4831   return myCurrentStudy->_is_nil() || myCurrentStudy->_non_existent() ? -1 : myCurrentStudy->StudyId();
4832 }
4833
4834 //=============================================================================
4835 /*!
4836  *  SMESHEngine_factory
4837  *
4838  *  C factory, accessible with dlsym, after dlopen
4839  */
4840 //=============================================================================
4841
4842 extern "C"
4843 { SMESH_I_EXPORT
4844   PortableServer::ObjectId* SMESHEngine_factory( CORBA::ORB_ptr            orb,
4845                                                  PortableServer::POA_ptr   poa,
4846                                                  PortableServer::ObjectId* contId,
4847                                                  const char*               instanceName,
4848                                                  const char*               interfaceName )
4849   {
4850     if(MYDEBUG) MESSAGE( "PortableServer::ObjectId* SMESHEngine_factory()" );
4851     if(MYDEBUG) SCRUTE(interfaceName);
4852     SMESH_Gen_i* aSMESHGen = new SMESH_Gen_i(orb, poa, contId, instanceName, interfaceName);
4853     return aSMESHGen->getId() ;
4854   }
4855 }