Salome HOME
Add methods to select mesh elements from python.
[modules/smesh.git] / src / SMESH_I / SMESH_Gen_i.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : SMESH_Gen_i.cxx
23 //  Author : Paul RASCLE, EDF
24 //  Module : SMESH
25
26 #include <TopExp.hxx>
27 #include <TopExp_Explorer.hxx>
28 #include <TopoDS.hxx>
29 #include <TopoDS_Iterator.hxx>
30 #include <TopoDS_Compound.hxx>
31 #include <TopoDS_CompSolid.hxx>
32 #include <TopoDS_Solid.hxx>
33 #include <TopoDS_Shell.hxx>
34 #include <TopoDS_Face.hxx>
35 #include <TopoDS_Wire.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Vertex.hxx>
38 #include <TopoDS_Shape.hxx>
39 #include <TopTools_MapOfShape.hxx>
40 #include <TopTools_IndexedMapOfShape.hxx>
41 #include <TopTools_ListOfShape.hxx>
42 #include <TopTools_ListIteratorOfListOfShape.hxx>
43 #include <gp_Pnt.hxx>
44 #include <BRep_Tool.hxx>
45 #include <TCollection_AsciiString.hxx>
46 #include <OSD.hxx>
47 #include <BRepPrimAPI_MakeSphere.hxx>
48 #include <BRepPrimAPI_MakeCylinder.hxx>
49 #include <BRepPrimAPI_MakeBox.hxx>
50
51
52 #ifdef WIN32
53  #include <windows.h>
54  #include <process.h>
55 #else
56  #include <dlfcn.h>
57 #endif
58
59 #ifdef WIN32
60  #define LibHandle HMODULE
61  #define LoadLib( name ) LoadLibrary( name )
62  #define GetProc GetProcAddress
63  #define UnLoadLib( handle ) FreeLibrary( handle );
64 #else
65  #define LibHandle void*
66  #define LoadLib( name ) dlopen( name, RTLD_LAZY )
67  #define GetProc dlsym
68  #define UnLoadLib( handle ) dlclose( handle );
69 #endif
70
71 #include "SMESH_Gen_i.hxx"
72 #include "SMESH_version.h"
73
74 #include "DriverMED_W_SMESHDS_Mesh.h"
75 #include "DriverMED_R_SMESHDS_Mesh.h"
76 #ifdef WITH_CGNS
77 #include "DriverCGNS_Read.hxx"
78 #endif
79 #include "MED_Factory.hxx"
80 #include "SMDS_EdgePosition.hxx"
81 #include "SMDS_FacePosition.hxx"
82 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
83 #include "SMDS_SetIterator.hxx"
84 #include "SMDS_SpacePosition.hxx"
85 #include "SMDS_VertexPosition.hxx"
86 #include "SMESHDS_Document.hxx"
87 #include "SMESHDS_Group.hxx"
88 #include "SMESHDS_GroupOnGeom.hxx"
89 #include "SMESH_Algo_i.hxx"
90 #include "SMESH_File.hxx"
91 #include "SMESH_Group.hxx"
92 #include "SMESH_Group_i.hxx"
93 #include "SMESH_Hypothesis.hxx"
94 #include "SMESH_Hypothesis_i.hxx"
95 #include "SMESH_Mesh.hxx"
96 #include "SMESH_MeshEditor.hxx"
97 #include "SMESH_Mesh_i.hxx"
98 #include "SMESH_PreMeshInfo.hxx"
99 #include "SMESH_PythonDump.hxx"
100 #include "SMESH_ControlsDef.hxx"
101 #include "SMESH_TryCatch.hxx" // to include after OCC headers!
102
103 #include CORBA_SERVER_HEADER(SMESH_Group)
104 #include CORBA_SERVER_HEADER(SMESH_Filter)
105 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
106
107
108 #include <GEOM_Client.hxx>
109
110 #include <Basics_Utils.hxx>
111 #include <Basics_DirUtils.hxx>
112 #include <HDFOI.hxx>
113 #include <OpUtil.hxx>
114 #include <SALOMEDS_Tool.hxx>
115 #include <SALOME_Container_i.hxx>
116 #include <SALOME_DataContainer_i.hxx>
117 #include <SALOME_LifeCycleCORBA.hxx>
118 #include <SALOME_NamingService.hxx>
119 #include <Utils_CorbaException.hxx>
120 #include <Utils_ExceptHandlers.hxx>
121 #include <Utils_SINGLETON.hxx>
122 #include <utilities.h>
123
124 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
125 #include CORBA_CLIENT_HEADER(SALOME_Session)
126
127 // helpers about SALOME::GenericObj
128 #include <SALOMEDS_wrap.hxx>
129 #include <SALOMEDS_Attributes_wrap.hxx>
130 #include <GEOM_wrap.hxx>
131
132 #include <map>
133 #include <fstream>
134 #include <cstdio>
135 #include <cstdlib>
136
137 using namespace std;
138 using SMESH::TPythonDump;
139 using SMESH::TVar;
140
141 #define NUM_TMP_FILES 2
142
143 #ifdef _DEBUG_
144 static int MYDEBUG = 0;
145 #else
146 static int MYDEBUG = 0;
147 #endif
148
149 // Static variables definition
150 GEOM::GEOM_Gen_var      SMESH_Gen_i::myGeomGen = GEOM::GEOM_Gen::_nil();
151 CORBA::ORB_var          SMESH_Gen_i::myOrb;
152 PortableServer::POA_var SMESH_Gen_i::myPoa;
153 SALOME_NamingService*   SMESH_Gen_i::myNS  = NULL;
154 SALOME_LifeCycleCORBA*  SMESH_Gen_i::myLCC = NULL;
155 SMESH_Gen_i*            SMESH_Gen_i::mySMESHGen = NULL;
156
157
158 const int nbElemPerDiagonal = 10;
159
160 //=============================================================================
161 /*!
162  *  GetServant [ static ]
163  *
164  *  Get servant of the CORBA object
165  */
166 //=============================================================================
167
168 PortableServer::ServantBase_var SMESH_Gen_i::GetServant( CORBA::Object_ptr theObject )
169 {
170   if( CORBA::is_nil( theObject ) || CORBA::is_nil( GetPOA() ) )
171     return NULL;
172   try {
173     PortableServer::Servant aServant = GetPOA()->reference_to_servant( theObject );
174     return aServant;
175   }
176   catch (...) {
177     INFOS( "GetServant - Unknown exception was caught!!!" );
178     return NULL;
179   }
180 }
181
182 //=============================================================================
183 /*!
184  *  SObjectToObject [ static ]
185  *
186  *  Get CORBA object corresponding to the SALOMEDS::SObject
187  */
188 //=============================================================================
189
190 CORBA::Object_var SMESH_Gen_i::SObjectToObject( SALOMEDS::SObject_ptr theSObject )
191 {
192   SALOMEDS::GenericAttribute_wrap anAttr;
193   CORBA::Object_var anObj;
194   if ( !theSObject->_is_nil() ) {
195     try {
196       if( theSObject->FindAttribute( anAttr.inout(), "AttributeIOR" ) ) {
197         SALOMEDS::AttributeIOR_wrap anIOR  = anAttr;
198         CORBA::String_var aValue = anIOR->Value();
199         if( strcmp( aValue, "" ) != 0 )
200           anObj = GetORB()->string_to_object( aValue );
201       }
202     }
203     catch( ... ) {
204       INFOS( "SObjectToObject - Unknown exception was caught!!!" );
205     }
206   }
207   return anObj;
208 }
209
210 //=============================================================================
211 /*!
212  *  GetNS [ static ]
213  *
214  *  Get SALOME_NamingService object
215  */
216 //=============================================================================
217
218 SALOME_NamingService* SMESH_Gen_i::GetNS()
219 {
220   if ( myNS == NULL ) {
221     myNS = SINGLETON_<SALOME_NamingService>::Instance();
222     ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting());
223     myNS->init_orb( GetORB() );
224   }
225   return myNS;
226 }
227
228 //=============================================================================
229 /*!
230  *  GetLCC [ static ]
231  *
232  *  Get SALOME_LifeCycleCORBA object
233  */
234 //=============================================================================
235 SALOME_LifeCycleCORBA*  SMESH_Gen_i::GetLCC() {
236   if ( myLCC == NULL ) {
237     myLCC = new SALOME_LifeCycleCORBA( GetNS() );
238   }
239   return myLCC;
240 }
241
242
243 //=============================================================================
244 /*!
245  *  GetGeomEngine [ static ]
246  *
247  *  Get GEOM::GEOM_Gen reference
248  */
249 //=============================================================================
250 GEOM::GEOM_Gen_var SMESH_Gen_i::GetGeomEngine() {
251   //CCRT GEOM::GEOM_Gen_var aGeomEngine =
252   //CCRT   GEOM::GEOM_Gen::_narrow( GetLCC()->FindOrLoad_Component("FactoryServer","GEOM") );
253   //CCRT return aGeomEngine._retn();
254   if(CORBA::is_nil(myGeomGen))
255   {
256     Engines::EngineComponent_ptr temp=GetLCC()->FindOrLoad_Component("FactoryServer","GEOM");
257     myGeomGen=GEOM::GEOM_Gen::_narrow(temp);
258   }
259   return myGeomGen;
260 }
261
262 //=============================================================================
263 /*!
264  *  SMESH_Gen_i::SMESH_Gen_i
265  *
266  *  Default constructor: not for use
267  */
268 //=============================================================================
269
270 SMESH_Gen_i::SMESH_Gen_i()
271 {
272   INFOS( "SMESH_Gen_i::SMESH_Gen_i : default constructor" );
273 }
274
275 //=============================================================================
276 /*!
277  *  SMESH_Gen_i::SMESH_Gen_i
278  *
279  *  Standard constructor, used with Container
280  */
281 //=============================================================================
282
283 SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr            orb,
284                           PortableServer::POA_ptr   poa,
285                           PortableServer::ObjectId* contId,
286                           const char*               instanceName,
287                           const char*               interfaceName )
288   : Engines_Component_i( orb, poa, contId, instanceName, interfaceName )
289 {
290   MESSAGE( "SMESH_Gen_i::SMESH_Gen_i : standard constructor" );
291
292   myOrb = CORBA::ORB::_duplicate(orb);
293   myPoa = PortableServer::POA::_duplicate(poa);
294
295   _thisObj = this ;
296   _id = myPoa->activate_object( _thisObj );
297
298   myIsEmbeddedMode = false;
299   myShapeReader = NULL;  // shape reader
300   mySMESHGen = this;
301   myIsHistoricalPythonDump = true;
302   myToForgetMeshDataOnHypModif = false;
303
304   myImportedStudyChanged = true;
305   myImportedStudyId      = 0;
306
307   // set it in standalone mode only
308   //OSD::SetSignal( true );
309
310   // 0020605: EDF 1190 SMESH: Display performance. 80 seconds for 52000 cells.
311   // find out mode (embedded or standalone) here else
312   // meshes created before calling SMESH_Client::GetSMESHGen(), which calls
313   // SMESH_Gen_i::SetEmbeddedMode(), have wrong IsEmbeddedMode flag
314   if ( SALOME_NamingService* ns = GetNS() )
315   {
316     CORBA::Object_var obj = ns->Resolve( "/Kernel/Session" );
317     SALOME::Session_var session = SALOME::Session::_narrow( obj ) ;
318     if ( !session->_is_nil() )
319     {
320       CORBA::String_var str_host = session->getHostname();
321       CORBA::Long        s_pid = session->getPID();
322       string my_host = Kernel_Utils::GetHostname();
323 #ifdef WIN32
324       long    my_pid = (long)_getpid();
325 #else
326       long    my_pid = (long) getpid();
327 #endif
328       SetEmbeddedMode( s_pid == my_pid && my_host == str_host.in() );
329     }
330   }
331 }
332
333 //=============================================================================
334 /*!
335  *  SMESH_Gen_i::~SMESH_Gen_i
336  *
337  *  Destructor
338  */
339 //=============================================================================
340
341 SMESH_Gen_i::~SMESH_Gen_i()
342 {
343   MESSAGE( "SMESH_Gen_i::~SMESH_Gen_i" );
344
345   // delete hypothesis creators
346   map<string, GenericHypothesisCreator_i*>::iterator itHyp;
347   for (itHyp = myHypCreatorMap.begin(); itHyp != myHypCreatorMap.end(); itHyp++)
348   {
349     delete (*itHyp).second;
350   }
351   myHypCreatorMap.clear();
352
353   // Clear study contexts data
354   map<int, StudyContext*>::iterator it;
355   for ( it = myStudyContextMap.begin(); it != myStudyContextMap.end(); ++it ) {
356     delete it->second;
357   }
358   myStudyContextMap.clear();
359   // delete shape reader
360   if ( myShapeReader )
361     delete myShapeReader;
362 }
363 //=============================================================================
364 /*!
365  *  SMESH_Gen_i::getHypothesisCreator
366  *
367  *  Get hypothesis creator
368  */
369 //=============================================================================
370 GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHypName,
371                                                               const char* theLibName,
372                                                               std::string& thePlatformLibName)
373   throw (SALOME::SALOME_Exception)
374 {
375   std::string aPlatformLibName;
376   /* It's Need to tranlate lib name for WIN32 or X platform */
377   if ( theLibName && theLibName[0] != '\0'  )
378   {
379     int libNameLen = strlen(theLibName);
380     //check for old format "libXXXXXXX.so"
381     if (libNameLen > 7 &&
382         !strncmp( theLibName, "lib", 3 ) &&
383         !strcmp( theLibName+libNameLen-3, ".so" ))
384     {
385       //the old format
386 #ifdef WIN32
387       aPlatformLibName = std::string( theLibName+3, libNameLen-6 ) + ".dll";
388 #else
389       aPlatformLibName = theLibName;
390 #endif
391     }
392     else
393     {
394       //try to use new format
395 #ifdef WIN32
396       aPlatformLibName = theLibName;
397       aPlatformLibName += ".dll";
398 #else
399       aPlatformLibName = "lib" + std::string( theLibName ) + ".so";
400 #endif
401     }
402   }
403   thePlatformLibName = aPlatformLibName;
404
405   Unexpect aCatch(SALOME_SalomeException);
406   if(MYDEBUG) MESSAGE( "Create Hypothesis <" << theHypName << "> from " << aPlatformLibName);
407
408   typedef GenericHypothesisCreator_i* (*GetHypothesisCreator)(const char* );
409   GenericHypothesisCreator_i* aCreator;
410   try
411   {
412     // check, if creator for this hypothesis type already exists
413     if (myHypCreatorMap.find(string(theHypName)) == myHypCreatorMap.end())
414     {
415       // load plugin library
416       if(MYDEBUG) MESSAGE("Loading server meshers plugin library ...");
417       LibHandle libHandle = LoadLib( aPlatformLibName.c_str() );
418       if (!libHandle)
419       {
420         // report any error, if occured
421 #ifndef WIN32
422         const char* anError = dlerror();
423         throw(SALOME_Exception(anError));
424 #else
425         throw(SALOME_Exception(LOCALIZED( "Can't load server meshers plugin library" )));
426 #endif
427       }
428
429       // get method, returning hypothesis creator
430       if(MYDEBUG) MESSAGE("Find GetHypothesisCreator() method ...");
431       GetHypothesisCreator procHandle =
432         (GetHypothesisCreator)GetProc( libHandle, "GetHypothesisCreator" );
433       if (!procHandle)
434       {
435         throw(SALOME_Exception(LOCALIZED("bad hypothesis plugin library")));
436         UnLoadLib(libHandle);
437       }
438
439       // get hypothesis creator
440       if(MYDEBUG) MESSAGE("Get Hypothesis Creator for " << theHypName);
441       aCreator = procHandle(theHypName);
442       if (!aCreator)
443       {
444         throw(SALOME_Exception(LOCALIZED("no such a hypothesis in this plugin")));
445       }
446       // map hypothesis creator to a hypothesis name
447       myHypCreatorMap[string(theHypName)] = aCreator;
448       return aCreator;
449     }
450     else
451     {
452       return myHypCreatorMap[string(theHypName)];
453     }
454   }
455   catch (SALOME_Exception& S_ex)
456   {
457     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
458   }
459   return aCreator;
460 }
461
462 //=============================================================================
463 /*!
464  *  SMESH_Gen_i::createHypothesis
465  *
466  *  Create hypothesis of given type
467  */
468 //=============================================================================
469 SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName,
470                                                           const char* theLibName)
471 {
472   SMESH_Hypothesis_i* myHypothesis_i = 0;
473   SMESH::SMESH_Hypothesis_var hypothesis_i;
474   std::string aPlatformLibName;
475   GenericHypothesisCreator_i* aCreator =
476     getHypothesisCreator(theHypName, theLibName, aPlatformLibName);
477
478   // create a new hypothesis object, store its ref. in studyContext
479   myHypothesis_i = aCreator->Create(myPoa, GetCurrentStudyID(), &myGen);
480   if (myHypothesis_i)
481   {
482     myHypothesis_i->SetLibName( aPlatformLibName.c_str() ); // for persistency assurance
483     CORBA::String_var hypName = myHypothesis_i->GetName();
484     myHypCreatorMap[ hypName.in() ] = aCreator;
485
486     // activate the CORBA servant of hypothesis
487     hypothesis_i = myHypothesis_i->_this();
488     int nextId = RegisterObject( hypothesis_i );
489     if(MYDEBUG) { MESSAGE( "Add hypo to map with id = "<< nextId ); }
490     else        { nextId = 0; } // avoid "unused variable" warning in release mode
491   }
492   return hypothesis_i._retn();
493 }
494
495 //=============================================================================
496 /*!
497  *  SMESH_Gen_i::createMesh
498  *
499  *  Create empty mesh on shape
500  */
501 //=============================================================================
502 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh()
503   throw ( SALOME::SALOME_Exception )
504 {
505   Unexpect aCatch(SALOME_SalomeException);
506   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::createMesh" );
507
508   // Get or create the GEOM_Client instance
509   try {
510     // create a new mesh object servant, store it in a map in study context
511     SMESH_Mesh_i* meshServant = new SMESH_Mesh_i( GetPOA(), this, GetCurrentStudyID() );
512     // create a new mesh object
513     MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode);
514     meshServant->SetImpl( myGen.CreateMesh( GetCurrentStudyID(), myIsEmbeddedMode ));
515
516     // activate the CORBA servant of Mesh
517     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( meshServant->_this() );
518     int nextId = RegisterObject( mesh );
519     if(MYDEBUG) { MESSAGE( "Add mesh to map with id = "<< nextId); }
520     else        { nextId = 0; } // avoid "unused variable" warning in release mode
521     return mesh._retn();
522   }
523   catch (SALOME_Exception& S_ex) {
524     THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
525   }
526   return SMESH::SMESH_Mesh::_nil();
527 }
528
529 //=============================================================================
530 /*!
531  *  SMESH_Gen_i::GetShapeReader
532  *
533  *  Get shape reader
534  */
535 //=============================================================================
536 GEOM_Client* SMESH_Gen_i::GetShapeReader()
537 {
538   // create shape reader if necessary
539   if ( !myShapeReader )
540     myShapeReader = new GEOM_Client(GetContainerRef());
541   ASSERT( myShapeReader );
542   return myShapeReader;
543 }
544
545 //=============================================================================
546 /*!
547  *  SMESH_Gen_i::SetGeomEngine
548  *
549  *  Set GEOM::GEOM_Gen reference
550  */
551 //=============================================================================
552 //GEOM::GEOM_Gen_ptr SMESH_Gen_i::SetGeomEngine( const char* containerLoc )
553 void SMESH_Gen_i::SetGeomEngine( GEOM::GEOM_Gen_ptr geomcompo )
554 {
555   //Engines::Component_ptr temp=GetLCC()->FindOrLoad_Component(containerLoc,"GEOM");
556   //myGeomGen=GEOM::GEOM_Gen::_narrow(temp);
557   myGeomGen=GEOM::GEOM_Gen::_duplicate(geomcompo);
558   //return myGeomGen;
559 }
560
561 //=============================================================================
562 /*!
563  *  SMESH_Gen_i::SetEmbeddedMode
564  *
565  *  Set current mode
566  */
567 //=============================================================================
568
569 void SMESH_Gen_i::SetEmbeddedMode( CORBA::Boolean theMode )
570 {
571   myIsEmbeddedMode = theMode;
572   MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode);
573
574   if ( !myIsEmbeddedMode ) {
575     //PAL10867: disable signals catching with "noexcepthandler" option
576     char* envNoCatchSignals = getenv("NOT_INTERCEPT_SIGNALS");
577     if (!envNoCatchSignals || !atoi(envNoCatchSignals))
578     {
579       bool raiseFPE;
580 #ifdef _DEBUG_
581       raiseFPE = true;
582       char* envDisableFPE = getenv("DISABLE_FPE");
583       if (envDisableFPE && atoi(envDisableFPE))
584         raiseFPE = false;
585 #else
586       raiseFPE = false;
587 #endif
588       OSD::SetSignal( raiseFPE );
589     }
590     // else OSD::SetSignal() is called in GUI
591   }
592 }
593
594 //=============================================================================
595 /*!
596  *  SMESH_Gen_i::IsEmbeddedMode
597  *
598  *  Get current mode
599  */
600 //=============================================================================
601
602 CORBA::Boolean SMESH_Gen_i::IsEmbeddedMode()
603 {
604   return myIsEmbeddedMode;
605 }
606
607 //=============================================================================
608 /*!
609  *  SMESH_Gen_i::SetCurrentStudy
610  *
611  *  Set current study
612  */
613 //=============================================================================
614
615 void SMESH_Gen_i::SetCurrentStudy( SALOMEDS::Study_ptr theStudy )
616 {
617   setCurrentStudy( theStudy );
618 }
619
620 void SMESH_Gen_i::setCurrentStudy( SALOMEDS::Study_ptr theStudy,
621                                    bool                theStudyIsBeingClosed)
622 {
623   int curStudyId = GetCurrentStudyID();
624   myCurrentStudy = SALOMEDS::Study::_duplicate( theStudy );
625   // create study context, if it doesn't exist and set current study
626   int studyId = GetCurrentStudyID();
627   if ( myStudyContextMap.find( studyId ) == myStudyContextMap.end() )
628     myStudyContextMap[ studyId ] = new StudyContext;
629
630   // myCurrentStudy may be nil
631   if ( !theStudyIsBeingClosed && !CORBA::is_nil( myCurrentStudy ) ) {
632     SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
633     SALOMEDS::SComponent_wrap GEOM_var = myCurrentStudy->FindComponent( "GEOM" );
634     if( !GEOM_var->_is_nil() )
635       aStudyBuilder->LoadWith( GEOM_var, GetGeomEngine() );
636     // NPAL16168, issue 0020210
637     // Let meshes update their data depending on GEOM groups that could change
638     if ( curStudyId != studyId )
639     {
640       CORBA::String_var compDataType = ComponentDataType();
641       SALOMEDS::SComponent_wrap me = myCurrentStudy->FindComponent( compDataType.in() );
642       if ( !me->_is_nil() ) {
643         SALOMEDS::ChildIterator_wrap anIter = myCurrentStudy->NewChildIterator( me );
644         for ( ; anIter->More(); anIter->Next() ) {
645           SALOMEDS::SObject_wrap so = anIter->Value();
646           CORBA::Object_var     ior = SObjectToObject( so );
647           if ( SMESH_Mesh_i*   mesh = SMESH::DownCast<SMESH_Mesh_i*>( ior ))
648             mesh->CheckGeomModif();
649         }
650       }
651     }
652   }
653 }
654
655 //=============================================================================
656 /*!
657  *  SMESH_Gen_i::GetCurrentStudy
658  *
659  *  Get current study
660  */
661 //=============================================================================
662
663 SALOMEDS::Study_ptr SMESH_Gen_i::GetCurrentStudy()
664 {
665   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetCurrentStudy: study Id = " << GetCurrentStudyID() );
666   if ( GetCurrentStudyID() < 0 )
667     return SALOMEDS::Study::_nil();
668   return SALOMEDS::Study::_duplicate( myCurrentStudy );
669 }
670
671 //=============================================================================
672 /*!
673  *  SMESH_Gen_i::GetCurrentStudyContext
674  *
675  *  Get current study context
676  */
677 //=============================================================================
678 StudyContext* SMESH_Gen_i::GetCurrentStudyContext()
679 {
680   if ( !CORBA::is_nil( myCurrentStudy ) &&
681        myStudyContextMap.find( GetCurrentStudyID() ) != myStudyContextMap.end() )
682     return myStudyContextMap[ myCurrentStudy->StudyId() ];
683   else
684     return 0;
685 }
686
687 //=============================================================================
688 /*!
689  *  SMESH_Gen_i::CreateHypothesis
690  *
691  *  Create hypothesis/algorothm of given type and publish it in the study
692  */
693 //=============================================================================
694
695 SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypName,
696                                                            const char* theLibName )
697   throw ( SALOME::SALOME_Exception )
698 {
699   Unexpect aCatch(SALOME_SalomeException);
700   // Create hypothesis/algorithm
701   SMESH::SMESH_Hypothesis_var hyp = this->createHypothesis( theHypName, theLibName );
702
703   // Publish hypothesis/algorithm in the study
704   if ( CanPublishInStudy( hyp ) ) {
705     SALOMEDS::SObject_wrap aSO = PublishHypothesis( myCurrentStudy, hyp );
706     if ( !aSO->_is_nil() ) {
707       // Update Python script
708       TPythonDump() << aSO << " = " << this << ".CreateHypothesis('"
709                     << theHypName << "', '" << theLibName << "')";
710     }
711   }
712
713   return hyp._retn();
714 }
715
716 //================================================================================
717 /*!
718  * \brief Return a hypothesis holding parameter values corresponding either to the mesh
719  * existing on the given geometry or to size of the geometry.
720  *  \param theHypType - hypothesis type name
721  *  \param theLibName - plugin library name
722  *  \param theMesh - The mesh of interest
723  *  \param theGeom - The shape to get parameter values from
724  *  \retval SMESH::SMESH_Hypothesis_ptr - The returned hypothesis may be the one existing
725  *     in a study and used to compute the mesh, or a temporary one created just to pass
726  *     parameter values
727  */
728 //================================================================================
729
730 SMESH::SMESH_Hypothesis_ptr
731 SMESH_Gen_i::GetHypothesisParameterValues (const char*           theHypType,
732                                            const char*           theLibName,
733                                            SMESH::SMESH_Mesh_ptr theMesh,
734                                            GEOM::GEOM_Object_ptr theGeom,
735                                            CORBA::Boolean        byMesh)
736   throw ( SALOME::SALOME_Exception )
737 {
738   Unexpect aCatch(SALOME_SalomeException);
739   if ( byMesh && CORBA::is_nil( theMesh ) )
740     return SMESH::SMESH_Hypothesis::_nil();
741   if ( byMesh && CORBA::is_nil( theGeom ) )
742     return SMESH::SMESH_Hypothesis::_nil();
743
744   // -----------------------------------------------
745   // find hypothesis used to mesh theGeom
746   // -----------------------------------------------
747
748   // get mesh and shape
749   SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
750   TopoDS_Shape shape = GeomObjectToShape( theGeom );
751   if ( byMesh && ( !meshServant || meshServant->NbNodes()==0 || shape.IsNull() ))
752     return SMESH::SMESH_Hypothesis::_nil();
753   ::SMESH_Mesh* mesh = meshServant ? &meshServant->GetImpl() : (::SMESH_Mesh*)0;
754
755   // create a temporary hypothesis to know its dimension
756   SMESH::SMESH_Hypothesis_var tmpHyp = this->createHypothesis( theHypType, theLibName );
757   SMESH_Hypothesis_i* hypServant = SMESH::DownCast<SMESH_Hypothesis_i*>( tmpHyp );
758   if ( !hypServant )
759     return SMESH::SMESH_Hypothesis::_nil();
760   ::SMESH_Hypothesis* hyp = hypServant->GetImpl();
761
762   if ( byMesh ) {
763     // look for a hypothesis of theHypType used to mesh the shape
764     if ( myGen.GetShapeDim( shape ) == hyp->GetDim() )
765     {
766       // check local shape
767       SMESH::ListOfHypothesis_var aHypList = theMesh->GetHypothesisList( theGeom );
768       int nbLocalHyps = aHypList->length();
769       for ( int i = 0; i < nbLocalHyps; i++ ) {
770         CORBA::String_var hypName = aHypList[i]->GetName();
771         if ( strcmp( theHypType, hypName.in() ) == 0 ) // FOUND local!
772           return SMESH::SMESH_Hypothesis::_duplicate( aHypList[i] );
773       }
774       // check super shapes
775       TopTools_ListIteratorOfListOfShape itShape( mesh->GetAncestors( shape ));
776       while ( nbLocalHyps == 0 && itShape.More() ) {
777         GEOM::GEOM_Object_ptr geomObj = ShapeToGeomObject( itShape.Value() );
778         if ( ! CORBA::is_nil( geomObj )) {
779           SMESH::ListOfHypothesis_var aHypList = theMesh->GetHypothesisList( geomObj );
780           nbLocalHyps = aHypList->length();
781           for ( int i = 0; i < nbLocalHyps; i++ )
782             if ( strcmp( theHypType, aHypList[i]->GetName() ) == 0 ) // FOUND global!
783               return SMESH::SMESH_Hypothesis::_duplicate( aHypList[i] );
784         }
785         itShape.Next();
786       }
787     }
788
789     // let the temporary hypothesis find out somehow parameter values by mesh
790     if ( hyp->SetParametersByMesh( mesh, shape ))
791       return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
792   }
793   else {
794     double diagonal = 0;
795     if ( mesh )
796       diagonal = mesh->GetShapeDiagonalSize();
797     else
798       diagonal = ::SMESH_Mesh::GetShapeDiagonalSize( shape );
799     ::SMESH_Hypothesis::TDefaults dflts;
800     dflts._elemLength = diagonal / myGen.GetBoundaryBoxSegmentation();
801     dflts._nbSegments = myGen.GetDefaultNbSegments();
802     dflts._shape      = &shape;
803     // let the temporary hypothesis initialize it's values
804     if ( hyp->SetParametersByDefaults( dflts, mesh ))
805       return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
806   }
807
808   return SMESH::SMESH_Hypothesis::_nil();
809 }
810
811 //=============================================================================
812 /*!
813  * Returns \c True if a hypothesis is assigned to a sole sub-mesh in a current Study
814  *  \param [in] theHyp - the hypothesis of interest
815  *  \param [out] theMesh - the sole mesh using \a theHyp
816  *  \param [out] theShape - the sole geometry \a theHyp is assigned to
817  *  \return boolean - \c True if \a theMesh and \a theShape are sole using \a theHyp
818  *
819  * If two meshes on same shape have theHyp assigned to the same sub-shape, they are
820  * considered as SAME sub-mesh => result is \c true.
821  * This method ids used to initialize SMESHGUI_GenericHypothesisCreator with
822  * a shape to which an hyp being edited is assigned.
823  */
824 //=============================================================================
825
826 CORBA::Boolean SMESH_Gen_i::GetSoleSubMeshUsingHyp( SMESH::SMESH_Hypothesis_ptr theHyp,
827                                                     SMESH::SMESH_Mesh_out       theMesh,
828                                                     GEOM::GEOM_Object_out       theShape)
829 {
830   if ( GetCurrentStudyID() < 0 || CORBA::is_nil( theHyp ))
831     return false;
832
833   // get Mesh component SO
834   CORBA::String_var compDataType = ComponentDataType();
835   SALOMEDS::SComponent_wrap comp = myCurrentStudy->FindComponent( compDataType.in() );
836   if ( CORBA::is_nil( comp ))
837     return false;
838
839   // look for child SO of meshes
840   SMESH::SMESH_Mesh_var foundMesh;
841   TopoDS_Shape          foundShape;
842   bool                  isSole = true;
843   SALOMEDS::ChildIterator_wrap meshIter = myCurrentStudy->NewChildIterator( comp );
844   for ( ; meshIter->More() && isSole; meshIter->Next() )
845   {
846     SALOMEDS::SObject_wrap curSO = meshIter->Value();
847     CORBA::Object_var        obj = SObjectToObject( curSO );
848     SMESH_Mesh_i*         mesh_i = SMESH::DownCast< SMESH_Mesh_i* >( obj );
849     if ( ! mesh_i )
850       continue;
851
852     // look for a sole shape where theHyp is assigned
853     bool isHypFound = false;
854     const ShapeToHypothesis & s2hyps = mesh_i->GetImpl().GetMeshDS()->GetHypotheses();
855     ShapeToHypothesis::Iterator s2hypsIt( s2hyps );
856     for ( ; s2hypsIt.More() && isSole; s2hypsIt.Next() )
857     {
858       const THypList& hyps = s2hypsIt.Value();
859       THypList::const_iterator h = hyps.begin();
860       for ( ; h != hyps.end(); ++h )
861         if ( (*h)->GetID() == theHyp->GetId() )
862           break;
863       if ( h != hyps.end()) // theHyp found
864       {
865         isHypFound = true;
866         if ( ! foundShape.IsNull() &&
867              ! foundShape.IsSame( s2hypsIt.Key() )) // not a sole sub-shape
868         {
869           foundShape.Nullify();
870           isSole = false;
871           break;
872         }
873         foundShape = s2hypsIt.Key();
874       }
875     } // loop on assigned hyps
876
877     if ( isHypFound && !foundShape.IsNull() ) // a mesh using theHyp is found
878     {
879       if ( !foundMesh->_is_nil() ) // not a sole mesh
880       {
881         GEOM::GEOM_Object_var s1 = mesh_i   ->GetShapeToMesh();
882         GEOM::GEOM_Object_var s2 = foundMesh->GetShapeToMesh();
883         if ( ! ( isSole = s1->IsSame( s2 )))
884           break;
885       }
886       foundMesh = SMESH::SMESH_Mesh::_narrow( obj );
887     }
888
889   } // loop on meshes
890
891   if ( isSole &&
892        ! foundMesh->_is_nil() &&
893        ! foundShape.IsNull() )
894   {
895     theMesh  = foundMesh._retn();
896     theShape = ShapeToGeomObject( foundShape );
897     return ( !theMesh->_is_nil() && !theShape->_is_nil() );
898   }
899   return false;
900 }
901
902 //=============================================================================
903 /*!
904  * Sets number of segments per diagonal of boundary box of geometry by which
905  * default segment length of appropriate 1D hypotheses is defined
906  */
907 //=============================================================================
908
909 void SMESH_Gen_i::SetBoundaryBoxSegmentation( CORBA::Long theNbSegments )
910   throw ( SALOME::SALOME_Exception )
911 {
912   if ( theNbSegments > 0 )
913     myGen.SetBoundaryBoxSegmentation( int( theNbSegments ));
914   else
915     THROW_SALOME_CORBA_EXCEPTION( "non-positive number of segments", SALOME::BAD_PARAM );
916 }
917 //=============================================================================
918   /*!
919    * \brief Sets default number of segments per edge
920    */
921 //=============================================================================
922 void SMESH_Gen_i::SetDefaultNbSegments(CORBA::Long theNbSegments)
923   throw ( SALOME::SALOME_Exception )
924 {
925   if ( theNbSegments > 0 )
926     myGen.SetDefaultNbSegments( int(theNbSegments) );
927   else
928     THROW_SALOME_CORBA_EXCEPTION( "non-positive number of segments", SALOME::BAD_PARAM );
929 }
930
931 //=============================================================================
932 /*!
933   Set an option value
934 */
935 //=============================================================================
936
937 void SMESH_Gen_i::SetOption(const char* name, const char* value)
938 {
939   if ( name && value && strlen( value ) > 0 )
940   {
941     string msgToGUI; 
942     if ( strcmp(name, "historical_python_dump") == 0 )
943     {
944       myIsHistoricalPythonDump = ( value[0] == '1' || toupper(value[0]) == 'T' ); // 1 || true
945       msgToGUI = "preferences/SMESH/historical_python_dump/";
946       msgToGUI += myIsHistoricalPythonDump ? "true" : "false";
947     }
948     else if ( strcmp(name, "forget_mesh_on_hyp_modif") == 0 )
949     {
950       myToForgetMeshDataOnHypModif = ( value[0] == '1' || toupper(value[0]) == 'T' ); // 1 || true
951       msgToGUI = "preferences/SMESH/forget_mesh_on_hyp_modif/";
952       msgToGUI += myToForgetMeshDataOnHypModif ? "true" : "false";
953     }
954
955     // update preferences in case if SetOption() is invoked from python console
956     if ( !msgToGUI.empty() )
957     {
958       CORBA::Object_var obj = SMESH_Gen_i::GetNS()->Resolve( "/Kernel/Session" );
959       SALOME::Session_var session = SALOME::Session::_narrow( obj );
960       if ( !CORBA::is_nil( session ) )
961         session->emitMessageOneWay(msgToGUI.c_str());
962     }
963   }
964 }
965
966 //=============================================================================
967 /*!
968   Return an option value
969 */
970 //=============================================================================
971
972 char* SMESH_Gen_i::GetOption(const char* name)
973 {
974   if ( name )
975   {
976     if ( strcmp(name, "historical_python_dump") == 0 )
977     {
978       return CORBA::string_dup( myIsHistoricalPythonDump ? "true" : "false" );
979     }
980     if ( strcmp(name, "forget_mesh_on_hyp_modif") == 0 )
981     {
982       return CORBA::string_dup( myToForgetMeshDataOnHypModif ? "true" : "false" );
983     }
984   }
985   return CORBA::string_dup( "" );
986 }
987
988 //=============================================================================
989 /*!
990  *  SMESH_Gen_i::CreateMesh
991  *
992  *  Create empty mesh on a shape and publish it in the study
993  */
994 //=============================================================================
995
996 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObject )
997      throw ( SALOME::SALOME_Exception )
998 {
999   Unexpect aCatch(SALOME_SalomeException);
1000   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMesh" );
1001   // create mesh
1002   SMESH::SMESH_Mesh_var mesh = this->createMesh();
1003   // set shape
1004   SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
1005   ASSERT( meshServant );
1006   meshServant->SetShape( theShapeObject );
1007
1008   // publish mesh in the study
1009   if ( CanPublishInStudy( mesh ) ) {
1010     SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
1011     aStudyBuilder->NewCommand();  // There is a transaction
1012     SALOMEDS::SObject_wrap aSO = PublishMesh( myCurrentStudy, mesh.in() );
1013     aStudyBuilder->CommitCommand();
1014     if ( !aSO->_is_nil() ) {
1015       // Update Python script
1016       TPythonDump() << aSO << " = " << this << ".CreateMesh(" << theShapeObject << ")";
1017     }
1018   }
1019
1020   return mesh._retn();
1021 }
1022
1023 //=============================================================================
1024 /*!
1025  *  SMESH_Gen_i::CreateEmptyMesh
1026  *
1027  *  Create empty mesh
1028  */
1029 //=============================================================================
1030
1031 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateEmptyMesh()
1032      throw ( SALOME::SALOME_Exception )
1033 {
1034   Unexpect aCatch(SALOME_SalomeException);
1035   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMesh" );
1036   // create mesh
1037   SMESH::SMESH_Mesh_var mesh = this->createMesh();
1038
1039   // publish mesh in the study
1040   if ( CanPublishInStudy( mesh ) ) {
1041     SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
1042     aStudyBuilder->NewCommand();  // There is a transaction
1043     SALOMEDS::SObject_wrap aSO = PublishMesh( myCurrentStudy, mesh.in() );
1044     aStudyBuilder->CommitCommand();
1045     if ( !aSO->_is_nil() ) {
1046       // Update Python script
1047       TPythonDump() << aSO << " = " << this << ".CreateEmptyMesh()";
1048     }
1049   }
1050
1051   return mesh._retn();
1052 }
1053
1054 namespace
1055 {
1056   //================================================================================
1057   /*!
1058    * \brief Throws an exception in case if the file can't be read
1059    */
1060   //================================================================================
1061
1062   void checkFileReadable( const char* theFileName ) throw ( SALOME::SALOME_Exception )
1063   {
1064     SMESH_File f ( theFileName );
1065     if ( !f )
1066     {
1067       if ( !f.error().empty() )
1068         THROW_SALOME_CORBA_EXCEPTION( f.error().c_str(), SALOME::BAD_PARAM);
1069
1070       THROW_SALOME_CORBA_EXCEPTION
1071         (( SMESH_Comment("Can't open for reading the file ") << theFileName ).c_str(),
1072          SALOME::BAD_PARAM );
1073     }
1074   }
1075 }
1076
1077 //=============================================================================
1078 /*!
1079  *  SMESH_Gen_i::CreateMeshFromUNV
1080  *
1081  *  Create mesh and import data from UNV file
1082  */
1083 //=============================================================================
1084
1085 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName )
1086   throw ( SALOME::SALOME_Exception )
1087 {
1088   Unexpect aCatch(SALOME_SalomeException);
1089
1090   checkFileReadable( theFileName );
1091
1092   SMESH::SMESH_Mesh_var aMesh = createMesh();
1093   string aFileName;
1094   // publish mesh in the study
1095   if ( CanPublishInStudy( aMesh ) ) {
1096     SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
1097     aStudyBuilder->NewCommand();  // There is a transaction
1098     SALOMEDS::SObject_wrap aSO = PublishMesh( myCurrentStudy, aMesh.in(), aFileName.c_str() );
1099     aStudyBuilder->CommitCommand();
1100     if ( !aSO->_is_nil() ) {
1101       // Update Python script
1102       TPythonDump() << aSO << " = " << this << ".CreateMeshesFromUNV(r'" << theFileName << "')";
1103     }
1104   }
1105
1106   SMESH_Mesh_i* aServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( aMesh ).in() );
1107   ASSERT( aServant );
1108   aServant->ImportUNVFile( theFileName );
1109
1110   // Dump creation of groups
1111   SMESH::ListOfGroups_var groups = aServant->GetGroups();
1112
1113   aServant->GetImpl().GetMeshDS()->Modified();
1114   return aMesh._retn();
1115 }
1116
1117 //=============================================================================
1118 /*!
1119  *  SMESH_Gen_i::CreateMeshFromMED
1120  *
1121  *  Create mesh and import data from MED file
1122  */
1123 //=============================================================================
1124
1125 SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMEDorSAUV( const char* theFileName,
1126                                                            SMESH::DriverMED_ReadStatus& theStatus,
1127                                                            const char* theCommandNameForPython,
1128                                                            const char* theFileNameForPython)
1129 {
1130 #ifdef WIN32
1131   char bname[ _MAX_FNAME ];
1132   _splitpath( theFileNameForPython, NULL, NULL, bname, NULL );
1133   string aFileName = bname;
1134 #else
1135   string aFileName = basename( theFileNameForPython );
1136 #endif
1137   // Retrieve mesh names from the file
1138   DriverMED_R_SMESHDS_Mesh myReader;
1139   myReader.SetFile( theFileName );
1140   myReader.SetMeshId( -1 );
1141   Driver_Mesh::Status aStatus;
1142   list<string> aNames = myReader.GetMeshNames(aStatus);
1143   SMESH::mesh_array_var aResult = new SMESH::mesh_array();
1144   theStatus = (SMESH::DriverMED_ReadStatus)aStatus;
1145
1146   { // open a new scope to make aPythonDump die before PythonDump in SMESH_Mesh::GetGroups()
1147
1148   // Python Dump
1149   TPythonDump aPythonDump;
1150   aPythonDump << "([";
1151
1152   if (theStatus == SMESH::DRS_OK) {
1153     SALOMEDS::StudyBuilder_var aStudyBuilder;
1154     if ( GetCurrentStudyID() > -1 )
1155     {
1156       aStudyBuilder = myCurrentStudy->NewBuilder();
1157       aStudyBuilder->NewCommand();  // There is a transaction
1158     }
1159     aResult->length( aNames.size() );
1160     int i = 0;
1161
1162     // Iterate through all meshes and create mesh objects
1163     for ( list<string>::iterator it = aNames.begin(); it != aNames.end(); it++ )
1164     {
1165       // Python Dump
1166       if (i > 0) aPythonDump << ", ";
1167
1168       // create mesh
1169       SMESH::SMESH_Mesh_var mesh = createMesh();
1170
1171       // publish mesh in the study
1172       SALOMEDS::SObject_wrap aSO;
1173       if ( CanPublishInStudy( mesh ) )
1174         // little trick: for MED file theFileName and theFileNameForPython are the same, but they are different for SAUV
1175         // - as names of meshes are stored in MED file, we use them for data publishing
1176         // - as mesh name is not stored in UNV file, we use file name as name of mesh when publishing data
1177         aSO = PublishMesh( myCurrentStudy, mesh.in(), ( theFileName == theFileNameForPython ) ? (*it).c_str() : aFileName.c_str() );
1178       if ( !aSO->_is_nil() ) {
1179         // Python Dump
1180         aPythonDump << aSO;
1181       } else {
1182         // Python Dump
1183         aPythonDump << "mesh_" << i;
1184       }
1185
1186       // Read mesh data (groups are published automatically by ImportMEDFile())
1187       SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
1188       ASSERT( meshServant );
1189       SMESH::DriverMED_ReadStatus status1 =
1190         meshServant->ImportMEDFile( theFileName, (*it).c_str() );
1191       if (status1 > theStatus)
1192         theStatus = status1;
1193
1194       aResult[i++] = SMESH::SMESH_Mesh::_duplicate( mesh );
1195       meshServant->GetImpl().GetMeshDS()->Modified();
1196     }
1197     if ( !aStudyBuilder->_is_nil() )
1198       aStudyBuilder->CommitCommand();
1199   }
1200
1201   // Update Python script
1202   aPythonDump << "], status) = " << this << "." << theCommandNameForPython << "(r'" << theFileNameForPython << "')";
1203   }
1204   // Dump creation of groups
1205   for ( int i = 0; i < aResult->length(); ++i )
1206     SMESH::ListOfGroups_var groups = aResult[ i ]->GetGroups();
1207
1208   return aResult._retn();
1209 }
1210
1211 SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char* theFileName,
1212                                                      SMESH::DriverMED_ReadStatus& theStatus)
1213   throw ( SALOME::SALOME_Exception )
1214 {
1215   Unexpect aCatch(SALOME_SalomeException);
1216   checkFileReadable( theFileName );
1217
1218   SMESH::mesh_array* result = CreateMeshesFromMEDorSAUV(theFileName, theStatus, "CreateMeshesFromMED", theFileName);
1219   return result;
1220 }
1221
1222 //=============================================================================
1223 /*!
1224  *  SMESH_Gen_i::CreateMeshFromSAUV
1225  *
1226  *  Create mesh and import data from SAUV file
1227  */
1228 //=============================================================================
1229
1230 SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromSAUV( const char* theFileName,
1231                                                       SMESH::DriverMED_ReadStatus& theStatus)
1232      throw ( SALOME::SALOME_Exception )
1233 {
1234   Unexpect aCatch(SALOME_SalomeException);
1235   checkFileReadable( theFileName );
1236
1237   std::string sauvfilename(theFileName);
1238   std::string medfilename(theFileName);
1239   medfilename += ".med";
1240   std::string cmd;
1241 #ifdef WIN32
1242   cmd = "%PYTHONBIN% ";
1243 #else
1244   cmd = "python ";
1245 #endif
1246   cmd += "-c \"";
1247   cmd += "from medutilities import convert ; convert(r'" + sauvfilename + "', 'GIBI', 'MED', 1, r'" + medfilename + "')";
1248   cmd += "\"";
1249   system(cmd.c_str());
1250   SMESH::mesh_array* result = CreateMeshesFromMEDorSAUV(medfilename.c_str(), theStatus, "CreateMeshesFromSAUV", sauvfilename.c_str());
1251 #ifdef WIN32
1252   cmd = "%PYTHONBIN% ";
1253 #else
1254   cmd = "python ";
1255 #endif
1256   cmd += "-c \"";
1257   cmd += "from medutilities import my_remove ; my_remove(r'" + medfilename + "')";
1258   cmd += "\"";
1259   system(cmd.c_str());
1260   return result;
1261 }
1262
1263 //=============================================================================
1264 /*!
1265  *  SMESH_Gen_i::CreateMeshFromSTL
1266  *
1267  *  Create mesh and import data from STL file
1268  */
1269 //=============================================================================
1270
1271 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromSTL( const char* theFileName )
1272   throw ( SALOME::SALOME_Exception )
1273 {
1274   Unexpect aCatch(SALOME_SalomeException);
1275   checkFileReadable( theFileName );
1276
1277   SMESH::SMESH_Mesh_var aMesh = createMesh();
1278   //string aFileName;
1279 #ifdef WIN32
1280   char bname[ _MAX_FNAME ];
1281   _splitpath( theFileName, NULL, NULL, bname, NULL );
1282   string aFileName = bname;
1283 #else
1284   string aFileName = basename( theFileName );
1285 #endif
1286   // publish mesh in the study
1287   if ( CanPublishInStudy( aMesh ) ) {
1288     SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
1289     aStudyBuilder->NewCommand();  // There is a transaction
1290     SALOMEDS::SObject_wrap aSO = PublishInStudy
1291       ( myCurrentStudy, SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() );
1292     aStudyBuilder->CommitCommand();
1293     if ( !aSO->_is_nil() ) {
1294       // Update Python script
1295       TPythonDump() << aSO << " = " << this << ".CreateMeshesFromSTL(r'" << theFileName << "')";
1296     }
1297   }
1298
1299   SMESH_Mesh_i* aServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( aMesh ).in() );
1300   ASSERT( aServant );
1301   aServant->ImportSTLFile( theFileName );
1302   aServant->GetImpl().GetMeshDS()->Modified();
1303   return aMesh._retn();
1304 }
1305
1306 //================================================================================
1307 /*!
1308  * \brief Create meshes and import data from the CGSN file
1309  */
1310 //================================================================================
1311
1312 SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromCGNS( const char* theFileName,
1313                                                       SMESH::DriverMED_ReadStatus& theStatus)
1314   throw ( SALOME::SALOME_Exception )
1315 {
1316   Unexpect aCatch(SALOME_SalomeException);
1317   checkFileReadable( theFileName );
1318
1319   SMESH::mesh_array_var aResult = new SMESH::mesh_array();
1320
1321 #ifdef WITH_CGNS
1322   // Retrieve nb meshes from the file
1323   DriverCGNS_Read myReader;
1324   myReader.SetFile( theFileName );
1325   Driver_Mesh::Status aStatus;
1326   int nbMeshes = myReader.GetNbMeshes(aStatus);
1327   theStatus = (SMESH::DriverMED_ReadStatus)aStatus;
1328
1329   aResult->length( nbMeshes );
1330
1331   { // open a new scope to make aPythonDump die before PythonDump in SMESH_Mesh::GetGroups()
1332
1333     // Python Dump
1334     TPythonDump aPythonDump;
1335     aPythonDump << "([";
1336
1337     if (theStatus == SMESH::DRS_OK)
1338     {
1339       SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
1340       aStudyBuilder->NewCommand();  // There is a transaction
1341
1342       int i = 0;
1343
1344       // Iterate through all meshes and create mesh objects
1345       for ( ; i < nbMeshes; ++i )
1346       {
1347         // Python Dump
1348         if (i > 0) aPythonDump << ", ";
1349
1350         // create mesh
1351         SMESH::SMESH_Mesh_var mesh = createMesh();
1352         aResult[i] = SMESH::SMESH_Mesh::_duplicate( mesh );
1353
1354         // Read mesh data (groups are published automatically by ImportMEDFile())
1355         SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
1356         ASSERT( meshServant );
1357         string meshName;
1358         SMESH::DriverMED_ReadStatus status1 =
1359           meshServant->ImportCGNSFile( theFileName, i, meshName );
1360         if (status1 > theStatus)
1361           theStatus = status1;
1362
1363         meshServant->GetImpl().GetMeshDS()->Modified();
1364         // publish mesh in the study
1365         SALOMEDS::SObject_wrap aSO;
1366         if ( CanPublishInStudy( mesh ) )
1367           aSO = PublishMesh( myCurrentStudy, mesh.in(), meshName.c_str() );
1368
1369         // Python Dump
1370         if ( !aSO->_is_nil() ) {
1371           aPythonDump << aSO;
1372         }
1373         else {
1374           aPythonDump << "mesh_" << i;
1375         }
1376       }
1377       aStudyBuilder->CommitCommand();
1378     }
1379
1380     aPythonDump << "], status) = " << this << ".CreateMeshesFromCGNS(r'" << theFileName << "')";
1381   }
1382   // Dump creation of groups
1383   for ( int i = 0; i < aResult->length(); ++i )
1384     SMESH::ListOfGroups_var groups = aResult[ i ]->GetGroups();
1385 #else
1386   THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
1387 #endif
1388
1389   return aResult._retn();
1390 }
1391
1392 //================================================================================
1393 /*!
1394  * \brief Create a mesh and import data from a GMF file
1395  */
1396 //================================================================================
1397
1398 SMESH::SMESH_Mesh_ptr
1399 SMESH_Gen_i::CreateMeshesFromGMF( const char*             theFileName,
1400                                   CORBA::Boolean          theMakeRequiredGroups,
1401                                   SMESH::ComputeError_out theError)
1402     throw ( SALOME::SALOME_Exception )
1403 {
1404   Unexpect aCatch(SALOME_SalomeException);
1405   checkFileReadable( theFileName );
1406
1407   SMESH::SMESH_Mesh_var aMesh = createMesh();
1408 #ifdef WIN32
1409   char bname[ _MAX_FNAME ];
1410   _splitpath( theFileName, NULL, NULL, bname, NULL );
1411   string aFileName = bname;
1412 #else
1413   string aFileName = basename( theFileName );
1414 #endif
1415   // publish mesh in the study
1416   if ( CanPublishInStudy( aMesh ) ) {
1417     SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
1418     aStudyBuilder->NewCommand();  // There is a transaction
1419     SALOMEDS::SObject_wrap aSO = PublishInStudy
1420       ( myCurrentStudy, SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() );
1421     aStudyBuilder->CommitCommand();
1422     if ( !aSO->_is_nil() ) {
1423       // Update Python script
1424       TPythonDump() << "("<< aSO << ", error) = " << this << ".CreateMeshesFromGMF(r'"
1425                     << theFileName << "', "
1426                     << theMakeRequiredGroups << " )";
1427     }
1428   }
1429   SMESH_Mesh_i* aServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( aMesh ).in() );
1430   ASSERT( aServant );
1431   theError = aServant->ImportGMFFile( theFileName, theMakeRequiredGroups );
1432   aServant->GetImpl().GetMeshDS()->Modified();
1433   return aMesh._retn();
1434 }
1435
1436
1437 //=============================================================================
1438 /*!
1439  *  SMESH_Gen_i::IsReadyToCompute
1440  *
1441  *  Returns true if mesh contains enough data to be computed
1442  */
1443 //=============================================================================
1444
1445 CORBA::Boolean SMESH_Gen_i::IsReadyToCompute( SMESH::SMESH_Mesh_ptr theMesh,
1446                                               GEOM::GEOM_Object_ptr theShapeObject )
1447   throw ( SALOME::SALOME_Exception )
1448 {
1449   Unexpect aCatch(SALOME_SalomeException);
1450   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IsReadyToCompute" );
1451
1452   if ( CORBA::is_nil( theShapeObject ) )
1453     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
1454                                   SALOME::BAD_PARAM );
1455
1456   if ( CORBA::is_nil( theMesh ) )
1457     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
1458                                   SALOME::BAD_PARAM );
1459
1460   try {
1461     // get mesh servant
1462     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
1463     ASSERT( meshServant );
1464     if ( meshServant ) {
1465       // get local TopoDS_Shape
1466       TopoDS_Shape myLocShape = GeomObjectToShape( theShapeObject );
1467       // call implementation
1468       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
1469       return myGen.CheckAlgoState( myLocMesh, myLocShape );
1470     }
1471   }
1472   catch ( SALOME_Exception& S_ex ) {
1473     INFOS( "catch exception "<< S_ex.what() );
1474   }
1475   return false;
1476 }
1477
1478 //================================================================================
1479 /*!
1480  * \brief  Find SObject for an algo
1481  */
1482 //================================================================================
1483
1484 SALOMEDS::SObject_ptr SMESH_Gen_i::GetAlgoSO(const ::SMESH_Algo* algo)
1485 {
1486   if ( algo ) {
1487     if ( !myCurrentStudy->_is_nil() ) {
1488       // find algo in the study
1489       CORBA::String_var compDataType  = ComponentDataType();
1490       SALOMEDS::SComponent_wrap father = myCurrentStudy->FindComponent( compDataType.in() );
1491       if ( !father->_is_nil() ) {
1492         SALOMEDS::ChildIterator_wrap itBig = myCurrentStudy->NewChildIterator( father );
1493         for ( ; itBig->More(); itBig->Next() ) {
1494           SALOMEDS::SObject_wrap gotBranch = itBig->Value();
1495           if ( gotBranch->Tag() == GetAlgorithmsRootTag() ) {
1496             SALOMEDS::ChildIterator_wrap algoIt = myCurrentStudy->NewChildIterator( gotBranch );
1497             for ( ; algoIt->More(); algoIt->Next() ) {
1498               SALOMEDS::SObject_wrap algoSO = algoIt->Value();
1499               CORBA::Object_var     algoIOR = SObjectToObject( algoSO );
1500               if ( !CORBA::is_nil( algoIOR )) {
1501                 SMESH_Hypothesis_i* impl = SMESH::DownCast<SMESH_Hypothesis_i*>( algoIOR );
1502                 if ( impl && impl->GetImpl() == algo )
1503                   return algoSO._retn();
1504               }
1505             } // loop on algo SO's
1506             break;
1507           } // if algo tag
1508         } // SMESH component iterator
1509       }
1510     }
1511   }
1512   return SALOMEDS::SObject::_nil();
1513 }
1514
1515 //================================================================================
1516 /*!
1517  * \brief Return errors of mesh computation
1518  */
1519 //================================================================================
1520
1521 SMESH::compute_error_array* SMESH_Gen_i::GetComputeErrors( SMESH::SMESH_Mesh_ptr theMesh,
1522                                                            GEOM::GEOM_Object_ptr theSubObject )
1523   throw ( SALOME::SALOME_Exception )
1524 {
1525   Unexpect aCatch(SALOME_SalomeException);
1526   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetComputeErrors()" );
1527
1528   if ( CORBA::is_nil( theSubObject ) && theMesh->HasShapeToMesh())
1529     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM );
1530
1531   if ( CORBA::is_nil( theMesh ) )
1532     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM );
1533
1534   SMESH::compute_error_array_var error_array = new SMESH::compute_error_array;
1535   try {
1536     if ( SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh ))
1537     {
1538       TopoDS_Shape shape;
1539       if(theMesh->HasShapeToMesh())
1540         shape = GeomObjectToShape( theSubObject );
1541       else
1542         shape = SMESH_Mesh::PseudoShape();
1543
1544       ::SMESH_Mesh& mesh = meshServant->GetImpl();
1545
1546       error_array->length( mesh.GetMeshDS()->MaxShapeIndex() );
1547       int nbErr = 0;
1548
1549       SMESH_subMesh *sm = mesh.GetSubMesh(shape);
1550       const bool includeSelf = true, complexShapeFirst = true;
1551       SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(includeSelf,
1552                                                                complexShapeFirst);
1553       while ( smIt->more() )
1554       {
1555         sm = smIt->next();
1556         // if ( sm->GetSubShape().ShapeType() == TopAbs_VERTEX )
1557         //   break;
1558         SMESH_ComputeErrorPtr error = sm->GetComputeError();
1559         if ( error && !error->IsOK() )
1560         {
1561           if ( !( error->myAlgo ) &&
1562                !( error->myAlgo = sm->GetAlgo() ))
1563             continue;
1564           SMESH::ComputeError & errStruct = error_array[ nbErr++ ];
1565           errStruct.code       = -( error->myName < 0 ? error->myName + 1: error->myName ); // -1 -> 0
1566           errStruct.comment    = error->myComment.c_str();
1567           errStruct.subShapeID = sm->GetId();
1568           SALOMEDS::SObject_wrap algoSO = GetAlgoSO( error->myAlgo );
1569           if ( !algoSO->_is_nil() ) {
1570             CORBA::String_var algoName = algoSO->GetName();
1571             errStruct.algoName = algoName;
1572           }
1573           else {
1574             errStruct.algoName = error->myAlgo->GetName();
1575           }
1576           errStruct.hasBadMesh = !error->myBadElements.empty();
1577         }
1578       }
1579       error_array->length( nbErr );
1580     }
1581   }
1582   catch ( SALOME_Exception& S_ex ) {
1583     INFOS( "catch exception "<< S_ex.what() );
1584   }
1585
1586   return error_array._retn();
1587 }
1588
1589 //================================================================================
1590 /*!
1591  * \brief Return mesh elements preventing computation of a subshape
1592  */
1593 //================================================================================
1594
1595 SMESH::MeshPreviewStruct*
1596 SMESH_Gen_i::GetBadInputElements( SMESH::SMESH_Mesh_ptr theMesh,
1597                                   CORBA::Short          theSubShapeID )
1598   throw ( SALOME::SALOME_Exception )
1599 {
1600   Unexpect aCatch(SALOME_SalomeException);
1601   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetBadInputElements()" );
1602
1603   if ( CORBA::is_nil( theMesh ) )
1604     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM );
1605
1606   SMESH::MeshPreviewStruct_var result = new SMESH::MeshPreviewStruct;
1607   try {
1608     // mesh servant
1609     if ( SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh ))
1610     {
1611       // mesh implementation
1612       ::SMESH_Mesh& mesh = meshServant->GetImpl();
1613       // submesh by subshape id
1614       if ( SMESH_subMesh * sm = mesh.GetSubMeshContaining( theSubShapeID ))
1615       {
1616         // compute error
1617         SMESH_ComputeErrorPtr error = sm->GetComputeError();
1618         if ( error && !error->myBadElements.empty())
1619         {
1620           typedef map<const SMDS_MeshElement*, int > TNode2LocalIDMap;
1621           typedef TNode2LocalIDMap::iterator         TNodeLocalID;
1622
1623           // get nodes of elements and count elements
1624           TNode2LocalIDMap mapNode2LocalID;
1625           list< TNodeLocalID > connectivity;
1626           int i, nbElements = 0, nbConnNodes = 0;
1627
1628           list<const SMDS_MeshElement*>::iterator elemIt  = error->myBadElements.begin();
1629           list<const SMDS_MeshElement*>::iterator elemEnd = error->myBadElements.end();
1630           for ( ; elemIt != elemEnd; ++elemIt, ++nbElements )
1631           {
1632             SMDS_ElemIteratorPtr nIt = (*elemIt)->nodesIterator();
1633             while ( nIt->more() )
1634               connectivity.push_back
1635                 ( mapNode2LocalID.insert( make_pair( nIt->next(), ++nbConnNodes)).first );
1636           }
1637           // fill node coords and assign local ids to the nodes
1638           int nbNodes = mapNode2LocalID.size();
1639           result->nodesXYZ.length( nbNodes );
1640           TNodeLocalID node2ID = mapNode2LocalID.begin();
1641           for ( i = 0; i < nbNodes; ++i, ++node2ID ) {
1642             node2ID->second = i;
1643             const SMDS_MeshNode* node = (const SMDS_MeshNode*) node2ID->first;
1644             result->nodesXYZ[i].x = node->X();
1645             result->nodesXYZ[i].y = node->Y();
1646             result->nodesXYZ[i].z = node->Z();
1647           }
1648           // fill connectivity
1649           result->elementConnectivities.length( nbConnNodes );
1650           list< TNodeLocalID >::iterator connIt = connectivity.begin();
1651           for ( i = 0; i < nbConnNodes; ++i, ++connIt ) {
1652             result->elementConnectivities[i] = (*connIt)->second;
1653           }
1654           // fill element types
1655           result->elementTypes.length( nbElements );
1656           for ( i = 0, elemIt = error->myBadElements.begin(); i <nbElements; ++i, ++elemIt )
1657           {
1658             const SMDS_MeshElement* elem = *elemIt;
1659             result->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) elem->GetType();
1660             result->elementTypes[i].isPoly           = elem->IsPoly();
1661             result->elementTypes[i].nbNodesInElement = elem->NbNodes();
1662           }
1663         }
1664       }
1665     }
1666   }
1667   catch ( SALOME_Exception& S_ex ) {
1668     INFOS( "catch exception "<< S_ex.what() );
1669   }
1670
1671   return result._retn();
1672 }
1673
1674 //================================================================================
1675 /*!
1676  * \brief Create a group of elements preventing computation of a sub-shape
1677  */
1678 //================================================================================
1679
1680 SMESH::ListOfGroups*
1681 SMESH_Gen_i::MakeGroupsOfBadInputElements( SMESH::SMESH_Mesh_ptr theMesh,
1682                                            CORBA::Short          theSubShapeID,
1683                                            const char*           theGroupName )
1684   throw ( SALOME::SALOME_Exception )
1685 {
1686   Unexpect aCatch(SALOME_SalomeException);
1687
1688   SMESH::ListOfGroups_var groups;
1689
1690   if ( CORBA::is_nil( theMesh ) )
1691     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM );
1692
1693   try {
1694     if ( SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh ))
1695     {
1696       groups = meshServant->MakeGroupsOfBadInputElements( theSubShapeID, theGroupName );
1697       TPythonDump() << groups << " = " << this
1698                     << ".MakeGroupsOfBadInputElements( "
1699                     << theMesh << ", " << theSubShapeID << ", '" << theGroupName << "' )";
1700     }
1701   }
1702   catch ( SALOME_Exception& S_ex ) {
1703     INFOS( "catch exception "<< S_ex.what() );
1704   }
1705   return groups._retn();
1706 }
1707
1708 //================================================================================
1709 /*!
1710  * \brief Returns errors of hypotheses definintion
1711  * \param theMesh - the mesh
1712  * \param theSubObject - the main or sub- shape
1713  * \retval SMESH::algo_error_array* - sequence of errors
1714  */
1715 //================================================================================
1716
1717 SMESH::algo_error_array* SMESH_Gen_i::GetAlgoState( SMESH::SMESH_Mesh_ptr theMesh,
1718                                                     GEOM::GEOM_Object_ptr theSubObject )
1719       throw ( SALOME::SALOME_Exception )
1720 {
1721   Unexpect aCatch(SALOME_SalomeException);
1722   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetAlgoState()" );
1723
1724   if ( CORBA::is_nil( theSubObject ) && theMesh->HasShapeToMesh())
1725     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM );
1726
1727   if ( CORBA::is_nil( theMesh ) )
1728     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM );
1729
1730   SMESH::algo_error_array_var error_array = new SMESH::algo_error_array;
1731   try {
1732     SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
1733     ASSERT( meshServant );
1734     if ( meshServant ) {
1735       TopoDS_Shape myLocShape;
1736       if(theMesh->HasShapeToMesh())
1737         myLocShape = GeomObjectToShape( theSubObject );
1738       else
1739         myLocShape = SMESH_Mesh::PseudoShape();
1740
1741       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
1742       list< ::SMESH_Gen::TAlgoStateError > error_list;
1743       list< ::SMESH_Gen::TAlgoStateError >::iterator error;
1744       // call ::SMESH_Gen::GetAlgoState()
1745       myGen.GetAlgoState( myLocMesh, myLocShape, error_list );
1746       error_array->length( error_list.size() );
1747       int i = 0;
1748       for ( error = error_list.begin(); error != error_list.end(); ++error )
1749       {
1750         // fill AlgoStateError structure
1751         SMESH::AlgoStateError & errStruct = error_array[ i++ ];
1752         errStruct.state        = SMESH_Mesh_i::ConvertHypothesisStatus( error->_name );
1753         errStruct.algoDim      = error->_algoDim;
1754         errStruct.isGlobalAlgo = error->_isGlobalAlgo;
1755         errStruct.algoName     = "";
1756         SALOMEDS::SObject_wrap algoSO = GetAlgoSO( error->_algo );
1757         if ( !algoSO->_is_nil() ) {
1758           CORBA::String_var algoName = algoSO->GetName();
1759           errStruct.algoName = algoName.in();
1760         }
1761       }
1762     }
1763   }
1764   catch ( SALOME_Exception& S_ex ) {
1765     INFOS( "catch exception "<< S_ex.what() );
1766   }
1767   return error_array._retn();
1768 }
1769
1770 //=============================================================================
1771 /*!
1772  *  SMESH_Gen_i::GetSubShapesId
1773  *
1774  *  Get sub-shapes unique ID's list
1775  */
1776 //=============================================================================
1777
1778 SMESH::long_array* SMESH_Gen_i::GetSubShapesId( GEOM::GEOM_Object_ptr theMainShapeObject,
1779                                             const SMESH::object_array& theListOfSubShapeObject )
1780      throw ( SALOME::SALOME_Exception )
1781 {
1782   Unexpect aCatch(SALOME_SalomeException);
1783   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetSubShapesId" );
1784
1785   SMESH::long_array_var shapesId = new SMESH::long_array;
1786   set<int> setId;
1787
1788   if ( CORBA::is_nil( theMainShapeObject ) )
1789     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
1790                                   SALOME::BAD_PARAM );
1791
1792   try
1793     {
1794       TopoDS_Shape myMainShape = GeomObjectToShape(theMainShapeObject);
1795       TopTools_IndexedMapOfShape myIndexToShape;
1796       TopExp::MapShapes(myMainShape,myIndexToShape);
1797
1798       for ( int i = 0; i < theListOfSubShapeObject.length(); i++ )
1799         {
1800           GEOM::GEOM_Object_var aShapeObject
1801             = GEOM::GEOM_Object::_narrow(theListOfSubShapeObject[i]);
1802           if ( CORBA::is_nil( aShapeObject ) )
1803             THROW_SALOME_CORBA_EXCEPTION ("bad shape object reference", \
1804                                         SALOME::BAD_PARAM );
1805
1806           TopoDS_Shape locShape  = GeomObjectToShape(aShapeObject);
1807           for (TopExp_Explorer exp(locShape,TopAbs_FACE); exp.More(); exp.Next())
1808             {
1809               const TopoDS_Face& F = TopoDS::Face(exp.Current());
1810               setId.insert(myIndexToShape.FindIndex(F));
1811               if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(F));
1812             }
1813           for (TopExp_Explorer exp(locShape,TopAbs_EDGE); exp.More(); exp.Next())
1814             {
1815               const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1816               setId.insert(myIndexToShape.FindIndex(E));
1817               if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(E));
1818             }
1819           for (TopExp_Explorer exp(locShape,TopAbs_VERTEX); exp.More(); exp.Next())
1820             {
1821               const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
1822               setId.insert(myIndexToShape.FindIndex(V));
1823               if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(V));
1824             }
1825         }
1826       shapesId->length(setId.size());
1827       set<int>::iterator iind;
1828       int i=0;
1829       for (iind = setId.begin(); iind != setId.end(); iind++)
1830         {
1831           if(MYDEBUG) SCRUTE((*iind));
1832           shapesId[i] = (*iind);
1833           if(MYDEBUG) SCRUTE(shapesId[i]);
1834           i++;
1835         }
1836     }
1837   catch (SALOME_Exception& S_ex)
1838     {
1839       THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
1840     }
1841
1842   return shapesId._retn();
1843 }
1844
1845 //=============================================================================
1846 /*!
1847  *  SMESH_Gen_i::Compute
1848  *
1849  *  Compute mesh on a shape
1850  */
1851 //=============================================================================
1852
1853 CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
1854                                      GEOM::GEOM_Object_ptr theShapeObject )
1855      throw ( SALOME::SALOME_Exception )
1856 {
1857   //MEMOSTAT;
1858   Unexpect aCatch(SALOME_SalomeException);
1859   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Compute" );
1860
1861   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
1862     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
1863                                   SALOME::BAD_PARAM );
1864
1865   if ( CORBA::is_nil( theMesh ) )
1866     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
1867                                   SALOME::BAD_PARAM );
1868
1869   // Update Python script
1870   TPythonDump() << "isDone = " << this << ".Compute( "
1871                 << theMesh << ", " << theShapeObject << ")";
1872
1873   try {
1874     // get mesh servant
1875     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
1876     meshServant->Load();
1877     ASSERT( meshServant );
1878     if ( meshServant ) {
1879       // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
1880       meshServant->CheckGeomModif();
1881       // get local TopoDS_Shape
1882       TopoDS_Shape myLocShape;
1883       if(theMesh->HasShapeToMesh())
1884         myLocShape = GeomObjectToShape( theShapeObject );
1885       else
1886         myLocShape = SMESH_Mesh::PseudoShape();
1887       // call implementation compute
1888       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
1889       myGen.PrepareCompute( myLocMesh, myLocShape);
1890       bool ok = myGen.Compute( myLocMesh, myLocShape);
1891       meshServant->CreateGroupServants(); // algos can create groups (issue 0020918)
1892       myLocMesh.GetMeshDS()->Modified();
1893       return ok;
1894     }
1895   }
1896   catch ( std::bad_alloc ) {
1897     INFOS( "Compute(): lack of memory" );
1898   }
1899   catch ( SALOME_Exception& S_ex ) {
1900     INFOS( "Compute(): catch exception "<< S_ex.what() );
1901   }
1902   catch ( ... ) {
1903     INFOS( "Compute(): unknown exception " );
1904   }
1905   return false;
1906 }
1907
1908 //=============================================================================
1909 /*!
1910  *  SMESH_Gen_i::CancelCompute
1911  *
1912  *  Cancel Compute mesh on a shape
1913  */
1914 //=============================================================================
1915
1916 void SMESH_Gen_i::CancelCompute( SMESH::SMESH_Mesh_ptr theMesh,
1917                                  GEOM::GEOM_Object_ptr theShapeObject )
1918 {
1919   SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
1920   ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
1921   TopoDS_Shape myLocShape;
1922   if(theMesh->HasShapeToMesh())
1923     myLocShape = GeomObjectToShape( theShapeObject );
1924   else
1925     myLocShape = SMESH_Mesh::PseudoShape();
1926   myGen.CancelCompute( myLocMesh, myLocShape);
1927 }
1928
1929 //=============================================================================
1930 /*!
1931  *  SMESH_Gen_i::Precompute
1932  *
1933  *  Compute mesh as preview till indicated dimension on shape
1934  */
1935 //=============================================================================
1936
1937 SMESH::MeshPreviewStruct* SMESH_Gen_i::Precompute( SMESH::SMESH_Mesh_ptr theMesh,
1938                                                    GEOM::GEOM_Object_ptr theShapeObject,
1939                                                    SMESH::Dimension      theDimension,
1940                                                    SMESH::long_array&    theShapesId)
1941      throw ( SALOME::SALOME_Exception )
1942 {
1943   Unexpect aCatch(SALOME_SalomeException);
1944   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Precompute" );
1945
1946   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
1947     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
1948                                   SALOME::BAD_PARAM );
1949
1950   if ( CORBA::is_nil( theMesh ) )
1951     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
1952                                   SALOME::BAD_PARAM );
1953
1954   SMESH::MeshPreviewStruct_var result = new SMESH::MeshPreviewStruct;
1955   try {
1956     // get mesh servant
1957     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
1958     meshServant->Load();
1959     ASSERT( meshServant );
1960     if ( meshServant ) {
1961       // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
1962       meshServant->CheckGeomModif();
1963       // get local TopoDS_Shape
1964       TopoDS_Shape myLocShape;
1965       if(theMesh->HasShapeToMesh())
1966         myLocShape = GeomObjectToShape( theShapeObject );
1967       else
1968         return result._retn();;
1969
1970       // call implementation compute
1971       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
1972       TSetOfInt shapeIds;
1973       ::MeshDimension aDim = (MeshDimension)theDimension;
1974       if ( myGen.Compute( myLocMesh, myLocShape, false, false, aDim, &shapeIds ) )
1975       {
1976         int nbShapeId = shapeIds.size();
1977         theShapesId.length( nbShapeId );
1978         // iterates on shapes and collect mesh entities into mesh preview
1979         TSetOfInt::const_iterator idIt = shapeIds.begin();
1980         TSetOfInt::const_iterator idEnd = shapeIds.end();
1981         std::map< int, int > mapOfShIdNb;
1982         std::set< SMESH_TLink > setOfEdge;
1983         std::list< SMDSAbs_ElementType > listOfElemType;
1984         typedef map<const SMDS_MeshElement*, int > TNode2LocalIDMap;
1985         typedef TNode2LocalIDMap::iterator         TNodeLocalID;
1986         TNode2LocalIDMap mapNode2LocalID;
1987         list< TNodeLocalID > connectivity;
1988         int i, nbConnNodes = 0;
1989         std::set< const SMESH_subMesh* > setOfVSubMesh;
1990         // iterates on shapes
1991         for ( ; idIt != idEnd; idIt++ )
1992         {
1993           if ( mapOfShIdNb.find( *idIt ) != mapOfShIdNb.end() )
1994             continue;
1995           SMESH_subMesh* sm = myLocMesh.GetSubMeshContaining(*idIt);
1996           if ( !sm || !sm->IsMeshComputed() )
1997             continue;
1998
1999           const TopoDS_Shape& aSh = sm->GetSubShape();
2000           const int shDim = myGen.GetShapeDim( aSh );
2001           if ( shDim < 1 || shDim > theDimension )
2002             continue;
2003
2004           mapOfShIdNb[ *idIt ] = 0;
2005           theShapesId[ mapOfShIdNb.size() - 1 ] = *idIt;
2006
2007           SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
2008           if ( !smDS ) continue;
2009
2010           if ( theDimension == SMESH::DIM_2D )
2011           {
2012             SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
2013             while ( faceIt->more() )
2014             {
2015               const SMDS_MeshElement* face = faceIt->next();
2016               int aNbNode = face->NbNodes();
2017               if ( aNbNode > 4 )
2018                 aNbNode /= 2; // do not take into account additional middle nodes
2019
2020               SMDS_MeshNode* node1 = (SMDS_MeshNode*)face->GetNode( 0 );
2021               for ( int nIndx = 0; nIndx < aNbNode; nIndx++ )
2022               {
2023                 SMDS_MeshNode* node2 = (SMDS_MeshNode*)face->GetNode( nIndx+1 < aNbNode ? nIndx+1 : 0 );
2024                 if ( setOfEdge.insert( SMESH_TLink ( node1, node2 ) ).second )
2025                 {
2026                   listOfElemType.push_back( SMDSAbs_Edge );
2027                   connectivity.push_back
2028                     ( mapNode2LocalID.insert( make_pair( node1, ++nbConnNodes)).first );
2029                   connectivity.push_back
2030                     ( mapNode2LocalID.insert( make_pair( node2, ++nbConnNodes)).first );
2031                 }
2032                 node1 = node2;
2033               }
2034             }
2035           }
2036           else if ( theDimension == SMESH::DIM_1D )
2037           {
2038             SMDS_NodeIteratorPtr nodeIt = smDS->GetNodes();
2039             while ( nodeIt->more() )
2040             {
2041               listOfElemType.push_back( SMDSAbs_Node );
2042               connectivity.push_back
2043                 ( mapNode2LocalID.insert( make_pair( nodeIt->next(), ++nbConnNodes)).first );
2044             }
2045             // add corner nodes by first vertex from edge
2046             SMESH_subMeshIteratorPtr edgeSmIt =
2047               sm->getDependsOnIterator(/*includeSelf*/false,
2048                                        /*complexShapeFirst*/false);
2049             while ( edgeSmIt->more() )
2050             {
2051               SMESH_subMesh* vertexSM = edgeSmIt->next();
2052               // check that vertex is not already treated
2053               if ( !setOfVSubMesh.insert( vertexSM ).second )
2054                 continue;
2055               if ( vertexSM->GetSubShape().ShapeType() != TopAbs_VERTEX )
2056                 continue;
2057
2058               const SMESHDS_SubMesh* vertexSmDS = vertexSM->GetSubMeshDS();
2059               SMDS_NodeIteratorPtr nodeIt = vertexSmDS->GetNodes();
2060               while ( nodeIt->more() )
2061               {
2062                 listOfElemType.push_back( SMDSAbs_Node );
2063                 connectivity.push_back
2064                   ( mapNode2LocalID.insert( make_pair( nodeIt->next(), ++nbConnNodes)).first );
2065               }
2066             }
2067           }
2068         }
2069
2070         // fill node coords and assign local ids to the nodes
2071         int nbNodes = mapNode2LocalID.size();
2072         result->nodesXYZ.length( nbNodes );
2073         TNodeLocalID node2ID = mapNode2LocalID.begin();
2074         for ( i = 0; i < nbNodes; ++i, ++node2ID ) {
2075           node2ID->second = i;
2076           const SMDS_MeshNode* node = (const SMDS_MeshNode*) node2ID->first;
2077           result->nodesXYZ[i].x = node->X();
2078           result->nodesXYZ[i].y = node->Y();
2079           result->nodesXYZ[i].z = node->Z();
2080         }
2081         // fill connectivity
2082         result->elementConnectivities.length( nbConnNodes );
2083         list< TNodeLocalID >::iterator connIt = connectivity.begin();
2084         for ( i = 0; i < nbConnNodes; ++i, ++connIt ) {
2085           result->elementConnectivities[i] = (*connIt)->second;
2086         }
2087
2088         // fill element types
2089         result->elementTypes.length( listOfElemType.size() );
2090         std::list< SMDSAbs_ElementType >::const_iterator typeIt = listOfElemType.begin();
2091         std::list< SMDSAbs_ElementType >::const_iterator typeEnd = listOfElemType.end();
2092         for ( i = 0; typeIt != typeEnd; ++i, ++typeIt )
2093         {
2094           SMDSAbs_ElementType elemType = *typeIt;
2095           result->elementTypes[i].SMDS_ElementType = (SMESH::ElementType)elemType;
2096           result->elementTypes[i].isPoly           = false;
2097           result->elementTypes[i].nbNodesInElement = elemType == SMDSAbs_Edge ? 2 : 1;
2098         }
2099
2100         // correct number of shapes
2101         theShapesId.length( mapOfShIdNb.size() );
2102       }
2103     }
2104   }
2105   catch ( std::bad_alloc ) {
2106     INFOS( "Precompute(): lack of memory" );
2107   }
2108   catch ( SALOME_Exception& S_ex ) {
2109     INFOS( "Precompute(): catch exception "<< S_ex.what() );
2110   }
2111   catch ( ... ) {
2112     INFOS( "Precompute(): unknown exception " );
2113   }
2114   return result._retn();
2115 }
2116
2117
2118 //=============================================================================
2119 /*!
2120  *  SMESH_Gen_i::Evaluate
2121  *
2122  *  Evaluate mesh on a shape
2123  */
2124 //=============================================================================
2125
2126 SMESH::long_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
2127                                          GEOM::GEOM_Object_ptr theShapeObject)
2128 //                                     SMESH::long_array& theNbElems)
2129      throw ( SALOME::SALOME_Exception )
2130 {
2131   Unexpect aCatch(SALOME_SalomeException);
2132   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Evaluate" );
2133
2134   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
2135     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
2136                                   SALOME::BAD_PARAM );
2137
2138   if ( CORBA::is_nil( theMesh ) )
2139     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
2140                                   SALOME::BAD_PARAM );
2141
2142   SMESH::long_array_var nbels = new SMESH::long_array;
2143   nbels->length(SMESH::Entity_Last);
2144   int i = SMESH::Entity_Node;
2145   for (; i < SMESH::Entity_Last; i++)
2146     nbels[i] = 0;
2147
2148   // Update Python script
2149   TPythonDump() << "theNbElems = " << this << ".Evaluate( "
2150                 << theMesh << ", " << theShapeObject << ")";
2151
2152   try {
2153     // get mesh servant
2154     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
2155     ASSERT( meshServant );
2156     if ( meshServant ) {
2157       // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
2158       meshServant->CheckGeomModif();
2159       // get local TopoDS_Shape
2160       TopoDS_Shape myLocShape;
2161       if(theMesh->HasShapeToMesh())
2162         myLocShape = GeomObjectToShape( theShapeObject );
2163       else
2164         myLocShape = SMESH_Mesh::PseudoShape();
2165       // call implementation compute
2166       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
2167       MapShapeNbElems aResMap;
2168       /*CORBA::Boolean ret =*/ myGen.Evaluate( myLocMesh, myLocShape, aResMap);
2169       MapShapeNbElemsItr anIt = aResMap.begin();
2170       for(; anIt!=aResMap.end(); anIt++) {
2171         const vector<int>& aVec = (*anIt).second;
2172         for(i = SMESH::Entity_Node; i < aVec.size(); i++) {
2173           int nbElem = aVec[i];
2174           if ( nbElem < 0 ) // algo failed, check that it has reported a message
2175           {
2176             SMESH_subMesh* sm = anIt->first;
2177             SMESH_ComputeErrorPtr& error = sm->GetComputeError();
2178             const SMESH_Algo* algo = myGen.GetAlgo( myLocMesh, sm->GetSubShape());
2179             if ( (algo && !error.get()) || error->IsOK() )
2180               error.reset( new SMESH_ComputeError( COMPERR_ALGO_FAILED,"Failed to evaluate",algo));
2181           }
2182           else
2183           {
2184             nbels[i] += aVec[i];
2185           }
2186         }
2187       }
2188       return nbels._retn();
2189     }
2190   }
2191   catch ( std::bad_alloc ) {
2192     INFOS( "Evaluate(): lack of memory" );
2193   }
2194   catch ( SALOME_Exception& S_ex ) {
2195     INFOS( "Evaluate(): catch exception "<< S_ex.what() );
2196   }
2197   catch ( ... ) {
2198     INFOS( "Evaluate(): unknown exception " );
2199   }
2200
2201   return nbels._retn();
2202 }
2203
2204 //================================================================================
2205 /*!
2206  * \brief Return geometrical object the given element is built on
2207  *  \param theMesh - the mesh the element is in
2208  *  \param theElementID - the element ID
2209  *  \param theGeomName - the name of the result geom object if it is not yet published
2210  *  \retval GEOM::GEOM_Object_ptr - the found or just published geom object (no need to UnRegister())
2211  */
2212 //================================================================================
2213
2214 GEOM::GEOM_Object_ptr
2215 SMESH_Gen_i::GetGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
2216                                        CORBA::Long            theElementID,
2217                                        const char*            theGeomName)
2218   throw ( SALOME::SALOME_Exception )
2219 {
2220   Unexpect aCatch(SALOME_SalomeException);
2221
2222   GEOM::GEOM_Object_wrap geom = FindGeometryByMeshElement(theMesh, theElementID);
2223   if ( !geom->_is_nil() ) {
2224     GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh();
2225     GEOM::GEOM_Gen_ptr    geomGen   = GetGeomEngine();
2226
2227     // try to find the corresponding SObject
2228     SALOMEDS::SObject_wrap SObj = ObjectToSObject( myCurrentStudy, geom.in() );
2229     if ( SObj->_is_nil() ) // submesh can be not found even if published
2230     {
2231       // try to find published submesh
2232       GEOM::ListOfLong_var list = geom->GetSubShapeIndices();
2233       if ( !geom->IsMainShape() && list->length() == 1 ) {
2234         SALOMEDS::SObject_wrap mainSO = ObjectToSObject( myCurrentStudy, mainShape );
2235         SALOMEDS::ChildIterator_wrap it;
2236         if ( !mainSO->_is_nil() ) {
2237           it = myCurrentStudy->NewChildIterator( mainSO );
2238         }
2239         if ( !it->_is_nil() ) {
2240           for ( it->InitEx(true); it->More(); it->Next() ) {
2241             SALOMEDS::SObject_wrap      so = it->Value();
2242             CORBA::Object_var         obj = SObjectToObject( so );
2243             GEOM::GEOM_Object_var subGeom = GEOM::GEOM_Object::_narrow( obj );
2244             if ( !subGeom->_is_nil() ) {
2245               GEOM::ListOfLong_var subList = subGeom->GetSubShapeIndices();
2246               if ( subList->length() == 1 && list[0] == subList[0] ) {
2247                 SObj = so;
2248                 geom = subGeom;
2249                 break;
2250               }
2251             }
2252           }
2253         }
2254       }
2255     }
2256     if ( SObj->_is_nil() ) // publish a new subshape
2257       SObj = geomGen->AddInStudy( myCurrentStudy, geom, theGeomName, mainShape );
2258
2259     // return only published geometry
2260     if ( !SObj->_is_nil() ) {
2261       //return geom._retn(); -- servant of geom must be UnRegister()ed;
2262       CORBA::Object_var    obj = SObjectToObject( SObj );
2263       GEOM::GEOM_Object_var go = GEOM::GEOM_Object::_narrow( obj );
2264       return go._retn();
2265     }
2266   }
2267   return GEOM::GEOM_Object::_nil();
2268 }
2269
2270 //================================================================================
2271 /*!
2272  * \brief Return geometrical object the given element is built on.
2273  *  \param theMesh - the mesh the element is in
2274  *  \param theElementID - the element ID
2275  *  \retval GEOM::GEOM_Object_ptr - the found or created (UnRegister()!) geom object
2276  */
2277 //================================================================================
2278
2279 GEOM::GEOM_Object_ptr
2280 SMESH_Gen_i::FindGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
2281                                         CORBA::Long            theElementID)
2282   throw ( SALOME::SALOME_Exception )
2283 {
2284   Unexpect aCatch(SALOME_SalomeException);
2285   if ( CORBA::is_nil( theMesh ) )
2286     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", SALOME::BAD_PARAM );
2287
2288   GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh();
2289   GEOM::GEOM_Gen_ptr    geomGen   = GetGeomEngine();
2290
2291   // get a core mesh DS
2292   SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
2293   if ( meshServant && !geomGen->_is_nil() && !mainShape->_is_nil() )
2294   {
2295     ::SMESH_Mesh & mesh = meshServant->GetImpl();
2296     SMESHDS_Mesh* meshDS = mesh.GetMeshDS();
2297     // find the element in mesh
2298     if ( const SMDS_MeshElement * elem = meshDS->FindElement( theElementID ) ) {
2299       // find a shape id by the element
2300       if ( int shapeID = ::SMESH_MeshEditor( &mesh ).FindShape( elem )) {
2301         // get a geom object by the shape id
2302         GEOM::GEOM_Object_var geom = ShapeToGeomObject( meshDS->IndexToShape( shapeID ));
2303         if ( geom->_is_nil() ) {
2304           // try to find a published sub-shape
2305           SALOMEDS::SObject_wrap mainSO = ObjectToSObject( myCurrentStudy, mainShape );
2306           SALOMEDS::ChildIterator_wrap it;
2307           if ( !mainSO->_is_nil() ) {
2308             it = myCurrentStudy->NewChildIterator( mainSO );
2309           }
2310           if ( !it->_is_nil() ) {
2311             for ( it->InitEx(true); it->More(); it->Next() ) {
2312               SALOMEDS::SObject_wrap      so = it->Value();
2313               CORBA::Object_var         obj = SObjectToObject( so );
2314               GEOM::GEOM_Object_var subGeom = GEOM::GEOM_Object::_narrow( obj );
2315               if ( !subGeom->_is_nil() ) {
2316                 GEOM::ListOfLong_var subList = subGeom->GetSubShapeIndices();
2317                 if ( subList->length() == 1 && shapeID == subList[0] ) {
2318                   geom = subGeom;
2319                   break;
2320                 }
2321               }
2322             }
2323           }
2324         }
2325         if ( geom->_is_nil() ) {
2326           // explode
2327           GEOM::GEOM_IShapesOperations_wrap op =
2328             geomGen->GetIShapesOperations( GetCurrentStudyID() );
2329           if ( !op->_is_nil() )
2330             geom = op->GetSubShape( mainShape, shapeID );
2331         }
2332         else {
2333           geom->Register();
2334         }
2335         if ( !geom->_is_nil() ) {
2336           GeomObjectToShape( geom ); // let geom client remember the found shape
2337           return geom._retn();
2338         }
2339       }
2340     }
2341   }
2342   return GEOM::GEOM_Object::_nil();
2343 }
2344
2345 //================================================================================
2346 /*!
2347  *  SMESH_Gen_i::Concatenate
2348  *
2349  *  Concatenate the given meshes into one mesh
2350  */
2351 //================================================================================
2352
2353 SMESH::SMESH_Mesh_ptr
2354 SMESH_Gen_i::Concatenate(const SMESH::ListOfIDSources& theMeshesArray,
2355                          CORBA::Boolean                theUniteIdenticalGroups,
2356                          CORBA::Boolean                theMergeNodesAndElements,
2357                          CORBA::Double                 theMergeTolerance)
2358   throw ( SALOME::SALOME_Exception )
2359 {
2360   return ConcatenateCommon(theMeshesArray,
2361                            theUniteIdenticalGroups,
2362                            theMergeNodesAndElements,
2363                            theMergeTolerance,
2364                            false);
2365 }
2366
2367 //================================================================================
2368 /*!
2369  *  SMESH_Gen_i::ConcatenateWithGroups
2370  *
2371  *  Concatenate the given meshes into one mesh
2372  *  Create the groups of all elements from initial meshes
2373  */
2374 //================================================================================
2375
2376 SMESH::SMESH_Mesh_ptr
2377 SMESH_Gen_i::ConcatenateWithGroups(const SMESH::ListOfIDSources& theMeshesArray,
2378                                    CORBA::Boolean                theUniteIdenticalGroups,
2379                                    CORBA::Boolean                theMergeNodesAndElements,
2380                                    CORBA::Double                 theMergeTolerance)
2381   throw ( SALOME::SALOME_Exception )
2382 {
2383   return ConcatenateCommon(theMeshesArray,
2384                            theUniteIdenticalGroups,
2385                            theMergeNodesAndElements,
2386                            theMergeTolerance,
2387                            true);
2388 }
2389
2390 //================================================================================
2391 /*!
2392  *  SMESH_Gen_i::ConcatenateCommon
2393  *
2394  *  Concatenate the given meshes into one mesh
2395  */
2396 //================================================================================
2397
2398 SMESH::SMESH_Mesh_ptr
2399 SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
2400                                CORBA::Boolean                theUniteIdenticalGroups,
2401                                CORBA::Boolean                theMergeNodesAndElements,
2402                                CORBA::Double                 theMergeTolerance,
2403                                CORBA::Boolean                theCommonGroups)
2404   throw ( SALOME::SALOME_Exception )
2405 {
2406   typedef list<SMESH::SMESH_Group_var> TListOfNewGroups;
2407   typedef map< pair<string, SMESH::ElementType>, TListOfNewGroups > TGroupsMap;
2408
2409   TPythonDump* pPythonDump = new TPythonDump;
2410   TPythonDump& aPythonDump = *pPythonDump; // prevent dump of called methods
2411
2412   // create mesh
2413   SMESH::SMESH_Mesh_var aNewMesh = CreateEmptyMesh();
2414
2415   if ( aNewMesh->_is_nil() )
2416     return aNewMesh._retn();
2417
2418   SMESH_Mesh_i* aNewImpl = SMESH::DownCast<SMESH_Mesh_i*>( aNewMesh );
2419   if ( !aNewImpl )
2420     return aNewMesh._retn();
2421
2422   ::SMESH_Mesh& aLocMesh = aNewImpl->GetImpl();
2423   SMESHDS_Mesh* aNewMeshDS = aLocMesh.GetMeshDS();
2424
2425   TGroupsMap aGroupsMap;
2426   TListOfNewGroups aListOfNewGroups;
2427   ::SMESH_MeshEditor aNewEditor(&aLocMesh);
2428   SMESH::ListOfGroups_var aListOfGroups;
2429
2430   ::SMESH_MeshEditor::ElemFeatures  elemType;
2431   std::vector<const SMDS_MeshNode*> aNodesArray;
2432
2433   // loop on sub-meshes
2434   for ( int i = 0; i < theMeshesArray.length(); i++)
2435   {
2436     if ( CORBA::is_nil( theMeshesArray[i] )) continue;
2437     SMESH::SMESH_Mesh_var anInitMesh = theMeshesArray[i]->GetMesh();
2438     if ( anInitMesh->_is_nil() ) continue;
2439     SMESH_Mesh_i* anInitImpl = SMESH::DownCast<SMESH_Mesh_i*>( anInitMesh );
2440     if ( !anInitImpl ) continue;
2441     anInitImpl->Load();
2442
2443     ::SMESH_Mesh& aInitLocMesh = anInitImpl->GetImpl();
2444     SMESHDS_Mesh* anInitMeshDS = aInitLocMesh.GetMeshDS();
2445
2446     // remember nb of elements before filling in
2447     SMESH::long_array_var prevState =  aNewMesh->GetNbElementsByType();
2448
2449     typedef std::map<const SMDS_MeshElement*, const SMDS_MeshElement*, TIDCompare > TEEMap;
2450     TEEMap elemsMap, nodesMap;
2451
2452     // loop on elements of a sub-mesh
2453     SMDS_ElemIteratorPtr itElems = anInitImpl->GetElements( theMeshesArray[i], SMESH::ALL );
2454     const SMDS_MeshElement* anElem;
2455     const SMDS_MeshElement* aNewElem;
2456     const SMDS_MeshNode*    aNode;
2457     const SMDS_MeshNode*    aNewNode;
2458     int anElemNbNodes;
2459
2460     while ( itElems->more() )
2461     {
2462       anElem = itElems->next();
2463       anElemNbNodes = anElem->NbNodes();
2464       aNodesArray.resize( anElemNbNodes );
2465
2466       // loop on nodes of an element
2467       SMDS_ElemIteratorPtr itNodes = anElem->nodesIterator();
2468       for ( int k = 0; itNodes->more(); k++)
2469       {
2470         aNode = static_cast<const SMDS_MeshNode*>( itNodes->next() );
2471         TEEMap::iterator n2nnIt = nodesMap.find( aNode );
2472         if ( n2nnIt == nodesMap.end() )
2473         {
2474           aNewNode = aNewMeshDS->AddNode(aNode->X(), aNode->Y(), aNode->Z());
2475           nodesMap.insert( make_pair( aNode, aNewNode ));
2476         }
2477         else
2478         {
2479           aNewNode = static_cast<const SMDS_MeshNode*>( n2nnIt->second );
2480         }
2481         aNodesArray[k] = aNewNode;
2482       }
2483
2484       // creates a corresponding element on existent nodes in new mesh
2485       if ( anElem->GetType() == SMDSAbs_Node )
2486         aNewElem = 0;
2487       else
2488         aNewElem =
2489           aNewEditor.AddElement( aNodesArray, elemType.Init( anElem, /*basicOnly=*/false ));
2490
2491       if ( aNewElem )
2492         elemsMap.insert( make_pair( anElem, aNewElem ));
2493
2494     } //elems loop
2495
2496     aNewEditor.ClearLastCreated(); // forget the history
2497
2498
2499     // create groups of just added elements
2500     SMESH::SMESH_Group_var aNewGroup;
2501     SMESH::ElementType aGroupType;
2502     if ( theCommonGroups )
2503     {
2504       SMESH::long_array_var curState = aNewMesh->GetNbElementsByType();
2505
2506       for( aGroupType = SMESH::NODE;
2507            aGroupType < SMESH::NB_ELEMENT_TYPES;
2508            aGroupType = (SMESH::ElementType)( aGroupType + 1 ))
2509       {
2510         if ( curState[ aGroupType ] <= prevState[ aGroupType ])
2511           continue;
2512
2513         // make a group name
2514         const char* typeNames[] = { "All","Nodes","Edges","Faces","Volumes","0DElems","Balls" };
2515         { // check of typeNames, compilation failure mains that NB_ELEMENT_TYPES changed:
2516           const int nbNames = sizeof(typeNames) / sizeof(const char*);
2517           int _assert[( nbNames == SMESH::NB_ELEMENT_TYPES ) ? 1 : -1 ];
2518         }
2519         string groupName = "Gr";
2520         SALOMEDS::SObject_wrap aMeshSObj = ObjectToSObject( myCurrentStudy, theMeshesArray[i] );
2521         if ( aMeshSObj ) {
2522           CORBA::String_var name = aMeshSObj->GetName();
2523           groupName += name;
2524         }
2525         groupName += "_";
2526         groupName += typeNames[ aGroupType ];
2527
2528         // make and fill a group
2529         TEEMap & e2neMap = ( aGroupType == SMESH::NODE ) ? nodesMap : elemsMap;
2530         aNewGroup = aNewImpl->CreateGroup( aGroupType, groupName.c_str() );
2531         if ( SMESH_Group_i* grp_i = SMESH::DownCast<SMESH_Group_i*>( aNewGroup ))
2532         {
2533           if ( SMESHDS_Group* grpDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() ))
2534           {
2535             TEEMap::iterator e2neIt = e2neMap.begin();
2536             for ( ; e2neIt != e2neMap.end(); ++e2neIt )
2537             {
2538               aNewElem = e2neIt->second;
2539               if ( aNewElem->GetType() == grpDS->GetType() )
2540               {
2541                 grpDS->Add( aNewElem );
2542
2543                 if ( prevState[ aGroupType ]++ >= curState[ aGroupType ] )
2544                   break;
2545               }
2546             }
2547           }
2548         }
2549         aListOfNewGroups.clear();
2550         aListOfNewGroups.push_back(aNewGroup);
2551         aGroupsMap.insert(make_pair( make_pair(groupName, aGroupType), aListOfNewGroups ));
2552       }
2553     }
2554
2555     if ( SMESH_Mesh_i* anSrcImpl = SMESH::DownCast<SMESH_Mesh_i*>( theMeshesArray[i] ))
2556     {
2557       // copy orphan nodes
2558       if ( anSrcImpl->NbNodes() > nodesMap.size() )
2559       {
2560         SMDS_ElemIteratorPtr itNodes = anInitImpl->GetElements( theMeshesArray[i], SMESH::NODE );
2561         while ( itNodes->more() )
2562         {
2563           const SMDS_MeshNode* aNode = static_cast< const SMDS_MeshNode* >( itNodes->next() );
2564           if ( aNode->NbInverseElements() == 0 )
2565           {
2566             aNewNode = aNewMeshDS->AddNode(aNode->X(), aNode->Y(), aNode->Z());
2567             nodesMap.insert( make_pair( aNode, aNewNode ));
2568           }
2569         }
2570       }
2571
2572       // copy groups
2573
2574       SMESH::SMESH_GroupBase_ptr aGroup;
2575       CORBA::String_var aGroupName;
2576       SMESH::long_array_var anNewIDs = new SMESH::long_array();
2577
2578       // loop on groups of a source mesh
2579       aListOfGroups = anSrcImpl->GetGroups();
2580       for (int iG = 0; iG < aListOfGroups->length(); iG++)
2581       {
2582         aGroup = aListOfGroups[iG];
2583         aGroupType = aGroup->GetType();
2584         aGroupName = aGroup->GetName();
2585
2586         // convert a list of IDs
2587         anNewIDs->length( aGroup->Size() );
2588         TEEMap & e2neMap = ( aGroupType == SMESH::NODE ) ? nodesMap : elemsMap;
2589         SMDS_ElemIteratorPtr itGrElems = anSrcImpl->GetElements( aGroup, SMESH::ALL );
2590         int iElem = 0;
2591         while ( itGrElems->more() )
2592         {
2593           anElem = itGrElems->next();
2594           TEEMap::iterator e2neIt = e2neMap.find( anElem );
2595           if ( e2neIt != e2neMap.end() )
2596             anNewIDs[ iElem++ ] = e2neIt->second->GetID();
2597         }
2598         anNewIDs->length( iElem );
2599
2600         // check a current group name and type don't have identical ones in final mesh
2601         aListOfNewGroups.clear();
2602         TGroupsMap::iterator anIter = aGroupsMap.find( make_pair( aGroupName, aGroupType ));
2603         if ( anIter == aGroupsMap.end() ) {
2604           // add a new group in the mesh
2605           aNewGroup = aNewImpl->CreateGroup( aGroupType, aGroupName );
2606           // add elements into new group
2607           aNewGroup->Add( anNewIDs );
2608
2609           aListOfNewGroups.push_back(aNewGroup);
2610           aGroupsMap.insert(make_pair( make_pair(aGroupName, aGroupType), aListOfNewGroups ));
2611         }
2612
2613         else if ( theUniteIdenticalGroups ) {
2614           // unite identical groups
2615           TListOfNewGroups& aNewGroups = anIter->second;
2616           aNewGroups.front()->Add( anNewIDs );
2617         }
2618
2619         else {
2620           // rename identical groups
2621           aNewGroup = aNewImpl->CreateGroup(aGroupType, aGroupName);
2622           aNewGroup->Add( anNewIDs );
2623
2624           TListOfNewGroups& aNewGroups = anIter->second;
2625           string aNewGroupName;
2626           if (aNewGroups.size() == 1) {
2627             aNewGroupName = string(aGroupName) + "_1";
2628             aNewGroups.front()->SetName(aNewGroupName.c_str());
2629           }
2630           char aGroupNum[128];
2631           sprintf(aGroupNum, "%u", aNewGroups.size()+1);
2632           aNewGroupName = string(aGroupName) + "_" + string(aGroupNum);
2633           aNewGroup->SetName(aNewGroupName.c_str());
2634           aNewGroups.push_back(aNewGroup);
2635         }
2636       } //groups loop
2637     } // if an IDSource is a mesh
2638   } //meshes loop
2639
2640   if (theMergeNodesAndElements) // merge nodes
2641   {
2642     TIDSortedNodeSet aMeshNodes; // no input nodes
2643     SMESH_MeshEditor::TListOfListOfNodes aGroupsOfNodes;
2644     aNewEditor.FindCoincidentNodes( aMeshNodes, theMergeTolerance, aGroupsOfNodes,
2645                                     /*SeparateCornersAndMedium=*/ false );
2646     aNewEditor.MergeNodes( aGroupsOfNodes );
2647     // merge elements
2648     aNewEditor.MergeEqualElements();
2649   }
2650
2651   // Update Python script
2652   aPythonDump << aNewMesh << " = " << this << "."
2653               << ( theCommonGroups ? "ConcatenateWithGroups" : "Concatenate" )
2654               << "([";
2655   for ( int i = 0; i < theMeshesArray.length(); i++) {
2656     if (i > 0) aPythonDump << ", ";
2657     aPythonDump << theMeshesArray[i];
2658   }
2659   aPythonDump << "], ";
2660   aPythonDump << theUniteIdenticalGroups << ", "
2661               << theMergeNodesAndElements << ", "
2662               << TVar( theMergeTolerance ) << ")";
2663
2664   delete pPythonDump; // enable python dump from GetGroups()
2665
2666   // 0020577: EDF 1164 SMESH: Bad dump of concatenate with create common groups
2667   if ( !aNewMesh->_is_nil() )
2668   {
2669     SMESH::ListOfGroups_var groups = aNewMesh->GetGroups();
2670   }
2671
2672   // IPAL21468 Change icon of compound because it need not be computed.
2673   SALOMEDS::SObject_wrap aMeshSObj = ObjectToSObject( myCurrentStudy, aNewMesh );
2674   SetPixMap( aMeshSObj, "ICON_SMESH_TREE_MESH" );
2675
2676   if (aNewMeshDS)
2677     aNewMeshDS->Modified();
2678
2679   return aNewMesh._retn();
2680 }
2681
2682 //================================================================================
2683 /*!
2684  * \brief Create a mesh by copying a part of another mesh
2685  *  \param meshPart - a part of mesh to copy
2686  *  \param toCopyGroups - to create in the new mesh groups
2687  *                        the copied elements belongs to
2688  *  \param toKeepIDs - to preserve IDs of the copied elements or not
2689  *  \retval SMESH::SMESH_Mesh_ptr - the new mesh
2690  */
2691 //================================================================================
2692
2693 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
2694                                             const char*               meshName,
2695                                             CORBA::Boolean            toCopyGroups,
2696                                             CORBA::Boolean            toKeepIDs)
2697 {
2698   Unexpect aCatch(SALOME_SalomeException);
2699
2700   TPythonDump* pyDump = new TPythonDump; // prevent dump from CreateMesh()
2701
2702   // 1. Get source mesh
2703
2704   if ( CORBA::is_nil( meshPart ))
2705     THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM );
2706
2707   SMESH::SMESH_Mesh_var srcMesh = meshPart->GetMesh();
2708   SMESH_Mesh_i*       srcMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( srcMesh );
2709   if ( !srcMesh_i )
2710     THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM );
2711
2712   SMESHDS_Mesh* srcMeshDS = srcMesh_i->GetImpl().GetMeshDS();
2713
2714   // 2. Make a new mesh
2715
2716   SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil());
2717   SMESH_Mesh_i*       newMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( newMesh );
2718   if ( !newMesh_i )
2719     THROW_SALOME_CORBA_EXCEPTION( "can't create a mesh", SALOME::INTERNAL_ERROR );
2720   SALOMEDS::SObject_wrap meshSO = ObjectToSObject(myCurrentStudy, newMesh );
2721   if ( !meshSO->_is_nil() )
2722   {
2723     SetName( meshSO, meshName, "Mesh" );
2724     SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
2725   }
2726   SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS();
2727   ::SMESH_MeshEditor editor( &newMesh_i->GetImpl() );
2728   ::SMESH_MeshEditor::ElemFeatures elemType;
2729
2730   // 3. Get elements to copy
2731
2732   SMDS_ElemIteratorPtr srcElemIt; SMDS_NodeIteratorPtr srcNodeIt;
2733   TIDSortedElemSet srcElems;
2734   SMESH::array_of_ElementType_var srcElemTypes = meshPart->GetTypes();
2735   if ( SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
2736   {
2737     srcMesh_i->Load();
2738     srcElemIt = srcMeshDS->elementsIterator();
2739     srcNodeIt = srcMeshDS->nodesIterator();
2740   }
2741   else
2742   {
2743     SMESH::long_array_var ids = meshPart->GetIDs();
2744     if ( srcElemTypes->length() == 1 && srcElemTypes[0] == SMESH::NODE ) // group of nodes
2745     {
2746       for (int i=0; i < ids->length(); i++)
2747         if ( const SMDS_MeshElement * elem = srcMeshDS->FindNode( ids[i] ))
2748           srcElems.insert( elem );
2749     }
2750     else
2751     {
2752       for (int i=0; i < ids->length(); i++)
2753         if ( const SMDS_MeshElement * elem = srcMeshDS->FindElement( ids[i] ))
2754           srcElems.insert( elem );
2755     }
2756     if ( srcElems.empty() )
2757       return newMesh._retn();
2758
2759     typedef SMDS_SetIterator< SMDS_pElement, TIDSortedElemSet::const_iterator > ElIter;
2760     srcElemIt = SMDS_ElemIteratorPtr( new ElIter( srcElems.begin(), srcElems.end() ));
2761   }
2762
2763   // 4. Copy elements
2764
2765   typedef map<SMDS_pElement, SMDS_pElement, TIDCompare> TE2EMap;
2766   TE2EMap e2eMapByType[ SMDSAbs_NbElementTypes ];
2767   TE2EMap& n2nMap = e2eMapByType[ SMDSAbs_Node ];
2768   int iN;
2769   const SMDS_MeshNode *nSrc, *nTgt;
2770   vector< const SMDS_MeshNode* > nodes;
2771   while ( srcElemIt->more() )
2772   {
2773     const SMDS_MeshElement * elem = srcElemIt->next();
2774     // find / add nodes
2775     nodes.resize( elem->NbNodes());
2776     SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
2777     if ( toKeepIDs ) {
2778       for ( iN = 0; nIt->more(); ++iN )
2779       {
2780         nSrc = static_cast<const SMDS_MeshNode*>( nIt->next() );
2781         nTgt = newMeshDS->FindNode( nSrc->GetID());
2782         if ( !nTgt )
2783           nTgt = newMeshDS->AddNodeWithID( nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID());
2784         nodes[ iN ] = nTgt;
2785       }
2786     }
2787     else {
2788       for ( iN = 0; nIt->more(); ++iN )
2789       {
2790         nSrc = static_cast<const SMDS_MeshNode*>( nIt->next() );
2791         TE2EMap::iterator n2n = n2nMap.insert( make_pair( nSrc, SMDS_pNode(0) )).first;
2792         if ( !n2n->second )
2793           n2n->second = newMeshDS->AddNode( nSrc->X(), nSrc->Y(), nSrc->Z() );
2794         nodes[ iN ] = (const SMDS_MeshNode*) n2n->second;
2795       }
2796     }
2797     // add elements
2798     if ( elem->GetType() != SMDSAbs_Node )
2799     {
2800       elemType.Init( elem, /*basicOnly=*/false );
2801       if ( toKeepIDs ) elemType.SetID( elem->GetID() );
2802
2803       const SMDS_MeshElement * newElem = editor.AddElement( nodes, elemType );
2804       if ( toCopyGroups && !toKeepIDs )
2805         e2eMapByType[ elem->GetType() ].insert( make_pair( elem, newElem ));
2806     }
2807   } // while ( srcElemIt->more() )
2808
2809   // 4(b). Copy free nodes
2810
2811   if ( srcNodeIt && srcMeshDS->NbNodes() != newMeshDS->NbNodes() )
2812   {
2813     while ( srcNodeIt->more() )
2814     {
2815       nSrc = srcNodeIt->next();
2816       if ( nSrc->NbInverseElements() == 0 )
2817       {
2818         if ( toKeepIDs )
2819           nTgt = newMeshDS->AddNodeWithID( nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID());
2820         else
2821           n2nMap[ nSrc ] = newMeshDS->AddNode( nSrc->X(), nSrc->Y(), nSrc->Z() );
2822       }
2823     }
2824   }
2825
2826   // 5. Copy groups
2827
2828   int nbNewGroups = 0;
2829   if ( toCopyGroups )
2830   {
2831     SMESH_Mesh::GroupIteratorPtr gIt = srcMesh_i->GetImpl().GetGroups();
2832     while ( gIt->more() )
2833     {
2834       SMESH_Group* group = gIt->next();
2835       const SMESHDS_GroupBase* groupDS = group->GetGroupDS();
2836
2837       // Check group type. We copy nodal groups containing nodes of copied element
2838       SMDSAbs_ElementType groupType = groupDS->GetType();
2839       if ( groupType != SMDSAbs_Node &&
2840            newMeshDS->GetMeshInfo().NbElements( groupType ) == 0 )
2841         continue; // group type differs from types of meshPart
2842
2843       // Find copied elements in the group
2844       vector< const SMDS_MeshElement* > groupElems;
2845       SMDS_ElemIteratorPtr eIt = groupDS->GetElements();
2846       if ( toKeepIDs )
2847       {
2848         const SMDS_MeshElement* foundElem;
2849         if ( groupType == SMDSAbs_Node )
2850         {
2851           while ( eIt->more() )
2852             if (( foundElem = newMeshDS->FindNode( eIt->next()->GetID() )))
2853               groupElems.push_back( foundElem );
2854         }
2855         else
2856         {
2857           while ( eIt->more() )
2858             if (( foundElem = newMeshDS->FindElement( eIt->next()->GetID() )))
2859               groupElems.push_back( foundElem );
2860         }
2861       }
2862       else
2863       {
2864         TE2EMap & e2eMap = e2eMapByType[ groupDS->GetType() ];
2865         if ( e2eMap.empty() ) continue;
2866         int minID = e2eMap.begin()->first->GetID();
2867         int maxID = e2eMap.rbegin()->first->GetID();
2868         TE2EMap::iterator e2e;
2869         while ( eIt->more() && groupElems.size() < e2eMap.size())
2870         {
2871           const SMDS_MeshElement* e = eIt->next();
2872           if ( e->GetID() < minID || e->GetID() > maxID ) continue;
2873           if ((e2e = e2eMap.find( e )) != e2eMap.end())
2874             groupElems.push_back( e2e->second );
2875         }
2876       }
2877       // Make a new group
2878       if ( !groupElems.empty() )
2879       {
2880         SMESH::SMESH_Group_var newGroupObj =
2881           newMesh->CreateGroup( SMESH::ElementType(groupType), group->GetName() );
2882         if ( SMESH_GroupBase_i* newGroup_i = SMESH::DownCast<SMESH_GroupBase_i*>( newGroupObj))
2883         {
2884           SMESHDS_GroupBase * newGroupDS = newGroup_i->GetGroupDS();
2885           SMDS_MeshGroup& smdsGroup = ((SMESHDS_Group*)newGroupDS)->SMDSGroup();
2886           for ( unsigned i = 0; i < groupElems.size(); ++i )
2887             smdsGroup.Add( groupElems[i] );
2888
2889           nbNewGroups++;
2890         }
2891       }
2892     }
2893   }
2894
2895   newMeshDS->Modified();
2896
2897   *pyDump << newMesh << " = " << this
2898           << ".CopyMesh( " << meshPart << ", "
2899           << "'" << meshName << "', "
2900           << toCopyGroups << ", "
2901           << toKeepIDs << ")";
2902
2903   delete pyDump; pyDump = 0; // allow dump in GetGroups()
2904
2905   if ( nbNewGroups > 0 ) // dump created groups
2906     SMESH::ListOfGroups_var groups = newMesh->GetGroups();
2907
2908   return newMesh._retn();
2909 }
2910
2911 //================================================================================
2912 /*!
2913  *  SMESH_Gen_i::GetMEDVersion
2914  *
2915  *  Get MED version of the file by its name
2916  */
2917 //================================================================================
2918 CORBA::Boolean SMESH_Gen_i::GetMEDVersion(const char* theFileName,
2919                                           SMESH::MED_VERSION& theVersion)
2920 {
2921   theVersion = SMESH::MED_V2_1;
2922   MED::EVersion aVersion = MED::GetVersionId( theFileName );
2923   switch( aVersion ) {
2924     case MED::eV2_1     : theVersion = SMESH::MED_V2_1; return true;
2925     case MED::eV2_2     : theVersion = SMESH::MED_V2_2; return true;
2926     case MED::eVUnknown : return false;
2927   }
2928   return false;
2929 }
2930
2931 //================================================================================
2932 /*!
2933  *  SMESH_Gen_i::GetMeshNames
2934  *
2935  *  Get names of meshes defined in file with the specified name
2936  */
2937 //================================================================================
2938 SMESH::string_array* SMESH_Gen_i::GetMeshNames(const char* theFileName)
2939 {
2940   SMESH::string_array_var aResult = new SMESH::string_array();
2941   MED::PWrapper aMed = MED::CrWrapper( theFileName );
2942   MED::TErr anErr;
2943   MED::TInt aNbMeshes = aMed->GetNbMeshes( &anErr );
2944   if( anErr >= 0 ) {
2945     aResult->length( aNbMeshes );
2946     for( MED::TInt i = 0; i < aNbMeshes; i++ ) {
2947       MED::PMeshInfo aMeshInfo = aMed->GetPMeshInfo( i+1 );
2948       aResult[i] = CORBA::string_dup( aMeshInfo->GetName().c_str() );
2949     }
2950   }
2951   return aResult._retn();
2952 }
2953
2954 //=============================================================================
2955 /*!
2956  *  SMESH_Gen_i::Save
2957  *
2958  *  Save SMESH module's data
2959  */
2960 //=============================================================================
2961 SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
2962                                       const char*              theURL,
2963                                       bool                     isMultiFile )
2964 {
2965   INFOS( "SMESH_Gen_i::Save" );
2966
2967   //  ASSERT( theComponent->GetStudy()->StudyId() == myCurrentStudy->StudyId() )
2968   // san -- in case <myCurrentStudy> differs from theComponent's study,
2969   // use that of the component
2970   if ( theComponent->GetStudy()->StudyId() != GetCurrentStudyID() )
2971     SetCurrentStudy( theComponent->GetStudy() );
2972
2973   // Store study contents as a set of python commands
2974   SavePython(myCurrentStudy);
2975
2976   StudyContext* myStudyContext = GetCurrentStudyContext();
2977
2978   // Declare a byte stream
2979   SALOMEDS::TMPFile_var aStreamFile;
2980
2981   // Obtain a temporary dir
2982   TCollection_AsciiString tmpDir =
2983     ( isMultiFile ) ? TCollection_AsciiString( ( char* )theURL ) : ( char* )SALOMEDS_Tool::GetTmpDir().c_str();
2984
2985   // Create a sequence of files processed
2986   SALOMEDS::ListOfFileNames_var aFileSeq = new SALOMEDS::ListOfFileNames;
2987   aFileSeq->length( NUM_TMP_FILES );
2988
2989   TCollection_AsciiString aStudyName( "" );
2990   if ( isMultiFile )
2991     aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( myCurrentStudy->URL() ).c_str() );
2992
2993   // Set names of temporary files
2994   TCollection_AsciiString filename =
2995     aStudyName + TCollection_AsciiString( "_SMESH.hdf" );        // for SMESH data itself
2996   TCollection_AsciiString meshfile =
2997     aStudyName + TCollection_AsciiString( "_SMESH_Mesh.med" );   // for mesh data to be stored in MED file
2998   aFileSeq[ 0 ] = CORBA::string_dup( filename.ToCString() );
2999   aFileSeq[ 1 ] = CORBA::string_dup( meshfile.ToCString() );
3000   filename = tmpDir + filename;
3001   meshfile = tmpDir + meshfile;
3002
3003   HDFfile*    aFile;
3004   HDFdataset* aDataset;
3005   HDFgroup*   aTopGroup;
3006   HDFgroup*   aGroup;
3007   HDFgroup*   aSubGroup;
3008   HDFgroup*   aSubSubGroup;
3009   hdf_size    aSize[ 1 ];
3010
3011
3012   //Remove the files if they exist: BugID: 11225
3013 #ifndef WIN32 /* unix functionality */
3014   TCollection_AsciiString cmd("rm -f \"");
3015 #else /* windows */
3016   TCollection_AsciiString cmd("del /F \"");
3017 #endif
3018
3019   cmd+=filename;
3020   cmd+="\" \"";
3021   cmd+=meshfile;
3022   cmd+="\"";
3023   system(cmd.ToCString());
3024
3025   // MED writer to be used by storage process
3026   DriverMED_W_SMESHDS_Mesh myWriter;
3027   myWriter.SetFile( meshfile.ToCString() );
3028
3029   // IMP issue 20918
3030   // SetStoreName() to groups before storing hypotheses to let them refer to
3031   // groups using "store name", which is "Group <group_persistent_id>"
3032   {
3033     SALOMEDS::ChildIterator_wrap itBig = myCurrentStudy->NewChildIterator( theComponent );
3034     for ( ; itBig->More(); itBig->Next() ) {
3035       SALOMEDS::SObject_wrap gotBranch = itBig->Value();
3036       if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) {
3037         CORBA::Object_var anObject = SObjectToObject( gotBranch );
3038         if ( !CORBA::is_nil( anObject ) ) {
3039           SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ;
3040           if ( !myMesh->_is_nil() ) {
3041             myMesh->Load(); // load from study file if not yet done
3042             TPythonDump pd; // not to dump GetGroups()
3043             SMESH::ListOfGroups_var groups = myMesh->GetGroups();
3044             pd << ""; // to avoid optimizing pd out
3045             for ( int i = 0; i < groups->length(); ++i )
3046             {
3047               SMESH_GroupBase_i* grImpl = SMESH::DownCast<SMESH_GroupBase_i*>( groups[i]);
3048               if ( grImpl )
3049               {
3050                 CORBA::String_var objStr = GetORB()->object_to_string( grImpl->_this() );
3051                 int anId = myStudyContext->findId( string( objStr.in() ) );
3052                 char grpName[ 30 ];
3053                 sprintf( grpName, "Group %d", anId );
3054                 SMESHDS_GroupBase* aGrpBaseDS = grImpl->GetGroupDS();
3055                 aGrpBaseDS->SetStoreName( grpName );
3056               }
3057             }
3058           }
3059         }
3060       }
3061     }
3062   }
3063
3064   // Write data
3065   // ---> create HDF file
3066   aFile = new HDFfile( (char*) filename.ToCString() );
3067   aFile->CreateOnDisk();
3068
3069   // --> iterator for top-level objects
3070   SALOMEDS::ChildIterator_wrap itBig = myCurrentStudy->NewChildIterator( theComponent );
3071   for ( ; itBig->More(); itBig->Next() ) {
3072     SALOMEDS::SObject_wrap gotBranch = itBig->Value();
3073
3074     // --> hypotheses root branch (only one for the study)
3075     if ( gotBranch->Tag() == GetHypothesisRootTag() ) {
3076       // create hypotheses root HDF group
3077       aTopGroup = new HDFgroup( "Hypotheses", aFile );
3078       aTopGroup->CreateOnDisk();
3079
3080       // iterator for all hypotheses
3081       SALOMEDS::ChildIterator_wrap it = myCurrentStudy->NewChildIterator( gotBranch );
3082       for ( ; it->More(); it->Next() ) {
3083         SALOMEDS::SObject_wrap mySObject = it->Value();
3084         CORBA::Object_var anObject = SObjectToObject( mySObject );
3085         if ( !CORBA::is_nil( anObject ) ) {
3086           SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject );
3087           if ( !myHyp->_is_nil() ) {
3088             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
3089             if ( myImpl ) {
3090               string hypname = string( myHyp->GetName() );
3091               string libname = string( myHyp->GetLibName() );
3092               // BUG SWP13062
3093               // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for
3094               // WIN32 and ".so" for X-system) must be deleted
3095               int libname_len = libname.length();
3096 #ifdef WIN32
3097               if( libname_len > 4 )
3098                 libname.resize( libname_len - 4 );
3099 #else
3100               // PAL17753 (Regresion: missing hypothesis in restored study)
3101               // "lib" also should be removed from the beginning
3102               //if( libname_len > 3 )
3103                 //libname.resize( libname_len - 3 );
3104               if( libname_len > 6 )
3105                 libname = libname.substr( 3, libname_len - 3 - 3 );
3106 #endif
3107               CORBA::String_var objStr = GetORB()->object_to_string( anObject );
3108               int    id      = myStudyContext->findId( string( objStr.in() ) );
3109               string hypdata = string( myImpl->SaveTo() );
3110
3111               // for each hypothesis create HDF group basing on its id
3112               char hypGrpName[30];
3113               sprintf( hypGrpName, "Hypothesis %d", id );
3114               aGroup = new HDFgroup( hypGrpName, aTopGroup );
3115               aGroup->CreateOnDisk();
3116               // --> type name of hypothesis
3117               aSize[ 0 ] = hypname.length() + 1;
3118               aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 );
3119               aDataset->CreateOnDisk();
3120               aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) );
3121               aDataset->CloseOnDisk();
3122               // --> server plugin library name of hypothesis
3123               aSize[ 0 ] = libname.length() + 1;
3124               aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 );
3125               aDataset->CreateOnDisk();
3126               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
3127               aDataset->CloseOnDisk();
3128               // --> persistent data of hypothesis
3129               aSize[ 0 ] = hypdata.length() + 1;
3130               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
3131               aDataset->CreateOnDisk();
3132               aDataset->WriteOnDisk( ( char* )( hypdata.c_str() ) );
3133               aDataset->CloseOnDisk();
3134               // close hypothesis HDF group
3135               aGroup->CloseOnDisk();
3136             }
3137           }
3138         }
3139       }
3140       // close hypotheses root HDF group
3141       aTopGroup->CloseOnDisk();
3142     }
3143     // --> algorithms root branch (only one for the study)
3144     else if ( gotBranch->Tag() == GetAlgorithmsRootTag() ) {
3145       // create algorithms root HDF group
3146       aTopGroup = new HDFgroup( "Algorithms", aFile );
3147       aTopGroup->CreateOnDisk();
3148
3149       // iterator for all algorithms
3150       SALOMEDS::ChildIterator_wrap it = myCurrentStudy->NewChildIterator( gotBranch );
3151       for ( ; it->More(); it->Next() ) {
3152         SALOMEDS::SObject_wrap mySObject = it->Value();
3153         CORBA::Object_var anObject = SObjectToObject( mySObject );
3154         if ( !CORBA::is_nil( anObject ) ) {
3155           SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject );
3156           if ( !myHyp->_is_nil() ) {
3157             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
3158             if ( myImpl ) {
3159               string hypname = string( myHyp->GetName() );
3160               string libname = string( myHyp->GetLibName() );
3161               // BUG SWP13062
3162               // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for
3163               // WIN32 and ".so" for X-system) must be deleted
3164               int libname_len = libname.length();
3165 #ifdef WIN32
3166               if( libname_len > 4 )
3167                 libname.resize( libname_len - 4 );
3168 #else
3169               // PAL17753 (Regresion: missing hypothesis in restored study)
3170               // "lib" also should be removed from the beginning
3171               //if( libname_len > 3 )
3172                 //libname.resize( libname_len - 3 );
3173               if( libname_len > 6 )
3174                 libname = libname.substr( 3, libname_len - 3 - 3 );
3175 #endif
3176               CORBA::String_var objStr = GetORB()->object_to_string( anObject );
3177               int    id      = myStudyContext->findId( string( objStr.in() ) );
3178               string hypdata = string( myImpl->SaveTo() );
3179
3180               // for each algorithm create HDF group basing on its id
3181               char hypGrpName[30];
3182               sprintf( hypGrpName, "Algorithm %d", id );
3183               aGroup = new HDFgroup( hypGrpName, aTopGroup );
3184               aGroup->CreateOnDisk();
3185               // --> type name of algorithm
3186               aSize[0] = hypname.length() + 1;
3187               aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 );
3188               aDataset->CreateOnDisk();
3189               aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) );
3190               aDataset->CloseOnDisk();
3191               // --> server plugin library name of hypothesis
3192               aSize[0] = libname.length() + 1;
3193               aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 );
3194               aDataset->CreateOnDisk();
3195               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
3196               aDataset->CloseOnDisk();
3197               // --> persistent data of algorithm
3198               aSize[0] = hypdata.length() + 1;
3199               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
3200               aDataset->CreateOnDisk();
3201               aDataset->WriteOnDisk( ( char* )( hypdata.c_str() ) );
3202               aDataset->CloseOnDisk();
3203               // close algorithm HDF group
3204               aGroup->CloseOnDisk();
3205             }
3206           }
3207         }
3208       }
3209       // close algorithms root HDF group
3210       aTopGroup->CloseOnDisk();
3211     }
3212     // --> mesh objects roots branches
3213     else if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) {
3214       CORBA::Object_var anObject = SObjectToObject( gotBranch );
3215       if ( !CORBA::is_nil( anObject ) ) {
3216         SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ;
3217         if ( !myMesh->_is_nil() ) {
3218           SMESH_Mesh_i* myImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( myMesh ).in() );
3219           if ( myImpl ) {
3220             CORBA::String_var objStr = GetORB()->object_to_string( anObject );
3221             int id = myStudyContext->findId( string( objStr.in() ) );
3222             ::SMESH_Mesh& myLocMesh = myImpl->GetImpl();
3223             SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS();
3224             bool hasShape = myLocMesh.HasShapeToMesh();
3225
3226             // for each mesh open the HDF group basing on its id
3227             char meshGrpName[ 30 ];
3228             sprintf( meshGrpName, "Mesh %d", id );
3229             aTopGroup = new HDFgroup( meshGrpName, aFile );
3230             aTopGroup->CreateOnDisk();
3231
3232             // --> put dataset to hdf file which is a flag that mesh has data
3233             string strHasData = "0";
3234             // check if the mesh is not empty
3235             if ( mySMESHDSMesh->NbNodes() > 0 ) {
3236               // write mesh data to med file
3237               myWriter.SetMesh( mySMESHDSMesh );
3238               myWriter.SetMeshId( id );
3239               strHasData = "1";
3240             }
3241             aSize[ 0 ] = strHasData.length() + 1;
3242             aDataset = new HDFdataset( "Has data", aTopGroup, HDF_STRING, aSize, 1 );
3243             aDataset->CreateOnDisk();
3244             aDataset->WriteOnDisk( ( char* )( strHasData.c_str() ) );
3245             aDataset->CloseOnDisk();
3246
3247             // ouv : NPAL12872
3248             // for each mesh open the HDF group basing on its auto color parameter
3249             char meshAutoColorName[ 30 ];
3250             sprintf( meshAutoColorName, "AutoColorMesh %d", id );
3251             int anAutoColor[1];
3252             anAutoColor[0] = myImpl->GetAutoColor();
3253             aSize[ 0 ] = 1;
3254             aDataset = new HDFdataset( meshAutoColorName, aTopGroup, HDF_INT32, aSize, 1 );
3255             aDataset->CreateOnDisk();
3256             aDataset->WriteOnDisk( anAutoColor );
3257             aDataset->CloseOnDisk();
3258
3259             // issue 0020693. Store _isModified flag
3260             int isModified = myLocMesh.GetIsModified();
3261             aSize[ 0 ] = 1;
3262             aDataset = new HDFdataset( "_isModified", aTopGroup, HDF_INT32, aSize, 1 );
3263             aDataset->CreateOnDisk();
3264             aDataset->WriteOnDisk( &isModified );
3265             aDataset->CloseOnDisk();
3266
3267             // issue 20918. Store Persistent Id of SMESHDS_Mesh
3268             int meshPersistentId = mySMESHDSMesh->GetPersistentId();
3269             aSize[ 0 ] = 1;
3270             aDataset = new HDFdataset( "meshPersistentId", aTopGroup, HDF_INT32, aSize, 1 );
3271             aDataset->CreateOnDisk();
3272             aDataset->WriteOnDisk( &meshPersistentId );
3273             aDataset->CloseOnDisk();
3274
3275             // write reference on a shape if exists
3276             SALOMEDS::SObject_wrap myRef;
3277             bool shapeRefFound = false;
3278             bool found = gotBranch->FindSubObject( GetRefOnShapeTag(), myRef.inout() );
3279             if ( found ) {
3280               SALOMEDS::SObject_wrap myShape;
3281               bool ok = myRef->ReferencedObject( myShape.inout() );
3282               if ( ok ) {
3283                 shapeRefFound = (! CORBA::is_nil( myShape->GetObject() ));
3284                 string myRefOnObject = myShape->GetID();
3285                 if ( shapeRefFound && myRefOnObject.length() > 0 ) {
3286                   aSize[ 0 ] = myRefOnObject.length() + 1;
3287                   aDataset = new HDFdataset( "Ref on shape", aTopGroup, HDF_STRING, aSize, 1 );
3288                   aDataset->CreateOnDisk();
3289                   aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3290                   aDataset->CloseOnDisk();
3291                 }
3292               }
3293             }
3294
3295             // write applied hypotheses if exist
3296             SALOMEDS::SObject_wrap myHypBranch;
3297             found = gotBranch->FindSubObject( GetRefOnAppliedHypothesisTag(), myHypBranch.inout() );
3298             if ( found && !shapeRefFound && hasShape) { // remove applied hyps
3299               myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( myHypBranch );
3300             }
3301             if ( found && (shapeRefFound || !hasShape) ) {
3302               aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup );
3303               aGroup->CreateOnDisk();
3304
3305               SALOMEDS::ChildIterator_wrap it = myCurrentStudy->NewChildIterator( myHypBranch );
3306               int hypNb = 0;
3307               for ( ; it->More(); it->Next() ) {
3308                 SALOMEDS::SObject_wrap mySObject = it->Value();
3309                 SALOMEDS::SObject_wrap myRefOnHyp;
3310                 bool ok = mySObject->ReferencedObject( myRefOnHyp.inout() );
3311                 if ( ok ) {
3312                   // san - it is impossible to recover applied hypotheses
3313                   //       using their entries within Load() method,
3314                   // for there are no AttributeIORs in the study when Load() is working.
3315                   // Hence, it is better to store persistent IDs of hypotheses as references to them
3316
3317                   //string myRefOnObject = myRefOnHyp->GetID();
3318                   CORBA::Object_var anObject = SObjectToObject( myRefOnHyp );
3319                   CORBA::String_var objStr = GetORB()->object_to_string( anObject );
3320                   int id = myStudyContext->findId( string( objStr.in() ) );
3321                   //if ( myRefOnObject.length() > 0 ) {
3322                   //aSize[ 0 ] = myRefOnObject.length() + 1;
3323                   char hypName[ 30 ], hypId[ 30 ];
3324                   sprintf( hypName, "Hyp %d", ++hypNb );
3325                   sprintf( hypId, "%d", id );
3326                   aSize[ 0 ] = strlen( hypId ) + 1;
3327                   aDataset = new HDFdataset( hypName, aGroup, HDF_STRING, aSize, 1 );
3328                   aDataset->CreateOnDisk();
3329                   //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3330                   aDataset->WriteOnDisk( hypId );
3331                   aDataset->CloseOnDisk();
3332                   //}
3333                 }
3334               }
3335               aGroup->CloseOnDisk();
3336             }
3337
3338             // write applied algorithms if exist
3339             SALOMEDS::SObject_wrap myAlgoBranch;
3340             found = gotBranch->FindSubObject( GetRefOnAppliedAlgorithmsTag(),
3341                                               myAlgoBranch.inout() );
3342             if ( found && !shapeRefFound && hasShape) { // remove applied algos
3343               myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( myAlgoBranch );
3344             }
3345             if ( found && (shapeRefFound || !hasShape)) {
3346               aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
3347               aGroup->CreateOnDisk();
3348
3349               SALOMEDS::ChildIterator_wrap it = myCurrentStudy->NewChildIterator( myAlgoBranch );
3350               int algoNb = 0;
3351               for ( ; it->More(); it->Next() ) {
3352                 SALOMEDS::SObject_wrap mySObject = it->Value();
3353                 SALOMEDS::SObject_wrap myRefOnAlgo;
3354                 bool ok = mySObject->ReferencedObject( myRefOnAlgo.inout() );
3355                 if ( ok ) {
3356                   // san - it is impossible to recover applied algorithms
3357                   //       using their entries within Load() method,
3358                   // for there are no AttributeIORs in the study when Load() is working.
3359                   // Hence, it is better to store persistent IDs of algorithms as references to them
3360
3361                   //string myRefOnObject = myRefOnAlgo->GetID();
3362                   CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo );
3363                   CORBA::String_var objStr = GetORB()->object_to_string( anObject );
3364                   int id = myStudyContext->findId( string( objStr.in() ) );
3365                   //if ( myRefOnObject.length() > 0 ) {
3366                   //aSize[ 0 ] = myRefOnObject.length() + 1;
3367                   char algoName[ 30 ], algoId[ 30 ];
3368                   sprintf( algoName, "Algo %d", ++algoNb );
3369                   sprintf( algoId, "%d", id );
3370                   aSize[ 0 ] = strlen( algoId ) + 1;
3371                   aDataset = new HDFdataset( algoName, aGroup, HDF_STRING, aSize, 1 );
3372                   aDataset->CreateOnDisk();
3373                   //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3374                   aDataset->WriteOnDisk( algoId );
3375                   aDataset->CloseOnDisk();
3376                   //}
3377                 }
3378               }
3379               aGroup->CloseOnDisk();
3380             }
3381
3382             // --> submesh objects sub-branches
3383
3384             for ( int i = GetSubMeshOnVertexTag(); i <= GetSubMeshOnCompoundTag(); i++ ) {
3385               SALOMEDS::SObject_wrap mySubmeshBranch;
3386               found = gotBranch->FindSubObject( i, mySubmeshBranch.inout() );
3387
3388               if ( found ) // check if there is shape reference in submeshes
3389               {
3390                 bool hasShapeRef = false;
3391                 SALOMEDS::ChildIterator_wrap itSM =
3392                   myCurrentStudy->NewChildIterator( mySubmeshBranch );
3393                 for ( ; itSM->More(); itSM->Next() ) {
3394                   SALOMEDS::SObject_wrap mySubRef, myShape, mySObject = itSM->Value();
3395                   if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef.inout() ))
3396                     mySubRef->ReferencedObject( myShape.inout() );
3397                   if ( !CORBA::is_nil( myShape ) && !CORBA::is_nil( myShape->GetObject() ))
3398                     hasShapeRef = true;
3399                   else
3400                   { // remove one submesh
3401                     if ( shapeRefFound )
3402                     { // unassign hypothesis
3403                       SMESH::SMESH_subMesh_var mySubMesh =
3404                         SMESH::SMESH_subMesh::_narrow( SObjectToObject( mySObject ));
3405                       if ( !mySubMesh->_is_nil() ) {
3406                         int shapeID = mySubMesh->GetId();
3407                         TopoDS_Shape S = mySMESHDSMesh->IndexToShape( shapeID );
3408                         const list<const SMESHDS_Hypothesis*>& hypList =
3409                           mySMESHDSMesh->GetHypothesis( S );
3410                         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
3411                         while ( hyp != hypList.end() ) {
3412                           int hypID = (*hyp++)->GetID(); // goto next hyp here because
3413                           myLocMesh.RemoveHypothesis( S, hypID ); // hypList changes here
3414                         }
3415                       }
3416                     }
3417                     myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( mySObject );
3418                   }
3419                 } // loop on submeshes of a type
3420                 if ( !shapeRefFound || !hasShapeRef ) { // remove the whole submeshes branch
3421                   myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( mySubmeshBranch );
3422                   found = false;
3423                 }
3424               }  // end check if there is shape reference in submeshes
3425               if ( found ) {
3426                 char name_meshgroup[ 30 ];
3427                 if ( i == GetSubMeshOnVertexTag() )
3428                   strcpy( name_meshgroup, "SubMeshes On Vertex" );
3429                 else if ( i == GetSubMeshOnEdgeTag() )
3430                   strcpy( name_meshgroup, "SubMeshes On Edge" );
3431                 else if ( i == GetSubMeshOnWireTag() )
3432                   strcpy( name_meshgroup, "SubMeshes On Wire" );
3433                 else if ( i == GetSubMeshOnFaceTag() )
3434                   strcpy( name_meshgroup, "SubMeshes On Face" );
3435                 else if ( i == GetSubMeshOnShellTag() )
3436                   strcpy( name_meshgroup, "SubMeshes On Shell" );
3437                 else if ( i == GetSubMeshOnSolidTag() )
3438                   strcpy( name_meshgroup, "SubMeshes On Solid" );
3439                 else if ( i == GetSubMeshOnCompoundTag() )
3440                   strcpy( name_meshgroup, "SubMeshes On Compound" );
3441
3442                 // for each type of submeshes create container HDF group
3443                 aGroup = new HDFgroup( name_meshgroup, aTopGroup );
3444                 aGroup->CreateOnDisk();
3445
3446                 // iterator for all submeshes of given type
3447                 SALOMEDS::ChildIterator_wrap itSM = myCurrentStudy->NewChildIterator( mySubmeshBranch );
3448                 for ( ; itSM->More(); itSM->Next() ) {
3449                   SALOMEDS::SObject_wrap mySObject = itSM->Value();
3450                   CORBA::Object_var anSubObject = SObjectToObject( mySObject );
3451                   if ( !CORBA::is_nil( anSubObject ))
3452                   {
3453                     SMESH::SMESH_subMesh_var mySubMesh = SMESH::SMESH_subMesh::_narrow( anSubObject ) ;
3454                     CORBA::String_var objStr = GetORB()->object_to_string( anSubObject );
3455                     int subid = myStudyContext->findId( string( objStr.in() ) );
3456
3457                     // for each mesh open the HDF group basing on its id
3458                     char submeshGrpName[ 30 ];
3459                     sprintf( submeshGrpName, "SubMesh %d", subid );
3460                     aSubGroup = new HDFgroup( submeshGrpName, aGroup );
3461                     aSubGroup->CreateOnDisk();
3462
3463                     // write reference on a shape, already checked if it exists
3464                     SALOMEDS::SObject_wrap mySubRef, myShape;
3465                     if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef.inout() ))
3466                       mySubRef->ReferencedObject( myShape.inout() );
3467                     string myRefOnObject = myShape->GetID();
3468                     if ( myRefOnObject.length() > 0 ) {
3469                       aSize[ 0 ] = myRefOnObject.length() + 1;
3470                       aDataset = new HDFdataset( "Ref on shape", aSubGroup, HDF_STRING, aSize, 1 );
3471                       aDataset->CreateOnDisk();
3472                       aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3473                       aDataset->CloseOnDisk();
3474                     }
3475
3476                     // write applied hypotheses if exist
3477                     SALOMEDS::SObject_wrap mySubHypBranch;
3478                     found = mySObject->FindSubObject( GetRefOnAppliedHypothesisTag(),
3479                                                       mySubHypBranch.inout() );
3480                     if ( found ) {
3481                       aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup );
3482                       aSubSubGroup->CreateOnDisk();
3483
3484                       SALOMEDS::ChildIterator_wrap it = myCurrentStudy->NewChildIterator( mySubHypBranch );
3485                       int hypNb = 0;
3486                       for ( ; it->More(); it->Next() ) {
3487                         SALOMEDS::SObject_wrap mySubSObject = it->Value();
3488                         SALOMEDS::SObject_wrap myRefOnHyp;
3489                         bool ok = mySubSObject->ReferencedObject( myRefOnHyp.inout() );
3490                         if ( ok ) {
3491                           //string myRefOnObject = myRefOnHyp->GetID();
3492                           CORBA::Object_var anObject = SObjectToObject( myRefOnHyp );
3493                           CORBA::String_var objStr = GetORB()->object_to_string( anObject );
3494                           int id = myStudyContext->findId( string( objStr.in() ) );
3495                           //if ( myRefOnObject.length() > 0 ) {
3496                           //aSize[ 0 ] = myRefOnObject.length() + 1;
3497                           char hypName[ 30 ], hypId[ 30 ];
3498                           sprintf( hypName, "Hyp %d", ++hypNb );
3499                           sprintf( hypId, "%d", id );
3500                           aSize[ 0 ] = strlen( hypId ) + 1;
3501                           aDataset = new HDFdataset( hypName, aSubSubGroup, HDF_STRING, aSize, 1 );
3502                           aDataset->CreateOnDisk();
3503                           //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3504                           aDataset->WriteOnDisk( hypId );
3505                           aDataset->CloseOnDisk();
3506                           //}
3507                         }
3508                       }
3509                       aSubSubGroup->CloseOnDisk();
3510                     }
3511
3512                     // write applied algorithms if exist
3513                     SALOMEDS::SObject_wrap mySubAlgoBranch;
3514                     found = mySObject->FindSubObject( GetRefOnAppliedAlgorithmsTag(),
3515                                                       mySubAlgoBranch.inout() );
3516                     if ( found ) {
3517                       aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup );
3518                       aSubSubGroup->CreateOnDisk();
3519
3520                       SALOMEDS::ChildIterator_wrap it =
3521                         myCurrentStudy->NewChildIterator( mySubAlgoBranch );
3522                       int algoNb = 0;
3523                       for ( ; it->More(); it->Next() ) {
3524                         SALOMEDS::SObject_wrap mySubSObject = it->Value();
3525                         SALOMEDS::SObject_wrap myRefOnAlgo;
3526                         bool ok = mySubSObject->ReferencedObject( myRefOnAlgo.inout() );
3527                         if ( ok ) {
3528                           //string myRefOnObject = myRefOnAlgo->GetID();
3529                           CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo );
3530                           CORBA::String_var objStr = GetORB()->object_to_string( anObject );
3531                           int id = myStudyContext->findId( string( objStr.in() ) );
3532                           //if ( myRefOnObject.length() > 0 ) {
3533                           //aSize[ 0 ] = myRefOnObject.length() + 1;
3534                           char algoName[ 30 ], algoId[ 30 ];
3535                           sprintf( algoName, "Algo %d", ++algoNb );
3536                           sprintf( algoId, "%d", id );
3537                           aSize[ 0 ] = strlen( algoId ) + 1;
3538                           aDataset = new HDFdataset( algoName, aSubSubGroup, HDF_STRING, aSize, 1 );
3539                           aDataset->CreateOnDisk();
3540                           //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3541                           aDataset->WriteOnDisk( algoId );
3542                           aDataset->CloseOnDisk();
3543                           //}
3544                         }
3545                       }
3546                       aSubSubGroup->CloseOnDisk();
3547                     }
3548                     // close submesh HDF group
3549                     aSubGroup->CloseOnDisk();
3550                   }
3551                 }
3552                 // close container of submeshes by type HDF group
3553                 aGroup->CloseOnDisk();
3554               }
3555             }
3556             // All sub-meshes will be stored in MED file
3557             // .. will NOT (PAL 12992)
3558             //if ( shapeRefFound )
3559             //myWriter.AddAllSubMeshes();
3560
3561             // store submesh order if any
3562             const TListOfListOfInt& theOrderIds = myLocMesh.GetMeshOrder();
3563             if ( theOrderIds.size() ) {
3564               char order_list[ 30 ];
3565               strcpy( order_list, "Mesh Order" );
3566               // count number of submesh ids
3567               int nbIDs = 0;
3568               TListOfListOfInt::const_iterator idIt = theOrderIds.begin();
3569               for ( ; idIt != theOrderIds.end(); idIt++ )
3570                 nbIDs += (*idIt).size();
3571               // number of values = number of IDs +
3572               //                    number of lists (for separators) - 1
3573               int* smIDs = new int [ nbIDs + theOrderIds.size() - 1 ];
3574               idIt = theOrderIds.begin();
3575               for ( int i = 0; idIt != theOrderIds.end(); idIt++ ) {
3576                 const TListOfInt& idList = *idIt;
3577                 if (idIt != theOrderIds.begin()) // not first list
3578                   smIDs[ i++ ] = -1/* *idList.size()*/; // separator between lists
3579                 // dump submesh ids from current list
3580                 TListOfInt::const_iterator id_smId = idList.begin();
3581                 for( ; id_smId != idList.end(); id_smId++ )
3582                   smIDs[ i++ ] = *id_smId;
3583               }
3584               // write HDF group
3585               aSize[ 0 ] = nbIDs + theOrderIds.size() - 1;
3586
3587               aDataset = new HDFdataset( order_list, aTopGroup, HDF_INT32, aSize, 1 );
3588               aDataset->CreateOnDisk();
3589               aDataset->WriteOnDisk( smIDs );
3590               aDataset->CloseOnDisk();
3591               //
3592               delete[] smIDs;
3593             }
3594
3595             // groups root sub-branch
3596             SALOMEDS::SObject_wrap myGroupsBranch;
3597             for ( int i = GetNodeGroupsTag(); i <= GetBallElementsGroupsTag(); i++ ) {
3598               found = gotBranch->FindSubObject( i, myGroupsBranch.inout() );
3599               if ( found ) {
3600                 char name_group[ 30 ];
3601                 if ( i == GetNodeGroupsTag() )
3602                   strcpy( name_group, "Groups of Nodes" );
3603                 else if ( i == GetEdgeGroupsTag() )
3604                   strcpy( name_group, "Groups of Edges" );
3605                 else if ( i == GetFaceGroupsTag() )
3606                   strcpy( name_group, "Groups of Faces" );
3607                 else if ( i == GetVolumeGroupsTag() )
3608                   strcpy( name_group, "Groups of Volumes" );
3609                 else if ( i == Get0DElementsGroupsTag() )
3610                   strcpy( name_group, "Groups of 0D Elements" );
3611                 else if ( i == GetBallElementsGroupsTag() )
3612                   strcpy( name_group, "Groups of Balls" );
3613
3614                 aGroup = new HDFgroup( name_group, aTopGroup );
3615                 aGroup->CreateOnDisk();
3616
3617                 SALOMEDS::ChildIterator_wrap it = myCurrentStudy->NewChildIterator( myGroupsBranch );
3618                 for ( ; it->More(); it->Next() ) {
3619                   SALOMEDS::SObject_wrap mySObject = it->Value();
3620                   CORBA::Object_var aSubObject = SObjectToObject( mySObject );
3621                   if ( !CORBA::is_nil( aSubObject ) ) {
3622                     SMESH_GroupBase_i* myGroupImpl =
3623                       dynamic_cast<SMESH_GroupBase_i*>( GetServant( aSubObject ).in() );
3624                     if ( !myGroupImpl )
3625                       continue;
3626                     SMESHDS_GroupBase* aGrpBaseDS = myGroupImpl->GetGroupDS();
3627                     if ( !aGrpBaseDS )
3628                       continue;
3629
3630                     CORBA::String_var objStr = GetORB()->object_to_string( aSubObject );
3631                     int anId = myStudyContext->findId( string( objStr.in() ) );
3632
3633                     // For each group, create a dataset named "Group <group_persistent_id>"
3634                     // and store the group's user name into it
3635                     const char* grpName = aGrpBaseDS->GetStoreName();
3636                     char* aUserName = myGroupImpl->GetName();
3637                     aSize[ 0 ] = strlen( aUserName ) + 1;
3638
3639                     aDataset = new HDFdataset( grpName, aGroup, HDF_STRING, aSize, 1 );
3640                     aDataset->CreateOnDisk();
3641                     aDataset->WriteOnDisk( aUserName );
3642                     aDataset->CloseOnDisk();
3643
3644                     // ouv : NPAL12872
3645                     // For each group, create a dataset named "Group <group_persistent_id> Color"
3646                     // and store the group's color into it
3647                     char grpColorName[ 30 ];
3648                     sprintf( grpColorName, "ColorGroup %d", anId );
3649                     SALOMEDS::Color aColor = myGroupImpl->GetColor();
3650                     double anRGB[3];
3651                     anRGB[ 0 ] = aColor.R;
3652                     anRGB[ 1 ] = aColor.G;
3653                     anRGB[ 2 ] = aColor.B;
3654                     aSize[ 0 ] = 3;
3655                     aDataset = new HDFdataset( grpColorName, aGroup, HDF_FLOAT64, aSize, 1 );
3656                     aDataset->CreateOnDisk();
3657                     aDataset->WriteOnDisk( anRGB );
3658                     aDataset->CloseOnDisk();
3659
3660                     // Pass SMESHDS_Group to MED writer
3661                     SMESHDS_Group* aGrpDS = dynamic_cast<SMESHDS_Group*>( aGrpBaseDS );
3662                     if ( aGrpDS )
3663                       myWriter.AddGroup( aGrpDS );
3664
3665                     // write reference on a shape if exists
3666                     SMESHDS_GroupOnGeom* aGeomGrp =
3667                       dynamic_cast<SMESHDS_GroupOnGeom*>( aGrpBaseDS );
3668                     if ( aGeomGrp ) {
3669                       SALOMEDS::SObject_wrap mySubRef, myShape;
3670                       if (mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef.inout() ) &&
3671                           mySubRef->ReferencedObject( myShape.inout() ) &&
3672                           !CORBA::is_nil( myShape->GetObject() ))
3673                       {
3674                         string myRefOnObject = myShape->GetID();
3675                         if ( myRefOnObject.length() > 0 ) {
3676                           char aRefName[ 30 ];
3677                           sprintf( aRefName, "Ref on shape %d", anId);
3678                           aSize[ 0 ] = myRefOnObject.length() + 1;
3679                           aDataset = new HDFdataset(aRefName, aGroup, HDF_STRING, aSize, 1);
3680                           aDataset->CreateOnDisk();
3681                           aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
3682                           aDataset->CloseOnDisk();
3683                         }
3684                       }
3685                       else // shape ref is invalid:
3686                       {
3687                         // save a group on geometry as ordinary group
3688                         myWriter.AddGroup( aGeomGrp );
3689                       }
3690                     }
3691                     else if ( SMESH_GroupOnFilter_i* aFilterGrp_i = 
3692                               dynamic_cast<SMESH_GroupOnFilter_i*>( myGroupImpl ))
3693                     {
3694                       std::string str = aFilterGrp_i->FilterToString();
3695                       std::string hdfGrpName = "Filter " + SMESH_Comment(anId);
3696                       aSize[ 0 ] = str.length() + 1;
3697                       aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup, HDF_STRING, aSize, 1);
3698                       aDataset->CreateOnDisk();
3699                       aDataset->WriteOnDisk( ( char* )( str.c_str() ) );
3700                       aDataset->CloseOnDisk();
3701                     }
3702                   }
3703                 }
3704                 aGroup->CloseOnDisk();
3705               }
3706             } // loop on groups
3707
3708             if ( strcmp( strHasData.c_str(), "1" ) == 0 )
3709             {
3710               // Flush current mesh information into MED file
3711               myWriter.Perform();
3712
3713               // save info on nb of elements
3714               SMESH_PreMeshInfo::SaveToFile( myImpl, id, aFile );
3715
3716               // maybe a shape was deleted in the study
3717               if ( !shapeRefFound && !mySMESHDSMesh->ShapeToMesh().IsNull() && hasShape) {
3718                 TopoDS_Shape nullShape;
3719                 myLocMesh.ShapeToMesh( nullShape ); // remove shape referring data
3720               }
3721
3722               SMESHDS_SubMeshIteratorPtr smIt = mySMESHDSMesh->SubMeshes();
3723               if ( smIt->more() )
3724               {
3725                 // Store submeshes
3726                 // ----------------
3727                 aGroup = new HDFgroup( "Submeshes", aTopGroup );
3728                 aGroup->CreateOnDisk();
3729
3730                 // each element belongs to one or none submesh,
3731                 // so for each node/element, we store a submesh ID
3732
3733                 // Store submesh IDs
3734                 for ( int isNode = 0; isNode < 2; ++isNode )
3735                 {
3736                   SMDS_ElemIteratorPtr eIt =
3737                     mySMESHDSMesh->elementsIterator( isNode ? SMDSAbs_Node : SMDSAbs_All );
3738                   int nbElems = isNode ? mySMESHDSMesh->NbNodes() : mySMESHDSMesh->GetMeshInfo().NbElements();
3739                   if ( nbElems < 1 )
3740                     continue;
3741                   std::vector<int> smIDs; smIDs.reserve( nbElems );
3742                   while ( eIt->more() )
3743                     if ( const SMDS_MeshElement* e = eIt->next())
3744                       smIDs.push_back( e->getshapeId() );
3745                   // write HDF group
3746                   aSize[ 0 ] = nbElems;
3747                   string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
3748                   aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_INT32, aSize, 1 );
3749                   aDataset->CreateOnDisk();
3750                   aDataset->WriteOnDisk( & smIDs[0] );
3751                   aDataset->CloseOnDisk();
3752                 }
3753
3754                 aGroup->CloseOnDisk();
3755
3756                 // Store node positions on sub-shapes (SMDS_Position):
3757                 // ----------------------------------------------------
3758
3759                 aGroup = new HDFgroup( "Node Positions", aTopGroup );
3760                 aGroup->CreateOnDisk();
3761
3762                 // in aGroup, create 5 datasets to contain:
3763                 // "Nodes on Edges" - ID of node on edge
3764                 // "Edge positions" - U parameter on node on edge
3765                 // "Nodes on Faces" - ID of node on face
3766                 // "Face U positions" - U parameter of node on face
3767                 // "Face V positions" - V parameter of node on face
3768
3769                 // Find out nb of nodes on edges and faces
3770                 // Collect corresponing sub-meshes
3771                 int nbEdgeNodes = 0, nbFaceNodes = 0;
3772                 list<SMESHDS_SubMesh*> aEdgeSM, aFaceSM;
3773                 // loop on SMESHDS_SubMesh'es
3774                 while ( smIt->more() )
3775                 {
3776                   SMESHDS_SubMesh* aSubMesh = const_cast< SMESHDS_SubMesh* >( smIt->next() );
3777                   if ( aSubMesh->IsComplexSubmesh() )
3778                     continue; // submesh containing other submeshs
3779                   int nbNodes = aSubMesh->NbNodes();
3780                   if ( nbNodes == 0 ) continue;
3781
3782                   int aShapeID = aSubMesh->GetID();
3783                   if ( aShapeID < 1 || aShapeID > mySMESHDSMesh->MaxShapeIndex() )
3784                     continue;
3785                   int aShapeType = mySMESHDSMesh->IndexToShape( aShapeID ).ShapeType();
3786                   // write only SMDS_FacePosition and SMDS_EdgePosition
3787                   switch ( aShapeType ) {
3788                   case TopAbs_FACE:
3789                     nbFaceNodes += nbNodes;
3790                     aFaceSM.push_back( aSubMesh );
3791                     break;
3792                   case TopAbs_EDGE:
3793                     nbEdgeNodes += nbNodes;
3794                     aEdgeSM.push_back( aSubMesh );
3795                     break;
3796                   default:
3797                     continue;
3798                   }
3799                 }
3800                 // Treat positions on edges or faces
3801                 for ( int onFace = 0; onFace < 2; onFace++ )
3802                 {
3803                   // Create arrays to store in datasets
3804                   int iNode = 0, nbNodes = ( onFace ? nbFaceNodes : nbEdgeNodes );
3805                   if (!nbNodes) continue;
3806                   int* aNodeIDs = new int [ nbNodes ];
3807                   double* aUPos = new double [ nbNodes ];
3808                   double* aVPos = ( onFace ? new double[ nbNodes ] : 0 );
3809
3810                   // Fill arrays
3811                   // loop on sub-meshes
3812                   list<SMESHDS_SubMesh*> * pListSM = ( onFace ? &aFaceSM : &aEdgeSM );
3813                   list<SMESHDS_SubMesh*>::iterator itSM = pListSM->begin();
3814                   for ( ; itSM != pListSM->end(); itSM++ )
3815                   {
3816                     SMESHDS_SubMesh* aSubMesh = (*itSM);
3817
3818                     SMDS_NodeIteratorPtr itNode = aSubMesh->GetNodes();
3819                     // loop on nodes in aSubMesh
3820                     while ( itNode->more() )
3821                     {
3822                       //node ID
3823                       const SMDS_MeshNode* node = itNode->next();
3824                       aNodeIDs [ iNode ] = node->GetID();
3825
3826                       // Position
3827                       const SMDS_PositionPtr pos = node->GetPosition();
3828                       if ( onFace ) { // on FACE
3829                         const SMDS_FacePosition* fPos =
3830                           dynamic_cast<const SMDS_FacePosition*>( pos );
3831                         if ( fPos ) {
3832                           aUPos[ iNode ] = fPos->GetUParameter();
3833                           aVPos[ iNode ] = fPos->GetVParameter();
3834                           iNode++;
3835                         }
3836                         else
3837                           nbNodes--;
3838                       }
3839                       else { // on EDGE
3840                         const SMDS_EdgePosition* ePos =
3841                           dynamic_cast<const SMDS_EdgePosition*>( pos );
3842                         if ( ePos ) {
3843                           aUPos[ iNode ] = ePos->GetUParameter();
3844                           iNode++;
3845                         }
3846                         else
3847                           nbNodes--;
3848                       }
3849                     } // loop on nodes in aSubMesh
3850                   } // loop on sub-meshes
3851
3852                   // Write datasets
3853                   if ( nbNodes )
3854                   {
3855                     aSize[ 0 ] = nbNodes;
3856                     // IDS
3857                     string aDSName( onFace ? "Nodes on Faces" : "Nodes on Edges");
3858                     aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_INT32, aSize, 1 );
3859                     aDataset->CreateOnDisk();
3860                     aDataset->WriteOnDisk( aNodeIDs );
3861                     aDataset->CloseOnDisk();
3862
3863                     // U Positions
3864                     aDSName = ( onFace ? "Face U positions" : "Edge positions");
3865                     aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_FLOAT64, aSize, 1);
3866                     aDataset->CreateOnDisk();
3867                     aDataset->WriteOnDisk( aUPos );
3868                     aDataset->CloseOnDisk();
3869                     // V Positions
3870                     if ( onFace ) {
3871                       aDataset = new HDFdataset( "Face V positions", aGroup, HDF_FLOAT64, aSize, 1);
3872                       aDataset->CreateOnDisk();
3873                       aDataset->WriteOnDisk( aVPos );
3874                       aDataset->CloseOnDisk();
3875                     }
3876                   }
3877                   delete [] aNodeIDs;
3878                   delete [] aUPos;
3879                   if ( aVPos ) delete [] aVPos;
3880
3881                 } // treat positions on edges or faces
3882
3883                 // close "Node Positions" group
3884                 aGroup->CloseOnDisk();
3885
3886               } // if ( there are submeshes in SMESHDS_Mesh )
3887             } // if ( hasData )
3888
3889             // close mesh HDF group
3890             aTopGroup->CloseOnDisk();
3891           }
3892         }
3893       }
3894     }
3895   }
3896
3897   // close HDF file
3898   aFile->CloseOnDisk();
3899   delete aFile;
3900
3901   // Convert temporary files to stream
3902   aStreamFile = SALOMEDS_Tool::PutFilesToStream( tmpDir.ToCString(), aFileSeq.in(), isMultiFile );
3903
3904   // Remove temporary files and directory
3905   if ( !isMultiFile )
3906     SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
3907
3908   INFOS( "SMESH_Gen_i::Save() completed" );
3909   return aStreamFile._retn();
3910 }
3911
3912 //=============================================================================
3913 /*!
3914  *  SMESH_Gen_i::SaveASCII
3915  *
3916  *  Save SMESH module's data in ASCII format
3917  */
3918 //=============================================================================
3919
3920 SALOMEDS::TMPFile* SMESH_Gen_i::SaveASCII( SALOMEDS::SComponent_ptr theComponent,
3921                                            const char*              theURL,
3922                                            bool                     isMultiFile ) {
3923   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::SaveASCII" );
3924   SALOMEDS::TMPFile_var aStreamFile = Save( theComponent, theURL, isMultiFile );
3925   return aStreamFile._retn();
3926
3927   //after usual saving needs to encipher binary to text string
3928   //Any binary symbol will be represent as "|xx" () hexadecimal format number
3929   int size = aStreamFile.in().length();
3930   _CORBA_Octet* buffer = new _CORBA_Octet[size*3+1];
3931   for ( int i = 0; i < size; i++ )
3932     sprintf( (char*)&(buffer[i*3]), "|%02x", aStreamFile[i] );
3933
3934   buffer[size * 3] = '\0';
3935
3936   SALOMEDS::TMPFile_var anAsciiStreamFile = new SALOMEDS::TMPFile(size*3, size*3, buffer, 1);
3937
3938   return anAsciiStreamFile._retn();
3939 }
3940
3941 //=============================================================================
3942 /*!
3943  *  SMESH_Gen_i::loadGeomData
3944  *
3945  *  Load GEOM module data
3946  */
3947 //=============================================================================
3948
3949 void SMESH_Gen_i::loadGeomData( SALOMEDS::SComponent_ptr theCompRoot )
3950 {
3951   if ( theCompRoot->_is_nil() )
3952     return;
3953
3954   SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow( theCompRoot->GetStudy() );
3955   if ( aStudy->_is_nil() )
3956     return;
3957
3958   SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
3959   aStudyBuilder->LoadWith( theCompRoot, GetGeomEngine() );
3960 }
3961
3962 //=============================================================================
3963 /*!
3964  *  SMESH_Gen_i::Load
3965  *
3966  *  Load SMESH module's data
3967  */
3968 //=============================================================================
3969
3970 bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
3971                         const SALOMEDS::TMPFile& theStream,
3972                         const char*              theURL,
3973                         bool                     isMultiFile )
3974 {
3975   INFOS( "SMESH_Gen_i::Load" );
3976
3977   if ( theComponent->GetStudy()->StudyId() != GetCurrentStudyID() )
3978     SetCurrentStudy( theComponent->GetStudy() );
3979
3980   /*  if( !theComponent->_is_nil() )
3981       {
3982       //SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow( theComponent->GetStudy() );
3983       if( !myCurrentStudy->FindComponent( "GEOM" )->_is_nil() )
3984       loadGeomData( myCurrentStudy->FindComponent( "GEOM" ) );
3985       }*/
3986
3987   StudyContext* myStudyContext = GetCurrentStudyContext();
3988
3989   // Get temporary files location
3990   TCollection_AsciiString tmpDir =
3991     ( char* )( isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir().c_str() );
3992
3993   INFOS( "THE URL++++++++++++++" );
3994   INFOS( theURL );
3995   INFOS( "THE TMP PATH+++++++++" );
3996   INFOS( tmpDir );
3997
3998   // Convert the stream into sequence of files to process
3999   SALOMEDS::ListOfFileNames_var aFileSeq = SALOMEDS_Tool::PutStreamToFiles( theStream,
4000                                                                             tmpDir.ToCString(),
4001                                                                             isMultiFile );
4002   TCollection_AsciiString aStudyName( "" );
4003   if ( isMultiFile ) {
4004     CORBA::String_var url = myCurrentStudy->URL();
4005     aStudyName = (char*)SALOMEDS_Tool::GetNameFromPath( url.in() ).c_str();
4006   }
4007   // Set names of temporary files
4008   TCollection_AsciiString filename = tmpDir + aStudyName + "_SMESH.hdf";
4009   TCollection_AsciiString meshfile = tmpDir + aStudyName + "_SMESH_Mesh.med";
4010
4011   int size;
4012   HDFfile*    aFile;
4013   HDFdataset* aDataset;
4014   HDFgroup*   aTopGroup;
4015   HDFgroup*   aGroup;
4016   HDFgroup*   aSubGroup;
4017   HDFgroup*   aSubSubGroup;
4018
4019   // Read data
4020   // ---> open HDF file
4021   aFile = new HDFfile( (char*) filename.ToCString() );
4022   try {
4023     aFile->OpenOnDisk( HDF_RDONLY );
4024   }
4025   catch ( HDFexception ) {
4026     INFOS( "Load(): " << filename << " not found!" );
4027     return false;
4028   }
4029
4030   TPythonDump pd; // prevent dump during loading
4031
4032   // DriverMED_R_SMESHDS_Mesh myReader;
4033   // myReader.SetFile( meshfile.ToCString() );
4034
4035   // For PAL13473 ("Repetitive mesh") implementation.
4036   // New dependencies between SMESH objects are established:
4037   // now hypotheses can refer to meshes, shapes and other hypotheses.
4038   // To keep data consistent, the following order of data restoration
4039   // imposed:
4040   // 1. Create hypotheses
4041   // 2. Create all meshes
4042   // 3. Load hypotheses' data
4043   // 4. All the rest
4044
4045   list< pair< SMESH_Hypothesis_i*, string > >    hypDataList;
4046   list< pair< SMESH_Mesh_i*,       HDFgroup* > > meshGroupList;
4047   list< SMESH::Filter_var >                      filters;
4048
4049   // get total number of top-level groups
4050   int aNbGroups = aFile->nInternalObjects();
4051   if ( aNbGroups > 0 ) {
4052     // --> in first turn we should read&create hypotheses
4053     if ( aFile->ExistInternalObject( "Hypotheses" ) ) {
4054       // open hypotheses root HDF group
4055       aTopGroup = new HDFgroup( "Hypotheses", aFile );
4056       aTopGroup->OpenOnDisk();
4057
4058       // get number of hypotheses
4059       int aNbObjects = aTopGroup->nInternalObjects();
4060       for ( int j = 0; j < aNbObjects; j++ ) {
4061         // try to identify hypothesis
4062         char hypGrpName[ HDF_NAME_MAX_LEN+1 ];
4063         aTopGroup->InternalObjectIndentify( j, hypGrpName );
4064
4065         if ( string( hypGrpName ).substr( 0, 10 ) == string( "Hypothesis" ) ) {
4066           // open hypothesis group
4067           aGroup = new HDFgroup( hypGrpName, aTopGroup );
4068           aGroup->OpenOnDisk();
4069
4070           // --> get hypothesis id
4071           int    id = atoi( string( hypGrpName ).substr( 10 ).c_str() );
4072           string hypname;
4073           string libname;
4074           string hypdata;
4075
4076           // get number of datasets
4077           int aNbSubObjects = aGroup->nInternalObjects();
4078           for ( int k = 0; k < aNbSubObjects; k++ ) {
4079             // identify dataset
4080             char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ];
4081             aGroup->InternalObjectIndentify( k, name_of_subgroup );
4082             // --> get hypothesis name
4083             if ( strcmp( name_of_subgroup, "Name"  ) == 0 ) {
4084               aDataset = new HDFdataset( name_of_subgroup, aGroup );
4085               aDataset->OpenOnDisk();
4086               size = aDataset->GetSize();
4087               char* hypname_str = new char[ size ];
4088               aDataset->ReadFromDisk( hypname_str );
4089               hypname = string( hypname_str );
4090               delete [] hypname_str;
4091               aDataset->CloseOnDisk();
4092             }
4093             // --> get hypothesis plugin library name
4094             if ( strcmp( name_of_subgroup, "LibName"  ) == 0 ) {
4095               aDataset = new HDFdataset( name_of_subgroup, aGroup );
4096               aDataset->OpenOnDisk();
4097               size = aDataset->GetSize();
4098               char* libname_str = new char[ size ];
4099               aDataset->ReadFromDisk( libname_str );
4100               if(MYDEBUG) SCRUTE( libname_str );
4101               libname = string( libname_str );
4102               delete [] libname_str;
4103               aDataset->CloseOnDisk();
4104             }
4105             // --> get hypothesis data
4106             if ( strcmp( name_of_subgroup, "Data"  ) == 0 ) {
4107               aDataset = new HDFdataset( name_of_subgroup, aGroup );
4108               aDataset->OpenOnDisk();
4109               size = aDataset->GetSize();
4110               char* hypdata_str = new char[ size ];
4111               aDataset->ReadFromDisk( hypdata_str );
4112               hypdata = string( hypdata_str );
4113               delete [] hypdata_str;
4114               aDataset->CloseOnDisk();
4115             }
4116           }
4117           // close hypothesis HDF group
4118           aGroup->CloseOnDisk();
4119
4120           // --> restore hypothesis from data
4121           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
4122             if(MYDEBUG) MESSAGE("VSR - load hypothesis : id = " << id <<
4123                                 ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
4124             SMESH::SMESH_Hypothesis_var myHyp;
4125
4126             try { // protect persistence mechanism against exceptions
4127               myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() );
4128             }
4129             catch (...) {
4130               INFOS( "Exception during hypothesis creation" );
4131             }
4132
4133             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
4134             if ( myImpl ) {
4135               // myImpl->LoadFrom( hypdata.c_str() );
4136               hypDataList.push_back( make_pair( myImpl, hypdata ));
4137               CORBA::String_var iorString = GetORB()->object_to_string( myHyp );
4138               int newId = myStudyContext->findId( iorString.in() );
4139               myStudyContext->mapOldToNew( id, newId );
4140             }
4141             else
4142               if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
4143           }
4144         }
4145       }
4146       // close hypotheses root HDF group
4147       aTopGroup->CloseOnDisk();
4148       aTopGroup = 0;
4149     }
4150
4151     // --> then we should read&create algorithms
4152     if ( aFile->ExistInternalObject( "Algorithms" ) ) {
4153       // open algorithms root HDF group
4154       aTopGroup = new HDFgroup( "Algorithms", aFile );
4155       aTopGroup->OpenOnDisk();
4156
4157       // get number of algorithms
4158       int aNbObjects = aTopGroup->nInternalObjects();
4159       for ( int j = 0; j < aNbObjects; j++ ) {
4160         // try to identify algorithm
4161         char hypGrpName[ HDF_NAME_MAX_LEN+1 ];
4162         aTopGroup->InternalObjectIndentify( j, hypGrpName );
4163
4164         if ( string( hypGrpName ).substr( 0, 9 ) == string( "Algorithm" ) ) {
4165           // open algorithm group
4166           aGroup = new HDFgroup( hypGrpName, aTopGroup );
4167           aGroup->OpenOnDisk();
4168
4169           // --> get algorithm id
4170           int    id = atoi( string( hypGrpName ).substr( 9 ).c_str() );
4171           string hypname;
4172           string libname;
4173           string hypdata;
4174
4175           // get number of datasets
4176           int aNbSubObjects = aGroup->nInternalObjects();
4177           for ( int k = 0; k < aNbSubObjects; k++ ) {
4178             // identify dataset
4179             char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ];
4180             aGroup->InternalObjectIndentify( k, name_of_subgroup );
4181             // --> get algorithm name
4182             if ( strcmp( name_of_subgroup, "Name"  ) == 0 ) {
4183               aDataset = new HDFdataset( name_of_subgroup, aGroup );
4184               aDataset->OpenOnDisk();
4185               size = aDataset->GetSize();
4186               char* hypname_str = new char[ size ];
4187               aDataset->ReadFromDisk( hypname_str );
4188               hypname = string( hypname_str );
4189               delete [] hypname_str;
4190               aDataset->CloseOnDisk();
4191             }
4192             // --> get algorithm plugin library name
4193             if ( strcmp( name_of_subgroup, "LibName"  ) == 0 ) {
4194               aDataset = new HDFdataset( name_of_subgroup, aGroup );
4195               aDataset->OpenOnDisk();
4196               size = aDataset->GetSize();
4197               char* libname_str = new char[ size ];
4198               aDataset->ReadFromDisk( libname_str );
4199               if(MYDEBUG) SCRUTE( libname_str );
4200               libname = string( libname_str );
4201               delete [] libname_str;
4202               aDataset->CloseOnDisk();
4203             }
4204             // --> get algorithm data
4205             if ( strcmp( name_of_subgroup, "Data"  ) == 0 ) {
4206               aDataset = new HDFdataset( name_of_subgroup, aGroup );
4207               aDataset->OpenOnDisk();
4208               size = aDataset->GetSize();
4209               char* hypdata_str = new char[ size ];
4210               aDataset->ReadFromDisk( hypdata_str );
4211               if(MYDEBUG) SCRUTE( hypdata_str );
4212               hypdata = string( hypdata_str );
4213               delete [] hypdata_str;
4214               aDataset->CloseOnDisk();
4215             }
4216           }
4217           // close algorithm HDF group
4218           aGroup->CloseOnDisk();
4219
4220           // --> restore algorithm from data
4221           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
4222             if(MYDEBUG) MESSAGE("VSR - load algo : id = " << id <<
4223                                 ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
4224             SMESH::SMESH_Hypothesis_var myHyp;
4225
4226             try { // protect persistence mechanism against exceptions
4227               myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() );
4228             }
4229             catch (...) {
4230               INFOS( "Exception during hypothesis creation" );
4231             }
4232
4233             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
4234             if ( myImpl ) {
4235               //myImpl->LoadFrom( hypdata.c_str() );
4236               hypDataList.push_back( make_pair( myImpl, hypdata ));
4237               CORBA::String_var iorString = GetORB()->object_to_string( myHyp );
4238               int newId = myStudyContext->findId( iorString.in() );
4239               myStudyContext->mapOldToNew( id, newId );
4240             }
4241             else
4242               if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
4243           }
4244         }
4245       }
4246       // close algorithms root HDF group
4247       aTopGroup->CloseOnDisk();
4248       aTopGroup = 0;
4249     }
4250
4251     // --> the rest groups should be meshes
4252     for ( int i = 0; i < aNbGroups; i++ ) {
4253       // identify next group
4254       char meshName[ HDF_NAME_MAX_LEN+1 ];
4255       aFile->InternalObjectIndentify( i, meshName );
4256
4257       if ( string( meshName ).substr( 0, 4 ) == string( "Mesh" ) ) {
4258         // --> get mesh id
4259         int id = atoi( string( meshName ).substr( 4 ).c_str() );
4260         if ( id <= 0 )
4261           continue;
4262
4263         // open mesh HDF group
4264         aTopGroup = new HDFgroup( meshName, aFile );
4265         aTopGroup->OpenOnDisk();
4266
4267         // get number of child HDF objects
4268         int aNbObjects = aTopGroup->nInternalObjects();
4269         if ( aNbObjects > 0 ) {
4270           // create mesh
4271           if(MYDEBUG) MESSAGE( "VSR - load mesh : id = " << id );
4272           SMESH::SMESH_Mesh_var myNewMesh = this->createMesh();
4273           SMESH_Mesh_i* myNewMeshImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( myNewMesh ).in() );
4274           if ( !myNewMeshImpl )
4275             continue;
4276           meshGroupList.push_back( make_pair( myNewMeshImpl, aTopGroup ));
4277
4278           CORBA::String_var iorString = GetORB()->object_to_string( myNewMesh );
4279           int newId = myStudyContext->findId( iorString.in() );
4280           myStudyContext->mapOldToNew( id, newId );
4281
4282           // ouv : NPAL12872
4283           // try to read and set auto color flag
4284           char aMeshAutoColorName[ 30 ];
4285           sprintf( aMeshAutoColorName, "AutoColorMesh %d", id);
4286           if( aTopGroup->ExistInternalObject( aMeshAutoColorName ) )
4287           {
4288             aDataset = new HDFdataset( aMeshAutoColorName, aTopGroup );
4289             aDataset->OpenOnDisk();
4290             size = aDataset->GetSize();
4291             int* anAutoColor = new int[ size ];
4292             aDataset->ReadFromDisk( anAutoColor );
4293             aDataset->CloseOnDisk();
4294             myNewMeshImpl->GetImpl().SetAutoColor( (bool)anAutoColor[0] );
4295             delete [] anAutoColor;
4296           }
4297
4298           // try to read and set reference to shape
4299           GEOM::GEOM_Object_var aShapeObject;
4300           if ( aTopGroup->ExistInternalObject( "Ref on shape" ) ) {
4301             // load mesh "Ref on shape" - it's an entry to SObject
4302             aDataset = new HDFdataset( "Ref on shape", aTopGroup );
4303             aDataset->OpenOnDisk();
4304             size = aDataset->GetSize();
4305             char* refFromFile = new char[ size ];
4306             aDataset->ReadFromDisk( refFromFile );
4307             aDataset->CloseOnDisk();
4308             if ( strlen( refFromFile ) > 0 ) {
4309               SALOMEDS::SObject_wrap shapeSO = myCurrentStudy->FindObjectID( refFromFile );
4310
4311               // Make sure GEOM data are loaded first
4312               //loadGeomData( shapeSO->GetFatherComponent() );
4313
4314               CORBA::Object_var shapeObject = SObjectToObject( shapeSO );
4315               if ( !CORBA::is_nil( shapeObject ) ) {
4316                 aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
4317                 if ( !aShapeObject->_is_nil() )
4318                   myNewMeshImpl->SetShape( aShapeObject );
4319               }
4320             }
4321             delete [] refFromFile;
4322           }
4323
4324           // issue 20918. Restore Persistent Id of SMESHDS_Mesh
4325           if( aTopGroup->ExistInternalObject( "meshPersistentId" ) )
4326           {
4327             aDataset = new HDFdataset( "meshPersistentId", aTopGroup );
4328             aDataset->OpenOnDisk();
4329             size = aDataset->GetSize();
4330             int* meshPersistentId = new int[ size ];
4331             aDataset->ReadFromDisk( meshPersistentId );
4332             aDataset->CloseOnDisk();
4333             myNewMeshImpl->GetImpl().GetMeshDS()->SetPersistentId( *meshPersistentId );
4334             delete [] meshPersistentId;
4335           }
4336         }
4337       }
4338     } // reading MESHes
4339
4340     // As all object that can be referred by hypothesis are created,
4341     // we can restore hypothesis data
4342
4343     list< pair< SMESH_Hypothesis_i*, string > >::iterator hyp_data;
4344     for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data )
4345     {
4346       SMESH_Hypothesis_i* hyp  = hyp_data->first;
4347       string &            data = hyp_data->second;
4348       hyp->LoadFrom( data.c_str() );
4349     }
4350
4351     // Restore the rest mesh data
4352
4353     list< pair< SMESH_Mesh_i*, HDFgroup* > >::iterator meshi_group;
4354     for ( meshi_group = meshGroupList.begin(); meshi_group != meshGroupList.end(); ++meshi_group )
4355     {
4356       aTopGroup                   = meshi_group->second;
4357       SMESH_Mesh_i* myNewMeshImpl = meshi_group->first;
4358       //::SMESH_Mesh& myLocMesh     = myNewMeshImpl->GetImpl();
4359       //SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS();
4360
4361       GEOM::GEOM_Object_var aShapeObject = myNewMeshImpl->GetShapeToMesh();
4362       bool hasData = false;
4363
4364       // get mesh old id
4365       CORBA::String_var iorString = GetORB()->object_to_string( myNewMeshImpl->_this() );
4366       int newId = myStudyContext->findId( iorString.in() );
4367       int id = myStudyContext->getOldId( newId );
4368
4369       // try to find mesh data dataset
4370       if ( aTopGroup->ExistInternalObject( "Has data" ) ) {
4371         // load mesh "has data" flag
4372         aDataset = new HDFdataset( "Has data", aTopGroup );
4373         aDataset->OpenOnDisk();
4374         size = aDataset->GetSize();
4375         char* strHasData = new char[ size ];
4376         aDataset->ReadFromDisk( strHasData );
4377         aDataset->CloseOnDisk();
4378         if ( strcmp( strHasData, "1") == 0 ) {
4379           // read mesh data from MED file
4380           // myReader.SetMesh( mySMESHDSMesh );
4381           // myReader.SetMeshId( id );
4382           // myReader.Perform();
4383           hasData = true;
4384         }
4385         delete [] strHasData;
4386       }
4387
4388       // Try to get applied ALGORITHMS (mesh is not cleared by algo addition because
4389       // nodes and elements are not yet put into sub-meshes)
4390       if ( aTopGroup->ExistInternalObject( "Applied Algorithms" ) ) {
4391         aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
4392         aGroup->OpenOnDisk();
4393         // get number of applied algorithms
4394         int aNbSubObjects = aGroup->nInternalObjects();
4395         if(MYDEBUG) MESSAGE( "VSR - number of applied algos " << aNbSubObjects );
4396         for ( int j = 0; j < aNbSubObjects; j++ ) {
4397           char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4398           aGroup->InternalObjectIndentify( j, name_dataset );
4399           // check if it is an algorithm
4400           if ( string( name_dataset ).substr( 0, 4 ) == string( "Algo" ) ) {
4401             aDataset = new HDFdataset( name_dataset, aGroup );
4402             aDataset->OpenOnDisk();
4403             size = aDataset->GetSize();
4404             char* refFromFile = new char[ size ];
4405             aDataset->ReadFromDisk( refFromFile );
4406             aDataset->CloseOnDisk();
4407             // san - it is impossible to recover applied algorithms using their entries within Load() method
4408             //SALOMEDS::SObject_wrap hypSO = myCurrentStudy->FindObjectID( refFromFile );
4409             //CORBA::Object_var hypObject = SObjectToObject( hypSO );
4410             int id = atoi( refFromFile );
4411             delete [] refFromFile;
4412             string anIOR = myStudyContext->getIORbyOldId( id );
4413             if ( !anIOR.empty() ) {
4414               CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
4415               if ( !CORBA::is_nil( hypObject ) ) {
4416                 SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
4417                 if ( !anHyp->_is_nil() && (!aShapeObject->_is_nil()
4418                                            || !myNewMeshImpl->HasShapeToMesh()) )
4419                   myNewMeshImpl->addHypothesis( aShapeObject, anHyp );
4420               }
4421             }
4422           }
4423         }
4424         aGroup->CloseOnDisk();
4425       }
4426
4427       // try to get applied hypotheses
4428       if ( aTopGroup->ExistInternalObject( "Applied Hypotheses" ) ) {
4429         aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup );
4430         aGroup->OpenOnDisk();
4431         // get number of applied hypotheses
4432         int aNbSubObjects = aGroup->nInternalObjects();
4433         for ( int j = 0; j < aNbSubObjects; j++ ) {
4434           char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4435           aGroup->InternalObjectIndentify( j, name_dataset );
4436           // check if it is a hypothesis
4437           if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) {
4438             aDataset = new HDFdataset( name_dataset, aGroup );
4439             aDataset->OpenOnDisk();
4440             size = aDataset->GetSize();
4441             char* refFromFile = new char[ size ];
4442             aDataset->ReadFromDisk( refFromFile );
4443             aDataset->CloseOnDisk();
4444             // san - it is impossible to recover applied hypotheses using their entries within Load() method
4445             //SALOMEDS::SObject_wrap hypSO = myCurrentStudy->FindObjectID( refFromFile );
4446             //CORBA::Object_var hypObject = SObjectToObject( hypSO );
4447             int id = atoi( refFromFile );
4448             delete [] refFromFile;
4449             string anIOR = myStudyContext->getIORbyOldId( id );
4450             if ( !anIOR.empty() ) {
4451               CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
4452               if ( !CORBA::is_nil( hypObject ) ) {
4453                 SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
4454                 if ( !anHyp->_is_nil() && (!aShapeObject->_is_nil()
4455                                            || !myNewMeshImpl->HasShapeToMesh()) )
4456                   myNewMeshImpl->addHypothesis( aShapeObject, anHyp );
4457               }
4458             }
4459           }
4460         }
4461         aGroup->CloseOnDisk();
4462       }
4463
4464       // --> try to find SUB-MESHES containers for each type of submesh
4465       for ( int j = GetSubMeshOnVertexTag(); j <= GetSubMeshOnCompoundTag(); j++ ) {
4466         const char* name_meshgroup;
4467         if ( j == GetSubMeshOnVertexTag() )
4468           name_meshgroup = "SubMeshes On Vertex";
4469         else if ( j == GetSubMeshOnEdgeTag() )
4470           name_meshgroup = "SubMeshes On Edge";
4471         else if ( j == GetSubMeshOnWireTag() )
4472           name_meshgroup = "SubMeshes On Wire";
4473         else if ( j == GetSubMeshOnFaceTag() )
4474           name_meshgroup = "SubMeshes On Face";
4475         else if ( j == GetSubMeshOnShellTag() )
4476           name_meshgroup = "SubMeshes On Shell";
4477         else if ( j == GetSubMeshOnSolidTag() )
4478           name_meshgroup = "SubMeshes On Solid";
4479         else if ( j == GetSubMeshOnCompoundTag() )
4480           name_meshgroup = "SubMeshes On Compound";
4481
4482         // try to get submeshes container HDF group
4483         if ( aTopGroup->ExistInternalObject( name_meshgroup ) ) {
4484           // open submeshes containers HDF group
4485           aGroup = new HDFgroup( name_meshgroup, aTopGroup );
4486           aGroup->OpenOnDisk();
4487
4488           // get number of submeshes
4489           int aNbSubMeshes = aGroup->nInternalObjects();
4490           for ( int k = 0; k < aNbSubMeshes; k++ ) {
4491             // identify submesh
4492             char name_submeshgroup[ HDF_NAME_MAX_LEN+1 ];
4493             aGroup->InternalObjectIndentify( k, name_submeshgroup );
4494             if ( strncmp( name_submeshgroup, "SubMesh", 7 ) == 0 ) {
4495               // --> get submesh id
4496               int subid = atoi( name_submeshgroup + 7 );
4497               if ( subid <= 0 )
4498                 continue;
4499               // open submesh HDF group
4500               aSubGroup = new HDFgroup( name_submeshgroup, aGroup );
4501               aSubGroup->OpenOnDisk();
4502
4503               // try to read and set reference to subshape
4504               GEOM::GEOM_Object_var aSubShapeObject;
4505               SMESH::SMESH_subMesh_var aSubMesh;
4506
4507               if ( aSubGroup->ExistInternalObject( "Ref on shape" ) ) {
4508                 // load submesh "Ref on shape" - it's an entry to SObject
4509                 aDataset = new HDFdataset( "Ref on shape", aSubGroup );
4510                 aDataset->OpenOnDisk();
4511                 size = aDataset->GetSize();
4512                 char* refFromFile = new char[ size ];
4513                 aDataset->ReadFromDisk( refFromFile );
4514                 aDataset->CloseOnDisk();
4515                 if ( strlen( refFromFile ) > 0 ) {
4516                   SALOMEDS::SObject_wrap subShapeSO = myCurrentStudy->FindObjectID( refFromFile );
4517                   CORBA::Object_var subShapeObject = SObjectToObject( subShapeSO );
4518                   if ( !CORBA::is_nil( subShapeObject ) ) {
4519                     aSubShapeObject = GEOM::GEOM_Object::_narrow( subShapeObject );
4520                     if ( !aSubShapeObject->_is_nil() )
4521                       aSubMesh = SMESH::SMESH_subMesh::_duplicate
4522                         ( myNewMeshImpl->createSubMesh( aSubShapeObject ) );
4523                     if ( aSubMesh->_is_nil() )
4524                       continue;
4525                     string iorSubString = GetORB()->object_to_string( aSubMesh );
4526                     int newSubId = myStudyContext->findId( iorSubString );
4527                     myStudyContext->mapOldToNew( subid, newSubId );
4528                   }
4529                 }
4530               }
4531
4532               if ( aSubMesh->_is_nil() )
4533                 continue;
4534
4535               // try to get applied algorithms
4536               if ( aSubGroup->ExistInternalObject( "Applied Algorithms" ) ) {
4537                 // open "applied algorithms" HDF group
4538                 aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup );
4539                 aSubSubGroup->OpenOnDisk();
4540                 // get number of applied algorithms
4541                 int aNbSubObjects = aSubSubGroup->nInternalObjects();
4542                 for ( int l = 0; l < aNbSubObjects; l++ ) {
4543                   char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4544                   aSubSubGroup->InternalObjectIndentify( l, name_dataset );
4545                   // check if it is an algorithm
4546                   if ( strncmp( name_dataset, "Algo", 4 ) == 0 ) {
4547                     aDataset = new HDFdataset( name_dataset, aSubSubGroup );
4548                     aDataset->OpenOnDisk();
4549                     size = aDataset->GetSize();
4550                     char* refFromFile = new char[ size ];
4551                     aDataset->ReadFromDisk( refFromFile );
4552                     aDataset->CloseOnDisk();
4553
4554                     int id = atoi( refFromFile );
4555                     string anIOR = myStudyContext->getIORbyOldId( id );
4556                     if ( !anIOR.empty() ) {
4557                       CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
4558                       if ( !CORBA::is_nil( hypObject ) ) {
4559                         SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
4560                         if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
4561                           myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
4562                       }
4563                     }
4564                   }
4565                 }
4566                 // close "applied algorithms" HDF group
4567                 aSubSubGroup->CloseOnDisk();
4568               }
4569
4570               // try to get applied hypotheses
4571               if ( aSubGroup->ExistInternalObject( "Applied Hypotheses" ) ) {
4572                 // open "applied hypotheses" HDF group
4573                 aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup );
4574                 aSubSubGroup->OpenOnDisk();
4575                 // get number of applied hypotheses
4576                 int aNbSubObjects = aSubSubGroup->nInternalObjects();
4577                 for ( int l = 0; l < aNbSubObjects; l++ ) {
4578                   char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4579                   aSubSubGroup->InternalObjectIndentify( l, name_dataset );
4580                   // check if it is a hypothesis
4581                   if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) {
4582                     aDataset = new HDFdataset( name_dataset, aSubSubGroup );
4583                     aDataset->OpenOnDisk();
4584                     size = aDataset->GetSize();
4585                     char* refFromFile = new char[ size ];
4586                     aDataset->ReadFromDisk( refFromFile );
4587                     aDataset->CloseOnDisk();
4588
4589                     int id = atoi( refFromFile );
4590                     string anIOR = myStudyContext->getIORbyOldId( id );
4591                     if ( !anIOR.empty() ) {
4592                       CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
4593                       if ( !CORBA::is_nil( hypObject ) ) {
4594                         SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
4595                         if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
4596                           myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
4597                       }
4598                     }
4599                   }
4600                 }
4601                 // close "APPLIED HYPOTHESES" hdf group
4602                 aSubSubGroup->CloseOnDisk();
4603               }
4604
4605               // close SUB-MESH hdf group
4606               aSubGroup->CloseOnDisk();
4607             }
4608           }
4609           // close SUB-MESHES containers hdf group
4610           aGroup->CloseOnDisk();
4611         }
4612       }
4613
4614       // try to get GROUPS
4615       for ( int ii = GetNodeGroupsTag(); ii <= GetBallElementsGroupsTag(); ii++ ) {
4616         char name_group[ 30 ];
4617         if ( ii == GetNodeGroupsTag() )
4618           strcpy( name_group, "Groups of Nodes" );
4619         else if ( ii == GetEdgeGroupsTag() )
4620           strcpy( name_group, "Groups of Edges" );
4621         else if ( ii == GetFaceGroupsTag() )
4622           strcpy( name_group, "Groups of Faces" );
4623         else if ( ii == GetVolumeGroupsTag() )
4624           strcpy( name_group, "Groups of Volumes" );
4625         else if ( ii == Get0DElementsGroupsTag() )
4626           strcpy( name_group, "Groups of 0D Elements" );
4627         else if ( ii == GetBallElementsGroupsTag() )
4628           strcpy( name_group, "Groups of Balls" );
4629
4630         if ( aTopGroup->ExistInternalObject( name_group ) ) {
4631           aGroup = new HDFgroup( name_group, aTopGroup );
4632           aGroup->OpenOnDisk();
4633           // get number of groups
4634           int aNbSubObjects = aGroup->nInternalObjects();
4635           for ( int j = 0; j < aNbSubObjects; j++ ) {
4636             char name_dataset[ HDF_NAME_MAX_LEN+1 ];
4637             aGroup->InternalObjectIndentify( j, name_dataset );
4638             // check if it is an group
4639             if ( string( name_dataset ).substr( 0, 5 ) == string( "Group" ) ) {
4640               // --> get group id
4641               int subid = atoi( string( name_dataset ).substr( 5 ).c_str() );
4642               if ( subid <= 0 )
4643                 continue;
4644               aDataset = new HDFdataset( name_dataset, aGroup );
4645               aDataset->OpenOnDisk();
4646
4647               // Retrieve actual group name
4648               size = aDataset->GetSize();
4649               char* nameFromFile = new char[ size ];
4650               aDataset->ReadFromDisk( nameFromFile );
4651               aDataset->CloseOnDisk();
4652
4653               // Try to find a shape reference
4654               TopoDS_Shape aShape;
4655               char aRefName[ 30 ];
4656               sprintf( aRefName, "Ref on shape %d", subid);
4657               if ( aGroup->ExistInternalObject( aRefName ) ) {
4658                 // load mesh "Ref on shape" - it's an entry to SObject
4659                 aDataset = new HDFdataset( aRefName, aGroup );
4660                 aDataset->OpenOnDisk();
4661                 size = aDataset->GetSize();
4662                 char* refFromFile = new char[ size ];
4663                 aDataset->ReadFromDisk( refFromFile );
4664                 aDataset->CloseOnDisk();
4665                 if ( strlen( refFromFile ) > 0 ) {
4666                   SALOMEDS::SObject_wrap shapeSO = myCurrentStudy->FindObjectID( refFromFile );
4667                   CORBA::Object_var shapeObject = SObjectToObject( shapeSO );
4668                   if ( !CORBA::is_nil( shapeObject ) ) {
4669                     aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
4670                     if ( !aShapeObject->_is_nil() )
4671                       aShape = GeomObjectToShape( aShapeObject );
4672                   }
4673                 }
4674               }
4675               // Try to read a filter of SMESH_GroupOnFilter
4676               SMESH::Filter_var filter;
4677               SMESH_PredicatePtr predicate;
4678               std::string hdfGrpName = "Filter " + SMESH_Comment(subid);
4679               if ( aGroup->ExistInternalObject( hdfGrpName.c_str() ))
4680               {
4681                 aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup );
4682                 aDataset->OpenOnDisk();
4683                 size = aDataset->GetSize();
4684                 char* persistStr = new char[ size ];
4685                 aDataset->ReadFromDisk( persistStr );
4686                 aDataset->CloseOnDisk();
4687                 if ( strlen( persistStr ) > 0 ) {
4688                   filter = SMESH_GroupOnFilter_i::StringToFilter( persistStr );
4689                   predicate = SMESH_GroupOnFilter_i::GetPredicate( filter );
4690                   filters.push_back( filter );
4691                 }
4692               }
4693
4694               // Create group servant
4695               SMESH::ElementType type = (SMESH::ElementType)(ii - GetNodeGroupsTag() + 1);
4696               SMESH::SMESH_GroupBase_var aNewGroup = SMESH::SMESH_GroupBase::_duplicate
4697                 ( myNewMeshImpl->createGroup( type, nameFromFile, aShape, predicate ) );
4698               // Obtain a SMESHDS_Group object
4699               if ( aNewGroup->_is_nil() )
4700                 continue;
4701
4702               string iorSubString = GetORB()->object_to_string( aNewGroup );
4703               int        newSubId = myStudyContext->findId( iorSubString );
4704               myStudyContext->mapOldToNew( subid, newSubId );
4705
4706               SMESH_GroupBase_i* aGroupImpl = SMESH::DownCast< SMESH_GroupBase_i*>( aNewGroup );
4707               if ( !aGroupImpl )
4708                 continue;
4709
4710               if ( SMESH_GroupOnFilter_i* aFilterGroup =
4711                    dynamic_cast< SMESH_GroupOnFilter_i*>( aGroupImpl ))
4712               {
4713                 aFilterGroup->SetFilter( filter );
4714                 filter->UnRegister();
4715               }
4716               SMESHDS_GroupBase* aGroupBaseDS = aGroupImpl->GetGroupDS();
4717               if ( !aGroupBaseDS )
4718                 continue;
4719
4720               aGroupBaseDS->SetStoreName( name_dataset );
4721
4722               // ouv : NPAL12872
4723               // Read color of the group
4724               char aGroupColorName[ 30 ];
4725               sprintf( aGroupColorName, "ColorGroup %d", subid);
4726               if ( aGroup->ExistInternalObject( aGroupColorName ) )
4727               {
4728                 aDataset = new HDFdataset( aGroupColorName, aGroup );
4729                 aDataset->OpenOnDisk();
4730                 size = aDataset->GetSize();
4731                 double* anRGB = new double[ size ];
4732                 aDataset->ReadFromDisk( anRGB );
4733                 aDataset->CloseOnDisk();
4734                 Quantity_Color aColor( anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB );
4735                 aGroupBaseDS->SetColor( aColor );
4736               }
4737             }
4738           }
4739           aGroup->CloseOnDisk();
4740         }
4741       } // reading GROUPs
4742
4743       // instead of reading mesh data, we read only brief information of all
4744       // objects: mesh, groups, sub-meshes (issue 0021208 )
4745       if ( hasData )
4746       {
4747         SMESH_PreMeshInfo::LoadFromFile( myNewMeshImpl, id,
4748                                          meshfile.ToCString(), filename.ToCString(),
4749                                          !isMultiFile );
4750       }
4751
4752       // read Sub-Mesh ORDER if any
4753       if( aTopGroup->ExistInternalObject( "Mesh Order" ) ) {
4754         aDataset = new HDFdataset( "Mesh Order", aTopGroup );
4755         aDataset->OpenOnDisk();
4756         size = aDataset->GetSize();
4757         int* smIDs = new int[ size ];
4758         aDataset->ReadFromDisk( smIDs );
4759         aDataset->CloseOnDisk();
4760         TListOfListOfInt anOrderIds;
4761         anOrderIds.push_back( TListOfInt() );
4762         for ( int i = 0; i < size; i++ )
4763           if ( smIDs[ i ] < 0 ) // is separator
4764             anOrderIds.push_back( TListOfInt() );
4765           else
4766             anOrderIds.back().push_back(smIDs[ i ]);
4767
4768         myNewMeshImpl->GetImpl().SetMeshOrder( anOrderIds );
4769       }
4770     } // loop on meshes
4771
4772     // update hyps needing full mesh data restored (issue 20918)
4773     for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data )
4774     {
4775       SMESH_Hypothesis_i* hyp  = hyp_data->first;
4776       hyp->UpdateAsMeshesRestored();
4777     }
4778
4779     // notify algos on completed restoration to set sub-mesh event listeners
4780     for ( meshi_group = meshGroupList.begin(); meshi_group != meshGroupList.end(); ++meshi_group )
4781     {
4782       SMESH_Mesh_i* myNewMeshImpl = meshi_group->first;
4783       ::SMESH_Mesh& myLocMesh     = myNewMeshImpl->GetImpl();
4784
4785       TopoDS_Shape myLocShape;
4786       if(myLocMesh.HasShapeToMesh())
4787         myLocShape = myLocMesh.GetShapeToMesh();
4788       else
4789         myLocShape = SMESH_Mesh::PseudoShape();
4790
4791       myLocMesh.GetSubMesh(myLocShape)->
4792         ComputeStateEngine (SMESH_subMesh::SUBMESH_RESTORED);
4793     }
4794
4795     // let filters detect dependency on mesh groups via FT_BelongToMeshGroup predicate (22877)
4796     list< SMESH::Filter_var >::iterator f = filters.begin();
4797     for ( ; f != filters.end(); ++f )
4798       if ( SMESH::Filter_i * fi = SMESH::DownCast< SMESH::Filter_i*>( *f ))
4799         fi->FindBaseObjects();
4800
4801
4802     // close mesh group
4803     if(aTopGroup)
4804       aTopGroup->CloseOnDisk();
4805   }
4806   // close HDF file
4807   aFile->CloseOnDisk();
4808   delete aFile;
4809
4810   // Remove temporary files created from the stream
4811   if ( !isMultiFile )
4812   {
4813     SMESH_File meshFile( meshfile.ToCString() );
4814     if ( !meshFile ) // no meshfile exists
4815     {
4816       SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
4817     }
4818     else
4819     {
4820       Engines::Container_var container = GetContainerRef();
4821       if ( Engines_Container_i* container_i = SMESH::DownCast<Engines_Container_i*>( container ))
4822       {
4823         container_i->registerTemporaryFile( filename.ToCString() );
4824         container_i->registerTemporaryFile( meshfile.ToCString() );
4825         container_i->registerTemporaryFile( tmpDir.ToCString() );
4826       }
4827     }
4828   }
4829   pd << ""; // prevent optimizing pd out
4830
4831   // creation of tree nodes for all data objects in the study
4832   // to support tree representation customization and drag-n-drop:
4833   SALOMEDS::Study_var                    study = theComponent->GetStudy();
4834   SALOMEDS::UseCaseBuilder_wrap useCaseBuilder = study->GetUseCaseBuilder();
4835   if ( !useCaseBuilder->IsUseCaseNode( theComponent ) ) {
4836     useCaseBuilder->SetRootCurrent();
4837     useCaseBuilder->Append( theComponent ); // component object is added as the top level item
4838     SALOMEDS::ChildIterator_wrap it = study->NewChildIterator( theComponent ); 
4839     for (it->InitEx(true); it->More(); it->Next()) {
4840       useCaseBuilder->AppendTo( it->Value()->GetFather(), it->Value() );
4841     }
4842   }
4843
4844   INFOS( "SMESH_Gen_i::Load completed" );
4845   return true;
4846 }
4847
4848 //=============================================================================
4849 /*!
4850  *  SMESH_Gen_i::LoadASCII
4851  *
4852  *  Load SMESH module's data in ASCII format
4853  */
4854 //=============================================================================
4855
4856 bool SMESH_Gen_i::LoadASCII( SALOMEDS::SComponent_ptr theComponent,
4857                              const SALOMEDS::TMPFile& theStream,
4858                              const char*              theURL,
4859                              bool                     isMultiFile ) {
4860   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LoadASCII" );
4861   return Load( theComponent, theStream, theURL, isMultiFile );
4862
4863   //before call main ::Load method it's need for decipher text format to
4864   //binary ( "|xx" => x' )
4865   int size = theStream.length();
4866   if ( int((size / 3 )*3) != size ) //error size of buffer
4867     return false;
4868
4869   int real_size = int(size / 3);
4870
4871   _CORBA_Octet* buffer = new _CORBA_Octet[real_size];
4872   char tmp[3];
4873   tmp[2]='\0';
4874   int c = -1;
4875   for ( int i = 0; i < real_size; i++ )
4876   {
4877     memcpy( &(tmp[0]), &(theStream[i*3+1]), 2 );
4878     sscanf( tmp, "%x", &c );
4879     sprintf( (char*)&(buffer[i]), "%c", (char)c );
4880   }
4881
4882   SALOMEDS::TMPFile_var aRealStreamFile = new SALOMEDS::TMPFile(real_size, real_size, buffer, 1);
4883
4884   return Load( theComponent, *(aRealStreamFile._retn()), theURL, isMultiFile );
4885 }
4886
4887 //=============================================================================
4888 /*!
4889  *  SMESH_Gen_i::Close
4890  *
4891  *  Clears study-connected data when it is closed
4892  */
4893 //=============================================================================
4894
4895 void SMESH_Gen_i::Close( SALOMEDS::SComponent_ptr theComponent )
4896 {
4897   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Close" );
4898
4899   // set correct current study
4900   SALOMEDS::Study_var study = theComponent->GetStudy();
4901   if ( study->StudyId() != GetCurrentStudyID())
4902     setCurrentStudy( study, /*IsBeingClosed=*/true );
4903
4904   // Clear study contexts data
4905   int studyId = GetCurrentStudyID();
4906   if ( myStudyContextMap.find( studyId ) != myStudyContextMap.end() ) {
4907     delete myStudyContextMap[ studyId ];
4908     myStudyContextMap.erase( studyId );
4909   }
4910
4911   // remove the tmp files meshes are loaded from
4912   SMESH_PreMeshInfo::RemoveStudyFiles_TMP_METHOD( theComponent );
4913
4914   myCurrentStudy = SALOMEDS::Study::_nil();
4915   return;
4916 }
4917
4918 //=============================================================================
4919 /*!
4920  *  SMESH_Gen_i::ComponentDataType
4921  *
4922  *  Get component data type
4923  */
4924 //=============================================================================
4925
4926 char* SMESH_Gen_i::ComponentDataType()
4927 {
4928   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::ComponentDataType" );
4929   return CORBA::string_dup( "SMESH" );
4930 }
4931
4932
4933 //=============================================================================
4934 /*!
4935  *  SMESH_Gen_i::IORToLocalPersistentID
4936  *
4937  *  Transform data from transient form to persistent
4938  */
4939 //=============================================================================
4940
4941 char* SMESH_Gen_i::IORToLocalPersistentID( SALOMEDS::SObject_ptr /*theSObject*/,
4942                                            const char*           IORString,
4943                                            CORBA::Boolean        /*isMultiFile*/,
4944                                            CORBA::Boolean        /*isASCII*/ )
4945 {
4946   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IORToLocalPersistentID" );
4947   StudyContext* myStudyContext = GetCurrentStudyContext();
4948
4949   if ( myStudyContext && strcmp( IORString, "" ) != 0 ) {
4950     int anId = myStudyContext->findId( IORString );
4951     if ( anId ) {
4952       if(MYDEBUG) MESSAGE( "VSR " << anId )
4953       char strId[ 20 ];
4954       sprintf( strId, "%d", anId );
4955       return  CORBA::string_dup( strId );
4956     }
4957   }
4958   return CORBA::string_dup( "" );
4959 }
4960
4961 //=============================================================================
4962 /*!
4963  *  SMESH_Gen_i::LocalPersistentIDToIOR
4964  *
4965  *  Transform data from persistent form to transient
4966  */
4967 //=============================================================================
4968
4969 char* SMESH_Gen_i::LocalPersistentIDToIOR( SALOMEDS::SObject_ptr /*theSObject*/,
4970                                            const char*           aLocalPersistentID,
4971                                            CORBA::Boolean        /*isMultiFile*/,
4972                                            CORBA::Boolean        /*isASCII*/ )
4973 {
4974   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LocalPersistentIDToIOR(): id = " << aLocalPersistentID );
4975   StudyContext* myStudyContext = GetCurrentStudyContext();
4976
4977   if ( myStudyContext && strcmp( aLocalPersistentID, "" ) != 0 ) {
4978     int anId = atoi( aLocalPersistentID );
4979     return CORBA::string_dup( myStudyContext->getIORbyOldId( anId ).c_str() );
4980   }
4981   return CORBA::string_dup( "" );
4982 }
4983
4984 //=======================================================================
4985 //function : RegisterObject
4986 //purpose  :
4987 //=======================================================================
4988
4989 int SMESH_Gen_i::RegisterObject(CORBA::Object_ptr theObject)
4990 {
4991   StudyContext* myStudyContext = GetCurrentStudyContext();
4992   if ( myStudyContext && !CORBA::is_nil( theObject )) {
4993     if (GetCurrentStudyID() == myImportedStudyId)
4994       myImportedStudyChanged = true;
4995     CORBA::String_var iorString = GetORB()->object_to_string( theObject );
4996     return myStudyContext->addObject( string( iorString.in() ) );
4997   }
4998   return 0;
4999 }
5000
5001 //================================================================================
5002 /*!
5003  * \brief Return id of registered object
5004   * \param theObject - the Object
5005   * \retval int - Object id
5006  */
5007 //================================================================================
5008
5009 CORBA::Long SMESH_Gen_i::GetObjectId(CORBA::Object_ptr theObject)
5010 {
5011   StudyContext* myStudyContext = GetCurrentStudyContext();
5012   if ( myStudyContext && !CORBA::is_nil( theObject )) {
5013     string iorString = GetORB()->object_to_string( theObject );
5014     return myStudyContext->findId( iorString );
5015   }
5016   return 0;
5017 }
5018
5019 //=============================================================================
5020 /*!
5021  *  SMESH_Gen_i::SetName
5022  *
5023  *  Set a new object name
5024  */
5025 //=============================================================================
5026 void SMESH_Gen_i::SetName(const char* theIOR,
5027                           const char* theName)
5028 {
5029   if ( theIOR && strcmp( theIOR, "" ) ) {
5030     CORBA::Object_var anObject = GetORB()->string_to_object( theIOR );
5031     SALOMEDS::SObject_wrap aSO = ObjectToSObject( myCurrentStudy, anObject );
5032     if ( !aSO->_is_nil() ) {
5033       SetName( aSO, theName );
5034     }
5035   }
5036 }
5037
5038 int SMESH_Gen_i::GetCurrentStudyID()
5039 {
5040   return myCurrentStudy->_is_nil() || myCurrentStudy->_non_existent() ? -1 : myCurrentStudy->StudyId();
5041 }
5042
5043 // Version information
5044 char* SMESH_Gen_i::getVersion()
5045 {
5046 #if SMESH_DEVELOPMENT
5047   return CORBA::string_dup(SMESH_VERSION_STR"dev");
5048 #else
5049   return CORBA::string_dup(SMESH_VERSION_STR);
5050 #endif
5051 }
5052
5053 //=================================================================================
5054 // function : Move()
5055 // purpose  : Moves objects to the specified position. 
5056 //            Is used in the drag-n-drop functionality.
5057 //=================================================================================
5058 void SMESH_Gen_i::Move( const SMESH::sobject_list& what,
5059                         SALOMEDS::SObject_ptr where,
5060                         CORBA::Long row )
5061 {
5062   if ( CORBA::is_nil( where ) ) return;
5063
5064   SALOMEDS::Study_var study = where->GetStudy();
5065   SALOMEDS::StudyBuilder_var studyBuilder = study->NewBuilder();
5066   SALOMEDS::UseCaseBuilder_var useCaseBuilder = study->GetUseCaseBuilder();
5067   SALOMEDS::SComponent_var father = where->GetFatherComponent();
5068   std::string dataType = father->ComponentDataType();
5069   if ( dataType != "SMESH" ) return; // not a SMESH component
5070   
5071   SALOMEDS::SObject_var objAfter;
5072   if ( row >= 0 && useCaseBuilder->HasChildren( where ) ) {
5073     // insert at given row -> find insertion position
5074     SALOMEDS::UseCaseIterator_var useCaseIt = useCaseBuilder->GetUseCaseIterator( where );
5075     int i;
5076     for ( i = 0; i < row && useCaseIt->More(); i++, useCaseIt->Next() );
5077     if ( i == row && useCaseIt->More() ) {
5078       objAfter = useCaseIt->Value();
5079     }
5080   }
5081   
5082   for ( int i = 0; i < what.length(); i++ ) {
5083     SALOMEDS::SObject_var sobj = what[i];
5084     if ( CORBA::is_nil( sobj ) ) continue; // skip bad object
5085     // insert the object to the use case tree
5086     if ( !CORBA::is_nil( objAfter ) )
5087       useCaseBuilder->InsertBefore( sobj, objAfter ); // insert at given row
5088     else
5089       useCaseBuilder->AppendTo( where, sobj );        // append to the end of list
5090   }
5091 }
5092 //================================================================================
5093 /*!
5094  * \brief Returns true if algorithm can be used to mesh a given geometry
5095  *  \param [in] theAlgoType - the algorithm type
5096  *  \param [in] theLibName - a name of the Plug-in library implementing the algorithm
5097  *  \param [in] theGeomObject - the geometry to mesh
5098  *  \param [in] toCheckAll - if \c True, returns \c True if all shapes are meshable,
5099  *         else, returns \c True if at least one shape is meshable
5100  *  \return CORBA::Boolean - can or can't
5101  */
5102 //================================================================================
5103
5104 CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char*           theAlgoType,
5105                                            const char*           theLibName,
5106                                            GEOM::GEOM_Object_ptr theGeomObject,
5107                                            CORBA::Boolean        toCheckAll)
5108 {
5109   SMESH_TRY;
5110
5111   std::string aPlatformLibName;
5112   typedef GenericHypothesisCreator_i* (*GetHypothesisCreator)(const char*);
5113   GenericHypothesisCreator_i* aCreator =
5114     getHypothesisCreator(theAlgoType, theLibName, aPlatformLibName);
5115   if (aCreator)
5116   {
5117     TopoDS_Shape shape = GeomObjectToShape( theGeomObject );
5118     return shape.IsNull() || aCreator->IsApplicable( shape, toCheckAll );
5119   }
5120   else
5121   {
5122     return false;
5123   }
5124
5125   SMESH_CATCH( SMESH::doNothing );
5126
5127 #ifdef _DEBUG_
5128   cout << "SMESH_Gen_i::IsApplicable(): exception in " << ( theAlgoType ? theAlgoType : "") << endl;
5129 #endif
5130   return true;
5131 }
5132
5133 //=================================================================================
5134 // function : GetInsideSphere
5135 // purpose  : Collect indices of elements, which are located inside the sphere
5136 //=================================================================================
5137 SMESH::long_array* SMESH_Gen_i::GetInsideSphere( SMESH::SMESH_IDSource_ptr meshPart,
5138                                                  SMESH::ElementType     theElemType,
5139                                                  CORBA::Double         theX,
5140                                                  CORBA::Double         theY,
5141                                                  CORBA::Double         theZ,
5142                                                  CORBA::Double         theR) {
5143   SMESH::long_array_var aResult = new SMESH::long_array();
5144   if(meshPart->_is_nil())
5145     return aResult._retn();
5146
5147   // 1. Create geometrical object
5148   gp_Pnt aP( theX, theY, theZ );
5149   TopoDS_Shape aShape = BRepPrimAPI_MakeSphere( aP, theR ).Shape();
5150
5151   std::vector<long> lst =_GetInside(meshPart, theElemType, aShape);
5152
5153   if( lst.size() > 0 ) {
5154     aResult->length( lst.size() );
5155     for ( long i = 0; i < lst.size(); i++ ) {
5156       aResult[i] = lst[i];
5157     }
5158   }
5159   return aResult._retn();
5160 }
5161
5162 SMESH::long_array* SMESH_Gen_i::GetInsideBox( SMESH::SMESH_IDSource_ptr meshPart,
5163                                               SMESH::ElementType        theElemType,
5164                                               CORBA::Double             theX1, 
5165                                               CORBA::Double             theY1, 
5166                                               CORBA::Double             theZ1,
5167                                               CORBA::Double             theX2,
5168                                               CORBA::Double             theY2,
5169                                               CORBA::Double             theZ2) {
5170   SMESH::long_array_var aResult = new SMESH::long_array();
5171   if( meshPart->_is_nil() )
5172     return aResult._retn();
5173
5174   TopoDS_Shape aShape = BRepPrimAPI_MakeBox( gp_Pnt( theX1, theY1, theZ1 ), gp_Pnt( theX2, theY2, theZ2 ) ).Shape();
5175
5176   std::vector<long> lst =_GetInside(meshPart, theElemType, aShape);
5177
5178   if( lst.size() > 0 ) {
5179     aResult->length( lst.size() );
5180     for ( long i = 0; i < lst.size(); i++ ) {
5181       aResult[i] = lst[i];
5182     }
5183   }
5184   return aResult._retn();
5185 }
5186
5187 SMESH::long_array* SMESH_Gen_i::GetInsideCylinder( SMESH::SMESH_IDSource_ptr meshPart,
5188                                                    SMESH::ElementType        theElemType,
5189                                                    CORBA::Double             theX, 
5190                                                    CORBA::Double             theY, 
5191                                                    CORBA::Double             theZ,
5192                                                    CORBA::Double             theDX, 
5193                                                    CORBA::Double             theDY, 
5194                                                    CORBA::Double             theDZ,
5195                                                    CORBA::Double             theH,
5196                                                    CORBA::Double             theR ){
5197   SMESH::long_array_var aResult = new SMESH::long_array();
5198   if( meshPart->_is_nil() )
5199     return aResult._retn();
5200
5201   gp_Pnt aP( theX, theY, theZ );
5202   gp_Vec aV( theDX, theDY, theDZ );
5203   gp_Ax2 anAxes (aP, aV);
5204
5205   TopoDS_Shape aShape = BRepPrimAPI_MakeCylinder(anAxes, theR, Abs(theH)).Shape();
5206
5207   std::vector<long> lst =_GetInside(meshPart, theElemType, aShape);
5208
5209   if( lst.size() > 0 ) {
5210     aResult->length( lst.size() );
5211     for ( long i = 0; i < lst.size(); i++ ) {
5212       aResult[i] = lst[i];
5213     }
5214   }
5215   return aResult._retn();
5216 }
5217
5218 SMESH::long_array* SMESH_Gen_i::GetInside( SMESH::SMESH_IDSource_ptr meshPart,
5219                                            SMESH::ElementType        theElemType,
5220                                            GEOM::GEOM_Object_ptr     theGeom,
5221                                            CORBA::Double             theTolerance ) {
5222   SMESH::long_array_var aResult = new SMESH::long_array();
5223   if( meshPart->_is_nil() || theGeom->_is_nil() )
5224     return aResult._retn();
5225
5226   TopoDS_Shape aShape = GeomObjectToShape( theGeom );
5227
5228   std::vector<long> lst =_GetInside(meshPart, theElemType, aShape, &theTolerance);
5229
5230   if( lst.size() > 0 ) {
5231     aResult->length( lst.size() );
5232     for ( long i = 0; i < lst.size(); i++ ) {
5233       aResult[i] = lst[i];
5234     }
5235   }
5236   return aResult._retn();
5237 }
5238
5239
5240
5241 std::vector<long> SMESH_Gen_i::_GetInside( SMESH::SMESH_IDSource_ptr meshPart,
5242                                            SMESH::ElementType theElemType,
5243                                            TopoDS_Shape& aShape,
5244                                            double* theTolerance) {
5245   
5246   std::vector<long> res;
5247   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
5248
5249   if ( mesh->_is_nil() ) 
5250     return res;
5251
5252   SMESH_Mesh_i* anImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
5253   if ( !anImpl ) 
5254     return res;
5255   
5256   const SMDS_Mesh* meshDS = anImpl->GetImpl().GetMeshDS();
5257
5258   if ( !meshDS ) 
5259     return res;
5260
5261   SMDSAbs_ElementType aType = SMDSAbs_ElementType(theElemType);
5262   SMESH::Controls::ElementsOnShape* anElementsOnShape = new SMESH::Controls::ElementsOnShape();
5263   anElementsOnShape->SetAllNodes( true );
5264   anElementsOnShape->SetMesh( meshDS );
5265   anElementsOnShape->SetShape( aShape, aType );
5266
5267   if(theTolerance)
5268     anElementsOnShape->SetTolerance(*theTolerance);  
5269
5270   SMESH::SMESH_Mesh_var msource = SMESH::SMESH_Mesh::_narrow(meshPart);
5271   if ( !msource->_is_nil() ) { // Mesh case
5272     SMDS_ElemIteratorPtr elemIt = meshDS->elementsIterator( aType );
5273     if ( elemIt ) {
5274       while ( elemIt->more() ) {
5275         const SMDS_MeshElement* anElem = elemIt->next();
5276         long anId = anElem->GetID();
5277         if ( anElementsOnShape->IsSatisfy( anId ) )
5278           res.push_back( anId );
5279       }
5280     }
5281   }
5282   SMESH::SMESH_Group_var gsource = SMESH::SMESH_Group::_narrow(meshPart);
5283   if ( !gsource->_is_nil() ) {
5284     if(theElemType == SMESH::NODE) {
5285       SMESH::long_array_var nodes = gsource->GetNodeIDs();
5286       for ( int i = 0; i < nodes->length(); ++i ) {
5287         if ( const SMDS_MeshNode* node = meshDS->FindNode( nodes[i] ) ) {
5288           long anId = node->GetID();
5289           if ( anElementsOnShape->IsSatisfy( anId ) )
5290             res.push_back( anId );
5291         }
5292       }
5293     } else if (gsource->GetType() == theElemType || theElemType == SMESH::ALL ) {
5294       SMESH::long_array_var elems = gsource->GetListOfID();
5295       for ( int i = 0; i < elems->length(); ++i ) {
5296         if ( const SMDS_MeshElement* elem = meshDS->FindElement( elems[i] ) ) {
5297           long anId = elem->GetID();
5298           if ( anElementsOnShape->IsSatisfy( anId ) )
5299             res.push_back( anId );
5300         }
5301       }      
5302     }
5303   }
5304   SMESH::SMESH_subMesh_var smsource = SMESH::SMESH_subMesh::_narrow(meshPart);
5305   if ( !smsource->_is_nil() ) {
5306     SMESH::long_array_var elems = smsource->GetElementsByType( theElemType );
5307     for ( int i = 0; i < elems->length(); ++i ) {
5308       const SMDS_MeshElement* elem = ( theElemType == SMESH::NODE ) ? meshDS->FindNode( elems[i] ) : meshDS->FindElement( elems[i] );
5309       if (elem) {
5310         long anId = elem->GetID();
5311         if ( anElementsOnShape->IsSatisfy( anId ) )
5312           res.push_back( anId );
5313       }
5314     }    
5315   }
5316   return res;
5317 }
5318
5319
5320 //=================================================================================
5321 // function : importData
5322 // purpose  : imports mesh data file (the med one) into the SMESH internal data structure
5323 //=================================================================================
5324 Engines::ListOfIdentifiers* SMESH_Gen_i::importData(CORBA::Long                   studyId,
5325                                                     Engines::DataContainer_ptr    data,
5326                                                     const Engines::ListOfOptions& options)
5327 {
5328   Engines::ListOfIdentifiers_var aResultIds = new Engines::ListOfIdentifiers;
5329   list<string> aResultList;
5330
5331   CORBA::Object_var aSMObject = myNS->Resolve( "/myStudyManager" );
5332   SALOMEDS::StudyManager_var aStudyManager = SALOMEDS::StudyManager::_narrow( aSMObject );
5333   SALOMEDS::Study_var aStudy = aStudyManager->GetStudyByID( studyId );
5334   SetCurrentStudy(aStudy);
5335
5336   // load and store temporary imported file
5337   string aFileName = Kernel_Utils::GetTmpFileName();
5338   aFileName += string(".") + data->extension();
5339   Engines::TMPFile* aFileStream = data->get();
5340   const char *aBuffer = (const char*)aFileStream->NP_data();
5341 #ifdef WIN32
5342   std::ofstream aFile(aFileName.c_str(), std::ios::binary);
5343 #else
5344   std::ofstream aFile(aFileName.c_str());
5345 #endif
5346   aFile.write(aBuffer, aFileStream->length());
5347   aFile.close();
5348
5349   // Retrieve mesh names from the file
5350   DriverMED_R_SMESHDS_Mesh aReader;
5351   aReader.SetFile( aFileName );
5352   aReader.SetMeshId(-1);
5353   Driver_Mesh::Status aStatus;
5354   list<string> aNames = aReader.GetMeshNames(aStatus);
5355   SMESH::mesh_array_var aResult = new SMESH::mesh_array();
5356   SMESH::DriverMED_ReadStatus aStatus2 = (SMESH::DriverMED_ReadStatus)aStatus;
5357   if (aStatus2 == SMESH::DRS_OK) {
5358     // Iterate through all meshes and create mesh objects
5359     for ( list<string>::iterator it = aNames.begin(); it != aNames.end(); it++ ) {
5360       // create mesh
5361       SMESH::SMESH_Mesh_var mesh = createMesh();
5362
5363       // publish mesh in the study
5364       SALOMEDS::SObject_var aSO;
5365       if (CanPublishInStudy(mesh)) {
5366         aSO = PublishMesh(aStudy, mesh.in(), (*it).c_str());
5367         aResultList.push_back(aSO->GetID());
5368       }
5369       // Read mesh data (groups are published automatically by ImportMEDFile())
5370       SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
5371       ASSERT( meshServant );
5372       meshServant->ImportMEDFile( aFileName.c_str(), (*it).c_str() );
5373       //meshServant->GetImpl().GetMeshDS()->Modified();
5374     }
5375   } else {
5376     MESSAGE("Opening MED file problems "<<aFileName.c_str())
5377     return aResultIds._retn();
5378   }
5379
5380   // remove temporary file 
5381 #ifdef WIN32
5382   DeleteFileA(aFileName.c_str());
5383 #else
5384   unlink(aFileName.c_str());
5385 #endif
5386
5387   if (!aResultList.empty()) {
5388     aResultIds->length(aResultList.size());
5389     list<string>::iterator aListIter = aResultList.begin();
5390     for(int a = 0; aListIter != aResultList.end(); aListIter++, a++)
5391       aResultIds[a] = aListIter->c_str();
5392   }
5393   
5394   myImportedStudyId = studyId;
5395   myImportedStudyChanged = false;
5396
5397   return aResultIds._retn();
5398 }
5399
5400 //=================================================================================
5401 // function : getModifiedData
5402 // purpose  : exports all geometry of this GEOM module into one BRep file
5403 //=================================================================================
5404 Engines::ListOfData* SMESH_Gen_i::getModifiedData(CORBA::Long studyId)
5405 {
5406   Engines::ListOfData_var aResult = new Engines::ListOfData;
5407   
5408   if (!myImportedStudyChanged) {
5409     INFOS("SMESH module data was not changed")
5410     return aResult._retn();
5411   }
5412
5413   CORBA::Object_var aSMObject = myNS->Resolve("/myStudyManager");
5414   SALOMEDS::StudyManager_var aStudyManager = SALOMEDS::StudyManager::_narrow(aSMObject);
5415   SALOMEDS::Study_var aStudy = aStudyManager->GetStudyByID(studyId);
5416   SetCurrentStudy(aStudy);
5417   SALOMEDS::SComponent_var aComponent = aStudy->FindComponent("SMESH");
5418   
5419   if (CORBA::is_nil(aComponent))
5420     return aResult._retn();
5421
5422   std::string aFullPath(Kernel_Utils::GetTmpFileName());
5423   aFullPath += ".med";
5424   StudyContext* myStudyContext = GetCurrentStudyContext();
5425
5426   SALOMEDS::ChildIterator_var anIter = aStudy->NewChildIterator(aComponent); // check only published meshes
5427   int aNumMeshes = 0; // number of meshes in result
5428   for(; anIter->More(); anIter->Next()) {
5429     SALOMEDS::SObject_var aSO = anIter->Value();
5430     CORBA::Object_var anObj = aSO->GetObject();
5431     if (!CORBA::is_nil(anObj)) {
5432       SMESH::SMESH_Mesh_var aCORBAMesh = SMESH::SMESH_Mesh::_narrow(anObj);
5433       if(!aCORBAMesh->_is_nil()) {
5434         SMESH_Mesh_i* myImpl = dynamic_cast<SMESH_Mesh_i*>(GetServant(aCORBAMesh).in());
5435         if (myImpl) {
5436           myImpl->Load();
5437           SMESH_Mesh& aMesh = myImpl->GetImpl();
5438           CORBA::String_var objName = aSO->GetName();
5439           aMesh.ExportMED(aFullPath.c_str(), objName.in(), false, MED::eV2_2, 0);
5440           aNumMeshes++;
5441         }
5442       }
5443     }
5444   }
5445   if (aNumMeshes > 0) { // prepare a container to store files
5446     INFOS("Write "<<aNumMeshes<<" meshes to "<<aFullPath.c_str());
5447     aResult->length(1);
5448     Engines::DataContainer_var aData = (new Engines_DataContainer_i(
5449                     aFullPath.c_str(), "", "", true))->_this();
5450     aResult[0] = aData;
5451   }
5452   return aResult._retn();
5453 }
5454
5455 //=============================================================================
5456 /*!
5457  *  SMESHEngine_factory
5458  *
5459  *  C factory, accessible with dlsym, after dlopen
5460  */
5461 //=============================================================================
5462
5463 extern "C"
5464 { SMESH_I_EXPORT
5465   PortableServer::ObjectId* SMESHEngine_factory( CORBA::ORB_ptr            orb,
5466                                                  PortableServer::POA_ptr   poa,
5467                                                  PortableServer::ObjectId* contId,
5468                                                  const char*               instanceName,
5469                                                  const char*               interfaceName )
5470   {
5471     if(MYDEBUG) MESSAGE( "PortableServer::ObjectId* SMESHEngine_factory()" );
5472     if(MYDEBUG) SCRUTE(interfaceName);
5473     SMESH_Gen_i* aSMESHGen = new SMESH_Gen_i(orb, poa, contId, instanceName, interfaceName);
5474     return aSMESHGen->getId() ;
5475   }
5476 }