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