Salome HOME
[bos #40505][CEA] Allow assign of 3D Tetra paramam on imported 2D mesh.
[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
2083   try {
2084     // get mesh servant
2085     SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
2086     ASSERT( meshServant );
2087     if ( meshServant ) {
2088       if ( isGeomModifIcon( theMesh ))
2089         meshServant->Clear();
2090       else
2091         meshServant->Load();
2092       // NPAL16168: "geometrical group edition from a submesh don't modify mesh computation"
2093       meshServant->CheckGeomModif();
2094       // get local TopoDS_Shape
2095       TopoDS_Shape myLocShape;
2096       if(theMesh->HasShapeToMesh())
2097         myLocShape = GeomObjectToShape( theShapeObject );
2098       else
2099         myLocShape = SMESH_Mesh::PseudoShape();
2100       // call implementation compute
2101       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
2102       myGen.PrepareCompute( myLocMesh, myLocShape );
2103       int how = ::SMESH_Gen::COMPACT_MESH;
2104       if ( myLocShape != myLocMesh.GetShapeToMesh() ) // compute a sub-mesh
2105         how |= ::SMESH_Gen::SHAPE_ONLY;
2106       bool ok = myGen.Compute( myLocMesh, myLocShape, how );
2107       meshServant->CreateGroupServants(); // algos can create groups (issue 0020918)
2108       myLocMesh.GetMeshDS()->Modified();
2109       UpdateIcons( theMesh );
2110       if ( ok )
2111         HighLightInvalid( theMesh, /*isInvalid=*/false );
2112       return ok;
2113     }
2114   }
2115   catch ( std::bad_alloc& ) {
2116     INFOS( "Compute(): lack of memory" );
2117   }
2118   catch ( SALOME_Exception& S_ex ) {
2119     INFOS( "Compute(): catch exception "<< S_ex.what() );
2120   }
2121   catch ( ... ) {
2122     INFOS( "Compute(): unknown exception " );
2123   }
2124   return false;
2125 }
2126
2127 //=============================================================================
2128 /*!
2129  *  SMESH_Gen_i::CancelCompute
2130  *
2131  *  Cancel Compute mesh on a shape
2132  */
2133 //=============================================================================
2134
2135 void SMESH_Gen_i::CancelCompute( SMESH::SMESH_Mesh_ptr theMesh,
2136                                  GEOM::GEOM_Object_ptr theShapeObject )
2137 {
2138   if ( SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() ))
2139   {
2140     ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
2141     TopoDS_Shape myLocShape;
2142     if(theMesh->HasShapeToMesh())
2143       myLocShape = GeomObjectToShape( theShapeObject );
2144     else
2145       myLocShape = SMESH_Mesh::PseudoShape();
2146     myGen.CancelCompute( myLocMesh, myLocShape);
2147   }
2148 }
2149
2150 //=============================================================================
2151 /*!
2152  *  SMESH_Gen_i::Precompute
2153  *
2154  *  Compute mesh as preview till indicated dimension on shape
2155  */
2156 //=============================================================================
2157
2158 SMESH::MeshPreviewStruct* SMESH_Gen_i::Precompute( SMESH::SMESH_Mesh_ptr theMesh,
2159                                                    GEOM::GEOM_Object_ptr theShapeObject,
2160                                                    SMESH::Dimension      theDimension,
2161                                                    SMESH::long_array&    theShapesId)
2162 {
2163   Unexpect aCatch(SALOME_SalomeException);
2164   MESSAGE( "SMESH_Gen_i::Precompute" );
2165
2166   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
2167     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
2168                                   SALOME::BAD_PARAM );
2169
2170   if ( CORBA::is_nil( theMesh ) )
2171     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
2172                                   SALOME::BAD_PARAM );
2173
2174   SMESH::MeshPreviewStruct_var result = new SMESH::MeshPreviewStruct;
2175   try {
2176     // get mesh servant
2177     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
2178     meshServant->Load();
2179     ASSERT( meshServant );
2180     if ( meshServant ) {
2181       // NPAL16168: "geometrical group edition from a submesh don't modify mesh computation"
2182       meshServant->CheckGeomModif();
2183       // get local TopoDS_Shape
2184       TopoDS_Shape myLocShape;
2185       if(theMesh->HasShapeToMesh())
2186         myLocShape = GeomObjectToShape( theShapeObject );
2187       else
2188         return result._retn();
2189
2190       // call implementation compute
2191       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
2192       TSetOfInt shapeIds;
2193       ::MeshDimension aDim = (MeshDimension)theDimension;
2194       if ( myGen.Compute( myLocMesh, myLocShape, ::SMESH_Gen::COMPACT_MESH, aDim, &shapeIds ) )
2195       {
2196         int nbShapeId = shapeIds.size();
2197         theShapesId.length( nbShapeId );
2198         // iterates on shapes and collect mesh entities into mesh preview
2199         TSetOfInt::const_iterator idIt = shapeIds.begin();
2200         TSetOfInt::const_iterator idEnd = shapeIds.end();
2201         std::map< int, int > mapOfShIdNb;
2202         std::set< SMESH_TLink > setOfEdge;
2203         std::list< SMDSAbs_ElementType > listOfElemType;
2204         typedef map<const SMDS_MeshElement*, int > TNode2LocalIDMap;
2205         typedef TNode2LocalIDMap::iterator         TNodeLocalID;
2206         TNode2LocalIDMap mapNode2LocalID;
2207         list< TNodeLocalID > connectivity;
2208         int i, nbConnNodes = 0;
2209         std::set< const SMESH_subMesh* > setOfVSubMesh;
2210         // iterates on shapes
2211         for ( ; idIt != idEnd; idIt++ )
2212         {
2213           if ( mapOfShIdNb.find( *idIt ) != mapOfShIdNb.end() )
2214             continue;
2215           SMESH_subMesh* sm = myLocMesh.GetSubMeshContaining(*idIt);
2216           if ( !sm || !sm->IsMeshComputed() )
2217             continue;
2218
2219           const TopoDS_Shape& aSh = sm->GetSubShape();
2220           const int shDim = myGen.GetShapeDim( aSh );
2221           if ( shDim < 1 || shDim > theDimension )
2222             continue;
2223
2224           mapOfShIdNb[ *idIt ] = 0;
2225           theShapesId[ mapOfShIdNb.size() - 1 ] = *idIt;
2226
2227           SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
2228           if ( !smDS ) continue;
2229
2230           if ( theDimension == SMESH::DIM_2D )
2231           {
2232             SMDS_ElemIteratorPtr faceIt = smDS->GetElements();
2233             while ( faceIt->more() )
2234             {
2235               const SMDS_MeshElement* face = faceIt->next();
2236               int aNbNode = face->NbNodes();
2237               if ( aNbNode > 4 )
2238                 aNbNode /= 2; // do not take into account additional middle nodes
2239
2240               SMDS_MeshNode* node1 = (SMDS_MeshNode*)face->GetNode( 0 );
2241               for ( int nIndx = 0; nIndx < aNbNode; nIndx++ )
2242               {
2243                 SMDS_MeshNode* node2 = (SMDS_MeshNode*)face->GetNode( nIndx+1 < aNbNode ? nIndx+1 : 0 );
2244                 if ( setOfEdge.insert( SMESH_TLink ( node1, node2 ) ).second )
2245                 {
2246                   listOfElemType.push_back( SMDSAbs_Edge );
2247                   connectivity.push_back
2248                     ( mapNode2LocalID.insert( make_pair( node1, ++nbConnNodes)).first );
2249                   connectivity.push_back
2250                     ( mapNode2LocalID.insert( make_pair( node2, ++nbConnNodes)).first );
2251                 }
2252                 node1 = node2;
2253               }
2254             }
2255           }
2256           else if ( theDimension == SMESH::DIM_1D )
2257           {
2258             SMDS_NodeIteratorPtr nodeIt = smDS->GetNodes();
2259             while ( nodeIt->more() )
2260             {
2261               listOfElemType.push_back( SMDSAbs_Node );
2262               connectivity.push_back
2263                 ( mapNode2LocalID.insert( make_pair( nodeIt->next(), ++nbConnNodes)).first );
2264             }
2265             // add corner nodes by first vertex from edge
2266             SMESH_subMeshIteratorPtr edgeSmIt =
2267               sm->getDependsOnIterator(/*includeSelf*/false,
2268                                        /*complexShapeFirst*/false);
2269             while ( edgeSmIt->more() )
2270             {
2271               SMESH_subMesh* vertexSM = edgeSmIt->next();
2272               // check that vertex is not already treated
2273               if ( !setOfVSubMesh.insert( vertexSM ).second )
2274                 continue;
2275               if ( vertexSM->GetSubShape().ShapeType() != TopAbs_VERTEX )
2276                 continue;
2277
2278               const SMESHDS_SubMesh* vertexSmDS = vertexSM->GetSubMeshDS();
2279               SMDS_NodeIteratorPtr nodeIt = vertexSmDS->GetNodes();
2280               while ( nodeIt->more() )
2281               {
2282                 listOfElemType.push_back( SMDSAbs_Node );
2283                 connectivity.push_back
2284                   ( mapNode2LocalID.insert( make_pair( nodeIt->next(), ++nbConnNodes)).first );
2285               }
2286             }
2287           }
2288         }
2289
2290         // fill node coords and assign local ids to the nodes
2291         int nbNodes = mapNode2LocalID.size();
2292         result->nodesXYZ.length( nbNodes );
2293         TNodeLocalID node2ID = mapNode2LocalID.begin();
2294         for ( i = 0; i < nbNodes; ++i, ++node2ID ) {
2295           node2ID->second = i;
2296           const SMDS_MeshNode* node = (const SMDS_MeshNode*) node2ID->first;
2297           result->nodesXYZ[i].x = node->X();
2298           result->nodesXYZ[i].y = node->Y();
2299           result->nodesXYZ[i].z = node->Z();
2300         }
2301         // fill connectivity
2302         result->elementConnectivities.length( nbConnNodes );
2303         list< TNodeLocalID >::iterator connIt = connectivity.begin();
2304         for ( i = 0; i < nbConnNodes; ++i, ++connIt ) {
2305           result->elementConnectivities[i] = (*connIt)->second;
2306         }
2307
2308         // fill element types
2309         result->elementTypes.length( listOfElemType.size() );
2310         std::list< SMDSAbs_ElementType >::const_iterator typeIt = listOfElemType.begin();
2311         std::list< SMDSAbs_ElementType >::const_iterator typeEnd = listOfElemType.end();
2312         for ( i = 0; typeIt != typeEnd; ++i, ++typeIt )
2313         {
2314           SMDSAbs_ElementType elemType = *typeIt;
2315           result->elementTypes[i].SMDS_ElementType = (SMESH::ElementType)elemType;
2316           result->elementTypes[i].isPoly           = false;
2317           result->elementTypes[i].nbNodesInElement = elemType == SMDSAbs_Edge ? 2 : 1;
2318         }
2319
2320         // correct number of shapes
2321         theShapesId.length( mapOfShIdNb.size() );
2322       }
2323     }
2324   }
2325   catch ( std::bad_alloc& ) {
2326     INFOS( "Precompute(): lack of memory" );
2327   }
2328   catch ( SALOME_Exception& S_ex ) {
2329     INFOS( "Precompute(): catch exception "<< S_ex.what() );
2330   }
2331   catch ( ... ) {
2332     INFOS( "Precompute(): unknown exception " );
2333   }
2334   return result._retn();
2335 }
2336
2337
2338 //=============================================================================
2339 /*!
2340  *  SMESH_Gen_i::Evaluate
2341  *
2342  *  Evaluate mesh on a shape
2343  */
2344 //=============================================================================
2345
2346 SMESH::smIdType_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
2347                                              GEOM::GEOM_Object_ptr theShapeObject)
2348 {
2349   Unexpect aCatch(SALOME_SalomeException);
2350   MESSAGE( "SMESH_Gen_i::Evaluate" );
2351
2352   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
2353     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM );
2354
2355   if ( CORBA::is_nil( theMesh ) )
2356     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", SALOME::BAD_PARAM );
2357
2358   SMESH::smIdType_array_var nbels = new SMESH::smIdType_array;
2359   nbels->length(SMESH::Entity_Last);
2360   int i = SMESH::Entity_Node;
2361   for (; i < SMESH::Entity_Last; i++)
2362     nbels[i] = 0;
2363
2364   // Update Python script
2365   TPythonDump(this) << "theNbElems = " << this << ".Evaluate( "
2366                 << theMesh << ", " << theShapeObject << ")";
2367
2368   try {
2369     // get mesh servant
2370     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
2371     ASSERT( meshServant );
2372     if ( meshServant ) {
2373       meshServant->Load();
2374       // NPAL16168: "geometrical group edition from a submesh don't modify mesh computation"
2375       meshServant->CheckGeomModif();
2376       // get local TopoDS_Shape
2377       TopoDS_Shape myLocShape;
2378       if(theMesh->HasShapeToMesh())
2379         myLocShape = GeomObjectToShape( theShapeObject );
2380       else
2381         myLocShape = SMESH_Mesh::PseudoShape();
2382       // call implementation compute
2383       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
2384       MapShapeNbElems aResMap;
2385       /*CORBA::Boolean ret =*/ myGen.Evaluate( myLocMesh, myLocShape, aResMap);
2386       MapShapeNbElemsItr anIt = aResMap.begin();
2387       for(; anIt!=aResMap.end(); anIt++) {
2388         const vector<smIdType>& aVec = (*anIt).second;
2389         for ( i = SMESH::Entity_Node; i < (int)aVec.size(); i++ ) {
2390           smIdType nbElem = aVec[i];
2391           if ( nbElem < 0 ) // algo failed, check that it has reported a message
2392           {
2393             SMESH_subMesh*            sm = anIt->first;
2394             SMESH_ComputeErrorPtr& error = sm->GetComputeError();
2395             const SMESH_Algo*       algo = sm->GetAlgo();
2396             if ( (algo && !error.get()) || error->IsOK() )
2397               error.reset( new SMESH_ComputeError( COMPERR_ALGO_FAILED,"Failed to evaluate",algo));
2398           }
2399           else
2400           {
2401             nbels[i] += aVec[i];
2402           }
2403         }
2404       }
2405       return nbels._retn();
2406     }
2407   }
2408   catch ( std::bad_alloc& ) {
2409     INFOS( "Evaluate(): lack of memory" );
2410   }
2411   catch ( SALOME_Exception& S_ex ) {
2412     INFOS( "Evaluate(): catch exception "<< S_ex.what() );
2413   }
2414   catch ( ... ) {
2415     INFOS( "Evaluate(): unknown exception " );
2416   }
2417
2418   return nbels._retn();
2419 }
2420
2421 //================================================================================
2422 /*!
2423  * \brief Return geometrical object the given element is built on
2424  *  \param theMesh - the mesh the element is in
2425  *  \param theElementID - the element ID
2426  *  \param theGeomName - the name of the result geom object if it is not yet published
2427  *  \retval GEOM::GEOM_Object_ptr - the found or just published geom object (no need to UnRegister())
2428  */
2429 //================================================================================
2430
2431 GEOM::GEOM_Object_ptr
2432 SMESH_Gen_i::GetGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
2433                                        SMESH::smIdType        theElementID,
2434                                        const char*            theGeomName)
2435 {
2436   Unexpect aCatch(SALOME_SalomeException);
2437
2438   GEOM::GEOM_Object_wrap geom = FindGeometryByMeshElement(theMesh, theElementID);
2439   if ( !geom->_is_nil() ) {
2440     GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh();
2441     GEOM::GEOM_Gen_var    geomGen   = GetGeomEngine( geom );
2442
2443     // try to find the corresponding SObject
2444     SALOMEDS::SObject_wrap SObj = ObjectToSObject( geom.in() );
2445     if ( SObj->_is_nil() ) // submesh can be not found even if published
2446     {
2447       // try to find published submesh
2448       GEOM::ListOfLong_var list = geom->GetSubShapeIndices();
2449       if ( !geom->IsMainShape() && list->length() == 1 ) {
2450         SALOMEDS::SObject_wrap mainSO = ObjectToSObject( mainShape );
2451         SALOMEDS::ChildIterator_wrap it;
2452         if ( !mainSO->_is_nil() ) {
2453           it = getStudyServant()->NewChildIterator( mainSO );
2454         }
2455         if ( !it->_is_nil() ) {
2456           for ( it->InitEx(true); it->More(); it->Next() ) {
2457             SALOMEDS::SObject_wrap      so = it->Value();
2458             CORBA::Object_var         obj = SObjectToObject( so );
2459             GEOM::GEOM_Object_var subGeom = GEOM::GEOM_Object::_narrow( obj );
2460             if ( !subGeom->_is_nil() ) {
2461               GEOM::ListOfLong_var subList = subGeom->GetSubShapeIndices();
2462               if ( subList->length() == 1 && list[0] == subList[0] ) {
2463                 SObj = so;
2464                 geom = subGeom;
2465                 break;
2466               }
2467             }
2468           }
2469         }
2470       }
2471     }
2472     if ( SObj->_is_nil() && !geomGen->_is_nil() ) // publish a new subshape
2473       SObj = geomGen->AddInStudy( geom, theGeomName, mainShape );
2474
2475     // return only published geometry
2476     if ( !SObj->_is_nil() ) {
2477       //return geom._retn(); -- servant of geom must be UnRegister()ed;
2478       CORBA::Object_var    obj = SObjectToObject( SObj );
2479       GEOM::GEOM_Object_var go = GEOM::GEOM_Object::_narrow( obj );
2480       return go._retn();
2481     }
2482   }
2483   return GEOM::GEOM_Object::_nil();
2484 }
2485
2486 //================================================================================
2487 /*!
2488  * \brief Return geometrical object the given element is built on.
2489  *  \param theMesh - the mesh the element is in
2490  *  \param theElementID - the element ID
2491  *  \retval GEOM::GEOM_Object_ptr - the found or created (UnRegister()!) geom object
2492  */
2493 //================================================================================
2494
2495 GEOM::GEOM_Object_ptr
2496 SMESH_Gen_i::FindGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
2497                                         SMESH::smIdType            theElementID)
2498 {
2499   Unexpect aCatch(SALOME_SalomeException);
2500   if ( CORBA::is_nil( theMesh ) )
2501     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", SALOME::BAD_PARAM );
2502
2503   GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh();
2504   GEOM::GEOM_Gen_var    geomGen   = GetGeomEngine( mainShape );
2505
2506   // get a core mesh DS
2507   SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
2508   if ( meshServant && !geomGen->_is_nil() && !mainShape->_is_nil() )
2509   {
2510     ::SMESH_Mesh & mesh = meshServant->GetImpl();
2511     SMESHDS_Mesh* meshDS = mesh.GetMeshDS();
2512     // find the element in mesh
2513     if ( const SMDS_MeshElement * elem = meshDS->FindElement( theElementID ) ) {
2514       // find a shape id by the element
2515       if ( int shapeID = ::SMESH_MeshEditor( &mesh ).FindShape( elem )) {
2516         // get a geom object by the shape id
2517         GEOM::GEOM_Object_var geom = ShapeToGeomObject( meshDS->IndexToShape( shapeID ));
2518         if ( geom->_is_nil() ) {
2519           // try to find a published sub-shape
2520           SALOMEDS::SObject_wrap mainSO = ObjectToSObject( mainShape );
2521           SALOMEDS::ChildIterator_wrap it;
2522           if ( !mainSO->_is_nil() ) {
2523             it = getStudyServant()->NewChildIterator( mainSO );
2524           }
2525           if ( !it->_is_nil() ) {
2526             for ( it->InitEx(true); it->More(); it->Next() ) {
2527               SALOMEDS::SObject_wrap     so = it->Value();
2528               CORBA::Object_var         obj = SObjectToObject( so );
2529               GEOM::GEOM_Object_var subGeom = GEOM::GEOM_Object::_narrow( obj );
2530               if ( !subGeom->_is_nil() ) {
2531                 GEOM::ListOfLong_var subList = subGeom->GetSubShapeIndices();
2532                 if ( subList->length() == 1 && shapeID == subList[0] ) {
2533                   geom = subGeom;
2534                   break;
2535                 }
2536               }
2537             }
2538           }
2539         }
2540         if ( geom->_is_nil() ) {
2541           // explode
2542           GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
2543           if ( !op->_is_nil() )
2544             geom = op->GetSubShape( mainShape, shapeID );
2545         }
2546         else {
2547           geom->Register();
2548         }
2549         if ( !geom->_is_nil() ) {
2550           GeomObjectToShape( geom ); // let geom client remember the found shape
2551           return geom._retn();
2552         }
2553       }
2554     }
2555   }
2556   return GEOM::GEOM_Object::_nil();
2557 }
2558
2559 //================================================================================
2560 /*!
2561  *  SMESH_Gen_i::Concatenate
2562  *
2563  *  Concatenate the given meshes into one mesh
2564  */
2565 //================================================================================
2566
2567 SMESH::SMESH_Mesh_ptr
2568 SMESH_Gen_i::Concatenate(const SMESH::ListOfIDSources& theMeshesArray,
2569                          CORBA::Boolean                theUniteIdenticalGroups,
2570                          CORBA::Boolean                theMergeNodesAndElements,
2571                          CORBA::Double                 theMergeTolerance,
2572                          SMESH::SMESH_Mesh_ptr         theMeshToAppendTo)
2573 {
2574   return ConcatenateCommon(theMeshesArray,
2575                            theUniteIdenticalGroups,
2576                            theMergeNodesAndElements,
2577                            theMergeTolerance,
2578                            false,
2579                            theMeshToAppendTo);
2580 }
2581
2582 //================================================================================
2583 /*!
2584  *  SMESH_Gen_i::ConcatenateWithGroups
2585  *
2586  *  Concatenate the given meshes into one mesh
2587  *  Create the groups of all elements from initial meshes
2588  */
2589 //================================================================================
2590
2591 SMESH::SMESH_Mesh_ptr
2592 SMESH_Gen_i::ConcatenateWithGroups(const SMESH::ListOfIDSources& theMeshesArray,
2593                                    CORBA::Boolean                theUniteIdenticalGroups,
2594                                    CORBA::Boolean                theMergeNodesAndElements,
2595                                    CORBA::Double                 theMergeTolerance,
2596                                    SMESH::SMESH_Mesh_ptr         theMeshToAppendTo)
2597 {
2598   return ConcatenateCommon(theMeshesArray,
2599                            theUniteIdenticalGroups,
2600                            theMergeNodesAndElements,
2601                            theMergeTolerance,
2602                            true,
2603                            theMeshToAppendTo);
2604 }
2605
2606 //================================================================================
2607 /*!
2608  *  SMESH_Gen_i::ConcatenateCommon
2609  *
2610  *  Concatenate the given meshes into one mesh
2611  */
2612 //================================================================================
2613
2614 SMESH::SMESH_Mesh_ptr
2615 SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
2616                                CORBA::Boolean                theUniteIdenticalGroups,
2617                                CORBA::Boolean                theMergeNodesAndElements,
2618                                CORBA::Double                 theMergeTolerance,
2619                                CORBA::Boolean                theCommonGroups,
2620                                SMESH::SMESH_Mesh_ptr         theMeshToAppendTo)
2621 {
2622   std::unique_ptr< TPythonDump > pPythonDump( new TPythonDump(this) );
2623   TPythonDump& pythonDump = *pPythonDump; // prevent dump of called methods
2624
2625   // create mesh if theMeshToAppendTo not provided
2626   SMESH::SMESH_Mesh_var newMesh;
2627   if ( CORBA::is_nil( theMeshToAppendTo ))
2628     newMesh = CreateEmptyMesh();
2629   else
2630     newMesh = SMESH::SMESH_Mesh::_duplicate( theMeshToAppendTo );
2631   SMESH_Mesh_i* newImpl = SMESH::DownCast<SMESH_Mesh_i*>( newMesh );
2632   if ( !newImpl ) return newMesh._retn();
2633   newImpl->Load();
2634
2635   ::SMESH_Mesh&   locMesh = newImpl->GetImpl();
2636   SMESHDS_Mesh* newMeshDS = locMesh.GetMeshDS();
2637
2638   typedef std::list<SMESH::SMESH_Group_var>          TListOfNewGroups;
2639   typedef std::pair<string, SMESH::ElementType >     TNameAndType;
2640   typedef std::map< TNameAndType, TListOfNewGroups > TGroupsMap;
2641   TGroupsMap       groupsMap;
2642   TListOfNewGroups listOfNewGroups;
2643
2644   if ( !CORBA::is_nil( theMeshToAppendTo ))
2645   {
2646     // fill groupsMap with existing groups
2647     SMESH::ListOfGroups_var groups = theMeshToAppendTo->GetGroups();
2648     for ( CORBA::ULong i = 0; i < groups->length(); ++i )
2649     {
2650       SMESH::SMESH_Group_var group = SMESH::SMESH_Group::_narrow( groups[ i ]);
2651       if ( !group->_is_nil() )
2652       {
2653         CORBA::String_var  name = group->GetName();
2654         SMESH::ElementType type = group->GetType();
2655         groupsMap[ TNameAndType( name.in(), type ) ].push_back( group );
2656       }
2657     }
2658   }
2659
2660   ::SMESH_MeshEditor               newEditor( &locMesh );
2661   ::SMESH_MeshEditor::ElemFeatures elemType;
2662
2663   // loop on sub-meshes
2664   for ( CORBA::ULong i = 0; i < theMeshesArray.length(); i++ )
2665   {
2666     if ( CORBA::is_nil( theMeshesArray[i] )) continue;
2667     SMESH::SMESH_Mesh_var initMesh = theMeshesArray[i]->GetMesh();
2668     SMESH_Mesh_i*         initImpl = SMESH::DownCast<SMESH_Mesh_i*>( initMesh );
2669     if ( !initImpl ) continue;
2670     if ( initMesh->_is_equivalent( theMeshToAppendTo ))
2671       continue;
2672     initImpl->Load();
2673
2674     // assure that IDs increment by one during iteration
2675     ::SMESH_Mesh& initLocMesh = initImpl->GetImpl();
2676     SMESHDS_Mesh*  initMeshDS = initLocMesh.GetMeshDS();
2677     if ( initMeshDS->MaxNodeID()    > initMeshDS->NbNodes() ||
2678          initMeshDS->MaxElementID() > initMeshDS->NbElements() )
2679     {
2680       initMeshDS->Modified();
2681       initMeshDS->CompactMesh();
2682     }
2683
2684     // remember nb of elements before filling in
2685     SMESH::smIdType_array_var prevState =  newMesh->GetNbElementsByType();
2686
2687     // copy nodes
2688
2689     std::vector< const SMDS_MeshElement* > newNodes( initMeshDS->NbNodes() + 1, 0 );
2690     SMDS_ElemIteratorPtr elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::NODE );
2691     while ( elemIt->more() )
2692     {
2693       SMESH_NodeXYZ node = elemIt->next();
2694       newNodes[ node->GetID() ] = newMeshDS->AddNode( node.X(), node.Y(), node.Z() );
2695     }
2696
2697     // copy elements
2698
2699     std::vector< const SMDS_MeshElement* > newElems( initMeshDS->NbElements() + 1, 0 );
2700     SMESH::array_of_ElementType_var srcElemTypes = theMeshesArray[i]->GetTypes();
2701     bool hasElems = (( srcElemTypes->length() > 1 ) ||
2702                      ( srcElemTypes->length() == 1 && srcElemTypes[0] != SMESH::NODE ));
2703     if ( hasElems )
2704     {
2705       elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::ALL );
2706       while ( elemIt->more() )
2707       {
2708         const SMDS_MeshElement* elem = elemIt->next();
2709         elemType.myNodes.resize( elem->NbNodes() );
2710
2711         SMDS_NodeIteratorPtr itNodes = elem->nodeIterator();
2712         for ( int k = 0; itNodes->more(); k++)
2713         {
2714           const SMDS_MeshNode* node = itNodes->next();
2715           elemType.myNodes[ k ] = static_cast< const SMDS_MeshNode*> ( newNodes[ node->GetID() ]);
2716         }
2717
2718         // creates a corresponding element on existent nodes in new mesh
2719         newElems[ elem->GetID() ] =
2720           newEditor.AddElement( elemType.myNodes, elemType.Init( elem, /*basicOnly=*/false ));
2721       }
2722       newEditor.ClearLastCreated(); // forget the history
2723     }
2724
2725
2726     // create groups of just added elements
2727     SMESH::SMESH_Group_var newGroup;
2728     SMESH::ElementType     groupType;
2729     if ( theCommonGroups )
2730     {
2731       // type names
2732       const char* typeNames[] = { "All","Nodes","Edges","Faces","Volumes","0DElems","Balls" };
2733
2734       // check of typeNames: compilation failure mains that NB_ELEMENT_TYPES changed:
2735       static_assert( sizeof(typeNames) / sizeof(const char*) ==SMESH::NB_ELEMENT_TYPES,
2736                      "Update names of ElementType's!!!" );
2737
2738       SMESH::smIdType_array_var curState = newMesh->GetNbElementsByType();
2739
2740       for( groupType = SMESH::NODE;
2741            groupType < SMESH::NB_ELEMENT_TYPES;
2742            groupType = (SMESH::ElementType)( groupType + 1 ))
2743       {
2744         if ( curState[ groupType ] <= prevState[ groupType ])
2745           continue; // no elements of groupType added from the i-th mesh
2746
2747         // make a group name
2748         std::string groupName = "Gr";
2749         SALOMEDS::SObject_wrap meshSO = ObjectToSObject( theMeshesArray[i] );
2750         if ( meshSO ) {
2751           CORBA::String_var name = meshSO->GetName();
2752           groupName += name;
2753         }
2754         groupName += "_";
2755         groupName += typeNames[ groupType ];
2756
2757         // make and fill a group
2758         newGroup = newImpl->CreateGroup( groupType, groupName.c_str() );
2759         std::vector< const SMDS_MeshElement* > & elemVec =
2760           ( groupType == SMESH::NODE ) ? newNodes : newElems;
2761         if ( SMESH_Group_i* grp_i = SMESH::DownCast<SMESH_Group_i*>( newGroup ))
2762         {
2763           if ( SMESHDS_Group* grpDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() ))
2764           {
2765             for ( size_t j = 0; j < elemVec.size(); ++j )
2766             {
2767               if ( elemVec[j] && elemVec[j]->GetType() == grpDS->GetType() )
2768                 grpDS->Add( elemVec[j] );
2769             }
2770           }
2771         }
2772         listOfNewGroups.clear();
2773         listOfNewGroups.push_back( newGroup );
2774         groupsMap.insert( std::make_pair( TNameAndType( groupName, groupType ),
2775                                           listOfNewGroups ));
2776       }
2777     }
2778
2779     if ( SMESH_Mesh_i* initImpl = SMESH::DownCast<SMESH_Mesh_i*>( theMeshesArray[i] ))
2780     {
2781       // copy groups
2782
2783       SMESH::SMESH_GroupBase_ptr group;
2784       CORBA::String_var          groupName;
2785       SMESH::smIdType_array_var newIDs = new SMESH::smIdType_array();
2786
2787       // loop on groups of a source mesh
2788       SMESH::ListOfGroups_var listOfGroups = initImpl->GetGroups();
2789       for ( CORBA::ULong iG = 0; iG < listOfGroups->length(); iG++ )
2790       {
2791         group     = listOfGroups[iG];
2792         groupType = group->GetType();
2793         groupName = group->GetName();
2794         std::string name = groupName.in();
2795
2796         // convert a list of IDs
2797         newIDs->length( group->Size() );
2798         std::vector< const SMDS_MeshElement* > & elemVec =
2799           ( groupType == SMESH::NODE ) ? newNodes : newElems;
2800         SMDS_ElemIteratorPtr itGrElems = initImpl->GetElements( group, SMESH::ALL );
2801         int nbElems = 0;
2802         while ( itGrElems->more() )
2803         {
2804           const SMDS_MeshElement*    elem = itGrElems->next();
2805           const SMDS_MeshElement* newElem = elemVec[ elem->GetID() ];
2806           if ( newElem )
2807             newIDs[ nbElems++ ] = newElem->GetID();
2808         }
2809         newIDs->length( nbElems );
2810
2811         // check that a current group name and type don't have identical ones in final mesh
2812         listOfNewGroups.clear();
2813         TNameAndType nameAndType( name, groupType );
2814         TGroupsMap::iterator anIter = groupsMap.find( nameAndType );
2815         if ( anIter == groupsMap.end() )
2816         {
2817           // add a new group in the mesh
2818           newGroup = newImpl->CreateGroup( groupType, groupName.in() );
2819           newGroup->Add( newIDs );
2820
2821           listOfNewGroups.push_back( newGroup );
2822           groupsMap.insert( std::make_pair( nameAndType, listOfNewGroups ));
2823         }
2824         else if ( theUniteIdenticalGroups )
2825         {
2826           // unite identical groups
2827           TListOfNewGroups& aNewGroups = anIter->second;
2828           aNewGroups.front()->Add( newIDs );
2829         }
2830         else
2831         {
2832           // rename identical groups
2833           newGroup = newImpl->CreateGroup( groupType, groupName );
2834           newGroup->Add( newIDs );
2835
2836           TListOfNewGroups& newGroups = anIter->second;
2837           std::string newGroupName;
2838           if ( newGroups.size() == 1 )
2839           {
2840             newGroupName = name + "_1";
2841             newGroups.front()->SetName( newGroupName.c_str() );
2842           }
2843           newGroupName = name + "_" + SMESH_Comment( newGroups.size() + 1 );
2844           newGroup->SetName( newGroupName.c_str() );
2845           newGroups.push_back( newGroup );
2846         }
2847       } // loop on groups
2848     } // if an IDSource is a mesh
2849   } //meshes loop
2850
2851   if ( theMergeNodesAndElements ) // merge nodes
2852   {
2853     TIDSortedNodeSet meshNodes; // no input nodes == treat all
2854     SMESH_MeshEditor::TListOfListOfNodes groupsOfNodes;
2855     newEditor.FindCoincidentNodes( meshNodes, theMergeTolerance, groupsOfNodes,
2856                                    /*SeparateCornersAndMedium=*/ false );
2857     newEditor.MergeNodes( groupsOfNodes );
2858     // merge elements
2859     newEditor.MergeEqualElements();
2860   }
2861
2862   // Update Python script
2863   pythonDump << newMesh << " = " << this
2864              << "." << ( theCommonGroups ? "ConcatenateWithGroups" : "Concatenate" ) << "( "
2865              << theMeshesArray << ", "
2866              << theUniteIdenticalGroups << ", "
2867              << theMergeNodesAndElements << ", "
2868              << TVar( theMergeTolerance ) << ", "
2869              << theMeshToAppendTo << " )";
2870
2871   pPythonDump.reset(); // enable python dump from GetGroups()
2872
2873   // 0020577: EDF 1164 SMESH: Bad dump of concatenate with create common groups
2874   if ( !newMesh->_is_nil() )
2875   {
2876     SMESH::ListOfGroups_var groups = newMesh->GetGroups();
2877   }
2878
2879   // IPAL21468 Change icon of compound because it need not be computed.
2880   SALOMEDS::SObject_wrap meshSO = ObjectToSObject( newMesh );
2881   SetPixMap( meshSO, "ICON_SMESH_TREE_MESH" );
2882
2883   newMeshDS->Modified();
2884
2885   return newMesh._retn();
2886 }
2887
2888
2889 //================================================================================
2890 /*!
2891  * \brief Create a mesh by copying a part of another mesh
2892  *  \param mesh - TetraHedron mesh
2893  *  \param meshName Name of the created mesh
2894  *  \retval SMESH::SMESH_Mesh_ptr - the new mesh
2895  */
2896 //================================================================================
2897
2898 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh,
2899                                                   const char*               meshName,
2900                                                   CORBA::Boolean            adapt_to_shape)
2901 {
2902   Unexpect aCatch(SALOME_SalomeException);
2903
2904   TPythonDump* pyDump = new TPythonDump(this); // prevent dump from CreateMesh()
2905   std::unique_ptr<TPythonDump> pyDumpDeleter( pyDump );
2906
2907   // 1. Get source mesh
2908
2909   if ( CORBA::is_nil( mesh ))
2910     THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM );
2911
2912   SMESH::SMESH_Mesh_var srcMesh = mesh->GetMesh();
2913   SMESH_Mesh_i*       srcMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( srcMesh );
2914   if ( !srcMesh_i )
2915     THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM );
2916
2917   CORBA::String_var mesh_var=GetORB()->object_to_string(mesh);
2918   std::string mesh_ior = mesh_var.in();
2919
2920   //temporary folder for the generation of the med file
2921   fs::path tmp_folder = fs::temp_directory_path() / fs::unique_path(fs::path("dual_mesh-%%%%"));
2922   fs::create_directories(tmp_folder);
2923   fs::path dual_mesh_file = tmp_folder / fs::path("tmp_dual_mesh.med");
2924   std::string mesh_name(meshName);
2925   MESSAGE("Working in folder" + tmp_folder.string());
2926
2927   // Running Python script
2928   assert(Py_IsInitialized());
2929   PyGILState_STATE gstate;
2930   gstate = PyGILState_Ensure();
2931
2932
2933   std::string ats;
2934   if(adapt_to_shape)
2935     ats = "True";
2936   else
2937     ats = "False";
2938
2939   std::string cmd="import salome.smesh.smesh_tools as smt\n";
2940   cmd +="smt.smesh_create_dual_mesh(\"" + mesh_ior + "\", r\"" +
2941         dual_mesh_file.string() + "\", mesh_name=\"" + mesh_name + "\", adapt_to_shape=" + ats + ")";
2942   MESSAGE(cmd);
2943
2944   PyObject *py_main = PyImport_AddModule("__main__");
2945   PyObject *py_dict = PyModule_GetDict(py_main);
2946   PyObject *local_dict = PyDict_New();
2947
2948   PyRun_String(cmd.c_str(), Py_file_input, py_dict, local_dict);
2949
2950   if (PyErr_Occurred()) {
2951     // Restrieving python error
2952     MESSAGE("Catching error");
2953     PyObject *errtype, *errvalue, *traceback;
2954     PyErr_Fetch(&errtype, &errvalue, &traceback);
2955     if(errvalue != NULL) {
2956       MESSAGE("Error has a value");
2957       PyObject *s = PyObject_Str(errvalue);
2958       Py_ssize_t size;
2959       std::string msg = PyUnicode_AsUTF8AndSize(s, &size);
2960       msg = "Issue with the execution of create_dual_mesh:\n"+msg;
2961       MESSAGE("throwing exception");
2962       // We need to deactivate the GIL before throwing the exception
2963       PyGILState_Release(gstate);
2964       THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::INTERNAL_ERROR );
2965       Py_DECREF(s);
2966     }
2967     Py_XDECREF(errvalue);
2968     Py_XDECREF(errtype);
2969     Py_XDECREF(traceback);
2970   }
2971
2972   PyGILState_Release(gstate);
2973
2974   MESSAGE("Mesh created in " + dual_mesh_file.string());
2975
2976   // Import created MED
2977   SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil());
2978   SMESH_Mesh_i*       newMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( newMesh );
2979   if ( !newMesh_i )
2980     THROW_SALOME_CORBA_EXCEPTION( "can't create a mesh", SALOME::INTERNAL_ERROR );
2981   SALOMEDS::SObject_wrap meshSO = ObjectToSObject( newMesh );
2982   if ( !meshSO->_is_nil() )
2983   {
2984     SetName( meshSO, meshName, meshName );
2985     SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
2986   }
2987   int ret = newMesh_i->ImportMEDFile(dual_mesh_file.string().c_str(), meshName);
2988   if(ret)
2989     THROW_SALOME_CORBA_EXCEPTION( "Issue when importing mesh", SALOME::INTERNAL_ERROR );
2990
2991   /*
2992   SMESH_Mesh& newMesh2 = newMesh_i->GetImpl();
2993
2994
2995   MESSAGE("Loading file: " << dual_mesh_file.string() << " with mesh " << meshName);
2996   int ret = newMesh2.MEDToMesh(dual_mesh_file.c_str(), meshName);
2997     */
2998
2999   newMesh_i->GetImpl().GetMeshDS()->Modified();
3000
3001   *pyDump << newMesh << " = " << this
3002           << ".CreateDualMesh("
3003           << mesh << ", "
3004           << "'" << mesh_name << "', "
3005           << ats << ") ";
3006
3007   pyDumpDeleter.reset(); // allow dump in GetGroups()
3008
3009   if ( srcMesh_i->GetImpl().GetGroupIds().size() > 0 ) // dump created groups
3010     MESSAGE("Dump of groups");
3011     SMESH::ListOfGroups_var groups = newMesh->GetGroups();
3012
3013 #ifndef _DEBUG_
3014   fs::remove_all(tmp_folder);
3015 #endif
3016
3017   return newMesh._retn();
3018 }
3019
3020 //================================================================================
3021 /*!
3022  * \brief Create a mesh by copying a part of another mesh
3023  *  \param meshPart - a part of mesh to copy
3024  *  \param toCopyGroups - to create in the new mesh groups
3025  *                        the copied elements belongs to
3026  *  \param toKeepIDs - to preserve IDs of the copied elements or not
3027  *  \retval SMESH::SMESH_Mesh_ptr - the new mesh
3028  */
3029 //================================================================================
3030
3031 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
3032                                             const char*               meshName,
3033                                             CORBA::Boolean            toCopyGroups,
3034                                             CORBA::Boolean            toKeepIDs)
3035 {
3036   Unexpect aCatch(SALOME_SalomeException);
3037
3038   TPythonDump* pyDump = new TPythonDump(this); // prevent dump from CreateMesh()
3039   std::unique_ptr<TPythonDump> pyDumpDeleter( pyDump );
3040
3041   // 1. Get source mesh
3042
3043   if ( CORBA::is_nil( meshPart ))
3044     THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM );
3045
3046   SMESH::SMESH_Mesh_var srcMesh = meshPart->GetMesh();
3047   SMESH_Mesh_i*       srcMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( srcMesh );
3048   if ( !srcMesh_i )
3049     THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM );
3050
3051   SMESHDS_Mesh* srcMeshDS = srcMesh_i->GetImpl().GetMeshDS();
3052
3053   // 2. Make a new mesh
3054
3055   SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil());
3056   SMESH_Mesh_i*       newMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( newMesh );
3057   if ( !newMesh_i )
3058     THROW_SALOME_CORBA_EXCEPTION( "can't create a mesh", SALOME::INTERNAL_ERROR );
3059   SALOMEDS::SObject_wrap meshSO = ObjectToSObject( newMesh );
3060   if ( !meshSO->_is_nil() )
3061   {
3062     SetName( meshSO, meshName, "Mesh" );
3063     SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
3064   }
3065   SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS();
3066   ::SMESH_MeshEditor editor( &newMesh_i->GetImpl() );
3067   ::SMESH_MeshEditor::ElemFeatures elemType;
3068
3069   // 3. Get elements to copy
3070
3071   SMDS_ElemIteratorPtr srcElemIt; SMDS_NodeIteratorPtr srcNodeIt;
3072   TIDSortedElemSet srcElems;
3073   SMESH::array_of_ElementType_var srcElemTypes = meshPart->GetTypes();
3074   if ( SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
3075   {
3076     srcMesh_i->Load();
3077     srcElemIt = srcMeshDS->elementsIterator();
3078     srcNodeIt = srcMeshDS->nodesIterator();
3079   }
3080   else
3081   {
3082     SMESH::smIdType_array_var ids = meshPart->GetIDs();
3083     if ( srcElemTypes->length() == 1 && srcElemTypes[0] == SMESH::NODE ) // group of nodes
3084     {
3085       for ( CORBA::ULong i=0; i < ids->length(); i++ )
3086         if ( const SMDS_MeshElement * elem = srcMeshDS->FindNode( ids[i] ))
3087           srcElems.insert( elem );
3088     }
3089     else
3090     {
3091       for ( CORBA::ULong i = 0; i < ids->length(); i++ )
3092         if ( const SMDS_MeshElement * elem = srcMeshDS->FindElement( ids[i] ))
3093           srcElems.insert( elem );
3094     }
3095     if ( srcElems.empty() )
3096       return newMesh._retn();
3097
3098     typedef SMDS_SetIterator< SMDS_pElement, TIDSortedElemSet::const_iterator > ElIter;
3099     srcElemIt = SMDS_ElemIteratorPtr( new ElIter( srcElems.begin(), srcElems.end() ));
3100   }
3101
3102   // 4. Copy elements
3103
3104   typedef map<SMDS_pElement, SMDS_pElement, TIDCompare> TE2EMap;
3105   TE2EMap e2eMapByType[ SMDSAbs_NbElementTypes ];
3106   TE2EMap& n2nMap = e2eMapByType[ SMDSAbs_Node ];
3107   int iN;
3108   const SMDS_MeshNode *nSrc, *nTgt;
3109   vector< const SMDS_MeshNode* > nodes;
3110   while ( srcElemIt->more() )
3111   {
3112     const SMDS_MeshElement * elem = srcElemIt->next();
3113     // find / add nodes
3114     nodes.resize( elem->NbNodes());
3115     SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
3116     if ( toKeepIDs ) {
3117       for ( iN = 0; nIt->more(); ++iN )
3118       {
3119         nSrc = static_cast<const SMDS_MeshNode*>( nIt->next() );
3120         nTgt = newMeshDS->FindNode( nSrc->GetID());
3121         if ( !nTgt )
3122           nTgt = newMeshDS->AddNodeWithID( nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID());
3123         nodes[ iN ] = nTgt;
3124       }
3125     }
3126     else {
3127       for ( iN = 0; nIt->more(); ++iN )
3128       {
3129         nSrc = static_cast<const SMDS_MeshNode*>( nIt->next() );
3130         TE2EMap::iterator n2n = n2nMap.insert( make_pair( nSrc, SMDS_pNode(0) )).first;
3131         if ( !n2n->second )
3132           n2n->second = newMeshDS->AddNode( nSrc->X(), nSrc->Y(), nSrc->Z() );
3133         nodes[ iN ] = (const SMDS_MeshNode*) n2n->second;
3134       }
3135     }
3136     // add elements
3137     if ( elem->GetType() != SMDSAbs_Node )
3138     {
3139       elemType.Init( elem, /*basicOnly=*/false );
3140       if ( toKeepIDs ) elemType.SetID( elem->GetID() );
3141
3142       const SMDS_MeshElement * newElem = editor.AddElement( nodes, elemType );
3143       if ( toCopyGroups && !toKeepIDs )
3144         e2eMapByType[ elem->GetType() ].insert( make_pair( elem, newElem ));
3145     }
3146   } // while ( srcElemIt->more() )
3147
3148   // 4(b). Copy free nodes
3149
3150   if ( srcNodeIt && srcMeshDS->NbNodes() != newMeshDS->NbNodes() )
3151   {
3152     while ( srcNodeIt->more() )
3153     {
3154       nSrc = srcNodeIt->next();
3155       if ( nSrc->NbInverseElements() == 0 )
3156       {
3157         if ( toKeepIDs )
3158           nTgt = newMeshDS->AddNodeWithID( nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID());
3159         else
3160           n2nMap[ nSrc ] = newMeshDS->AddNode( nSrc->X(), nSrc->Y(), nSrc->Z() );
3161       }
3162     }
3163   }
3164
3165   // 5. Copy groups
3166
3167   int nbNewGroups = 0;
3168   if ( toCopyGroups )
3169   {
3170     SMESH_Mesh::GroupIteratorPtr gIt = srcMesh_i->GetImpl().GetGroups();
3171     while ( gIt->more() )
3172     {
3173       SMESH_Group* group = gIt->next();
3174       const SMESHDS_GroupBase* groupDS = group->GetGroupDS();
3175
3176       // Check group type. We copy nodal groups containing nodes of copied element
3177       SMDSAbs_ElementType groupType = groupDS->GetType();
3178       if ( groupType != SMDSAbs_Node &&
3179            newMeshDS->GetMeshInfo().NbElements( groupType ) == 0 )
3180         continue; // group type differs from types of meshPart
3181
3182       // Find copied elements in the group
3183       vector< const SMDS_MeshElement* > groupElems;
3184       SMDS_ElemIteratorPtr eIt = groupDS->GetElements();
3185       if ( toKeepIDs )
3186       {
3187         const SMDS_MeshElement* foundElem;
3188         if ( groupType == SMDSAbs_Node )
3189         {
3190           while ( eIt->more() )
3191             if (( foundElem = newMeshDS->FindNode( eIt->next()->GetID() )))
3192               groupElems.push_back( foundElem );
3193         }
3194         else
3195         {
3196           while ( eIt->more() )
3197             if (( foundElem = newMeshDS->FindElement( eIt->next()->GetID() )))
3198               groupElems.push_back( foundElem );
3199         }
3200       }
3201       else
3202       {
3203         TE2EMap & e2eMap = e2eMapByType[ groupDS->GetType() ];
3204         if ( e2eMap.empty() ) continue;
3205         smIdType minID = e2eMap.begin()->first->GetID();
3206         smIdType maxID = e2eMap.rbegin()->first->GetID();
3207         TE2EMap::iterator e2e;
3208         while ( eIt->more() && groupElems.size() < e2eMap.size())
3209         {
3210           const SMDS_MeshElement* e = eIt->next();
3211           if ( e->GetID() < minID || e->GetID() > maxID ) continue;
3212           if ((e2e = e2eMap.find( e )) != e2eMap.end())
3213             groupElems.push_back( e2e->second );
3214         }
3215       }
3216       // Make a new group
3217       if ( !groupElems.empty() )
3218       {
3219         SMESH::SMESH_Group_var newGroupObj =
3220           newMesh->CreateGroup( SMESH::ElementType(groupType), group->GetName() );
3221         if ( SMESH_GroupBase_i* newGroup_i = SMESH::DownCast<SMESH_GroupBase_i*>( newGroupObj))
3222         {
3223           SMESHDS_GroupBase * newGroupDS = newGroup_i->GetGroupDS();
3224           SMDS_MeshGroup& smdsGroup = ((SMESHDS_Group*)newGroupDS)->SMDSGroup();
3225           for ( unsigned i = 0; i < groupElems.size(); ++i )
3226             smdsGroup.Add( groupElems[i] );
3227
3228           nbNewGroups++;
3229         }
3230       }
3231     }
3232   }
3233
3234   newMeshDS->Modified();
3235
3236   *pyDump << newMesh << " = " << this
3237           << ".CopyMesh( " << meshPart << ", "
3238           << "'" << meshName << "', "
3239           << toCopyGroups << ", "
3240           << toKeepIDs << ")";
3241
3242   pyDumpDeleter.reset(); // allow dump in GetGroups()
3243
3244   if ( nbNewGroups > 0 ) // dump created groups
3245     SMESH::ListOfGroups_var groups = newMesh->GetGroups();
3246
3247   return newMesh._retn();
3248 }
3249
3250
3251 namespace // utils for CopyMeshWithGeom()
3252 {
3253   typedef std::map< std::string, std::string >             TStr2StrMap;
3254   typedef std::map< std::string, std::set< std::string > > TStr2StrSetMap;
3255   typedef std::map< std::set<int>, int >                   TIdSet2IndexMap;
3256   typedef std::map< std::string, int >                     TName2IndexMap;
3257
3258   //================================================================================
3259   /*!
3260    * \brief Return a new sub-shape corresponding to an old one
3261    */
3262   //================================================================================
3263
3264   struct ShapeMapper
3265   {
3266     SMESH_Mesh_i* mySrcMesh_i;
3267     SMESH_Mesh_i* myNewMesh_i;
3268     SMESH_Gen_i*  myGen_i;
3269     bool          myToPublish;
3270     bool          myIsSameGeom;
3271
3272     TStr2StrMap   myOld2NewEntryMap; // map of study entries
3273
3274     GEOM::ListOfGO_var         mySubshapes; // sub-shapes existing in the new geometry
3275     TIdSet2IndexMap            myIds2SubshapeIndex; // to find an existing sub-shape
3276     TName2IndexMap             myName2SubshapeIndex; // to find an existing sub-shape by name
3277
3278     bool                       myGIPMapDone;
3279     GEOM::ListOfListOfLong_var myGIPMap; // filled by GetInPlaceMap()
3280
3281     // not directly relating to shape search
3282     TStr2StrSetMap myInvalidMap; // blame shape -> invalid objects
3283
3284     //================================================================================
3285     /*!
3286      * \brief Constructor
3287      */
3288     ShapeMapper( SMESH_Mesh_i* srcMesh_i,
3289                  SMESH_Mesh_i* newMesh_i,
3290                  SMESH_Gen_i*  smeshGen_i )
3291       : mySrcMesh_i( srcMesh_i ),
3292         myNewMesh_i( newMesh_i ),
3293         myGen_i    ( smeshGen_i ),
3294         myToPublish( smeshGen_i->IsEnablePublish() ),
3295         myGIPMapDone( false )
3296     {
3297       // retrieve from the study shape mapping made thanks to
3298       // "Set presentation parameters and sub-shapes from arguments" option
3299
3300       GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh();
3301       GEOM::GEOM_Object_var mainShapeOld = mySrcMesh_i->GetShapeToMesh();
3302       SALOMEDS::SObject_wrap oldSO = myGen_i->ObjectToSObject( mainShapeOld );
3303       SALOMEDS::SObject_wrap newSO = myGen_i->ObjectToSObject( mainShapeNew );
3304       if ( newSO->_is_nil() )
3305       {
3306         myToPublish = false;
3307         return;
3308       }
3309       if (( myIsSameGeom = mainShapeNew->_is_equivalent( mainShapeOld )))
3310         return;
3311       CORBA::String_var oldEntry = oldSO->GetID();
3312       CORBA::String_var newEntry = newSO->GetID();
3313       myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ),
3314                                                 std::string( newEntry.in() )));
3315       std::string  newMainEntry = newEntry.in();
3316
3317       SALOMEDS::Study_var            study = myGen_i->getStudyServant();
3318       GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine( mainShapeNew );
3319       GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
3320       mySubshapes                          = op->GetExistingSubObjects( mainShapeNew,
3321                                                                         /*groupsOnly=*/false );
3322       for ( CORBA::ULong i = 0; i < mySubshapes->length(); ++i )
3323       {
3324         newSO = myGen_i->ObjectToSObject( mySubshapes[ i ]);
3325         SALOMEDS::ChildIterator_wrap anIter = study->NewChildIterator( newSO );
3326         bool refFound = false;
3327         for ( ; anIter->More(); anIter->Next() )
3328         {
3329           SALOMEDS::SObject_wrap so = anIter->Value();
3330           if ( so->ReferencedObject( oldSO.inout() ))
3331           {
3332             oldEntry = oldSO->GetID();
3333             newEntry = newSO->GetID();
3334             if (( refFound = ( newMainEntry != oldEntry.in() )))
3335               myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ),
3336                                                         std::string( newEntry.in() )));
3337           }
3338         }
3339         if ( !refFound )
3340         {
3341           GEOM::GEOM_Object_var father = mySubshapes[ i ]->GetMainShape();
3342           if ( father->_is_equivalent( mainShapeNew ))
3343           {
3344             GEOM::ListOfLong_var ids = mySubshapes[ i ]->GetSubShapeIndices();
3345             std::set< int > idSet( &ids[0] , &ids[0] + ids->length() );
3346             myIds2SubshapeIndex.insert( std::make_pair( idSet, i ));
3347             CORBA::String_var name = newSO->GetName();
3348             if ( name.in()[0] )
3349               myName2SubshapeIndex.insert( std::make_pair( name.in(), i ));
3350           }
3351         }
3352       }
3353     }
3354
3355     //================================================================================
3356     /*!
3357      * \brief Find a new sub-shape corresponding to an old one
3358      */
3359     GEOM::GEOM_Object_ptr FindNew( GEOM::GEOM_Object_ptr oldShape )
3360     {
3361       if ( myIsSameGeom )
3362         return GEOM::GEOM_Object::_duplicate( oldShape );
3363
3364       GEOM::GEOM_Object_var newShape;
3365
3366       if ( CORBA::is_nil( oldShape ))
3367         return newShape._retn();
3368
3369       if ( !isChildOfOld( oldShape ))
3370         return GEOM::GEOM_Object::_duplicate( oldShape ); // shape independent of the old shape
3371
3372       GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh();
3373       GEOM::GEOM_Gen_var         geomGen = myGen_i->GetGeomEngine( mainShapeNew );
3374
3375       // try to find by entry or name
3376       if ( myToPublish )
3377       {
3378         CORBA::String_var  oldEntry = oldShape->GetStudyEntry();
3379         TStr2StrMap::iterator o2nID = myOld2NewEntryMap.find( oldEntry.in() );
3380         if ( o2nID != myOld2NewEntryMap.end() )
3381         {
3382           newShape = getShapeByEntry( o2nID->second );
3383         }
3384         if ( newShape->_is_nil() )
3385         {
3386           CORBA::String_var name = oldShape->GetName();
3387           TName2IndexMap::iterator n2ind = myName2SubshapeIndex.find( name.in() );
3388           if ( n2ind != myName2SubshapeIndex.end() )
3389           {
3390             newShape = GEOM::GEOM_Object::_duplicate( mySubshapes[ n2ind->second ]);
3391             GEOM::ListOfLong_var oldIndices = oldShape->GetSubShapeIndices();
3392             GEOM::ListOfLong_var newIndices = newShape->GetSubShapeIndices();
3393             if ( oldIndices->length() == 0 ||
3394                  newIndices->length() == 0 ||
3395                  getShapeType( myNewMesh_i, newIndices[0] ) !=
3396                  getShapeType( mySrcMesh_i, oldIndices[0] ))
3397               newShape = GEOM::GEOM_Object::_nil();
3398           }
3399         }
3400       }
3401
3402       if ( newShape->_is_nil() )
3403       {
3404         // try to construct a new sub-shape using myGIPMap
3405         buildGIPMap();
3406         std::vector< int >   newIndices;
3407         GEOM::ListOfLong_var oldIndices = oldShape->GetSubShapeIndices();
3408         for ( CORBA::ULong i = 0; i < oldIndices->length(); ++i )
3409         {
3410           findNewIDs( oldIndices[i], newIndices );
3411         }
3412         if ( newIndices.size() < oldIndices->length() ) // issue #17096
3413         {
3414           newIndices.clear();
3415           newShape = getInPlace( oldShape );
3416         }
3417         if ( !newIndices.empty() && newShape->_is_nil() )
3418         {
3419           // search for a sub-shape with same ids
3420           std::set< int > idSet( newIndices.begin(), newIndices.end() );
3421           TIdSet2IndexMap::iterator ids2ind = myIds2SubshapeIndex.find( idSet );
3422           if ( ids2ind != myIds2SubshapeIndex.end() ) {
3423             newShape = GEOM::GEOM_Object::_duplicate( mySubshapes[ ids2ind->second ]);
3424           }
3425           if ( newShape->_is_nil() )
3426             try
3427             {
3428               // create a new shape
3429               if ( newIndices.size() > 1 || oldShape->GetType() == GEOM_GROUP )
3430               {
3431                 int groupType = getShapeType( myNewMesh_i, newIndices[0] );
3432
3433                 GEOM::GEOM_IGroupOperations_wrap grOp = geomGen->GetIGroupOperations();
3434                 newShape = grOp->CreateGroup( mainShapeNew, groupType );
3435
3436                 GEOM::ListOfLong_var  newIndicesList = new GEOM::ListOfLong();
3437                 newIndicesList->length( newIndices.size() );
3438                 for ( size_t i = 0; i < newIndices.size(); ++i )
3439                   newIndicesList[ i ] = newIndices[ i ];
3440                 grOp->UnionIDs( newShape, newIndicesList );
3441               }
3442               else
3443               {
3444                 GEOM::GEOM_IShapesOperations_wrap shOp = geomGen->GetIShapesOperations();
3445                 newShape = shOp->GetSubShape( mainShapeNew, newIndices[0] );
3446               }
3447             }
3448             catch (...)
3449             {
3450             }
3451         }
3452       }
3453
3454       if ( !newShape->_is_nil() && myToPublish )
3455       {
3456         CORBA::String_var oldEntry, newEntry = newShape->GetStudyEntry();
3457         if ( !newEntry.in() || !newEntry.in()[0] )
3458         {
3459           CORBA::String_var    name = oldShape->GetName();
3460           SALOMEDS::SObject_wrap so = geomGen->AddInStudy( newShape, name, mainShapeNew );
3461           newEntry = newShape->GetStudyEntry();
3462           oldEntry = oldShape->GetStudyEntry();
3463           myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ),
3464                                                     std::string( newEntry.in() )));
3465         }
3466       }
3467
3468       return newShape._retn();
3469     }
3470
3471     //================================================================================
3472     /*!
3473      * \brief Return a study entry of a new shape by study entry of the old one
3474      */
3475     std::string FindNew( const std::string & oldEntry )
3476     {
3477       if ( myIsSameGeom )
3478         return oldEntry;
3479
3480       TStr2StrMap::iterator o2nID = myOld2NewEntryMap.find( oldEntry );
3481       if ( o2nID != myOld2NewEntryMap.end() )
3482         return o2nID->second;
3483
3484       GEOM::GEOM_Object_var oldShape = getShapeByEntry( oldEntry );
3485       if ( oldShape->_is_nil() || !isChildOfOld( oldShape ))
3486         return oldEntry;
3487
3488       GEOM::GEOM_Object_ptr newShape = FindNew( oldShape );
3489       if ( newShape->_is_nil() )
3490         return std::string();
3491
3492       CORBA::String_var newEntry = newShape->GetStudyEntry();
3493       return newEntry.in();
3494     }
3495
3496     //================================================================================
3497     /*!
3498      * \brief Return a sub-shape ID of a new shape by a sub-shape ID of the old one.
3499      *        Return zero if not found or there are more than one new ID
3500      */
3501     int FindNew( int oldID )
3502     {
3503       if ( myIsSameGeom )
3504         return oldID;
3505
3506       buildGIPMap();
3507
3508       int newID = 0;
3509
3510       if ( 0 < oldID && oldID < (int)myGIPMap->length() )
3511       {
3512         if ( myGIPMap[ oldID ].length() == 1 )
3513         {
3514           newID = myGIPMap[ oldID ][ 0 ];
3515         }
3516         else if ( myGIPMap[ oldID ].length() > 1 &&
3517                   getShapeType( mySrcMesh_i, oldID ) == TopAbs_VERTEX )
3518         {
3519           // select a meshed VERTEX
3520           SMESH_subMesh* newSM;
3521           for ( CORBA::ULong i = 0; i < myGIPMap[ oldID ].length() && !newID; ++i )
3522             if (( newSM = myNewMesh_i->GetImpl().GetSubMeshContaining( myGIPMap[ oldID ][ i ] )) &&
3523                 ( !newSM->IsEmpty() ))
3524               newID = myGIPMap[ oldID ][ i ];
3525         }
3526       }
3527       return newID;
3528     }
3529
3530     //================================================================================
3531     /*!
3532      * \brief Return a sub-shape ID of a new shape by an old sub-mesh.
3533      *        Return zero if the old shape is not kept as is in the new shape.
3534      */
3535     int FindNewNotChanged( SMESH_subMesh* oldSM )
3536     {
3537       if ( myIsSameGeom )
3538         return oldSM->GetId();
3539
3540       int newID = FindNew( oldSM->GetId() );
3541       if ( !newID )
3542         return 0;
3543
3544       SMESH_subMesh* newSM = myNewMesh_i->GetImpl().GetSubMeshContaining( newID );
3545       if ( !newSM )
3546         return 0;
3547
3548       // consider a sub-shape as not changed if all its sub-shapes are mapped into
3549       // one new sub-shape of the same type.
3550
3551       if ( oldSM->DependsOn().size() !=
3552            newSM->DependsOn().size() )
3553         return 0;
3554
3555       SMESH_subMeshIteratorPtr srcSMIt = oldSM->getDependsOnIterator( /*includeSelf=*/true );
3556       while ( srcSMIt->more() )
3557       {
3558         oldSM = srcSMIt->next();
3559         int newSubID = FindNew( oldSM->GetId() );
3560         if ( getShapeType( myNewMesh_i, newSubID ) !=
3561              getShapeType( mySrcMesh_i, oldSM->GetId() ))
3562           return 0;
3563       }
3564       return newID;
3565     }
3566
3567     //================================================================================
3568     /*!
3569      * \brief Return shape by study entry
3570      */
3571     GEOM::GEOM_Object_ptr getShapeByEntry( const std::string & entry )
3572     {
3573       GEOM::GEOM_Object_var shape;
3574       SALOMEDS::SObject_wrap so = myGen_i->getStudyServant()->FindObjectID( entry.c_str() );
3575       if ( !so->_is_nil() )
3576       {
3577         CORBA::Object_var obj = so->GetObject();
3578         shape = GEOM::GEOM_Object::_narrow( obj );
3579       }
3580       return shape._retn();
3581     }
3582
3583     //================================================================================
3584     /*!
3585      * \brief Fill myGIPMap by calling GetInPlaceMap()
3586      */
3587     void buildGIPMap()
3588     {
3589       if ( !myGIPMapDone )
3590       {
3591         myGIPMapDone = true;
3592
3593         GEOM::GEOM_Object_var   mainShapeNew = myNewMesh_i->GetShapeToMesh();
3594         GEOM::GEOM_Object_var   mainShapeOld = mySrcMesh_i->GetShapeToMesh();
3595         GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine( mainShapeNew );
3596         GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
3597         try
3598         {
3599           myGIPMap = op->GetInPlaceMap( mainShapeNew, mainShapeOld );
3600         }
3601         catch( ... )
3602         {
3603           myGIPMap = new GEOM::ListOfListOfLong();
3604         }
3605       }
3606     }
3607
3608     //================================================================================
3609     /*!
3610      * \brief Get new sub-shape by calling GetInPlace()
3611      */
3612     GEOM::GEOM_Object_ptr getInPlace( GEOM::GEOM_Object_ptr oldShape )
3613     {
3614       GEOM::GEOM_Object_var newShape;
3615
3616       GEOM::GEOM_Object_var   mainShapeNew = myNewMesh_i->GetShapeToMesh();
3617       GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine( mainShapeNew );
3618       GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
3619       try
3620       {
3621         newShape = op->GetInPlace( mainShapeNew, oldShape );
3622       }
3623       catch( ... )
3624       {
3625       }
3626       return newShape._retn();
3627     }
3628
3629     //================================================================================
3630     /*!
3631      * \brief Find a new sub-shape indices by an old one in myGIPMap. Return
3632      *        number of found IDs
3633      */
3634     int findNewIDs( int oldID, std::vector< int >& newIDs  )
3635     {
3636       size_t prevNbIDs = newIDs.size();
3637
3638       if ( 0 < oldID && oldID < (int) myGIPMap->length() )
3639       {
3640         for ( CORBA::ULong i = 0; i < myGIPMap[ oldID ].length(); ++i )
3641           newIDs.push_back( myGIPMap[ oldID ][ i ]);
3642       }
3643       return newIDs.size() - prevNbIDs;
3644     }
3645
3646     //================================================================================
3647     /*!
3648      * \brief Check if an object relates to the old shape
3649      */
3650     bool isChildOfOld( GEOM::GEOM_Object_ptr oldShape )
3651     {
3652       if ( CORBA::is_nil( oldShape ))
3653         return false;
3654       GEOM::GEOM_Object_var mainShapeOld1 = mySrcMesh_i->GetShapeToMesh();
3655       GEOM::GEOM_Object_var mainShapeOld2 = oldShape->GetMainShape();
3656       return ( mainShapeOld1->_is_equivalent( mainShapeOld2 ) ||
3657                mainShapeOld1->_is_equivalent( oldShape ));
3658     }
3659
3660     //================================================================================
3661     /*!
3662      * \brief Return shape type by shape ID
3663      */
3664     TopAbs_ShapeEnum getShapeType( SMESH_Mesh_i* mesh_i, int shapeID )
3665     {
3666       SMESHDS_Mesh* meshDS = mesh_i->GetImpl().GetMeshDS();
3667       const TopoDS_Shape& shape = meshDS->IndexToShape( shapeID );
3668       return shape.IsNull() ? TopAbs_SHAPE : shape.ShapeType();
3669     }
3670
3671     //================================================================================
3672     /*!
3673      * \brief Store a source sub-shape for which a counterpart not found and
3674      *        a smesh object invalid due to that
3675      */
3676     void AddInvalid( GEOM::GEOM_Object_var  srcShape,
3677                      SALOMEDS::SObject_wrap smeshSO )
3678     {
3679       CORBA::String_var geomEntry = srcShape->GetStudyEntry();
3680       if ( geomEntry.in()[0] && !smeshSO->_is_nil() )
3681       {
3682         CORBA::String_var smeshEntry = smeshSO->GetID();
3683         myInvalidMap[ geomEntry.in() ].insert( smeshEntry.in() );
3684       }
3685     }
3686
3687     //================================================================================
3688     /*!
3689      * \brief Store a source sub-shape for which a counterpart not found and
3690      *        a smesh object invalid due to that
3691      */
3692     void AddInvalid( std::string            geomEntry,
3693                      SALOMEDS::SObject_wrap smeshSO )
3694     {
3695       if ( !geomEntry.empty() )
3696       {
3697         CORBA::String_var smeshEntry = smeshSO->GetID();
3698         myInvalidMap[ geomEntry ].insert( smeshEntry.in() );
3699       }
3700     }
3701
3702     //================================================================================
3703     /*!
3704      * \brief Store a source sub-shape for which a counterpart not found and
3705      *        a smesh object invalid due to that
3706      */
3707     void AddInvalid( int                    oldGeomID,
3708                      SALOMEDS::SObject_wrap smeshSO )
3709     {
3710       int shapeType = getShapeType( mySrcMesh_i, oldGeomID );
3711       if ( shapeType < 0 || shapeType > TopAbs_SHAPE )
3712         return;
3713
3714       const char* typeName[] = { "COMPOUND","COMPSOLID","SOLID","SHELL",
3715                                  "FACE","WIRE","EDGE","VERTEX","SHAPE" };
3716
3717       SMESH_Comment geomName( typeName[ shapeType ]);
3718       geomName << " #" << oldGeomID;
3719
3720       CORBA::String_var smeshEntry = smeshSO->GetID();
3721       myInvalidMap[ geomName ].insert( smeshEntry.in() );
3722     }
3723
3724     //================================================================================
3725     /*!
3726      * \brief Return entries of a source sub-shape for which a counterpart not found and
3727      *        of smesh objects invalid due to that
3728      */
3729     void GetInvalid( SMESH::string_array_out &               theInvalidEntries,
3730                      std::vector< SALOMEDS::SObject_wrap > & theInvalidMeshSObjects)
3731     {
3732       int nbSO = 0;
3733       TStr2StrSetMap::iterator entry2entrySet = myInvalidMap.begin();
3734       for ( ; entry2entrySet != myInvalidMap.end(); ++entry2entrySet )
3735       {
3736         nbSO += 1 + entry2entrySet->second.size();
3737       }
3738       int iSO = theInvalidMeshSObjects.size(), iEntry = 0;
3739       theInvalidEntries->length  ( nbSO );
3740       theInvalidMeshSObjects.resize( theInvalidMeshSObjects.size() + nbSO - myInvalidMap.size() );
3741
3742       entry2entrySet = myInvalidMap.begin();
3743       for ( ; entry2entrySet != myInvalidMap.end(); ++entry2entrySet )
3744       {
3745         theInvalidEntries[ iEntry++ ] = entry2entrySet->first.c_str();
3746
3747         std::set< std::string > & entrySet = entry2entrySet->second;
3748         std::set< std::string >::iterator entry = entrySet.begin();
3749         for ( ; entry != entrySet.end(); ++entry )
3750         {
3751           theInvalidEntries[ iEntry++ ] = entry->c_str();
3752
3753           SALOMEDS::SObject_wrap so = myGen_i->getStudyServant()->FindObjectID( entry->c_str() );
3754           if ( !so->_is_nil() )
3755             theInvalidMeshSObjects[ iSO++ ] = so;
3756         }
3757       }
3758     }
3759
3760   }; // struct ShapeMapper
3761
3762   //================================================================================
3763   /*!
3764    * \brief Append an item to a CORBA sequence
3765    */
3766   template < class CORBA_seq, class ITEM >
3767   void append( CORBA_seq& seq, ITEM item )
3768   {
3769     if ( !CORBA::is_nil( item ))
3770     {
3771       seq->length( 1 + seq->length() );
3772       seq[ seq->length() - 1 ] = item;
3773     }
3774   }
3775 } // namespace // utils for CopyMeshWithGeom()
3776
3777 //================================================================================
3778 /*!
3779  * \brief Create a mesh by copying definitions of another mesh to a given geometry
3780  *  \param [in] sourceMesh - a mesh to copy
3781  *  \param [in] newGeometry - a new geometry
3782  *  \param [in] toCopyGroups - to create groups in the new mesh
3783  *  \param [in] toReuseHypotheses - if True, existing hypothesis will be used by the new mesh,
3784  *         otherwise new hypotheses with the same parameters will be created for the new mesh.
3785  *  \param [in] toCopyElements - to copy mesh elements of same sub-shapes of the two geometries
3786  *  \param [out] newMesh - return a new mesh
3787  *  \param [out] newGroups - return new groups
3788  *  \param [out] newSubmeshes - return new sub-meshes
3789  *  \param [out] newHypotheses - return new algorithms and hypotheses
3790  *  \param [out] invalidEntries - return study entries of objects whose
3791  *         counterparts are not found in the newGeometry, followed by entries
3792  *         of mesh sub-objects that are invalid because they depend on a not found
3793  *         preceding sub-shape
3794  *  \return CORBA::Boolean - is a success
3795  */
3796 //================================================================================
3797
3798 CORBA::Boolean SMESH_Gen_i::CopyMeshWithGeom( SMESH::SMESH_Mesh_ptr       theSourceMesh,
3799                                               GEOM::GEOM_Object_ptr       theNewGeometry,
3800                                               const char*                 theMeshName,
3801                                               CORBA::Boolean              theToCopyGroups,
3802                                               CORBA::Boolean              theToReuseHypotheses,
3803                                               CORBA::Boolean              theToCopyElements,
3804                                               SMESH::SMESH_Mesh_out       theNewMesh,
3805                                               SMESH::ListOfGroups_out     theNewGroups,
3806                                               SMESH::submesh_array_out    theNewSubmeshes,
3807                                               SMESH::ListOfHypothesis_out theNewHypotheses,
3808                                               SMESH::string_array_out     theInvalidEntries)
3809 {
3810   if ( CORBA::is_nil( theSourceMesh ) ||
3811        CORBA::is_nil( theNewGeometry ))
3812     THROW_SALOME_CORBA_EXCEPTION( "NULL arguments", SALOME::BAD_PARAM );
3813
3814   if ( !theSourceMesh->HasShapeToMesh() )
3815     THROW_SALOME_CORBA_EXCEPTION( "Source mesh not on geometry", SALOME::BAD_PARAM );
3816
3817   bool ok = true;
3818   SMESH_TRY;
3819
3820   TPythonDump pyDump(this); // prevent dump from CreateMesh()
3821
3822   theNewMesh        = CreateMesh( theNewGeometry );
3823   theNewGroups      = new SMESH::ListOfGroups();
3824   theNewSubmeshes   = new SMESH::submesh_array();
3825   theNewHypotheses  = new SMESH::ListOfHypothesis();
3826   theInvalidEntries = new SMESH::string_array();
3827
3828   std::vector< SALOMEDS::SObject_wrap > invalidSObjects;
3829
3830   GEOM::GEOM_Object_var srcGeom = theSourceMesh->GetShapeToMesh();
3831   GEOM::GEOM_Object_var geom, newGeom;
3832   SALOMEDS::SObject_wrap so;
3833
3834   SMESH_Mesh_i* srcMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( theSourceMesh );
3835   SMESH_Mesh_i* newMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( theNewMesh );
3836   srcMesh_i->Load();
3837
3838   ShapeMapper shapeMapper( srcMesh_i, newMesh_i, this );
3839
3840   // treat hypotheses of mesh and sub-meshes
3841   SMESH::submesh_array_var smList = theSourceMesh->GetSubMeshes();
3842   for ( CORBA::ULong iSM = 0; iSM <= smList->length(); ++iSM )
3843   {
3844     bool isSubMesh = ( iSM < smList->length() );
3845     if ( isSubMesh )
3846     {
3847       // create a new sub-mesh
3848       SMESH::SMESH_subMesh_var newSM;
3849       geom = smList[iSM]->GetSubShape();
3850       so   = ObjectToSObject( smList[iSM] );
3851       CORBA::String_var name;
3852       if ( !so->_is_nil() )
3853         name = so->GetName();
3854       newGeom = shapeMapper.FindNew( geom );
3855       if ( newGeom->_is_nil() )
3856       {
3857         newSM = createInvalidSubMesh( theNewMesh, geom, name.in() );
3858         shapeMapper.AddInvalid( geom, ObjectToSObject( newSM ));
3859         ok = false;
3860       }
3861       else
3862       {
3863         newSM = theNewMesh->GetSubMesh( newGeom, name.in() );
3864       }
3865       append( theNewSubmeshes, newSM );
3866
3867       if ( newGeom->_is_nil() )
3868         continue; // don't assign hypotheses
3869     }
3870     else
3871     {
3872       newGeom = GEOM::GEOM_Object::_duplicate( theNewGeometry );
3873       geom    = srcGeom;
3874       so      = ObjectToSObject( theNewMesh );
3875       SetName( so, theMeshName, "Mesh" );
3876     }
3877
3878     // assign hypotheses
3879     SMESH::ListOfHypothesis_var hypList = theSourceMesh->GetHypothesisList( geom );
3880     for ( CORBA::ULong iHyp = 0; iHyp < hypList->length(); ++iHyp )
3881     {
3882       SMESH::SMESH_Hypothesis_var hyp = hypList[ iHyp ];
3883       SMESH_Hypothesis_i*       hyp_i = SMESH::DownCast< SMESH_Hypothesis_i* >( hyp );
3884
3885       // get geometry hyp depends on
3886       std::vector< std::string > entryArray;
3887       std::vector< int >         subIDArray;
3888       bool dependsOnGeom = hyp_i->getObjectsDependOn( entryArray, subIDArray );
3889
3890       if ( !theToReuseHypotheses || dependsOnGeom )
3891       {
3892         // create a new hypothesis
3893         CORBA::String_var type = hyp->GetName();
3894         CORBA::String_var lib  = hyp->GetLibName();
3895         CORBA::String_var data = hyp_i->SaveTo();
3896         if ( data.in()[0] )
3897         {
3898           hyp   = CreateHypothesis( type, lib );
3899           hyp_i = SMESH::DownCast< SMESH_Hypothesis_i* >( hyp );
3900           hyp_i->LoadFrom( data.in() );
3901           append( theNewHypotheses, hyp );
3902         }
3903       }
3904
3905       // update geometry hyp depends on
3906       if ( dependsOnGeom )
3907       {
3908         for ( size_t iGeo = 0; iGeo < entryArray.size(); ++iGeo )
3909         {
3910           if ( !entryArray[ iGeo ].empty() )
3911           {
3912             std::string newEntry = shapeMapper.FindNew( entryArray[ iGeo ]);
3913             if ( newEntry.empty() )
3914             {
3915               ok = false;
3916               shapeMapper.AddInvalid( entryArray[ iGeo ], ObjectToSObject( hyp ));
3917               shapeMapper.AddInvalid( entryArray[ iGeo ], so ); // sub-mesh
3918             }
3919             entryArray[ iGeo ] = newEntry;
3920           }
3921         }
3922         for ( size_t iGeo = 0; iGeo < subIDArray.size(); ++iGeo )
3923         {
3924           if ( subIDArray[ iGeo ] > 0 )
3925           {
3926             int newID = shapeMapper.FindNew( subIDArray[ iGeo ]);
3927             if ( newID < 1 )
3928             {
3929               ok = false;
3930               shapeMapper.AddInvalid( subIDArray[ iGeo ], ObjectToSObject( hyp ));
3931               shapeMapper.AddInvalid( subIDArray[ iGeo ], so ); // sub-mesh
3932             }
3933             subIDArray[ iGeo ] = newID;
3934           }
3935         }
3936         if ( !hyp_i->setObjectsDependOn( entryArray, subIDArray ))
3937           ok = false;
3938       }
3939
3940       CORBA::String_var errorText;
3941       theNewMesh->AddHypothesis( newGeom, hyp, errorText.out() );
3942       if ( errorText.in()[0] )
3943         ok = false;
3944
3945     } // loop on hypotheses
3946   } // loop on sub-meshes and mesh
3947
3948
3949   // copy mesh elements, keeping IDs
3950   SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS();
3951   if ( theToCopyElements && theSourceMesh->NbNodes() > 0 )
3952   {
3953     ::SMESH_MeshEditor editor( &newMesh_i->GetImpl() );
3954     ::SMESH_MeshEditor::ElemFeatures elemData;
3955
3956     SMESH_subMesh*         srcMainSM = srcMesh_i->GetImpl().GetSubMeshContaining( 1 );
3957     SMESH_subMeshIteratorPtr srcSMIt = srcMainSM->getDependsOnIterator( /*includeSelf=*/true,
3958                                                                         /*vertexLast=*/false);
3959     while ( srcSMIt->more() )
3960     {
3961       SMESH_subMesh* srcSM = srcSMIt->next();
3962       if ( srcSM->IsEmpty() )
3963         continue; // not yet computed
3964       int newID = shapeMapper.FindNewNotChanged( srcSM );
3965       if ( newID < 1 )
3966         continue;
3967
3968       SMESHDS_SubMesh* srcSMDS = srcSM->GetSubMeshDS();
3969       SMDS_NodeIteratorPtr nIt = srcSMDS->GetNodes();
3970       while ( nIt->more() )
3971       {
3972         SMESH_NodeXYZ node( nIt->next() );
3973         const SMDS_MeshNode* newNode = newMeshDS->AddNodeWithID( node.X(), node.Y(), node.Z(),
3974                                                                  node->GetID() );
3975         const SMDS_PositionPtr pos = node->GetPosition();
3976         const double*           uv = pos->GetParameters();
3977         switch ( pos->GetTypeOfPosition() )
3978         {
3979         case SMDS_TOP_3DSPACE: newMeshDS->SetNodeInVolume( newNode, newID );               break;
3980         case SMDS_TOP_FACE:    newMeshDS->SetNodeOnFace  ( newNode, newID, uv[0], uv[1] ); break;
3981         case SMDS_TOP_EDGE:    newMeshDS->SetNodeOnEdge  ( newNode, newID, uv[0] );        break;
3982         case SMDS_TOP_VERTEX:  newMeshDS->SetNodeOnVertex( newNode, newID );               break;
3983         default: ;
3984         }
3985       }
3986       SMDS_ElemIteratorPtr eIt = srcSMDS->GetElements();
3987       while( eIt->more() )
3988       {
3989         const SMDS_MeshElement* e = eIt->next();
3990         elemData.Init( e, /*basicOnly=*/false );
3991         elemData.SetID( e->GetID() );
3992         elemData.myNodes.resize( e->NbNodes() );
3993         SMDS_NodeIteratorPtr nnIt = e->nodeIterator();
3994         size_t iN;
3995         for ( iN = 0; nnIt->more(); ++iN )
3996         {
3997           const SMDS_MeshNode* srcNode = nnIt->next();
3998           elemData.myNodes[ iN ] = newMeshDS->FindNode( srcNode->GetID() );
3999           if ( !elemData.myNodes[ iN ])
4000             break;
4001         }
4002         if ( iN == elemData.myNodes.size() )
4003           if ( const SMDS_MeshElement * newElem = editor.AddElement( elemData.myNodes, elemData ))
4004             newMeshDS->SetMeshElementOnShape( newElem, newID );
4005       }
4006       if ( SMESH_subMesh* newSM = newMesh_i->GetImpl().GetSubMeshContaining( newID ))
4007         newSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
4008     }
4009
4010     newMeshDS->Modified();
4011   }
4012
4013
4014   // treat groups
4015
4016   TStr2StrMap old2newGroupMap;
4017
4018   SALOME::GenericObj_wrap< SMESH::FilterManager > filterMgr = CreateFilterManager();
4019
4020   SMESH::ListOfGroups_var groups = theSourceMesh->GetGroups();
4021   CORBA::ULong nbGroups = theToCopyGroups ? groups->length() : 0, nbAddedGroups = 0;
4022   for ( CORBA::ULong i = 0; i < nbGroups + nbAddedGroups; ++i )
4023   {
4024     SMESH::SMESH_Group_var         stdlGroup = SMESH::SMESH_Group::_narrow        ( groups[ i ]);
4025     SMESH::SMESH_GroupOnGeom_var   geomGroup = SMESH::SMESH_GroupOnGeom::_narrow  ( groups[ i ]);
4026     SMESH::SMESH_GroupOnFilter_var fltrGroup = SMESH::SMESH_GroupOnFilter::_narrow( groups[ i ]);
4027
4028     CORBA::String_var      name = groups[ i ]->GetName();
4029     SMESH::ElementType elemType = groups[ i ]->GetType();
4030
4031     SMESH::SMESH_GroupBase_var newGroup;
4032
4033     if ( !stdlGroup->_is_nil() )
4034     {
4035       if ( newMeshDS->GetMeshInfo().NbElements( SMDSAbs_ElementType( elemType )) > 0 )
4036       {
4037         SMESH::smIdType_array_var elemIDs = stdlGroup->GetIDs();
4038         const bool isElem = ( elemType != SMESH::NODE );
4039         CORBA::ULong iE = 0;
4040         for ( ; iE < elemIDs->length(); ++iE ) // check if any element has been copied
4041           if ( newMeshDS->GetElementType( elemIDs[ iE ], isElem ) != SMDSAbs_All )
4042             break;
4043         if ( iE < elemIDs->length() )
4044         {
4045           stdlGroup = theNewMesh->CreateGroup( elemType, name );
4046           stdlGroup->Add( elemIDs );
4047           newGroup = SMESH::SMESH_GroupBase::_narrow( stdlGroup );
4048         }
4049       }
4050     }
4051     else if ( !geomGroup->_is_nil() )
4052     {
4053       GEOM::GEOM_Object_var    geom = geomGroup->GetShape();
4054       GEOM::GEOM_Object_var newGeom = shapeMapper.FindNew( geom );
4055       if ( newGeom->_is_nil() )
4056       {
4057         newGroup = theNewMesh->CreateGroup( elemType, name ); // just to notify the user
4058         shapeMapper.AddInvalid( geom, ObjectToSObject( newGroup ));
4059         ok = false;
4060       }
4061       else
4062       {
4063         newGroup = theNewMesh->CreateGroupFromGEOM( elemType, name, newGeom );
4064       }
4065     }
4066     else if ( !fltrGroup->_is_nil() )
4067     {
4068       // replace geometry in a filter
4069       SMESH::Filter_var filter = fltrGroup->GetFilter();
4070       SMESH::Filter::Criteria_var criteria;
4071       filter->GetCriteria( criteria.out() );
4072
4073       bool isMissingGroup = false;
4074       std::vector< std::string > badEntries;
4075
4076       for ( CORBA::ULong iCr = 0; iCr < criteria->length(); ++iCr )
4077       {
4078         const char* thresholdID = criteria[ iCr ].ThresholdID.in();
4079         switch ( criteria[ iCr ].Type )
4080         {
4081         case SMESH::FT_BelongToMeshGroup:
4082         {
4083           SALOME::GenericObj_wrap< SMESH::BelongToMeshGroup > btgg = filterMgr->CreateBelongToMeshGroup();
4084           btgg->SetGroupID( thresholdID );
4085           SMESH::SMESH_GroupBase_ptr refGroup = btgg->GetGroup();
4086           SALOMEDS::SObject_wrap   refGroupSO = ObjectToSObject( refGroup );
4087           if ( refGroupSO->_is_nil() )
4088             break;
4089           CORBA::String_var     refID = refGroupSO->GetID();
4090           TStr2StrMap::iterator o2nID = old2newGroupMap.find( refID.in() );
4091           if ( o2nID == old2newGroupMap.end() )
4092           {
4093             isMissingGroup = true; // corresponding new group not yet created
4094             break;
4095           }
4096           criteria[ iCr ].ThresholdID = o2nID->second.c_str();
4097
4098           if ( o2nID->second.empty() ) // new referred group is invalid
4099             badEntries.push_back( refID.in() );
4100           break;
4101         }
4102         case SMESH::FT_BelongToGeom:
4103         case SMESH::FT_BelongToPlane:
4104         case SMESH::FT_BelongToCylinder:
4105         case SMESH::FT_BelongToGenSurface:
4106         case SMESH::FT_LyingOnGeom:
4107         {
4108           std::string newID = shapeMapper.FindNew( thresholdID );
4109           criteria[ iCr ].ThresholdID = newID.c_str();
4110           if ( newID.empty() )
4111             badEntries.push_back( thresholdID );
4112           break;
4113         }
4114         case SMESH::FT_ConnectedElements:
4115         {
4116           if ( thresholdID && thresholdID[0] )
4117           {
4118             std::string newID = shapeMapper.FindNew( thresholdID );
4119             criteria[ iCr ].ThresholdID = newID.c_str();
4120             if ( newID.empty() )
4121               badEntries.push_back( thresholdID );
4122           }
4123           break;
4124         }
4125         default:;
4126         }
4127       } // loop on criteria
4128
4129       if ( isMissingGroup && i < nbGroups )
4130       {
4131         // to treat the group again
4132         append( groups, SMESH::SMESH_GroupBase::_duplicate( groups[ i ]));
4133         ++nbAddedGroups;
4134         continue;
4135       }
4136       SMESH::Filter_var newFilter = filterMgr->CreateFilter();
4137       newFilter->SetCriteria( criteria );
4138
4139       newGroup = theNewMesh->CreateGroupFromFilter( elemType, name, newFilter );
4140       newFilter->UnRegister();
4141
4142       SALOMEDS::SObject_wrap newSO = ObjectToSObject( newGroup );
4143       for ( size_t iEnt = 0; iEnt < badEntries.size(); ++iEnt )
4144         shapeMapper.AddInvalid( badEntries[ iEnt ], newSO );
4145
4146       if ( isMissingGroup ) // all groups treated but a referred groups still not found
4147       {
4148         invalidSObjects.push_back( ObjectToSObject( newGroup ));
4149         ok = false;
4150       }
4151       if ( !badEntries.empty() )
4152         ok = false;
4153
4154     } // treat a group on filter
4155
4156     append( theNewGroups, newGroup );
4157
4158     // fill old2newGroupMap
4159     SALOMEDS::SObject_wrap srcSO = ObjectToSObject( groups[i] );
4160     SALOMEDS::SObject_wrap newSO = ObjectToSObject( newGroup );
4161     if ( !srcSO->_is_nil() )
4162     {
4163       CORBA::String_var srcID, newID("");
4164       srcID = srcSO->GetID();
4165       if ( !newSO->_is_nil() )
4166         newID = newSO->GetID();
4167       old2newGroupMap.insert( std::make_pair( std::string( srcID.in() ),
4168                                               std::string( newID.in() )));
4169     }
4170
4171     if ( newGroup->_is_nil() )
4172       ok = false;
4173
4174   } // loop on groups
4175
4176   newMeshDS->CompactMesh();
4177
4178   // set mesh name
4179   if ( !theMeshName || !theMeshName[0] )
4180   {
4181     SALOMEDS::SObject_wrap soNew = ObjectToSObject( theNewMesh );
4182     SALOMEDS::SObject_wrap soOld = ObjectToSObject( theSourceMesh );
4183     CORBA::String_var oldName = soOld->GetName();
4184     SetName( soNew, oldName.in(), "Mesh" );
4185   }
4186   // mark invalid objects
4187   shapeMapper.GetInvalid( theInvalidEntries, invalidSObjects );
4188
4189   for ( size_t i = 0; i < invalidSObjects.size(); ++i )
4190     highLightInvalid( invalidSObjects[i].in(), true );
4191
4192   pyDump << "ok, "
4193          << theNewMesh << ", "
4194          << theNewGroups << ", "
4195          << *theNewSubmeshes.ptr() << ", "
4196          << *theNewHypotheses.ptr() << ", "
4197          << "invalidEntries = " << this << ".CopyMeshWithGeom( "
4198          << theSourceMesh << ", "
4199          << theNewGeometry << ", "
4200          << "'" << theMeshName << "', "
4201          << theToCopyGroups << ", "
4202          << theToReuseHypotheses << ", "
4203          << theToCopyElements << " )";
4204
4205   SMESH_CATCH( SMESH::throwCorbaException );
4206
4207   return ok;
4208 }
4209
4210 //================================================================================
4211 /*!
4212  * \brief Get version of MED format being used.
4213  */
4214 //================================================================================
4215
4216 char* SMESH_Gen_i::GetMEDFileVersion()
4217 {
4218   MED::TInt majeur, mineur, release;
4219   majeur =  mineur = release = 0;
4220   MED::GetVersionRelease(majeur, mineur, release);
4221   std::ostringstream version;
4222   version << majeur << "." << mineur << "." << release;
4223   return CORBA::string_dup( version.str().c_str() );
4224 }
4225
4226 //================================================================================
4227 /*!
4228  *  SMESH_Gen_i::GetMEDVersion
4229  *
4230  *  Get MED version of the file by its name
4231  */
4232 //================================================================================
4233
4234 char* SMESH_Gen_i::GetMEDVersion(const char* theFileName)
4235 {
4236   std::string version = MED::GetMEDVersion( theFileName );
4237   return CORBA::string_dup( version.c_str() );
4238 }
4239
4240 //================================================================================
4241 /*!
4242  *  SMESH_Gen_i::CheckCompatibility
4243  *
4244  *  Check compatibility of file with MED format being used, read only.
4245  */
4246 //================================================================================
4247
4248 CORBA::Boolean SMESH_Gen_i::CheckCompatibility(const char* theFileName)
4249 {
4250   return MED::CheckCompatibility( theFileName );
4251 }
4252
4253 //================================================================================
4254 /*!
4255  *  SMESH_Gen_i::CheckWriteCompatibility
4256  *
4257  *  Check compatibility of file with MED format being used, for append on write.
4258  */
4259 //================================================================================
4260
4261 CORBA::Boolean SMESH_Gen_i::CheckWriteCompatibility(const char* theFileName)
4262 {
4263   return MED::CheckCompatibility( theFileName, true );
4264 }
4265
4266 //================================================================================
4267 /*!
4268  *  SMESH_Gen_i::GetMeshNames
4269  *
4270  *  Get names of meshes defined in file with the specified name
4271  */
4272 //================================================================================
4273 SMESH::string_array* SMESH_Gen_i::GetMeshNames(const char* theFileName)
4274
4275 {
4276   SMESH::string_array_var aResult = new SMESH::string_array();
4277   MED::PWrapper aMed = MED::CrWrapperR( theFileName );
4278   MED::TErr anErr;
4279   MED::TInt aNbMeshes = aMed->GetNbMeshes( &anErr );
4280   if( anErr >= 0 ) {
4281     aResult->length( aNbMeshes );
4282     for( MED::TInt i = 0; i < aNbMeshes; i++ ) {
4283       MED::PMeshInfo aMeshInfo = aMed->GetPMeshInfo( i+1 );
4284       aResult[i] = CORBA::string_dup( aMeshInfo->GetName().c_str() );
4285     }
4286   }
4287   return aResult._retn();
4288 }
4289
4290 //=============================================================================
4291 /*!
4292  *  SMESH_Gen_i::Save
4293  *
4294  *  Save SMESH module's data
4295  */
4296 //=============================================================================
4297
4298 SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
4299                                       const char*              theURL,
4300                                       bool                     isMultiFile )
4301 {
4302   // localizing
4303   Kernel_Utils::Localizer loc;
4304
4305   if (!myStudyContext)
4306     UpdateStudy();
4307
4308   // Store study contents as a set of python commands
4309   SavePython();
4310
4311   SALOMEDS::Study_var aStudy = getStudyServant();
4312
4313   // Declare a byte stream
4314   SALOMEDS::TMPFile_var aStreamFile;
4315
4316   // Obtain a temporary dir
4317   TCollection_AsciiString tmpDir =
4318     ( isMultiFile ) ? TCollection_AsciiString( ( char* )theURL ) : ( char* )SALOMEDS_Tool::GetTmpDir().c_str();
4319
4320   // Create a sequence of files processed
4321   SALOMEDS_Tool::ListOfFiles aFileSeq;
4322   aFileSeq.reserve( NUM_TMP_FILES );
4323
4324   TCollection_AsciiString aStudyName( "" );
4325   if ( isMultiFile )
4326     aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( Kernel_Utils::encode(aStudy->URL()) ).c_str() );
4327
4328   // Set names of temporary files
4329   TCollection_AsciiString filename =
4330     aStudyName + TCollection_AsciiString( "_SMESH.hdf" );        // for SMESH data itself
4331   TCollection_AsciiString meshfile =
4332     aStudyName + TCollection_AsciiString( "_SMESH_Mesh.med" );   // for mesh data to be stored in MED file
4333   aFileSeq.push_back(CORBA::string_dup( filename.ToCString() ));
4334   aFileSeq.push_back(CORBA::string_dup( meshfile.ToCString() ));
4335   filename = tmpDir + filename;
4336   meshfile = tmpDir + meshfile;
4337
4338   HDFfile*    aFile;
4339   HDFdataset* aDataset;
4340   HDFgroup*   aTopGroup;
4341   HDFgroup*   aGroup;
4342   HDFgroup*   aSubGroup;
4343   HDFgroup*   aSubSubGroup;
4344   hdf_size    aSize[ 1 ];
4345
4346
4347   //Remove the files if they exist: BugID: 11225
4348 #ifndef WIN32 /* unix functionality */
4349   TCollection_AsciiString cmd("rm -f \"");
4350 #else /* windows */
4351   TCollection_AsciiString cmd("del /F \"");
4352 #endif
4353
4354   cmd+=filename;
4355   cmd+="\" \"";
4356   cmd+=meshfile;
4357   cmd+="\"";
4358 #ifdef WIN32
4359   cmd+=" 2>NUL";
4360 #endif
4361   system(cmd.ToCString());
4362
4363   // MED writer to be used by storage process
4364   DriverMED_W_SMESHDS_Mesh writer;
4365   writer.SetFile( meshfile.ToCString() );
4366   //writer.SetSaveNumbers( false ); // bos #24400 -- it leads to change of element IDs
4367
4368   // IMP issue 20918
4369   // SetStoreName() to groups before storing hypotheses to let them refer to
4370   // groups using "store name", which is "Group <group_persistent_id>"
4371   {
4372     SALOMEDS::ChildIterator_wrap itBig = aStudy->NewChildIterator( theComponent );
4373     for ( ; itBig->More(); itBig->Next() ) {
4374       SALOMEDS::SObject_wrap gotBranch = itBig->Value();
4375       if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) {
4376         CORBA::Object_var anObject = SObjectToObject( gotBranch );
4377         if ( !CORBA::is_nil( anObject ) ) {
4378           SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ;
4379           if ( !myMesh->_is_nil() ) {
4380             myMesh->Load(); // load from study file if not yet done
4381             TPythonDump pd(this); // not to dump GetGroups()
4382             SMESH::ListOfGroups_var groups = myMesh->GetGroups();
4383             for ( CORBA::ULong i = 0; i < groups->length(); ++i )
4384             {
4385               SMESH_GroupBase_i* grImpl = SMESH::DownCast<SMESH_GroupBase_i*>( groups[i]);
4386               if ( grImpl )
4387               {
4388                 CORBA::String_var objStr = GetORB()->object_to_string( grImpl->_this() );
4389                 int anId = myStudyContext->findId( string( objStr.in() ) );
4390                 char grpName[ 30 ];
4391                 sprintf( grpName, "Group %d %d", anId, grImpl->GetLocalID() );
4392                 SMESHDS_GroupBase* aGrpBaseDS = grImpl->GetGroupDS();
4393                 aGrpBaseDS->SetStoreName( grpName );
4394               }
4395             }
4396           }
4397         }
4398       }
4399     }
4400   }
4401
4402   // Write data
4403   // ---> create HDF file
4404   aFile = new HDFfile( (char*) filename.ToCString() );
4405   aFile->CreateOnDisk();
4406
4407   // --> iterator for top-level objects
4408   SALOMEDS::ChildIterator_wrap itBig = aStudy->NewChildIterator( theComponent );
4409   for ( ; itBig->More(); itBig->Next() ) {
4410     SALOMEDS::SObject_wrap gotBranch = itBig->Value();
4411
4412     // --> hypotheses root branch (only one for the study)
4413     if ( gotBranch->Tag() == GetHypothesisRootTag() ) {
4414       // create hypotheses root HDF group
4415       aTopGroup = new HDFgroup( "Hypotheses", aFile );
4416       aTopGroup->CreateOnDisk();
4417
4418       // iterator for all hypotheses
4419       SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( gotBranch );
4420       for ( ; it->More(); it->Next() ) {
4421         SALOMEDS::SObject_wrap mySObject = it->Value();
4422         CORBA::Object_var anObject = SObjectToObject( mySObject );
4423         if ( !CORBA::is_nil( anObject ) ) {
4424           SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject );
4425           if ( !myHyp->_is_nil() ) {
4426             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
4427             if ( myImpl ) {
4428               CORBA::String_var hn = myHyp->GetName(), ln = myHyp->GetLibName();
4429               std::string hypname = hn.in();
4430               std::string libname = ln.in();
4431               // BUG SWP13062
4432               // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for
4433               // WIN32 and ".so" for X-system) must be deleted
4434               int libname_len = libname.length();
4435 #ifdef WIN32
4436               if( libname_len > 4 )
4437                 libname.resize( libname_len - 4 );
4438 #else
4439               // PAL17753 (Regression: missing hypothesis in restored study)
4440               // "lib" also should be removed from the beginning
4441               if( libname_len > 6 )
4442                 libname = libname.substr( 3, libname_len - 3 - 3 );
4443 #endif
4444               CORBA::String_var  objStr = GetORB()->object_to_string( anObject );
4445               CORBA::String_var hypdata = myImpl->SaveTo();
4446               int                    id = myStudyContext->findId( string( objStr.in() ));
4447
4448               // for each hypothesis create HDF group basing on its id
4449               char hypGrpName[30];
4450               sprintf( hypGrpName, "Hypothesis %d", id );
4451               aGroup = new HDFgroup( hypGrpName, aTopGroup );
4452               aGroup->CreateOnDisk();
4453               // --> type name of hypothesis
4454               aSize[ 0 ] = hypname.length() + 1;
4455               aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 );
4456               aDataset->CreateOnDisk();
4457               aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) );
4458               aDataset->CloseOnDisk();
4459               // --> server plugin library name of hypothesis
4460               aSize[ 0 ] = libname.length() + 1;
4461               aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 );
4462               aDataset->CreateOnDisk();
4463               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
4464               aDataset->CloseOnDisk();
4465               // --> persistent data of hypothesis
4466               aSize[ 0 ] = strlen( hypdata.in() ) + 1;
4467               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
4468               aDataset->CreateOnDisk();
4469               aDataset->WriteOnDisk( ( char* )( hypdata.in() ) );
4470               aDataset->CloseOnDisk();
4471               // close hypothesis HDF group
4472               aGroup->CloseOnDisk();
4473             }
4474           }
4475         }
4476       }
4477       // close hypotheses root HDF group
4478       aTopGroup->CloseOnDisk();
4479     }
4480     // --> algorithms root branch (only one for the study)
4481     else if ( gotBranch->Tag() == GetAlgorithmsRootTag() ) {
4482       // create algorithms root HDF group
4483       aTopGroup = new HDFgroup( "Algorithms", aFile );
4484       aTopGroup->CreateOnDisk();
4485
4486       // iterator for all algorithms
4487       SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( gotBranch );
4488       for ( ; it->More(); it->Next() ) {
4489         SALOMEDS::SObject_wrap mySObject = it->Value();
4490         CORBA::Object_var anObject = SObjectToObject( mySObject );
4491         if ( !CORBA::is_nil( anObject ) ) {
4492           SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject );
4493           if ( !myHyp->_is_nil() ) {
4494             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
4495             if ( myImpl ) {
4496               CORBA::String_var hn = myHyp->GetName(), ln = myHyp->GetLibName();
4497               std::string hypname = hn.in();
4498               std::string libname = ln.in();
4499               // BUG SWP13062
4500               // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for
4501               // WIN32 and ".so" for X-system) must be deleted
4502               int libname_len = libname.length();
4503 #ifdef WIN32
4504               if( libname_len > 4 )
4505                 libname.resize( libname_len - 4 );
4506 #else
4507               // PAL17753 (Regression: missing hypothesis in restored study)
4508               // "lib" also should be removed from the beginning
4509               if( libname_len > 6 )
4510                 libname = libname.substr( 3, libname_len - 3 - 3 );
4511 #endif
4512               CORBA::String_var  objStr = GetORB()->object_to_string( anObject );
4513               CORBA::String_var hypdata = myImpl->SaveTo();
4514               int                    id = myStudyContext->findId( string( objStr.in() ) );
4515
4516               // for each algorithm create HDF group basing on its id
4517               char hypGrpName[30];
4518               sprintf( hypGrpName, "Algorithm %d", id );
4519               aGroup = new HDFgroup( hypGrpName, aTopGroup );
4520               aGroup->CreateOnDisk();
4521               // --> type name of algorithm
4522               aSize[0] = hypname.length() + 1;
4523               aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 );
4524               aDataset->CreateOnDisk();
4525               aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) );
4526               aDataset->CloseOnDisk();
4527               // --> server plugin library name of hypothesis
4528               aSize[0] = libname.length() + 1;
4529               aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 );
4530               aDataset->CreateOnDisk();
4531               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
4532               aDataset->CloseOnDisk();
4533               // --> persistent data of algorithm
4534               aSize[0] = strlen( hypdata.in() ) + 1;
4535               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
4536               aDataset->CreateOnDisk();
4537               aDataset->WriteOnDisk( ( char* )( hypdata.in() ));
4538               aDataset->CloseOnDisk();
4539               // close algorithm HDF group
4540               aGroup->CloseOnDisk();
4541             }
4542           }
4543         }
4544       }
4545       // close algorithms root HDF group
4546       aTopGroup->CloseOnDisk();
4547     }
4548     // --> mesh objects roots branches
4549     else if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) {
4550       CORBA::Object_var anObject = SObjectToObject( gotBranch );
4551       if ( !CORBA::is_nil( anObject ) ) {
4552         SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ;
4553         if ( !myMesh->_is_nil() ) {
4554           SMESH_Mesh_i* myImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( myMesh ).in() );
4555           if ( myImpl ) {
4556             CORBA::String_var objStr = GetORB()->object_to_string( anObject );
4557             int id = myStudyContext->findId( string( objStr.in() ) );
4558             ::SMESH_Mesh& myLocMesh = myImpl->GetImpl();
4559             SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS();
4560             bool hasShape = myLocMesh.HasShapeToMesh();
4561
4562             // for each mesh open the HDF group basing on its id
4563             char meshGrpName[ 30 ];
4564             sprintf( meshGrpName, "Mesh %d", id );
4565             aTopGroup = new HDFgroup( meshGrpName, aFile );
4566             aTopGroup->CreateOnDisk();
4567
4568             // --> put dataset to hdf file which is a flag that mesh has data
4569             string strHasData = "0";
4570             // check if the mesh is not empty
4571             if ( mySMESHDSMesh->NbNodes() > 0 ) {
4572               // write mesh data to med file
4573               writer.SetMesh( mySMESHDSMesh );
4574               writer.SetMeshId( id );
4575               strHasData = "1";
4576             }
4577             aSize[ 0 ] = strHasData.length() + 1;
4578             aDataset = new HDFdataset( "Has data", aTopGroup, HDF_STRING, aSize, 1 );
4579             aDataset->CreateOnDisk();
4580             aDataset->WriteOnDisk( ( char* )( strHasData.c_str() ) );
4581             aDataset->CloseOnDisk();
4582
4583             // ouv : NPAL12872
4584             // for each mesh open the HDF group basing on its auto color parameter
4585             char meshAutoColorName[ 30 ];
4586             sprintf( meshAutoColorName, "AutoColorMesh %d", id );
4587             int anAutoColor[1];
4588             anAutoColor[0] = myImpl->GetAutoColor();
4589             aSize[ 0 ] = 1;
4590             aDataset = new HDFdataset( meshAutoColorName, aTopGroup, HDF_INT32, aSize, 1 );
4591             aDataset->CreateOnDisk();
4592             aDataset->WriteOnDisk( anAutoColor );
4593             aDataset->CloseOnDisk();
4594
4595             // issue 0020693. Store _isModified flag
4596             int isModified = myLocMesh.GetIsModified();
4597             aSize[ 0 ] = 1;
4598             aDataset = new HDFdataset( "_isModified", aTopGroup, HDF_INT32, aSize, 1 );
4599             aDataset->CreateOnDisk();
4600             aDataset->WriteOnDisk( &isModified );
4601             aDataset->CloseOnDisk();
4602
4603             // issue 20918. Store Persistent Id of SMESHDS_Mesh
4604             int meshPersistentId = mySMESHDSMesh->GetPersistentId();
4605             aSize[ 0 ] = 1;
4606             aDataset = new HDFdataset( "meshPersistentId", aTopGroup, HDF_INT32, aSize, 1 );
4607             aDataset->CreateOnDisk();
4608             aDataset->WriteOnDisk( &meshPersistentId );
4609             aDataset->CloseOnDisk();
4610
4611             // Store SMESH_Mesh_i::_mainShapeTick
4612             int shapeTick = myImpl->MainShapeTick();
4613             aSize[ 0 ] = 1;
4614             aDataset = new HDFdataset( "shapeTick", aTopGroup, HDF_INT32, aSize, 1 );
4615             aDataset->CreateOnDisk();
4616             aDataset->WriteOnDisk( &shapeTick );
4617             aDataset->CloseOnDisk();
4618
4619             // write reference on a shape if exists
4620             SALOMEDS::SObject_wrap myRef;
4621             bool shapeRefFound = false;
4622             bool found = gotBranch->FindSubObject( (CORBA::Long)GetRefOnShapeTag(), myRef.inout() );
4623             if ( found ) {
4624               SALOMEDS::SObject_wrap myShape;
4625               bool ok = myRef->ReferencedObject( myShape.inout() );
4626               if ( ok ) {
4627                 CORBA::Object_var shapeObj = myShape->GetObject();
4628                 shapeRefFound = (! CORBA::is_nil( shapeObj ));
4629                 CORBA::String_var myRefOnObject = myShape->GetID();
4630                 if ( shapeRefFound && myRefOnObject.in()[0] ) {
4631                   aSize[ 0 ] = strlen( myRefOnObject.in() ) + 1;
4632                   aDataset = new HDFdataset( "Ref on shape", aTopGroup, HDF_STRING, aSize, 1 );
4633                   aDataset->CreateOnDisk();
4634                   aDataset->WriteOnDisk( ( char* )( myRefOnObject.in() ) );
4635                   aDataset->CloseOnDisk();
4636                 }
4637               }
4638             }
4639
4640             // Store file info
4641             std::string info = myImpl->FileInfoToString();
4642             if ( !info.empty() )
4643             {
4644               aSize[ 0 ] = info.size();
4645               aDataset = new HDFdataset( "file info", aTopGroup, HDF_STRING, aSize, 1 );
4646               aDataset->CreateOnDisk();
4647               aDataset->WriteOnDisk( (char*) info.data() );
4648               aDataset->CloseOnDisk();
4649             }
4650
4651             // write applied hypotheses if exist
4652             SALOMEDS::SObject_wrap myHypBranch;
4653             found = gotBranch->FindSubObject( (CORBA::Long)GetRefOnAppliedHypothesisTag(), myHypBranch.inout() );
4654             if ( found && !shapeRefFound && hasShape ) { // remove applied hyps
4655               aStudy->NewBuilder()->RemoveObjectWithChildren( myHypBranch );
4656             }
4657             if ( found && (shapeRefFound || !hasShape) ) {
4658               aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup );
4659               aGroup->CreateOnDisk();
4660
4661               SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( myHypBranch );
4662               int hypNb = 0;
4663               for ( ; it->More(); it->Next() ) {
4664                 SALOMEDS::SObject_wrap mySObject = it->Value();
4665                 SALOMEDS::SObject_wrap myRefOnHyp;
4666                 bool ok = mySObject->ReferencedObject( myRefOnHyp.inout() );
4667                 if ( ok ) {
4668                   // san - it is impossible to recover applied hypotheses
4669                   //       using their entries within Load() method,
4670                   // for there are no AttributeIORs in the study when Load() is working.
4671                   // Hence, it is better to store persistent IDs of hypotheses as references to them
4672
4673                   //string myRefOnObject = myRefOnHyp->GetID();
4674                   CORBA::Object_var anObject = SObjectToObject( myRefOnHyp );
4675                   CORBA::String_var objStr = GetORB()->object_to_string( anObject );
4676                   int id = myStudyContext->findId( string( objStr.in() ) );
4677                   //if ( myRefOnObject.length() > 0 ) {
4678                   //aSize[ 0 ] = myRefOnObject.length() + 1;
4679                   char hypName[ 30 ], hypId[ 30 ];
4680                   sprintf( hypName, "Hyp %d", ++hypNb );
4681                   sprintf( hypId, "%d", id );
4682                   aSize[ 0 ] = strlen( hypId ) + 1;
4683                   aDataset = new HDFdataset( hypName, aGroup, HDF_STRING, aSize, 1 );
4684                   aDataset->CreateOnDisk();
4685                   //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
4686                   aDataset->WriteOnDisk( hypId );
4687                   aDataset->CloseOnDisk();
4688                   //}
4689                 }
4690               }
4691               aGroup->CloseOnDisk();
4692             }
4693
4694             // write applied algorithms if exist
4695             SALOMEDS::SObject_wrap myAlgoBranch;
4696             found = gotBranch->FindSubObject( GetRefOnAppliedAlgorithmsTag(),
4697                                               myAlgoBranch.inout() );
4698             if ( found && !shapeRefFound && hasShape) { // remove applied algos
4699               aStudy->NewBuilder()->RemoveObjectWithChildren( myAlgoBranch );
4700             }
4701             if ( found && (shapeRefFound || !hasShape)) {
4702               aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
4703               aGroup->CreateOnDisk();
4704
4705               SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( myAlgoBranch );
4706               int algoNb = 0;
4707               for ( ; it->More(); it->Next() ) {
4708                 SALOMEDS::SObject_wrap mySObject = it->Value();
4709                 SALOMEDS::SObject_wrap myRefOnAlgo;
4710                 bool ok = mySObject->ReferencedObject( myRefOnAlgo.inout() );
4711                 if ( ok ) {
4712                   // san - it is impossible to recover applied algorithms
4713                   //       using their entries within Load() method,
4714                   // for there are no AttributeIORs in the study when Load() is working.
4715                   // Hence, it is better to store persistent IDs of algorithms as references to them
4716
4717                   //string myRefOnObject = myRefOnAlgo->GetID();
4718                   CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo );
4719                   CORBA::String_var objStr = GetORB()->object_to_string( anObject );
4720                   int id = myStudyContext->findId( string( objStr.in() ) );
4721                   //if ( myRefOnObject.length() > 0 ) {
4722                   //aSize[ 0 ] = myRefOnObject.length() + 1;
4723                   char algoName[ 30 ], algoId[ 30 ];
4724                   sprintf( algoName, "Algo %d", ++algoNb );
4725                   sprintf( algoId, "%d", id );
4726                   aSize[ 0 ] = strlen( algoId ) + 1;
4727                   aDataset = new HDFdataset( algoName, aGroup, HDF_STRING, aSize, 1 );
4728                   aDataset->CreateOnDisk();
4729                   //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
4730                   aDataset->WriteOnDisk( algoId );
4731                   aDataset->CloseOnDisk();
4732                   //}
4733                 }
4734               }
4735               aGroup->CloseOnDisk();
4736             }
4737
4738             // --> submesh objects sub-branches
4739
4740             for ( int i = GetSubMeshOnVertexTag(); i <= GetSubMeshOnCompoundTag(); i++ ) {
4741               SALOMEDS::SObject_wrap mySubmeshBranch;
4742               found = gotBranch->FindSubObject( i, mySubmeshBranch.inout() );
4743
4744               if ( found ) // check if there is shape reference in submeshes
4745               {
4746                 bool hasShapeRef = false;
4747                 SALOMEDS::ChildIterator_wrap itSM =
4748                   aStudy->NewChildIterator( mySubmeshBranch );
4749                 for ( ; itSM->More(); itSM->Next() ) {
4750                   SALOMEDS::SObject_wrap mySubRef, myShape, mySObject = itSM->Value();
4751                   if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef.inout() ))
4752                     mySubRef->ReferencedObject( myShape.inout() );
4753                   if ( !CORBA::is_nil( myShape ) && !CORBA::is_nil( myShape->GetObject() ))
4754                     hasShapeRef = true;
4755                   else
4756                   { // remove one submesh
4757                     if ( shapeRefFound )
4758                     { // unassign hypothesis
4759                       SMESH::SMESH_subMesh_var mySubMesh =
4760                         SMESH::SMESH_subMesh::_narrow( SObjectToObject( mySObject ));
4761                       if ( !mySubMesh->_is_nil() ) {
4762                         int shapeID = mySubMesh->GetId();
4763                         TopoDS_Shape S = mySMESHDSMesh->IndexToShape( shapeID );
4764                         const list<const SMESHDS_Hypothesis*>& hypList =
4765                           mySMESHDSMesh->GetHypothesis( S );
4766                         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
4767                         while ( hyp != hypList.end() ) {
4768                           int hypID = (*hyp++)->GetID(); // goto next hyp here because
4769                           myLocMesh.RemoveHypothesis( S, hypID ); // hypList changes here
4770                         }
4771                       }
4772                     }
4773                     aStudy->NewBuilder()->RemoveObjectWithChildren( mySObject );
4774                   }
4775                 } // loop on submeshes of a type
4776                 if ( !shapeRefFound || !hasShapeRef ) { // remove the whole submeshes branch
4777                   aStudy->NewBuilder()->RemoveObjectWithChildren( mySubmeshBranch );
4778                   found = false;
4779                 }
4780               }  // end check if there is shape reference in submeshes
4781               if ( found ) {
4782                 char name_meshgroup[ 30 ];
4783                 if ( i == GetSubMeshOnVertexTag() )
4784                   strcpy( name_meshgroup, "SubMeshes On Vertex" );
4785                 else if ( i == GetSubMeshOnEdgeTag() )
4786                   strcpy( name_meshgroup, "SubMeshes On Edge" );
4787                 else if ( i == GetSubMeshOnWireTag() )
4788                   strcpy( name_meshgroup, "SubMeshes On Wire" );
4789                 else if ( i == GetSubMeshOnFaceTag() )
4790                   strcpy( name_meshgroup, "SubMeshes On Face" );
4791                 else if ( i == GetSubMeshOnShellTag() )
4792                   strcpy( name_meshgroup, "SubMeshes On Shell" );
4793                 else if ( i == GetSubMeshOnSolidTag() )
4794                   strcpy( name_meshgroup, "SubMeshes On Solid" );
4795                 else if ( i == GetSubMeshOnCompoundTag() )
4796                   strcpy( name_meshgroup, "SubMeshes On Compound" );
4797
4798                 // for each type of submeshes create container HDF group
4799                 aGroup = new HDFgroup( name_meshgroup, aTopGroup );
4800                 aGroup->CreateOnDisk();
4801
4802                 // iterator for all submeshes of given type
4803                 SALOMEDS::ChildIterator_wrap itSM = aStudy->NewChildIterator( mySubmeshBranch );
4804                 for ( ; itSM->More(); itSM->Next() ) {
4805                   SALOMEDS::SObject_wrap mySObject = itSM->Value();
4806                   CORBA::Object_var anSubObject = SObjectToObject( mySObject );
4807                   if ( !CORBA::is_nil( anSubObject ))
4808                   {
4809                     SMESH::SMESH_subMesh_var mySubMesh = SMESH::SMESH_subMesh::_narrow( anSubObject ) ;
4810                     CORBA::String_var objStr = GetORB()->object_to_string( anSubObject );
4811                     int subid = myStudyContext->findId( string( objStr.in() ) );
4812
4813                     // for each mesh open the HDF group basing on its id
4814                     char submeshGrpName[ 30 ];
4815                     sprintf( submeshGrpName, "SubMesh %d", subid );
4816                     aSubGroup = new HDFgroup( submeshGrpName, aGroup );
4817                     aSubGroup->CreateOnDisk();
4818
4819                     // write reference on a shape, already checked if it exists
4820                     SALOMEDS::SObject_wrap mySubRef, myShape;
4821                     if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef.inout() ))
4822                       mySubRef->ReferencedObject( myShape.inout() );
4823                     string myRefOnObject = myShape->GetID();
4824                     if ( myRefOnObject.length() > 0 ) {
4825                       aSize[ 0 ] = myRefOnObject.length() + 1;
4826                       aDataset = new HDFdataset( "Ref on shape", aSubGroup, HDF_STRING, aSize, 1 );
4827                       aDataset->CreateOnDisk();
4828                       aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
4829                       aDataset->CloseOnDisk();
4830                     }
4831
4832                     // write applied hypotheses if exist
4833                     SALOMEDS::SObject_wrap mySubHypBranch;
4834                     found = mySObject->FindSubObject( GetRefOnAppliedHypothesisTag(),
4835                                                       mySubHypBranch.inout() );
4836                     if ( found ) {
4837                       aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup );
4838                       aSubSubGroup->CreateOnDisk();
4839
4840                       SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( mySubHypBranch );
4841                       int hypNb = 0;
4842                       for ( ; it->More(); it->Next() ) {
4843                         SALOMEDS::SObject_wrap mySubSObject = it->Value();
4844                         SALOMEDS::SObject_wrap myRefOnHyp;
4845                         bool ok = mySubSObject->ReferencedObject( myRefOnHyp.inout() );
4846                         if ( ok ) {
4847                           //string myRefOnObject = myRefOnHyp->GetID();
4848                           CORBA::Object_var anObject = SObjectToObject( myRefOnHyp );
4849                           CORBA::String_var objStr = GetORB()->object_to_string( anObject );
4850                           int id = myStudyContext->findId( string( objStr.in() ) );
4851                           //if ( myRefOnObject.length() > 0 ) {
4852                           //aSize[ 0 ] = myRefOnObject.length() + 1;
4853                           char hypName[ 30 ], hypId[ 30 ];
4854                           sprintf( hypName, "Hyp %d", ++hypNb );
4855                           sprintf( hypId, "%d", id );
4856                           aSize[ 0 ] = strlen( hypId ) + 1;
4857                           aDataset = new HDFdataset( hypName, aSubSubGroup, HDF_STRING, aSize, 1 );
4858                           aDataset->CreateOnDisk();
4859                           //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
4860                           aDataset->WriteOnDisk( hypId );
4861                           aDataset->CloseOnDisk();
4862                           //}
4863                         }
4864                       }
4865                       aSubSubGroup->CloseOnDisk();
4866                     }
4867
4868                     // write applied algorithms if exist
4869                     SALOMEDS::SObject_wrap mySubAlgoBranch;
4870                     found = mySObject->FindSubObject( GetRefOnAppliedAlgorithmsTag(),
4871                                                       mySubAlgoBranch.inout() );
4872                     if ( found ) {
4873                       aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup );
4874                       aSubSubGroup->CreateOnDisk();
4875
4876                       SALOMEDS::ChildIterator_wrap it =
4877                         aStudy->NewChildIterator( mySubAlgoBranch );
4878                       int algoNb = 0;
4879                       for ( ; it->More(); it->Next() ) {
4880                         SALOMEDS::SObject_wrap mySubSObject = it->Value();
4881                         SALOMEDS::SObject_wrap myRefOnAlgo;
4882                         bool ok = mySubSObject->ReferencedObject( myRefOnAlgo.inout() );
4883                         if ( ok ) {
4884                           //string myRefOnObject = myRefOnAlgo->GetID();
4885                           CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo );
4886                           CORBA::String_var objStr = GetORB()->object_to_string( anObject );
4887                           int id = myStudyContext->findId( string( objStr.in() ) );
4888                           //if ( myRefOnObject.length() > 0 ) {
4889                           //aSize[ 0 ] = myRefOnObject.length() + 1;
4890                           char algoName[ 30 ], algoId[ 30 ];
4891                           sprintf( algoName, "Algo %d", ++algoNb );
4892                           sprintf( algoId, "%d", id );
4893                           aSize[ 0 ] = strlen( algoId ) + 1;
4894                           aDataset = new HDFdataset( algoName, aSubSubGroup, HDF_STRING, aSize, 1 );
4895                           aDataset->CreateOnDisk();
4896                           //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
4897                           aDataset->WriteOnDisk( algoId );
4898                           aDataset->CloseOnDisk();
4899                           //}
4900                         }
4901                       }
4902                       aSubSubGroup->CloseOnDisk();
4903                     }
4904                     // close submesh HDF group
4905                     aSubGroup->CloseOnDisk();
4906                   }
4907                 }
4908                 // close container of submeshes by type HDF group
4909                 aGroup->CloseOnDisk();
4910               }
4911             }
4912
4913             // store submesh order if any
4914             const TListOfListOfInt& theOrderIds = myLocMesh.GetMeshOrder();
4915             const bool isNewOrederVersion = true; // old version saves ids, new one, entries
4916             if ( !theOrderIds.empty() && !isNewOrederVersion ) { // keep old version for reference
4917               char order_list[ 30 ];
4918               strcpy( order_list, "Mesh Order" );
4919               // count number of submesh ids
4920               int nbIDs = 0;
4921               TListOfListOfInt::const_iterator idIt = theOrderIds.begin();
4922               for ( ; idIt != theOrderIds.end(); idIt++ )
4923                 nbIDs += (*idIt).size();
4924               // number of values = number of IDs +
4925               //                    number of lists (for separators) - 1
4926               int* smIDs = new int [ nbIDs + theOrderIds.size() - 1 ];
4927               idIt = theOrderIds.begin();
4928               for ( int i = 0; idIt != theOrderIds.end(); idIt++ ) {
4929                 const TListOfInt& idList = *idIt;
4930                 if (idIt != theOrderIds.begin()) // not first list
4931                   smIDs[ i++ ] = -1/* *idList.size()*/; // separator between lists
4932                 // dump submesh ids from current list
4933                 TListOfInt::const_iterator id_smId = idList.begin();
4934                 for( ; id_smId != idList.end(); id_smId++ )
4935                   smIDs[ i++ ] = *id_smId;
4936               }
4937               // write HDF group
4938               aSize[ 0 ] = nbIDs + theOrderIds.size() - 1;
4939
4940               aDataset = new HDFdataset( order_list, aTopGroup, HDF_INT32, aSize, 1 );
4941               aDataset->CreateOnDisk();
4942               aDataset->WriteOnDisk( smIDs );
4943               aDataset->CloseOnDisk();
4944               //
4945               delete[] smIDs;
4946             }
4947             if ( !theOrderIds.empty() && isNewOrederVersion )
4948             {
4949               // convert ids to entries
4950               std::list< std::list< std::string > > orderEntryLists;
4951               for ( const TListOfInt& idList : theOrderIds )
4952               {
4953                 orderEntryLists.emplace_back();
4954                 std::list< std::string > & entryList = orderEntryLists.back();
4955                 for ( const int& id : idList )
4956                 {
4957                   const TopoDS_Shape& shape = mySMESHDSMesh->IndexToShape( id );
4958                   GEOM::GEOM_Object_var  go = ShapeToGeomObject( shape );
4959                   SALOMEDS::SObject_var  so = ObjectToSObject( go );
4960                   if ( !so->_is_nil() )
4961                   {
4962                     CORBA::String_var entry = so->GetID();
4963                     entryList.emplace_back( entry.in() );
4964                   }
4965                 }
4966               }
4967               // convert orderEntryLists to string
4968               std::ostringstream ostream;
4969               boost::archive::text_oarchive( ostream ) << orderEntryLists;
4970               std::string orderEntryString = ostream.str();
4971
4972               // write HDF group
4973               aSize[ 0 ] = orderEntryString.size() + 1;
4974               aDataset = new HDFdataset( "MeshOrder_new", aTopGroup, HDF_STRING, aSize, 1 );
4975               aDataset->CreateOnDisk();
4976               aDataset->WriteOnDisk((char*) orderEntryString.data() );
4977               aDataset->CloseOnDisk();
4978             }
4979
4980             // groups root sub-branch
4981             SALOMEDS::SObject_wrap myGroupsBranch;
4982             for ( int i = GetNodeGroupsTag(); i <= GetBallElementsGroupsTag(); i++ ) {
4983               found = gotBranch->FindSubObject( i, myGroupsBranch.inout() );
4984               if ( found ) {
4985                 char name_group[ 30 ];
4986                 if ( i == GetNodeGroupsTag() )
4987                   strcpy( name_group, "Groups of Nodes" );
4988                 else if ( i == GetEdgeGroupsTag() )
4989                   strcpy( name_group, "Groups of Edges" );
4990                 else if ( i == GetFaceGroupsTag() )
4991                   strcpy( name_group, "Groups of Faces" );
4992                 else if ( i == GetVolumeGroupsTag() )
4993                   strcpy( name_group, "Groups of Volumes" );
4994                 else if ( i == Get0DElementsGroupsTag() )
4995                   strcpy( name_group, "Groups of 0D Elements" );
4996                 else if ( i == GetBallElementsGroupsTag() )
4997                   strcpy( name_group, "Groups of Balls" );
4998
4999                 aGroup = new HDFgroup( name_group, aTopGroup );
5000                 aGroup->CreateOnDisk();
5001
5002                 SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( myGroupsBranch );
5003                 for ( ; it->More(); it->Next() ) {
5004                   SALOMEDS::SObject_wrap mySObject = it->Value();
5005                   CORBA::Object_var aSubObject = SObjectToObject( mySObject );
5006                   if ( !CORBA::is_nil( aSubObject ) ) {
5007                     SMESH_GroupBase_i* myGroupImpl =
5008                       dynamic_cast<SMESH_GroupBase_i*>( GetServant( aSubObject ).in() );
5009                     if ( !myGroupImpl )
5010                       continue;
5011                     SMESHDS_GroupBase* aGrpBaseDS = myGroupImpl->GetGroupDS();
5012                     if ( !aGrpBaseDS )
5013                       continue;
5014
5015                     CORBA::String_var objStr = GetORB()->object_to_string( aSubObject );
5016                     int anId = myStudyContext->findId( string( objStr.in() ) );
5017
5018                     // For each group, create a dataset named "Group <group_persistent_id>"
5019                     // and store the group's user name into it
5020                     const char*         grpName = aGrpBaseDS->GetStoreName();
5021                     CORBA::String_var aUserName = myGroupImpl->GetName();
5022                     aSize[ 0 ] = strlen( aUserName ) + 1;
5023
5024                     aDataset = new HDFdataset( grpName, aGroup, HDF_STRING, aSize, 1 );
5025                     aDataset->CreateOnDisk();
5026                     aDataset->WriteOnDisk( aUserName );
5027                     aDataset->CloseOnDisk();
5028
5029                     // ouv : NPAL12872
5030                     // For each group, create a dataset named "Group <group_persistent_id> Color"
5031                     // and store the group's color into it
5032                     char grpColorName[ 30 ];
5033                     sprintf( grpColorName, "ColorGroup %d", anId );
5034                     SALOMEDS::Color aColor = myGroupImpl->GetColor();
5035                     double anRGB[3];
5036                     anRGB[ 0 ] = aColor.R;
5037                     anRGB[ 1 ] = aColor.G;
5038                     anRGB[ 2 ] = aColor.B;
5039                     aSize[ 0 ] = 3;
5040                     aDataset = new HDFdataset( grpColorName, aGroup, HDF_FLOAT64, aSize, 1 );
5041                     aDataset->CreateOnDisk();
5042                     aDataset->WriteOnDisk( anRGB );
5043                     aDataset->CloseOnDisk();
5044
5045                     // Pass SMESHDS_Group to MED writer
5046                     SMESHDS_Group* aGrpDS = dynamic_cast<SMESHDS_Group*>( aGrpBaseDS );
5047                     if ( aGrpDS )
5048                       writer.AddGroup( aGrpDS );
5049
5050                     // write reference on a shape if exists
5051                     SMESHDS_GroupOnGeom* aGeomGrp =
5052                       dynamic_cast<SMESHDS_GroupOnGeom*>( aGrpBaseDS );
5053                     if ( aGeomGrp ) {
5054                       SALOMEDS::SObject_wrap mySubRef, myShape;
5055                       if (mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef.inout() ) &&
5056                           mySubRef->ReferencedObject( myShape.inout() ) &&
5057                           !CORBA::is_nil( myShape->GetObject() ))
5058                       {
5059                         CORBA::String_var myRefOnObject = myShape->GetID();
5060                         if ( myRefOnObject.in()[0] ) {
5061                           char aRefName[ 30 ];
5062                           sprintf( aRefName, "Ref on shape %d", anId);
5063                           aSize[ 0 ] = strlen( myRefOnObject.in() ) + 1;
5064                           aDataset = new HDFdataset(aRefName, aGroup, HDF_STRING, aSize, 1);
5065                           aDataset->CreateOnDisk();
5066                           aDataset->WriteOnDisk( ( char* )( myRefOnObject.in() ));
5067                           aDataset->CloseOnDisk();
5068                         }
5069                       }
5070                       else // shape ref is invalid:
5071                       {
5072                         // save a group on geometry as ordinary group
5073                         writer.AddGroup( aGeomGrp );
5074                       }
5075                     }
5076                     else if ( SMESH_GroupOnFilter_i* aFilterGrp_i =
5077                               dynamic_cast<SMESH_GroupOnFilter_i*>( myGroupImpl ))
5078                     {
5079                       std::string str = aFilterGrp_i->FilterToString();
5080                       std::string hdfGrpName = "Filter " + SMESH_Comment(anId);
5081                       aSize[ 0 ] = str.length() + 1;
5082                       aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup, HDF_STRING, aSize, 1);
5083                       aDataset->CreateOnDisk();
5084                       aDataset->WriteOnDisk( ( char* )( str.c_str() ) );
5085                       aDataset->CloseOnDisk();
5086                     }
5087                   }
5088                 }
5089                 aGroup->CloseOnDisk();
5090               }
5091             } // loop on groups
5092
5093             if ( strcmp( strHasData.c_str(), "1" ) == 0 )
5094             {
5095               // Flush current mesh information into MED file
5096               writer.Perform();
5097
5098               // save info on nb of elements
5099               SMESH_PreMeshInfo::SaveToFile( myImpl, id, aFile );
5100
5101               // maybe a shape was deleted in the study
5102               if ( !shapeRefFound && !mySMESHDSMesh->ShapeToMesh().IsNull() && hasShape) {
5103                 TopoDS_Shape nullShape;
5104                 myLocMesh.ShapeToMesh( nullShape ); // remove shape referring data
5105               }
5106
5107               SMESHDS_SubMeshIteratorPtr smIt = mySMESHDSMesh->SubMeshes();
5108               if ( smIt->more() )
5109               {
5110                 // Store submeshes
5111                 // ----------------
5112                 aGroup = new HDFgroup( "Submeshes", aTopGroup );
5113                 aGroup->CreateOnDisk();
5114
5115                 // each element belongs to one or none submesh,
5116                 // so for each node/element, we store a submesh ID
5117
5118                 // Store submesh IDs
5119                 for ( int isNode = 0; isNode < 2; ++isNode )
5120                 {
5121                   SMDS_ElemIteratorPtr eIt =
5122                     mySMESHDSMesh->elementsIterator( isNode ? SMDSAbs_Node : SMDSAbs_All );
5123                   smIdType nbElems = isNode ? mySMESHDSMesh->NbNodes() : mySMESHDSMesh->GetMeshInfo().NbElements();
5124                   if ( nbElems < 1 )
5125                     continue;
5126                   std::vector<int> smIDs; smIDs.reserve( nbElems );
5127                   while ( eIt->more() )
5128                     if ( const SMDS_MeshElement* e = eIt->next())
5129                       smIDs.push_back( e->getshapeId() );
5130                   // write HDF group
5131                   aSize[ 0 ] = nbElems;
5132                   string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
5133                   aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_INT32, aSize, 1 );
5134                   aDataset->CreateOnDisk();
5135                   aDataset->WriteOnDisk( & smIDs[0] );
5136                   aDataset->CloseOnDisk();
5137                 }
5138
5139                 aGroup->CloseOnDisk();
5140
5141                 // Store node positions on sub-shapes (SMDS_Position):
5142                 // ----------------------------------------------------
5143
5144                 aGroup = new HDFgroup( "Node Positions", aTopGroup );
5145                 aGroup->CreateOnDisk();
5146
5147                 // in aGroup, create 5 datasets to contain:
5148                 // "Nodes on Edges" - ID of node on edge
5149                 // "Edge positions" - U parameter on node on edge
5150                 // "Nodes on Faces" - ID of node on face
5151                 // "Face U positions" - U parameter of node on face
5152                 // "Face V positions" - V parameter of node on face
5153
5154                 // Find out nb of nodes on edges and faces
5155                 // Collect corresponding sub-meshes
5156                 int nbEdgeNodes = 0, nbFaceNodes = 0;
5157                 list<SMESHDS_SubMesh*> aEdgeSM, aFaceSM;
5158                 // loop on SMESHDS_SubMesh'es
5159                 while ( smIt->more() )
5160                 {
5161                   SMESHDS_SubMesh* aSubMesh = const_cast< SMESHDS_SubMesh* >( smIt->next() );
5162                   if ( aSubMesh->IsComplexSubmesh() )
5163                     continue; // submesh containing other submeshs
5164                   smIdType nbNodes = aSubMesh->NbNodes();
5165                   if ( nbNodes == 0 ) continue;
5166
5167                   int aShapeID = aSubMesh->GetID();
5168                   if ( aShapeID < 1 || aShapeID > mySMESHDSMesh->MaxShapeIndex() )
5169                     continue;
5170                   int aShapeType = mySMESHDSMesh->IndexToShape( aShapeID ).ShapeType();
5171                   // write only SMDS_FacePosition and SMDS_EdgePosition
5172                   switch ( aShapeType ) {
5173                   case TopAbs_FACE:
5174                     nbFaceNodes += nbNodes;
5175                     aFaceSM.push_back( aSubMesh );
5176                     break;
5177                   case TopAbs_EDGE:
5178                     nbEdgeNodes += nbNodes;
5179                     aEdgeSM.push_back( aSubMesh );
5180                     break;
5181                   default:
5182                     continue;
5183                   }
5184                 }
5185                 // Treat positions on edges or faces
5186                 for ( int onFace = 0; onFace < 2; onFace++ )
5187                 {
5188                   // Create arrays to store in datasets
5189                   int iNode = 0, nbNodes = ( onFace ? nbFaceNodes : nbEdgeNodes );
5190                   if (!nbNodes) continue;
5191                   int* aNodeIDs = new int [ nbNodes ];
5192                   double* aUPos = new double [ nbNodes ];
5193                   double* aVPos = ( onFace ? new double[ nbNodes ] : 0 );
5194
5195                   // Fill arrays
5196                   // loop on sub-meshes
5197                   list<SMESHDS_SubMesh*> * pListSM = ( onFace ? &aFaceSM : &aEdgeSM );
5198                   list<SMESHDS_SubMesh*>::iterator itSM = pListSM->begin();
5199                   for ( ; itSM != pListSM->end(); itSM++ )
5200                   {
5201                     SMESHDS_SubMesh* aSubMesh = (*itSM);
5202
5203                     SMDS_NodeIteratorPtr itNode = aSubMesh->GetNodes();
5204                     // loop on nodes in aSubMesh
5205                     while ( itNode->more() )
5206                     {
5207                       //node ID
5208                       const SMDS_MeshNode* node = itNode->next();
5209                       aNodeIDs [ iNode ] = node->GetID();
5210
5211                       // Position
5212                       const SMDS_PositionPtr pos = node->GetPosition();
5213                       if ( onFace ) { // on FACE
5214                         SMDS_FacePositionPtr fPos = pos;
5215                         if ( fPos ) {
5216                           aUPos[ iNode ] = fPos->GetUParameter();
5217                           aVPos[ iNode ] = fPos->GetVParameter();
5218                           iNode++;
5219                         }
5220                         else
5221                           nbNodes--;
5222                       }
5223                       else { // on EDGE
5224                         SMDS_EdgePositionPtr ePos = pos;
5225                         if ( ePos ) {
5226                           aUPos[ iNode ] = ePos->GetUParameter();
5227                           iNode++;
5228                         }
5229                         else
5230                           nbNodes--;
5231                       }
5232                     } // loop on nodes in aSubMesh
5233                   } // loop on sub-meshes
5234
5235                   // Write datasets
5236                   if ( nbNodes )
5237                   {
5238                     aSize[ 0 ] = nbNodes;
5239                     // IDS
5240                     string aDSName( onFace ? "Nodes on Faces" : "Nodes on Edges");
5241                     aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_INT32, aSize, 1 );
5242                     aDataset->CreateOnDisk();
5243                     aDataset->WriteOnDisk( aNodeIDs );
5244                     aDataset->CloseOnDisk();
5245
5246                     // U Positions
5247                     aDSName = ( onFace ? "Face U positions" : "Edge positions");
5248                     aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_FLOAT64, aSize, 1);
5249                     aDataset->CreateOnDisk();
5250                     aDataset->WriteOnDisk( aUPos );
5251                     aDataset->CloseOnDisk();
5252                     // V Positions
5253                     if ( onFace ) {
5254                       aDataset = new HDFdataset( "Face V positions", aGroup, HDF_FLOAT64, aSize, 1);
5255                       aDataset->CreateOnDisk();
5256                       aDataset->WriteOnDisk( aVPos );
5257                       aDataset->CloseOnDisk();
5258                     }
5259                   }
5260                   delete [] aNodeIDs;
5261                   delete [] aUPos;
5262                   if ( aVPos ) delete [] aVPos;
5263
5264                 } // treat positions on edges or faces
5265
5266                 // close "Node Positions" group
5267                 aGroup->CloseOnDisk();
5268
5269               } // if ( there are submeshes in SMESHDS_Mesh )
5270             } // if ( hasData )
5271
5272             // close mesh HDF group
5273             aTopGroup->CloseOnDisk();
5274           }
5275         }
5276       }
5277     }
5278   }
5279
5280   // close HDF file
5281   aFile->CloseOnDisk();
5282   delete aFile;
5283
5284   // Convert temporary files to stream
5285   aStreamFile = SALOMEDS_Tool::PutFilesToStream( tmpDir.ToCString(), aFileSeq, isMultiFile );
5286
5287   // Remove temporary files and directory
5288   if ( !isMultiFile )
5289     SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq, true );
5290
5291   return aStreamFile._retn();
5292 }
5293
5294 //=============================================================================
5295 /*!
5296  *  SMESH_Gen_i::SaveASCII
5297  *
5298  *  Save SMESH module's data in ASCII format
5299  */
5300 //=============================================================================
5301
5302 SALOMEDS::TMPFile* SMESH_Gen_i::SaveASCII( SALOMEDS::SComponent_ptr theComponent,
5303                                            const char*              theURL,
5304                                            bool                     isMultiFile ) {
5305   MESSAGE( "SMESH_Gen_i::SaveASCII" );
5306   SALOMEDS::TMPFile_var aStreamFile = Save( theComponent, theURL, isMultiFile );
5307   return aStreamFile._retn();
5308
5309   //after usual saving needs to encipher binary to text string
5310   //Any binary symbol will be represent as "|xx" () hexadecimal format number
5311   int size = aStreamFile.in().length();
5312   _CORBA_Octet* buffer = new _CORBA_Octet[size*3+1];
5313   for ( int i = 0; i < size; i++ )
5314     sprintf( (char*)&(buffer[i*3]), "|%02x", aStreamFile[i] );
5315
5316   buffer[size * 3] = '\0';
5317
5318   SALOMEDS::TMPFile_var anAsciiStreamFile = new SALOMEDS::TMPFile(size*3, size*3, buffer, 1);
5319
5320   return anAsciiStreamFile._retn();
5321 }
5322
5323 //=============================================================================
5324 /*!
5325  *  SMESH_Gen_i::Load
5326  *
5327  *  Load SMESH module's data
5328  */
5329 //=============================================================================
5330
5331 bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
5332                         const SALOMEDS::TMPFile& theStream,
5333                         const char*              theURL,
5334                         bool                     isMultiFile )
5335 {
5336   UpdateStudy(); // load geom data
5337   Kernel_Utils::Localizer loc;
5338
5339   SALOMEDS::Study_var aStudy = getStudyServant();
5340
5341   // Get temporary files location
5342   TCollection_AsciiString tmpDir =
5343     ( char* )( isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir().c_str() );
5344
5345   // Convert the stream into sequence of files to process
5346   SALOMEDS_Tool::ListOfFiles aFileSeq = SALOMEDS_Tool::PutStreamToFiles( theStream,
5347                                                                          tmpDir.ToCString(),
5348                                                                          isMultiFile );
5349   TCollection_AsciiString aStudyName( "" );
5350   if ( isMultiFile ) {
5351     CORBA::WString_var url = aStudy->URL();
5352     SMESHUtils::ArrayDeleter<const char> urlMulibyte( Kernel_Utils::encode( url.in()) );
5353     aStudyName = (char*)SALOMEDS_Tool::GetNameFromPath( urlMulibyte.get() ).c_str();
5354   }
5355   // Set names of temporary files
5356   TCollection_AsciiString filename = tmpDir + aStudyName + "_SMESH.hdf";
5357   TCollection_AsciiString meshfile = tmpDir + aStudyName + "_SMESH_Mesh.med";
5358
5359   int size;
5360   HDFfile*    aFile;
5361   HDFdataset* aDataset;
5362   HDFgroup*   aTopGroup;
5363   HDFgroup*   aGroup;
5364   HDFgroup*   aSubGroup;
5365   HDFgroup*   aSubSubGroup;
5366
5367   // Read data
5368   // ---> open HDF file
5369   aFile = new HDFfile( (char*) filename.ToCString() );
5370   try {
5371     aFile->OpenOnDisk( HDF_RDONLY );
5372   }
5373   catch ( HDFexception ) {
5374     INFOS( "Load(): " << filename << " not found!" );
5375     return false;
5376   }
5377
5378   TPythonDump pd(this); // prevent dump during loading
5379
5380   // For PAL13473 ("Repetitive mesh") implementation.
5381   // New dependencies between SMESH objects are established:
5382   // now hypotheses can refer to meshes, shapes and other hypotheses.
5383   // To keep data consistent, the following order of data restoration
5384   // imposed:
5385   // 1. Create hypotheses
5386   // 2. Create all meshes
5387   // 3. Load hypotheses' data
5388   // 4. All the rest
5389
5390   list< pair< SMESH_Hypothesis_i*, string > >    hypDataList;
5391   list< pair< SMESH_Mesh_i*,       HDFgroup* > > meshGroupList;
5392   list< SMESH::Filter_var >                      filters;
5393
5394   // get total number of top-level groups
5395   int aNbGroups = aFile->nInternalObjects();
5396   if ( aNbGroups > 0 ) {
5397     // --> in first turn we should read&create hypotheses
5398     if ( aFile->ExistInternalObject( "Hypotheses" ) ) {
5399       // open hypotheses root HDF group
5400       aTopGroup = new HDFgroup( "Hypotheses", aFile );
5401       aTopGroup->OpenOnDisk();
5402
5403       // get number of hypotheses
5404       int aNbObjects = aTopGroup->nInternalObjects();
5405       for ( int j = 0; j < aNbObjects; j++ ) {
5406         // try to identify hypothesis
5407         char hypGrpName[ HDF_NAME_MAX_LEN+1 ];
5408         aTopGroup->InternalObjectIndentify( j, hypGrpName );
5409
5410         if ( string( hypGrpName ).substr( 0, 10 ) == string( "Hypothesis" ) ) {
5411           // open hypothesis group
5412           aGroup = new HDFgroup( hypGrpName, aTopGroup );
5413           aGroup->OpenOnDisk();
5414
5415           // --> get hypothesis id
5416           int    id = atoi( string( hypGrpName ).substr( 10 ).c_str() );
5417           string hypname;
5418           string libname;
5419           string hypdata;
5420
5421           // get number of datasets
5422           int aNbSubObjects = aGroup->nInternalObjects();
5423           for ( int k = 0; k < aNbSubObjects; k++ ) {
5424             // identify dataset
5425             char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ];
5426             aGroup->InternalObjectIndentify( k, name_of_subgroup );
5427             // --> get hypothesis name
5428             if ( strcmp( name_of_subgroup, "Name"  ) == 0 ) {
5429               aDataset = new HDFdataset( name_of_subgroup, aGroup );
5430               aDataset->OpenOnDisk();
5431               size = aDataset->GetSize();
5432               char* hypname_str = new char[ size ];
5433               aDataset->ReadFromDisk( hypname_str );
5434               hypname = string( hypname_str );
5435               delete [] hypname_str;
5436               aDataset->CloseOnDisk();
5437             }
5438             // --> get hypothesis plugin library name
5439             if ( strcmp( name_of_subgroup, "LibName"  ) == 0 ) {
5440               aDataset = new HDFdataset( name_of_subgroup, aGroup );
5441               aDataset->OpenOnDisk();
5442               size = aDataset->GetSize();
5443               char* libname_str = new char[ size ];
5444               aDataset->ReadFromDisk( libname_str );
5445               SCRUTE( libname_str );
5446               libname = string( libname_str );
5447               delete [] libname_str;
5448               aDataset->CloseOnDisk();
5449             }
5450             // --> get hypothesis data
5451             if ( strcmp( name_of_subgroup, "Data"  ) == 0 ) {
5452               aDataset = new HDFdataset( name_of_subgroup, aGroup );
5453               aDataset->OpenOnDisk();
5454               size = aDataset->GetSize();
5455               char* hypdata_str = new char[ size ];
5456               aDataset->ReadFromDisk( hypdata_str );
5457               hypdata = string( hypdata_str );
5458               delete [] hypdata_str;
5459               aDataset->CloseOnDisk();
5460             }
5461           }
5462           // close hypothesis HDF group
5463           aGroup->CloseOnDisk();
5464
5465           // --> restore hypothesis from data
5466           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
5467             MESSAGE("VSR - load hypothesis : id = " << id <<
5468                                 ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
5469             SMESH::SMESH_Hypothesis_var myHyp;
5470
5471             try { // protect persistence mechanism against exceptions
5472               myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() );
5473             }
5474             catch (...) {
5475               INFOS( "Exception during hypothesis creation" );
5476             }
5477
5478             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
5479             if ( myImpl ) {
5480               // myImpl->LoadFrom( hypdata.c_str() );
5481               hypDataList.push_back( make_pair( myImpl, hypdata ));
5482               CORBA::String_var iorString = GetORB()->object_to_string( myHyp );
5483               int newId = myStudyContext->findId( iorString.in() );
5484               myStudyContext->mapOldToNew( id, newId );
5485             }
5486             else
5487               MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
5488           }
5489         }
5490       }
5491       // close hypotheses root HDF group
5492       aTopGroup->CloseOnDisk();
5493       aTopGroup = 0;
5494     }
5495
5496     // --> then we should read&create algorithms
5497     if ( aFile->ExistInternalObject( "Algorithms" ) ) {
5498       // open algorithms root HDF group
5499       aTopGroup = new HDFgroup( "Algorithms", aFile );
5500       aTopGroup->OpenOnDisk();
5501
5502       // get number of algorithms
5503       int aNbObjects = aTopGroup->nInternalObjects();
5504       for ( int j = 0; j < aNbObjects; j++ ) {
5505         // try to identify algorithm
5506         char hypGrpName[ HDF_NAME_MAX_LEN+1 ];
5507         aTopGroup->InternalObjectIndentify( j, hypGrpName );
5508
5509         if ( string( hypGrpName ).substr( 0, 9 ) == string( "Algorithm" ) ) {
5510           // open algorithm group
5511           aGroup = new HDFgroup( hypGrpName, aTopGroup );
5512           aGroup->OpenOnDisk();
5513
5514           // --> get algorithm id
5515           int    id = atoi( string( hypGrpName ).substr( 9 ).c_str() );
5516           string hypname;
5517           string libname;
5518           string hypdata;
5519
5520           // get number of datasets
5521           int aNbSubObjects = aGroup->nInternalObjects();
5522           for ( int k = 0; k < aNbSubObjects; k++ ) {
5523             // identify dataset
5524             char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ];
5525             aGroup->InternalObjectIndentify( k, name_of_subgroup );
5526             // --> get algorithm name
5527             if ( strcmp( name_of_subgroup, "Name"  ) == 0 ) {
5528               aDataset = new HDFdataset( name_of_subgroup, aGroup );
5529               aDataset->OpenOnDisk();
5530               size = aDataset->GetSize();
5531               char* hypname_str = new char[ size ];
5532               aDataset->ReadFromDisk( hypname_str );
5533               hypname = string( hypname_str );
5534               delete [] hypname_str;
5535               aDataset->CloseOnDisk();
5536             }
5537             // --> get algorithm plugin library name
5538             if ( strcmp( name_of_subgroup, "LibName"  ) == 0 ) {
5539               aDataset = new HDFdataset( name_of_subgroup, aGroup );
5540               aDataset->OpenOnDisk();
5541               size = aDataset->GetSize();
5542               char* libname_str = new char[ size ];
5543               aDataset->ReadFromDisk( libname_str );
5544               SCRUTE( libname_str );
5545               libname = string( libname_str );
5546               delete [] libname_str;
5547               aDataset->CloseOnDisk();
5548             }
5549             // --> get algorithm data
5550             if ( strcmp( name_of_subgroup, "Data"  ) == 0 ) {
5551               aDataset = new HDFdataset( name_of_subgroup, aGroup );
5552               aDataset->OpenOnDisk();
5553               size = aDataset->GetSize();
5554               char* hypdata_str = new char[ size ];
5555               aDataset->ReadFromDisk( hypdata_str );
5556               SCRUTE( hypdata_str );
5557               hypdata = string( hypdata_str );
5558               delete [] hypdata_str;
5559               aDataset->CloseOnDisk();
5560             }
5561           }
5562           // close algorithm HDF group
5563           aGroup->CloseOnDisk();
5564
5565           // --> restore algorithm from data
5566           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
5567             MESSAGE("VSR - load algo : id = " << id <<
5568                                 ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
5569             SMESH::SMESH_Hypothesis_var myHyp;
5570
5571             try { // protect persistence mechanism against exceptions
5572               myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() );
5573             }
5574             catch( SALOME::SALOME_Exception& ex )
5575             {
5576               INFOS( "Exception during hypothesis creation: " << ex.details.text );
5577             }
5578             catch (...) {
5579               INFOS( "Exception during hypothesis creation" );
5580             }
5581
5582             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
5583             if ( myImpl ) {
5584               //myImpl->LoadFrom( hypdata.c_str() );
5585               hypDataList.push_back( make_pair( myImpl, hypdata ));
5586               CORBA::String_var iorString = GetORB()->object_to_string( myHyp );
5587               int newId = myStudyContext->findId( iorString.in() );
5588               myStudyContext->mapOldToNew( id, newId );
5589             }
5590             else
5591               MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
5592           }
5593         }
5594       }
5595       // close algorithms root HDF group
5596       aTopGroup->CloseOnDisk();
5597       aTopGroup = 0;
5598     }
5599
5600     // --> the rest groups should be meshes
5601     for ( int i = 0; i < aNbGroups; i++ ) {
5602       // identify next group
5603       char meshName[ HDF_NAME_MAX_LEN+1 ];
5604       aFile->InternalObjectIndentify( i, meshName );
5605
5606       if ( string( meshName ).substr( 0, 4 ) == string( "Mesh" ) ) {
5607         // --> get mesh id
5608         int id = atoi( string( meshName ).substr( 4 ).c_str() );
5609         if ( id <= 0 )
5610           continue;
5611
5612         // open mesh HDF group
5613         aTopGroup = new HDFgroup( meshName, aFile );
5614         aTopGroup->OpenOnDisk();
5615
5616         // get number of child HDF objects
5617         int aNbObjects = aTopGroup->nInternalObjects();
5618         if ( aNbObjects > 0 ) {
5619           // create mesh
5620           MESSAGE( "VSR - load mesh : id = " << id );
5621           SMESH::SMESH_Mesh_var myNewMesh = this->createMesh();
5622           SMESH_Mesh_i* myNewMeshImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( myNewMesh ).in() );
5623           if ( !myNewMeshImpl )
5624             continue;
5625           meshGroupList.push_back( make_pair( myNewMeshImpl, aTopGroup ));
5626
5627           CORBA::String_var iorString = GetORB()->object_to_string( myNewMesh );
5628           int newId = myStudyContext->findId( iorString.in() );
5629           myStudyContext->mapOldToNew( id, newId );
5630
5631           // ouv : NPAL12872
5632           // try to read and set auto color flag
5633           char aMeshAutoColorName[ 30 ];
5634           sprintf( aMeshAutoColorName, "AutoColorMesh %d", id);
5635           if( aTopGroup->ExistInternalObject( aMeshAutoColorName ) )
5636           {
5637             aDataset = new HDFdataset( aMeshAutoColorName, aTopGroup );
5638             aDataset->OpenOnDisk();
5639             size = aDataset->GetSize();
5640             int* anAutoColor = new int[ size ];
5641             aDataset->ReadFromDisk( anAutoColor );
5642             aDataset->CloseOnDisk();
5643             myNewMeshImpl->GetImpl().SetAutoColor( (bool)anAutoColor[0] );
5644             delete [] anAutoColor;
5645           }
5646
5647           // try to read and set reference to shape
5648           GEOM::GEOM_Object_var aShapeObject;
5649           if ( aTopGroup->ExistInternalObject( "Ref on shape" ) ) {
5650             // load mesh "Ref on shape" - it's an entry to SObject
5651             aDataset = new HDFdataset( "Ref on shape", aTopGroup );
5652             aDataset->OpenOnDisk();
5653             size = aDataset->GetSize();
5654             char* refFromFile = new char[ size ];
5655             aDataset->ReadFromDisk( refFromFile );
5656             aDataset->CloseOnDisk();
5657             if ( strlen( refFromFile ) > 0 ) {
5658               SALOMEDS::SObject_wrap shapeSO = aStudy->FindObjectID( refFromFile );
5659               CORBA::Object_var  shapeObject = SObjectToObject( shapeSO );
5660               if ( !CORBA::is_nil( shapeObject ) ) {
5661                 aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
5662                 if ( !aShapeObject->_is_nil() )
5663                   myNewMeshImpl->SetShape( aShapeObject );
5664               }
5665             }
5666             delete [] refFromFile;
5667           }
5668
5669           // issue 20918. Restore Persistent Id of SMESHDS_Mesh
5670           if ( aTopGroup->ExistInternalObject( "meshPersistentId" ) )
5671           {
5672             aDataset = new HDFdataset( "meshPersistentId", aTopGroup );
5673             aDataset->OpenOnDisk();
5674             size = aDataset->GetSize();
5675             int* meshPersistentId = new int[ size ];
5676             aDataset->ReadFromDisk( meshPersistentId );
5677             aDataset->CloseOnDisk();
5678             myNewMeshImpl->GetImpl().GetMeshDS()->SetPersistentId( *meshPersistentId );
5679             delete [] meshPersistentId;
5680           }
5681
5682           // Restore SMESH_Mesh_i::_mainShapeTick
5683           if ( aTopGroup->ExistInternalObject( "shapeTick" ))
5684           {
5685             aDataset = new HDFdataset( "shapeTick", aTopGroup );
5686             aDataset->OpenOnDisk();
5687             int* shapeTick = & myNewMeshImpl->MainShapeTick();
5688             aDataset->ReadFromDisk( shapeTick );
5689             aDataset->CloseOnDisk();
5690           }
5691
5692           // Restore file info
5693           if ( aTopGroup->ExistInternalObject( "file info" ))
5694           {
5695             aDataset = new HDFdataset( "file info", aTopGroup );
5696             aDataset->OpenOnDisk();
5697             size = aDataset->GetSize();
5698             std::string info( size, ' ');
5699             aDataset->ReadFromDisk( (char*) info.data() );
5700             aDataset->CloseOnDisk();
5701             myNewMeshImpl->FileInfoFromString( info );
5702           }
5703         }
5704       }
5705     } // reading MESHes
5706
5707     // As all objects that can be referred by hypothesis are created,
5708     // we can restore hypothesis data
5709
5710     list< pair< SMESH_Hypothesis_i*, string > >::iterator hyp_data;
5711     for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data )
5712     {
5713       SMESH_Hypothesis_i* hyp  = hyp_data->first;
5714       string &            data = hyp_data->second;
5715       hyp->LoadFrom( data.c_str() );
5716     }
5717
5718     // Restore the rest mesh data
5719
5720     list< pair< SMESH_Mesh_i*, HDFgroup* > >::iterator meshi_group;
5721     for ( meshi_group = meshGroupList.begin(); meshi_group != meshGroupList.end(); ++meshi_group )
5722     {
5723       aTopGroup                   = meshi_group->second;
5724       SMESH_Mesh_i* myNewMeshImpl = meshi_group->first;
5725
5726       GEOM::GEOM_Object_var aShapeObject = myNewMeshImpl->GetShapeToMesh();
5727       bool hasData = false;
5728
5729       // get mesh old id
5730       CORBA::String_var iorString = GetORB()->object_to_string( myNewMeshImpl->_this() );
5731       int newId = myStudyContext->findId( iorString.in() );
5732       int meshOldId = myStudyContext->getOldId( newId );
5733
5734       // try to find mesh data dataset
5735       if ( aTopGroup->ExistInternalObject( "Has data" ) ) {
5736         // load mesh "has data" flag
5737         aDataset = new HDFdataset( "Has data", aTopGroup );
5738         aDataset->OpenOnDisk();
5739         size = aDataset->GetSize();
5740         char* strHasData = new char[ size ];
5741         aDataset->ReadFromDisk( strHasData );
5742         aDataset->CloseOnDisk();
5743         if ( strcmp( strHasData, "1") == 0 ) {
5744           hasData = true;
5745         }
5746         delete [] strHasData;
5747       }
5748
5749       // Try to get applied ALGORITHMS (mesh is not cleared by algo addition because
5750       // nodes and elements are not yet put into sub-meshes)
5751       if ( aTopGroup->ExistInternalObject( "Applied Algorithms" ) ) {
5752         aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
5753         aGroup->OpenOnDisk();
5754         // get number of applied algorithms
5755         int aNbSubObjects = aGroup->nInternalObjects();
5756         MESSAGE( "VSR - number of applied algos " << aNbSubObjects );
5757         for ( int j = 0; j < aNbSubObjects; j++ ) {
5758           char name_dataset[ HDF_NAME_MAX_LEN+1 ];
5759           aGroup->InternalObjectIndentify( j, name_dataset );
5760           // check if it is an algorithm
5761           if ( string( name_dataset ).substr( 0, 4 ) == string( "Algo" ) ) {
5762             aDataset = new HDFdataset( name_dataset, aGroup );
5763             aDataset->OpenOnDisk();
5764             size = aDataset->GetSize();
5765             char* refFromFile = new char[ size ];
5766             aDataset->ReadFromDisk( refFromFile );
5767             aDataset->CloseOnDisk();
5768             // san - it is impossible to recover applied algorithms using their entries within Load() method
5769             int id = atoi( refFromFile );
5770             delete [] refFromFile;
5771             string anIOR = myStudyContext->getIORbyOldId( id );
5772             if ( !anIOR.empty() ) {
5773               CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
5774               if ( !CORBA::is_nil( hypObject ) ) {
5775                 SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
5776                 if ( !anHyp->_is_nil() && (!aShapeObject->_is_nil()
5777                                            || !myNewMeshImpl->HasShapeToMesh()) )
5778                   myNewMeshImpl->addHypothesis( aShapeObject, anHyp );
5779               }
5780             }
5781           }
5782         }
5783         aGroup->CloseOnDisk();
5784       }
5785
5786       // try to get applied hypotheses
5787       if ( aTopGroup->ExistInternalObject( "Applied Hypotheses" ) ) {
5788         aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup );
5789         aGroup->OpenOnDisk();
5790         // get number of applied hypotheses
5791         int aNbSubObjects = aGroup->nInternalObjects();
5792         for ( int j = 0; j < aNbSubObjects; j++ ) {
5793           char name_dataset[ HDF_NAME_MAX_LEN+1 ];
5794           aGroup->InternalObjectIndentify( j, name_dataset );
5795           // check if it is a hypothesis
5796           if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) {
5797             aDataset = new HDFdataset( name_dataset, aGroup );
5798             aDataset->OpenOnDisk();
5799             size = aDataset->GetSize();
5800             char* refFromFile = new char[ size ];
5801             aDataset->ReadFromDisk( refFromFile );
5802             aDataset->CloseOnDisk();
5803             // san - it is impossible to recover applied hypotheses using their entries within Load() method
5804             int id = atoi( refFromFile );
5805             delete [] refFromFile;
5806             string anIOR = myStudyContext->getIORbyOldId( id );
5807             if ( !anIOR.empty() ) {
5808               CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
5809               if ( !CORBA::is_nil( hypObject ) ) {
5810                 SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
5811                 if ( !anHyp->_is_nil() && (!aShapeObject->_is_nil()
5812                                            || !myNewMeshImpl->HasShapeToMesh()) )
5813                   myNewMeshImpl->addHypothesis( aShapeObject, anHyp );
5814               }
5815             }
5816           }
5817         }
5818         aGroup->CloseOnDisk();
5819       }
5820
5821       // --> try to find SUB-MESHES containers for each type of submesh
5822       for ( int j = GetSubMeshOnVertexTag(); j <= GetSubMeshOnCompoundTag(); j++ ) {
5823         const char* name_meshgroup = 0;
5824         if ( j == GetSubMeshOnVertexTag() )
5825           name_meshgroup = "SubMeshes On Vertex";
5826         else if ( j == GetSubMeshOnEdgeTag() )
5827           name_meshgroup = "SubMeshes On Edge";
5828         else if ( j == GetSubMeshOnWireTag() )
5829           name_meshgroup = "SubMeshes On Wire";
5830         else if ( j == GetSubMeshOnFaceTag() )
5831           name_meshgroup = "SubMeshes On Face";
5832         else if ( j == GetSubMeshOnShellTag() )
5833           name_meshgroup = "SubMeshes On Shell";
5834         else if ( j == GetSubMeshOnSolidTag() )
5835           name_meshgroup = "SubMeshes On Solid";
5836         else if ( j == GetSubMeshOnCompoundTag() )
5837           name_meshgroup = "SubMeshes On Compound";
5838
5839         // try to get submeshes container HDF group
5840         if ( aTopGroup->ExistInternalObject( name_meshgroup ) ) {
5841           // open submeshes containers HDF group
5842           aGroup = new HDFgroup( name_meshgroup, aTopGroup );
5843           aGroup->OpenOnDisk();
5844
5845           // get number of submeshes
5846           int aNbSubMeshes = aGroup->nInternalObjects();
5847           for ( int k = 0; k < aNbSubMeshes; k++ ) {
5848             // identify submesh
5849             char name_submeshgroup[ HDF_NAME_MAX_LEN+1 ];
5850             aGroup->InternalObjectIndentify( k, name_submeshgroup );
5851             if ( strncmp( name_submeshgroup, "SubMesh", 7 ) == 0 ) {
5852               // --> get submesh id
5853               int subid = atoi( name_submeshgroup + 7 );
5854               if ( subid <= 0 )
5855                 continue;
5856               // open submesh HDF group
5857               aSubGroup = new HDFgroup( name_submeshgroup, aGroup );
5858               aSubGroup->OpenOnDisk();
5859
5860               // try to read and set reference to subshape
5861               GEOM::GEOM_Object_var aSubShapeObject;
5862               SMESH::SMESH_subMesh_var aSubMesh;
5863
5864               if ( aSubGroup->ExistInternalObject( "Ref on shape" ) ) {
5865                 // load submesh "Ref on shape" - it's an entry to SObject
5866                 aDataset = new HDFdataset( "Ref on shape", aSubGroup );
5867                 aDataset->OpenOnDisk();
5868                 size = aDataset->GetSize();
5869                 char* refFromFile = new char[ size ];
5870                 aDataset->ReadFromDisk( refFromFile );
5871                 aDataset->CloseOnDisk();
5872                 if ( strlen( refFromFile ) > 0 ) {
5873                   SALOMEDS::SObject_wrap subShapeSO = aStudy->FindObjectID( refFromFile );
5874                   CORBA::Object_var subShapeObject = SObjectToObject( subShapeSO );
5875                   if ( !CORBA::is_nil( subShapeObject ) ) {
5876                     aSubShapeObject = GEOM::GEOM_Object::_narrow( subShapeObject );
5877                     if ( !aSubShapeObject->_is_nil() )
5878                       aSubMesh = SMESH::SMESH_subMesh::_duplicate
5879                         ( myNewMeshImpl->createSubMesh( aSubShapeObject ) );
5880                     if ( aSubMesh->_is_nil() )
5881                       continue;
5882                     string iorSubString = GetORB()->object_to_string( aSubMesh );
5883                     int        newSubId = myStudyContext->findId( iorSubString );
5884                     myStudyContext->mapOldToNew( subid, newSubId );
5885                   }
5886                 }
5887                 delete [] refFromFile;
5888               }
5889
5890               if ( aSubMesh->_is_nil() )
5891                 continue;
5892
5893               // try to get applied algorithms
5894               if ( aSubGroup->ExistInternalObject( "Applied Algorithms" ) ) {
5895                 // open "applied algorithms" HDF group
5896                 aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup );
5897                 aSubSubGroup->OpenOnDisk();
5898                 // get number of applied algorithms
5899                 int aNbSubObjects = aSubSubGroup->nInternalObjects();
5900                 for ( int l = 0; l < aNbSubObjects; l++ ) {
5901                   char name_dataset[ HDF_NAME_MAX_LEN+1 ];
5902                   aSubSubGroup->InternalObjectIndentify( l, name_dataset );
5903                   // check if it is an algorithm
5904                   if ( strncmp( name_dataset, "Algo", 4 ) == 0 ) {
5905                     aDataset = new HDFdataset( name_dataset, aSubSubGroup );
5906                     aDataset->OpenOnDisk();
5907                     size = aDataset->GetSize();
5908                     char* refFromFile = new char[ size ];
5909                     aDataset->ReadFromDisk( refFromFile );
5910                     aDataset->CloseOnDisk();
5911
5912                     int id = atoi( refFromFile );
5913                     string anIOR = myStudyContext->getIORbyOldId( id );
5914                     if ( !anIOR.empty() ) {
5915                       CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
5916                       if ( !CORBA::is_nil( hypObject ) ) {
5917                         SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
5918                         if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
5919                           myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
5920                       }
5921                     }
5922                     delete [] refFromFile;
5923                   }
5924                 }
5925                 // close "applied algorithms" HDF group
5926                 aSubSubGroup->CloseOnDisk();
5927               }
5928
5929               // try to get applied hypotheses
5930               if ( aSubGroup->ExistInternalObject( "Applied Hypotheses" ) ) {
5931                 // open "applied hypotheses" HDF group
5932                 aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup );
5933                 aSubSubGroup->OpenOnDisk();
5934                 // get number of applied hypotheses
5935                 int aNbSubObjects = aSubSubGroup->nInternalObjects();
5936                 for ( int l = 0; l < aNbSubObjects; l++ ) {
5937                   char name_dataset[ HDF_NAME_MAX_LEN+1 ];
5938                   aSubSubGroup->InternalObjectIndentify( l, name_dataset );
5939                   // check if it is a hypothesis
5940                   if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) {
5941                     aDataset = new HDFdataset( name_dataset, aSubSubGroup );
5942                     aDataset->OpenOnDisk();
5943                     size = aDataset->GetSize();
5944                     char* refFromFile = new char[ size ];
5945                     aDataset->ReadFromDisk( refFromFile );
5946                     aDataset->CloseOnDisk();
5947
5948                     int id = atoi( refFromFile );
5949                     string anIOR = myStudyContext->getIORbyOldId( id );
5950                     if ( !anIOR.empty() ) {
5951                       CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() );
5952                       if ( !CORBA::is_nil( hypObject ) ) {
5953                         SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject );
5954                         if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() )
5955                           myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
5956                       }
5957                     }
5958                     delete [] refFromFile;
5959                   }
5960                 }
5961                 // close "APPLIED HYPOTHESES" hdf group
5962                 aSubSubGroup->CloseOnDisk();
5963               }
5964
5965               // close SUB-MESH hdf group
5966               aSubGroup->CloseOnDisk();
5967             }
5968           }
5969           // close SUB-MESHES containers hdf group
5970           aGroup->CloseOnDisk();
5971         }
5972       }
5973
5974       // try to get GROUPS
5975       for ( int ii = GetNodeGroupsTag(); ii <= GetBallElementsGroupsTag(); ii++ ) {
5976         char name_group[ 30 ];
5977         if ( ii == GetNodeGroupsTag() )
5978           strcpy( name_group, "Groups of Nodes" );
5979         else if ( ii == GetEdgeGroupsTag() )
5980           strcpy( name_group, "Groups of Edges" );
5981         else if ( ii == GetFaceGroupsTag() )
5982           strcpy( name_group, "Groups of Faces" );
5983         else if ( ii == GetVolumeGroupsTag() )
5984           strcpy( name_group, "Groups of Volumes" );
5985         else if ( ii == Get0DElementsGroupsTag() )
5986           strcpy( name_group, "Groups of 0D Elements" );
5987         else if ( ii == GetBallElementsGroupsTag() )
5988           strcpy( name_group, "Groups of Balls" );
5989
5990         if ( aTopGroup->ExistInternalObject( name_group ) ) {
5991           aGroup = new HDFgroup( name_group, aTopGroup );
5992           aGroup->OpenOnDisk();
5993           // PAL23514: get all names from the HDFgroup to avoid iteration on its contents
5994           // within aGroup->ExistInternalObject( name )
5995           std::vector< std::string > subNames;
5996           TColStd_MapOfAsciiString mapOfNames;
5997           aGroup->GetAllObjects( subNames );
5998           for ( size_t iN = 0; iN < subNames.size(); ++iN )
5999             mapOfNames.Add( subNames[ iN ].c_str() );
6000           // loop on groups
6001           for ( size_t j = 0; j < subNames.size(); j++ ) {
6002             const std::string& name_dataset = subNames[ j ];
6003             // check if it is a group
6004             if ( name_dataset.substr( 0, 5 ) == "Group" ) {
6005               // --> get group id
6006               char * endptr;
6007               int subid = strtol( name_dataset.data() + 5, &endptr, 10 );
6008               if ( subid <= 0 )
6009                 continue;
6010               int groupID = -1; // group local ID (also persistent)
6011               if ( *endptr )
6012                 groupID = atoi( endptr + 1 );
6013               aDataset = new HDFdataset( name_dataset.c_str(), aGroup );
6014               aDataset->OpenOnDisk();
6015
6016               // Retrieve actual group name
6017               size = aDataset->GetSize();
6018               char* nameFromFile = new char[ size ];
6019               aDataset->ReadFromDisk( nameFromFile );
6020               aDataset->CloseOnDisk();
6021
6022               // Try to find a shape reference
6023               TopoDS_Shape aShape;
6024               char aRefName[ 30 ];
6025               sprintf( aRefName, "Ref on shape %d", subid);
6026               if ( mapOfNames.Contains( aRefName ))
6027               {
6028                 // load mesh "Ref on shape" - it's an entry to SObject
6029                 aDataset = new HDFdataset( aRefName, aGroup );
6030                 aDataset->OpenOnDisk();
6031                 size = aDataset->GetSize();
6032                 char* refFromFile = new char[ size ];
6033                 aDataset->ReadFromDisk( refFromFile );
6034                 aDataset->CloseOnDisk();
6035                 if ( strlen( refFromFile ) > 0 ) {
6036                   SALOMEDS::SObject_wrap shapeSO = aStudy->FindObjectID( refFromFile );
6037                   CORBA::Object_var shapeObject = SObjectToObject( shapeSO );
6038                   if ( !CORBA::is_nil( shapeObject ) ) {
6039                     aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
6040                     if ( !aShapeObject->_is_nil() )
6041                       aShape = GeomObjectToShape( aShapeObject );
6042                   }
6043                 }
6044                 delete [] refFromFile;
6045               }
6046               // Try to read a filter of SMESH_GroupOnFilter
6047               SMESH::Filter_var filter;
6048               SMESH_PredicatePtr predicate;
6049               std::string hdfGrpName = ( SMESH_Comment( "Filter ") << subid );
6050               if ( mapOfNames.Contains( hdfGrpName.c_str() ))
6051               {
6052                 aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup );
6053                 aDataset->OpenOnDisk();
6054                 size = aDataset->GetSize();
6055                 char* persistStr = new char[ size ];
6056                 aDataset->ReadFromDisk( persistStr );
6057                 aDataset->CloseOnDisk();
6058                 if ( strlen( persistStr ) > 0 ) {
6059                   filter = SMESH_GroupOnFilter_i::StringToFilter( persistStr );
6060                   predicate = SMESH_GroupOnFilter_i::GetPredicate( filter );
6061                   filters.push_back( filter );
6062                 }
6063                 delete [] persistStr;
6064               }
6065
6066               // Create group servant
6067               SMESH::ElementType type = (SMESH::ElementType)(ii - GetNodeGroupsTag() + 1);
6068               SMESH::SMESH_GroupBase_var aNewGroup = SMESH::SMESH_GroupBase::_duplicate
6069                 ( myNewMeshImpl->createGroup( type, nameFromFile, groupID, aShape, predicate ) );
6070               delete [] nameFromFile;
6071               // Obtain a SMESHDS_Group object
6072               if ( aNewGroup->_is_nil() )
6073                 continue;
6074
6075               CORBA::String_var iorSubStringVar = GetORB()->object_to_string( aNewGroup );
6076               string iorSubString(iorSubStringVar.in());
6077               int        newSubId = myStudyContext->findId( iorSubString );
6078               myStudyContext->mapOldToNew( subid, newSubId );
6079
6080               SMESH_GroupBase_i* aGroupImpl = SMESH::DownCast< SMESH_GroupBase_i*>( aNewGroup );
6081               if ( !aGroupImpl )
6082                 continue;
6083
6084               if ( SMESH_GroupOnFilter_i* aFilterGroup =
6085                    dynamic_cast< SMESH_GroupOnFilter_i*>( aGroupImpl ))
6086               {
6087                 aFilterGroup->SetFilter( filter );
6088                 filter->UnRegister();
6089               }
6090               SMESHDS_GroupBase* aGroupBaseDS = aGroupImpl->GetGroupDS();
6091               if ( !aGroupBaseDS )
6092                 continue;
6093
6094               aGroupBaseDS->SetStoreName( name_dataset.c_str() );
6095
6096               // ouv : NPAL12872
6097               // Read color of the group
6098               char aGroupColorName[ 30 ];
6099               sprintf( aGroupColorName, "ColorGroup %d", subid);
6100               if ( mapOfNames.Contains( aGroupColorName ))
6101               {
6102                 aDataset = new HDFdataset( aGroupColorName, aGroup );
6103                 aDataset->OpenOnDisk();
6104                 size = aDataset->GetSize();
6105                 double* anRGB = new double[ size ];
6106                 aDataset->ReadFromDisk( anRGB );
6107                 aDataset->CloseOnDisk();
6108                 Quantity_Color aColor( anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB );
6109                 aGroupBaseDS->SetColor( aColor );
6110                 delete [] anRGB;
6111               }
6112             }
6113           }
6114           aGroup->CloseOnDisk();
6115         }
6116       } // reading GROUPs
6117
6118       // instead of reading mesh data, we read only brief information of all
6119       // objects: mesh, groups, sub-meshes (issue 0021208)
6120       if ( hasData )
6121       {
6122         SMESH_PreMeshInfo::LoadFromFile( myNewMeshImpl, meshOldId,
6123                                          meshfile.ToCString(), filename.ToCString(),
6124                                          !isMultiFile );
6125       }
6126
6127       // read Sub-Mesh ORDER if any
6128       if ( aTopGroup->ExistInternalObject( "Mesh Order" )) { // old version keeps ids
6129         aDataset = new HDFdataset( "Mesh Order", aTopGroup );
6130         aDataset->OpenOnDisk();
6131         size = aDataset->GetSize();
6132         int* smIDs = new int[ size ];
6133         aDataset->ReadFromDisk( smIDs );
6134         aDataset->CloseOnDisk();
6135         TListOfListOfInt anOrderIds;
6136         anOrderIds.push_back( TListOfInt() );
6137         for ( int i = 0; i < size; i++ )
6138           if ( smIDs[ i ] < 0 ) // is separator
6139             anOrderIds.push_back( TListOfInt() );
6140           else
6141             anOrderIds.back().push_back(smIDs[ i ]);
6142
6143         myNewMeshImpl->GetImpl().SetMeshOrder( anOrderIds );
6144         delete [] smIDs;
6145       }
6146       if ( aTopGroup->ExistInternalObject( "MeshOrder_new" )) // new version keeps entries
6147       {
6148         aDataset = new HDFdataset( "MeshOrder_new", aTopGroup );
6149         aDataset->OpenOnDisk();
6150         size = aDataset->GetSize();
6151         std::string dataString; dataString.resize( size );
6152         aDataset->ReadFromDisk((char*) dataString.data() );
6153         aDataset->CloseOnDisk();
6154
6155         std::list< std::list< std::string > > orderEntryLists;
6156         SMESHUtils::BoostTxtArchive( dataString ) >> orderEntryLists;
6157
6158         TListOfListOfInt anOrderIds;
6159         for ( const std::list< std::string >& entryList : orderEntryLists )
6160         {
6161           anOrderIds.emplace_back();
6162           for ( const std::string & entry : entryList )
6163           {
6164             GEOM::GEOM_Object_var go = GetGeomObjectByEntry( entry );
6165             TopoDS_Shape       shape = GeomObjectToShape( go );
6166             if ( SMESH_subMesh*   sm = myNewMeshImpl->GetImpl().GetSubMesh( shape ))
6167               anOrderIds.back().emplace_back( sm->GetId() );
6168           }
6169         }
6170         myNewMeshImpl->GetImpl().SetMeshOrder( anOrderIds );
6171       }
6172     } // loop on meshes
6173
6174     // update hyps needing full mesh data restored (issue 20918)
6175     for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data )
6176     {
6177       SMESH_Hypothesis_i* hyp  = hyp_data->first;
6178       hyp->UpdateAsMeshesRestored();
6179     }
6180
6181     // notify algos on completed restoration to set sub-mesh event listeners
6182     for ( meshi_group = meshGroupList.begin(); meshi_group != meshGroupList.end(); ++meshi_group )
6183     {
6184       SMESH_Mesh_i* myNewMeshImpl = meshi_group->first;
6185       ::SMESH_Mesh& myLocMesh     = myNewMeshImpl->GetImpl();
6186
6187       TopoDS_Shape myLocShape;
6188       if(myLocMesh.HasShapeToMesh())
6189         myLocShape = myLocMesh.GetShapeToMesh();
6190       else
6191         myLocShape = SMESH_Mesh::PseudoShape();
6192
6193       myLocMesh.GetSubMesh(myLocShape)->
6194         ComputeStateEngine (SMESH_subMesh::SUBMESH_RESTORED);
6195     }
6196
6197     // let filters detect dependency on mesh groups via FT_BelongToMeshGroup predicate (22877)
6198     list< SMESH::Filter_var >::iterator f = filters.begin();
6199     for ( ; f != filters.end(); ++f )
6200       if ( SMESH::Filter_i * fi = SMESH::DownCast< SMESH::Filter_i*>( *f ))
6201         fi->FindBaseObjects();
6202
6203
6204     // close mesh group
6205     if(aTopGroup)
6206       aTopGroup->CloseOnDisk();
6207   }
6208   // close HDF file
6209   aFile->CloseOnDisk();
6210   delete aFile;
6211
6212   // Remove temporary files created from the stream
6213   if ( !isMultiFile )
6214   {
6215     SMESH_File meshFile( meshfile.ToCString() );
6216     if ( !meshFile ) // no meshfile exists
6217     {
6218       SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq, true );
6219     }
6220     else
6221     {
6222       Engines::Container_var container = GetContainerRef();
6223       if ( Engines_Container_i* container_i = SMESH::DownCast<Engines_Container_i*>( container ))
6224       {
6225         container_i->registerTemporaryFile( filename.ToCString() );
6226         container_i->registerTemporaryFile( meshfile.ToCString() );
6227         container_i->registerTemporaryFile( tmpDir.ToCString() );
6228       }
6229     }
6230   }
6231
6232   // creation of tree nodes for all data objects in the study
6233   // to support tree representation customization and drag-n-drop:
6234   SALOMEDS::UseCaseBuilder_wrap useCaseBuilder = aStudy->GetUseCaseBuilder();
6235   if ( !useCaseBuilder->IsUseCaseNode( theComponent ) ) {
6236     useCaseBuilder->SetRootCurrent();
6237     useCaseBuilder->Append( theComponent ); // component object is added as the top level item
6238     SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( theComponent );
6239     for (it->InitEx(true); it->More(); it->Next()) {
6240       useCaseBuilder->AppendTo( it->Value()->GetFather(), it->Value() );
6241     }
6242   }
6243
6244   return true;
6245 }
6246
6247 //=============================================================================
6248 /*!
6249  *  SMESH_Gen_i::LoadASCII
6250  *
6251  *  Load SMESH module's data in ASCII format
6252  */
6253 //=============================================================================
6254
6255 bool SMESH_Gen_i::LoadASCII( SALOMEDS::SComponent_ptr theComponent,
6256                              const SALOMEDS::TMPFile& theStream,
6257                              const char*              theURL,
6258                              bool                     isMultiFile ) {
6259   MESSAGE( "SMESH_Gen_i::LoadASCII" );
6260   return Load( theComponent, theStream, theURL, isMultiFile );
6261
6262   //before call main ::Load method it's need for decipher text format to
6263   //binary ( "|xx" => x' )
6264   int size = theStream.length();
6265   if ( int((size / 3 )*3) != size ) //error size of buffer
6266     return false;
6267
6268   int real_size = int(size / 3);
6269
6270   _CORBA_Octet* buffer = new _CORBA_Octet[real_size];
6271   char tmp[3];
6272   tmp[2]='\0';
6273   unsigned int c = -1;
6274   for ( int i = 0; i < real_size; i++ )
6275   {
6276     memcpy( &(tmp[0]), &(theStream[i*3+1]), 2 );
6277     sscanf( tmp, "%x", &c );
6278     sprintf( (char*)&(buffer[i]), "%c", (char)c );
6279   }
6280
6281   SALOMEDS::TMPFile_var aRealStreamFile = new SALOMEDS::TMPFile(real_size, real_size, buffer, 1);
6282
6283   return Load( theComponent, *(aRealStreamFile._retn()), theURL, isMultiFile );
6284 }
6285
6286 //=============================================================================
6287 /*!
6288  *  SMESH_Gen_i::Close
6289  *
6290  *  Clears study-connected data when it is closed
6291  */
6292 //=============================================================================
6293
6294 void SMESH_Gen_i::Close( SALOMEDS::SComponent_ptr theComponent )
6295 {
6296   MESSAGE( "SMESH_Gen_i::Close" );
6297
6298   // Clear study contexts data
6299   myStudyContext->Clear();
6300
6301   // remove the tmp files meshes are loaded from
6302   SMESH_PreMeshInfo::RemoveStudyFiles_TMP_METHOD( theComponent );
6303
6304   // Clean trace of API methods calls
6305   CleanPythonTrace();
6306
6307   return;
6308 }
6309
6310 //=============================================================================
6311 /*!
6312  *  SMESH_Gen_i::ComponentDataType
6313  *
6314  *  Get component data type
6315  */
6316 //=============================================================================
6317
6318 char* SMESH_Gen_i::ComponentDataType()
6319 {
6320   MESSAGE( "SMESH_Gen_i::ComponentDataType" );
6321   return CORBA::string_dup( "SMESH" );
6322 }
6323
6324
6325 //=============================================================================
6326 /*!
6327  *  SMESH_Gen_i::IORToLocalPersistentID
6328  *
6329  *  Transform data from transient form to persistent
6330  */
6331 //=============================================================================
6332
6333 char* SMESH_Gen_i::IORToLocalPersistentID( SALOMEDS::SObject_ptr /*theSObject*/,
6334                                            const char*           IORString,
6335                                            CORBA::Boolean        /*isMultiFile*/,
6336                                            CORBA::Boolean        /*isASCII*/ )
6337 {
6338   MESSAGE( "SMESH_Gen_i::IORToLocalPersistentID" );
6339
6340   if ( myStudyContext && strcmp( IORString, "" ) != 0 ) {
6341     int anId = myStudyContext->findId( IORString );
6342     if ( anId ) {
6343       MESSAGE( "VSR " << anId );
6344       char strId[ 20 ];
6345       sprintf( strId, "%d", anId );
6346       return  CORBA::string_dup( strId );
6347     }
6348   }
6349   return CORBA::string_dup( "" );
6350 }
6351
6352 //=============================================================================
6353 /*!
6354  *  SMESH_Gen_i::LocalPersistentIDToIOR
6355  *
6356  *  Transform data from persistent form to transient
6357  */
6358 //=============================================================================
6359
6360 char* SMESH_Gen_i::LocalPersistentIDToIOR( SALOMEDS::SObject_ptr /*theSObject*/,
6361                                            const char*           aLocalPersistentID,
6362                                            CORBA::Boolean        /*isMultiFile*/,
6363                                            CORBA::Boolean        /*isASCII*/ )
6364 {
6365   MESSAGE( "SMESH_Gen_i::LocalPersistentIDToIOR(): id = " << aLocalPersistentID );
6366
6367   if ( myStudyContext && strcmp( aLocalPersistentID, "" ) != 0 ) {
6368     int anId = atoi( aLocalPersistentID );
6369     return CORBA::string_dup( myStudyContext->getIORbyOldId( anId ).c_str() );
6370   }
6371   return CORBA::string_dup( "" );
6372 }
6373
6374 //=======================================================================
6375 //function : RegisterObject
6376 //purpose  :
6377 //=======================================================================
6378
6379 int SMESH_Gen_i::RegisterObject(CORBA::Object_ptr theObject)
6380 {
6381   if ( myStudyContext && !CORBA::is_nil( theObject )) {
6382     CORBA::String_var iorString = GetORB()->object_to_string( theObject );
6383     return myStudyContext->addObject( string( iorString.in() ) );
6384   }
6385   return 0;
6386 }
6387
6388 //================================================================================
6389 /*!
6390  * \brief Return id of registered object
6391   * \param theObject - the Object
6392   * \retval int - Object id
6393  */
6394 //================================================================================
6395
6396 CORBA::Long  SMESH_Gen_i::GetObjectId(CORBA::Object_ptr theObject)
6397 {
6398   if ( myStudyContext && !CORBA::is_nil( theObject )) {
6399     CORBA::String_var iorString = GetORB()->object_to_string( theObject );
6400     string iorStringCpp(iorString.in());
6401     return myStudyContext->findId( iorStringCpp );
6402   }
6403   return 0;
6404 }
6405
6406 //=============================================================================
6407 /*!
6408  *  SMESH_Gen_i::SetName
6409  *
6410  *  Set a new object name
6411  */
6412 //=============================================================================
6413
6414 void SMESH_Gen_i::SetName(const char* theIOR,
6415                           const char* theName)
6416 {
6417   if ( theIOR && strcmp( theIOR, "" ) ) {
6418     CORBA::Object_var anObject = GetORB()->string_to_object( theIOR );
6419     SALOMEDS::SObject_wrap aSO = ObjectToSObject( anObject );
6420     if ( !aSO->_is_nil() ) {
6421       SetName( aSO, theName );
6422     }
6423   }
6424 }
6425
6426 // Version information
6427 char* SMESH_Gen_i::getVersion()
6428 {
6429 #if SMESH_DEVELOPMENT
6430   return CORBA::string_dup(SMESH_VERSION_STR"dev");
6431 #else
6432   return CORBA::string_dup(SMESH_VERSION_STR);
6433 #endif
6434 }
6435
6436 //=================================================================================
6437 // function : Move()
6438 // purpose  : Moves objects to the specified position.
6439 //            Is used in the drag-n-drop functionality.
6440 //=================================================================================
6441
6442 void SMESH_Gen_i::Move( const SMESH::sobject_list& what,
6443                         SALOMEDS::SObject_ptr      where,
6444                         CORBA::Long                row )
6445 {
6446   if ( CORBA::is_nil( where ) ) return;
6447
6448   SALOMEDS::StudyBuilder_var studyBuilder = getStudyServant()->NewBuilder();
6449   SALOMEDS::UseCaseBuilder_var useCaseBuilder = getStudyServant()->GetUseCaseBuilder();
6450   SALOMEDS::SComponent_var father = where->GetFatherComponent();
6451   std::string dataType = father->ComponentDataType();
6452   if ( dataType != "SMESH" ) return; // not a SMESH component
6453
6454   SALOMEDS::SObject_var objAfter;
6455   if ( row >= 0 && useCaseBuilder->HasChildren( where ) ) {
6456     // insert at given row -> find insertion position
6457     SALOMEDS::UseCaseIterator_var useCaseIt = useCaseBuilder->GetUseCaseIterator( where );
6458     int i;
6459     for ( i = 0; i < row && useCaseIt->More(); i++, useCaseIt->Next() );
6460     if ( i == row && useCaseIt->More() ) {
6461       objAfter = useCaseIt->Value();
6462     }
6463   }
6464
6465   for ( CORBA::ULong i = 0; i < what.length(); i++ ) {
6466     SALOMEDS::SObject_var sobj = what[i];
6467     if ( CORBA::is_nil( sobj ) ) continue; // skip bad object
6468     // insert the object to the use case tree
6469     if ( !CORBA::is_nil( objAfter ) )
6470       useCaseBuilder->InsertBefore( sobj, objAfter ); // insert at given row
6471     else
6472       useCaseBuilder->AppendTo( where, sobj );        // append to the end of list
6473   }
6474 }
6475
6476 //================================================================================
6477 /*!
6478  * \brief Collect indices of elements, which are located inside the sphere
6479  */
6480 //================================================================================
6481
6482 SMESH::long_array* SMESH_Gen_i::GetInsideSphere( SMESH::SMESH_IDSource_ptr meshPart,
6483                                                  SMESH::ElementType     theElemType,
6484                                                  CORBA::Double         theX,
6485                                                  CORBA::Double         theY,
6486                                                  CORBA::Double         theZ,
6487                                                  CORBA::Double         theR)
6488 {
6489   SMESH::long_array_var aResult = new SMESH::long_array();
6490   if ( meshPart->_is_nil() )
6491     return aResult._retn();
6492
6493   // 1. Create geometrical object
6494   gp_Pnt aP( theX, theY, theZ );
6495   TopoDS_Shape aShape = BRepPrimAPI_MakeSphere( aP, theR ).Shape();
6496
6497   std::vector<long> lst =_GetInside(meshPart, theElemType, aShape);
6498
6499   if ( lst.size() > 0 ) {
6500     aResult->length( lst.size() );
6501     for ( size_t i = 0; i < lst.size(); i++ ) {
6502       aResult[i] = lst[i];
6503     }
6504   }
6505   return aResult._retn();
6506 }
6507
6508 //================================================================================
6509 /*!
6510  * \brief Collect indices of elements, which are located inside the box
6511  */
6512 //================================================================================
6513
6514 SMESH::long_array* SMESH_Gen_i::GetInsideBox( SMESH::SMESH_IDSource_ptr meshPart,
6515                                               SMESH::ElementType        theElemType,
6516                                               CORBA::Double             theX1,
6517                                               CORBA::Double             theY1,
6518                                               CORBA::Double             theZ1,
6519                                               CORBA::Double             theX2,
6520                                               CORBA::Double             theY2,
6521                                               CORBA::Double             theZ2)
6522 {
6523   SMESH::long_array_var aResult = new SMESH::long_array();
6524   if( meshPart->_is_nil() )
6525     return aResult._retn();
6526
6527   TopoDS_Shape aShape = BRepPrimAPI_MakeBox( gp_Pnt( theX1, theY1, theZ1 ),
6528                                              gp_Pnt( theX2, theY2, theZ2 ) ).Shape();
6529
6530   std::vector<long> lst =_GetInside(meshPart, theElemType, aShape);
6531
6532   if( lst.size() > 0 ) {
6533     aResult->length( lst.size() );
6534     for ( size_t i = 0; i < lst.size(); i++ ) {
6535       aResult[i] = lst[i];
6536     }
6537   }
6538   return aResult._retn();
6539 }
6540
6541 //================================================================================
6542 /*!
6543  * \brief Collect indices of elements, which are located inside the cylinder
6544  */
6545 //================================================================================
6546
6547 SMESH::long_array* SMESH_Gen_i::GetInsideCylinder( SMESH::SMESH_IDSource_ptr meshPart,
6548                                                    SMESH::ElementType        theElemType,
6549                                                    CORBA::Double             theX,
6550                                                    CORBA::Double             theY,
6551                                                    CORBA::Double             theZ,
6552                                                    CORBA::Double             theDX,
6553                                                    CORBA::Double             theDY,
6554                                                    CORBA::Double             theDZ,
6555                                                    CORBA::Double             theH,
6556                                                    CORBA::Double             theR )
6557 {
6558   SMESH::long_array_var aResult = new SMESH::long_array();
6559   if( meshPart->_is_nil() )
6560     return aResult._retn();
6561
6562   gp_Pnt aP( theX, theY, theZ );
6563   gp_Vec aV( theDX, theDY, theDZ );
6564   gp_Ax2 anAxes (aP, aV);
6565
6566   TopoDS_Shape aShape = BRepPrimAPI_MakeCylinder(anAxes, theR, Abs(theH)).Shape();
6567
6568   std::vector<long> lst =_GetInside(meshPart, theElemType, aShape);
6569
6570   if( lst.size() > 0 ) {
6571     aResult->length( lst.size() );
6572     for ( size_t i = 0; i < lst.size(); i++ ) {
6573       aResult[i] = lst[i];
6574     }
6575   }
6576   return aResult._retn();
6577 }
6578
6579 //================================================================================
6580 /*!
6581  * \brief Collect indices of elements, which are located inside the geom object
6582  */
6583 //================================================================================
6584
6585 SMESH::long_array* SMESH_Gen_i::GetInside( SMESH::SMESH_IDSource_ptr meshPart,
6586                                            SMESH::ElementType        theElemType,
6587                                            GEOM::GEOM_Object_ptr     theGeom,
6588                                            CORBA::Double             theTolerance )
6589 {
6590   SMESH::long_array_var aResult = new SMESH::long_array();
6591   if( meshPart->_is_nil() || theGeom->_is_nil() )
6592     return aResult._retn();
6593
6594   TopoDS_Shape aShape = GeomObjectToShape( theGeom );
6595
6596   std::vector<long> lst =_GetInside(meshPart, theElemType, aShape, &theTolerance);
6597
6598   if( lst.size() > 0 ) {
6599     aResult->length( lst.size() );
6600     for ( size_t i = 0; i < lst.size(); i++ ) {
6601       aResult[i] = lst[i];
6602     }
6603   }
6604   return aResult._retn();
6605 }
6606
6607 //================================================================================
6608 /*!
6609  * \brief Collect indices of elements, which are located inside the TopoDS_Shape
6610  */
6611 //================================================================================
6612
6613 std::vector<long> SMESH_Gen_i::_GetInside( SMESH::SMESH_IDSource_ptr meshPart,
6614                                            SMESH::ElementType        theElemType,
6615                                            const TopoDS_Shape&       theShape,
6616                                            double*                   theTolerance) {
6617
6618   std::vector<long> res;
6619   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
6620
6621   if ( mesh->_is_nil() )
6622     return res;
6623
6624   SMESH_Mesh_i* anImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
6625   if ( !anImpl )
6626     return res;
6627
6628   const SMDS_Mesh* meshDS = anImpl->GetImpl().GetMeshDS();
6629
6630   if ( !meshDS )
6631     return res;
6632
6633   SMDSAbs_ElementType aType = SMDSAbs_ElementType(theElemType);
6634   SMESH::Controls::ElementsOnShape* anElementsOnShape = new SMESH::Controls::ElementsOnShape();
6635   anElementsOnShape->SetAllNodes( true );
6636   anElementsOnShape->SetMesh( meshDS );
6637   anElementsOnShape->SetShape( theShape, aType );
6638
6639   if(theTolerance)
6640     anElementsOnShape->SetTolerance(*theTolerance);
6641
6642   SMESH::SMESH_Mesh_var msource = SMESH::SMESH_Mesh::_narrow(meshPart);
6643   if ( !msource->_is_nil() ) { // Mesh case
6644     SMDS_ElemIteratorPtr elemIt = meshDS->elementsIterator( aType );
6645     if ( elemIt ) {
6646       while ( elemIt->more() ) {
6647         const SMDS_MeshElement* anElem = elemIt->next();
6648         long anId = anElem->GetID();
6649         if ( anElementsOnShape->IsSatisfy( anId ) )
6650           res.push_back( anId );
6651       }
6652     }
6653   }
6654   SMESH::SMESH_Group_var gsource = SMESH::SMESH_Group::_narrow(meshPart);
6655   if ( !gsource->_is_nil() ) {
6656     if(theElemType == SMESH::NODE) {
6657       SMESH::smIdType_array_var nodes = gsource->GetNodeIDs();
6658       for ( CORBA::ULong i = 0; i < nodes->length(); ++i ) {
6659         if ( const SMDS_MeshNode* node = meshDS->FindNode( nodes[i] )) {
6660           long anId = node->GetID();
6661           if ( anElementsOnShape->IsSatisfy( anId ) )
6662             res.push_back( anId );
6663         }
6664       }
6665     } else if (gsource->GetType() == theElemType || theElemType == SMESH::ALL ) {
6666       SMESH::smIdType_array_var elems = gsource->GetListOfID();
6667       for ( CORBA::ULong i = 0; i < elems->length(); ++i ) {
6668         if ( const SMDS_MeshElement* elem = meshDS->FindElement( elems[i] )) {
6669           long anId = elem->GetID();
6670           if ( anElementsOnShape->IsSatisfy( anId ) )
6671             res.push_back( anId );
6672         }
6673       }
6674     }
6675   }
6676   SMESH::SMESH_subMesh_var smsource = SMESH::SMESH_subMesh::_narrow(meshPart);
6677   if ( !smsource->_is_nil() ) {
6678     SMESH::smIdType_array_var elems = smsource->GetElementsByType( theElemType );
6679     for ( CORBA::ULong i = 0; i < elems->length(); ++i ) {
6680       const SMDS_MeshElement* elem = ( theElemType == SMESH::NODE ) ? meshDS->FindNode( elems[i] ) : meshDS->FindElement( elems[i] );
6681       if (elem) {
6682         long anId = elem->GetID();
6683         if ( anElementsOnShape->IsSatisfy( anId ) )
6684           res.push_back( anId );
6685       }
6686     }
6687   }
6688   return res;
6689 }
6690
6691 //================================================================================
6692 /*!
6693  * \brief Returns true if algorithm can be used to mesh a given geometry
6694  *  \param [in] theAlgoType - the algorithm type
6695  *  \param [in] theLibName - a name of the Plug-in library implementing the algorithm
6696  *  \param [in] theGeomObject - the geometry to mesh
6697  *  \param [in] toCheckAll - if \c True, returns \c True if all shapes are meshable,
6698  *         else, returns \c True if at least one shape is meshable
6699  *  \return CORBA::Boolean - can or can't
6700  */
6701 //================================================================================
6702
6703 #undef SMY_OWN_CATCH
6704 #define SMY_OWN_CATCH // prevent re-throwing SALOME::SALOME_Exception in IsApplicable()
6705
6706 CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char*           theAlgoType,
6707                                            const char*           theLibName,
6708                                            GEOM::GEOM_Object_ptr theGeomObject,
6709                                            CORBA::Boolean        toCheckAll)
6710 {
6711   SMESH_TRY;
6712
6713   std::string aPlatformLibName;
6714   GenericHypothesisCreator_i* aCreator =
6715     getHypothesisCreator(theAlgoType, theLibName, aPlatformLibName);
6716   if (aCreator)
6717   {
6718     TopoDS_Shape shape = GeomObjectToShape( theGeomObject );
6719     const SMESH_Algo::Features& feat = SMESH_Algo::GetFeatures( theAlgoType );
6720     return shape.IsNull() || aCreator->IsApplicable( shape, toCheckAll, feat._dim );
6721   }
6722   else
6723   {
6724     return false;
6725   }
6726
6727   SMESH_CATCH( SMESH::doNothing );
6728
6729   MESSAGE("SMESH_Gen_i::IsApplicable(): exception in " << ( theAlgoType ? theAlgoType : ""));
6730   return true;
6731 }