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