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