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