Salome HOME
[bos #40653][CEA] New mesh import export formats with meshio.
[modules/smesh.git] / src / SMESH_I / SMESH_Gen_i.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : SMESH_Gen_i.cxx
23 //  Author : Paul RASCLE, EDF
24 //  Module : SMESH
25
26 #include <BRepPrimAPI_MakeBox.hxx>
27 #include <BRepPrimAPI_MakeCylinder.hxx>
28 #include <BRepPrimAPI_MakeSphere.hxx>
29 #include <BRep_Tool.hxx>
30 #include <OSD.hxx>
31 #include <TColStd_MapOfAsciiString.hxx>
32 #include <TCollection_AsciiString.hxx>
33 #include <TopExp.hxx>
34 #include <TopExp_Explorer.hxx>
35 #include <TopTools_IndexedMapOfShape.hxx>
36 #include <TopTools_ListIteratorOfListOfShape.hxx>
37 #include <TopTools_ListOfShape.hxx>
38 #include <TopTools_MapOfShape.hxx>
39 #include <TopoDS.hxx>
40 #include <TopoDS_CompSolid.hxx>
41 #include <TopoDS_Compound.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Face.hxx>
44 #include <TopoDS_Iterator.hxx>
45 #include <TopoDS_Shape.hxx>
46 #include <TopoDS_Shell.hxx>
47 #include <TopoDS_Solid.hxx>
48 #include <TopoDS_Vertex.hxx>
49 #include <TopoDS_Wire.hxx>
50 #include <gp_Pnt.hxx>
51
52 // Have to be included before std headers
53 #include <Python.h>
54 #include <structmember.h>
55
56 #ifdef WIN32
57  #include <windows.h>
58  #include <process.h>
59 #else
60  #include <dlfcn.h>
61  #include <libgen.h> // for basename function
62 #endif
63
64 #ifdef WIN32
65  #define LibHandle HMODULE
66  #define LoadLib( name ) LoadLibrary( name )
67  #define GetProc GetProcAddress
68  #define UnLoadLib( handle ) FreeLibrary( handle );
69 #else // WIN32
70  #define LibHandle void*
71  #ifdef DYNLOAD_LOCAL
72   #define LoadLib( name ) dlopen( name, RTLD_LAZY | RTLD_LOCAL )
73  #else // DYNLOAD_LOCAL
74   #define LoadLib( name ) dlopen( name, RTLD_LAZY | RTLD_GLOBAL )
75  #endif // DYNLOAD_LOCAL
76  #define GetProc dlsym
77  #define UnLoadLib( handle ) dlclose( handle );
78 #endif // WIN32
79
80 #include "SMESH_Gen_i.hxx"
81 #include "SMESH_version.h"
82
83 #include "DriverMED_W_SMESHDS_Mesh.h"
84 #include "DriverMED_R_SMESHDS_Mesh.h"
85 #ifdef WITH_CGNS
86 #include "DriverCGNS_Read.hxx"
87 #endif
88 #include "MED_Factory.hxx"
89 #include "SMDS_EdgePosition.hxx"
90 #include "SMDS_FacePosition.hxx"
91 #include "SMDS_SetIterator.hxx"
92 #include "SMDS_SpacePosition.hxx"
93 #include "SMDS_VertexPosition.hxx"
94 #include "SMESHDS_Document.hxx"
95 #include "SMESHDS_Group.hxx"
96 #include "SMESHDS_GroupOnGeom.hxx"
97 #include "SMESH_Algo_i.hxx"
98 #include "SMESH_File.hxx"
99 #include "SMESH_Group.hxx"
100 #include "SMESH_Group_i.hxx"
101 #include "SMESH_Hypothesis.hxx"
102 #include "SMESH_Hypothesis_i.hxx"
103 #include "SMESH_Mesh.hxx"
104 #include "SMESH_ParallelMesh.hxx"
105 #include "SMESH_MeshEditor.hxx"
106 #include "SMESH_Mesh_i.hxx"
107 #include <SMESH_SequentialMesh_i.hxx>
108 #include "SMESH_ParallelMesh_i.hxx"
109 #include "SMESH_PreMeshInfo.hxx"
110 #include "SMESH_PythonDump.hxx"
111 #include "SMESH_ControlsDef.hxx"
112 #include <SMESH_BoostTxtArchive.hxx>
113 #include <SMESH_SequentialMesh_i.hxx>
114 #include <SMESH_ParallelMesh_i.hxx>
115 #include "SMESH_Meshio.h"
116
117 // to pass CORBA exception through SMESH_TRY
118 #define SMY_OWN_CATCH catch( SALOME::SALOME_Exception& se ) { throw se; }
119 #include "SMESH_TryCatch.hxx" // to include after OCC headers!
120
121 #include CORBA_SERVER_HEADER(SMESH_Group)
122 #include CORBA_SERVER_HEADER(SMESH_Filter)
123 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
124
125
126 #include <GEOMImpl_Types.hxx>
127 #include <GEOM_Client.hxx>
128
129 #include <Basics_Utils.hxx>
130 #include <Basics_DirUtils.hxx>
131 #include <HDFOI.hxx>
132 #include <OpUtil.hxx>
133 #include <SALOMEDS_Tool.hxx>
134 #include <SALOME_Container_i.hxx>
135 #include <SALOME_LifeCycleCORBA.hxx>
136 #include <SALOME_NamingService.hxx>
137 #include <Utils_CorbaException.hxx>
138 #include <Utils_ExceptHandlers.hxx>
139 #include <Utils_SINGLETON.hxx>
140 #include <utilities.h>
141
142 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
143 #include CORBA_CLIENT_HEADER(SALOME_Session)
144
145 // helpers about SALOME::GenericObj
146 #include <SALOMEDS_wrap.hxx>
147 #include <SALOMEDS_Attributes_wrap.hxx>
148 #include <GEOM_wrap.hxx>
149
150 #include <map>
151 #include <fstream>
152 #include <sstream>
153 #include <cstdio>
154 #include <cstdlib>
155 #include <memory>
156
157 #include <boost/archive/text_oarchive.hpp>
158 #include <boost/serialization/list.hpp>
159 #include <boost/serialization/string.hpp>
160 #include <boost/filesystem.hpp>
161
162 namespace fs = boost::filesystem;
163
164 using namespace std;
165 using SMESH::TPythonDump;
166 using SMESH::TVar;
167
168 #define NUM_TMP_FILES 2
169
170 // Static variables definition
171 GEOM::GEOM_Gen_var      SMESH_Gen_i::myGeomGen;
172 CORBA::ORB_var          SMESH_Gen_i::myOrb;
173 PortableServer::POA_var SMESH_Gen_i::myPoa;
174 SALOME_NamingService_Abstract*   SMESH_Gen_i::myNS  = nullptr;
175 SALOME_LifeCycleCORBA*  SMESH_Gen_i::myLCC = nullptr;
176 SMESH_Gen_i*            SMESH_Gen_i::mySMESHGen = nullptr;
177
178
179 const int nbElemPerDiagonal = 10;
180
181 //=============================================================================
182 /*!
183  *  GetServant [ static ]
184  *
185  *  Get servant of the CORBA object
186  */
187 //=============================================================================
188
189 PortableServer::ServantBase_var SMESH_Gen_i::GetServant( CORBA::Object_ptr theObject )
190 {
191   if( CORBA::is_nil( theObject ) || CORBA::is_nil( GetPOA() ) )
192     return NULL;
193   try {
194     PortableServer::Servant aServant = GetPOA()->reference_to_servant( theObject );
195     return aServant;
196   }
197   catch (PortableServer::POA::ObjectNotActive &ex)
198   {
199     MESSAGE("GetServant: ObjectNotActive");
200     return NULL;
201   }
202   catch (PortableServer::POA::WrongAdapter &ex)
203   {
204     MESSAGE("GetServant: WrongAdapter: OK when several servants used to build several mesh in parallel...");
205     return NULL;
206   }
207   catch (PortableServer::POA::WrongPolicy &ex)
208   {
209     MESSAGE("GetServant: WrongPolicy");
210     return NULL;
211   }
212   catch (...)
213   {
214     MESSAGE( "GetServant - Unknown exception was caught!!!" );
215     return NULL;
216   }
217 }
218
219 //=============================================================================
220 /*!
221  *  SObjectToObject [ static ]
222  *
223  *  Get CORBA object corresponding to the SALOMEDS::SObject
224  */
225 //=============================================================================
226
227 CORBA::Object_var SMESH_Gen_i::SObjectToObject( SALOMEDS::SObject_ptr theSObject )
228 {
229   SALOMEDS::GenericAttribute_wrap anAttr;
230   CORBA::Object_var anObj;
231   if ( !theSObject->_is_nil() ) {
232     try {
233       if( theSObject->FindAttribute( anAttr.inout(), "AttributeIOR" ) ) {
234         SALOMEDS::AttributeIOR_wrap anIOR  = anAttr;
235         CORBA::String_var aValue = anIOR->Value();
236         if( strcmp( aValue, "" ) != 0 )
237           anObj = GetORB()->string_to_object( aValue );
238       }
239     }
240     catch( ... ) {
241       INFOS( "SObjectToObject - Unknown exception was caught!!!" );
242     }
243   }
244   return anObj;
245 }
246
247 // Set Naming Service object
248 void SMESH_Gen_i::SetNS(SALOME_NamingService_Abstract *ns)
249 {
250   if(myNS)
251     delete myNS;
252   myNS = ns;
253 }
254
255 //=============================================================================
256 /*!
257  *  GetNS [ static ]
258  *
259  *  Get SALOME_NamingService object
260  */
261 //=============================================================================
262
263 SALOME_NamingService_Abstract* SMESH_Gen_i::GetNS()
264 {
265   if ( !myNS ) {
266     myNS = SINGLETON_<SALOME_NamingService>::Instance();
267     ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting());
268     myNS->init_orb( GetORB() );
269   }
270   return myNS;
271 }
272
273 //=============================================================================
274 /*!
275  *  GetLCC [ static ]
276  *
277  *  Get SALOME_LifeCycleCORBA object
278  */
279 //=============================================================================
280
281 SALOME_LifeCycleCORBA*  SMESH_Gen_i::GetLCC()
282 {
283   if ( myLCC == NULL ) {
284     myLCC = new SALOME_LifeCycleCORBA( GetNS() );
285   }
286   return myLCC;
287 }
288
289 //=============================================================================
290 /*!
291  *  GetGeomEngine [ static ]
292  *
293  *  Get GEOM::GEOM_Gen reference
294  */
295 //=============================================================================
296
297 GEOM::GEOM_Gen_var SMESH_Gen_i::GetGeomEngine( GEOM::GEOM_Object_ptr go )
298 {
299   GEOM::GEOM_Gen_ptr gen = GEOM::GEOM_Gen::_nil();
300   if ( !CORBA::is_nil( go ))
301     gen = go->GetGen();
302   return gen;
303 }
304
305 //=============================================================================
306 /*!
307  *  SMESH_Gen_i::SMESH_Gen_i
308  *
309  *  Default constructor: not for use
310  */
311 //=============================================================================
312
313 SMESH_Gen_i::SMESH_Gen_i()
314 {
315 }
316
317 //=============================================================================
318 /*!
319  *  SMESH_Gen_i::SMESH_Gen_i
320  *
321  *  Standard constructor, used with Container
322  */
323 //=============================================================================
324
325 SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr            orb,
326                           PortableServer::POA_ptr   poa,
327                           PortableServer::ObjectId* contId,
328                           const char*               instanceName,
329                           const char*               interfaceName,
330                           bool                      checkNS)
331   : Engines_Component_i( orb, poa, contId, instanceName, interfaceName, false, checkNS )
332 {
333
334   myOrb = CORBA::ORB::_duplicate(orb);
335   myPoa = PortableServer::POA::_duplicate(poa);
336
337   _thisObj = this ;
338   _id = myPoa->activate_object( _thisObj );
339
340   myStudyContext = new StudyContext;
341
342   myIsEmbeddedMode = false;
343   myIsEnablePublish = true;
344   myShapeReader = NULL;  // shape reader
345   mySMESHGen = this;
346   myIsHistoricalPythonDump = true;
347   myToForgetMeshDataOnHypModif = false;
348
349   // set it in standalone mode only
350   //OSD::SetSignal( true );
351
352   // 0020605: EDF 1190 SMESH: Display performance. 80 seconds for 52000 cells.
353   // find out mode (embedded or standalone) here else
354   // meshes created before calling SMESH_Client::GetSMESHGen(), which calls
355   // SMESH_Gen_i::SetEmbeddedMode(), have wrong IsEmbeddedMode flag
356   if(checkNS)
357   {
358     if ( SALOME_NamingService_Abstract* ns = GetNS() )
359     {
360       CORBA::Object_var obj = ns->Resolve( "/Kernel/Session" );
361       SALOME::Session_var session = SALOME::Session::_narrow( obj ) ;
362       if ( !session->_is_nil() )
363       {
364         CORBA::String_var str_host = session->getHostname();
365         CORBA::Long        s_pid = session->getPID();
366         string my_host = Kernel_Utils::GetHostname();
367 #ifdef WIN32
368         long    my_pid = (long)_getpid();
369 #else
370         long    my_pid = (long) getpid();
371 #endif
372         SetEmbeddedMode( s_pid == my_pid && my_host == str_host.in() );
373       }
374     }
375   }
376 }
377
378 //=============================================================================
379 /*!
380  *  SMESH_Gen_i::~SMESH_Gen_i
381  *
382  *  Destructor
383  */
384 //=============================================================================
385
386 SMESH_Gen_i::~SMESH_Gen_i()
387 {
388   // delete hypothesis creators
389   map<string, GenericHypothesisCreator_i*>::iterator itHyp, itHyp2;
390   for (itHyp = myHypCreatorMap.begin(); itHyp != myHypCreatorMap.end(); itHyp++)
391   {
392     // same creator can be mapped under different names
393     GenericHypothesisCreator_i* creator = (*itHyp).second;
394     if ( !creator )
395       continue;
396     delete creator;
397     for (itHyp2 = itHyp; itHyp2 != myHypCreatorMap.end(); itHyp2++)
398       if ( creator == (*itHyp2).second )
399         (*itHyp2).second = 0;
400   }
401   myHypCreatorMap.clear();
402
403   // Clear study contexts data
404   delete myStudyContext;
405
406   // delete shape reader
407   if ( myShapeReader )
408     delete myShapeReader;
409 }
410
411 //=============================================================================
412 /*!
413  *  SMESH_Gen_i::getHypothesisCreator
414  *
415  *  Get hypothesis creator
416  */
417 //=============================================================================
418
419 GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHypName,
420                                                               const char* theLibName,
421                                                               std::string& thePlatformLibName)
422 {
423   std::string aPlatformLibName;
424   /* It's Need to translate lib name for WIN32 or X platform */
425   if ( theLibName && theLibName[0] != '\0'  )
426   {
427     int libNameLen = strlen(theLibName);
428     //check for old format "libXXXXXXX.so"
429     if (libNameLen > 7 &&
430         !strncmp( theLibName, "lib", 3 ) &&
431         !strcmp( theLibName+libNameLen-3, ".so" ))
432     {
433       //the old format
434 #if defined(WIN32)
435       aPlatformLibName = std::string( theLibName+3, libNameLen-6 ) + ".dll";
436 #elif defined(__APPLE__)
437       aPlatformLibName = std::string( theLibName, libNameLen-3 ) + ".dylib";
438 #else
439       aPlatformLibName = theLibName;
440 #endif
441     }
442     else
443     {
444       //try to use new format
445 #if defined(WIN32)
446       aPlatformLibName = theLibName;
447       aPlatformLibName += ".dll";
448 #elif defined(__APPLE__)
449       aPlatformLibName = std::string( "lib" ) + std::string( theLibName ) + ".dylib";
450 #else
451       aPlatformLibName = std::string( "lib" ) + std::string( theLibName ) + ".so";
452 #endif
453     }
454   }
455   thePlatformLibName = aPlatformLibName;
456
457   Unexpect aCatch(SALOME_SalomeException);
458   MESSAGE( "Create Hypothesis <" << theHypName << "> from " << aPlatformLibName);
459
460   typedef GenericHypothesisCreator_i* (*GetHypothesisCreator)(const char* );
461   GenericHypothesisCreator_i* aCreator;
462   try
463   {
464     // check, if creator for this hypothesis type already exists
465     if (myHypCreatorMap.find(string(theHypName)) == myHypCreatorMap.end())
466     {
467       // load plugin library
468       MESSAGE("Loading server meshers plugin library ...");
469 #ifdef WIN32
470 #  ifdef UNICODE
471       const wchar_t* path = Kernel_Utils::decode_s(aPlatformLibName);
472       SMESHUtils::ArrayDeleter<const wchar_t> deleter( path );
473 #  else
474       const char* path = aPlatformLibName.c_str();
475 #  endif
476 #else
477       const char* path = aPlatformLibName.c_str();
478 #endif
479       LibHandle libHandle = LoadLib( path );
480
481       if (!libHandle)
482       {
483         // report any error, if occurred
484 #ifndef WIN32
485         const char* anError = dlerror();
486         throw(SALOME_Exception( anError ));
487 #else
488         throw(SALOME_Exception ( SMESH_Comment("Can't load meshers plugin library " )
489                                  << aPlatformLibName));
490 #endif
491       }
492
493       // get method, returning hypothesis creator
494       MESSAGE("Find GetHypothesisCreator() method ...");
495       GetHypothesisCreator procHandle =
496         (GetHypothesisCreator)GetProc( libHandle, "GetHypothesisCreator" );
497       if (!procHandle)
498       {
499         throw(SALOME_Exception(SMESH_Comment("bad hypothesis plugin library")
500                                << aPlatformLibName ));
501         UnLoadLib(libHandle);
502       }
503
504       // get hypothesis creator
505       MESSAGE("Get Hypothesis Creator for " << theHypName);
506       aCreator = procHandle(theHypName);
507       if (!aCreator)
508       {
509         throw(SALOME_Exception( SMESH_Comment( theHypName ) << " is missing from "
510                                 << aPlatformLibName));
511       }
512       // map hypothesis creator to a hypothesis name
513       myHypCreatorMap[string(theHypName)] = aCreator;
514       return aCreator;
515     }
516     else
517     {
518       return myHypCreatorMap[string(theHypName)];
519     }
520   }
521   catch (SALOME_Exception& S_ex)
522   {
523     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
524   }
525   return aCreator;
526 }
527
528 //=============================================================================
529 /*!
530  *  SMESH_Gen_i::createHypothesis
531  *
532  *  Create hypothesis of given type
533  */
534 //=============================================================================
535
536 SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName,
537                                                           const char* theLibName)
538 {
539   SMESH_Hypothesis_i* myHypothesis_i = 0;
540   SMESH::SMESH_Hypothesis_var hypothesis_i;
541   std::string aPlatformLibName;
542   GenericHypothesisCreator_i* aCreator =
543     getHypothesisCreator(theHypName, theLibName, aPlatformLibName);
544
545   // create a new hypothesis object, store its ref. in studyContext
546   myHypothesis_i = aCreator->Create(myPoa, &myGen);
547   if (myHypothesis_i)
548   {
549     myHypothesis_i->SetLibName( aPlatformLibName.c_str() ); // for persistency assurance
550     CORBA::String_var hypName = myHypothesis_i->GetName();
551     myHypCreatorMap[ hypName.in() ] = aCreator;
552
553     // activate the CORBA servant of hypothesis
554     hypothesis_i = myHypothesis_i->_this();
555     int nextId = RegisterObject( hypothesis_i );
556     MESSAGE( "Add hypo to map with id = "<< nextId );
557   }
558   return hypothesis_i._retn();
559 }
560
561 //=============================================================================
562 /*!
563  *  SMESH_Gen_i::createMesh
564  *
565  *  Create empty mesh on shape
566  */
567 //=============================================================================
568
569 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh()
570 {
571   Unexpect aCatch(SALOME_SalomeException);
572   MESSAGE( "SMESH_Gen_i::createMesh" );
573
574   // Get or create the GEOM_Client instance
575   try {
576     // create a new mesh object servant, store it in a map in study context
577     SMESH_Mesh_i* meshServant = new SMESH_Mesh_i( GetPOA(), this );
578     // create a new mesh object
579     MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode);
580     SMESH_Mesh* myImpl = dynamic_cast<SMESH_Mesh*>(myGen.CreateMesh( myIsEmbeddedMode ));
581     if(myImpl == NULL )
582       THROW_SALOME_CORBA_EXCEPTION( "Could not cast SequentialMesh as Mesh", SALOME::INTERNAL_ERROR );
583     meshServant->SetImpl(myImpl);
584
585     // activate the CORBA servant of Mesh
586     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( meshServant->_this() );
587     int nextId = RegisterObject( mesh );
588     MESSAGE( "Add mesh to map with id = "<< nextId);
589
590     return mesh._retn();
591   }
592   catch (SALOME_Exception& S_ex) {
593     THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
594   }
595   return SMESH::SMESH_Mesh::_nil();
596 }
597
598 //=============================================================================
599 /*!
600  *  SMESH_Gen_i::createParallelMesh
601  *
602  *  Create empty parallel mesh on shape
603  */
604 //=============================================================================
605 SMESH::SMESH_ParallelMesh_ptr SMESH_Gen_i::createParallelMesh()
606 {
607   Unexpect aCatch(SALOME_SalomeException);
608   MESSAGE( "SMESH_Gen_i::createParallelMesh" );
609
610   // Get or create the GEOM_Client instance
611   try {
612     // create a new mesh object servant, store it in a map in study context
613     SMESH_ParallelMesh_i* meshServant = new SMESH_ParallelMesh_i( GetPOA(), this );
614     // create a new mesh object
615     MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode);
616     SMESH_Mesh* myImpl = dynamic_cast<SMESH_Mesh*>(myGen.CreateParallelMesh( myIsEmbeddedMode ));
617     if(myImpl == NULL )
618       THROW_SALOME_CORBA_EXCEPTION( "Could not cast ParallelMesh as Mesh", SALOME::INTERNAL_ERROR );
619     meshServant->SetImpl(myImpl);
620
621     // activate the CORBA servant of Mesh
622     SMESH::SMESH_ParallelMesh_var mesh = SMESH::SMESH_ParallelMesh::_narrow( meshServant->_this() );
623     int nextId = RegisterObject( mesh );
624     MESSAGE( "Add mesh to map with id = "<< nextId);
625
626     return mesh._retn();
627   }
628   catch (SALOME_Exception& S_ex) {
629     THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
630   }
631   return SMESH::SMESH_ParallelMesh::_nil();
632 }
633
634 //=============================================================================
635 /*!
636  *  SMESH_Gen_i::GetShapeReader
637  *
638  *  Get shape reader
639  */
640 //=============================================================================
641
642 GEOM_Client* SMESH_Gen_i::GetShapeReader()
643 {
644   // create shape reader if necessary
645   if ( !myShapeReader )
646     myShapeReader = new GEOM_Client(GetContainerRef());
647   ASSERT( myShapeReader );
648   return myShapeReader;
649 }
650
651 //=============================================================================
652 /*!
653  *  SMESH_Gen_i::SetGeomEngine
654  *
655  *  Set GEOM::GEOM_Gen reference
656  */
657 //=============================================================================
658
659 void SMESH_Gen_i::SetGeomEngine( GEOM::GEOM_Gen_ptr geomcompo )
660 {
661   myGeomGen = GEOM::GEOM_Gen::_duplicate( geomcompo );
662 }
663
664 //=============================================================================
665 /*!
666  *  SMESH_Gen_i::SetEmbeddedMode
667  *
668  *  Set current mode
669  */
670 //=============================================================================
671
672 void SMESH_Gen_i::SetEmbeddedMode( CORBA::Boolean theMode )
673 {
674   myIsEmbeddedMode = theMode;
675
676   if ( !myIsEmbeddedMode ) {
677     //PAL10867: disable signals catching with "noexcepthandler" option
678     char* envNoCatchSignals = getenv("NOT_INTERCEPT_SIGNALS");
679     if (!envNoCatchSignals || !atoi(envNoCatchSignals))
680     {
681       bool raiseFPE;
682
683       if (SALOME::VerbosityActivated())
684       {
685         raiseFPE = true;
686         char* envDisableFPE = getenv("DISABLE_FPE");
687         if (envDisableFPE && atoi(envDisableFPE))
688           raiseFPE = false;
689       }
690       else
691       {
692         raiseFPE = false;
693       }
694
695       OSD::SetSignal( raiseFPE );
696     }
697     // else OSD::SetSignal() is called in GUI
698   }
699 }
700
701 //=============================================================================
702 /*!
703  *  SMESH_Gen_i::IsEmbeddedMode
704  *
705  *  Get current mode
706  */
707 //=============================================================================
708
709 CORBA::Boolean SMESH_Gen_i::IsEmbeddedMode()
710 {
711   return myIsEmbeddedMode;
712 }
713
714 //=============================================================================
715 /*!
716  *  SMESH_Gen_i::SetEnablePublish
717  *
718  *  Set enable publishing in the study
719  */
720 //=============================================================================
721
722 void SMESH_Gen_i::SetEnablePublish( CORBA::Boolean theIsEnablePublish )
723 {
724   myIsEnablePublish = theIsEnablePublish;
725 }
726
727 //=============================================================================
728 /*!
729  *  SMESH_Gen_i::IsEnablePublish
730  *
731  *  Check enable publishing
732  */
733 //=============================================================================
734
735 CORBA::Boolean SMESH_Gen_i::IsEnablePublish()
736 {
737   return myIsEnablePublish;
738 }
739
740 //=============================================================================
741 /*!
742  *  SMESH_Gen_i::UpdateStudy
743  *
744  *  Update study (needed at switching GEOM->SMESH)
745  */
746 //=============================================================================
747
748 void SMESH_Gen_i::UpdateStudy()
749 {
750   if ( !myStudyContext )
751     myStudyContext = new StudyContext;
752
753   SALOMEDS::Study_var aStudy = getStudyServant();
754   if ( !CORBA::is_nil( aStudy ) )
755   {
756     SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
757
758     SALOMEDS::SComponent_wrap GEOM_var = aStudy->FindComponent( "GEOM" );
759     if( !GEOM_var->_is_nil() )
760       aStudyBuilder->LoadWith( GEOM_var, GetGeomEngine( /*isShaper=*/false ) );
761
762     GEOM_var = aStudy->FindComponent( "SHAPERSTUDY" );
763     if( !GEOM_var->_is_nil() )
764       aStudyBuilder->LoadWith( GEOM_var, GetGeomEngine( /*isShaper=*/true ) );
765
766     // NPAL16168, issue 0020210
767     // Let meshes update their data depending on GEOM groups that could change
768     CORBA::String_var compDataType = ComponentDataType();
769     SALOMEDS::SComponent_wrap me = aStudy->FindComponent( compDataType.in() );
770     if ( !me->_is_nil() ) {
771       SALOMEDS::ChildIterator_wrap anIter = aStudy->NewChildIterator( me );
772       for ( ; anIter->More(); anIter->Next() ) {
773         SALOMEDS::SObject_wrap so = anIter->Value();
774         CORBA::Object_var     ior = SObjectToObject( so );
775         if ( SMESH_Mesh_i*   mesh = SMESH::DownCast<SMESH_Mesh_i*>( ior ))
776           mesh->CheckGeomModif();
777       }
778     }
779   }
780 }
781
782 //================================================================================
783 /*!
784  * \brief Return true if mesh has ICON_SMESH_TREE_GEOM_MODIF icon
785  */
786 //================================================================================
787
788 bool SMESH_Gen_i::isGeomModifIcon( SMESH::SMESH_Mesh_ptr mesh )
789 {
790   SALOMEDS::SObject_wrap so = ObjectToSObject( mesh );
791   SALOMEDS::GenericAttribute_wrap attr;
792   if ( ! so->_is_nil() && so->FindAttribute( attr.inout(), "AttributePixMap" ))
793   {
794     SALOMEDS::AttributePixMap_wrap pm = attr;
795     CORBA::String_var             ico = pm->GetPixMap();
796     return ( strcmp( ico.in(), "ICON_SMESH_TREE_GEOM_MODIF" ) == 0 );
797   }
798   return false;
799 }
800
801 //=================================================================================
802 // function : hasObjectInfo()
803 // purpose  : shows if module provides information for its objects
804 //=================================================================================
805
806 bool SMESH_Gen_i::hasObjectInfo()
807 {
808   return true;
809 }
810
811 //=================================================================================
812 // function : getObjectInfo()
813 // purpose  : returns an information for a given object by its entry
814 //=================================================================================
815
816 char* SMESH_Gen_i::getObjectInfo( const char* entry )
817 {
818   // for a mesh with icon == ICON_SMESH_TREE_GEOM_MODIF show a warning;
819   // for the rest, "module 'SMESH', ID=0:1:2:*"
820
821   SMESH_Comment txt;
822
823   SALOMEDS::SObject_wrap  so = getStudyServant()->FindObjectID( entry );
824   CORBA::Object_var      obj = SObjectToObject( so );
825   SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( obj );
826   if ( isGeomModifIcon( mesh ))
827   {
828     txt << "The geometry was changed and the mesh needs to be recomputed";
829   }
830
831   if ( txt.empty() )
832   {
833     CORBA::String_var compType = ComponentDataType();
834     txt << "module '" << compType << "', ID=" << entry;
835   }
836   return CORBA::string_dup( txt );
837 }
838
839 //=============================================================================
840 /*!
841  *  SMESH_Gen_i::GetStudyContext
842  *
843  *  Get study context
844  */
845 //=============================================================================
846
847 StudyContext* SMESH_Gen_i::GetStudyContext()
848 {
849   return myStudyContext;
850 }
851
852 //=============================================================================
853 /*!
854  *  SMESH_Gen_i::CreateHypothesis
855  *
856  *  Create hypothesis/algorithm of given type and publish it in the study
857  */
858 //=============================================================================
859
860 SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypName,
861                                                            const char* theLibName )
862 {
863   Unexpect aCatch(SALOME_SalomeException);
864   // Create hypothesis/algorithm
865   SMESH::SMESH_Hypothesis_var hyp = this->createHypothesis( theHypName, theLibName );
866
867   // Publish hypothesis/algorithm in the study
868   if ( CanPublishInStudy( hyp ) ) {
869     SALOMEDS::SObject_wrap aSO = PublishHypothesis( hyp );
870     if ( !aSO->_is_nil() ) {
871       // Update Python script
872       TPythonDump(this) << aSO << " = " << this << ".CreateHypothesis('"
873                     << theHypName << "', '" << theLibName << "')";
874     }
875   }
876
877   return hyp._retn();
878 }
879
880 //================================================================================
881 /*!
882  * \brief Return a hypothesis initialized by given average length.
883  *  \param theHypType - hypothesis type name
884  *  \param theLibName - plugin library name
885  *  \param theAverageLength - average length
886  *  \param theQuadDominated - is quad-dominated flag
887  *  \retval SMESH::SMESH_Hypothesis_ptr - the new hypothesis
888  */
889 //================================================================================
890
891 SMESH::SMESH_Hypothesis_ptr
892 SMESH_Gen_i::CreateHypothesisByAverageLength( const char*    theHypType,
893                                               const char*    theLibName,
894                                               CORBA::Double  theAverageLength,
895                                               CORBA::Boolean theQuadDominated)
896 {
897   SMESH::HypInitParams initParams = { ::SMESH_Hypothesis::BY_AVERAGE_LENGTH,
898                                       theAverageLength, theQuadDominated };
899
900   SMESH::SMESH_Hypothesis_var hyp =
901     GetHypothesisParameterValues( theHypType, theLibName,
902                                   SMESH::SMESH_Mesh::_nil(),
903                                   GEOM::GEOM_Object::_nil(),
904                                   initParams );
905   SALOMEDS::SObject_wrap so = PublishHypothesis( hyp );
906
907   TPythonDump(this) << hyp << " = " << this << ".CreateHypothesisByAverageLength( '"
908                 << theHypType << "', '"
909                 << theLibName << "', "
910                 << theAverageLength << ", "
911                 << theQuadDominated << " )";
912
913   return hyp._retn();
914 }
915
916 //================================================================================
917 /*!
918  * \brief Return a hypothesis holding parameter values corresponding either to the mesh
919  * existing on the given geometry or to size of the geometry.
920  *  \param theHypType - hypothesis type name
921  *  \param theLibName - plugin library name
922  *  \param theMesh - The mesh of interest
923  *  \param theGeom - The shape to get parameter values from
924  *  \retval SMESH::SMESH_Hypothesis_ptr - The returned hypothesis may be the one existing
925  *     in a study and used to compute the mesh, or a temporary one created just to pass
926  *     parameter values
927  */
928 //================================================================================
929
930 SMESH::SMESH_Hypothesis_ptr
931 SMESH_Gen_i::GetHypothesisParameterValues( const char*                 theHypType,
932                                            const char*                 theLibName,
933                                            SMESH::SMESH_Mesh_ptr       theMesh,
934                                            GEOM::GEOM_Object_ptr       theGeom,
935                                            const SMESH::HypInitParams& theParams)
936 {
937   Unexpect aCatch(SALOME_SalomeException);
938
939   const bool byMesh = ( theParams.way == ::SMESH_Hypothesis::BY_MESH );
940   if ( byMesh && CORBA::is_nil( theMesh ) )
941     return SMESH::SMESH_Hypothesis::_nil();
942   if ( byMesh && CORBA::is_nil( theGeom ) )
943     return SMESH::SMESH_Hypothesis::_nil();
944
945   // -----------------------------------------------
946   // find hypothesis used to mesh theGeom
947   // -----------------------------------------------
948
949   // get mesh and shape
950   SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
951   TopoDS_Shape shape = GeomObjectToShape( theGeom );
952   if ( byMesh && ( !meshServant || meshServant->NbNodes()==0 || shape.IsNull() ))
953     return SMESH::SMESH_Hypothesis::_nil();
954   ::SMESH_Mesh* mesh = meshServant ? &meshServant->GetImpl() : (::SMESH_Mesh*)0;
955
956   // create a temporary hypothesis to know its dimension
957   SMESH::SMESH_Hypothesis_var tmpHyp = this->createHypothesis( theHypType, theLibName );
958   SMESH_Hypothesis_i* hypServant = SMESH::DownCast<SMESH_Hypothesis_i*>( tmpHyp );
959   if ( !hypServant )
960     return SMESH::SMESH_Hypothesis::_nil();
961   ::SMESH_Hypothesis* hyp = hypServant->GetImpl();
962
963   if ( byMesh ) {
964     // look for a hypothesis of theHypType used to mesh the shape
965     if ( myGen.GetShapeDim( shape ) == hyp->GetDim() )
966     {
967       // check local shape
968       SMESH::ListOfHypothesis_var aHypList = theMesh->GetHypothesisList( theGeom );
969       int nbLocalHyps = aHypList->length();
970       for ( int i = 0; i < nbLocalHyps; i++ ) {
971         CORBA::String_var hypName = aHypList[i]->GetName();
972         if ( strcmp( theHypType, hypName.in() ) == 0 ) // FOUND local!
973           return SMESH::SMESH_Hypothesis::_duplicate( aHypList[i] );
974       }
975       // check super shapes
976       TopTools_ListIteratorOfListOfShape itShape( mesh->GetAncestors( shape ));
977       while ( nbLocalHyps == 0 && itShape.More() ) {
978         GEOM::GEOM_Object_ptr geomObj = ShapeToGeomObject( itShape.Value() );
979         if ( ! CORBA::is_nil( geomObj )) {
980           SMESH::ListOfHypothesis_var aHypList = theMesh->GetHypothesisList( geomObj );
981           nbLocalHyps = aHypList->length();
982           for ( int i = 0; i < nbLocalHyps; i++ )
983             if ( strcmp( theHypType, aHypList[i]->GetName() ) == 0 ) // FOUND global!
984               return SMESH::SMESH_Hypothesis::_duplicate( aHypList[i] );
985         }
986         itShape.Next();
987       }
988     }
989
990     // let the temporary hypothesis find out somehow parameter values by mesh
991     if ( hyp->SetParametersByMesh( mesh, shape ))
992       return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
993   }
994   else
995   {
996     ::SMESH_Hypothesis::TDefaults dflts;
997     dflts._way           = ( ::SMESH_Hypothesis::InitWay) theParams.way;
998     dflts._nbSegments    = myGen.GetDefaultNbSegments();
999     dflts._elemLength    = theParams.averageLength;
1000     dflts._quadDominated = theParams.quadDominated;
1001     if ( theParams.way == ::SMESH_Hypothesis::BY_GEOM )
1002     {
1003       if ( mesh )
1004         dflts._diagonal  = mesh->GetShapeDiagonalSize();
1005       else
1006         dflts._diagonal  = ::SMESH_Mesh::GetShapeDiagonalSize( shape );
1007       dflts._elemLength  = dflts._diagonal / myGen.GetBoundaryBoxSegmentation();
1008       dflts._shape       = &shape;
1009     }
1010
1011     // let the hypothesis initialize it's values
1012     if ( hyp->SetParametersByDefaults( dflts, mesh ))
1013       return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
1014   }
1015
1016   return SMESH::SMESH_Hypothesis::_nil();
1017 }
1018
1019 //=============================================================================
1020 /*!
1021  * Returns \c True if a hypothesis is assigned to a sole sub-mesh in a current Study
1022  *  \param [in] theHyp - the hypothesis of interest
1023  *  \param [out] theMesh - the sole mesh using \a theHyp
1024  *  \param [out] theShape - the sole geometry \a theHyp is assigned to
1025  *  \return boolean - \c True if \a theMesh and \a theShape are sole using \a theHyp
1026  *
1027  * If two meshes on same shape have theHyp assigned to the same sub-shape, they are
1028  * considered as SAME sub-mesh => result is \c true.
1029  * This method ids used to initialize SMESHGUI_GenericHypothesisCreator with
1030  * a shape to which an hyp being edited is assigned.
1031  */
1032 //=============================================================================
1033
1034 CORBA::Boolean SMESH_Gen_i::GetSoleSubMeshUsingHyp( SMESH::SMESH_Hypothesis_ptr theHyp,
1035                                                     SMESH::SMESH_Mesh_out       theMesh,
1036                                                     GEOM::GEOM_Object_out       theShape)
1037 {
1038   if ( CORBA::is_nil( theHyp ))
1039     return false;
1040
1041   // get Mesh component SO
1042   CORBA::String_var compDataType = ComponentDataType();
1043   SALOMEDS::SComponent_wrap comp = getStudyServant()->FindComponent( compDataType.in() );
1044   if ( CORBA::is_nil( comp ))
1045     return false;
1046
1047   // look for child SO of meshes
1048   SMESH::SMESH_Mesh_var foundMesh;
1049   TopoDS_Shape          foundShape;
1050   bool                  isSole = true;
1051   SALOMEDS::ChildIterator_wrap meshIter = getStudyServant()->NewChildIterator( comp );
1052   for ( ; meshIter->More() && isSole; meshIter->Next() )
1053   {
1054     SALOMEDS::SObject_wrap curSO = meshIter->Value();
1055     CORBA::Object_var        obj = SObjectToObject( curSO );
1056     SMESH_Mesh_i*         mesh_i = SMESH::DownCast< SMESH_Mesh_i* >( obj );
1057     if ( ! mesh_i )
1058       continue;
1059
1060     // look for a sole shape where theHyp is assigned
1061     bool isHypFound = false;
1062     const ShapeToHypothesis & s2hyps = mesh_i->GetImpl().GetMeshDS()->GetHypotheses();
1063     ShapeToHypothesis::Iterator s2hypsIt( s2hyps );
1064     for ( ; s2hypsIt.More() && isSole; s2hypsIt.Next() )
1065     {
1066       const THypList& hyps = s2hypsIt.Value();
1067       THypList::const_iterator h = hyps.begin();
1068       for ( ; h != hyps.end(); ++h )
1069         if ( (*h)->GetID() == theHyp->GetId() )
1070           break;
1071       if ( h != hyps.end()) // theHyp found
1072       {
1073         isHypFound = true;
1074         if ( ! foundShape.IsNull() &&
1075              ! foundShape.IsSame( s2hypsIt.Key() )) // not a sole sub-shape
1076         {
1077           foundShape.Nullify();
1078           isSole = false;
1079           break;
1080         }
1081         foundShape = s2hypsIt.Key();
1082       }
1083     } // loop on assigned hyps
1084
1085     if ( isHypFound && !foundShape.IsNull() ) // a mesh using theHyp is found
1086     {
1087       if ( !foundMesh->_is_nil() ) // not a sole mesh
1088       {
1089         if ( !foundMesh->HasShapeToMesh() ||
1090              !mesh_i   ->HasShapeToMesh() )
1091         {
1092           isSole = ( foundMesh->HasShapeToMesh() == mesh_i->HasShapeToMesh() );
1093         }
1094         else
1095         {
1096           GEOM::GEOM_Object_var s1 = mesh_i   ->GetShapeToMesh();
1097           GEOM::GEOM_Object_var s2 = foundMesh->GetShapeToMesh();
1098           isSole = s1->IsSame( s2 );
1099         }
1100       }
1101       foundMesh = SMESH::SMESH_Mesh::_narrow( obj );
1102     }
1103
1104   } // loop on meshes
1105
1106   if ( isSole &&
1107        ! foundMesh->_is_nil() &&
1108        ! foundShape.IsNull() )
1109   {
1110     theMesh  = foundMesh._retn();
1111     theShape = ShapeToGeomObject( foundShape );
1112     return ( !theMesh->_is_nil() && !theShape->_is_nil() );
1113   }
1114   return false;
1115 }
1116
1117 //=============================================================================
1118 /*!
1119  * Set number of segments per diagonal of boundary box of geometry by which
1120  * default segment length of appropriate 1D hypotheses is defined
1121  */
1122 //=============================================================================
1123
1124 void SMESH_Gen_i::SetBoundaryBoxSegmentation( CORBA::Long theNbSegments )
1125 {
1126   if ( theNbSegments > 0 )
1127     myGen.SetBoundaryBoxSegmentation( int( theNbSegments ));
1128   else
1129     THROW_SALOME_CORBA_EXCEPTION( "non-positive number of segments", SALOME::BAD_PARAM );
1130 }
1131
1132 //=============================================================================
1133 /*!
1134  * \brief Set default number of segments per edge
1135  */
1136 //=============================================================================
1137
1138 void SMESH_Gen_i::SetDefaultNbSegments(CORBA::Long theNbSegments)
1139 {
1140   if ( theNbSegments > 0 )
1141     myGen.SetDefaultNbSegments( int(theNbSegments) );
1142   else
1143     THROW_SALOME_CORBA_EXCEPTION( "non-positive number of segments", SALOME::BAD_PARAM );
1144 }
1145
1146 //=============================================================================
1147 /*!
1148  * Set an option value
1149  */
1150 //=============================================================================
1151
1152 void SMESH_Gen_i::SetOption(const char* name, const char* value)
1153 {
1154   if ( name && value && strlen( value ) > 0 )
1155   {
1156     string msgToGUI;
1157     if ( strcmp(name, "historical_python_dump") == 0 )
1158     {
1159       myIsHistoricalPythonDump = ( value[0] == '1' || toupper(value[0]) == 'T' ); // 1 || true
1160       msgToGUI = "preferences/SMESH/historical_python_dump/";
1161       msgToGUI += myIsHistoricalPythonDump ? "true" : "false";
1162     }
1163     else if ( strcmp(name, "forget_mesh_on_hyp_modif") == 0 )
1164     {
1165       myToForgetMeshDataOnHypModif = ( value[0] == '1' || toupper(value[0]) == 'T' ); // 1 || true
1166       msgToGUI = "preferences/SMESH/forget_mesh_on_hyp_modif/";
1167       msgToGUI += myToForgetMeshDataOnHypModif ? "true" : "false";
1168     }
1169     else if ( strcmp(name, "default_grp_color") == 0 )
1170     {
1171       vector<int> color;
1172       string str = value;
1173       // color must be presented as a string of following form:
1174       if ( str.at(0) == '#' && str.length() == 7 ) { // hexadecimal color ("#ffaa00", for example)
1175         str = str.substr(1);
1176         for ( size_t i = 0; i < str.length()/2; i++ )
1177           if ( str.at(i*2) >= '0' && str.at(i*2) <= 'f' && str.at(i*2+1) >= '0' && str.at(i*2+1) <= 'f' )
1178             color.push_back( strtol( str.substr( i*2, 2 ).c_str(), NULL, 16 ) );
1179       }
1180       else if ( value ) { // rgb color ("255,170,0", for example)
1181         string tempValue( value );
1182         char* colorValue = strtok( &tempValue[0], "," );
1183         while ( colorValue != NULL ) {
1184           int c_value = atoi( colorValue );
1185           if ( c_value >= 0 && c_value <= 255 )
1186             color.push_back( c_value );
1187           colorValue = strtok( NULL, "," );
1188         }
1189       }
1190       if ( color.size() == 3 ) { // color must have three valid component
1191         SMESHDS_GroupBase::SetDefaultColor( Quantity_Color( color[0]/255., color[1]/255., color[2]/255., Quantity_TOC_RGB ) );
1192         myDefaultGroupColor = value;
1193         msgToGUI = "preferences/SMESH/default_grp_color/";
1194         msgToGUI += value;
1195       }
1196     }
1197
1198     // update preferences in case if SetOption() is invoked from python console
1199     if ( !msgToGUI.empty() )
1200     {
1201       CORBA::Object_var obj = SMESH_Gen_i::GetNS()->Resolve( "/Kernel/Session" );
1202       SALOME::Session_var session = SALOME::Session::_narrow( obj );
1203       if ( !CORBA::is_nil( session ) )
1204         session->emitMessageOneWay(msgToGUI.c_str());
1205     }
1206   }
1207 }
1208
1209 //=============================================================================
1210 /*!
1211  *  Return an option value
1212  */
1213 //=============================================================================
1214
1215 char* SMESH_Gen_i::GetOption(const char* name)
1216 {
1217   if ( name )
1218   {
1219     if ( strcmp(name, "historical_python_dump") == 0 )
1220     {
1221       return CORBA::string_dup( myIsHistoricalPythonDump ? "true" : "false" );
1222     }
1223     if ( strcmp(name, "forget_mesh_on_hyp_modif") == 0 )
1224     {
1225       return CORBA::string_dup( myToForgetMeshDataOnHypModif ? "true" : "false" );
1226     }
1227     if ( strcmp(name, "default_grp_color") == 0 )
1228     {
1229       return CORBA::string_dup( myDefaultGroupColor.c_str() );
1230     }
1231   }
1232   return CORBA::string_dup( "" );
1233 }
1234
1235 //=============================================================================
1236 /*!
1237  *  SMESH_Gen_i::CreateMesh
1238  *
1239  *  Create empty mesh on a shape and publish it in the study
1240  */
1241 //=============================================================================
1242
1243 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObject )
1244 {
1245   Unexpect aCatch(SALOME_SalomeException);
1246   MESSAGE( "SMESH_Gen_i::CreateMesh(GEOM_Object_ptr)" );
1247   // create mesh
1248   SMESH::SMESH_Mesh_var mesh = this->createMesh();
1249   // set shape
1250   SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
1251   ASSERT( meshServant );
1252   meshServant->SetShape( theShapeObject );
1253
1254   // publish mesh in the study
1255   if ( CanPublishInStudy( mesh ) ) {
1256     SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
1257     aStudyBuilder->NewCommand();  // There is a transaction
1258     SALOMEDS::SObject_wrap aSO = PublishMesh( mesh.in() );
1259     aStudyBuilder->CommitCommand();
1260     if ( !aSO->_is_nil() ) {
1261       // Update Python script
1262       TPythonDump(this) << aSO << " = " << this << ".CreateMesh(" << theShapeObject << ")";
1263     }
1264   }
1265
1266   return mesh._retn();
1267 }
1268
1269 //=============================================================================
1270 /*!
1271  *  SMESH_Gen_i::CreateParallelMesh
1272  *
1273  *  Create empty parallel mesh on a shape and publish it in the study
1274  */
1275 //=============================================================================
1276
1277 SMESH::SMESH_ParallelMesh_ptr SMESH_Gen_i::CreateParallelMesh( GEOM::GEOM_Object_ptr theShapeObject )
1278 {
1279   Unexpect aCatch(SALOME_SalomeException);
1280   MESSAGE( "SMESH_Gen_i::CreateParallelMesh" );
1281   // create mesh
1282   SMESH::SMESH_ParallelMesh_var mesh = this->createParallelMesh();
1283   // set shape
1284   SMESH_ParallelMesh_i* meshServant = SMESH::DownCast<SMESH_ParallelMesh_i*>( mesh );
1285   ASSERT( meshServant );
1286   meshServant->SetShape( theShapeObject );
1287
1288   // publish mesh in the study
1289   if ( CanPublishInStudy( mesh ) ) {
1290     SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
1291     aStudyBuilder->NewCommand();  // There is a transaction
1292     SALOMEDS::SObject_wrap aSO = PublishMesh( mesh.in() );
1293     aStudyBuilder->CommitCommand();
1294     if ( !aSO->_is_nil() ) {
1295       // Update Python script
1296       TPythonDump(this) << aSO << " = " << this << ".CreateParallelMesh(" << theShapeObject << ")";
1297     }
1298   }
1299
1300   return mesh._retn();
1301 }
1302
1303 //=============================================================================
1304 /*!
1305  *  SMESH_Gen_i::CreateEmptyMesh
1306  *
1307  *  Create empty mesh
1308  */
1309 //=============================================================================
1310
1311 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateEmptyMesh()
1312 {
1313   Unexpect aCatch(SALOME_SalomeException);
1314   MESSAGE( "SMESH_Gen_i::CreateEmptyMesh" );
1315   // create mesh
1316   SMESH::SMESH_Mesh_var mesh = this->createMesh();
1317
1318   // publish mesh in the study
1319   if ( CanPublishInStudy( mesh ) ) {
1320     SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
1321     aStudyBuilder->NewCommand();  // There is a transaction
1322     SALOMEDS::SObject_wrap aSO = PublishMesh( mesh.in() );
1323     aStudyBuilder->CommitCommand();
1324     if ( !aSO->_is_nil() ) {
1325       // Update Python script
1326       TPythonDump(this) << aSO << " = " << this << ".CreateEmptyMesh()";
1327     }
1328   }
1329
1330   return mesh._retn();
1331 }
1332
1333 namespace
1334 {
1335   //================================================================================
1336   /*!
1337    * \brief Throw an exception in case if the file can't be read
1338    */
1339   //================================================================================
1340
1341   void checkFileReadable( const char* theFileName )
1342   {
1343     SMESH_File f ( theFileName );
1344     if ( !f )
1345     {
1346       if ( !f.error().empty() )
1347         THROW_SALOME_CORBA_EXCEPTION( f.error().c_str(), SALOME::BAD_PARAM);
1348
1349       THROW_SALOME_CORBA_EXCEPTION
1350         (( SMESH_Comment("Can't open for reading the file ") << theFileName ).c_str(),
1351          SALOME::BAD_PARAM );
1352     }
1353   }
1354
1355   //================================================================================
1356   /*!
1357    * \brief Makes a python dump for a function by iterating the given SObjects 
1358    */
1359   //================================================================================
1360
1361   void functionToPythonDump(
1362     SMESH_Gen_i* smesh, const std::string& functionName, std::vector<SALOMEDS::SObject_wrap>& sobjects)
1363   {
1364     TPythonDump aPythonDump(smesh);
1365     aPythonDump << "([";
1366
1367     int i = 0;
1368     for (const SALOMEDS::SObject_wrap& so : sobjects)
1369     {
1370       if (i > 0)
1371       {
1372         aPythonDump << ", ";
1373       }
1374
1375       if (!so->_is_nil())
1376       {
1377         aPythonDump << so;
1378       }
1379       else
1380       {
1381         aPythonDump << "mesh_" << i;
1382       }
1383     }
1384
1385     aPythonDump << "], status) = " << smesh << functionName;
1386   }
1387 }
1388
1389 //=============================================================================
1390 /*!
1391  *  SMESH_Gen_i::CreateMeshFromUNV
1392  *
1393  *  Create mesh and import data from UNV file
1394  */
1395 //=============================================================================
1396
1397 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName )
1398 {
1399   Unexpect aCatch(SALOME_SalomeException);
1400
1401   checkFileReadable( theFileName );
1402
1403   SMESH::SMESH_Mesh_var aMesh = createMesh();
1404   string aFileName;
1405   // publish mesh in the study
1406   if ( CanPublishInStudy( aMesh ) ) {
1407     SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
1408     aStudyBuilder->NewCommand();  // There is a transaction
1409     SALOMEDS::SObject_wrap aSO = PublishMesh( aMesh.in(), aFileName.c_str() );
1410     aStudyBuilder->CommitCommand();
1411     if ( !aSO->_is_nil() ) {
1412       // Update Python script
1413       TPythonDump(this) << aSO << " = " << this << ".CreateMeshesFromUNV(r'" << theFileName << "')";
1414     }
1415   }
1416
1417   SMESH_Mesh_i* aServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( aMesh ).in() );
1418   ASSERT( aServant );
1419   aServant->ImportUNVFile( theFileName );
1420
1421   // Dump creation of groups
1422   SMESH::ListOfGroups_var groups = aServant->GetGroups();
1423
1424   aServant->GetImpl().GetMeshDS()->Modified();
1425   return aMesh._retn();
1426 }
1427
1428 //=============================================================================
1429 /*!
1430  *  SMESH_Gen_i::CreateMeshFromMED
1431  *
1432  *  Create mesh and import data from MED file
1433  */
1434 //=============================================================================
1435
1436 SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char*                  theFileName,
1437                                                      SMESH::DriverMED_ReadStatus& theStatus )
1438 {
1439   checkFileReadable( theFileName );
1440
1441 #ifdef WIN32
1442   char bname[ _MAX_FNAME ];
1443   _splitpath( theFileName, NULL, NULL, bname, NULL );
1444   string aFileName = bname;
1445 #else
1446   string aFileName = basename( const_cast<char *>( theFileName ));
1447 #endif
1448   // Retrieve mesh names from the file
1449   DriverMED_R_SMESHDS_Mesh myReader;
1450   myReader.SetFile( theFileName );
1451   myReader.SetMeshId( -1 );
1452   Driver_Mesh::Status aStatus;
1453   list<string> aNames = myReader.GetMeshNames(aStatus);
1454   SMESH::mesh_array_var aResult = new SMESH::mesh_array();
1455   theStatus = (SMESH::DriverMED_ReadStatus)aStatus;
1456
1457   { // open a new scope to make aPythonDump die before PythonDump in SMESH_Mesh::GetGroups()
1458
1459     // Python Dump
1460     TPythonDump aPythonDump(this);
1461     aPythonDump << "([";
1462
1463     if (theStatus == SMESH::DRS_OK)
1464     {
1465       SALOMEDS::StudyBuilder_var aStudyBuilder;
1466       aStudyBuilder = getStudyServant()->NewBuilder();
1467       aStudyBuilder->NewCommand();  // There is a transaction
1468
1469       aResult->length( aNames.size() );
1470       int i = 0;
1471
1472       // Iterate through all meshes and create mesh objects
1473       for ( const std::string & meshName : aNames )
1474       {
1475         // Python Dump
1476         if (i > 0) aPythonDump << ", ";
1477
1478         // create mesh
1479         SMESH::SMESH_Mesh_var mesh = createMesh();
1480
1481         // publish mesh in the study
1482         SALOMEDS::SObject_wrap aSO;
1483         if ( CanPublishInStudy( mesh ) )
1484           aSO = PublishMesh( mesh.in(), meshName.c_str() );
1485
1486         // Python Dump
1487         if ( !aSO->_is_nil() ) {
1488           aPythonDump << aSO;
1489         } else {
1490           aPythonDump << "mesh_" << i;
1491         }
1492
1493         // Read mesh data (groups are published automatically by ImportMEDFile())
1494         SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
1495         ASSERT( meshServant );
1496         SMESH::DriverMED_ReadStatus status1 =
1497           meshServant->ImportMEDFile( theFileName, meshName.c_str() );
1498         if (status1 > theStatus)
1499           theStatus = status1;
1500
1501         aResult[i++] = SMESH::SMESH_Mesh::_duplicate( mesh );
1502         meshServant->GetImpl().GetMeshDS()->Modified();
1503       }
1504       if ( !aStudyBuilder->_is_nil() )
1505         aStudyBuilder->CommitCommand();
1506     }
1507
1508     // Update Python script
1509     aPythonDump << "], status) = " << this << ".CreateMeshesFromMED( r'" << theFileName << "' )";
1510   }
1511   // Dump creation of groups
1512   for ( CORBA::ULong  i = 0; i < aResult->length(); ++i )
1513     SMESH::ListOfGroups_var groups = aResult[ i ]->GetGroups();
1514
1515   return aResult._retn();
1516 }
1517
1518 //=============================================================================
1519 /*!
1520  *  SMESH_Gen_i::CreateMeshFromSTL
1521  *
1522  *  Create mesh and import data from STL file
1523  */
1524 //=============================================================================
1525
1526 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromSTL( const char* theFileName )
1527 {
1528   Unexpect aCatch(SALOME_SalomeException);
1529   checkFileReadable( theFileName );
1530
1531   SMESH::SMESH_Mesh_var aMesh = createMesh();
1532   //string aFileName;
1533 #ifdef WIN32
1534   char bname[ _MAX_FNAME ];
1535   _splitpath( theFileName, NULL, NULL, bname, NULL );
1536   string aFileName = bname;
1537 #else
1538   string aFileName = basename( const_cast<char *>(theFileName) );
1539 #endif
1540   // publish mesh in the study
1541   if ( CanPublishInStudy( aMesh ) ) {
1542     SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
1543     aStudyBuilder->NewCommand();  // There is a transaction
1544     SALOMEDS::SObject_wrap aSO = PublishInStudy( SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() );
1545     aStudyBuilder->CommitCommand();
1546     if ( !aSO->_is_nil() ) {
1547       // Update Python script
1548       TPythonDump(this) << aSO << " = " << this << ".CreateMeshesFromSTL(r'" << theFileName << "')";
1549     }
1550   }
1551
1552   SMESH_Mesh_i* aServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( aMesh ).in() );
1553   ASSERT( aServant );
1554   aServant->ImportSTLFile( theFileName );
1555   aServant->GetImpl().GetMeshDS()->Modified();
1556   return aMesh._retn();
1557 }
1558
1559 //================================================================================
1560 /*!
1561  * \brief Create meshes and import data from the CGSN file
1562  */
1563 //================================================================================
1564
1565 SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromCGNS( const char*                  theFileName,
1566                                                       SMESH::DriverMED_ReadStatus& theStatus)
1567 {
1568   Unexpect aCatch(SALOME_SalomeException);
1569   checkFileReadable( theFileName );
1570
1571   SMESH::mesh_array_var aResult = new SMESH::mesh_array();
1572
1573 #ifdef WITH_CGNS
1574   // Retrieve nb meshes from the file
1575   DriverCGNS_Read myReader;
1576   myReader.SetFile( theFileName );
1577   Driver_Mesh::Status aStatus;
1578   int nbMeshes = myReader.GetNbMeshes(aStatus);
1579   theStatus = (SMESH::DriverMED_ReadStatus)aStatus;
1580
1581   aResult->length( nbMeshes );
1582
1583   { // open a new scope to make aPythonDump die before PythonDump in SMESH_Mesh::GetGroups()
1584
1585     // Python Dump
1586     TPythonDump aPythonDump(this);
1587     aPythonDump << "([";
1588
1589     if (theStatus == SMESH::DRS_OK)
1590     {
1591       SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
1592       aStudyBuilder->NewCommand();  // There is a transaction
1593
1594       int i = 0;
1595
1596       // Iterate through all meshes and create mesh objects
1597       for ( ; i < nbMeshes; ++i )
1598       {
1599         // Python Dump
1600         if (i > 0) aPythonDump << ", ";
1601
1602         // create mesh
1603         SMESH::SMESH_Mesh_var mesh = createMesh();
1604         aResult[i] = SMESH::SMESH_Mesh::_duplicate( mesh );
1605
1606         // Read mesh data (groups are published automatically by ImportMEDFile())
1607         SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
1608         ASSERT( meshServant );
1609         string meshName;
1610         SMESH::DriverMED_ReadStatus status1 =
1611           meshServant->ImportCGNSFile( theFileName, i, meshName );
1612         if (status1 > theStatus)
1613           theStatus = status1;
1614
1615         meshServant->GetImpl().GetMeshDS()->Modified();
1616         // publish mesh in the study
1617         SALOMEDS::SObject_wrap aSO;
1618         if ( CanPublishInStudy( mesh ) )
1619           aSO = PublishMesh( mesh.in(), meshName.c_str() );
1620
1621         // Python Dump
1622         if ( !aSO->_is_nil() ) {
1623           aPythonDump << aSO;
1624         }
1625         else {
1626           aPythonDump << "mesh_" << i;
1627         }
1628       }
1629       aStudyBuilder->CommitCommand();
1630     }
1631
1632     aPythonDump << "], status) = " << this << ".CreateMeshesFromCGNS(r'" << theFileName << "')";
1633   }
1634   // Dump creation of groups
1635   for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
1636     SMESH::ListOfGroups_var groups = aResult[ i ]->GetGroups();
1637 #else
1638   THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
1639 #endif
1640
1641   return aResult._retn();
1642 }
1643
1644 //================================================================================
1645 /*!
1646  * \brief Create a mesh and import data from a GMF file
1647  */
1648 //================================================================================
1649
1650 SMESH::SMESH_Mesh_ptr
1651 SMESH_Gen_i::CreateMeshesFromGMF( const char*             theFileName,
1652                                   CORBA::Boolean          theMakeRequiredGroups,
1653                                   SMESH::ComputeError_out theError)
1654 {
1655   Unexpect aCatch(SALOME_SalomeException);
1656   checkFileReadable( theFileName );
1657
1658   SMESH::SMESH_Mesh_var aMesh = createMesh();
1659 #ifdef WIN32
1660   char bname[ _MAX_FNAME ];
1661   _splitpath( theFileName, NULL, NULL, bname, NULL );
1662   string aFileName = bname;
1663 #else
1664   string aFileName = basename( const_cast<char *>(theFileName) );
1665 #endif
1666   // publish mesh in the study
1667   if ( CanPublishInStudy( aMesh ) ) {
1668     SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
1669     aStudyBuilder->NewCommand();  // There is a transaction
1670     SALOMEDS::SObject_wrap aSO = PublishInStudy( SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() );
1671     aStudyBuilder->CommitCommand();
1672     if ( !aSO->_is_nil() ) {
1673       // Update Python script
1674       TPythonDump(this) << "("<< aSO << ", error) = " << this << ".CreateMeshesFromGMF(r'"
1675                     << theFileName << "', "
1676                     << theMakeRequiredGroups << " )";
1677     }
1678   }
1679   SMESH_Mesh_i* aServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( aMesh ).in() );
1680   ASSERT( aServant );
1681   theError = aServant->ImportGMFFile( theFileName, theMakeRequiredGroups );
1682   aServant->GetImpl().GetMeshDS()->Modified();
1683   return aMesh._retn();
1684 }
1685
1686 //================================================================================
1687 /*!
1688  * \brief Create a mesh and import data from any file supported by meshio library
1689  */
1690 //================================================================================
1691
1692 SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMESHIO(const char* theFileName,
1693                                                        SMESH::DriverMED_ReadStatus& theStatus)
1694 {
1695   Unexpect aCatch(SALOME_SalomeException);
1696   checkFileReadable(theFileName);
1697
1698   MESSAGE("Import part with meshio through an intermediate MED file");
1699
1700   // Create an object that holds a temp file name and
1701   // removes the file when goes out of scope.
1702   SMESH_Meshio meshio;
1703   const QString tempFileName = meshio.CreateTempFileName(theFileName);
1704
1705   // Convert temp file into a target one with meshio command
1706   meshio.Convert(theFileName, tempFileName);
1707
1708   // We don't need a python dump from SMESH_Gen_i::CreateMeshesFromMED(), so
1709   // we can't use this method as is here. The followed code is an edited part of
1710   // copy pasted CreateMeshesFromMED().
1711
1712   // Retrieve mesh names from the file
1713   DriverMED_R_SMESHDS_Mesh myReader;
1714   myReader.SetFile(tempFileName.toStdString());
1715   myReader.SetMeshId(-1);
1716   Driver_Mesh::Status aStatus;
1717   list<string> aNames = myReader.GetMeshNames(aStatus);
1718   SMESH::mesh_array_var aResult = new SMESH::mesh_array();
1719   theStatus = (SMESH::DriverMED_ReadStatus)aStatus;
1720
1721   if (theStatus == SMESH::DRS_OK)
1722   {
1723     SALOMEDS::StudyBuilder_var aStudyBuilder;
1724     aStudyBuilder = getStudyServant()->NewBuilder();
1725     aStudyBuilder->NewCommand();  // There is a transaction
1726
1727     aResult->length(aNames.size());
1728     std::vector<SALOMEDS::SObject_wrap> sobjects;
1729     int i = 0;
1730
1731     // Iterate through all meshes and create mesh objects
1732     for (const std::string& meshName : aNames)
1733     {
1734       // create mesh
1735       SMESH::SMESH_Mesh_var mesh = createMesh();
1736
1737       // publish mesh in the study
1738       SALOMEDS::SObject_wrap aSO;
1739       if (CanPublishInStudy(mesh))
1740         aSO = PublishMesh(mesh.in(), meshName.c_str());
1741
1742       // Save SO to use in a python dump
1743       sobjects.emplace_back(aSO);
1744
1745       // Read mesh data (groups are published automatically by ImportMEDFile())
1746       SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>(GetServant(mesh).in());
1747       ASSERT(meshServant);
1748       SMESH::DriverMED_ReadStatus status1 =
1749         meshServant->ImportMEDFile(tempFileName.toUtf8().data(), meshName.c_str());
1750       if (status1 > theStatus)
1751         theStatus = status1;
1752
1753       aResult[i++] = SMESH::SMESH_Mesh::_duplicate(mesh);
1754       meshServant->GetImpl().GetMeshDS()->Modified();
1755     }
1756
1757     if (!aStudyBuilder->_is_nil())
1758       aStudyBuilder->CommitCommand();
1759
1760     // Python dump
1761     const std::string functionName = std::string(".CreateMeshesFromMESHIO(r'") + theFileName + "')";
1762     functionToPythonDump(this, functionName, sobjects);
1763   }
1764
1765   // Dump creation of groups
1766   for (CORBA::ULong  i = 0; i < aResult->length(); ++i)
1767     SMESH::ListOfGroups_var groups = aResult[i]->GetGroups();
1768
1769   return aResult._retn();
1770 }
1771
1772 //=============================================================================
1773 /*!
1774  *  SMESH_Gen_i::IsReadyToCompute
1775  *
1776  *  Return true if mesh contains enough data to be computed
1777  */
1778 //=============================================================================
1779
1780 CORBA::Boolean SMESH_Gen_i::IsReadyToCompute( SMESH::SMESH_Mesh_ptr theMesh,
1781                                               GEOM::GEOM_Object_ptr theShapeObject )
1782 {
1783   Unexpect aCatch(SALOME_SalomeException);
1784   MESSAGE( "SMESH_Gen_i::IsReadyToCompute" );
1785
1786   if ( CORBA::is_nil( theShapeObject ) )
1787     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
1788                                   SALOME::BAD_PARAM );
1789   if ( CORBA::is_nil( theMesh ) )
1790     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
1791                                   SALOME::BAD_PARAM );
1792   try {
1793     // get mesh servant
1794     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
1795     ASSERT( meshServant );
1796     if ( meshServant ) {
1797       // get local TopoDS_Shape
1798       TopoDS_Shape myLocShape = GeomObjectToShape( theShapeObject );
1799       // call implementation
1800       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
1801       return myGen.CheckAlgoState( myLocMesh, myLocShape );
1802     }
1803   }
1804   catch ( SALOME_Exception& S_ex ) {
1805     INFOS( "catch exception "<< S_ex.what() );
1806   }
1807   return false;
1808 }
1809
1810 //================================================================================
1811 /*!
1812  * \brief  Find SObject for an algo
1813  */
1814 //================================================================================
1815
1816 SALOMEDS::SObject_ptr SMESH_Gen_i::GetAlgoSO(const ::SMESH_Algo* algo)
1817 {
1818   if ( algo ) {
1819     SALOMEDS::Study_var aStudy = getStudyServant();
1820     if ( !aStudy->_is_nil() ) {
1821       // find algo in the study
1822       CORBA::String_var compDataType  = ComponentDataType();
1823       SALOMEDS::SComponent_wrap father = aStudy->FindComponent( compDataType.in() );
1824       if ( !father->_is_nil() ) {
1825         SALOMEDS::ChildIterator_wrap itBig = aStudy->NewChildIterator( father );
1826         for ( ; itBig->More(); itBig->Next() ) {
1827           SALOMEDS::SObject_wrap gotBranch = itBig->Value();
1828           if ( gotBranch->Tag() == GetAlgorithmsRootTag() ) {
1829             SALOMEDS::ChildIterator_wrap algoIt = aStudy->NewChildIterator( gotBranch );
1830             for ( ; algoIt->More(); algoIt->Next() ) {
1831               SALOMEDS::SObject_wrap algoSO = algoIt->Value();
1832               CORBA::Object_var     algoIOR = SObjectToObject( algoSO );
1833               if ( !CORBA::is_nil( algoIOR )) {
1834                 SMESH_Hypothesis_i* impl = SMESH::DownCast<SMESH_Hypothesis_i*>( algoIOR );
1835                 if ( impl && impl->GetImpl() == algo )
1836                   return algoSO._retn();
1837               }
1838             } // loop on algo SO's
1839             break;
1840           } // if algo tag
1841         } // SMESH component iterator
1842       }
1843     }
1844   }
1845   return SALOMEDS::SObject::_nil();
1846 }
1847
1848 //================================================================================
1849 /*!
1850  * \brief Return errors of mesh computation
1851  */
1852 //================================================================================
1853
1854 SMESH::compute_error_array* SMESH_Gen_i::GetComputeErrors( SMESH::SMESH_Mesh_ptr theMesh,
1855                                                            GEOM::GEOM_Object_ptr theSubObject )
1856 {
1857   Unexpect aCatch(SALOME_SalomeException);
1858   MESSAGE( "SMESH_Gen_i::GetComputeErrors()" );
1859
1860   if ( CORBA::is_nil( theSubObject ) && theMesh->HasShapeToMesh())
1861     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM );
1862
1863   if ( CORBA::is_nil( theMesh ) )
1864     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM );
1865
1866   SMESH::compute_error_array_var error_array = new SMESH::compute_error_array;
1867   try {
1868     if ( SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh ))
1869     {
1870       TopoDS_Shape shape;
1871       if(theMesh->HasShapeToMesh())
1872         shape = GeomObjectToShape( theSubObject );
1873       else
1874         shape = SMESH_Mesh::PseudoShape();
1875
1876       ::SMESH_Mesh& mesh = meshServant->GetImpl();
1877
1878       error_array->length( mesh.GetMeshDS()->MaxShapeIndex() );
1879       int nbErr = 0;
1880
1881       SMESH_subMesh *sm = mesh.GetSubMesh(shape);
1882       const bool includeSelf = true, complexShapeFirst = true;
1883       SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(includeSelf,
1884                                                                complexShapeFirst);
1885       while ( smIt->more() )
1886       {
1887         sm = smIt->next();
1888         // if ( sm->GetSubShape().ShapeType() == TopAbs_VERTEX )
1889         //   break;
1890         SMESH_ComputeErrorPtr error = sm->GetComputeError();
1891         if ( error && !error->IsOK() )
1892         {
1893           if ( !( error->myAlgo ) &&
1894                !( error->myAlgo = sm->GetAlgo() ))
1895             continue;
1896           SMESH::ComputeError & errStruct = error_array[ nbErr++ ];
1897           errStruct.code       = -( error->myName < 0 ? error->myName + 1: error->myName ); // -1 -> 0
1898           errStruct.comment    = error->myComment.c_str();
1899           errStruct.subShapeID = sm->GetId();
1900           SALOMEDS::SObject_wrap algoSO = GetAlgoSO( error->myAlgo );
1901           if ( !algoSO->_is_nil() ) {
1902             CORBA::String_var algoName = algoSO->GetName();
1903             errStruct.algoName = algoName;
1904           }
1905           else {
1906             errStruct.algoName = error->myAlgo->GetName();
1907           }
1908           errStruct.hasBadMesh = error->HasBadElems();
1909         }
1910       }
1911       error_array->length( nbErr );
1912     }
1913   }
1914   catch ( SALOME_Exception& S_ex ) {
1915     INFOS( "catch exception "<< S_ex.what() );
1916   }
1917
1918   return error_array._retn();
1919 }
1920
1921 //================================================================================
1922 /*!
1923  * \brief Return mesh elements preventing computation of a subshape
1924  */
1925 //================================================================================
1926
1927 SMESH::MeshPreviewStruct*
1928 SMESH_Gen_i::GetBadInputElements( SMESH::SMESH_Mesh_ptr theMesh,
1929                                   CORBA::Short          theSubShapeID )
1930 {
1931   Unexpect aCatch(SALOME_SalomeException);
1932   MESSAGE( "SMESH_Gen_i::GetBadInputElements()" );
1933
1934   if ( CORBA::is_nil( theMesh ) )
1935     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM );
1936
1937   SMESH::MeshPreviewStruct_var result = new SMESH::MeshPreviewStruct;
1938   try {
1939     // mesh servant
1940     if ( SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh ))
1941     {
1942       // mesh implementation
1943       ::SMESH_Mesh& mesh = meshServant->GetImpl();
1944       // submesh by subshape id
1945       if ( SMESH_subMesh * sm = mesh.GetSubMeshContaining( theSubShapeID ))
1946       {
1947         // compute error
1948         SMESH_ComputeErrorPtr error = sm->GetComputeError();
1949         if ( error && error->HasBadElems() )
1950         {
1951           typedef map<const SMDS_MeshElement*, int > TNode2LocalIDMap;
1952           typedef TNode2LocalIDMap::iterator         TNodeLocalID;
1953
1954           // get nodes of elements and count elements
1955           TNode2LocalIDMap mapNode2LocalID;
1956           list< TNodeLocalID > connectivity;
1957           int i, nbElements = 0, nbConnNodes = 0;
1958
1959           const list<const SMDS_MeshElement*>& badElems =
1960             static_cast<SMESH_BadInputElements*>( error.get() )->myBadElements;
1961           list<const SMDS_MeshElement*>::const_iterator elemIt  = badElems.begin();
1962           list<const SMDS_MeshElement*>::const_iterator elemEnd = badElems.end();
1963           for ( ; elemIt != elemEnd; ++elemIt, ++nbElements )
1964           {
1965             SMDS_ElemIteratorPtr nIt = (*elemIt)->nodesIterator();
1966             while ( nIt->more() )
1967               connectivity.push_back
1968                 ( mapNode2LocalID.insert( make_pair( nIt->next(), ++nbConnNodes)).first );
1969           }
1970           // fill node coords and assign local ids to the nodes
1971           int nbNodes = mapNode2LocalID.size();
1972           result->nodesXYZ.length( nbNodes );
1973           TNodeLocalID node2ID = mapNode2LocalID.begin();
1974           for ( i = 0; i < nbNodes; ++i, ++node2ID ) {
1975             node2ID->second = i;
1976             const SMDS_MeshNode* node = (const SMDS_MeshNode*) node2ID->first;
1977             result->nodesXYZ[i].x = node->X();
1978             result->nodesXYZ[i].y = node->Y();
1979             result->nodesXYZ[i].z = node->Z();
1980           }
1981           // fill connectivity
1982           result->elementConnectivities.length( nbConnNodes );
1983           list< TNodeLocalID >::iterator connIt = connectivity.begin();
1984           for ( i = 0; i < nbConnNodes; ++i, ++connIt ) {
1985             result->elementConnectivities[i] = (*connIt)->second;
1986           }
1987           // fill element types
1988           result->elementTypes.length( nbElements );
1989           for ( i = 0, elemIt = badElems.begin(); i <nbElements; ++i, ++elemIt )
1990           {
1991             const SMDS_MeshElement* elem = *elemIt;
1992             result->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) elem->GetType();
1993             result->elementTypes[i].isPoly           = elem->IsPoly();
1994             result->elementTypes[i].nbNodesInElement = elem->NbNodes();
1995           }
1996         }
1997       }
1998     }
1999   }
2000   catch ( SALOME_Exception& S_ex ) {
2001     INFOS( "catch exception "<< S_ex.what() );
2002   }
2003
2004   return result._retn();
2005 }
2006
2007 //================================================================================
2008 /*!
2009  * \brief Create a group of elements preventing computation of a sub-shape
2010  */
2011 //================================================================================
2012
2013 SMESH::ListOfGroups*
2014 SMESH_Gen_i::MakeGroupsOfBadInputElements( SMESH::SMESH_Mesh_ptr theMesh,
2015                                            CORBA::Short          theSubShapeID,
2016                                            const char*           theGroupName )
2017 {
2018   Unexpect aCatch(SALOME_SalomeException);
2019
2020   SMESH::ListOfGroups_var groups;
2021
2022   if ( CORBA::is_nil( theMesh ) )
2023     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM );
2024
2025   try {
2026     if ( SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh ))
2027     {
2028       groups = meshServant->MakeGroupsOfBadInputElements( theSubShapeID, theGroupName );
2029       TPythonDump(this) << groups << " = " << this
2030                     << ".MakeGroupsOfBadInputElements( "
2031                     << theMesh << ", " << theSubShapeID << ", '" << theGroupName << "' )";
2032     }
2033   }
2034   catch ( SALOME_Exception& S_ex ) {
2035     INFOS( "catch exception "<< S_ex.what() );
2036   }
2037   return groups._retn();
2038 }
2039
2040 //================================================================================
2041 /*!
2042  * \brief Returns errors of hypotheses definition
2043  *  \param theMesh - the mesh
2044  *  \param theSubObject - the main or sub- shape
2045  *  \retval SMESH::algo_error_array* - sequence of errors
2046  */
2047 //================================================================================
2048
2049 SMESH::algo_error_array* SMESH_Gen_i::GetAlgoState( SMESH::SMESH_Mesh_ptr theMesh,
2050                                                     GEOM::GEOM_Object_ptr theSubObject )
2051 {
2052   Unexpect aCatch(SALOME_SalomeException);
2053   MESSAGE( "SMESH_Gen_i::GetAlgoState()" );
2054
2055   if ( CORBA::is_nil( theSubObject ) && theMesh->HasShapeToMesh())
2056     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM );
2057
2058   if ( CORBA::is_nil( theMesh ) )
2059     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM );
2060
2061   SMESH::algo_error_array_var error_array = new SMESH::algo_error_array;
2062   try {
2063     SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
2064     ASSERT( meshServant );
2065     if ( meshServant ) {
2066       TopoDS_Shape myLocShape;
2067       if(theMesh->HasShapeToMesh())
2068         myLocShape = GeomObjectToShape( theSubObject );
2069       else
2070         myLocShape = SMESH_Mesh::PseudoShape();
2071
2072       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
2073       list< ::SMESH_Gen::TAlgoStateError > error_list;
2074       list< ::SMESH_Gen::TAlgoStateError >::iterator error;
2075       // call ::SMESH_Gen::GetAlgoState()
2076       myGen.GetAlgoState( myLocMesh, myLocShape, error_list );
2077       error_array->length( error_list.size() );
2078       int i = 0;
2079       for ( error = error_list.begin(); error != error_list.end(); ++error )
2080       {
2081         // fill AlgoStateError structure
2082         SMESH::AlgoStateError & errStruct = error_array[ i++ ];
2083         errStruct.state        = SMESH_Mesh_i::ConvertHypothesisStatus( error->_name );
2084         errStruct.algoDim      = error->_algoDim;
2085         errStruct.isGlobalAlgo = error->_isGlobalAlgo;
2086         errStruct.algoName     = "";
2087         SALOMEDS::SObject_wrap algoSO = GetAlgoSO( error->_algo );
2088         if ( !algoSO->_is_nil() ) {
2089           CORBA::String_var algoName = algoSO->GetName();
2090           errStruct.algoName = algoName.in();
2091         }
2092       }
2093     }
2094   }
2095   catch ( SALOME_Exception& S_ex ) {
2096     INFOS( "catch exception "<< S_ex.what() );
2097   }
2098   return error_array._retn();
2099 }
2100
2101 //=============================================================================
2102 /*!
2103  *  SMESH_Gen_i::GetSubShapesId
2104  *
2105  *  Get sub-shapes unique ID's list
2106  */
2107 //=============================================================================
2108
2109 SMESH::long_array*
2110 SMESH_Gen_i::GetSubShapesId( GEOM::GEOM_Object_ptr      theMainShapeObject,
2111                              const SMESH::object_array& theListOfSubShapeObject )
2112 {
2113   Unexpect aCatch(SALOME_SalomeException);
2114   MESSAGE( "SMESH_Gen_i::GetSubShapesId" );
2115
2116   SMESH::long_array_var shapesId = new SMESH::long_array;
2117   set<int> setId;
2118
2119   if ( CORBA::is_nil( theMainShapeObject ) )
2120     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM );
2121
2122   try
2123   {
2124     TopoDS_Shape myMainShape = GeomObjectToShape(theMainShapeObject);
2125     TopTools_IndexedMapOfShape myIndexToShape;
2126     TopExp::MapShapes(myMainShape,myIndexToShape);
2127
2128     for ( CORBA::ULong i = 0; i < theListOfSubShapeObject.length(); i++ )
2129     {
2130       GEOM::GEOM_Object_var aShapeObject
2131         = GEOM::GEOM_Object::_narrow(theListOfSubShapeObject[i]);
2132       if ( CORBA::is_nil( aShapeObject ) )
2133         THROW_SALOME_CORBA_EXCEPTION ("bad shape object reference",     \
2134                                       SALOME::BAD_PARAM );
2135
2136       TopoDS_Shape locShape  = GeomObjectToShape(aShapeObject);
2137       for (TopExp_Explorer exp(locShape,TopAbs_FACE); exp.More(); exp.Next())
2138       {
2139         const TopoDS_Face& F = TopoDS::Face(exp.Current());
2140         setId.insert(myIndexToShape.FindIndex(F));
2141         SCRUTE(myIndexToShape.FindIndex(F));
2142       }
2143       for (TopExp_Explorer exp(locShape,TopAbs_EDGE); exp.More(); exp.Next())
2144       {
2145         const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
2146         setId.insert(myIndexToShape.FindIndex(E));
2147         SCRUTE(myIndexToShape.FindIndex(E));
2148       }
2149       for (TopExp_Explorer exp(locShape,TopAbs_VERTEX); exp.More(); exp.Next())
2150       {
2151         const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
2152         setId.insert(myIndexToShape.FindIndex(V));
2153         SCRUTE(myIndexToShape.FindIndex(V));
2154       }
2155     }
2156     shapesId->length(setId.size());
2157     set<int>::iterator iind;
2158     int i=0;
2159     for (iind = setId.begin(); iind != setId.end(); iind++)
2160     {
2161       SCRUTE((*iind));
2162       shapesId[i] = (*iind);
2163       SCRUTE(shapesId[i]);
2164       i++;
2165     }
2166   }
2167   catch (SALOME_Exception& S_ex)
2168   {
2169     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
2170   }
2171
2172   return shapesId._retn();
2173 }
2174
2175 //=============================================================================
2176 /*!
2177  *  SMESH_Gen_i::Compute
2178  *
2179  *  Compute mesh on a shape
2180  */
2181 //=============================================================================
2182
2183 CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
2184                                      GEOM::GEOM_Object_ptr theShapeObject )
2185 {
2186   //MEMOSTAT;
2187   Unexpect aCatch(SALOME_SalomeException);
2188   MESSAGE( "SMESH_Gen_i::Compute" );
2189
2190   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
2191     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
2192                                   SALOME::BAD_PARAM );
2193
2194   if ( CORBA::is_nil( theMesh ) )
2195     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
2196                                   SALOME::BAD_PARAM );
2197
2198   // Update Python script
2199   TPythonDump(this) << "isDone = " << this << ".Compute( "
2200                     << theMesh << ", " << theShapeObject << ")";
2201   TPythonDump(this) << this << ".CheckCompute( "
2202                     << theMesh << ")";
2203
2204   try {
2205     // get mesh servant
2206     SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
2207     ASSERT( meshServant );
2208     if ( meshServant ) {
2209       if ( isGeomModifIcon( theMesh ))
2210         meshServant->Clear();
2211       else
2212         meshServant->Load();
2213       // NPAL16168: "geometrical group edition from a submesh don't modify mesh computation"
2214       meshServant->CheckGeomModif();
2215       // get local TopoDS_Shape
2216       TopoDS_Shape myLocShape;
2217       if(theMesh->HasShapeToMesh())
2218         myLocShape = GeomObjectToShape( theShapeObject );
2219       else
2220         myLocShape = SMESH_Mesh::PseudoShape();
2221       // call implementation compute
2222       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
2223       myGen.PrepareCompute( myLocMesh, myLocShape );
2224       int how = ::SMESH_Gen::COMPACT_MESH;
2225       if ( myLocShape != myLocMesh.GetShapeToMesh() ) // compute a sub-mesh
2226         how |= ::SMESH_Gen::SHAPE_ONLY;
2227       bool ok = myGen.Compute( myLocMesh, myLocShape, how );
2228       meshServant->CreateGroupServants(); // algos can create groups (issue 0020918)
2229       myLocMesh.GetMeshDS()->Modified();
2230       UpdateIcons( theMesh );
2231       if ( ok )
2232         HighLightInvalid( theMesh, /*isInvalid=*/false );
2233       return ok;
2234     }
2235   }
2236   catch ( std::bad_alloc& ) {
2237     INFOS( "Compute(): lack of memory" );
2238   }
2239   catch ( SALOME_Exception& S_ex ) {
2240     INFOS( "Compute(): catch exception "<< S_ex.what() );
2241   }
2242   catch ( ... ) {
2243     INFOS( "Compute(): unknown exception " );
2244   }
2245   return false;
2246 }
2247
2248 //=============================================================================
2249 /*!
2250  *  SMESH_Gen_i::CancelCompute
2251  *
2252  *  Cancel Compute mesh on a shape
2253  */
2254 //=============================================================================
2255
2256 void SMESH_Gen_i::CancelCompute( SMESH::SMESH_Mesh_ptr theMesh,
2257                                  GEOM::GEOM_Object_ptr theShapeObject )
2258 {
2259   if ( SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() ))
2260   {
2261     ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
2262     TopoDS_Shape myLocShape;
2263     if(theMesh->HasShapeToMesh())
2264       myLocShape = GeomObjectToShape( theShapeObject );
2265     else
2266       myLocShape = SMESH_Mesh::PseudoShape();
2267     myGen.CancelCompute( myLocMesh, myLocShape);
2268   }
2269 }
2270
2271 //=============================================================================
2272 /*!
2273  *  SMESH_Gen_i::Precompute
2274  *
2275  *  Compute mesh as preview till indicated dimension on shape
2276  */
2277 //=============================================================================
2278
2279 SMESH::MeshPreviewStruct* SMESH_Gen_i::Precompute( SMESH::SMESH_Mesh_ptr theMesh,
2280                                                    GEOM::GEOM_Object_ptr theShapeObject,
2281                                                    SMESH::Dimension      theDimension,
2282                                                    SMESH::long_array&    theShapesId)
2283 {
2284   Unexpect aCatch(SALOME_SalomeException);
2285   MESSAGE( "SMESH_Gen_i::Precompute" );
2286
2287   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
2288     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
2289                                   SALOME::BAD_PARAM );
2290
2291   if ( CORBA::is_nil( theMesh ) )
2292     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
2293                                   SALOME::BAD_PARAM );
2294
2295   SMESH::MeshPreviewStruct_var result = new SMESH::MeshPreviewStruct;
2296   try {
2297     // get mesh servant
2298     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
2299     meshServant->Load();
2300     ASSERT( meshServant );
2301     if ( meshServant ) {
2302       // NPAL16168: "geometrical group edition from a submesh don't modify mesh computation"
2303       meshServant->CheckGeomModif();
2304       // get local TopoDS_Shape
2305       TopoDS_Shape myLocShape;
2306       if(theMesh->HasShapeToMesh())
2307         myLocShape = GeomObjectToShape( theShapeObject );
2308       else
2309         return result._retn();
2310
2311       // call implementation compute
2312       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
2313       TSetOfInt shapeIds;
2314       ::MeshDimension aDim = (MeshDimension)theDimension;
2315       if ( myGen.Compute( myLocMesh, myLocShape, ::SMESH_Gen::COMPACT_MESH, aDim, &shapeIds ) )
2316       {
2317         int nbShapeId = shapeIds.size();
2318         theShapesId.length( nbShapeId );
2319         // iterates on shapes and collect mesh entities into mesh preview
2320         TSetOfInt::const_iterator idIt = shapeIds.begin();
2321         TSetOfInt::const_iterator idEnd = shapeIds.end();
2322         std::map< int, int > mapOfShIdNb;
2323         std::set< SMESH_TLink > setOfEdge;
2324         std::list< SMDSAbs_ElementType > listOfElemType;
2325         typedef map<const SMDS_MeshElement*, int > TNode2LocalIDMap;
2326         typedef TNode2LocalIDMap::iterator         TNodeLocalID;
2327         TNode2LocalIDMap mapNode2LocalID;
2328         list< TNodeLocalID > connectivity;
2329         int i, nbConnNodes = 0;
2330         std::set< const SMESH_subMesh* > setOfVSubMesh;
2331         // iterates on shapes
2332         for ( ; idIt != idEnd; idIt++ )
2333         {
2334           if ( mapOfShIdNb.find( *idIt ) != mapOfShIdNb.end() )
2335             continue;
2336           SMESH_subMesh* sm = myLocMesh.GetSubMeshContaining(*idIt);
2337           if ( !sm || !sm->IsMeshComputed() )
2338             continue;
2339
2340           const TopoDS_Shape& aSh = sm->GetSubShape();
2341           const int shDim = myGen.GetShapeDim( aSh );
2342           if ( shDim < 1 || shDim > theDimension )
2343             continue;
2344
2345           mapOfShIdNb[ *idIt ] = 0;
2346           theShapesId[ mapOfShIdNb.size() - 1 ] = *idIt;
2347
2348           SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
2349           if ( !smDS ) continue;
2350
2351           if ( theDimension == SMESH::DIM_2D )
2352           {
2353             SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
2354             while ( faceIt->more() )
2355             {
2356               const SMDS_MeshElement* face = faceIt->next();
2357               int aNbNode = face->NbNodes();
2358               if ( aNbNode > 4 )
2359                 aNbNode /= 2; // do not take into account additional middle nodes
2360
2361               SMDS_MeshNode* node1 = (SMDS_MeshNode*)face->GetNode( 0 );
2362               for ( int nIndx = 0; nIndx < aNbNode; nIndx++ )
2363               {
2364                 SMDS_MeshNode* node2 = (SMDS_MeshNode*)face->GetNode( nIndx+1 < aNbNode ? nIndx+1 : 0 );
2365                 if ( setOfEdge.insert( SMESH_TLink ( node1, node2 ) ).second )
2366                 {
2367                   listOfElemType.push_back( SMDSAbs_Edge );
2368                   connectivity.push_back
2369                     ( mapNode2LocalID.insert( make_pair( node1, ++nbConnNodes)).first );
2370                   connectivity.push_back
2371                     ( mapNode2LocalID.insert( make_pair( node2, ++nbConnNodes)).first );
2372                 }
2373                 node1 = node2;
2374               }
2375             }
2376           }
2377           else if ( theDimension == SMESH::DIM_1D )
2378           {
2379             SMDS_NodeIteratorPtr nodeIt = smDS->GetNodes();
2380             while ( nodeIt->more() )
2381             {
2382               listOfElemType.push_back( SMDSAbs_Node );
2383               connectivity.push_back
2384                 ( mapNode2LocalID.insert( make_pair( nodeIt->next(), ++nbConnNodes)).first );
2385             }
2386             // add corner nodes by first vertex from edge
2387             SMESH_subMeshIteratorPtr edgeSmIt =
2388               sm->getDependsOnIterator(/*includeSelf*/false,
2389                                        /*complexShapeFirst*/false);
2390             while ( edgeSmIt->more() )
2391             {
2392               SMESH_subMesh* vertexSM = edgeSmIt->next();
2393               // check that vertex is not already treated
2394               if ( !setOfVSubMesh.insert( vertexSM ).second )
2395                 continue;
2396               if ( vertexSM->GetSubShape().ShapeType() != TopAbs_VERTEX )
2397                 continue;
2398
2399               const SMESHDS_SubMesh* vertexSmDS = vertexSM->GetSubMeshDS();
2400               SMDS_NodeIteratorPtr nodeIt = vertexSmDS->GetNodes();
2401               while ( nodeIt->more() )
2402               {
2403                 listOfElemType.push_back( SMDSAbs_Node );
2404                 connectivity.push_back
2405                   ( mapNode2LocalID.insert( make_pair( nodeIt->next(), ++nbConnNodes)).first );
2406               }
2407             }
2408           }
2409         }
2410
2411         // fill node coords and assign local ids to the nodes
2412         int nbNodes = mapNode2LocalID.size();
2413         result->nodesXYZ.length( nbNodes );
2414         TNodeLocalID node2ID = mapNode2LocalID.begin();
2415         for ( i = 0; i < nbNodes; ++i, ++node2ID ) {
2416           node2ID->second = i;
2417           const SMDS_MeshNode* node = (const SMDS_MeshNode*) node2ID->first;
2418           result->nodesXYZ[i].x = node->X();
2419           result->nodesXYZ[i].y = node->Y();
2420           result->nodesXYZ[i].z = node->Z();
2421         }
2422         // fill connectivity
2423         result->elementConnectivities.length( nbConnNodes );
2424         list< TNodeLocalID >::iterator connIt = connectivity.begin();
2425         for ( i = 0; i < nbConnNodes; ++i, ++connIt ) {
2426           result->elementConnectivities[i] = (*connIt)->second;
2427         }
2428
2429         // fill element types
2430         result->elementTypes.length( listOfElemType.size() );
2431         std::list< SMDSAbs_ElementType >::const_iterator typeIt = listOfElemType.begin();
2432         std::list< SMDSAbs_ElementType >::const_iterator typeEnd = listOfElemType.end();
2433         for ( i = 0; typeIt != typeEnd; ++i, ++typeIt )
2434         {
2435           SMDSAbs_ElementType elemType = *typeIt;
2436           result->elementTypes[i].SMDS_ElementType = (SMESH::ElementType)elemType;
2437           result->elementTypes[i].isPoly           = false;
2438           result->elementTypes[i].nbNodesInElement = elemType == SMDSAbs_Edge ? 2 : 1;
2439         }
2440
2441         // correct number of shapes
2442         theShapesId.length( mapOfShIdNb.size() );
2443       }
2444     }
2445   }
2446   catch ( std::bad_alloc& ) {
2447     INFOS( "Precompute(): lack of memory" );
2448   }
2449   catch ( SALOME_Exception& S_ex ) {
2450     INFOS( "Precompute(): catch exception "<< S_ex.what() );
2451   }
2452   catch ( ... ) {
2453     INFOS( "Precompute(): unknown exception " );
2454   }
2455   return result._retn();
2456 }
2457
2458
2459 //=============================================================================
2460 /*!
2461  *  SMESH_Gen_i::Evaluate
2462  *
2463  *  Evaluate mesh on a shape
2464  */
2465 //=============================================================================
2466
2467 SMESH::smIdType_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
2468                                              GEOM::GEOM_Object_ptr theShapeObject)
2469 {
2470   Unexpect aCatch(SALOME_SalomeException);
2471   MESSAGE( "SMESH_Gen_i::Evaluate" );
2472
2473   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
2474     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM );
2475
2476   if ( CORBA::is_nil( theMesh ) )
2477     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", SALOME::BAD_PARAM );
2478
2479   SMESH::smIdType_array_var nbels = new SMESH::smIdType_array;
2480   nbels->length(SMESH::Entity_Last);
2481   int i = SMESH::Entity_Node;
2482   for (; i < SMESH::Entity_Last; i++)
2483     nbels[i] = 0;
2484
2485   // Update Python script
2486   TPythonDump(this) << "theNbElems = " << this << ".Evaluate( "
2487                 << theMesh << ", " << theShapeObject << ")";
2488
2489   try {
2490     // get mesh servant
2491     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
2492     ASSERT( meshServant );
2493     if ( meshServant ) {
2494       meshServant->Load();
2495       // NPAL16168: "geometrical group edition from a submesh don't modify mesh computation"
2496       meshServant->CheckGeomModif();
2497       // get local TopoDS_Shape
2498       TopoDS_Shape myLocShape;
2499       if(theMesh->HasShapeToMesh())
2500         myLocShape = GeomObjectToShape( theShapeObject );
2501       else
2502         myLocShape = SMESH_Mesh::PseudoShape();
2503       // call implementation compute
2504       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
2505       MapShapeNbElems aResMap;
2506       /*CORBA::Boolean ret =*/ myGen.Evaluate( myLocMesh, myLocShape, aResMap);
2507       MapShapeNbElemsItr anIt = aResMap.begin();
2508       for(; anIt!=aResMap.end(); anIt++) {
2509         const vector<smIdType>& aVec = (*anIt).second;
2510         for ( i = SMESH::Entity_Node; i < (int)aVec.size(); i++ ) {
2511           smIdType nbElem = aVec[i];
2512           if ( nbElem < 0 ) // algo failed, check that it has reported a message
2513           {
2514             SMESH_subMesh*            sm = anIt->first;
2515             SMESH_ComputeErrorPtr& error = sm->GetComputeError();
2516             const SMESH_Algo*       algo = sm->GetAlgo();
2517             if ( (algo && !error.get()) || error->IsOK() )
2518               error.reset( new SMESH_ComputeError( COMPERR_ALGO_FAILED,"Failed to evaluate",algo));
2519           }
2520           else
2521           {
2522             nbels[i] += aVec[i];
2523           }
2524         }
2525       }
2526       return nbels._retn();
2527     }
2528   }
2529   catch ( std::bad_alloc& ) {
2530     INFOS( "Evaluate(): lack of memory" );
2531   }
2532   catch ( SALOME_Exception& S_ex ) {
2533     INFOS( "Evaluate(): catch exception "<< S_ex.what() );
2534   }
2535   catch ( ... ) {
2536     INFOS( "Evaluate(): unknown exception " );
2537   }
2538
2539   return nbels._retn();
2540 }
2541
2542 //================================================================================
2543 /*!
2544  * \brief Return geometrical object the given element is built on
2545  *  \param theMesh - the mesh the element is in
2546  *  \param theElementID - the element ID
2547  *  \param theGeomName - the name of the result geom object if it is not yet published
2548  *  \retval GEOM::GEOM_Object_ptr - the found or just published geom object (no need to UnRegister())
2549  */
2550 //================================================================================
2551
2552 GEOM::GEOM_Object_ptr
2553 SMESH_Gen_i::GetGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
2554                                        SMESH::smIdType        theElementID,
2555                                        const char*            theGeomName)
2556 {
2557   Unexpect aCatch(SALOME_SalomeException);
2558
2559   GEOM::GEOM_Object_wrap geom = FindGeometryByMeshElement(theMesh, theElementID);
2560   if ( !geom->_is_nil() ) {
2561     GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh();
2562     GEOM::GEOM_Gen_var    geomGen   = GetGeomEngine( geom );
2563
2564     // try to find the corresponding SObject
2565     SALOMEDS::SObject_wrap SObj = ObjectToSObject( geom.in() );
2566     if ( SObj->_is_nil() ) // submesh can be not found even if published
2567     {
2568       // try to find published submesh
2569       GEOM::ListOfLong_var list = geom->GetSubShapeIndices();
2570       if ( !geom->IsMainShape() && list->length() == 1 ) {
2571         SALOMEDS::SObject_wrap mainSO = ObjectToSObject( mainShape );
2572         SALOMEDS::ChildIterator_wrap it;
2573         if ( !mainSO->_is_nil() ) {
2574           it = getStudyServant()->NewChildIterator( mainSO );
2575         }
2576         if ( !it->_is_nil() ) {
2577           for ( it->InitEx(true); it->More(); it->Next() ) {
2578             SALOMEDS::SObject_wrap      so = it->Value();
2579             CORBA::Object_var         obj = SObjectToObject( so );
2580             GEOM::GEOM_Object_var subGeom = GEOM::GEOM_Object::_narrow( obj );
2581             if ( !subGeom->_is_nil() ) {
2582               GEOM::ListOfLong_var subList = subGeom->GetSubShapeIndices();
2583               if ( subList->length() == 1 && list[0] == subList[0] ) {
2584                 SObj = so;
2585                 geom = subGeom;
2586                 break;
2587               }
2588             }
2589           }
2590         }
2591       }
2592     }
2593     if ( SObj->_is_nil() && !geomGen->_is_nil() ) // publish a new subshape
2594       SObj = geomGen->AddInStudy( geom, theGeomName, mainShape );
2595
2596     // return only published geometry
2597     if ( !SObj->_is_nil() ) {
2598       //return geom._retn(); -- servant of geom must be UnRegister()ed;
2599       CORBA::Object_var    obj = SObjectToObject( SObj );
2600       GEOM::GEOM_Object_var go = GEOM::GEOM_Object::_narrow( obj );
2601       return go._retn();
2602     }
2603   }
2604   return GEOM::GEOM_Object::_nil();
2605 }
2606
2607 //================================================================================
2608 /*!
2609  * \brief Return geometrical object the given element is built on.
2610  *  \param theMesh - the mesh the element is in
2611  *  \param theElementID - the element ID
2612  *  \retval GEOM::GEOM_Object_ptr - the found or created (UnRegister()!) geom object
2613  */
2614 //================================================================================
2615
2616 GEOM::GEOM_Object_ptr
2617 SMESH_Gen_i::FindGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
2618                                         SMESH::smIdType            theElementID)
2619 {
2620   Unexpect aCatch(SALOME_SalomeException);
2621   if ( CORBA::is_nil( theMesh ) )
2622     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", SALOME::BAD_PARAM );
2623
2624   GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh();
2625   GEOM::GEOM_Gen_var    geomGen   = GetGeomEngine( mainShape );
2626
2627   // get a core mesh DS
2628   SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
2629   if ( meshServant && !geomGen->_is_nil() && !mainShape->_is_nil() )
2630   {
2631     ::SMESH_Mesh & mesh = meshServant->GetImpl();
2632     SMESHDS_Mesh* meshDS = mesh.GetMeshDS();
2633     // find the element in mesh
2634     if ( const SMDS_MeshElement * elem = meshDS->FindElement( theElementID ) ) {
2635       // find a shape id by the element
2636       if ( int shapeID = ::SMESH_MeshEditor( &mesh ).FindShape( elem )) {
2637         // get a geom object by the shape id
2638         GEOM::GEOM_Object_var geom = ShapeToGeomObject( meshDS->IndexToShape( shapeID ));
2639         if ( geom->_is_nil() ) {
2640           // try to find a published sub-shape
2641           SALOMEDS::SObject_wrap mainSO = ObjectToSObject( mainShape );
2642           SALOMEDS::ChildIterator_wrap it;
2643           if ( !mainSO->_is_nil() ) {
2644             it = getStudyServant()->NewChildIterator( mainSO );
2645           }
2646           if ( !it->_is_nil() ) {
2647             for ( it->InitEx(true); it->More(); it->Next() ) {
2648               SALOMEDS::SObject_wrap     so = it->Value();
2649               CORBA::Object_var         obj = SObjectToObject( so );
2650               GEOM::GEOM_Object_var subGeom = GEOM::GEOM_Object::_narrow( obj );
2651               if ( !subGeom->_is_nil() ) {
2652                 GEOM::ListOfLong_var subList = subGeom->GetSubShapeIndices();
2653                 if ( subList->length() == 1 && shapeID == subList[0] ) {
2654                   geom = subGeom;
2655                   break;
2656                 }
2657               }
2658             }
2659           }
2660         }
2661         if ( geom->_is_nil() ) {
2662           // explode
2663           GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
2664           if ( !op->_is_nil() )
2665             geom = op->GetSubShape( mainShape, shapeID );
2666         }
2667         else {
2668           geom->Register();
2669         }
2670         if ( !geom->_is_nil() ) {
2671           GeomObjectToShape( geom ); // let geom client remember the found shape
2672           return geom._retn();
2673         }
2674       }
2675     }
2676   }
2677   return GEOM::GEOM_Object::_nil();
2678 }
2679
2680 //================================================================================
2681 /*!
2682  *  SMESH_Gen_i::Concatenate
2683  *
2684  *  Concatenate the given meshes into one mesh
2685  */
2686 //================================================================================
2687
2688 SMESH::SMESH_Mesh_ptr
2689 SMESH_Gen_i::Concatenate(const SMESH::ListOfIDSources& theMeshesArray,
2690                          CORBA::Boolean                theUniteIdenticalGroups,
2691                          CORBA::Boolean                theMergeNodesAndElements,
2692                          CORBA::Double                 theMergeTolerance,
2693                          SMESH::SMESH_Mesh_ptr         theMeshToAppendTo)
2694 {
2695   return ConcatenateCommon(theMeshesArray,
2696                            theUniteIdenticalGroups,
2697                            theMergeNodesAndElements,
2698                            theMergeTolerance,
2699                            false,
2700                            theMeshToAppendTo);
2701 }
2702
2703 //================================================================================
2704 /*!
2705  *  SMESH_Gen_i::ConcatenateWithGroups
2706  *
2707  *  Concatenate the given meshes into one mesh
2708  *  Create the groups of all elements from initial meshes
2709  */
2710 //================================================================================
2711
2712 SMESH::SMESH_Mesh_ptr
2713 SMESH_Gen_i::ConcatenateWithGroups(const SMESH::ListOfIDSources& theMeshesArray,
2714                                    CORBA::Boolean                theUniteIdenticalGroups,
2715                                    CORBA::Boolean                theMergeNodesAndElements,
2716                                    CORBA::Double                 theMergeTolerance,
2717                                    SMESH::SMESH_Mesh_ptr         theMeshToAppendTo)
2718 {
2719   return ConcatenateCommon(theMeshesArray,
2720                            theUniteIdenticalGroups,
2721                            theMergeNodesAndElements,
2722                            theMergeTolerance,
2723                            true,
2724                            theMeshToAppendTo);
2725 }
2726
2727 //================================================================================
2728 /*!
2729  *  SMESH_Gen_i::ConcatenateCommon
2730  *
2731  *  Concatenate the given meshes into one mesh
2732  */
2733 //================================================================================
2734
2735 SMESH::SMESH_Mesh_ptr
2736 SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
2737                                CORBA::Boolean                theUniteIdenticalGroups,
2738                                CORBA::Boolean                theMergeNodesAndElements,
2739                                CORBA::Double                 theMergeTolerance,
2740                                CORBA::Boolean                theCommonGroups,
2741                                SMESH::SMESH_Mesh_ptr         theMeshToAppendTo)
2742 {
2743   std::unique_ptr< TPythonDump > pPythonDump( new TPythonDump(this) );
2744   TPythonDump& pythonDump = *pPythonDump; // prevent dump of called methods
2745
2746   // create mesh if theMeshToAppendTo not provided
2747   SMESH::SMESH_Mesh_var newMesh;
2748   if ( CORBA::is_nil( theMeshToAppendTo ))
2749     newMesh = CreateEmptyMesh();
2750   else
2751     newMesh = SMESH::SMESH_Mesh::_duplicate( theMeshToAppendTo );
2752   SMESH_Mesh_i* newImpl = SMESH::DownCast<SMESH_Mesh_i*>( newMesh );
2753   if ( !newImpl ) return newMesh._retn();
2754   newImpl->Load();
2755
2756   ::SMESH_Mesh&   locMesh = newImpl->GetImpl();
2757   SMESHDS_Mesh* newMeshDS = locMesh.GetMeshDS();
2758
2759   typedef std::list<SMESH::SMESH_Group_var>          TListOfNewGroups;
2760   typedef std::pair<string, SMESH::ElementType >     TNameAndType;
2761   typedef std::map< TNameAndType, TListOfNewGroups > TGroupsMap;
2762   TGroupsMap       groupsMap;
2763   TListOfNewGroups listOfNewGroups;
2764
2765   if ( !CORBA::is_nil( theMeshToAppendTo ))
2766   {
2767     // fill groupsMap with existing groups
2768     SMESH::ListOfGroups_var groups = theMeshToAppendTo->GetGroups();
2769     for ( CORBA::ULong i = 0; i < groups->length(); ++i )
2770     {
2771       SMESH::SMESH_Group_var group = SMESH::SMESH_Group::_narrow( groups[ i ]);
2772       if ( !group->_is_nil() )
2773       {
2774         CORBA::String_var  name = group->GetName();
2775         SMESH::ElementType type = group->GetType();
2776         groupsMap[ TNameAndType( name.in(), type ) ].push_back( group );
2777       }
2778     }
2779   }
2780
2781   ::SMESH_MeshEditor               newEditor( &locMesh );
2782   ::SMESH_MeshEditor::ElemFeatures elemType;
2783
2784   // loop on sub-meshes
2785   for ( CORBA::ULong i = 0; i < theMeshesArray.length(); i++ )
2786   {
2787     if ( CORBA::is_nil( theMeshesArray[i] )) continue;
2788     SMESH::SMESH_Mesh_var initMesh = theMeshesArray[i]->GetMesh();
2789     SMESH_Mesh_i*         initImpl = SMESH::DownCast<SMESH_Mesh_i*>( initMesh );
2790     if ( !initImpl ) continue;
2791     if ( initMesh->_is_equivalent( theMeshToAppendTo ))
2792       continue;
2793     initImpl->Load();
2794
2795     // assure that IDs increment by one during iteration
2796     ::SMESH_Mesh& initLocMesh = initImpl->GetImpl();
2797     SMESHDS_Mesh*  initMeshDS = initLocMesh.GetMeshDS();
2798     if ( initMeshDS->MaxNodeID()    > initMeshDS->NbNodes() ||
2799          initMeshDS->MaxElementID() > initMeshDS->NbElements() )
2800     {
2801       initMeshDS->Modified();
2802       initMeshDS->CompactMesh();
2803     }
2804
2805     // remember nb of elements before filling in
2806     SMESH::smIdType_array_var prevState =  newMesh->GetNbElementsByType();
2807
2808     // copy nodes
2809
2810     std::vector< const SMDS_MeshElement* > newNodes( initMeshDS->NbNodes() + 1, 0 );
2811     SMDS_ElemIteratorPtr elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::NODE );
2812     while ( elemIt->more() )
2813     {
2814       SMESH_NodeXYZ node = elemIt->next();
2815       newNodes[ node->GetID() ] = newMeshDS->AddNode( node.X(), node.Y(), node.Z() );
2816     }
2817
2818     // copy elements
2819
2820     std::vector< const SMDS_MeshElement* > newElems( initMeshDS->NbElements() + 1, 0 );
2821     SMESH::array_of_ElementType_var srcElemTypes = theMeshesArray[i]->GetTypes();
2822     bool hasElems = (( srcElemTypes->length() > 1 ) ||
2823                      ( srcElemTypes->length() == 1 && srcElemTypes[0] != SMESH::NODE ));
2824     if ( hasElems )
2825     {
2826       elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::ALL );
2827       while ( elemIt->more() )
2828       {
2829         const SMDS_MeshElement* elem = elemIt->next();
2830         elemType.myNodes.resize( elem->NbNodes() );
2831
2832         SMDS_NodeIteratorPtr itNodes = elem->nodeIterator();
2833         for ( int k = 0; itNodes->more(); k++)
2834         {
2835           const SMDS_MeshNode* node = itNodes->next();
2836           elemType.myNodes[ k ] = static_cast< const SMDS_MeshNode*> ( newNodes[ node->GetID() ]);
2837         }
2838
2839         // creates a corresponding element on existent nodes in new mesh
2840         newElems[ elem->GetID() ] =
2841           newEditor.AddElement( elemType.myNodes, elemType.Init( elem, /*basicOnly=*/false ));
2842       }
2843       newEditor.ClearLastCreated(); // forget the history
2844     }
2845
2846
2847     // create groups of just added elements
2848     SMESH::SMESH_Group_var newGroup;
2849     SMESH::ElementType     groupType;
2850     if ( theCommonGroups )
2851     {
2852       // type names
2853       const char* typeNames[] = { "All","Nodes","Edges","Faces","Volumes","0DElems","Balls" };
2854
2855       // check of typeNames: compilation failure mains that NB_ELEMENT_TYPES changed:
2856       static_assert( sizeof(typeNames) / sizeof(const char*) ==SMESH::NB_ELEMENT_TYPES,
2857                      "Update names of ElementType's!!!" );
2858
2859       SMESH::smIdType_array_var curState = newMesh->GetNbElementsByType();
2860
2861       for( groupType = SMESH::NODE;
2862            groupType < SMESH::NB_ELEMENT_TYPES;
2863            groupType = (SMESH::ElementType)( groupType + 1 ))
2864       {
2865         if ( curState[ groupType ] <= prevState[ groupType ])
2866           continue; // no elements of groupType added from the i-th mesh
2867
2868         // make a group name
2869         std::string groupName = "Gr";
2870         SALOMEDS::SObject_wrap meshSO = ObjectToSObject( theMeshesArray[i] );
2871         if ( meshSO ) {
2872           CORBA::String_var name = meshSO->GetName();
2873           groupName += name;
2874         }
2875         groupName += "_";
2876         groupName += typeNames[ groupType ];
2877
2878         // make and fill a group
2879         newGroup = newImpl->CreateGroup( groupType, groupName.c_str() );
2880         std::vector< const SMDS_MeshElement* > & elemVec =
2881           ( groupType == SMESH::NODE ) ? newNodes : newElems;
2882         if ( SMESH_Group_i* grp_i = SMESH::DownCast<SMESH_Group_i*>( newGroup ))
2883         {
2884           if ( SMESHDS_Group* grpDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() ))
2885           {
2886             for ( size_t j = 0; j < elemVec.size(); ++j )
2887             {
2888               if ( elemVec[j] && elemVec[j]->GetType() == grpDS->GetType() )
2889                 grpDS->Add( elemVec[j] );
2890             }
2891           }
2892         }
2893         listOfNewGroups.clear();
2894         listOfNewGroups.push_back( newGroup );
2895         groupsMap.insert( std::make_pair( TNameAndType( groupName, groupType ),
2896                                           listOfNewGroups ));
2897       }
2898     }
2899
2900     if ( SMESH_Mesh_i* initImpl = SMESH::DownCast<SMESH_Mesh_i*>( theMeshesArray[i] ))
2901     {
2902       // copy groups
2903
2904       SMESH::SMESH_GroupBase_ptr group;
2905       CORBA::String_var          groupName;
2906       SMESH::smIdType_array_var newIDs = new SMESH::smIdType_array();
2907
2908       // loop on groups of a source mesh
2909       SMESH::ListOfGroups_var listOfGroups = initImpl->GetGroups();
2910       for ( CORBA::ULong iG = 0; iG < listOfGroups->length(); iG++ )
2911       {
2912         group     = listOfGroups[iG];
2913         groupType = group->GetType();
2914         groupName = group->GetName();
2915         std::string name = groupName.in();
2916
2917         // convert a list of IDs
2918         newIDs->length( group->Size() );
2919         std::vector< const SMDS_MeshElement* > & elemVec =
2920           ( groupType == SMESH::NODE ) ? newNodes : newElems;
2921         SMDS_ElemIteratorPtr itGrElems = initImpl->GetElements( group, SMESH::ALL );
2922         int nbElems = 0;
2923         while ( itGrElems->more() )
2924         {
2925           const SMDS_MeshElement*    elem = itGrElems->next();
2926           const SMDS_MeshElement* newElem = elemVec[ elem->GetID() ];
2927           if ( newElem )
2928             newIDs[ nbElems++ ] = newElem->GetID();
2929         }
2930         newIDs->length( nbElems );
2931
2932         // check that a current group name and type don't have identical ones in final mesh
2933         listOfNewGroups.clear();
2934         TNameAndType nameAndType( name, groupType );
2935         TGroupsMap::iterator anIter = groupsMap.find( nameAndType );
2936         if ( anIter == groupsMap.end() )
2937         {
2938           // add a new group in the mesh
2939           newGroup = newImpl->CreateGroup( groupType, groupName.in() );
2940           newGroup->Add( newIDs );
2941
2942           listOfNewGroups.push_back( newGroup );
2943           groupsMap.insert( std::make_pair( nameAndType, listOfNewGroups ));
2944         }
2945         else if ( theUniteIdenticalGroups )
2946         {
2947           // unite identical groups
2948           TListOfNewGroups& aNewGroups = anIter->second;
2949           aNewGroups.front()->Add( newIDs );
2950         }
2951         else
2952         {
2953           // rename identical groups
2954           newGroup = newImpl->CreateGroup( groupType, groupName );
2955           newGroup->Add( newIDs );
2956
2957           TListOfNewGroups& newGroups = anIter->second;
2958           std::string newGroupName;
2959           if ( newGroups.size() == 1 )
2960           {
2961             newGroupName = name + "_1";
2962             newGroups.front()->SetName( newGroupName.c_str() );
2963           }
2964           newGroupName = name + "_" + SMESH_Comment( newGroups.size() + 1 );
2965           newGroup->SetName( newGroupName.c_str() );
2966           newGroups.push_back( newGroup );
2967         }
2968       } // loop on groups
2969     } // if an IDSource is a mesh
2970   } //meshes loop
2971
2972   if ( theMergeNodesAndElements ) // merge nodes
2973   {
2974     TIDSortedNodeSet meshNodes; // no input nodes == treat all
2975     SMESH_MeshEditor::TListOfListOfNodes groupsOfNodes;
2976     newEditor.FindCoincidentNodes( meshNodes, theMergeTolerance, groupsOfNodes,
2977                                    /*SeparateCornersAndMedium=*/ false );
2978     newEditor.MergeNodes( groupsOfNodes );
2979     // merge elements
2980     newEditor.MergeEqualElements();
2981   }
2982
2983   // Update Python script
2984   pythonDump << newMesh << " = " << this
2985              << "." << ( theCommonGroups ? "ConcatenateWithGroups" : "Concatenate" ) << "( "
2986              << theMeshesArray << ", "
2987              << theUniteIdenticalGroups << ", "
2988              << theMergeNodesAndElements << ", "
2989              << TVar( theMergeTolerance ) << ", "
2990              << theMeshToAppendTo << " )";
2991
2992   pPythonDump.reset(); // enable python dump from GetGroups()
2993
2994   // 0020577: EDF 1164 SMESH: Bad dump of concatenate with create common groups
2995   if ( !newMesh->_is_nil() )
2996   {
2997     SMESH::ListOfGroups_var groups = newMesh->GetGroups();
2998   }
2999
3000   // IPAL21468 Change icon of compound because it need not be computed.
3001   SALOMEDS::SObject_wrap meshSO = ObjectToSObject( newMesh );
3002   SetPixMap( meshSO, "ICON_SMESH_TREE_MESH" );
3003
3004   newMeshDS->Modified();
3005
3006   return newMesh._retn();
3007 }
3008
3009
3010 //================================================================================
3011 /*!
3012  * \brief Create a mesh by copying a part of another mesh
3013  *  \param mesh - TetraHedron mesh
3014  *  \param meshName Name of the created mesh
3015  *  \retval SMESH::SMESH_Mesh_ptr - the new mesh
3016  */
3017 //================================================================================
3018
3019 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh,
3020                                                   const char*               meshName,
3021                                                   CORBA::Boolean            adapt_to_shape)
3022 {
3023   Unexpect aCatch(SALOME_SalomeException);
3024
3025   TPythonDump* pyDump = new TPythonDump(this); // prevent dump from CreateMesh()
3026   std::unique_ptr<TPythonDump> pyDumpDeleter( pyDump );
3027
3028   // 1. Get source mesh
3029
3030   if ( CORBA::is_nil( mesh ))
3031     THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM );
3032
3033   SMESH::SMESH_Mesh_var srcMesh = mesh->GetMesh();
3034   SMESH_Mesh_i*       srcMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( srcMesh );
3035   if ( !srcMesh_i )
3036     THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM );
3037
3038   CORBA::String_var mesh_var=GetORB()->object_to_string(mesh);
3039   std::string mesh_ior = mesh_var.in();
3040
3041   //temporary folder for the generation of the med file
3042   fs::path tmp_folder = fs::temp_directory_path() / fs::unique_path(fs::path("dual_mesh-%%%%"));
3043   fs::create_directories(tmp_folder);
3044   fs::path dual_mesh_file = tmp_folder / fs::path("tmp_dual_mesh.med");
3045   std::string mesh_name(meshName);
3046   MESSAGE("Working in folder" + tmp_folder.string());
3047
3048   // Running Python script
3049   assert(Py_IsInitialized());
3050   PyGILState_STATE gstate;
3051   gstate = PyGILState_Ensure();
3052
3053
3054   std::string ats;
3055   if(adapt_to_shape)
3056     ats = "True";
3057   else
3058     ats = "False";
3059
3060   std::string cmd="import salome.smesh.smesh_tools as smt\n";
3061   cmd +="smt.smesh_create_dual_mesh(\"" + mesh_ior + "\", r\"" +
3062         dual_mesh_file.string() + "\", mesh_name=\"" + mesh_name + "\", adapt_to_shape=" + ats + ")";
3063   MESSAGE(cmd);
3064
3065   PyObject *py_main = PyImport_AddModule("__main__");
3066   PyObject *py_dict = PyModule_GetDict(py_main);
3067   PyObject *local_dict = PyDict_New();
3068
3069   PyRun_String(cmd.c_str(), Py_file_input, py_dict, local_dict);
3070
3071   if (PyErr_Occurred()) {
3072     // Restrieving python error
3073     MESSAGE("Catching error");
3074     PyObject *errtype, *errvalue, *traceback;
3075     PyErr_Fetch(&errtype, &errvalue, &traceback);
3076     if(errvalue != NULL) {
3077       MESSAGE("Error has a value");
3078       PyObject *s = PyObject_Str(errvalue);
3079       Py_ssize_t size;
3080       std::string msg = PyUnicode_AsUTF8AndSize(s, &size);
3081       msg = "Issue with the execution of create_dual_mesh:\n"+msg;
3082       MESSAGE("throwing exception");
3083       // We need to deactivate the GIL before throwing the exception
3084       PyGILState_Release(gstate);
3085       THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::INTERNAL_ERROR );
3086       Py_DECREF(s);
3087     }
3088     Py_XDECREF(errvalue);
3089     Py_XDECREF(errtype);
3090     Py_XDECREF(traceback);
3091   }
3092
3093   PyGILState_Release(gstate);
3094
3095   MESSAGE("Mesh created in " + dual_mesh_file.string());
3096
3097   // Import created MED
3098   SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil());
3099   SMESH_Mesh_i*       newMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( newMesh );
3100   if ( !newMesh_i )
3101     THROW_SALOME_CORBA_EXCEPTION( "can't create a mesh", SALOME::INTERNAL_ERROR );
3102   SALOMEDS::SObject_wrap meshSO = ObjectToSObject( newMesh );
3103   if ( !meshSO->_is_nil() )
3104   {
3105     SetName( meshSO, meshName, meshName );
3106     SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
3107   }
3108   int ret = newMesh_i->ImportMEDFile(dual_mesh_file.string().c_str(), meshName);
3109   if(ret)
3110     THROW_SALOME_CORBA_EXCEPTION( "Issue when importing mesh", SALOME::INTERNAL_ERROR );
3111
3112   /*
3113   SMESH_Mesh& newMesh2 = newMesh_i->GetImpl();
3114
3115
3116   MESSAGE("Loading file: " << dual_mesh_file.string() << " with mesh " << meshName);
3117   int ret = newMesh2.MEDToMesh(dual_mesh_file.c_str(), meshName);
3118     */
3119
3120   newMesh_i->GetImpl().GetMeshDS()->Modified();
3121
3122   *pyDump << newMesh << " = " << this
3123           << ".CreateDualMesh("
3124           << mesh << ", "
3125           << "'" << mesh_name << "', "
3126           << ats << ") ";
3127
3128   pyDumpDeleter.reset(); // allow dump in GetGroups()
3129
3130   if ( srcMesh_i->GetImpl().GetGroupIds().size() > 0 ) // dump created groups
3131     MESSAGE("Dump of groups");
3132     SMESH::ListOfGroups_var groups = newMesh->GetGroups();
3133
3134 #ifndef _DEBUG_
3135   fs::remove_all(tmp_folder);
3136 #endif
3137
3138   return newMesh._retn();
3139 }
3140
3141 //================================================================================
3142 /*!
3143  * \brief Create a mesh by copying a part of another mesh
3144  *  \param meshPart - a part of mesh to copy
3145  *  \param toCopyGroups - to create in the new mesh groups
3146  *                        the copied elements belongs to
3147  *  \param toKeepIDs - to preserve IDs of the copied elements or not
3148  *  \retval SMESH::SMESH_Mesh_ptr - the new mesh
3149  */
3150 //================================================================================
3151
3152 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
3153                                             const char*               meshName,
3154                                             CORBA::Boolean            toCopyGroups,
3155                                             CORBA::Boolean            toKeepIDs)
3156 {
3157   Unexpect aCatch(SALOME_SalomeException);
3158
3159   TPythonDump* pyDump = new TPythonDump(this); // prevent dump from CreateMesh()
3160   std::unique_ptr<TPythonDump> pyDumpDeleter( pyDump );
3161
3162   // 1. Get source mesh
3163
3164   if ( CORBA::is_nil( meshPart ))
3165     THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM );
3166
3167   SMESH::SMESH_Mesh_var srcMesh = meshPart->GetMesh();
3168   SMESH_Mesh_i*       srcMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( srcMesh );
3169   if ( !srcMesh_i )
3170     THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM );
3171
3172   SMESHDS_Mesh* srcMeshDS = srcMesh_i->GetImpl().GetMeshDS();
3173
3174   // 2. Make a new mesh
3175
3176   SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil());
3177   SMESH_Mesh_i*       newMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( newMesh );
3178   if ( !newMesh_i )
3179     THROW_SALOME_CORBA_EXCEPTION( "can't create a mesh", SALOME::INTERNAL_ERROR );
3180   SALOMEDS::SObject_wrap meshSO = ObjectToSObject( newMesh );
3181   if ( !meshSO->_is_nil() )
3182   {
3183     SetName( meshSO, meshName, "Mesh" );
3184     SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
3185   }
3186   SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS();
3187   ::SMESH_MeshEditor editor( &newMesh_i->GetImpl() );
3188   ::SMESH_MeshEditor::ElemFeatures elemType;
3189
3190   // 3. Get elements to copy
3191
3192   SMDS_ElemIteratorPtr srcElemIt; SMDS_NodeIteratorPtr srcNodeIt;
3193   TIDSortedElemSet srcElems;
3194   SMESH::array_of_ElementType_var srcElemTypes = meshPart->GetTypes();
3195   if ( SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
3196   {
3197     srcMesh_i->Load();
3198     srcElemIt = srcMeshDS->elementsIterator();
3199     srcNodeIt = srcMeshDS->nodesIterator();
3200   }
3201   else
3202   {
3203     SMESH::smIdType_array_var ids = meshPart->GetIDs();
3204     if ( srcElemTypes->length() == 1 && srcElemTypes[0] == SMESH::NODE ) // group of nodes
3205     {
3206       for ( CORBA::ULong i=0; i < ids->length(); i++ )
3207         if ( const SMDS_MeshElement * elem = srcMeshDS->FindNode( ids[i] ))
3208           srcElems.insert( elem );
3209     }
3210     else
3211     {
3212       for ( CORBA::ULong i = 0; i < ids->length(); i++ )
3213         if ( const SMDS_MeshElement * elem = srcMeshDS->FindElement( ids[i] ))
3214           srcElems.insert( elem );
3215     }
3216     if ( srcElems.empty() )
3217       return newMesh._retn();
3218
3219     typedef SMDS_SetIterator< SMDS_pElement, TIDSortedElemSet::const_iterator > ElIter;
3220     srcElemIt = SMDS_ElemIteratorPtr( new ElIter( srcElems.begin(), srcElems.end() ));
3221   }
3222
3223   // 4. Copy elements
3224
3225   typedef map<SMDS_pElement, SMDS_pElement, TIDCompare> TE2EMap;
3226   TE2EMap e2eMapByType[ SMDSAbs_NbElementTypes ];
3227   TE2EMap& n2nMap = e2eMapByType[ SMDSAbs_Node ];
3228   int iN;
3229   const SMDS_MeshNode *nSrc, *nTgt;
3230   vector< const SMDS_MeshNode* > nodes;
3231   while ( srcElemIt->more() )
3232   {
3233     const SMDS_MeshElement * elem = srcElemIt->next();
3234     // find / add nodes
3235     nodes.resize( elem->NbNodes());
3236     SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
3237     if ( toKeepIDs ) {
3238       for ( iN = 0; nIt->more(); ++iN )
3239       {
3240         nSrc = static_cast<const SMDS_MeshNode*>( nIt->next() );
3241         nTgt = newMeshDS->FindNode( nSrc->GetID());
3242         if ( !nTgt )
3243           nTgt = newMeshDS->AddNodeWithID( nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID());
3244         nodes[ iN ] = nTgt;
3245       }
3246     }
3247     else {
3248       for ( iN = 0; nIt->more(); ++iN )
3249       {
3250         nSrc = static_cast<const SMDS_MeshNode*>( nIt->next() );
3251         TE2EMap::iterator n2n = n2nMap.insert( make_pair( nSrc, SMDS_pNode(0) )).first;
3252         if ( !n2n->second )
3253           n2n->second = newMeshDS->AddNode( nSrc->X(), nSrc->Y(), nSrc->Z() );
3254         nodes[ iN ] = (const SMDS_MeshNode*) n2n->second;
3255       }
3256     }
3257     // add elements
3258     if ( elem->GetType() != SMDSAbs_Node )
3259     {
3260       elemType.Init( elem, /*basicOnly=*/false );
3261       if ( toKeepIDs ) elemType.SetID( elem->GetID() );
3262
3263       const SMDS_MeshElement * newElem = editor.AddElement( nodes, elemType );
3264       if ( toCopyGroups && !toKeepIDs )
3265         e2eMapByType[ elem->GetType() ].insert( make_pair( elem, newElem ));
3266     }
3267   } // while ( srcElemIt->more() )
3268
3269   // 4(b). Copy free nodes
3270
3271   if ( srcNodeIt && srcMeshDS->NbNodes() != newMeshDS->NbNodes() )
3272   {
3273     while ( srcNodeIt->more() )
3274     {
3275       nSrc = srcNodeIt->next();
3276       if ( nSrc->NbInverseElements() == 0 )
3277       {
3278         if ( toKeepIDs )
3279           nTgt = newMeshDS->AddNodeWithID( nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID());
3280         else
3281           n2nMap[ nSrc ] = newMeshDS->AddNode( nSrc->X(), nSrc->Y(), nSrc->Z() );
3282       }
3283     }
3284   }
3285
3286   // 5. Copy groups
3287
3288   int nbNewGroups = 0;
3289   if ( toCopyGroups )
3290   {
3291     SMESH_Mesh::GroupIteratorPtr gIt = srcMesh_i->GetImpl().GetGroups();
3292     while ( gIt->more() )
3293     {
3294       SMESH_Group* group = gIt->next();
3295       const SMESHDS_GroupBase* groupDS = group->GetGroupDS();
3296
3297       // Check group type. We copy nodal groups containing nodes of copied element
3298       SMDSAbs_ElementType groupType = groupDS->GetType();
3299       if ( groupType != SMDSAbs_Node &&
3300            newMeshDS->GetMeshInfo().NbElements( groupType ) == 0 )
3301         continue; // group type differs from types of meshPart
3302
3303       // Find copied elements in the group
3304       vector< const SMDS_MeshElement* > groupElems;
3305       SMDS_ElemIteratorPtr eIt = groupDS->GetElements();
3306       if ( toKeepIDs )
3307       {
3308         const SMDS_MeshElement* foundElem;
3309         if ( groupType == SMDSAbs_Node )
3310         {
3311           while ( eIt->more() )
3312             if (( foundElem = newMeshDS->FindNode( eIt->next()->GetID() )))
3313               groupElems.push_back( foundElem );
3314         }
3315         else
3316         {
3317           while ( eIt->more() )
3318             if (( foundElem = newMeshDS->FindElement( eIt->next()->GetID() )))
3319               groupElems.push_back( foundElem );
3320         }
3321       }
3322       else
3323       {
3324         TE2EMap & e2eMap = e2eMapByType[ groupDS->GetType() ];
3325         if ( e2eMap.empty() ) continue;
3326         smIdType minID = e2eMap.begin()->first->GetID();
3327         smIdType maxID = e2eMap.rbegin()->first->GetID();
3328         TE2EMap::iterator e2e;
3329         while ( eIt->more() && groupElems.size() < e2eMap.size())
3330         {
3331           const SMDS_MeshElement* e = eIt->next();
3332           if ( e->GetID() < minID || e->GetID() > maxID ) continue;
3333           if ((e2e = e2eMap.find( e )) != e2eMap.end())
3334             groupElems.push_back( e2e->second );
3335         }
3336       }
3337       // Make a new group
3338       if ( !groupElems.empty() )
3339       {
3340         SMESH::SMESH_Group_var newGroupObj =
3341           newMesh->CreateGroup( SMESH::ElementType(groupType), group->GetName() );
3342         if ( SMESH_GroupBase_i* newGroup_i = SMESH::DownCast<SMESH_GroupBase_i*>( newGroupObj))
3343         {
3344           SMESHDS_GroupBase * newGroupDS = newGroup_i->GetGroupDS();
3345           SMDS_MeshGroup& smdsGroup = ((SMESHDS_Group*)newGroupDS)->SMDSGroup();
3346           for ( unsigned i = 0; i < groupElems.size(); ++i )
3347             smdsGroup.Add( groupElems[i] );
3348
3349           nbNewGroups++;
3350         }
3351       }
3352     }
3353   }
3354
3355   newMeshDS->Modified();
3356
3357   *pyDump << newMesh << " = " << this
3358           << ".CopyMesh( " << meshPart << ", "
3359           << "'" << meshName << "', "
3360           << toCopyGroups << ", "
3361           << toKeepIDs << ")";
3362
3363   pyDumpDeleter.reset(); // allow dump in GetGroups()
3364
3365   if ( nbNewGroups > 0 ) // dump created groups
3366     SMESH::ListOfGroups_var groups = newMesh->GetGroups();
3367
3368   return newMesh._retn();
3369 }
3370
3371
3372 namespace // utils for CopyMeshWithGeom()
3373 {
3374   typedef std::map< std::string, std::string >             TStr2StrMap;
3375   typedef std::map< std::string, std::set< std::string > > TStr2StrSetMap;
3376   typedef std::map< std::set<int>, int >                   TIdSet2IndexMap;
3377   typedef std::map< std::string, int >                     TName2IndexMap;
3378
3379   //================================================================================
3380   /*!
3381    * \brief Return a new sub-shape corresponding to an old one
3382    */
3383   //================================================================================
3384
3385   struct ShapeMapper
3386   {
3387     SMESH_Mesh_i* mySrcMesh_i;
3388     SMESH_Mesh_i* myNewMesh_i;
3389     SMESH_Gen_i*  myGen_i;
3390     bool          myToPublish;
3391     bool          myIsSameGeom;
3392
3393     TStr2StrMap   myOld2NewEntryMap; // map of study entries
3394
3395     GEOM::ListOfGO_var         mySubshapes; // sub-shapes existing in the new geometry
3396     TIdSet2IndexMap            myIds2SubshapeIndex; // to find an existing sub-shape
3397     TName2IndexMap             myName2SubshapeIndex; // to find an existing sub-shape by name
3398
3399     bool                       myGIPMapDone;
3400     GEOM::ListOfListOfLong_var myGIPMap; // filled by GetInPlaceMap()
3401
3402     // not directly relating to shape search
3403     TStr2StrSetMap myInvalidMap; // blame shape -> invalid objects
3404
3405     //================================================================================
3406     /*!
3407      * \brief Constructor
3408      */
3409     ShapeMapper( SMESH_Mesh_i* srcMesh_i,
3410                  SMESH_Mesh_i* newMesh_i,
3411                  SMESH_Gen_i*  smeshGen_i )
3412       : mySrcMesh_i( srcMesh_i ),
3413         myNewMesh_i( newMesh_i ),
3414         myGen_i    ( smeshGen_i ),
3415         myToPublish( smeshGen_i->IsEnablePublish() ),
3416         myGIPMapDone( false )
3417     {
3418       // retrieve from the study shape mapping made thanks to
3419       // "Set presentation parameters and sub-shapes from arguments" option
3420
3421       GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh();
3422       GEOM::GEOM_Object_var mainShapeOld = mySrcMesh_i->GetShapeToMesh();
3423       SALOMEDS::SObject_wrap oldSO = myGen_i->ObjectToSObject( mainShapeOld );
3424       SALOMEDS::SObject_wrap newSO = myGen_i->ObjectToSObject( mainShapeNew );
3425       if ( newSO->_is_nil() )
3426       {
3427         myToPublish = false;
3428         return;
3429       }
3430       if (( myIsSameGeom = mainShapeNew->_is_equivalent( mainShapeOld )))
3431         return;
3432       CORBA::String_var oldEntry = oldSO->GetID();
3433       CORBA::String_var newEntry = newSO->GetID();
3434       myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ),
3435                                                 std::string( newEntry.in() )));
3436       std::string  newMainEntry = newEntry.in();
3437
3438       SALOMEDS::Study_var            study = myGen_i->getStudyServant();
3439       GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine( mainShapeNew );
3440       GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
3441       mySubshapes                          = op->GetExistingSubObjects( mainShapeNew,
3442                                                                         /*groupsOnly=*/false );
3443       for ( CORBA::ULong i = 0; i < mySubshapes->length(); ++i )
3444       {
3445         newSO = myGen_i->ObjectToSObject( mySubshapes[ i ]);
3446         SALOMEDS::ChildIterator_wrap anIter = study->NewChildIterator( newSO );
3447         bool refFound = false;
3448         for ( ; anIter->More(); anIter->Next() )
3449         {
3450           SALOMEDS::SObject_wrap so = anIter->Value();
3451           if ( so->ReferencedObject( oldSO.inout() ))
3452           {
3453             oldEntry = oldSO->GetID();
3454             newEntry = newSO->GetID();
3455             if (( refFound = ( newMainEntry != oldEntry.in() )))
3456               myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ),
3457                                                         std::string( newEntry.in() )));
3458           }
3459         }
3460         if ( !refFound )
3461         {
3462           GEOM::GEOM_Object_var father = mySubshapes[ i ]->GetMainShape();
3463           if ( father->_is_equivalent( mainShapeNew ))
3464           {
3465             GEOM::ListOfLong_var ids = mySubshapes[ i ]->GetSubShapeIndices();
3466             std::set< int > idSet( &ids[0] , &ids[0] + ids->length() );
3467             myIds2SubshapeIndex.insert( std::make_pair( idSet, i ));
3468             CORBA::String_var name = newSO->GetName();
3469             if ( name.in()[0] )
3470               myName2SubshapeIndex.insert( std::make_pair( name.in(), i ));
3471           }
3472         }
3473       }
3474     }
3475
3476     //================================================================================
3477     /*!
3478      * \brief Find a new sub-shape corresponding to an old one
3479      */
3480     GEOM::GEOM_Object_ptr FindNew( GEOM::GEOM_Object_ptr oldShape )
3481     {
3482       if ( myIsSameGeom )
3483         return GEOM::GEOM_Object::_duplicate( oldShape );
3484
3485       GEOM::GEOM_Object_var newShape;
3486
3487       if ( CORBA::is_nil( oldShape ))
3488         return newShape._retn();
3489
3490       if ( !isChildOfOld( oldShape ))
3491         return GEOM::GEOM_Object::_duplicate( oldShape ); // shape independent of the old shape
3492
3493       GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh();
3494       GEOM::GEOM_Gen_var         geomGen = myGen_i->GetGeomEngine( mainShapeNew );
3495
3496       // try to find by entry or name
3497       if ( myToPublish )
3498       {
3499         CORBA::String_var  oldEntry = oldShape->GetStudyEntry();
3500         TStr2StrMap::iterator o2nID = myOld2NewEntryMap.find( oldEntry.in() );
3501         if ( o2nID != myOld2NewEntryMap.end() )
3502         {
3503           newShape = getShapeByEntry( o2nID->second );
3504         }
3505         if ( newShape->_is_nil() )
3506         {
3507           CORBA::String_var name = oldShape->GetName();
3508           TName2IndexMap::iterator n2ind = myName2SubshapeIndex.find( name.in() );
3509           if ( n2ind != myName2SubshapeIndex.end() )
3510           {
3511             newShape = GEOM::GEOM_Object::_duplicate( mySubshapes[ n2ind->second ]);
3512             GEOM::ListOfLong_var oldIndices = oldShape->GetSubShapeIndices();
3513             GEOM::ListOfLong_var newIndices = newShape->GetSubShapeIndices();
3514             if ( oldIndices->length() == 0 ||
3515                  newIndices->length() == 0 ||
3516                  getShapeType( myNewMesh_i, newIndices[0] ) !=
3517                  getShapeType( mySrcMesh_i, oldIndices[0] ))
3518               newShape = GEOM::GEOM_Object::_nil();
3519           }
3520         }
3521       }
3522
3523       if ( newShape->_is_nil() )
3524       {
3525         // try to construct a new sub-shape using myGIPMap
3526         buildGIPMap();
3527         std::vector< int >   newIndices;
3528         GEOM::ListOfLong_var oldIndices = oldShape->GetSubShapeIndices();
3529         for ( CORBA::ULong i = 0; i < oldIndices->length(); ++i )
3530         {
3531           findNewIDs( oldIndices[i], newIndices );
3532         }
3533         if ( newIndices.size() < oldIndices->length() ) // issue #17096
3534         {
3535           newIndices.clear();
3536           newShape = getInPlace( oldShape );
3537         }
3538         if ( !newIndices.empty() && newShape->_is_nil() )
3539         {
3540           // search for a sub-shape with same ids
3541           std::set< int > idSet( newIndices.begin(), newIndices.end() );
3542           TIdSet2IndexMap::iterator ids2ind = myIds2SubshapeIndex.find( idSet );
3543           if ( ids2ind != myIds2SubshapeIndex.end() ) {
3544             newShape = GEOM::GEOM_Object::_duplicate( mySubshapes[ ids2ind->second ]);
3545           }
3546           if ( newShape->_is_nil() )
3547             try
3548             {
3549               // create a new shape
3550               if ( newIndices.size() > 1 || oldShape->GetType() == GEOM_GROUP )
3551               {
3552                 int groupType = getShapeType( myNewMesh_i, newIndices[0] );
3553
3554                 GEOM::GEOM_IGroupOperations_wrap grOp = geomGen->GetIGroupOperations();
3555                 newShape = grOp->CreateGroup( mainShapeNew, groupType );
3556
3557                 GEOM::ListOfLong_var  newIndicesList = new GEOM::ListOfLong();
3558                 newIndicesList->length( newIndices.size() );
3559                 for ( size_t i = 0; i < newIndices.size(); ++i )
3560                   newIndicesList[ i ] = newIndices[ i ];
3561                 grOp->UnionIDs( newShape, newIndicesList );
3562               }
3563               else
3564               {
3565                 GEOM::GEOM_IShapesOperations_wrap shOp = geomGen->GetIShapesOperations();
3566                 newShape = shOp->GetSubShape( mainShapeNew, newIndices[0] );
3567               }
3568             }
3569             catch (...)
3570             {
3571             }
3572         }
3573       }
3574
3575       if ( !newShape->_is_nil() && myToPublish )
3576       {
3577         CORBA::String_var oldEntry, newEntry = newShape->GetStudyEntry();
3578         if ( !newEntry.in() || !newEntry.in()[0] )
3579         {
3580           CORBA::String_var    name = oldShape->GetName();
3581           SALOMEDS::SObject_wrap so = geomGen->AddInStudy( newShape, name, mainShapeNew );
3582           newEntry = newShape->GetStudyEntry();
3583           oldEntry = oldShape->GetStudyEntry();
3584           myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ),
3585                                                     std::string( newEntry.in() )));
3586         }
3587       }
3588
3589       return newShape._retn();
3590     }
3591
3592     //================================================================================
3593     /*!
3594      * \brief Return a study entry of a new shape by study entry of the old one
3595      */
3596     std::string FindNew( const std::string & oldEntry )
3597     {
3598       if ( myIsSameGeom )
3599         return oldEntry;
3600
3601       TStr2StrMap::iterator o2nID = myOld2NewEntryMap.find( oldEntry );
3602       if ( o2nID != myOld2NewEntryMap.end() )
3603         return o2nID->second;
3604
3605       GEOM::GEOM_Object_var oldShape = getShapeByEntry( oldEntry );
3606       if ( oldShape->_is_nil() || !isChildOfOld( oldShape ))
3607         return oldEntry;
3608
3609       GEOM::GEOM_Object_ptr newShape = FindNew( oldShape );
3610       if ( newShape->_is_nil() )
3611         return std::string();
3612
3613       CORBA::String_var newEntry = newShape->GetStudyEntry();
3614       return newEntry.in();
3615     }
3616
3617     //================================================================================
3618     /*!
3619      * \brief Return a sub-shape ID of a new shape by a sub-shape ID of the old one.
3620      *        Return zero if not found or there are more than one new ID
3621      */
3622     int FindNew( int oldID )
3623     {
3624       if ( myIsSameGeom )
3625         return oldID;
3626
3627       buildGIPMap();
3628
3629       int newID = 0;
3630
3631       if ( 0 < oldID && oldID < (int)myGIPMap->length() )
3632       {
3633         if ( myGIPMap[ oldID ].length() == 1 )
3634         {
3635           newID = myGIPMap[ oldID ][ 0 ];
3636         }
3637         else if ( myGIPMap[ oldID ].length() > 1 &&
3638                   getShapeType( mySrcMesh_i, oldID ) == TopAbs_VERTEX )
3639         {
3640           // select a meshed VERTEX
3641           SMESH_subMesh* newSM;
3642           for ( CORBA::ULong i = 0; i < myGIPMap[ oldID ].length() && !newID; ++i )
3643             if (( newSM = myNewMesh_i->GetImpl().GetSubMeshContaining( myGIPMap[ oldID ][ i ] )) &&
3644                 ( !newSM->IsEmpty() ))
3645               newID = myGIPMap[ oldID ][ i ];
3646         }
3647       }
3648       return newID;
3649     }
3650
3651     //================================================================================
3652     /*!
3653      * \brief Return a sub-shape ID of a new shape by an old sub-mesh.
3654      *        Return zero if the old shape is not kept as is in the new shape.
3655      */
3656     int FindNewNotChanged( SMESH_subMesh* oldSM )
3657     {
3658       if ( myIsSameGeom )
3659         return oldSM->GetId();
3660
3661       int newID = FindNew( oldSM->GetId() );
3662       if ( !newID )
3663         return 0;
3664
3665       SMESH_subMesh* newSM = myNewMesh_i->GetImpl().GetSubMeshContaining( newID );
3666       if ( !newSM )
3667         return 0;
3668
3669       // consider a sub-shape as not changed if all its sub-shapes are mapped into
3670       // one new sub-shape of the same type.
3671
3672       if ( oldSM->DependsOn().size() !=
3673            newSM->DependsOn().size() )
3674         return 0;
3675
3676       SMESH_subMeshIteratorPtr srcSMIt = oldSM->getDependsOnIterator( /*includeSelf=*/true );
3677       while ( srcSMIt->more() )
3678       {
3679         oldSM = srcSMIt->next();
3680         int newSubID = FindNew( oldSM->GetId() );
3681         if ( getShapeType( myNewMesh_i, newSubID ) !=
3682              getShapeType( mySrcMesh_i, oldSM->GetId() ))
3683           return 0;
3684       }
3685       return newID;
3686     }
3687
3688     //================================================================================
3689     /*!
3690      * \brief Return shape by study entry
3691      */
3692     GEOM::GEOM_Object_ptr getShapeByEntry( const std::string & entry )
3693     {
3694       GEOM::GEOM_Object_var shape;
3695       SALOMEDS::SObject_wrap so = myGen_i->getStudyServant()->FindObjectID( entry.c_str() );
3696       if ( !so->_is_nil() )
3697       {
3698         CORBA::Object_var obj = so->GetObject();
3699         shape = GEOM::GEOM_Object::_narrow( obj );
3700       }
3701       return shape._retn();
3702     }
3703
3704     //================================================================================
3705     /*!
3706      * \brief Fill myGIPMap by calling GetInPlaceMap()
3707      */
3708     void buildGIPMap()
3709     {
3710       if ( !myGIPMapDone )
3711       {
3712         myGIPMapDone = true;
3713
3714         GEOM::GEOM_Object_var   mainShapeNew = myNewMesh_i->GetShapeToMesh();
3715         GEOM::GEOM_Object_var   mainShapeOld = mySrcMesh_i->GetShapeToMesh();
3716         GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine( mainShapeNew );
3717         GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
3718         try
3719         {
3720           myGIPMap = op->GetInPlaceMap( mainShapeNew, mainShapeOld );
3721         }
3722         catch( ... )
3723         {
3724           myGIPMap = new GEOM::ListOfListOfLong();
3725         }
3726       }
3727     }
3728
3729     //================================================================================
3730     /*!
3731      * \brief Get new sub-shape by calling GetInPlace()
3732      */
3733     GEOM::GEOM_Object_ptr getInPlace( GEOM::GEOM_Object_ptr oldShape )
3734     {
3735       GEOM::GEOM_Object_var newShape;
3736
3737       GEOM::GEOM_Object_var   mainShapeNew = myNewMesh_i->GetShapeToMesh();
3738       GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine( mainShapeNew );
3739       GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
3740       try
3741       {
3742         newShape = op->GetInPlace( mainShapeNew, oldShape );
3743       }
3744       catch( ... )
3745       {
3746       }
3747       return newShape._retn();
3748     }
3749
3750     //================================================================================
3751     /*!
3752      * \brief Find a new sub-shape indices by an old one in myGIPMap. Return
3753      *        number of found IDs
3754      */
3755     int findNewIDs( int oldID, std::vector< int >& newIDs  )
3756     {
3757       size_t prevNbIDs = newIDs.size();
3758
3759       if ( 0 < oldID && oldID < (int) myGIPMap->length() )
3760       {
3761         for ( CORBA::ULong i = 0; i < myGIPMap[ oldID ].length(); ++i )
3762           newIDs.push_back( myGIPMap[ oldID ][ i ]);
3763       }
3764       return newIDs.size() - prevNbIDs;
3765     }
3766
3767     //================================================================================
3768     /*!
3769      * \brief Check if an object relates to the old shape
3770      */
3771     bool isChildOfOld( GEOM::GEOM_Object_ptr oldShape )
3772     {
3773       if ( CORBA::is_nil( oldShape ))
3774         return false;
3775       GEOM::GEOM_Object_var mainShapeOld1 = mySrcMesh_i->GetShapeToMesh();
3776       GEOM::GEOM_Object_var mainShapeOld2 = oldShape->GetMainShape();
3777       return ( mainShapeOld1->_is_equivalent( mainShapeOld2 ) ||
3778                mainShapeOld1->_is_equivalent( oldShape ));
3779     }
3780
3781     //================================================================================
3782     /*!
3783      * \brief Return shape type by shape ID
3784      */
3785     TopAbs_ShapeEnum getShapeType( SMESH_Mesh_i* mesh_i, int shapeID )
3786     {
3787       SMESHDS_Mesh* meshDS = mesh_i->GetImpl().GetMeshDS();
3788       const TopoDS_Shape& shape = meshDS->IndexToShape( shapeID );
3789       return shape.IsNull() ? TopAbs_SHAPE : shape.ShapeType();
3790     }
3791
3792     //================================================================================
3793     /*!
3794      * \brief Store a source sub-shape for which a counterpart not found and
3795      *        a smesh object invalid due to that
3796      */
3797     void AddInvalid( GEOM::GEOM_Object_var  srcShape,
3798                      SALOMEDS::SObject_wrap smeshSO )
3799     {
3800       CORBA::String_var geomEntry = srcShape->GetStudyEntry();
3801       if ( geomEntry.in()[0] && !smeshSO->_is_nil() )
3802       {
3803         CORBA::String_var smeshEntry = smeshSO->GetID();
3804         myInvalidMap[ geomEntry.in() ].insert( smeshEntry.in() );
3805       }
3806     }
3807
3808     //================================================================================
3809     /*!
3810      * \brief Store a source sub-shape for which a counterpart not found and
3811      *        a smesh object invalid due to that
3812      */
3813     void AddInvalid( std::string            geomEntry,
3814                      SALOMEDS::SObject_wrap smeshSO )
3815     {
3816       if ( !geomEntry.empty() )
3817       {
3818         CORBA::String_var smeshEntry = smeshSO->GetID();
3819         myInvalidMap[ geomEntry ].insert( smeshEntry.in() );
3820       }
3821     }
3822
3823     //================================================================================
3824     /*!
3825      * \brief Store a source sub-shape for which a counterpart not found and
3826      *        a smesh object invalid due to that
3827      */
3828     void AddInvalid( int                    oldGeomID,
3829                      SALOMEDS::SObject_wrap smeshSO )
3830     {
3831       int shapeType = getShapeType( mySrcMesh_i, oldGeomID );
3832       if ( shapeType < 0 || shapeType > TopAbs_SHAPE )
3833         return;
3834
3835       const char* typeName[] = { "COMPOUND","COMPSOLID","SOLID","SHELL",
3836                                  "FACE","WIRE","EDGE","VERTEX","SHAPE" };
3837
3838       SMESH_Comment geomName( typeName[ shapeType ]);
3839       geomName << " #" << oldGeomID;
3840
3841       CORBA::String_var smeshEntry = smeshSO->GetID();
3842       myInvalidMap[ geomName ].insert( smeshEntry.in() );
3843     }
3844
3845     //================================================================================
3846     /*!
3847      * \brief Return entries of a source sub-shape for which a counterpart not found and
3848      *        of smesh objects invalid due to that
3849      */
3850     void GetInvalid( SMESH::string_array_out &               theInvalidEntries,
3851                      std::vector< SALOMEDS::SObject_wrap > & theInvalidMeshSObjects)
3852     {
3853       int nbSO = 0;
3854       TStr2StrSetMap::iterator entry2entrySet = myInvalidMap.begin();
3855       for ( ; entry2entrySet != myInvalidMap.end(); ++entry2entrySet )
3856       {
3857         nbSO += 1 + entry2entrySet->second.size();
3858       }
3859       int iSO = theInvalidMeshSObjects.size(), iEntry = 0;
3860       theInvalidEntries->length  ( nbSO );
3861       theInvalidMeshSObjects.resize( theInvalidMeshSObjects.size() + nbSO - myInvalidMap.size() );
3862
3863       entry2entrySet = myInvalidMap.begin();
3864       for ( ; entry2entrySet != myInvalidMap.end(); ++entry2entrySet )
3865       {
3866         theInvalidEntries[ iEntry++ ] = entry2entrySet->first.c_str();
3867
3868         std::set< std::string > & entrySet = entry2entrySet->second;
3869         std::set< std::string >::iterator entry = entrySet.begin();
3870         for ( ; entry != entrySet.end(); ++entry )
3871         {
3872           theInvalidEntries[ iEntry++ ] = entry->c_str();
3873
3874           SALOMEDS::SObject_wrap so = myGen_i->getStudyServant()->FindObjectID( entry->c_str() );
3875           if ( !so->_is_nil() )
3876             theInvalidMeshSObjects[ iSO++ ] = so;
3877         }
3878       }
3879     }
3880
3881   }; // struct ShapeMapper
3882
3883   //================================================================================
3884   /*!
3885    * \brief Append an item to a CORBA sequence
3886    */
3887   template < class CORBA_seq, class ITEM >
3888   void append( CORBA_seq& seq, ITEM item )
3889   {
3890     if ( !CORBA::is_nil( item ))
3891     {
3892       seq->length( 1 + seq->length() );
3893       seq[ seq->length() - 1 ] = item;
3894     }
3895   }
3896 } // namespace // utils for CopyMeshWithGeom()
3897
3898 //================================================================================
3899 /*!
3900  * \brief Create a mesh by copying definitions of another mesh to a given geometry
3901  *  \param [in] sourceMesh - a mesh to copy
3902  *  \param [in] newGeometry - a new geometry
3903  *  \param [in] toCopyGroups - to create groups in the new mesh
3904  *  \param [in] toReuseHypotheses - if True, existing hypothesis will be used by the new mesh,
3905  *         otherwise new hypotheses with the same parameters will be created for the new mesh.
3906  *  \param [in] toCopyElements - to copy mesh elements of same sub-shapes of the two geometries
3907  *  \param [out] newMesh - return a new mesh
3908  *  \param [out] newGroups - return new groups
3909  *  \param [out] newSubmeshes - return new sub-meshes
3910  *  \param [out] newHypotheses - return new algorithms and hypotheses
3911  *  \param [out] invalidEntries - return study entries of objects whose
3912  *         counterparts are not found in the newGeometry, followed by entries
3913  *         of mesh sub-objects that are invalid because they depend on a not found
3914  *         preceding sub-shape
3915  *  \return CORBA::Boolean - is a success
3916  */
3917 //================================================================================
3918
3919 CORBA::Boolean SMESH_Gen_i::CopyMeshWithGeom( SMESH::SMESH_Mesh_ptr       theSourceMesh,
3920                                               GEOM::GEOM_Object_ptr       theNewGeometry,
3921                                               const char*                 theMeshName,
3922                                               CORBA::Boolean              theToCopyGroups,
3923                                               CORBA::Boolean              theToReuseHypotheses,
3924                                               CORBA::Boolean              theToCopyElements,
3925                                               SMESH::SMESH_Mesh_out       theNewMesh,
3926                                               SMESH::ListOfGroups_out     theNewGroups,
3927                                               SMESH::submesh_array_out    theNewSubmeshes,
3928                                               SMESH::ListOfHypothesis_out theNewHypotheses,
3929                                               SMESH::string_array_out     theInvalidEntries)
3930 {
3931   if ( CORBA::is_nil( theSourceMesh ) ||
3932        CORBA::is_nil( theNewGeometry ))
3933     THROW_SALOME_CORBA_EXCEPTION( "NULL arguments", SALOME::BAD_PARAM );
3934
3935   if ( !theSourceMesh->HasShapeToMesh() )
3936     THROW_SALOME_CORBA_EXCEPTION( "Source mesh not on geometry", SALOME::BAD_PARAM );
3937
3938   bool ok = true;
3939   SMESH_TRY;
3940
3941   TPythonDump pyDump(this); // prevent dump from CreateMesh()
3942
3943   theNewMesh        = CreateMesh( theNewGeometry );
3944   theNewGroups      = new SMESH::ListOfGroups();
3945   theNewSubmeshes   = new SMESH::submesh_array();
3946   theNewHypotheses  = new SMESH::ListOfHypothesis();
3947   theInvalidEntries = new SMESH::string_array();
3948
3949   std::vector< SALOMEDS::SObject_wrap > invalidSObjects;
3950
3951   GEOM::GEOM_Object_var srcGeom = theSourceMesh->GetShapeToMesh();
3952   GEOM::GEOM_Object_var geom, newGeom;
3953   SALOMEDS::SObject_wrap so;
3954
3955   SMESH_Mesh_i* srcMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( theSourceMesh );
3956   SMESH_Mesh_i* newMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( theNewMesh );
3957   srcMesh_i->Load();
3958
3959   ShapeMapper shapeMapper( srcMesh_i, newMesh_i, this );
3960
3961   // treat hypotheses of mesh and sub-meshes
3962   SMESH::submesh_array_var smList = theSourceMesh->GetSubMeshes();
3963   for ( CORBA::ULong iSM = 0; iSM <= smList->length(); ++iSM )
3964   {
3965     bool isSubMesh = ( iSM < smList->length() );
3966     if ( isSubMesh )
3967     {
3968       // create a new sub-mesh
3969       SMESH::SMESH_subMesh_var newSM;
3970       geom = smList[iSM]->GetSubShape();
3971       so   = ObjectToSObject( smList[iSM] );
3972       CORBA::String_var name;
3973       if ( !so->_is_nil() )
3974         name = so->GetName();
3975       newGeom = shapeMapper.FindNew( geom );
3976       if ( newGeom->_is_nil() )
3977       {
3978         newSM = createInvalidSubMesh( theNewMesh, geom, name.in() );
3979         shapeMapper.AddInvalid( geom, ObjectToSObject( newSM ));
3980         ok = false;
3981       }
3982       else
3983       {
3984         newSM = theNewMesh->GetSubMesh( newGeom, name.in() );
3985       }
3986       append( theNewSubmeshes, newSM );
3987
3988       if ( newGeom->_is_nil() )
3989         continue; // don't assign hypotheses
3990     }
3991     else
3992     {
3993       newGeom = GEOM::GEOM_Object::_duplicate( theNewGeometry );
3994       geom    = srcGeom;
3995       so      = ObjectToSObject( theNewMesh );
3996       SetName( so, theMeshName, "Mesh" );
3997     }
3998
3999     // assign hypotheses
4000     SMESH::ListOfHypothesis_var hypList = theSourceMesh->GetHypothesisList( geom );
4001     for ( CORBA::ULong iHyp = 0; iHyp < hypList->length(); ++iHyp )
4002     {
4003       SMESH::SMESH_Hypothesis_var hyp = hypList[ iHyp ];
4004       SMESH_Hypothesis_i*       hyp_i = SMESH::DownCast< SMESH_Hypothesis_i* >( hyp );
4005
4006       // get geometry hyp depends on
4007       std::vector< std::string > entryArray;
4008       std::vector< int >         subIDArray;
4009       bool dependsOnGeom = hyp_i->getObjectsDependOn( entryArray, subIDArray );
4010
4011       if ( !theToReuseHypotheses || dependsOnGeom )
4012       {
4013         // create a new hypothesis
4014         CORBA::String_var type = hyp->GetName();
4015         CORBA::String_var lib  = hyp->GetLibName();
4016         CORBA::String_var data = hyp_i->SaveTo();
4017         if ( data.in()[0] )
4018         {
4019           hyp   = CreateHypothesis( type, lib );
4020           hyp_i = SMESH::DownCast< SMESH_Hypothesis_i* >( hyp );
4021           hyp_i->LoadFrom( data.in() );
4022           append( theNewHypotheses, hyp );
4023         }
4024       }
4025
4026       // update geometry hyp depends on
4027       if ( dependsOnGeom )
4028       {
4029         for ( size_t iGeo = 0; iGeo < entryArray.size(); ++iGeo )
4030         {
4031           if ( !entryArray[ iGeo ].empty() )
4032           {
4033             std::string newEntry = shapeMapper.FindNew( entryArray[ iGeo ]);
4034             if ( newEntry.empty() )
4035             {
4036               ok = false;
4037               shapeMapper.AddInvalid( entryArray[ iGeo ], ObjectToSObject( hyp ));
4038               shapeMapper.AddInvalid( entryArray[ iGeo ], so ); // sub-mesh
4039             }
4040             entryArray[ iGeo ] = newEntry;
4041           }
4042         }
4043         for ( size_t iGeo = 0; iGeo < subIDArray.size(); ++iGeo )
4044         {
4045           if ( subIDArray[ iGeo ] > 0 )
4046           {
4047             int newID = shapeMapper.FindNew( subIDArray[ iGeo ]);
4048             if ( newID < 1 )
4049             {
4050               ok = false;
4051               shapeMapper.AddInvalid( subIDArray[ iGeo ], ObjectToSObject( hyp ));
4052               shapeMapper.AddInvalid( subIDArray[ iGeo ], so ); // sub-mesh
4053             }
4054             subIDArray[ iGeo ] = newID;
4055           }
4056         }
4057         if ( !hyp_i->setObjectsDependOn( entryArray, subIDArray ))
4058           ok = false;
4059       }
4060
4061       CORBA::String_var errorText;
4062       theNewMesh->AddHypothesis( newGeom, hyp, errorText.out() );
4063       if ( errorText.in()[0] )
4064         ok = false;
4065
4066     } // loop on hypotheses
4067   } // loop on sub-meshes and mesh
4068
4069
4070   // copy mesh elements, keeping IDs
4071   SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS();
4072   if ( theToCopyElements && theSourceMesh->NbNodes() > 0 )
4073   {
4074     ::SMESH_MeshEditor editor( &newMesh_i->GetImpl() );
4075     ::SMESH_MeshEditor::ElemFeatures elemData;
4076
4077     SMESH_subMesh*         srcMainSM = srcMesh_i->GetImpl().GetSubMeshContaining( 1 );
4078     SMESH_subMeshIteratorPtr srcSMIt = srcMainSM->getDependsOnIterator( /*includeSelf=*/true,
4079                                                                         /*vertexLast=*/false);
4080     while ( srcSMIt->more() )
4081     {
4082       SMESH_subMesh* srcSM = srcSMIt->next();
4083       if ( srcSM->IsEmpty() )
4084         continue; // not yet computed
4085       int newID = shapeMapper.FindNewNotChanged( srcSM );
4086       if ( newID < 1 )
4087         continue;
4088
4089       SMESHDS_SubMesh* srcSMDS = srcSM->GetSubMeshDS();
4090       SMDS_NodeIteratorPtr nIt = srcSMDS->GetNodes();
4091       while ( nIt->more() )
4092       {
4093         SMESH_NodeXYZ node( nIt->next() );
4094         const SMDS_MeshNode* newNode = newMeshDS->AddNodeWithID( node.X(), node.Y(), node.Z(),
4095                                                                  node->GetID() );
4096         const SMDS_PositionPtr pos = node->GetPosition();
4097         const double*           uv = pos->GetParameters();
4098         switch ( pos->GetTypeOfPosition() )
4099         {
4100         case SMDS_TOP_3DSPACE: newMeshDS->SetNodeInVolume( newNode, newID );               break;
4101         case SMDS_TOP_FACE:    newMeshDS->SetNodeOnFace  ( newNode, newID, uv[0], uv[1] ); break;
4102         case SMDS_TOP_EDGE:    newMeshDS->SetNodeOnEdge  ( newNode, newID, uv[0] );        break;
4103         case SMDS_TOP_VERTEX:  newMeshDS->SetNodeOnVertex( newNode, newID );               break;
4104         default: ;
4105         }
4106       }
4107       SMDS_ElemIteratorPtr eIt = srcSMDS->GetElements();
4108       while( eIt->more() )
4109       {
4110         const SMDS_MeshElement* e = eIt->next();
4111         elemData.Init( e, /*basicOnly=*/false );
4112         elemData.SetID( e->GetID() );
4113         elemData.myNodes.resize( e->NbNodes() );
4114         SMDS_NodeIteratorPtr nnIt = e->nodeIterator();
4115         size_t iN;
4116         for ( iN = 0; nnIt->more(); ++iN )
4117         {
4118           const SMDS_MeshNode* srcNode = nnIt->next();
4119           elemData.myNodes[ iN ] = newMeshDS->FindNode( srcNode->GetID() );
4120           if ( !elemData.myNodes[ iN ])
4121             break;
4122         }
4123         if ( iN == elemData.myNodes.size() )
4124           if ( const SMDS_MeshElement * newElem = editor.AddElement( elemData.myNodes, elemData ))
4125             newMeshDS->SetMeshElementOnShape( newElem, newID );
4126       }
4127       if ( SMESH_subMesh* newSM = newMesh_i->GetImpl().GetSubMeshContaining( newID ))
4128         newSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
4129     }
4130
4131     newMeshDS->Modified();
4132   }
4133
4134
4135   // treat groups
4136
4137   TStr2StrMap old2newGroupMap;
4138
4139   SALOME::GenericObj_wrap< SMESH::FilterManager > filterMgr = CreateFilterManager();
4140
4141   SMESH::ListOfGroups_var groups = theSourceMesh->GetGroups();
4142   CORBA::ULong nbGroups = theToCopyGroups ? groups->length() : 0, nbAddedGroups = 0;
4143   for ( CORBA::ULong i = 0; i < nbGroups + nbAddedGroups; ++i )
4144   {
4145     SMESH::SMESH_Group_var         stdlGroup = SMESH::SMESH_Group::_narrow        ( groups[ i ]);
4146     SMESH::SMESH_GroupOnGeom_var   geomGroup = SMESH::SMESH_GroupOnGeom::_narrow  ( groups[ i ]);
4147     SMESH::SMESH_GroupOnFilter_var fltrGroup = SMESH::SMESH_GroupOnFilter::_narrow( groups[ i ]);
4148
4149     CORBA::String_var      name = groups[ i ]->GetName();
4150     SMESH::ElementType elemType = groups[ i ]->GetType();
4151
4152     SMESH::SMESH_GroupBase_var newGroup;
4153
4154     if ( !stdlGroup->_is_nil() )
4155     {
4156       if ( newMeshDS->GetMeshInfo().NbElements( SMDSAbs_ElementType( elemType )) > 0 )
4157       {
4158         SMESH::smIdType_array_var elemIDs = stdlGroup->GetIDs();
4159         const bool isElem = ( elemType != SMESH::NODE );
4160         CORBA::ULong iE = 0;
4161         for ( ; iE < elemIDs->length(); ++iE ) // check if any element has been copied
4162           if ( newMeshDS->GetElementType( elemIDs[ iE ], isElem ) != SMDSAbs_All )
4163             break;
4164         if ( iE < elemIDs->length() )
4165         {
4166           stdlGroup = theNewMesh->CreateGroup( elemType, name );
4167           stdlGroup->Add( elemIDs );
4168           newGroup = SMESH::SMESH_GroupBase::_narrow( stdlGroup );
4169         }
4170       }
4171     }
4172     else if ( !geomGroup->_is_nil() )
4173     {
4174       GEOM::GEOM_Object_var    geom = geomGroup->GetShape();
4175       GEOM::GEOM_Object_var newGeom = shapeMapper.FindNew( geom );
4176       if ( newGeom->_is_nil() )
4177       {
4178         newGroup = theNewMesh->CreateGroup( elemType, name ); // just to notify the user
4179         shapeMapper.AddInvalid( geom, ObjectToSObject( newGroup ));
4180         ok = false;
4181       }
4182       else
4183       {
4184         newGroup = theNewMesh->CreateGroupFromGEOM( elemType, name, newGeom );
4185       }
4186     }
4187     else if ( !fltrGroup->_is_nil() )
4188     {
4189       // replace geometry in a filter
4190       SMESH::Filter_var filter = fltrGroup->GetFilter();
4191       SMESH::Filter::Criteria_var criteria;
4192       filter->GetCriteria( criteria.out() );
4193
4194       bool isMissingGroup = false;
4195       std::vector< std::string > badEntries;
4196
4197       for ( CORBA::ULong iCr = 0; iCr < criteria->length(); ++iCr )
4198       {
4199         const char* thresholdID = criteria[ iCr ].ThresholdID.in();
4200         switch ( criteria[ iCr ].Type )
4201         {
4202         case SMESH::FT_BelongToMeshGroup:
4203         {
4204           SALOME::GenericObj_wrap< SMESH::BelongToMeshGroup > btgg = filterMgr->CreateBelongToMeshGroup();
4205           btgg->SetGroupID( thresholdID );
4206           SMESH::SMESH_GroupBase_ptr refGroup = btgg->GetGroup();
4207           SALOMEDS::SObject_wrap   refGroupSO = ObjectToSObject( refGroup );
4208           if ( refGroupSO->_is_nil() )
4209             break;
4210           CORBA::String_var     refID = refGroupSO->GetID();
4211           TStr2StrMap::iterator o2nID = old2newGroupMap.find( refID.in() );
4212           if ( o2nID == old2newGroupMap.end() )
4213           {
4214             isMissingGroup = true; // corresponding new group not yet created
4215             break;
4216           }
4217           criteria[ iCr ].ThresholdID = o2nID->second.c_str();
4218
4219           if ( o2nID->second.empty() ) // new referred group is invalid
4220             badEntries.push_back( refID.in() );
4221           break;
4222         }
4223         case SMESH::FT_BelongToGeom:
4224         case SMESH::FT_BelongToPlane:
4225         case SMESH::FT_BelongToCylinder:
4226         case SMESH::FT_BelongToGenSurface:
4227         case SMESH::FT_LyingOnGeom:
4228         {
4229           std::string newID = shapeMapper.FindNew( thresholdID );
4230           criteria[ iCr ].ThresholdID = newID.c_str();
4231           if ( newID.empty() )
4232             badEntries.push_back( thresholdID );
4233           break;
4234         }
4235         case SMESH::FT_ConnectedElements:
4236         {
4237           if ( thresholdID && thresholdID[0] )
4238           {
4239             std::string newID = shapeMapper.FindNew( thresholdID );
4240             criteria[ iCr ].ThresholdID = newID.c_str();
4241             if ( newID.empty() )
4242               badEntries.push_back( thresholdID );
4243           }
4244           break;
4245         }
4246         default:;
4247         }
4248       } // loop on criteria
4249
4250       if ( isMissingGroup && i < nbGroups )
4251       {
4252         // to treat the group again
4253         append( groups, SMESH::SMESH_GroupBase::_duplicate( groups[ i ]));
4254         ++nbAddedGroups;
4255         continue;
4256       }
4257       SMESH::Filter_var newFilter = filterMgr->CreateFilter();
4258       newFilter->SetCriteria( criteria );
4259
4260       newGroup = theNewMesh->CreateGroupFromFilter( elemType, name, newFilter );
4261       newFilter->UnRegister();
4262
4263       SALOMEDS::SObject_wrap newSO = ObjectToSObject( newGroup );
4264       for ( size_t iEnt = 0; iEnt < badEntries.size(); ++iEnt )
4265         shapeMapper.AddInvalid( badEntries[ iEnt ], newSO );
4266
4267       if ( isMissingGroup ) // all groups treated but a referred groups still not found
4268       {
4269         invalidSObjects.push_back( ObjectToSObject( newGroup ));
4270         ok = false;
4271       }
4272       if ( !badEntries.empty() )
4273         ok = false;
4274
4275     } // treat a group on filter
4276
4277     append( theNewGroups, newGroup );
4278
4279     // fill old2newGroupMap
4280     SALOMEDS::SObject_wrap srcSO = ObjectToSObject( groups[i] );
4281     SALOMEDS::SObject_wrap newSO = ObjectToSObject( newGroup );
4282     if ( !srcSO->_is_nil() )
4283     {
4284       CORBA::String_var srcID, newID("");
4285       srcID = srcSO->GetID();
4286       if ( !newSO->_is_nil() )
4287         newID = newSO->GetID();
4288       old2newGroupMap.insert( std::make_pair( std::string( srcID.in() ),
4289                                               std::string( newID.in() )));
4290     }
4291
4292     if ( newGroup->_is_nil() )
4293       ok = false;
4294
4295   } // loop on groups
4296
4297   newMeshDS->CompactMesh();
4298
4299   // set mesh name
4300   if ( !theMeshName || !theMeshName[0] )
4301   {
4302     SALOMEDS::SObject_wrap soNew = ObjectToSObject( theNewMesh );
4303     SALOMEDS::SObject_wrap soOld = ObjectToSObject( theSourceMesh );
4304     CORBA::String_var oldName = soOld->GetName();
4305     SetName( soNew, oldName.in(), "Mesh" );
4306   }
4307   // mark invalid objects
4308   shapeMapper.GetInvalid( theInvalidEntries, invalidSObjects );
4309
4310   for ( size_t i = 0; i < invalidSObjects.size(); ++i )
4311     highLightInvalid( invalidSObjects[i].in(), true );
4312
4313   pyDump << "ok, "
4314          << theNewMesh << ", "
4315          << theNewGroups << ", "
4316          << *theNewSubmeshes.ptr() << ", "
4317          << *theNewHypotheses.ptr() << ", "
4318          << "invalidEntries = " << this << ".CopyMeshWithGeom( "
4319          << theSourceMesh << ", "
4320          << theNewGeometry << ", "
4321          << "'" << theMeshName << "', "
4322          << theToCopyGroups << ", "
4323          << theToReuseHypotheses << ", "
4324          << theToCopyElements << " )";
4325
4326   SMESH_CATCH( SMESH::throwCorbaException );
4327
4328   return ok;
4329 }
4330
4331 //================================================================================
4332 /*!
4333  * \brief Get version of MED format being used.
4334  */
4335 //================================================================================
4336
4337 char* SMESH_Gen_i::GetMEDFileVersion()
4338 {
4339   MED::TInt majeur, mineur, release;
4340   majeur =  mineur = release = 0;
4341   MED::GetVersionRelease(majeur, mineur, release);
4342   std::ostringstream version;
4343   version << majeur << "." << mineur << "." << release;
4344   return CORBA::string_dup( version.str().c_str() );
4345 }
4346
4347 //================================================================================
4348 /*!
4349  *  SMESH_Gen_i::GetMEDVersion
4350  *
4351  *  Get MED version of the file by its name
4352  */
4353 //================================================================================
4354
4355 char* SMESH_Gen_i::GetMEDVersion(const char* theFileName)
4356 {
4357   std::string version = MED::GetMEDVersion( theFileName );
4358   return CORBA::string_dup( version.c_str() );
4359 }
4360
4361 //================================================================================
4362 /*!
4363  *  SMESH_Gen_i::CheckCompatibility
4364  *
4365  *  Check compatibility of file with MED format being used, read only.
4366  */
4367 //================================================================================
4368
4369 CORBA::Boolean SMESH_Gen_i::CheckCompatibility(const char* theFileName)
4370 {
4371   return MED::CheckCompatibility( theFileName );
4372 }
4373
4374 //================================================================================
4375 /*!
4376  *  SMESH_Gen_i::CheckWriteCompatibility
4377  *
4378  *  Check compatibility of file with MED format being used, for append on write.
4379  */
4380 //================================================================================
4381
4382 CORBA::Boolean SMESH_Gen_i::CheckWriteCompatibility(const char* theFileName)
4383 {
4384   return MED::CheckCompatibility( theFileName, true );
4385 }
4386
4387 //================================================================================
4388 /*!
4389  *  SMESH_Gen_i::GetMeshNames
4390  *
4391  *  Get names of meshes defined in file with the specified name
4392  */
4393 //================================================================================
4394 SMESH::string_array* SMESH_Gen_i::GetMeshNames(const char* theFileName)
4395
4396 {
4397   SMESH::string_array_var aResult = new SMESH::string_array();
4398   MED::PWrapper aMed = MED::CrWrapperR( theFileName );
4399   MED::TErr anErr;
4400   MED::TInt aNbMeshes = aMed->GetNbMeshes( &anErr );
4401   if( anErr >= 0 ) {
4402     aResult->length( aNbMeshes );
4403     for( MED::TInt i = 0; i < aNbMeshes; i++ ) {
4404       MED::PMeshInfo aMeshInfo = aMed->GetPMeshInfo( i+1 );
4405       aResult[i] = CORBA::string_dup( aMeshInfo->GetName().c_str() );
4406     }
4407   }
4408   return aResult._retn();
4409 }
4410
4411 //=============================================================================
4412 /*!
4413  *  SMESH_Gen_i::Save
4414  *
4415  *  Save SMESH module's data
4416  */
4417 //=============================================================================
4418
4419 SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
4420                                       const char*              theURL,
4421                                       bool                     isMultiFile )
4422 {
4423   // localizing
4424   Kernel_Utils::Localizer loc;
4425
4426   if (!myStudyContext)
4427     UpdateStudy();
4428
4429   // Store study contents as a set of python commands
4430   SavePython();
4431
4432   SALOMEDS::Study_var aStudy = getStudyServant();
4433
4434   // Declare a byte stream
4435   SALOMEDS::TMPFile_var aStreamFile;
4436
4437   // Obtain a temporary dir
4438   TCollection_AsciiString tmpDir =
4439     ( isMultiFile ) ? TCollection_AsciiString( ( char* )theURL ) : ( char* )SALOMEDS_Tool::GetTmpDir().c_str();
4440
4441   // Create a sequence of files processed
4442   SALOMEDS_Tool::ListOfFiles aFileSeq;
4443   aFileSeq.reserve( NUM_TMP_FILES );
4444
4445   TCollection_AsciiString aStudyName( "" );
4446   if ( isMultiFile )
4447     aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( Kernel_Utils::encode(aStudy->URL()) ).c_str() );
4448
4449   // Set names of temporary files
4450   TCollection_AsciiString filename =
4451     aStudyName + TCollection_AsciiString( "_SMESH.hdf" );        // for SMESH data itself
4452   TCollection_AsciiString meshfile =
4453     aStudyName + TCollection_AsciiString( "_SMESH_Mesh.med" );   // for mesh data to be stored in MED file
4454   aFileSeq.push_back(CORBA::string_dup( filename.ToCString() ));
4455   aFileSeq.push_back(CORBA::string_dup( meshfile.ToCString() ));
4456   filename = tmpDir + filename;
4457   meshfile = tmpDir + meshfile;
4458
4459   HDFfile*    aFile;
4460   HDFdataset* aDataset;
4461   HDFgroup*   aTopGroup;
4462   HDFgroup*   aGroup;
4463   HDFgroup*   aSubGroup;
4464   HDFgroup*   aSubSubGroup;
4465   hdf_size    aSize[ 1 ];
4466
4467
4468   //Remove the files if they exist: BugID: 11225
4469 #ifndef WIN32 /* unix functionality */
4470   TCollection_AsciiString cmd("rm -f \"");
4471 #else /* windows */
4472   TCollection_AsciiString cmd("del /F \"");
4473 #endif
4474
4475   cmd+=filename;
4476   cmd+="\" \"";
4477   cmd+=meshfile;
4478   cmd+="\"";
4479 #ifdef WIN32
4480   cmd+=" 2>NUL";
4481 #endif
4482   system(cmd.ToCString());
4483
4484   // MED writer to be used by storage process
4485   DriverMED_W_SMESHDS_Mesh writer;
4486   writer.SetFile( meshfile.ToCString() );
4487   //writer.SetSaveNumbers( false ); // bos #24400 -- it leads to change of element IDs
4488
4489   // IMP issue 20918
4490   // SetStoreName() to groups before storing hypotheses to let them refer to
4491   // groups using "store name", which is "Group <group_persistent_id>"
4492   {
4493     SALOMEDS::ChildIterator_wrap itBig = aStudy->NewChildIterator( theComponent );
4494     for ( ; itBig->More(); itBig->Next() ) {
4495       SALOMEDS::SObject_wrap gotBranch = itBig->Value();
4496       if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) {
4497         CORBA::Object_var anObject = SObjectToObject( gotBranch );
4498         if ( !CORBA::is_nil( anObject ) ) {
4499           SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ;
4500           if ( !myMesh->_is_nil() ) {
4501             myMesh->Load(); // load from study file if not yet done
4502             TPythonDump pd(this); // not to dump GetGroups()
4503             SMESH::ListOfGroups_var groups = myMesh->GetGroups();
4504             for ( CORBA::ULong i = 0; i < groups->length(); ++i )
4505             {
4506               SMESH_GroupBase_i* grImpl = SMESH::DownCast<SMESH_GroupBase_i*>( groups[i]);
4507               if ( grImpl )
4508               {
4509                 CORBA::String_var objStr = GetORB()->object_to_string( grImpl->_this() );
4510                 int anId = myStudyContext->findId( string( objStr.in() ) );
4511                 char grpName[ 30 ];
4512                 sprintf( grpName, "Group %d %d", anId, grImpl->GetLocalID() );
4513                 SMESHDS_GroupBase* aGrpBaseDS = grImpl->GetGroupDS();
4514                 aGrpBaseDS->SetStoreName( grpName );
4515               }
4516             }
4517           }
4518         }
4519       }
4520     }
4521   }
4522
4523   // Write data
4524   // ---> create HDF file
4525   aFile = new HDFfile( (char*) filename.ToCString() );
4526   aFile->CreateOnDisk();
4527
4528   // --> iterator for top-level objects
4529   SALOMEDS::ChildIterator_wrap itBig = aStudy->NewChildIterator( theComponent );
4530   for ( ; itBig->More(); itBig->Next() ) {
4531     SALOMEDS::SObject_wrap gotBranch = itBig->Value();
4532
4533     // --> hypotheses root branch (only one for the study)
4534     if ( gotBranch->Tag() == GetHypothesisRootTag() ) {
4535       // create hypotheses root HDF group
4536       aTopGroup = new HDFgroup( "Hypotheses", aFile );
4537       aTopGroup->CreateOnDisk();
4538
4539       // iterator for all hypotheses
4540       SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( gotBranch );
4541       for ( ; it->More(); it->Next() ) {
4542         SALOMEDS::SObject_wrap mySObject = it->Value();
4543         CORBA::Object_var anObject = SObjectToObject( mySObject );
4544         if ( !CORBA::is_nil( anObject ) ) {
4545           SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject );
4546           if ( !myHyp->_is_nil() ) {
4547             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
4548             if ( myImpl ) {
4549               CORBA::String_var hn = myHyp->GetName(), ln = myHyp->GetLibName();
4550               std::string hypname = hn.in();
4551               std::string libname = ln.in();
4552               // BUG SWP13062
4553               // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for
4554               // WIN32 and ".so" for X-system) must be deleted
4555               int libname_len = libname.length();
4556 #ifdef WIN32
4557               if( libname_len > 4 )
4558                 libname.resize( libname_len - 4 );
4559 #else
4560               // PAL17753 (Regression: missing hypothesis in restored study)
4561               // "lib" also should be removed from the beginning
4562               if( libname_len > 6 )
4563                 libname = libname.substr( 3, libname_len - 3 - 3 );
4564 #endif
4565               CORBA::String_var  objStr = GetORB()->object_to_string( anObject );
4566               CORBA::String_var hypdata = myImpl->SaveTo();
4567               int                    id = myStudyContext->findId( string( objStr.in() ));
4568
4569               // for each hypothesis create HDF group basing on its id
4570               char hypGrpName[30];
4571               sprintf( hypGrpName, "Hypothesis %d", id );
4572               aGroup = new HDFgroup( hypGrpName, aTopGroup );
4573               aGroup->CreateOnDisk();
4574               // --> type name of hypothesis
4575               aSize[ 0 ] = hypname.length() + 1;
4576               aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 );
4577               aDataset->CreateOnDisk();
4578               aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) );
4579               aDataset->CloseOnDisk();
4580               // --> server plugin library name of hypothesis
4581               aSize[ 0 ] = libname.length() + 1;
4582               aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 );
4583               aDataset->CreateOnDisk();
4584               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
4585               aDataset->CloseOnDisk();
4586               // --> persistent data of hypothesis
4587               aSize[ 0 ] = strlen( hypdata.in() ) + 1;
4588               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
4589               aDataset->CreateOnDisk();
4590               aDataset->WriteOnDisk( ( char* )( hypdata.in() ) );
4591               aDataset->CloseOnDisk();
4592               // close hypothesis HDF group
4593               aGroup->CloseOnDisk();
4594             }
4595           }
4596         }
4597       }
4598       // close hypotheses root HDF group
4599       aTopGroup->CloseOnDisk();
4600     }
4601     // --> algorithms root branch (only one for the study)
4602     else if ( gotBranch->Tag() == GetAlgorithmsRootTag() ) {
4603       // create algorithms root HDF group
4604       aTopGroup = new HDFgroup( "Algorithms", aFile );
4605       aTopGroup->CreateOnDisk();
4606
4607       // iterator for all algorithms
4608       SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( gotBranch );
4609       for ( ; it->More(); it->Next() ) {
4610         SALOMEDS::SObject_wrap mySObject = it->Value();
4611         CORBA::Object_var anObject = SObjectToObject( mySObject );
4612         if ( !CORBA::is_nil( anObject ) ) {
4613           SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject );
4614           if ( !myHyp->_is_nil() ) {
4615             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
4616             if ( myImpl ) {
4617               CORBA::String_var hn = myHyp->GetName(), ln = myHyp->GetLibName();
4618               std::string hypname = hn.in();
4619               std::string libname = ln.in();
4620               // BUG SWP13062
4621               // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for
4622               // WIN32 and ".so" for X-system) must be deleted
4623               int libname_len = libname.length();
4624 #ifdef WIN32
4625               if( libname_len > 4 )
4626                 libname.resize( libname_len - 4 );
4627 #else
4628               // PAL17753 (Regression: missing hypothesis in restored study)
4629               // "lib" also should be removed from the beginning
4630               if( libname_len > 6 )
4631                 libname = libname.substr( 3, libname_len - 3 - 3 );
4632 #endif
4633               CORBA::String_var  objStr = GetORB()->object_to_string( anObject );
4634               CORBA::String_var hypdata = myImpl->SaveTo();
4635               int                    id = myStudyContext->findId( string( objStr.in() ) );
4636
4637               // for each algorithm create HDF group basing on its id
4638               char hypGrpName[30];
4639               sprintf( hypGrpName, "Algorithm %d", id );
4640               aGroup = new HDFgroup( hypGrpName, aTopGroup );
4641               aGroup->CreateOnDisk();
4642               // --> type name of algorithm
4643               aSize[0] = hypname.length() + 1;
4644               aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 );
4645               aDataset->CreateOnDisk();
4646               aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) );
4647               aDataset->CloseOnDisk();
4648               // --> server plugin library name of hypothesis
4649               aSize[0] = libname.length() + 1;
4650               aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 );
4651               aDataset->CreateOnDisk();
4652               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
4653               aDataset->CloseOnDisk();
4654               // --> persistent data of algorithm
4655               aSize[0] = strlen( hypdata.in() ) + 1;
4656               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
4657               aDataset->CreateOnDisk();
4658               aDataset->WriteOnDisk( ( char* )( hypdata.in() ));
4659               aDataset->CloseOnDisk();
4660               // close algorithm HDF group
4661               aGroup->CloseOnDisk();
4662             }
4663           }
4664         }
4665       }
4666       // close algorithms root HDF group
4667       aTopGroup->CloseOnDisk();
4668     }
4669     // --> mesh objects roots branches
4670     else if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) {
4671       CORBA::Object_var anObject = SObjectToObject( gotBranch );
4672       if ( !CORBA::is_nil( anObject ) ) {
4673         SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ;
4674         if ( !myMesh->_is_nil() ) {
4675           SMESH_Mesh_i* myImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( myMesh ).in() );
4676           if ( myImpl ) {
4677             CORBA::String_var objStr = GetORB()->object_to_string( anObject );
4678             int id = myStudyContext->findId( string( objStr.in() ) );
4679             ::SMESH_Mesh& myLocMesh = myImpl->GetImpl();
4680             SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS();
4681             bool hasShape = myLocMesh.HasShapeToMesh();
4682
4683             // for each mesh open the HDF group basing on its id
4684             char meshGrpName[ 30 ];
4685             sprintf( meshGrpName, "Mesh %d", id );
4686             aTopGroup = new HDFgroup( meshGrpName, aFile );
4687             aTopGroup->CreateOnDisk();
4688
4689             // --> put dataset to hdf file which is a flag that mesh has data
4690             string strHasData = "0";
4691             // check if the mesh is not empty
4692             if ( mySMESHDSMesh->NbNodes() > 0 ) {
4693               // write mesh data to med file
4694               writer.SetMesh( mySMESHDSMesh );
4695               writer.SetMeshId( id );
4696               strHasData = "1";
4697             }
4698             aSize[ 0 ] = strHasData.length() + 1;
4699             aDataset = new HDFdataset( "Has data", aTopGroup, HDF_STRING, aSize, 1 );
4700             aDataset->CreateOnDisk();
4701             aDataset->WriteOnDisk( ( char* )( strHasData.c_str() ) );
4702             aDataset->CloseOnDisk();
4703
4704             // ouv : NPAL12872
4705             // for each mesh open the HDF group basing on its auto color parameter
4706             char meshAutoColorName[ 30 ];
4707             sprintf( meshAutoColorName, "AutoColorMesh %d", id );
4708             int anAutoColor[1];
4709             anAutoColor[0] = myImpl->GetAutoColor();
4710             aSize[ 0 ] = 1;
4711             aDataset = new HDFdataset( meshAutoColorName, aTopGroup, HDF_INT32, aSize, 1 );
4712             aDataset->CreateOnDisk();
4713             aDataset->WriteOnDisk( anAutoColor );
4714             aDataset->CloseOnDisk();
4715
4716             // issue 0020693. Store _isModified flag
4717             int isModified = myLocMesh.GetIsModified();
4718             aSize[ 0 ] = 1;
4719             aDataset = new HDFdataset( "_isModified", aTopGroup, HDF_INT32, aSize, 1 );
4720             aDataset->CreateOnDisk();
4721             aDataset->WriteOnDisk( &isModified );
4722             aDataset->CloseOnDisk();
4723
4724             // issue 20918. Store Persistent Id of SMESHDS_Mesh
4725             int meshPersistentId = mySMESHDSMesh->GetPersistentId();
4726             aSize[ 0 ] = 1;
4727             aDataset = new HDFdataset( "meshPersistentId", aTopGroup, HDF_INT32, aSize, 1 );
4728             aDataset->CreateOnDisk();
4729             aDataset->WriteOnDisk( &meshPersistentId );
4730             aDataset->CloseOnDisk();
4731
4732             // Store SMESH_Mesh_i::_mainShapeTick
4733             int shapeTick = myImpl->MainShapeTick();
4734             aSize[ 0 ] = 1;
4735             aDataset = new HDFdataset( "shapeTick", aTopGroup, HDF_INT32, aSize, 1 );
4736             aDataset->CreateOnDisk();
4737             aDataset->WriteOnDisk( &shapeTick );
4738             aDataset->CloseOnDisk();
4739
4740             // write reference on a shape if exists
4741             SALOMEDS::SObject_wrap myRef;
4742             bool shapeRefFound = false;
4743             bool found = gotBranch->FindSubObject( (CORBA::Long)GetRefOnShapeTag(), myRef.inout() );
4744             if ( found ) {
4745               SALOMEDS::SObject_wrap myShape;
4746               bool ok = myRef->ReferencedObject( myShape.inout() );
4747               if ( ok ) {
4748                 CORBA::Object_var shapeObj = myShape->GetObject();
4749                 shapeRefFound = (! CORBA::is_nil( shapeObj ));
4750                 CORBA::String_var myRefOnObject = myShape->GetID();
4751                 if ( shapeRefFound && myRefOnObject.in()[0] ) {
4752                   aSize[ 0 ] = strlen( myRefOnObject.in() ) + 1;
4753                   aDataset = new HDFdataset( "Ref on shape", aTopGroup, HDF_STRING, aSize, 1 );
4754                   aDataset->CreateOnDisk();
4755                   aDataset->WriteOnDisk( ( char* )( myRefOnObject.in() ) );
4756                   aDataset->CloseOnDisk();
4757                 }
4758               }
4759             }
4760
4761             // Store file info
4762             std::string info = myImpl->FileInfoToString();
4763             if ( !info.empty() )
4764             {
4765               aSize[ 0 ] = info.size();
4766               aDataset = new HDFdataset( "file info", aTopGroup, HDF_STRING, aSize, 1 );
4767               aDataset->CreateOnDisk();
4768               aDataset->WriteOnDisk( (char*) info.data() );
4769               aDataset->CloseOnDisk();
4770             }
4771
4772             // write applied hypotheses if exist
4773             SALOMEDS::SObject_wrap myHypBranch;
4774             found = gotBranch->FindSubObject( (CORBA::Long)GetRefOnAppliedHypothesisTag(), myHypBranch.inout() );
4775             if ( found && !shapeRefFound && hasShape ) { // remove applied hyps
4776               aStudy->NewBuilder()->RemoveObjectWithChildren( myHypBranch );
4777             }
4778             if ( found && (shapeRefFound || !hasShape) ) {
4779               aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup );
4780               aGroup->CreateOnDisk();
4781
4782               SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( myHypBranch );
4783               int hypNb = 0;
4784               for ( ; it->More(); it->Next() ) {
4785                 SALOMEDS::SObject_wrap mySObject = it->Value();
4786                 SALOMEDS::SObject_wrap myRefOnHyp;
4787                 bool ok = mySObject->ReferencedObject( myRefOnHyp.inout() );
4788                 if ( ok ) {
4789                   // san - it is impossible to recover applied hypotheses
4790                   //       using their entries within Load() method,
4791                   // for there are no AttributeIORs in the study when Load() is working.
4792                   // Hence, it is better to store persistent IDs of hypotheses as references to them
4793
4794                   //string myRefOnObject = myRefOnHyp->GetID();
4795                   CORBA::Object_var anObject = SObjectToObject( myRefOnHyp );
4796                   CORBA::String_var objStr = GetORB()->object_to_string( anObject );
4797                   int id = myStudyContext->findId( string( objStr.in() ) );
4798                   //if ( myRefOnObject.length() > 0 ) {
4799                   //aSize[ 0 ] = myRefOnObject.length() + 1;
4800                   char hypName[ 30 ], hypId[ 30 ];
4801                   sprintf( hypName, "Hyp %d", ++hypNb );
4802                   sprintf( hypId, "%d", id );
4803                   aSize[ 0 ] = strlen( hypId ) + 1;
4804                   aDataset = new HDFdataset( hypName, aGroup, HDF_STRING, aSize, 1 );
4805                   aDataset->CreateOnDisk();
4806                   //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
4807                   aDataset->WriteOnDisk( hypId );
4808                   aDataset->CloseOnDisk();
4809                   //}
4810                 }
4811               }
4812               aGroup->CloseOnDisk();
4813             }
4814
4815             // write applied algorithms if exist
4816             SALOMEDS::SObject_wrap myAlgoBranch;
4817             found = gotBranch->FindSubObject( GetRefOnAppliedAlgorithmsTag(),
4818                                               myAlgoBranch.inout() );
4819             if ( found && !shapeRefFound && hasShape) { // remove applied algos
4820               aStudy->NewBuilder()->RemoveObjectWithChildren( myAlgoBranch );
4821             }
4822             if ( found && (shapeRefFound || !hasShape)) {
4823               aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
4824               aGroup->CreateOnDisk();
4825
4826               SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( myAlgoBranch );
4827               int algoNb = 0;
4828               for ( ; it->More(); it->Next() ) {
4829                 SALOMEDS::SObject_wrap mySObject = it->Value();
4830                 SALOMEDS::SObject_wrap myRefOnAlgo;
4831                 bool ok = mySObject->ReferencedObject( myRefOnAlgo.inout() );
4832                 if ( ok ) {
4833                   // san - it is impossible to recover applied algorithms
4834                   //       using their entries within Load() method,
4835                   // for there are no AttributeIORs in the study when Load() is working.
4836                   // Hence, it is better to store persistent IDs of algorithms as references to them
4837
4838                   //string myRefOnObject = myRefOnAlgo->GetID();
4839                   CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo );
4840                   CORBA::String_var objStr = GetORB()->object_to_string( anObject );
4841                   int id = myStudyContext->findId( string( objStr.in() ) );
4842                   //if ( myRefOnObject.length() > 0 ) {
4843                   //aSize[ 0 ] = myRefOnObject.length() + 1;
4844                   char algoName[ 30 ], algoId[ 30 ];
4845                   sprintf( algoName, "Algo %d", ++algoNb );
4846                   sprintf( algoId, "%d", id );
4847                   aSize[ 0 ] = strlen( algoId ) + 1;
4848                   aDataset = new HDFdataset( algoName, aGroup, HDF_STRING, aSize, 1 );
4849                   aDataset->CreateOnDisk();
4850                   //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
4851                   aDataset->WriteOnDisk( algoId );
4852                   aDataset->CloseOnDisk();
4853                   //}
4854                 }
4855               }
4856               aGroup->CloseOnDisk();
4857             }
4858
4859             // --> submesh objects sub-branches
4860
4861             for ( int i = GetSubMeshOnVertexTag(); i <= GetSubMeshOnCompoundTag(); i++ ) {
4862               SALOMEDS::SObject_wrap mySubmeshBranch;
4863               found = gotBranch->FindSubObject( i, mySubmeshBranch.inout() );
4864
4865               if ( found ) // check if there is shape reference in submeshes
4866               {
4867                 bool hasShapeRef = false;
4868                 SALOMEDS::ChildIterator_wrap itSM =
4869                   aStudy->NewChildIterator( mySubmeshBranch );
4870                 for ( ; itSM->More(); itSM->Next() ) {
4871                   SALOMEDS::SObject_wrap mySubRef, myShape, mySObject = itSM->Value();
4872                   if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef.inout() ))
4873                     mySubRef->ReferencedObject( myShape.inout() );
4874                   if ( !CORBA::is_nil( myShape ) && !CORBA::is_nil( myShape->GetObject() ))
4875                     hasShapeRef = true;
4876                   else
4877                   { // remove one submesh
4878                     if ( shapeRefFound )
4879                     { // unassign hypothesis
4880                       SMESH::SMESH_subMesh_var mySubMesh =
4881                         SMESH::SMESH_subMesh::_narrow( SObjectToObject( mySObject ));
4882                       if ( !mySubMesh->_is_nil() ) {
4883                         int shapeID = mySubMesh->GetId();
4884                         TopoDS_Shape S = mySMESHDSMesh->IndexToShape( shapeID );
4885                         const list<const SMESHDS_Hypothesis*>& hypList =
4886                           mySMESHDSMesh->GetHypothesis( S );
4887                         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
4888                         while ( hyp != hypList.end() ) {
4889                           int hypID = (*hyp++)->GetID(); // goto next hyp here because
4890                           myLocMesh.RemoveHypothesis( S, hypID ); // hypList changes here
4891                         }
4892                       }
4893                     }
4894                     aStudy->NewBuilder()->RemoveObjectWithChildren( mySObject );
4895                   }
4896                 } // loop on submeshes of a type
4897                 if ( !shapeRefFound || !hasShapeRef ) { // remove the whole submeshes branch
4898                   aStudy->NewBuilder()->RemoveObjectWithChildren( mySubmeshBranch );
4899                   found = false;
4900                 }
4901               }  // end check if there is shape reference in submeshes
4902               if ( found ) {
4903                 char name_meshgroup[ 30 ];
4904                 if ( i == GetSubMeshOnVertexTag() )
4905                   strcpy( name_meshgroup, "SubMeshes On Vertex" );
4906                 else if ( i == GetSubMeshOnEdgeTag() )
4907                   strcpy( name_meshgroup, "SubMeshes On Edge" );
4908                 else if ( i == GetSubMeshOnWireTag() )
4909                   strcpy( name_meshgroup, "SubMeshes On Wire" );
4910                 else if ( i == GetSubMeshOnFaceTag() )
4911                   strcpy( name_meshgroup, "SubMeshes On Face" );
4912                 else if ( i == GetSubMeshOnShellTag() )
4913                   strcpy( name_meshgroup, "SubMeshes On Shell" );
4914                 else if ( i == GetSubMeshOnSolidTag() )
4915                   strcpy( name_meshgroup, "SubMeshes On Solid" );
4916                 else if ( i == GetSubMeshOnCompoundTag() )
4917                   strcpy( name_meshgroup, "SubMeshes On Compound" );
4918
4919                 // for each type of submeshes create container HDF group
4920                 aGroup = new HDFgroup( name_meshgroup, aTopGroup );
4921                 aGroup->CreateOnDisk();
4922
4923                 // iterator for all submeshes of given type
4924                 SALOMEDS::ChildIterator_wrap itSM = aStudy->NewChildIterator( mySubmeshBranch );
4925                 for ( ; itSM->More(); itSM->Next() ) {
4926                   SALOMEDS::SObject_wrap mySObject = itSM->Value();
4927                   CORBA::Object_var anSubObject = SObjectToObject( mySObject );
4928                   if ( !CORBA::is_nil( anSubObject ))
4929                   {
4930                     SMESH::SMESH_subMesh_var mySubMesh = SMESH::SMESH_subMesh::_narrow( anSubObject ) ;
4931                     CORBA::String_var objStr = GetORB()->object_to_string( anSubObject );
4932                     int subid = myStudyContext->findId( string( objStr.in() ) );
4933
4934                     // for each mesh open the HDF group basing on its id
4935                     char submeshGrpName[ 30 ];
4936                     sprintf( submeshGrpName, "SubMesh %d", subid );
4937                     aSubGroup = new HDFgroup( submeshGrpName, aGroup );
4938                     aSubGroup->CreateOnDisk();
4939
4940                     // write reference on a shape, already checked if it exists
4941                     SALOMEDS::SObject_wrap mySubRef, myShape;
4942                     if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef.inout() ))
4943                       mySubRef->ReferencedObject( myShape.inout() );
4944                     string myRefOnObject = myShape->GetID();
4945                     if ( myRefOnObject.length() > 0 ) {
4946                       aSize[ 0 ] = myRefOnObject.length() + 1;
4947                       aDataset = new HDFdataset( "Ref on shape", aSubGroup, HDF_STRING, aSize, 1 );
4948                       aDataset->CreateOnDisk();
4949                       aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
4950                       aDataset->CloseOnDisk();
4951                     }
4952
4953                     // write applied hypotheses if exist
4954                     SALOMEDS::SObject_wrap mySubHypBranch;
4955                     found = mySObject->FindSubObject( GetRefOnAppliedHypothesisTag(),
4956                                                       mySubHypBranch.inout() );
4957                     if ( found ) {
4958                       aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup );
4959                       aSubSubGroup->CreateOnDisk();
4960
4961                       SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( mySubHypBranch );
4962                       int hypNb = 0;
4963                       for ( ; it->More(); it->Next() ) {
4964                         SALOMEDS::SObject_wrap mySubSObject = it->Value();
4965                         SALOMEDS::SObject_wrap myRefOnHyp;
4966                         bool ok = mySubSObject->ReferencedObject( myRefOnHyp.inout() );
4967                         if ( ok ) {
4968                           //string myRefOnObject = myRefOnHyp->GetID();
4969                           CORBA::Object_var anObject = SObjectToObject( myRefOnHyp );
4970                           CORBA::String_var objStr = GetORB()->object_to_string( anObject );
4971                           int id = myStudyContext->findId( string( objStr.in() ) );
4972                           //if ( myRefOnObject.length() > 0 ) {
4973                           //aSize[ 0 ] = myRefOnObject.length() + 1;
4974                           char hypName[ 30 ], hypId[ 30 ];
4975                           sprintf( hypName, "Hyp %d", ++hypNb );
4976                           sprintf( hypId, "%d", id );
4977                           aSize[ 0 ] = strlen( hypId ) + 1;
4978                           aDataset = new HDFdataset( hypName, aSubSubGroup, HDF_STRING, aSize, 1 );
4979                           aDataset->CreateOnDisk();
4980                           //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
4981                           aDataset->WriteOnDisk( hypId );
4982                           aDataset->CloseOnDisk();
4983                           //}
4984                         }
4985                       }
4986                       aSubSubGroup->CloseOnDisk();
4987                     }
4988
4989                     // write applied algorithms if exist
4990                     SALOMEDS::SObject_wrap mySubAlgoBranch;
4991                     found = mySObject->FindSubObject( GetRefOnAppliedAlgorithmsTag(),
4992                                                       mySubAlgoBranch.inout() );
4993                     if ( found ) {
4994                       aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup );
4995                       aSubSubGroup->CreateOnDisk();
4996
4997                       SALOMEDS::ChildIterator_wrap it =
4998                         aStudy->NewChildIterator( mySubAlgoBranch );
4999                       int algoNb = 0;
5000                       for ( ; it->More(); it->Next() ) {
5001                         SALOMEDS::SObject_wrap mySubSObject = it->Value();
5002                         SALOMEDS::SObject_wrap myRefOnAlgo;
5003                         bool ok = mySubSObject->ReferencedObject( myRefOnAlgo.inout() );
5004                         if ( ok ) {
5005                           //string myRefOnObject = myRefOnAlgo->GetID();
5006                           CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo );
5007                           CORBA::String_var objStr = GetORB()->object_to_string( anObject );
5008                           int id = myStudyContext->findId( string( objStr.in() ) );
5009                           //if ( myRefOnObject.length() > 0 ) {
5010                           //aSize[ 0 ] = myRefOnObject.length() + 1;
5011                           char algoName[ 30 ], algoId[ 30 ];
5012                           sprintf( algoName, "Algo %d", ++algoNb );
5013                           sprintf( algoId, "%d", id );
5014                           aSize[ 0 ] = strlen( algoId ) + 1;
5015                           aDataset = new HDFdataset( algoName, aSubSubGroup, HDF_STRING, aSize, 1 );
5016                           aDataset->CreateOnDisk();
5017                           //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
5018                           aDataset->WriteOnDisk( algoId );
5019                           aDataset->CloseOnDisk();
5020                           //}
5021                         }
5022                       }
5023                       aSubSubGroup->CloseOnDisk();
5024                     }
5025                     // close submesh HDF group
5026                     aSubGroup->CloseOnDisk();
5027                   }
5028                 }
5029                 // close container of submeshes by type HDF group
5030                 aGroup->CloseOnDisk();
5031               }
5032             }
5033
5034             // store submesh order if any
5035             const TListOfListOfInt& theOrderIds = myLocMesh.GetMeshOrder();
5036             const bool isNewOrederVersion = true; // old version saves ids, new one, entries
5037             if ( !theOrderIds.empty() && !isNewOrederVersion ) { // keep old version for reference
5038               char order_list[ 30 ];
5039               strcpy( order_list, "Mesh Order" );
5040               // count number of submesh ids
5041               int nbIDs = 0;
5042               TListOfListOfInt::const_iterator idIt = theOrderIds.begin();
5043               for ( ; idIt != theOrderIds.end(); idIt++ )
5044                 nbIDs += (*idIt).size();
5045               // number of values = number of IDs +
5046               //                    number of lists (for separators) - 1
5047               int* smIDs = new int [ nbIDs + theOrderIds.size() - 1 ];
5048               idIt = theOrderIds.begin();
5049               for ( int i = 0; idIt != theOrderIds.end(); idIt++ ) {
5050                 const TListOfInt& idList = *idIt;
5051                 if (idIt != theOrderIds.begin()) // not first list
5052                   smIDs[ i++ ] = -1/* *idList.size()*/; // separator between lists
5053                 // dump submesh ids from current list
5054                 TListOfInt::const_iterator id_smId = idList.begin();
5055                 for( ; id_smId != idList.end(); id_smId++ )
5056                   smIDs[ i++ ] = *id_smId;
5057               }
5058               // write HDF group
5059               aSize[ 0 ] = nbIDs + theOrderIds.size() - 1;
5060
5061               aDataset = new HDFdataset( order_list, aTopGroup, HDF_INT32, aSize, 1 );
5062               aDataset->CreateOnDisk();
5063               aDataset->WriteOnDisk( smIDs );
5064               aDataset->CloseOnDisk();
5065               //
5066               delete[] smIDs;
5067             }
5068             if ( !theOrderIds.empty() && isNewOrederVersion )
5069             {
5070               // convert ids to entries
5071               std::list< std::list< std::string > > orderEntryLists;
5072               for ( const TListOfInt& idList : theOrderIds )
5073               {
5074                 orderEntryLists.emplace_back();
5075                 std::list< std::string > & entryList = orderEntryLists.back();
5076                 for ( const int& id : idList )
5077                 {
5078                   const TopoDS_Shape& shape = mySMESHDSMesh->IndexToShape( id );
5079                   GEOM::GEOM_Object_var  go = ShapeToGeomObject( shape );
5080                   SALOMEDS::SObject_var  so = ObjectToSObject( go );
5081                   if ( !so->_is_nil() )
5082                   {
5083                     CORBA::String_var entry = so->GetID();
5084                     entryList.emplace_back( entry.in() );
5085                   }
5086                 }
5087               }
5088               // convert orderEntryLists to string
5089               std::ostringstream ostream;
5090               boost::archive::text_oarchive( ostream ) << orderEntryLists;
5091               std::string orderEntryString = ostream.str();
5092
5093               // write HDF group
5094               aSize[ 0 ] = orderEntryString.size() + 1;
5095               aDataset = new HDFdataset( "MeshOrder_new", aTopGroup, HDF_STRING, aSize, 1 );
5096               aDataset->CreateOnDisk();
5097               aDataset->WriteOnDisk((char*) orderEntryString.data() );
5098               aDataset->CloseOnDisk();
5099             }
5100
5101             // groups root sub-branch
5102             SALOMEDS::SObject_wrap myGroupsBranch;
5103             for ( int i = GetNodeGroupsTag(); i <= GetBallElementsGroupsTag(); i++ ) {
5104               found = gotBranch->FindSubObject( i, myGroupsBranch.inout() );
5105               if ( found ) {
5106                 char name_group[ 30 ];
5107                 if ( i == GetNodeGroupsTag() )
5108                   strcpy( name_group, "Groups of Nodes" );
5109                 else if ( i == GetEdgeGroupsTag() )
5110                   strcpy( name_group, "Groups of Edges" );
5111                 else if ( i == GetFaceGroupsTag() )
5112                   strcpy( name_group, "Groups of Faces" );
5113                 else if ( i == GetVolumeGroupsTag() )
5114                   strcpy( name_group, "Groups of Volumes" );
5115                 else if ( i == Get0DElementsGroupsTag() )
5116                   strcpy( name_group, "Groups of 0D Elements" );
5117                 else if ( i == GetBallElementsGroupsTag() )
5118                   strcpy( name_group, "Groups of Balls" );
5119
5120                 aGroup = new HDFgroup( name_group, aTopGroup );
5121                 aGroup->CreateOnDisk();
5122
5123                 SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( myGroupsBranch );
5124                 for ( ; it->More(); it->Next() ) {
5125                   SALOMEDS::SObject_wrap mySObject = it->Value();
5126                   CORBA::Object_var aSubObject = SObjectToObject( mySObject );
5127                   if ( !CORBA::is_nil( aSubObject ) ) {
5128                     SMESH_GroupBase_i* myGroupImpl =
5129                       dynamic_cast<SMESH_GroupBase_i*>( GetServant( aSubObject ).in() );
5130                     if ( !myGroupImpl )
5131                       continue;
5132                     SMESHDS_GroupBase* aGrpBaseDS = myGroupImpl->GetGroupDS();
5133                     if ( !aGrpBaseDS )
5134                       continue;
5135
5136                     CORBA::String_var objStr = GetORB()->object_to_string( aSubObject );
5137                     int anId = myStudyContext->findId( string( objStr.in() ) );
5138
5139                     // For each group, create a dataset named "Group <group_persistent_id>"
5140                     // and store the group's user name into it
5141                     const char*         grpName = aGrpBaseDS->GetStoreName();
5142                     CORBA::String_var aUserName = myGroupImpl->GetName();
5143                     aSize[ 0 ] = strlen( aUserName ) + 1;
5144
5145                     aDataset = new HDFdataset( grpName, aGroup, HDF_STRING, aSize, 1 );
5146                     aDataset->CreateOnDisk();
5147                     aDataset->WriteOnDisk( aUserName );
5148                     aDataset->CloseOnDisk();
5149
5150                     // ouv : NPAL12872
5151                     // For each group, create a dataset named "Group <group_persistent_id> Color"
5152                     // and store the group's color into it
5153                     char grpColorName[ 30 ];
5154                     sprintf( grpColorName, "ColorGroup %d", anId );
5155                     SALOMEDS::Color aColor = myGroupImpl->GetColor();
5156                     double anRGB[3];
5157                     anRGB[ 0 ] = aColor.R;
5158                     anRGB[ 1 ] = aColor.G;
5159                     anRGB[ 2 ] = aColor.B;
5160                     aSize[ 0 ] = 3;
5161                     aDataset = new HDFdataset( grpColorName, aGroup, HDF_FLOAT64, aSize, 1 );
5162                     aDataset->CreateOnDisk();
5163                     aDataset->WriteOnDisk( anRGB );
5164                     aDataset->CloseOnDisk();
5165
5166                     // Pass SMESHDS_Group to MED writer
5167                     SMESHDS_Group* aGrpDS = dynamic_cast<SMESHDS_Group*>( aGrpBaseDS );
5168                     if ( aGrpDS )
5169                       writer.AddGroup( aGrpDS );
5170
5171                     // write reference on a shape if exists
5172                     SMESHDS_GroupOnGeom* aGeomGrp =
5173                       dynamic_cast<SMESHDS_GroupOnGeom*>( aGrpBaseDS );
5174                     if ( aGeomGrp ) {
5175                       SALOMEDS::SObject_wrap mySubRef, myShape;
5176                       if (mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef.inout() ) &&
5177                           mySubRef->ReferencedObject( myShape.inout() ) &&
5178                           !CORBA::is_nil( myShape->GetObject() ))
5179                       {
5180                         CORBA::String_var myRefOnObject = myShape->GetID();
5181                         if ( myRefOnObject.in()[0] ) {
5182                           char aRefName[ 30 ];
5183                           sprintf( aRefName, "Ref on shape %d", anId);
5184                           aSize[ 0 ] = strlen( myRefOnObject.in() ) + 1;
5185                           aDataset = new HDFdataset(aRefName, aGroup, HDF_STRING, aSize, 1);
5186                           aDataset->CreateOnDisk();
5187                           aDataset->WriteOnDisk( ( char* )( myRefOnObject.in() ));
5188                           aDataset->CloseOnDisk();
5189                         }
5190                       }
5191                       else // shape ref is invalid:
5192                       {
5193                         // save a group on geometry as ordinary group
5194                         writer.AddGroup( aGeomGrp );
5195                       }
5196                     }
5197                     else if ( SMESH_GroupOnFilter_i* aFilterGrp_i =
5198                               dynamic_cast<SMESH_GroupOnFilter_i*>( myGroupImpl ))
5199                     {
5200                       std::string str = aFilterGrp_i->FilterToString();
5201                       std::string hdfGrpName = "Filter " + SMESH_Comment(anId);
5202                       aSize[ 0 ] = str.length() + 1;
5203                       aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup, HDF_STRING, aSize, 1);
5204                       aDataset->CreateOnDisk();
5205                       aDataset->WriteOnDisk( ( char* )( str.c_str() ) );
5206                       aDataset->CloseOnDisk();
5207                     }
5208                   }
5209                 }
5210                 aGroup->CloseOnDisk();
5211               }
5212             } // loop on groups
5213
5214             if ( strcmp( strHasData.c_str(), "1" ) == 0 )
5215             {
5216               // Flush current mesh information into MED file
5217               writer.Perform();
5218
5219               // save info on nb of elements
5220               SMESH_PreMeshInfo::SaveToFile( myImpl, id, aFile );
5221
5222               // maybe a shape was deleted in the study
5223               if ( !shapeRefFound && !mySMESHDSMesh->ShapeToMesh().IsNull() && hasShape) {
5224                 TopoDS_Shape nullShape;
5225                 myLocMesh.ShapeToMesh( nullShape ); // remove shape referring data
5226               }
5227
5228               SMESHDS_SubMeshIteratorPtr smIt = mySMESHDSMesh->SubMeshes();
5229               if ( smIt->more() )
5230               {
5231                 // Store submeshes
5232                 // ----------------
5233                 aGroup = new HDFgroup( "Submeshes", aTopGroup );
5234                 aGroup->CreateOnDisk();
5235
5236                 // each element belongs to one or none submesh,
5237                 // so for each node/element, we store a submesh ID
5238
5239                 // Store submesh IDs
5240                 for ( int isNode = 0; isNode < 2; ++isNode )
5241                 {
5242                   SMDS_ElemIteratorPtr eIt =
5243                     mySMESHDSMesh->elementsIterator( isNode ? SMDSAbs_Node : SMDSAbs_All );
5244                   smIdType nbElems = isNode ? mySMESHDSMesh->NbNodes() : mySMESHDSMesh->GetMeshInfo().NbElements();
5245                   if ( nbElems < 1 )
5246                     continue;
5247                   std::vector<int> smIDs; smIDs.reserve( nbElems );
5248                   while ( eIt->more() )
5249                     if ( const SMDS_MeshElement* e = eIt->next())
5250                       smIDs.push_back( e->getshapeId() );
5251                   // write HDF group
5252                   aSize[ 0 ] = nbElems;
5253                   string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
5254                   aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_INT32, aSize, 1 );
5255                   aDataset->CreateOnDisk();
5256                   aDataset->WriteOnDisk( & smIDs[0] );
5257                   aDataset->CloseOnDisk();
5258                 }
5259
5260                 aGroup->CloseOnDisk();
5261
5262                 // Store node positions on sub-shapes (SMDS_Position):
5263                 // ----------------------------------------------------
5264
5265                 aGroup = new HDFgroup( "Node Positions", aTopGroup );
5266                 aGroup->CreateOnDisk();
5267
5268                 // in aGroup, create 5 datasets to contain:
5269                 // "Nodes on Edges" - ID of node on edge
5270                 // "Edge positions" - U parameter on node on edge
5271                 // "Nodes on Faces" - ID of node on face
5272                 // "Face U positions" - U parameter of node on face
5273                 // "Face V positions" - V parameter of node on face
5274
5275                 // Find out nb of nodes on edges and faces
5276                 // Collect corresponding sub-meshes
5277                 int nbEdgeNodes = 0, nbFaceNodes = 0;
5278                 list<SMESHDS_SubMesh*> aEdgeSM, aFaceSM;
5279                 // loop on SMESHDS_SubMesh'es
5280                 while ( smIt->more() )
5281                 {
5282                   SMESHDS_SubMesh* aSubMesh = const_cast< SMESHDS_SubMesh* >( smIt->next() );
5283                   if ( aSubMesh->IsComplexSubmesh() )
5284                     continue; // submesh containing other submeshs
5285                   smIdType nbNodes = aSubMesh->NbNodes();
5286                   if ( nbNodes == 0 ) continue;
5287
5288                   int aShapeID = aSubMesh->GetID();
5289                   if ( aShapeID < 1 || aShapeID > mySMESHDSMesh->MaxShapeIndex() )
5290                     continue;
5291                   int aShapeType = mySMESHDSMesh->IndexToShape( aShapeID ).ShapeType();
5292                   // write only SMDS_FacePosition and SMDS_EdgePosition
5293                   switch ( aShapeType ) {
5294                   case TopAbs_FACE:
5295                     nbFaceNodes += nbNodes;
5296                     aFaceSM.push_back( aSubMesh );
5297                     break;
5298                   case TopAbs_EDGE:
5299                     nbEdgeNodes += nbNodes;
5300                     aEdgeSM.push_back( aSubMesh );
5301                     break;
5302                   default:
5303                     continue;
5304                   }
5305                 }
5306                 // Treat positions on edges or faces
5307                 for ( int onFace = 0; onFace < 2; onFace++ )
5308                 {
5309                   // Create arrays to store in datasets
5310                   int iNode = 0, nbNodes = ( onFace ? nbFaceNodes : nbEdgeNodes );
5311                   if (!nbNodes) continue;
5312                   int* aNodeIDs = new int [ nbNodes ];
5313                   double* aUPos = new double [ nbNodes ];
5314                   double* aVPos = ( onFace ? new double[ nbNodes ] : 0 );
5315
5316                   // Fill arrays
5317                   // loop on sub-meshes
5318                   list<SMESHDS_SubMesh*> * pListSM = ( onFace ? &aFaceSM : &aEdgeSM );
5319                   list<SMESHDS_SubMesh*>::iterator itSM = pListSM->begin();
5320                   for ( ; itSM != pListSM->end(); itSM++ )
5321                   {
5322                     SMESHDS_SubMesh* aSubMesh = (*itSM);
5323
5324                     SMDS_NodeIteratorPtr itNode = aSubMesh->GetNodes();
5325                     // loop on nodes in aSubMesh
5326                     while ( itNode->more() )
5327                     {
5328                       //node ID
5329                       const SMDS_MeshNode* node = itNode->next();
5330                       aNodeIDs [ iNode ] = node->GetID();
5331
5332                       // Position
5333                       const SMDS_PositionPtr pos = node->GetPosition();
5334                       if ( onFace ) { // on FACE
5335                         SMDS_FacePositionPtr fPos = pos;
5336                         if ( fPos ) {
5337                           aUPos[ iNode ] = fPos->GetUParameter();
5338                           aVPos[ iNode ] = fPos->GetVParameter();
5339                           iNode++;
5340                         }
5341                         else
5342                           nbNodes--;
5343                       }
5344                       else { // on EDGE
5345                         SMDS_EdgePositionPtr ePos = pos;
5346                         if ( ePos ) {
5347                           aUPos[ iNode ] = ePos->GetUParameter();
5348                           iNode++;
5349                         }
5350                         else
5351                           nbNodes--;
5352                       }
5353                     } // loop on nodes in aSubMesh
5354                   } // loop on sub-meshes
5355
5356                   // Write datasets
5357                   if ( nbNodes )
5358                   {
5359                     aSize[ 0 ] = nbNodes;
5360                     // IDS
5361                     string aDSName( onFace ? "Nodes on Faces" : "Nodes on Edges");
5362                     aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_INT32, aSize, 1 );
5363                     aDataset->CreateOnDisk();
5364                     aDataset->WriteOnDisk( aNodeIDs );
5365                     aDataset->CloseOnDisk();
5366
5367                     // U Positions
5368                     aDSName = ( onFace ? "Face U positions" : "Edge positions");
5369                     aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_FLOAT64, aSize, 1);
5370                     aDataset->CreateOnDisk();
5371                     aDataset->WriteOnDisk( aUPos );
5372                     aDataset->CloseOnDisk();
5373                     // V Positions
5374                     if ( onFace ) {
5375                       aDataset = new HDFdataset( "Face V positions", aGroup, HDF_FLOAT64, aSize, 1);
5376                       aDataset->CreateOnDisk();
5377                       aDataset->WriteOnDisk( aVPos );
5378                       aDataset->CloseOnDisk();
5379                     }
5380                   }
5381                   delete [] aNodeIDs;
5382                   delete [] aUPos;
5383                   if ( aVPos ) delete [] aVPos;
5384
5385                 } // treat positions on edges or faces
5386
5387                 // close "Node Positions" group
5388                 aGroup->CloseOnDisk();
5389
5390               } // if ( there are submeshes in SMESHDS_Mesh )
5391             } // if ( hasData )
5392
5393             // close mesh HDF group
5394             aTopGroup->CloseOnDisk();
5395           }
5396         }
5397       }
5398     }
5399   }
5400
5401   // close HDF file
5402   aFile->CloseOnDisk();
5403   delete aFile;
5404
5405   // Convert temporary files to stream
5406   aStreamFile = SALOMEDS_Tool::PutFilesToStream( tmpDir.ToCString(), aFileSeq, isMultiFile );
5407
5408   // Remove temporary files and directory
5409   if ( !isMultiFile )
5410     SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq, true );
5411
5412   return aStreamFile._retn();
5413 }
5414
5415 //=============================================================================
5416 /*!
5417  *  SMESH_Gen_i::SaveASCII
5418  *
5419  *  Save SMESH module's data in ASCII format
5420  */
5421 //=============================================================================
5422
5423 SALOMEDS::TMPFile* SMESH_Gen_i::SaveASCII( SALOMEDS::SComponent_ptr theComponent,
5424                                            const char*              theURL,
5425                                            bool                     isMultiFile ) {
5426   MESSAGE( "SMESH_Gen_i::SaveASCII" );
5427   SALOMEDS::TMPFile_var aStreamFile = Save( theComponent, theURL, isMultiFile );
5428   return aStreamFile._retn();
5429
5430   //after usual saving needs to encipher binary to text string
5431   //Any binary symbol will be represent as "|xx" () hexadecimal format number
5432   int size = aStreamFile.in().length();
5433   _CORBA_Octet* buffer = new _CORBA_Octet[size*3+1];
5434   for ( int i = 0; i < size; i++ )
5435     sprintf( (char*)&(buffer[i*3]), "|%02x", aStreamFile[i] );
5436
5437   buffer[size * 3] = '\0';
5438
5439   SALOMEDS::TMPFile_var anAsciiStreamFile = new SALOMEDS::TMPFile(size*3, size*3, buffer, 1);
5440
5441   return anAsciiStreamFile._retn();
5442 }
5443
5444 //=============================================================================
5445 /*!
5446  *  SMESH_Gen_i::Load
5447  *
5448  *  Load SMESH module's data
5449  */
5450 //=============================================================================
5451
5452 bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
5453                         const SALOMEDS::TMPFile& theStream,
5454                         const char*              theURL,
5455                         bool                     isMultiFile )
5456 {
5457   UpdateStudy(); // load geom data
5458   Kernel_Utils::Localizer loc;
5459
5460   SALOMEDS::Study_var aStudy = getStudyServant();
5461
5462   // Get temporary files location
5463   TCollection_AsciiString tmpDir =
5464     ( char* )( isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir().c_str() );
5465
5466   // Convert the stream into sequence of files to process
5467   SALOMEDS_Tool::ListOfFiles aFileSeq = SALOMEDS_Tool::PutStreamToFiles( theStream,
5468                                                                          tmpDir.ToCString(),
5469                                                                          isMultiFile );
5470   TCollection_AsciiString aStudyName( "" );
5471   if ( isMultiFile ) {
5472     CORBA::WString_var url = aStudy->URL();
5473     SMESHUtils::ArrayDeleter<const char> urlMulibyte( Kernel_Utils::encode( url.in()) );
5474     aStudyName = (char*)SALOMEDS_Tool::GetNameFromPath( urlMulibyte.get() ).c_str();
5475   }
5476   // Set names of temporary files
5477   TCollection_AsciiString filename = tmpDir + aStudyName + "_SMESH.hdf";
5478   TCollection_AsciiString meshfile = tmpDir + aStudyName + "_SMESH_Mesh.med";
5479
5480   int size;
5481   HDFfile*    aFile;
5482   HDFdataset* aDataset;
5483   HDFgroup*   aTopGroup;
5484   HDFgroup*   aGroup;
5485   HDFgroup*   aSubGroup;
5486   HDFgroup*   aSubSubGroup;
5487
5488   // Read data
5489   // ---> open HDF file
5490   aFile = new HDFfile( (char*) filename.ToCString() );
5491   try {
5492     aFile->OpenOnDisk( HDF_RDONLY );
5493   }
5494   catch ( HDFexception ) {
5495     INFOS( "Load(): " << filename << " not found!" );
5496     return false;
5497   }
5498
5499   TPythonDump pd(this); // prevent dump during loading
5500
5501   // For PAL13473 ("Repetitive mesh") implementation.
5502   // New dependencies between SMESH objects are established:
5503   // now hypotheses can refer to meshes, shapes and other hypotheses.
5504   // To keep data consistent, the following order of data restoration
5505   // imposed:
5506   // 1. Create hypotheses
5507   // 2. Create all meshes
5508   // 3. Load hypotheses' data
5509   // 4. All the rest
5510
5511   list< pair< SMESH_Hypothesis_i*, string > >    hypDataList;
5512   list< pair< SMESH_Mesh_i*,       HDFgroup* > > meshGroupList;
5513   list< SMESH::Filter_var >                      filters;
5514
5515   // get total number of top-level groups
5516   int aNbGroups = aFile->nInternalObjects();
5517   if ( aNbGroups > 0 ) {
5518     // --> in first turn we should read&create hypotheses
5519     if ( aFile->ExistInternalObject( "Hypotheses" ) ) {
5520       // open hypotheses root HDF group
5521       aTopGroup = new HDFgroup( "Hypotheses", aFile );
5522       aTopGroup->OpenOnDisk();
5523
5524       // get number of hypotheses
5525       int aNbObjects = aTopGroup->nInternalObjects();
5526       for ( int j = 0; j < aNbObjects; j++ ) {
5527         // try to identify hypothesis
5528         char hypGrpName[ HDF_NAME_MAX_LEN+1 ];
5529         aTopGroup->InternalObjectIndentify( j, hypGrpName );
5530
5531         if ( string( hypGrpName ).substr( 0, 10 ) == string( "Hypothesis" ) ) {
5532           // open hypothesis group
5533           aGroup = new HDFgroup( hypGrpName, aTopGroup );
5534           aGroup->OpenOnDisk();
5535
5536           // --> get hypothesis id
5537           int    id = atoi( string( hypGrpName ).substr( 10 ).c_str() );
5538           string hypname;
5539           string libname;
5540           string hypdata;
5541
5542           // get number of datasets
5543           int aNbSubObjects = aGroup->nInternalObjects();
5544           for ( int k = 0; k < aNbSubObjects; k++ ) {
5545             // identify dataset
5546             char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ];
5547             aGroup->InternalObjectIndentify( k, name_of_subgroup );
5548             // --> get hypothesis name
5549             if ( strcmp( name_of_subgroup, "Name"  ) == 0 ) {
5550               aDataset = new HDFdataset( name_of_subgroup, aGroup );
5551               aDataset->OpenOnDisk();
5552               size = aDataset->GetSize();
5553               char* hypname_str = new char[ size ];
5554               aDataset->ReadFromDisk( hypname_str );
5555               hypname = string( hypname_str );
5556               delete [] hypname_str;
5557               aDataset->CloseOnDisk();
5558             }
5559             // --> get hypothesis plugin library name
5560             if ( strcmp( name_of_subgroup, "LibName"  ) == 0 ) {
5561               aDataset = new HDFdataset( name_of_subgroup, aGroup );
5562               aDataset->OpenOnDisk();
5563               size = aDataset->GetSize();
5564               char* libname_str = new char[ size ];
5565               aDataset->ReadFromDisk( libname_str );
5566               SCRUTE( libname_str );
5567               libname = string( libname_str );
5568               delete [] libname_str;
5569               aDataset->CloseOnDisk();
5570             }
5571             // --> get hypothesis data
5572             if ( strcmp( name_of_subgroup, "Data"  ) == 0 ) {
5573               aDataset = new HDFdataset( name_of_subgroup, aGroup );
5574               aDataset->OpenOnDisk();
5575               size = aDataset->GetSize();
5576               char* hypdata_str = new char[ size ];
5577               aDataset->ReadFromDisk( hypdata_str );
5578               hypdata = string( hypdata_str );
5579               delete [] hypdata_str;
5580               aDataset->CloseOnDisk();
5581             }
5582           }
5583           // close hypothesis HDF group
5584           aGroup->CloseOnDisk();
5585
5586           // --> restore hypothesis from data
5587           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
5588             MESSAGE("VSR - load hypothesis : id = " << id <<
5589                                 ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
5590             SMESH::SMESH_Hypothesis_var myHyp;
5591
5592             try { // protect persistence mechanism against exceptions
5593               myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() );
5594             }
5595             catch (...) {
5596               INFOS( "Exception during hypothesis creation" );
5597             }
5598
5599             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
5600             if ( myImpl ) {
5601               // myImpl->LoadFrom( hypdata.c_str() );
5602               hypDataList.push_back( make_pair( myImpl, hypdata ));
5603               CORBA::String_var iorString = GetORB()->object_to_string( myHyp );
5604               int newId = myStudyContext->findId( iorString.in() );
5605               myStudyContext->mapOldToNew( id, newId );
5606             }
5607             else
5608               MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
5609           }
5610         }
5611       }
5612       // close hypotheses root HDF group
5613       aTopGroup->CloseOnDisk();
5614       aTopGroup = 0;
5615     }
5616
5617     // --> then we should read&create algorithms
5618     if ( aFile->ExistInternalObject( "Algorithms" ) ) {
5619       // open algorithms root HDF group
5620       aTopGroup = new HDFgroup( "Algorithms", aFile );
5621       aTopGroup->OpenOnDisk();
5622
5623       // get number of algorithms
5624       int aNbObjects = aTopGroup->nInternalObjects();
5625       for ( int j = 0; j < aNbObjects; j++ ) {
5626         // try to identify algorithm
5627         char hypGrpName[ HDF_NAME_MAX_LEN+1 ];
5628         aTopGroup->InternalObjectIndentify( j, hypGrpName );
5629
5630         if ( string( hypGrpName ).substr( 0, 9 ) == string( "Algorithm" ) ) {
5631           // open algorithm group
5632           aGroup = new HDFgroup( hypGrpName, aTopGroup );
5633           aGroup->OpenOnDisk();
5634
5635           // --> get algorithm id
5636           int    id = atoi( string( hypGrpName ).substr( 9 ).c_str() );
5637           string hypname;
5638           string libname;
5639           string hypdata;
5640
5641           // get number of datasets
5642           int aNbSubObjects = aGroup->nInternalObjects();
5643           for ( int k = 0; k < aNbSubObjects; k++ ) {
5644             // identify dataset
5645             char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ];
5646             aGroup->InternalObjectIndentify( k, name_of_subgroup );
5647             // --> get algorithm name
5648             if ( strcmp( name_of_subgroup, "Name"  ) == 0 ) {
5649               aDataset = new HDFdataset( name_of_subgroup, aGroup );
5650               aDataset->OpenOnDisk();
5651               size = aDataset->GetSize();
5652               char* hypname_str = new char[ size ];
5653               aDataset->ReadFromDisk( hypname_str );
5654               hypname = string( hypname_str );
5655               delete [] hypname_str;
5656               aDataset->CloseOnDisk();
5657             }
5658             // --> get algorithm plugin library name
5659             if ( strcmp( name_of_subgroup, "LibName"  ) == 0 ) {
5660               aDataset = new HDFdataset( name_of_subgroup, aGroup );
5661               aDataset->OpenOnDisk();
5662               size = aDataset->GetSize();
5663               char* libname_str = new char[ size ];
5664               aDataset->ReadFromDisk( libname_str );
5665               SCRUTE( libname_str );
5666               libname = string( libname_str );
5667               delete [] libname_str;
5668               aDataset->CloseOnDisk();
5669             }
5670             // --> get algorithm data
5671             if ( strcmp( name_of_subgroup, "Data"  ) == 0 ) {
5672               aDataset = new HDFdataset( name_of_subgroup, aGroup );
5673               aDataset->OpenOnDisk();
5674               size = aDataset->GetSize();
5675               char* hypdata_str = new char[ size ];
5676               aDataset->ReadFromDisk( hypdata_str );
5677               SCRUTE( hypdata_str );
5678               hypdata = string( hypdata_str );
5679               delete [] hypdata_str;
5680               aDataset->CloseOnDisk();
5681             }
5682           }
5683           // close algorithm HDF group
5684           aGroup->CloseOnDisk();
5685
5686           // --> restore algorithm from data
5687           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
5688             MESSAGE("VSR - load algo : id = " << id <<
5689                                 ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
5690             SMESH::SMESH_Hypothesis_var myHyp;
5691
5692             try { // protect persistence mechanism against exceptions
5693               myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() );
5694             }
5695             catch( SALOME::SALOME_Exception& ex )
5696             {
5697               INFOS( "Exception during hypothesis creation: " << ex.details.text );
5698             }
5699             catch (...) {
5700               INFOS( "Exception during hypothesis creation" );
5701             }
5702
5703             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
5704             if ( myImpl ) {
5705               //myImpl->LoadFrom( hypdata.c_str() );
5706               hypDataList.push_back( make_pair( myImpl, hypdata ));
5707               CORBA::String_var iorString = GetORB()->object_to_string( myHyp );
5708               int newId = myStudyContext->findId( iorString.in() );
5709               myStudyContext->mapOldToNew( id, newId );
5710             }
5711             else
5712               MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
5713           }
5714         }
5715       }
5716       // close algorithms root HDF group
5717       aTopGroup->CloseOnDisk();
5718       aTopGroup = 0;
5719     }
5720
5721     // --> the rest groups should be meshes
5722     for ( int i = 0; i < aNbGroups; i++ ) {
5723       // identify next group
5724       char meshName[ HDF_NAME_MAX_LEN+1 ];
5725       aFile->InternalObjectIndentify( i, meshName );
5726
5727       if ( string( meshName ).substr( 0, 4 ) == string( "Mesh" ) ) {
5728         // --> get mesh id
5729         int id = atoi( string( meshName ).substr( 4 ).c_str() );
5730         if ( id <= 0 )
5731           continue;
5732
5733         // open mesh HDF group
5734         aTopGroup = new HDFgroup( meshName, aFile );
5735         aTopGroup->OpenOnDisk();
5736
5737         // get number of child HDF objects
5738         int aNbObjects = aTopGroup->nInternalObjects();
5739         if ( aNbObjects > 0 ) {
5740           // create mesh
5741           MESSAGE( "VSR - load mesh : id = " << id );
5742           SMESH::SMESH_Mesh_var myNewMesh = this->createMesh();
5743           SMESH_Mesh_i* myNewMeshImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( myNewMesh ).in() );
5744           if ( !myNewMeshImpl )
5745             continue;
5746           meshGroupList.push_back( make_pair( myNewMeshImpl, aTopGroup ));
5747
5748           CORBA::String_var iorString = GetORB()->object_to_string( myNewMesh );
5749           int newId = myStudyContext->findId( iorString.in() );
5750           myStudyContext->mapOldToNew( id, newId );
5751
5752           // ouv : NPAL12872
5753           // try to read and set auto color flag
5754           char aMeshAutoColorName[ 30 ];
5755           sprintf( aMeshAutoColorName, "AutoColorMesh %d", id);
5756           if( aTopGroup->ExistInternalObject( aMeshAutoColorName ) )
5757           {
5758             aDataset = new HDFdataset( aMeshAutoColorName, aTopGroup );
5759             aDataset->OpenOnDisk();
5760             size = aDataset->GetSize();
5761             int* anAutoColor = new int[ size ];
5762             aDataset->ReadFromDisk( anAutoColor );
5763             aDataset->CloseOnDisk();
5764             myNewMeshImpl->GetImpl().SetAutoColor( (bool)anAutoColor[0] );
5765             delete [] anAutoColor;
5766           }
5767
5768           // try to read and set reference to shape
5769           GEOM::GEOM_Object_var aShapeObject;
5770           if ( aTopGroup->ExistInternalObject( "Ref on shape" ) ) {
5771             // load mesh "Ref on shape" - it's an entry to SObject
5772             aDataset = new HDFdataset( "Ref on shape", aTopGroup );
5773             aDataset->OpenOnDisk();
5774             size = aDataset->GetSize();
5775             char* refFromFile = new char[ size ];
5776             aDataset->ReadFromDisk( refFromFile );
5777             aDataset->CloseOnDisk();
5778             if ( strlen( refFromFile ) > 0 ) {
5779               SALOMEDS::SObject_wrap shapeSO = aStudy->FindObjectID( refFromFile );
5780               CORBA::Object_var  shapeObject = SObjectToObject( shapeSO );
5781               if ( !CORBA::is_nil( shapeObject ) ) {
5782                 aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
5783                 if ( !aShapeObject->_is_nil() )
5784                   myNewMeshImpl->SetShape( aShapeObject );
5785               }
5786             }
5787             delete [] refFromFile;
5788           }
5789
5790           // issue 20918. Restore Persistent Id of SMESHDS_Mesh
5791           if ( aTopGroup->ExistInternalObject( "meshPersistentId" ) )
5792           {
5793             aDataset = new HDFdataset( "meshPersistentId", aTopGroup );
5794             aDataset->OpenOnDisk();
5795             size = aDataset->GetSize();
5796             int* meshPersistentId = new int[ size ];
5797             aDataset->ReadFromDisk( meshPersistentId );
5798             aDataset->CloseOnDisk();
5799             myNewMeshImpl->GetImpl().GetMeshDS()->SetPersistentId( *meshPersistentId );
5800             delete [] meshPersistentId;
5801           }
5802
5803           // Restore SMESH_Mesh_i::_mainShapeTick
5804           if ( aTopGroup->ExistInternalObject( "shapeTick" ))
5805           {
5806             aDataset = new HDFdataset( "shapeTick", aTopGroup );
5807             aDataset->OpenOnDisk();
5808             int* shapeTick = & myNewMeshImpl->MainShapeTick();
5809             aDataset->ReadFromDisk( shapeTick );
5810             aDataset->CloseOnDisk();
5811           }
5812
5813           // Restore file info
5814           if ( aTopGroup->ExistInternalObject( "file info" ))
5815           {
5816             aDataset = new HDFdataset( "file info", aTopGroup );
5817             aDataset->OpenOnDisk();
5818             size = aDataset->GetSize();
5819             std::string info( size, ' ');
5820             aDataset->ReadFromDisk( (char*) info.data() );
5821             aDataset->CloseOnDisk();
5822             myNewMeshImpl->FileInfoFromString( info );
5823           }
5824         }
5825       }
5826     } // reading MESHes
5827
5828     // As all objects that can be referred by hypothesis are created,
5829     // we can restore hypothesis data
5830
5831     list< pair< SMESH_Hypothesis_i*, string > >::iterator hyp_data;
5832     for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data )
5833     {
5834       SMESH_Hypothesis_i* hyp  = hyp_data->first;
5835       string &            data = hyp_data->second;
5836       hyp->LoadFrom( data.c_str() );
5837     }
5838
5839     // Restore the rest mesh data
5840
5841     list< pair< SMESH_Mesh_i*, HDFgroup* > >::iterator meshi_group;
5842     for ( meshi_group = meshGroupList.begin(); meshi_group != meshGroupList.end(); ++meshi_group )
5843     {
5844       aTopGroup                   = meshi_group->second;
5845       SMESH_Mesh_i* myNewMeshImpl = meshi_group->first;
5846
5847       GEOM::GEOM_Object_var aShapeObject = myNewMeshImpl->GetShapeToMesh();
5848       bool hasData = false;
5849
5850       // get mesh old id
5851       CORBA::String_var iorString = GetORB()->object_to_string( myNewMeshImpl->_this() );
5852       int newId = myStudyContext->findId( iorString.in() );
5853       int meshOldId = myStudyContext->getOldId( newId );
5854
5855       // try to find mesh data dataset
5856       if ( aTopGroup->ExistInternalObject( "Has data" ) ) {
5857         // load mesh "has data" flag
5858         aDataset = new HDFdataset( "Has data", aTopGroup );
5859         aDataset->OpenOnDisk();
5860         size = aDataset->GetSize();
5861         char* strHasData = new char[ size ];
5862         aDataset->ReadFromDisk( strHasData );
5863         aDataset->CloseOnDisk();
5864         if ( strcmp( strHasData, "1") == 0 ) {
5865           hasData = true;
5866         }
5867         delete [] strHasData;
5868       }
5869
5870       // Try to get applied ALGORITHMS (mesh is not cleared by algo addition because
5871       // nodes and elements are not yet put into sub-meshes)
5872       if ( aTopGroup->ExistInternalObject( "Applied Algorithms" ) ) {
5873         aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
5874         aGroup->OpenOnDisk();
5875         // get number of applied algorithms
5876         int aNbSubObjects = aGroup->nInternalObjects();
5877         MESSAGE( "VSR - number of applied algos " << aNbSubObjects );
5878         for ( int j = 0; j < aNbSubObjects; j++ ) {
5879           char name_dataset[ HDF_NAME_MAX_LEN+1 ];
5880           aGroup->InternalObjectIndentify( j, name_dataset );
5881           // check if it is an algorithm
5882           if ( string( name_dataset ).substr( 0, 4 ) == string( "Algo" ) ) {
5883             aDataset = new HDFdataset( name_dataset, aGroup );
5884             aDataset->OpenOnDisk();
5885             size = aDataset->GetSize();
5886             char* refFromFile = new char[ size ];
5887             aDataset->ReadFromDisk( refFromFile );
5888             aDataset->CloseOnDisk();
5889             // san - it is impossible to recover applied algorithms using their entries within Load() method
5890             int id = atoi( refFromFile );
5891             delete [] refFromFile;
5892             string anIOR = myStudyContext->getIORbyOldId( id );
5893             if ( !anIOR.empty() ) {
5894               CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
5895               if ( !CORBA::is_nil( hypObject ) ) {
5896                 SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
5897                 if ( !anHyp->_is_nil() && (!aShapeObject->_is_nil()
5898                                            || !myNewMeshImpl->HasShapeToMesh()) )
5899                   myNewMeshImpl->addHypothesis( aShapeObject, anHyp );
5900               }
5901             }
5902           }
5903         }
5904         aGroup->CloseOnDisk();
5905       }
5906
5907       // try to get applied hypotheses
5908       if ( aTopGroup->ExistInternalObject( "Applied Hypotheses" ) ) {
5909         aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup );
5910         aGroup->OpenOnDisk();
5911         // get number of applied hypotheses
5912         int aNbSubObjects = aGroup->nInternalObjects();
5913         for ( int j = 0; j < aNbSubObjects; j++ ) {
5914           char name_dataset[ HDF_NAME_MAX_LEN+1 ];
5915           aGroup->InternalObjectIndentify( j, name_dataset );
5916           // check if it is a hypothesis
5917           if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) {
5918             aDataset = new HDFdataset( name_dataset, aGroup );
5919             aDataset->OpenOnDisk();
5920             size = aDataset->GetSize();
5921             char* refFromFile = new char[ size ];
5922             aDataset->ReadFromDisk( refFromFile );
5923             aDataset->CloseOnDisk();
5924             // san - it is impossible to recover applied hypotheses using their entries within Load() method
5925             int id = atoi( refFromFile );
5926             delete [] refFromFile;
5927             string anIOR = myStudyContext->getIORbyOldId( id );
5928             if ( !anIOR.empty() ) {
5929               CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
5930               if ( !CORBA::is_nil( hypObject ) ) {
5931                 SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
5932                 if ( !anHyp->_is_nil() && (!aShapeObject->_is_nil()
5933                                            || !myNewMeshImpl->HasShapeToMesh()) )
5934                   myNewMeshImpl->addHypothesis( aShapeObject, anHyp );
5935               }
5936             }
5937           }
5938         }
5939         aGroup->CloseOnDisk();
5940       }
5941
5942       // --> try to find SUB-MESHES containers for each type of submesh
5943       for ( int j = GetSubMeshOnVertexTag(); j <= GetSubMeshOnCompoundTag(); j++ ) {
5944         const char* name_meshgroup = 0;
5945         if ( j == GetSubMeshOnVertexTag() )
5946           name_meshgroup = "SubMeshes On Vertex";
5947         else if ( j == GetSubMeshOnEdgeTag() )
5948           name_meshgroup = "SubMeshes On Edge";
5949         else if ( j == GetSubMeshOnWireTag() )
5950           name_meshgroup = "SubMeshes On Wire";
5951         else if ( j == GetSubMeshOnFaceTag() )
5952           name_meshgroup = "SubMeshes On Face";
5953         else if ( j == GetSubMeshOnShellTag() )
5954           name_meshgroup = "SubMeshes On Shell";
5955         else if ( j == GetSubMeshOnSolidTag() )
5956           name_meshgroup = "SubMeshes On Solid";
5957         else if ( j == GetSubMeshOnCompoundTag() )
5958           name_meshgroup = "SubMeshes On Compound";
5959
5960         // try to get submeshes container HDF group
5961         if ( aTopGroup->ExistInternalObject( name_meshgroup ) ) {
5962           // open submeshes containers HDF group
5963           aGroup = new HDFgroup( name_meshgroup, aTopGroup );
5964           aGroup->OpenOnDisk();
5965
5966           // get number of submeshes
5967           int aNbSubMeshes = aGroup->nInternalObjects();
5968           for ( int k = 0; k < aNbSubMeshes; k++ ) {
5969             // identify submesh
5970             char name_submeshgroup[ HDF_NAME_MAX_LEN+1 ];
5971             aGroup->InternalObjectIndentify( k, name_submeshgroup );
5972             if ( strncmp( name_submeshgroup, "SubMesh", 7 ) == 0 ) {
5973               // --> get submesh id
5974               int subid = atoi( name_submeshgroup + 7 );
5975               if ( subid <= 0 )
5976                 continue;
5977               // open submesh HDF group
5978               aSubGroup = new HDFgroup( name_submeshgroup, aGroup );
5979               aSubGroup->OpenOnDisk();
5980
5981               // try to read and set reference to subshape
5982               GEOM::GEOM_Object_var aSubShapeObject;
5983               SMESH::SMESH_subMesh_var aSubMesh;
5984
5985               if ( aSubGroup->ExistInternalObject( "Ref on shape" ) ) {
5986                 // load submesh "Ref on shape" - it's an entry to SObject
5987                 aDataset = new HDFdataset( "Ref on shape", aSubGroup );
5988                 aDataset->OpenOnDisk();
5989                 size = aDataset->GetSize();
5990                 char* refFromFile = new char[ size ];
5991                 aDataset->ReadFromDisk( refFromFile );
5992                 aDataset->CloseOnDisk();
5993                 if ( strlen( refFromFile ) > 0 ) {
5994                   SALOMEDS::SObject_wrap subShapeSO = aStudy->FindObjectID( refFromFile );
5995                   CORBA::Object_var subShapeObject = SObjectToObject( subShapeSO );
5996                   if ( !CORBA::is_nil( subShapeObject ) ) {
5997                     aSubShapeObject = GEOM::GEOM_Object::_narrow( subShapeObject );
5998                     if ( !aSubShapeObject->_is_nil() )
5999                       aSubMesh = SMESH::SMESH_subMesh::_duplicate
6000                         ( myNewMeshImpl->createSubMesh( aSubShapeObject ) );
6001                     if ( aSubMesh->_is_nil() )
6002                       continue;
6003                     string iorSubString = GetORB()->object_to_string( aSubMesh );
6004                     int        newSubId = myStudyContext->findId( iorSubString );
6005                     myStudyContext->mapOldToNew( subid, newSubId );
6006                   }
6007                 }
6008                 delete [] refFromFile;
6009               }
6010
6011               if ( aSubMesh->_is_nil() )
6012                 continue;
6013
6014               // try to get applied algorithms
6015               if ( aSubGroup->ExistInternalObject( "Applied Algorithms" ) ) {
6016                 // open "applied algorithms" HDF group
6017                 aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup );
6018                 aSubSubGroup->OpenOnDisk();
6019                 // get number of applied algorithms
6020                 int aNbSubObjects = aSubSubGroup->nInternalObjects();
6021                 for ( int l = 0; l < aNbSubObjects; l++ ) {
6022                   char name_dataset[ HDF_NAME_MAX_LEN+1 ];
6023                   aSubSubGroup->InternalObjectIndentify( l, name_dataset );
6024                   // check if it is an algorithm
6025                   if ( strncmp( name_dataset, "Algo", 4 ) == 0 ) {
6026                     aDataset = new HDFdataset( name_dataset, aSubSubGroup );
6027                     aDataset->OpenOnDisk();
6028                     size = aDataset->GetSize();
6029                     char* refFromFile = new char[ size ];
6030                     aDataset->ReadFromDisk( refFromFile );
6031                     aDataset->CloseOnDisk();
6032
6033                     int id = atoi( refFromFile );
6034                     string anIOR = myStudyContext->getIORbyOldId( id );
6035                     if ( !anIOR.empty() ) {
6036                       CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
6037                       if ( !CORBA::is_nil( hypObject ) ) {
6038                         SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
6039                         if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
6040                           myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
6041                       }
6042                     }
6043                     delete [] refFromFile;
6044                   }
6045                 }
6046                 // close "applied algorithms" HDF group
6047                 aSubSubGroup->CloseOnDisk();
6048               }
6049
6050               // try to get applied hypotheses
6051               if ( aSubGroup->ExistInternalObject( "Applied Hypotheses" ) ) {
6052                 // open "applied hypotheses" HDF group
6053                 aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup );
6054                 aSubSubGroup->OpenOnDisk();
6055                 // get number of applied hypotheses
6056                 int aNbSubObjects = aSubSubGroup->nInternalObjects();
6057                 for ( int l = 0; l < aNbSubObjects; l++ ) {
6058                   char name_dataset[ HDF_NAME_MAX_LEN+1 ];
6059                   aSubSubGroup->InternalObjectIndentify( l, name_dataset );
6060                   // check if it is a hypothesis
6061                   if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) {
6062                     aDataset = new HDFdataset( name_dataset, aSubSubGroup );
6063                     aDataset->OpenOnDisk();
6064                     size = aDataset->GetSize();
6065                     char* refFromFile = new char[ size ];
6066                     aDataset->ReadFromDisk( refFromFile );
6067                     aDataset->CloseOnDisk();
6068
6069                     int id = atoi( refFromFile );
6070                     string anIOR = myStudyContext->getIORbyOldId( id );
6071                     if ( !anIOR.empty() ) {
6072                       CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
6073                       if ( !CORBA::is_nil( hypObject ) ) {
6074                         SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
6075                         if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
6076                           myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
6077                       }
6078                     }
6079                     delete [] refFromFile;
6080                   }
6081                 }
6082                 // close "APPLIED HYPOTHESES" hdf group
6083                 aSubSubGroup->CloseOnDisk();
6084               }
6085
6086               // close SUB-MESH hdf group
6087               aSubGroup->CloseOnDisk();
6088             }
6089           }
6090           // close SUB-MESHES containers hdf group
6091           aGroup->CloseOnDisk();
6092         }
6093       }
6094
6095       // try to get GROUPS
6096       for ( int ii = GetNodeGroupsTag(); ii <= GetBallElementsGroupsTag(); ii++ ) {
6097         char name_group[ 30 ];
6098         if ( ii == GetNodeGroupsTag() )
6099           strcpy( name_group, "Groups of Nodes" );
6100         else if ( ii == GetEdgeGroupsTag() )
6101           strcpy( name_group, "Groups of Edges" );
6102         else if ( ii == GetFaceGroupsTag() )
6103           strcpy( name_group, "Groups of Faces" );
6104         else if ( ii == GetVolumeGroupsTag() )
6105           strcpy( name_group, "Groups of Volumes" );
6106         else if ( ii == Get0DElementsGroupsTag() )
6107           strcpy( name_group, "Groups of 0D Elements" );
6108         else if ( ii == GetBallElementsGroupsTag() )
6109           strcpy( name_group, "Groups of Balls" );
6110
6111         if ( aTopGroup->ExistInternalObject( name_group ) ) {
6112           aGroup = new HDFgroup( name_group, aTopGroup );
6113           aGroup->OpenOnDisk();
6114           // PAL23514: get all names from the HDFgroup to avoid iteration on its contents
6115           // within aGroup->ExistInternalObject( name )
6116           std::vector< std::string > subNames;
6117           TColStd_MapOfAsciiString mapOfNames;
6118           aGroup->GetAllObjects( subNames );
6119           for ( size_t iN = 0; iN < subNames.size(); ++iN )
6120             mapOfNames.Add( subNames[ iN ].c_str() );
6121           // loop on groups
6122           for ( size_t j = 0; j < subNames.size(); j++ ) {
6123             const std::string& name_dataset = subNames[ j ];
6124             // check if it is a group
6125             if ( name_dataset.substr( 0, 5 ) == "Group" ) {
6126               // --> get group id
6127               char * endptr;
6128               int subid = strtol( name_dataset.data() + 5, &endptr, 10 );
6129               if ( subid <= 0 )
6130                 continue;
6131               int groupID = -1; // group local ID (also persistent)
6132               if ( *endptr )
6133                 groupID = atoi( endptr + 1 );
6134               aDataset = new HDFdataset( name_dataset.c_str(), aGroup );
6135               aDataset->OpenOnDisk();
6136
6137               // Retrieve actual group name
6138               size = aDataset->GetSize();
6139               char* nameFromFile = new char[ size ];
6140               aDataset->ReadFromDisk( nameFromFile );
6141               aDataset->CloseOnDisk();
6142
6143               // Try to find a shape reference
6144               TopoDS_Shape aShape;
6145               char aRefName[ 30 ];
6146               sprintf( aRefName, "Ref on shape %d", subid);
6147               if ( mapOfNames.Contains( aRefName ))
6148               {
6149                 // load mesh "Ref on shape" - it's an entry to SObject
6150                 aDataset = new HDFdataset( aRefName, aGroup );
6151                 aDataset->OpenOnDisk();
6152                 size = aDataset->GetSize();
6153                 char* refFromFile = new char[ size ];
6154                 aDataset->ReadFromDisk( refFromFile );
6155                 aDataset->CloseOnDisk();
6156                 if ( strlen( refFromFile ) > 0 ) {
6157                   SALOMEDS::SObject_wrap shapeSO = aStudy->FindObjectID( refFromFile );
6158                   CORBA::Object_var shapeObject = SObjectToObject( shapeSO );
6159                   if ( !CORBA::is_nil( shapeObject ) ) {
6160                     aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
6161                     if ( !aShapeObject->_is_nil() )
6162                       aShape = GeomObjectToShape( aShapeObject );
6163                   }
6164                 }
6165                 delete [] refFromFile;
6166               }
6167               // Try to read a filter of SMESH_GroupOnFilter
6168               SMESH::Filter_var filter;
6169               SMESH_PredicatePtr predicate;
6170               std::string hdfGrpName = ( SMESH_Comment( "Filter ") << subid );
6171               if ( mapOfNames.Contains( hdfGrpName.c_str() ))
6172               {
6173                 aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup );
6174                 aDataset->OpenOnDisk();
6175                 size = aDataset->GetSize();
6176                 char* persistStr = new char[ size ];
6177                 aDataset->ReadFromDisk( persistStr );
6178                 aDataset->CloseOnDisk();
6179                 if ( strlen( persistStr ) > 0 ) {
6180                   filter = SMESH_GroupOnFilter_i::StringToFilter( persistStr );
6181                   predicate = SMESH_GroupOnFilter_i::GetPredicate( filter );
6182                   filters.push_back( filter );
6183                 }
6184                 delete [] persistStr;
6185               }
6186
6187               // Create group servant
6188               SMESH::ElementType type = (SMESH::ElementType)(ii - GetNodeGroupsTag() + 1);
6189               SMESH::SMESH_GroupBase_var aNewGroup = SMESH::SMESH_GroupBase::_duplicate
6190                 ( myNewMeshImpl->createGroup( type, nameFromFile, groupID, aShape, predicate ) );
6191               delete [] nameFromFile;
6192               // Obtain a SMESHDS_Group object
6193               if ( aNewGroup->_is_nil() )
6194                 continue;
6195
6196               CORBA::String_var iorSubStringVar = GetORB()->object_to_string( aNewGroup );
6197               string iorSubString(iorSubStringVar.in());
6198               int        newSubId = myStudyContext->findId( iorSubString );
6199               myStudyContext->mapOldToNew( subid, newSubId );
6200
6201               SMESH_GroupBase_i* aGroupImpl = SMESH::DownCast< SMESH_GroupBase_i*>( aNewGroup );
6202               if ( !aGroupImpl )
6203                 continue;
6204
6205               if ( SMESH_GroupOnFilter_i* aFilterGroup =
6206                    dynamic_cast< SMESH_GroupOnFilter_i*>( aGroupImpl ))
6207               {
6208                 aFilterGroup->SetFilter( filter );
6209                 filter->UnRegister();
6210               }
6211               SMESHDS_GroupBase* aGroupBaseDS = aGroupImpl->GetGroupDS();
6212               if ( !aGroupBaseDS )
6213                 continue;
6214
6215               aGroupBaseDS->SetStoreName( name_dataset.c_str() );
6216
6217               // ouv : NPAL12872
6218               // Read color of the group
6219               char aGroupColorName[ 30 ];
6220               sprintf( aGroupColorName, "ColorGroup %d", subid);
6221               if ( mapOfNames.Contains( aGroupColorName ))
6222               {
6223                 aDataset = new HDFdataset( aGroupColorName, aGroup );
6224                 aDataset->OpenOnDisk();
6225                 size = aDataset->GetSize();
6226                 double* anRGB = new double[ size ];
6227                 aDataset->ReadFromDisk( anRGB );
6228                 aDataset->CloseOnDisk();
6229                 Quantity_Color aColor( anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB );
6230                 aGroupBaseDS->SetColor( aColor );
6231                 delete [] anRGB;
6232               }
6233             }
6234           }
6235           aGroup->CloseOnDisk();
6236         }
6237       } // reading GROUPs
6238
6239       // instead of reading mesh data, we read only brief information of all
6240       // objects: mesh, groups, sub-meshes (issue 0021208)
6241       if ( hasData )
6242       {
6243         SMESH_PreMeshInfo::LoadFromFile( myNewMeshImpl, meshOldId,
6244                                          meshfile.ToCString(), filename.ToCString(),
6245                                          !isMultiFile );
6246       }
6247
6248       // read Sub-Mesh ORDER if any
6249       if ( aTopGroup->ExistInternalObject( "Mesh Order" )) { // old version keeps ids
6250         aDataset = new HDFdataset( "Mesh Order", aTopGroup );
6251         aDataset->OpenOnDisk();
6252         size = aDataset->GetSize();
6253         int* smIDs = new int[ size ];
6254         aDataset->ReadFromDisk( smIDs );
6255         aDataset->CloseOnDisk();
6256         TListOfListOfInt anOrderIds;
6257         anOrderIds.push_back( TListOfInt() );
6258         for ( int i = 0; i < size; i++ )
6259           if ( smIDs[ i ] < 0 ) // is separator
6260             anOrderIds.push_back( TListOfInt() );
6261           else
6262             anOrderIds.back().push_back(smIDs[ i ]);
6263
6264         myNewMeshImpl->GetImpl().SetMeshOrder( anOrderIds );
6265         delete [] smIDs;
6266       }
6267       if ( aTopGroup->ExistInternalObject( "MeshOrder_new" )) // new version keeps entries
6268       {
6269         aDataset = new HDFdataset( "MeshOrder_new", aTopGroup );
6270         aDataset->OpenOnDisk();
6271         size = aDataset->GetSize();
6272         std::string dataString; dataString.resize( size );
6273         aDataset->ReadFromDisk((char*) dataString.data() );
6274         aDataset->CloseOnDisk();
6275
6276         std::list< std::list< std::string > > orderEntryLists;
6277         SMESHUtils::BoostTxtArchive( dataString ) >> orderEntryLists;
6278
6279         TListOfListOfInt anOrderIds;
6280         for ( const std::list< std::string >& entryList : orderEntryLists )
6281         {
6282           anOrderIds.emplace_back();
6283           for ( const std::string & entry : entryList )
6284           {
6285             GEOM::GEOM_Object_var go = GetGeomObjectByEntry( entry );
6286             TopoDS_Shape       shape = GeomObjectToShape( go );
6287             if ( SMESH_subMesh*   sm = myNewMeshImpl->GetImpl().GetSubMesh( shape ))
6288               anOrderIds.back().emplace_back( sm->GetId() );
6289           }
6290         }
6291         myNewMeshImpl->GetImpl().SetMeshOrder( anOrderIds );
6292       }
6293     } // loop on meshes
6294
6295     // update hyps needing full mesh data restored (issue 20918)
6296     for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data )
6297     {
6298       SMESH_Hypothesis_i* hyp  = hyp_data->first;
6299       hyp->UpdateAsMeshesRestored();
6300     }
6301
6302     // notify algos on completed restoration to set sub-mesh event listeners
6303     for ( meshi_group = meshGroupList.begin(); meshi_group != meshGroupList.end(); ++meshi_group )
6304     {
6305       SMESH_Mesh_i* myNewMeshImpl = meshi_group->first;
6306       ::SMESH_Mesh& myLocMesh     = myNewMeshImpl->GetImpl();
6307
6308       TopoDS_Shape myLocShape;
6309       if(myLocMesh.HasShapeToMesh())
6310         myLocShape = myLocMesh.GetShapeToMesh();
6311       else
6312         myLocShape = SMESH_Mesh::PseudoShape();
6313
6314       myLocMesh.GetSubMesh(myLocShape)->
6315         ComputeStateEngine (SMESH_subMesh::SUBMESH_RESTORED);
6316     }
6317
6318     // let filters detect dependency on mesh groups via FT_BelongToMeshGroup predicate (22877)
6319     list< SMESH::Filter_var >::iterator f = filters.begin();
6320     for ( ; f != filters.end(); ++f )
6321       if ( SMESH::Filter_i * fi = SMESH::DownCast< SMESH::Filter_i*>( *f ))
6322         fi->FindBaseObjects();
6323
6324
6325     // close mesh group
6326     if(aTopGroup)
6327       aTopGroup->CloseOnDisk();
6328   }
6329   // close HDF file
6330   aFile->CloseOnDisk();
6331   delete aFile;
6332
6333   // Remove temporary files created from the stream
6334   if ( !isMultiFile )
6335   {
6336     SMESH_File meshFile( meshfile.ToCString() );
6337     if ( !meshFile ) // no meshfile exists
6338     {
6339       SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq, true );
6340     }
6341     else
6342     {
6343       Engines::Container_var container = GetContainerRef();
6344       if ( Engines_Container_i* container_i = SMESH::DownCast<Engines_Container_i*>( container ))
6345       {
6346         container_i->registerTemporaryFile( filename.ToCString() );
6347         container_i->registerTemporaryFile( meshfile.ToCString() );
6348         container_i->registerTemporaryFile( tmpDir.ToCString() );
6349       }
6350     }
6351   }
6352
6353   // creation of tree nodes for all data objects in the study
6354   // to support tree representation customization and drag-n-drop:
6355   SALOMEDS::UseCaseBuilder_wrap useCaseBuilder = aStudy->GetUseCaseBuilder();
6356   if ( !useCaseBuilder->IsUseCaseNode( theComponent ) ) {
6357     useCaseBuilder->SetRootCurrent();
6358     useCaseBuilder->Append( theComponent ); // component object is added as the top level item
6359     SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( theComponent );
6360     for (it->InitEx(true); it->More(); it->Next()) {
6361       useCaseBuilder->AppendTo( it->Value()->GetFather(), it->Value() );
6362     }
6363   }
6364
6365   return true;
6366 }
6367
6368 //=============================================================================
6369 /*!
6370  *  SMESH_Gen_i::LoadASCII
6371  *
6372  *  Load SMESH module's data in ASCII format
6373  */
6374 //=============================================================================
6375
6376 bool SMESH_Gen_i::LoadASCII( SALOMEDS::SComponent_ptr theComponent,
6377                              const SALOMEDS::TMPFile& theStream,
6378                              const char*              theURL,
6379                              bool                     isMultiFile ) {
6380   MESSAGE( "SMESH_Gen_i::LoadASCII" );
6381   return Load( theComponent, theStream, theURL, isMultiFile );
6382
6383   //before call main ::Load method it's need for decipher text format to
6384   //binary ( "|xx" => x' )
6385   int size = theStream.length();
6386   if ( int((size / 3 )*3) != size ) //error size of buffer
6387     return false;
6388
6389   int real_size = int(size / 3);
6390
6391   _CORBA_Octet* buffer = new _CORBA_Octet[real_size];
6392   char tmp[3];
6393   tmp[2]='\0';
6394   unsigned int c = -1;
6395   for ( int i = 0; i < real_size; i++ )
6396   {
6397     memcpy( &(tmp[0]), &(theStream[i*3+1]), 2 );
6398     sscanf( tmp, "%x", &c );
6399     sprintf( (char*)&(buffer[i]), "%c", (char)c );
6400   }
6401
6402   SALOMEDS::TMPFile_var aRealStreamFile = new SALOMEDS::TMPFile(real_size, real_size, buffer, 1);
6403
6404   return Load( theComponent, *(aRealStreamFile._retn()), theURL, isMultiFile );
6405 }
6406
6407 //=============================================================================
6408 /*!
6409  *  SMESH_Gen_i::Close
6410  *
6411  *  Clears study-connected data when it is closed
6412  */
6413 //=============================================================================
6414
6415 void SMESH_Gen_i::Close( SALOMEDS::SComponent_ptr theComponent )
6416 {
6417   MESSAGE( "SMESH_Gen_i::Close" );
6418
6419   // Clear study contexts data
6420   myStudyContext->Clear();
6421
6422   // remove the tmp files meshes are loaded from
6423   SMESH_PreMeshInfo::RemoveStudyFiles_TMP_METHOD( theComponent );
6424
6425   // Clean trace of API methods calls
6426   CleanPythonTrace();
6427
6428   return;
6429 }
6430
6431 //=============================================================================
6432 /*!
6433  *  SMESH_Gen_i::ComponentDataType
6434  *
6435  *  Get component data type
6436  */
6437 //=============================================================================
6438
6439 char* SMESH_Gen_i::ComponentDataType()
6440 {
6441   MESSAGE( "SMESH_Gen_i::ComponentDataType" );
6442   return CORBA::string_dup( "SMESH" );
6443 }
6444
6445
6446 //=============================================================================
6447 /*!
6448  *  SMESH_Gen_i::IORToLocalPersistentID
6449  *
6450  *  Transform data from transient form to persistent
6451  */
6452 //=============================================================================
6453
6454 char* SMESH_Gen_i::IORToLocalPersistentID( SALOMEDS::SObject_ptr /*theSObject*/,
6455                                            const char*           IORString,
6456                                            CORBA::Boolean        /*isMultiFile*/,
6457                                            CORBA::Boolean        /*isASCII*/ )
6458 {
6459   MESSAGE( "SMESH_Gen_i::IORToLocalPersistentID" );
6460
6461   if ( myStudyContext && strcmp( IORString, "" ) != 0 ) {
6462     int anId = myStudyContext->findId( IORString );
6463     if ( anId ) {
6464       MESSAGE( "VSR " << anId );
6465       char strId[ 20 ];
6466       sprintf( strId, "%d", anId );
6467       return  CORBA::string_dup( strId );
6468     }
6469   }
6470   return CORBA::string_dup( "" );
6471 }
6472
6473 //=============================================================================
6474 /*!
6475  *  SMESH_Gen_i::LocalPersistentIDToIOR
6476  *
6477  *  Transform data from persistent form to transient
6478  */
6479 //=============================================================================
6480
6481 char* SMESH_Gen_i::LocalPersistentIDToIOR( SALOMEDS::SObject_ptr /*theSObject*/,
6482                                            const char*           aLocalPersistentID,
6483                                            CORBA::Boolean        /*isMultiFile*/,
6484                                            CORBA::Boolean        /*isASCII*/ )
6485 {
6486   MESSAGE( "SMESH_Gen_i::LocalPersistentIDToIOR(): id = " << aLocalPersistentID );
6487
6488   if ( myStudyContext && strcmp( aLocalPersistentID, "" ) != 0 ) {
6489     int anId = atoi( aLocalPersistentID );
6490     return CORBA::string_dup( myStudyContext->getIORbyOldId( anId ).c_str() );
6491   }
6492   return CORBA::string_dup( "" );
6493 }
6494
6495 //=======================================================================
6496 //function : RegisterObject
6497 //purpose  :
6498 //=======================================================================
6499
6500 int SMESH_Gen_i::RegisterObject(CORBA::Object_ptr theObject)
6501 {
6502   if ( myStudyContext && !CORBA::is_nil( theObject )) {
6503     CORBA::String_var iorString = GetORB()->object_to_string( theObject );
6504     return myStudyContext->addObject( string( iorString.in() ) );
6505   }
6506   return 0;
6507 }
6508
6509 //================================================================================
6510 /*!
6511  * \brief Return id of registered object
6512   * \param theObject - the Object
6513   * \retval int - Object id
6514  */
6515 //================================================================================
6516
6517 CORBA::Long  SMESH_Gen_i::GetObjectId(CORBA::Object_ptr theObject)
6518 {
6519   if ( myStudyContext && !CORBA::is_nil( theObject )) {
6520     CORBA::String_var iorString = GetORB()->object_to_string( theObject );
6521     string iorStringCpp(iorString.in());
6522     return myStudyContext->findId( iorStringCpp );
6523   }
6524   return 0;
6525 }
6526
6527 //=============================================================================
6528 /*!
6529  *  SMESH_Gen_i::SetName
6530  *
6531  *  Set a new object name
6532  */
6533 //=============================================================================
6534
6535 void SMESH_Gen_i::SetName(const char* theIOR,
6536                           const char* theName)
6537 {
6538   if ( theIOR && strcmp( theIOR, "" ) ) {
6539     CORBA::Object_var anObject = GetORB()->string_to_object( theIOR );
6540     SALOMEDS::SObject_wrap aSO = ObjectToSObject( anObject );
6541     if ( !aSO->_is_nil() ) {
6542       SetName( aSO, theName );
6543     }
6544   }
6545 }
6546
6547 // Version information
6548 char* SMESH_Gen_i::getVersion()
6549 {
6550 #if SMESH_DEVELOPMENT
6551   return CORBA::string_dup(SMESH_VERSION_STR"dev");
6552 #else
6553   return CORBA::string_dup(SMESH_VERSION_STR);
6554 #endif
6555 }
6556
6557 //=================================================================================
6558 // function : Move()
6559 // purpose  : Moves objects to the specified position.
6560 //            Is used in the drag-n-drop functionality.
6561 //=================================================================================
6562
6563 void SMESH_Gen_i::Move( const SMESH::sobject_list& what,
6564                         SALOMEDS::SObject_ptr      where,
6565                         CORBA::Long                row )
6566 {
6567   if ( CORBA::is_nil( where ) ) return;
6568
6569   SALOMEDS::StudyBuilder_var studyBuilder = getStudyServant()->NewBuilder();
6570   SALOMEDS::UseCaseBuilder_var useCaseBuilder = getStudyServant()->GetUseCaseBuilder();
6571   SALOMEDS::SComponent_var father = where->GetFatherComponent();
6572   std::string dataType = father->ComponentDataType();
6573   if ( dataType != "SMESH" ) return; // not a SMESH component
6574
6575   SALOMEDS::SObject_var objAfter;
6576   if ( row >= 0 && useCaseBuilder->HasChildren( where ) ) {
6577     // insert at given row -> find insertion position
6578     SALOMEDS::UseCaseIterator_var useCaseIt = useCaseBuilder->GetUseCaseIterator( where );
6579     int i;
6580     for ( i = 0; i < row && useCaseIt->More(); i++, useCaseIt->Next() );
6581     if ( i == row && useCaseIt->More() ) {
6582       objAfter = useCaseIt->Value();
6583     }
6584   }
6585
6586   for ( CORBA::ULong i = 0; i < what.length(); i++ ) {
6587     SALOMEDS::SObject_var sobj = what[i];
6588     if ( CORBA::is_nil( sobj ) ) continue; // skip bad object
6589     // insert the object to the use case tree
6590     if ( !CORBA::is_nil( objAfter ) )
6591       useCaseBuilder->InsertBefore( sobj, objAfter ); // insert at given row
6592     else
6593       useCaseBuilder->AppendTo( where, sobj );        // append to the end of list
6594   }
6595 }
6596
6597 //================================================================================
6598 /*!
6599  * \brief Collect indices of elements, which are located inside the sphere
6600  */
6601 //================================================================================
6602
6603 SMESH::long_array* SMESH_Gen_i::GetInsideSphere( SMESH::SMESH_IDSource_ptr meshPart,
6604                                                  SMESH::ElementType     theElemType,
6605                                                  CORBA::Double         theX,
6606                                                  CORBA::Double         theY,
6607                                                  CORBA::Double         theZ,
6608                                                  CORBA::Double         theR)
6609 {
6610   SMESH::long_array_var aResult = new SMESH::long_array();
6611   if ( meshPart->_is_nil() )
6612     return aResult._retn();
6613
6614   // 1. Create geometrical object
6615   gp_Pnt aP( theX, theY, theZ );
6616   TopoDS_Shape aShape = BRepPrimAPI_MakeSphere( aP, theR ).Shape();
6617
6618   std::vector<long> lst =_GetInside(meshPart, theElemType, aShape);
6619
6620   if ( lst.size() > 0 ) {
6621     aResult->length( lst.size() );
6622     for ( size_t i = 0; i < lst.size(); i++ ) {
6623       aResult[i] = lst[i];
6624     }
6625   }
6626   return aResult._retn();
6627 }
6628
6629 //================================================================================
6630 /*!
6631  * \brief Collect indices of elements, which are located inside the box
6632  */
6633 //================================================================================
6634
6635 SMESH::long_array* SMESH_Gen_i::GetInsideBox( SMESH::SMESH_IDSource_ptr meshPart,
6636                                               SMESH::ElementType        theElemType,
6637                                               CORBA::Double             theX1,
6638                                               CORBA::Double             theY1,
6639                                               CORBA::Double             theZ1,
6640                                               CORBA::Double             theX2,
6641                                               CORBA::Double             theY2,
6642                                               CORBA::Double             theZ2)
6643 {
6644   SMESH::long_array_var aResult = new SMESH::long_array();
6645   if( meshPart->_is_nil() )
6646     return aResult._retn();
6647
6648   TopoDS_Shape aShape = BRepPrimAPI_MakeBox( gp_Pnt( theX1, theY1, theZ1 ),
6649                                              gp_Pnt( theX2, theY2, theZ2 ) ).Shape();
6650
6651   std::vector<long> lst =_GetInside(meshPart, theElemType, aShape);
6652
6653   if( lst.size() > 0 ) {
6654     aResult->length( lst.size() );
6655     for ( size_t i = 0; i < lst.size(); i++ ) {
6656       aResult[i] = lst[i];
6657     }
6658   }
6659   return aResult._retn();
6660 }
6661
6662 //================================================================================
6663 /*!
6664  * \brief Collect indices of elements, which are located inside the cylinder
6665  */
6666 //================================================================================
6667
6668 SMESH::long_array* SMESH_Gen_i::GetInsideCylinder( SMESH::SMESH_IDSource_ptr meshPart,
6669                                                    SMESH::ElementType        theElemType,
6670                                                    CORBA::Double             theX,
6671                                                    CORBA::Double             theY,
6672                                                    CORBA::Double             theZ,
6673                                                    CORBA::Double             theDX,
6674                                                    CORBA::Double             theDY,
6675                                                    CORBA::Double             theDZ,
6676                                                    CORBA::Double             theH,
6677                                                    CORBA::Double             theR )
6678 {
6679   SMESH::long_array_var aResult = new SMESH::long_array();
6680   if( meshPart->_is_nil() )
6681     return aResult._retn();
6682
6683   gp_Pnt aP( theX, theY, theZ );
6684   gp_Vec aV( theDX, theDY, theDZ );
6685   gp_Ax2 anAxes (aP, aV);
6686
6687   TopoDS_Shape aShape = BRepPrimAPI_MakeCylinder(anAxes, theR, Abs(theH)).Shape();
6688
6689   std::vector<long> lst =_GetInside(meshPart, theElemType, aShape);
6690
6691   if( lst.size() > 0 ) {
6692     aResult->length( lst.size() );
6693     for ( size_t i = 0; i < lst.size(); i++ ) {
6694       aResult[i] = lst[i];
6695     }
6696   }
6697   return aResult._retn();
6698 }
6699
6700 //================================================================================
6701 /*!
6702  * \brief Collect indices of elements, which are located inside the geom object
6703  */
6704 //================================================================================
6705
6706 SMESH::long_array* SMESH_Gen_i::GetInside( SMESH::SMESH_IDSource_ptr meshPart,
6707                                            SMESH::ElementType        theElemType,
6708                                            GEOM::GEOM_Object_ptr     theGeom,
6709                                            CORBA::Double             theTolerance )
6710 {
6711   SMESH::long_array_var aResult = new SMESH::long_array();
6712   if( meshPart->_is_nil() || theGeom->_is_nil() )
6713     return aResult._retn();
6714
6715   TopoDS_Shape aShape = GeomObjectToShape( theGeom );
6716
6717   std::vector<long> lst =_GetInside(meshPart, theElemType, aShape, &theTolerance);
6718
6719   if( lst.size() > 0 ) {
6720     aResult->length( lst.size() );
6721     for ( size_t i = 0; i < lst.size(); i++ ) {
6722       aResult[i] = lst[i];
6723     }
6724   }
6725   return aResult._retn();
6726 }
6727
6728 //================================================================================
6729 /*!
6730  * \brief Collect indices of elements, which are located inside the TopoDS_Shape
6731  */
6732 //================================================================================
6733
6734 std::vector<long> SMESH_Gen_i::_GetInside( SMESH::SMESH_IDSource_ptr meshPart,
6735                                            SMESH::ElementType        theElemType,
6736                                            const TopoDS_Shape&       theShape,
6737                                            double*                   theTolerance) {
6738
6739   std::vector<long> res;
6740   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
6741
6742   if ( mesh->_is_nil() )
6743     return res;
6744
6745   SMESH_Mesh_i* anImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
6746   if ( !anImpl )
6747     return res;
6748
6749   const SMDS_Mesh* meshDS = anImpl->GetImpl().GetMeshDS();
6750
6751   if ( !meshDS )
6752     return res;
6753
6754   SMDSAbs_ElementType aType = SMDSAbs_ElementType(theElemType);
6755   SMESH::Controls::ElementsOnShape* anElementsOnShape = new SMESH::Controls::ElementsOnShape();
6756   anElementsOnShape->SetAllNodes( true );
6757   anElementsOnShape->SetMesh( meshDS );
6758   anElementsOnShape->SetShape( theShape, aType );
6759
6760   if(theTolerance)
6761     anElementsOnShape->SetTolerance(*theTolerance);
6762
6763   SMESH::SMESH_Mesh_var msource = SMESH::SMESH_Mesh::_narrow(meshPart);
6764   if ( !msource->_is_nil() ) { // Mesh case
6765     SMDS_ElemIteratorPtr elemIt = meshDS->elementsIterator( aType );
6766     if ( elemIt ) {
6767       while ( elemIt->more() ) {
6768         const SMDS_MeshElement* anElem = elemIt->next();
6769         long anId = anElem->GetID();
6770         if ( anElementsOnShape->IsSatisfy( anId ) )
6771           res.push_back( anId );
6772       }
6773     }
6774   }
6775   SMESH::SMESH_Group_var gsource = SMESH::SMESH_Group::_narrow(meshPart);
6776   if ( !gsource->_is_nil() ) {
6777     if(theElemType == SMESH::NODE) {
6778       SMESH::smIdType_array_var nodes = gsource->GetNodeIDs();
6779       for ( CORBA::ULong i = 0; i < nodes->length(); ++i ) {
6780         if ( const SMDS_MeshNode* node = meshDS->FindNode( nodes[i] )) {
6781           long anId = node->GetID();
6782           if ( anElementsOnShape->IsSatisfy( anId ) )
6783             res.push_back( anId );
6784         }
6785       }
6786     } else if (gsource->GetType() == theElemType || theElemType == SMESH::ALL ) {
6787       SMESH::smIdType_array_var elems = gsource->GetListOfID();
6788       for ( CORBA::ULong i = 0; i < elems->length(); ++i ) {
6789         if ( const SMDS_MeshElement* elem = meshDS->FindElement( elems[i] )) {
6790           long anId = elem->GetID();
6791           if ( anElementsOnShape->IsSatisfy( anId ) )
6792             res.push_back( anId );
6793         }
6794       }
6795     }
6796   }
6797   SMESH::SMESH_subMesh_var smsource = SMESH::SMESH_subMesh::_narrow(meshPart);
6798   if ( !smsource->_is_nil() ) {
6799     SMESH::smIdType_array_var elems = smsource->GetElementsByType( theElemType );
6800     for ( CORBA::ULong i = 0; i < elems->length(); ++i ) {
6801       const SMDS_MeshElement* elem = ( theElemType == SMESH::NODE ) ? meshDS->FindNode( elems[i] ) : meshDS->FindElement( elems[i] );
6802       if (elem) {
6803         long anId = elem->GetID();
6804         if ( anElementsOnShape->IsSatisfy( anId ) )
6805           res.push_back( anId );
6806       }
6807     }
6808   }
6809   return res;
6810 }
6811
6812 //================================================================================
6813 /*!
6814  * \brief Returns true if algorithm can be used to mesh a given geometry
6815  *  \param [in] theAlgoType - the algorithm type
6816  *  \param [in] theLibName - a name of the Plug-in library implementing the algorithm
6817  *  \param [in] theGeomObject - the geometry to mesh
6818  *  \param [in] toCheckAll - if \c True, returns \c True if all shapes are meshable,
6819  *         else, returns \c True if at least one shape is meshable
6820  *  \return CORBA::Boolean - can or can't
6821  */
6822 //================================================================================
6823
6824 #undef SMY_OWN_CATCH
6825 #define SMY_OWN_CATCH // prevent re-throwing SALOME::SALOME_Exception in IsApplicable()
6826
6827 CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char*           theAlgoType,
6828                                            const char*           theLibName,
6829                                            GEOM::GEOM_Object_ptr theGeomObject,
6830                                            CORBA::Boolean        toCheckAll)
6831 {
6832   SMESH_TRY;
6833
6834   std::string aPlatformLibName;
6835   GenericHypothesisCreator_i* aCreator =
6836     getHypothesisCreator(theAlgoType, theLibName, aPlatformLibName);
6837   if (aCreator)
6838   {
6839     TopoDS_Shape shape = GeomObjectToShape( theGeomObject );
6840     const SMESH_Algo::Features& feat = SMESH_Algo::GetFeatures( theAlgoType );
6841     return shape.IsNull() || aCreator->IsApplicable( shape, toCheckAll, feat._dim );
6842   }
6843   else
6844   {
6845     return false;
6846   }
6847
6848   SMESH_CATCH( SMESH::doNothing );
6849
6850   MESSAGE("SMESH_Gen_i::IsApplicable(): exception in " << ( theAlgoType ? theAlgoType : ""));
6851   return true;
6852 }