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