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