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