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