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