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