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