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