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