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