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