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