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