Salome HOME
[Bug PAL7444] display mesh takes a lot of more memory in 2.1.0 than in 2.0.0.
[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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
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 <gp_Pnt.hxx>
45 #include <BRep_Tool.hxx>
46 #include <TCollection_AsciiString.hxx>
47
48 #include "Utils_CorbaException.hxx"
49
50 #include "utilities.h"
51 #include <fstream>
52 #include <stdio.h>
53 #include <dlfcn.h>
54
55 #include <HDFOI.hxx>
56
57 #include "SMESH_Gen_i.hxx"
58 #include "SMESH_Mesh_i.hxx"
59 #include "SMESH_Hypothesis_i.hxx"
60 #include "SMESH_Algo_i.hxx"
61 #include "SMESH_Group_i.hxx"
62
63 #include "SMESHDS_Document.hxx"
64 #include "SMESHDS_Group.hxx"
65 #include "SMESHDS_GroupOnGeom.hxx"
66 #include "SMESH_Group.hxx"
67
68 #include "SMDS_EdgePosition.hxx"
69 #include "SMDS_FacePosition.hxx"
70
71 #include CORBA_SERVER_HEADER(SMESH_Group)
72 #include CORBA_SERVER_HEADER(SMESH_Filter)
73
74 #include "DriverMED_W_SMESHDS_Mesh.h"
75 #include "DriverMED_R_SMESHDS_Mesh.h"
76
77 #include "SALOMEDS_Tool.hxx"
78 #include "SALOME_NamingService.hxx"
79 #include "SALOME_LifeCycleCORBA.hxx"
80 #include "Utils_SINGLETON.hxx"
81 #include "OpUtil.hxx"
82
83 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
84
85 #include "GEOM_Client.hxx"
86 #include "Utils_ExceptHandlers.hxx"
87
88 #include <map>
89 #include <boost/filesystem/path.hpp>
90
91 using namespace std;
92
93 #define NUM_TMP_FILES 2
94
95 #ifdef _DEBUG_
96 static int MYDEBUG = 0;
97 #else
98 static int MYDEBUG = 0;
99 #endif
100
101 // Static variables definition
102 CORBA::ORB_var          SMESH_Gen_i::myOrb;
103 PortableServer::POA_var SMESH_Gen_i::myPoa;
104 SALOME_NamingService*   SMESH_Gen_i::myNS  = NULL;
105 SALOME_LifeCycleCORBA*  SMESH_Gen_i::myLCC = NULL;
106 SMESH_Gen_i*            SMESH_Gen_i::mySMESHGen = NULL;
107
108 //=============================================================================
109 /*!
110  *  GetServant [ static ]
111  *
112  *  Get servant of the CORBA object
113  */
114 //=============================================================================
115
116 PortableServer::ServantBase_var SMESH_Gen_i::GetServant( CORBA::Object_ptr theObject )
117 {
118   if( CORBA::is_nil( theObject ) || CORBA::is_nil( GetPOA() ) )
119     return NULL;
120   try {
121     PortableServer::Servant aServant = GetPOA()->reference_to_servant( theObject );
122     return aServant;
123   } 
124   catch (...) {
125     INFOS( "GetServant - Unknown exception was caught!!!" ); 
126     return NULL;
127   }
128 }
129
130 //=============================================================================
131 /*!
132  *  SObjectToObject [ static ]
133  *
134  *  Get CORBA object corresponding to the SALOMEDS::SObject
135  */
136 //=============================================================================
137
138 CORBA::Object_var SMESH_Gen_i::SObjectToObject( SALOMEDS::SObject_ptr theSObject )
139 {
140   SALOMEDS::GenericAttribute_var anAttr;
141   CORBA::Object_var anObj;
142   if ( !theSObject->_is_nil() ) {
143     try {
144       if( theSObject->FindAttribute( anAttr, "AttributeIOR" ) ) {
145         SALOMEDS::AttributeIOR_var anIOR  = SALOMEDS::AttributeIOR::_narrow( anAttr );
146         CORBA::String_var aValue = anIOR->Value();
147         if( strcmp( aValue, "" ) != 0 )
148           anObj = GetORB()->string_to_object( aValue );
149         }
150     }
151     catch( ... ) {
152       INFOS( "SObjectToObject - Unknown exception was caught!!!" );
153     }
154   }
155   return anObj;
156 }
157
158 //=============================================================================
159 /*!
160  *  GetNS [ static ]
161  *
162  *  Get SALOME_NamingService object 
163  */
164 //=============================================================================
165
166 SALOME_NamingService* SMESH_Gen_i::GetNS()
167 {
168   if ( myNS == NULL ) {
169     myNS = SINGLETON_<SALOME_NamingService>::Instance();
170     ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting());
171     myNS->init_orb( GetORB() );
172   }
173   return myNS;
174 }
175
176 //=============================================================================
177 /*!
178  *  GetLCC [ static ]
179  *
180  *  Get SALOME_LifeCycleCORBA object
181  */
182 //=============================================================================     
183 SALOME_LifeCycleCORBA*  SMESH_Gen_i::GetLCC() {
184   if ( myLCC == NULL ) {
185     myLCC = new SALOME_LifeCycleCORBA( GetNS() );
186   }
187   return myLCC;
188 }
189
190
191 //=============================================================================
192 /*!
193  *  GetGeomEngine [ static ]
194  *
195  *  Get GEOM::GEOM_Gen reference
196  */
197 //=============================================================================     
198 GEOM::GEOM_Gen_ptr SMESH_Gen_i::GetGeomEngine() {
199   GEOM::GEOM_Gen_var aGeomEngine =
200     GEOM::GEOM_Gen::_narrow( GetLCC()->FindOrLoad_Component("FactoryServer","GEOM") );
201   return aGeomEngine._retn();
202 }
203
204 //=============================================================================
205 /*!
206  *  SMESH_Gen_i::SMESH_Gen_i
207  *
208  *  Default constructor: not for use
209  */
210 //=============================================================================
211
212 SMESH_Gen_i::SMESH_Gen_i()
213 {
214   INFOS( "SMESH_Gen_i::SMESH_Gen_i : default constructor" );
215 }
216
217 //=============================================================================
218 /*!
219  *  SMESH_Gen_i::SMESH_Gen_i 
220  *
221  *  Standard constructor, used with Container
222  */
223 //=============================================================================
224
225 SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr            orb,
226                           PortableServer::POA_ptr   poa,
227                           PortableServer::ObjectId* contId, 
228                           const char*               instanceName, 
229                           const char*               interfaceName )
230      : Engines_Component_i( orb, poa, contId, instanceName, interfaceName )
231 {
232   INFOS( "SMESH_Gen_i::SMESH_Gen_i : standard constructor" );
233
234   myOrb = CORBA::ORB::_duplicate(orb);
235   myPoa = PortableServer::POA::_duplicate(poa);
236   
237   _thisObj = this ;
238   _id = myPoa->activate_object( _thisObj );
239   
240   myShapeReader = NULL;  // shape reader
241   mySMESHGen = this;
242 }
243
244 //=============================================================================
245 /*!
246  *  SMESH_Gen_i::~SMESH_Gen_i
247  *
248  *  Destructor
249  */
250 //=============================================================================
251
252 SMESH_Gen_i::~SMESH_Gen_i()
253 {
254   INFOS( "SMESH_Gen_i::~SMESH_Gen_i" );
255
256   // delete hypothesis creators
257   map<string, GenericHypothesisCreator_i*>::iterator itHyp;
258   for (itHyp = myHypCreatorMap.begin(); itHyp != myHypCreatorMap.end(); itHyp++)
259   {
260     delete (*itHyp).second;
261   }
262   myHypCreatorMap.clear();
263
264   // Clear study contexts data
265   map<int, StudyContext*>::iterator it;
266   for ( it = myStudyContextMap.begin(); it != myStudyContextMap.end(); ++it ) {
267     delete it->second;
268   }
269   myStudyContextMap.clear();
270   // delete shape reader
271   if ( !myShapeReader ) 
272     delete myShapeReader;
273 }
274   
275 //=============================================================================
276 /*!
277  *  SMESH_Gen_i::createHypothesis
278  *
279  *  Create hypothesis of given type
280  */
281 //=============================================================================
282 SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName,
283                                                           const char* theLibName)
284      throw (SALOME::SALOME_Exception)
285 {
286   Unexpect aCatch(SALOME_SalomeException);
287   if(MYDEBUG) MESSAGE( "Create Hypothesis <" << theHypName << "> from " << theLibName);
288
289   // create a new hypothesis object servant
290   SMESH_Hypothesis_i* myHypothesis_i = 0;
291   SMESH::SMESH_Hypothesis_var hypothesis_i;
292
293   try
294   {
295     // check, if creator for this hypothesis type already exists
296     if (myHypCreatorMap.find(string(theHypName)) == myHypCreatorMap.end())
297     {
298       // load plugin library
299       if(MYDEBUG) MESSAGE("Loading server meshers plugin library ...");
300       void* libHandle = dlopen (theLibName, RTLD_LAZY);
301       if (!libHandle)
302       {
303         // report any error, if occured
304         const char* anError = dlerror();
305         throw(SALOME_Exception(anError));
306       }
307
308       // get method, returning hypothesis creator
309       if(MYDEBUG) MESSAGE("Find GetHypothesisCreator() method ...");
310       typedef GenericHypothesisCreator_i* (*GetHypothesisCreator)(const char* theHypName);
311       GetHypothesisCreator procHandle =
312         (GetHypothesisCreator)dlsym( libHandle, "GetHypothesisCreator" );
313       if (!procHandle)
314       {
315         throw(SALOME_Exception(LOCALIZED("bad hypothesis plugin library")));
316         dlclose(libHandle);
317       }
318
319       // get hypothesis creator
320       if(MYDEBUG) MESSAGE("Get Hypothesis Creator for " << theHypName);
321       GenericHypothesisCreator_i* aCreator = procHandle(theHypName);
322       if (!aCreator)
323       {
324         throw(SALOME_Exception(LOCALIZED("no such a hypothesis in this plugin")));
325       }
326
327       // map hypothesis creator to a hypothesis name
328       myHypCreatorMap[string(theHypName)] = aCreator;
329     }
330
331     // create a new hypothesis object, store its ref. in studyContext
332     if(MYDEBUG) MESSAGE("Create Hypothesis " << theHypName);
333     myHypothesis_i =
334       myHypCreatorMap[string(theHypName)]->Create (myPoa, GetCurrentStudyID(), &myGen);
335     // _CS_gbo Explicit activation (no longer made in the constructor).
336     myHypothesis_i->Activate();
337     myHypothesis_i->SetLibName(theLibName); // for persistency assurance
338   }
339   catch (SALOME_Exception& S_ex)
340   {
341     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
342   }
343
344   if (!myHypothesis_i)
345     return hypothesis_i._retn();
346
347   // activate the CORBA servant of hypothesis
348   hypothesis_i = SMESH::SMESH_Hypothesis::_narrow( myHypothesis_i->_this() );
349   int nextId = RegisterObject( hypothesis_i );
350   if(MYDEBUG) MESSAGE( "Add hypo to map with id = "<< nextId );
351
352   return hypothesis_i._retn();
353 }
354   
355 //=============================================================================
356 /*!
357  *  SMESH_Gen_i::createMesh
358  *
359  *  Create empty mesh on shape
360  */
361 //=============================================================================
362 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh()
363      throw ( SALOME::SALOME_Exception )
364 {
365   Unexpect aCatch(SALOME_SalomeException);
366   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::createMesh" );
367
368   // Get or create the GEOM_Client instance
369   try {
370     // create a new mesh object servant, store it in a map in study context
371     SMESH_Mesh_i* meshServant = new SMESH_Mesh_i( GetPOA(), this, GetCurrentStudyID() );
372     // create a new mesh object
373     meshServant->SetImpl( myGen.CreateMesh( GetCurrentStudyID() ));
374
375     // activate the CORBA servant of Mesh
376     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( meshServant->_this() );
377     int nextId = RegisterObject( mesh );
378     if(MYDEBUG) MESSAGE( "Add mesh to map with id = "<< nextId);
379     return mesh._retn();
380   }
381   catch (SALOME_Exception& S_ex) {
382     THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
383   }
384   return SMESH::SMESH_Mesh::_nil();
385 }
386
387 //=============================================================================
388 /*!
389  *  SMESH_Gen_i::GetShapeReader
390  *
391  *  Get shape reader
392  */
393 //=============================================================================
394 GEOM_Client* SMESH_Gen_i::GetShapeReader()
395 {
396   // create shape reader if necessary
397   if ( !myShapeReader ) 
398     myShapeReader = new GEOM_Client(GetContainerRef());
399   ASSERT( myShapeReader );
400   return myShapeReader;
401 }
402
403 //=============================================================================
404 /*!
405  *  SMESH_Gen_i::SetCurrentStudy
406  *
407  *  Set current study
408  */
409 //=============================================================================
410
411 void SMESH_Gen_i::SetCurrentStudy( SALOMEDS::Study_ptr theStudy )
412 {
413   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::SetCurrentStudy" );
414   myCurrentStudy = SALOMEDS::Study::_duplicate( theStudy );
415   // create study context, if it doesn't exist and set current study
416   int studyId = GetCurrentStudyID();
417   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::SetCurrentStudy: study Id = " << studyId );
418   if ( myStudyContextMap.find( studyId ) == myStudyContextMap.end() ) {
419     myStudyContextMap[ studyId ] = new StudyContext;      
420   }
421   SetStudyID(studyId);
422   // set current study for geom engine
423   /*
424   if ( !CORBA::is_nil( GetGeomEngine() ) )
425     GetGeomEngine()->GetCurrentStudy( myCurrentStudy->StudyId() );
426   */
427 }
428
429 //=============================================================================
430 /*!
431  *  SMESH_Gen_i::GetCurrentStudy
432  *
433  *  Get current study
434  */
435 //=============================================================================
436
437 SALOMEDS::Study_ptr SMESH_Gen_i::GetCurrentStudy()
438 {
439   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetCurrentStudy: study Id = " << GetCurrentStudyID() );
440   return SALOMEDS::Study::_duplicate( myCurrentStudy );
441 }
442
443 //=============================================================================
444 /*!
445  *  SMESH_Gen_i::GetCurrentStudyContext 
446  *
447  *  Get current study context
448  */
449 //=============================================================================
450 StudyContext* SMESH_Gen_i::GetCurrentStudyContext()
451 {
452   if ( !CORBA::is_nil( myCurrentStudy ) &&
453       myStudyContextMap.find( GetCurrentStudyID() ) != myStudyContextMap.end() )
454     return myStudyContextMap[ myCurrentStudy->StudyId() ];
455   else
456     return 0;
457 }
458
459 //=============================================================================
460 /*!
461  *  SMESH_Gen_i::CreateHypothesis 
462  *
463  *  Create hypothesis/algorothm of given type and publish it in the study
464  */
465 //=============================================================================
466
467 SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypName,
468                                                            const char* theLibName )
469      throw ( SALOME::SALOME_Exception )
470 {
471   Unexpect aCatch(SALOME_SalomeException);
472   // Create hypothesis/algorithm
473   SMESH::SMESH_Hypothesis_var hyp = this->createHypothesis( theHypName, theLibName );
474
475   // Publish hypothesis/algorithm in the study
476   if ( CanPublishInStudy( hyp ) )
477     PublishHypothesis( myCurrentStudy, hyp );
478
479   return hyp._retn();
480 }
481   
482 //=============================================================================
483 /*!
484  *  SMESH_Gen_i::CreateMesh
485  *
486  *  Create empty mesh on a shape and publish it in the study
487  */
488 //=============================================================================
489
490 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObject )
491      throw ( SALOME::SALOME_Exception )
492 {
493   Unexpect aCatch(SALOME_SalomeException);
494   using namespace SMESH;
495   FactoryHandler aFactory;
496
497   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMesh" );
498   // create mesh
499   SMESH::SMESH_Mesh_var mesh = this->createMesh();
500   // set shape
501   SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
502   ASSERT( meshServant );
503   meshServant->SetShape( theShapeObject );
504   // publish mesh in the study
505   if ( CanPublishInStudy( mesh ) )
506     PublishMesh( myCurrentStudy, mesh.in() );
507
508   CORBA::String_var anEntry = theShapeObject->GetEntry();
509   aFactory->Register(TInvocationID(TResultCont(1,meshServant->GetID()),
510                                    GetID(),
511                                    "SMESH_Mesh",
512                                    "CreateMesh",
513                                    TArgumentCont(),
514                                    anEntry.in()));
515
516   return mesh._retn();
517 }
518
519 //=============================================================================
520 /*!
521  *  SMESH_Gen_i::CreateMeshFromUNV
522  *
523  *  Create mesh and import data from UNV file
524  */
525 //=============================================================================
526
527 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName )
528   throw ( SALOME::SALOME_Exception )
529 {
530   Unexpect aCatch(SALOME_SalomeException);
531   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMeshesFromUNV" );
532
533   SMESH::SMESH_Mesh_var aMesh = createMesh();
534   string aFileName; // = boost::filesystem::path(theFileName).leaf();
535   // publish mesh in the study
536   if ( CanPublishInStudy( aMesh ) )
537     PublishMesh( myCurrentStudy, aMesh.in(), aFileName.c_str() );
538
539   SMESH_Mesh_i* aServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( aMesh ).in() );
540   ASSERT( aServant );
541   aServant->ImportUNVFile( theFileName );
542   return aMesh._retn();
543 }
544
545 //=============================================================================
546 /*!
547  *  SMESH_Gen_i::CreateMeshFromMED
548  *
549  *  Create mesh and import data from MED file
550  */
551 //=============================================================================
552
553 SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char* theFileName,
554                                                      SMESH::DriverMED_ReadStatus& theStatus)
555      throw ( SALOME::SALOME_Exception )
556 {
557   Unexpect aCatch(SALOME_SalomeException);
558   using namespace SMESH;
559   FactoryHandler aFactory;
560
561   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMeshFromMED" );
562
563   // Retrieve mesh names from the file
564   DriverMED_R_SMESHDS_Mesh myReader;
565   myReader.SetFile( theFileName );
566   myReader.SetMeshId( -1 );
567   Driver_Mesh::Status aStatus;
568   list<string> aNames = myReader.GetMeshNames(aStatus);
569   SMESH::mesh_array_var aResult = new SMESH::mesh_array();
570   theStatus = (SMESH::DriverMED_ReadStatus)aStatus;
571   if(theStatus == SMESH::DRS_OK){
572     aResult->length( aNames.size() );
573     TResultCont aResultCont;
574     int i = 0;
575     
576     // Iterate through all meshes and create mesh objects
577     for ( list<string>::iterator it = aNames.begin(); it != aNames.end(); it++ ) {
578       // create mesh
579       SMESH::SMESH_Mesh_var mesh = createMesh();
580       
581       // publish mesh in the study
582       if ( CanPublishInStudy( mesh ) )
583         PublishMesh( myCurrentStudy, mesh.in(), (*it).c_str() );
584       
585       // Read mesh data (groups are published automatically by ImportMEDFile())
586       SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
587       ASSERT( meshServant );
588       SMESH::DriverMED_ReadStatus status1 =
589         meshServant->ImportMEDFile( theFileName, (*it).c_str() );
590       if (status1 > theStatus)
591         theStatus = status1;
592
593       aResult[i++] = SMESH::SMESH_Mesh::_duplicate( mesh );
594
595       aResultCont.push_back(meshServant->GetID());
596     }
597     aFactory->Register(TInvocationID(aResultCont,
598                                      GetID(),
599                                      "SMESH_Mesh",
600                                      "CreateMeshesFromMED",
601                                      TArgumentCont(1,std::string(theFileName)),
602                                      ""));
603   }
604   return aResult._retn();
605 }
606
607 //=============================================================================
608 /*!
609  *  SMESH_Gen_i::CreateMeshFromSTL
610  *
611  *  Create mesh and import data from STL file
612  */
613 //=============================================================================
614
615 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromSTL( const char* theFileName )
616   throw ( SALOME::SALOME_Exception )
617 {
618   Unexpect aCatch(SALOME_SalomeException);
619   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMeshesFromSTL" );
620
621   SMESH::SMESH_Mesh_var aMesh = createMesh();
622   string aFileName; // = boost::filesystem::path(theFileName).leaf();
623   // publish mesh in the study
624   if ( CanPublishInStudy( aMesh ) )
625     PublishInStudy( myCurrentStudy, SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() );
626
627   SMESH_Mesh_i* aServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( aMesh ).in() );
628   ASSERT( aServant );
629   aServant->ImportSTLFile( theFileName );
630   return aMesh._retn();
631 }
632
633 //=============================================================================
634 /*!
635  *  SMESH_Gen_i::IsReadyToCompute
636  *
637  *  Returns true if mesh contains enough data to be computed
638  */
639 //=============================================================================
640
641 CORBA::Boolean SMESH_Gen_i::IsReadyToCompute( SMESH::SMESH_Mesh_ptr theMesh,
642                                               GEOM::GEOM_Object_ptr theShapeObject )
643   throw ( SALOME::SALOME_Exception )
644 {
645   Unexpect aCatch(SALOME_SalomeException);
646   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IsReadyToCompute" );
647
648   if ( CORBA::is_nil( theShapeObject ) )
649     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", 
650                                   SALOME::BAD_PARAM );
651
652   if ( CORBA::is_nil( theMesh ) )
653     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
654                                   SALOME::BAD_PARAM );
655
656   try {
657     // get mesh servant
658     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
659     ASSERT( meshServant );
660     if ( meshServant ) {
661       // get local TopoDS_Shape
662       TopoDS_Shape myLocShape = GeomObjectToShape( theShapeObject );
663       // call implementation
664       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
665       return myGen.CheckAlgoState( myLocMesh, myLocShape );
666     }
667   }
668   catch ( SALOME_Exception& S_ex ) {
669     INFOS( "catch exception "<< S_ex.what() );
670   }
671   return false;
672 }
673
674 //=============================================================================
675 /*!
676  *  SMESH_Gen_i::GetSubShapesId
677  *
678  *  Get sub-shapes unique ID's list
679  */
680 //=============================================================================
681
682 SMESH::long_array* SMESH_Gen_i::GetSubShapesId( GEOM::GEOM_Object_ptr theMainShapeObject,
683                                             const SMESH::object_array& theListOfSubShapeObject )
684      throw ( SALOME::SALOME_Exception )
685 {
686   Unexpect aCatch(SALOME_SalomeException);
687   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetSubShapesId" );
688
689   SMESH::long_array_var shapesId = new SMESH::long_array;
690   set<int> setId;
691
692   if ( CORBA::is_nil( theMainShapeObject ) )
693     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
694                                   SALOME::BAD_PARAM );
695
696   try
697     {
698       TopoDS_Shape myMainShape = GeomObjectToShape(theMainShapeObject);
699       TopTools_IndexedMapOfShape myIndexToShape;      
700       TopExp::MapShapes(myMainShape,myIndexToShape);
701
702       for ( int i = 0; i < theListOfSubShapeObject.length(); i++ )
703         {
704           GEOM::GEOM_Object_var aShapeObject
705             = GEOM::GEOM_Object::_narrow(theListOfSubShapeObject[i]);
706           if ( CORBA::is_nil( aShapeObject ) )
707             THROW_SALOME_CORBA_EXCEPTION ("bad shape object reference", \
708                                         SALOME::BAD_PARAM );
709
710           TopoDS_Shape locShape  = GeomObjectToShape(aShapeObject);
711           for (TopExp_Explorer exp(locShape,TopAbs_FACE); exp.More(); exp.Next())
712             {
713               const TopoDS_Face& F = TopoDS::Face(exp.Current());
714               setId.insert(myIndexToShape.FindIndex(F));
715               if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(F));
716             }
717           for (TopExp_Explorer exp(locShape,TopAbs_EDGE); exp.More(); exp.Next())
718             {
719               const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
720               setId.insert(myIndexToShape.FindIndex(E));
721               if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(E));
722             }
723           for (TopExp_Explorer exp(locShape,TopAbs_VERTEX); exp.More(); exp.Next())
724             {
725               const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
726               setId.insert(myIndexToShape.FindIndex(V));
727               if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(V));
728             }
729         }
730       shapesId->length(setId.size());
731       set<int>::iterator iind;
732       int i=0;
733       for (iind = setId.begin(); iind != setId.end(); iind++)
734         {
735           if(MYDEBUG) SCRUTE((*iind));
736           shapesId[i] = (*iind);
737           if(MYDEBUG) SCRUTE(shapesId[i]);
738           i++;
739         }
740     }
741   catch (SALOME_Exception& S_ex)
742     {
743       THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
744     }
745
746   return shapesId._retn();
747 }
748
749 //=============================================================================
750 /*!
751  *  SMESH_Gen_i::Compute
752  *
753  *  Compute mesh on a shape
754  */
755 //=============================================================================
756
757 CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
758                                      GEOM::GEOM_Object_ptr theShapeObject )
759      throw ( SALOME::SALOME_Exception )
760 {
761   Unexpect aCatch(SALOME_SalomeException);
762   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Compute" );
763
764   if ( CORBA::is_nil( theShapeObject ) )
765     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", 
766                                   SALOME::BAD_PARAM );
767
768   if ( CORBA::is_nil( theMesh ) )
769     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
770                                   SALOME::BAD_PARAM );
771
772   try {
773     // get mesh servant
774     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
775     ASSERT( meshServant );
776     if ( meshServant ) {
777       // get local TopoDS_Shape
778       TopoDS_Shape myLocShape = GeomObjectToShape( theShapeObject );
779       // call implementation compute
780       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
781       return myGen.Compute( myLocMesh, myLocShape);
782     }
783   }
784   catch ( SALOME_Exception& S_ex ) {
785     INFOS( "Compute(): catch exception "<< S_ex.what() );
786   }
787   catch ( ... ) {
788     INFOS( "Compute(): unknown exception " );
789   }
790   return false;
791 }
792
793 //=============================================================================
794 /*!
795  *  SMESH_Gen_i::Save
796  *
797  *  Save SMESH module's data
798  */
799 //=============================================================================
800 SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
801                                       const char*              theURL,
802                                       bool                     isMultiFile )
803 {
804   INFOS( "SMESH_Gen_i::Save" );
805
806   CORBA::Boolean anIsValidScript;
807   SALOMEDS::Study_var aStudy = theComponent->GetStudy(); 
808   SALOMEDS::TMPFile_var aDump = DumpPython(aStudy,false,anIsValidScript);
809
810 //  ASSERT( theComponent->GetStudy()->StudyId() == myCurrentStudy->StudyId() )
811   // san -- in case <myCurrentStudy> differs from theComponent's study,
812   // use that of the component
813   if ( myCurrentStudy->_is_nil() || 
814        theComponent->GetStudy()->StudyId() != myCurrentStudy->StudyId() )
815     SetCurrentStudy( theComponent->GetStudy() );
816
817   StudyContext* myStudyContext = GetCurrentStudyContext();
818   
819   // Declare a byte stream
820   SALOMEDS::TMPFile_var aStreamFile;
821   
822   // Obtain a temporary dir
823   TCollection_AsciiString tmpDir =
824     ( isMultiFile ) ? TCollection_AsciiString( ( char* )theURL ) : ( char* )SALOMEDS_Tool::GetTmpDir().c_str();
825
826   // Create a sequence of files processed
827   SALOMEDS::ListOfFileNames_var aFileSeq = new SALOMEDS::ListOfFileNames;
828   aFileSeq->length( NUM_TMP_FILES );
829
830   TCollection_AsciiString aStudyName( "" );
831   if ( isMultiFile ) 
832     aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( myCurrentStudy->URL() ).c_str() );
833
834   // Set names of temporary files
835   TCollection_AsciiString filename =
836     aStudyName + TCollection_AsciiString( "_SMESH.hdf" );        // for SMESH data itself
837   TCollection_AsciiString meshfile =
838     aStudyName + TCollection_AsciiString( "_SMESH_Mesh.med" );   // for mesh data to be stored in MED file
839   aFileSeq[ 0 ] = CORBA::string_dup( filename.ToCString() );
840   aFileSeq[ 1 ] = CORBA::string_dup( meshfile.ToCString() );
841   filename = tmpDir + filename;
842   meshfile = tmpDir + meshfile;
843
844   HDFfile*    aFile;
845   HDFdataset* aDataset;
846   HDFgroup*   aTopGroup;
847   HDFgroup*   aGroup;
848   HDFgroup*   aSubGroup;
849   HDFgroup*   aSubSubGroup;
850   hdf_size    aSize[ 1 ];
851
852   // MED writer to be used by storage process
853   DriverMED_W_SMESHDS_Mesh myWriter;
854   myWriter.SetFile( meshfile.ToCString() );
855
856   // Write data
857   // ---> create HDF file
858   aFile = new HDFfile( filename.ToCString() );
859   aFile->CreateOnDisk();
860   
861   // --> iterator for top-level objects
862   SALOMEDS::ChildIterator_var itBig = myCurrentStudy->NewChildIterator( theComponent );
863   for ( ; itBig->More(); itBig->Next() ) {
864     SALOMEDS::SObject_var gotBranch = itBig->Value();
865
866     // --> hypotheses root branch (only one for the study)
867     if ( gotBranch->Tag() == GetHypothesisRootTag() ) {
868       // create hypotheses root HDF group
869       aTopGroup = new HDFgroup( "Hypotheses", aFile );
870       aTopGroup->CreateOnDisk();
871
872       // iterator for all hypotheses
873       SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( gotBranch );
874       for ( ; it->More(); it->Next() ) {
875         SALOMEDS::SObject_var mySObject = it->Value();
876         CORBA::Object_var anObject = SObjectToObject( mySObject );
877         if ( !CORBA::is_nil( anObject ) ) {
878           SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject );
879           if ( !myHyp->_is_nil() ) {
880             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
881             if ( myImpl ) {
882               string hypname = string( myHyp->GetName() );
883               string libname = string( myHyp->GetLibName() );
884               int    id      = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) );
885               string hypdata = string( myImpl->SaveTo() );
886
887               // for each hypothesis create HDF group basing on its id
888               char hypGrpName[30];
889               sprintf( hypGrpName, "Hypothesis %d", id );
890               aGroup = new HDFgroup( hypGrpName, aTopGroup );
891               aGroup->CreateOnDisk();
892               // --> type name of hypothesis
893               aSize[ 0 ] = hypname.length() + 1;
894               aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 );
895               aDataset->CreateOnDisk();
896               aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) );
897               aDataset->CloseOnDisk();
898               // --> server plugin library name of hypothesis
899               aSize[ 0 ] = libname.length() + 1;
900               aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 );
901               aDataset->CreateOnDisk();
902               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
903               aDataset->CloseOnDisk();
904               // --> persistent data of hypothesis
905               aSize[ 0 ] = hypdata.length() + 1;
906               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
907               aDataset->CreateOnDisk();
908               aDataset->WriteOnDisk( ( char* )( hypdata.c_str() ) );
909               aDataset->CloseOnDisk();
910               // close hypothesis HDF group
911               aGroup->CloseOnDisk();
912             }
913           }
914         }
915       }
916       // close hypotheses root HDF group
917       aTopGroup->CloseOnDisk();
918     }
919     // --> algorithms root branch (only one for the study)
920     else if ( gotBranch->Tag() == GetAlgorithmsRootTag() ) {
921       // create algorithms root HDF group
922       aTopGroup = new HDFgroup( "Algorithms", aFile );
923       aTopGroup->CreateOnDisk();
924
925       // iterator for all algorithms
926       SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( gotBranch );
927       for ( ; it->More(); it->Next() ) {
928         SALOMEDS::SObject_var mySObject = it->Value();
929         CORBA::Object_var anObject = SObjectToObject( mySObject );
930         if ( !CORBA::is_nil( anObject ) ) {
931           SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject );
932           if ( !myHyp->_is_nil() ) {
933             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
934             if ( myImpl ) {
935               string hypname = string( myHyp->GetName() );
936               string libname = string( myHyp->GetLibName() );
937               int    id      = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) );
938               string hypdata = string( myImpl->SaveTo() );
939
940               // for each algorithm create HDF group basing on its id
941               char hypGrpName[30];
942               sprintf( hypGrpName, "Algorithm %d", id );
943               aGroup = new HDFgroup( hypGrpName, aTopGroup );
944               aGroup->CreateOnDisk();
945               // --> type name of algorithm
946               aSize[0] = hypname.length() + 1;
947               aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 );
948               aDataset->CreateOnDisk();
949               aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) );
950               aDataset->CloseOnDisk();
951               // --> server plugin library name of hypothesis
952               aSize[0] = libname.length() + 1;
953               aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 );
954               aDataset->CreateOnDisk();
955               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
956               aDataset->CloseOnDisk();
957               // --> persistent data of algorithm
958               aSize[0] = hypdata.length() + 1;
959               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
960               aDataset->CreateOnDisk();
961               aDataset->WriteOnDisk( ( char* )( hypdata.c_str() ) );
962               aDataset->CloseOnDisk();
963               // close algorithm HDF group
964               aGroup->CloseOnDisk();
965             }
966           }
967         }
968       }
969       // close algorithms root HDF group
970       aTopGroup->CloseOnDisk();
971     }
972     // --> mesh objects roots branches
973     else if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) {
974       CORBA::Object_var anObject = SObjectToObject( gotBranch );
975       if ( !CORBA::is_nil( anObject ) ) {
976         SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ;
977         if ( !myMesh->_is_nil() ) {
978           SMESH_Mesh_i* myImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( myMesh ).in() );
979           if ( myImpl ) {
980             int id = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) );
981             ::SMESH_Mesh& myLocMesh = myImpl->GetImpl();
982             SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS();
983
984             // for each mesh open the HDF group basing on its id
985             char meshGrpName[ 30 ];
986             sprintf( meshGrpName, "Mesh %d", id );
987             aTopGroup = new HDFgroup( meshGrpName, aFile );
988             aTopGroup->CreateOnDisk();
989
990             // --> put dataset to hdf file which is a flag that mesh has data
991             string strHasData = "0";
992             // check if the mesh is not empty
993             if ( mySMESHDSMesh->NbNodes() > 0 ) {
994               // write mesh data to med file
995               myWriter.SetMesh( mySMESHDSMesh );
996               myWriter.SetMeshId( id );
997               strHasData = "1";
998             }
999             aSize[ 0 ] = strHasData.length() + 1;
1000             aDataset = new HDFdataset( "Has data", aTopGroup, HDF_STRING, aSize, 1 );
1001             aDataset->CreateOnDisk();
1002             aDataset->WriteOnDisk( ( char* )( strHasData.c_str() ) );
1003             aDataset->CloseOnDisk();
1004             
1005             // write reference on a shape if exists
1006             SALOMEDS::SObject_var myRef;
1007             bool shapeRefFound = false;
1008             bool found = gotBranch->FindSubObject( GetRefOnShapeTag(), myRef );
1009             if ( found ) {
1010               SALOMEDS::SObject_var myShape;
1011               bool ok = myRef->ReferencedObject( myShape );
1012               if ( ok ) {
1013                 shapeRefFound = (! CORBA::is_nil( myShape->GetObject() ));
1014                 string myRefOnObject = myShape->GetID();
1015                 if ( shapeRefFound && myRefOnObject.length() > 0 ) {
1016                   aSize[ 0 ] = myRefOnObject.length() + 1;
1017                   aDataset = new HDFdataset( "Ref on shape", aTopGroup, HDF_STRING, aSize, 1 );
1018                   aDataset->CreateOnDisk();
1019                   aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
1020                   aDataset->CloseOnDisk();
1021                 }
1022               }
1023             }
1024
1025             // write applied hypotheses if exist
1026             SALOMEDS::SObject_var myHypBranch;
1027             found = gotBranch->FindSubObject( GetRefOnAppliedHypothesisTag(), myHypBranch );
1028             if ( found && !shapeRefFound ) { // remove applied hyps
1029               myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( myHypBranch );
1030             }
1031             if ( found && shapeRefFound ) {
1032               aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup );
1033               aGroup->CreateOnDisk();
1034
1035               SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( myHypBranch );
1036               int hypNb = 0;
1037               for ( ; it->More(); it->Next() ) {
1038                 SALOMEDS::SObject_var mySObject = it->Value();
1039                 SALOMEDS::SObject_var myRefOnHyp;
1040                 bool ok = mySObject->ReferencedObject( myRefOnHyp );
1041                 if ( ok ) {
1042                   // san - it is impossible to recover applied hypotheses
1043                   //       using their entries within Load() method,
1044                   // for there are no AttributeIORs in the study when Load() is working. 
1045                   // Hence, it is better to store persistent IDs of hypotheses as references to them
1046
1047                   //string myRefOnObject = myRefOnHyp->GetID();
1048                   CORBA::Object_var anObject = SObjectToObject( myRefOnHyp );
1049                   int id = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) );
1050                   //if ( myRefOnObject.length() > 0 ) {
1051                   //aSize[ 0 ] = myRefOnObject.length() + 1;
1052                   char hypName[ 30 ], hypId[ 30 ];
1053                   sprintf( hypName, "Hyp %d", ++hypNb );
1054                   sprintf( hypId, "%d", id );
1055                   aSize[ 0 ] = strlen( hypId ) + 1;
1056                   aDataset = new HDFdataset( hypName, aGroup, HDF_STRING, aSize, 1 );
1057                   aDataset->CreateOnDisk();
1058                   //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
1059                   aDataset->WriteOnDisk( hypId );
1060                   aDataset->CloseOnDisk();
1061                   //}
1062                 }
1063               }
1064               aGroup->CloseOnDisk();
1065             }
1066
1067             // write applied algorithms if exist
1068             SALOMEDS::SObject_var myAlgoBranch;
1069             found = gotBranch->FindSubObject( GetRefOnAppliedAlgorithmsTag(), myAlgoBranch );
1070             if ( found && !shapeRefFound ) { // remove applied algos
1071               myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( myAlgoBranch );
1072             }
1073             if ( found && shapeRefFound ) {
1074               aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
1075               aGroup->CreateOnDisk();
1076
1077               SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( myAlgoBranch );
1078               int algoNb = 0;
1079               for ( ; it->More(); it->Next() ) {
1080                 SALOMEDS::SObject_var mySObject = it->Value();
1081                 SALOMEDS::SObject_var myRefOnAlgo;
1082                 bool ok = mySObject->ReferencedObject( myRefOnAlgo );
1083                 if ( ok ) {
1084                   // san - it is impossible to recover applied algorithms
1085                   //       using their entries within Load() method,
1086                   // for there are no AttributeIORs in the study when Load() is working. 
1087                   // Hence, it is better to store persistent IDs of algorithms as references to them
1088
1089                   //string myRefOnObject = myRefOnAlgo->GetID();
1090                   CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo );
1091                   int id = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) );
1092                   //if ( myRefOnObject.length() > 0 ) {
1093                   //aSize[ 0 ] = myRefOnObject.length() + 1;
1094                   char algoName[ 30 ], algoId[ 30 ];
1095                   sprintf( algoName, "Algo %d", ++algoNb );
1096                   sprintf( algoId, "%d", id );
1097                   aSize[ 0 ] = strlen( algoId ) + 1;
1098                   aDataset = new HDFdataset( algoName, aGroup, HDF_STRING, aSize, 1 );
1099                   aDataset->CreateOnDisk();
1100                   //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
1101                   aDataset->WriteOnDisk( algoId );
1102                   aDataset->CloseOnDisk();
1103                   //}
1104                 }
1105               }
1106               aGroup->CloseOnDisk();
1107             }
1108
1109             // --> submesh objects sub-branches
1110
1111             for ( int i = GetSubMeshOnVertexTag(); i <= GetSubMeshOnCompoundTag(); i++ ) {
1112               SALOMEDS::SObject_var mySubmeshBranch;
1113               found = gotBranch->FindSubObject( i, mySubmeshBranch );
1114
1115               if ( found ) // check if there is shape reference in submeshes
1116               {
1117                 bool hasShapeRef = false;
1118                 SALOMEDS::ChildIterator_var itSM =
1119                   myCurrentStudy->NewChildIterator( mySubmeshBranch );
1120                 for ( ; itSM->More(); itSM->Next() ) {
1121                   SALOMEDS::SObject_var mySubRef, myShape, mySObject = itSM->Value();
1122                   if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef ))
1123                     mySubRef->ReferencedObject( myShape );
1124                   if ( !CORBA::is_nil( myShape ) && !CORBA::is_nil( myShape->GetObject() ))
1125                     hasShapeRef = true;
1126                   else
1127                   { // remove one submesh
1128                     if ( shapeRefFound )
1129                     { // unassign hypothesis
1130                       SMESH::SMESH_subMesh_var mySubMesh =
1131                         SMESH::SMESH_subMesh::_narrow( SObjectToObject( mySObject ));
1132                       if ( !mySubMesh->_is_nil() ) {
1133                         int shapeID = mySubMesh->GetId();
1134                         TopoDS_Shape S = mySMESHDSMesh->IndexToShape( shapeID );
1135                         const list<const SMESHDS_Hypothesis*>& hypList =
1136                           mySMESHDSMesh->GetHypothesis( S );
1137                         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
1138                         while ( hyp != hypList.end() ) {
1139                           int hypID = (*hyp++)->GetID(); // goto next hyp here because
1140                           myLocMesh.RemoveHypothesis( S, hypID ); // hypList changes here
1141                         }
1142                       }
1143                     }
1144                     myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( mySObject );
1145                   }
1146                 } // loop on submeshes of a type
1147                 if ( !shapeRefFound || !hasShapeRef ) { // remove the whole submeshes branch
1148                   myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( mySubmeshBranch );
1149                   found = false;
1150                 }
1151               }  // end check if there is shape reference in submeshes
1152               if ( found ) {
1153                 char name_meshgroup[ 30 ];
1154                 if ( i == GetSubMeshOnVertexTag() )
1155                   strcpy( name_meshgroup, "SubMeshes On Vertex" );
1156                 else if ( i == GetSubMeshOnEdgeTag() )
1157                   strcpy( name_meshgroup, "SubMeshes On Edge" );
1158                 else if ( i == GetSubMeshOnWireTag() )
1159                   strcpy( name_meshgroup, "SubMeshes On Wire" );
1160                 else if ( i == GetSubMeshOnFaceTag() )
1161                   strcpy( name_meshgroup, "SubMeshes On Face" );
1162                 else if ( i == GetSubMeshOnShellTag() )
1163                   strcpy( name_meshgroup, "SubMeshes On Shell" );
1164                 else if ( i == GetSubMeshOnSolidTag() )
1165                   strcpy( name_meshgroup, "SubMeshes On Solid" );
1166                 else if ( i == GetSubMeshOnCompoundTag() )
1167                   strcpy( name_meshgroup, "SubMeshes On Compound" );
1168                 
1169                 // for each type of submeshes create container HDF group
1170                 aGroup = new HDFgroup( name_meshgroup, aTopGroup );
1171                 aGroup->CreateOnDisk();
1172             
1173                 // iterator for all submeshes of given type
1174                 SALOMEDS::ChildIterator_var itSM = myCurrentStudy->NewChildIterator( mySubmeshBranch );
1175                 for ( ; itSM->More(); itSM->Next() ) {
1176                   SALOMEDS::SObject_var mySObject = itSM->Value();
1177                   CORBA::Object_var anSubObject = SObjectToObject( mySObject );
1178                   if ( !CORBA::is_nil( anSubObject ))
1179                   {
1180                     SMESH::SMESH_subMesh_var mySubMesh = SMESH::SMESH_subMesh::_narrow( anSubObject ) ;
1181                     int subid = myStudyContext->findId( string( GetORB()->object_to_string( anSubObject ) ) );
1182                       
1183                     // for each mesh open the HDF group basing on its id
1184                     char submeshGrpName[ 30 ];
1185                     sprintf( submeshGrpName, "SubMesh %d", subid );
1186                     aSubGroup = new HDFgroup( submeshGrpName, aGroup );
1187                     aSubGroup->CreateOnDisk();
1188
1189                     // write reference on a shape, already checked if it exists
1190                     SALOMEDS::SObject_var mySubRef, myShape;
1191                     if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef ))
1192                       mySubRef->ReferencedObject( myShape );
1193                     string myRefOnObject = myShape->GetID();
1194                     if ( myRefOnObject.length() > 0 ) {
1195                       aSize[ 0 ] = myRefOnObject.length() + 1;
1196                       aDataset = new HDFdataset( "Ref on shape", aSubGroup, HDF_STRING, aSize, 1 );
1197                       aDataset->CreateOnDisk();
1198                       aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
1199                       aDataset->CloseOnDisk();
1200                     }
1201
1202                     // write applied hypotheses if exist
1203                     SALOMEDS::SObject_var mySubHypBranch;
1204                     found = mySObject->FindSubObject( GetRefOnAppliedHypothesisTag(), mySubHypBranch );
1205                     if ( found ) {
1206                       aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup );
1207                       aSubSubGroup->CreateOnDisk();
1208
1209                       SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( mySubHypBranch );
1210                       int hypNb = 0;
1211                       for ( ; it->More(); it->Next() ) {
1212                         SALOMEDS::SObject_var mySubSObject = it->Value();
1213                         SALOMEDS::SObject_var myRefOnHyp;
1214                         bool ok = mySubSObject->ReferencedObject( myRefOnHyp );
1215                         if ( ok ) {
1216                           //string myRefOnObject = myRefOnHyp->GetID();
1217                           CORBA::Object_var anObject = SObjectToObject( myRefOnHyp );
1218                           int id = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) );
1219                           //if ( myRefOnObject.length() > 0 ) {
1220                           //aSize[ 0 ] = myRefOnObject.length() + 1;
1221                           char hypName[ 30 ], hypId[ 30 ];
1222                           sprintf( hypName, "Hyp %d", ++hypNb );
1223                           sprintf( hypId, "%d", id );
1224                           aSize[ 0 ] = strlen( hypId ) + 1;
1225                           aDataset = new HDFdataset( hypName, aSubSubGroup, HDF_STRING, aSize, 1 );
1226                           aDataset->CreateOnDisk();
1227                           //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
1228                           aDataset->WriteOnDisk( hypId );
1229                           aDataset->CloseOnDisk();
1230                           //}
1231                         }
1232                       }
1233                       aSubSubGroup->CloseOnDisk();
1234                     }
1235                     
1236                     // write applied algorithms if exist
1237                     SALOMEDS::SObject_var mySubAlgoBranch;
1238                     found = mySObject->FindSubObject( GetRefOnAppliedAlgorithmsTag(), mySubAlgoBranch );
1239                     if ( found ) {
1240                       aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup );
1241                       aSubSubGroup->CreateOnDisk();
1242
1243                       SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( mySubAlgoBranch );
1244                       int algoNb = 0;
1245                       for ( ; it->More(); it->Next() ) {
1246                         SALOMEDS::SObject_var mySubSObject = it->Value();
1247                         SALOMEDS::SObject_var myRefOnAlgo;
1248                         bool ok = mySubSObject->ReferencedObject( myRefOnAlgo );
1249                         if ( ok ) {
1250                           //string myRefOnObject = myRefOnAlgo->GetID();
1251                           CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo );
1252                           int id = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) );
1253                           //if ( myRefOnObject.length() > 0 ) {
1254                           //aSize[ 0 ] = myRefOnObject.length() + 1;
1255                           char algoName[ 30 ], algoId[ 30 ];
1256                           sprintf( algoName, "Algo %d", ++algoNb );
1257                           sprintf( algoId, "%d", id );
1258                           aSize[ 0 ] = strlen( algoId ) + 1;
1259                           aDataset = new HDFdataset( algoName, aSubSubGroup, HDF_STRING, aSize, 1 );
1260                           aDataset->CreateOnDisk();
1261                           //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
1262                           aDataset->WriteOnDisk( algoId );
1263                           aDataset->CloseOnDisk();
1264                           //}
1265                         }
1266                       }
1267                       aSubSubGroup->CloseOnDisk();
1268                     }
1269                     // close submesh HDF group
1270                     aSubGroup->CloseOnDisk();
1271                   }
1272                 }
1273                 // close container of submeshes by type HDF group
1274                 aGroup->CloseOnDisk();
1275               }
1276             }
1277             // All sub-meshes will be stored in MED file
1278             if ( shapeRefFound )
1279               myWriter.AddAllSubMeshes();
1280
1281             // groups root sub-branch
1282             SALOMEDS::SObject_var myGroupsBranch;
1283             for ( int i = GetNodeGroupsTag(); i <= GetVolumeGroupsTag(); i++ ) {
1284               found = gotBranch->FindSubObject( i, myGroupsBranch );
1285               if ( found ) {
1286                 char name_group[ 30 ];
1287                 if ( i == GetNodeGroupsTag() )
1288                   strcpy( name_group, "Groups of Nodes" );
1289                 else if ( i == GetEdgeGroupsTag() )
1290                   strcpy( name_group, "Groups of Edges" );
1291                 else if ( i == GetFaceGroupsTag() )
1292                   strcpy( name_group, "Groups of Faces" );
1293                 else if ( i == GetVolumeGroupsTag() )
1294                   strcpy( name_group, "Groups of Volumes" );
1295
1296                 aGroup = new HDFgroup( name_group, aTopGroup );
1297                 aGroup->CreateOnDisk();
1298
1299                 SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( myGroupsBranch );
1300                 for ( ; it->More(); it->Next() ) {
1301                   SALOMEDS::SObject_var mySObject = it->Value();
1302                   CORBA::Object_var aSubObject = SObjectToObject( mySObject );
1303                   if ( !CORBA::is_nil( aSubObject ) ) {
1304                     SMESH_GroupBase_i* myGroupImpl =
1305                       dynamic_cast<SMESH_GroupBase_i*>( GetServant( aSubObject ).in() );
1306                     if ( !myGroupImpl )
1307                       continue;
1308
1309                     int anId = myStudyContext->findId( string( GetORB()->object_to_string( aSubObject ) ) );
1310                     
1311                     // For each group, create a dataset named "Group <group_persistent_id>"
1312                     // and store the group's user name into it
1313                     char grpName[ 30 ];
1314                     sprintf( grpName, "Group %d", anId );
1315                     char* aUserName = myGroupImpl->GetName();
1316                     aSize[ 0 ] = strlen( aUserName ) + 1;
1317
1318                     aDataset = new HDFdataset( grpName, aGroup, HDF_STRING, aSize, 1 );
1319                     aDataset->CreateOnDisk();
1320                     aDataset->WriteOnDisk( aUserName );
1321                     aDataset->CloseOnDisk();
1322
1323                     // Store the group contents into MED file
1324                     if ( myLocMesh.GetGroup( myGroupImpl->GetLocalID() ) ) {
1325
1326                       if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen_i::Save(): saving group with StoreName = "
1327                               << grpName << " to MED file" );
1328                       SMESHDS_GroupBase* aGrpBaseDS =
1329                         myLocMesh.GetGroup( myGroupImpl->GetLocalID() )->GetGroupDS();
1330                       aGrpBaseDS->SetStoreName( grpName );
1331
1332                       // Pass SMESHDS_Group to MED writer 
1333                       SMESHDS_Group* aGrpDS = dynamic_cast<SMESHDS_Group*>( aGrpBaseDS );
1334                       if ( aGrpDS )
1335                         myWriter.AddGroup( aGrpDS );
1336
1337                       // write reference on a shape if exists
1338                       SMESHDS_GroupOnGeom* aGeomGrp =
1339                         dynamic_cast<SMESHDS_GroupOnGeom*>( aGrpBaseDS );
1340                       if ( aGeomGrp ) {
1341                         SALOMEDS::SObject_var mySubRef, myShape;
1342                         if (mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef ) &&
1343                             mySubRef->ReferencedObject( myShape ) &&
1344                             !CORBA::is_nil( myShape->GetObject() ))
1345                         {
1346                           string myRefOnObject = myShape->GetID();
1347                           if ( myRefOnObject.length() > 0 ) {
1348                             char aRefName[ 30 ];
1349                             sprintf( aRefName, "Ref on shape %d", anId);
1350                             aSize[ 0 ] = myRefOnObject.length() + 1;
1351                             aDataset = new HDFdataset(aRefName, aGroup, HDF_STRING, aSize, 1);
1352                             aDataset->CreateOnDisk();
1353                             aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
1354                             aDataset->CloseOnDisk();
1355                           }
1356                         }
1357                         else // shape ref is invalid:
1358                         {
1359                           // save a group on geometry as ordinary group
1360                           myWriter.AddGroup( aGeomGrp );
1361                         }
1362                       }
1363                     }
1364                   }
1365                 }
1366                 aGroup->CloseOnDisk();
1367               }
1368             } // loop on groups 
1369
1370             if ( strcmp( strHasData.c_str(), "1" ) == 0 )
1371             {
1372               // Flush current mesh information into MED file
1373               myWriter.Perform();
1374
1375               // maybe a shape was deleted in the study
1376               if ( !shapeRefFound && !mySMESHDSMesh->ShapeToMesh().IsNull() ) {
1377                 TopoDS_Shape nullShape;
1378                 myLocMesh.ShapeToMesh( nullShape ); // remove shape referring data
1379               }
1380
1381               // Store node positions on sub-shapes (SMDS_Position):
1382
1383               if ( !mySMESHDSMesh->SubMeshes().empty() )
1384               {
1385                 aGroup = new HDFgroup( "Node Positions", aTopGroup );
1386                 aGroup->CreateOnDisk();
1387
1388                 // in aGroup, create 5 datasets to contain:
1389                 // "Nodes on Edges" - ID of node on edge
1390                 // "Edge positions" - U parameter on node on edge
1391                 // "Nodes on Faces" - ID of node on face
1392                 // "Face U positions" - U parameter of node on face
1393                 // "Face V positions" - V parameter of node on face
1394
1395                 // Find out nb of nodes on edges and faces
1396                 // Collect corresponing sub-meshes
1397                 int nbEdgeNodes = 0, nbFaceNodes = 0;
1398                 list<SMESHDS_SubMesh*> aEdgeSM, aFaceSM;
1399                 // loop on SMESHDS_SubMesh'es
1400                 const map<int,SMESHDS_SubMesh*>& aSubMeshes = mySMESHDSMesh->SubMeshes();
1401                 map<int,SMESHDS_SubMesh*>::const_iterator itSubM ( aSubMeshes.begin() );
1402                 for ( ; itSubM != aSubMeshes.end() ; itSubM++ )
1403                 {
1404                   SMESHDS_SubMesh* aSubMesh = (*itSubM).second;
1405                   if ( aSubMesh->IsComplexSubmesh() )
1406                     continue; // submesh containing other submeshs
1407                   int nbNodes = aSubMesh->NbNodes();
1408                   if ( nbNodes == 0 ) continue;
1409
1410                   int aShapeID = (*itSubM).first;
1411                   int aShapeType = mySMESHDSMesh->IndexToShape( aShapeID ).ShapeType();
1412                   // write only SMDS_FacePosition and SMDS_EdgePosition
1413                   switch ( aShapeType ) {
1414                   case TopAbs_FACE:
1415                     nbFaceNodes += nbNodes;
1416                     aFaceSM.push_back( aSubMesh );
1417                     break;
1418                   case TopAbs_EDGE:
1419                     nbEdgeNodes += nbNodes;
1420                     aEdgeSM.push_back( aSubMesh );
1421                     break;
1422                   default:
1423                     continue;
1424                   }
1425                 }
1426                 // Treat positions on edges or faces
1427                 for ( int onFace = 0; onFace < 2; onFace++ )
1428                 {
1429                   // Create arrays to store in datasets
1430                   int iNode = 0, nbNodes = ( onFace ? nbFaceNodes : nbEdgeNodes );
1431                   if (!nbNodes) continue;
1432                   int* aNodeIDs = new int [ nbNodes ];
1433                   double* aUPos = new double [ nbNodes ];
1434                   double* aVPos = ( onFace ? new double[ nbNodes ] : 0 );
1435
1436                   // Fill arrays
1437                   // loop on sub-meshes
1438                   list<SMESHDS_SubMesh*> * pListSM = ( onFace ? &aFaceSM : &aEdgeSM );
1439                   list<SMESHDS_SubMesh*>::iterator itSM = pListSM->begin();
1440                   for ( ; itSM != pListSM->end(); itSM++ )
1441                   {
1442                     SMESHDS_SubMesh* aSubMesh = (*itSM);
1443                     if ( aSubMesh->IsComplexSubmesh() )
1444                       continue; // submesh containing other submeshs
1445
1446                     SMDS_NodeIteratorPtr itNode = aSubMesh->GetNodes();
1447                     // loop on nodes in aSubMesh
1448                     while ( itNode->more() )
1449                     {
1450                       //node ID
1451                       const SMDS_MeshNode* node = itNode->next();
1452                       aNodeIDs [ iNode ] = node->GetID();
1453
1454                       // Position
1455                       const SMDS_PositionPtr pos = node->GetPosition();
1456                       if ( onFace ) { // on FACE
1457                         const SMDS_FacePosition* fPos =
1458                           dynamic_cast<const SMDS_FacePosition*>( pos.get() );
1459                         if ( fPos ) {
1460                           aUPos[ iNode ] = fPos->GetUParameter();
1461                           aVPos[ iNode ] = fPos->GetVParameter();
1462                           iNode++;
1463                         }
1464                         else
1465                           nbNodes--;
1466                       }
1467                       else { // on EDGE
1468                         const SMDS_EdgePosition* ePos =
1469                           dynamic_cast<const SMDS_EdgePosition*>( pos.get() );
1470                         if ( ePos ) {
1471                           aUPos[ iNode ] = ePos->GetUParameter();
1472                           iNode++;
1473                         }
1474                         else
1475                           nbNodes--;
1476                       }
1477                     } // loop on nodes in aSubMesh
1478                   } // loop on sub-meshes
1479
1480                   // Write datasets
1481                   if ( nbNodes )
1482                   {
1483                     aSize[ 0 ] = nbNodes;
1484                     // IDS
1485                     string aDSName( onFace ? "Nodes on Faces" : "Nodes on Edges");
1486                     aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_INT32, aSize, 1 );
1487                     aDataset->CreateOnDisk();
1488                     aDataset->WriteOnDisk( aNodeIDs );
1489                     aDataset->CloseOnDisk();
1490
1491                     // U Positions
1492                     aDSName = ( onFace ? "Face U positions" : "Edge positions");
1493                     aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_FLOAT64, aSize, 1);
1494                     aDataset->CreateOnDisk();
1495                     aDataset->WriteOnDisk( aUPos );
1496                     aDataset->CloseOnDisk();
1497                     // V Positions
1498                     if ( onFace ) {
1499                       aDataset = new HDFdataset( "Face V positions", aGroup, HDF_FLOAT64, aSize, 1);
1500                       aDataset->CreateOnDisk();
1501                       aDataset->WriteOnDisk( aVPos );
1502                       aDataset->CloseOnDisk();
1503                     }
1504                   }
1505                   delete [] aNodeIDs;
1506                   delete [] aUPos;
1507                   if ( aVPos ) delete [] aVPos;
1508
1509                 } // treat positions on edges or faces
1510
1511                 // close "Node Positions" group
1512                 aGroup->CloseOnDisk(); 
1513
1514               } // if ( there are submeshes in SMESHDS_Mesh )
1515             } // if ( hasData )
1516
1517             // close mesh HDF group
1518             aTopGroup->CloseOnDisk();
1519           }
1520         }
1521       }
1522     }
1523   }
1524
1525   // close HDF file
1526   aFile->CloseOnDisk();
1527   delete aFile;
1528
1529   // Convert temporary files to stream
1530   aStreamFile = SALOMEDS_Tool::PutFilesToStream( tmpDir.ToCString(), aFileSeq.in(), isMultiFile );
1531
1532   // Remove temporary files and directory
1533   if ( !isMultiFile ) 
1534     SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
1535
1536   INFOS( "SMESH_Gen_i::Save() completed" );
1537   return aStreamFile._retn();
1538 }
1539
1540 //=============================================================================
1541 /*!
1542  *  SMESH_Gen_i::SaveASCII
1543  *
1544  *  Save SMESH module's data in ASCII format (not implemented yet)
1545  */
1546 //=============================================================================
1547
1548 SALOMEDS::TMPFile* SMESH_Gen_i::SaveASCII( SALOMEDS::SComponent_ptr theComponent,
1549                                            const char*              theURL,
1550                                            bool                     isMultiFile ) {
1551   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::SaveASCII" );
1552   SALOMEDS::TMPFile_var aStreamFile = Save( theComponent, theURL, isMultiFile );
1553   return aStreamFile._retn();
1554 }
1555
1556 //=============================================================================
1557 /*!
1558  *  SMESH_Gen_i::loadGeomData
1559  *
1560  *  Load GEOM module data
1561  */
1562 //=============================================================================
1563
1564 void SMESH_Gen_i::loadGeomData( SALOMEDS::SComponent_ptr theCompRoot )
1565 {
1566   if ( theCompRoot->_is_nil() )
1567     return;
1568
1569   SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow( theCompRoot->GetStudy() );
1570   if ( aStudy->_is_nil() )
1571     return;
1572
1573   SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder(); 
1574   aStudyBuilder->LoadWith( theCompRoot, GetGeomEngine() );
1575 }
1576
1577 //=============================================================================
1578 /*!
1579  *  SMESH_Gen_i::Load
1580  *
1581  *  Load SMESH module's data
1582  */
1583 //=============================================================================
1584
1585 bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
1586                         const SALOMEDS::TMPFile& theStream,
1587                         const char*              theURL,
1588                         bool                     isMultiFile )
1589 {
1590   INFOS( "SMESH_Gen_i::Load" );
1591
1592   if ( myCurrentStudy->_is_nil() || 
1593        theComponent->GetStudy()->StudyId() != myCurrentStudy->StudyId() )
1594     SetCurrentStudy( theComponent->GetStudy() );
1595
1596   StudyContext* myStudyContext = GetCurrentStudyContext();
1597   
1598   // Get temporary files location
1599   TCollection_AsciiString tmpDir =
1600     isMultiFile ? TCollection_AsciiString( ( char* )theURL ) : ( char* )SALOMEDS_Tool::GetTmpDir().c_str();
1601
1602   // Convert the stream into sequence of files to process
1603   SALOMEDS::ListOfFileNames_var aFileSeq = SALOMEDS_Tool::PutStreamToFiles( theStream,
1604                                                                             tmpDir.ToCString(),
1605                                                                             isMultiFile );
1606   TCollection_AsciiString aStudyName( "" );
1607   if ( isMultiFile ) 
1608     aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( myCurrentStudy->URL() ).c_str() );
1609
1610   // Set names of temporary files
1611   TCollection_AsciiString filename = tmpDir + aStudyName + TCollection_AsciiString( "_SMESH.hdf" );
1612   TCollection_AsciiString meshfile = tmpDir + aStudyName + TCollection_AsciiString( "_SMESH_Mesh.med" );
1613
1614   int size;
1615   HDFfile*    aFile;
1616   HDFdataset* aDataset;
1617   HDFgroup*   aTopGroup;
1618   HDFgroup*   aGroup;
1619   HDFgroup*   aSubGroup;
1620   HDFgroup*   aSubSubGroup;
1621
1622   // Read data
1623   // ---> open HDF file
1624   aFile = new HDFfile( filename.ToCString() );
1625   try {
1626     aFile->OpenOnDisk( HDF_RDONLY );
1627   }
1628   catch ( HDFexception ) {
1629     INFOS( "Load(): " << filename << " not found!" );
1630     return false;
1631   }
1632
1633   DriverMED_R_SMESHDS_Mesh myReader;
1634   myReader.SetFile( meshfile.ToCString() );
1635
1636   // get total number of top-level groups
1637   int aNbGroups = aFile->nInternalObjects(); 
1638   if ( aNbGroups > 0 ) {
1639     // --> in first turn we should read&create hypotheses
1640     if ( aFile->ExistInternalObject( "Hypotheses" ) ) {
1641       // open hypotheses root HDF group
1642       aTopGroup = new HDFgroup( "Hypotheses", aFile ); 
1643       aTopGroup->OpenOnDisk();
1644
1645       // get number of hypotheses
1646       int aNbObjects = aTopGroup->nInternalObjects(); 
1647       for ( int j = 0; j < aNbObjects; j++ ) {
1648         // try to identify hypothesis
1649         char hypGrpName[ HDF_NAME_MAX_LEN+1 ];
1650         aTopGroup->InternalObjectIndentify( j, hypGrpName );
1651
1652         if ( string( hypGrpName ).substr( 0, 10 ) == string( "Hypothesis" ) ) {
1653           // open hypothesis group
1654           aGroup = new HDFgroup( hypGrpName, aTopGroup ); 
1655           aGroup->OpenOnDisk();
1656
1657           // --> get hypothesis id
1658           int    id = atoi( string( hypGrpName ).substr( 10 ).c_str() );
1659           string hypname;
1660           string libname;
1661           string hypdata;
1662
1663           // get number of datasets
1664           int aNbSubObjects = aGroup->nInternalObjects();
1665           for ( int k = 0; k < aNbSubObjects; k++ ) {
1666             // identify dataset
1667             char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ];
1668             aGroup->InternalObjectIndentify( k, name_of_subgroup );
1669             // --> get hypothesis name
1670             if ( strcmp( name_of_subgroup, "Name"  ) == 0 ) {
1671               aDataset = new HDFdataset( name_of_subgroup, aGroup );
1672               aDataset->OpenOnDisk();
1673               size = aDataset->GetSize();
1674               char* hypname_str = new char[ size ];
1675               aDataset->ReadFromDisk( hypname_str );
1676               hypname = string( hypname_str );
1677               delete hypname_str;
1678               aDataset->CloseOnDisk();
1679             }
1680             // --> get hypothesis plugin library name
1681             if ( strcmp( name_of_subgroup, "LibName"  ) == 0 ) {
1682               aDataset = new HDFdataset( name_of_subgroup, aGroup );
1683               aDataset->OpenOnDisk();
1684               size = aDataset->GetSize();
1685               char* libname_str = new char[ size ];
1686               aDataset->ReadFromDisk( libname_str );
1687               if(MYDEBUG) SCRUTE( libname_str );
1688               libname = string( libname_str );
1689               delete libname_str;
1690               aDataset->CloseOnDisk();
1691             }
1692             // --> get hypothesis data
1693             if ( strcmp( name_of_subgroup, "Data"  ) == 0 ) {
1694               aDataset = new HDFdataset( name_of_subgroup, aGroup );
1695               aDataset->OpenOnDisk();
1696               size = aDataset->GetSize();
1697               char* hypdata_str = new char[ size ];
1698               aDataset->ReadFromDisk( hypdata_str );
1699               hypdata = string( hypdata_str );
1700               delete hypdata_str;
1701               aDataset->CloseOnDisk();
1702             }
1703           }
1704           // close hypothesis HDF group
1705           aGroup->CloseOnDisk();
1706
1707           // --> restore hypothesis from data
1708           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
1709             if(MYDEBUG) MESSAGE("VSR - load hypothesis : id = " << id <<
1710                     ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
1711             SMESH::SMESH_Hypothesis_var myHyp;
1712             
1713             try { // protect persistence mechanism against exceptions
1714               myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() );
1715             }
1716             catch (...) {
1717               INFOS( "Exception during hypothesis creation" );
1718             }
1719
1720             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
1721             if ( myImpl ) {
1722               myImpl->LoadFrom( hypdata.c_str() );
1723               string iorString = GetORB()->object_to_string( myHyp );
1724               int newId = myStudyContext->findId( iorString );
1725               myStudyContext->mapOldToNew( id, newId );
1726             }
1727             else
1728               if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
1729           }
1730         }
1731       }
1732       // close hypotheses root HDF group
1733       aTopGroup->CloseOnDisk();
1734     }
1735
1736     // --> then we should read&create algorithms
1737     if ( aFile->ExistInternalObject( "Algorithms" ) ) {
1738       // open algorithms root HDF group
1739       aTopGroup = new HDFgroup( "Algorithms", aFile ); 
1740       aTopGroup->OpenOnDisk();
1741
1742       // get number of algorithms
1743       int aNbObjects = aTopGroup->nInternalObjects(); 
1744       for ( int j = 0; j < aNbObjects; j++ ) {
1745         // try to identify algorithm
1746         char hypGrpName[ HDF_NAME_MAX_LEN+1 ];
1747         aTopGroup->InternalObjectIndentify( j, hypGrpName );
1748
1749         if ( string( hypGrpName ).substr( 0, 9 ) == string( "Algorithm" ) ) {
1750           // open algorithm group
1751           aGroup = new HDFgroup( hypGrpName, aTopGroup ); 
1752           aGroup->OpenOnDisk();
1753
1754           // --> get algorithm id
1755           int    id = atoi( string( hypGrpName ).substr( 9 ).c_str() );
1756           string hypname;
1757           string libname;
1758           string hypdata;
1759
1760           // get number of datasets
1761           int aNbSubObjects = aGroup->nInternalObjects();
1762           for ( int k = 0; k < aNbSubObjects; k++ ) {
1763             // identify dataset
1764             char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ];
1765             aGroup->InternalObjectIndentify( k, name_of_subgroup );
1766             // --> get algorithm name
1767             if ( strcmp( name_of_subgroup, "Name"  ) == 0 ) {
1768               aDataset = new HDFdataset( name_of_subgroup, aGroup );
1769               aDataset->OpenOnDisk();
1770               size = aDataset->GetSize();
1771               char* hypname_str = new char[ size ];
1772               aDataset->ReadFromDisk( hypname_str );
1773               hypname = string( hypname_str );
1774               delete hypname_str;
1775               aDataset->CloseOnDisk();
1776             }
1777             // --> get algorithm plugin library name
1778             if ( strcmp( name_of_subgroup, "LibName"  ) == 0 ) {
1779               aDataset = new HDFdataset( name_of_subgroup, aGroup );
1780               aDataset->OpenOnDisk();
1781               size = aDataset->GetSize();
1782               char* libname_str = new char[ size ];
1783               aDataset->ReadFromDisk( libname_str );
1784               if(MYDEBUG) SCRUTE( libname_str );
1785               libname = string( libname_str );
1786               delete libname_str;
1787               aDataset->CloseOnDisk();
1788             }
1789             // --> get algorithm data
1790             if ( strcmp( name_of_subgroup, "Data"  ) == 0 ) {
1791               aDataset = new HDFdataset( name_of_subgroup, aGroup );
1792               aDataset->OpenOnDisk();
1793               size = aDataset->GetSize();
1794               char* hypdata_str = new char[ size ];
1795               aDataset->ReadFromDisk( hypdata_str );
1796               if(MYDEBUG) SCRUTE( hypdata_str );
1797               hypdata = string( hypdata_str );
1798               delete hypdata_str;
1799               aDataset->CloseOnDisk();
1800             }
1801           }
1802           // close algorithm HDF group
1803           aGroup->CloseOnDisk();
1804           
1805           // --> restore algorithm from data
1806           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
1807             if(MYDEBUG) MESSAGE("VSR - load algo : id = " << id <<
1808                     ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
1809             SMESH::SMESH_Hypothesis_var myHyp;
1810                     
1811             try { // protect persistence mechanism against exceptions
1812               myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() );
1813             }
1814             catch (...) {
1815               INFOS( "Exception during hypothesis creation" );
1816             }
1817             
1818             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
1819             if ( myImpl ) {
1820               myImpl->LoadFrom( hypdata.c_str() );
1821               string iorString = GetORB()->object_to_string( myHyp );
1822               int newId = myStudyContext->findId( iorString );
1823               myStudyContext->mapOldToNew( id, newId );
1824             }
1825             else
1826               if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
1827           }
1828         }
1829       }
1830       // close algorithms root HDF group
1831       aTopGroup->CloseOnDisk();
1832     }
1833
1834     // --> the rest groups should be meshes
1835     for ( int i = 0; i < aNbGroups; i++ ) {
1836       // identify next group
1837       char meshName[ HDF_NAME_MAX_LEN+1 ];
1838       aFile->InternalObjectIndentify( i, meshName );
1839
1840       if ( string( meshName ).substr( 0, 4 ) == string( "Mesh" ) ) {
1841         // --> get mesh id
1842         int id = atoi( string( meshName ).substr( 4 ).c_str() );
1843         if ( id <= 0 )
1844           continue;
1845
1846         bool hasData = false;
1847
1848         // open mesh HDF group
1849         aTopGroup = new HDFgroup( meshName, aFile ); 
1850         aTopGroup->OpenOnDisk();
1851
1852         // get number of child HDF objects
1853         int aNbObjects = aTopGroup->nInternalObjects(); 
1854         if ( aNbObjects > 0 ) {
1855           // create mesh
1856           if(MYDEBUG) MESSAGE( "VSR - load mesh : id = " << id );
1857           SMESH::SMESH_Mesh_var myNewMesh = this->createMesh();
1858           SMESH_Mesh_i* myNewMeshImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( myNewMesh ).in() );
1859           if ( !myNewMeshImpl )
1860             continue;
1861           string iorString = GetORB()->object_to_string( myNewMesh );
1862           int newId = myStudyContext->findId( iorString );
1863           myStudyContext->mapOldToNew( id, newId );
1864           
1865           ::SMESH_Mesh& myLocMesh = myNewMeshImpl->GetImpl();
1866           SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS();
1867
1868           // try to find mesh data dataset
1869           if ( aTopGroup->ExistInternalObject( "Has data" ) ) {
1870             // load mesh "has data" flag
1871             aDataset = new HDFdataset( "Has data", aTopGroup );
1872             aDataset->OpenOnDisk();
1873             size = aDataset->GetSize();
1874             char* strHasData = new char[ size ];
1875             aDataset->ReadFromDisk( strHasData );
1876             aDataset->CloseOnDisk();
1877             if ( strcmp( strHasData, "1") == 0 ) {
1878               // read mesh data from MED file
1879               myReader.SetMesh( mySMESHDSMesh );
1880               myReader.SetMeshId( id );
1881               myReader.Perform();
1882               hasData = true;
1883             }
1884           }
1885
1886           // try to read and set reference to shape
1887           GEOM::GEOM_Object_var aShapeObject;
1888           if ( aTopGroup->ExistInternalObject( "Ref on shape" ) ) {
1889             // load mesh "Ref on shape" - it's an entry to SObject
1890             aDataset = new HDFdataset( "Ref on shape", aTopGroup );
1891             aDataset->OpenOnDisk();
1892             size = aDataset->GetSize();
1893             char* refFromFile = new char[ size ];
1894             aDataset->ReadFromDisk( refFromFile );
1895             aDataset->CloseOnDisk();
1896             if ( strlen( refFromFile ) > 0 ) {
1897               SALOMEDS::SObject_var shapeSO = myCurrentStudy->FindObjectID( refFromFile );
1898
1899               // Make sure GEOM data are loaded first
1900               loadGeomData( shapeSO->GetFatherComponent() );
1901
1902               CORBA::Object_var shapeObject = SObjectToObject( shapeSO );
1903               if ( !CORBA::is_nil( shapeObject ) ) {
1904                 aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
1905                 if ( !aShapeObject->_is_nil() )
1906                   myNewMeshImpl->SetShape( aShapeObject );
1907               }
1908             }
1909           }
1910
1911           // try to get applied algorithms
1912           if ( aTopGroup->ExistInternalObject( "Applied Algorithms" ) ) {
1913             aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
1914             aGroup->OpenOnDisk();
1915             // get number of applied algorithms
1916             int aNbSubObjects = aGroup->nInternalObjects(); 
1917             if(MYDEBUG) MESSAGE( "VSR - number of applied algos " << aNbSubObjects );
1918             for ( int j = 0; j < aNbSubObjects; j++ ) {
1919               char name_dataset[ HDF_NAME_MAX_LEN+1 ];
1920               aGroup->InternalObjectIndentify( j, name_dataset );
1921               // check if it is an algorithm
1922               if ( string( name_dataset ).substr( 0, 4 ) == string( "Algo" ) ) {
1923                 aDataset = new HDFdataset( name_dataset, aGroup );
1924                 aDataset->OpenOnDisk();
1925                 size = aDataset->GetSize();
1926                 char* refFromFile = new char[ size ];
1927                 aDataset->ReadFromDisk( refFromFile );
1928                 aDataset->CloseOnDisk();
1929
1930                 // san - it is impossible to recover applied algorithms using their entries within Load() method
1931                 
1932                 //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
1933                 //CORBA::Object_var hypObject = SObjectToObject( hypSO );
1934                 int id = atoi( refFromFile );
1935                 string anIOR = myStudyContext->getIORbyOldId( id );
1936                 if ( !anIOR.empty() ) {
1937                   CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
1938                   if ( !CORBA::is_nil( hypObject ) ) {
1939                     SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
1940                     if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
1941                       myNewMeshImpl->addHypothesis( aShapeObject, anHyp );
1942                   }
1943                 }
1944               }
1945             }
1946             aGroup->CloseOnDisk();
1947           }
1948
1949           // try to get applied hypotheses
1950           if ( aTopGroup->ExistInternalObject( "Applied Hypotheses" ) ) {
1951             aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup );
1952             aGroup->OpenOnDisk();
1953             // get number of applied hypotheses
1954             int aNbSubObjects = aGroup->nInternalObjects(); 
1955             for ( int j = 0; j < aNbSubObjects; j++ ) {
1956               char name_dataset[ HDF_NAME_MAX_LEN+1 ];
1957               aGroup->InternalObjectIndentify( j, name_dataset );
1958               // check if it is a hypothesis
1959               if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) {
1960                 aDataset = new HDFdataset( name_dataset, aGroup );
1961                 aDataset->OpenOnDisk();
1962                 size = aDataset->GetSize();
1963                 char* refFromFile = new char[ size ];
1964                 aDataset->ReadFromDisk( refFromFile );
1965                 aDataset->CloseOnDisk();
1966
1967                 // san - it is impossible to recover applied hypotheses using their entries within Load() method
1968                 
1969                 //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
1970                 //CORBA::Object_var hypObject = SObjectToObject( hypSO );
1971                 int id = atoi( refFromFile );
1972                 string anIOR = myStudyContext->getIORbyOldId( id );
1973                 if ( !anIOR.empty() ) {
1974                   CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
1975                   if ( !CORBA::is_nil( hypObject ) ) {
1976                     SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
1977                     if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
1978                       myNewMeshImpl->addHypothesis( aShapeObject, anHyp );
1979                   }
1980                 }
1981               }
1982             }
1983             aGroup->CloseOnDisk();
1984           }
1985
1986           // --> try to find submeshes containers for each type of submesh
1987           for ( int j = GetSubMeshOnVertexTag(); j <= GetSubMeshOnCompoundTag(); j++ ) {
1988             char name_meshgroup[ 30 ];
1989             if ( j == GetSubMeshOnVertexTag() )
1990               strcpy( name_meshgroup, "SubMeshes On Vertex" );
1991             else if ( j == GetSubMeshOnEdgeTag() )
1992               strcpy( name_meshgroup, "SubMeshes On Edge" );
1993             else if ( j == GetSubMeshOnWireTag() )
1994               strcpy( name_meshgroup, "SubMeshes On Wire" );
1995             else if ( j == GetSubMeshOnFaceTag() )
1996               strcpy( name_meshgroup, "SubMeshes On Face" );
1997             else if ( j == GetSubMeshOnShellTag() )
1998               strcpy( name_meshgroup, "SubMeshes On Shell" );
1999             else if ( j == GetSubMeshOnSolidTag() )
2000               strcpy( name_meshgroup, "SubMeshes On Solid" );
2001             else if ( j == GetSubMeshOnCompoundTag() )
2002               strcpy( name_meshgroup, "SubMeshes On Compound" );
2003             
2004             // try to get submeshes container HDF group
2005             if ( aTopGroup->ExistInternalObject( name_meshgroup ) ) {
2006               // open submeshes containers HDF group
2007               aGroup = new HDFgroup( name_meshgroup, aTopGroup );
2008               aGroup->OpenOnDisk();
2009               
2010               // get number of submeshes
2011               int aNbSubMeshes = aGroup->nInternalObjects(); 
2012               for ( int k = 0; k < aNbSubMeshes; k++ ) {
2013                 // identify submesh
2014                 char name_submeshgroup[ HDF_NAME_MAX_LEN+1 ];
2015                 aGroup->InternalObjectIndentify( k, name_submeshgroup );
2016                 if ( string( name_submeshgroup ).substr( 0, 7 ) == string( "SubMesh" )  ) {
2017                   // --> get submesh id
2018                   int subid = atoi( string( name_submeshgroup ).substr( 7 ).c_str() );
2019                   if ( subid <= 0 )
2020                     continue;
2021                   // open submesh HDF group
2022                   aSubGroup = new HDFgroup( name_submeshgroup, aGroup );
2023                   aSubGroup->OpenOnDisk();
2024                   
2025                   // try to read and set reference to subshape
2026                   GEOM::GEOM_Object_var aSubShapeObject;
2027                   SMESH::SMESH_subMesh_var aSubMesh;
2028
2029                   if ( aSubGroup->ExistInternalObject( "Ref on shape" ) ) {
2030                     // load submesh "Ref on shape" - it's an entry to SObject
2031                     aDataset = new HDFdataset( "Ref on shape", aSubGroup );
2032                     aDataset->OpenOnDisk();
2033                     size = aDataset->GetSize();
2034                     char* refFromFile = new char[ size ];
2035                     aDataset->ReadFromDisk( refFromFile );
2036                     aDataset->CloseOnDisk();
2037                     if ( strlen( refFromFile ) > 0 ) {
2038                       SALOMEDS::SObject_var subShapeSO = myCurrentStudy->FindObjectID( refFromFile );
2039                       CORBA::Object_var subShapeObject = SObjectToObject( subShapeSO );
2040                       if ( !CORBA::is_nil( subShapeObject ) ) {
2041                         aSubShapeObject = GEOM::GEOM_Object::_narrow( subShapeObject );
2042                         if ( !aSubShapeObject->_is_nil() )
2043                           aSubMesh = SMESH::SMESH_subMesh::_duplicate
2044                             ( myNewMeshImpl->createSubMesh( aSubShapeObject ) );
2045                         if ( aSubMesh->_is_nil() )
2046                           continue;
2047                         string iorSubString = GetORB()->object_to_string( aSubMesh );
2048                         int newSubId = myStudyContext->findId( iorSubString );
2049                         myStudyContext->mapOldToNew( subid, newSubId );
2050                       }
2051                     }
2052                   }
2053                   
2054                   if ( aSubMesh->_is_nil() )
2055                     continue;
2056
2057                   // VSR: Get submesh data from MED convertor
2058 //                int anInternalSubmeshId = aSubMesh->GetId(); // this is not a persistent ID, it's an internal one computed from sub-shape
2059 //                if (myNewMeshImpl->_mapSubMesh.find(anInternalSubmeshId) != myNewMeshImpl->_mapSubMesh.end()) {
2060 //                  if(MYDEBUG) MESSAGE("VSR - SMESH_Gen_i::Load(): loading from MED file submesh with ID = " <<
2061 //                            subid << " for subshape # " << anInternalSubmeshId);
2062 //                  SMESHDS_SubMesh* aSubMeshDS =
2063 //                      myNewMeshImpl->_mapSubMesh[anInternalSubmeshId]->CreateSubMeshDS();
2064 //                  if ( !aSubMeshDS ) {
2065 //                    if(MYDEBUG) MESSAGE("VSR - SMESH_Gen_i::Load(): FAILED to create a submesh for subshape # " <<
2066 //                              anInternalSubmeshId << " in current mesh!");
2067 //                  }
2068 //                  else
2069 //                    myReader.GetSubMesh( aSubMeshDS, subid );
2070 //                }
2071                     
2072                   // try to get applied algorithms
2073                   if ( aSubGroup->ExistInternalObject( "Applied Algorithms" ) ) {
2074                     // open "applied algorithms" HDF group
2075                     aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup );
2076                     aSubSubGroup->OpenOnDisk();
2077                     // get number of applied algorithms
2078                     int aNbSubObjects = aSubSubGroup->nInternalObjects(); 
2079                     for ( int l = 0; l < aNbSubObjects; l++ ) {
2080                       char name_dataset[ HDF_NAME_MAX_LEN+1 ];
2081                       aSubSubGroup->InternalObjectIndentify( l, name_dataset );
2082                       // check if it is an algorithm
2083                       if ( string( name_dataset ).substr( 0, 4 ) == string( "Algo" ) ) {
2084                         aDataset = new HDFdataset( name_dataset, aSubSubGroup );
2085                         aDataset->OpenOnDisk();
2086                         size = aDataset->GetSize();
2087                         char* refFromFile = new char[ size ];
2088                         aDataset->ReadFromDisk( refFromFile );
2089                         aDataset->CloseOnDisk();
2090
2091                         //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
2092                         //CORBA::Object_var hypObject = SObjectToObject( hypSO );
2093                         int id = atoi( refFromFile );
2094                         string anIOR = myStudyContext->getIORbyOldId( id );
2095                         if ( !anIOR.empty() ) {
2096                           CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
2097                           if ( !CORBA::is_nil( hypObject ) ) {
2098                             SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
2099                             if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
2100                               myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
2101                           }
2102                         }
2103                       }
2104                     }
2105                     // close "applied algorithms" HDF group
2106                     aSubSubGroup->CloseOnDisk();
2107                   }
2108                   
2109                   // try to get applied hypotheses
2110                   if ( aSubGroup->ExistInternalObject( "Applied Hypotheses" ) ) {
2111                     // open "applied hypotheses" HDF group
2112                     aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup );
2113                     aSubSubGroup->OpenOnDisk();
2114                     // get number of applied hypotheses
2115                     int aNbSubObjects = aSubSubGroup->nInternalObjects(); 
2116                     for ( int l = 0; l < aNbSubObjects; l++ ) {
2117                       char name_dataset[ HDF_NAME_MAX_LEN+1 ];
2118                       aSubSubGroup->InternalObjectIndentify( l, name_dataset );
2119                       // check if it is a hypothesis
2120                       if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) {
2121                         aDataset = new HDFdataset( name_dataset, aSubSubGroup );
2122                         aDataset->OpenOnDisk();
2123                         size = aDataset->GetSize();
2124                         char* refFromFile = new char[ size ];
2125                         aDataset->ReadFromDisk( refFromFile );
2126                         aDataset->CloseOnDisk();
2127                         
2128                         //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
2129                         //CORBA::Object_var hypObject = SObjectToObject( hypSO );
2130                         int id = atoi( refFromFile );
2131                         string anIOR = myStudyContext->getIORbyOldId( id );
2132                         if ( !anIOR.empty() ) {
2133                           CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
2134                           if ( !CORBA::is_nil( hypObject ) ) {
2135                             SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
2136                             if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
2137                               myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
2138                           }
2139                         }
2140                       }
2141                     }
2142                     // close "applied hypotheses" HDF group
2143                     aSubSubGroup->CloseOnDisk();
2144                   }
2145
2146                   // close submesh HDF group
2147                   aSubGroup->CloseOnDisk();
2148                 }
2149               }
2150               // close submeshes containers HDF group
2151               aGroup->CloseOnDisk();
2152             }
2153           }
2154
2155           if(hasData) {
2156             // Read sub-meshes from MED
2157             if(MYDEBUG) MESSAGE("JFA - Create all sub-meshes");
2158             myReader.CreateAllSubMeshes();
2159
2160
2161             // Read node positions on sub-shapes (SMDS_Position)
2162
2163             if ( aTopGroup->ExistInternalObject( "Node Positions" ))
2164             {
2165               // There are 5 datasets to read:
2166               // "Nodes on Edges" - ID of node on edge
2167               // "Edge positions" - U parameter on node on edge
2168               // "Nodes on Faces" - ID of node on face
2169               // "Face U positions" - U parameter of node on face
2170               // "Face V positions" - V parameter of node on face
2171               char* aEid_DSName = "Nodes on Edges";
2172               char* aEu_DSName  = "Edge positions";
2173               char* aFu_DSName  = "Face U positions";
2174               //char* aFid_DSName = "Nodes on Faces";
2175               //char* aFv_DSName  = "Face V positions";
2176
2177               // data to retrieve
2178               int nbEids = 0, nbFids = 0;
2179               int *aEids = 0, *aFids  = 0;
2180               double *aEpos = 0, *aFupos = 0, *aFvpos = 0;
2181
2182               // open a group
2183               aGroup = new HDFgroup( "Node Positions", aTopGroup ); 
2184               aGroup->OpenOnDisk();
2185
2186               // loop on 5 data sets
2187               int aNbObjects = aGroup->nInternalObjects();
2188               for ( int i = 0; i < aNbObjects; i++ )
2189               {
2190                 // identify dataset
2191                 char aDSName[ HDF_NAME_MAX_LEN+1 ];
2192                 aGroup->InternalObjectIndentify( i, aDSName );
2193                 // read data
2194                 aDataset = new HDFdataset( aDSName, aGroup );
2195                 aDataset->OpenOnDisk();
2196                 if ( aDataset->GetType() == HDF_FLOAT64 ) // Positions
2197                 {
2198                   double* pos = new double [ aDataset->GetSize() ];
2199                   aDataset->ReadFromDisk( pos );
2200                   // which one?
2201                   if ( strncmp( aDSName, aEu_DSName, strlen( aEu_DSName )) == 0 )
2202                     aEpos = pos;
2203                   else if ( strncmp( aDSName, aFu_DSName, strlen( aFu_DSName )) == 0 )
2204                     aFupos = pos;
2205                   else
2206                     aFvpos = pos;
2207                 }
2208                 else // NODE IDS
2209                 {
2210                   int* ids = new int [ aDataset->GetSize() ];
2211                   aDataset->ReadFromDisk( ids );
2212                   // on face or nodes?
2213                   if ( strncmp( aDSName, aEid_DSName, strlen( aEid_DSName )) == 0 ) {
2214                     aEids = ids;
2215                     nbEids = aDataset->GetSize();
2216                   }
2217                   else {
2218                     aFids = ids;
2219                     nbFids = aDataset->GetSize();
2220                   }
2221                 }
2222               } // loop on 5 datasets
2223
2224               // Set node positions on edges or faces
2225               for ( int onFace = 0; onFace < 2; onFace++ )
2226               {
2227                 int nbNodes = ( onFace ? nbFids : nbEids );
2228                 if ( nbNodes == 0 ) continue;
2229                 int* aNodeIDs = ( onFace ? aFids : aEids );
2230                 double* aUPos = ( onFace ? aFupos : aEpos );
2231                 double* aVPos = ( onFace ? aFvpos : 0 );
2232                 // loop on node IDs
2233                 for ( int iNode = 0; iNode < nbNodes; iNode++ )
2234                 {
2235                   const SMDS_MeshNode* node = mySMESHDSMesh->FindNode( aNodeIDs[ iNode ]);
2236                   ASSERT( node );
2237                   SMDS_PositionPtr aPos = node->GetPosition();
2238                   ASSERT( aPos )
2239                   if ( onFace ) {
2240                     ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_FACE );
2241                     SMDS_FacePosition* fPos = const_cast<SMDS_FacePosition*>
2242                       ( static_cast<const SMDS_FacePosition*>( aPos.get() ));
2243                     fPos->SetUParameter( aUPos[ iNode ]);
2244                     fPos->SetVParameter( aVPos[ iNode ]);
2245                   }
2246                   else {
2247                     ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE );
2248                     SMDS_EdgePosition* fPos = const_cast<SMDS_EdgePosition*>
2249                       ( static_cast<const SMDS_EdgePosition*>( aPos.get() ));
2250                     fPos->SetUParameter( aUPos[ iNode ]);
2251                   }
2252                 }
2253               }
2254               if ( aEids ) delete [] aEids;
2255               if ( aFids ) delete [] aFids;
2256               if ( aEpos ) delete [] aEpos;
2257               if ( aFupos ) delete [] aFupos;
2258               if ( aFvpos ) delete [] aFvpos;
2259               
2260               aGroup->CloseOnDisk();
2261
2262             } // if ( aTopGroup->ExistInternalObject( "Node Positions" ) )
2263           } // if ( hasData )
2264
2265           // Recompute State (as computed sub-meshes are restored from MED)
2266           if ( !aShapeObject->_is_nil() ) {
2267             MESSAGE("JFA - Compute State Engine ...");
2268             TopoDS_Shape myLocShape = GeomObjectToShape( aShapeObject );
2269             myNewMeshImpl->GetImpl().GetSubMesh(myLocShape)->ComputeStateEngine
2270               (SMESH_subMesh::SUBMESH_RESTORED);
2271             MESSAGE("JFA - Compute State Engine finished");
2272           }
2273
2274           // try to get groups
2275           for ( int ii = GetNodeGroupsTag(); ii <= GetVolumeGroupsTag(); ii++ ) {
2276             char name_group[ 30 ];
2277             if ( ii == GetNodeGroupsTag() )
2278               strcpy( name_group, "Groups of Nodes" );
2279             else if ( ii == GetEdgeGroupsTag() )
2280               strcpy( name_group, "Groups of Edges" );
2281             else if ( ii == GetFaceGroupsTag() )
2282               strcpy( name_group, "Groups of Faces" );
2283             else if ( ii == GetVolumeGroupsTag() )
2284               strcpy( name_group, "Groups of Volumes" );
2285
2286             if ( aTopGroup->ExistInternalObject( name_group ) ) {
2287               aGroup = new HDFgroup( name_group, aTopGroup );
2288               aGroup->OpenOnDisk();
2289               // get number of groups
2290               int aNbSubObjects = aGroup->nInternalObjects(); 
2291               for ( int j = 0; j < aNbSubObjects; j++ ) {
2292                 char name_dataset[ HDF_NAME_MAX_LEN+1 ];
2293                 aGroup->InternalObjectIndentify( j, name_dataset );
2294                 // check if it is an group
2295                 if ( string( name_dataset ).substr( 0, 5 ) == string( "Group" ) ) {
2296                   // --> get group id
2297                   int subid = atoi( string( name_dataset ).substr( 5 ).c_str() );
2298                   if ( subid <= 0 )
2299                     continue;
2300                   aDataset = new HDFdataset( name_dataset, aGroup );
2301                   aDataset->OpenOnDisk();
2302
2303                   // Retrieve actual group name
2304                   size = aDataset->GetSize();
2305                   char* nameFromFile = new char[ size ];
2306                   aDataset->ReadFromDisk( nameFromFile );
2307                   aDataset->CloseOnDisk();
2308
2309                   // Try to find a shape reference
2310                   TopoDS_Shape aShape;
2311                   char aRefName[ 30 ];
2312                   sprintf( aRefName, "Ref on shape %d", subid);
2313                   if ( aGroup->ExistInternalObject( aRefName ) ) {
2314                     // load mesh "Ref on shape" - it's an entry to SObject
2315                     aDataset = new HDFdataset( aRefName, aGroup );
2316                     aDataset->OpenOnDisk();
2317                     size = aDataset->GetSize();
2318                     char* refFromFile = new char[ size ];
2319                     aDataset->ReadFromDisk( refFromFile );
2320                     aDataset->CloseOnDisk();
2321                     if ( strlen( refFromFile ) > 0 ) {
2322                       SALOMEDS::SObject_var shapeSO = myCurrentStudy->FindObjectID( refFromFile );
2323                       CORBA::Object_var shapeObject = SObjectToObject( shapeSO );
2324                       if ( !CORBA::is_nil( shapeObject ) ) {
2325                         aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
2326                         if ( !aShapeObject->_is_nil() )
2327                           aShape = GeomObjectToShape( aShapeObject );
2328                       }
2329                     }
2330                   }
2331                   // Create group servant
2332                   SMESH::ElementType type = (SMESH::ElementType)(ii - GetNodeGroupsTag() + 1);
2333                   SMESH::SMESH_GroupBase_var aNewGroup = SMESH::SMESH_GroupBase::_duplicate
2334                     ( myNewMeshImpl->createGroup( type, nameFromFile, aShape ) );
2335                   // Obtain a SMESHDS_Group object 
2336                   if ( aNewGroup->_is_nil() )
2337                     continue;
2338
2339                   string iorSubString = GetORB()->object_to_string( aNewGroup );
2340                   int newSubId = myStudyContext->findId( iorSubString );
2341                   myStudyContext->mapOldToNew( subid, newSubId );
2342
2343                   SMESH_GroupBase_i* aGroupImpl =
2344                     dynamic_cast<SMESH_GroupBase_i*>( GetServant( aNewGroup ).in() );
2345                   if ( !aGroupImpl )
2346                     continue;
2347
2348                   SMESH_Group* aLocalGroup  = myLocMesh.GetGroup( aGroupImpl->GetLocalID() );
2349                   if ( !aLocalGroup )
2350                     continue;
2351
2352                   SMESHDS_GroupBase* aGroupBaseDS = aLocalGroup->GetGroupDS();
2353                   aGroupBaseDS->SetStoreName( name_dataset );
2354
2355                   // Fill group with contents from MED file
2356                   SMESHDS_Group* aGrp = dynamic_cast<SMESHDS_Group*>( aGroupBaseDS );
2357                   if ( aGrp )
2358                     myReader.GetGroup( aGrp );
2359                 }
2360               }
2361               aGroup->CloseOnDisk();
2362             }
2363           }
2364         }
2365         // close mesh group
2366         aTopGroup->CloseOnDisk();       
2367       }
2368     }
2369   }
2370   // close HDF file
2371   aFile->CloseOnDisk();
2372   delete aFile;
2373
2374   // Remove temporary files created from the stream
2375   if ( !isMultiFile ) 
2376     SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
2377
2378   INFOS( "SMESH_Gen_i::Load completed" );
2379   return true;
2380 }
2381
2382 //=============================================================================
2383 /*!
2384  *  SMESH_Gen_i::LoadASCII
2385  *
2386  *  Load SMESH module's data in ASCII format (not implemented yet)
2387  */
2388 //=============================================================================
2389
2390 bool SMESH_Gen_i::LoadASCII( SALOMEDS::SComponent_ptr theComponent,
2391                              const SALOMEDS::TMPFile& theStream,
2392                              const char*              theURL,
2393                              bool                     isMultiFile ) {
2394   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LoadASCII" );
2395   return Load( theComponent, theStream, theURL, isMultiFile );
2396 }
2397
2398 //=============================================================================
2399 /*!
2400  *  SMESH_Gen_i::Close
2401  *
2402  *  Clears study-connected data when it is closed
2403  */
2404 //=============================================================================
2405
2406 void SMESH_Gen_i::Close( SALOMEDS::SComponent_ptr theComponent )
2407 {
2408   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Close" );
2409
2410   // Clear study contexts data
2411   int studyId = GetCurrentStudyID();
2412   if ( myStudyContextMap.find( studyId ) != myStudyContextMap.end() ) {
2413     delete myStudyContextMap[ studyId ];
2414     myStudyContextMap.erase( studyId );
2415   }
2416   return;
2417 }
2418
2419 //=============================================================================
2420 /*!
2421  *  SMESH_Gen_i::ComponentDataType
2422  * 
2423  *  Get component data type
2424  */
2425 //=============================================================================
2426
2427 char* SMESH_Gen_i::ComponentDataType()
2428 {
2429   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::ComponentDataType" );
2430   return CORBA::string_dup( "SMESH" );
2431 }
2432
2433     
2434 //=============================================================================
2435 /*!
2436  *  SMESH_Gen_i::IORToLocalPersistentID
2437  *  
2438  *  Transform data from transient form to persistent
2439  */
2440 //=============================================================================
2441
2442 char* SMESH_Gen_i::IORToLocalPersistentID( SALOMEDS::SObject_ptr /*theSObject*/,
2443                                            const char*           IORString,
2444                                            CORBA::Boolean        /*isMultiFile*/,
2445                                            CORBA::Boolean        /*isASCII*/ )
2446 {
2447   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IORToLocalPersistentID" );
2448   StudyContext* myStudyContext = GetCurrentStudyContext();
2449   
2450   if ( myStudyContext && strcmp( IORString, "" ) != 0 ) {
2451     int anId = myStudyContext->findId( IORString );
2452     if ( anId ) {
2453       if(MYDEBUG) MESSAGE( "VSR " << anId )
2454       char strId[ 20 ];
2455       sprintf( strId, "%d", anId );
2456       return  CORBA::string_dup( strId );
2457     }
2458   }
2459   return CORBA::string_dup( "" );
2460 }
2461
2462 //=============================================================================
2463 /*!
2464  *  SMESH_Gen_i::LocalPersistentIDToIOR
2465  *
2466  *  Transform data from persistent form to transient
2467  */
2468 //=============================================================================
2469
2470 char* SMESH_Gen_i::LocalPersistentIDToIOR( SALOMEDS::SObject_ptr /*theSObject*/,
2471                                            const char*           aLocalPersistentID,
2472                                            CORBA::Boolean        /*isMultiFile*/,
2473                                            CORBA::Boolean        /*isASCII*/ )
2474 {
2475   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LocalPersistentIDToIOR(): id = " << aLocalPersistentID );
2476   StudyContext* myStudyContext = GetCurrentStudyContext();
2477
2478   if ( myStudyContext && strcmp( aLocalPersistentID, "" ) != 0 ) {
2479     int anId = atoi( aLocalPersistentID );
2480     return CORBA::string_dup( myStudyContext->getIORbyOldId( anId ).c_str() );
2481   }
2482   return CORBA::string_dup( "" );
2483 }
2484
2485 //=======================================================================
2486 //function : RegisterObject
2487 //purpose  : 
2488 //=======================================================================
2489
2490 int SMESH_Gen_i::RegisterObject(CORBA::Object_ptr theObject)
2491 {
2492   StudyContext* myStudyContext = GetCurrentStudyContext();
2493   if ( myStudyContext && !CORBA::is_nil( theObject )) {
2494     string iorString = GetORB()->object_to_string( theObject );
2495     return myStudyContext->addObject( iorString );
2496   }
2497   return 0;
2498 }
2499       
2500 //=============================================================================
2501 /*! 
2502  *  SMESHEngine_factory
2503  *
2504  *  C factory, accessible with dlsym, after dlopen  
2505  */
2506 //=============================================================================
2507
2508 extern "C"
2509 {
2510   PortableServer::ObjectId* SMESHEngine_factory( CORBA::ORB_ptr            orb,
2511                                                  PortableServer::POA_ptr   poa, 
2512                                                  PortableServer::ObjectId* contId,
2513                                                  const char*               instanceName, 
2514                                                  const char*               interfaceName )
2515   {
2516     if(MYDEBUG) MESSAGE( "PortableServer::ObjectId* SMESHEngine_factory()" );
2517     if(MYDEBUG) SCRUTE(interfaceName);
2518     SMESH_Gen_i* aSMESHGen = new SMESH_Gen_i(orb, poa, contId, instanceName, interfaceName);
2519     return aSMESHGen->getId() ;
2520   }
2521 }