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