]> SALOME platform Git repositories - modules/smesh.git/blob - src/SMESH_I/SMESH_Mesh_i.cxx
Salome HOME
Imp 19925 - Mesh preview
[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   // Update Python script
1992   TPythonDump() << _this() << ".ExportToMED( '"
1993                 << file << "', " << auto_groups << ", " << theVersion << " )";
1994
1995   // Perform Export
1996   PrepareForWriting(file);
1997   const char* aMeshName = "Mesh";
1998   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1999   if ( !aStudy->_is_nil() ) {
2000     SALOMEDS::SObject_var aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
2001     if ( !aMeshSO->_is_nil() ) {
2002       aMeshName = aMeshSO->GetName();
2003       //SCRUTE(file);
2004       //SCRUTE(aMeshName);
2005       //SCRUTE(aMeshSO->GetID());
2006
2007       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
2008       if ( !aStudy->GetProperties()->IsLocked() )
2009         {
2010         SALOMEDS::GenericAttribute_var anAttr;
2011         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
2012         SALOMEDS::AttributeExternalFileDef_var aFileName;
2013         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
2014         aFileName = SALOMEDS::AttributeExternalFileDef::_narrow(anAttr);
2015         ASSERT(!aFileName->_is_nil());
2016         aFileName->SetValue(file);
2017         SALOMEDS::AttributeFileType_var aFileType;
2018         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
2019         aFileType = SALOMEDS::AttributeFileType::_narrow(anAttr);
2020         ASSERT(!aFileType->_is_nil());
2021         aFileType->SetValue("FICHIERMED");
2022         }
2023     }
2024   }
2025   _impl->ExportMED( file, aMeshName, auto_groups, theVersion );
2026 }
2027
2028 void SMESH_Mesh_i::ExportMED (const char* file,
2029                               CORBA::Boolean auto_groups)
2030   throw(SALOME::SALOME_Exception)
2031 {
2032   ExportToMED(file,auto_groups,SMESH::MED_V2_1);
2033 }
2034
2035 void SMESH_Mesh_i::ExportDAT (const char *file)
2036   throw(SALOME::SALOME_Exception)
2037 {
2038   Unexpect aCatch(SALOME_SalomeException);
2039
2040   // Update Python script
2041   TPythonDump() << _this() << ".ExportDAT( '" << file << "' )";
2042
2043   // Perform Export
2044   PrepareForWriting(file);
2045   _impl->ExportDAT(file);
2046 }
2047
2048 void SMESH_Mesh_i::ExportUNV (const char *file)
2049   throw(SALOME::SALOME_Exception)
2050 {
2051   Unexpect aCatch(SALOME_SalomeException);
2052
2053   // Update Python script
2054   TPythonDump() << _this() << ".ExportUNV( '" << file << "' )";
2055
2056   // Perform Export
2057   PrepareForWriting(file);
2058   _impl->ExportUNV(file);
2059 }
2060
2061 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
2062   throw(SALOME::SALOME_Exception)
2063 {
2064   Unexpect aCatch(SALOME_SalomeException);
2065
2066   // Update Python script
2067   TPythonDump() << _this() << ".ExportSTL( '" << file << "', " << isascii << " )";
2068
2069   // Perform Export
2070   PrepareForWriting(file);
2071   _impl->ExportSTL(file, isascii);
2072 }
2073
2074 //=============================================================================
2075 /*!
2076  *
2077  */
2078 //=============================================================================
2079
2080 SALOME_MED::MESH_ptr SMESH_Mesh_i::GetMEDMesh()throw(SALOME::SALOME_Exception)
2081 {
2082   Unexpect aCatch(SALOME_SalomeException);
2083   SMESH_MEDMesh_i *aMedMesh = new SMESH_MEDMesh_i(this);
2084   SALOME_MED::MESH_var aMesh = aMedMesh->_this();
2085   return aMesh._retn();
2086 }
2087
2088 //=============================================================================
2089 /*!
2090  *
2091  */
2092 //=============================================================================
2093 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
2094 {
2095   Unexpect aCatch(SALOME_SalomeException);
2096   return _impl->NbNodes();
2097 }
2098
2099 //=============================================================================
2100 /*!
2101  *
2102  */
2103 //=============================================================================
2104 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
2105 {
2106   Unexpect aCatch(SALOME_SalomeException);
2107   return NbEdges() + NbFaces() + NbVolumes();
2108 }
2109
2110 //=============================================================================
2111 /*!
2112  *
2113  */
2114 //=============================================================================
2115 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
2116 {
2117   Unexpect aCatch(SALOME_SalomeException);
2118   return _impl->NbEdges();
2119 }
2120
2121 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
2122   throw(SALOME::SALOME_Exception)
2123 {
2124   Unexpect aCatch(SALOME_SalomeException);
2125   return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
2126 }
2127
2128 //=============================================================================
2129 /*!
2130  *
2131  */
2132 //=============================================================================
2133 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
2134 {
2135   Unexpect aCatch(SALOME_SalomeException);
2136   return _impl->NbFaces();
2137 }
2138
2139 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
2140 {
2141   Unexpect aCatch(SALOME_SalomeException);
2142   return _impl->NbTriangles();
2143 }
2144
2145 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
2146 {
2147   Unexpect aCatch(SALOME_SalomeException);
2148   return _impl->NbQuadrangles();
2149 }
2150
2151 CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
2152 {
2153   Unexpect aCatch(SALOME_SalomeException);
2154   return _impl->NbPolygons();
2155 }
2156
2157 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
2158   throw(SALOME::SALOME_Exception)
2159 {
2160   Unexpect aCatch(SALOME_SalomeException);
2161   return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
2162 }
2163
2164 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
2165   throw(SALOME::SALOME_Exception)
2166 {
2167   Unexpect aCatch(SALOME_SalomeException);
2168   return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
2169 }
2170
2171 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
2172   throw(SALOME::SALOME_Exception)
2173 {
2174   Unexpect aCatch(SALOME_SalomeException);
2175   return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
2176 }
2177
2178 //=============================================================================
2179 /*!
2180  *
2181  */
2182 //=============================================================================
2183 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
2184 {
2185   Unexpect aCatch(SALOME_SalomeException);
2186   return _impl->NbVolumes();
2187 }
2188
2189 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
2190 {
2191   Unexpect aCatch(SALOME_SalomeException);
2192   return _impl->NbTetras();
2193 }
2194
2195 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
2196 {
2197   Unexpect aCatch(SALOME_SalomeException);
2198   return _impl->NbHexas();
2199 }
2200
2201 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
2202 {
2203   Unexpect aCatch(SALOME_SalomeException);
2204   return _impl->NbPyramids();
2205 }
2206
2207 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
2208 {
2209   Unexpect aCatch(SALOME_SalomeException);
2210   return _impl->NbPrisms();
2211 }
2212
2213 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
2214 {
2215   Unexpect aCatch(SALOME_SalomeException);
2216   return _impl->NbPolyhedrons();
2217 }
2218
2219 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
2220   throw(SALOME::SALOME_Exception)
2221 {
2222   Unexpect aCatch(SALOME_SalomeException);
2223   return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
2224 }
2225
2226 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
2227   throw(SALOME::SALOME_Exception)
2228 {
2229   Unexpect aCatch(SALOME_SalomeException);
2230   return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
2231 }
2232
2233 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
2234   throw(SALOME::SALOME_Exception)
2235 {
2236   Unexpect aCatch(SALOME_SalomeException);
2237   return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
2238 }
2239
2240 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
2241   throw(SALOME::SALOME_Exception)
2242 {
2243   Unexpect aCatch(SALOME_SalomeException);
2244   return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
2245 }
2246
2247 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
2248   throw(SALOME::SALOME_Exception)
2249 {
2250   Unexpect aCatch(SALOME_SalomeException);
2251   return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
2252 }
2253
2254 //=============================================================================
2255 /*!
2256  *
2257  */
2258 //=============================================================================
2259 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
2260 {
2261   Unexpect aCatch(SALOME_SalomeException);
2262   return _impl->NbSubMesh();
2263 }
2264
2265 //=============================================================================
2266 /*!
2267  *
2268  */
2269 //=============================================================================
2270 char* SMESH_Mesh_i::Dump()
2271 {
2272   std::ostringstream os;
2273   _impl->Dump( os );
2274   return CORBA::string_dup( os.str().c_str() );
2275 }
2276
2277 //=============================================================================
2278 /*!
2279  *
2280  */
2281 //=============================================================================
2282 SMESH::long_array* SMESH_Mesh_i::GetIDs()
2283 {
2284 //   SMESH::long_array_var aResult = new SMESH::long_array();
2285 //   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2286 //   int aMinId = aSMESHDS_Mesh->MinElementID();
2287 //   int aMaxId =  aSMESHDS_Mesh->MaxElementID();
2288
2289 //   aResult->length(aMaxId - aMinId + 1);
2290
2291 //   for (int i = 0, id = aMinId; id <= aMaxId; id++  )
2292 //     aResult[i++] = id;
2293
2294 //   return aResult._retn();
2295   // PAL12398
2296   return GetElementsId();
2297 }
2298
2299 //=============================================================================
2300 /*!
2301  *
2302  */
2303 //=============================================================================
2304
2305 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
2306      throw (SALOME::SALOME_Exception)
2307 {
2308   Unexpect aCatch(SALOME_SalomeException);
2309   MESSAGE("SMESH_Mesh_i::GetElementsId");
2310   SMESH::long_array_var aResult = new SMESH::long_array();
2311   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2312
2313   if ( aSMESHDS_Mesh == NULL )
2314     return aResult._retn();
2315
2316   long nbElements = NbElements();
2317   aResult->length( nbElements );
2318   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
2319   for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
2320     aResult[i] = anIt->next()->GetID();
2321
2322   return aResult._retn();
2323 }
2324
2325
2326 //=============================================================================
2327 /*!
2328  *
2329  */
2330 //=============================================================================
2331
2332 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
2333     throw (SALOME::SALOME_Exception)
2334 {
2335   Unexpect aCatch(SALOME_SalomeException);
2336   MESSAGE("SMESH_subMesh_i::GetElementsByType");
2337   SMESH::long_array_var aResult = new SMESH::long_array();
2338   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2339
2340   if ( aSMESHDS_Mesh == NULL )
2341     return aResult._retn();
2342
2343   long nbElements = NbElements();
2344
2345   // No sense in returning ids of elements along with ids of nodes:
2346   // when theElemType == SMESH::ALL, return node ids only if
2347   // there are no elements
2348   if ( theElemType == SMESH::NODE || theElemType == SMESH::ALL && nbElements == 0 )
2349     return GetNodesId();
2350
2351   aResult->length( nbElements );
2352
2353   int i = 0;
2354
2355   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
2356   while ( i < nbElements && anIt->more() ) {
2357     const SMDS_MeshElement* anElem = anIt->next();
2358     if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
2359       aResult[i++] = anElem->GetID();
2360   }
2361
2362   aResult->length( i );
2363
2364   return aResult._retn();
2365 }
2366
2367 //=============================================================================
2368 /*!
2369  *
2370  */
2371 //=============================================================================
2372
2373 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
2374   throw (SALOME::SALOME_Exception)
2375 {
2376   Unexpect aCatch(SALOME_SalomeException);
2377   MESSAGE("SMESH_subMesh_i::GetNodesId");
2378   SMESH::long_array_var aResult = new SMESH::long_array();
2379   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2380
2381   if ( aSMESHDS_Mesh == NULL )
2382     return aResult._retn();
2383
2384   long nbNodes = NbNodes();
2385   aResult->length( nbNodes );
2386   SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator();
2387   for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
2388     aResult[i] = anIt->next()->GetID();
2389
2390   return aResult._retn();
2391 }
2392
2393 //=============================================================================
2394 /*!
2395  *
2396  */
2397 //=============================================================================
2398
2399 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
2400   throw (SALOME::SALOME_Exception)
2401 {
2402   return ( SMESH::ElementType )_impl->GetElementType( id, iselem );
2403 }
2404
2405
2406 //=============================================================================
2407 /*!
2408  * Returns ID of elements for given submesh
2409  */
2410 //=============================================================================
2411 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
2412      throw (SALOME::SALOME_Exception)
2413 {
2414   SMESH::long_array_var aResult = new SMESH::long_array();
2415
2416   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2417   if(!SM) return aResult._retn();
2418
2419   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2420   if(!SDSM) return aResult._retn();
2421
2422   aResult->length(SDSM->NbElements());
2423
2424   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2425   int i = 0;
2426   while ( eIt->more() ) {
2427     aResult[i++] = eIt->next()->GetID();
2428   }
2429
2430   return aResult._retn();
2431 }
2432
2433
2434 //=============================================================================
2435 /*!
2436  * Returns ID of nodes for given submesh
2437  * If param all==true - returns all nodes, else -
2438  * returns only nodes on shapes.
2439  */
2440 //=============================================================================
2441 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID, CORBA::Boolean all)
2442      throw (SALOME::SALOME_Exception)
2443 {
2444   SMESH::long_array_var aResult = new SMESH::long_array();
2445
2446   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2447   if(!SM) return aResult._retn();
2448
2449   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2450   if(!SDSM) return aResult._retn();
2451
2452   set<int> theElems;
2453   if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
2454     SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
2455     while ( nIt->more() ) {
2456       const SMDS_MeshNode* elem = nIt->next();
2457       theElems.insert( elem->GetID() );
2458     }
2459   }
2460   else { // all nodes of submesh elements
2461     SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2462     while ( eIt->more() ) {
2463       const SMDS_MeshElement* anElem = eIt->next();
2464       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
2465       while ( nIt->more() ) {
2466         const SMDS_MeshElement* elem = nIt->next();
2467         theElems.insert( elem->GetID() );
2468       }
2469     }
2470   }
2471
2472   aResult->length(theElems.size());
2473   set<int>::iterator itElem;
2474   int i = 0;
2475   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
2476     aResult[i++] = *itElem;
2477
2478   return aResult._retn();
2479 }
2480   
2481
2482 //=============================================================================
2483 /*!
2484  * Returns type of elements for given submesh
2485  */
2486 //=============================================================================
2487 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
2488      throw (SALOME::SALOME_Exception)
2489 {
2490   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2491   if(!SM) return SMESH::ALL;
2492
2493   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2494   if(!SDSM) return SMESH::ALL;
2495
2496   if(SDSM->NbElements()==0)
2497     return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
2498
2499   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2500   const SMDS_MeshElement* anElem = eIt->next();
2501   return ( SMESH::ElementType ) anElem->GetType();
2502 }
2503   
2504
2505 //=============================================================================
2506 /*!
2507  *
2508  */
2509 //=============================================================================
2510
2511 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
2512 {
2513   CORBA::LongLong pointeur = CORBA::LongLong(_impl);
2514   if ( MYDEBUG )
2515     MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
2516   return pointeur;
2517 }
2518
2519
2520 //=============================================================================
2521 /*!
2522  * Get XYZ coordinates of node as list of double
2523  * If there is not node for given ID - returns empty list
2524  */
2525 //=============================================================================
2526
2527 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
2528 {
2529   SMESH::double_array_var aResult = new SMESH::double_array();
2530   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2531   if ( aSMESHDS_Mesh == NULL )
2532     return aResult._retn();
2533
2534   // find node
2535   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2536   if(!aNode)
2537     return aResult._retn();
2538
2539   // add coordinates
2540   aResult->length(3);
2541   aResult[0] = aNode->X();
2542   aResult[1] = aNode->Y();
2543   aResult[2] = aNode->Z();
2544   return aResult._retn();
2545 }
2546
2547
2548 //=============================================================================
2549 /*!
2550  * For given node returns list of IDs of inverse elements
2551  * If there is not node for given ID - returns empty list
2552  */
2553 //=============================================================================
2554
2555 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
2556 {
2557   SMESH::long_array_var aResult = new SMESH::long_array();
2558   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2559   if ( aSMESHDS_Mesh == NULL )
2560     return aResult._retn();
2561
2562   // find node
2563   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2564   if(!aNode)
2565     return aResult._retn();
2566
2567   // find inverse elements
2568   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
2569   TColStd_SequenceOfInteger IDs;
2570   while(eIt->more()) {
2571     const SMDS_MeshElement* elem = eIt->next();
2572     IDs.Append(elem->GetID());
2573   }
2574   if(IDs.Length()>0) {
2575     aResult->length(IDs.Length());
2576     int i = 1;
2577     for(; i<=IDs.Length(); i++) {
2578       aResult[i-1] = IDs.Value(i);
2579     }
2580   }
2581   return aResult._retn();
2582 }
2583
2584 //=============================================================================
2585 /*!
2586  * \brief Return position of a node on shape
2587  */
2588 //=============================================================================
2589
2590 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
2591 {
2592   SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
2593   aNodePosition->shapeID = 0;
2594   aNodePosition->shapeType = GEOM::SHAPE;
2595
2596   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
2597   if ( !mesh ) return aNodePosition;
2598
2599   if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
2600   {
2601     if ( SMDS_PositionPtr pos = aNode->GetPosition() )
2602     {
2603       aNodePosition->shapeID = pos->GetShapeId();
2604       switch ( pos->GetTypeOfPosition() ) {
2605       case SMDS_TOP_EDGE:
2606         aNodePosition->shapeType = GEOM::EDGE;
2607         aNodePosition->params.length(1);
2608         aNodePosition->params[0] =
2609           static_cast<SMDS_EdgePosition*>( pos.get() )->GetUParameter();
2610         break;
2611       case SMDS_TOP_FACE:
2612         aNodePosition->shapeType = GEOM::FACE;
2613         aNodePosition->params.length(2);
2614         aNodePosition->params[0] =
2615           static_cast<SMDS_FacePosition*>( pos.get() )->GetUParameter();
2616         aNodePosition->params[1] =
2617           static_cast<SMDS_FacePosition*>( pos.get() )->GetVParameter();
2618         break;
2619       case SMDS_TOP_VERTEX:
2620         aNodePosition->shapeType = GEOM::VERTEX;
2621         break;
2622       case SMDS_TOP_3DSPACE:
2623         if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
2624           aNodePosition->shapeType = GEOM::SOLID;
2625         else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
2626           aNodePosition->shapeType = GEOM::SHELL;
2627         break;
2628       default:;
2629       }
2630     }
2631   }
2632   return aNodePosition;
2633 }
2634
2635 //=============================================================================
2636 /*!
2637  * If given element is node returns IDs of shape from position
2638  * If there is not node for given ID - returns -1
2639  */
2640 //=============================================================================
2641
2642 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
2643 {
2644   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2645   if ( aSMESHDS_Mesh == NULL )
2646     return -1;
2647
2648   // try to find node
2649   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2650   if(aNode) {
2651     SMDS_PositionPtr pos = aNode->GetPosition();
2652     if(!pos)
2653       return -1;
2654     else
2655       return pos->GetShapeId();
2656   }
2657
2658   return -1;
2659 }
2660
2661
2662 //=============================================================================
2663 /*!
2664  * For given element returns ID of result shape after 
2665  * ::FindShape() from SMESH_MeshEditor
2666  * If there is not element for given ID - returns -1
2667  */
2668 //=============================================================================
2669
2670 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
2671 {
2672   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2673   if ( aSMESHDS_Mesh == NULL )
2674     return -1;
2675
2676   // try to find element
2677   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2678   if(!elem)
2679     return -1;
2680
2681   //SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
2682   ::SMESH_MeshEditor aMeshEditor(_impl);
2683   int index = aMeshEditor.FindShape( elem );
2684   if(index>0)
2685     return index;
2686
2687   return -1;
2688 }
2689
2690
2691 //=============================================================================
2692 /*!
2693  * Returns number of nodes for given element
2694  * If there is not element for given ID - returns -1
2695  */
2696 //=============================================================================
2697
2698 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
2699 {
2700   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2701   if ( aSMESHDS_Mesh == NULL ) return -1;
2702   // try to find element
2703   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2704   if(!elem) return -1;
2705   return elem->NbNodes();
2706 }
2707
2708
2709 //=============================================================================
2710 /*!
2711  * Returns ID of node by given index for given element
2712  * If there is not element for given ID - returns -1
2713  * If there is not node for given index - returns -2
2714  */
2715 //=============================================================================
2716
2717 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
2718 {
2719   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2720   if ( aSMESHDS_Mesh == NULL ) return -1;
2721   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2722   if(!elem) return -1;
2723   if( index>=elem->NbNodes() || index<0 ) return -1;
2724   return elem->GetNode(index)->GetID();
2725 }
2726
2727 //=============================================================================
2728 /*!
2729  * Returns IDs of nodes of given element
2730  */
2731 //=============================================================================
2732
2733 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
2734 {
2735   SMESH::long_array_var aResult = new SMESH::long_array();
2736   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
2737   {
2738     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id) )
2739     {
2740       aResult->length( elem->NbNodes() );
2741       for ( int i = 0; i < elem->NbNodes(); ++i )
2742         aResult[ i ] = elem->GetNode( i )->GetID();
2743     }
2744   }
2745   return aResult._retn();
2746 }
2747
2748 //=============================================================================
2749 /*!
2750  * Returns true if given node is medium node
2751  * in given quadratic element
2752  */
2753 //=============================================================================
2754
2755 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
2756 {
2757   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2758   if ( aSMESHDS_Mesh == NULL ) return false;
2759   // try to find node
2760   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
2761   if(!aNode) return false;
2762   // try to find element
2763   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(ide);
2764   if(!elem) return false;
2765
2766   return elem->IsMediumNode(aNode);
2767 }
2768
2769
2770 //=============================================================================
2771 /*!
2772  * Returns true if given node is medium node
2773  * in one of quadratic elements
2774  */
2775 //=============================================================================
2776
2777 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
2778                                                    SMESH::ElementType theElemType)
2779 {
2780   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2781   if ( aSMESHDS_Mesh == NULL ) return false;
2782
2783   // try to find node
2784   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
2785   if(!aNode) return false;
2786
2787   SMESH_MesherHelper aHelper( *(_impl) );
2788
2789   SMDSAbs_ElementType aType;
2790   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
2791   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
2792   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
2793   else aType = SMDSAbs_All;
2794
2795   return aHelper.IsMedium(aNode,aType);
2796 }
2797
2798
2799 //=============================================================================
2800 /*!
2801  * Returns number of edges for given element
2802  */
2803 //=============================================================================
2804
2805 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
2806 {
2807   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2808   if ( aSMESHDS_Mesh == NULL ) return -1;
2809   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2810   if(!elem) return -1;
2811   return elem->NbEdges();
2812 }
2813
2814
2815 //=============================================================================
2816 /*!
2817  * Returns number of faces for given element
2818  */
2819 //=============================================================================
2820
2821 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
2822 {
2823   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2824   if ( aSMESHDS_Mesh == NULL ) return -1;
2825   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2826   if(!elem) return -1;
2827   return elem->NbFaces();
2828 }
2829
2830
2831 //=============================================================================
2832 /*!
2833  * Returns true if given element is polygon
2834  */
2835 //=============================================================================
2836
2837 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
2838 {
2839   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2840   if ( aSMESHDS_Mesh == NULL ) return false;
2841   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2842   if(!elem) return false;
2843   return elem->IsPoly();
2844 }
2845
2846
2847 //=============================================================================
2848 /*!
2849  * Returns true if given element is quadratic
2850  */
2851 //=============================================================================
2852
2853 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
2854 {
2855   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2856   if ( aSMESHDS_Mesh == NULL ) return false;
2857   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2858   if(!elem) return false;
2859   return elem->IsQuadratic();
2860 }
2861
2862
2863 //=============================================================================
2864 /*!
2865  * Returns bary center for given element
2866  */
2867 //=============================================================================
2868
2869 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
2870 {
2871   SMESH::double_array_var aResult = new SMESH::double_array();
2872   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2873   if ( aSMESHDS_Mesh == NULL )
2874     return aResult._retn();
2875
2876   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2877   if(!elem)
2878     return aResult._retn();
2879
2880   if(elem->GetType()==SMDSAbs_Volume) {
2881     SMDS_VolumeTool aTool;
2882     if(aTool.Set(elem)) {
2883       aResult->length(3);
2884       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
2885         aResult->length(0);
2886     }
2887   }
2888   else {
2889     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
2890     int nbn = 0;
2891     double x=0., y=0., z=0.;
2892     for(; anIt->more(); ) {
2893       nbn++;
2894       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
2895       x += aNode->X();
2896       y += aNode->Y();
2897       z += aNode->Z();
2898     }
2899     if(nbn>0) {
2900       // add coordinates
2901       aResult->length(3);
2902       aResult[0] = x/nbn;
2903       aResult[1] = y/nbn;
2904       aResult[2] = z/nbn;
2905     }
2906   }
2907
2908   return aResult._retn();
2909 }
2910
2911
2912 //=============================================================================
2913 /*!
2914  * Create and publish group servants if any groups were imported or created anyhow
2915  */
2916 //=============================================================================
2917
2918 void SMESH_Mesh_i::CreateGroupServants() 
2919 {
2920   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
2921
2922   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
2923   while ( groupIt->more() )
2924   {
2925     ::SMESH_Group* group = groupIt->next();
2926     int            anId = group->GetGroupDS()->GetID();
2927
2928     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
2929     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
2930       continue;
2931
2932     SMESH_GroupBase_i* aGroupImpl;
2933     TopoDS_Shape       shape;
2934     if ( SMESHDS_GroupOnGeom* groupOnGeom =
2935          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
2936     {
2937       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
2938       shape      = groupOnGeom->GetShape();
2939     }
2940     else {
2941       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2942     }
2943
2944     // To ensure correct mapping of servant and correct reference counting in GenericObj_i
2945     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
2946     aGroupImpl->Register();
2947
2948     SMESH::SMESH_GroupBase_var groupVar =
2949       SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
2950     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
2951
2952     // register CORBA object for persistence
2953     int nextId = _gen_i->RegisterObject( groupVar );
2954     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
2955
2956     // publishing of the groups in the study
2957     if ( !aStudy->_is_nil() ) {
2958       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
2959       _gen_i->PublishGroup( aStudy, _this(), groupVar, shapeVar, groupVar->GetName());
2960     }
2961   }
2962 }
2963
2964 //=============================================================================
2965 /*!
2966  * \brief Return groups cantained in _mapGroups by their IDs
2967  */
2968 //=============================================================================
2969
2970 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
2971 {
2972   int nbGroups = groupIDs.size();
2973   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
2974   aList->length( nbGroups );
2975
2976   list<int>::const_iterator ids = groupIDs.begin();
2977   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
2978   {
2979     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
2980     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
2981       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
2982   }
2983   aList->length( nbGroups );
2984   return aList._retn();
2985 }
2986
2987 //=============================================================================
2988 /*!
2989  * \brief Return information about imported file
2990  */
2991 //=============================================================================
2992
2993 SALOME_MED::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
2994 {
2995   SALOME_MED::MedFileInfo_var res( myFileInfo );
2996   if ( !res.operator->() ) {
2997     res = new SALOME_MED::MedFileInfo;
2998     res->fileName = "";
2999     res->fileSize = res->major = res->minor = res->release = -1;
3000   }
3001   return res._retn();
3002 }