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