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