Salome HOME
22316: EDF 2719 SMESH: Split hexas into prisms
[modules/smesh.git] / src / SMESH_I / SMESH_Mesh_i.cxx
1 // Copyright (C) 2007-2013  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.
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_Mesh_i.cxx
23 //  Author : Paul RASCLE, EDF
24 //  Module : SMESH
25
26 #include "SMESH_Mesh_i.hxx"
27
28 #include "DriverMED_R_SMESHDS_Mesh.h"
29 #include "DriverMED_W_SMESHDS_Mesh.h"
30 #include "MED_Factory.hxx"
31 #include "SMDS_EdgePosition.hxx"
32 #include "SMDS_ElemIterator.hxx"
33 #include "SMDS_FacePosition.hxx"
34 #include "SMDS_IteratorOnIterators.hxx"
35 #include "SMDS_MeshGroup.hxx"
36 #include "SMDS_SetIterator.hxx"
37 #include "SMDS_VolumeTool.hxx"
38 #include "SMESHDS_Command.hxx"
39 #include "SMESHDS_CommandType.hxx"
40 #include "SMESHDS_Group.hxx"
41 #include "SMESHDS_GroupOnGeom.hxx"
42 #include "SMESH_Controls.hxx"
43 #include "SMESH_Filter_i.hxx"
44 #include "SMESH_Gen_i.hxx"
45 #include "SMESH_Group.hxx"
46 #include "SMESH_Group_i.hxx"
47 #include "SMESH_MeshAlgos.hxx"
48 #include "SMESH_MeshEditor.hxx"
49 #include "SMESH_MeshEditor_i.hxx"
50 #include "SMESH_MeshPartDS.hxx"
51 #include "SMESH_MesherHelper.hxx"
52 #include "SMESH_PreMeshInfo.hxx"
53 #include "SMESH_PythonDump.hxx"
54 #include "SMESH_subMesh_i.hxx"
55
56 #include <OpUtil.hxx>
57 #include <SALOMEDS_Attributes_wrap.hxx>
58 #include <SALOMEDS_wrap.hxx>
59 #include <SALOME_NamingService.hxx>
60 #include <Utils_ExceptHandlers.hxx>
61 #include <Utils_SINGLETON.hxx>
62 #include <utilities.h>
63
64 #include <GEOMImpl_Types.hxx>
65 #include <GEOM_wrap.hxx>
66
67 // OCCT Includes
68 #include <BRep_Builder.hxx>
69 #include <OSD_Directory.hxx>
70 #include <OSD_File.hxx>
71 #include <OSD_Path.hxx>
72 #include <OSD_Protection.hxx>
73 #include <Standard_OutOfMemory.hxx>
74 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
75 #include <TColStd_MapOfInteger.hxx>
76 #include <TColStd_SequenceOfInteger.hxx>
77 #include <TCollection_AsciiString.hxx>
78 #include <TopExp.hxx>
79 #include <TopExp_Explorer.hxx>
80 #include <TopTools_MapIteratorOfMapOfShape.hxx>
81 #include <TopTools_MapOfShape.hxx>
82 #include <TopoDS_Compound.hxx>
83
84 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
85
86 // STL Includes
87 #include <algorithm>
88 #include <string>
89 #include <iostream>
90 #include <sstream>
91
92 #include <sys/stat.h>
93
94 #ifdef _DEBUG_
95 static int MYDEBUG = 0;
96 #else
97 static int MYDEBUG = 0;
98 #endif
99
100 using namespace std;
101 using SMESH::TPythonDump;
102
103 int SMESH_Mesh_i::_idGenerator = 0;
104
105 //=============================================================================
106 /*!
107  *  Constructor
108  */
109 //=============================================================================
110
111 SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
112                             SMESH_Gen_i*            gen_i,
113                             CORBA::Long studyId )
114 : SALOME::GenericObj_i( thePOA )
115 {
116   MESSAGE("SMESH_Mesh_i");
117   _impl          = NULL;
118   _gen_i         = gen_i;
119   _id            = _idGenerator++;
120   _studyId       = studyId;
121   _editor        = NULL;
122   _previewEditor = NULL;
123   _preMeshInfo   = NULL;
124 }
125
126 //=============================================================================
127 /*!
128  *  Destructor
129  */
130 //=============================================================================
131
132 SMESH_Mesh_i::~SMESH_Mesh_i()
133 {
134   MESSAGE("~SMESH_Mesh_i");
135
136   // destroy groups
137   map<int, SMESH::SMESH_GroupBase_ptr>::iterator itGr;
138   for (itGr = _mapGroups.begin(); itGr != _mapGroups.end(); itGr++)
139     if (SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>(itGr->second))
140     {
141       aGroup->UnRegister();
142       SMESH::SMESH_GroupBase_var( itGr->second );
143     }
144   _mapGroups.clear();
145
146   // destroy submeshes
147   map<int, SMESH::SMESH_subMesh_ptr>::iterator itSM;
148   for ( itSM = _mapSubMeshIor.begin(); itSM != _mapSubMeshIor.end(); itSM++ )
149     if ( SMESH_subMesh_i* aSubMesh = SMESH::DownCast<SMESH_subMesh_i*>( itSM->second ))
150     {
151       aSubMesh->UnRegister();
152       SMESH::SMESH_subMesh_var( itSM->second );
153     }
154   _mapSubMeshIor.clear();
155
156   // destroy hypotheses. _mapHypo contains all hyps ever been assigned
157   map<int, SMESH::SMESH_Hypothesis_ptr>::iterator itH;
158   for ( itH = _mapHypo.begin(); itH != _mapHypo.end(); itH++ ) {
159     if ( SMESH_Hypothesis_i* hyp_i = SMESH::DownCast<SMESH_Hypothesis_i*>( itH->second ))
160       if ( SMESH_Hypothesis * smHyp = _impl->GetHypothesis( itH->first ))
161         if ( _impl->GetMeshDS()->IsUsedHypothesis( smHyp ))
162           hyp_i->UnRegister();
163
164     SMESH::SMESH_Hypothesis_var( itH->second ); // decref CORBA object
165   }
166   _mapHypo.clear();
167
168   delete _editor; _editor = NULL;
169   delete _previewEditor; _previewEditor = NULL;
170   delete _impl; _impl = NULL;
171   delete _preMeshInfo; _preMeshInfo = NULL;
172 }
173
174 //=============================================================================
175 /*!
176  *  SetShape
177  *
178  *  Associates <this> mesh with <theShape> and puts a reference
179  *  to <theShape> into the current study;
180  *  the previous shape is substituted by the new one.
181  */
182 //=============================================================================
183
184 void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
185     throw (SALOME::SALOME_Exception)
186 {
187   Unexpect aCatch(SALOME_SalomeException);
188   try {
189     _impl->ShapeToMesh( _gen_i->GeomObjectToShape( theShapeObject ));
190   }
191   catch(SALOME_Exception & S_ex) {
192     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
193   }
194   // to track changes of GEOM groups
195   SMESH::SMESH_Mesh_var mesh = _this();
196   addGeomGroupData( theShapeObject, mesh );
197 }
198
199 //================================================================================
200 /*!
201  * \brief return true if mesh has a shape to build a shape on
202  */
203 //================================================================================
204
205 CORBA::Boolean SMESH_Mesh_i::HasShapeToMesh()
206   throw (SALOME::SALOME_Exception)
207 {
208   Unexpect aCatch(SALOME_SalomeException);
209   bool res = false;
210   try {
211     res = _impl->HasShapeToMesh();
212   }
213   catch(SALOME_Exception & S_ex) {
214     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
215   }
216   return res;
217 }
218
219 //=======================================================================
220 //function : GetShapeToMesh
221 //purpose  :
222 //=======================================================================
223
224 GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
225   throw (SALOME::SALOME_Exception)
226 {
227   Unexpect aCatch(SALOME_SalomeException);
228   GEOM::GEOM_Object_var aShapeObj;
229   try {
230     TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
231     if ( !S.IsNull() )
232       aShapeObj = _gen_i->ShapeToGeomObject( S );
233   }
234   catch(SALOME_Exception & S_ex) {
235     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
236   }
237   return aShapeObj._retn();
238 }
239
240 //================================================================================
241 /*!
242  * \brief Return false if the mesh is not yet fully loaded from the study file
243  */
244 //================================================================================
245
246 CORBA::Boolean SMESH_Mesh_i::IsLoaded() throw (SALOME::SALOME_Exception)
247 {
248   Unexpect aCatch(SALOME_SalomeException);
249   return !_preMeshInfo;
250 }
251
252 //================================================================================
253 /*!
254  * \brief Load full mesh data from the study file
255  */
256 //================================================================================
257
258 void SMESH_Mesh_i::Load() throw (SALOME::SALOME_Exception)
259 {
260   Unexpect aCatch(SALOME_SalomeException);
261   if ( _preMeshInfo )
262     _preMeshInfo->FullLoadFromFile();
263 }
264
265 //================================================================================
266 /*!
267  * \brief Remove all nodes and elements
268  */
269 //================================================================================
270
271 void SMESH_Mesh_i::Clear() throw (SALOME::SALOME_Exception)
272 {
273   Unexpect aCatch(SALOME_SalomeException);
274   if ( _preMeshInfo )
275     _preMeshInfo->ForgetAllData();
276
277   try {
278     _impl->Clear();
279     CheckGeomGroupModif(); // issue 20145
280   }
281   catch(SALOME_Exception & S_ex) {
282     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
283   }
284   _impl->GetMeshDS()->Modified();
285
286   TPythonDump() <<  SMESH::SMESH_Mesh_var(_this()) << ".Clear()";
287 }
288
289 //================================================================================
290 /*!
291  * \brief Remove all nodes and elements for indicated shape
292  */
293 //================================================================================
294
295 void SMESH_Mesh_i::ClearSubMesh(CORBA::Long ShapeID)
296   throw (SALOME::SALOME_Exception)
297 {
298   Unexpect aCatch(SALOME_SalomeException);
299   if ( _preMeshInfo )
300     _preMeshInfo->FullLoadFromFile();
301
302   try {
303     _impl->ClearSubMesh( ShapeID );
304   }
305   catch(SALOME_Exception & S_ex) {
306     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
307   }
308   _impl->GetMeshDS()->Modified();
309
310   TPythonDump() <<  SMESH::SMESH_Mesh_var(_this()) << ".ClearSubMesh( " << ShapeID << " )";
311 }
312
313 //=============================================================================
314 /*!
315  * Convert enum Driver_Mesh::Status to SMESH::DriverMED_ReadStatus
316  */
317 //=============================================================================
318
319 static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
320 {
321   SMESH::DriverMED_ReadStatus res;
322   switch (theStatus)
323   {
324   case DriverMED_R_SMESHDS_Mesh::DRS_OK:
325     res = SMESH::DRS_OK; break;
326   case DriverMED_R_SMESHDS_Mesh::DRS_EMPTY:
327     res = SMESH::DRS_EMPTY; break;
328   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_RENUMBER:
329     res = SMESH::DRS_WARN_RENUMBER; break;
330   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
331     res = SMESH::DRS_WARN_SKIP_ELEM; break;
332   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_DESCENDING:
333     res = SMESH::DRS_WARN_DESCENDING; break;
334   case DriverMED_R_SMESHDS_Mesh::DRS_FAIL:
335   default:
336     res = SMESH::DRS_FAIL; break;
337   }
338   return res;
339 }
340
341 //=============================================================================
342 /*!
343  * Convert ::SMESH_ComputeError to SMESH::ComputeError
344  */
345 //=============================================================================
346
347 static SMESH::ComputeError* ConvertComputeError( SMESH_ComputeErrorPtr errorPtr )
348 {
349   SMESH::ComputeError_var errVar = new SMESH::ComputeError();
350   errVar->subShapeID = -1;
351   errVar->hasBadMesh = false;
352
353   if ( !errorPtr || errorPtr->IsOK() )
354   {
355     errVar->code = SMESH::COMPERR_OK;
356   }
357   else
358   {
359     errVar->code    = ConvertDriverMEDReadStatus( errorPtr->myName );
360     errVar->comment = errorPtr->myComment.c_str();
361   }
362   return errVar._retn();
363 }
364
365 //=============================================================================
366 /*!
367  *  ImportMEDFile
368  *
369  *  Imports mesh data from MED file
370  */
371 //=============================================================================
372
373 SMESH::DriverMED_ReadStatus
374 SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
375   throw ( SALOME::SALOME_Exception )
376 {
377   Unexpect aCatch(SALOME_SalomeException);
378   int status;
379   try {
380     status = _impl->MEDToMesh( theFileName, theMeshName );
381   }
382   catch( SALOME_Exception& S_ex ) {
383     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
384   }
385   catch ( ... ) {
386     THROW_SALOME_CORBA_EXCEPTION("ImportMEDFile(): unknown exception", SALOME::BAD_PARAM);
387   }
388
389   CreateGroupServants();
390
391   int major, minor, release;
392   if( !MED::getMEDVersion( theFileName, major, minor, release ) )
393     major = minor = release = -1;
394   _medFileInfo           = new SMESH::MedFileInfo();
395   _medFileInfo->fileName = theFileName;
396   _medFileInfo->fileSize = 0;
397   _medFileInfo->major    = major;
398   _medFileInfo->minor    = minor;
399   _medFileInfo->release  = release;
400 #ifdef WIN32
401   struct _stati64 d;
402   if ( ::_stati64( theFileName, &d ) != -1 )
403 #else
404   struct stat64 d;
405   if ( ::stat64( theFileName, &d ) != -1 )
406 #endif
407     _medFileInfo->fileSize = d.st_size;
408
409   return ConvertDriverMEDReadStatus(status);
410 }
411
412 //================================================================================
413 /*!
414  * \brief Imports mesh data from the CGNS file
415  */
416 //================================================================================
417
418 SMESH::DriverMED_ReadStatus SMESH_Mesh_i::ImportCGNSFile( const char*  theFileName,
419                                                           const int    theMeshIndex,
420                                                           std::string& theMeshName )
421   throw ( SALOME::SALOME_Exception )
422 {
423   Unexpect aCatch(SALOME_SalomeException);
424   int status;
425   try {
426     status = _impl->CGNSToMesh( theFileName, theMeshIndex, theMeshName );
427   }
428   catch( SALOME_Exception& S_ex ) {
429     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
430   }
431   catch ( ... ) {
432     THROW_SALOME_CORBA_EXCEPTION("ImportCGNSFile(): unknown exception", SALOME::BAD_PARAM);
433   }
434
435   CreateGroupServants();
436
437   return ConvertDriverMEDReadStatus(status);
438 }
439
440 //================================================================================
441 /*!
442  * \brief Return string representation of a MED file version comprising nbDigits
443  */
444 //================================================================================
445
446 char* SMESH_Mesh_i::GetVersionString(SMESH::MED_VERSION version, CORBA::Short nbDigits)
447 {
448   string ver = DriverMED_W_SMESHDS_Mesh::GetVersionString(MED::EVersion(version),
449                                                           nbDigits);
450   return CORBA::string_dup( ver.c_str() );
451 }
452
453 //=============================================================================
454 /*!
455  *  ImportUNVFile
456  *
457  *  Imports mesh data from MED file
458  */
459 //=============================================================================
460
461 int SMESH_Mesh_i::ImportUNVFile( const char* theFileName )
462   throw ( SALOME::SALOME_Exception )
463 {
464   SMESH_TRY;
465
466   // Read mesh with name = <theMeshName> into SMESH_Mesh
467   _impl->UNVToMesh( theFileName );
468
469   CreateGroupServants();
470
471   SMESH_CATCH( SMESH::throwCorbaException );
472
473   return 1;
474 }
475
476 //=============================================================================
477 /*!
478  *  ImportSTLFile
479  *
480  *  Imports mesh data from STL file
481  */
482 //=============================================================================
483 int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
484   throw ( SALOME::SALOME_Exception )
485 {
486   SMESH_TRY;
487
488   // Read mesh with name = <theMeshName> into SMESH_Mesh
489   _impl->STLToMesh( theFileName );
490
491   SMESH_CATCH( SMESH::throwCorbaException );
492
493   return 1;
494 }
495
496 //================================================================================
497 /*!
498  * \brief Function used in SMESH_CATCH by ImportGMFFile()
499  */
500 //================================================================================
501
502 namespace
503 {
504   SMESH_ComputeErrorPtr exceptionToComputeError(const char* excText)
505   {
506     return SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, excText );
507   }
508 }
509
510 //================================================================================
511 /*!
512  * \brief Imports data from a GMF file and returns an error description
513  */
514 //================================================================================
515
516 SMESH::ComputeError* SMESH_Mesh_i::ImportGMFFile( const char* theFileName,
517                                                   bool        theMakeRequiredGroups )
518   throw (SALOME::SALOME_Exception)
519 {
520   SMESH_ComputeErrorPtr error;
521
522 #undef SMESH_CAUGHT
523 #define SMESH_CAUGHT error =
524   SMESH_TRY;
525
526   error = _impl->GMFToMesh( theFileName, theMakeRequiredGroups );
527
528   SMESH_CATCH( exceptionToComputeError );
529 #undef SMESH_CAUGHT
530 #define SMESH_CAUGHT
531
532   CreateGroupServants();
533
534   return ConvertComputeError( error );
535 }
536
537 //=============================================================================
538 /*!
539  *
540  */
541 //=============================================================================
542
543 #define RETURNCASE(hyp_stat) case SMESH_Hypothesis::hyp_stat: return SMESH::hyp_stat;
544
545 SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
546                          (SMESH_Hypothesis::Hypothesis_Status theStatus)
547 {
548   switch (theStatus) {
549   RETURNCASE( HYP_OK            );
550   RETURNCASE( HYP_MISSING       );
551   RETURNCASE( HYP_CONCURENT     );
552   RETURNCASE( HYP_BAD_PARAMETER );
553   RETURNCASE( HYP_HIDDEN_ALGO   );
554   RETURNCASE( HYP_HIDING_ALGO   );
555   RETURNCASE( HYP_UNKNOWN_FATAL );
556   RETURNCASE( HYP_INCOMPATIBLE  );
557   RETURNCASE( HYP_NOTCONFORM    );
558   RETURNCASE( HYP_ALREADY_EXIST );
559   RETURNCASE( HYP_BAD_DIM       );
560   RETURNCASE( HYP_BAD_SUBSHAPE  );
561   RETURNCASE( HYP_BAD_GEOMETRY  );
562   RETURNCASE( HYP_NEED_SHAPE    );
563   default:;
564   }
565   return SMESH::HYP_UNKNOWN_FATAL;
566 }
567
568 //=============================================================================
569 /*!
570  *  AddHypothesis
571  *
572  *  calls internal addHypothesis() and then adds a reference to <anHyp> under
573  *  the SObject actually having a reference to <aSubShape>.
574  *  NB: For this method to work, it is necessary to add a reference to sub-shape first.
575  */
576 //=============================================================================
577
578 SMESH::Hypothesis_Status SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
579                                                      SMESH::SMESH_Hypothesis_ptr anHyp)
580   throw(SALOME::SALOME_Exception)
581 {
582   Unexpect aCatch(SALOME_SalomeException);
583   if ( _preMeshInfo )
584     _preMeshInfo->ForgetOrLoad();
585
586   SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShapeObject, anHyp );
587
588   SMESH::SMESH_Mesh_var mesh( _this() );
589   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
590   {
591     SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
592     _gen_i->AddHypothesisToShape( study, mesh, aSubShapeObject, anHyp );
593   }
594   if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
595
596   // Update Python script
597   //if(_impl->HasShapeToMesh())
598   {
599     TPythonDump() << "status = " << mesh << ".AddHypothesis( "
600                   << aSubShapeObject << ", " << anHyp << " )";
601   }
602   // else {
603   //   TPythonDump() << "status = " << mesh << ".AddHypothesis( "<< anHyp << " )";
604   // }
605
606   return ConvertHypothesisStatus(status);
607 }
608
609 //=============================================================================
610 /*!
611  *
612  */
613 //=============================================================================
614
615 SMESH_Hypothesis::Hypothesis_Status
616 SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
617                             SMESH::SMESH_Hypothesis_ptr anHyp)
618 {
619   if(MYDEBUG) MESSAGE("addHypothesis");
620
621   if (CORBA::is_nil( aSubShapeObject ) && HasShapeToMesh())
622     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",SALOME::BAD_PARAM);
623
624   if (CORBA::is_nil( anHyp ))
625     THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",SALOME::BAD_PARAM);
626
627   SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
628   try
629   {
630     TopoDS_Shape myLocSubShape;
631     //use PseudoShape in case if mesh has no shape
632     if(HasShapeToMesh())
633       myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject);
634     else              
635       myLocSubShape = _impl->GetShapeToMesh();
636     
637     const int hypId = anHyp->GetId();
638     status = _impl->AddHypothesis(myLocSubShape, hypId);
639     if ( !SMESH_Hypothesis::IsStatusFatal(status) ) {
640       _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( anHyp );
641       anHyp->Register();
642       // assure there is a corresponding submesh
643       if ( !_impl->IsMainShape( myLocSubShape )) {
644         int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
645         if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
646           SMESH::SMESH_subMesh_var( createSubMesh( aSubShapeObject ));
647       }
648     }
649   }
650   catch(SALOME_Exception & S_ex)
651   {
652     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
653   }
654   return status;
655 }
656
657 //=============================================================================
658 /*!
659  *
660  */
661 //=============================================================================
662
663 SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
664                                                         SMESH::SMESH_Hypothesis_ptr anHyp)
665   throw(SALOME::SALOME_Exception)
666 {
667   Unexpect aCatch(SALOME_SalomeException);
668   if ( _preMeshInfo )
669     _preMeshInfo->ForgetOrLoad();
670
671   SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShapeObject, anHyp );
672   SMESH::SMESH_Mesh_var mesh = _this();
673
674   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
675   {
676     SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
677     _gen_i->RemoveHypothesisFromShape( study, mesh, aSubShapeObject, anHyp );
678   }
679   // Update Python script
680   if(_impl->HasShapeToMesh())
681     TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
682                   << aSubShapeObject << ", " << anHyp << " )";
683   else
684     TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
685                   << anHyp << " )";
686
687   return ConvertHypothesisStatus(status);
688 }
689
690 //=============================================================================
691 /*!
692  *
693  */
694 //=============================================================================
695
696 SMESH_Hypothesis::Hypothesis_Status
697 SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
698                                SMESH::SMESH_Hypothesis_ptr anHyp)
699 {
700   if(MYDEBUG) MESSAGE("removeHypothesis()");
701
702   if (CORBA::is_nil( aSubShapeObject ) && HasShapeToMesh())
703     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
704
705   if (CORBA::is_nil( anHyp ))
706     THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference", SALOME::BAD_PARAM);
707
708   SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
709   try
710   {
711     TopoDS_Shape myLocSubShape;
712     //use PseudoShape in case if mesh has no shape
713     if( _impl->HasShapeToMesh() )
714       myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject );
715     else
716       myLocSubShape = _impl->GetShapeToMesh();
717
718     const int hypId = anHyp->GetId();
719     status = _impl->RemoveHypothesis(myLocSubShape, hypId);
720     if ( !SMESH_Hypothesis::IsStatusFatal(status) )
721     {
722       // _mapHypo.erase( hypId ); EAP: hyp can be used on many sub-shapes
723       anHyp->UnRegister();
724     }
725   }
726   catch(SALOME_Exception & S_ex)
727   {
728     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
729   }
730   return status;
731 }
732
733 //=============================================================================
734 /*!
735  *
736  */
737 //=============================================================================
738
739 SMESH::ListOfHypothesis *
740 SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShapeObject)
741 throw(SALOME::SALOME_Exception)
742 {
743   Unexpect aCatch(SALOME_SalomeException);
744   if (MYDEBUG) MESSAGE("GetHypothesisList");
745   if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShapeObject))
746     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
747
748   SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
749
750   try {
751     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
752     if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() )
753       myLocSubShape = _impl->GetShapeToMesh();
754     const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
755     int i = 0, n = aLocalList.size();
756     aList->length( n );
757
758     list<const SMESHDS_Hypothesis*>::const_iterator aHyp = aLocalList.begin();
759     std::map<int, SMESH::SMESH_Hypothesis_ptr>::iterator id_hypptr;
760     for ( ; i < n && aHyp != aLocalList.end(); aHyp++ )
761     {
762       id_hypptr = _mapHypo.find( (*aHyp)->GetID() );
763       if ( id_hypptr != _mapHypo.end() )
764         aList[i++] = SMESH::SMESH_Hypothesis::_narrow( id_hypptr->second );
765     }
766     aList->length( i );
767   }
768   catch(SALOME_Exception & S_ex) {
769     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
770   }
771
772   return aList._retn();
773 }
774
775 SMESH::submesh_array* SMESH_Mesh_i::GetSubMeshes() throw (SALOME::SALOME_Exception)
776 {
777   Unexpect aCatch(SALOME_SalomeException);
778   if (MYDEBUG) MESSAGE("GetSubMeshes");
779
780   SMESH::submesh_array_var aList = new SMESH::submesh_array();
781
782   // Python Dump
783   TPythonDump aPythonDump;
784   if ( !_mapSubMeshIor.empty() )
785     aPythonDump << "[ ";
786
787   try {
788     aList->length( _mapSubMeshIor.size() );
789     int i = 0;
790     map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.begin();
791     for ( ; it != _mapSubMeshIor.end(); it++ ) {
792       if ( CORBA::is_nil( it->second )) continue;
793       aList[i++] = SMESH::SMESH_subMesh::_duplicate( it->second );
794       // Python Dump
795       if (i > 1) aPythonDump << ", ";
796       aPythonDump << it->second;
797     }
798     aList->length( i );
799   }
800   catch(SALOME_Exception & S_ex) {
801     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
802   }
803
804   // Update Python script
805   if ( !_mapSubMeshIor.empty() )
806     aPythonDump << " ] = " << SMESH::SMESH_Mesh_var( _this() ) << ".GetSubMeshes()";
807
808   return aList._retn();
809 }
810
811 //=============================================================================
812 /*!
813  *
814  */
815 //=============================================================================
816
817 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShapeObject,
818                                                   const char*           theName )
819      throw(SALOME::SALOME_Exception)
820 {
821   Unexpect aCatch(SALOME_SalomeException);
822   if (CORBA::is_nil(aSubShapeObject))
823     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
824
825   SMESH::SMESH_subMesh_var subMesh;
826   SMESH::SMESH_Mesh_var    aMesh = _this();
827   try {
828     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
829
830     //Get or Create the SMESH_subMesh object implementation
831
832     int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
833
834     if ( !subMeshId && ! _impl->GetMeshDS()->IsGroupOfSubShapes( myLocSubShape ))
835     {
836       TopoDS_Iterator it( myLocSubShape );
837       if ( it.More() )
838         THROW_SALOME_CORBA_EXCEPTION("not sub-shape of the main shape", SALOME::BAD_PARAM);
839     }
840     subMesh = getSubMesh( subMeshId );
841
842     // create a new subMesh object servant if there is none for the shape
843     if ( subMesh->_is_nil() )
844       subMesh = createSubMesh( aSubShapeObject );
845     if ( _gen_i->CanPublishInStudy( subMesh ))
846     {
847       SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
848       SALOMEDS::SObject_wrap aSO =
849         _gen_i->PublishSubMesh( study, aMesh, subMesh, aSubShapeObject, theName );
850       if ( !aSO->_is_nil()) {
851         // Update Python script
852         TPythonDump() << aSO << " = " << aMesh << ".GetSubMesh( "
853                       << aSubShapeObject << ", '" << theName << "' )";
854       }
855     }
856   }
857   catch(SALOME_Exception & S_ex) {
858     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
859   }
860   return subMesh._retn();
861 }
862
863 //=============================================================================
864 /*!
865  *
866  */
867 //=============================================================================
868
869 void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
870   throw (SALOME::SALOME_Exception)
871 {
872   SMESH_TRY;
873
874   if ( theSubMesh->_is_nil() )
875     return;
876
877   GEOM::GEOM_Object_var aSubShapeObject;
878   SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
879   if ( !aStudy->_is_nil() )  {
880     // Remove submesh's SObject
881     SALOMEDS::SObject_wrap anSO = _gen_i->ObjectToSObject( aStudy, theSubMesh );
882     if ( !anSO->_is_nil() ) {
883       long aTag = SMESH_Gen_i::GetRefOnShapeTag();
884       SALOMEDS::SObject_wrap anObj, aRef;
885       if ( anSO->FindSubObject( aTag, anObj.inout() ) &&
886            anObj->ReferencedObject( aRef.inout() ))
887       {
888         CORBA::Object_var obj = aRef->GetObject();
889         aSubShapeObject = GEOM::GEOM_Object::_narrow( obj );
890       }
891       // if ( aSubShapeObject->_is_nil() ) // not published shape (IPAL13617)
892       //   aSubShapeObject = theSubMesh->GetSubShape();
893
894       SALOMEDS::StudyBuilder_var builder = aStudy->NewBuilder();
895       builder->RemoveObjectWithChildren( anSO );
896
897       // Update Python script
898       TPythonDump() << SMESH::SMESH_Mesh_var( _this() ) << ".RemoveSubMesh( " << anSO << " )";
899     }
900   }
901
902   if ( removeSubMesh( theSubMesh, aSubShapeObject.in() ))
903     if ( _preMeshInfo )
904       _preMeshInfo->ForgetOrLoad();
905
906   SMESH_CATCH( SMESH::throwCorbaException );
907 }
908
909 //=============================================================================
910 /*!
911  *
912  */
913 //=============================================================================
914
915 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType,
916                                                   const char*        theName )
917   throw(SALOME::SALOME_Exception)
918 {
919   Unexpect aCatch(SALOME_SalomeException);
920   if ( _preMeshInfo )
921     _preMeshInfo->FullLoadFromFile();
922
923   SMESH::SMESH_Group_var aNewGroup =
924     SMESH::SMESH_Group::_narrow( createGroup( theElemType, theName ));
925
926   if ( _gen_i->CanPublishInStudy( aNewGroup ) )
927   {
928     SMESH::SMESH_Mesh_var mesh = _this();
929     SALOMEDS::Study_var  study = _gen_i->GetCurrentStudy();
930     SALOMEDS::SObject_wrap aSO =
931       _gen_i->PublishGroup( study, mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName);
932     if ( !aSO->_is_nil())
933       // Update Python script
934       TPythonDump() << aSO << " = " << mesh << ".CreateGroup( "
935                     << theElemType << ", '" << theName << "' )";
936   }
937   return aNewGroup._retn();
938 }
939
940 //=============================================================================
941 /*!
942  *
943  */
944 //=============================================================================
945 SMESH::SMESH_GroupOnGeom_ptr
946 SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType    theElemType,
947                                    const char*           theName,
948                                    GEOM::GEOM_Object_ptr theGeomObj)
949   throw(SALOME::SALOME_Exception)
950 {
951   Unexpect aCatch(SALOME_SalomeException);
952   if ( _preMeshInfo )
953     _preMeshInfo->FullLoadFromFile();
954
955   SMESH::SMESH_GroupOnGeom_var aNewGroup;
956
957   TopoDS_Shape aShape = _gen_i->GeomObjectToShape( theGeomObj );
958   if ( !aShape.IsNull() )
959   {
960     aNewGroup = 
961       SMESH::SMESH_GroupOnGeom::_narrow( createGroup( theElemType, theName, aShape ));
962
963     if ( _gen_i->CanPublishInStudy( aNewGroup ) )
964     {
965       SMESH::SMESH_Mesh_var mesh = _this();
966       SALOMEDS::Study_var  study = _gen_i->GetCurrentStudy();
967       SALOMEDS::SObject_wrap aSO =
968         _gen_i->PublishGroup( study, mesh, aNewGroup, theGeomObj, theName );
969       if ( !aSO->_is_nil())
970         TPythonDump() << aSO << " = " << mesh << ".CreateGroupFromGEOM( "
971                       << theElemType << ", '" << theName << "', " << theGeomObj << " )";
972     }
973   }
974
975   return aNewGroup._retn();
976 }
977
978 //================================================================================
979 /*!
980  * \brief Creates a group whose contents is defined by filter
981  *  \param theElemType - group type
982  *  \param theName - group name
983  *  \param theFilter - the filter
984  *  \retval SMESH::SMESH_GroupOnFilter_ptr - group defined by filter
985  */
986 //================================================================================
987
988 SMESH::SMESH_GroupOnFilter_ptr
989 SMESH_Mesh_i::CreateGroupFromFilter(SMESH::ElementType theElemType,
990                                     const char*        theName,
991                                     SMESH::Filter_ptr  theFilter )
992   throw (SALOME::SALOME_Exception)
993 {
994   Unexpect aCatch(SALOME_SalomeException);
995   if ( _preMeshInfo )
996     _preMeshInfo->FullLoadFromFile();
997
998   if ( CORBA::is_nil( theFilter ))
999     THROW_SALOME_CORBA_EXCEPTION("NULL filter", SALOME::BAD_PARAM);
1000
1001   SMESH_PredicatePtr predicate = SMESH_GroupOnFilter_i::GetPredicate( theFilter );
1002   if ( !predicate )
1003     THROW_SALOME_CORBA_EXCEPTION("Invalid filter", SALOME::BAD_PARAM);
1004
1005   SMESH::SMESH_GroupOnFilter_var aNewGroup = SMESH::SMESH_GroupOnFilter::_narrow
1006     ( createGroup( theElemType, theName, TopoDS_Shape(), predicate ));
1007
1008   TPythonDump pd;
1009   if ( !aNewGroup->_is_nil() )
1010     aNewGroup->SetFilter( theFilter );
1011
1012   if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1013   {
1014     SMESH::SMESH_Mesh_var mesh = _this();
1015     SALOMEDS::Study_var  study = _gen_i->GetCurrentStudy();
1016     SALOMEDS::SObject_wrap aSO =
1017       _gen_i->PublishGroup( study, mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName );
1018
1019     if ( !aSO->_is_nil())
1020       pd << aSO << " = " << mesh << ".CreateGroupFromFilter( "
1021          << theElemType << ", '" << theName << "', " << theFilter << " )";
1022   }
1023   return aNewGroup._retn();
1024 }
1025
1026 //=============================================================================
1027 /*!
1028  *
1029  */
1030 //=============================================================================
1031
1032 void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
1033   throw (SALOME::SALOME_Exception)
1034 {
1035   if ( theGroup->_is_nil() )
1036     return;
1037
1038   SMESH_TRY;
1039
1040   SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
1041   if ( !aGroup )
1042     return;
1043
1044   SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
1045   if ( !aStudy->_is_nil() )
1046   {
1047     SALOMEDS::SObject_wrap aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
1048     if ( !aGroupSO->_is_nil() )
1049     {
1050       // Update Python script
1051       TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".RemoveGroup( " << aGroupSO << " )";
1052
1053       // Remove group's SObject
1054       SALOMEDS::StudyBuilder_var builder = aStudy->NewBuilder();
1055       builder->RemoveObjectWithChildren( aGroupSO );
1056     }
1057   }
1058
1059   // Remove the group from SMESH data structures
1060   removeGroup( aGroup->GetLocalID() );
1061
1062   SMESH_CATCH( SMESH::throwCorbaException );
1063 }
1064
1065 //=============================================================================
1066 /*!
1067  *  Remove group with its contents
1068  */
1069 //=============================================================================
1070
1071 void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup )
1072   throw (SALOME::SALOME_Exception)
1073 {
1074   SMESH_TRY;
1075   if ( _preMeshInfo )
1076     _preMeshInfo->FullLoadFromFile();
1077
1078   if ( theGroup->_is_nil() )
1079     return;
1080
1081   // Remove contents
1082   SMESH::SMESH_IDSource_var idSrc = SMESH::SMESH_IDSource::_narrow( theGroup );
1083   SMDS_ElemIteratorPtr     elemIt = GetElements( idSrc, theGroup->GetType() );
1084   while ( elemIt->more() )
1085     _impl->GetMeshDS()->RemoveElement( elemIt->next() );
1086
1087   TPythonDump pyDump; // Supress dump from RemoveGroup()
1088
1089   // Update Python script (theGroup must be alive for this)
1090   pyDump << SMESH::SMESH_Mesh_var(_this())
1091          << ".RemoveGroupWithContents( " << theGroup << " )";
1092
1093   // Remove group
1094   RemoveGroup( theGroup );
1095
1096   SMESH_CATCH( SMESH::throwCorbaException );
1097 }
1098
1099 //================================================================================
1100 /*!
1101  * \brief Get the list of groups existing in the mesh
1102  *  \retval SMESH::ListOfGroups * - list of groups
1103  */
1104 //================================================================================
1105
1106 SMESH::ListOfGroups * SMESH_Mesh_i::GetGroups() throw(SALOME::SALOME_Exception)
1107 {
1108   Unexpect aCatch(SALOME_SalomeException);
1109   if (MYDEBUG) MESSAGE("GetGroups");
1110
1111   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
1112
1113   // Python Dump
1114   TPythonDump aPythonDump;
1115   if ( !_mapGroups.empty() )
1116   {
1117     aPythonDump << "[ ";
1118     try {
1119       aList->length( _mapGroups.size() );
1120       int i = 0;
1121       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
1122       for ( ; it != _mapGroups.end(); it++ ) {
1123         if ( CORBA::is_nil( it->second )) continue;
1124         aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
1125         // Python Dump
1126         if (i > 1) aPythonDump << ", ";
1127         aPythonDump << it->second;
1128       }
1129       aList->length( i );
1130     }
1131     catch(SALOME_Exception & S_ex) {
1132       THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
1133     }
1134     aPythonDump << " ] = " << SMESH::SMESH_Mesh_var(_this()) << ".GetGroups()";
1135   }
1136   return aList._retn();
1137 }
1138
1139 //=============================================================================
1140 /*!
1141  *  Get number of groups existing in the mesh
1142  */
1143 //=============================================================================
1144
1145 CORBA::Long SMESH_Mesh_i::NbGroups() throw (SALOME::SALOME_Exception)
1146 {
1147   Unexpect aCatch(SALOME_SalomeException);
1148   return _mapGroups.size();
1149 }
1150
1151 //=============================================================================
1152 /*!
1153  * New group including all mesh elements present in initial groups is created.
1154  */
1155 //=============================================================================
1156
1157 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1158                                                   SMESH::SMESH_GroupBase_ptr theGroup2,
1159                                                   const char*                theName )
1160   throw (SALOME::SALOME_Exception)
1161 {
1162   SMESH::SMESH_Group_var aResGrp;
1163
1164   SMESH_TRY;
1165   if ( _preMeshInfo )
1166     _preMeshInfo->FullLoadFromFile();
1167
1168   if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1169     THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): NULL Group",
1170                                  SALOME::BAD_PARAM);
1171   if ( theGroup1->GetType() != theGroup2->GetType() )
1172     THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): different group types",
1173                                  SALOME::BAD_PARAM);
1174   TPythonDump pyDump;
1175
1176   // Create Union
1177   aResGrp = CreateGroup( theGroup1->GetType(), theName );
1178   if ( aResGrp->_is_nil() )
1179     return SMESH::SMESH_Group::_nil();
1180
1181   aResGrp->AddFrom( theGroup1 );
1182   aResGrp->AddFrom( theGroup2 );
1183
1184   // Update Python script
1185   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this())
1186          << ".UnionGroups( " << theGroup1 << ", " << theGroup2 << ", '" << theName << "' )";
1187
1188   SMESH_CATCH( SMESH::throwCorbaException );
1189
1190   return aResGrp._retn();
1191 }
1192
1193 //=============================================================================
1194 /*!
1195  * \brief New group including all mesh elements present in initial groups is created.
1196  *  \param theGroups list of groups
1197  *  \param theName name of group to be created
1198  *  \return pointer to the new group
1199  */
1200 //=============================================================================
1201
1202 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionListOfGroups(const SMESH::ListOfGroups& theGroups,
1203                                                        const char*                theName )
1204   throw (SALOME::SALOME_Exception)
1205 {
1206   SMESH::SMESH_Group_var aResGrp;
1207
1208   if ( _preMeshInfo )
1209     _preMeshInfo->FullLoadFromFile();
1210
1211   if ( !theName )
1212     return SMESH::SMESH_Group::_nil();
1213
1214   SMESH_TRY;
1215
1216   // check types
1217   SMESH::ElementType aType = SMESH::ALL;
1218   for ( int g = 0, n = theGroups.length(); g < n; g++ )
1219   {
1220     SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1221     if ( CORBA::is_nil( aGrp ) )
1222       continue;
1223     if ( aType == SMESH::ALL )
1224       aType = aGrp->GetType();
1225     else if ( aType != aGrp->GetType() )
1226       THROW_SALOME_CORBA_EXCEPTION("UnionListOfGroups(): different group types",
1227                                    SALOME::BAD_PARAM);
1228   }
1229   if ( aType == SMESH::ALL )
1230     return SMESH::SMESH_Group::_nil();
1231
1232   TPythonDump pyDump;
1233
1234   // Create Union
1235   aResGrp = CreateGroup( aType, theName );
1236   if ( aResGrp->_is_nil() )
1237     return SMESH::SMESH_Group::_nil();
1238
1239   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".UnionListOfGroups([ ";
1240   for ( int g = 0, n = theGroups.length(); g < n; g++ )
1241   {
1242     SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1243     if ( !CORBA::is_nil( aGrp ) )
1244     {
1245       aResGrp->AddFrom( aGrp );
1246       if ( g > 0 ) pyDump << ", ";
1247       pyDump << aGrp;
1248     }
1249   }
1250   pyDump << " ], '" << theName << "' )";
1251
1252   SMESH_CATCH( SMESH::throwCorbaException );
1253
1254   return aResGrp._retn();
1255 }
1256
1257 //=============================================================================
1258 /*!
1259  *  New group is created. All mesh elements that are
1260  *  present in both initial groups are added to the new one.
1261  */
1262 //=============================================================================
1263
1264 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1265                                                       SMESH::SMESH_GroupBase_ptr theGroup2,
1266                                                       const char*                theName )
1267   throw (SALOME::SALOME_Exception)
1268 {
1269   SMESH::SMESH_Group_var aResGrp;
1270
1271   SMESH_TRY;
1272
1273   if ( _preMeshInfo )
1274     _preMeshInfo->FullLoadFromFile();
1275
1276   if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1277     THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): NULL Group",
1278                                  SALOME::BAD_PARAM);
1279   if ( theGroup1->GetType() != theGroup2->GetType() )
1280     THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): different group types",
1281                                  SALOME::BAD_PARAM);
1282   TPythonDump pyDump;
1283
1284   // Create Intersection
1285   aResGrp = CreateGroup( theGroup1->GetType(), theName );
1286   if ( aResGrp->_is_nil() )
1287     return aResGrp._retn();
1288
1289   SMESHDS_GroupBase* groupDS1 = 0;
1290   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1291     groupDS1 = grp_i->GetGroupDS();
1292
1293   SMESHDS_GroupBase* groupDS2 = 0;
1294   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1295     groupDS2 = grp_i->GetGroupDS();
1296
1297   SMESHDS_Group* resGroupDS = 0;
1298   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1299     resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1300
1301   if ( groupDS1 && groupDS2 && resGroupDS && !groupDS2->IsEmpty() )
1302   {
1303     SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1304     while ( elemIt1->more() )
1305     {
1306       const SMDS_MeshElement* e = elemIt1->next();
1307       if ( groupDS2->Contains( e ))
1308         resGroupDS->SMDSGroup().Add( e );
1309     }
1310   }
1311   // Update Python script
1312   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".IntersectGroups( "
1313          << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1314
1315   SMESH_CATCH( SMESH::throwCorbaException );
1316
1317   return aResGrp._retn();
1318 }
1319
1320 //=============================================================================
1321 /*!
1322   \brief Intersect list of groups. New group is created. All mesh elements that 
1323   are present in all initial groups simultaneously are added to the new one.
1324   \param theGroups list of groups
1325   \param theName name of group to be created
1326   \return pointer on the group
1327 */
1328 //=============================================================================
1329 SMESH::SMESH_Group_ptr
1330 SMESH_Mesh_i::IntersectListOfGroups(const SMESH::ListOfGroups& theGroups,
1331                                     const char*                theName )
1332   throw (SALOME::SALOME_Exception)
1333 {
1334   SMESH::SMESH_Group_var aResGrp;
1335
1336   SMESH_TRY;
1337
1338   if ( _preMeshInfo )
1339     _preMeshInfo->FullLoadFromFile();
1340
1341   if ( !theName )
1342     return SMESH::SMESH_Group::_nil();
1343
1344   // check types and get SMESHDS_GroupBase's
1345   SMESH::ElementType aType = SMESH::ALL;
1346   vector< SMESHDS_GroupBase* > groupVec;
1347   for ( int g = 0, n = theGroups.length(); g < n; g++ )
1348   {
1349     SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1350     if ( CORBA::is_nil( aGrp ) )
1351       continue;
1352     if ( aType == SMESH::ALL )
1353       aType = aGrp->GetType();
1354     else if ( aType != aGrp->GetType() )
1355       THROW_SALOME_CORBA_EXCEPTION("IntersectListOfGroups(): different group types",
1356                                    SALOME::BAD_PARAM);
1357
1358     if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1359       if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1360       {
1361         if ( grpDS->IsEmpty() )
1362         {
1363           groupVec.clear();
1364           break;
1365         }
1366         groupVec.push_back( grpDS );
1367       }
1368   }
1369   if ( aType == SMESH::ALL ) // all groups are nil
1370     return SMESH::SMESH_Group::_nil();
1371
1372   TPythonDump pyDump;
1373
1374   // Create a group
1375   aResGrp = CreateGroup( aType, theName );
1376
1377   SMESHDS_Group* resGroupDS = 0;
1378   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1379     resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1380   if ( !resGroupDS || groupVec.empty() )
1381     return aResGrp._retn();
1382
1383   // Fill the group
1384   size_t i, nb = groupVec.size();
1385   SMDS_ElemIteratorPtr elemIt1 = groupVec[0]->GetElements();
1386   while ( elemIt1->more() )
1387   {
1388     const SMDS_MeshElement* e = elemIt1->next();
1389     bool inAll = true;
1390     for ( i = 1; ( i < nb && inAll ); ++i )
1391       inAll = groupVec[i]->Contains( e );
1392
1393     if ( inAll )
1394       resGroupDS->SMDSGroup().Add( e );
1395   }
1396
1397   // Update Python script
1398   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1399          << ".IntersectListOfGroups( " << theGroups << ", '" << theName << "' )";
1400
1401   SMESH_CATCH( SMESH::throwCorbaException );
1402
1403   return aResGrp._retn();
1404 }
1405
1406 //=============================================================================
1407 /*! 
1408  *  New group is created. All mesh elements that are present in
1409  *  a main group but is not present in a tool group are added to the new one
1410  */
1411 //=============================================================================
1412
1413 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1414                                                 SMESH::SMESH_GroupBase_ptr theGroup2,
1415                                                 const char*                theName )
1416   throw (SALOME::SALOME_Exception)
1417 {
1418   SMESH::SMESH_Group_var aResGrp;
1419
1420   SMESH_TRY;
1421
1422   if ( _preMeshInfo )
1423     _preMeshInfo->FullLoadFromFile();
1424
1425   if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1426     THROW_SALOME_CORBA_EXCEPTION("CutGroups(): NULL Group",
1427                                  SALOME::BAD_PARAM);
1428   if ( theGroup1->GetType() != theGroup2->GetType() )
1429     THROW_SALOME_CORBA_EXCEPTION("CutGroups(): different group types",
1430                                  SALOME::BAD_PARAM);
1431   TPythonDump pyDump;
1432
1433   aResGrp = CreateGroup( theGroup1->GetType(), theName );
1434   if ( aResGrp->_is_nil() )
1435     return aResGrp._retn();
1436
1437   SMESHDS_GroupBase* groupDS1 = 0;
1438   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1439     groupDS1 = grp_i->GetGroupDS();
1440
1441   SMESHDS_GroupBase* groupDS2 = 0;
1442   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1443     groupDS2 = grp_i->GetGroupDS();
1444
1445   SMESHDS_Group* resGroupDS = 0;
1446   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1447     resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1448
1449   if ( groupDS1 && groupDS2 && resGroupDS )
1450   {
1451     SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1452     while ( elemIt1->more() )
1453     {
1454       const SMDS_MeshElement* e = elemIt1->next();
1455       if ( !groupDS2->Contains( e ))
1456         resGroupDS->SMDSGroup().Add( e );
1457     }
1458   }
1459   // Update Python script
1460   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".CutGroups( "
1461          << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1462
1463   SMESH_CATCH( SMESH::throwCorbaException );
1464
1465   return aResGrp._retn();
1466 }
1467
1468 //=============================================================================
1469 /*!
1470   \brief Cut lists of groups. New group is created. All mesh elements that are 
1471   present in main groups but do not present in tool groups are added to the new one
1472   \param theMainGroups list of main groups
1473   \param theToolGroups list of tool groups
1474   \param theName name of group to be created
1475   \return pointer on the group
1476 */
1477 //=============================================================================
1478 SMESH::SMESH_Group_ptr
1479 SMESH_Mesh_i::CutListOfGroups(const SMESH::ListOfGroups& theMainGroups, 
1480                               const SMESH::ListOfGroups& theToolGroups, 
1481                               const char*                theName )
1482   throw (SALOME::SALOME_Exception)
1483 {
1484   SMESH::SMESH_Group_var aResGrp;
1485
1486   SMESH_TRY;
1487
1488   if ( _preMeshInfo )
1489     _preMeshInfo->FullLoadFromFile();
1490
1491   if ( !theName )
1492     return SMESH::SMESH_Group::_nil();
1493
1494   // check types and get SMESHDS_GroupBase's
1495   SMESH::ElementType aType = SMESH::ALL;
1496   vector< SMESHDS_GroupBase* >   toolGroupVec;
1497   vector< SMDS_ElemIteratorPtr > mainIterVec;
1498
1499   for ( int g = 0, n = theMainGroups.length(); g < n; g++ )
1500   {
1501     SMESH::SMESH_GroupBase_var aGrp = theMainGroups[ g ];
1502     if ( CORBA::is_nil( aGrp ) )
1503       continue;
1504     if ( aType == SMESH::ALL )
1505       aType = aGrp->GetType();
1506     else if ( aType != aGrp->GetType() )
1507       THROW_SALOME_CORBA_EXCEPTION("UnionListOfGroups(): different group types",
1508                                    SALOME::BAD_PARAM);
1509     if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1510       if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1511         if ( !grpDS->IsEmpty() )
1512           mainIterVec.push_back( grpDS->GetElements() );
1513   }
1514   if ( aType == SMESH::ALL ) // all main groups are nil
1515     return SMESH::SMESH_Group::_nil();
1516   if ( mainIterVec.empty() ) // all main groups are empty
1517     return aResGrp._retn();
1518
1519   for ( int g = 0, n = theToolGroups.length(); g < n; g++ )
1520   {
1521     SMESH::SMESH_GroupBase_var aGrp = theToolGroups[ g ];
1522     if ( CORBA::is_nil( aGrp ) )
1523       continue;
1524     if ( aType != aGrp->GetType() )
1525       THROW_SALOME_CORBA_EXCEPTION("UnionListOfGroups(): different group types",
1526                                    SALOME::BAD_PARAM);
1527     if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1528       if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1529         toolGroupVec.push_back( grpDS );
1530   }
1531
1532   TPythonDump pyDump;
1533
1534   // Create a group
1535   aResGrp = CreateGroup( aType, theName );
1536
1537   SMESHDS_Group* resGroupDS = 0;
1538   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1539     resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1540   if ( !resGroupDS )
1541     return aResGrp._retn();
1542
1543   // Fill the group
1544   size_t i, nb = toolGroupVec.size();
1545   SMDS_ElemIteratorPtr mainElemIt
1546     ( new SMDS_IteratorOnIterators
1547       < const SMDS_MeshElement*, vector< SMDS_ElemIteratorPtr > >( mainIterVec ));
1548   while ( mainElemIt->more() )
1549   {
1550     const SMDS_MeshElement* e = mainElemIt->next();
1551     bool isIn = false;
1552     for ( i = 0; ( i < nb && !isIn ); ++i )
1553       isIn = toolGroupVec[i]->Contains( e );
1554
1555     if ( !isIn )
1556       resGroupDS->SMDSGroup().Add( e );
1557   }
1558
1559   // Update Python script
1560   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1561          << ".CutListOfGroups( " << theMainGroups
1562          << theToolGroups << ", '" << theName << "' )";
1563
1564   SMESH_CATCH( SMESH::throwCorbaException );
1565
1566   return aResGrp._retn();
1567 }
1568
1569 //=============================================================================
1570 /*!
1571   \brief Create groups of entities from existing groups of superior dimensions 
1572   System
1573   1) extract all nodes from each group,
1574   2) combine all elements of specified dimension laying on these nodes.
1575   \param theGroups list of source groups 
1576   \param theElemType dimension of elements 
1577   \param theName name of new group
1578   \return pointer on new group
1579   *
1580   IMP 19939
1581 */
1582 //=============================================================================
1583
1584 SMESH::SMESH_Group_ptr
1585 SMESH_Mesh_i::CreateDimGroup(const SMESH::ListOfGroups& theGroups, 
1586                              SMESH::ElementType         theElemType, 
1587                              const char*                theName )
1588   throw (SALOME::SALOME_Exception)
1589 {
1590   SMESH::SMESH_Group_var aResGrp;
1591
1592   SMESH_TRY;
1593   if ( _preMeshInfo )
1594     _preMeshInfo->FullLoadFromFile();
1595
1596   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
1597
1598   if ( !theName || !aMeshDS )
1599     return SMESH::SMESH_Group::_nil();
1600
1601   SMDSAbs_ElementType anElemType = (SMDSAbs_ElementType)theElemType;
1602
1603   // Create a group
1604
1605   TPythonDump pyDump;
1606
1607   aResGrp = CreateGroup( theElemType, theName );
1608   if ( aResGrp->_is_nil() )
1609     return SMESH::SMESH_Group::_nil();
1610
1611   SMESHDS_GroupBase* groupBaseDS =
1612     SMESH::DownCast<SMESH_GroupBase_i*>( aResGrp )->GetGroupDS();
1613   SMDS_MeshGroup& resGroupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
1614
1615   for ( int g = 0, n = theGroups.length(); g < n; g++ ) // loop on theGroups
1616   {
1617     SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1618     if ( CORBA::is_nil( aGrp ) )
1619       continue;
1620
1621     groupBaseDS = SMESH::DownCast<SMESH_GroupBase_i*>( aGrp )->GetGroupDS();
1622     SMDS_ElemIteratorPtr elIt = groupBaseDS->GetElements();
1623
1624     if ( theElemType == SMESH::NODE ) // get all nodes of elements
1625     {
1626       while ( elIt->more() ) {
1627         const SMDS_MeshElement* el = elIt->next();
1628         SMDS_ElemIteratorPtr nIt = el->nodesIterator();
1629         while ( nIt->more() )
1630           resGroupCore.Add( nIt->next() );
1631       }
1632     }
1633     else // get elements of theElemType based on nodes of every element of group
1634     {
1635       while ( elIt->more() )
1636       {
1637         const SMDS_MeshElement* el = elIt->next(); // an element of group
1638         TIDSortedElemSet elNodes( el->begin_nodes(), el->end_nodes() );
1639         TIDSortedElemSet checkedElems;
1640         SMDS_ElemIteratorPtr nIt = el->nodesIterator();
1641         while ( nIt->more() )
1642         {
1643           const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nIt->next() );
1644           SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
1645           // check nodes of elements of theElemType around el
1646           while ( elOfTypeIt->more() )
1647           {
1648             const SMDS_MeshElement* elOfType = elOfTypeIt->next();
1649             if ( !checkedElems.insert( elOfType ).second ) continue;
1650
1651             SMDS_ElemIteratorPtr nIt2 = elOfType->nodesIterator();
1652             bool allNodesOK = true;
1653             while ( nIt2->more() && allNodesOK )
1654               allNodesOK = elNodes.count( nIt2->next() );
1655             if ( allNodesOK )
1656               resGroupCore.Add( elOfType );
1657           }
1658         }
1659       }
1660     }
1661   }
1662
1663   // Update Python script
1664   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this())
1665          << ".CreateDimGroup( "
1666          << theGroups << ", " << theElemType << ", '" << theName << "' )";
1667
1668   SMESH_CATCH( SMESH::throwCorbaException );
1669
1670   return aResGrp._retn();
1671 }
1672
1673 //================================================================================
1674 /*!
1675  * \brief Remember GEOM group data
1676  */
1677 //================================================================================
1678
1679 void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj,
1680                                     CORBA::Object_ptr     theSmeshObj)
1681 {
1682   if ( CORBA::is_nil( theGeomObj ) || theGeomObj->GetType() != GEOM_GROUP )
1683     return;
1684   // group SO
1685   SALOMEDS::Study_var    study   = _gen_i->GetCurrentStudy();
1686   SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( study, theGeomObj );
1687   if ( groupSO->_is_nil() )
1688     return;
1689   // group indices
1690   GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
1691   GEOM::GEOM_IGroupOperations_wrap groupOp =
1692     geomGen->GetIGroupOperations( _gen_i->GetCurrentStudyID() );
1693   GEOM::ListOfLong_var ids = groupOp->GetObjects( theGeomObj );
1694
1695   // store data
1696   _geomGroupData.push_back( TGeomGroupData() );
1697   TGeomGroupData & groupData = _geomGroupData.back();
1698   // entry
1699   CORBA::String_var entry = groupSO->GetID();
1700   groupData._groupEntry = entry.in();
1701   // indices
1702   for ( int i = 0; i < ids->length(); ++i )
1703     groupData._indices.insert( ids[i] );
1704   // SMESH object
1705   groupData._smeshObject = CORBA::Object::_duplicate( theSmeshObj );
1706 }
1707
1708 //================================================================================
1709 /*!
1710  * Remove GEOM group data relating to removed smesh object
1711  */
1712 //================================================================================
1713
1714 void SMESH_Mesh_i::removeGeomGroupData(CORBA::Object_ptr theSmeshObj)
1715 {
1716   list<TGeomGroupData>::iterator
1717     data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
1718   for ( ; data != dataEnd; ++data ) {
1719     if ( theSmeshObj->_is_equivalent( data->_smeshObject )) {
1720       _geomGroupData.erase( data );
1721       return;
1722     }
1723   }
1724 }
1725
1726 //================================================================================
1727 /*!
1728  * \brief Return new group contents if it has been changed and update group data
1729  */
1730 //================================================================================
1731
1732 TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData)
1733 {
1734   TopoDS_Shape newShape;
1735
1736   // get geom group
1737   SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1738   if ( study->_is_nil() ) return newShape; // means "not changed"
1739   SALOMEDS::SObject_wrap groupSO = study->FindObjectID( groupData._groupEntry.c_str() );
1740   if ( !groupSO->_is_nil() )
1741   {
1742     CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO );
1743     if ( CORBA::is_nil( groupObj )) return newShape;
1744     GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj );
1745
1746     // get indices of group items
1747     set<int> curIndices;
1748     GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
1749     GEOM::GEOM_IGroupOperations_wrap groupOp =
1750       geomGen->GetIGroupOperations( _gen_i->GetCurrentStudyID() );
1751     GEOM::ListOfLong_var   ids = groupOp->GetObjects( geomGroup );
1752     for ( int i = 0; i < ids->length(); ++i )
1753       curIndices.insert( ids[i] );
1754
1755     if ( groupData._indices == curIndices )
1756       return newShape; // group not changed
1757
1758     // update data
1759     groupData._indices = curIndices;
1760
1761     GEOM_Client* geomClient = _gen_i->GetShapeReader();
1762     if ( !geomClient ) return newShape;
1763     CORBA::String_var groupIOR = geomGen->GetStringFromIOR( geomGroup );
1764     geomClient->RemoveShapeFromBuffer( groupIOR.in() );
1765     newShape = _gen_i->GeomObjectToShape( geomGroup );
1766   }
1767
1768   if ( newShape.IsNull() ) {
1769     // geom group becomes empty - return empty compound
1770     TopoDS_Compound compound;
1771     BRep_Builder().MakeCompound(compound);
1772     newShape = compound;
1773   }
1774   return newShape;
1775 }
1776
1777 namespace
1778 {
1779   //=============================================================================
1780   /*!
1781    * \brief Storage of shape and index used in CheckGeomGroupModif()
1782    */
1783   //=============================================================================
1784   struct TIndexedShape
1785   {
1786     int          _index;
1787     TopoDS_Shape _shape;
1788     TIndexedShape( int i, const TopoDS_Shape& s ):_index(i), _shape(s) {}
1789   };
1790 }
1791 //=============================================================================
1792 /*!
1793  * \brief Update objects depending on changed geom groups
1794  * 
1795  * NPAL16168: geometrical group edition from a submesh don't modifiy mesh computation
1796  * issue 0020210: Update of a smesh group after modification of the associated geom group
1797  */
1798 //=============================================================================
1799
1800 void SMESH_Mesh_i::CheckGeomGroupModif()
1801 {
1802   if ( !_impl->HasShapeToMesh() ) return;
1803
1804   SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1805   if ( study->_is_nil() ) return;
1806
1807   CORBA::Long nbEntities = NbNodes() + NbElements();
1808
1809   // Check if group contents changed
1810
1811   typedef map< string, TopoDS_Shape > TEntry2Geom;
1812   TEntry2Geom newGroupContents;
1813
1814   list<TGeomGroupData>::iterator
1815     data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
1816   for ( ; data != dataEnd; ++data )
1817   {
1818     pair< TEntry2Geom::iterator, bool > it_new =
1819       newGroupContents.insert( make_pair( data->_groupEntry, TopoDS_Shape() ));
1820     bool processedGroup    = !it_new.second;
1821     TopoDS_Shape& newShape = it_new.first->second;
1822     if ( !processedGroup )
1823       newShape = newGroupShape( *data );
1824     if ( newShape.IsNull() )
1825       continue; // no changes
1826
1827     if ( _preMeshInfo )
1828       _preMeshInfo->ForgetOrLoad();
1829
1830     if ( processedGroup ) { // update group indices
1831       list<TGeomGroupData>::iterator data2 = data;
1832       for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) {}
1833       data->_indices = data2->_indices;
1834     }
1835
1836     // Update SMESH objects according to new GEOM group contents
1837
1838     SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject );
1839     if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
1840     {
1841       int oldID = submesh->GetId();
1842       if ( !_mapSubMeshIor.count( oldID ))
1843         continue;
1844       TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
1845
1846       // update hypotheses
1847       list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldShape);
1848       list <const SMESHDS_Hypothesis * >::iterator hypIt;
1849       for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
1850       {
1851         _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
1852         _impl->AddHypothesis   ( newShape, (*hypIt)->GetID());
1853       }
1854       // care of submeshes
1855       SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newShape );
1856       int newID = newSubmesh->GetId();
1857       if ( newID != oldID ) {
1858         _mapSubMesh   [ newID ] = newSubmesh;
1859         _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
1860         _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
1861         _mapSubMesh.   erase(oldID);
1862         _mapSubMesh_i. erase(oldID);
1863         _mapSubMeshIor.erase(oldID);
1864         _mapSubMesh_i [ newID ]->changeLocalId( newID );
1865       }
1866       continue;
1867     }
1868
1869     SMESH::SMESH_GroupOnGeom_var smeshGroup =
1870       SMESH::SMESH_GroupOnGeom::_narrow( data->_smeshObject );
1871     if ( !smeshGroup->_is_nil() ) // ------------ GROUP -----------------------
1872     {
1873       SMESH_GroupOnGeom_i* group_i = SMESH::DownCast<SMESH_GroupOnGeom_i*>( smeshGroup );
1874       if ( group_i ) {
1875         ::SMESH_Group* group = _impl->GetGroup( group_i->GetLocalID() );
1876         SMESHDS_GroupOnGeom* ds = static_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() );
1877         ds->SetShape( newShape );
1878       }
1879       continue;
1880     }
1881
1882     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject );
1883     if ( !mesh->_is_nil() ) // -------------- MESH ----------------------------
1884     {
1885       // Remove groups and submeshes basing on removed sub-shapes
1886
1887       TopTools_MapOfShape newShapeMap;
1888       TopoDS_Iterator shapeIt( newShape );
1889       for ( ; shapeIt.More(); shapeIt.Next() )
1890         newShapeMap.Add( shapeIt.Value() );
1891
1892       SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
1893       for ( shapeIt.Initialize( meshDS->ShapeToMesh() ); shapeIt.More(); shapeIt.Next() )
1894       {
1895         if ( newShapeMap.Contains( shapeIt.Value() ))
1896           continue;
1897         TopTools_IndexedMapOfShape oldShapeMap;
1898         TopExp::MapShapes( shapeIt.Value(), oldShapeMap );
1899         for ( int i = 1; i <= oldShapeMap.Extent(); ++i )
1900         {
1901           const TopoDS_Shape& oldShape = oldShapeMap(i);
1902           int oldInd = meshDS->ShapeToIndex( oldShape );
1903           // -- submeshes --
1904           map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldInd );
1905           if ( i_smIor != _mapSubMeshIor.end() ) {
1906             RemoveSubMesh( i_smIor->second ); // one submesh per shape index
1907           }
1908           // --- groups ---
1909           map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
1910           for ( ; i_grp != _mapGroups.end(); ++i_grp )
1911           {
1912             // check if a group bases on oldInd shape
1913             SMESHDS_GroupOnGeom* grpOnGeom = 0;
1914             if ( ::SMESH_Group* g = _impl->GetGroup( i_grp->first ))
1915               grpOnGeom = dynamic_cast<SMESHDS_GroupOnGeom*>( g->GetGroupDS() );
1916             if ( grpOnGeom && oldShape.IsSame( grpOnGeom->GetShape() ))
1917             { // remove
1918               RemoveGroup( i_grp->second ); // several groups can base on same shape
1919               i_grp = _mapGroups.begin(); // _mapGroups changed - restart iteration
1920             }
1921           }
1922         }
1923       }
1924       // Reassign hypotheses and update groups after setting the new shape to mesh
1925
1926       // collect anassigned hypotheses
1927       typedef list< pair< TIndexedShape, list<const SMESHDS_Hypothesis*> > > TShapeHypList;
1928       list <const SMESHDS_Hypothesis * >::const_iterator hypIt;
1929       TShapeHypList assignedHyps;
1930       for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i )
1931       {
1932         const TopoDS_Shape& oldShape = meshDS->IndexToShape(i);
1933         list<const SMESHDS_Hypothesis*> hyps = meshDS->GetHypothesis( oldShape );// copy
1934         if ( !hyps.empty() ) {
1935           assignedHyps.push_back( make_pair( TIndexedShape(i,oldShape), hyps ));
1936           for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
1937             _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
1938         }
1939       }
1940       // collect shapes supporting groups
1941       typedef list < pair< TIndexedShape, SMDSAbs_ElementType > > TShapeTypeList;
1942       TShapeTypeList groupData;
1943       const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
1944       set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
1945       for ( ; grIt != groups.end(); ++grIt )
1946       {
1947         if ( SMESHDS_GroupOnGeom* gog = dynamic_cast<SMESHDS_GroupOnGeom*>( *grIt ))
1948           groupData.push_back
1949             ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
1950       }
1951       // set new shape to mesh -> DS of submeshes and geom groups is deleted
1952       _impl->ShapeToMesh( newShape );
1953       
1954       // reassign hypotheses
1955       TShapeHypList::iterator indS_hyps = assignedHyps.begin();
1956       for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
1957       {
1958         TIndexedShape&                   geom = indS_hyps->first;
1959         list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
1960         int oldID = geom._index;
1961         int newID = meshDS->ShapeToIndex( geom._shape );
1962         if ( oldID == 1 ) { // main shape
1963           newID = 1;
1964           geom._shape = newShape;
1965         }
1966         if ( !newID )
1967           continue;
1968         for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
1969           _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
1970         // care of submeshes
1971         SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
1972         if ( newID != oldID ) {
1973           _mapSubMesh   [ newID ] = newSubmesh;
1974           _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
1975           _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
1976           _mapSubMesh.   erase(oldID);
1977           _mapSubMesh_i. erase(oldID);
1978           _mapSubMeshIor.erase(oldID);
1979           _mapSubMesh_i [ newID ]->changeLocalId( newID );
1980         }
1981       }
1982       // recreate groups
1983       TShapeTypeList::iterator geomType = groupData.begin();
1984       for ( ; geomType != groupData.end(); ++geomType )
1985       {
1986         const TIndexedShape& geom = geomType->first;
1987         int oldID = geom._index;
1988         if ( _mapGroups.find( oldID ) == _mapGroups.end() )
1989           continue;
1990         // get group name
1991         SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( study,_mapGroups[oldID] );
1992         CORBA::String_var      name    = groupSO->GetName();
1993         // update
1994         SMESH_GroupBase_i*  group_i    = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID] );
1995         int newID;
1996         if ( group_i && _impl->AddGroup( geomType->second, name.in(), newID, geom._shape ))
1997           group_i->changeLocalId( newID );
1998       }
1999
2000       break; // everything has been updated
2001
2002     } // update mesh
2003   } // loop on group data
2004
2005   // Update icons
2006
2007   CORBA::Long newNbEntities = NbNodes() + NbElements();
2008   list< SALOMEDS::SObject_wrap > soToUpdateIcons;
2009   if ( newNbEntities != nbEntities )
2010   {
2011     // Add all SObjects with icons to soToUpdateIcons
2012     soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, _this() )); // mesh
2013
2014     for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
2015          i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
2016       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, i_sm->second ));
2017
2018     for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
2019           i_gr != _mapGroups.end(); ++i_gr ) // groups
2020       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, i_gr->second ));
2021   }
2022
2023   list< SALOMEDS::SObject_wrap >::iterator so = soToUpdateIcons.begin();
2024   for ( ; so != soToUpdateIcons.end(); ++so )
2025     _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
2026 }
2027
2028 //=============================================================================
2029 /*!
2030  * \brief Create standalone group from a group on geometry or filter
2031  */
2032 //=============================================================================
2033
2034 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase_ptr theGroup )
2035   throw (SALOME::SALOME_Exception)
2036 {
2037   SMESH::SMESH_Group_var aGroup;
2038
2039   SMESH_TRY;
2040
2041   if ( _preMeshInfo )
2042     _preMeshInfo->FullLoadFromFile();
2043
2044   if ( theGroup->_is_nil() )
2045     return aGroup._retn();
2046
2047   SMESH_GroupBase_i* aGroupToRem = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
2048   if ( !aGroupToRem )
2049     return aGroup._retn();
2050
2051   const bool isOnFilter = ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ));
2052
2053   const int anId = aGroupToRem->GetLocalID();
2054   if ( !_impl->ConvertToStandalone( anId ) )
2055     return aGroup._retn();
2056   removeGeomGroupData( theGroup );
2057
2058   SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2059
2060   // remove old instance of group from own map
2061   { SMESH::SMESH_GroupBase_var var( _mapGroups[anId] ); } // decref CORBA object
2062   _mapGroups.erase( anId );
2063
2064   SALOMEDS::StudyBuilder_var builder;
2065   SALOMEDS::SObject_wrap     aGroupSO;
2066   SALOMEDS::Study_var        aStudy = _gen_i->GetCurrentStudy();
2067   if ( !aStudy->_is_nil() ) {
2068     builder  = aStudy->NewBuilder();
2069     aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
2070     if ( !aGroupSO->_is_nil() )
2071     {
2072       // remove reference to geometry
2073       SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO);
2074       for ( ; chItr->More(); chItr->Next() )
2075         // Remove group's child SObject
2076         builder->RemoveObject( chItr->Value() );
2077
2078       // Update Python script
2079       TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this())
2080                     << ".ConvertToStandalone( " << aGroupSO << " )";
2081
2082       // change icon of Group on Filter
2083       if ( isOnFilter )
2084       {
2085         SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
2086         const int isEmpty = ( elemTypes->length() == 0 );
2087         if ( !isEmpty )
2088         {
2089           SALOMEDS::GenericAttribute_wrap anAttr =
2090             builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
2091           SALOMEDS::AttributePixMap_wrap pm = anAttr;
2092           pm->SetPixMap( "ICON_SMESH_TREE_GROUP" );
2093         }
2094       }
2095     }
2096   }
2097
2098   // remember new group in own map
2099   aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
2100   _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2101
2102   // register CORBA object for persistence
2103   _gen_i->RegisterObject( aGroup );
2104
2105   CORBA::String_var ior = _gen_i->GetORB()->object_to_string( aGroup );
2106   builder->SetIOR( aGroupSO, ior.in() ); //  == aGroup->Register();
2107   //aGroup->Register();
2108   aGroupToRem->UnRegister();
2109
2110   SMESH_CATCH( SMESH::throwCorbaException );
2111
2112   return aGroup._retn();
2113 }
2114
2115 //=============================================================================
2116 /*!
2117  *
2118  */
2119 //=============================================================================
2120
2121 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
2122 {
2123   if(MYDEBUG) MESSAGE( "createSubMesh" );
2124   TopoDS_Shape  myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
2125   ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
2126   const int         subMeshId = mySubMesh->GetId();
2127
2128   SMESH_subMesh_i * subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
2129   SMESH::SMESH_subMesh_var subMesh = subMeshServant->_this();
2130
2131   _mapSubMesh   [subMeshId] = mySubMesh;
2132   _mapSubMesh_i [subMeshId] = subMeshServant;
2133   _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate( subMesh );
2134
2135   subMeshServant->Register();
2136
2137   // register CORBA object for persistence
2138   int nextId = _gen_i->RegisterObject( subMesh );
2139   if(MYDEBUG) { MESSAGE( "Add submesh to map with id = "<< nextId); }
2140   else        { nextId = 0; } // avoid "unused variable" warning
2141
2142   // to track changes of GEOM groups
2143   addGeomGroupData( theSubShapeObject, subMesh );
2144
2145   return subMesh._retn();
2146 }
2147
2148 //=======================================================================
2149 //function : getSubMesh
2150 //purpose  :
2151 //=======================================================================
2152
2153 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
2154 {
2155   map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
2156   if ( it == _mapSubMeshIor.end() )
2157     return SMESH::SMESH_subMesh::_nil();
2158
2159   return SMESH::SMESH_subMesh::_duplicate( (*it).second );
2160 }
2161
2162 //=============================================================================
2163 /*!
2164  *
2165  */
2166 //=============================================================================
2167
2168 bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
2169                                   GEOM::GEOM_Object_ptr    theSubShapeObject )
2170 {
2171   bool isHypChanged = false;
2172   if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
2173     return isHypChanged;
2174
2175   const int subMeshId = theSubMesh->GetId();
2176
2177   if ( theSubShapeObject->_is_nil() )  // not published shape (IPAL13617)
2178   {
2179     if ( _mapSubMesh.find( subMeshId ) != _mapSubMesh.end())
2180     {
2181       TopoDS_Shape S = _mapSubMesh[ subMeshId ]->GetSubShape();
2182       if ( !S.IsNull() )
2183       {
2184         list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
2185         isHypChanged = !hyps.empty();
2186         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
2187         for ( ; hyp != hyps.end(); ++hyp )
2188           _impl->RemoveHypothesis(S, (*hyp)->GetID());
2189       }
2190     }
2191   }
2192   else
2193   {
2194     try {
2195       SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
2196       isHypChanged = ( aHypList->length() > 0 );
2197       for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
2198         removeHypothesis( theSubShapeObject, aHypList[i] );
2199       }
2200     }
2201     catch( const SALOME::SALOME_Exception& ) {
2202       INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
2203     }
2204     removeGeomGroupData( theSubShapeObject );
2205   }
2206
2207   // remove a servant
2208   std::map<int, SMESH_subMesh_i*>::iterator id_smi = _mapSubMesh_i.find( subMeshId );
2209   if ( id_smi != _mapSubMesh_i.end() )
2210     id_smi->second->UnRegister();
2211
2212   // remove a CORBA object
2213   std::map<int, SMESH::SMESH_subMesh_ptr>::iterator id_smptr = _mapSubMeshIor.find( subMeshId );
2214   if ( id_smptr != _mapSubMeshIor.end() )
2215     SMESH::SMESH_subMesh_var( id_smptr->second );
2216
2217   _mapSubMesh.erase(subMeshId);
2218   _mapSubMesh_i.erase(subMeshId);
2219   _mapSubMeshIor.erase(subMeshId);
2220
2221   return isHypChanged;
2222 }
2223
2224 //=============================================================================
2225 /*!
2226  *
2227  */
2228 //=============================================================================
2229
2230 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType        theElemType,
2231                                                       const char*               theName,
2232                                                       const TopoDS_Shape&       theShape,
2233                                                       const SMESH_PredicatePtr& thePredicate )
2234 {
2235   std::string newName;
2236   if ( !theName || strlen( theName ) == 0 )
2237   {
2238     std::set< std::string > presentNames;
2239     std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
2240     for ( ; i_gr != _mapGroups.end(); ++i_gr )
2241     {
2242       CORBA::String_var name = i_gr->second->GetName();
2243       presentNames.insert( name.in() );
2244     }
2245     do {
2246       newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
2247     } while ( !presentNames.insert( newName ).second );
2248     theName = newName.c_str();
2249   }
2250   int anId;
2251   SMESH::SMESH_GroupBase_var aGroup;
2252   if ( _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName, anId, theShape, thePredicate ))
2253   {
2254     SMESH_GroupBase_i* aGroupImpl;
2255     if ( !theShape.IsNull() )
2256       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
2257     else if ( thePredicate )
2258       aGroupImpl = new SMESH_GroupOnFilter_i( SMESH_Gen_i::GetPOA(), this, anId );
2259     else
2260       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2261
2262     aGroup = aGroupImpl->_this();
2263     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2264     aGroupImpl->Register();
2265
2266     // register CORBA object for persistence
2267     int nextId = _gen_i->RegisterObject( aGroup );
2268     if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
2269     else        { nextId = 0; } // avoid "unused variable" warning in release mode
2270
2271     // to track changes of GEOM groups
2272     if ( !theShape.IsNull() ) {
2273       GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
2274       addGeomGroupData( geom, aGroup );
2275     }
2276   }
2277   return aGroup._retn();
2278 }
2279
2280 //=============================================================================
2281 /*!
2282  * SMESH_Mesh_i::removeGroup
2283  *
2284  * Should be called by ~SMESH_Group_i()
2285  */
2286 //=============================================================================
2287
2288 void SMESH_Mesh_i::removeGroup( const int theId )
2289 {
2290   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
2291   if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
2292     SMESH::SMESH_GroupBase_var group = _mapGroups[theId];
2293     _mapGroups.erase( theId );
2294     removeGeomGroupData( group );
2295     if ( !_impl->RemoveGroup( theId ))
2296     {
2297       // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
2298       RemoveGroup( group );
2299     }
2300     group->UnRegister();
2301   }
2302 }
2303
2304 //=============================================================================
2305 /*!
2306  *
2307  */
2308 //=============================================================================
2309
2310 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
2311   throw(SALOME::SALOME_Exception)
2312 {
2313   SMESH::log_array_var aLog;
2314
2315   SMESH_TRY;
2316   if ( _preMeshInfo )
2317     _preMeshInfo->FullLoadFromFile();
2318
2319   list < SMESHDS_Command * >logDS = _impl->GetLog();
2320   aLog = new SMESH::log_array;
2321   int indexLog = 0;
2322   int lg = logDS.size();
2323   SCRUTE(lg);
2324   aLog->length(lg);
2325   list < SMESHDS_Command * >::iterator its = logDS.begin();
2326   while(its != logDS.end()){
2327     SMESHDS_Command *com = *its;
2328     int comType = com->GetType();
2329     //SCRUTE(comType);
2330     int lgcom = com->GetNumber();
2331     //SCRUTE(lgcom);
2332     const list < int >&intList = com->GetIndexes();
2333     int inum = intList.size();
2334     //SCRUTE(inum);
2335     list < int >::const_iterator ii = intList.begin();
2336     const list < double >&coordList = com->GetCoords();
2337     int rnum = coordList.size();
2338     //SCRUTE(rnum);
2339     list < double >::const_iterator ir = coordList.begin();
2340     aLog[indexLog].commandType = comType;
2341     aLog[indexLog].number = lgcom;
2342     aLog[indexLog].coords.length(rnum);
2343     aLog[indexLog].indexes.length(inum);
2344     for(int i = 0; i < rnum; i++){
2345       aLog[indexLog].coords[i] = *ir;
2346       //MESSAGE(" "<<i<<" "<<ir.Value());
2347       ir++;
2348     }
2349     for(int i = 0; i < inum; i++){
2350       aLog[indexLog].indexes[i] = *ii;
2351       //MESSAGE(" "<<i<<" "<<ii.Value());
2352       ii++;
2353     }
2354     indexLog++;
2355     its++;
2356   }
2357   if(clearAfterGet)
2358     _impl->ClearLog();
2359
2360   SMESH_CATCH( SMESH::throwCorbaException );
2361
2362   return aLog._retn();
2363 }
2364
2365
2366 //=============================================================================
2367 /*!
2368  *
2369  */
2370 //=============================================================================
2371
2372 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
2373 {
2374   SMESH_TRY;
2375   _impl->ClearLog();
2376   SMESH_CATCH( SMESH::throwCorbaException );
2377 }
2378
2379 //=============================================================================
2380 /*!
2381  *
2382  */
2383 //=============================================================================
2384
2385 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
2386 {
2387   return _id;
2388 }
2389
2390 //=============================================================================
2391 /*!
2392  *
2393  */
2394 //=============================================================================
2395
2396 CORBA::Long SMESH_Mesh_i::GetStudyId()throw(SALOME::SALOME_Exception)
2397 {
2398   return _studyId;
2399 }
2400
2401 //=============================================================================
2402 namespace
2403 {
2404   //!< implementation of struct used to call methods of SMESH_Mesh_i from SMESH_Mesh
2405   // issue 0020918: groups removal is caused by hyp modification
2406   // issue 0021208: to forget not loaded mesh data at hyp modification
2407   struct TCallUp_i : public SMESH_Mesh::TCallUp
2408   {
2409     SMESH_Mesh_i* _mesh;
2410     TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
2411     virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); }
2412     virtual void HypothesisModified ()              { _mesh->onHypothesisModified(); }
2413     virtual void Load ()                            { _mesh->Load(); }
2414   };
2415 }
2416
2417 //================================================================================
2418 /*!
2419  * \brief callback from _impl to forget not loaded mesh data (issue 0021208)
2420  */
2421 //================================================================================
2422
2423 void SMESH_Mesh_i::onHypothesisModified()
2424 {
2425   if ( _preMeshInfo )
2426     _preMeshInfo->ForgetOrLoad();
2427 }
2428
2429 //=============================================================================
2430 /*!
2431  *
2432  */
2433 //=============================================================================
2434
2435 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
2436 {
2437   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
2438   _impl = impl;
2439   if ( _impl )
2440     _impl->SetCallUp( new TCallUp_i(this));
2441 }
2442
2443 //=============================================================================
2444 /*!
2445  *
2446  */
2447 //=============================================================================
2448
2449 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
2450 {
2451   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
2452   return *_impl;
2453 }
2454
2455 //=============================================================================
2456 /*!
2457  * Return mesh editor
2458  */
2459 //=============================================================================
2460
2461 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
2462   throw (SALOME::SALOME_Exception)
2463 {
2464   SMESH::SMESH_MeshEditor_var aMeshEdVar;
2465
2466   SMESH_TRY;
2467   if ( _preMeshInfo )
2468     _preMeshInfo->FullLoadFromFile();
2469
2470   // Create MeshEditor
2471   if ( !_editor )
2472     _editor = new SMESH_MeshEditor_i( this, false );
2473   aMeshEdVar = _editor->_this();
2474
2475   // Update Python script
2476   TPythonDump() << _editor << " = "
2477                 << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshEditor()";
2478
2479   SMESH_CATCH( SMESH::throwCorbaException );
2480
2481   return aMeshEdVar._retn();
2482 }
2483
2484 //=============================================================================
2485 /*!
2486  * Return mesh edition previewer
2487  */
2488 //=============================================================================
2489
2490 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
2491   throw (SALOME::SALOME_Exception)
2492 {
2493   SMESH::SMESH_MeshEditor_var aMeshEdVar;
2494
2495   SMESH_TRY;
2496   if ( _preMeshInfo )
2497     _preMeshInfo->FullLoadFromFile();
2498
2499   if ( !_previewEditor )
2500     _previewEditor = new SMESH_MeshEditor_i( this, true );
2501   aMeshEdVar = _previewEditor->_this();
2502
2503   SMESH_CATCH( SMESH::throwCorbaException );
2504
2505   return aMeshEdVar._retn();
2506 }
2507
2508 //================================================================================
2509 /*!
2510  * \brief Return true if the mesh has been edited since a last total re-compute
2511  *        and those modifications may prevent successful partial re-compute
2512  */
2513 //================================================================================
2514
2515 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard() throw(SALOME::SALOME_Exception)
2516 {
2517   Unexpect aCatch(SALOME_SalomeException);
2518   return _impl->HasModificationsToDiscard();
2519 }
2520
2521 //================================================================================
2522 /*!
2523  * \brief Returns a random unique color
2524  */
2525 //================================================================================
2526
2527 static SALOMEDS::Color getUniqueColor( const std::list<SALOMEDS::Color>& theReservedColors )
2528 {
2529   const int MAX_ATTEMPTS = 100;
2530   int cnt = 0;
2531   double tolerance = 0.5;
2532   SALOMEDS::Color col;
2533
2534   bool ok = false;
2535   while ( !ok ) {
2536     // generate random color
2537     double red    = (double)rand() / RAND_MAX;
2538     double green  = (double)rand() / RAND_MAX;
2539     double blue   = (double)rand() / RAND_MAX;
2540     // check existence in the list of the existing colors
2541     bool matched = false;
2542     std::list<SALOMEDS::Color>::const_iterator it;
2543     for ( it = theReservedColors.begin(); it != theReservedColors.end() && !matched; ++it ) {
2544       SALOMEDS::Color color = *it;
2545       double tol = fabs( color.R - red ) + fabs( color.G - green ) + fabs( color.B  - blue  );
2546       matched = tol < tolerance;
2547     }
2548     if ( (cnt+1) % 20 == 0 ) tolerance = tolerance/2;
2549     ok = ( ++cnt == MAX_ATTEMPTS ) || !matched;
2550     col.R = red;
2551     col.G = green;
2552     col.B = blue;
2553   }
2554   return col;
2555 }
2556
2557 //=============================================================================
2558 /*!
2559  * Sets auto-color mode. If it is on, groups get unique random colors
2560  */
2561 //=============================================================================
2562
2563 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOME_Exception)
2564 {
2565   Unexpect aCatch(SALOME_SalomeException);
2566   _impl->SetAutoColor(theAutoColor);
2567
2568   TPythonDump pyDump; // not to dump group->SetColor() from below code
2569   pyDump << SMESH::SMESH_Mesh_var(_this()) <<".SetAutoColor( "<<theAutoColor<<" )";
2570
2571   std::list<SALOMEDS::Color> aReservedColors;
2572   map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
2573   for ( ; it != _mapGroups.end(); it++ ) {
2574     if ( CORBA::is_nil( it->second )) continue;
2575     SALOMEDS::Color aColor = getUniqueColor( aReservedColors );
2576     it->second->SetColor( aColor );
2577     aReservedColors.push_back( aColor );
2578   }
2579 }
2580
2581 //=============================================================================
2582 /*!
2583  * Returns true if auto-color mode is on
2584  */
2585 //=============================================================================
2586
2587 CORBA::Boolean SMESH_Mesh_i::GetAutoColor() throw(SALOME::SALOME_Exception)
2588 {
2589   Unexpect aCatch(SALOME_SalomeException);
2590   return _impl->GetAutoColor();
2591 }
2592
2593 //=============================================================================
2594 /*!
2595  *  Checks if there are groups with equal names
2596  */
2597 //=============================================================================
2598
2599 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
2600 {
2601   return _impl->HasDuplicatedGroupNamesMED();
2602 }
2603
2604 //================================================================================
2605 /*!
2606  * \brief Care of a file before exporting mesh into it
2607  */
2608 //================================================================================
2609
2610 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
2611 {
2612   TCollection_AsciiString aFullName ((char*)file);
2613   OSD_Path aPath (aFullName);
2614   OSD_File aFile (aPath);
2615   if (aFile.Exists()) {
2616     // existing filesystem node
2617     if (aFile.KindOfFile() == OSD_FILE) {
2618       if (aFile.IsWriteable()) {
2619         if (overwrite) {
2620           aFile.Reset();
2621           aFile.Remove();
2622         }
2623         if (aFile.Failed()) {
2624           TCollection_AsciiString msg ("File ");
2625           msg += aFullName + " cannot be replaced.";
2626           THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2627         }
2628       } else {
2629         TCollection_AsciiString msg ("File ");
2630         msg += aFullName + " cannot be overwritten.";
2631         THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2632       }
2633     } else {
2634       TCollection_AsciiString msg ("Location ");
2635       msg += aFullName + " is not a file.";
2636       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2637     }
2638   } else {
2639     // nonexisting file; check if it can be created
2640     aFile.Reset();
2641     aFile.Build(OSD_WriteOnly, OSD_Protection());
2642     if (aFile.Failed()) {
2643       TCollection_AsciiString msg ("You cannot create the file ");
2644       msg += aFullName + ". Check the directory existance and access rights.";
2645       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2646     } else {
2647       aFile.Close();
2648       aFile.Remove();
2649     }
2650   }
2651 }
2652
2653 //================================================================================
2654 /*!
2655  * \brief Prepares a file for export and pass names of mesh groups from study to mesh DS
2656  *  \param file - file name
2657  *  \param overwrite - to erase the file or not
2658  *  \retval string - mesh name
2659  */
2660 //================================================================================
2661
2662 string SMESH_Mesh_i::prepareMeshNameAndGroups(const char*    file,
2663                                               CORBA::Boolean overwrite)
2664 {
2665   // Perform Export
2666   PrepareForWriting(file, overwrite);
2667   string aMeshName = "Mesh";
2668   SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
2669   if ( !aStudy->_is_nil() ) {
2670     SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
2671     if ( !aMeshSO->_is_nil() ) {
2672       CORBA::String_var name = aMeshSO->GetName();
2673       aMeshName = name;
2674       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
2675       if ( !aStudy->GetProperties()->IsLocked() )
2676       {
2677         SALOMEDS::GenericAttribute_wrap anAttr;
2678         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
2679         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
2680         SALOMEDS::AttributeExternalFileDef_wrap aFileName = anAttr;
2681         ASSERT(!aFileName->_is_nil());
2682         aFileName->SetValue(file);
2683         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
2684         SALOMEDS::AttributeFileType_wrap aFileType = anAttr;
2685         ASSERT(!aFileType->_is_nil());
2686         aFileType->SetValue("FICHIERMED");
2687       }
2688     }
2689   }
2690   // Update Python script
2691   // set name of mesh before export
2692   TPythonDump() << _gen_i << ".SetName("
2693                 << SMESH::SMESH_Mesh_var(_this()) << ", '" << aMeshName.c_str() << "')";
2694
2695   // check names of groups
2696   checkGroupNames();
2697
2698   return aMeshName;
2699 }
2700
2701 //================================================================================
2702 /*!
2703  * \brief Export to med file
2704  */
2705 //================================================================================
2706
2707 void SMESH_Mesh_i::ExportToMEDX (const char*        file,
2708                                  CORBA::Boolean     auto_groups,
2709                                  SMESH::MED_VERSION theVersion,
2710                                  CORBA::Boolean     overwrite,
2711                                  CORBA::Boolean     autoDimension)
2712   throw(SALOME::SALOME_Exception)
2713 {
2714   SMESH_TRY;
2715   if ( _preMeshInfo )
2716     _preMeshInfo->FullLoadFromFile();
2717
2718   string aMeshName = prepareMeshNameAndGroups(file, overwrite);
2719   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportToMEDX( r'"
2720                 << file << "', " << auto_groups << ", "
2721                 << theVersion << ", " << overwrite << ", "
2722                 << autoDimension << " )";
2723
2724   _impl->ExportMED( file, aMeshName.c_str(), auto_groups, theVersion, 0, autoDimension );
2725
2726   SMESH_CATCH( SMESH::throwCorbaException );
2727 }
2728
2729 //================================================================================
2730 /*!
2731  * \brief Export a mesh to a med file
2732  */
2733 //================================================================================
2734
2735 void SMESH_Mesh_i::ExportToMED (const char*        file,
2736                                 CORBA::Boolean     auto_groups,
2737                                 SMESH::MED_VERSION theVersion)
2738   throw(SALOME::SALOME_Exception)
2739 {
2740   ExportToMEDX(file,auto_groups,theVersion,true);
2741 }
2742
2743 //================================================================================
2744 /*!
2745  * \brief Export a mesh to a med file
2746  */
2747 //================================================================================
2748
2749 void SMESH_Mesh_i::ExportMED (const char* file,
2750                               CORBA::Boolean auto_groups)
2751   throw(SALOME::SALOME_Exception)
2752 {
2753   ExportToMEDX(file,auto_groups,SMESH::MED_V2_2,true);
2754 }
2755
2756 //================================================================================
2757 /*!
2758  * \brief Export a mesh to a SAUV file
2759  */
2760 //================================================================================
2761
2762 void SMESH_Mesh_i::ExportSAUV (const char* file,
2763                                CORBA::Boolean auto_groups)
2764   throw(SALOME::SALOME_Exception)
2765 {
2766   Unexpect aCatch(SALOME_SalomeException);
2767   if ( _preMeshInfo )
2768     _preMeshInfo->FullLoadFromFile();
2769
2770   string aMeshName = prepareMeshNameAndGroups(file, true);
2771   TPythonDump() << SMESH::SMESH_Mesh_var( _this())
2772                 << ".ExportSAUV( r'" << file << "', " << auto_groups << " )";
2773   _impl->ExportSAUV(file, aMeshName.c_str(), auto_groups);
2774 }
2775
2776
2777 //================================================================================
2778 /*!
2779  * \brief Export a mesh to a DAT file
2780  */
2781 //================================================================================
2782
2783 void SMESH_Mesh_i::ExportDAT (const char *file)
2784   throw(SALOME::SALOME_Exception)
2785 {
2786   Unexpect aCatch(SALOME_SalomeException);
2787   if ( _preMeshInfo )
2788     _preMeshInfo->FullLoadFromFile();
2789
2790   // Update Python script
2791   // check names of groups
2792   checkGroupNames();
2793   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportDAT( r'" << file << "' )";
2794
2795   // Perform Export
2796   PrepareForWriting(file);
2797   _impl->ExportDAT(file);
2798 }
2799
2800 //================================================================================
2801 /*!
2802  * \brief Export a mesh to an UNV file
2803  */
2804 //================================================================================
2805
2806 void SMESH_Mesh_i::ExportUNV (const char *file)
2807   throw(SALOME::SALOME_Exception)
2808 {
2809   Unexpect aCatch(SALOME_SalomeException);
2810   if ( _preMeshInfo )
2811     _preMeshInfo->FullLoadFromFile();
2812
2813   // Update Python script
2814   // check names of groups
2815   checkGroupNames();
2816   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportUNV( r'" << file << "' )";
2817
2818   // Perform Export
2819   PrepareForWriting(file);
2820   _impl->ExportUNV(file);
2821 }
2822
2823 //================================================================================
2824 /*!
2825  * \brief Export a mesh to an STL file
2826  */
2827 //================================================================================
2828
2829 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
2830   throw(SALOME::SALOME_Exception)
2831 {
2832   Unexpect aCatch(SALOME_SalomeException);
2833   if ( _preMeshInfo )
2834     _preMeshInfo->FullLoadFromFile();
2835
2836   // Update Python script
2837   // check names of groups
2838   checkGroupNames();
2839   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
2840                 << ".ExportSTL( r'" << file << "', " << isascii << " )";
2841
2842   // Perform Export
2843   PrepareForWriting(file);
2844   _impl->ExportSTL(file, isascii);
2845 }
2846
2847 //================================================================================
2848 /*!
2849  * \brief Export a part of mesh to a med file
2850  */
2851 //================================================================================
2852
2853 void SMESH_Mesh_i::ExportPartToMED(::SMESH::SMESH_IDSource_ptr meshPart,
2854                                    const char*                 file,
2855                                    CORBA::Boolean              auto_groups,
2856                                    ::SMESH::MED_VERSION        version,
2857                                    ::CORBA::Boolean            overwrite,
2858                                    ::CORBA::Boolean            autoDimension)
2859   throw (SALOME::SALOME_Exception)
2860 {
2861   Unexpect aCatch(SALOME_SalomeException);
2862   TPythonDump pyDump;
2863
2864   if ( SMESH_Mesh_i * mesh = SMESH::DownCast< SMESH_Mesh_i* >( meshPart ))
2865   {
2866     mesh->ExportToMEDX( file, auto_groups, version, autoDimension );
2867   }
2868   else
2869   {
2870     if ( _preMeshInfo )
2871       _preMeshInfo->FullLoadFromFile();
2872
2873     PrepareForWriting(file, overwrite);
2874
2875     string aMeshName = "Mesh";
2876     SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
2877     if ( !aStudy->_is_nil() ) {
2878       SALOMEDS::SObject_wrap SO = _gen_i->ObjectToSObject( aStudy, meshPart );
2879       if ( !SO->_is_nil() ) {
2880         CORBA::String_var name = SO->GetName();
2881         aMeshName = name;
2882       }
2883     }
2884     SMESH_MeshPartDS partDS( meshPart );
2885     _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version, &partDS, autoDimension );
2886   }
2887   pyDump << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToMED( "
2888          << meshPart << ", r'" << file << "', "
2889          << auto_groups << ", " << version << ", " << overwrite << ", "
2890          << autoDimension << " )";
2891 }
2892
2893 //================================================================================
2894 /*!
2895  * \brief Export a part of mesh to a DAT file
2896  */
2897 //================================================================================
2898
2899 void SMESH_Mesh_i::ExportPartToDAT(::SMESH::SMESH_IDSource_ptr meshPart,
2900                                    const char*                 file)
2901   throw (SALOME::SALOME_Exception)
2902 {
2903   Unexpect aCatch(SALOME_SalomeException);
2904   if ( _preMeshInfo )
2905     _preMeshInfo->FullLoadFromFile();
2906
2907   PrepareForWriting(file);
2908
2909   SMESH_MeshPartDS partDS( meshPart );
2910   _impl->ExportDAT(file,&partDS);
2911
2912   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
2913                 << ".ExportPartToDAT( " << meshPart << ", r'" << file << "' )";
2914 }
2915 //================================================================================
2916 /*!
2917  * \brief Export a part of mesh to an UNV file
2918  */
2919 //================================================================================
2920
2921 void SMESH_Mesh_i::ExportPartToUNV(::SMESH::SMESH_IDSource_ptr meshPart,
2922                                    const char*                 file)
2923   throw (SALOME::SALOME_Exception)
2924 {
2925   Unexpect aCatch(SALOME_SalomeException);
2926   if ( _preMeshInfo )
2927     _preMeshInfo->FullLoadFromFile();
2928
2929   PrepareForWriting(file);
2930
2931   SMESH_MeshPartDS partDS( meshPart );
2932   _impl->ExportUNV(file, &partDS);
2933
2934   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
2935                 << ".ExportPartToUNV( " << meshPart<< ", r'" << file << "' )";
2936 }
2937 //================================================================================
2938 /*!
2939  * \brief Export a part of mesh to an STL file
2940  */
2941 //================================================================================
2942
2943 void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
2944                                    const char*                 file,
2945                                    ::CORBA::Boolean            isascii)
2946   throw (SALOME::SALOME_Exception)
2947 {
2948   Unexpect aCatch(SALOME_SalomeException);
2949   if ( _preMeshInfo )
2950     _preMeshInfo->FullLoadFromFile();
2951
2952   PrepareForWriting(file);
2953
2954   SMESH_MeshPartDS partDS( meshPart );
2955   _impl->ExportSTL(file, isascii, &partDS);
2956
2957   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( "
2958                 << meshPart<< ", r'" << file << "', " << isascii << ")";
2959 }
2960
2961 //================================================================================
2962 /*!
2963  * \brief Export a part of mesh to an STL file
2964  */
2965 //================================================================================
2966
2967 void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart,
2968                               const char*                 file,
2969                               CORBA::Boolean              overwrite)
2970   throw (SALOME::SALOME_Exception)
2971 {
2972 #ifdef WITH_CGNS
2973   Unexpect aCatch(SALOME_SalomeException);
2974   if ( _preMeshInfo )
2975     _preMeshInfo->FullLoadFromFile();
2976
2977   PrepareForWriting(file,overwrite);
2978
2979   SMESH_MeshPartDS partDS( meshPart );
2980   _impl->ExportCGNS(file, &partDS);
2981
2982   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportCGNS( "
2983                 << meshPart<< ", r'" << file << "', " << overwrite << ")";
2984 #else
2985   THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
2986 #endif
2987 }
2988
2989 //================================================================================
2990 /*!
2991  * \brief Export a part of mesh to a GMF file
2992  */
2993 //================================================================================
2994
2995 void SMESH_Mesh_i::ExportGMF(::SMESH::SMESH_IDSource_ptr meshPart,
2996                              const char*                 file,
2997                              bool                        withRequiredGroups)
2998   throw (SALOME::SALOME_Exception)
2999 {
3000   Unexpect aCatch(SALOME_SalomeException);
3001   if ( _preMeshInfo )
3002     _preMeshInfo->FullLoadFromFile();
3003
3004   PrepareForWriting(file,/*overwrite=*/true);
3005
3006   SMESH_MeshPartDS partDS( meshPart );
3007   _impl->ExportGMF(file, &partDS, withRequiredGroups);
3008
3009   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportGMF( "
3010                 << meshPart<< ", r'"
3011                 << file << "', "
3012                 << withRequiredGroups << ")";
3013 }
3014
3015 //=============================================================================
3016 /*!
3017  * Return computation progress [0.,1]
3018  */
3019 //=============================================================================
3020
3021 CORBA::Double SMESH_Mesh_i::GetComputeProgress()
3022 {
3023   SMESH_TRY;
3024
3025   return _impl->GetComputeProgress();
3026
3027   SMESH_CATCH( SMESH::doNothing );
3028   return 0.;
3029 }
3030
3031 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
3032 {
3033   Unexpect aCatch(SALOME_SalomeException);
3034   if ( _preMeshInfo )
3035     return _preMeshInfo->NbNodes();
3036
3037   return _impl->NbNodes();
3038 }
3039
3040 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
3041 {
3042   Unexpect aCatch(SALOME_SalomeException);
3043   if ( _preMeshInfo )
3044     return _preMeshInfo->NbElements();
3045
3046   return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes() + NbBalls();
3047 }
3048
3049 CORBA::Long SMESH_Mesh_i::Nb0DElements()throw (SALOME::SALOME_Exception)
3050 {
3051   Unexpect aCatch(SALOME_SalomeException);
3052   if ( _preMeshInfo )
3053     return _preMeshInfo->Nb0DElements();
3054
3055   return _impl->Nb0DElements();
3056 }
3057
3058 CORBA::Long SMESH_Mesh_i::NbBalls() throw (SALOME::SALOME_Exception)
3059 {
3060   Unexpect aCatch(SALOME_SalomeException);
3061   if ( _preMeshInfo )
3062     return _preMeshInfo->NbBalls();
3063
3064   return _impl->NbBalls();
3065 }
3066
3067 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
3068 {
3069   Unexpect aCatch(SALOME_SalomeException);
3070   if ( _preMeshInfo )
3071     return _preMeshInfo->NbEdges();
3072
3073   return _impl->NbEdges();
3074 }
3075
3076 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
3077   throw(SALOME::SALOME_Exception)
3078 {
3079   Unexpect aCatch(SALOME_SalomeException);
3080   if ( _preMeshInfo )
3081     return _preMeshInfo->NbEdges( (SMDSAbs_ElementOrder) order );
3082
3083   return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
3084 }
3085
3086 //=============================================================================
3087
3088 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
3089 {
3090   Unexpect aCatch(SALOME_SalomeException);
3091   if ( _preMeshInfo )
3092     return _preMeshInfo->NbFaces();
3093
3094   return _impl->NbFaces();
3095 }
3096
3097 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
3098 {
3099   Unexpect aCatch(SALOME_SalomeException);
3100   if ( _preMeshInfo )
3101     return _preMeshInfo->NbTriangles();
3102
3103   return _impl->NbTriangles();
3104 }
3105
3106 CORBA::Long SMESH_Mesh_i::NbBiQuadTriangles()throw(SALOME::SALOME_Exception)
3107 {
3108   Unexpect aCatch(SALOME_SalomeException);
3109   if ( _preMeshInfo )
3110     return _preMeshInfo->NbBiQuadTriangles();
3111
3112   return _impl->NbBiQuadTriangles();
3113 }
3114
3115 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
3116 {
3117   Unexpect aCatch(SALOME_SalomeException);
3118   if ( _preMeshInfo )
3119     return _preMeshInfo->NbQuadrangles();
3120
3121   return _impl->NbQuadrangles();
3122 }
3123
3124 CORBA::Long SMESH_Mesh_i::NbBiQuadQuadrangles()throw(SALOME::SALOME_Exception)
3125 {
3126   Unexpect aCatch(SALOME_SalomeException);
3127   if ( _preMeshInfo )
3128     return _preMeshInfo->NbBiQuadQuadrangles();
3129
3130   return _impl->NbBiQuadQuadrangles();
3131 }
3132
3133 CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
3134 {
3135   Unexpect aCatch(SALOME_SalomeException);
3136   if ( _preMeshInfo )
3137     return _preMeshInfo->NbPolygons();
3138
3139   return _impl->NbPolygons();
3140 }
3141
3142 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
3143   throw(SALOME::SALOME_Exception)
3144 {
3145   Unexpect aCatch(SALOME_SalomeException);
3146   if ( _preMeshInfo )
3147     return _preMeshInfo->NbFaces( (SMDSAbs_ElementOrder) order );
3148
3149   return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
3150 }
3151
3152 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
3153   throw(SALOME::SALOME_Exception)
3154 {
3155   Unexpect aCatch(SALOME_SalomeException);
3156   if ( _preMeshInfo )
3157     return _preMeshInfo->NbTriangles( (SMDSAbs_ElementOrder) order );
3158
3159   return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
3160 }
3161
3162 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
3163   throw(SALOME::SALOME_Exception)
3164 {
3165   Unexpect aCatch(SALOME_SalomeException);
3166   if ( _preMeshInfo )
3167     return _preMeshInfo->NbQuadrangles( (SMDSAbs_ElementOrder) order );
3168
3169   return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
3170 }
3171
3172 //=============================================================================
3173
3174 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
3175 {
3176   Unexpect aCatch(SALOME_SalomeException);
3177   if ( _preMeshInfo )
3178     return _preMeshInfo->NbVolumes();
3179
3180   return _impl->NbVolumes();
3181 }
3182
3183 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
3184 {
3185   Unexpect aCatch(SALOME_SalomeException);
3186   if ( _preMeshInfo )
3187     return _preMeshInfo->NbTetras();
3188
3189   return _impl->NbTetras();
3190 }
3191
3192 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
3193 {
3194   Unexpect aCatch(SALOME_SalomeException);
3195   if ( _preMeshInfo )
3196     return _preMeshInfo->NbHexas();
3197
3198   return _impl->NbHexas();
3199 }
3200
3201 CORBA::Long SMESH_Mesh_i::NbTriQuadraticHexas()throw(SALOME::SALOME_Exception)
3202 {
3203   Unexpect aCatch(SALOME_SalomeException);
3204   if ( _preMeshInfo )
3205     return _preMeshInfo->NbTriQuadHexas();
3206
3207   return _impl->NbTriQuadraticHexas();
3208 }
3209
3210 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
3211 {
3212   Unexpect aCatch(SALOME_SalomeException);
3213   if ( _preMeshInfo )
3214     return _preMeshInfo->NbPyramids();
3215
3216   return _impl->NbPyramids();
3217 }
3218
3219 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
3220 {
3221   Unexpect aCatch(SALOME_SalomeException);
3222   if ( _preMeshInfo )
3223     return _preMeshInfo->NbPrisms();
3224
3225   return _impl->NbPrisms();
3226 }
3227
3228 CORBA::Long SMESH_Mesh_i::NbHexagonalPrisms()throw(SALOME::SALOME_Exception)
3229 {
3230   Unexpect aCatch(SALOME_SalomeException);
3231   if ( _preMeshInfo )
3232     return _preMeshInfo->NbHexPrisms();
3233
3234   return _impl->NbHexagonalPrisms();
3235 }
3236
3237 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
3238 {
3239   Unexpect aCatch(SALOME_SalomeException);
3240   if ( _preMeshInfo )
3241     return _preMeshInfo->NbPolyhedrons();
3242
3243   return _impl->NbPolyhedrons();
3244 }
3245
3246 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
3247   throw(SALOME::SALOME_Exception)
3248 {
3249   Unexpect aCatch(SALOME_SalomeException);
3250   if ( _preMeshInfo )
3251     return _preMeshInfo->NbVolumes( (SMDSAbs_ElementOrder) order );
3252
3253   return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
3254 }
3255
3256 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
3257   throw(SALOME::SALOME_Exception)
3258 {
3259   Unexpect aCatch(SALOME_SalomeException);