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