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