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