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