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