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