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