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