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