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