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