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