Salome HOME
877a0170a29853be4ab3e0cdb13f41a7ede97762
[modules/smesh.git] / src / SMESH_I / SMESH_Mesh_i.cxx
1 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //
23 //
24 //  File   : SMESH_Mesh_i.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SMESH
27 //  $Header$
28
29 #include "SMESH_Mesh_i.hxx"
30
31 #include "SMESH_Filter_i.hxx"
32 #include "SMESH_Gen_i.hxx"
33 #include "SMESH_Group_i.hxx"
34 #include "SMESH_MEDMesh_i.hxx"
35 #include "SMESH_MeshEditor_i.hxx"
36 #include "SMESH_PythonDump.hxx"
37 #include "SMESH_subMesh_i.hxx"
38
39 #include "DriverMED_R_SMESHDS_Mesh.h"
40 #include "SMDS_VolumeTool.hxx"
41 #include "SMESHDS_Command.hxx"
42 #include "SMESHDS_CommandType.hxx"
43 #include "SMESHDS_GroupOnGeom.hxx"
44 #include "SMESH_Group.hxx"
45 #include "SMESH_MeshEditor.hxx"
46 #include "SMESH_MesherHelper.hxx"
47 #include "SMDS_EdgePosition.hxx"
48 #include "SMDS_FacePosition.hxx"
49
50 #include "OpUtil.hxx"
51 #include "SALOME_NamingService.hxx"
52 #include "Utils_CorbaException.hxx"
53 #include "Utils_ExceptHandlers.hxx"
54 #include "Utils_SINGLETON.hxx"
55 #include "utilities.h"
56
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_Explorer.hxx>
68 #include <TopoDS_Compound.hxx>
69
70 // STL Includes
71 #include <string>
72 #include <iostream>
73 #include <sstream>
74
75 #ifdef _DEBUG_
76 static int MYDEBUG = 0;
77 #else
78 static int MYDEBUG = 0;
79 #endif
80
81 using namespace std;
82 using SMESH::TPythonDump;
83
84 int SMESH_Mesh_i::myIdGenerator = 0;
85
86
87
88 //=============================================================================
89 /*!
90  *  Constructor
91  */
92 //=============================================================================
93
94 SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
95                             SMESH_Gen_i*            gen_i,
96                             CORBA::Long studyId )
97 : SALOME::GenericObj_i( thePOA )
98 {
99   MESSAGE("SMESH_Mesh_i");
100   _impl = NULL;
101   _gen_i = gen_i;
102   _id = myIdGenerator++;
103   _studyId = studyId;
104   thePOA->activate_object( this );
105 }
106
107 //=============================================================================
108 /*!
109  *  Destructor
110  */
111 //=============================================================================
112
113 SMESH_Mesh_i::~SMESH_Mesh_i()
114 {
115   INFOS("~SMESH_Mesh_i");
116   map<int, SMESH::SMESH_GroupBase_ptr>::iterator it;
117   for ( it = _mapGroups.begin(); it != _mapGroups.end(); it++ ) {
118     SMESH_GroupBase_i* aGroup = dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( it->second ).in() );
119     if ( aGroup ) {
120
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 }
129
130 //=============================================================================
131 /*!
132  *  SetShape
133  *
134  *  Associates <this> mesh with <theShape> and puts a reference
135  *  to <theShape> into the current study;
136  *  the previous shape is substituted by the new one.
137  */
138 //=============================================================================
139
140 void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
141     throw (SALOME::SALOME_Exception)
142 {
143   Unexpect aCatch(SALOME_SalomeException);
144   try {
145     _impl->ShapeToMesh( _gen_i->GeomObjectToShape( theShapeObject ));
146   }
147   catch(SALOME_Exception & S_ex) {
148     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
149   }
150 }
151
152 //================================================================================
153 /*!
154  * \brief return true if mesh has a shape to build a shape on
155  */
156 //================================================================================
157
158 CORBA::Boolean SMESH_Mesh_i::HasShapeToMesh()
159   throw (SALOME::SALOME_Exception)
160 {
161   Unexpect aCatch(SALOME_SalomeException);
162   bool res = false;
163   try {
164     res = _impl->HasShapeToMesh();
165   }
166   catch(SALOME_Exception & S_ex) {
167     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
168   }
169   return res;
170 }
171
172 //=======================================================================
173 //function : GetShapeToMesh
174 //purpose  :
175 //=======================================================================
176
177 GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
178     throw (SALOME::SALOME_Exception)
179 {
180   Unexpect aCatch(SALOME_SalomeException);
181   GEOM::GEOM_Object_var aShapeObj;
182   try {
183     TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
184     if ( !S.IsNull() )
185       aShapeObj = _gen_i->ShapeToGeomObject( S );
186   }
187   catch(SALOME_Exception & S_ex) {
188     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
189   }
190   return aShapeObj._retn();
191 }
192
193 //=============================================================================
194 /*!
195  *
196  */
197 //=============================================================================
198
199 static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
200 {
201   SMESH::DriverMED_ReadStatus res;
202   switch (theStatus)
203   {
204   case DriverMED_R_SMESHDS_Mesh::DRS_OK:
205     res = SMESH::DRS_OK; break;
206   case DriverMED_R_SMESHDS_Mesh::DRS_EMPTY:
207     res = SMESH::DRS_EMPTY; break;
208   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_RENUMBER:
209     res = SMESH::DRS_WARN_RENUMBER; break;
210   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
211     res = SMESH::DRS_WARN_SKIP_ELEM; break;
212   case DriverMED_R_SMESHDS_Mesh::DRS_FAIL:
213   default:
214     res = SMESH::DRS_FAIL; break;
215   }
216   return res;
217 }
218
219 //=============================================================================
220 /*!
221  *  ImportMEDFile
222  *
223  *  Imports mesh data from MED file
224  */
225 //=============================================================================
226
227 SMESH::DriverMED_ReadStatus
228 SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
229   throw ( SALOME::SALOME_Exception )
230 {
231   Unexpect aCatch(SALOME_SalomeException);
232   int status;
233   try {
234     status = _impl->MEDToMesh( theFileName, theMeshName );
235   }
236   catch( SALOME_Exception& S_ex ) {
237     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
238   }
239   catch ( ... ) {
240     THROW_SALOME_CORBA_EXCEPTION("ImportMEDFile(): unknown exception", SALOME::BAD_PARAM);
241   }
242
243   CreateGroupServants();
244
245   return ConvertDriverMEDReadStatus(status);
246 }
247
248 //=============================================================================
249 /*!
250  *  ImportUNVFile
251  *
252  *  Imports mesh data from MED file
253  */
254 //=============================================================================
255
256 int SMESH_Mesh_i::ImportUNVFile( const char* theFileName )
257   throw ( SALOME::SALOME_Exception )
258 {
259   // Read mesh with name = <theMeshName> into SMESH_Mesh
260   _impl->UNVToMesh( theFileName );
261
262   CreateGroupServants();
263
264   return 1;
265 }
266
267 //=============================================================================
268 /*!
269  *  ImportSTLFile
270  *
271  *  Imports mesh data from STL file
272  */
273 //=============================================================================
274 int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
275   throw ( SALOME::SALOME_Exception )
276 {
277   // Read mesh with name = <theMeshName> into SMESH_Mesh
278   _impl->STLToMesh( theFileName );
279
280   return 1;
281 }
282
283 //=============================================================================
284 /*!
285  *  importMEDFile
286  *
287  *  Imports mesh data from MED file
288  */
289 //=============================================================================
290
291 // int SMESH_Mesh_i::importMEDFile( const char* theFileName, const char* theMeshName )
292 // {
293 //   // Read mesh with name = <theMeshName> and all its groups into SMESH_Mesh
294 //   int status = _impl->MEDToMesh( theFileName, theMeshName );
295 //   CreateGroupServants();
296
297 //   return status;
298 // }
299
300 //=============================================================================
301 /*!
302  *
303  */
304 //=============================================================================
305
306 #define RETURNCASE(hyp_stat) case SMESH_Hypothesis::hyp_stat: return SMESH::hyp_stat;
307
308 SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
309                          (SMESH_Hypothesis::Hypothesis_Status theStatus)
310 {
311   switch (theStatus) {
312   RETURNCASE( HYP_OK            );
313   RETURNCASE( HYP_MISSING       );
314   RETURNCASE( HYP_CONCURENT     );
315   RETURNCASE( HYP_BAD_PARAMETER );
316   RETURNCASE( HYP_HIDDEN_ALGO   );
317   RETURNCASE( HYP_HIDING_ALGO   );
318   RETURNCASE( HYP_UNKNOWN_FATAL );
319   RETURNCASE( HYP_INCOMPATIBLE  );
320   RETURNCASE( HYP_NOTCONFORM    );
321   RETURNCASE( HYP_ALREADY_EXIST );
322   RETURNCASE( HYP_BAD_DIM       );
323   RETURNCASE( HYP_BAD_SUBSHAPE  );
324   RETURNCASE( HYP_BAD_GEOMETRY  );
325   default:;
326   }
327   return SMESH::HYP_UNKNOWN_FATAL;
328 }
329
330 //=============================================================================
331 /*!
332  *  AddHypothesis
333  *
334  *  calls internal addHypothesis() and then adds a reference to <anHyp> under
335  *  the SObject actually having a reference to <aSubShape>.
336  *  NB: For this method to work, it is necessary to add a reference to sub-shape first.
337  */
338 //=============================================================================
339
340 SMESH::Hypothesis_Status SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
341                                                      SMESH::SMESH_Hypothesis_ptr anHyp)
342   throw(SALOME::SALOME_Exception)
343 {
344   Unexpect aCatch(SALOME_SalomeException);
345   SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShapeObject, anHyp );
346
347   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
348     _gen_i->AddHypothesisToShape(_gen_i->GetCurrentStudy(), _this(),
349                                  aSubShapeObject, anHyp );
350
351   if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
352
353   // Update Python script
354   TPythonDump() << "status = " << _this() << ".AddHypothesis( "
355                 << aSubShapeObject << ", " << anHyp << " )";
356
357   return ConvertHypothesisStatus(status);
358 }
359
360 //=============================================================================
361 /*!
362  *
363  */
364 //=============================================================================
365
366 SMESH_Hypothesis::Hypothesis_Status
367   SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
368                               SMESH::SMESH_Hypothesis_ptr anHyp)
369 {
370   if(MYDEBUG) MESSAGE("addHypothesis");
371
372   if (CORBA::is_nil(aSubShapeObject))
373     THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
374                                  SALOME::BAD_PARAM);
375
376   SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp);
377   if (CORBA::is_nil(myHyp))
378     THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",
379                                  SALOME::BAD_PARAM);
380
381   SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
382   try
383   {
384     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject);
385     int hypId = myHyp->GetId();
386     status = _impl->AddHypothesis(myLocSubShape, hypId);
387     if ( !SMESH_Hypothesis::IsStatusFatal(status) ) {
388       _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( myHyp );
389       // assure there is a corresponding submesh
390       if ( !_impl->IsMainShape( myLocSubShape )) {
391         int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
392         if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
393           createSubMesh( aSubShapeObject );
394       }
395     }
396   }
397   catch(SALOME_Exception & S_ex)
398   {
399     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
400   }
401   return status;
402 }
403
404 //=============================================================================
405 /*!
406  *
407  */
408 //=============================================================================
409
410 SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
411                                                         SMESH::SMESH_Hypothesis_ptr anHyp)
412      throw(SALOME::SALOME_Exception)
413 {
414   Unexpect aCatch(SALOME_SalomeException);
415   SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShapeObject, anHyp );
416
417   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
418     _gen_i->RemoveHypothesisFromShape(_gen_i->GetCurrentStudy(), _this(),
419                                       aSubShapeObject, anHyp );
420
421   // Update Python script
422   TPythonDump() << "status = " << _this() << ".RemoveHypothesis( "
423                 << aSubShapeObject << ", " << anHyp << " )";
424
425   return ConvertHypothesisStatus(status);
426 }
427
428 //=============================================================================
429 /*!
430  *
431  */
432 //=============================================================================
433
434 SMESH_Hypothesis::Hypothesis_Status SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
435                                  SMESH::SMESH_Hypothesis_ptr anHyp)
436 {
437         if(MYDEBUG) MESSAGE("removeHypothesis()");
438         // **** proposer liste de subShape (selection multiple)
439
440         if (CORBA::is_nil(aSubShapeObject))
441                 THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
442                         SALOME::BAD_PARAM);
443
444         SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp);
445         if (CORBA::is_nil(myHyp))
446           THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",
447                         SALOME::BAD_PARAM);
448
449         SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
450         try
451         {
452                 TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
453                 int hypId = myHyp->GetId();
454                 status = _impl->RemoveHypothesis(myLocSubShape, hypId);
455                 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
456                   _mapHypo.erase( hypId );
457         }
458         catch(SALOME_Exception & S_ex)
459         {
460                 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
461         }
462         return status;
463 }
464
465 //=============================================================================
466 /*!
467  *
468  */
469 //=============================================================================
470
471 SMESH::ListOfHypothesis *
472         SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShapeObject)
473 throw(SALOME::SALOME_Exception)
474 {
475   Unexpect aCatch(SALOME_SalomeException);
476   if (MYDEBUG) MESSAGE("GetHypothesisList");
477   if (CORBA::is_nil(aSubShapeObject))
478     THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
479                                  SALOME::BAD_PARAM);
480
481   SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
482
483   try {
484     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
485     const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
486     int i = 0, n = aLocalList.size();
487     aList->length( n );
488
489     for ( list<const SMESHDS_Hypothesis*>::const_iterator anIt = aLocalList.begin(); i < n && anIt != aLocalList.end(); anIt++ ) {
490       SMESHDS_Hypothesis* aHyp = (SMESHDS_Hypothesis*)(*anIt);
491       if ( _mapHypo.find( aHyp->GetID() ) != _mapHypo.end() )
492         aList[i++] = SMESH::SMESH_Hypothesis::_narrow( _mapHypo[aHyp->GetID()] );
493     }
494
495     aList->length( i );
496   }
497   catch(SALOME_Exception & S_ex) {
498     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
499   }
500
501   return aList._retn();
502 }
503
504 //=============================================================================
505 /*!
506  *
507  */
508 //=============================================================================
509 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShapeObject,
510                                                   const char*           theName )
511      throw(SALOME::SALOME_Exception)
512 {
513   Unexpect aCatch(SALOME_SalomeException);
514   MESSAGE("SMESH_Mesh_i::GetSubMesh");
515   if (CORBA::is_nil(aSubShapeObject))
516     THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
517                                  SALOME::BAD_PARAM);
518
519   SMESH::SMESH_subMesh_var subMesh;
520   SMESH::SMESH_Mesh_var    aMesh = SMESH::SMESH_Mesh::_narrow(_this());
521   try {
522     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
523
524     //Get or Create the SMESH_subMesh object implementation
525
526     int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
527     subMesh = getSubMesh( subMeshId );
528
529     // create a new subMesh object servant if there is none for the shape
530     if ( subMesh->_is_nil() )
531       subMesh = createSubMesh( aSubShapeObject );
532
533     if ( _gen_i->CanPublishInStudy( subMesh )) {
534       SALOMEDS::SObject_var aSO =
535         _gen_i->PublishSubMesh(_gen_i->GetCurrentStudy(), aMesh,
536                                subMesh, aSubShapeObject, theName );
537       if ( !aSO->_is_nil()) {
538         // Update Python script
539         TPythonDump() << aSO << " = " << _this() << ".GetSubMesh( "
540                       << aSubShapeObject << ", '" << theName << "' )";
541       }
542     }
543   }
544   catch(SALOME_Exception & S_ex) {
545     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
546   }
547   return subMesh._retn();
548 }
549
550 //=============================================================================
551 /*!
552  *
553  */
554 //=============================================================================
555
556 void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
557      throw (SALOME::SALOME_Exception)
558 {
559   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::RemoveSubMesh");
560   if ( theSubMesh->_is_nil() )
561     return;
562
563   GEOM::GEOM_Object_var aSubShapeObject;
564   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
565   if ( !aStudy->_is_nil() )  {
566     // Remove submesh's SObject
567     SALOMEDS::SObject_var anSO = _gen_i->ObjectToSObject( aStudy, theSubMesh );
568     if ( !anSO->_is_nil() ) {
569       long aTag = SMESH_Gen_i::GetRefOnShapeTag();
570       SALOMEDS::SObject_var anObj, aRef;
571       if ( anSO->FindSubObject( aTag, anObj ) && anObj->ReferencedObject( aRef ) )
572         aSubShapeObject = GEOM::GEOM_Object::_narrow( aRef->GetObject() );
573
574       aStudy->NewBuilder()->RemoveObjectWithChildren( anSO );
575
576       // Update Python script
577       TPythonDump() << _this() << ".RemoveSubMesh( " << anSO << " )";
578     }
579   }
580
581   removeSubMesh( theSubMesh, aSubShapeObject.in() );
582 }
583
584 //=============================================================================
585 /*!
586  *  ElementTypeString
587  */
588 //=============================================================================
589 #define CASE2STRING(enum) case SMESH::enum: return "SMESH."#enum;
590 inline TCollection_AsciiString ElementTypeString (SMESH::ElementType theElemType)
591 {
592   switch (theElemType) {
593     CASE2STRING( ALL );
594     CASE2STRING( NODE );
595     CASE2STRING( EDGE );
596     CASE2STRING( FACE );
597     CASE2STRING( VOLUME );
598   default:;
599   }
600   return "";
601 }
602
603 //=============================================================================
604 /*!
605  *
606  */
607 //=============================================================================
608
609 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType,
610                                                  const char*         theName )
611      throw(SALOME::SALOME_Exception)
612 {
613   Unexpect aCatch(SALOME_SalomeException);
614   SMESH::SMESH_Group_var aNewGroup =
615     SMESH::SMESH_Group::_narrow( createGroup( theElemType, theName ));
616
617   if ( _gen_i->CanPublishInStudy( aNewGroup ) ) {
618     SALOMEDS::SObject_var aSO =
619       _gen_i->PublishGroup(_gen_i->GetCurrentStudy(), _this(),
620                            aNewGroup, GEOM::GEOM_Object::_nil(), theName);
621     if ( !aSO->_is_nil()) {
622       // Update Python script
623       TPythonDump() << aSO << " = " << _this() << ".CreateGroup( "
624                     << ElementTypeString(theElemType) << ", '" << theName << "' )";
625     }
626   }
627   return aNewGroup._retn();
628 }
629
630
631 //=============================================================================
632 /*!
633  *
634  */
635 //=============================================================================
636 SMESH::SMESH_GroupOnGeom_ptr SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType    theElemType,
637                                                                 const char*           theName,
638                                                                 GEOM::GEOM_Object_ptr theGeomObj)
639      throw(SALOME::SALOME_Exception)
640 {
641   Unexpect aCatch(SALOME_SalomeException);
642   SMESH::SMESH_GroupOnGeom_var aNewGroup;
643
644   TopoDS_Shape aShape = _gen_i->GeomObjectToShape( theGeomObj );
645   if ( !aShape.IsNull() ) {
646     aNewGroup = SMESH::SMESH_GroupOnGeom::_narrow
647       ( createGroup( theElemType, theName, aShape ));
648     if ( _gen_i->CanPublishInStudy( aNewGroup ) ) {
649       SALOMEDS::SObject_var aSO =
650         _gen_i->PublishGroup(_gen_i->GetCurrentStudy(), _this(),
651                              aNewGroup, theGeomObj, theName);
652       if ( !aSO->_is_nil()) {
653         // Update Python script
654         TPythonDump() << aSO << " = " << _this() << ".CreateGroupFromGEOM("
655                       << ElementTypeString(theElemType) << ", '" << theName << "', "
656                       << theGeomObj << " )";
657       }
658     }
659   }
660
661   return aNewGroup._retn();
662 }
663
664 //=============================================================================
665 /*!
666  *
667  */
668 //=============================================================================
669
670 void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
671      throw (SALOME::SALOME_Exception)
672 {
673   if ( theGroup->_is_nil() )
674     return;
675
676   SMESH_GroupBase_i* aGroup =
677     dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
678   if ( !aGroup )
679     return;
680
681   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
682   if ( !aStudy->_is_nil() )  {
683     SALOMEDS::SObject_var aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
684
685     if ( !aGroupSO->_is_nil() ) {
686       // Update Python script
687       TPythonDump() << _this() << ".RemoveGroup( " << aGroupSO << " )";
688
689       // Remove group's SObject
690       aStudy->NewBuilder()->RemoveObject( aGroupSO );
691     }
692   }
693
694   // Remove the group from SMESH data structures
695   removeGroup( aGroup->GetLocalID() );
696 }
697
698 //=============================================================================
699 /*! RemoveGroupWithContents
700  *  Remove group with its contents
701  */
702 //=============================================================================
703 void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup )
704   throw (SALOME::SALOME_Exception)
705 {
706   if ( theGroup->_is_nil() )
707     return;
708
709   SMESH_GroupBase_i* aGroup =
710     dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
711   if ( !aGroup )
712     return;
713
714   SMESH::long_array_var anIds = aGroup->GetListOfID();
715   SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
716
717   // Update Python script
718   TPythonDump() << _this() << ".RemoveGroupWithContents( " << theGroup << " )";
719
720   // Remove contents
721   if ( aGroup->GetType() == SMESH::NODE )
722     aMeshEditor->RemoveNodes( anIds );
723   else
724     aMeshEditor->RemoveElements( anIds );
725
726   // Remove group
727   RemoveGroup( theGroup );
728
729   // Clear python lines, created by RemoveNodes/Elements() and RemoveGroup()
730   _gen_i->RemoveLastFromPythonScript(_gen_i->GetCurrentStudy()->StudyId());
731   _gen_i->RemoveLastFromPythonScript(_gen_i->GetCurrentStudy()->StudyId());
732 }
733
734
735 //================================================================================
736 /*!
737  * \brief Get the list of groups existing in the mesh
738   * \retval SMESH::ListOfGroups * - list of groups
739  */
740 //================================================================================
741
742 SMESH::ListOfGroups * SMESH_Mesh_i::GetGroups() throw(SALOME::SALOME_Exception)
743 {
744   Unexpect aCatch(SALOME_SalomeException);
745   if (MYDEBUG) MESSAGE("GetGroups");
746
747   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
748
749   // Python Dump
750   TPythonDump aPythonDump;
751   if ( !_mapGroups.empty() ) // (IMP13463) avoid "SyntaxError: can't assign to []"
752     aPythonDump << "[ ";
753
754   try {
755     aList->length( _mapGroups.size() );
756     int i = 0;
757     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
758     for ( ; it != _mapGroups.end(); it++ ) {
759       if ( CORBA::is_nil( it->second )) continue;
760       aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
761       // Python Dump
762       if (i > 1) aPythonDump << ", ";
763       aPythonDump << it->second;
764     }
765     aList->length( i );
766   }
767   catch(SALOME_Exception & S_ex) {
768     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
769   }
770
771   // Update Python script
772   if ( !_mapGroups.empty() ) // (IMP13463) avoid "SyntaxError: can't assign to []"
773     aPythonDump << " ] = " << _this() << ".GetGroups()";
774
775   return aList._retn();
776 }
777 //=============================================================================
778 /*!
779  *  Get number of groups existing in the mesh
780  */
781 //=============================================================================
782
783 CORBA::Long SMESH_Mesh_i::NbGroups() throw (SALOME::SALOME_Exception)
784 {
785   Unexpect aCatch(SALOME_SalomeException);
786   return _mapGroups.size();
787 }
788
789 //=============================================================================
790 /*! UnionGroups
791  *  New group is created. All mesh elements that are
792  *  present in initial groups are added to the new one
793  */
794 //=============================================================================
795 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
796                                                   SMESH::SMESH_GroupBase_ptr theGroup2,
797                                                   const char* theName )
798   throw (SALOME::SALOME_Exception)
799 {
800   try
801   {
802     if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
803          theGroup1->GetType() != theGroup2->GetType() )
804       return SMESH::SMESH_Group::_nil();
805
806     // Create Union
807     SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
808     if ( aResGrp->_is_nil() )
809       return SMESH::SMESH_Group::_nil();
810
811     SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
812     SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
813
814     TColStd_MapOfInteger aResMap;
815
816     for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
817       aResMap.Add( anIds1[ i1 ] );
818
819     for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
820       aResMap.Add( anIds2[ i2 ] );
821
822     SMESH::long_array_var aResIds = new SMESH::long_array;
823     aResIds->length( aResMap.Extent() );
824
825     int resI = 0;
826     TColStd_MapIteratorOfMapOfInteger anIter( aResMap );
827     for( ; anIter.More(); anIter.Next() )
828       aResIds[ resI++ ] = anIter.Key();
829
830     aResGrp->Add( aResIds );
831
832     // Clear python lines, created by CreateGroup() and Add()
833     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
834     _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
835     _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
836
837     // Update Python script
838     TPythonDump() << aResGrp << " = " << _this() << ".UnionGroups( "
839                   << theGroup1 << ", " << theGroup2 << ", '"
840                   << theName << "' )";
841
842     return aResGrp._retn();
843   }
844   catch( ... )
845   {
846     return SMESH::SMESH_Group::_nil();
847   }
848 }
849
850 //=============================================================================
851 /*! IntersectGroups
852  *  New group is created. All mesh elements that are
853  *  present in both initial groups are added to the new one.
854  */
855 //=============================================================================
856 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
857                                                       SMESH::SMESH_GroupBase_ptr theGroup2,
858                                                       const char* theName )
859   throw (SALOME::SALOME_Exception)
860 {
861   if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
862        theGroup1->GetType() != theGroup2->GetType() )
863     return SMESH::SMESH_Group::_nil();
864
865   // Create Intersection
866   SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
867   if ( aResGrp->_is_nil() )
868     return aResGrp;
869
870   SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
871   SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
872
873   TColStd_MapOfInteger aMap1;
874
875   for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
876     aMap1.Add( anIds1[ i1 ] );
877
878   TColStd_SequenceOfInteger aSeq;
879
880   for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
881     if ( aMap1.Contains( anIds2[ i2 ] ) )
882       aSeq.Append( anIds2[ i2 ] );
883
884   SMESH::long_array_var aResIds = new SMESH::long_array;
885   aResIds->length( aSeq.Length() );
886
887   for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
888     aResIds[ resI ] = aSeq( resI + 1 );
889
890   aResGrp->Add( aResIds );
891
892   // Clear python lines, created by CreateGroup() and Add()
893   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
894   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
895   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
896
897   // Update Python script
898   TPythonDump() << aResGrp << " = " << _this() << ".IntersectGroups( "
899                 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
900
901   return aResGrp._retn();
902 }
903
904 //=============================================================================
905 /*! CutGroups
906  *  New group is created. All mesh elements that are present in
907  *  main group but do not present in tool group are added to the new one
908  */
909 //=============================================================================
910 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
911                                                 SMESH::SMESH_GroupBase_ptr theGroup2,
912                                                 const char* theName )
913   throw (SALOME::SALOME_Exception)
914 {
915   if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
916        theGroup1->GetType() != theGroup2->GetType() )
917     return SMESH::SMESH_Group::_nil();
918
919   // Perform Cutting
920   SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
921   if ( aResGrp->_is_nil() )
922     return aResGrp;
923
924   SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
925   SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
926
927   TColStd_MapOfInteger aMap2;
928
929   for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
930     aMap2.Add( anIds2[ i2 ] );
931
932
933   TColStd_SequenceOfInteger aSeq;
934   for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
935     if ( !aMap2.Contains( anIds1[ i1 ] ) )
936       aSeq.Append( anIds1[ i1 ] );
937
938   SMESH::long_array_var aResIds = new SMESH::long_array;
939   aResIds->length( aSeq.Length() );
940
941   for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
942     aResIds[ resI ] = aSeq( resI + 1 );
943
944   aResGrp->Add( aResIds );
945
946   // Clear python lines, created by CreateGroup() and Add()
947   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
948   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
949   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
950
951   // Update Python script
952   TPythonDump() << aResGrp << " = " << _this() << ".CutGroups( "
953                 << theGroup1 << ", " << theGroup2 << ", '"
954                 << theName << "' )";
955
956   return aResGrp._retn();
957 }
958
959 //================================================================================
960 /*!
961  * \brief Return group items of a group present in a study
962  */
963 //================================================================================
964
965 static GEOM::GEOM_Object_ptr getGroupItemsFromStudy(CORBA::Object_ptr    theMesh,
966                                                     SMESH_Gen_i*         theGen,
967                                                     list<TopoDS_Shape> & theItems)
968 {
969   GEOM::GEOM_Object_var groupObj;
970   SALOMEDS::Study_var  study = theGen->GetCurrentStudy();
971   GEOM::GEOM_Gen_var geomGen = theGen->GetGeomEngine();
972   if ( study->_is_nil() || geomGen->_is_nil() )
973     return groupObj._retn();
974   
975   GEOM::GEOM_IGroupOperations_var groupOp =
976     geomGen->GetIGroupOperations( theGen->GetCurrentStudyID() );
977   GEOM::GEOM_IShapesOperations_var shapeOp =
978     geomGen->GetIShapesOperations( theGen->GetCurrentStudyID() );
979
980   SALOMEDS::SObject_var meshOS = theGen->ObjectToSObject(study, theMesh);
981   if ( meshOS->_is_nil() || groupOp->_is_nil() || shapeOp->_is_nil() )
982     return groupObj._retn();
983   SALOMEDS::SObject_var fatherSO = meshOS->GetFather();
984   if ( fatherSO->_is_nil() || fatherSO->Tag() != theGen->GetSubMeshOnCompoundTag() )
985     return groupObj._retn(); // keep only submeshes on groups
986
987   SALOMEDS::ChildIterator_var anIter = study->NewChildIterator(meshOS);
988   if ( anIter->_is_nil() ) return groupObj._retn();
989   for ( ; anIter->More(); anIter->Next())
990   {
991     SALOMEDS::SObject_var aSObject = anIter->Value();
992     SALOMEDS::SObject_var aRefSO;
993     if ( !aSObject->_is_nil() && aSObject->ReferencedObject(aRefSO) )
994     {
995       groupObj = GEOM::GEOM_Object::_narrow(aRefSO->GetObject());
996       if ( groupObj->_is_nil() ) break;
997       GEOM::ListOfLong_var  ids = groupOp->GetObjects( groupObj );
998       GEOM::GEOM_Object_var mainShape = groupObj->GetMainShape();
999       for ( int i = 0; i < ids->length(); ++i ) {
1000         GEOM::GEOM_Object_var subShape = shapeOp->GetSubShape( mainShape, ids[i] );
1001         TopoDS_Shape S = theGen->GeomObjectToShape( subShape );
1002         if ( !S.IsNull() )
1003           theItems.push_back( S );
1004       }
1005       break;
1006     }
1007   }
1008   return groupObj._retn();
1009 }
1010
1011 //=============================================================================
1012 /*!
1013  * \brief Update hypotheses assigned to geom groups if the latter change
1014  * 
1015  * NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
1016  */
1017 //=============================================================================
1018
1019 void SMESH_Mesh_i::CheckGeomGroupModif()
1020 {
1021   if ( !_impl->HasShapeToMesh() ) return;
1022
1023   SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1024   if ( study->_is_nil() ) return;
1025
1026   // check if items of groups changed
1027   map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
1028   for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
1029   {
1030     const TopoDS_Shape & oldGroupShape = i_sm->second->GetSubShape();
1031     SMESHDS_SubMesh * oldDS = i_sm->second->GetSubMeshDS();
1032     if ( !oldDS /*|| !oldDS->IsComplexSubmesh()*/ )
1033       continue;
1034     int oldID = i_sm->first;
1035     map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldID );
1036     if ( i_smIor == _mapSubMeshIor.end() )
1037       continue;
1038     list< TopoDS_Shape> newItems;
1039     GEOM::GEOM_Object_var groupObj = getGroupItemsFromStudy ( i_smIor->second, _gen_i, newItems );
1040     if ( groupObj->_is_nil() )
1041       continue;
1042
1043     int nbOldItems = oldDS->IsComplexSubmesh() ? oldDS->NbSubMeshes() : 1;
1044     int nbNewItems = newItems.size();
1045     bool groupChanged = ( nbOldItems != nbNewItems);
1046     if ( !groupChanged ) {
1047       if ( !oldDS->IsComplexSubmesh() ) { // old group has one item
1048         groupChanged = ( oldGroupShape != newItems.front() );
1049       }
1050       else {
1051         list<TopoDS_Shape>::iterator item = newItems.begin();
1052         for ( ; item != newItems.end() && !groupChanged; ++item )
1053         {
1054           SMESHDS_SubMesh * itemDS = _impl->GetMeshDS()->MeshElements( *item );
1055           groupChanged = ( !itemDS || !oldDS->ContainsSubMesh( itemDS ));
1056         }
1057       }
1058     }
1059     // update hypotheses and submeshes if necessary
1060     if ( groupChanged )
1061     {
1062       // get a new group shape
1063       GEOM_Client* geomClient = _gen_i->GetShapeReader();
1064       if ( !geomClient ) continue;
1065       TCollection_AsciiString groupIOR = _gen_i->GetGeomEngine()->GetStringFromIOR( groupObj );
1066       geomClient->RemoveShapeFromBuffer( groupIOR );
1067       TopoDS_Shape newGroupShape = _gen_i->GeomObjectToShape( groupObj );
1068       // update hypotheses
1069       list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldGroupShape);
1070       list <const SMESHDS_Hypothesis * >::iterator hypIt;
1071       for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
1072       {
1073         _impl->RemoveHypothesis( oldGroupShape, (*hypIt)->GetID());
1074         _impl->AddHypothesis   ( newGroupShape, (*hypIt)->GetID());
1075       }
1076       // care of submeshes
1077       SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newGroupShape );
1078       int newID = newSubmesh->GetId();
1079       if ( newID != oldID ) {
1080         _mapSubMesh   [ newID ] = newSubmesh;
1081         _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
1082         _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
1083         _mapSubMesh.erase   (oldID);
1084         _mapSubMesh_i.erase (oldID);
1085         _mapSubMeshIor.erase(oldID);
1086         _mapSubMesh_i [ newID ]->changeLocalId( newID );
1087       }
1088     }
1089   }
1090 }
1091
1092 //=============================================================================
1093 /*!
1094  *
1095  */
1096 //=============================================================================
1097
1098 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
1099 {
1100   if(MYDEBUG) MESSAGE( "createSubMesh" );
1101   TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
1102
1103   ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
1104   int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
1105   SMESH_subMesh_i *subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
1106   SMESH::SMESH_subMesh_var subMesh
1107     = SMESH::SMESH_subMesh::_narrow(subMeshServant->_this());
1108
1109   _mapSubMesh[subMeshId] = mySubMesh;
1110   _mapSubMesh_i[subMeshId] = subMeshServant;
1111   _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate(subMesh);
1112
1113   // register CORBA object for persistence
1114   int nextId = _gen_i->RegisterObject( subMesh );
1115   if(MYDEBUG) MESSAGE( "Add submesh to map with id = "<< nextId);
1116
1117   return subMesh._retn();
1118 }
1119
1120 //=======================================================================
1121 //function : getSubMesh
1122 //purpose  :
1123 //=======================================================================
1124
1125 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
1126 {
1127   map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
1128   if ( it == _mapSubMeshIor.end() )
1129     return SMESH::SMESH_subMesh::_nil();
1130
1131   return SMESH::SMESH_subMesh::_duplicate( (*it).second );
1132 }
1133
1134
1135 //=============================================================================
1136 /*!
1137  *
1138  */
1139 //=============================================================================
1140
1141 void SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
1142                                   GEOM::GEOM_Object_ptr    theSubShapeObject )
1143 {
1144   MESSAGE("SMESH_Mesh_i::removeSubMesh()");
1145   if ( theSubMesh->_is_nil() || theSubShapeObject->_is_nil() )
1146     return;
1147
1148   try {
1149     SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
1150     for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
1151       removeHypothesis( theSubShapeObject, aHypList[i] );
1152     }
1153   }
1154   catch( const SALOME::SALOME_Exception& ) {
1155     INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
1156   }
1157
1158   int subMeshId = theSubMesh->GetId();
1159
1160   _mapSubMesh.erase(subMeshId);
1161   _mapSubMesh_i.erase(subMeshId);
1162   _mapSubMeshIor.erase(subMeshId);
1163   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeSubMesh() completed");
1164 }
1165
1166 //=============================================================================
1167 /*!
1168  *
1169  */
1170 //=============================================================================
1171
1172 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType theElemType,
1173                                                       const char*         theName,
1174                                                       const TopoDS_Shape& theShape )
1175 {
1176   int anId;
1177   SMESH::SMESH_GroupBase_var aGroup;
1178   if ( _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName, anId, theShape )) {
1179     SMESH_GroupBase_i* aGroupImpl;
1180     if ( !theShape.IsNull() )
1181       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
1182     else
1183       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
1184
1185     // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1186     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
1187     aGroupImpl->Register();
1188     // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1189
1190     aGroup = SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
1191     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
1192
1193     // register CORBA object for persistence
1194     int nextId = _gen_i->RegisterObject( aGroup );
1195     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
1196   }
1197   return aGroup._retn();
1198 }
1199
1200 //=============================================================================
1201 /*!
1202  * SMESH_Mesh_i::removeGroup
1203  *
1204  * Should be called by ~SMESH_Group_i()
1205  */
1206 //=============================================================================
1207
1208 void SMESH_Mesh_i::removeGroup( const int theId )
1209 {
1210   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
1211   if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
1212     _mapGroups.erase( theId );
1213     _impl->RemoveGroup( theId );
1214   }
1215 }
1216
1217
1218 //=============================================================================
1219 /*!
1220  *
1221  */
1222 //=============================================================================
1223
1224 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
1225 throw(SALOME::SALOME_Exception)
1226 {
1227   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetLog");
1228
1229   SMESH::log_array_var aLog;
1230   try{
1231     list < SMESHDS_Command * >logDS = _impl->GetLog();
1232     aLog = new SMESH::log_array;
1233     int indexLog = 0;
1234     int lg = logDS.size();
1235     SCRUTE(lg);
1236     aLog->length(lg);
1237     list < SMESHDS_Command * >::iterator its = logDS.begin();
1238     while(its != logDS.end()){
1239       SMESHDS_Command *com = *its;
1240       int comType = com->GetType();
1241       //SCRUTE(comType);
1242       int lgcom = com->GetNumber();
1243       //SCRUTE(lgcom);
1244       const list < int >&intList = com->GetIndexes();
1245       int inum = intList.size();
1246       //SCRUTE(inum);
1247       list < int >::const_iterator ii = intList.begin();
1248       const list < double >&coordList = com->GetCoords();
1249       int rnum = coordList.size();
1250       //SCRUTE(rnum);
1251       list < double >::const_iterator ir = coordList.begin();
1252       aLog[indexLog].commandType = comType;
1253       aLog[indexLog].number = lgcom;
1254       aLog[indexLog].coords.length(rnum);
1255       aLog[indexLog].indexes.length(inum);
1256       for(int i = 0; i < rnum; i++){
1257         aLog[indexLog].coords[i] = *ir;
1258         //MESSAGE(" "<<i<<" "<<ir.Value());
1259         ir++;
1260       }
1261       for(int i = 0; i < inum; i++){
1262         aLog[indexLog].indexes[i] = *ii;
1263         //MESSAGE(" "<<i<<" "<<ii.Value());
1264         ii++;
1265       }
1266       indexLog++;
1267       its++;
1268     }
1269     if(clearAfterGet)
1270       _impl->ClearLog();
1271   }
1272   catch(SALOME_Exception & S_ex){
1273     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
1274   }
1275   return aLog._retn();
1276 }
1277
1278
1279 //=============================================================================
1280 /*!
1281  *
1282  */
1283 //=============================================================================
1284
1285 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
1286 {
1287   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::ClearLog");
1288   // ****
1289 }
1290
1291 //=============================================================================
1292 /*!
1293  *
1294  */
1295 //=============================================================================
1296
1297 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
1298 {
1299   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetId");
1300   return _id;
1301 }
1302
1303 //=============================================================================
1304 /*!
1305  *
1306  */
1307 //=============================================================================
1308
1309 CORBA::Long SMESH_Mesh_i::GetStudyId()throw(SALOME::SALOME_Exception)
1310 {
1311   return _studyId;
1312 }
1313
1314 //=============================================================================
1315 /*!
1316  *
1317  */
1318 //=============================================================================
1319
1320 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
1321 {
1322   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
1323   _impl = impl;
1324 }
1325
1326 //=============================================================================
1327 /*!
1328  *
1329  */
1330 //=============================================================================
1331
1332 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
1333 {
1334   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
1335   return *_impl;
1336 }
1337
1338 //=============================================================================
1339 /*!
1340  * Return mesh editor
1341  */
1342 //=============================================================================
1343
1344 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
1345 {
1346   // Create MeshEditor
1347   SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, false );
1348   SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
1349
1350   // Update Python script
1351   TPythonDump() << aMeshEditor << " = " << _this() << ".GetMeshEditor()";
1352
1353   return aMesh._retn();
1354 }
1355
1356 //=============================================================================
1357 /*!
1358  * Return mesh edition previewer
1359  */
1360 //=============================================================================
1361
1362 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
1363 {
1364   SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, true );
1365   SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
1366   return aMesh._retn();
1367 }
1368
1369 //=============================================================================
1370 /*!
1371  *  Export in different formats
1372  */
1373 //=============================================================================
1374
1375 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
1376 {
1377   return _impl->HasDuplicatedGroupNamesMED();
1378 }
1379
1380 static void PrepareForWriting (const char* file)
1381 {
1382   TCollection_AsciiString aFullName ((char*)file);
1383   OSD_Path aPath (aFullName);
1384   OSD_File aFile (aPath);
1385   if (aFile.Exists()) {
1386     // existing filesystem node
1387     if (aFile.KindOfFile() == OSD_FILE) {
1388       if (aFile.IsWriteable()) {
1389         aFile.Reset();
1390         aFile.Remove();
1391         if (aFile.Failed()) {
1392           TCollection_AsciiString msg ("File ");
1393           msg += aFullName + " cannot be replaced.";
1394           THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
1395         }
1396       } else {
1397         TCollection_AsciiString msg ("File ");
1398         msg += aFullName + " cannot be overwritten.";
1399         THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
1400       }
1401     } else {
1402       TCollection_AsciiString msg ("Location ");
1403       msg += aFullName + " is not a file.";
1404       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
1405     }
1406   } else {
1407     // nonexisting file; check if it can be created
1408     aFile.Reset();
1409     aFile.Build(OSD_WriteOnly, OSD_Protection());
1410     if (aFile.Failed()) {
1411       TCollection_AsciiString msg ("You cannot create the file ");
1412       msg += aFullName + ". Check the directory existance and access rights.";
1413       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
1414     } else {
1415       aFile.Close();
1416       aFile.Remove();
1417     }
1418   }
1419 }
1420
1421 void SMESH_Mesh_i::ExportToMED (const char* file,
1422                                 CORBA::Boolean auto_groups,
1423                                 SMESH::MED_VERSION theVersion)
1424   throw(SALOME::SALOME_Exception)
1425 {
1426   Unexpect aCatch(SALOME_SalomeException);
1427
1428   // Update Python script
1429   TPythonDump() << _this() << ".ExportToMED( '"
1430                 << file << "', " << auto_groups << ", " << theVersion << " )";
1431
1432   // Perform Export
1433   PrepareForWriting(file);
1434   char* aMeshName = "Mesh";
1435   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1436   if ( !aStudy->_is_nil() ) {
1437     SALOMEDS::SObject_var aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
1438     if ( !aMeshSO->_is_nil() ) {
1439       aMeshName = aMeshSO->GetName();
1440       //SCRUTE(file);
1441       //SCRUTE(aMeshName);
1442       //SCRUTE(aMeshSO->GetID());
1443
1444       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
1445       if ( !aStudy->GetProperties()->IsLocked() )
1446         {
1447         SALOMEDS::GenericAttribute_var anAttr;
1448         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
1449         SALOMEDS::AttributeExternalFileDef_var aFileName;
1450         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
1451         aFileName = SALOMEDS::AttributeExternalFileDef::_narrow(anAttr);
1452         ASSERT(!aFileName->_is_nil());
1453         aFileName->SetValue(file);
1454         SALOMEDS::AttributeFileType_var aFileType;
1455         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
1456         aFileType = SALOMEDS::AttributeFileType::_narrow(anAttr);
1457         ASSERT(!aFileType->_is_nil());
1458         aFileType->SetValue("FICHIERMED");
1459         }
1460     }
1461   }
1462   _impl->ExportMED( file, aMeshName, auto_groups, theVersion );
1463 }
1464
1465 void SMESH_Mesh_i::ExportMED (const char* file,
1466                               CORBA::Boolean auto_groups)
1467   throw(SALOME::SALOME_Exception)
1468 {
1469   ExportToMED(file,auto_groups,SMESH::MED_V2_1);
1470 }
1471
1472 void SMESH_Mesh_i::ExportDAT (const char *file)
1473   throw(SALOME::SALOME_Exception)
1474 {
1475   Unexpect aCatch(SALOME_SalomeException);
1476
1477   // Update Python script
1478   TPythonDump() << _this() << ".ExportDAT( '" << file << "' )";
1479
1480   // Perform Export
1481   PrepareForWriting(file);
1482   _impl->ExportDAT(file);
1483 }
1484
1485 void SMESH_Mesh_i::ExportUNV (const char *file)
1486   throw(SALOME::SALOME_Exception)
1487 {
1488   Unexpect aCatch(SALOME_SalomeException);
1489
1490   // Update Python script
1491   TPythonDump() << _this() << ".ExportUNV( '" << file << "' )";
1492
1493   // Perform Export
1494   PrepareForWriting(file);
1495   _impl->ExportUNV(file);
1496 }
1497
1498 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
1499   throw(SALOME::SALOME_Exception)
1500 {
1501   Unexpect aCatch(SALOME_SalomeException);
1502
1503   // Update Python script
1504   TPythonDump() << _this() << ".ExportSTL( '" << file << "', " << isascii << " )";
1505
1506   // Perform Export
1507   PrepareForWriting(file);
1508   _impl->ExportSTL(file, isascii);
1509 }
1510
1511 //=============================================================================
1512 /*!
1513  *
1514  */
1515 //=============================================================================
1516
1517 SALOME_MED::MESH_ptr SMESH_Mesh_i::GetMEDMesh()throw(SALOME::SALOME_Exception)
1518 {
1519   Unexpect aCatch(SALOME_SalomeException);
1520   SMESH_MEDMesh_i *aMedMesh = new SMESH_MEDMesh_i(this);
1521   SALOME_MED::MESH_var aMesh = aMedMesh->_this();
1522   return aMesh._retn();
1523 }
1524
1525 //=============================================================================
1526 /*!
1527  *
1528  */
1529 //=============================================================================
1530 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
1531 {
1532   Unexpect aCatch(SALOME_SalomeException);
1533   return _impl->NbNodes();
1534 }
1535
1536 //=============================================================================
1537 /*!
1538  *
1539  */
1540 //=============================================================================
1541 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
1542 {
1543   Unexpect aCatch(SALOME_SalomeException);
1544   return NbEdges() + NbFaces() + NbVolumes();
1545 }
1546
1547 //=============================================================================
1548 /*!
1549  *
1550  */
1551 //=============================================================================
1552 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
1553 {
1554   Unexpect aCatch(SALOME_SalomeException);
1555   return _impl->NbEdges();
1556 }
1557
1558 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
1559   throw(SALOME::SALOME_Exception)
1560 {
1561   Unexpect aCatch(SALOME_SalomeException);
1562   return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
1563 }
1564
1565 //=============================================================================
1566 /*!
1567  *
1568  */
1569 //=============================================================================
1570 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
1571 {
1572   Unexpect aCatch(SALOME_SalomeException);
1573   return _impl->NbFaces();
1574 }
1575
1576 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
1577 {
1578   Unexpect aCatch(SALOME_SalomeException);
1579   return _impl->NbTriangles();
1580 }
1581
1582 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
1583 {
1584   Unexpect aCatch(SALOME_SalomeException);
1585   return _impl->NbQuadrangles();
1586 }
1587
1588 CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
1589 {
1590   Unexpect aCatch(SALOME_SalomeException);
1591   return _impl->NbPolygons();
1592 }
1593
1594 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
1595   throw(SALOME::SALOME_Exception)
1596 {
1597   Unexpect aCatch(SALOME_SalomeException);
1598   return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
1599 }
1600
1601 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
1602   throw(SALOME::SALOME_Exception)
1603 {
1604   Unexpect aCatch(SALOME_SalomeException);
1605   return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
1606 }
1607
1608 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
1609   throw(SALOME::SALOME_Exception)
1610 {
1611   Unexpect aCatch(SALOME_SalomeException);
1612   return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
1613 }
1614
1615 //=============================================================================
1616 /*!
1617  *
1618  */
1619 //=============================================================================
1620 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
1621 {
1622   Unexpect aCatch(SALOME_SalomeException);
1623   return _impl->NbVolumes();
1624 }
1625
1626 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
1627 {
1628   Unexpect aCatch(SALOME_SalomeException);
1629   return _impl->NbTetras();
1630 }
1631
1632 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
1633 {
1634   Unexpect aCatch(SALOME_SalomeException);
1635   return _impl->NbHexas();
1636 }
1637
1638 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
1639 {
1640   Unexpect aCatch(SALOME_SalomeException);
1641   return _impl->NbPyramids();
1642 }
1643
1644 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
1645 {
1646   Unexpect aCatch(SALOME_SalomeException);
1647   return _impl->NbPrisms();
1648 }
1649
1650 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
1651 {
1652   Unexpect aCatch(SALOME_SalomeException);
1653   return _impl->NbPolyhedrons();
1654 }
1655
1656 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
1657   throw(SALOME::SALOME_Exception)
1658 {
1659   Unexpect aCatch(SALOME_SalomeException);
1660   return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
1661 }
1662
1663 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
1664   throw(SALOME::SALOME_Exception)
1665 {
1666   Unexpect aCatch(SALOME_SalomeException);
1667   return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
1668 }
1669
1670 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
1671   throw(SALOME::SALOME_Exception)
1672 {
1673   Unexpect aCatch(SALOME_SalomeException);
1674   return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
1675 }
1676
1677 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
1678   throw(SALOME::SALOME_Exception)
1679 {
1680   Unexpect aCatch(SALOME_SalomeException);
1681   return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
1682 }
1683
1684 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
1685   throw(SALOME::SALOME_Exception)
1686 {
1687   Unexpect aCatch(SALOME_SalomeException);
1688   return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
1689 }
1690
1691 //=============================================================================
1692 /*!
1693  *
1694  */
1695 //=============================================================================
1696 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
1697 {
1698   Unexpect aCatch(SALOME_SalomeException);
1699   return _impl->NbSubMesh();
1700 }
1701
1702 //=============================================================================
1703 /*!
1704  *
1705  */
1706 //=============================================================================
1707 char* SMESH_Mesh_i::Dump()
1708 {
1709   std::ostringstream os;
1710   _impl->Dump( os );
1711   return CORBA::string_dup( os.str().c_str() );
1712 }
1713
1714 //=============================================================================
1715 /*!
1716  *
1717  */
1718 //=============================================================================
1719 SMESH::long_array* SMESH_Mesh_i::GetIDs()
1720 {
1721 //   SMESH::long_array_var aResult = new SMESH::long_array();
1722 //   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
1723 //   int aMinId = aSMESHDS_Mesh->MinElementID();
1724 //   int aMaxId =  aSMESHDS_Mesh->MaxElementID();
1725
1726 //   aResult->length(aMaxId - aMinId + 1);
1727
1728 //   for (int i = 0, id = aMinId; id <= aMaxId; id++  )
1729 //     aResult[i++] = id;
1730
1731 //   return aResult._retn();
1732   // PAL12398
1733   return GetElementsId();
1734 }
1735
1736 //=============================================================================
1737 /*!
1738  *
1739  */
1740 //=============================================================================
1741
1742 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
1743      throw (SALOME::SALOME_Exception)
1744 {
1745   Unexpect aCatch(SALOME_SalomeException);
1746   MESSAGE("SMESH_Mesh_i::GetElementsId");
1747   SMESH::long_array_var aResult = new SMESH::long_array();
1748   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
1749
1750   if ( aSMESHDS_Mesh == NULL )
1751     return aResult._retn();
1752
1753   long nbElements = NbElements();
1754   aResult->length( nbElements );
1755   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
1756   for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
1757     aResult[i] = anIt->next()->GetID();
1758
1759   return aResult._retn();
1760 }
1761
1762
1763 //=============================================================================
1764 /*!
1765  *
1766  */
1767 //=============================================================================
1768
1769 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
1770     throw (SALOME::SALOME_Exception)
1771 {
1772   Unexpect aCatch(SALOME_SalomeException);
1773   MESSAGE("SMESH_subMesh_i::GetElementsByType");
1774   SMESH::long_array_var aResult = new SMESH::long_array();
1775   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
1776
1777   if ( aSMESHDS_Mesh == NULL )
1778     return aResult._retn();
1779
1780   long nbElements = NbElements();
1781
1782   // No sense in returning ids of elements along with ids of nodes:
1783   // when theElemType == SMESH::ALL, return node ids only if
1784   // there are no elements
1785   if ( theElemType == SMESH::NODE || theElemType == SMESH::ALL && nbElements == 0 )
1786     return GetNodesId();
1787
1788   aResult->length( nbElements );
1789
1790   int i = 0;
1791
1792   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
1793   while ( i < nbElements && anIt->more() ) {
1794     const SMDS_MeshElement* anElem = anIt->next();
1795     if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
1796       aResult[i++] = anElem->GetID();
1797   }
1798
1799   aResult->length( i );
1800
1801   return aResult._retn();
1802 }
1803
1804 //=============================================================================
1805 /*!
1806  *
1807  */
1808 //=============================================================================
1809
1810 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
1811   throw (SALOME::SALOME_Exception)
1812 {
1813   Unexpect aCatch(SALOME_SalomeException);
1814   MESSAGE("SMESH_subMesh_i::GetNodesId");
1815   SMESH::long_array_var aResult = new SMESH::long_array();
1816   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
1817
1818   if ( aSMESHDS_Mesh == NULL )
1819     return aResult._retn();
1820
1821   long nbNodes = NbNodes();
1822   aResult->length( nbNodes );
1823   SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator();
1824   for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
1825     aResult[i] = anIt->next()->GetID();
1826
1827   return aResult._retn();
1828 }
1829
1830 //=============================================================================
1831 /*!
1832  *
1833  */
1834 //=============================================================================
1835
1836 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
1837   throw (SALOME::SALOME_Exception)
1838 {
1839   return ( SMESH::ElementType )_impl->GetElementType( id, iselem );
1840 }
1841
1842
1843 //=============================================================================
1844 /*!
1845  * Returns ID of elements for given submesh
1846  */
1847 //=============================================================================
1848 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
1849      throw (SALOME::SALOME_Exception)
1850 {
1851   SMESH::long_array_var aResult = new SMESH::long_array();
1852
1853   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
1854   if(!SM) return aResult._retn();
1855
1856   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
1857   if(!SDSM) return aResult._retn();
1858
1859   aResult->length(SDSM->NbElements());
1860
1861   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
1862   int i = 0;
1863   while ( eIt->more() ) {
1864     aResult[i++] = eIt->next()->GetID();
1865   }
1866
1867   return aResult._retn();
1868 }
1869
1870
1871 //=============================================================================
1872 /*!
1873  * Returns ID of nodes for given submesh
1874  * If param all==true - returns all nodes, else -
1875  * returns only nodes on shapes.
1876  */
1877 //=============================================================================
1878 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID, CORBA::Boolean all)
1879      throw (SALOME::SALOME_Exception)
1880 {
1881   SMESH::long_array_var aResult = new SMESH::long_array();
1882
1883   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
1884   if(!SM) return aResult._retn();
1885
1886   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
1887   if(!SDSM) return aResult._retn();
1888
1889   map<int,const SMDS_MeshElement*> theElems;
1890   if( !all || (SDSM->NbElements()==0 && SDSM->NbNodes()==1) ) {
1891     SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
1892     while ( nIt->more() ) {
1893       const SMDS_MeshNode* elem = nIt->next();
1894       theElems.insert( make_pair(elem->GetID(),elem) );
1895     }
1896   }
1897   else { // all nodes of submesh elements
1898     SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
1899     while ( eIt->more() ) {
1900       const SMDS_MeshElement* anElem = eIt->next();
1901       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
1902       while ( nIt->more() ) {
1903         const SMDS_MeshElement* elem = nIt->next();
1904         theElems.insert( make_pair(elem->GetID(),elem) );
1905       }
1906     }
1907   }
1908
1909   aResult->length(theElems.size());
1910   map<int, const SMDS_MeshElement * >::iterator itElem;
1911   int i = 0;
1912   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
1913     aResult[i++] = (*itElem).first;
1914
1915   return aResult._retn();
1916 }
1917   
1918
1919 //=============================================================================
1920 /*!
1921  * Returns type of elements for given submesh
1922  */
1923 //=============================================================================
1924 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
1925      throw (SALOME::SALOME_Exception)
1926 {
1927   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
1928   if(!SM) return SMESH::ALL;
1929
1930   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
1931   if(!SDSM) return SMESH::ALL;
1932
1933   if(SDSM->NbElements()==0)
1934     return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
1935
1936   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
1937   const SMDS_MeshElement* anElem = eIt->next();
1938   return ( SMESH::ElementType ) anElem->GetType();
1939 }
1940   
1941
1942 //=============================================================================
1943 /*!
1944  *
1945  */
1946 //=============================================================================
1947
1948 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
1949 {
1950   CORBA::LongLong pointeur = CORBA::LongLong(_impl);
1951   cerr << "CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() " << pointeur << endl;
1952   return pointeur;
1953 }
1954
1955
1956 //=============================================================================
1957 /*!
1958  * Get XYZ coordinates of node as list of double
1959  * If there is not node for given ID - returns empty list
1960  */
1961 //=============================================================================
1962
1963 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
1964 {
1965   SMESH::double_array_var aResult = new SMESH::double_array();
1966   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
1967   if ( aSMESHDS_Mesh == NULL )
1968     return aResult._retn();
1969
1970   // find node
1971   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
1972   if(!aNode)
1973     return aResult._retn();
1974
1975   // add coordinates
1976   aResult->length(3);
1977   aResult[0] = aNode->X();
1978   aResult[1] = aNode->Y();
1979   aResult[2] = aNode->Z();
1980   return aResult._retn();
1981 }
1982
1983
1984 //=============================================================================
1985 /*!
1986  * For given node returns list of IDs of inverse elements
1987  * If there is not node for given ID - returns empty list
1988  */
1989 //=============================================================================
1990
1991 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
1992 {
1993   SMESH::long_array_var aResult = new SMESH::long_array();
1994   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
1995   if ( aSMESHDS_Mesh == NULL )
1996     return aResult._retn();
1997
1998   // find node
1999   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2000   if(!aNode)
2001     return aResult._retn();
2002
2003   // find inverse elements
2004   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
2005   TColStd_SequenceOfInteger IDs;
2006   while(eIt->more()) {
2007     const SMDS_MeshElement* elem = eIt->next();
2008     IDs.Append(elem->GetID());
2009   }
2010   if(IDs.Length()>0) {
2011     aResult->length(IDs.Length());
2012     int i = 1;
2013     for(; i<=IDs.Length(); i++) {
2014       aResult[i-1] = IDs.Value(i);
2015     }
2016   }
2017   return aResult._retn();
2018 }
2019
2020 //=============================================================================
2021 /*!
2022  * \brief Return position of a node on shape
2023  */
2024 //=============================================================================
2025
2026 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
2027 {
2028   SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
2029   aNodePosition->shapeID = 0;
2030   aNodePosition->shapeType = GEOM::SHAPE;
2031
2032   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
2033   if ( !mesh ) return aNodePosition;
2034
2035   if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
2036   {
2037     if ( SMDS_PositionPtr pos = aNode->GetPosition() )
2038     {
2039       aNodePosition->shapeID = pos->GetShapeId();
2040       switch ( pos->GetTypeOfPosition() ) {
2041       case SMDS_TOP_EDGE:
2042         aNodePosition->shapeType = GEOM::EDGE;
2043         aNodePosition->params.length(1);
2044         aNodePosition->params[0] =
2045           static_cast<SMDS_EdgePosition*>( pos.get() )->GetUParameter();
2046         break;
2047       case SMDS_TOP_FACE:
2048         aNodePosition->shapeType = GEOM::FACE;
2049         aNodePosition->params.length(2);
2050         aNodePosition->params[0] =
2051           static_cast<SMDS_FacePosition*>( pos.get() )->GetUParameter();
2052         aNodePosition->params[1] =
2053           static_cast<SMDS_FacePosition*>( pos.get() )->GetVParameter();
2054         break;
2055       case SMDS_TOP_VERTEX:
2056         aNodePosition->shapeType = GEOM::VERTEX;
2057         break;
2058       case SMDS_TOP_3DSPACE:
2059         if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
2060           aNodePosition->shapeType = GEOM::SOLID;
2061         else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
2062           aNodePosition->shapeType = GEOM::SHELL;
2063         break;
2064       default:;
2065       }
2066     }
2067   }
2068   return aNodePosition;
2069 }
2070
2071 //=============================================================================
2072 /*!
2073  * If given element is node returns IDs of shape from position
2074  * If there is not node for given ID - returns -1
2075  */
2076 //=============================================================================
2077
2078 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
2079 {
2080   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2081   if ( aSMESHDS_Mesh == NULL )
2082     return -1;
2083
2084   // try to find node
2085   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2086   if(aNode) {
2087     SMDS_PositionPtr pos = aNode->GetPosition();
2088     if(!pos)
2089       return -1;
2090     else
2091       return pos->GetShapeId();
2092   }
2093
2094   return -1;
2095 }
2096
2097
2098 //=============================================================================
2099 /*!
2100  * For given element returns ID of result shape after 
2101  * ::FindShape() from SMESH_MeshEditor
2102  * If there is not element for given ID - returns -1
2103  */
2104 //=============================================================================
2105
2106 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
2107 {
2108   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2109   if ( aSMESHDS_Mesh == NULL )
2110     return -1;
2111
2112   // try to find element
2113   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2114   if(!elem)
2115     return -1;
2116
2117   //SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
2118   ::SMESH_MeshEditor aMeshEditor(_impl);
2119   int index = aMeshEditor.FindShape( elem );
2120   if(index>0)
2121     return index;
2122
2123   return -1;
2124 }
2125
2126
2127 //=============================================================================
2128 /*!
2129  * Returns number of nodes for given element
2130  * If there is not element for given ID - returns -1
2131  */
2132 //=============================================================================
2133
2134 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
2135 {
2136   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2137   if ( aSMESHDS_Mesh == NULL ) return -1;
2138   // try to find element
2139   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2140   if(!elem) return -1;
2141   return elem->NbNodes();
2142 }
2143
2144
2145 //=============================================================================
2146 /*!
2147  * Returns ID of node by given index for given element
2148  * If there is not element for given ID - returns -1
2149  * If there is not node for given index - returns -2
2150  */
2151 //=============================================================================
2152
2153 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
2154 {
2155   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2156   if ( aSMESHDS_Mesh == NULL ) return -1;
2157   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2158   if(!elem) return -1;
2159   if( index>=elem->NbNodes() || index<0 ) return -1;
2160   return elem->GetNode(index)->GetID();
2161 }
2162
2163 //=============================================================================
2164 /*!
2165  * Returns IDs of nodes of given element
2166  */
2167 //=============================================================================
2168
2169 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
2170 {
2171   SMESH::long_array_var aResult = new SMESH::long_array();
2172   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
2173   {
2174     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id) )
2175     {
2176       aResult->length( elem->NbNodes() );
2177       for ( int i = 0; i < elem->NbNodes(); ++i )
2178         aResult[ i ] = elem->GetNode( i )->GetID();
2179     }
2180   }
2181   return aResult._retn();
2182 }
2183
2184 //=============================================================================
2185 /*!
2186  * Returns true if given node is medium node
2187  * in given quadratic element
2188  */
2189 //=============================================================================
2190
2191 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
2192 {
2193   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2194   if ( aSMESHDS_Mesh == NULL ) return false;
2195   // try to find node
2196   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
2197   if(!aNode) return false;
2198   // try to find element
2199   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(ide);
2200   if(!elem) return false;
2201
2202   return elem->IsMediumNode(aNode);
2203 }
2204
2205
2206 //=============================================================================
2207 /*!
2208  * Returns true if given node is medium node
2209  * in one of quadratic elements
2210  */
2211 //=============================================================================
2212
2213 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
2214                                                    SMESH::ElementType theElemType)
2215 {
2216   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2217   if ( aSMESHDS_Mesh == NULL ) return false;
2218
2219   // try to find node
2220   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
2221   if(!aNode) return false;
2222
2223   SMESH_MesherHelper aHelper( *(_impl) );
2224
2225   SMDSAbs_ElementType aType;
2226   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
2227   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
2228   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
2229   else aType = SMDSAbs_All;
2230
2231   return aHelper.IsMedium(aNode,aType);
2232 }
2233
2234
2235 //=============================================================================
2236 /*!
2237  * Returns number of edges for given element
2238  */
2239 //=============================================================================
2240
2241 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
2242 {
2243   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2244   if ( aSMESHDS_Mesh == NULL ) return -1;
2245   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2246   if(!elem) return -1;
2247   return elem->NbEdges();
2248 }
2249
2250
2251 //=============================================================================
2252 /*!
2253  * Returns number of faces for given element
2254  */
2255 //=============================================================================
2256
2257 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
2258 {
2259   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2260   if ( aSMESHDS_Mesh == NULL ) return -1;
2261   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2262   if(!elem) return -1;
2263   return elem->NbFaces();
2264 }
2265
2266
2267 //=============================================================================
2268 /*!
2269  * Returns true if given element is polygon
2270  */
2271 //=============================================================================
2272
2273 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
2274 {
2275   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2276   if ( aSMESHDS_Mesh == NULL ) return false;
2277   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2278   if(!elem) return false;
2279   return elem->IsPoly();
2280 }
2281
2282
2283 //=============================================================================
2284 /*!
2285  * Returns true if given element is quadratic
2286  */
2287 //=============================================================================
2288
2289 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
2290 {
2291   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2292   if ( aSMESHDS_Mesh == NULL ) return false;
2293   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2294   if(!elem) return false;
2295   return elem->IsQuadratic();
2296 }
2297
2298
2299 //=============================================================================
2300 /*!
2301  * Returns bary center for given element
2302  */
2303 //=============================================================================
2304
2305 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
2306 {
2307   SMESH::double_array_var aResult = new SMESH::double_array();
2308   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2309   if ( aSMESHDS_Mesh == NULL )
2310     return aResult._retn();
2311
2312   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2313   if(!elem)
2314     return aResult._retn();
2315
2316   if(elem->GetType()==SMDSAbs_Volume) {
2317     SMDS_VolumeTool aTool;
2318     if(aTool.Set(elem)) {
2319       aResult->length(3);
2320       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
2321         aResult->length(0);
2322     }
2323   }
2324   else {
2325     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
2326     int nbn = 0;
2327     double x=0., y=0., z=0.;
2328     for(; anIt->more(); ) {
2329       nbn++;
2330       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
2331       x += aNode->X();
2332       y += aNode->Y();
2333       z += aNode->Z();
2334     }
2335     if(nbn>0) {
2336       // add coordinates
2337       aResult->length(3);
2338       aResult[0] = x/nbn;
2339       aResult[1] = y/nbn;
2340       aResult[2] = z/nbn;
2341     }
2342   }
2343
2344   return aResult._retn();
2345 }
2346
2347
2348 //=============================================================================
2349 /*!
2350  * Create and publish group servants if any groups were imported or created anyhow
2351  */
2352 //=============================================================================
2353
2354 void SMESH_Mesh_i::CreateGroupServants() 
2355 {
2356   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
2357
2358   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
2359   while ( groupIt->more() )
2360   {
2361     ::SMESH_Group* group = groupIt->next();
2362     int            anId = group->GetGroupDS()->GetID();
2363
2364     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
2365     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
2366       continue;
2367
2368     SMESH_GroupBase_i* aGroupImpl;
2369     TopoDS_Shape       shape;
2370     if ( SMESHDS_GroupOnGeom* groupOnGeom =
2371          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
2372     {
2373       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
2374       shape      = groupOnGeom->GetShape();
2375     }
2376     else {
2377       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2378     }
2379
2380     // To ensure correct mapping of servant and correct reference counting in GenericObj_i
2381     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
2382     aGroupImpl->Register();
2383
2384     SMESH::SMESH_GroupBase_var groupVar =
2385       SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
2386     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
2387
2388     // register CORBA object for persistence
2389     int nextId = _gen_i->RegisterObject( groupVar );
2390     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
2391
2392     // publishing of the groups in the study
2393     if ( !aStudy->_is_nil() ) {
2394       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
2395       _gen_i->PublishGroup( aStudy, _this(), groupVar, shapeVar, groupVar->GetName());
2396     }
2397   }
2398 }
2399
2400 //=============================================================================
2401 /*!
2402  * \brief Return groups cantained in _mapGroups by their IDs
2403  */
2404 //=============================================================================
2405
2406 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
2407 {
2408   int nbGroups = groupIDs.size();
2409   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
2410   aList->length( nbGroups );
2411
2412   list<int>::const_iterator ids = groupIDs.begin();
2413   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
2414   {
2415     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
2416     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
2417       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
2418   }
2419   aList->length( nbGroups );
2420   return aList._retn();
2421 }