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