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