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