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