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