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