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