Salome HOME
merge from branch BR_SMDS_MEMIMP 29 nov 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     vector< int > anIds;
1011     SMESH::ElementType aType = SMESH::ALL;
1012     for ( int g = 0, n = theGroups.length(); g < n; g++ )
1013     {
1014       SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1015       if ( CORBA::is_nil( aGrp ) )
1016         continue;
1017
1018       // check type
1019       SMESH::ElementType aCurrType = aGrp->GetType();
1020       if ( aType == SMESH::ALL )
1021         aType = aCurrType;
1022       else 
1023       {
1024         if ( aType != aCurrType )
1025           return SMESH::SMESH_Group::_nil();
1026       }
1027
1028       // unite ids
1029       SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1030       for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1031       {
1032         int aCurrId = aCurrIds[ i ];
1033         anIds.push_back( aCurrId );
1034       }
1035     }
1036
1037     // Create group
1038     SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
1039     if ( aResGrp->_is_nil() )
1040       return SMESH::SMESH_Group::_nil();
1041     
1042     // Create array of identifiers
1043     SMESH::long_array_var aResIds = new SMESH::long_array;
1044     aResIds->length( anIds.size() );
1045     
1046     //NCollection_Map< int >::Iterator anIter( anIds );
1047     for ( int i = 0; i<anIds.size(); i++ )
1048     {
1049       aResIds[ i ] = anIds[i];
1050     }
1051     aResGrp->Add( aResIds );
1052
1053     // Clear python lines, created by CreateGroup() and Add()
1054     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1055     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1056     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1057
1058     // Update Python script
1059     
1060     TPythonDump() << aResGrp << " = " << _this() << ".UnionListOfGroups( "
1061                   << &theGroups << ", '" << theName << "' )";
1062
1063     return aResGrp._retn();
1064   }
1065   catch( ... )
1066   {
1067     return SMESH::SMESH_Group::_nil();
1068   }
1069 }
1070
1071 //=============================================================================
1072 /*! IntersectGroups
1073  *  New group is created. All mesh elements that are
1074  *  present in both initial groups are added to the new one.
1075  */
1076 //=============================================================================
1077 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1078                                                       SMESH::SMESH_GroupBase_ptr theGroup2,
1079                                                       const char* theName )
1080   throw (SALOME::SALOME_Exception)
1081 {
1082   if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
1083        theGroup1->GetType() != theGroup2->GetType() )
1084     return SMESH::SMESH_Group::_nil();
1085
1086   // Create Intersection
1087   SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
1088   if ( aResGrp->_is_nil() )
1089     return aResGrp;
1090
1091   SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
1092   SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
1093
1094   TColStd_MapOfInteger aMap1;
1095
1096   for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
1097     aMap1.Add( anIds1[ i1 ] );
1098
1099   TColStd_SequenceOfInteger aSeq;
1100
1101   for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
1102     if ( aMap1.Contains( anIds2[ i2 ] ) )
1103       aSeq.Append( anIds2[ i2 ] );
1104
1105   SMESH::long_array_var aResIds = new SMESH::long_array;
1106   aResIds->length( aSeq.Length() );
1107
1108   for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
1109     aResIds[ resI ] = aSeq( resI + 1 );
1110
1111   aResGrp->Add( aResIds );
1112
1113   // Clear python lines, created by CreateGroup() and Add()
1114   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1115   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1116   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1117
1118   // Update Python script
1119   TPythonDump() << aResGrp << " = " << _this() << ".IntersectGroups( "
1120                 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1121
1122   return aResGrp._retn();
1123 }
1124
1125 //=============================================================================
1126 /*!
1127   \brief Intersect list of groups. New group is created. All mesh elements that 
1128   are present in all initial groups simultaneously are added to the new one.
1129   \param theGroups list of groups
1130   \param theName name of group to be created
1131   \return pointer on the group
1132 */
1133 //=============================================================================
1134 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectListOfGroups( 
1135   const SMESH::ListOfGroups& theGroups, const char* theName )
1136 throw (SALOME::SALOME_Exception)
1137 {
1138   if ( !theName )
1139     return SMESH::SMESH_Group::_nil();
1140
1141   try
1142   {
1143     NCollection_DataMap< int, int > anIdToCount;
1144     SMESH::ElementType aType = SMESH::ALL;
1145     for ( int g = 0, n = theGroups.length(); g < n; g++ )
1146     {
1147       SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1148       if ( CORBA::is_nil( aGrp ) )
1149         continue;
1150
1151       // check type
1152       SMESH::ElementType aCurrType = aGrp->GetType();
1153       if ( aType == SMESH::ALL )
1154         aType = aCurrType;
1155       else 
1156       {
1157         if ( aType != aCurrType )
1158           return SMESH::SMESH_Group::_nil();
1159       }
1160
1161       // calculates number of occurance ids in groups
1162       SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1163       for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1164       {
1165         int aCurrId = aCurrIds[ i ];
1166         if ( !anIdToCount.IsBound( aCurrId ) )
1167           anIdToCount.Bind( aCurrId, 1 );
1168         else 
1169           anIdToCount( aCurrId ) = anIdToCount( aCurrId ) + 1;
1170       }
1171     }
1172     
1173     // create map of ids
1174     int nbGrp = theGroups.length();
1175     vector< int > anIds;
1176     NCollection_DataMap< int, int >::Iterator anIter( anIdToCount );
1177     for ( ; anIter.More(); anIter.Next() )
1178     {
1179       int aCurrId = anIter.Key();
1180       int aCurrNb = anIter.Value();
1181       if ( aCurrNb == nbGrp )
1182         anIds.push_back( aCurrId );
1183     }
1184
1185     // Create group
1186     SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
1187     if ( aResGrp->_is_nil() )
1188       return SMESH::SMESH_Group::_nil();
1189     
1190     // Create array of identifiers
1191     SMESH::long_array_var aResIds = new SMESH::long_array;
1192     aResIds->length( anIds.size() );
1193     
1194     //NCollection_Map< int >::Iterator aListIter( anIds );
1195     for ( int i = 0; i<anIds.size(); i++ )
1196     {
1197       aResIds[ i ] = anIds[i];
1198     }
1199     aResGrp->Add( aResIds );
1200
1201     // Clear python lines, created by CreateGroup() and Add()
1202     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1203     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1204     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1205
1206     // Update Python script
1207     
1208     TPythonDump() << aResGrp << " = " << _this() << ".IntersectListOfGroups( "
1209                   << &theGroups << ", '" << theName << "' )";
1210
1211     return aResGrp._retn();
1212   }
1213   catch( ... )
1214   {
1215     return SMESH::SMESH_Group::_nil();
1216   }
1217 }
1218
1219 //=============================================================================
1220 /*! CutGroups
1221  *  New group is created. All mesh elements that are present in
1222  *  main group but do not present in tool group are added to the new one
1223  */
1224 //=============================================================================
1225 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1226                                                 SMESH::SMESH_GroupBase_ptr theGroup2,
1227                                                 const char* theName )
1228   throw (SALOME::SALOME_Exception)
1229 {
1230   if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
1231        theGroup1->GetType() != theGroup2->GetType() )
1232     return SMESH::SMESH_Group::_nil();
1233
1234   // Perform Cutting
1235   SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
1236   if ( aResGrp->_is_nil() )
1237     return aResGrp;
1238
1239   SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
1240   SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
1241
1242   TColStd_MapOfInteger aMap2;
1243
1244   for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
1245     aMap2.Add( anIds2[ i2 ] );
1246
1247   TColStd_SequenceOfInteger aSeq;
1248   for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
1249     if ( !aMap2.Contains( anIds1[ i1 ] ) )
1250       aSeq.Append( anIds1[ i1 ] );
1251
1252   SMESH::long_array_var aResIds = new SMESH::long_array;
1253   aResIds->length( aSeq.Length() );
1254
1255   for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
1256     aResIds[ resI ] = aSeq( resI + 1 );
1257
1258   aResGrp->Add( aResIds );
1259
1260   // Clear python lines, created by CreateGroup() and Add()
1261   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1262   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1263   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
1264
1265   // Update Python script
1266   TPythonDump() << aResGrp << " = " << _this() << ".CutGroups( "
1267                 << theGroup1 << ", " << theGroup2 << ", '"
1268                 << theName << "' )";
1269
1270   return aResGrp._retn();
1271 }
1272
1273 //=============================================================================
1274 /*!
1275   \brief Cut lists of groups. New group is created. All mesh elements that are 
1276   present in main groups but do not present in tool groups are added to the new one
1277   \param theMainGroups list of main groups
1278   \param theToolGroups list of tool groups
1279   \param theName name of group to be created
1280   \return pointer on the group
1281 */
1282 //=============================================================================
1283 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutListOfGroups( 
1284   const SMESH::ListOfGroups& theMainGroups, 
1285   const SMESH::ListOfGroups& theToolGroups, 
1286   const char* theName )
1287   throw (SALOME::SALOME_Exception)
1288 {
1289   if ( !theName )
1290     return SMESH::SMESH_Group::_nil();
1291
1292   try
1293   {
1294     set< int > aToolIds;
1295     SMESH::ElementType aType = SMESH::ALL;
1296     int g, n;
1297     // iterate through tool groups
1298     for ( g = 0, n = theToolGroups.length(); g < n; g++ )
1299     {
1300       SMESH::SMESH_GroupBase_var aGrp = theToolGroups[ g ];
1301       if ( CORBA::is_nil( aGrp ) )
1302         continue;
1303
1304       // check type
1305       SMESH::ElementType aCurrType = aGrp->GetType();
1306       if ( aType == SMESH::ALL )
1307         aType = aCurrType;
1308       else 
1309       {
1310         if ( aType != aCurrType )
1311           return SMESH::SMESH_Group::_nil();
1312       }
1313
1314       // unite tool ids
1315       SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1316       for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1317       {
1318         int aCurrId = aCurrIds[ i ];
1319         aToolIds.insert( aCurrId );
1320       }
1321     }
1322
1323     vector< int > anIds; // result
1324
1325     // Iterate through main group 
1326     for ( g = 0, n = theMainGroups.length(); g < n; g++ )
1327     {
1328       SMESH::SMESH_GroupBase_var aGrp = theMainGroups[ g ];
1329       if ( CORBA::is_nil( aGrp ) )
1330         continue;
1331
1332       // check type
1333       SMESH::ElementType aCurrType = aGrp->GetType();
1334       if ( aType == SMESH::ALL )
1335         aType = aCurrType;
1336       else 
1337       {
1338         if ( aType != aCurrType )
1339           return SMESH::SMESH_Group::_nil();
1340       }
1341
1342       // unite tool ids
1343       SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1344       for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1345       {
1346         int aCurrId = aCurrIds[ i ];
1347         if ( !aToolIds.count( aCurrId ) )
1348           anIds.push_back( aCurrId );
1349       }
1350     }
1351
1352     // Create group
1353     SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
1354     if ( aResGrp->_is_nil() )
1355       return SMESH::SMESH_Group::_nil();
1356     
1357     // Create array of identifiers
1358     SMESH::long_array_var aResIds = new SMESH::long_array;
1359     aResIds->length( anIds.size() );
1360     
1361     for (int i=0; i<anIds.size(); i++ )
1362     {
1363       aResIds[ i ] = anIds[i];
1364     }
1365     aResGrp->Add( aResIds );
1366
1367     // Clear python lines, created by CreateGroup() and Add()
1368     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1369     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1370     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1371
1372     // Update Python script
1373
1374     TPythonDump() << aResGrp << " = " << _this() << ".CutListOfGroups( "
1375                   << &theMainGroups << ", " << &theToolGroups << ", '"
1376                   << theName << "' )";
1377     
1378     return aResGrp._retn();
1379   }
1380   catch( ... )
1381   {
1382     return SMESH::SMESH_Group::_nil();
1383   }
1384 }
1385
1386 //=============================================================================
1387 /*!
1388   \brief Create groups of entities from existing groups of superior dimensions 
1389   System 
1390   1) extract all nodes from each group,
1391   2) combine all elements of specified dimension laying on these nodes.
1392   \param theGroups list of source groups 
1393   \param theElemType dimension of elements 
1394   \param theName name of new group
1395   \return pointer on new group
1396 */
1397 //=============================================================================
1398 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateDimGroup( 
1399   const SMESH::ListOfGroups& theGroups, 
1400   SMESH::ElementType         theElemType, 
1401   const char*                theName )
1402   throw (SALOME::SALOME_Exception)
1403 {
1404   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
1405
1406   if ( !theName || !aMeshDS )
1407     return SMESH::SMESH_Group::_nil();
1408
1409   SMDSAbs_ElementType anElemType = (SMDSAbs_ElementType)theElemType;
1410
1411   try
1412   {
1413     // Create map of nodes from all groups 
1414
1415     set< int > aNodeMap;
1416     
1417     for ( int g = 0, n = theGroups.length(); g < n; g++ )
1418     {
1419       SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1420       if ( CORBA::is_nil( aGrp ) )
1421         continue;
1422
1423       SMESH::ElementType aType = aGrp->GetType();
1424       if ( aType == SMESH::ALL )
1425         continue;
1426       else if ( aType == SMESH::NODE )
1427       {
1428         SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1429         for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1430         {
1431           int aCurrId = aCurrIds[ i ];
1432           const SMDS_MeshNode* aNode = aMeshDS->FindNode( aCurrId );
1433           if ( aNode )
1434             aNodeMap.insert( aNode->GetID() );
1435         }
1436       }
1437       else 
1438       {
1439         SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
1440         for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
1441         {
1442           int aCurrId = aCurrIds[ i ];
1443           const SMDS_MeshElement* anElem = aMeshDS->FindElement( aCurrId );
1444           if ( !anElem )
1445             continue;
1446           SMDS_ElemIteratorPtr aNodeIter = anElem->nodesIterator();
1447           while( aNodeIter->more() )
1448           {
1449             const SMDS_MeshNode* aNode = 
1450               dynamic_cast<const SMDS_MeshNode*>( aNodeIter->next() );
1451             if ( aNode )
1452               aNodeMap.insert( aNode->GetID() );
1453           }
1454         }
1455       }
1456     }
1457
1458     // Get result identifiers 
1459
1460     vector< int > aResultIds;
1461     if ( theElemType == SMESH::NODE )
1462     {
1463       //NCollection_Map< int >::Iterator aNodeIter( aNodeMap );
1464       set<int>::iterator iter = aNodeMap.begin();
1465       for ( ; iter != aNodeMap.end(); iter++ )
1466         aResultIds.push_back( *iter);
1467     }
1468     else
1469     {
1470       // Create list of elements of given dimension constructed on the nodes
1471       vector< int > anElemList;
1472       //NCollection_Map< int >::Iterator aNodeIter( aNodeMap );
1473       //for ( ; aNodeIter.More(); aNodeIter.Next() )
1474       set<int>::iterator iter = aNodeMap.begin();
1475       for ( ; iter != aNodeMap.end(); iter++ )
1476       {
1477         const SMDS_MeshElement* aNode = 
1478           dynamic_cast<const SMDS_MeshElement*>( aMeshDS->FindNode( *iter ) );
1479         if ( !aNode )
1480           continue;
1481
1482          SMDS_ElemIteratorPtr anElemIter = aNode->elementsIterator( anElemType );
1483         while( anElemIter->more() )
1484         {
1485           const SMDS_MeshElement* anElem = 
1486             dynamic_cast<const SMDS_MeshElement*>( anElemIter->next() );
1487           if ( anElem && anElem->GetType() == anElemType )
1488             anElemList.push_back( anElem->GetID() );
1489         }
1490       }
1491
1492       // check whether all nodes of elements are present in nodes map
1493       //NCollection_Map< int >::Iterator anIter( anElemList );
1494       //for ( ; anIter.More(); anIter.Next() )
1495       for (int i=0; i< anElemList.size(); i++)
1496       {
1497         const SMDS_MeshElement* anElem = aMeshDS->FindElement( anElemList[i] );
1498         if ( !anElem )
1499           continue;
1500
1501         bool isOk = true;
1502         SMDS_ElemIteratorPtr aNodeIter = anElem->nodesIterator();
1503         while( aNodeIter->more() )
1504         {
1505           const SMDS_MeshNode* aNode = 
1506             dynamic_cast<const SMDS_MeshNode*>( aNodeIter->next() );
1507           if ( !aNode || !aNodeMap.count( aNode->GetID() ) )
1508           {
1509             isOk = false;
1510             break;
1511           }
1512         } 
1513         if ( isOk )
1514           aResultIds.push_back( anElem->GetID() );
1515       }
1516     }
1517
1518     // Create group
1519
1520     SMESH::SMESH_Group_var aResGrp = CreateGroup( theElemType, theName );
1521     if ( aResGrp->_is_nil() )
1522       return SMESH::SMESH_Group::_nil();
1523     
1524     // Create array of identifiers
1525     SMESH::long_array_var aResIds = new SMESH::long_array;
1526     aResIds->length( aResultIds.size() );
1527     
1528     //NCollection_Map< int >::Iterator aResIter( aResultIds );
1529     //for ( int i = 0; aResIter.More(); aResIter.Next(), i++ )
1530     for (int i=0; i< aResultIds.size(); i++)
1531       aResIds[ i ] = aResultIds[i];
1532     aResGrp->Add( aResIds );
1533
1534     // Remove strings corresponding to group creation
1535     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1536     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1537     _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
1538
1539     // Update Python script
1540     
1541     TPythonDump() << aResGrp << " = " << _this() << ".CreateDimGroup( "
1542                   << &theGroups << ", " << theElemType << ", '" << theName << "' )";
1543
1544     return aResGrp._retn();
1545   }
1546   catch( ... )
1547   {
1548     return SMESH::SMESH_Group::_nil();
1549   }
1550 }
1551
1552 //================================================================================
1553 /*!
1554  * \brief Remember GEOM group data
1555  */
1556 //================================================================================
1557
1558 void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj,
1559                                     CORBA::Object_ptr     theSmeshObj)
1560 {
1561   if ( CORBA::is_nil( theGeomObj ) || theGeomObj->GetType() != GEOM_GROUP )
1562     return;
1563   // group SO
1564   SALOMEDS::Study_var   study  = _gen_i->GetCurrentStudy();
1565   SALOMEDS::SObject_var groupSO = _gen_i->ObjectToSObject( study, theGeomObj );
1566   if ( groupSO->_is_nil() )
1567     return;
1568   // group indices
1569   GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
1570   GEOM::GEOM_IGroupOperations_var groupOp =
1571     geomGen->GetIGroupOperations( _gen_i->GetCurrentStudyID() );
1572   GEOM::ListOfLong_var ids = groupOp->GetObjects( theGeomObj );
1573
1574   // store data
1575   _geomGroupData.push_back( TGeomGroupData() );
1576   TGeomGroupData & groupData = _geomGroupData.back();
1577   // entry
1578   CORBA::String_var entry = groupSO->GetID();
1579   groupData._groupEntry = entry.in();
1580   // indices
1581   for ( int i = 0; i < ids->length(); ++i )
1582     groupData._indices.insert( ids[i] );
1583   // SMESH object
1584   groupData._smeshObject = theSmeshObj;
1585 }
1586
1587 //================================================================================
1588 /*!
1589  * Remove GEOM group data relating to removed smesh object
1590  */
1591 //================================================================================
1592
1593 void SMESH_Mesh_i::removeGeomGroupData(CORBA::Object_ptr theSmeshObj)
1594 {
1595   list<TGeomGroupData>::iterator
1596     data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
1597   for ( ; data != dataEnd; ++data ) {
1598     if ( theSmeshObj->_is_equivalent( data->_smeshObject )) {
1599       _geomGroupData.erase( data );
1600       return;
1601     }
1602   }
1603 }
1604
1605 //================================================================================
1606 /*!
1607  * \brief Return new group contents if it has been changed and update group data
1608  */
1609 //================================================================================
1610
1611 TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData)
1612 {
1613   TopoDS_Shape newShape;
1614
1615   // get geom group
1616   SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1617   if ( study->_is_nil() ) return newShape; // means "not changed"
1618   SALOMEDS::SObject_var groupSO = study->FindObjectID( groupData._groupEntry.c_str() );
1619   if ( !groupSO->_is_nil() )
1620   {
1621     CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO );
1622     if ( CORBA::is_nil( groupObj )) return newShape;
1623     GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj );
1624
1625     // get indices of group items
1626     set<int> curIndices;
1627     GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
1628     GEOM::GEOM_IGroupOperations_var groupOp =
1629       geomGen->GetIGroupOperations( _gen_i->GetCurrentStudyID() );
1630     GEOM::ListOfLong_var ids = groupOp->GetObjects( geomGroup );
1631     for ( int i = 0; i < ids->length(); ++i )
1632       curIndices.insert( ids[i] );
1633
1634     if ( groupData._indices == curIndices )
1635       return newShape; // group not changed
1636
1637     // update data
1638     groupData._indices = curIndices;
1639
1640     GEOM_Client* geomClient = _gen_i->GetShapeReader();
1641     if ( !geomClient ) return newShape;
1642     TCollection_AsciiString groupIOR = geomGen->GetStringFromIOR( geomGroup );
1643     geomClient->RemoveShapeFromBuffer( groupIOR );
1644     newShape = _gen_i->GeomObjectToShape( geomGroup );
1645   }    
1646
1647   if ( newShape.IsNull() ) {
1648     // geom group becomes empty - return empty compound
1649     TopoDS_Compound compound;
1650     BRep_Builder().MakeCompound(compound);
1651     newShape = compound;
1652   }
1653   return newShape;
1654 }
1655
1656 namespace {
1657   //=============================================================================
1658   /*!
1659    * \brief Storage of shape and index used in CheckGeomGroupModif()
1660    */
1661   //=============================================================================
1662   struct TIndexedShape {
1663     int          _index;
1664     TopoDS_Shape _shape;
1665     TIndexedShape( int i, const TopoDS_Shape& s ):_index(i), _shape(s) {}
1666   };
1667 }
1668 //=============================================================================
1669 /*!
1670  * \brief Update objects depending on changed geom groups
1671  * 
1672  * NPAL16168: geometrical group edition from a submesh don't modifiy mesh computation
1673  * issue 0020210: Update of a smesh group after modification of the associated geom group
1674  */
1675 //=============================================================================
1676
1677 void SMESH_Mesh_i::CheckGeomGroupModif()
1678 {
1679   if ( !_impl->HasShapeToMesh() ) return;
1680
1681   SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1682   if ( study->_is_nil() ) return;
1683
1684   CORBA::Long nbEntities = NbNodes() + NbElements();
1685
1686   // Check if group contents changed
1687
1688   typedef map< string, TopoDS_Shape > TEntry2Geom;
1689   TEntry2Geom newGroupContents;
1690
1691   list<TGeomGroupData>::iterator
1692     data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
1693   for ( ; data != dataEnd; ++data )
1694   {
1695     pair< TEntry2Geom::iterator, bool > it_new =
1696       newGroupContents.insert( make_pair( data->_groupEntry, TopoDS_Shape() ));
1697     bool processedGroup    = !it_new.second;
1698     TopoDS_Shape& newShape = it_new.first->second;
1699     if ( !processedGroup )
1700       newShape = newGroupShape( *data );
1701     if ( newShape.IsNull() )
1702       continue; // no changes
1703
1704     if ( processedGroup ) { // update group indices
1705       list<TGeomGroupData>::iterator data2 = data;
1706       for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) {}
1707       data->_indices = data2->_indices;
1708     }
1709
1710     // Update SMESH objects according to new GEOM group contents
1711
1712     SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject );
1713     if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
1714     {
1715       int oldID = submesh->GetId();
1716       if ( _mapSubMeshIor.find( oldID ) == _mapSubMeshIor.end() )
1717         continue;
1718       TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
1719
1720       // update hypotheses
1721       list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldShape);
1722       list <const SMESHDS_Hypothesis * >::iterator hypIt;
1723       for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
1724       {
1725         _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
1726         _impl->AddHypothesis   ( newShape, (*hypIt)->GetID());
1727       }
1728       // care of submeshes
1729       SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newShape );
1730       int newID = newSubmesh->GetId();
1731       if ( newID != oldID ) {
1732         _mapSubMesh   [ newID ] = newSubmesh;
1733         _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
1734         _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
1735         _mapSubMesh.   erase(oldID);
1736         _mapSubMesh_i. erase(oldID);
1737         _mapSubMeshIor.erase(oldID);
1738         _mapSubMesh_i [ newID ]->changeLocalId( newID );
1739       }
1740       continue;
1741     }
1742
1743     SMESH::SMESH_GroupOnGeom_var smeshGroup =
1744       SMESH::SMESH_GroupOnGeom::_narrow( data->_smeshObject );
1745     if ( !smeshGroup->_is_nil() ) // ------------ GROUP -----------------------
1746     {
1747       SMESH_GroupOnGeom_i* group_i = SMESH::DownCast<SMESH_GroupOnGeom_i*>( smeshGroup );
1748       if ( group_i ) {
1749         ::SMESH_Group* group = _impl->GetGroup( group_i->GetLocalID() );
1750         SMESHDS_GroupOnGeom* ds = static_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() );
1751         ds->SetShape( newShape );
1752       }
1753       continue;
1754     }
1755
1756     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject );
1757     if ( !mesh->_is_nil() ) // -------------- MESH ----------------------------
1758     {
1759       // Remove groups and submeshes basing on removed sub-shapes
1760
1761       TopTools_MapOfShape newShapeMap;
1762       TopoDS_Iterator shapeIt( newShape );
1763       for ( ; shapeIt.More(); shapeIt.Next() )
1764         newShapeMap.Add( shapeIt.Value() );
1765
1766       SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
1767       for ( shapeIt.Initialize( meshDS->ShapeToMesh() ); shapeIt.More(); shapeIt.Next() )
1768       {
1769         if ( newShapeMap.Contains( shapeIt.Value() ))
1770           continue;
1771         TopTools_IndexedMapOfShape oldShapeMap;
1772         TopExp::MapShapes( shapeIt.Value(), oldShapeMap );
1773         for ( int i = 1; i <= oldShapeMap.Extent(); ++i )
1774         {
1775           const TopoDS_Shape& oldShape = oldShapeMap(i);
1776           int oldInd = meshDS->ShapeToIndex( oldShape );
1777           // -- submeshes --
1778           map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldInd );
1779           if ( i_smIor != _mapSubMeshIor.end() ) {
1780             RemoveSubMesh( i_smIor->second ); // one submesh per shape index
1781           }
1782           // --- groups ---
1783           map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
1784           for ( ; i_grp != _mapGroups.end(); ++i_grp )
1785           {
1786             // check if a group bases on oldInd shape
1787             SMESHDS_GroupOnGeom* grpOnGeom = 0;
1788             if ( ::SMESH_Group* g = _impl->GetGroup( i_grp->first ))
1789               grpOnGeom = dynamic_cast<SMESHDS_GroupOnGeom*>( g->GetGroupDS() );
1790             if ( grpOnGeom && oldShape.IsSame( grpOnGeom->GetShape() ))
1791             { // remove
1792               RemoveGroup( i_grp->second ); // several groups can base on same shape
1793               i_grp = _mapGroups.begin(); // _mapGroups changed - restart iteration
1794             }
1795           }
1796         }
1797       }
1798       // Reassign hypotheses and update groups after setting the new shape to mesh
1799
1800       // collect anassigned hypotheses
1801       typedef list< pair< TIndexedShape, list<const SMESHDS_Hypothesis*> > > TShapeHypList;
1802       list <const SMESHDS_Hypothesis * >::const_iterator hypIt;
1803       TShapeHypList assignedHyps;
1804       for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i )
1805       {
1806         const TopoDS_Shape& oldShape = meshDS->IndexToShape(i);
1807         list<const SMESHDS_Hypothesis*> hyps = meshDS->GetHypothesis( oldShape );// copy
1808         if ( !hyps.empty() ) {
1809           assignedHyps.push_back( make_pair( TIndexedShape(i,oldShape), hyps ));
1810           for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
1811             _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
1812         }
1813       }
1814       // collect shapes supporting groups
1815       typedef list < pair< TIndexedShape, SMDSAbs_ElementType > > TShapeTypeList;
1816       TShapeTypeList groupData;
1817       const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
1818       set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
1819       for ( ; grIt != groups.end(); ++grIt )
1820       {
1821         if ( SMESHDS_GroupOnGeom* gog = dynamic_cast<SMESHDS_GroupOnGeom*>( *grIt ))
1822           groupData.push_back
1823             ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
1824       }
1825       // set new shape to mesh -> DS of submeshes and geom groups is deleted
1826       _impl->ShapeToMesh( newShape );
1827       
1828       // reassign hypotheses
1829       TShapeHypList::iterator indS_hyps = assignedHyps.begin();
1830       for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
1831       {
1832         TIndexedShape&                   geom = indS_hyps->first;
1833         list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
1834         int oldID = geom._index;
1835         int newID = meshDS->ShapeToIndex( geom._shape );
1836         if ( !newID )
1837           continue;
1838         if ( oldID == 1 ) { // main shape
1839           newID = 1;
1840           geom._shape = newShape;
1841         }
1842         for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
1843           _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
1844         // care of submeshes
1845         SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
1846         if ( newID != oldID ) {
1847           _mapSubMesh   [ newID ] = newSubmesh;
1848           _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
1849           _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
1850           _mapSubMesh.   erase(oldID);
1851           _mapSubMesh_i. erase(oldID);
1852           _mapSubMeshIor.erase(oldID);
1853           _mapSubMesh_i [ newID ]->changeLocalId( newID );
1854         }
1855       }
1856       // recreate groups
1857       TShapeTypeList::iterator geomType = groupData.begin();
1858       for ( ; geomType != groupData.end(); ++geomType )
1859       {
1860         const TIndexedShape& geom = geomType->first;
1861         int oldID = geom._index;
1862         if ( _mapGroups.find( oldID ) == _mapGroups.end() )
1863           continue;
1864         // get group name
1865         SALOMEDS::SObject_var groupSO = _gen_i->ObjectToSObject( study,_mapGroups[oldID] );
1866         CORBA::String_var     name    = groupSO->GetName();
1867         // update
1868         SMESH_GroupBase_i* group_i    = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID] );
1869         int newID;
1870         if ( group_i && _impl->AddGroup( geomType->second, name.in(), newID, geom._shape ))
1871           group_i->changeLocalId( newID );
1872       }
1873
1874       break; // everything has been updated
1875
1876     } // update mesh
1877   } // loop on group data
1878
1879   // Update icons
1880
1881   CORBA::Long newNbEntities = NbNodes() + NbElements();
1882   list< SALOMEDS::SObject_var > soToUpdateIcons;
1883   if ( newNbEntities != nbEntities )
1884   {
1885     // Add all SObjects with icons
1886     soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, _this() )); // mesh
1887
1888     for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
1889          i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
1890       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, i_sm->second ));
1891
1892     for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
1893           i_gr != _mapGroups.end(); ++i_gr ) // groups
1894       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, i_gr->second ));
1895   }
1896
1897   list< SALOMEDS::SObject_var >::iterator so = soToUpdateIcons.begin();
1898   for ( ; so != soToUpdateIcons.end(); ++so )
1899     _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
1900 }
1901
1902 //=============================================================================
1903 /*!
1904  * \brief Create standalone group instead if group on geometry
1905  */
1906 //=============================================================================
1907
1908 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupOnGeom_ptr theGroup )
1909 {
1910   SMESH::SMESH_Group_var aGroup;
1911   if ( theGroup->_is_nil() )
1912     return aGroup._retn();
1913
1914   Unexpect aCatch(SALOME_SalomeException);
1915
1916   SMESH_GroupBase_i* aGroupToRem =
1917     dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
1918   if ( !aGroupToRem )
1919     return aGroup._retn();
1920
1921   int anId = aGroupToRem->GetLocalID();
1922   if ( !_impl->ConvertToStandalone( anId ) )
1923     return aGroup._retn();
1924   removeGeomGroupData( theGroup );
1925
1926   SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
1927
1928   // remove old instance of group from own map
1929   _mapGroups.erase( anId );
1930
1931   SALOMEDS::StudyBuilder_var builder;
1932   SALOMEDS::SObject_var aGroupSO;
1933   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1934   if ( !aStudy->_is_nil() )  {
1935     builder = aStudy->NewBuilder();
1936     aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
1937     if ( !aGroupSO->_is_nil() ) {
1938
1939     // remove reference to geometry
1940     SALOMEDS::ChildIterator_var chItr = aStudy->NewChildIterator(aGroupSO);
1941     for ( ; chItr->More(); chItr->Next() )
1942       // Remove group's child SObject
1943       builder->RemoveObject( chItr->Value() );
1944
1945       // Update Python script
1946       TPythonDump() << aGroupSO << " = " << _this() << ".ConvertToStandalone( "
1947                     << aGroupSO << " )";
1948     }
1949   }
1950
1951   // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1952   SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
1953   aGroupImpl->Register();
1954   // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1955
1956   // remember new group in own map
1957   aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
1958   _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
1959
1960   // register CORBA object for persistence
1961   /*int nextId =*/ _gen_i->RegisterObject( aGroup );
1962
1963   builder->SetIOR( aGroupSO, _gen_i->GetORB()->object_to_string( aGroup ) );
1964
1965   return aGroup._retn();
1966 }
1967
1968 //=============================================================================
1969 /*!
1970  *
1971  */
1972 //=============================================================================
1973
1974 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
1975 {
1976   if(MYDEBUG) MESSAGE( "createSubMesh" );
1977   TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
1978
1979   ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
1980   int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
1981   SMESH_subMesh_i *subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
1982   SMESH::SMESH_subMesh_var subMesh
1983     = SMESH::SMESH_subMesh::_narrow(subMeshServant->_this());
1984
1985   _mapSubMesh[subMeshId] = mySubMesh;
1986   _mapSubMesh_i[subMeshId] = subMeshServant;
1987   _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate(subMesh);
1988
1989   // register CORBA object for persistence
1990   int nextId = _gen_i->RegisterObject( subMesh );
1991   if(MYDEBUG) MESSAGE( "Add submesh to map with id = "<< nextId);
1992
1993   // to track changes of GEOM groups
1994   addGeomGroupData( theSubShapeObject, subMesh );
1995
1996   return subMesh._retn();
1997 }
1998
1999 //=======================================================================
2000 //function : getSubMesh
2001 //purpose  :
2002 //=======================================================================
2003
2004 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
2005 {
2006   map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
2007   if ( it == _mapSubMeshIor.end() )
2008     return SMESH::SMESH_subMesh::_nil();
2009
2010   return SMESH::SMESH_subMesh::_duplicate( (*it).second );
2011 }
2012
2013
2014 //=============================================================================
2015 /*!
2016  *
2017  */
2018 //=============================================================================
2019
2020 void SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
2021                                   GEOM::GEOM_Object_ptr    theSubShapeObject )
2022 {
2023   MESSAGE("SMESH_Mesh_i::removeSubMesh()");
2024   if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
2025     return;
2026
2027   if ( theSubShapeObject->_is_nil() )  // not published shape (IPAL13617)
2028   {
2029     CORBA::Long shapeId = theSubMesh->GetId();
2030     if ( _mapSubMesh.find( shapeId ) != _mapSubMesh.end())
2031     {
2032       TopoDS_Shape S = _mapSubMesh[ shapeId ]->GetSubShape();
2033       if ( !S.IsNull() )
2034       {
2035         list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
2036         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
2037         for ( ; hyp != hyps.end(); ++hyp )
2038           _impl->RemoveHypothesis(S, (*hyp)->GetID());
2039       }
2040     }
2041   }
2042   else
2043   {
2044     try {
2045       SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
2046       for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
2047         removeHypothesis( theSubShapeObject, aHypList[i] );
2048       }
2049     }
2050     catch( const SALOME::SALOME_Exception& ) {
2051       INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
2052     }
2053     removeGeomGroupData( theSubShapeObject );
2054   }
2055   int subMeshId = theSubMesh->GetId();
2056
2057   _mapSubMesh.erase(subMeshId);
2058   _mapSubMesh_i.erase(subMeshId);
2059   _mapSubMeshIor.erase(subMeshId);
2060   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeSubMesh() completed");
2061 }
2062
2063 //=============================================================================
2064 /*!
2065  *
2066  */
2067 //=============================================================================
2068
2069 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType theElemType,
2070                                                       const char*         theName,
2071                                                       const TopoDS_Shape& theShape )
2072 {
2073   int anId;
2074   SMESH::SMESH_GroupBase_var aGroup;
2075   if ( _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName, anId, theShape )) {
2076     SMESH_GroupBase_i* aGroupImpl;
2077     if ( !theShape.IsNull() )
2078       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
2079     else
2080       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2081
2082     // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
2083     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
2084     aGroupImpl->Register();
2085     // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
2086
2087     aGroup = SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
2088     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2089
2090     // register CORBA object for persistence
2091     int nextId = _gen_i->RegisterObject( aGroup );
2092     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
2093
2094     // to track changes of GEOM groups
2095     if ( !theShape.IsNull() ) {
2096       GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
2097       addGeomGroupData( geom, aGroup );
2098     }
2099   }
2100   return aGroup._retn();
2101 }
2102
2103 //=============================================================================
2104 /*!
2105  * SMESH_Mesh_i::removeGroup
2106  *
2107  * Should be called by ~SMESH_Group_i()
2108  */
2109 //=============================================================================
2110
2111 void SMESH_Mesh_i::removeGroup( const int theId )
2112 {
2113   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
2114   if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
2115     SMESH::SMESH_GroupBase_ptr group = _mapGroups[theId];
2116     _mapGroups.erase( theId );
2117     removeGeomGroupData( group );
2118     if (! _impl->RemoveGroup( theId ))
2119     {
2120       // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
2121       RemoveGroup( group );
2122     }
2123   }
2124 }
2125
2126 //=============================================================================
2127 /*!
2128  *
2129  */
2130 //=============================================================================
2131
2132 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
2133 throw(SALOME::SALOME_Exception)
2134 {
2135   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetLog");
2136
2137   SMESH::log_array_var aLog;
2138   try{
2139     list < SMESHDS_Command * >logDS = _impl->GetLog();
2140     aLog = new SMESH::log_array;
2141     int indexLog = 0;
2142     int lg = logDS.size();
2143     SCRUTE(lg);
2144     aLog->length(lg);
2145     list < SMESHDS_Command * >::iterator its = logDS.begin();
2146     while(its != logDS.end()){
2147       SMESHDS_Command *com = *its;
2148       int comType = com->GetType();
2149       //SCRUTE(comType);
2150       int lgcom = com->GetNumber();
2151       //SCRUTE(lgcom);
2152       const list < int >&intList = com->GetIndexes();
2153       int inum = intList.size();
2154       //SCRUTE(inum);
2155       list < int >::const_iterator ii = intList.begin();
2156       const list < double >&coordList = com->GetCoords();
2157       int rnum = coordList.size();
2158       //SCRUTE(rnum);
2159       list < double >::const_iterator ir = coordList.begin();
2160       aLog[indexLog].commandType = comType;
2161       aLog[indexLog].number = lgcom;
2162       aLog[indexLog].coords.length(rnum);
2163       aLog[indexLog].indexes.length(inum);
2164       for(int i = 0; i < rnum; i++){
2165         aLog[indexLog].coords[i] = *ir;
2166         //MESSAGE(" "<<i<<" "<<ir.Value());
2167         ir++;
2168       }
2169       for(int i = 0; i < inum; i++){
2170         aLog[indexLog].indexes[i] = *ii;
2171         //MESSAGE(" "<<i<<" "<<ii.Value());
2172         ii++;
2173       }
2174       indexLog++;
2175       its++;
2176     }
2177     if(clearAfterGet)
2178       _impl->ClearLog();
2179   }
2180   catch(SALOME_Exception & S_ex){
2181     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
2182   }
2183   return aLog._retn();
2184 }
2185
2186
2187 //=============================================================================
2188 /*!
2189  *
2190  */
2191 //=============================================================================
2192
2193 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
2194 {
2195   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::ClearLog");
2196   _impl->ClearLog();
2197 }
2198
2199 //=============================================================================
2200 /*!
2201  *
2202  */
2203 //=============================================================================
2204
2205 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
2206 {
2207   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetId");
2208   return _id;
2209 }
2210
2211 //=============================================================================
2212 /*!
2213  *
2214  */
2215 //=============================================================================
2216
2217 CORBA::Long SMESH_Mesh_i::GetStudyId()throw(SALOME::SALOME_Exception)
2218 {
2219   return _studyId;
2220 }
2221
2222 //=============================================================================
2223 namespace
2224 {
2225   //!< implementation of struct used to call SMESH_Mesh_i::removeGroup() from
2226   // SMESH_Mesh::RemoveGroup() (issue 0020918)
2227   struct TRmGroupCallUp_i : public SMESH_Mesh::TRmGroupCallUp
2228   {
2229     SMESH_Mesh_i* _mesh;
2230     TRmGroupCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
2231     virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); }
2232   };
2233 }
2234
2235 //=============================================================================
2236 /*!
2237  *
2238  */
2239 //=============================================================================
2240
2241 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
2242 {
2243   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
2244   _impl = impl;
2245   if ( _impl )
2246     _impl->SetRemoveGroupCallUp( new TRmGroupCallUp_i(this));
2247 }
2248
2249 //=============================================================================
2250 /*!
2251  *
2252  */
2253 //=============================================================================
2254
2255 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
2256 {
2257   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
2258   return *_impl;
2259 }
2260
2261 //=============================================================================
2262 /*!
2263  * Return mesh editor
2264  */
2265 //=============================================================================
2266
2267 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
2268 {
2269   // Create MeshEditor
2270   SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, false );
2271   SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
2272
2273   // Update Python script
2274   TPythonDump() << aMeshEditor << " = " << _this() << ".GetMeshEditor()";
2275
2276   return aMesh._retn();
2277 }
2278
2279 //=============================================================================
2280 /*!
2281  * Return mesh edition previewer
2282  */
2283 //=============================================================================
2284
2285 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
2286 {
2287   SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, true );
2288   SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
2289   return aMesh._retn();
2290 }
2291
2292 //================================================================================
2293 /*!
2294  * \brief Return true if the mesh has been edited since a last total re-compute
2295  *        and those modifications may prevent successful partial re-compute
2296  */
2297 //================================================================================
2298
2299 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard() throw(SALOME::SALOME_Exception)
2300 {
2301   Unexpect aCatch(SALOME_SalomeException);
2302   return _impl->HasModificationsToDiscard();
2303 }
2304
2305 //=============================================================================
2306 /*!
2307  *
2308  */
2309 //=============================================================================
2310 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOME_Exception)
2311 {
2312   Unexpect aCatch(SALOME_SalomeException);
2313   _impl->SetAutoColor(theAutoColor);
2314 }
2315
2316 //=============================================================================
2317 /*!
2318  *
2319  */
2320 //=============================================================================
2321 CORBA::Boolean SMESH_Mesh_i::GetAutoColor() throw(SALOME::SALOME_Exception)
2322 {
2323   Unexpect aCatch(SALOME_SalomeException);
2324   return _impl->GetAutoColor();
2325 }
2326
2327
2328 //=============================================================================
2329 /*!
2330  *  Export in different formats
2331  */
2332 //=============================================================================
2333
2334 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
2335 {
2336   return _impl->HasDuplicatedGroupNamesMED();
2337 }
2338
2339 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
2340 {
2341   TCollection_AsciiString aFullName ((char*)file);
2342   OSD_Path aPath (aFullName);
2343   OSD_File aFile (aPath);
2344   if (aFile.Exists()) {
2345     // existing filesystem node
2346     if (aFile.KindOfFile() == OSD_FILE) {
2347       if (aFile.IsWriteable()) {
2348         if (overwrite) {
2349           aFile.Reset();
2350           aFile.Remove();
2351         }
2352         if (aFile.Failed()) {
2353           TCollection_AsciiString msg ("File ");
2354           msg += aFullName + " cannot be replaced.";
2355           THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2356         }
2357       } else {
2358         TCollection_AsciiString msg ("File ");
2359         msg += aFullName + " cannot be overwritten.";
2360         THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2361       }
2362     } else {
2363       TCollection_AsciiString msg ("Location ");
2364       msg += aFullName + " is not a file.";
2365       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2366     }
2367   } else {
2368     // nonexisting file; check if it can be created
2369     aFile.Reset();
2370     aFile.Build(OSD_WriteOnly, OSD_Protection());
2371     if (aFile.Failed()) {
2372       TCollection_AsciiString msg ("You cannot create the file ");
2373       msg += aFullName + ". Check the directory existance and access rights.";
2374       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2375     } else {
2376       aFile.Close();
2377       aFile.Remove();
2378     }
2379   }
2380 }
2381
2382 void SMESH_Mesh_i::ExportToMEDX (const char* file,
2383                                  CORBA::Boolean auto_groups,
2384                                  SMESH::MED_VERSION theVersion,
2385                                  CORBA::Boolean overwrite)
2386   throw(SALOME::SALOME_Exception)
2387 {
2388   Unexpect aCatch(SALOME_SalomeException);
2389
2390   // Perform Export
2391   PrepareForWriting(file, overwrite);
2392   const char* aMeshName = "Mesh";
2393   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
2394   if ( !aStudy->_is_nil() ) {
2395     SALOMEDS::SObject_var aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
2396     if ( !aMeshSO->_is_nil() ) {
2397       aMeshName = aMeshSO->GetName();
2398       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
2399       if ( !aStudy->GetProperties()->IsLocked() )
2400         {
2401         SALOMEDS::GenericAttribute_var anAttr;
2402         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
2403         SALOMEDS::AttributeExternalFileDef_var aFileName;
2404         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
2405         aFileName = SALOMEDS::AttributeExternalFileDef::_narrow(anAttr);
2406         ASSERT(!aFileName->_is_nil());
2407         aFileName->SetValue(file);
2408         SALOMEDS::AttributeFileType_var aFileType;
2409         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
2410         aFileType = SALOMEDS::AttributeFileType::_narrow(anAttr);
2411         ASSERT(!aFileType->_is_nil());
2412         aFileType->SetValue("FICHIERMED");
2413         }
2414     }
2415   }
2416   // Update Python script
2417   // set name of mesh before export
2418   TPythonDump() << _gen_i << ".SetName(" << _this() << ", '" << aMeshName << "')";
2419   
2420   // check names of groups
2421   checkGroupNames();
2422
2423   TPythonDump() << _this() << ".ExportToMEDX( r'"
2424                 << file << "', " << auto_groups << ", " << theVersion << ", " << overwrite << " )";
2425
2426   _impl->ExportMED( file, aMeshName, auto_groups, theVersion );
2427 }
2428
2429 void SMESH_Mesh_i::ExportToMED (const char* file,
2430                                 CORBA::Boolean auto_groups,
2431                                 SMESH::MED_VERSION theVersion)
2432   throw(SALOME::SALOME_Exception)
2433 {
2434   ExportToMEDX(file,auto_groups,theVersion,true);
2435 }
2436
2437 void SMESH_Mesh_i::ExportMED (const char* file,
2438                               CORBA::Boolean auto_groups)
2439   throw(SALOME::SALOME_Exception)
2440 {
2441   ExportToMEDX(file,auto_groups,SMESH::MED_V2_1,true);
2442 }
2443
2444 void SMESH_Mesh_i::ExportDAT (const char *file)
2445   throw(SALOME::SALOME_Exception)
2446 {
2447   Unexpect aCatch(SALOME_SalomeException);
2448
2449   // Update Python script
2450   // check names of groups
2451   checkGroupNames();
2452   TPythonDump() << _this() << ".ExportDAT( r'" << file << "' )";
2453
2454   // Perform Export
2455   PrepareForWriting(file);
2456   _impl->ExportDAT(file);
2457 }
2458
2459 void SMESH_Mesh_i::ExportUNV (const char *file)
2460   throw(SALOME::SALOME_Exception)
2461 {
2462   Unexpect aCatch(SALOME_SalomeException);
2463
2464   // Update Python script
2465   // check names of groups
2466   checkGroupNames();
2467   TPythonDump() << _this() << ".ExportUNV( r'" << file << "' )";
2468
2469   // Perform Export
2470   PrepareForWriting(file);
2471   _impl->ExportUNV(file);
2472 }
2473
2474 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
2475   throw(SALOME::SALOME_Exception)
2476 {
2477   Unexpect aCatch(SALOME_SalomeException);
2478
2479   // Update Python script
2480   // check names of groups
2481   checkGroupNames();
2482   TPythonDump() << _this() << ".ExportSTL( r'" << file << "', " << isascii << " )";
2483
2484   // Perform Export
2485   PrepareForWriting(file);
2486   _impl->ExportSTL(file, isascii);
2487 }
2488
2489 //=============================================================================
2490 /*!
2491  *
2492  */
2493 //=============================================================================
2494
2495 SALOME_MED::MESH_ptr SMESH_Mesh_i::GetMEDMesh()throw(SALOME::SALOME_Exception)
2496 {
2497   Unexpect aCatch(SALOME_SalomeException);
2498   SMESH_MEDMesh_i *aMedMesh = new SMESH_MEDMesh_i(this);
2499   SALOME_MED::MESH_var aMesh = aMedMesh->_this();
2500   return aMesh._retn();
2501 }
2502
2503 //=============================================================================
2504 /*!
2505  *
2506  */
2507 //=============================================================================
2508 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
2509 {
2510   Unexpect aCatch(SALOME_SalomeException);
2511   return _impl->NbNodes();
2512 }
2513
2514 //=============================================================================
2515 /*!
2516  *
2517  */
2518 //=============================================================================
2519 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
2520 {
2521   Unexpect aCatch(SALOME_SalomeException);
2522   return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes();
2523 }
2524
2525 //=============================================================================
2526 /*!
2527  *
2528  */
2529 //=============================================================================
2530 CORBA::Long SMESH_Mesh_i::Nb0DElements()throw (SALOME::SALOME_Exception)
2531 {
2532   Unexpect aCatch(SALOME_SalomeException);
2533   return _impl->Nb0DElements();
2534 }
2535
2536 //=============================================================================
2537 /*!
2538  *
2539  */
2540 //=============================================================================
2541 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
2542 {
2543   Unexpect aCatch(SALOME_SalomeException);
2544   return _impl->NbEdges();
2545 }
2546
2547 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
2548   throw(SALOME::SALOME_Exception)
2549 {
2550   Unexpect aCatch(SALOME_SalomeException);
2551   return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
2552 }
2553
2554 //=============================================================================
2555 /*!
2556  *
2557  */
2558 //=============================================================================
2559 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
2560 {
2561   Unexpect aCatch(SALOME_SalomeException);
2562   return _impl->NbFaces();
2563 }
2564
2565 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
2566 {
2567   Unexpect aCatch(SALOME_SalomeException);
2568   return _impl->NbTriangles();
2569 }
2570
2571 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
2572 {
2573   Unexpect aCatch(SALOME_SalomeException);
2574   return _impl->NbQuadrangles();
2575 }
2576
2577 CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
2578 {
2579   Unexpect aCatch(SALOME_SalomeException);
2580   return _impl->NbPolygons();
2581 }
2582
2583 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
2584   throw(SALOME::SALOME_Exception)
2585 {
2586   Unexpect aCatch(SALOME_SalomeException);
2587   return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
2588 }
2589
2590 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
2591   throw(SALOME::SALOME_Exception)
2592 {
2593   Unexpect aCatch(SALOME_SalomeException);
2594   return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
2595 }
2596
2597 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
2598   throw(SALOME::SALOME_Exception)
2599 {
2600   Unexpect aCatch(SALOME_SalomeException);
2601   return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
2602 }
2603
2604 //=============================================================================
2605 /*!
2606  *
2607  */
2608 //=============================================================================
2609 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
2610 {
2611   Unexpect aCatch(SALOME_SalomeException);
2612   return _impl->NbVolumes();
2613 }
2614
2615 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
2616 {
2617   Unexpect aCatch(SALOME_SalomeException);
2618   return _impl->NbTetras();
2619 }
2620
2621 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
2622 {
2623   Unexpect aCatch(SALOME_SalomeException);
2624   return _impl->NbHexas();
2625 }
2626
2627 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
2628 {
2629   Unexpect aCatch(SALOME_SalomeException);
2630   return _impl->NbPyramids();
2631 }
2632
2633 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
2634 {
2635   Unexpect aCatch(SALOME_SalomeException);
2636   return _impl->NbPrisms();
2637 }
2638
2639 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
2640 {
2641   Unexpect aCatch(SALOME_SalomeException);
2642   return _impl->NbPolyhedrons();
2643 }
2644
2645 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
2646   throw(SALOME::SALOME_Exception)
2647 {
2648   Unexpect aCatch(SALOME_SalomeException);
2649   return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
2650 }
2651
2652 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
2653   throw(SALOME::SALOME_Exception)
2654 {
2655   Unexpect aCatch(SALOME_SalomeException);
2656   return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
2657 }
2658
2659 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
2660   throw(SALOME::SALOME_Exception)
2661 {
2662   Unexpect aCatch(SALOME_SalomeException);
2663   return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
2664 }
2665
2666 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
2667   throw(SALOME::SALOME_Exception)
2668 {
2669   Unexpect aCatch(SALOME_SalomeException);
2670   return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
2671 }
2672
2673 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
2674   throw(SALOME::SALOME_Exception)
2675 {
2676   Unexpect aCatch(SALOME_SalomeException);
2677   return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
2678 }
2679
2680 //=============================================================================
2681 /*!
2682  *
2683  */
2684 //=============================================================================
2685 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
2686 {
2687   Unexpect aCatch(SALOME_SalomeException);
2688   return _mapSubMesh_i.size();
2689 }
2690
2691 //=============================================================================
2692 /*!
2693  *
2694  */
2695 //=============================================================================
2696 char* SMESH_Mesh_i::Dump()
2697 {
2698   ostringstream os;
2699   _impl->Dump( os );
2700   return CORBA::string_dup( os.str().c_str() );
2701 }
2702
2703 //=============================================================================
2704 /*!
2705  *
2706  */
2707 //=============================================================================
2708 SMESH::long_array* SMESH_Mesh_i::GetIDs()
2709 {
2710 //   SMESH::long_array_var aResult = new SMESH::long_array();
2711 //   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2712 //   int aMinId = aSMESHDS_Mesh->MinElementID();
2713 //   int aMaxId =  aSMESHDS_Mesh->MaxElementID();
2714
2715 //   aResult->length(aMaxId - aMinId + 1);
2716
2717 //   for (int i = 0, id = aMinId; id <= aMaxId; id++  )
2718 //     aResult[i++] = id;
2719
2720 //   return aResult._retn();
2721   // PAL12398
2722   return GetElementsId();
2723 }
2724
2725 //=============================================================================
2726 /*!
2727  *
2728  */
2729 //=============================================================================
2730
2731 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
2732      throw (SALOME::SALOME_Exception)
2733 {
2734   Unexpect aCatch(SALOME_SalomeException);
2735   MESSAGE("SMESH_Mesh_i::GetElementsId");
2736   SMESH::long_array_var aResult = new SMESH::long_array();
2737   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2738
2739   if ( aSMESHDS_Mesh == NULL )
2740     return aResult._retn();
2741
2742   long nbElements = NbElements();
2743   aResult->length( nbElements );
2744   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
2745   for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
2746     aResult[i] = anIt->next()->GetID();
2747
2748   return aResult._retn();
2749 }
2750
2751
2752 //=============================================================================
2753 /*!
2754  *
2755  */
2756 //=============================================================================
2757
2758 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
2759     throw (SALOME::SALOME_Exception)
2760 {
2761   Unexpect aCatch(SALOME_SalomeException);
2762   MESSAGE("SMESH_subMesh_i::GetElementsByType");
2763   SMESH::long_array_var aResult = new SMESH::long_array();
2764   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2765
2766   if ( aSMESHDS_Mesh == NULL )
2767     return aResult._retn();
2768
2769   long nbElements = NbElements();
2770
2771   // No sense in returning ids of elements along with ids of nodes:
2772   // when theElemType == SMESH::ALL, return node ids only if
2773   // there are no elements
2774   if ( theElemType == SMESH::NODE || theElemType == SMESH::ALL && nbElements == 0 )
2775     return GetNodesId();
2776
2777   aResult->length( nbElements );
2778
2779   int i = 0;
2780
2781   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
2782   while ( i < nbElements && anIt->more() ) {
2783     const SMDS_MeshElement* anElem = anIt->next();
2784     if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
2785       aResult[i++] = anElem->GetID();
2786   }
2787
2788   aResult->length( i );
2789
2790   return aResult._retn();
2791 }
2792
2793 //=============================================================================
2794 /*!
2795  *
2796  */
2797 //=============================================================================
2798
2799 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
2800   throw (SALOME::SALOME_Exception)
2801 {
2802   Unexpect aCatch(SALOME_SalomeException);
2803   MESSAGE("SMESH_subMesh_i::GetNodesId");
2804   SMESH::long_array_var aResult = new SMESH::long_array();
2805   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2806
2807   if ( aSMESHDS_Mesh == NULL )
2808     return aResult._retn();
2809
2810   long nbNodes = NbNodes();
2811   aResult->length( nbNodes );
2812   SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator(/*idInceasingOrder=*/true);
2813   for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
2814     aResult[i] = anIt->next()->GetID();
2815
2816   return aResult._retn();
2817 }
2818
2819 //=============================================================================
2820 /*!
2821  *
2822  */
2823 //=============================================================================
2824
2825 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
2826   throw (SALOME::SALOME_Exception)
2827 {
2828   return ( SMESH::ElementType )_impl->GetElementType( id, iselem );
2829 }
2830
2831 //=============================================================================
2832 /*!
2833  *
2834  */
2835 //=============================================================================
2836
2837 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id )
2838   throw (SALOME::SALOME_Exception)
2839 {
2840   const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
2841   if ( !e )
2842     THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
2843
2844   return ( SMESH::EntityType ) e->GetEntityType();
2845 }
2846
2847 //=============================================================================
2848 /*!
2849  * Returns ID of elements for given submesh
2850  */
2851 //=============================================================================
2852 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
2853      throw (SALOME::SALOME_Exception)
2854 {
2855   SMESH::long_array_var aResult = new SMESH::long_array();
2856
2857   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2858   if(!SM) return aResult._retn();
2859
2860   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2861   if(!SDSM) return aResult._retn();
2862
2863   aResult->length(SDSM->NbElements());
2864
2865   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2866   int i = 0;
2867   while ( eIt->more() ) {
2868     aResult[i++] = eIt->next()->GetID();
2869   }
2870
2871   return aResult._retn();
2872 }
2873
2874
2875 //=============================================================================
2876 /*!
2877  * Returns ID of nodes for given submesh
2878  * If param all==true - returns all nodes, else -
2879  * returns only nodes on shapes.
2880  */
2881 //=============================================================================
2882 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID, CORBA::Boolean all)
2883      throw (SALOME::SALOME_Exception)
2884 {
2885   SMESH::long_array_var aResult = new SMESH::long_array();
2886
2887   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2888   if(!SM) return aResult._retn();
2889
2890   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2891   if(!SDSM) return aResult._retn();
2892
2893   set<int> theElems;
2894   if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
2895     SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
2896     while ( nIt->more() ) {
2897       const SMDS_MeshNode* elem = nIt->next();
2898       theElems.insert( elem->GetID() );
2899     }
2900   }
2901   else { // all nodes of submesh elements
2902     SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2903     while ( eIt->more() ) {
2904       const SMDS_MeshElement* anElem = eIt->next();
2905       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
2906       while ( nIt->more() ) {
2907         const SMDS_MeshElement* elem = nIt->next();
2908         theElems.insert( elem->GetID() );
2909       }
2910     }
2911   }
2912
2913   aResult->length(theElems.size());
2914   set<int>::iterator itElem;
2915   int i = 0;
2916   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
2917     aResult[i++] = *itElem;
2918
2919   return aResult._retn();
2920 }
2921   
2922
2923 //=============================================================================
2924 /*!
2925  * Returns type of elements for given submesh
2926  */
2927 //=============================================================================
2928 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
2929      throw (SALOME::SALOME_Exception)
2930 {
2931   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
2932   if(!SM) return SMESH::ALL;
2933
2934   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
2935   if(!SDSM) return SMESH::ALL;
2936
2937   if(SDSM->NbElements()==0)
2938     return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
2939
2940   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
2941   const SMDS_MeshElement* anElem = eIt->next();
2942   return ( SMESH::ElementType ) anElem->GetType();
2943 }
2944   
2945
2946 //=============================================================================
2947 /*!
2948  *
2949  */
2950 //=============================================================================
2951
2952 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
2953 {
2954   CORBA::LongLong pointeur = CORBA::LongLong(_impl);
2955   if ( MYDEBUG )
2956     MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
2957   return pointeur;
2958 }
2959
2960
2961 //=============================================================================
2962 /*!
2963  * Get XYZ coordinates of node as list of double
2964  * If there is not node for given ID - returns empty list
2965  */
2966 //=============================================================================
2967
2968 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
2969 {
2970   SMESH::double_array_var aResult = new SMESH::double_array();
2971   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2972   if ( aSMESHDS_Mesh == NULL )
2973     return aResult._retn();
2974
2975   // find node
2976   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2977   if(!aNode)
2978     return aResult._retn();
2979
2980   // add coordinates
2981   aResult->length(3);
2982   aResult[0] = aNode->X();
2983   aResult[1] = aNode->Y();
2984   aResult[2] = aNode->Z();
2985   return aResult._retn();
2986 }
2987
2988
2989 //=============================================================================
2990 /*!
2991  * For given node returns list of IDs of inverse elements
2992  * If there is not node for given ID - returns empty list
2993  */
2994 //=============================================================================
2995
2996 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
2997 {
2998   SMESH::long_array_var aResult = new SMESH::long_array();
2999   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3000   if ( aSMESHDS_Mesh == NULL )
3001     return aResult._retn();
3002
3003   // find node
3004   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3005   if(!aNode)
3006     return aResult._retn();
3007
3008   // find inverse elements
3009   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
3010   TColStd_SequenceOfInteger IDs;
3011   while(eIt->more()) {
3012     const SMDS_MeshElement* elem = eIt->next();
3013     IDs.Append(elem->GetID());
3014   }
3015   if(IDs.Length()>0) {
3016     aResult->length(IDs.Length());
3017     int i = 1;
3018     for(; i<=IDs.Length(); i++) {
3019       aResult[i-1] = IDs.Value(i);
3020     }
3021   }
3022   return aResult._retn();
3023 }
3024
3025 //=============================================================================
3026 /*!
3027  * \brief Return position of a node on shape
3028  */
3029 //=============================================================================
3030
3031 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
3032 {
3033   SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
3034   aNodePosition->shapeID = 0;
3035   aNodePosition->shapeType = GEOM::SHAPE;
3036
3037   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
3038   if ( !mesh ) return aNodePosition;
3039
3040   if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
3041   {
3042     if ( SMDS_PositionPtr pos = aNode->GetPosition() )
3043     {
3044       aNodePosition->shapeID = aNode->getshapeId();
3045       switch ( pos->GetTypeOfPosition() ) {
3046       case SMDS_TOP_EDGE:
3047         aNodePosition->shapeType = GEOM::EDGE;
3048         aNodePosition->params.length(1);
3049         aNodePosition->params[0] =
3050           static_cast<SMDS_EdgePosition*>( pos )->GetUParameter();
3051         break;
3052       case SMDS_TOP_FACE:
3053         aNodePosition->shapeType = GEOM::FACE;
3054         aNodePosition->params.length(2);
3055         aNodePosition->params[0] =
3056           static_cast<SMDS_FacePosition*>( pos )->GetUParameter();
3057         aNodePosition->params[1] =
3058           static_cast<SMDS_FacePosition*>( pos )->GetVParameter();
3059         break;
3060       case SMDS_TOP_VERTEX:
3061         aNodePosition->shapeType = GEOM::VERTEX;
3062         break;
3063       case SMDS_TOP_3DSPACE:
3064         if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
3065           aNodePosition->shapeType = GEOM::SOLID;
3066         else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
3067           aNodePosition->shapeType = GEOM::SHELL;
3068         break;
3069       default:;
3070       }
3071     }
3072   }
3073   return aNodePosition;
3074 }
3075
3076 //=============================================================================
3077 /*!
3078  * If given element is node returns IDs of shape from position
3079  * If there is not node for given ID - returns -1
3080  */
3081 //=============================================================================
3082
3083 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
3084 {
3085   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3086   if ( aSMESHDS_Mesh == NULL )
3087     return -1;
3088
3089   // try to find node
3090   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3091   if(aNode) {
3092     return aNode->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 }