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