Salome HOME
Update copyright
[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   *pyDump << newMesh << " = " << this
2448           << ".CopyMesh( " << meshPart << ", "
2449           << "'" << meshName << "', "
2450           << toCopyGroups << ", "
2451           << toKeepIDs << ")";
2452
2453   delete pyDump; pyDump = 0; // allow dump in GetGroups()
2454
2455   if ( nbNewGroups > 0 ) // dump created groups
2456     SMESH::ListOfGroups_var groups = newMesh->GetGroups();
2457
2458   return newMesh._retn();
2459 }
2460
2461 //================================================================================
2462 /*!
2463  *  SMESH_Gen_i::GetMEDVersion
2464  *
2465  *  Get MED version of the file by its name
2466  */
2467 //================================================================================
2468 CORBA::Boolean SMESH_Gen_i::GetMEDVersion(const char* theFileName,
2469                                           SMESH::MED_VERSION& theVersion)
2470 {
2471   theVersion = SMESH::MED_V2_1;
2472   MED::EVersion aVersion = MED::GetVersionId( theFileName );
2473   switch( aVersion ) {
2474     case MED::eV2_1     : theVersion = SMESH::MED_V2_1; return true;
2475     case MED::eV2_2     : theVersion = SMESH::MED_V2_2; return true;
2476     case MED::eVUnknown : return false;
2477   }
2478   return false;
2479 }
2480
2481 //================================================================================
2482 /*!
2483  *  SMESH_Gen_i::GetMeshNames
2484  *
2485  *  Get names of meshes defined in file with the specified name
2486  */
2487 //================================================================================
2488 SMESH::string_array* SMESH_Gen_i::GetMeshNames(const char* theFileName)
2489 {
2490   SMESH::string_array_var aResult = new SMESH::string_array();
2491   MED::PWrapper aMed = MED::CrWrapper( theFileName );
2492   MED::TErr anErr;
2493   MED::TInt aNbMeshes = aMed->GetNbMeshes( &anErr );
2494   if( anErr >= 0 ) {
2495     aResult->length( aNbMeshes );
2496     for( MED::TInt i = 0; i < aNbMeshes; i++ ) {
2497       MED::PMeshInfo aMeshInfo = aMed->GetPMeshInfo( i+1 );
2498       aResult[i] = CORBA::string_dup( aMeshInfo->GetName().c_str() );
2499     }
2500   }
2501   return aResult._retn();
2502 }
2503
2504 //=============================================================================
2505 /*!
2506  *  SMESH_Gen_i::Save
2507  *
2508  *  Save SMESH module's data
2509  */
2510 //=============================================================================
2511 SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
2512                                       const char*              theURL,
2513                                       bool                     isMultiFile )
2514 {
2515   INFOS( "SMESH_Gen_i::Save" );
2516
2517   //  ASSERT( theComponent->GetStudy()->StudyId() == myCurrentStudy->StudyId() )
2518   // san -- in case <myCurrentStudy> differs from theComponent's study,
2519   // use that of the component
2520   if ( myCurrentStudy->_is_nil() ||
2521     theComponent->GetStudy()->StudyId() != myCurrentStudy->StudyId() )
2522     SetCurrentStudy( theComponent->GetStudy() );
2523
2524   // Store study contents as a set of python commands
2525   SavePython(myCurrentStudy);
2526
2527   StudyContext* myStudyContext = GetCurrentStudyContext();
2528
2529   // Declare a byte stream
2530   SALOMEDS::TMPFile_var aStreamFile;
2531
2532   // Obtain a temporary dir
2533   TCollection_AsciiString tmpDir =
2534     ( isMultiFile ) ? TCollection_AsciiString( ( char* )theURL ) : ( char* )SALOMEDS_Tool::GetTmpDir().c_str();
2535
2536   // Create a sequence of files processed
2537   SALOMEDS::ListOfFileNames_var aFileSeq = new SALOMEDS::ListOfFileNames;
2538   aFileSeq->length( NUM_TMP_FILES );
2539
2540   TCollection_AsciiString aStudyName( "" );
2541   if ( isMultiFile )
2542     aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( myCurrentStudy->URL() ).c_str() );
2543
2544   // Set names of temporary files
2545   TCollection_AsciiString filename =
2546     aStudyName + TCollection_AsciiString( "_SMESH.hdf" );        // for SMESH data itself
2547   TCollection_AsciiString meshfile =
2548     aStudyName + TCollection_AsciiString( "_SMESH_Mesh.med" );   // for mesh data to be stored in MED file
2549   aFileSeq[ 0 ] = CORBA::string_dup( filename.ToCString() );
2550   aFileSeq[ 1 ] = CORBA::string_dup( meshfile.ToCString() );
2551   filename = tmpDir + filename;
2552   meshfile = tmpDir + meshfile;
2553
2554   HDFfile*    aFile;
2555   HDFdataset* aDataset;
2556   HDFgroup*   aTopGroup;
2557   HDFgroup*   aGroup;
2558   HDFgroup*   aSubGroup;
2559   HDFgroup*   aSubSubGroup;
2560   hdf_size    aSize[ 1 ];
2561
2562
2563   //Remove the files if they exist: BugID: 11225
2564 #ifndef WNT /* unix functionality */
2565   TCollection_AsciiString cmd("rm -f \"");
2566 #else /* windows */
2567   TCollection_AsciiString cmd("del /F \"");
2568 #endif
2569
2570   cmd+=filename;
2571   cmd+="\" \"";
2572   cmd+=meshfile;
2573   cmd+="\"";
2574   system(cmd.ToCString());
2575
2576   // MED writer to be used by storage process
2577   DriverMED_W_SMESHDS_Mesh myWriter;
2578   myWriter.SetFile( meshfile.ToCString() );
2579
2580   // IMP issue 20918
2581   // SetStoreName() to groups before storing hypotheses to let them refer to
2582   // groups using "store name", which is "Group <group_persistent_id>"
2583   {
2584     SALOMEDS::ChildIterator_var itBig = myCurrentStudy->NewChildIterator( theComponent );
2585     for ( ; itBig->More(); itBig->Next() ) {
2586       SALOMEDS::SObject_var gotBranch = itBig->Value();
2587       if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) {
2588         CORBA::Object_var anObject = SObjectToObject( gotBranch );
2589         if ( !CORBA::is_nil( anObject ) ) {
2590           SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ;
2591           if ( !myMesh->_is_nil() ) {
2592             SMESH::ListOfGroups_var groups = myMesh->GetGroups();
2593             for ( int i = 0; i < groups->length(); ++i )
2594             {
2595               SMESH_GroupBase_i* grImpl = SMESH::DownCast<SMESH_GroupBase_i*>( groups[i]);
2596               if ( grImpl )
2597               {
2598                 CORBA::String_var objStr = GetORB()->object_to_string( grImpl->_this() );
2599                 int anId = myStudyContext->findId( string( objStr.in() ) );
2600                 char grpName[ 30 ];
2601                 sprintf( grpName, "Group %d", anId );
2602                 SMESHDS_GroupBase* aGrpBaseDS = grImpl->GetGroupDS();
2603                 aGrpBaseDS->SetStoreName( grpName );
2604               }
2605             }
2606           }
2607         }
2608       }
2609     }
2610   }
2611
2612   // Write data
2613   // ---> create HDF file
2614   aFile = new HDFfile( (char*) filename.ToCString() );
2615   aFile->CreateOnDisk();
2616
2617   // --> iterator for top-level objects
2618   SALOMEDS::ChildIterator_var itBig = myCurrentStudy->NewChildIterator( theComponent );
2619   for ( ; itBig->More(); itBig->Next() ) {
2620     SALOMEDS::SObject_var gotBranch = itBig->Value();
2621
2622     // --> hypotheses root branch (only one for the study)
2623     if ( gotBranch->Tag() == GetHypothesisRootTag() ) {
2624       // create hypotheses root HDF group
2625       aTopGroup = new HDFgroup( "Hypotheses", aFile );
2626       aTopGroup->CreateOnDisk();
2627
2628       // iterator for all hypotheses
2629       SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( gotBranch );
2630       for ( ; it->More(); it->Next() ) {
2631         SALOMEDS::SObject_var mySObject = it->Value();
2632         CORBA::Object_var anObject = SObjectToObject( mySObject );
2633         if ( !CORBA::is_nil( anObject ) ) {
2634           SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject );
2635           if ( !myHyp->_is_nil() ) {
2636             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
2637             if ( myImpl ) {
2638               string hypname = string( myHyp->GetName() );
2639               string libname = string( myHyp->GetLibName() );
2640               // BUG SWP13062
2641               // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for
2642               // WNT and ".so" for X-system) must be deleted
2643               int libname_len = libname.length();
2644 #ifdef WNT
2645               if( libname_len > 4 )
2646                 libname.resize( libname_len - 4 );
2647 #else
2648               // PAL17753 (Regresion: missing hypothesis in restored study)
2649               // "lib" also should be removed from the beginning
2650               //if( libname_len > 3 )
2651                 //libname.resize( libname_len - 3 );
2652               if( libname_len > 6 )
2653                 libname = libname.substr( 3, libname_len - 3 - 3 );
2654 #endif
2655               CORBA::String_var objStr = GetORB()->object_to_string( anObject );
2656               int    id      = myStudyContext->findId( string( objStr.in() ) );
2657               string hypdata = string( myImpl->SaveTo() );
2658
2659               // for each hypothesis create HDF group basing on its id
2660               char hypGrpName[30];
2661               sprintf( hypGrpName, "Hypothesis %d", id );
2662               aGroup = new HDFgroup( hypGrpName, aTopGroup );
2663               aGroup->CreateOnDisk();
2664               // --> type name of hypothesis
2665               aSize[ 0 ] = hypname.length() + 1;
2666               aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 );
2667               aDataset->CreateOnDisk();
2668               aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) );
2669               aDataset->CloseOnDisk();
2670               // --> server plugin library name of hypothesis
2671               aSize[ 0 ] = libname.length() + 1;
2672               aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 );
2673               aDataset->CreateOnDisk();
2674               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
2675               aDataset->CloseOnDisk();
2676               // --> persistent data of hypothesis
2677               aSize[ 0 ] = hypdata.length() + 1;
2678               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
2679               aDataset->CreateOnDisk();
2680               aDataset->WriteOnDisk( ( char* )( hypdata.c_str() ) );
2681               aDataset->CloseOnDisk();
2682               // close hypothesis HDF group
2683               aGroup->CloseOnDisk();
2684             }
2685           }
2686         }
2687       }
2688       // close hypotheses root HDF group
2689       aTopGroup->CloseOnDisk();
2690     }
2691     // --> algorithms root branch (only one for the study)
2692     else if ( gotBranch->Tag() == GetAlgorithmsRootTag() ) {
2693       // create algorithms root HDF group
2694       aTopGroup = new HDFgroup( "Algorithms", aFile );
2695       aTopGroup->CreateOnDisk();
2696
2697       // iterator for all algorithms
2698       SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( gotBranch );
2699       for ( ; it->More(); it->Next() ) {
2700         SALOMEDS::SObject_var mySObject = it->Value();
2701         CORBA::Object_var anObject = SObjectToObject( mySObject );
2702         if ( !CORBA::is_nil( anObject ) ) {
2703           SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject );
2704           if ( !myHyp->_is_nil() ) {
2705             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
2706             if ( myImpl ) {
2707               string hypname = string( myHyp->GetName() );
2708               string libname = string( myHyp->GetLibName() );
2709               // BUG SWP13062
2710               // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for
2711               // WNT and ".so" for X-system) must be deleted
2712               int libname_len = libname.length();
2713 #ifdef WNT
2714               if( libname_len > 4 )
2715                 libname.resize( libname_len - 4 );
2716 #else
2717               // PAL17753 (Regresion: missing hypothesis in restored study)
2718               // "lib" also should be removed from the beginning
2719               //if( libname_len > 3 )
2720                 //libname.resize( libname_len - 3 );
2721               if( libname_len > 6 )
2722                 libname = libname.substr( 3, libname_len - 3 - 3 );
2723 #endif
2724               CORBA::String_var objStr = GetORB()->object_to_string( anObject );
2725               int    id      = myStudyContext->findId( string( objStr.in() ) );
2726               string hypdata = string( myImpl->SaveTo() );
2727
2728               // for each algorithm create HDF group basing on its id
2729               char hypGrpName[30];
2730               sprintf( hypGrpName, "Algorithm %d", id );
2731               aGroup = new HDFgroup( hypGrpName, aTopGroup );
2732               aGroup->CreateOnDisk();
2733               // --> type name of algorithm
2734               aSize[0] = hypname.length() + 1;
2735               aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 );
2736               aDataset->CreateOnDisk();
2737               aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) );
2738               aDataset->CloseOnDisk();
2739               // --> server plugin library name of hypothesis
2740               aSize[0] = libname.length() + 1;
2741               aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 );
2742               aDataset->CreateOnDisk();
2743               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
2744               aDataset->CloseOnDisk();
2745               // --> persistent data of algorithm
2746               aSize[0] = hypdata.length() + 1;
2747               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
2748               aDataset->CreateOnDisk();
2749               aDataset->WriteOnDisk( ( char* )( hypdata.c_str() ) );
2750               aDataset->CloseOnDisk();
2751               // close algorithm HDF group
2752               aGroup->CloseOnDisk();
2753             }
2754           }
2755         }
2756       }
2757       // close algorithms root HDF group
2758       aTopGroup->CloseOnDisk();
2759     }
2760     // --> mesh objects roots branches
2761     else if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) {
2762       CORBA::Object_var anObject = SObjectToObject( gotBranch );
2763       if ( !CORBA::is_nil( anObject ) ) {
2764         SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ;
2765         if ( !myMesh->_is_nil() ) {
2766           SMESH_Mesh_i* myImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( myMesh ).in() );
2767           if ( myImpl ) {
2768             CORBA::String_var objStr = GetORB()->object_to_string( anObject );
2769             int id = myStudyContext->findId( string( objStr.in() ) );
2770             ::SMESH_Mesh& myLocMesh = myImpl->GetImpl();
2771             SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS();
2772             bool hasShape = myLocMesh.HasShapeToMesh();
2773
2774             // for each mesh open the HDF group basing on its id
2775             char meshGrpName[ 30 ];
2776             sprintf( meshGrpName, "Mesh %d", id );
2777             aTopGroup = new HDFgroup( meshGrpName, aFile );
2778             aTopGroup->CreateOnDisk();
2779
2780             // --> put dataset to hdf file which is a flag that mesh has data
2781             string strHasData = "0";
2782             // check if the mesh is not empty
2783             if ( mySMESHDSMesh->NbNodes() > 0 ) {
2784               // write mesh data to med file
2785               myWriter.SetMesh( mySMESHDSMesh );
2786               myWriter.SetMeshId( id );
2787               strHasData = "1";
2788             }
2789             aSize[ 0 ] = strHasData.length() + 1;
2790             aDataset = new HDFdataset( "Has data", aTopGroup, HDF_STRING, aSize, 1 );
2791             aDataset->CreateOnDisk();
2792             aDataset->WriteOnDisk( ( char* )( strHasData.c_str() ) );
2793             aDataset->CloseOnDisk();
2794
2795             // ouv : NPAL12872
2796             // for each mesh open the HDF group basing on its auto color parameter
2797             char meshAutoColorName[ 30 ];
2798             sprintf( meshAutoColorName, "AutoColorMesh %d", id );
2799             int anAutoColor[1];
2800             anAutoColor[0] = myImpl->GetAutoColor();
2801             aSize[ 0 ] = 1;
2802             aDataset = new HDFdataset( meshAutoColorName, aTopGroup, HDF_INT32, aSize, 1 );
2803             aDataset->CreateOnDisk();
2804             aDataset->WriteOnDisk( anAutoColor );
2805             aDataset->CloseOnDisk();
2806
2807             // issue 0020693. Store _isModified flag
2808             int isModified = myLocMesh.GetIsModified();
2809             aSize[ 0 ] = 1;
2810             aDataset = new HDFdataset( "_isModified", aTopGroup, HDF_INT32, aSize, 1 );
2811             aDataset->CreateOnDisk();
2812             aDataset->WriteOnDisk( &isModified );
2813             aDataset->CloseOnDisk();
2814
2815             // issue 20918. Store Persistent Id of SMESHDS_Mesh
2816             int meshPersistentId = mySMESHDSMesh->GetPersistentId();
2817             aSize[ 0 ] = 1;
2818             aDataset = new HDFdataset( "meshPersistentId", aTopGroup, HDF_INT32, aSize, 1 );
2819             aDataset->CreateOnDisk();
2820             aDataset->WriteOnDisk( &meshPersistentId );
2821             aDataset->CloseOnDisk();
2822
2823             // write reference on a shape if exists
2824             SALOMEDS::SObject_var myRef;
2825             bool shapeRefFound = false;
2826             bool found = gotBranch->FindSubObject( GetRefOnShapeTag(), myRef );
2827             if ( found ) {
2828               SALOMEDS::SObject_var myShape;
2829               bool ok = myRef->ReferencedObject( myShape );
2830               if ( ok ) {
2831                 shapeRefFound = (! CORBA::is_nil( myShape->GetObject() ));
2832                 string myRefOnObject = myShape->GetID();
2833                 if ( shapeRefFound && myRefOnObject.length() > 0 ) {
2834                   aSize[ 0 ] = myRefOnObject.length() + 1;
2835                   aDataset = new HDFdataset( "Ref on shape", aTopGroup, HDF_STRING, aSize, 1 );
2836                   aDataset->CreateOnDisk();
2837                   aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
2838                   aDataset->CloseOnDisk();
2839                 }
2840               }
2841             }
2842
2843             // write applied hypotheses if exist
2844             SALOMEDS::SObject_var myHypBranch;
2845             found = gotBranch->FindSubObject( GetRefOnAppliedHypothesisTag(), myHypBranch );
2846             if ( found && !shapeRefFound && hasShape) { // remove applied hyps
2847               myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( myHypBranch );
2848             }
2849             if ( found && (shapeRefFound || !hasShape) ) {
2850               aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup );
2851               aGroup->CreateOnDisk();
2852
2853               SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( myHypBranch );
2854               int hypNb = 0;
2855               for ( ; it->More(); it->Next() ) {
2856                 SALOMEDS::SObject_var mySObject = it->Value();
2857                 SALOMEDS::SObject_var myRefOnHyp;
2858                 bool ok = mySObject->ReferencedObject( myRefOnHyp );
2859                 if ( ok ) {
2860                   // san - it is impossible to recover applied hypotheses
2861                   //       using their entries within Load() method,
2862                   // for there are no AttributeIORs in the study when Load() is working.
2863                   // Hence, it is better to store persistent IDs of hypotheses as references to them
2864
2865                   //string myRefOnObject = myRefOnHyp->GetID();
2866                   CORBA::Object_var anObject = SObjectToObject( myRefOnHyp );
2867                   CORBA::String_var objStr = GetORB()->object_to_string( anObject );
2868                   int id = myStudyContext->findId( string( objStr.in() ) );
2869                   //if ( myRefOnObject.length() > 0 ) {
2870                   //aSize[ 0 ] = myRefOnObject.length() + 1;
2871                   char hypName[ 30 ], hypId[ 30 ];
2872                   sprintf( hypName, "Hyp %d", ++hypNb );
2873                   sprintf( hypId, "%d", id );
2874                   aSize[ 0 ] = strlen( hypId ) + 1;
2875                   aDataset = new HDFdataset( hypName, aGroup, HDF_STRING, aSize, 1 );
2876                   aDataset->CreateOnDisk();
2877                   //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
2878                   aDataset->WriteOnDisk( hypId );
2879                   aDataset->CloseOnDisk();
2880                   //}
2881                 }
2882               }
2883               aGroup->CloseOnDisk();
2884             }
2885
2886             // write applied algorithms if exist
2887             SALOMEDS::SObject_var myAlgoBranch;
2888             found = gotBranch->FindSubObject( GetRefOnAppliedAlgorithmsTag(), myAlgoBranch );
2889             if ( found && !shapeRefFound && hasShape) { // remove applied algos
2890               myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( myAlgoBranch );
2891             }
2892             if ( found && (shapeRefFound || !hasShape)) {
2893               aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
2894               aGroup->CreateOnDisk();
2895
2896               SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( myAlgoBranch );
2897               int algoNb = 0;
2898               for ( ; it->More(); it->Next() ) {
2899                 SALOMEDS::SObject_var mySObject = it->Value();
2900                 SALOMEDS::SObject_var myRefOnAlgo;
2901                 bool ok = mySObject->ReferencedObject( myRefOnAlgo );
2902                 if ( ok ) {
2903                   // san - it is impossible to recover applied algorithms
2904                   //       using their entries within Load() method,
2905                   // for there are no AttributeIORs in the study when Load() is working.
2906                   // Hence, it is better to store persistent IDs of algorithms as references to them
2907
2908                   //string myRefOnObject = myRefOnAlgo->GetID();
2909                   CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo );
2910                   CORBA::String_var objStr = GetORB()->object_to_string( anObject );
2911                   int id = myStudyContext->findId( string( objStr.in() ) );
2912                   //if ( myRefOnObject.length() > 0 ) {
2913                   //aSize[ 0 ] = myRefOnObject.length() + 1;
2914                   char algoName[ 30 ], algoId[ 30 ];
2915                   sprintf( algoName, "Algo %d", ++algoNb );
2916                   sprintf( algoId, "%d", id );
2917                   aSize[ 0 ] = strlen( algoId ) + 1;
2918                   aDataset = new HDFdataset( algoName, aGroup, HDF_STRING, aSize, 1 );
2919                   aDataset->CreateOnDisk();
2920                   //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
2921                   aDataset->WriteOnDisk( algoId );
2922                   aDataset->CloseOnDisk();
2923                   //}
2924                 }
2925               }
2926               aGroup->CloseOnDisk();
2927             }
2928
2929             // --> submesh objects sub-branches
2930
2931             for ( int i = GetSubMeshOnVertexTag(); i <= GetSubMeshOnCompoundTag(); i++ ) {
2932               SALOMEDS::SObject_var mySubmeshBranch;
2933               found = gotBranch->FindSubObject( i, mySubmeshBranch );
2934
2935               if ( found ) // check if there is shape reference in submeshes
2936               {
2937                 bool hasShapeRef = false;
2938                 SALOMEDS::ChildIterator_var itSM =
2939                   myCurrentStudy->NewChildIterator( mySubmeshBranch );
2940                 for ( ; itSM->More(); itSM->Next() ) {
2941                   SALOMEDS::SObject_var mySubRef, myShape, mySObject = itSM->Value();
2942                   if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef ))
2943                     mySubRef->ReferencedObject( myShape );
2944                   if ( !CORBA::is_nil( myShape ) && !CORBA::is_nil( myShape->GetObject() ))
2945                     hasShapeRef = true;
2946                   else
2947                   { // remove one submesh
2948                     if ( shapeRefFound )
2949                     { // unassign hypothesis
2950                       SMESH::SMESH_subMesh_var mySubMesh =
2951                         SMESH::SMESH_subMesh::_narrow( SObjectToObject( mySObject ));
2952                       if ( !mySubMesh->_is_nil() ) {
2953                         int shapeID = mySubMesh->GetId();
2954                         TopoDS_Shape S = mySMESHDSMesh->IndexToShape( shapeID );
2955                         const list<const SMESHDS_Hypothesis*>& hypList =
2956                           mySMESHDSMesh->GetHypothesis( S );
2957                         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
2958                         while ( hyp != hypList.end() ) {
2959                           int hypID = (*hyp++)->GetID(); // goto next hyp here because
2960                           myLocMesh.RemoveHypothesis( S, hypID ); // hypList changes here
2961                         }
2962                       }
2963                     }
2964                     myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( mySObject );
2965                   }
2966                 } // loop on submeshes of a type
2967                 if ( !shapeRefFound || !hasShapeRef ) { // remove the whole submeshes branch
2968                   myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( mySubmeshBranch );
2969                   found = false;
2970                 }
2971               }  // end check if there is shape reference in submeshes
2972               if ( found ) {
2973                 char name_meshgroup[ 30 ];
2974                 if ( i == GetSubMeshOnVertexTag() )
2975                   strcpy( name_meshgroup, "SubMeshes On Vertex" );
2976                 else if ( i == GetSubMeshOnEdgeTag() )
2977                   strcpy( name_meshgroup, "SubMeshes On Edge" );
2978                 else if ( i == GetSubMeshOnWireTag() )
2979                   strcpy( name_meshgroup, "SubMeshes On Wire" );
2980                 else if ( i == GetSubMeshOnFaceTag() )
2981                   strcpy( name_meshgroup, "SubMeshes On Face" );
2982                 else if ( i == GetSubMeshOnShellTag() )
2983                   strcpy( name_meshgroup, "SubMeshes On Shell" );
2984                 else if ( i == GetSubMeshOnSolidTag() )
2985                   strcpy( name_meshgroup, "SubMeshes On Solid" );
2986                 else if ( i == GetSubMeshOnCompoundTag() )
2987                   strcpy( name_meshgroup, "SubMeshes On Compound" );
2988
2989                 // for each type of submeshes create container HDF group
2990                 aGroup = new HDFgroup( name_meshgroup, aTopGroup );
2991                 aGroup->CreateOnDisk();
2992
2993                 // iterator for all submeshes of given type
2994                 SALOMEDS::ChildIterator_var itSM = myCurrentStudy->NewChildIterator( mySubmeshBranch );
2995                 for ( ; itSM->More(); itSM->Next() ) {
2996                   SALOMEDS::SObject_var mySObject = itSM->Value();
2997                   CORBA::Object_var anSubObject = SObjectToObject( mySObject );
2998                   if ( !CORBA::is_nil( anSubObject ))
2999                   {
3000                     SMESH::SMESH_subMesh_var mySubMesh = SMESH::SMESH_subMesh::_narrow( anSubObject ) ;
3001                     CORBA::String_var objStr = GetORB()->object_to_string( anSubObject );
3002                     int subid = myStudyContext->findId( string( objStr.in() ) );
3003
3004                     // for each mesh open the HDF group basing on its id
3005                     char submeshGrpName[ 30 ];
3006                     sprintf( submeshGrpName, "SubMesh %d", subid );
3007                     aSubGroup = new HDFgroup( submeshGrpName, aGroup );
3008                     aSubGroup->CreateOnDisk();
3009
3010                     // write reference on a shape, already checked if it exists
3011                     SALOMEDS::SObject_var mySubRef, myShape;
3012                     if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef ))
3013                       mySubRef->ReferencedObject( myShape );
3014                     string myRefOnObject = myShape->GetID();
3015                     if ( myRefOnObject.length() > 0 ) {
3016                       aSize[ 0 ] = myRefOnObject.length() + 1;
3017                       aDataset = new HDFdataset( "Ref on shape", aSubGroup, HDF_STRING, aSize, 1 );
3018                       aDataset->CreateOnDisk();
3019                       aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3020                       aDataset->CloseOnDisk();
3021                     }
3022
3023                     // write applied hypotheses if exist
3024                     SALOMEDS::SObject_var mySubHypBranch;
3025                     found = mySObject->FindSubObject( GetRefOnAppliedHypothesisTag(), mySubHypBranch );
3026                     if ( found ) {
3027                       aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup );
3028                       aSubSubGroup->CreateOnDisk();
3029
3030                       SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( mySubHypBranch );
3031                       int hypNb = 0;
3032                       for ( ; it->More(); it->Next() ) {
3033                         SALOMEDS::SObject_var mySubSObject = it->Value();
3034                         SALOMEDS::SObject_var myRefOnHyp;
3035                         bool ok = mySubSObject->ReferencedObject( myRefOnHyp );
3036                         if ( ok ) {
3037                           //string myRefOnObject = myRefOnHyp->GetID();
3038                           CORBA::Object_var anObject = SObjectToObject( myRefOnHyp );
3039                           CORBA::String_var objStr = GetORB()->object_to_string( anObject );
3040                           int id = myStudyContext->findId( string( objStr.in() ) );
3041                           //if ( myRefOnObject.length() > 0 ) {
3042                           //aSize[ 0 ] = myRefOnObject.length() + 1;
3043                           char hypName[ 30 ], hypId[ 30 ];
3044                           sprintf( hypName, "Hyp %d", ++hypNb );
3045                           sprintf( hypId, "%d", id );
3046                           aSize[ 0 ] = strlen( hypId ) + 1;
3047                           aDataset = new HDFdataset( hypName, aSubSubGroup, HDF_STRING, aSize, 1 );
3048                           aDataset->CreateOnDisk();
3049                           //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3050                           aDataset->WriteOnDisk( hypId );
3051                           aDataset->CloseOnDisk();
3052                           //}
3053                         }
3054                       }
3055                       aSubSubGroup->CloseOnDisk();
3056                     }
3057
3058                     // write applied algorithms if exist
3059                     SALOMEDS::SObject_var mySubAlgoBranch;
3060                     found = mySObject->FindSubObject( GetRefOnAppliedAlgorithmsTag(), mySubAlgoBranch );
3061                     if ( found ) {
3062                       aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup );
3063                       aSubSubGroup->CreateOnDisk();
3064
3065                       SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( mySubAlgoBranch );
3066                       int algoNb = 0;
3067                       for ( ; it->More(); it->Next() ) {
3068                         SALOMEDS::SObject_var mySubSObject = it->Value();
3069                         SALOMEDS::SObject_var myRefOnAlgo;
3070                         bool ok = mySubSObject->ReferencedObject( myRefOnAlgo );
3071                         if ( ok ) {
3072                           //string myRefOnObject = myRefOnAlgo->GetID();
3073                           CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo );
3074                           CORBA::String_var objStr = GetORB()->object_to_string( anObject );
3075                           int id = myStudyContext->findId( string( objStr.in() ) );
3076                           //if ( myRefOnObject.length() > 0 ) {
3077                           //aSize[ 0 ] = myRefOnObject.length() + 1;
3078                           char algoName[ 30 ], algoId[ 30 ];
3079                           sprintf( algoName, "Algo %d", ++algoNb );
3080                           sprintf( algoId, "%d", id );
3081                           aSize[ 0 ] = strlen( algoId ) + 1;
3082                           aDataset = new HDFdataset( algoName, aSubSubGroup, HDF_STRING, aSize, 1 );
3083                           aDataset->CreateOnDisk();
3084                           //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3085                           aDataset->WriteOnDisk( algoId );
3086                           aDataset->CloseOnDisk();
3087                           //}
3088                         }
3089                       }
3090                       aSubSubGroup->CloseOnDisk();
3091                     }
3092                     // close submesh HDF group
3093                     aSubGroup->CloseOnDisk();
3094                   }
3095                 }
3096                 // close container of submeshes by type HDF group
3097                 aGroup->CloseOnDisk();
3098               }
3099             }
3100             // All sub-meshes will be stored in MED file
3101             // .. will NOT (PAL 12992)
3102             //if ( shapeRefFound )
3103             //myWriter.AddAllSubMeshes();
3104
3105             // store submesh order if any
3106             const TListOfListOfInt& theOrderIds = myLocMesh.GetMeshOrder();
3107             if ( theOrderIds.size() ) {
3108               char order_list[ 30 ];
3109               strcpy( order_list, "Mesh Order" );
3110               // count number of submesh ids
3111               int nbIDs = 0;
3112               TListOfListOfInt::const_iterator idIt = theOrderIds.begin();
3113               for ( ; idIt != theOrderIds.end(); idIt++ )
3114                 nbIDs += (*idIt).size();
3115               // number of values = number of IDs +
3116               //                    number of lists (for separators) - 1
3117               int* smIDs = new int [ nbIDs + theOrderIds.size() - 1 ];
3118               idIt = theOrderIds.begin();
3119               for ( int i = 0; idIt != theOrderIds.end(); idIt++ ) {
3120                 const TListOfInt& idList = *idIt;
3121                 if (idIt != theOrderIds.begin()) // not first list
3122                   smIDs[ i++ ] = -1/* *idList.size()*/; // separator between lists
3123                 // dump submesh ids from current list
3124                 TListOfInt::const_iterator id_smId = idList.begin();
3125                 for( ; id_smId != idList.end(); id_smId++ )
3126                   smIDs[ i++ ] = *id_smId;
3127               }
3128               // write HDF group
3129               aSize[ 0 ] = nbIDs + theOrderIds.size() - 1;
3130
3131               aDataset = new HDFdataset( order_list, aTopGroup, HDF_INT32, aSize, 1 );
3132               aDataset->CreateOnDisk();
3133               aDataset->WriteOnDisk( smIDs );
3134               aDataset->CloseOnDisk();
3135               //
3136               delete[] smIDs;
3137             }
3138
3139             // groups root sub-branch
3140             SALOMEDS::SObject_var myGroupsBranch;
3141             for ( int i = GetNodeGroupsTag(); i <= GetVolumeGroupsTag(); i++ ) {
3142               found = gotBranch->FindSubObject( i, myGroupsBranch );
3143               if ( found ) {
3144                 char name_group[ 30 ];
3145                 if ( i == GetNodeGroupsTag() )
3146                   strcpy( name_group, "Groups of Nodes" );
3147                 else if ( i == GetEdgeGroupsTag() )
3148                   strcpy( name_group, "Groups of Edges" );
3149                 else if ( i == GetFaceGroupsTag() )
3150                   strcpy( name_group, "Groups of Faces" );
3151                 else if ( i == GetVolumeGroupsTag() )
3152                   strcpy( name_group, "Groups of Volumes" );
3153
3154                 aGroup = new HDFgroup( name_group, aTopGroup );
3155                 aGroup->CreateOnDisk();
3156
3157                 SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( myGroupsBranch );
3158                 for ( ; it->More(); it->Next() ) {
3159                   SALOMEDS::SObject_var mySObject = it->Value();
3160                   CORBA::Object_var aSubObject = SObjectToObject( mySObject );
3161                   if ( !CORBA::is_nil( aSubObject ) ) {
3162                     SMESH_GroupBase_i* myGroupImpl =
3163                       dynamic_cast<SMESH_GroupBase_i*>( GetServant( aSubObject ).in() );
3164                     if ( !myGroupImpl )
3165                       continue;
3166                     SMESHDS_GroupBase* aGrpBaseDS = myGroupImpl->GetGroupDS();
3167                     if ( !aGrpBaseDS )
3168                       continue;
3169
3170                     CORBA::String_var objStr = GetORB()->object_to_string( aSubObject );
3171                     int anId = myStudyContext->findId( string( objStr.in() ) );
3172
3173                     // For each group, create a dataset named "Group <group_persistent_id>"
3174                     // and store the group's user name into it
3175                     const char* grpName = aGrpBaseDS->GetStoreName();
3176                     char* aUserName = myGroupImpl->GetName();
3177                     aSize[ 0 ] = strlen( aUserName ) + 1;
3178
3179                     aDataset = new HDFdataset( grpName, aGroup, HDF_STRING, aSize, 1 );
3180                     aDataset->CreateOnDisk();
3181                     aDataset->WriteOnDisk( aUserName );
3182                     aDataset->CloseOnDisk();
3183
3184                     // ouv : NPAL12872
3185                     // For each group, create a dataset named "Group <group_persistent_id> Color"
3186                     // and store the group's color into it
3187                     char grpColorName[ 30 ];
3188                     sprintf( grpColorName, "ColorGroup %d", anId );
3189                     SALOMEDS::Color aColor = myGroupImpl->GetColor();
3190                     double anRGB[3];
3191                     anRGB[ 0 ] = aColor.R;
3192                     anRGB[ 1 ] = aColor.G;
3193                     anRGB[ 2 ] = aColor.B;
3194                     aSize[ 0 ] = 3;
3195                     aDataset = new HDFdataset( grpColorName, aGroup, HDF_FLOAT64, aSize, 1 );
3196                     aDataset->CreateOnDisk();
3197                     aDataset->WriteOnDisk( anRGB );
3198                     aDataset->CloseOnDisk();
3199
3200                     // Pass SMESHDS_Group to MED writer
3201                     SMESHDS_Group* aGrpDS = dynamic_cast<SMESHDS_Group*>( aGrpBaseDS );
3202                     if ( aGrpDS )
3203                       myWriter.AddGroup( aGrpDS );
3204
3205                     // write reference on a shape if exists
3206                     SMESHDS_GroupOnGeom* aGeomGrp =
3207                       dynamic_cast<SMESHDS_GroupOnGeom*>( aGrpBaseDS );
3208                     if ( aGeomGrp ) {
3209                       SALOMEDS::SObject_var mySubRef, myShape;
3210                       if (mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef ) &&
3211                           mySubRef->ReferencedObject( myShape ) &&
3212                           !CORBA::is_nil( myShape->GetObject() ))
3213                       {
3214                         string myRefOnObject = myShape->GetID();
3215                         if ( myRefOnObject.length() > 0 ) {
3216                           char aRefName[ 30 ];
3217                           sprintf( aRefName, "Ref on shape %d", anId);
3218                           aSize[ 0 ] = myRefOnObject.length() + 1;
3219                           aDataset = new HDFdataset(aRefName, aGroup, HDF_STRING, aSize, 1);
3220                           aDataset->CreateOnDisk();
3221                           aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3222                           aDataset->CloseOnDisk();
3223                         }
3224                       }
3225                       else // shape ref is invalid:
3226                       {
3227                         // save a group on geometry as ordinary group
3228                         myWriter.AddGroup( aGeomGrp );
3229                       }
3230                     }
3231                   }
3232                 }
3233                 aGroup->CloseOnDisk();
3234               }
3235             } // loop on groups
3236
3237             if ( strcmp( strHasData.c_str(), "1" ) == 0 )
3238             {
3239               // Flush current mesh information into MED file
3240               myWriter.Perform();
3241
3242               // maybe a shape was deleted in the study
3243               if ( !shapeRefFound && !mySMESHDSMesh->ShapeToMesh().IsNull() && hasShape) {
3244                 TopoDS_Shape nullShape;
3245                 myLocMesh.ShapeToMesh( nullShape ); // remove shape referring data
3246               }
3247
3248               if ( !mySMESHDSMesh->SubMeshes().empty() )
3249               {
3250                 // Store submeshes
3251                 // ----------------
3252                 aGroup = new HDFgroup( "Submeshes", aTopGroup );
3253                 aGroup->CreateOnDisk();
3254
3255                 // each element belongs to one or none submesh,
3256                 // so for each node/element, we store a submesh ID
3257
3258                 // Make maps of submesh IDs of elements sorted by element IDs
3259                 typedef int TElemID;
3260                 typedef int TSubMID;
3261                 map< TElemID, TSubMID > eId2smId, nId2smId;
3262                 map< TElemID, TSubMID >::iterator hint; // insertion to map is done before hint
3263                 const map<int,SMESHDS_SubMesh*>& aSubMeshes = mySMESHDSMesh->SubMeshes();
3264                 map<int,SMESHDS_SubMesh*>::const_iterator itSubM ( aSubMeshes.begin() );
3265                 SMDS_NodeIteratorPtr itNode;
3266                 SMDS_ElemIteratorPtr itElem;
3267                 for ( itSubM = aSubMeshes.begin(); itSubM != aSubMeshes.end() ; itSubM++ )
3268                 {
3269                   TSubMID          aSubMeID = itSubM->first;
3270                   SMESHDS_SubMesh* aSubMesh = itSubM->second;
3271                   if ( aSubMesh->IsComplexSubmesh() )
3272                     continue; // submesh containing other submeshs
3273                   // nodes
3274                   hint = nId2smId.begin(); // optimize insertion basing on increasing order of elem Ids in submesh
3275                   for ( itNode = aSubMesh->GetNodes(); itNode->more(); ++hint)
3276                     hint = nId2smId.insert( hint, make_pair( itNode->next()->GetID(), aSubMeID ));
3277                   // elements
3278                   hint = eId2smId.begin();
3279                   for ( itElem = aSubMesh->GetElements(); itElem->more(); ++hint)
3280                     hint = eId2smId.insert( hint, make_pair( itElem->next()->GetID(), aSubMeID ));
3281                 }
3282
3283                 // Care of elements that are not on submeshes
3284                 if ( mySMESHDSMesh->NbNodes() != nId2smId.size() ) {
3285                   for ( itNode = mySMESHDSMesh->nodesIterator(); itNode->more(); )
3286                     /*  --- stl_map.h says : */
3287                     /*  A %map relies on unique keys and thus a %pair is only inserted if its */
3288                     /*  first element (the key) is not already present in the %map.           */
3289                     nId2smId.insert( make_pair( itNode->next()->GetID(), 0 ));
3290                 }
3291                 int nbElems = mySMESHDSMesh->NbEdges() + mySMESHDSMesh->NbFaces() + mySMESHDSMesh->NbVolumes();
3292                 if ( nbElems != eId2smId.size() ) {
3293                   for ( itElem = mySMESHDSMesh->elementsIterator(); itElem->more(); )
3294                     eId2smId.insert( make_pair( itElem->next()->GetID(), 0 ));
3295                 }
3296
3297                 // Store submesh IDs
3298                 for ( int isNode = 0; isNode < 2; ++isNode )
3299                 {
3300                   map< TElemID, TSubMID >& id2smId = isNode ? nId2smId : eId2smId;
3301                   if ( id2smId.empty() ) continue;
3302                   map< TElemID, TSubMID >::const_iterator id_smId = id2smId.begin();
3303                   // make and fill array of submesh IDs
3304                   int* smIDs = new int [ id2smId.size() ];
3305                   for ( int i = 0; id_smId != id2smId.end(); ++id_smId, ++i )
3306                     smIDs[ i ] = id_smId->second;
3307                   // write HDF group
3308                   aSize[ 0 ] = id2smId.size();
3309                   string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
3310                   aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_INT32, aSize, 1 );
3311                   aDataset->CreateOnDisk();
3312                   aDataset->WriteOnDisk( smIDs );
3313                   aDataset->CloseOnDisk();
3314                   //
3315                   delete[] smIDs;
3316                 }
3317
3318                 // Store node positions on sub-shapes (SMDS_Position):
3319                 // ----------------------------------------------------
3320
3321                 aGroup = new HDFgroup( "Node Positions", aTopGroup );
3322                 aGroup->CreateOnDisk();
3323
3324                 // in aGroup, create 5 datasets to contain:
3325                 // "Nodes on Edges" - ID of node on edge
3326                 // "Edge positions" - U parameter on node on edge
3327                 // "Nodes on Faces" - ID of node on face
3328                 // "Face U positions" - U parameter of node on face
3329                 // "Face V positions" - V parameter of node on face
3330
3331                 // Find out nb of nodes on edges and faces
3332                 // Collect corresponing sub-meshes
3333                 int nbEdgeNodes = 0, nbFaceNodes = 0;
3334                 list<SMESHDS_SubMesh*> aEdgeSM, aFaceSM;
3335                 // loop on SMESHDS_SubMesh'es
3336                 for ( itSubM = aSubMeshes.begin(); itSubM != aSubMeshes.end() ; itSubM++ )
3337                 {
3338                   SMESHDS_SubMesh* aSubMesh = (*itSubM).second;
3339                   if ( aSubMesh->IsComplexSubmesh() )
3340                     continue; // submesh containing other submeshs
3341                   int nbNodes = aSubMesh->NbNodes();
3342                   if ( nbNodes == 0 ) continue;
3343
3344                   int aShapeID = (*itSubM).first;
3345                   if ( aShapeID < 1 || aShapeID > mySMESHDSMesh->MaxShapeIndex() )
3346                     continue;
3347                   int aShapeType = mySMESHDSMesh->IndexToShape( aShapeID ).ShapeType();
3348                   // write only SMDS_FacePosition and SMDS_EdgePosition
3349                   switch ( aShapeType ) {
3350                   case TopAbs_FACE:
3351                     nbFaceNodes += nbNodes;
3352                     aFaceSM.push_back( aSubMesh );
3353                     break;
3354                   case TopAbs_EDGE:
3355                     nbEdgeNodes += nbNodes;
3356                     aEdgeSM.push_back( aSubMesh );
3357                     break;
3358                   default:
3359                     continue;
3360                   }
3361                 }
3362                 // Treat positions on edges or faces
3363                 for ( int onFace = 0; onFace < 2; onFace++ )
3364                 {
3365                   // Create arrays to store in datasets
3366                   int iNode = 0, nbNodes = ( onFace ? nbFaceNodes : nbEdgeNodes );
3367                   if (!nbNodes) continue;
3368                   int* aNodeIDs = new int [ nbNodes ];
3369                   double* aUPos = new double [ nbNodes ];
3370                   double* aVPos = ( onFace ? new double[ nbNodes ] : 0 );
3371
3372                   // Fill arrays
3373                   // loop on sub-meshes
3374                   list<SMESHDS_SubMesh*> * pListSM = ( onFace ? &aFaceSM : &aEdgeSM );
3375                   list<SMESHDS_SubMesh*>::iterator itSM = pListSM->begin();
3376                   for ( ; itSM != pListSM->end(); itSM++ )
3377                   {
3378                     SMESHDS_SubMesh* aSubMesh = (*itSM);
3379
3380                     SMDS_NodeIteratorPtr itNode = aSubMesh->GetNodes();
3381                     // loop on nodes in aSubMesh
3382                     while ( itNode->more() )
3383                     {
3384                       //node ID
3385                       const SMDS_MeshNode* node = itNode->next();
3386                       aNodeIDs [ iNode ] = node->GetID();
3387
3388                       // Position
3389                       const SMDS_PositionPtr pos = node->GetPosition();
3390                       if ( onFace ) { // on FACE
3391                         const SMDS_FacePosition* fPos =
3392                           dynamic_cast<const SMDS_FacePosition*>( pos );
3393                         if ( fPos ) {
3394                           aUPos[ iNode ] = fPos->GetUParameter();
3395                           aVPos[ iNode ] = fPos->GetVParameter();
3396                           iNode++;
3397                         }
3398                         else
3399                           nbNodes--;
3400                       }
3401                       else { // on EDGE
3402                         const SMDS_EdgePosition* ePos =
3403                           dynamic_cast<const SMDS_EdgePosition*>( pos );
3404                         if ( ePos ) {
3405                           aUPos[ iNode ] = ePos->GetUParameter();
3406                           iNode++;
3407                         }
3408                         else
3409                           nbNodes--;
3410                       }
3411                     } // loop on nodes in aSubMesh
3412                   } // loop on sub-meshes
3413
3414                   // Write datasets
3415                   if ( nbNodes )
3416                   {
3417                     aSize[ 0 ] = nbNodes;
3418                     // IDS
3419                     string aDSName( onFace ? "Nodes on Faces" : "Nodes on Edges");
3420                     aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_INT32, aSize, 1 );
3421                     aDataset->CreateOnDisk();
3422                     aDataset->WriteOnDisk( aNodeIDs );
3423                     aDataset->CloseOnDisk();
3424
3425                     // U Positions
3426                     aDSName = ( onFace ? "Face U positions" : "Edge positions");
3427                     aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_FLOAT64, aSize, 1);
3428                     aDataset->CreateOnDisk();
3429                     aDataset->WriteOnDisk( aUPos );
3430                     aDataset->CloseOnDisk();
3431                     // V Positions
3432                     if ( onFace ) {
3433                       aDataset = new HDFdataset( "Face V positions", aGroup, HDF_FLOAT64, aSize, 1);
3434                       aDataset->CreateOnDisk();
3435                       aDataset->WriteOnDisk( aVPos );
3436                       aDataset->CloseOnDisk();
3437                     }
3438                   }
3439                   delete [] aNodeIDs;
3440                   delete [] aUPos;
3441                   if ( aVPos ) delete [] aVPos;
3442
3443                 } // treat positions on edges or faces
3444
3445                 // close "Node Positions" group
3446                 aGroup->CloseOnDisk();
3447
3448               } // if ( there are submeshes in SMESHDS_Mesh )
3449             } // if ( hasData )
3450
3451             // close mesh HDF group
3452             aTopGroup->CloseOnDisk();
3453           }
3454         }
3455       }
3456     }
3457   }
3458
3459   // close HDF file
3460   aFile->CloseOnDisk();
3461   delete aFile;
3462
3463   // Convert temporary files to stream
3464   aStreamFile = SALOMEDS_Tool::PutFilesToStream( tmpDir.ToCString(), aFileSeq.in(), isMultiFile );
3465
3466   // Remove temporary files and directory
3467   if ( !isMultiFile )
3468     SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
3469
3470   INFOS( "SMESH_Gen_i::Save() completed" );
3471   return aStreamFile._retn();
3472 }
3473
3474 //=============================================================================
3475 /*!
3476  *  SMESH_Gen_i::SaveASCII
3477  *
3478  *  Save SMESH module's data in ASCII format
3479  */
3480 //=============================================================================
3481
3482 SALOMEDS::TMPFile* SMESH_Gen_i::SaveASCII( SALOMEDS::SComponent_ptr theComponent,
3483                                            const char*              theURL,
3484                                            bool                     isMultiFile ) {
3485   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::SaveASCII" );
3486   SALOMEDS::TMPFile_var aStreamFile = Save( theComponent, theURL, isMultiFile );
3487   return aStreamFile._retn();
3488
3489   //after usual saving needs to encipher binary to text string
3490   //Any binary symbol will be represent as "|xx" () hexadecimal format number
3491   int size = aStreamFile.in().length();
3492   _CORBA_Octet* buffer = new _CORBA_Octet[size*3+1];
3493   for ( int i = 0; i < size; i++ )
3494     sprintf( (char*)&(buffer[i*3]), "|%02x", aStreamFile[i] );
3495
3496   buffer[size * 3] = '\0';
3497
3498   SALOMEDS::TMPFile_var anAsciiStreamFile = new SALOMEDS::TMPFile(size*3, size*3, buffer, 1);
3499
3500   return anAsciiStreamFile._retn();
3501 }
3502
3503 //=============================================================================
3504 /*!
3505  *  SMESH_Gen_i::loadGeomData
3506  *
3507  *  Load GEOM module data
3508  */
3509 //=============================================================================
3510
3511 void SMESH_Gen_i::loadGeomData( SALOMEDS::SComponent_ptr theCompRoot )
3512 {
3513   if ( theCompRoot->_is_nil() )
3514     return;
3515
3516   SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow( theCompRoot->GetStudy() );
3517   if ( aStudy->_is_nil() )
3518     return;
3519
3520   SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
3521   aStudyBuilder->LoadWith( theCompRoot, GetGeomEngine() );
3522 }
3523 //=============================================================================
3524 /*!
3525  * \brief Creates SMDS_Position according to shape type
3526  */
3527 //=============================================================================
3528
3529 class PositionCreator {
3530 public:
3531   SMDS_PositionPtr MakePosition(const TopAbs_ShapeEnum type) {
3532     return (this->*myFuncTable[ type ])();
3533   }
3534   PositionCreator() {
3535     myFuncTable.resize( (size_t) TopAbs_SHAPE, & PositionCreator::defaultPosition );
3536     myFuncTable[ TopAbs_SOLID  ] = & PositionCreator::volumePosition;
3537     myFuncTable[ TopAbs_FACE   ] = & PositionCreator::facePosition;
3538     myFuncTable[ TopAbs_EDGE   ] = & PositionCreator::edgePosition;
3539     myFuncTable[ TopAbs_VERTEX ] = & PositionCreator::vertexPosition;
3540   }
3541 private:
3542   SMDS_PositionPtr edgePosition()    const { return SMDS_PositionPtr( new SMDS_EdgePosition  ); }
3543   SMDS_PositionPtr facePosition()    const { return SMDS_PositionPtr( new SMDS_FacePosition  ); }
3544   SMDS_PositionPtr volumePosition()  const { return SMDS_PositionPtr( new SMDS_SpacePosition ); }
3545   SMDS_PositionPtr vertexPosition()  const { return SMDS_PositionPtr( new SMDS_VertexPosition); }
3546   SMDS_PositionPtr defaultPosition() const { return SMDS_SpacePosition::originSpacePosition();  }
3547   typedef SMDS_PositionPtr (PositionCreator:: * FmakePos)() const;
3548   vector<FmakePos> myFuncTable;
3549 };
3550
3551 //=============================================================================
3552 /*!
3553  *  SMESH_Gen_i::Load
3554  *
3555  *  Load SMESH module's data
3556  */
3557 //=============================================================================
3558
3559 bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
3560                         const SALOMEDS::TMPFile& theStream,
3561                         const char*              theURL,
3562                         bool                     isMultiFile )
3563 {
3564   INFOS( "SMESH_Gen_i::Load" );
3565
3566   if ( myCurrentStudy->_is_nil() ||
3567        theComponent->GetStudy()->StudyId() != myCurrentStudy->StudyId() )
3568     SetCurrentStudy( theComponent->GetStudy() );
3569
3570   /*  if( !theComponent->_is_nil() )
3571       {
3572       //SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow( theComponent->GetStudy() );
3573       if( !myCurrentStudy->FindComponent( "GEOM" )->_is_nil() )
3574       loadGeomData( myCurrentStudy->FindComponent( "GEOM" ) );
3575       }*/
3576
3577   StudyContext* myStudyContext = GetCurrentStudyContext();
3578
3579   // Get temporary files location
3580   TCollection_AsciiString tmpDir =
3581     isMultiFile ? TCollection_AsciiString( ( char* )theURL ) : ( char* )SALOMEDS_Tool::GetTmpDir().c_str();
3582
3583     INFOS( "THE URL++++++++++++++" )
3584     INFOS( theURL );
3585     INFOS( "THE TMP PATH+++++++++" );
3586     INFOS( tmpDir );
3587
3588   // Convert the stream into sequence of files to process
3589   SALOMEDS::ListOfFileNames_var aFileSeq = SALOMEDS_Tool::PutStreamToFiles( theStream,
3590                                                                             tmpDir.ToCString(),
3591                                                                             isMultiFile );
3592   TCollection_AsciiString aStudyName( "" );
3593   if ( isMultiFile )
3594     aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( myCurrentStudy->URL() ).c_str() );
3595
3596   // Set names of temporary files
3597   TCollection_AsciiString filename = tmpDir + aStudyName + TCollection_AsciiString( "_SMESH.hdf" );
3598   TCollection_AsciiString meshfile = tmpDir + aStudyName + TCollection_AsciiString( "_SMESH_Mesh.med" );
3599
3600   int size;
3601   HDFfile*    aFile;
3602   HDFdataset* aDataset;
3603   HDFgroup*   aTopGroup;
3604   HDFgroup*   aGroup;
3605   HDFgroup*   aSubGroup;
3606   HDFgroup*   aSubSubGroup;
3607
3608   // Read data
3609   // ---> open HDF file
3610   aFile = new HDFfile( (char*) filename.ToCString() );
3611   try {
3612     aFile->OpenOnDisk( HDF_RDONLY );
3613   }
3614   catch ( HDFexception ) {
3615     INFOS( "Load(): " << filename << " not found!" );
3616     return false;
3617   }
3618
3619   DriverMED_R_SMESHDS_Mesh myReader;
3620   myReader.SetFile( meshfile.ToCString() );
3621
3622   // For PAL13473 ("Repetitive mesh") implementation.
3623   // New dependencies between SMESH objects are established:
3624   // now hypotheses can refer to meshes, shapes and other hypotheses.
3625   // To keep data consistent, the following order of data restoration
3626   // imposed:
3627   // 1. Create hypotheses
3628   // 2. Create all meshes
3629   // 3. Load hypotheses' data
3630   // 4. All the rest
3631
3632   list< pair< SMESH_Hypothesis_i*, string > >    hypDataList;
3633   list< pair< SMESH_Mesh_i*,       HDFgroup* > > meshGroupList;
3634
3635   // get total number of top-level groups
3636   int aNbGroups = aFile->nInternalObjects();
3637   if ( aNbGroups > 0 ) {
3638     // --> in first turn we should read&create hypotheses
3639     if ( aFile->ExistInternalObject( "Hypotheses" ) ) {
3640       // open hypotheses root HDF group
3641       aTopGroup = new HDFgroup( "Hypotheses", aFile );
3642       aTopGroup->OpenOnDisk();
3643
3644       // get number of hypotheses
3645       int aNbObjects = aTopGroup->nInternalObjects();
3646       for ( int j = 0; j < aNbObjects; j++ ) {
3647         // try to identify hypothesis
3648         char hypGrpName[ HDF_NAME_MAX_LEN+1 ];
3649         aTopGroup->InternalObjectIndentify( j, hypGrpName );
3650
3651         if ( string( hypGrpName ).substr( 0, 10 ) == string( "Hypothesis" ) ) {
3652           // open hypothesis group
3653           aGroup = new HDFgroup( hypGrpName, aTopGroup );
3654           aGroup->OpenOnDisk();
3655
3656           // --> get hypothesis id
3657           int    id = atoi( string( hypGrpName ).substr( 10 ).c_str() );
3658           string hypname;
3659           string libname;
3660           string hypdata;
3661
3662           // get number of datasets
3663           int aNbSubObjects = aGroup->nInternalObjects();
3664           for ( int k = 0; k < aNbSubObjects; k++ ) {
3665             // identify dataset
3666             char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ];
3667             aGroup->InternalObjectIndentify( k, name_of_subgroup );
3668             // --> get hypothesis name
3669             if ( strcmp( name_of_subgroup, "Name"  ) == 0 ) {
3670               aDataset = new HDFdataset( name_of_subgroup, aGroup );
3671               aDataset->OpenOnDisk();
3672               size = aDataset->GetSize();
3673               char* hypname_str = new char[ size ];
3674               aDataset->ReadFromDisk( hypname_str );
3675               hypname = string( hypname_str );
3676               delete [] hypname_str;
3677               aDataset->CloseOnDisk();
3678             }
3679             // --> get hypothesis plugin library name
3680             if ( strcmp( name_of_subgroup, "LibName"  ) == 0 ) {
3681               aDataset = new HDFdataset( name_of_subgroup, aGroup );
3682               aDataset->OpenOnDisk();
3683               size = aDataset->GetSize();
3684               char* libname_str = new char[ size ];
3685               aDataset->ReadFromDisk( libname_str );
3686               if(MYDEBUG) SCRUTE( libname_str );
3687               libname = string( libname_str );
3688               delete [] libname_str;
3689               aDataset->CloseOnDisk();
3690             }
3691             // --> get hypothesis data
3692             if ( strcmp( name_of_subgroup, "Data"  ) == 0 ) {
3693               aDataset = new HDFdataset( name_of_subgroup, aGroup );
3694               aDataset->OpenOnDisk();
3695               size = aDataset->GetSize();
3696               char* hypdata_str = new char[ size ];
3697               aDataset->ReadFromDisk( hypdata_str );
3698               hypdata = string( hypdata_str );
3699               delete [] hypdata_str;
3700               aDataset->CloseOnDisk();
3701             }
3702           }
3703           // close hypothesis HDF group
3704           aGroup->CloseOnDisk();
3705
3706           // --> restore hypothesis from data
3707           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
3708             if(MYDEBUG) MESSAGE("VSR - load hypothesis : id = " << id <<
3709                                 ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
3710             SMESH::SMESH_Hypothesis_var myHyp;
3711
3712             try { // protect persistence mechanism against exceptions
3713               myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() );
3714             }
3715             catch (...) {
3716               INFOS( "Exception during hypothesis creation" );
3717             }
3718
3719             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
3720             if ( myImpl ) {
3721               // myImpl->LoadFrom( hypdata.c_str() );
3722               hypDataList.push_back( make_pair( myImpl, hypdata ));
3723               string iorString = GetORB()->object_to_string( myHyp );
3724               int newId = myStudyContext->findId( iorString );
3725               myStudyContext->mapOldToNew( id, newId );
3726             }
3727             else
3728               if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
3729           }
3730         }
3731       }
3732       // close hypotheses root HDF group
3733       aTopGroup->CloseOnDisk();
3734       aTopGroup = 0;
3735     }
3736
3737     // --> then we should read&create algorithms
3738     if ( aFile->ExistInternalObject( "Algorithms" ) ) {
3739       // open algorithms root HDF group
3740       aTopGroup = new HDFgroup( "Algorithms", aFile );
3741       aTopGroup->OpenOnDisk();
3742
3743       // get number of algorithms
3744       int aNbObjects = aTopGroup->nInternalObjects();
3745       for ( int j = 0; j < aNbObjects; j++ ) {
3746         // try to identify algorithm
3747         char hypGrpName[ HDF_NAME_MAX_LEN+1 ];
3748         aTopGroup->InternalObjectIndentify( j, hypGrpName );
3749
3750         if ( string( hypGrpName ).substr( 0, 9 ) == string( "Algorithm" ) ) {
3751           // open algorithm group
3752           aGroup = new HDFgroup( hypGrpName, aTopGroup );
3753           aGroup->OpenOnDisk();
3754
3755           // --> get algorithm id
3756           int    id = atoi( string( hypGrpName ).substr( 9 ).c_str() );
3757           string hypname;
3758           string libname;
3759           string hypdata;
3760
3761           // get number of datasets
3762           int aNbSubObjects = aGroup->nInternalObjects();
3763           for ( int k = 0; k < aNbSubObjects; k++ ) {
3764             // identify dataset
3765             char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ];
3766             aGroup->InternalObjectIndentify( k, name_of_subgroup );
3767             // --> get algorithm name
3768             if ( strcmp( name_of_subgroup, "Name"  ) == 0 ) {
3769               aDataset = new HDFdataset( name_of_subgroup, aGroup );
3770               aDataset->OpenOnDisk();
3771               size = aDataset->GetSize();
3772               char* hypname_str = new char[ size ];
3773               aDataset->ReadFromDisk( hypname_str );
3774               hypname = string( hypname_str );
3775               delete [] hypname_str;
3776               aDataset->CloseOnDisk();
3777             }
3778             // --> get algorithm plugin library name
3779             if ( strcmp( name_of_subgroup, "LibName"  ) == 0 ) {
3780               aDataset = new HDFdataset( name_of_subgroup, aGroup );
3781               aDataset->OpenOnDisk();
3782               size = aDataset->GetSize();
3783               char* libname_str = new char[ size ];
3784               aDataset->ReadFromDisk( libname_str );
3785               if(MYDEBUG) SCRUTE( libname_str );
3786               libname = string( libname_str );
3787               delete [] libname_str;
3788               aDataset->CloseOnDisk();
3789             }
3790             // --> get algorithm data
3791             if ( strcmp( name_of_subgroup, "Data"  ) == 0 ) {
3792               aDataset = new HDFdataset( name_of_subgroup, aGroup );
3793               aDataset->OpenOnDisk();
3794               size = aDataset->GetSize();
3795               char* hypdata_str = new char[ size ];
3796               aDataset->ReadFromDisk( hypdata_str );
3797               if(MYDEBUG) SCRUTE( hypdata_str );
3798               hypdata = string( hypdata_str );
3799               delete [] hypdata_str;
3800               aDataset->CloseOnDisk();
3801             }
3802           }
3803           // close algorithm HDF group
3804           aGroup->CloseOnDisk();
3805
3806           // --> restore algorithm from data
3807           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
3808             if(MYDEBUG) MESSAGE("VSR - load algo : id = " << id <<
3809                                 ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
3810             SMESH::SMESH_Hypothesis_var myHyp;
3811
3812             try { // protect persistence mechanism against exceptions
3813               myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() );
3814             }
3815             catch (...) {
3816               INFOS( "Exception during hypothesis creation" );
3817             }
3818
3819             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
3820             if ( myImpl ) {
3821               //myImpl->LoadFrom( hypdata.c_str() );
3822               hypDataList.push_back( make_pair( myImpl, hypdata ));
3823               string iorString = GetORB()->object_to_string( myHyp );
3824               int newId = myStudyContext->findId( iorString );
3825               myStudyContext->mapOldToNew( id, newId );
3826             }
3827             else
3828               if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
3829           }
3830         }
3831       }
3832       // close algorithms root HDF group
3833       aTopGroup->CloseOnDisk();
3834       aTopGroup = 0;
3835     }
3836
3837     // --> the rest groups should be meshes
3838     for ( int i = 0; i < aNbGroups; i++ ) {
3839       // identify next group
3840       char meshName[ HDF_NAME_MAX_LEN+1 ];
3841       aFile->InternalObjectIndentify( i, meshName );
3842
3843       if ( string( meshName ).substr( 0, 4 ) == string( "Mesh" ) ) {
3844         // --> get mesh id
3845         int id = atoi( string( meshName ).substr( 4 ).c_str() );
3846         if ( id <= 0 )
3847           continue;
3848
3849         // open mesh HDF group
3850         aTopGroup = new HDFgroup( meshName, aFile );
3851         aTopGroup->OpenOnDisk();
3852
3853         // get number of child HDF objects
3854         int aNbObjects = aTopGroup->nInternalObjects();
3855         if ( aNbObjects > 0 ) {
3856           // create mesh
3857           if(MYDEBUG) MESSAGE( "VSR - load mesh : id = " << id );
3858           SMESH::SMESH_Mesh_var myNewMesh = this->createMesh();
3859           SMESH_Mesh_i* myNewMeshImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( myNewMesh ).in() );
3860           if ( !myNewMeshImpl )
3861             continue;
3862           meshGroupList.push_back( make_pair( myNewMeshImpl, aTopGroup ));
3863
3864           string iorString = GetORB()->object_to_string( myNewMesh );
3865           int newId = myStudyContext->findId( iorString );
3866           myStudyContext->mapOldToNew( id, newId );
3867
3868           // ouv : NPAL12872
3869           // try to read and set auto color flag
3870           char aMeshAutoColorName[ 30 ];
3871           sprintf( aMeshAutoColorName, "AutoColorMesh %d", id);
3872           if( aTopGroup->ExistInternalObject( aMeshAutoColorName ) )
3873           {
3874             aDataset = new HDFdataset( aMeshAutoColorName, aTopGroup );
3875             aDataset->OpenOnDisk();
3876             size = aDataset->GetSize();
3877             int* anAutoColor = new int[ size ];
3878             aDataset->ReadFromDisk( anAutoColor );
3879             aDataset->CloseOnDisk();
3880             myNewMeshImpl->GetImpl().SetAutoColor( (bool)anAutoColor[0] );
3881           }
3882
3883           // try to read and set reference to shape
3884           GEOM::GEOM_Object_var aShapeObject;
3885           if ( aTopGroup->ExistInternalObject( "Ref on shape" ) ) {
3886             // load mesh "Ref on shape" - it's an entry to SObject
3887             aDataset = new HDFdataset( "Ref on shape", aTopGroup );
3888             aDataset->OpenOnDisk();
3889             size = aDataset->GetSize();
3890             char* refFromFile = new char[ size ];
3891             aDataset->ReadFromDisk( refFromFile );
3892             aDataset->CloseOnDisk();
3893             if ( strlen( refFromFile ) > 0 ) {
3894               SALOMEDS::SObject_var shapeSO = myCurrentStudy->FindObjectID( refFromFile );
3895
3896               // Make sure GEOM data are loaded first
3897               //loadGeomData( shapeSO->GetFatherComponent() );
3898
3899               CORBA::Object_var shapeObject = SObjectToObject( shapeSO );
3900               if ( !CORBA::is_nil( shapeObject ) ) {
3901                 aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
3902                 if ( !aShapeObject->_is_nil() )
3903                   myNewMeshImpl->SetShape( aShapeObject );
3904               }
3905             }
3906           }
3907
3908           // issue 0020693. Restore _isModified flag
3909           if( aTopGroup->ExistInternalObject( "_isModified" ) )
3910           {
3911             aDataset = new HDFdataset( "_isModified", aTopGroup );
3912             aDataset->OpenOnDisk();
3913             size = aDataset->GetSize();
3914             int* isModified = new int[ size ];
3915             aDataset->ReadFromDisk( isModified );
3916             aDataset->CloseOnDisk();
3917             myNewMeshImpl->GetImpl().SetIsModified( bool(*isModified));
3918           }
3919
3920           // issue 20918. Restore Persistent Id of SMESHDS_Mesh
3921           if( aTopGroup->ExistInternalObject( "meshPersistentId" ) )
3922           {
3923             aDataset = new HDFdataset( "meshPersistentId", aTopGroup );
3924             aDataset->OpenOnDisk();
3925             size = aDataset->GetSize();
3926             int* meshPersistentId = new int[ size ];
3927             aDataset->ReadFromDisk( meshPersistentId );
3928             aDataset->CloseOnDisk();
3929             myNewMeshImpl->GetImpl().GetMeshDS()->SetPersistentId( *meshPersistentId );
3930           }
3931         }
3932       }
3933     }
3934
3935     // As all object that can be referred by hypothesis are created,
3936     // we can restore hypothesis data
3937
3938     list< pair< SMESH_Hypothesis_i*, string > >::iterator hyp_data;
3939     for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data )
3940     {
3941       SMESH_Hypothesis_i* hyp  = hyp_data->first;
3942       string &            data = hyp_data->second;
3943       hyp->LoadFrom( data.c_str() );
3944     }
3945
3946     // Restore the rest mesh data
3947
3948     list< pair< SMESH_Mesh_i*, HDFgroup* > >::iterator meshi_group;
3949     for ( meshi_group = meshGroupList.begin(); meshi_group != meshGroupList.end(); ++meshi_group )
3950     {
3951       aTopGroup                   = meshi_group->second;
3952       SMESH_Mesh_i* myNewMeshImpl = meshi_group->first;
3953       ::SMESH_Mesh& myLocMesh     = myNewMeshImpl->GetImpl();
3954       SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS();
3955
3956       GEOM::GEOM_Object_var aShapeObject = myNewMeshImpl->GetShapeToMesh();
3957       bool hasData = false;
3958
3959       // get mesh old id
3960       string iorString = GetORB()->object_to_string( myNewMeshImpl->_this() );
3961       int newId = myStudyContext->findId( iorString );
3962       int id = myStudyContext->getOldId( newId );
3963
3964       // try to find mesh data dataset
3965       if ( aTopGroup->ExistInternalObject( "Has data" ) ) {
3966         // load mesh "has data" flag
3967         aDataset = new HDFdataset( "Has data", aTopGroup );
3968         aDataset->OpenOnDisk();
3969         size = aDataset->GetSize();
3970         char* strHasData = new char[ size ];
3971         aDataset->ReadFromDisk( strHasData );
3972         aDataset->CloseOnDisk();
3973         if ( strcmp( strHasData, "1") == 0 ) {
3974           // read mesh data from MED file
3975           myReader.SetMesh( mySMESHDSMesh );
3976           myReader.SetMeshId( id );
3977           myReader.Perform();
3978           hasData = true;
3979         }
3980       }
3981
3982       // try to get applied algorithms
3983       if ( aTopGroup->ExistInternalObject( "Applied Algorithms" ) ) {
3984         aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
3985         aGroup->OpenOnDisk();
3986         // get number of applied algorithms
3987         int aNbSubObjects = aGroup->nInternalObjects();
3988         if(MYDEBUG) MESSAGE( "VSR - number of applied algos " << aNbSubObjects );
3989         for ( int j = 0; j < aNbSubObjects; j++ ) {
3990           char name_dataset[ HDF_NAME_MAX_LEN+1 ];
3991           aGroup->InternalObjectIndentify( j, name_dataset );
3992           // check if it is an algorithm
3993           if ( string( name_dataset ).substr( 0, 4 ) == string( "Algo" ) ) {
3994             aDataset = new HDFdataset( name_dataset, aGroup );
3995             aDataset->OpenOnDisk();
3996             size = aDataset->GetSize();
3997             char* refFromFile = new char[ size ];
3998             aDataset->ReadFromDisk( refFromFile );
3999             aDataset->CloseOnDisk();
4000
4001             // san - it is impossible to recover applied algorithms using their entries within Load() method
4002
4003             //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
4004             //CORBA::Object_var hypObject = SObjectToObject( hypSO );
4005             int id = atoi( refFromFile );
4006             string anIOR = myStudyContext->getIORbyOldId( id );
4007             if ( !anIOR.empty() ) {
4008               CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
4009               if ( !CORBA::is_nil( hypObject ) ) {
4010                 SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
4011                 if ( !anHyp->_is_nil() && (!aShapeObject->_is_nil()
4012                                            || !myNewMeshImpl->HasShapeToMesh()) )
4013                   myNewMeshImpl->addHypothesis( aShapeObject, anHyp );
4014               }
4015             }
4016           }
4017         }
4018         aGroup->CloseOnDisk();
4019       }
4020
4021       // try to get applied hypotheses
4022       if ( aTopGroup->ExistInternalObject( "Applied Hypotheses" ) ) {
4023         aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup );
4024         aGroup->OpenOnDisk();
4025         // get number of applied hypotheses
4026         int aNbSubObjects = aGroup->nInternalObjects();
4027         for ( int j = 0; j < aNbSubObjects; j++ ) {
4028           char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4029           aGroup->InternalObjectIndentify( j, name_dataset );
4030           // check if it is a hypothesis
4031           if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) {
4032             aDataset = new HDFdataset( name_dataset, aGroup );
4033             aDataset->OpenOnDisk();
4034             size = aDataset->GetSize();
4035             char* refFromFile = new char[ size ];
4036             aDataset->ReadFromDisk( refFromFile );
4037             aDataset->CloseOnDisk();
4038
4039             // san - it is impossible to recover applied hypotheses using their entries within Load() method
4040
4041             //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
4042             //CORBA::Object_var hypObject = SObjectToObject( hypSO );
4043             int id = atoi( refFromFile );
4044             string anIOR = myStudyContext->getIORbyOldId( id );
4045             if ( !anIOR.empty() ) {
4046               CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
4047               if ( !CORBA::is_nil( hypObject ) ) {
4048                 SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
4049                 if ( !anHyp->_is_nil() && (!aShapeObject->_is_nil()
4050                                            || !myNewMeshImpl->HasShapeToMesh()) )
4051                   myNewMeshImpl->addHypothesis( aShapeObject, anHyp );
4052               }
4053             }
4054           }
4055         }
4056         aGroup->CloseOnDisk();
4057       }
4058
4059       // --> try to find submeshes containers for each type of submesh
4060       for ( int j = GetSubMeshOnVertexTag(); j <= GetSubMeshOnCompoundTag(); j++ ) {
4061         char name_meshgroup[ 30 ];
4062         if ( j == GetSubMeshOnVertexTag() )
4063           strcpy( name_meshgroup, "SubMeshes On Vertex" );
4064         else if ( j == GetSubMeshOnEdgeTag() )
4065           strcpy( name_meshgroup, "SubMeshes On Edge" );
4066         else if ( j == GetSubMeshOnWireTag() )
4067           strcpy( name_meshgroup, "SubMeshes On Wire" );
4068         else if ( j == GetSubMeshOnFaceTag() )
4069           strcpy( name_meshgroup, "SubMeshes On Face" );
4070         else if ( j == GetSubMeshOnShellTag() )
4071           strcpy( name_meshgroup, "SubMeshes On Shell" );
4072         else if ( j == GetSubMeshOnSolidTag() )
4073           strcpy( name_meshgroup, "SubMeshes On Solid" );
4074         else if ( j == GetSubMeshOnCompoundTag() )
4075           strcpy( name_meshgroup, "SubMeshes On Compound" );
4076
4077         // try to get submeshes container HDF group
4078         if ( aTopGroup->ExistInternalObject( name_meshgroup ) ) {
4079           // open submeshes containers HDF group
4080           aGroup = new HDFgroup( name_meshgroup, aTopGroup );
4081           aGroup->OpenOnDisk();
4082
4083           // get number of submeshes
4084           int aNbSubMeshes = aGroup->nInternalObjects();
4085           for ( int k = 0; k < aNbSubMeshes; k++ ) {
4086             // identify submesh
4087             char name_submeshgroup[ HDF_NAME_MAX_LEN+1 ];
4088             aGroup->InternalObjectIndentify( k, name_submeshgroup );
4089             if ( string( name_submeshgroup ).substr( 0, 7 ) == string( "SubMesh" )  ) {
4090               // --> get submesh id
4091               int subid = atoi( string( name_submeshgroup ).substr( 7 ).c_str() );
4092               if ( subid <= 0 )
4093                 continue;
4094               // open submesh HDF group
4095               aSubGroup = new HDFgroup( name_submeshgroup, aGroup );
4096               aSubGroup->OpenOnDisk();
4097
4098               // try to read and set reference to subshape
4099               GEOM::GEOM_Object_var aSubShapeObject;
4100               SMESH::SMESH_subMesh_var aSubMesh;
4101
4102               if ( aSubGroup->ExistInternalObject( "Ref on shape" ) ) {
4103                 // load submesh "Ref on shape" - it's an entry to SObject
4104                 aDataset = new HDFdataset( "Ref on shape", aSubGroup );
4105                 aDataset->OpenOnDisk();
4106                 size = aDataset->GetSize();
4107                 char* refFromFile = new char[ size ];
4108                 aDataset->ReadFromDisk( refFromFile );
4109                 aDataset->CloseOnDisk();
4110                 if ( strlen( refFromFile ) > 0 ) {
4111                   SALOMEDS::SObject_var subShapeSO = myCurrentStudy->FindObjectID( refFromFile );
4112                   CORBA::Object_var subShapeObject = SObjectToObject( subShapeSO );
4113                   if ( !CORBA::is_nil( subShapeObject ) ) {
4114                     aSubShapeObject = GEOM::GEOM_Object::_narrow( subShapeObject );
4115                     if ( !aSubShapeObject->_is_nil() )
4116                       aSubMesh = SMESH::SMESH_subMesh::_duplicate
4117                         ( myNewMeshImpl->createSubMesh( aSubShapeObject ) );
4118                     if ( aSubMesh->_is_nil() )
4119                       continue;
4120                     string iorSubString = GetORB()->object_to_string( aSubMesh );
4121                     int newSubId = myStudyContext->findId( iorSubString );
4122                     myStudyContext->mapOldToNew( subid, newSubId );
4123                   }
4124                 }
4125               }
4126
4127               if ( aSubMesh->_is_nil() )
4128                 continue;
4129
4130               // VSR: Get submesh data from MED convertor
4131               //                  int anInternalSubmeshId = aSubMesh->GetId(); // this is not a persistent ID, it's an internal one computed from sub-shape
4132               //                  if (myNewMeshImpl->_mapSubMesh.find(anInternalSubmeshId) != myNewMeshImpl->_mapSubMesh.end()) {
4133               //                    if(MYDEBUG) MESSAGE("VSR - SMESH_Gen_i::Load(): loading from MED file submesh with ID = " <<
4134               //                            subid << " for subshape # " << anInternalSubmeshId);
4135               //                    SMESHDS_SubMesh* aSubMeshDS =
4136               //                      myNewMeshImpl->_mapSubMesh[anInternalSubmeshId]->CreateSubMeshDS();
4137               //                    if ( !aSubMeshDS ) {
4138               //                      if(MYDEBUG) MESSAGE("VSR - SMESH_Gen_i::Load(): FAILED to create a submesh for subshape # " <<
4139               //                              anInternalSubmeshId << " in current mesh!");
4140               //                    }
4141               //                    else
4142               //                      myReader.GetSubMesh( aSubMeshDS, subid );
4143               //                  }
4144
4145               // try to get applied algorithms
4146               if ( aSubGroup->ExistInternalObject( "Applied Algorithms" ) ) {
4147                 // open "applied algorithms" HDF group
4148                 aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup );
4149                 aSubSubGroup->OpenOnDisk();
4150                 // get number of applied algorithms
4151                 int aNbSubObjects = aSubSubGroup->nInternalObjects();
4152                 for ( int l = 0; l < aNbSubObjects; l++ ) {
4153                   char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4154                   aSubSubGroup->InternalObjectIndentify( l, name_dataset );
4155                   // check if it is an algorithm
4156                   if ( string( name_dataset ).substr( 0, 4 ) == string( "Algo" ) ) {
4157                     aDataset = new HDFdataset( name_dataset, aSubSubGroup );
4158                     aDataset->OpenOnDisk();
4159                     size = aDataset->GetSize();
4160                     char* refFromFile = new char[ size ];
4161                     aDataset->ReadFromDisk( refFromFile );
4162                     aDataset->CloseOnDisk();
4163
4164                     //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
4165                     //CORBA::Object_var hypObject = SObjectToObject( hypSO );
4166                     int id = atoi( refFromFile );
4167                     string anIOR = myStudyContext->getIORbyOldId( id );
4168                     if ( !anIOR.empty() ) {
4169                       CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
4170                       if ( !CORBA::is_nil( hypObject ) ) {
4171                         SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
4172                         if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
4173                           myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
4174                       }
4175                     }
4176                   }
4177                 }
4178                 // close "applied algorithms" HDF group
4179                 aSubSubGroup->CloseOnDisk();
4180               }
4181
4182               // try to get applied hypotheses
4183               if ( aSubGroup->ExistInternalObject( "Applied Hypotheses" ) ) {
4184                 // open "applied hypotheses" HDF group
4185                 aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup );
4186                 aSubSubGroup->OpenOnDisk();
4187                 // get number of applied hypotheses
4188                 int aNbSubObjects = aSubSubGroup->nInternalObjects();
4189                 for ( int l = 0; l < aNbSubObjects; l++ ) {
4190                   char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4191                   aSubSubGroup->InternalObjectIndentify( l, name_dataset );
4192                   // check if it is a hypothesis
4193                   if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) {
4194                     aDataset = new HDFdataset( name_dataset, aSubSubGroup );
4195                     aDataset->OpenOnDisk();
4196                     size = aDataset->GetSize();
4197                     char* refFromFile = new char[ size ];
4198                     aDataset->ReadFromDisk( refFromFile );
4199                     aDataset->CloseOnDisk();
4200
4201                     //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
4202                     //CORBA::Object_var hypObject = SObjectToObject( hypSO );
4203                     int id = atoi( refFromFile );
4204                     string anIOR = myStudyContext->getIORbyOldId( id );
4205                     if ( !anIOR.empty() ) {
4206                       CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
4207                       if ( !CORBA::is_nil( hypObject ) ) {
4208                         SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
4209                         if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
4210                           myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
4211                       }
4212                     }
4213                   }
4214                 }
4215                 // close "applied hypotheses" HDF group
4216                 aSubSubGroup->CloseOnDisk();
4217               }
4218
4219               // close submesh HDF group
4220               aSubGroup->CloseOnDisk();
4221             }
4222           }
4223           // close submeshes containers HDF group
4224           aGroup->CloseOnDisk();
4225         }
4226       }
4227
4228       if(hasData) {
4229
4230         // Read sub-meshes from MED
4231         // -------------------------
4232         if(MYDEBUG) MESSAGE("Create all sub-meshes");
4233         bool submeshesInFamilies = ( ! aTopGroup->ExistInternalObject( "Submeshes" ));
4234         if ( submeshesInFamilies )
4235         {
4236           // old way working before fix of PAL 12992
4237           myReader.CreateAllSubMeshes();
4238         }
4239         else
4240         {
4241           // open a group
4242           aGroup = new HDFgroup( "Submeshes", aTopGroup );
4243           aGroup->OpenOnDisk();
4244
4245           int maxID = Max( mySMESHDSMesh->MaxSubMeshIndex(), mySMESHDSMesh->MaxShapeIndex() );
4246           vector< SMESHDS_SubMesh * > subMeshes( maxID + 1, (SMESHDS_SubMesh*) 0 );
4247           vector< TopAbs_ShapeEnum  > smType   ( maxID + 1, TopAbs_SHAPE );
4248
4249           PositionCreator aPositionCreator;
4250
4251           SMDS_NodeIteratorPtr nIt = mySMESHDSMesh->nodesIterator();
4252           SMDS_ElemIteratorPtr eIt = mySMESHDSMesh->elementsIterator();
4253           for ( int isNode = 0; isNode < 2; ++isNode )
4254           {
4255             string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
4256             if ( aGroup->ExistInternalObject( (char*) aDSName.c_str() ))
4257             {
4258               aDataset = new HDFdataset( (char*) aDSName.c_str(), aGroup );
4259               aDataset->OpenOnDisk();
4260               // read submesh IDs for all elements sorted by ID
4261               int nbElems = aDataset->GetSize();
4262               int* smIDs = new int [ nbElems ];
4263               aDataset->ReadFromDisk( smIDs );
4264               aDataset->CloseOnDisk();
4265
4266               // get elements sorted by ID
4267               TIDSortedElemSet elemSet;
4268               if ( isNode )
4269                 while ( nIt->more() ) elemSet.insert( nIt->next() );
4270               else
4271                 while ( eIt->more() ) elemSet.insert( eIt->next() );
4272               //ASSERT( elemSet.size() == nbElems ); -- issue 20182
4273               // -- Most probably a bad study was saved when there were
4274               // not fixed bugs in SMDS_MeshInfo
4275               if ( elemSet.size() < nbElems ) {
4276 #ifdef _DEBUG_
4277                 cout << "SMESH_Gen_i::Load(), warning: Node position data is invalid" << endl;
4278 #endif
4279                 nbElems = elemSet.size();
4280               }
4281               // add elements to submeshes
4282               TIDSortedElemSet::iterator iE = elemSet.begin();
4283               for ( int i = 0; i < nbElems; ++i, ++iE )
4284               {
4285                 int smID = smIDs[ i ];
4286                 if ( smID == 0 ) continue;
4287                 const SMDS_MeshElement* elem = *iE;
4288                 if( smID > maxID ) {
4289                   // corresponding subshape no longer exists: maybe geom group has been edited
4290                   if ( myNewMeshImpl->HasShapeToMesh() )
4291                     mySMESHDSMesh->RemoveElement( elem );
4292                   continue;
4293                 }
4294                 // get or create submesh
4295                 SMESHDS_SubMesh* & sm = subMeshes[ smID ];
4296                 if ( ! sm ) {
4297                   sm = mySMESHDSMesh->NewSubMesh( smID );
4298                   smType[ smID ] = mySMESHDSMesh->IndexToShape( smID ).ShapeType();
4299                 }
4300                 // add
4301                 if ( isNode ) {
4302                   SMDS_PositionPtr pos = aPositionCreator.MakePosition( smType[ smID ]);
4303                   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( static_cast<const SMDS_MeshNode*>( elem ));
4304                   node->SetPosition( pos );
4305                   sm->AddNode( node );
4306                 } else {
4307                   sm->AddElement( elem );
4308                 }
4309               }
4310               delete [] smIDs;
4311             }
4312           }
4313         } // end reading submeshes
4314
4315         // Read node positions on sub-shapes (SMDS_Position)
4316
4317         if ( aTopGroup->ExistInternalObject( "Node Positions" ))
4318         {
4319           // There are 5 datasets to read:
4320           // "Nodes on Edges" - ID of node on edge
4321           // "Edge positions" - U parameter on node on edge
4322           // "Nodes on Faces" - ID of node on face
4323           // "Face U positions" - U parameter of node on face
4324           // "Face V positions" - V parameter of node on face
4325           const char* aEid_DSName = "Nodes on Edges";
4326           const char* aEu_DSName  = "Edge positions";
4327           const char* aFu_DSName  = "Face U positions";
4328           //char* aFid_DSName = "Nodes on Faces";
4329           //char* aFv_DSName  = "Face V positions";
4330
4331           // data to retrieve
4332           int nbEids = 0, nbFids = 0;
4333           int *aEids = 0, *aFids  = 0;
4334           double *aEpos = 0, *aFupos = 0, *aFvpos = 0;
4335
4336           // open a group
4337           aGroup = new HDFgroup( "Node Positions", aTopGroup );
4338           aGroup->OpenOnDisk();
4339
4340           // loop on 5 data sets
4341           int aNbObjects = aGroup->nInternalObjects();
4342           for ( int i = 0; i < aNbObjects; i++ )
4343           {
4344             // identify dataset
4345             char aDSName[ HDF_NAME_MAX_LEN+1 ];
4346             aGroup->InternalObjectIndentify( i, aDSName );
4347             // read data
4348             aDataset = new HDFdataset( aDSName, aGroup );
4349             aDataset->OpenOnDisk();
4350             if ( aDataset->GetType() == HDF_FLOAT64 ) // Positions
4351             {
4352               double* pos = new double [ aDataset->GetSize() ];
4353               aDataset->ReadFromDisk( pos );
4354               // which one?
4355               if ( strncmp( aDSName, aEu_DSName, strlen( aEu_DSName )) == 0 )
4356                 aEpos = pos;
4357               else if ( strncmp( aDSName, aFu_DSName, strlen( aFu_DSName )) == 0 )
4358                 aFupos = pos;
4359               else
4360                 aFvpos = pos;
4361             }
4362             else // NODE IDS
4363             {
4364               int aSize = aDataset->GetSize();
4365
4366               // for reading files, created from 18.07.2005 till 10.10.2005
4367               if (aDataset->GetType() == HDF_STRING)
4368                 aSize /= sizeof(int);
4369
4370               int* ids = new int [aSize];
4371               aDataset->ReadFromDisk( ids );
4372               // on face or nodes?
4373               if ( strncmp( aDSName, aEid_DSName, strlen( aEid_DSName )) == 0 ) {
4374                 aEids = ids;
4375                 nbEids = aSize;
4376               }
4377               else {
4378                 aFids = ids;
4379                 nbFids = aSize;
4380               }
4381             }
4382             aDataset->CloseOnDisk();
4383           } // loop on 5 datasets
4384
4385           // Set node positions on edges or faces
4386           for ( int onFace = 0; onFace < 2; onFace++ )
4387           {
4388             int nbNodes = ( onFace ? nbFids : nbEids );
4389             if ( nbNodes == 0 ) continue;
4390             int* aNodeIDs = ( onFace ? aFids : aEids );
4391             double* aUPos = ( onFace ? aFupos : aEpos );
4392             double* aVPos = ( onFace ? aFvpos : 0 );
4393             // loop on node IDs
4394             for ( int iNode = 0; iNode < nbNodes; iNode++ )
4395             {
4396               const SMDS_MeshNode* node = mySMESHDSMesh->FindNode( aNodeIDs[ iNode ]);
4397               if ( !node ) continue; // maybe removed while Loading() if geometry changed
4398               SMDS_PositionPtr aPos = node->GetPosition();
4399               ASSERT( aPos );
4400               if ( onFace ) {
4401                 // ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_FACE );-- issue 20182
4402                 // -- Most probably a bad study was saved when there were
4403                 // not fixed bugs in SMDS_MeshInfo
4404                 if ( aPos->GetTypeOfPosition() == SMDS_TOP_FACE ) {
4405                   SMDS_FacePosition* fPos = const_cast<SMDS_FacePosition*>
4406                     ( static_cast<const SMDS_FacePosition*>( aPos ));
4407                   fPos->SetUParameter( aUPos[ iNode ]);
4408                   fPos->SetVParameter( aVPos[ iNode ]);
4409                 }
4410               }
4411               else {
4412                 // ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE );-- issue 20182
4413                 if ( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE ) {
4414                   SMDS_EdgePosition* fPos = const_cast<SMDS_EdgePosition*>
4415                     ( static_cast<const SMDS_EdgePosition*>( aPos ));
4416                   fPos->SetUParameter( aUPos[ iNode ]);
4417                 }
4418               }
4419             }
4420           }
4421           if ( aEids ) delete [] aEids;
4422           if ( aFids ) delete [] aFids;
4423           if ( aEpos ) delete [] aEpos;
4424           if ( aFupos ) delete [] aFupos;
4425           if ( aFvpos ) delete [] aFvpos;
4426
4427           aGroup->CloseOnDisk();
4428
4429         } // if ( aTopGroup->ExistInternalObject( "Node Positions" ) )
4430       } // if ( hasData )
4431
4432       // try to get groups
4433       for ( int ii = GetNodeGroupsTag(); ii <= GetVolumeGroupsTag(); ii++ ) {
4434         char name_group[ 30 ];
4435         if ( ii == GetNodeGroupsTag() )
4436           strcpy( name_group, "Groups of Nodes" );
4437         else if ( ii == GetEdgeGroupsTag() )
4438           strcpy( name_group, "Groups of Edges" );
4439         else if ( ii == GetFaceGroupsTag() )
4440           strcpy( name_group, "Groups of Faces" );
4441         else if ( ii == GetVolumeGroupsTag() )
4442           strcpy( name_group, "Groups of Volumes" );
4443
4444         if ( aTopGroup->ExistInternalObject( name_group ) ) {
4445           aGroup = new HDFgroup( name_group, aTopGroup );
4446           aGroup->OpenOnDisk();
4447           // get number of groups
4448           int aNbSubObjects = aGroup->nInternalObjects();
4449           for ( int j = 0; j < aNbSubObjects; j++ ) {
4450             char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4451             aGroup->InternalObjectIndentify( j, name_dataset );
4452             // check if it is an group
4453             if ( string( name_dataset ).substr( 0, 5 ) == string( "Group" ) ) {
4454               // --> get group id
4455               int subid = atoi( string( name_dataset ).substr( 5 ).c_str() );
4456               if ( subid <= 0 )
4457                 continue;
4458               aDataset = new HDFdataset( name_dataset, aGroup );
4459               aDataset->OpenOnDisk();
4460
4461               // Retrieve actual group name
4462               size = aDataset->GetSize();
4463               char* nameFromFile = new char[ size ];
4464               aDataset->ReadFromDisk( nameFromFile );
4465               aDataset->CloseOnDisk();
4466
4467               // Try to find a shape reference
4468               TopoDS_Shape aShape;
4469               char aRefName[ 30 ];
4470               sprintf( aRefName, "Ref on shape %d", subid);
4471               if ( aGroup->ExistInternalObject( aRefName ) ) {
4472                 // load mesh "Ref on shape" - it's an entry to SObject
4473                 aDataset = new HDFdataset( aRefName, aGroup );
4474                 aDataset->OpenOnDisk();
4475                 size = aDataset->GetSize();
4476                 char* refFromFile = new char[ size ];
4477                 aDataset->ReadFromDisk( refFromFile );
4478                 aDataset->CloseOnDisk();
4479                 if ( strlen( refFromFile ) > 0 ) {
4480                   SALOMEDS::SObject_var shapeSO = myCurrentStudy->FindObjectID( refFromFile );
4481                   CORBA::Object_var shapeObject = SObjectToObject( shapeSO );
4482                   if ( !CORBA::is_nil( shapeObject ) ) {
4483                     aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
4484                     if ( !aShapeObject->_is_nil() )
4485                       aShape = GeomObjectToShape( aShapeObject );
4486                   }
4487                 }
4488               }
4489               // Create group servant
4490               SMESH::ElementType type = (SMESH::ElementType)(ii - GetNodeGroupsTag() + 1);
4491               SMESH::SMESH_GroupBase_var aNewGroup = SMESH::SMESH_GroupBase::_duplicate
4492                 ( myNewMeshImpl->createGroup( type, nameFromFile, aShape ) );
4493               // Obtain a SMESHDS_Group object
4494               if ( aNewGroup->_is_nil() )
4495                 continue;
4496
4497               string iorSubString = GetORB()->object_to_string( aNewGroup );
4498               int newSubId = myStudyContext->findId( iorSubString );
4499               myStudyContext->mapOldToNew( subid, newSubId );
4500
4501               SMESH_GroupBase_i* aGroupImpl =
4502                 dynamic_cast<SMESH_GroupBase_i*>( GetServant( aNewGroup ).in() );
4503               if ( !aGroupImpl )
4504                 continue;
4505
4506               SMESH_Group* aLocalGroup  = myLocMesh.GetGroup( aGroupImpl->GetLocalID() );
4507               if ( !aLocalGroup )
4508                 continue;
4509
4510               SMESHDS_GroupBase* aGroupBaseDS = aLocalGroup->GetGroupDS();
4511               aGroupBaseDS->SetStoreName( name_dataset );
4512
4513               // ouv : NPAL12872
4514               // Read color of the group
4515               char aGroupColorName[ 30 ];
4516               sprintf( aGroupColorName, "ColorGroup %d", subid);
4517               if ( aGroup->ExistInternalObject( aGroupColorName ) )
4518               {
4519                 aDataset = new HDFdataset( aGroupColorName, aGroup );
4520                 aDataset->OpenOnDisk();
4521                 size = aDataset->GetSize();
4522                 double* anRGB = new double[ size ];
4523                 aDataset->ReadFromDisk( anRGB );
4524                 aDataset->CloseOnDisk();
4525                 Quantity_Color aColor( anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB );
4526                 aGroupBaseDS->SetColor( aColor );
4527               }
4528
4529               // Fill group with contents from MED file
4530               SMESHDS_Group* aGrp = dynamic_cast<SMESHDS_Group*>( aGroupBaseDS );
4531               if ( aGrp )
4532                 myReader.GetGroup( aGrp );
4533             }
4534           }
4535           aGroup->CloseOnDisk();
4536         }
4537       }
4538
4539       // read submeh order if any
4540       if( aTopGroup->ExistInternalObject( "Mesh Order" ) ) {
4541         aDataset = new HDFdataset( "Mesh Order", aTopGroup );
4542         aDataset->OpenOnDisk();
4543         size = aDataset->GetSize();
4544         int* smIDs = new int[ size ];
4545         aDataset->ReadFromDisk( smIDs );
4546         aDataset->CloseOnDisk();
4547         TListOfListOfInt anOrderIds;
4548         anOrderIds.push_back( TListOfInt() );
4549         for ( int i = 0; i < size; i++ )
4550           if ( smIDs[ i ] < 0 ) // is separator
4551             anOrderIds.push_back( TListOfInt() );
4552           else
4553             anOrderIds.back().push_back(smIDs[ i ]);
4554
4555         myNewMeshImpl->GetImpl().SetMeshOrder( anOrderIds );
4556       }
4557     } // loop on meshes
4558
4559     // notify algos on completed restoration
4560     for ( meshi_group = meshGroupList.begin(); meshi_group != meshGroupList.end(); ++meshi_group )
4561     {
4562       SMESH_Mesh_i* myNewMeshImpl = meshi_group->first;
4563       ::SMESH_Mesh& myLocMesh     = myNewMeshImpl->GetImpl();
4564
4565       TopoDS_Shape myLocShape;
4566       if(myLocMesh.HasShapeToMesh())
4567         myLocShape = myLocMesh.GetShapeToMesh();
4568       else
4569         myLocShape = SMESH_Mesh::PseudoShape();
4570
4571       myLocMesh.GetSubMesh(myLocShape)->
4572         ComputeStateEngine (SMESH_subMesh::SUBMESH_RESTORED);
4573     }
4574
4575     for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data )
4576     {
4577       SMESH_Hypothesis_i* hyp  = hyp_data->first;
4578       hyp->UpdateAsMeshesRestored(); // for hyps needing full mesh data restored (issue 20918)
4579     }
4580
4581     // close mesh group
4582     if(aTopGroup)
4583       aTopGroup->CloseOnDisk();
4584   }
4585   // close HDF file
4586   aFile->CloseOnDisk();
4587   delete aFile;
4588
4589   // Remove temporary files created from the stream
4590   if ( !isMultiFile )
4591     SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
4592
4593   INFOS( "SMESH_Gen_i::Load completed" );
4594   return true;
4595 }
4596
4597 //=============================================================================
4598 /*!
4599  *  SMESH_Gen_i::LoadASCII
4600  *
4601  *  Load SMESH module's data in ASCII format
4602  */
4603 //=============================================================================
4604
4605 bool SMESH_Gen_i::LoadASCII( SALOMEDS::SComponent_ptr theComponent,
4606                              const SALOMEDS::TMPFile& theStream,
4607                              const char*              theURL,
4608                              bool                     isMultiFile ) {
4609   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LoadASCII" );
4610   return Load( theComponent, theStream, theURL, isMultiFile );
4611
4612   //before call main ::Load method it's need for decipher text format to
4613   //binary ( "|xx" => x' )
4614   int size = theStream.length();
4615   if ( int((size / 3 )*3) != size ) //error size of buffer
4616     return false;
4617
4618   int real_size = int(size / 3);
4619
4620   _CORBA_Octet* buffer = new _CORBA_Octet[real_size];
4621   char tmp[3];
4622   tmp[2]='\0';
4623   int c = -1;
4624   for ( int i = 0; i < real_size; i++ )
4625   {
4626     memcpy( &(tmp[0]), &(theStream[i*3+1]), 2 );
4627     sscanf( tmp, "%x", &c );
4628     sprintf( (char*)&(buffer[i]), "%c", (char)c );
4629   }
4630
4631   SALOMEDS::TMPFile_var aRealStreamFile = new SALOMEDS::TMPFile(real_size, real_size, buffer, 1);
4632
4633   return Load( theComponent, *(aRealStreamFile._retn()), theURL, isMultiFile );
4634 }
4635
4636 //=============================================================================
4637 /*!
4638  *  SMESH_Gen_i::Close
4639  *
4640  *  Clears study-connected data when it is closed
4641  */
4642 //=============================================================================
4643
4644 void SMESH_Gen_i::Close( SALOMEDS::SComponent_ptr theComponent )
4645 {
4646   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Close" );
4647
4648   // set correct current study
4649   if (theComponent->GetStudy()->StudyId() != GetCurrentStudyID())
4650     SetCurrentStudy(theComponent->GetStudy());
4651
4652   // Clear study contexts data
4653   int studyId = GetCurrentStudyID();
4654   if ( myStudyContextMap.find( studyId ) != myStudyContextMap.end() ) {
4655     delete myStudyContextMap[ studyId ];
4656     myStudyContextMap.erase( studyId );
4657   }
4658
4659   // delete SMESH_Mesh's
4660 //   See bug IPAL19437.
4661 //
4662 //   StudyContextStruct* context = myGen.GetStudyContext( studyId );
4663 //   map< int, SMESH_Mesh* >::iterator i_mesh = context->mapMesh.begin();
4664 //   for ( ; i_mesh != context->mapMesh.end(); ++i_mesh ) {
4665 //     printf( "--------------------------- SMESH_Gen_i::Close, delete aGroup = %p \n", i_mesh->second );
4666 //     delete i_mesh->second;
4667 //   }
4668
4669
4670   // delete SMESHDS_Mesh's
4671   // it's too long on big meshes
4672 //   if ( context->myDocument ) {
4673 //     delete context->myDocument;
4674 //     context->myDocument = 0;
4675 //   }
4676
4677   myCurrentStudy = SALOMEDS::Study::_nil();
4678   return;
4679 }
4680
4681 //=============================================================================
4682 /*!
4683  *  SMESH_Gen_i::ComponentDataType
4684  *
4685  *  Get component data type
4686  */
4687 //=============================================================================
4688
4689 char* SMESH_Gen_i::ComponentDataType()
4690 {
4691   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::ComponentDataType" );
4692   return CORBA::string_dup( "SMESH" );
4693 }
4694
4695
4696 //=============================================================================
4697 /*!
4698  *  SMESH_Gen_i::IORToLocalPersistentID
4699  *
4700  *  Transform data from transient form to persistent
4701  */
4702 //=============================================================================
4703
4704 char* SMESH_Gen_i::IORToLocalPersistentID( SALOMEDS::SObject_ptr /*theSObject*/,
4705                                            const char*           IORString,
4706                                            CORBA::Boolean        /*isMultiFile*/,
4707                                            CORBA::Boolean        /*isASCII*/ )
4708 {
4709   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IORToLocalPersistentID" );
4710   StudyContext* myStudyContext = GetCurrentStudyContext();
4711
4712   if ( myStudyContext && strcmp( IORString, "" ) != 0 ) {
4713     int anId = myStudyContext->findId( IORString );
4714     if ( anId ) {
4715       if(MYDEBUG) MESSAGE( "VSR " << anId )
4716       char strId[ 20 ];
4717       sprintf( strId, "%d", anId );
4718       return  CORBA::string_dup( strId );
4719     }
4720   }
4721   return CORBA::string_dup( "" );
4722 }
4723
4724 //=============================================================================
4725 /*!
4726  *  SMESH_Gen_i::LocalPersistentIDToIOR
4727  *
4728  *  Transform data from persistent form to transient
4729  */
4730 //=============================================================================
4731
4732 char* SMESH_Gen_i::LocalPersistentIDToIOR( SALOMEDS::SObject_ptr /*theSObject*/,
4733                                            const char*           aLocalPersistentID,
4734                                            CORBA::Boolean        /*isMultiFile*/,
4735                                            CORBA::Boolean        /*isASCII*/ )
4736 {
4737   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LocalPersistentIDToIOR(): id = " << aLocalPersistentID );
4738   StudyContext* myStudyContext = GetCurrentStudyContext();
4739
4740   if ( myStudyContext && strcmp( aLocalPersistentID, "" ) != 0 ) {
4741     int anId = atoi( aLocalPersistentID );
4742     return CORBA::string_dup( myStudyContext->getIORbyOldId( anId ).c_str() );
4743   }
4744   return CORBA::string_dup( "" );
4745 }
4746
4747 //=======================================================================
4748 //function : RegisterObject
4749 //purpose  :
4750 //=======================================================================
4751
4752 int SMESH_Gen_i::RegisterObject(CORBA::Object_ptr theObject)
4753 {
4754   StudyContext* myStudyContext = GetCurrentStudyContext();
4755   if ( myStudyContext && !CORBA::is_nil( theObject )) {
4756     CORBA::String_var iorString = GetORB()->object_to_string( theObject );
4757     return myStudyContext->addObject( string( iorString.in() ) );
4758   }
4759   return 0;
4760 }
4761
4762 //================================================================================
4763 /*!
4764  * \brief Return id of registered object
4765   * \param theObject - the Object
4766   * \retval int - Object id
4767  */
4768 //================================================================================
4769
4770 CORBA::Long SMESH_Gen_i::GetObjectId(CORBA::Object_ptr theObject)
4771 {
4772   StudyContext* myStudyContext = GetCurrentStudyContext();
4773   if ( myStudyContext && !CORBA::is_nil( theObject )) {
4774     string iorString = GetORB()->object_to_string( theObject );
4775     return myStudyContext->findId( iorString );
4776   }
4777   return 0;
4778 }
4779
4780 //=============================================================================
4781 /*!
4782  *  SMESH_Gen_i::SetName
4783  *
4784  *  Set a new object name
4785  */
4786 //=============================================================================
4787 void SMESH_Gen_i::SetName(const char* theIOR,
4788                           const char* theName)
4789 {
4790   if ( theIOR && strcmp( theIOR, "" ) ) {
4791     CORBA::Object_var anObject = GetORB()->string_to_object( theIOR );
4792     SALOMEDS::SObject_var aSO = ObjectToSObject( myCurrentStudy, anObject );
4793     if ( !aSO->_is_nil() ) {
4794       SetName( aSO, theName );
4795     }
4796   }
4797 }
4798
4799 int SMESH_Gen_i::GetCurrentStudyID()
4800 {
4801   return myCurrentStudy->_is_nil() || myCurrentStudy->_non_existent() ? -1 : myCurrentStudy->StudyId();
4802 }
4803
4804 //=============================================================================
4805 /*!
4806  *  SMESHEngine_factory
4807  *
4808  *  C factory, accessible with dlsym, after dlopen
4809  */
4810 //=============================================================================
4811
4812 extern "C"
4813 { SMESH_I_EXPORT
4814   PortableServer::ObjectId* SMESHEngine_factory( CORBA::ORB_ptr            orb,
4815                                                  PortableServer::POA_ptr   poa,
4816                                                  PortableServer::ObjectId* contId,
4817                                                  const char*               instanceName,
4818                                                  const char*               interfaceName )
4819   {
4820     if(MYDEBUG) MESSAGE( "PortableServer::ObjectId* SMESHEngine_factory()" );
4821     if(MYDEBUG) SCRUTE(interfaceName);
4822     SMESH_Gen_i* aSMESHGen = new SMESH_Gen_i(orb, poa, contId, instanceName, interfaceName);
4823     return aSMESHGen->getId() ;
4824   }
4825 }