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