Salome HOME
0020279: [CEA 334] control the "random" use when using mesh algorithms
[modules/smesh.git] / src / SMESH_I / SMESH_Mesh_i.cxx
1 //  Copyright (C) 2007-2008  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.
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 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
23 //  File   : SMESH_Mesh_i.cxx
24 //  Author : Paul RASCLE, EDF
25 //  Module : SMESH
26 //
27 #include "SMESH_Mesh_i.hxx"
28
29 #include "SMESH_Filter_i.hxx"
30 #include "SMESH_Gen_i.hxx"
31 #include "SMESH_Group_i.hxx"
32 #include "SMESH_MEDMesh_i.hxx"
33 #include "SMESH_MeshEditor_i.hxx"
34 #include "SMESH_PythonDump.hxx"
35 #include "SMESH_subMesh_i.hxx"
36
37 #include "DriverMED_R_SMESHDS_Mesh.h"
38 #include "DriverMED_W_SMESHDS_Mesh.h"
39 #include "SMDS_VolumeTool.hxx"
40 #include "SMESHDS_Command.hxx"
41 #include "SMESHDS_CommandType.hxx"
42 #include "SMESHDS_GroupOnGeom.hxx"
43 #include "SMESH_Group.hxx"
44 #include "SMESH_MeshEditor.hxx"
45 #include "SMESH_MesherHelper.hxx"
46 #include "SMDS_EdgePosition.hxx"
47 #include "SMDS_FacePosition.hxx"
48
49 #include "OpUtil.hxx"
50 #include "SALOME_NamingService.hxx"
51 #include "Utils_CorbaException.hxx"
52 #include "Utils_ExceptHandlers.hxx"
53 #include "Utils_SINGLETON.hxx"
54 #include "utilities.h"
55 #include "GEOMImpl_Types.hxx"
56
57 // OCCT Includes
58 #include <BRep_Builder.hxx>
59 #include <OSD_Directory.hxx>
60 #include <OSD_File.hxx>
61 #include <OSD_Path.hxx>
62 #include <OSD_Protection.hxx>
63 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
64 #include <TColStd_MapOfInteger.hxx>
65 #include <TColStd_SequenceOfInteger.hxx>
66 #include <TCollection_AsciiString.hxx>
67 #include <TopExp_Explorer.hxx>
68 #include <TopoDS_Compound.hxx>
69
70 // STL Includes
71 #include <string>
72 #include <iostream>
73 #include <sstream>
74 #include <sys/stat.h>
75
76 #ifdef _DEBUG_
77 static int MYDEBUG = 0;
78 #else
79 static int MYDEBUG = 0;
80 #endif
81
82 using namespace std;
83 using SMESH::TPythonDump;
84
85 int SMESH_Mesh_i::myIdGenerator = 0;
86
87
88
89 //=============================================================================
90 /*!
91  *  Constructor
92  */
93 //=============================================================================
94
95 SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
96                             SMESH_Gen_i*            gen_i,
97                             CORBA::Long studyId )
98 : SALOME::GenericObj_i( thePOA )
99 {
100   MESSAGE("SMESH_Mesh_i");
101   _impl = NULL;
102   _gen_i = gen_i;
103   _id = myIdGenerator++;
104   _studyId = studyId;
105 }
106
107 //=============================================================================
108 /*!
109  *  Destructor
110  */
111 //=============================================================================
112
113 SMESH_Mesh_i::~SMESH_Mesh_i()
114 {
115   INFOS("~SMESH_Mesh_i");
116   map<int, SMESH::SMESH_GroupBase_ptr>::iterator it;
117   for ( it = _mapGroups.begin(); it != _mapGroups.end(); it++ ) {
118     SMESH_GroupBase_i* aGroup = dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( it->second ).in() );
119     if ( aGroup ) {
120       // this method is colled from destructor of group (PAL6331)
121       //_impl->RemoveGroup( aGroup->GetLocalID() );
122       
123       aGroup->Destroy();
124     }
125   }
126   _mapGroups.clear();
127   delete _impl;
128 }
129
130 //=============================================================================
131 /*!
132  *  SetShape
133  *
134  *  Associates <this> mesh with <theShape> and puts a reference
135  *  to <theShape> into the current study;
136  *  the previous shape is substituted by the new one.
137  */
138 //=============================================================================
139
140 void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
141     throw (SALOME::SALOME_Exception)
142 {
143   Unexpect aCatch(SALOME_SalomeException);
144   try {
145     _impl->ShapeToMesh( _gen_i->GeomObjectToShape( theShapeObject ));
146   }
147   catch(SALOME_Exception & S_ex) {
148     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
149   }
150   // to track changes of GEOM groups
151   addGeomGroupData( theShapeObject, _this() );
152 }
153
154 //================================================================================
155 /*!
156  * \brief return true if mesh has a shape to build a shape on
157  */
158 //================================================================================
159
160 CORBA::Boolean SMESH_Mesh_i::HasShapeToMesh()
161   throw (SALOME::SALOME_Exception)
162 {
163   Unexpect aCatch(SALOME_SalomeException);
164   bool res = false;
165   try {
166     res = _impl->HasShapeToMesh();
167   }
168   catch(SALOME_Exception & S_ex) {
169     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
170   }
171   return res;
172 }
173
174 //=======================================================================
175 //function : GetShapeToMesh
176 //purpose  :
177 //=======================================================================
178
179 GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
180   throw (SALOME::SALOME_Exception)
181 {
182   Unexpect aCatch(SALOME_SalomeException);
183   GEOM::GEOM_Object_var aShapeObj;
184   try {
185     TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
186     if ( !S.IsNull() )
187       aShapeObj = _gen_i->ShapeToGeomObject( S );
188   }
189   catch(SALOME_Exception & S_ex) {
190     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
191   }
192   return aShapeObj._retn();
193 }
194
195 //================================================================================
196 /*!
197  * \brief Remove all nodes and elements
198  */
199 //================================================================================
200
201 void SMESH_Mesh_i::Clear() throw (SALOME::SALOME_Exception)
202 {
203   Unexpect aCatch(SALOME_SalomeException);
204   try {
205     _impl->Clear();
206   }
207   catch(SALOME_Exception & S_ex) {
208     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
209   }
210   TPythonDump() <<  _this() << ".Clear()";
211 }
212
213 //================================================================================
214 /*!
215  * \brief Remove all nodes and elements for indicated shape
216  */
217 //================================================================================
218
219 void SMESH_Mesh_i::ClearSubMesh(CORBA::Long ShapeID)
220   throw (SALOME::SALOME_Exception)
221 {
222   Unexpect aCatch(SALOME_SalomeException);
223   try {
224     _impl->ClearSubMesh( ShapeID );
225   }
226   catch(SALOME_Exception & S_ex) {
227     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
228   }
229 }
230
231 //=============================================================================
232 /*!
233  *
234  */
235 //=============================================================================
236
237 static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
238 {
239   SMESH::DriverMED_ReadStatus res;
240   switch (theStatus)
241   {
242   case DriverMED_R_SMESHDS_Mesh::DRS_OK:
243     res = SMESH::DRS_OK; break;
244   case DriverMED_R_SMESHDS_Mesh::DRS_EMPTY:
245     res = SMESH::DRS_EMPTY; break;
246   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_RENUMBER:
247     res = SMESH::DRS_WARN_RENUMBER; break;
248   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
249     res = SMESH::DRS_WARN_SKIP_ELEM; break;
250   case DriverMED_R_SMESHDS_Mesh::DRS_FAIL:
251   default:
252     res = SMESH::DRS_FAIL; break;
253   }
254   return res;
255 }
256
257 //=============================================================================
258 /*!
259  *  ImportMEDFile
260  *
261  *  Imports mesh data from MED file
262  */
263 //=============================================================================
264
265 SMESH::DriverMED_ReadStatus
266 SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
267   throw ( SALOME::SALOME_Exception )
268 {
269   Unexpect aCatch(SALOME_SalomeException);
270   int status;
271   try {
272     status = _impl->MEDToMesh( theFileName, theMeshName );
273   }
274   catch( SALOME_Exception& S_ex ) {
275     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
276   }
277   catch ( ... ) {
278     THROW_SALOME_CORBA_EXCEPTION("ImportMEDFile(): unknown exception", SALOME::BAD_PARAM);
279   }
280
281   CreateGroupServants();
282
283   int major, minor, release;
284   if( !MED::getMEDVersion( theFileName, major, minor, release ) )
285     major = minor = release = -1;
286   myFileInfo           = new SALOME_MED::MedFileInfo();
287   myFileInfo->fileName = theFileName;
288   myFileInfo->fileSize = 0;
289 #ifdef WIN32
290   struct _stati64 d;
291   if ( ::_stati64( theFileName, &d ) != -1 )
292 #else
293   struct stat64 d;
294   if ( ::stat64( theFileName, &d ) != -1 )
295 #endif
296     myFileInfo->fileSize = d.st_size;
297   myFileInfo->major    = major;
298   myFileInfo->minor    = minor;
299   myFileInfo->release  = release;
300
301   return ConvertDriverMEDReadStatus(status);
302 }
303
304 //================================================================================
305 /*!
306  * \brief Return string representation of a MED file version comprising nbDigits
307  */
308 //================================================================================
309
310 char* SMESH_Mesh_i::GetVersionString(SMESH::MED_VERSION version, CORBA::Short nbDigits)
311 {
312   std::string ver = DriverMED_W_SMESHDS_Mesh::GetVersionString(MED::EVersion(version),
313                                                                nbDigits);
314   return CORBA::string_dup( ver.c_str() );
315 }
316
317 //=============================================================================
318 /*!
319  *  ImportUNVFile
320  *
321  *  Imports mesh data from MED file
322  */
323 //=============================================================================
324
325 int SMESH_Mesh_i::ImportUNVFile( const char* theFileName )
326   throw ( SALOME::SALOME_Exception )
327 {
328   // Read mesh with name = <theMeshName> into SMESH_Mesh
329   _impl->UNVToMesh( theFileName );
330
331   CreateGroupServants();
332
333   return 1;
334 }
335
336 //=============================================================================
337 /*!
338  *  ImportSTLFile
339  *
340  *  Imports mesh data from STL file
341  */
342 //=============================================================================
343 int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
344   throw ( SALOME::SALOME_Exception )
345 {
346   // Read mesh with name = <theMeshName> into SMESH_Mesh
347   _impl->STLToMesh( theFileName );
348
349   return 1;
350 }
351
352 //=============================================================================
353 /*!
354  *  importMEDFile
355  *
356  *  Imports mesh data from MED file
357  */
358 //=============================================================================
359
360 // int SMESH_Mesh_i::importMEDFile( const char* theFileName, const char* theMeshName )
361 // {
362 //   // Read mesh with name = <theMeshName> and all its groups into SMESH_Mesh
363 //   int status = _impl->MEDToMesh( theFileName, theMeshName );
364 //   CreateGroupServants();
365
366 //   return status;
367 // }
368
369 //=============================================================================
370 /*!
371  *
372  */
373 //=============================================================================
374
375 #define RETURNCASE(hyp_stat) case SMESH_Hypothesis::hyp_stat: return SMESH::hyp_stat;
376
377 SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
378                          (SMESH_Hypothesis::Hypothesis_Status theStatus)
379 {
380   switch (theStatus) {
381   RETURNCASE( HYP_OK            );
382   RETURNCASE( HYP_MISSING       );
383   RETURNCASE( HYP_CONCURENT     );
384   RETURNCASE( HYP_BAD_PARAMETER );
385   RETURNCASE( HYP_HIDDEN_ALGO   );
386   RETURNCASE( HYP_HIDING_ALGO   );
387   RETURNCASE( HYP_UNKNOWN_FATAL );
388   RETURNCASE( HYP_INCOMPATIBLE  );
389   RETURNCASE( HYP_NOTCONFORM    );
390   RETURNCASE( HYP_ALREADY_EXIST );
391   RETURNCASE( HYP_BAD_DIM       );
392   RETURNCASE( HYP_BAD_SUBSHAPE  );
393   RETURNCASE( HYP_BAD_GEOMETRY  );
394   RETURNCASE( HYP_NEED_SHAPE    );
395   default:;
396   }
397   return SMESH::HYP_UNKNOWN_FATAL;
398 }
399
400 //=============================================================================
401 /*!
402  *  AddHypothesis
403  *
404  *  calls internal addHypothesis() and then adds a reference to <anHyp> under
405  *  the SObject actually having a reference to <aSubShape>.
406  *  NB: For this method to work, it is necessary to add a reference to sub-shape first.
407  */
408 //=============================================================================
409
410 SMESH::Hypothesis_Status SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
411                                                      SMESH::SMESH_Hypothesis_ptr anHyp)
412   throw(SALOME::SALOME_Exception)
413 {
414   Unexpect aCatch(SALOME_SalomeException);
415   SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShapeObject, anHyp );
416
417   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
418     _gen_i->AddHypothesisToShape(_gen_i->GetCurrentStudy(), _this(),
419                                  aSubShapeObject, anHyp );
420
421   if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
422
423   // Update Python script
424   if(_impl->HasShapeToMesh()) {
425     TPythonDump() << "status = " << _this() << ".AddHypothesis( "
426                   << aSubShapeObject << ", " << anHyp << " )";
427   }
428   else {
429     TPythonDump() << "status = " << _this() << ".AddHypothesis( "<< anHyp << " )";
430   }
431   
432   return ConvertHypothesisStatus(status);
433 }
434
435 //=============================================================================
436 /*!
437  *
438  */
439 //=============================================================================
440
441 SMESH_Hypothesis::Hypothesis_Status
442   SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
443                               SMESH::SMESH_Hypothesis_ptr anHyp)
444 {
445   if(MYDEBUG) MESSAGE("addHypothesis");
446
447   if (CORBA::is_nil(aSubShapeObject) && HasShapeToMesh())
448     THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
449                                  SALOME::BAD_PARAM);
450
451   SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp);
452   if (CORBA::is_nil(myHyp))
453     THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",
454                                  SALOME::BAD_PARAM);
455
456   SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
457   try
458   {
459     TopoDS_Shape myLocSubShape;
460     //use PseudoShape in case if mesh has no shape
461     if(HasShapeToMesh())
462       myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject);
463     else              
464       myLocSubShape = _impl->GetShapeToMesh();
465     
466     int hypId = myHyp->GetId();
467     status = _impl->AddHypothesis(myLocSubShape, hypId);
468     if ( !SMESH_Hypothesis::IsStatusFatal(status) ) {
469       _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( myHyp );
470       // assure there is a corresponding submesh
471       if ( !_impl->IsMainShape( myLocSubShape )) {
472         int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
473         if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
474           createSubMesh( aSubShapeObject );
475       }
476     }
477   }
478   catch(SALOME_Exception & S_ex)
479   {
480     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
481   }
482   return status;
483 }
484
485 //=============================================================================
486 /*!
487  *
488  */
489 //=============================================================================
490
491 SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
492                                                         SMESH::SMESH_Hypothesis_ptr anHyp)
493      throw(SALOME::SALOME_Exception)
494 {
495   Unexpect aCatch(SALOME_SalomeException);
496   SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShapeObject, anHyp );
497
498   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
499     _gen_i->RemoveHypothesisFromShape(_gen_i->GetCurrentStudy(), _this(),
500                                       aSubShapeObject, anHyp );
501
502   // Update Python script
503     // Update Python script
504   if(_impl->HasShapeToMesh()) {
505   TPythonDump() << "status = " << _this() << ".RemoveHypothesis( "
506                 << aSubShapeObject << ", " << anHyp << " )";
507   }
508   else {
509     TPythonDump() << "status = " << _this() << ".RemoveHypothesis( "
510                   << anHyp << " )";
511   }
512
513   return ConvertHypothesisStatus(status);
514 }
515
516 //=============================================================================
517 /*!
518  *
519  */
520 //=============================================================================
521
522 SMESH_Hypothesis::Hypothesis_Status SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
523                                  SMESH::SMESH_Hypothesis_ptr anHyp)
524 {
525         if(MYDEBUG) MESSAGE("removeHypothesis()");
526         // **** proposer liste de subShape (selection multiple)
527
528         if (CORBA::is_nil(aSubShapeObject) && HasShapeToMesh())
529                 THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
530                         SALOME::BAD_PARAM);
531
532         SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp);
533         if (CORBA::is_nil(myHyp))
534           THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",
535                         SALOME::BAD_PARAM);
536
537         SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
538         try
539         {
540                 TopoDS_Shape myLocSubShape;
541                 //use PseudoShape in case if mesh has no shape
542                 if(HasShapeToMesh())
543                   myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject);
544                 else
545                   myLocSubShape = _impl->GetShapeToMesh();
546                 
547                 int hypId = myHyp->GetId();
548                 status = _impl->RemoveHypothesis(myLocSubShape, hypId);
549                 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
550                   _mapHypo.erase( hypId );
551         }
552         catch(SALOME_Exception & S_ex)
553         {
554                 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
555         }
556         return status;
557 }
558
559 //=============================================================================
560 /*!
561  *
562  */
563 //=============================================================================
564
565 SMESH::ListOfHypothesis *
566         SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShapeObject)
567 throw(SALOME::SALOME_Exception)
568 {
569   Unexpect aCatch(SALOME_SalomeException);
570   if (MYDEBUG) MESSAGE("GetHypothesisList");
571   if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShapeObject))
572     THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
573                                  SALOME::BAD_PARAM);
574
575   SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
576
577   try {
578     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
579     if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() )
580       myLocSubShape = _impl->GetShapeToMesh();
581     const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
582     int i = 0, n = aLocalList.size();
583     aList->length( n );
584
585     for ( list<const SMESHDS_Hypothesis*>::const_iterator anIt = aLocalList.begin(); i < n && anIt != aLocalList.end(); anIt++ ) {
586       SMESHDS_Hypothesis* aHyp = (SMESHDS_Hypothesis*)(*anIt);
587       if ( _mapHypo.find( aHyp->GetID() ) != _mapHypo.end() )
588         aList[i++] = SMESH::SMESH_Hypothesis::_narrow( _mapHypo[aHyp->GetID()] );
589     }
590
591     aList->length( i );
592   }
593   catch(SALOME_Exception & S_ex) {
594     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
595   }
596
597   return aList._retn();
598 }
599
600 //=============================================================================
601 /*!
602  *
603  */
604 //=============================================================================
605 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShapeObject,
606                                                   const char*           theName )
607      throw(SALOME::SALOME_Exception)
608 {
609   Unexpect aCatch(SALOME_SalomeException);
610   MESSAGE("SMESH_Mesh_i::GetSubMesh");
611   if (CORBA::is_nil(aSubShapeObject))
612     THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
613                                  SALOME::BAD_PARAM);
614
615   SMESH::SMESH_subMesh_var subMesh;
616   SMESH::SMESH_Mesh_var    aMesh = SMESH::SMESH_Mesh::_narrow(_this());
617   try {
618     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
619
620     //Get or Create the SMESH_subMesh object implementation
621
622     int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
623     subMesh = getSubMesh( subMeshId );
624
625     // create a new subMesh object servant if there is none for the shape
626     if ( subMesh->_is_nil() )
627       subMesh = createSubMesh( aSubShapeObject );
628     if ( _gen_i->CanPublishInStudy( subMesh )) {
629       SALOMEDS::SObject_var aSO =
630         _gen_i->PublishSubMesh(_gen_i->GetCurrentStudy(), aMesh,
631                                subMesh, aSubShapeObject, theName );
632       if ( !aSO->_is_nil()) {
633         // Update Python script
634         TPythonDump() << aSO << " = " << _this() << ".GetSubMesh( "
635                       << aSubShapeObject << ", '" << theName << "' )";
636       }
637     }
638   }
639   catch(SALOME_Exception & S_ex) {
640     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
641   }
642   return subMesh._retn();
643 }
644
645 //=============================================================================
646 /*!
647  *
648  */
649 //=============================================================================
650
651 void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
652      throw (SALOME::SALOME_Exception)
653 {
654   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::RemoveSubMesh");
655   if ( theSubMesh->_is_nil() )
656     return;
657
658   GEOM::GEOM_Object_var aSubShapeObject;
659   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
660   if ( !aStudy->_is_nil() )  {
661     // Remove submesh's SObject
662     SALOMEDS::SObject_var anSO = _gen_i->ObjectToSObject( aStudy, theSubMesh );
663     if ( !anSO->_is_nil() ) {
664       long aTag = SMESH_Gen_i::GetRefOnShapeTag();
665       SALOMEDS::SObject_var anObj, aRef;
666       if ( anSO->FindSubObject( aTag, anObj ) && anObj->ReferencedObject( aRef ) )
667         aSubShapeObject = GEOM::GEOM_Object::_narrow( aRef->GetObject() );
668
669       aStudy->NewBuilder()->RemoveObjectWithChildren( anSO );
670
671       // Update Python script
672       TPythonDump() << _this() << ".RemoveSubMesh( " << anSO << " )";
673     }
674   }
675
676   removeSubMesh( theSubMesh, aSubShapeObject.in() );
677 }
678
679 //=============================================================================
680 /*!
681  *  ElementTypeString
682  */
683 //=============================================================================
684 #define CASE2STRING(enum) case SMESH::enum: return "SMESH."#enum;
685 inline TCollection_AsciiString ElementTypeString (SMESH::ElementType theElemType)
686 {
687   switch (theElemType) {
688     CASE2STRING( ALL );
689     CASE2STRING( NODE );
690     CASE2STRING( EDGE );
691     CASE2STRING( FACE );
692     CASE2STRING( VOLUME );
693   default:;
694   }
695   return "";
696 }
697
698 //=============================================================================
699 /*!
700  *
701  */
702 //=============================================================================
703
704 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType,
705                                                  const char*         theName )
706      throw(SALOME::SALOME_Exception)
707 {
708   Unexpect aCatch(SALOME_SalomeException);
709   SMESH::SMESH_Group_var aNewGroup =
710     SMESH::SMESH_Group::_narrow( createGroup( theElemType, theName ));
711
712   if ( _gen_i->CanPublishInStudy( aNewGroup ) ) {
713     SALOMEDS::SObject_var aSO =
714       _gen_i->PublishGroup(_gen_i->GetCurrentStudy(), _this(),
715                            aNewGroup, GEOM::GEOM_Object::_nil(), theName);
716     if ( !aSO->_is_nil()) {
717       // Update Python script
718       TPythonDump() << aSO << " = " << _this() << ".CreateGroup( "
719                     << ElementTypeString(theElemType) << ", '" << theName << "' )";
720     }
721   }
722   return aNewGroup._retn();
723 }
724
725
726 //=============================================================================
727 /*!
728  *
729  */
730 //=============================================================================
731 SMESH::SMESH_GroupOnGeom_ptr SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType    theElemType,
732                                                                 const char*           theName,
733                                                                 GEOM::GEOM_Object_ptr theGeomObj)
734      throw(SALOME::SALOME_Exception)
735 {
736   Unexpect aCatch(SALOME_SalomeException);
737   SMESH::SMESH_GroupOnGeom_var aNewGroup;
738
739   TopoDS_Shape aShape = _gen_i->GeomObjectToShape( theGeomObj );
740   if ( !aShape.IsNull() )
741   {
742     aNewGroup = SMESH::SMESH_GroupOnGeom::_narrow
743       ( createGroup( theElemType, theName, aShape ));
744
745     if ( _gen_i->CanPublishInStudy( aNewGroup ) ) {
746       SALOMEDS::SObject_var aSO =
747         _gen_i->PublishGroup(_gen_i->GetCurrentStudy(), _this(),
748                              aNewGroup, theGeomObj, theName);
749       if ( !aSO->_is_nil()) {
750         // Update Python script
751         TPythonDump() << aSO << " = " << _this() << ".CreateGroupFromGEOM("
752                       << ElementTypeString(theElemType) << ", '" << theName << "', "
753                       << theGeomObj << " )";
754       }
755     }
756   }
757
758   return aNewGroup._retn();
759 }
760
761 //=============================================================================
762 /*!
763  *
764  */
765 //=============================================================================
766
767 void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
768      throw (SALOME::SALOME_Exception)
769 {
770   if ( theGroup->_is_nil() )
771     return;
772
773   SMESH_GroupBase_i* aGroup =
774     dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
775   if ( !aGroup )
776     return;
777
778   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
779   if ( !aStudy->_is_nil() )  {
780     SALOMEDS::SObject_var aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
781
782     if ( !aGroupSO->_is_nil() ) {
783       // Update Python script
784       TPythonDump() << _this() << ".RemoveGroup( " << aGroupSO << " )";
785
786       // Remove group's SObject
787       aStudy->NewBuilder()->RemoveObjectWithChildren( aGroupSO );
788     }
789   }
790
791   // Remove the group from SMESH data structures
792   removeGroup( aGroup->GetLocalID() );
793 }
794
795 //=============================================================================
796 /*! RemoveGroupWithContents
797  *  Remove group with its contents
798  */
799 //=============================================================================
800 void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup )
801   throw (SALOME::SALOME_Exception)
802 {
803   if ( theGroup->_is_nil() )
804     return;
805
806   SMESH_GroupBase_i* aGroup =
807     dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
808   if ( !aGroup )
809     return;
810
811   SMESH::long_array_var anIds = aGroup->GetListOfID();
812   SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
813
814   // Update Python script
815   TPythonDump() << _this() << ".RemoveGroupWithContents( " << theGroup << " )";
816
817   // Remove contents
818   if ( aGroup->GetType() == SMESH::NODE )
819     aMeshEditor->RemoveNodes( anIds );
820   else
821     aMeshEditor->RemoveElements( anIds );
822
823   // Remove group
824   RemoveGroup( theGroup );
825
826   // Clear python lines, created by RemoveNodes/Elements() and RemoveGroup()
827   _gen_i->RemoveLastFromPythonScript(_gen_i->GetCurrentStudy()->StudyId());
828   _gen_i->RemoveLastFromPythonScript(_gen_i->GetCurrentStudy()->StudyId());
829 }
830
831
832 //================================================================================
833 /*!
834  * \brief Get the list of groups existing in the mesh
835   * \retval SMESH::ListOfGroups * - list of groups
836  */
837 //================================================================================
838
839 SMESH::ListOfGroups * SMESH_Mesh_i::GetGroups() throw(SALOME::SALOME_Exception)
840 {
841   Unexpect aCatch(SALOME_SalomeException);
842   if (MYDEBUG) MESSAGE("GetGroups");
843
844   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
845
846   // Python Dump
847   TPythonDump aPythonDump;
848   if ( !_mapGroups.empty() ) // (IMP13463) avoid "SyntaxError: can't assign to []"
849     aPythonDump << "[ ";
850
851   try {
852     aList->length( _mapGroups.size() );
853     int i = 0;
854     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
855     for ( ; it != _mapGroups.end(); it++ ) {
856       if ( CORBA::is_nil( it->second )) continue;
857       aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
858       // Python Dump
859       if (i > 1) aPythonDump << ", ";
860       aPythonDump << it->second;
861     }
862     aList->length( i );
863   }
864   catch(SALOME_Exception & S_ex) {
865     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
866   }
867
868   // Update Python script
869   if ( !_mapGroups.empty() ) // (IMP13463) avoid "SyntaxError: can't assign to []"
870     aPythonDump << " ] = " << _this() << ".GetGroups()";
871
872   return aList._retn();
873 }
874 //=============================================================================
875 /*!
876  *  Get number of groups existing in the mesh
877  */
878 //=============================================================================
879
880 CORBA::Long SMESH_Mesh_i::NbGroups() throw (SALOME::SALOME_Exception)
881 {
882   Unexpect aCatch(SALOME_SalomeException);
883   return _mapGroups.size();
884 }
885
886 //=============================================================================
887 /*! UnionGroups
888  *  New group is created. All mesh elements that are
889  *  present in initial groups are added to the new one
890  */
891 //=============================================================================
892 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
893                                                   SMESH::SMESH_GroupBase_ptr theGroup2,
894                                                   const char* theName )
895   throw (SALOME::SALOME_Exception)
896 {
897   try
898   {
899     if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
900          theGroup1->GetType() != theGroup2->GetType() )
901       return SMESH::SMESH_Group::_nil();
902
903     // Create Union
904     SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
905     if ( aResGrp->_is_nil() )
906       return SMESH::SMESH_Group::_nil();
907
908     SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
909     SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
910
911     TColStd_MapOfInteger aResMap;
912
913     for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
914       aResMap.Add( anIds1[ i1 ] );
915
916     for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
917       aResMap.Add( anIds2[ i2 ] );
918
919     SMESH::long_array_var aResIds = new SMESH::long_array;
920     aResIds->length( aResMap.Extent() );
921
922     int resI = 0;
923     TColStd_MapIteratorOfMapOfInteger anIter( aResMap );
924     for( ; anIter.More(); anIter.Next() )
925       aResIds[ resI++ ] = anIter.Key();
926
927     aResGrp->Add( aResIds );
928
929     // Clear python lines, created by CreateGroup() and Add()
930     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
931     _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
932     _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
933
934     // Update Python script
935     TPythonDump() << aResGrp << " = " << _this() << ".UnionGroups( "
936                   << theGroup1 << ", " << theGroup2 << ", '"
937                   << theName << "' )";
938
939     return aResGrp._retn();
940   }
941   catch( ... )
942   {
943     return SMESH::SMESH_Group::_nil();
944   }
945 }
946
947 //=============================================================================
948 /*!
949   \brief Union list of groups. New group is created. All mesh elements that are
950    present in initial groups are added to the new one.
951   \param theGroups list of groups
952   \param theName name of group to be created
953   \return pointer on the group
954 */
955 //=============================================================================
956 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionListOfGroups(const SMESH::ListOfGroups& theGroups,
957                                                        const char*                theName )
958 throw (SALOME::SALOME_Exception)
959 {
960   if ( !theName )
961     return SMESH::SMESH_Group::_nil();
962
963   try
964   {
965     NCollection_Map< int > anIds;
966     SMESH::ElementType aType = SMESH::ALL;
967     for ( int g = 0, n = theGroups.length(); g < n; g++ )
968     {
969       SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
970       if ( CORBA::is_nil( aGrp ) )
971         continue;
972
973       // check type
974       SMESH::ElementType aCurrType = aGrp->GetType();
975       if ( aType == SMESH::ALL )
976         aType = aCurrType;
977       else 
978       {
979         if ( aType != aCurrType )
980           return SMESH::SMESH_Group::_nil();
981       }
982
983       // unite ids
984       SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
985       for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
986       {
987         int aCurrId = aCurrIds[ i ];
988         anIds.Add( aCurrId );
989       }
990     }
991
992     // Create group
993     SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
994     if ( aResGrp->_is_nil() )
995       return SMESH::SMESH_Group::_nil();
996     
997     // Create array of identifiers
998     SMESH::long_array_var aResIds = new SMESH::long_array;
999     aResIds->length( anIds.Extent() );
1000     
1001     NCollection_Map< int >::Iterator anIter( anIds );
1002     for ( int i = 0; anIter.More(); anIter.Next(), i++ )
1003     {
1004       aResIds[ i ] = anIter.Value();
1005     }
1006     aResGrp->Add( aResIds );
1007
1008     // Clear python lines, created by CreateGroup() and Add()
1009     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1010     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1011     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1012
1013     // Update Python script
1014     
1015     TPythonDump() << aResGrp << " = " << _this() << ".UnionListOfGroups( "
1016                   << &theGroups << ", '" << theName << "' )";
1017
1018     return aResGrp._retn();
1019   }
1020   catch( ... )
1021   {
1022     return SMESH::SMESH_Group::_nil();
1023   }
1024 }
1025
1026 //=============================================================================
1027 /*! IntersectGroups
1028  *  New group is created. All mesh elements that are
1029  *  present in both initial groups are added to the new one.
1030  */
1031 //=============================================================================
1032 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1033                                                       SMESH::SMESH_GroupBase_ptr theGroup2,
1034                                                       const char* theName )
1035   throw (SALOME::SALOME_Exception)
1036 {
1037   if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
1038        theGroup1->GetType() != theGroup2->GetType() )
1039     return SMESH::SMESH_Group::_nil();
1040
1041   // Create Intersection
1042   SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
1043   if ( aResGrp->_is_nil() )
1044     return aResGrp;
1045
1046   SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
1047   SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
1048
1049   TColStd_MapOfInteger aMap1;
1050
1051   for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
1052     aMap1.Add( anIds1[ i1 ] );
1053
1054   TColStd_SequenceOfInteger aSeq;
1055
1056   for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
1057     if ( aMap1.Contains( anIds2[ i2 ] ) )
1058       aSeq.Append( anIds2[ i2 ] );
1059
1060   SMESH::long_array_var aResIds = new SMESH::long_array;
1061   aResIds->length( aSeq.Length() );
1062
1063   for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
1064     aResIds[ resI ] = aSeq( resI + 1 );
1065
1066   aResGrp->Add( aResIds );
1067
1068   // Clear python lines, created by CreateGroup() and Add()
1069   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1070   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1071   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1072
1073   // Update Python script
1074   TPythonDump() << aResGrp << " = " << _this() << ".IntersectGroups( "
1075                 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1076
1077   return aResGrp._retn();
1078 }
1079
1080 //=============================================================================
1081 /*!
1082   \brief Intersect list of groups. New group is created. All mesh elements that 
1083   are present in all initial groups simultaneously are added to the new one.
1084   \param theGroups list of groups
1085   \param theName name of group to be created
1086   \return pointer on the group
1087 */
1088 //=============================================================================
1089 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectListOfGroups( 
1090   const SMESH::ListOfGroups& theGroups, const char* theName )
1091 throw (SALOME::SALOME_Exception)
1092 {
1093   if ( !theName )
1094     return SMESH::SMESH_Group::_nil();
1095
1096   try
1097   {
1098     NCollection_DataMap< int, int > anIdToCount;
1099     SMESH::ElementType aType = SMESH::ALL;
1100     for ( int g = 0, n = theGroups.length(); g < n; g++ )
1101     {
1102       SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1103       if ( CORBA::is_nil( aGrp ) )
1104         continue;
1105
1106       // check type
1107       SMESH::ElementType aCurrType = aGrp->GetType();
1108       if ( aType == SMESH::ALL )
1109         aType = aCurrType;
1110       else 
1111       {
1112         if ( aType != aCurrType )
1113           return SMESH::SMESH_Group::_nil();
1114       }
1115
1116       // calculates number of occurance ids in groups
1117       SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1118       for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1119       {
1120         int aCurrId = aCurrIds[ i ];
1121         if ( !anIdToCount.IsBound( aCurrId ) )
1122           anIdToCount.Bind( aCurrId, 1 );
1123         else 
1124           anIdToCount( aCurrId ) = anIdToCount( aCurrId ) + 1;
1125       }
1126     }
1127     
1128     // create map of ids
1129     int nbGrp = theGroups.length();
1130     NCollection_Map< int > anIds;
1131     NCollection_DataMap< int, int >::Iterator anIter( anIdToCount );
1132     for ( ; anIter.More(); anIter.Next() )
1133     {
1134       int aCurrId = anIter.Key();
1135       int aCurrNb = anIter.Value();
1136       if ( aCurrNb == nbGrp )
1137         anIds.Add( aCurrId );
1138     }
1139
1140     // Create group
1141     SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
1142     if ( aResGrp->_is_nil() )
1143       return SMESH::SMESH_Group::_nil();
1144     
1145     // Create array of identifiers
1146     SMESH::long_array_var aResIds = new SMESH::long_array;
1147     aResIds->length( anIds.Extent() );
1148     
1149     NCollection_Map< int >::Iterator aListIter( anIds );
1150     for ( int i = 0; aListIter.More(); aListIter.Next(), i++ )
1151     {
1152       aResIds[ i ] = aListIter.Value();
1153     }
1154     aResGrp->Add( aResIds );
1155
1156     // Clear python lines, created by CreateGroup() and Add()
1157     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1158     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1159     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1160
1161     // Update Python script
1162     
1163     TPythonDump() << aResGrp << " = " << _this() << ".IntersectListOfGroups( "
1164                   << &theGroups << ", '" << theName << "' )";
1165
1166     return aResGrp._retn();
1167   }
1168   catch( ... )
1169   {
1170     return SMESH::SMESH_Group::_nil();
1171   }
1172 }
1173
1174 //=============================================================================
1175 /*! CutGroups
1176  *  New group is created. All mesh elements that are present in
1177  *  main group but do not present in tool group are added to the new one
1178  */
1179 //=============================================================================
1180 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1181                                                 SMESH::SMESH_GroupBase_ptr theGroup2,
1182                                                 const char* theName )
1183   throw (SALOME::SALOME_Exception)
1184 {
1185   if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
1186        theGroup1->GetType() != theGroup2->GetType() )
1187     return SMESH::SMESH_Group::_nil();
1188
1189   // Perform Cutting
1190   SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
1191   if ( aResGrp->_is_nil() )
1192     return aResGrp;
1193
1194   SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
1195   SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
1196
1197   TColStd_MapOfInteger aMap2;
1198
1199   for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
1200     aMap2.Add( anIds2[ i2 ] );
1201
1202   TColStd_SequenceOfInteger aSeq;
1203   for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
1204     if ( !aMap2.Contains( anIds1[ i1 ] ) )
1205       aSeq.Append( anIds1[ i1 ] );
1206
1207   SMESH::long_array_var aResIds = new SMESH::long_array;
1208   aResIds->length( aSeq.Length() );
1209
1210   for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
1211     aResIds[ resI ] = aSeq( resI + 1 );
1212
1213   aResGrp->Add( aResIds );
1214
1215   // Clear python lines, created by CreateGroup() and Add()
1216   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1217   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1218   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1219
1220   // Update Python script
1221   TPythonDump() << aResGrp << " = " << _this() << ".CutGroups( "
1222                 << theGroup1 << ", " << theGroup2 << ", '"
1223                 << theName << "' )";
1224
1225   return aResGrp._retn();
1226 }
1227
1228 //=============================================================================
1229 /*!
1230   \brief Cut lists of groups. New group is created. All mesh elements that are 
1231   present in main groups but do not present in tool groups are added to the new one
1232   \param theMainGroups list of main groups
1233   \param theToolGroups list of tool groups
1234   \param theName name of group to be created
1235   \return pointer on the group
1236 */
1237 //=============================================================================
1238 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutListOfGroups( 
1239   const SMESH::ListOfGroups& theMainGroups, 
1240   const SMESH::ListOfGroups& theToolGroups, 
1241   const char* theName )
1242   throw (SALOME::SALOME_Exception)
1243 {
1244   if ( !theName )
1245     return SMESH::SMESH_Group::_nil();
1246
1247   try
1248   {
1249     NCollection_Map< int > aToolIds;
1250     SMESH::ElementType aType = SMESH::ALL;
1251     int g, n;
1252     // iterate through tool groups
1253     for ( g = 0, n = theToolGroups.length(); g < n; g++ )
1254     {
1255       SMESH::SMESH_GroupBase_var aGrp = theToolGroups[ g ];
1256       if ( CORBA::is_nil( aGrp ) )
1257         continue;
1258
1259       // check type
1260       SMESH::ElementType aCurrType = aGrp->GetType();
1261       if ( aType == SMESH::ALL )
1262         aType = aCurrType;
1263       else 
1264       {
1265         if ( aType != aCurrType )
1266           return SMESH::SMESH_Group::_nil();
1267       }
1268
1269       // unite tool ids
1270       SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1271       for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1272       {
1273         int aCurrId = aCurrIds[ i ];
1274         aToolIds.Add( aCurrId );
1275       }
1276     }
1277
1278     NCollection_Map< int > anIds; // result
1279
1280     // Iterate through main group 
1281     for ( g = 0, n = theMainGroups.length(); g < n; g++ )
1282     {
1283       SMESH::SMESH_GroupBase_var aGrp = theMainGroups[ g ];
1284       if ( CORBA::is_nil( aGrp ) )
1285         continue;
1286
1287       // check type
1288       SMESH::ElementType aCurrType = aGrp->GetType();
1289       if ( aType == SMESH::ALL )
1290         aType = aCurrType;
1291       else 
1292       {
1293         if ( aType != aCurrType )
1294           return SMESH::SMESH_Group::_nil();
1295       }
1296
1297       // unite tool ids
1298       SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1299       for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1300       {
1301         int aCurrId = aCurrIds[ i ];
1302         if ( !aToolIds.Contains( aCurrId ) )
1303           anIds.Add( aCurrId );
1304       }
1305     }
1306
1307     // Create group
1308     SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
1309     if ( aResGrp->_is_nil() )
1310       return SMESH::SMESH_Group::_nil();
1311     
1312     // Create array of identifiers
1313     SMESH::long_array_var aResIds = new SMESH::long_array;
1314     aResIds->length( anIds.Extent() );
1315     
1316     NCollection_Map< int >::Iterator anIter( anIds );
1317     for ( int i = 0; anIter.More(); anIter.Next(), i++ )
1318     {
1319       aResIds[ i ] = anIter.Value();
1320     }
1321     aResGrp->Add( aResIds );
1322
1323     // Clear python lines, created by CreateGroup() and Add()
1324     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1325     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1326     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1327
1328     // Update Python script
1329
1330     TPythonDump() << aResGrp << " = " << _this() << ".CutListOfGroups( "
1331                   << &theMainGroups << ", " << &theToolGroups << ", '"
1332                   << theName << "' )";
1333     
1334     return aResGrp._retn();
1335   }
1336   catch( ... )
1337   {
1338     return SMESH::SMESH_Group::_nil();
1339   }
1340 }
1341
1342 //=============================================================================
1343 /*!
1344   \brief Create groups of entities from existing groups of superior dimensions 
1345   System 
1346   1) extract all nodes from each group,
1347   2) combine all elements of specified dimension laying on these nodes.
1348   \param theGroups list of source groups 
1349   \param theElemType dimension of elements 
1350   \param theName name of new group
1351   \return pointer on new group
1352 */
1353 //=============================================================================
1354 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateDimGroup( 
1355   const SMESH::ListOfGroups& theGroups, 
1356   SMESH::ElementType         theElemType, 
1357   const char*                theName )
1358   throw (SALOME::SALOME_Exception)
1359 {
1360   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
1361
1362   if ( !theName || !aMeshDS )
1363     return SMESH::SMESH_Group::_nil();
1364
1365   SMDSAbs_ElementType anElemType = (SMDSAbs_ElementType)theElemType;
1366
1367   try
1368   {
1369     // Create map of nodes from all groups 
1370
1371     NCollection_Map< int > aNodeMap;
1372     
1373     for ( int g = 0, n = theGroups.length(); g < n; g++ )
1374     {
1375       SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1376       if ( CORBA::is_nil( aGrp ) )
1377         continue;
1378
1379       SMESH::ElementType aType = aGrp->GetType();
1380       if ( aType == SMESH::ALL )
1381         continue;
1382       else if ( aType == SMESH::NODE )
1383       {
1384         SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1385         for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1386         {
1387           int aCurrId = aCurrIds[ i ];
1388           const SMDS_MeshNode* aNode = aMeshDS->FindNode( aCurrId );
1389           if ( aNode )
1390             aNodeMap.Add( aNode->GetID() );
1391         }
1392       }
1393       else 
1394       {
1395         SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1396         for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1397         {
1398           int aCurrId = aCurrIds[ i ];
1399           const SMDS_MeshElement* anElem = aMeshDS->FindElement( aCurrId );
1400           if ( !anElem )
1401             continue;
1402           SMDS_ElemIteratorPtr aNodeIter = anElem->nodesIterator();
1403           while( aNodeIter->more() )
1404           {
1405             const SMDS_MeshNode* aNode = 
1406               dynamic_cast<const SMDS_MeshNode*>( aNodeIter->next() );
1407             if ( aNode )
1408               aNodeMap.Add( aNode->GetID() );
1409           }
1410         }
1411       }
1412     }
1413
1414     // Get result identifiers 
1415
1416     NCollection_Map< int > aResultIds;
1417     if ( theElemType == SMESH::NODE )
1418     {
1419       NCollection_Map< int >::Iterator aNodeIter( aNodeMap );
1420       for ( ; aNodeIter.More(); aNodeIter.Next() )
1421         aResultIds.Add( aNodeIter.Value() );
1422     }
1423     else
1424     {
1425       // Create list of elements of given dimension constructed on the nodes
1426       NCollection_Map< int > anElemList;
1427       NCollection_Map< int >::Iterator aNodeIter( aNodeMap );
1428       for ( ; aNodeIter.More(); aNodeIter.Next() )
1429       {
1430         const SMDS_MeshElement* aNode = 
1431           dynamic_cast<const SMDS_MeshElement*>( aMeshDS->FindNode( aNodeIter.Value() ) );
1432         if ( !aNode )
1433           continue;
1434
1435          SMDS_ElemIteratorPtr anElemIter = aNode->elementsIterator( anElemType );
1436         while( anElemIter->more() )
1437         {
1438           const SMDS_MeshElement* anElem = 
1439             dynamic_cast<const SMDS_MeshElement*>( anElemIter->next() );
1440           if ( anElem && anElem->GetType() == anElemType )
1441             anElemList.Add( anElem->GetID() );
1442         }
1443       }
1444
1445       // check whether all nodes of elements are present in nodes map
1446       NCollection_Map< int >::Iterator anIter( anElemList );
1447       for ( ; anIter.More(); anIter.Next() )
1448       {
1449         const SMDS_MeshElement* anElem = aMeshDS->FindElement( anIter.Value() );
1450         if ( !anElem )
1451           continue;
1452
1453         bool isOk = true;
1454         SMDS_ElemIteratorPtr aNodeIter = anElem->nodesIterator();
1455         while( aNodeIter->more() )
1456         {
1457           const SMDS_MeshNode* aNode = 
1458             dynamic_cast<const SMDS_MeshNode*>( aNodeIter->next() );
1459           if ( !aNode || !aNodeMap.Contains( aNode->GetID() ) )
1460           {
1461             isOk = false;
1462             break;
1463           }
1464         } 
1465         if ( isOk )
1466           aResultIds.Add( anElem->GetID() );
1467       }
1468     }
1469
1470     // Create group
1471
1472     SMESH::SMESH_Group_var aResGrp = CreateGroup( theElemType, theName );
1473     if ( aResGrp->_is_nil() )
1474       return SMESH::SMESH_Group::_nil();
1475     
1476     // Create array of identifiers
1477     SMESH::long_array_var aResIds = new SMESH::long_array;
1478     aResIds->length( aResultIds.Extent() );
1479     
1480     NCollection_Map< int >::Iterator aResIter( aResultIds );
1481     for ( int i = 0; aResIter.More(); aResIter.Next(), i++ )
1482       aResIds[ i ] = aResIter.Value();
1483     aResGrp->Add( aResIds );
1484
1485     // Remove strings corresponding to group creation
1486     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1487     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1488     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1489
1490     // Update Python script
1491     
1492     TPythonDump() << aResGrp << " = " << _this() << ".CreateDimGroup( "
1493                   << &theGroups << ", " << theElemType << ", '" << theName << "' )";
1494
1495     return aResGrp._retn();
1496   }
1497   catch( ... )
1498   {
1499     return SMESH::SMESH_Group::_nil();
1500   }
1501 }
1502
1503 //================================================================================
1504 /*!
1505  * \brief Remember GEOM group data
1506  */
1507 //================================================================================
1508
1509 void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj,
1510                                     CORBA::Object_ptr     theSmeshObj)
1511 {
1512   if ( CORBA::is_nil( theGeomObj ) || theGeomObj->GetType() != GEOM_GROUP )
1513     return;
1514   // group SO
1515   SALOMEDS::Study_var   study  = _gen_i->GetCurrentStudy();
1516   SALOMEDS::SObject_var groupSO = _gen_i->ObjectToSObject( study, theGeomObj );
1517   if ( groupSO->_is_nil() )
1518     return;
1519   // group indices
1520   GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
1521   GEOM::GEOM_IGroupOperations_var groupOp =
1522     geomGen->GetIGroupOperations( _gen_i->GetCurrentStudyID() );
1523   GEOM::ListOfLong_var ids = groupOp->GetObjects( theGeomObj );
1524
1525   // store data
1526   _geomGroupData.push_back( TGeomGroupData() );
1527   TGeomGroupData & groupData = _geomGroupData.back();
1528   // entry
1529   CORBA::String_var entry = groupSO->GetID();
1530   groupData._groupEntry = entry.in();
1531   // indices
1532   for ( int i = 0; i < ids->length(); ++i )
1533     groupData._indices.insert( ids[i] );
1534   // SMESH object
1535   groupData._smeshObject = theSmeshObj;
1536 }
1537
1538 //================================================================================
1539 /*!
1540  * Remove GEOM group data relating to removed smesh object
1541  */
1542 //================================================================================
1543
1544 void SMESH_Mesh_i::removeGeomGroupData(CORBA::Object_ptr theSmeshObj)
1545 {
1546   list<TGeomGroupData>::iterator
1547     data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
1548   for ( ; data != dataEnd; ++data ) {
1549     if ( theSmeshObj->_is_equivalent( data->_smeshObject )) {
1550       _geomGroupData.erase( data );
1551       return;
1552     }
1553   }
1554 }
1555
1556 //================================================================================
1557 /*!
1558  * \brief Return new group contents if it has been changed and update group data
1559  */
1560 //================================================================================
1561
1562 TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData)
1563 {
1564   TopoDS_Shape newShape;
1565
1566   // get geom group
1567   SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1568   if ( study->_is_nil() ) return newShape; // means "not changed"
1569   SALOMEDS::SObject_var groupSO = study->FindObjectID( groupData._groupEntry.c_str() );
1570   if ( !groupSO->_is_nil() )
1571   {
1572     CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO );
1573     if ( CORBA::is_nil( groupObj )) return newShape;
1574     GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj );
1575     
1576     // get indices of group items
1577     set<int> curIndices;
1578     GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
1579     GEOM::GEOM_IGroupOperations_var groupOp =
1580       geomGen->GetIGroupOperations( _gen_i->GetCurrentStudyID() );
1581     GEOM::ListOfLong_var ids = groupOp->GetObjects( geomGroup );
1582     for ( int i = 0; i < ids->length(); ++i )
1583       curIndices.insert( ids[i] );
1584
1585     if ( groupData._indices == curIndices )
1586       return newShape; // group not changed
1587
1588     // update data
1589     groupData._indices = curIndices;
1590
1591     GEOM_Client* geomClient = _gen_i->GetShapeReader();
1592     if ( !geomClient ) return newShape;
1593     TCollection_AsciiString groupIOR = geomGen->GetStringFromIOR( geomGroup );
1594     geomClient->RemoveShapeFromBuffer( groupIOR );
1595     newShape = _gen_i->GeomObjectToShape( geomGroup );
1596   }    
1597
1598   if ( newShape.IsNull() ) {
1599     // geom group becomes empty - return empty compound
1600     TopoDS_Compound compound;
1601     BRep_Builder    builder;
1602     builder.MakeCompound(compound);
1603     newShape = compound;
1604   }
1605   return newShape;
1606 }
1607
1608 //=============================================================================
1609 /*!
1610  * \brief Update objects depending on changed geom groups
1611  * 
1612  * NPAL16168: geometrical group edition from a submesh don't modifiy mesh computation
1613  * issue 0020210: Update of a smesh group after modification of the associated geom group
1614  */
1615 //=============================================================================
1616
1617 void SMESH_Mesh_i::CheckGeomGroupModif()
1618 {
1619   if ( !_impl->HasShapeToMesh() ) return;
1620
1621   SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1622   if ( study->_is_nil() ) return;
1623
1624   CORBA::Long nbEntities = NbNodes() + NbElements();
1625
1626   // Check if group contents changed
1627
1628   typedef map< string, TopoDS_Shape > TEntry2Geom;
1629   TEntry2Geom newGroupContents;
1630
1631   list<TGeomGroupData>::iterator
1632     data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
1633   for ( ; data != dataEnd; ++data )
1634   {
1635     pair< TEntry2Geom::iterator, bool > it_new =
1636       newGroupContents.insert( make_pair( data->_groupEntry, TopoDS_Shape() ));
1637     bool processedGroup    = !it_new.second;
1638     TopoDS_Shape& newShape = it_new.first->second;
1639     if ( !processedGroup )
1640       newShape = newGroupShape( *data );
1641     if ( newShape.IsNull() )
1642       continue; // no changes
1643
1644     if ( processedGroup ) { // update group indices
1645       list<TGeomGroupData>::iterator data2 = data;
1646       for ( --data2; data2->_groupEntry != data->_groupEntry; --data2)
1647         data->_indices = data2->_indices;
1648     }
1649
1650     // Update SMESH objects according to new GEOM group contents
1651
1652     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject );
1653     if ( !mesh->_is_nil() ) // -------------- MESH ----------------------------
1654     {
1655       // TODO
1656       continue;
1657     }
1658
1659     SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject );
1660     if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
1661     {
1662       int oldID = submesh->GetId();
1663       if ( _mapSubMeshIor.find( oldID ) == _mapSubMeshIor.end() )
1664         continue;
1665       TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
1666
1667       // update hypotheses
1668       list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldShape);
1669       list <const SMESHDS_Hypothesis * >::iterator hypIt;
1670       for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
1671       {
1672         _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
1673         _impl->AddHypothesis   ( newShape, (*hypIt)->GetID());
1674       }
1675       // care of submeshes
1676       SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newShape );
1677       int newID = newSubmesh->GetId();
1678       if ( newID != oldID ) {
1679         _mapSubMesh   [ newID ] = newSubmesh;
1680         _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
1681         _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
1682         _mapSubMesh.   erase(oldID);
1683         _mapSubMesh_i. erase(oldID);
1684         _mapSubMeshIor.erase(oldID);
1685         _mapSubMesh_i [ newID ]->changeLocalId( newID );
1686       }
1687       continue;
1688     }
1689
1690     SMESH::SMESH_GroupOnGeom_var smeshGroup =
1691       SMESH::SMESH_GroupOnGeom::_narrow( data->_smeshObject );
1692     if ( !smeshGroup->_is_nil() ) // ------------ GROUP -----------------------
1693     {
1694       SMESH_GroupOnGeom_i* group_i = SMESH::DownCast<SMESH_GroupOnGeom_i*>( smeshGroup );
1695       if ( group_i ) {
1696         ::SMESH_Group* group = _impl->GetGroup( group_i->GetLocalID() );
1697         SMESHDS_GroupOnGeom* ds = static_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() );
1698         ds->SetShape( newShape );
1699       }
1700       continue;
1701     }
1702   }
1703
1704   // Update icons
1705
1706   CORBA::Long newNbEntities = NbNodes() + NbElements();
1707   list< SALOMEDS::SObject_var > soToUpdateIcons;
1708   if ( newNbEntities != nbEntities )
1709   {
1710     // Add all SObjects with icons
1711     soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, _this() )); // mesh
1712
1713     for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
1714          i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
1715       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, i_sm->second ));
1716
1717     for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
1718           i_gr != _mapGroups.end(); ++i_gr ) // groups
1719       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, i_gr->second ));
1720   }
1721
1722   list< SALOMEDS::SObject_var >::iterator so = soToUpdateIcons.begin();
1723   for ( ; so != soToUpdateIcons.end(); ++so )
1724     _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
1725 }
1726
1727 //=============================================================================
1728 /*!
1729  * \brief Create standalone group instead if group on geometry
1730  * 
1731  */
1732 //=============================================================================
1733
1734 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupOnGeom_ptr theGroup )
1735 {
1736   SMESH::SMESH_Group_var aGroup;
1737   if ( theGroup->_is_nil() )
1738     return aGroup._retn();
1739
1740   Unexpect aCatch(SALOME_SalomeException);
1741
1742   SMESH_GroupBase_i* aGroupToRem =
1743     dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
1744   if ( !aGroupToRem )
1745     return aGroup._retn();
1746
1747   int anId = aGroupToRem->GetLocalID();
1748   if ( !_impl->ConvertToStandalone( anId ) )
1749     return aGroup._retn();
1750   removeGeomGroupData( theGroup );
1751
1752   SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
1753
1754   // remove old instance of group from own map
1755   _mapGroups.erase( anId );
1756
1757   SALOMEDS::StudyBuilder_var builder;
1758   SALOMEDS::SObject_var aGroupSO;
1759   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1760   if ( !aStudy->_is_nil() )  {
1761     builder = aStudy->NewBuilder();
1762     aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
1763     if ( !aGroupSO->_is_nil() ) {
1764
1765     // remove reference to geometry
1766     SALOMEDS::ChildIterator_var chItr = aStudy->NewChildIterator(aGroupSO);
1767     for ( ; chItr->More(); chItr->Next() )
1768       // Remove group's child SObject
1769       builder->RemoveObject( chItr->Value() );
1770
1771       // Update Python script
1772       TPythonDump() << aGroupSO << " = " << _this() << ".ConvertToStandalone( "
1773                     << aGroupSO << " )";
1774     }
1775   }
1776
1777   // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1778   SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
1779   aGroupImpl->Register();
1780   // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1781
1782   // remember new group in own map
1783   aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
1784   _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
1785
1786   // register CORBA object for persistence
1787   //int nextId = _gen_i->RegisterObject( aGroup );
1788   //if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
1789   builder->SetIOR( aGroupSO, _gen_i->GetORB()->object_to_string( aGroup ) );
1790
1791   return aGroup._retn();
1792 }
1793
1794 //=============================================================================
1795 /*!
1796  *
1797  */
1798 //=============================================================================
1799
1800 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
1801 {
1802   if(MYDEBUG) MESSAGE( "createSubMesh" );
1803   TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
1804
1805   ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
1806   int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
1807   SMESH_subMesh_i *subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
1808   SMESH::SMESH_subMesh_var subMesh
1809     = SMESH::SMESH_subMesh::_narrow(subMeshServant->_this());
1810
1811   _mapSubMesh[subMeshId] = mySubMesh;
1812   _mapSubMesh_i[subMeshId] = subMeshServant;
1813   _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate(subMesh);
1814
1815   // register CORBA object for persistence
1816   int nextId = _gen_i->RegisterObject( subMesh );
1817   if(MYDEBUG) MESSAGE( "Add submesh to map with id = "<< nextId);
1818
1819   // to track changes of GEOM groups
1820   addGeomGroupData( theSubShapeObject, subMesh );
1821
1822   return subMesh._retn();
1823 }
1824
1825 //=======================================================================
1826 //function : getSubMesh
1827 //purpose  :
1828 //=======================================================================
1829
1830 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
1831 {
1832   map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
1833   if ( it == _mapSubMeshIor.end() )
1834     return SMESH::SMESH_subMesh::_nil();
1835
1836   return SMESH::SMESH_subMesh::_duplicate( (*it).second );
1837 }
1838
1839
1840 //=============================================================================
1841 /*!
1842  *
1843  */
1844 //=============================================================================
1845
1846 void SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
1847                                   GEOM::GEOM_Object_ptr    theSubShapeObject )
1848 {
1849   MESSAGE("SMESH_Mesh_i::removeSubMesh()");
1850   if ( theSubMesh->_is_nil() || theSubShapeObject->_is_nil() )
1851     return;
1852
1853   try {
1854     SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
1855     for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
1856       removeHypothesis( theSubShapeObject, aHypList[i] );
1857     }
1858   }
1859   catch( const SALOME::SALOME_Exception& ) {
1860     INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
1861   }
1862   removeGeomGroupData( theSubShapeObject );
1863
1864   int subMeshId = theSubMesh->GetId();
1865
1866   _mapSubMesh.erase(subMeshId);
1867   _mapSubMesh_i.erase(subMeshId);
1868   _mapSubMeshIor.erase(subMeshId);
1869   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeSubMesh() completed");
1870 }
1871
1872 //=============================================================================
1873 /*!
1874  *
1875  */
1876 //=============================================================================
1877
1878 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType theElemType,
1879                                                       const char*         theName,
1880                                                       const TopoDS_Shape& theShape )
1881 {
1882   int anId;
1883   SMESH::SMESH_GroupBase_var aGroup;
1884   if ( _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName, anId, theShape )) {
1885     SMESH_GroupBase_i* aGroupImpl;
1886     if ( !theShape.IsNull() )
1887       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
1888     else
1889       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
1890
1891     // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1892     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
1893     aGroupImpl->Register();
1894     // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1895
1896     aGroup = SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
1897     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
1898
1899     // register CORBA object for persistence
1900     int nextId = _gen_i->RegisterObject( aGroup );
1901     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
1902
1903     // to track changes of GEOM groups
1904     if ( !theShape.IsNull() ) {
1905       GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
1906       addGeomGroupData( geom, aGroup );
1907     }
1908   }
1909   return aGroup._retn();
1910 }
1911
1912 //=============================================================================
1913 /*!
1914  * SMESH_Mesh_i::removeGroup
1915  *
1916  * Should be called by ~SMESH_Group_i()
1917  */
1918 //=============================================================================
1919
1920 void SMESH_Mesh_i::removeGroup( const int theId )
1921 {
1922   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
1923   if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
1924     removeGeomGroupData( _mapGroups[theId] );
1925     _mapGroups.erase( theId );
1926     _impl->RemoveGroup( theId );
1927   }
1928 }
1929
1930
1931 //=============================================================================
1932 /*!
1933  *
1934  */
1935 //=============================================================================
1936
1937 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
1938 throw(SALOME::SALOME_Exception)
1939 {
1940   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetLog");
1941
1942   SMESH::log_array_var aLog;
1943   try{
1944     list < SMESHDS_Command * >logDS = _impl->GetLog();
1945     aLog = new SMESH::log_array;
1946     int indexLog = 0;
1947     int lg = logDS.size();
1948     SCRUTE(lg);
1949     aLog->length(lg);
1950     list < SMESHDS_Command * >::iterator its = logDS.begin();
1951     while(its != logDS.end()){
1952       SMESHDS_Command *com = *its;
1953       int comType = com->GetType();
1954       //SCRUTE(comType);
1955       int lgcom = com->GetNumber();
1956       //SCRUTE(lgcom);
1957       const list < int >&intList = com->GetIndexes();
1958       int inum = intList.size();
1959       //SCRUTE(inum);
1960       list < int >::const_iterator ii = intList.begin();
1961       const list < double >&coordList = com->GetCoords();
1962       int rnum = coordList.size();
1963       //SCRUTE(rnum);
1964       list < double >::const_iterator ir = coordList.begin();
1965       aLog[indexLog].commandType = comType;
1966       aLog[indexLog].number = lgcom;
1967       aLog[indexLog].coords.length(rnum);
1968       aLog[indexLog].indexes.length(inum);
1969       for(int i = 0; i < rnum; i++){
1970         aLog[indexLog].coords[i] = *ir;
1971         //MESSAGE(" "<<i<<" "<<ir.Value());
1972         ir++;
1973       }
1974       for(int i = 0; i < inum; i++){
1975         aLog[indexLog].indexes[i] = *ii;
1976         //MESSAGE(" "<<i<<" "<<ii.Value());
1977         ii++;
1978       }
1979       indexLog++;
1980       its++;
1981     }
1982     if(clearAfterGet)
1983       _impl->ClearLog();
1984   }
1985   catch(SALOME_Exception & S_ex){
1986     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
1987   }
1988   return aLog._retn();
1989 }
1990
1991
1992 //=============================================================================
1993 /*!
1994  *
1995  */
1996 //=============================================================================
1997
1998 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
1999 {
2000   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::ClearLog");
2001   // ****
2002 }
2003
2004 //=============================================================================
2005 /*!
2006  *
2007  */
2008 //=============================================================================
2009
2010 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
2011 {
2012   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetId");
2013   return _id;
2014 }
2015
2016 //=============================================================================
2017 /*!
2018  *
2019  */
2020 //=============================================================================
2021
2022 CORBA::Long SMESH_Mesh_i::GetStudyId()throw(SALOME::SALOME_Exception)
2023 {
2024   return _studyId;
2025 }
2026
2027 //=============================================================================
2028 /*!
2029  *
2030  */
2031 //=============================================================================
2032
2033 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
2034 {
2035   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
2036   _impl = impl;
2037 }
2038
2039 //=============================================================================
2040 /*!
2041  *
2042  */
2043 //=============================================================================
2044
2045 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
2046 {
2047   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
2048   return *_impl;
2049 }
2050
2051 //=============================================================================
2052 /*!
2053  * Return mesh editor
2054  */
2055 //=============================================================================
2056
2057 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
2058 {
2059   // Create MeshEditor
2060   SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, false );
2061   SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
2062
2063   // Update Python script
2064   TPythonDump() << aMeshEditor << " = " << _this() << ".GetMeshEditor()";
2065
2066   return aMesh._retn();
2067 }
2068
2069 //=============================================================================
2070 /*!
2071  * Return mesh edition previewer
2072  */
2073 //=============================================================================
2074
2075 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
2076 {
2077   SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, true );
2078   SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
2079   return aMesh._retn();
2080 }
2081
2082 //=============================================================================
2083 /*!
2084  *
2085  */
2086 //=============================================================================
2087 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOME_Exception)
2088 {
2089   Unexpect aCatch(SALOME_SalomeException);
2090   _impl->SetAutoColor(theAutoColor);
2091 }
2092
2093 //=============================================================================
2094 /*!
2095  *
2096  */
2097 //=============================================================================
2098 CORBA::Boolean SMESH_Mesh_i::GetAutoColor() throw(SALOME::SALOME_Exception)
2099 {
2100   Unexpect aCatch(SALOME_SalomeException);
2101   return _impl->GetAutoColor();
2102 }
2103
2104
2105 //=============================================================================
2106 /*!
2107  *  Export in different formats
2108  */
2109 //=============================================================================
2110
2111 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
2112 {
2113   return _impl->HasDuplicatedGroupNamesMED();
2114 }
2115
2116 void SMESH_Mesh_i::PrepareForWriting (const char* file)
2117 {
2118   TCollection_AsciiString aFullName ((char*)file);
2119   OSD_Path aPath (aFullName);
2120   OSD_File aFile (aPath);
2121   if (aFile.Exists()) {
2122     // existing filesystem node
2123     if (aFile.KindOfFile() == OSD_FILE) {
2124       if (aFile.IsWriteable()) {
2125         aFile.Reset();
2126         aFile.Remove();
2127         if (aFile.Failed()) {
2128           TCollection_AsciiString msg ("File ");
2129           msg += aFullName + " cannot be replaced.";
2130           THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2131         }
2132       } else {
2133         TCollection_AsciiString msg ("File ");
2134         msg += aFullName + " cannot be overwritten.";
2135         THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2136       }
2137     } else {
2138       TCollection_AsciiString msg ("Location ");
2139       msg += aFullName + " is not a file.";
2140       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2141     }
2142   } else {
2143     // nonexisting file; check if it can be created
2144     aFile.Reset();
2145     aFile.Build(OSD_WriteOnly, OSD_Protection());
2146     if (aFile.Failed()) {
2147       TCollection_AsciiString msg ("You cannot create the file ");
2148       msg += aFullName + ". Check the directory existance and access rights.";
2149       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2150     } else {
2151       aFile.Close();
2152       aFile.Remove();
2153     }
2154   }
2155 }
2156
2157 void SMESH_Mesh_i::ExportToMED (const char* file,
2158                                 CORBA::Boolean auto_groups,
2159                                 SMESH::MED_VERSION theVersion)
2160   throw(SALOME::SALOME_Exception)
2161 {
2162   Unexpect aCatch(SALOME_SalomeException);
2163
2164   // Perform Export
2165   PrepareForWriting(file);
2166   const char* aMeshName = "Mesh";
2167   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
2168   if ( !aStudy->_is_nil() ) {
2169     SALOMEDS::SObject_var aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
2170     if ( !aMeshSO->_is_nil() ) {
2171       aMeshName = aMeshSO->GetName();
2172       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
2173       if ( !aStudy->GetProperties()->IsLocked() )
2174         {
2175         SALOMEDS::GenericAttribute_var anAttr;
2176         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
2177         SALOMEDS::AttributeExternalFileDef_var aFileName;
2178         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
2179         aFileName = SALOMEDS::AttributeExternalFileDef::_narrow(anAttr);
2180         ASSERT(!aFileName->_is_nil());
2181         aFileName->SetValue(file);
2182         SALOMEDS::AttributeFileType_var aFileType;
2183         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
2184         aFileType = SALOMEDS::AttributeFileType::_narrow(anAttr);
2185         ASSERT(!aFileType->_is_nil());
2186         aFileType->SetValue("FICHIERMED");
2187         }
2188     }
2189   }
2190   // Update Python script
2191   // set name of mesh before export
2192   TPythonDump() << _gen_i << ".SetName(" << _this() << ", '" << aMeshName << "')";
2193   
2194   // check names of groups
2195   checkGroupNames();
2196
2197   TPythonDump() << _this() << ".ExportToMED( '"
2198                 << file << "', " << auto_groups << ", " << theVersion << " )";
2199
2200   _impl->ExportMED( file, aMeshName, auto_groups, theVersion );
2201 }
2202
2203 void SMESH_Mesh_i::ExportMED (const char* file,
2204                               CORBA::Boolean auto_groups)
2205   throw(SALOME::SALOME_Exception)
2206 {
2207   ExportToMED(file,auto_groups,SMESH::MED_V2_1);
2208 }
2209
2210 void SMESH_Mesh_i::ExportDAT (const char *file)
2211   throw(SALOME::SALOME_Exception)
2212 {
2213   Unexpect aCatch(SALOME_SalomeException);
2214
2215   // Update Python script
2216   // check names of groups
2217   checkGroupNames();
2218   TPythonDump() << _this() << ".ExportDAT( '" << file << "' )";
2219
2220   // Perform Export
2221   PrepareForWriting(file);
2222   _impl->ExportDAT(file);
2223 }
2224
2225 void SMESH_Mesh_i::ExportUNV (const char *file)
2226   throw(SALOME::SALOME_Exception)
2227 {
2228   Unexpect aCatch(SALOME_SalomeException);
2229
2230   // Update Python script
2231   // check names of groups
2232   checkGroupNames();
2233   TPythonDump() << _this() << ".ExportUNV( '" << file << "' )";
2234
2235   // Perform Export
2236   PrepareForWriting(file);
2237   _impl->ExportUNV(file);
2238 }
2239
2240 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
2241   throw(SALOME::SALOME_Exception)
2242 {
2243   Unexpect aCatch(SALOME_SalomeException);
2244
2245   // Update Python script
2246   // check names of groups
2247   checkGroupNames();
2248   TPythonDump() << _this() << ".ExportSTL( '" << file << "', " << isascii << " )";
2249
2250   // Perform Export
2251   PrepareForWriting(file);
2252   _impl->ExportSTL(file, isascii);
2253 }
2254
2255 //=============================================================================
2256 /*!
2257  *
2258  */
2259 //=============================================================================
2260
2261 SALOME_MED::MESH_ptr SMESH_Mesh_i::GetMEDMesh()throw(SALOME::SALOME_Exception)
2262 {
2263   Unexpect aCatch(SALOME_SalomeException);
2264   SMESH_MEDMesh_i *aMedMesh = new SMESH_MEDMesh_i(this);
2265   SALOME_MED::MESH_var aMesh = aMedMesh->_this();
2266   return aMesh._retn();
2267 }
2268
2269 //=============================================================================
2270 /*!
2271  *
2272  */
2273 //=============================================================================
2274 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
2275 {
2276   Unexpect aCatch(SALOME_SalomeException);
2277   return _impl->NbNodes();
2278 }
2279
2280 //=============================================================================
2281 /*!
2282  *
2283  */
2284 //=============================================================================
2285 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
2286 {
2287   Unexpect aCatch(SALOME_SalomeException);
2288   return NbEdges() + NbFaces() + NbVolumes();
2289 }
2290
2291 //=============================================================================
2292 /*!
2293  *
2294  */
2295 //=============================================================================
2296 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
2297 {
2298   Unexpect aCatch(SALOME_SalomeException);
2299   return _impl->NbEdges();
2300 }
2301
2302 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
2303   throw(SALOME::SALOME_Exception)
2304 {
2305   Unexpect aCatch(SALOME_SalomeException);
2306   return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
2307 }
2308
2309 //=============================================================================
2310 /*!
2311  *
2312  */
2313 //=============================================================================
2314 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
2315 {
2316   Unexpect aCatch(SALOME_SalomeException);
2317   return _impl->NbFaces();
2318 }
2319
2320 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
2321 {
2322   Unexpect aCatch(SALOME_SalomeException);
2323   return _impl->NbTriangles();
2324 }
2325
2326 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
2327 {
2328   Unexpect aCatch(SALOME_SalomeException);
2329   return _impl->NbQuadrangles();
2330 }
2331
2332 CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
2333 {
2334   Unexpect aCatch(SALOME_SalomeException);
2335   return _impl->NbPolygons();
2336 }
2337
2338 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
2339   throw(SALOME::SALOME_Exception)
2340 {
2341   Unexpect aCatch(SALOME_SalomeException);
2342   return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
2343 }
2344
2345 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
2346   throw(SALOME::SALOME_Exception)
2347 {
2348   Unexpect aCatch(SALOME_SalomeException);
2349   return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
2350 }
2351
2352 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
2353   throw(SALOME::SALOME_Exception)
2354 {
2355   Unexpect aCatch(SALOME_SalomeException);
2356   return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
2357 }
2358
2359 //=============================================================================
2360 /*!
2361  *
2362  */
2363 //=============================================================================
2364 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
2365 {
2366   Unexpect aCatch(SALOME_SalomeException);
2367   return _impl->NbVolumes();
2368 }
2369
2370 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
2371 {
2372   Unexpect aCatch(SALOME_SalomeException);
2373   return _impl->NbTetras();
2374 }
2375
2376 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
2377 {
2378   Unexpect aCatch(SALOME_SalomeException);
2379   return _impl->NbHexas();
2380 }
2381
2382 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
2383 {
2384   Unexpect aCatch(SALOME_SalomeException);
2385   return _impl->NbPyramids();
2386 }
2387
2388 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
2389 {
2390   Unexpect aCatch(SALOME_SalomeException);
2391   return _impl->NbPrisms();
2392 }
2393
2394 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
2395 {
2396   Unexpect aCatch(SALOME_SalomeException);
2397   return _impl->NbPolyhedrons();
2398 }
2399
2400 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
2401   throw(SALOME::SALOME_Exception)
2402 {
2403   Unexpect aCatch(SALOME_SalomeException);
2404   return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
2405 }
2406
2407 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
2408   throw(SALOME::SALOME_Exception)
2409 {
2410   Unexpect aCatch(SALOME_SalomeException);
2411   return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
2412 }
2413
2414 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
2415   throw(SALOME::SALOME_Exception)
2416 {
2417   Unexpect aCatch(SALOME_SalomeException);
2418   return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
2419 }
2420
2421 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
2422   throw(SALOME::SALOME_Exception)
2423 {
2424   Unexpect aCatch(SALOME_SalomeException);
2425   return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
2426 }
2427
2428 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
2429   throw(SALOME::SALOME_Exception)
2430 {
2431   Unexpect aCatch(SALOME_SalomeException);
2432   return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
2433 }
2434
2435 //=============================================================================
2436 /*!
2437  *
2438  */
2439 //=============================================================================
2440 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
2441 {
2442   Unexpect aCatch(SALOME_SalomeException);
2443   return _mapSubMesh_i.size();
2444 }
2445
2446 //=============================================================================
2447 /*!
2448  *
2449  */
2450 //=============================================================================
2451 char* SMESH_Mesh_i::Dump()
2452 {
2453   std::ostringstream os;
2454   _impl->Dump( os );
2455   return CORBA::string_dup( os.str().c_str() );
2456 }
2457
2458 //=============================================================================
2459 /*!
2460  *
2461  */
2462 //=============================================================================
2463 SMESH::long_array* SMESH_Mesh_i::GetIDs()
2464 {
2465 //   SMESH::long_array_var aResult = new SMESH::long_array();
2466 //   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2467 //   int aMinId = aSMESHDS_Mesh->MinElementID();
2468 //   int aMaxId =  aSMESHDS_Mesh->MaxElementID();
2469
2470 //   aResult->length(aMaxId - aMinId + 1);
2471
2472 //   for (int i = 0, id = aMinId; id <= aMaxId; id++  )
2473 //     aResult[i++] = id;
2474
2475 //   return aResult._retn();
2476   // PAL12398
2477   return GetElementsId();
2478 }
2479
2480 //=============================================================================
2481 /*!
2482  *
2483  */
2484 //=============================================================================
2485
2486 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
2487      throw (SALOME::SALOME_Exception)
2488 {
2489   Unexpect aCatch(SALOME_SalomeException);
2490   MESSAGE("SMESH_Mesh_i::GetElementsId");
2491   SMESH::long_array_var aResult = new SMESH::long_array();
2492   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2493
2494   if ( aSMESHDS_Mesh == NULL )
2495     return aResult._retn();
2496
2497   long nbElements = NbElements();
2498   aResult->length( nbElements );
2499   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
2500   for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
2501     aResult[i] = anIt->next()->GetID();
2502
2503   return aResult._retn();
2504 }
2505
2506
2507 //=============================================================================
2508 /*!
2509  *
2510  */
2511 //=============================================================================
2512
2513 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
2514     throw (SALOME::SALOME_Exception)
2515 {
2516   Unexpect aCatch(SALOME_SalomeException);
2517   MESSAGE("SMESH_subMesh_i::GetElementsByType");
2518   SMESH::long_array_var aResult = new SMESH::long_array();
2519   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2520
2521   if ( aSMESHDS_Mesh == NULL )
2522     return aResult._retn();
2523
2524   long nbElements = NbElements();
2525
2526   // No sense in returning ids of elements along with ids of nodes:
2527   // when theElemType == SMESH::ALL, return node ids only if
2528   // there are no elements
2529   if ( theElemType == SMESH::NODE || theElemType == SMESH::ALL && nbElements == 0 )
2530     return GetNodesId();
2531
2532   aResult->length( nbElements );
2533
2534   int i = 0;
2535
2536   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
2537   while ( i < nbElements && anIt->more() ) {
2538     const SMDS_MeshElement* anElem = anIt->next();
2539     if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
2540       aResult[i++] = anElem->GetID();
2541   }
2542
2543   aResult->length( i );
2544
2545   return aResult._retn();
2546 }
2547
2548 //=============================================================================
2549 /*!
2550  *
2551  */
2552 //=============================================================================
2553
2554 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
2555   throw (SALOME::SALOME_Exception)
2556 {
2557   Unexpect aCatch(SALOME_SalomeException);
2558   MESSAGE("SMESH_subMesh_i::GetNodesId");
2559   SMESH::long_array_var aResult = new SMESH::long_array();
2560   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2561
2562   if ( aSMESHDS_Mesh == NULL )
2563     return aResult._retn();
2564
2565   long nbNodes = NbNodes();
2566   aResult->length( nbNodes );
2567   SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator();
2568   for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
2569     aResult[i] = anIt->next()->GetID();
2570
2571   return aResult._retn();
2572 }
2573
2574 //=============================================================================
2575 /*!
2576  *
2577  */
2578 //=============================================================================
2579
2580 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
2581   throw (SALOME::SALOME_Exception)
2582 {
2583   return ( SMESH::ElementType )_impl->GetElementType( id, iselem );
2584 }
2585
2586
2587 //=============================================================================
2588 /*!
2589  * Returns ID of elements for given submesh
2590  */
2591 //=============================================================================
2592 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
2593      throw (SALOME::SALOME_Exception)
2594 {
2595   SMESH::long_array_var aResult = new SMESH::long_array();
2596
2597   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2598   if(!SM) return aResult._retn();
2599
2600   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2601   if(!SDSM) return aResult._retn();
2602
2603   aResult->length(SDSM->NbElements());
2604
2605   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2606   int i = 0;
2607   while ( eIt->more() ) {
2608     aResult[i++] = eIt->next()->GetID();
2609   }
2610
2611   return aResult._retn();
2612 }
2613
2614
2615 //=============================================================================
2616 /*!
2617  * Returns ID of nodes for given submesh
2618  * If param all==true - returns all nodes, else -
2619  * returns only nodes on shapes.
2620  */
2621 //=============================================================================
2622 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID, CORBA::Boolean all)
2623      throw (SALOME::SALOME_Exception)
2624 {
2625   SMESH::long_array_var aResult = new SMESH::long_array();
2626
2627   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2628   if(!SM) return aResult._retn();
2629
2630   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2631   if(!SDSM) return aResult._retn();
2632
2633   set<int> theElems;
2634   if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
2635     SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
2636     while ( nIt->more() ) {
2637       const SMDS_MeshNode* elem = nIt->next();
2638       theElems.insert( elem->GetID() );
2639     }
2640   }
2641   else { // all nodes of submesh elements
2642     SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2643     while ( eIt->more() ) {
2644       const SMDS_MeshElement* anElem = eIt->next();
2645       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
2646       while ( nIt->more() ) {
2647         const SMDS_MeshElement* elem = nIt->next();
2648         theElems.insert( elem->GetID() );
2649       }
2650     }
2651   }
2652
2653   aResult->length(theElems.size());
2654   set<int>::iterator itElem;
2655   int i = 0;
2656   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
2657     aResult[i++] = *itElem;
2658
2659   return aResult._retn();
2660 }
2661   
2662
2663 //=============================================================================
2664 /*!
2665  * Returns type of elements for given submesh
2666  */
2667 //=============================================================================
2668 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
2669      throw (SALOME::SALOME_Exception)
2670 {
2671   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2672   if(!SM) return SMESH::ALL;
2673
2674   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2675   if(!SDSM) return SMESH::ALL;
2676
2677   if(SDSM->NbElements()==0)
2678     return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
2679
2680   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2681   const SMDS_MeshElement* anElem = eIt->next();
2682   return ( SMESH::ElementType ) anElem->GetType();
2683 }
2684   
2685
2686 //=============================================================================
2687 /*!
2688  *
2689  */
2690 //=============================================================================
2691
2692 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
2693 {
2694   CORBA::LongLong pointeur = CORBA::LongLong(_impl);
2695   if ( MYDEBUG )
2696     MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
2697   return pointeur;
2698 }
2699
2700
2701 //=============================================================================
2702 /*!
2703  * Get XYZ coordinates of node as list of double
2704  * If there is not node for given ID - returns empty list
2705  */
2706 //=============================================================================
2707
2708 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
2709 {
2710   SMESH::double_array_var aResult = new SMESH::double_array();
2711   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2712   if ( aSMESHDS_Mesh == NULL )
2713     return aResult._retn();
2714
2715   // find node
2716   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2717   if(!aNode)
2718     return aResult._retn();
2719
2720   // add coordinates
2721   aResult->length(3);
2722   aResult[0] = aNode->X();
2723   aResult[1] = aNode->Y();
2724   aResult[2] = aNode->Z();
2725   return aResult._retn();
2726 }
2727
2728
2729 //=============================================================================
2730 /*!
2731  * For given node returns list of IDs of inverse elements
2732  * If there is not node for given ID - returns empty list
2733  */
2734 //=============================================================================
2735
2736 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
2737 {
2738   SMESH::long_array_var aResult = new SMESH::long_array();
2739   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2740   if ( aSMESHDS_Mesh == NULL )
2741     return aResult._retn();
2742
2743   // find node
2744   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2745   if(!aNode)
2746     return aResult._retn();
2747
2748   // find inverse elements
2749   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
2750   TColStd_SequenceOfInteger IDs;
2751   while(eIt->more()) {
2752     const SMDS_MeshElement* elem = eIt->next();
2753     IDs.Append(elem->GetID());
2754   }
2755   if(IDs.Length()>0) {
2756     aResult->length(IDs.Length());
2757     int i = 1;
2758     for(; i<=IDs.Length(); i++) {
2759       aResult[i-1] = IDs.Value(i);
2760     }
2761   }
2762   return aResult._retn();
2763 }
2764
2765 //=============================================================================
2766 /*!
2767  * \brief Return position of a node on shape
2768  */
2769 //=============================================================================
2770
2771 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
2772 {
2773   SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
2774   aNodePosition->shapeID = 0;
2775   aNodePosition->shapeType = GEOM::SHAPE;
2776
2777   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
2778   if ( !mesh ) return aNodePosition;
2779
2780   if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
2781   {
2782     if ( SMDS_PositionPtr pos = aNode->GetPosition() )
2783     {
2784       aNodePosition->shapeID = pos->GetShapeId();
2785       switch ( pos->GetTypeOfPosition() ) {
2786       case SMDS_TOP_EDGE:
2787         aNodePosition->shapeType = GEOM::EDGE;
2788         aNodePosition->params.length(1);
2789         aNodePosition->params[0] =
2790           static_cast<SMDS_EdgePosition*>( pos.get() )->GetUParameter();
2791         break;
2792       case SMDS_TOP_FACE:
2793         aNodePosition->shapeType = GEOM::FACE;
2794         aNodePosition->params.length(2);
2795         aNodePosition->params[0] =
2796           static_cast<SMDS_FacePosition*>( pos.get() )->GetUParameter();
2797         aNodePosition->params[1] =
2798           static_cast<SMDS_FacePosition*>( pos.get() )->GetVParameter();
2799         break;
2800       case SMDS_TOP_VERTEX:
2801         aNodePosition->shapeType = GEOM::VERTEX;
2802         break;
2803       case SMDS_TOP_3DSPACE:
2804         if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
2805           aNodePosition->shapeType = GEOM::SOLID;
2806         else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
2807           aNodePosition->shapeType = GEOM::SHELL;
2808         break;
2809       default:;
2810       }
2811     }
2812   }
2813   return aNodePosition;
2814 }
2815
2816 //=============================================================================
2817 /*!
2818  * If given element is node returns IDs of shape from position
2819  * If there is not node for given ID - returns -1
2820  */
2821 //=============================================================================
2822
2823 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
2824 {
2825   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2826   if ( aSMESHDS_Mesh == NULL )
2827     return -1;
2828
2829   // try to find node
2830   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2831   if(aNode) {
2832     SMDS_PositionPtr pos = aNode->GetPosition();
2833     if(!pos)
2834       return -1;
2835     else
2836       return pos->GetShapeId();
2837   }
2838
2839   return -1;
2840 }
2841
2842
2843 //=============================================================================
2844 /*!
2845  * For given element returns ID of result shape after 
2846  * ::FindShape() from SMESH_MeshEditor
2847  * If there is not element for given ID - returns -1
2848  */
2849 //=============================================================================
2850
2851 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
2852 {
2853   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2854   if ( aSMESHDS_Mesh == NULL )
2855     return -1;
2856
2857   // try to find element
2858   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2859   if(!elem)
2860     return -1;
2861
2862   //SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
2863   ::SMESH_MeshEditor aMeshEditor(_impl);
2864   int index = aMeshEditor.FindShape( elem );
2865   if(index>0)
2866     return index;
2867
2868   return -1;
2869 }
2870
2871
2872 //=============================================================================
2873 /*!
2874  * Returns number of nodes for given element
2875  * If there is not element for given ID - returns -1
2876  */
2877 //=============================================================================
2878
2879 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
2880 {
2881   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2882   if ( aSMESHDS_Mesh == NULL ) return -1;
2883   // try to find element
2884   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2885   if(!elem) return -1;
2886   return elem->NbNodes();
2887 }
2888
2889
2890 //=============================================================================
2891 /*!
2892  * Returns ID of node by given index for given element
2893  * If there is not element for given ID - returns -1
2894  * If there is not node for given index - returns -2
2895  */
2896 //=============================================================================
2897
2898 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
2899 {
2900   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2901   if ( aSMESHDS_Mesh == NULL ) return -1;
2902   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2903   if(!elem) return -1;
2904   if( index>=elem->NbNodes() || index<0 ) return -1;
2905   return elem->GetNode(index)->GetID();
2906 }
2907
2908 //=============================================================================
2909 /*!
2910  * Returns IDs of nodes of given element
2911  */
2912 //=============================================================================
2913
2914 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
2915 {
2916   SMESH::long_array_var aResult = new SMESH::long_array();
2917   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
2918   {
2919     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id) )
2920     {
2921       aResult->length( elem->NbNodes() );
2922       for ( int i = 0; i < elem->NbNodes(); ++i )
2923         aResult[ i ] = elem->GetNode( i )->GetID();
2924     }
2925   }
2926   return aResult._retn();
2927 }
2928
2929 //=============================================================================
2930 /*!
2931  * Returns true if given node is medium node
2932  * in given quadratic element
2933  */
2934 //=============================================================================
2935
2936 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
2937 {
2938   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2939   if ( aSMESHDS_Mesh == NULL ) return false;
2940   // try to find node
2941   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
2942   if(!aNode) return false;
2943   // try to find element
2944   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(ide);
2945   if(!elem) return false;
2946
2947   return elem->IsMediumNode(aNode);
2948 }
2949
2950
2951 //=============================================================================
2952 /*!
2953  * Returns true if given node is medium node
2954  * in one of quadratic elements
2955  */
2956 //=============================================================================
2957
2958 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
2959                                                    SMESH::ElementType theElemType)
2960 {
2961   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2962   if ( aSMESHDS_Mesh == NULL ) return false;
2963
2964   // try to find node
2965   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
2966   if(!aNode) return false;
2967
2968   SMESH_MesherHelper aHelper( *(_impl) );
2969
2970   SMDSAbs_ElementType aType;
2971   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
2972   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
2973   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
2974   else aType = SMDSAbs_All;
2975
2976   return aHelper.IsMedium(aNode,aType);
2977 }
2978
2979
2980 //=============================================================================
2981 /*!
2982  * Returns number of edges for given element
2983  */
2984 //=============================================================================
2985
2986 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
2987 {
2988   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2989   if ( aSMESHDS_Mesh == NULL ) return -1;
2990   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2991   if(!elem) return -1;
2992   return elem->NbEdges();
2993 }
2994
2995
2996 //=============================================================================
2997 /*!
2998  * Returns number of faces for given element
2999  */
3000 //=============================================================================
3001
3002 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
3003 {
3004   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3005   if ( aSMESHDS_Mesh == NULL ) return -1;
3006   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3007   if(!elem) return -1;
3008   return elem->NbFaces();
3009 }
3010
3011
3012 //=============================================================================
3013 /*!
3014  * Returns true if given element is polygon
3015  */
3016 //=============================================================================
3017
3018 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
3019 {
3020   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3021   if ( aSMESHDS_Mesh == NULL ) return false;
3022   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3023   if(!elem) return false;
3024   return elem->IsPoly();
3025 }
3026
3027
3028 //=============================================================================
3029 /*!
3030  * Returns true if given element is quadratic
3031  */
3032 //=============================================================================
3033
3034 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
3035 {
3036   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3037   if ( aSMESHDS_Mesh == NULL ) return false;
3038   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3039   if(!elem) return false;
3040   return elem->IsQuadratic();
3041 }
3042
3043
3044 //=============================================================================
3045 /*!
3046  * Returns bary center for given element
3047  */
3048 //=============================================================================
3049
3050 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
3051 {
3052   SMESH::double_array_var aResult = new SMESH::double_array();
3053   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3054   if ( aSMESHDS_Mesh == NULL )
3055     return aResult._retn();
3056
3057   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3058   if(!elem)
3059     return aResult._retn();
3060
3061   if(elem->GetType()==SMDSAbs_Volume) {
3062     SMDS_VolumeTool aTool;
3063     if(aTool.Set(elem)) {
3064       aResult->length(3);
3065       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
3066         aResult->length(0);
3067     }
3068   }
3069   else {
3070     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
3071     int nbn = 0;
3072     double x=0., y=0., z=0.;
3073     for(; anIt->more(); ) {
3074       nbn++;
3075       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
3076       x += aNode->X();
3077       y += aNode->Y();
3078       z += aNode->Z();
3079     }
3080     if(nbn>0) {
3081       // add coordinates
3082       aResult->length(3);
3083       aResult[0] = x/nbn;
3084       aResult[1] = y/nbn;
3085       aResult[2] = z/nbn;
3086     }
3087   }
3088
3089   return aResult._retn();
3090 }
3091
3092
3093 //=============================================================================
3094 /*!
3095  * Create and publish group servants if any groups were imported or created anyhow
3096  */
3097 //=============================================================================
3098
3099 void SMESH_Mesh_i::CreateGroupServants() 
3100 {
3101   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
3102
3103   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
3104   while ( groupIt->more() )
3105   {
3106     ::SMESH_Group* group = groupIt->next();
3107     int            anId = group->GetGroupDS()->GetID();
3108
3109     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
3110     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
3111       continue;
3112
3113     SMESH_GroupBase_i* aGroupImpl;
3114     TopoDS_Shape       shape;
3115     if ( SMESHDS_GroupOnGeom* groupOnGeom =
3116          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
3117     {
3118       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
3119       shape      = groupOnGeom->GetShape();
3120     }
3121     else {
3122       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3123     }
3124
3125     // To ensure correct mapping of servant and correct reference counting in GenericObj_i
3126     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
3127     aGroupImpl->Register();
3128
3129     SMESH::SMESH_GroupBase_var groupVar =
3130       SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
3131     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
3132
3133     // register CORBA object for persistence
3134     int nextId = _gen_i->RegisterObject( groupVar );
3135     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
3136
3137     // publishing of the groups in the study
3138     if ( !aStudy->_is_nil() ) {
3139       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
3140       _gen_i->PublishGroup( aStudy, _this(), groupVar, shapeVar, groupVar->GetName());
3141     }
3142   }
3143 }
3144
3145 //=============================================================================
3146 /*!
3147  * \brief Return groups cantained in _mapGroups by their IDs
3148  */
3149 //=============================================================================
3150
3151 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
3152 {
3153   int nbGroups = groupIDs.size();
3154   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
3155   aList->length( nbGroups );
3156
3157   list<int>::const_iterator ids = groupIDs.begin();
3158   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
3159   {
3160     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
3161     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
3162       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
3163   }
3164   aList->length( nbGroups );
3165   return aList._retn();
3166 }
3167
3168 //=============================================================================
3169 /*!
3170  * \brief Return information about imported file
3171  */
3172 //=============================================================================
3173
3174 SALOME_MED::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
3175 {
3176   SALOME_MED::MedFileInfo_var res( myFileInfo );
3177   if ( !res.operator->() ) {
3178     res = new SALOME_MED::MedFileInfo;
3179     res->fileName = "";
3180     res->fileSize = res->major = res->minor = res->release = -1;
3181   }
3182   return res._retn();
3183 }
3184
3185 //=============================================================================
3186 /*!
3187  * \brief Check and correct names of mesh groups
3188  */
3189 //=============================================================================
3190
3191 void SMESH_Mesh_i::checkGroupNames()
3192 {
3193   int nbGrp = NbGroups();
3194   if ( !nbGrp )
3195     return;
3196
3197   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
3198   if ( aStudy->_is_nil() )
3199     return; // nothing to do
3200   
3201   SMESH::ListOfGroups* grpList = 0;
3202   // avoid dump of "GetGroups"
3203   {
3204     // store python dump into a local variable inside local scope
3205     SMESH::TPythonDump pDump; // do not delete this line of code
3206     grpList = GetGroups();
3207   }
3208
3209   for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
3210     SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
3211     if ( !aGrp )
3212       continue;
3213     SALOMEDS::SObject_var aGrpSO = _gen_i->ObjectToSObject( aStudy, aGrp );
3214     if ( aGrpSO->_is_nil() )
3215       continue;
3216     // correct name of the mesh group if necessary
3217     const char* guiName = aGrpSO->GetName();
3218     if ( strcmp(guiName, aGrp->GetName()) )
3219       aGrp->SetName( guiName );
3220   }
3221 }
3222
3223 //=============================================================================
3224 /*!
3225  * \brief Sets list of notebook variables used for Mesh operations separated by ":" symbol
3226  */
3227 //=============================================================================
3228 void SMESH_Mesh_i::SetParameters(const char* theParameters)
3229 {
3230   SMESH_Gen_i::GetSMESHGen()->UpdateParameters(SMESH::SMESH_Mesh::_narrow(_this()),
3231                                                CORBA::string_dup(theParameters));
3232 }
3233
3234 //=============================================================================
3235 /*!
3236  * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
3237  */
3238 //=============================================================================
3239 char* SMESH_Mesh_i::GetParameters()
3240 {
3241   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
3242   return CORBA::string_dup(gen->GetParameters(SMESH::SMESH_Mesh::_narrow(_this())));
3243 }
3244
3245 //=============================================================================
3246 /*!
3247  * \brief Returns list of notebook variables used for last Mesh operation
3248  */
3249 //=============================================================================
3250 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
3251 {
3252   SMESH::string_array_var aResult = new SMESH::string_array();
3253   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
3254   if(gen) {
3255     char *aParameters = GetParameters();
3256     SALOMEDS::Study_ptr aStudy = gen->GetCurrentStudy();
3257     if(!aStudy->_is_nil()) {
3258       SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters); 
3259       if(aSections->length() > 0) {
3260         SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1];
3261         aResult->length(aVars.length());
3262         for(int i = 0;i < aVars.length();i++)
3263           aResult[i] = CORBA::string_dup( aVars[i]);
3264       }
3265     }
3266   }
3267   return aResult._retn();
3268 }