Salome HOME
f2e1ca4c83c1494ddf71d2d2d2e78f79b2963c10
[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   // shape index in SMESHDS
1713   // TopoDS_Shape shape = _gen_i->GeomObjectToShape( theGeomObj );
1714   // groupData._dsID = shape.IsNull() ? 0 : _impl->GetSubMesh( shape )->GetId();
1715 }
1716
1717 //================================================================================
1718 /*!
1719  * Remove GEOM group data relating to removed smesh object
1720  */
1721 //================================================================================
1722
1723 void SMESH_Mesh_i::removeGeomGroupData(CORBA::Object_ptr theSmeshObj)
1724 {
1725   list<TGeomGroupData>::iterator
1726     data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
1727   for ( ; data != dataEnd; ++data ) {
1728     if ( theSmeshObj->_is_equivalent( data->_smeshObject )) {
1729       _geomGroupData.erase( data );
1730       return;
1731     }
1732   }
1733 }
1734
1735 //================================================================================
1736 /*!
1737  * \brief Return new group contents if it has been changed and update group data
1738  */
1739 //================================================================================
1740
1741 TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData)
1742 {
1743   TopoDS_Shape newShape;
1744
1745   // get geom group
1746   SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1747   if ( study->_is_nil() ) return newShape; // means "not changed"
1748   SALOMEDS::SObject_wrap groupSO = study->FindObjectID( groupData._groupEntry.c_str() );
1749   if ( !groupSO->_is_nil() )
1750   {
1751     CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO );
1752     if ( CORBA::is_nil( groupObj )) return newShape;
1753     GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj );
1754
1755     // get indices of group items
1756     set<int> curIndices;
1757     GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
1758     GEOM::GEOM_IGroupOperations_wrap groupOp =
1759       geomGen->GetIGroupOperations( _gen_i->GetCurrentStudyID() );
1760     GEOM::ListOfLong_var   ids = groupOp->GetObjects( geomGroup );
1761     for ( int i = 0; i < ids->length(); ++i )
1762       curIndices.insert( ids[i] );
1763
1764     if ( groupData._indices == curIndices )
1765       return newShape; // group not changed
1766
1767     // update data
1768     groupData._indices = curIndices;
1769
1770     GEOM_Client* geomClient = _gen_i->GetShapeReader();
1771     if ( !geomClient ) return newShape;
1772     CORBA::String_var groupIOR = geomGen->GetStringFromIOR( geomGroup );
1773     geomClient->RemoveShapeFromBuffer( groupIOR.in() );
1774     newShape = _gen_i->GeomObjectToShape( geomGroup );
1775   }
1776
1777   if ( newShape.IsNull() ) {
1778     // geom group becomes empty - return empty compound
1779     TopoDS_Compound compound;
1780     BRep_Builder().MakeCompound(compound);
1781     newShape = compound;
1782   }
1783   return newShape;
1784 }
1785
1786 namespace
1787 {
1788   //-----------------------------------------------------------------------------
1789   /*!
1790    * \brief Storage of shape and index used in CheckGeomGroupModif()
1791    */
1792   struct TIndexedShape
1793   {
1794     int          _index;
1795     TopoDS_Shape _shape;
1796     TIndexedShape( int i, const TopoDS_Shape& s ):_index(i), _shape(s) {}
1797   };
1798   //-----------------------------------------------------------------------------
1799   /*!
1800    * \brief Data to re-create a group on geometry
1801    */
1802   struct TGroupOnGeomData
1803   {
1804     int                 _oldID;
1805     int                 _shapeID;
1806     SMDSAbs_ElementType _type;
1807     std::string         _name;
1808     Quantity_Color      _color;
1809   };
1810 }
1811
1812 //=============================================================================
1813 /*!
1814  * \brief Update data if geometry changes
1815  *
1816  * Issue 0022501
1817  */
1818 //=============================================================================
1819
1820 void SMESH_Mesh_i::CheckGeomModif()
1821 {
1822   if ( !_impl->HasShapeToMesh() ) return;
1823
1824   SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1825   if ( study->_is_nil() ) return;
1826
1827   GEOM::GEOM_Object_var mainGO = _gen_i->ShapeToGeomObject( _impl->GetShapeToMesh() );
1828   if ( mainGO->_is_nil() ) return;
1829
1830   if ( mainGO->GetType() == GEOM_GROUP ||
1831        mainGO->GetTick() == _mainShapeTick )
1832   {
1833     CheckGeomGroupModif();
1834     return;
1835   }
1836
1837   GEOM_Client* geomClient = _gen_i->GetShapeReader();
1838   if ( !geomClient ) return;
1839   GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
1840   if ( geomGen->_is_nil() ) return;
1841
1842   CORBA::String_var ior = geomGen->GetStringFromIOR( mainGO );
1843   geomClient->RemoveShapeFromBuffer( ior.in() );
1844
1845   // Update data taking into account that
1846   // all sub-shapes change but IDs of sub-shapes remain (except for geom groups)
1847
1848   _impl->Clear();
1849   TopoDS_Shape newShape = _gen_i->GeomObjectToShape( mainGO );
1850   if ( newShape.IsNull() )
1851     return;
1852
1853   _mainShapeTick = mainGO->GetTick();
1854
1855   SMESHDS_Mesh * meshDS = _impl->GetMeshDS();
1856
1857   // store data of groups on geometry
1858   vector< TGroupOnGeomData > groupsData;
1859   const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
1860   groupsData.reserve( groups.size() );
1861   set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
1862   for ( ; g != groups.end(); ++g )
1863     if ( const SMESHDS_GroupOnGeom* group = dynamic_cast< SMESHDS_GroupOnGeom* >( *g ))
1864     {
1865       TGroupOnGeomData data;
1866       data._oldID   = group->GetID();
1867       data._shapeID = meshDS->ShapeToIndex( group->GetShape() );
1868       data._type    = group->GetType();
1869       data._name    = group->GetStoreName();
1870       data._color   = group->GetColor();
1871       groupsData.push_back( data );
1872     }
1873   // store assigned hypotheses
1874   vector< pair< int, THypList > > ids2Hyps;
1875   const ShapeToHypothesis & hyps = meshDS->GetHypotheses();
1876   for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() )
1877   {
1878     const TopoDS_Shape& s = s2hyps.Key();
1879     const THypList&  hyps = s2hyps.ChangeValue();
1880     ids2Hyps.push_back( make_pair( meshDS->ShapeToIndex( s ), hyps ));
1881   }
1882
1883   // change shape to mesh
1884   int oldNbSubShapes = meshDS->MaxShapeIndex();
1885   _impl->ShapeToMesh( TopoDS_Shape() );
1886   _impl->ShapeToMesh( newShape );
1887
1888   // re-add shapes of geom groups
1889   list<TGeomGroupData>::iterator data = _geomGroupData.begin();
1890   for ( ; data != _geomGroupData.end(); ++data )
1891   {
1892     TopoDS_Shape newShape = newGroupShape( *data );
1893     if ( !newShape.IsNull() )
1894     {
1895       if ( meshDS->ShapeToIndex( newShape ) > 0 ) // a group reduced to one sub-shape
1896       {
1897         TopoDS_Compound compound;
1898         BRep_Builder().MakeCompound( compound );
1899         BRep_Builder().Add( compound, newShape );
1900         newShape = compound;
1901       }
1902       _impl->GetSubMesh( newShape );
1903     }
1904   }
1905   if ( oldNbSubShapes != meshDS->MaxShapeIndex() )
1906     THROW_SALOME_CORBA_EXCEPTION( "SMESH_Mesh_i::CheckGeomModif() bug",
1907                                   SALOME::INTERNAL_ERROR );
1908
1909   // re-assign hypotheses
1910   for ( size_t i = 0; i < ids2Hyps.size(); ++i )
1911   {
1912     const TopoDS_Shape& s = meshDS->IndexToShape( ids2Hyps[i].first );
1913     const THypList&  hyps = ids2Hyps[i].second;
1914     THypList::const_iterator h = hyps.begin();
1915     for ( ; h != hyps.end(); ++h )
1916       _impl->AddHypothesis( s, (*h)->GetID() );
1917   }
1918
1919   // restore groups
1920   for ( size_t i = 0; i < groupsData.size(); ++i )
1921   {
1922     const TGroupOnGeomData& data = groupsData[i];
1923
1924     map<int, SMESH::SMESH_GroupBase_ptr>::iterator i2g = _mapGroups.find( data._oldID );
1925     if ( i2g == _mapGroups.end() ) continue;
1926
1927     SMESH_GroupBase_i* gr_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2g->second );
1928     if ( !gr_i ) continue;
1929
1930     int id;
1931     SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), id,
1932                                       meshDS->IndexToShape( data._shapeID ));
1933     if ( !g )
1934     {
1935       _mapGroups.erase( i2g );
1936     }
1937     else
1938     {
1939       g->GetGroupDS()->SetColor( data._color );
1940       gr_i->changeLocalId( id );
1941       _mapGroups[ id ] = i2g->second;
1942       if ( data._oldID != id )
1943         _mapGroups.erase( i2g );
1944     }
1945   }
1946
1947   // update _mapSubMesh
1948   map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
1949   for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
1950     i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first ));
1951
1952 }
1953
1954 //=============================================================================
1955 /*!
1956  * \brief Update objects depending on changed geom groups
1957  *
1958  * NPAL16168: geometrical group edition from a submesh don't modifiy mesh computation
1959  * issue 0020210: Update of a smesh group after modification of the associated geom group
1960  */
1961 //=============================================================================
1962
1963 void SMESH_Mesh_i::CheckGeomGroupModif()
1964 {
1965   if ( !_impl->HasShapeToMesh() ) return;
1966
1967   SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1968   if ( study->_is_nil() ) return;
1969
1970   CORBA::Long nbEntities = NbNodes() + NbElements();
1971
1972   // Check if group contents changed
1973
1974   typedef map< string, TopoDS_Shape > TEntry2Geom;
1975   TEntry2Geom newGroupContents;
1976
1977   list<TGeomGroupData>::iterator
1978     data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
1979   for ( ; data != dataEnd; ++data )
1980   {
1981     pair< TEntry2Geom::iterator, bool > it_new =
1982       newGroupContents.insert( make_pair( data->_groupEntry, TopoDS_Shape() ));
1983     bool processedGroup    = !it_new.second;
1984     TopoDS_Shape& newShape = it_new.first->second;
1985     if ( !processedGroup )
1986       newShape = newGroupShape( *data );
1987     if ( newShape.IsNull() )
1988       continue; // no changes
1989
1990     if ( _preMeshInfo )
1991       _preMeshInfo->ForgetOrLoad();
1992
1993     if ( processedGroup ) { // update group indices
1994       list<TGeomGroupData>::iterator data2 = data;
1995       for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) {}
1996       data->_indices = data2->_indices;
1997     }
1998
1999     // Update SMESH objects according to new GEOM group contents
2000
2001     SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject );
2002     if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
2003     {
2004       int oldID = submesh->GetId();
2005       if ( !_mapSubMeshIor.count( oldID ))
2006         continue;
2007       TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
2008
2009       // update hypotheses
2010       list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldShape);
2011       list <const SMESHDS_Hypothesis * >::iterator hypIt;
2012       for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2013       {
2014         _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2015         _impl->AddHypothesis   ( newShape, (*hypIt)->GetID());
2016       }
2017       // care of submeshes
2018       SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newShape );
2019       int newID = newSubmesh->GetId();
2020       if ( newID != oldID ) {
2021         _mapSubMesh   [ newID ] = newSubmesh;
2022         _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2023         _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2024         _mapSubMesh.   erase(oldID);
2025         _mapSubMesh_i. erase(oldID);
2026         _mapSubMeshIor.erase(oldID);
2027         _mapSubMesh_i [ newID ]->changeLocalId( newID );
2028       }
2029       continue;
2030     }
2031
2032     SMESH::SMESH_GroupOnGeom_var smeshGroup =
2033       SMESH::SMESH_GroupOnGeom::_narrow( data->_smeshObject );
2034     if ( !smeshGroup->_is_nil() ) // ------------ GROUP -----------------------
2035     {
2036       SMESH_GroupOnGeom_i* group_i = SMESH::DownCast<SMESH_GroupOnGeom_i*>( smeshGroup );
2037       if ( group_i ) {
2038         ::SMESH_Group* group = _impl->GetGroup( group_i->GetLocalID() );
2039         SMESHDS_GroupOnGeom* ds = static_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() );
2040         ds->SetShape( newShape );
2041       }
2042       continue;
2043     }
2044
2045     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject );
2046     if ( !mesh->_is_nil() ) // -------------- MESH ----------------------------
2047     {
2048       // Remove groups and submeshes basing on removed sub-shapes
2049
2050       TopTools_MapOfShape newShapeMap;
2051       TopoDS_Iterator shapeIt( newShape );
2052       for ( ; shapeIt.More(); shapeIt.Next() )
2053         newShapeMap.Add( shapeIt.Value() );
2054
2055       SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2056       for ( shapeIt.Initialize( meshDS->ShapeToMesh() ); shapeIt.More(); shapeIt.Next() )
2057       {
2058         if ( newShapeMap.Contains( shapeIt.Value() ))
2059           continue;
2060         TopTools_IndexedMapOfShape oldShapeMap;
2061         TopExp::MapShapes( shapeIt.Value(), oldShapeMap );
2062         for ( int i = 1; i <= oldShapeMap.Extent(); ++i )
2063         {
2064           const TopoDS_Shape& oldShape = oldShapeMap(i);
2065           int oldInd = meshDS->ShapeToIndex( oldShape );
2066           // -- submeshes --
2067           map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldInd );
2068           if ( i_smIor != _mapSubMeshIor.end() ) {
2069             RemoveSubMesh( i_smIor->second ); // one submesh per shape index
2070           }
2071           // --- groups ---
2072           map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
2073           for ( ; i_grp != _mapGroups.end(); ++i_grp )
2074           {
2075             // check if a group bases on oldInd shape
2076             SMESHDS_GroupOnGeom* grpOnGeom = 0;
2077             if ( ::SMESH_Group* g = _impl->GetGroup( i_grp->first ))
2078               grpOnGeom = dynamic_cast<SMESHDS_GroupOnGeom*>( g->GetGroupDS() );
2079             if ( grpOnGeom && oldShape.IsSame( grpOnGeom->GetShape() ))
2080             { // remove
2081               RemoveGroup( i_grp->second ); // several groups can base on same shape
2082               i_grp = _mapGroups.begin(); // _mapGroups changed - restart iteration
2083             }
2084           }
2085         }
2086       }
2087       // Reassign hypotheses and update groups after setting the new shape to mesh
2088
2089       // collect anassigned hypotheses
2090       typedef list< pair< TIndexedShape, list<const SMESHDS_Hypothesis*> > > TShapeHypList;
2091       list <const SMESHDS_Hypothesis * >::const_iterator hypIt;
2092       TShapeHypList assignedHyps;
2093       for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i )
2094       {
2095         const TopoDS_Shape& oldShape = meshDS->IndexToShape(i);
2096         list<const SMESHDS_Hypothesis*> hyps = meshDS->GetHypothesis( oldShape );// copy
2097         if ( !hyps.empty() ) {
2098           assignedHyps.push_back( make_pair( TIndexedShape(i,oldShape), hyps ));
2099           for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2100             _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2101         }
2102       }
2103       // collect shapes supporting groups
2104       typedef list < pair< TIndexedShape, SMDSAbs_ElementType > > TShapeTypeList;
2105       TShapeTypeList groupData;
2106       const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2107       set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
2108       for ( ; grIt != groups.end(); ++grIt )
2109       {
2110         if ( SMESHDS_GroupOnGeom* gog = dynamic_cast<SMESHDS_GroupOnGeom*>( *grIt ))
2111           groupData.push_back
2112             ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
2113       }
2114       // set new shape to mesh -> DS of submeshes and geom groups is deleted
2115       _impl->ShapeToMesh( newShape );
2116       
2117       // reassign hypotheses
2118       TShapeHypList::iterator indS_hyps = assignedHyps.begin();
2119       for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
2120       {
2121         TIndexedShape&                   geom = indS_hyps->first;
2122         list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
2123         int oldID = geom._index;
2124         int newID = meshDS->ShapeToIndex( geom._shape );
2125         if ( oldID == 1 ) { // main shape
2126           newID = 1;
2127           geom._shape = newShape;
2128         }
2129         if ( !newID )
2130           continue;
2131         for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2132           _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
2133         // care of submeshes
2134         SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
2135         if ( newID != oldID ) {
2136           _mapSubMesh   [ newID ] = newSubmesh;
2137           _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2138           _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2139           _mapSubMesh.   erase(oldID);
2140           _mapSubMesh_i. erase(oldID);
2141           _mapSubMeshIor.erase(oldID);
2142           _mapSubMesh_i [ newID ]->changeLocalId( newID );
2143         }
2144       }
2145       // recreate groups
2146       TShapeTypeList::iterator geomType = groupData.begin();
2147       for ( ; geomType != groupData.end(); ++geomType )
2148       {
2149         const TIndexedShape& geom = geomType->first;
2150         int oldID = geom._index;
2151         if ( _mapGroups.find( oldID ) == _mapGroups.end() )
2152           continue;
2153         // get group name
2154         SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( study,_mapGroups[oldID] );
2155         CORBA::String_var      name    = groupSO->GetName();
2156         // update
2157         SMESH_GroupBase_i*  group_i    = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID] );
2158         int newID;
2159         if ( group_i && _impl->AddGroup( geomType->second, name.in(), newID, geom._shape ))
2160           group_i->changeLocalId( newID );
2161       }
2162
2163       break; // everything has been updated
2164
2165     } // update mesh
2166   } // loop on group data
2167
2168   // Update icons
2169
2170   CORBA::Long newNbEntities = NbNodes() + NbElements();
2171   list< SALOMEDS::SObject_wrap > soToUpdateIcons;
2172   if ( newNbEntities != nbEntities )
2173   {
2174     // Add all SObjects with icons to soToUpdateIcons
2175     soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, _this() )); // mesh
2176
2177     for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
2178          i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
2179       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, i_sm->second ));
2180
2181     for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
2182           i_gr != _mapGroups.end(); ++i_gr ) // groups
2183       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, i_gr->second ));
2184   }
2185
2186   list< SALOMEDS::SObject_wrap >::iterator so = soToUpdateIcons.begin();
2187   for ( ; so != soToUpdateIcons.end(); ++so )
2188     _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
2189 }
2190
2191 //=============================================================================
2192 /*!
2193  * \brief Create standalone group from a group on geometry or filter
2194  */
2195 //=============================================================================
2196
2197 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase_ptr theGroup )
2198   throw (SALOME::SALOME_Exception)
2199 {
2200   SMESH::SMESH_Group_var aGroup;
2201
2202   SMESH_TRY;
2203
2204   if ( _preMeshInfo )
2205     _preMeshInfo->FullLoadFromFile();
2206
2207   if ( theGroup->_is_nil() )
2208     return aGroup._retn();
2209
2210   SMESH_GroupBase_i* aGroupToRem = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
2211   if ( !aGroupToRem )
2212     return aGroup._retn();
2213
2214   const bool isOnFilter = ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ));
2215
2216   const int anId = aGroupToRem->GetLocalID();
2217   if ( !_impl->ConvertToStandalone( anId ) )
2218     return aGroup._retn();
2219   removeGeomGroupData( theGroup );
2220
2221   SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2222
2223   // remove old instance of group from own map
2224   { SMESH::SMESH_GroupBase_var var( _mapGroups[anId] ); } // decref CORBA object
2225   _mapGroups.erase( anId );
2226
2227   SALOMEDS::StudyBuilder_var builder;
2228   SALOMEDS::SObject_wrap     aGroupSO;
2229   SALOMEDS::Study_var        aStudy = _gen_i->GetCurrentStudy();
2230   if ( !aStudy->_is_nil() ) {
2231     builder  = aStudy->NewBuilder();
2232     aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
2233     if ( !aGroupSO->_is_nil() )
2234     {
2235       // remove reference to geometry
2236       SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO);
2237       for ( ; chItr->More(); chItr->Next() )
2238         // Remove group's child SObject
2239         builder->RemoveObject( chItr->Value() );
2240
2241       // Update Python script
2242       TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this())
2243                     << ".ConvertToStandalone( " << aGroupSO << " )";
2244
2245       // change icon of Group on Filter
2246       if ( isOnFilter )
2247       {
2248         SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
2249         const int isEmpty = ( elemTypes->length() == 0 );
2250         if ( !isEmpty )
2251         {
2252           SALOMEDS::GenericAttribute_wrap anAttr =
2253             builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
2254           SALOMEDS::AttributePixMap_wrap pm = anAttr;
2255           pm->SetPixMap( "ICON_SMESH_TREE_GROUP" );
2256         }
2257       }
2258     }
2259   }
2260
2261   // remember new group in own map
2262   aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
2263   _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2264
2265   // register CORBA object for persistence
2266   _gen_i->RegisterObject( aGroup );
2267
2268   CORBA::String_var ior = _gen_i->GetORB()->object_to_string( aGroup );
2269   builder->SetIOR( aGroupSO, ior.in() ); //  == aGroup->Register();
2270   //aGroup->Register();
2271   aGroupToRem->UnRegister();
2272
2273   SMESH_CATCH( SMESH::throwCorbaException );
2274
2275   return aGroup._retn();
2276 }
2277
2278 //=============================================================================
2279 /*!
2280  *
2281  */
2282 //=============================================================================
2283
2284 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
2285 {
2286   if(MYDEBUG) MESSAGE( "createSubMesh" );
2287   TopoDS_Shape  myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
2288   ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
2289   const int         subMeshId = mySubMesh->GetId();
2290
2291   SMESH_subMesh_i * subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
2292   SMESH::SMESH_subMesh_var subMesh = subMeshServant->_this();
2293
2294   _mapSubMesh   [subMeshId] = mySubMesh;
2295   _mapSubMesh_i [subMeshId] = subMeshServant;
2296   _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate( subMesh );
2297
2298   subMeshServant->Register();
2299
2300   // register CORBA object for persistence
2301   int nextId = _gen_i->RegisterObject( subMesh );
2302   if(MYDEBUG) { MESSAGE( "Add submesh to map with id = "<< nextId); }
2303   else        { nextId = 0; } // avoid "unused variable" warning
2304
2305   // to track changes of GEOM groups
2306   addGeomGroupData( theSubShapeObject, subMesh );
2307
2308   return subMesh._retn();
2309 }
2310
2311 //=======================================================================
2312 //function : getSubMesh
2313 //purpose  :
2314 //=======================================================================
2315
2316 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
2317 {
2318   map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
2319   if ( it == _mapSubMeshIor.end() )
2320     return SMESH::SMESH_subMesh::_nil();
2321
2322   return SMESH::SMESH_subMesh::_duplicate( (*it).second );
2323 }
2324
2325 //=============================================================================
2326 /*!
2327  *
2328  */
2329 //=============================================================================
2330
2331 bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
2332                                   GEOM::GEOM_Object_ptr    theSubShapeObject )
2333 {
2334   bool isHypChanged = false;
2335   if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
2336     return isHypChanged;
2337
2338   const int subMeshId = theSubMesh->GetId();
2339
2340   if ( theSubShapeObject->_is_nil() )  // not published shape (IPAL13617)
2341   {
2342     if ( _mapSubMesh.find( subMeshId ) != _mapSubMesh.end())
2343     {
2344       TopoDS_Shape S = _mapSubMesh[ subMeshId ]->GetSubShape();
2345       if ( !S.IsNull() )
2346       {
2347         list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
2348         isHypChanged = !hyps.empty();
2349         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
2350         for ( ; hyp != hyps.end(); ++hyp )
2351           _impl->RemoveHypothesis(S, (*hyp)->GetID());
2352       }
2353     }
2354   }
2355   else
2356   {
2357     try {
2358       SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
2359       isHypChanged = ( aHypList->length() > 0 );
2360       for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
2361         removeHypothesis( theSubShapeObject, aHypList[i] );
2362       }
2363     }
2364     catch( const SALOME::SALOME_Exception& ) {
2365       INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
2366     }
2367     removeGeomGroupData( theSubShapeObject );
2368   }
2369
2370   // remove a servant
2371   std::map<int, SMESH_subMesh_i*>::iterator id_smi = _mapSubMesh_i.find( subMeshId );
2372   if ( id_smi != _mapSubMesh_i.end() )
2373     id_smi->second->UnRegister();
2374
2375   // remove a CORBA object
2376   std::map<int, SMESH::SMESH_subMesh_ptr>::iterator id_smptr = _mapSubMeshIor.find( subMeshId );
2377   if ( id_smptr != _mapSubMeshIor.end() )
2378     SMESH::SMESH_subMesh_var( id_smptr->second );
2379
2380   _mapSubMesh.erase(subMeshId);
2381   _mapSubMesh_i.erase(subMeshId);
2382   _mapSubMeshIor.erase(subMeshId);
2383
2384   return isHypChanged;
2385 }
2386
2387 //=============================================================================
2388 /*!
2389  *
2390  */
2391 //=============================================================================
2392
2393 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType        theElemType,
2394                                                       const char*               theName,
2395                                                       const TopoDS_Shape&       theShape,
2396                                                       const SMESH_PredicatePtr& thePredicate )
2397 {
2398   std::string newName;
2399   if ( !theName || strlen( theName ) == 0 )
2400   {
2401     std::set< std::string > presentNames;
2402     std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
2403     for ( ; i_gr != _mapGroups.end(); ++i_gr )
2404     {
2405       CORBA::String_var name = i_gr->second->GetName();
2406       presentNames.insert( name.in() );
2407     }
2408     do {
2409       newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
2410     } while ( !presentNames.insert( newName ).second );
2411     theName = newName.c_str();
2412   }
2413   int anId;
2414   SMESH::SMESH_GroupBase_var aGroup;
2415   if ( _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName, anId, theShape, thePredicate ))
2416   {
2417     SMESH_GroupBase_i* aGroupImpl;
2418     if ( !theShape.IsNull() )
2419       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
2420     else if ( thePredicate )
2421       aGroupImpl = new SMESH_GroupOnFilter_i( SMESH_Gen_i::GetPOA(), this, anId );
2422     else
2423       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2424
2425     aGroup = aGroupImpl->_this();
2426     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2427     aGroupImpl->Register();
2428
2429     // register CORBA object for persistence
2430     int nextId = _gen_i->RegisterObject( aGroup );
2431     if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
2432     else        { nextId = 0; } // avoid "unused variable" warning in release mode
2433
2434     // to track changes of GEOM groups
2435     if ( !theShape.IsNull() ) {
2436       GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
2437       addGeomGroupData( geom, aGroup );
2438     }
2439   }
2440   return aGroup._retn();
2441 }
2442
2443 //=============================================================================
2444 /*!
2445  * SMESH_Mesh_i::removeGroup
2446  *
2447  * Should be called by ~SMESH_Group_i()
2448  */
2449 //=============================================================================
2450
2451 void SMESH_Mesh_i::removeGroup( const int theId )
2452 {
2453   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
2454   if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
2455     SMESH::SMESH_GroupBase_var group = _mapGroups[theId];
2456     _mapGroups.erase( theId );
2457     removeGeomGroupData( group );
2458     if ( !_impl->RemoveGroup( theId ))
2459     {
2460       // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
2461       RemoveGroup( group );
2462     }
2463     group->UnRegister();
2464   }
2465 }
2466
2467 //=============================================================================
2468 /*!
2469  *
2470  */
2471 //=============================================================================
2472
2473 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
2474   throw(SALOME::SALOME_Exception)
2475 {
2476   SMESH::log_array_var aLog;
2477
2478   SMESH_TRY;
2479   if ( _preMeshInfo )
2480     _preMeshInfo->FullLoadFromFile();
2481
2482   list < SMESHDS_Command * >logDS = _impl->GetLog();
2483   aLog = new SMESH::log_array;
2484   int indexLog = 0;
2485   int lg = logDS.size();
2486   SCRUTE(lg);
2487   aLog->length(lg);
2488   list < SMESHDS_Command * >::iterator its = logDS.begin();
2489   while(its != logDS.end()){
2490     SMESHDS_Command *com = *its;
2491     int comType = com->GetType();
2492     //SCRUTE(comType);
2493     int lgcom = com->GetNumber();
2494     //SCRUTE(lgcom);
2495     const list < int >&intList = com->GetIndexes();
2496     int inum = intList.size();
2497     //SCRUTE(inum);
2498     list < int >::const_iterator ii = intList.begin();
2499     const list < double >&coordList = com->GetCoords();
2500     int rnum = coordList.size();
2501     //SCRUTE(rnum);
2502     list < double >::const_iterator ir = coordList.begin();
2503     aLog[indexLog].commandType = comType;
2504     aLog[indexLog].number = lgcom;
2505     aLog[indexLog].coords.length(rnum);
2506     aLog[indexLog].indexes.length(inum);
2507     for(int i = 0; i < rnum; i++){
2508       aLog[indexLog].coords[i] = *ir;
2509       //MESSAGE(" "<<i<<" "<<ir.Value());
2510       ir++;
2511     }
2512     for(int i = 0; i < inum; i++){
2513       aLog[indexLog].indexes[i] = *ii;
2514       //MESSAGE(" "<<i<<" "<<ii.Value());
2515       ii++;
2516     }
2517     indexLog++;
2518     its++;
2519   }
2520   if(clearAfterGet)
2521     _impl->ClearLog();
2522
2523   SMESH_CATCH( SMESH::throwCorbaException );
2524
2525   return aLog._retn();
2526 }
2527
2528
2529 //=============================================================================
2530 /*!
2531  *
2532  */
2533 //=============================================================================
2534
2535 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
2536 {
2537   SMESH_TRY;
2538   _impl->ClearLog();
2539   SMESH_CATCH( SMESH::throwCorbaException );
2540 }
2541
2542 //=============================================================================
2543 /*!
2544  *
2545  */
2546 //=============================================================================
2547
2548 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
2549 {
2550   return _id;
2551 }
2552
2553 //=============================================================================
2554 /*!
2555  *
2556  */
2557 //=============================================================================
2558
2559 CORBA::Long SMESH_Mesh_i::GetStudyId()throw(SALOME::SALOME_Exception)
2560 {
2561   return _studyId;
2562 }
2563
2564 //=============================================================================
2565 namespace
2566 {
2567   //!< implementation of struct used to call methods of SMESH_Mesh_i from SMESH_Mesh
2568   // issue 0020918: groups removal is caused by hyp modification
2569   // issue 0021208: to forget not loaded mesh data at hyp modification
2570   struct TCallUp_i : public SMESH_Mesh::TCallUp
2571   {
2572     SMESH_Mesh_i* _mesh;
2573     TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
2574     virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); }
2575     virtual void HypothesisModified ()              { _mesh->onHypothesisModified(); }
2576     virtual void Load ()                            { _mesh->Load(); }
2577   };
2578 }
2579
2580 //================================================================================
2581 /*!
2582  * \brief callback from _impl to forget not loaded mesh data (issue 0021208)
2583  */
2584 //================================================================================
2585
2586 void SMESH_Mesh_i::onHypothesisModified()
2587 {
2588   if ( _preMeshInfo )
2589     _preMeshInfo->ForgetOrLoad();
2590 }
2591
2592 //=============================================================================
2593 /*!
2594  *
2595  */
2596 //=============================================================================
2597
2598 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
2599 {
2600   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
2601   _impl = impl;
2602   if ( _impl )
2603     _impl->SetCallUp( new TCallUp_i(this));
2604 }
2605
2606 //=============================================================================
2607 /*!
2608  *
2609  */
2610 //=============================================================================
2611
2612 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
2613 {
2614   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
2615   return *_impl;
2616 }
2617
2618 //=============================================================================
2619 /*!
2620  * Return mesh editor
2621  */
2622 //=============================================================================
2623
2624 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
2625   throw (SALOME::SALOME_Exception)
2626 {
2627   SMESH::SMESH_MeshEditor_var aMeshEdVar;
2628
2629   SMESH_TRY;
2630   if ( _preMeshInfo )
2631     _preMeshInfo->FullLoadFromFile();
2632
2633   // Create MeshEditor
2634   if ( !_editor )
2635     _editor = new SMESH_MeshEditor_i( this, false );
2636   aMeshEdVar = _editor->_this();
2637
2638   // Update Python script
2639   TPythonDump() << _editor << " = "
2640                 << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshEditor()";
2641
2642   SMESH_CATCH( SMESH::throwCorbaException );
2643
2644   return aMeshEdVar._retn();
2645 }
2646
2647 //=============================================================================
2648 /*!
2649  * Return mesh edition previewer
2650  */
2651 //=============================================================================
2652
2653 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
2654   throw (SALOME::SALOME_Exception)
2655 {
2656   SMESH::SMESH_MeshEditor_var aMeshEdVar;
2657
2658   SMESH_TRY;
2659   if ( _preMeshInfo )
2660     _preMeshInfo->FullLoadFromFile();
2661
2662   if ( !_previewEditor )
2663     _previewEditor = new SMESH_MeshEditor_i( this, true );
2664   aMeshEdVar = _previewEditor->_this();
2665
2666   SMESH_CATCH( SMESH::throwCorbaException );
2667
2668   return aMeshEdVar._retn();
2669 }
2670
2671 //================================================================================
2672 /*!
2673  * \brief Return true if the mesh has been edited since a last total re-compute
2674  *        and those modifications may prevent successful partial re-compute
2675  */
2676 //================================================================================
2677
2678 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard() throw(SALOME::SALOME_Exception)
2679 {
2680   Unexpect aCatch(SALOME_SalomeException);
2681   return _impl->HasModificationsToDiscard();
2682 }
2683
2684 //================================================================================
2685 /*!
2686  * \brief Returns a random unique color
2687  */
2688 //================================================================================
2689
2690 static SALOMEDS::Color getUniqueColor( const std::list<SALOMEDS::Color>& theReservedColors )
2691 {
2692   const int MAX_ATTEMPTS = 100;
2693   int cnt = 0;
2694   double tolerance = 0.5;
2695   SALOMEDS::Color col;
2696
2697   bool ok = false;
2698   while ( !ok ) {
2699     // generate random color
2700     double red    = (double)rand() / RAND_MAX;
2701     double green  = (double)rand() / RAND_MAX;
2702     double blue   = (double)rand() / RAND_MAX;
2703     // check existence in the list of the existing colors
2704     bool matched = false;
2705     std::list<SALOMEDS::Color>::const_iterator it;
2706     for ( it = theReservedColors.begin(); it != theReservedColors.end() && !matched; ++it ) {
2707       SALOMEDS::Color color = *it;
2708       double tol = fabs( color.R - red ) + fabs( color.G - green ) + fabs( color.B  - blue  );
2709       matched = tol < tolerance;
2710     }
2711     if ( (cnt+1) % 20 == 0 ) tolerance = tolerance/2;
2712     ok = ( ++cnt == MAX_ATTEMPTS ) || !matched;
2713     col.R = red;
2714     col.G = green;
2715     col.B = blue;
2716   }
2717   return col;
2718 }
2719
2720 //=============================================================================
2721 /*!
2722  * Sets auto-color mode. If it is on, groups get unique random colors
2723  */
2724 //=============================================================================
2725
2726 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOME_Exception)
2727 {
2728   Unexpect aCatch(SALOME_SalomeException);
2729   _impl->SetAutoColor(theAutoColor);
2730
2731   TPythonDump pyDump; // not to dump group->SetColor() from below code
2732   pyDump << SMESH::SMESH_Mesh_var(_this()) <<".SetAutoColor( "<<theAutoColor<<" )";
2733
2734   std::list<SALOMEDS::Color> aReservedColors;
2735   map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
2736   for ( ; it != _mapGroups.end(); it++ ) {
2737     if ( CORBA::is_nil( it->second )) continue;
2738     SALOMEDS::Color aColor = getUniqueColor( aReservedColors );
2739     it->second->SetColor( aColor );
2740     aReservedColors.push_back( aColor );
2741   }
2742 }
2743
2744 //=============================================================================
2745 /*!
2746  * Returns true if auto-color mode is on
2747  */
2748 //=============================================================================
2749
2750 CORBA::Boolean SMESH_Mesh_i::GetAutoColor() throw(SALOME::SALOME_Exception)
2751 {
2752   Unexpect aCatch(SALOME_SalomeException);
2753   return _impl->GetAutoColor();
2754 }
2755
2756 //=============================================================================
2757 /*!
2758  *  Checks if there are groups with equal names
2759  */
2760 //=============================================================================
2761
2762 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
2763 {
2764   return _impl->HasDuplicatedGroupNamesMED();
2765 }
2766
2767 //================================================================================
2768 /*!
2769  * \brief Care of a file before exporting mesh into it
2770  */
2771 //================================================================================
2772
2773 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
2774 {
2775   TCollection_AsciiString aFullName ((char*)file);
2776   OSD_Path aPath (aFullName);
2777   OSD_File aFile (aPath);
2778   if (aFile.Exists()) {
2779     // existing filesystem node
2780     if (aFile.KindOfFile() == OSD_FILE) {
2781       if (aFile.IsWriteable()) {
2782         if (overwrite) {
2783           aFile.Reset();
2784           aFile.Remove();
2785         }
2786         if (aFile.Failed()) {
2787           TCollection_AsciiString msg ("File ");
2788           msg += aFullName + " cannot be replaced.";
2789           THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2790         }
2791       } else {
2792         TCollection_AsciiString msg ("File ");
2793         msg += aFullName + " cannot be overwritten.";
2794         THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2795       }
2796     } else {
2797       TCollection_AsciiString msg ("Location ");
2798       msg += aFullName + " is not a file.";
2799       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2800     }
2801   } else {
2802     // nonexisting file; check if it can be created
2803     aFile.Reset();
2804     aFile.Build(OSD_WriteOnly, OSD_Protection());
2805     if (aFile.Failed()) {
2806       TCollection_AsciiString msg ("You cannot create the file ");
2807       msg += aFullName + ". Check the directory existance and access rights.";
2808       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2809     } else {
2810       aFile.Close();
2811       aFile.Remove();
2812     }
2813   }
2814 }
2815
2816 //================================================================================
2817 /*!
2818  * \brief Prepares a file for export and pass names of mesh groups from study to mesh DS
2819  *  \param file - file name
2820  *  \param overwrite - to erase the file or not
2821  *  \retval string - mesh name
2822  */
2823 //================================================================================
2824
2825 string SMESH_Mesh_i::prepareMeshNameAndGroups(const char*    file,
2826                                               CORBA::Boolean overwrite)
2827 {
2828   // Perform Export
2829   PrepareForWriting(file, overwrite);
2830   string aMeshName = "Mesh";
2831   SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
2832   if ( !aStudy->_is_nil() ) {
2833     SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
2834     if ( !aMeshSO->_is_nil() ) {
2835       CORBA::String_var name = aMeshSO->GetName();
2836       aMeshName = name;
2837       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
2838       if ( !aStudy->GetProperties()->IsLocked() )
2839       {
2840         SALOMEDS::GenericAttribute_wrap anAttr;
2841         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
2842         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
2843         SALOMEDS::AttributeExternalFileDef_wrap aFileName = anAttr;
2844         ASSERT(!aFileName->_is_nil());
2845         aFileName->SetValue(file);
2846         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
2847         SALOMEDS::AttributeFileType_wrap aFileType = anAttr;
2848         ASSERT(!aFileType->_is_nil());
2849         aFileType->SetValue("FICHIERMED");
2850       }
2851     }
2852   }
2853   // Update Python script
2854   // set name of mesh before export
2855   TPythonDump() << _gen_i << ".SetName("
2856                 << SMESH::SMESH_Mesh_var(_this()) << ", '" << aMeshName.c_str() << "')";
2857
2858   // check names of groups
2859   checkGroupNames();
2860
2861   return aMeshName;
2862 }
2863
2864 //================================================================================
2865 /*!
2866  * \brief Export to med file
2867  */
2868 //================================================================================
2869
2870 void SMESH_Mesh_i::ExportToMEDX (const char*        file,
2871                                  CORBA::Boolean     auto_groups,
2872                                  SMESH::MED_VERSION theVersion,
2873                                  CORBA::Boolean     overwrite,
2874                                  CORBA::Boolean     autoDimension)
2875   throw(SALOME::SALOME_Exception)
2876 {
2877   SMESH_TRY;
2878   if ( _preMeshInfo )
2879     _preMeshInfo->FullLoadFromFile();
2880
2881   string aMeshName = prepareMeshNameAndGroups(file, overwrite);
2882   _impl->ExportMED( file, aMeshName.c_str(), auto_groups, theVersion, 0, autoDimension );
2883
2884   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportToMEDX( r'"
2885                 << file << "', " << auto_groups << ", "
2886                 << theVersion << ", " << overwrite << ", "
2887                 << autoDimension << " )";
2888
2889   SMESH_CATCH( SMESH::throwCorbaException );
2890 }
2891
2892 //================================================================================
2893 /*!
2894  * \brief Export a mesh to a med file
2895  */
2896 //================================================================================
2897
2898 void SMESH_Mesh_i::ExportToMED (const char*        file,
2899                                 CORBA::Boolean     auto_groups,
2900                                 SMESH::MED_VERSION theVersion)
2901   throw(SALOME::SALOME_Exception)
2902 {
2903   ExportToMEDX(file,auto_groups,theVersion,true);
2904 }
2905
2906 //================================================================================
2907 /*!
2908  * \brief Export a mesh to a med file
2909  */
2910 //================================================================================
2911
2912 void SMESH_Mesh_i::ExportMED (const char* file,
2913                               CORBA::Boolean auto_groups)
2914   throw(SALOME::SALOME_Exception)
2915 {
2916   ExportToMEDX(file,auto_groups,SMESH::MED_V2_2,true);
2917 }
2918
2919 //================================================================================
2920 /*!
2921  * \brief Export a mesh to a SAUV file
2922  */
2923 //================================================================================
2924
2925 void SMESH_Mesh_i::ExportSAUV (const char* file,
2926                                CORBA::Boolean auto_groups)
2927   throw(SALOME::SALOME_Exception)
2928 {
2929   Unexpect aCatch(SALOME_SalomeException);
2930   if ( _preMeshInfo )
2931     _preMeshInfo->FullLoadFromFile();
2932
2933   string aMeshName = prepareMeshNameAndGroups(file, true);
2934   TPythonDump() << SMESH::SMESH_Mesh_var( _this())
2935                 << ".ExportSAUV( r'" << file << "', " << auto_groups << " )";
2936   _impl->ExportSAUV(file, aMeshName.c_str(), auto_groups);
2937 }
2938
2939
2940 //================================================================================
2941 /*!
2942  * \brief Export a mesh to a DAT file
2943  */
2944 //================================================================================
2945
2946 void SMESH_Mesh_i::ExportDAT (const char *file)
2947   throw(SALOME::SALOME_Exception)
2948 {
2949   Unexpect aCatch(SALOME_SalomeException);
2950   if ( _preMeshInfo )
2951     _preMeshInfo->FullLoadFromFile();
2952
2953   // Update Python script
2954   // check names of groups
2955   checkGroupNames();
2956   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportDAT( r'" << file << "' )";
2957
2958   // Perform Export
2959   PrepareForWriting(file);
2960   _impl->ExportDAT(file);
2961 }
2962
2963 //================================================================================
2964 /*!
2965  * \brief Export a mesh to an UNV file
2966  */
2967 //================================================================================
2968
2969 void SMESH_Mesh_i::ExportUNV (const char *file)
2970   throw(SALOME::SALOME_Exception)
2971 {
2972   Unexpect aCatch(SALOME_SalomeException);
2973   if ( _preMeshInfo )
2974     _preMeshInfo->FullLoadFromFile();
2975
2976   // Update Python script
2977   // check names of groups
2978   checkGroupNames();
2979   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportUNV( r'" << file << "' )";
2980
2981   // Perform Export
2982   PrepareForWriting(file);
2983   _impl->ExportUNV(file);
2984 }
2985
2986 //================================================================================
2987 /*!
2988  * \brief Export a mesh to an STL file
2989  */
2990 //================================================================================
2991
2992 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
2993   throw(SALOME::SALOME_Exception)
2994 {
2995   Unexpect aCatch(SALOME_SalomeException);
2996   if ( _preMeshInfo )
2997     _preMeshInfo->FullLoadFromFile();
2998
2999   // Update Python script
3000   // check names of groups
3001   checkGroupNames();
3002   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3003                 << ".ExportSTL( r'" << file << "', " << isascii << " )";
3004
3005   // Perform Export
3006   PrepareForWriting(file);
3007   _impl->ExportSTL(file, isascii);
3008 }
3009
3010 //================================================================================
3011 /*!
3012  * \brief Export a part of mesh to a med file
3013  */
3014 //================================================================================
3015
3016 void SMESH_Mesh_i::ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart,
3017                                    const char*               file,
3018                                    CORBA::Boolean            auto_groups,
3019                                    SMESH::MED_VERSION        version,
3020                                    CORBA::Boolean            overwrite,
3021                                    CORBA::Boolean            autoDimension,
3022                                    const GEOM::ListOfFields& fields,
3023                                    const char*               geomAssocFields)
3024   throw (SALOME::SALOME_Exception)
3025 {
3026   SMESH_TRY;
3027   if ( _preMeshInfo )
3028     _preMeshInfo->FullLoadFromFile();
3029
3030   // check fields
3031   bool have0dField = false;
3032   if ( fields.length() > 0 )
3033   {
3034     GEOM::GEOM_Object_var shapeToMesh = GetShapeToMesh();
3035     if ( shapeToMesh->_is_nil() )
3036       THROW_SALOME_CORBA_EXCEPTION( "No shape to mesh", SALOME::INTERNAL_ERROR );
3037
3038     for ( size_t i = 0; i < fields.length(); ++i )
3039     {
3040       if ( fields[i]->GetDataType() == GEOM::FDT_String )
3041         THROW_SALOME_CORBA_EXCEPTION
3042           ( "Export of string fields is not supported", SALOME::BAD_PARAM);
3043       GEOM::GEOM_Object_var fieldShape = fields[i]->GetShape();
3044       if ( fieldShape->_is_nil() )
3045         THROW_SALOME_CORBA_EXCEPTION( "Null shape under a field", SALOME::INTERNAL_ERROR );
3046       if ( !fieldShape->IsSame( shapeToMesh ) )
3047         THROW_SALOME_CORBA_EXCEPTION
3048           ( "Field defined not on shape", SALOME::BAD_PARAM);
3049       if ( fields[i]->GetDimension() == 0 )
3050         have0dField = true;
3051     }
3052     if ( geomAssocFields )
3053       for ( int i = 0; geomAssocFields[i]; ++i )
3054         switch ( geomAssocFields[i] ) {
3055         case 'v':case 'e':case 'f':case 's': break;
3056         case 'V':case 'E':case 'F':case 'S': break;
3057         default: THROW_SALOME_CORBA_EXCEPTION
3058             ( "geomAssocFields can include only [vefs] characters", SALOME::BAD_PARAM);
3059         }
3060   }
3061
3062   SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
3063
3064   // write mesh
3065
3066   string aMeshName = "Mesh";
3067   SMESHUtils::Deleter< SMESH_MeshPartDS > tmpDSDeleter(0);
3068   if ( CORBA::is_nil( meshPart ) ||
3069        SMESH::DownCast< SMESH_Mesh_i* >( meshPart ))
3070   {
3071     aMeshName = prepareMeshNameAndGroups(file, overwrite);
3072     _impl->ExportMED( file, aMeshName.c_str(), auto_groups,
3073                       version, 0, autoDimension, /*addODOnVertices=*/have0dField);
3074     meshDS = _impl->GetMeshDS();
3075   }
3076   else
3077   {
3078     if ( _preMeshInfo )
3079       _preMeshInfo->FullLoadFromFile();
3080
3081     PrepareForWriting(file, overwrite);
3082
3083     SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
3084     if ( !aStudy->_is_nil() ) {
3085       SALOMEDS::SObject_wrap SO = _gen_i->ObjectToSObject( aStudy, meshPart );
3086       if ( !SO->_is_nil() ) {
3087         CORBA::String_var name = SO->GetName();
3088         aMeshName = name;
3089       }
3090     }
3091     SMESH_MeshPartDS* partDS = new SMESH_MeshPartDS( meshPart );
3092     _impl->ExportMED( file, aMeshName.c_str(), auto_groups,
3093                       version, partDS, autoDimension, /*addODOnVertices=*/have0dField);
3094     meshDS = tmpDSDeleter._obj = partDS;
3095   }
3096
3097   // write fields
3098
3099   if ( _impl->HasShapeToMesh() )
3100   {
3101     DriverMED_W_Field fieldWriter;
3102     fieldWriter.SetFile( file );
3103     fieldWriter.SetMeshName( aMeshName );
3104     fieldWriter.AddODOnVertices( have0dField );
3105
3106     exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
3107   }
3108
3109   // dump
3110   GEOM::ListOfGBO_var goList = new GEOM::ListOfGBO;
3111   goList->length( fields.length() );
3112   for ( size_t i = 0; i < fields.length(); ++i )
3113   {
3114     GEOM::GEOM_BaseObject_var gbo = GEOM::GEOM_BaseObject::_narrow( fields[i] );
3115     goList[i] = gbo;
3116   }
3117   TPythonDump() << _this() << ".ExportPartToMED( "
3118                 << meshPart << ", r'" << file << "', "
3119                 << auto_groups << ", " << version << ", " << overwrite << ", "
3120                 << autoDimension << ", " << goList
3121                 << ", '" << ( geomAssocFields ? geomAssocFields : "" ) << "'" << " )";
3122
3123   SMESH_CATCH( SMESH::throwCorbaException );
3124 }
3125
3126 //================================================================================
3127 /*!
3128  * Write GEOM fields to MED file
3129  */
3130 //================================================================================
3131
3132 void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field&        fieldWriter,
3133                                     SMESHDS_Mesh*             meshDS,
3134                                     const GEOM::ListOfFields& fields,
3135                                     const char*               geomAssocFields)
3136 {
3137 #define METH "SMESH_Mesh_i::exportMEDFields() "
3138
3139   if (( fields.length() < 1 ) &&
3140       ( !geomAssocFields || !geomAssocFields[0] ))
3141     return;
3142
3143   std::vector< double > dblVals( meshDS->MaxShapeIndex()+1 );
3144   std::vector< int >    intVals( meshDS->MaxShapeIndex()+1 );
3145   std::vector< int >    subIdsByDim[ 4 ];
3146   const double noneDblValue = 0.;
3147   const double noneIntValue = 0;
3148
3149   for ( size_t iF = 0; iF < fields.length(); ++iF )
3150   {
3151     // set field data
3152
3153     int dim = fields[ iF ]->GetDimension();
3154     SMDSAbs_ElementType elemType;
3155     TopAbs_ShapeEnum    shapeType;
3156     switch ( dim ) {
3157     case 0: elemType = SMDSAbs_0DElement; shapeType = TopAbs_VERTEX; break;
3158     case 1: elemType = SMDSAbs_Edge;      shapeType = TopAbs_EDGE;   break;
3159     case 2: elemType = SMDSAbs_Face;      shapeType = TopAbs_FACE;   break;
3160     case 3: elemType = SMDSAbs_Volume;    shapeType = TopAbs_SOLID;  break;
3161     default:
3162       continue; // skip fields on whole shape
3163     }
3164     GEOM::field_data_type dataType = fields[ iF ]->GetDataType();
3165     if ( dataType == GEOM::FDT_String )
3166       continue;
3167     GEOM::ListOfLong_var stepIDs = fields[ iF ]->GetSteps();
3168     if ( stepIDs->length() < 1 )
3169       continue;
3170     GEOM::string_array_var comps = fields[ iF ]->GetComponents();
3171     if ( comps->length() < 1 )
3172       continue;
3173     CORBA::String_var       name = fields[ iF ]->GetName();
3174
3175     if ( !fieldWriter.Set( meshDS,
3176                            name.in(),
3177                            elemType,
3178                            comps->length(),
3179                            /*isIntData=*/false ))//( dataType == GEOM::FDT_Int )))
3180       continue;
3181
3182     for ( size_t iC = 0; iC < comps->length(); ++iC )
3183       fieldWriter.SetCompName( iC, comps[ iC ].in() );
3184
3185     // find sub-shape IDs
3186
3187     std::vector< int >& subIds = subIdsByDim[ dim ];
3188     if ( subIds.empty() )
3189       for ( int id = 1; id <= meshDS->MaxShapeIndex(); ++id )
3190         if ( meshDS->IndexToShape( id ).ShapeType() == shapeType )
3191           subIds.push_back( id );
3192
3193     // write steps
3194
3195     SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
3196     if ( !elemIt )
3197       continue;
3198
3199     for ( size_t iS = 0; iS < stepIDs->length(); ++iS )
3200     {
3201       GEOM::GEOM_FieldStep_var step = fields[ iF ]->GetStep( stepIDs[ iS ]);
3202       if ( step->_is_nil() )
3203         continue;
3204
3205       CORBA::Long stamp = step->GetStamp();
3206       CORBA::Long id    = step->GetID();
3207       fieldWriter.SetDtIt( int( stamp ), int( id ));
3208
3209       // fill dblVals or intVals
3210       switch ( dataType )
3211       {
3212       case GEOM::FDT_Double:
3213       {
3214         GEOM::GEOM_DoubleFieldStep_var dblStep = GEOM::GEOM_DoubleFieldStep::_narrow( step );
3215         if ( dblStep->_is_nil() ) continue;
3216         GEOM::ListOfDouble_var vv = dblStep->GetValues();
3217         if ( vv->length() != subIds.size() )
3218           THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
3219         for ( size_t i = 0; i < vv->length(); ++i )
3220           dblVals[ subIds[ i ]] = vv[ i ];
3221         break;
3222       }
3223       case GEOM::FDT_Int:
3224       {
3225         GEOM::GEOM_IntFieldStep_var intStep = GEOM::GEOM_IntFieldStep::_narrow( step );
3226         if ( intStep->_is_nil() ) continue;
3227         GEOM::ListOfLong_var vv = intStep->GetValues();
3228         if ( vv->length() != subIds.size() )
3229           THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
3230         for ( size_t i = 0; i < vv->length(); ++i )
3231           intVals[ subIds[ i ]] = (int) vv[ i ];
3232         break;
3233       }
3234       case GEOM::FDT_Bool:
3235       {
3236         GEOM::GEOM_BoolFieldStep_var boolStep = GEOM::GEOM_BoolFieldStep::_narrow( step );
3237         if ( boolStep->_is_nil() ) continue;
3238         GEOM::short_array_var vv = boolStep->GetValues();
3239         if ( vv->length() != subIds.size() )
3240           THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
3241         for ( size_t i = 0; i < vv->length(); ++i )
3242           intVals[ subIds[ i ]] = (int) vv[ i ];
3243         break;
3244       }
3245       default: continue;
3246       }
3247
3248       // pass values to fieldWriter
3249       elemIt = fieldWriter.GetOrderedElems();
3250       if ( dataType == GEOM::FDT_Double )
3251         while ( elemIt->more() )
3252         {
3253           const SMDS_MeshElement* e = elemIt->next();
3254           const int shapeID = e->getshapeId();
3255           if ( shapeID < 1 || shapeID >= dblVals.size() )
3256             fieldWriter.AddValue( noneDblValue );
3257           else
3258             fieldWriter.AddValue( dblVals[ shapeID ]);
3259         }
3260       else
3261         while ( elemIt->more() )
3262         {
3263           const SMDS_MeshElement* e = elemIt->next();
3264           const int shapeID = e->getshapeId();
3265           if ( shapeID < 1 || shapeID >= intVals.size() )
3266             fieldWriter.AddValue( (double) noneIntValue );
3267           else
3268             fieldWriter.AddValue( (double) intVals[ shapeID ]);
3269         }
3270
3271       // write a step
3272       fieldWriter.Perform();
3273       SMESH_ComputeErrorPtr res = fieldWriter.GetError();
3274       if ( res && res->IsKO() )
3275       {
3276         if ( res->myComment.empty() )
3277         { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
3278         else
3279         { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
3280       }
3281
3282     } // loop on steps
3283   } // loop on fields
3284
3285   if ( !geomAssocFields || !geomAssocFields[0] )
3286     return;
3287
3288   // write geomAssocFields
3289
3290   std::vector< int > shapeDim( TopAbs_SHAPE + 1 );
3291   shapeDim[ TopAbs_COMPOUND  ] = 3;
3292   shapeDim[ TopAbs_COMPSOLID ] = 3;
3293   shapeDim[ TopAbs_SOLID     ] = 3;
3294   shapeDim[ TopAbs_SHELL     ] = 2;
3295   shapeDim[ TopAbs_FACE      ] = 2;
3296   shapeDim[ TopAbs_WIRE      ] = 1;
3297   shapeDim[ TopAbs_EDGE      ] = 1;
3298   shapeDim[ TopAbs_VERTEX    ] = 0;
3299   shapeDim[ TopAbs_SHAPE     ] = 3;
3300
3301   for ( int iF = 0; geomAssocFields[ iF ]; ++iF )
3302   {
3303     std::vector< std::string > compNames;
3304     switch ( geomAssocFields[ iF ]) {
3305     case 'v': case 'V':
3306       fieldWriter.Set( meshDS, "_vertices_", SMDSAbs_Node, /*nbComps=*/2, /*isInt=*/false );
3307       compNames.push_back( "dim" );
3308       break;
3309     case 'e': case 'E':
3310       fieldWriter.Set( meshDS, "_edges_", SMDSAbs_Edge, /*nbComps=*/1, /*isInt=*/false );
3311       break;
3312     case 'f': case 'F':
3313       fieldWriter.Set( meshDS, "_faces_", SMDSAbs_Face, /*nbComps=*/1, /*isInt=*/false );
3314       break;
3315     case 's': case 'S':
3316       fieldWriter.Set( meshDS, "_solids_", SMDSAbs_Volume, /*nbComps=*/1, /*isInt=*/false );
3317       break;
3318     default: continue;
3319     }
3320     compNames.push_back( "id" );
3321     for ( size_t iC = 0; iC < compNames.size(); ++iC )
3322       fieldWriter.SetCompName( iC, compNames[ iC ].c_str() );
3323
3324     fieldWriter.SetDtIt( -1, -1 );
3325
3326     SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
3327     if ( !elemIt )
3328       continue;
3329
3330     if ( compNames.size() == 2 ) // _vertices_
3331       while ( elemIt->more() )
3332       {
3333         const SMDS_MeshElement* e = elemIt->next();
3334         const int shapeID = e->getshapeId();
3335         if ( shapeID < 1 )
3336         {
3337           fieldWriter.AddValue( (double) -1 );
3338           fieldWriter.AddValue( (double) -1 );
3339         }
3340         else
3341         {
3342           const TopoDS_Shape& S = meshDS->IndexToShape( shapeID );
3343           fieldWriter.AddValue( (double) ( S.IsNull() ? -1 : shapeDim[ S.ShapeType() ]));
3344           fieldWriter.AddValue( (double) shapeID );
3345         }
3346       }
3347     else
3348       while ( elemIt->more() )
3349       {
3350         const SMDS_MeshElement* e = elemIt->next();
3351         const int shapeID = e->getshapeId();
3352         if ( shapeID < 1 )
3353           fieldWriter.AddValue( (double) -1 );
3354         else
3355           fieldWriter.AddValue( (double) shapeID );
3356       }
3357
3358     // write a step
3359     fieldWriter.Perform();
3360     SMESH_ComputeErrorPtr res = fieldWriter.GetError();
3361     if ( res && res->IsKO() )
3362     {
3363       if ( res->myComment.empty() )
3364       { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
3365       else
3366       { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
3367     }
3368
3369   } // loop on geomAssocFields
3370
3371 #undef METH
3372 }
3373
3374 //================================================================================
3375 /*!
3376  * \brief Export a part of mesh to a DAT file
3377  */
3378 //================================================================================
3379
3380 void SMESH_Mesh_i::ExportPartToDAT(::SMESH::SMESH_IDSource_ptr meshPart,
3381                                    const char*                 file)
3382   throw (SALOME::SALOME_Exception)
3383 {
3384   Unexpect aCatch(SALOME_SalomeException);
3385   if ( _preMeshInfo )
3386     _preMeshInfo->FullLoadFromFile();
3387
3388   PrepareForWriting(file);
3389
3390   SMESH_MeshPartDS partDS( meshPart );
3391   _impl->ExportDAT(file,&partDS);
3392
3393   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3394                 << ".ExportPartToDAT( " << meshPart << ", r'" << file << "' )";
3395 }
3396 //================================================================================
3397 /*!
3398  * \brief Export a part of mesh to an UNV file
3399  */
3400 //================================================================================
3401
3402 void SMESH_Mesh_i::ExportPartToUNV(::SMESH::SMESH_IDSource_ptr meshPart,
3403                                    const char*                 file)
3404   throw (SALOME::SALOME_Exception)
3405 {
3406   Unexpect aCatch(SALOME_SalomeException);
3407   if ( _preMeshInfo )
3408     _preMeshInfo->FullLoadFromFile();
3409
3410   PrepareForWriting(file);
3411
3412   SMESH_MeshPartDS partDS( meshPart );
3413   _impl->ExportUNV(file, &partDS);
3414
3415   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3416                 << ".ExportPartToUNV( " << meshPart<< ", r'" << file << "' )";
3417 }
3418 //================================================================================
3419 /*!
3420  * \brief Export a part of mesh to an STL file
3421  */
3422 //================================================================================
3423
3424 void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
3425                                    const char*                 file,
3426                                    ::CORBA::Boolean            isascii)
3427   throw (SALOME::SALOME_Exception)
3428 {
3429   Unexpect aCatch(SALOME_SalomeException);
3430   if ( _preMeshInfo )
3431     _preMeshInfo->FullLoadFromFile();
3432
3433   PrepareForWriting(file);
3434
3435   SMESH_MeshPartDS partDS( meshPart );
3436   _impl->ExportSTL(file, isascii, &partDS);
3437
3438   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( "
3439                 << meshPart<< ", r'" << file << "', " << isascii << ")";
3440 }
3441
3442 //================================================================================
3443 /*!
3444  * \brief Export a part of mesh to an STL file
3445  */
3446 //================================================================================
3447
3448 void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart,
3449                               const char*                 file,
3450                               CORBA::Boolean              overwrite)
3451   throw (SALOME::SALOME_Exception)
3452 {
3453 #ifdef WITH_CGNS
3454   Unexpect aCatch(SALOME_SalomeException);
3455   if ( _preMeshInfo )
3456     _preMeshInfo->FullLoadFromFile();
3457
3458   PrepareForWriting(file,overwrite);
3459
3460   SMESH_MeshPartDS partDS( meshPart );
3461   _impl->ExportCGNS(file, &partDS);
3462
3463   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportCGNS( "
3464                 << meshPart<< ", r'" << file << "', " << overwrite << ")";
3465 #else
3466   THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
3467 #endif
3468 }
3469
3470 //================================================================================
3471 /*!
3472  * \brief Export a part of mesh to a GMF file
3473  */
3474 //================================================================================
3475
3476 void SMESH_Mesh_i::ExportGMF(::SMESH::SMESH_IDSource_ptr meshPart,
3477                              const char*                 file,
3478                              bool                        withRequiredGroups)
3479   throw (SALOME::SALOME_Exception)
3480 {
3481   Unexpect aCatch(SALOME_SalomeException);
3482   if ( _preMeshInfo )
3483     _preMeshInfo->FullLoadFromFile();
3484
3485   PrepareForWriting(file,/*overwrite=*/true);
3486
3487   SMESH_MeshPartDS partDS( meshPart );
3488   _impl->ExportGMF(file, &partDS, withRequiredGroups);
3489
3490   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportGMF( "
3491                 << meshPart<< ", r'"
3492                 << file << "', "
3493                 << withRequiredGroups << ")";
3494 }
3495
3496 //=============================================================================
3497 /*!
3498  * Return computation progress [0.,1]
3499  */
3500 //=============================================================================
3501
3502 CORBA::Double SMESH_Mesh_i::GetComputeProgress()
3503 {
3504   SMESH_TRY;
3505
3506   return _impl->GetComputeProgress();
3507
3508   SMESH_CATCH( SMESH::doNothing );
3509   return 0.;
3510 }
3511
3512 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
3513 {
3514   Unexpect aCatch(SALOME_SalomeException);
3515   if ( _preMeshInfo )
3516     return _preMeshInfo->NbNodes();
3517
3518   return _impl->NbNodes();
3519 }
3520
3521 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
3522 {
3523   Unexpect aCatch(SALOME_SalomeException);
3524   if ( _preMeshInfo )
3525     return _preMeshInfo->NbElements();
3526
3527   return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes() + NbBalls();
3528 }
3529
3530 CORBA::Long SMESH_Mesh_i::Nb0DElements()throw (SALOME::SALOME_Exception)
3531 {
3532   Unexpect aCatch(SALOME_SalomeException);
3533   if ( _preMeshInfo )
3534     return _preMeshInfo->Nb0DElements();
3535
3536   return _impl->Nb0DElements();
3537 }
3538
3539 CORBA::Long SMESH_Mesh_i::NbBalls() throw (SALOME::SALOME_Exception)
3540 {
3541   Unexpect aCatch(SALOME_SalomeException);
3542   if ( _preMeshInfo )
3543     return _preMeshInfo->NbBalls();
3544
3545   return _impl->NbBalls();
3546 }
3547
3548 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
3549 {
3550   Unexpect aCatch(SALOME_SalomeException);
3551   if ( _preMeshInfo )
3552     return _preMeshInfo->NbEdges();
3553
3554   return _impl->NbEdges();
3555 }
3556
3557 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
3558   throw(SALOME::SALOME_Exception)
3559 {
3560   Unexpect aCatch(SALOME_SalomeException);
3561   if ( _preMeshInfo )
3562     return _preMeshInfo->NbEdges( (SMDSAbs_ElementOrder) order );
3563
3564   return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
3565 }
3566
3567 //=============================================================================
3568
3569 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
3570 {
3571   Unexpect aCatch(SALOME_SalomeException);
3572   if ( _preMeshInfo )
3573     return _preMeshInfo->NbFaces();
3574
3575   return _impl->NbFaces();
3576 }
3577
3578 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
3579 {
3580   Unexpect aCatch(SALOME_SalomeException);
3581   if ( _preMeshInfo )
3582     return _preMeshInfo->NbTriangles();
3583
3584   return _impl->NbTriangles();
3585 }
3586
3587 CORBA::Long SMESH_Mesh_i::NbBiQuadTriangles()throw(SALOME::SALOME_Exception)
3588 {
3589   Unexpect aCatch(SALOME_SalomeException);
3590   if ( _preMeshInfo )
3591     return _preMeshInfo->NbBiQuadTriangles();
3592
3593   return _impl->NbBiQuadTriangles();
3594 }
3595
3596 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
3597 {
3598   Unexpect aCatch(SALOME_SalomeException);
3599   if ( _preMeshInfo )
3600     return _preMeshInfo->NbQuadrangles();
3601
3602   return _impl->NbQuadrangles();
3603 }
3604
3605 CORBA::Long SMESH_Mesh_i::NbBiQuadQuadrangles()throw(SALOME::SALOME_Exception)
3606 {
3607   Unexpect aCatch(SALOME_SalomeException);
3608   if ( _preMeshInfo )
3609     return _preMeshInfo->NbBiQuadQuadrangles();
3610
3611   return _impl->NbBiQuadQuadrangles();
3612 }
3613
3614 CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
3615 {
3616   Unexpect aCatch(SALOME_SalomeException);
3617   if ( _preMeshInfo )
3618     return _preMeshInfo->NbPolygons();
3619
3620   return _impl->NbPolygons();
3621 }
3622
3623 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
3624   throw(SALOME::SALOME_Exception)
3625 {
3626   Unexpect aCatch(SALOME_SalomeException);
3627   if ( _preMeshInfo )
3628     return _preMeshInfo->NbFaces( (SMDSAbs_ElementOrder) order );
3629
3630   return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
3631 }
3632
3633 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
3634   throw(SALOME::SALOME_Exception)
3635 {
3636   Unexpect aCatch(SALOME_SalomeException);
3637   if ( _preMeshInfo )
3638     return _preMeshInfo->NbTriangles( (SMDSAbs_ElementOrder) order );
3639
3640   return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
3641 }
3642
3643 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
3644   throw(SALOME::SALOME_Exception)
3645 {
3646   Unexpect aCatch(SALOME_SalomeException);
3647   if ( _preMeshInfo )
3648     return _preMeshInfo->NbQuadrangles( (SMDSAbs_ElementOrder) order );
3649
3650   return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
3651 }
3652
3653 //=============================================================================
3654
3655 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
3656 {
3657   Unexpect aCatch(SALOME_SalomeException);
3658   if ( _preMeshInfo )
3659     return _preMeshInfo->NbVolumes();
3660
3661   return _impl->NbVolumes();
3662 }
3663
3664 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
3665 {
3666   Unexpect aCatch(SALOME_SalomeException);
3667   if ( _preMeshInfo )
3668     return _preMeshInfo->NbTetras();
3669
3670   return _impl->NbTetras();
3671 }
3672
3673 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
3674 {
3675   Unexpect aCatch(SALOME_SalomeException);
3676   if ( _preMeshInfo )
3677     return _preMeshInfo->NbHexas();
3678
3679   return _impl->NbHexas();
3680 }
3681
3682 CORBA::Long SMESH_Mesh_i::NbTriQuadraticHexas()throw(SALOME::SALOME_Exception)
3683 {
3684   Unexpect aCatch(SALOME_SalomeException);
3685   if ( _preMeshInfo )
3686     return _preMeshInfo->NbTriQuadHexas();
3687
3688   return _impl->NbTriQuadraticHexas();
3689 }
3690
3691 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
3692 {
3693   Unexpect aCatch(SALOME_SalomeException);
3694   if ( _preMeshInfo )
3695     return _preMeshInfo->NbPyramids();
3696
3697   return _impl->NbPyramids();
3698 }
3699
3700 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
3701 {
3702   Unexpect aCatch(SALOME_SalomeException);
3703   if ( _preMeshInfo )
3704     return _preMeshInfo->NbPrisms();
3705
3706   return _impl->NbPrisms();
3707 }
3708
3709 CORBA::Long SMESH_Mesh_i::NbHexagonalPrisms()throw(SALOME::SALOME_Exception)
3710 {
3711   Unexpect aCatch(SALOME_SalomeException);
3712   if ( _preMeshInfo )
3713     return _preMeshInfo->NbHexPrisms();
3714
3715   return _impl->NbHexagonalPrisms();
3716 }
3717
3718 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
3719 {
3720   Unexpect aCatch(SALOME_SalomeException);
3721   if ( _preMeshInfo )
3722     return _preMeshInfo->NbPolyhedrons();
3723
3724   return _impl->NbPolyhedrons();
3725 }
3726
3727 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
3728   throw(SALOME::SALOME_Exception)
3729 {
3730   Unexpect aCatch(SALOME_SalomeException);
3731   if ( _preMeshInfo )
3732     return _preMeshInfo->NbVolumes( (SMDSAbs_ElementOrder) order );
3733
3734   return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
3735 }
3736
3737 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
3738   throw(SALOME::SALOME_Exception)
3739 {
3740   Unexpect aCatch(SALOME_SalomeException);
3741   if ( _preMeshInfo )
3742     return _preMeshInfo->NbTetras( (SMDSAbs_ElementOrder) order);
3743
3744   return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
3745 }
3746
3747 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
3748   throw(SALOME::SALOME_Exception)
3749 {
3750   Unexpect aCatch(SALOME_SalomeException);
3751   if ( _preMeshInfo )
3752     return _preMeshInfo->NbHexas( (SMDSAbs_ElementOrder) order);
3753
3754   return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
3755 }
3756
3757 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
3758   throw(SALOME::SALOME_Exception)
3759 {
3760   Unexpect aCatch(SALOME_SalomeException);
3761   if ( _preMeshInfo )
3762     return _preMeshInfo->NbPyramids( (SMDSAbs_ElementOrder) order);
3763
3764   return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
3765 }
3766
3767 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
3768   throw(SALOME::SALOME_Exception)
3769 {
3770   Unexpect aCatch(SALOME_SalomeException);
3771   if ( _preMeshInfo )
3772     return _preMeshInfo->NbPrisms( (SMDSAbs_ElementOrder) order);
3773
3774   return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
3775 }
3776
3777 //=============================================================================
3778 /*!
3779  * Returns nb of published sub-meshes
3780  */
3781 //=============================================================================
3782
3783 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
3784 {
3785   Unexpect aCatch(SALOME_SalomeException);
3786   return _mapSubMesh_i.size();
3787 }
3788
3789 //=============================================================================
3790 /*!
3791  * Dumps mesh into a string
3792  */
3793 //=============================================================================
3794
3795 char* SMESH_Mesh_i::Dump()
3796 {
3797   ostringstream os;
3798   _impl->Dump( os );
3799   return CORBA::string_dup( os.str().c_str() );
3800 }
3801
3802 //=============================================================================
3803 /*!
3804  * Method of SMESH_IDSource interface
3805  */
3806 //=============================================================================
3807
3808 SMESH::long_array* SMESH_Mesh_i::GetIDs()
3809 {
3810   return GetElementsId();
3811 }
3812
3813 //=============================================================================
3814 /*!
3815  * Returns ids of all elements
3816  */
3817 //=============================================================================
3818
3819 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
3820   throw (SALOME::SALOME_Exception)
3821 {
3822   Unexpect aCatch(SALOME_SalomeException);
3823   if ( _preMeshInfo )
3824     _preMeshInfo->FullLoadFromFile();
3825
3826   SMESH::long_array_var aResult = new SMESH::long_array();
3827   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3828
3829   if ( aSMESHDS_Mesh == NULL )
3830     return aResult._retn();
3831
3832   long nbElements = NbElements();
3833   aResult->length( nbElements );
3834   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
3835   for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
3836     aResult[i] = anIt->next()->GetID();
3837
3838   return aResult._retn();
3839 }
3840
3841
3842 //=============================================================================
3843 /*!
3844  * Returns ids of all elements of given type
3845  */
3846 //=============================================================================
3847
3848 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
3849     throw (SALOME::SALOME_Exception)
3850 {
3851   Unexpect aCatch(SALOME_SalomeException);
3852   if ( _preMeshInfo )
3853     _preMeshInfo->FullLoadFromFile();
3854
3855   SMESH::long_array_var aResult = new SMESH::long_array();
3856   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3857
3858   if ( aSMESHDS_Mesh == NULL )
3859     return aResult._retn();
3860
3861   long nbElements = NbElements();
3862
3863   // No sense in returning ids of elements along with ids of nodes:
3864   // when theElemType == SMESH::ALL, return node ids only if
3865   // there are no elements
3866   if ( theElemType == SMESH::NODE || (theElemType == SMESH::ALL && nbElements == 0) )
3867     return GetNodesId();
3868
3869   aResult->length( nbElements );
3870
3871   int i = 0;
3872
3873   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator( (SMDSAbs_ElementType)theElemType );
3874   while ( i < nbElements && anIt->more() )
3875     aResult[i++] = anIt->next()->GetID();
3876
3877   aResult->length( i );
3878
3879   return aResult._retn();
3880 }
3881
3882 //=============================================================================
3883 /*!
3884  * Returns ids of all nodes
3885  */
3886 //=============================================================================
3887
3888 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
3889   throw (SALOME::SALOME_Exception)
3890 {
3891   Unexpect aCatch(SALOME_SalomeException);
3892   if ( _preMeshInfo )
3893     _preMeshInfo->FullLoadFromFile();
3894
3895   SMESH::long_array_var aResult = new SMESH::long_array();
3896   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3897
3898   if ( aSMESHDS_Mesh == NULL )
3899     return aResult._retn();
3900
3901   long nbNodes = NbNodes();
3902   aResult->length( nbNodes );
3903   SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator(/*idInceasingOrder=*/true);
3904   for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
3905     aResult[i] = anIt->next()->GetID();
3906
3907   return aResult._retn();
3908 }
3909
3910 //=============================================================================
3911 /*!
3912  *
3913  */
3914 //=============================================================================
3915
3916 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
3917   throw (SALOME::SALOME_Exception)
3918 {
3919   SMESH::ElementType type;
3920   SMESH_TRY;
3921
3922   if ( _preMeshInfo )
3923     _preMeshInfo->FullLoadFromFile();
3924
3925   type = ( SMESH::ElementType ) _impl->GetElementType( id, iselem );
3926
3927   SMESH_CATCH( SMESH::throwCorbaException );
3928
3929   return type;
3930 }
3931
3932 //=============================================================================
3933 /*!
3934  *
3935  */
3936 //=============================================================================
3937
3938 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id )
3939   throw (SALOME::SALOME_Exception)
3940 {
3941   if ( _preMeshInfo )
3942     _preMeshInfo->FullLoadFromFile();
3943
3944   const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
3945   if ( !e )
3946     THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
3947
3948   return ( SMESH::EntityType ) e->GetEntityType();
3949 }
3950
3951 //=============================================================================
3952 /*!
3953  *
3954  */
3955 //=============================================================================
3956
3957 SMESH::GeometryType SMESH_Mesh_i::GetElementShape( const CORBA::Long id )
3958   throw (SALOME::SALOME_Exception)
3959 {
3960   if ( _preMeshInfo )
3961     _preMeshInfo->FullLoadFromFile();
3962
3963   const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
3964   if ( !e )
3965     THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
3966
3967   return ( SMESH::GeometryType ) e->GetGeomType();
3968 }
3969
3970 //=============================================================================
3971 /*!
3972  * Returns ID of elements for given submesh
3973  */
3974 //=============================================================================
3975 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
3976      throw (SALOME::SALOME_Exception)
3977 {
3978   SMESH::long_array_var aResult = new SMESH::long_array();
3979
3980   SMESH_TRY;
3981   if ( _preMeshInfo )
3982     _preMeshInfo->FullLoadFromFile();
3983
3984   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
3985   if(!SM) return aResult._retn();
3986
3987   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
3988   if(!SDSM) return aResult._retn();
3989
3990   aResult->length(SDSM->NbElements());
3991
3992   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
3993   int i = 0;
3994   while ( eIt->more() ) {
3995     aResult[i++] = eIt->next()->GetID();
3996   }
3997
3998   SMESH_CATCH( SMESH::throwCorbaException );
3999
4000   return aResult._retn();
4001 }
4002
4003 //=============================================================================
4004 /*!
4005  * Returns ID of nodes for given submesh
4006  * If param all==true - returns all nodes, else -
4007  * returns only nodes on shapes.
4008  */
4009 //=============================================================================
4010
4011 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
4012                                                    CORBA::Boolean    all)
4013   throw (SALOME::SALOME_Exception)
4014 {
4015   SMESH::long_array_var aResult = new SMESH::long_array();
4016
4017   SMESH_TRY;
4018   if ( _preMeshInfo )
4019     _preMeshInfo->FullLoadFromFile();
4020
4021   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4022   if(!SM) return aResult._retn();
4023
4024   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
4025   if(!SDSM) return aResult._retn();
4026
4027   set<int> theElems;
4028   if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
4029     SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
4030     while ( nIt->more() ) {
4031       const SMDS_MeshNode* elem = nIt->next();
4032       theElems.insert( elem->GetID() );
4033     }
4034   }
4035   else { // all nodes of submesh elements
4036     SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
4037     while ( eIt->more() ) {
4038       const SMDS_MeshElement* anElem = eIt->next();
4039       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
4040       while ( nIt->more() ) {
4041         const SMDS_MeshElement* elem = nIt->next();
4042         theElems.insert( elem->GetID() );
4043       }
4044     }
4045   }
4046
4047   aResult->length(theElems.size());
4048   set<int>::iterator itElem;
4049   int i = 0;
4050   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
4051     aResult[i++] = *itElem;
4052
4053   SMESH_CATCH( SMESH::throwCorbaException );
4054
4055   return aResult._retn();
4056 }
4057   
4058 //=============================================================================
4059 /*!
4060  * Returns type of elements for given submesh
4061  */
4062 //=============================================================================
4063
4064 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
4065   throw (SALOME::SALOME_Exception)
4066 {
4067   SMESH::ElementType type;
4068
4069   SMESH_TRY;
4070   if ( _preMeshInfo )
4071     _preMeshInfo->FullLoadFromFile();
4072
4073   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4074   if(!SM) return SMESH::ALL;
4075
4076   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
4077   if(!SDSM) return SMESH::ALL;
4078
4079   if(SDSM->NbElements()==0)
4080     return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
4081
4082   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
4083   const SMDS_MeshElement* anElem = eIt->next();
4084
4085   type = ( SMESH::ElementType ) anElem->GetType();
4086
4087   SMESH_CATCH( SMESH::throwCorbaException );
4088
4089   return type; 
4090 }
4091   
4092
4093 //=============================================================================
4094 /*!
4095  * Returns pointer to _impl as an integer value. Is called from constructor of SMESH_Client
4096  */
4097 //=============================================================================
4098
4099 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
4100 {
4101   if ( _preMeshInfo )
4102     _preMeshInfo->FullLoadFromFile();
4103
4104   CORBA::LongLong pointeur = CORBA::LongLong(_impl);
4105   if ( MYDEBUG )
4106     MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
4107   return pointeur;
4108 }
4109
4110
4111 //=============================================================================
4112 /*!
4113  * Get XYZ coordinates of node as list of double
4114  * If there is not node for given ID - returns empty list
4115  */
4116 //=============================================================================
4117
4118 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
4119 {
4120   if ( _preMeshInfo )
4121     _preMeshInfo->FullLoadFromFile();
4122
4123   SMESH::double_array_var aResult = new SMESH::double_array();
4124   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4125   if ( aSMESHDS_Mesh == NULL )
4126     return aResult._retn();
4127
4128   // find node
4129   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
4130   if(!aNode)
4131     return aResult._retn();
4132
4133   // add coordinates
4134   aResult->length(3);
4135   aResult[0] = aNode->X();
4136   aResult[1] = aNode->Y();
4137   aResult[2] = aNode->Z();
4138   return aResult._retn();
4139 }
4140
4141
4142 //=============================================================================
4143 /*!
4144  * For given node returns list of IDs of inverse elements
4145  * If there is not node for given ID - returns empty list
4146  */
4147 //=============================================================================
4148
4149 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
4150 {
4151   if ( _preMeshInfo )
4152     _preMeshInfo->FullLoadFromFile();
4153
4154   SMESH::long_array_var aResult = new SMESH::long_array();
4155   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4156   if ( aSMESHDS_Mesh == NULL )
4157     return aResult._retn();
4158
4159   // find node
4160   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
4161   if(!aNode)
4162     return aResult._retn();
4163
4164   // find inverse elements
4165   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
4166   TColStd_SequenceOfInteger IDs;
4167   while(eIt->more()) {
4168     const SMDS_MeshElement* elem = eIt->next();
4169     IDs.Append(elem->GetID());
4170   }
4171   if(IDs.Length()>0) {
4172     aResult->length(IDs.Length());
4173     int i = 1;
4174     for(; i<=IDs.Length(); i++) {
4175       aResult[i-1] = IDs.Value(i);
4176     }
4177   }
4178   return aResult._retn();
4179 }
4180
4181 //=============================================================================
4182 /*!
4183  * \brief Return position of a node on shape
4184  */
4185 //=============================================================================
4186
4187 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
4188 {
4189   if ( _preMeshInfo )
4190     _preMeshInfo->FullLoadFromFile();
4191
4192   SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
4193   aNodePosition->shapeID = 0;
4194   aNodePosition->shapeType = GEOM::SHAPE;
4195
4196   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
4197   if ( !mesh ) return aNodePosition;
4198
4199   if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
4200   {
4201     if ( SMDS_PositionPtr pos = aNode->GetPosition() )
4202     {
4203       aNodePosition->shapeID = aNode->getshapeId();
4204       switch ( pos->GetTypeOfPosition() ) {
4205       case SMDS_TOP_EDGE:
4206         aNodePosition->shapeType = GEOM::EDGE;
4207         aNodePosition->params.length(1);
4208         aNodePosition->params[0] =
4209           static_cast<SMDS_EdgePosition*>( pos )->GetUParameter();
4210         break;
4211       case SMDS_TOP_FACE:
4212         aNodePosition->shapeType = GEOM::FACE;
4213         aNodePosition->params.length(2);
4214         aNodePosition->params[0] =
4215           static_cast<SMDS_FacePosition*>( pos )->GetUParameter();
4216         aNodePosition->params[1] =
4217           static_cast<SMDS_FacePosition*>( pos )->GetVParameter();
4218         break;
4219       case SMDS_TOP_VERTEX:
4220         aNodePosition->shapeType = GEOM::VERTEX;
4221         break;
4222       case SMDS_TOP_3DSPACE:
4223         if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
4224           aNodePosition->shapeType = GEOM::SOLID;
4225         else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
4226           aNodePosition->shapeType = GEOM::SHELL;
4227         break;
4228       default:;
4229       }
4230     }
4231   }
4232   return aNodePosition;
4233 }
4234
4235 //=============================================================================
4236 /*!
4237  * \brief Return position of an element on shape
4238  */
4239 //=============================================================================
4240
4241 SMESH::ElementPosition SMESH_Mesh_i::GetElementPosition(CORBA::Long ElemID)
4242 {
4243   if ( _preMeshInfo )
4244     _preMeshInfo->FullLoadFromFile();
4245
4246   SMESH::ElementPosition anElementPosition;
4247   anElementPosition.shapeID = 0;
4248   anElementPosition.shapeType = GEOM::SHAPE;
4249
4250   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
4251   if ( !mesh ) return anElementPosition;
4252
4253   if ( const SMDS_MeshElement* anElem = mesh->FindElement( ElemID ) )
4254   {
4255     anElementPosition.shapeID = anElem->getshapeId();
4256     const TopoDS_Shape& aSp = mesh->IndexToShape( anElem->getshapeId() );
4257     if ( !aSp.IsNull() ) {
4258       switch ( aSp.ShapeType() ) {
4259       case TopAbs_EDGE:
4260         anElementPosition.shapeType = GEOM::EDGE;
4261         break;
4262       case TopAbs_FACE:
4263         anElementPosition.shapeType = GEOM::FACE;
4264         break;
4265       case TopAbs_VERTEX:
4266         anElementPosition.shapeType = GEOM::VERTEX;
4267         break;
4268       case TopAbs_SOLID:
4269         anElementPosition.shapeType = GEOM::SOLID;
4270         break;
4271       case TopAbs_SHELL:
4272         anElementPosition.shapeType = GEOM::SHELL;
4273         break;
4274       default:;
4275       }
4276     }
4277   }
4278   return anElementPosition;
4279 }
4280
4281 //=============================================================================
4282 /*!
4283  * If given element is node returns IDs of shape from position
4284  * If there is not node for given ID - returns -1
4285  */
4286 //=============================================================================
4287
4288 CORBA::Long SMESH_Mesh_i::GetShapeID(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 node
4298   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
4299   if(aNode) {
4300     return aNode->getshapeId();
4301   }
4302
4303   return -1;
4304 }
4305
4306
4307 //=============================================================================
4308 /*!
4309  * For given element returns ID of result shape after 
4310  * ::FindShape() from SMESH_MeshEditor
4311  * If there is not element for given ID - returns -1
4312  */
4313 //=============================================================================
4314
4315 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
4316 {
4317   if ( _preMeshInfo )
4318     _preMeshInfo->FullLoadFromFile();
4319
4320   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4321   if ( aSMESHDS_Mesh == NULL )
4322     return -1;
4323
4324   // try to find element
4325   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4326   if(!elem)
4327     return -1;
4328
4329   ::SMESH_MeshEditor aMeshEditor(_impl);
4330   int index = aMeshEditor.FindShape( elem );
4331   if(index>0)
4332     return index;
4333
4334   return -1;
4335 }
4336
4337
4338 //=============================================================================
4339 /*!
4340  * Returns number of nodes for given element
4341  * If there is not element for given ID - returns -1
4342  */
4343 //=============================================================================
4344
4345 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
4346 {
4347   if ( _preMeshInfo )
4348     _preMeshInfo->FullLoadFromFile();
4349
4350   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4351   if ( aSMESHDS_Mesh == NULL ) return -1;
4352   // try to find element
4353   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4354   if(!elem) return -1;
4355   return elem->NbNodes();
4356 }
4357
4358
4359 //=============================================================================
4360 /*!
4361  * Returns ID of node by given index for given element
4362  * If there is not element for given ID - returns -1
4363  * If there is not node for given index - returns -2
4364  */
4365 //=============================================================================
4366
4367 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
4368 {
4369   if ( _preMeshInfo )
4370     _preMeshInfo->FullLoadFromFile();
4371
4372   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4373   if ( aSMESHDS_Mesh == NULL ) return -1;
4374   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4375   if(!elem) return -1;
4376   if( index>=elem->NbNodes() || index<0 ) return -1;
4377   return elem->GetNode(index)->GetID();
4378 }
4379
4380 //=============================================================================
4381 /*!
4382  * Returns IDs of nodes of given element
4383  */
4384 //=============================================================================
4385
4386 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
4387 {
4388   if ( _preMeshInfo )
4389     _preMeshInfo->FullLoadFromFile();
4390
4391   SMESH::long_array_var aResult = new SMESH::long_array();
4392   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
4393   {
4394     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id) )
4395     {
4396       aResult->length( elem->NbNodes() );
4397       for ( int i = 0; i < elem->NbNodes(); ++i )
4398         aResult[ i ] = elem->GetNode( i )->GetID();
4399     }
4400   }
4401   return aResult._retn();
4402 }
4403
4404 //=============================================================================
4405 /*!
4406  * Returns true if given node is medium node
4407  * in given quadratic element
4408  */
4409 //=============================================================================
4410
4411 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
4412 {
4413   if ( _preMeshInfo )
4414     _preMeshInfo->FullLoadFromFile();
4415
4416   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4417   if ( aSMESHDS_Mesh == NULL ) return false;
4418   // try to find node
4419   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
4420   if(!aNode) return false;
4421   // try to find element
4422   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(ide);
4423   if(!elem) return false;
4424
4425   return elem->IsMediumNode(aNode);
4426 }
4427
4428
4429 //=============================================================================
4430 /*!
4431  * Returns true if given node is medium node
4432  * in one of quadratic elements
4433  */
4434 //=============================================================================
4435
4436 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
4437                                                    SMESH::ElementType theElemType)
4438 {
4439   if ( _preMeshInfo )
4440     _preMeshInfo->FullLoadFromFile();
4441
4442   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4443   if ( aSMESHDS_Mesh == NULL ) return false;
4444
4445   // try to find node
4446   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
4447   if(!aNode) return false;
4448
4449   SMESH_MesherHelper aHelper( *(_impl) );
4450
4451   SMDSAbs_ElementType aType;
4452   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
4453   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
4454   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
4455   else aType = SMDSAbs_All;
4456
4457   return aHelper.IsMedium(aNode,aType);
4458 }
4459
4460
4461 //=============================================================================
4462 /*!
4463  * Returns number of edges for given element
4464  */
4465 //=============================================================================
4466
4467 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
4468 {
4469   if ( _preMeshInfo )
4470     _preMeshInfo->FullLoadFromFile();
4471
4472   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4473   if ( aSMESHDS_Mesh == NULL ) return -1;
4474   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4475   if(!elem) return -1;
4476   return elem->NbEdges();
4477 }
4478
4479
4480 //=============================================================================
4481 /*!
4482  * Returns number of faces for given element
4483  */
4484 //=============================================================================
4485
4486 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
4487 {
4488   if ( _preMeshInfo )
4489     _preMeshInfo->FullLoadFromFile();
4490
4491   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4492   if ( aSMESHDS_Mesh == NULL ) return -1;
4493   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4494   if(!elem) return -1;
4495   return elem->NbFaces();
4496 }
4497
4498 //=======================================================================
4499 //function : GetElemFaceNodes
4500 //purpose  : Returns nodes of given face (counted from zero) for given element.
4501 //=======================================================================
4502
4503 SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long  elemId,
4504                                                   CORBA::Short faceIndex)
4505 {
4506   if ( _preMeshInfo )
4507     _preMeshInfo->FullLoadFromFile();
4508
4509   SMESH::long_array_var aResult = new SMESH::long_array();
4510   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
4511   {
4512     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(elemId) )
4513     {
4514       SMDS_VolumeTool vtool( elem );
4515       if ( faceIndex < vtool.NbFaces() )
4516       {
4517         aResult->length( vtool.NbFaceNodes( faceIndex ));
4518         const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
4519         for ( int i = 0; i < aResult->length(); ++i )
4520           aResult[ i ] = nn[ i ]->GetID();
4521       }
4522     }
4523   }
4524   return aResult._retn();
4525 }
4526
4527 //=======================================================================
4528 //function : GetElemFaceNodes
4529 //purpose  : Returns three components of normal of given mesh face.
4530 //=======================================================================
4531
4532 SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long    elemId,
4533                                                  CORBA::Boolean normalized)
4534 {
4535   if ( _preMeshInfo )
4536     _preMeshInfo->FullLoadFromFile();
4537
4538   SMESH::double_array_var aResult = new SMESH::double_array();
4539
4540   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
4541   {
4542     gp_XYZ normal;
4543     if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, normalized ))
4544     {
4545       aResult->length( 3 );
4546       aResult[ 0 ] = normal.X();
4547       aResult[ 1 ] = normal.Y();
4548       aResult[ 2 ] = normal.Z();
4549     }
4550   }
4551   return aResult._retn();
4552 }
4553
4554 //=======================================================================
4555 //function : FindElementByNodes
4556 //purpose  : Returns an element based on all given nodes.
4557 //=======================================================================
4558
4559 CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
4560 {
4561   if ( _preMeshInfo )
4562     _preMeshInfo->FullLoadFromFile();
4563
4564   CORBA::Long elemID(0);
4565   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
4566   {
4567     vector< const SMDS_MeshNode * > nn( nodes.length() );
4568     for ( int i = 0; i < nodes.length(); ++i )
4569       if ( !( nn[i] = mesh->FindNode( nodes[i] )))
4570         return elemID;
4571
4572     const SMDS_MeshElement* elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/false );
4573     if ( !elem && ( _impl->NbEdges  ( ORDER_QUADRATIC ) ||
4574                     _impl->NbFaces  ( ORDER_QUADRATIC ) ||
4575                     _impl->NbVolumes( ORDER_QUADRATIC )))
4576       elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
4577
4578     if ( elem ) elemID = CORBA::Long( elem->GetID() );
4579   }
4580   return elemID;
4581 }
4582
4583 //=============================================================================
4584 /*!
4585  * Returns true if given element is polygon
4586  */
4587 //=============================================================================
4588
4589 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
4590 {
4591   if ( _preMeshInfo )
4592     _preMeshInfo->FullLoadFromFile();
4593
4594   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4595   if ( aSMESHDS_Mesh == NULL ) return false;
4596   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4597   if(!elem) return false;
4598   return elem->IsPoly();
4599 }
4600
4601
4602 //=============================================================================
4603 /*!
4604  * Returns true if given element is quadratic
4605  */
4606 //=============================================================================
4607
4608 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
4609 {
4610   if ( _preMeshInfo )
4611     _preMeshInfo->FullLoadFromFile();
4612
4613   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4614   if ( aSMESHDS_Mesh == NULL ) return false;
4615   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4616   if(!elem) return false;
4617   return elem->IsQuadratic();
4618 }
4619
4620 //=============================================================================
4621 /*!
4622  * Returns diameter of ball discrete element or zero in case of an invalid \a id
4623  */
4624 //=============================================================================
4625
4626 CORBA::Double SMESH_Mesh_i::GetBallDiameter(CORBA::Long id)
4627 {
4628   if ( _preMeshInfo )
4629     _preMeshInfo->FullLoadFromFile();
4630
4631   if ( const SMDS_BallElement* ball =
4632        dynamic_cast<const SMDS_BallElement*>( _impl->GetMeshDS()->FindElement( id )))
4633     return ball->GetDiameter();
4634
4635   return 0;
4636 }
4637
4638 //=============================================================================
4639 /*!
4640  * Returns bary center for given element
4641  */
4642 //=============================================================================
4643
4644 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
4645 {
4646   if ( _preMeshInfo )
4647     _preMeshInfo->FullLoadFromFile();
4648
4649   SMESH::double_array_var aResult = new SMESH::double_array();
4650   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4651   if ( aSMESHDS_Mesh == NULL )
4652     return aResult._retn();
4653
4654   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4655   if(!elem)
4656     return aResult._retn();
4657
4658   if(elem->GetType()==SMDSAbs_Volume) {
4659     SMDS_VolumeTool aTool;
4660     if(aTool.Set(elem)) {
4661       aResult->length(3);
4662       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
4663         aResult->length(0);
4664     }
4665   }
4666   else {
4667     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
4668     int nbn = 0;
4669     double x=0., y=0., z=0.;
4670     for(; anIt->more(); ) {
4671       nbn++;
4672       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
4673       x += aNode->X();
4674       y += aNode->Y();
4675       z += aNode->Z();
4676     }
4677     if(nbn>0) {
4678       // add coordinates
4679       aResult->length(3);
4680       aResult[0] = x/nbn;
4681       aResult[1] = y/nbn;
4682       aResult[2] = z/nbn;
4683     }
4684   }
4685
4686   return aResult._retn();
4687 }
4688
4689 //================================================================================
4690 /*!
4691  * \brief Create a group of elements preventing computation of a sub-shape
4692  */
4693 //================================================================================
4694
4695 SMESH::ListOfGroups*
4696 SMESH_Mesh_i::MakeGroupsOfBadInputElements( int         theSubShapeID,
4697                                             const char* theGroupName )
4698   throw ( SALOME::SALOME_Exception )
4699 {
4700   Unexpect aCatch(SALOME_SalomeException);
4701
4702   if ( !theGroupName || strlen( theGroupName) == 0 )
4703     THROW_SALOME_CORBA_EXCEPTION( "empty group name",SALOME::BAD_PARAM );
4704
4705   SMESH::ListOfGroups_var groups = new SMESH::ListOfGroups;
4706
4707   // submesh by subshape id
4708   if ( !_impl->HasShapeToMesh() ) theSubShapeID = 1;
4709   if ( SMESH_subMesh * sm = _impl->GetSubMeshContaining( theSubShapeID ))
4710   {
4711     // compute error
4712     SMESH_ComputeErrorPtr error = sm->GetComputeError();
4713     if ( error && !error->myBadElements.empty())
4714     {
4715       // sort bad elements by type
4716       vector< const SMDS_MeshElement* > elemsByType[ SMDSAbs_NbElementTypes ];
4717       list<const SMDS_MeshElement*>::iterator elemIt  = error->myBadElements.begin();
4718       list<const SMDS_MeshElement*>::iterator elemEnd = error->myBadElements.end();
4719       for ( ; elemIt != elemEnd; ++elemIt )
4720       {
4721         const SMDS_MeshElement* elem = *elemIt;
4722         if ( !elem ) continue;
4723
4724         if ( elem->GetID() < 1 )
4725         {
4726           // elem is a temporary element, make a real element
4727           vector< const SMDS_MeshNode* > nodes;
4728           SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
4729           while ( nIt->more() && elem )
4730           {
4731             nodes.push_back( nIt->next() );
4732             if ( nodes.back()->GetID() < 1 )
4733               elem = 0;  // a temporary element on temporary nodes
4734           }
4735           if ( elem )
4736           {
4737             ::SMESH_MeshEditor editor( _impl );
4738             elem = editor.AddElement( nodes, elem->GetType(), elem->IsPoly() );
4739           }
4740         }
4741         if ( elem )
4742           elemsByType[ elem->GetType() ].push_back( elem );
4743       }
4744
4745       // how many groups to create?
4746       int nbTypes = 0;
4747       for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
4748         nbTypes += int( !elemsByType[ i ].empty() );
4749       groups->length( nbTypes );
4750
4751       // create groups
4752       for ( int i = 0, iG = -1; i < SMDSAbs_NbElementTypes; ++i )
4753       {
4754         vector< const SMDS_MeshElement* >& elems = elemsByType[ i ];
4755         if ( elems.empty() ) continue;
4756
4757         groups[ ++iG ] = createGroup( SMESH::ElementType(i), theGroupName );
4758         if ( _gen_i->CanPublishInStudy( groups[ iG ] ))
4759         {
4760           SALOMEDS::Study_var  study = _gen_i->GetCurrentStudy();
4761           SMESH::SMESH_Mesh_var mesh = _this();
4762           SALOMEDS::SObject_wrap aSO =
4763             _gen_i->PublishGroup( study, mesh, groups[ iG ],
4764                                  GEOM::GEOM_Object::_nil(), theGroupName);
4765           aSO->_is_nil(); // avoid "unused variable" warning
4766         }
4767         SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
4768         if ( !grp_i ) continue;
4769
4770         if ( SMESHDS_Group*  grpDS = dynamic_cast< SMESHDS_Group* >( grp_i->GetGroupDS() ))
4771           for ( size_t iE = 0; iE < elems.size(); ++iE )
4772             grpDS->SMDSGroup().Add( elems[ iE ]);
4773       }
4774     }
4775   }
4776
4777   return groups._retn();
4778 }
4779
4780 //=============================================================================
4781 /*!
4782  * Create and publish group servants if any groups were imported or created anyhow
4783  */
4784 //=============================================================================
4785
4786 void SMESH_Mesh_i::CreateGroupServants()
4787 {
4788   SALOMEDS::Study_var  aStudy = _gen_i->GetCurrentStudy();
4789   SMESH::SMESH_Mesh_var aMesh = _this();
4790
4791   set<int> addedIDs;
4792   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
4793   while ( groupIt->more() )
4794   {
4795     ::SMESH_Group* group = groupIt->next();
4796     int            anId = group->GetGroupDS()->GetID();
4797
4798     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
4799     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
4800       continue;
4801     addedIDs.insert( anId );
4802
4803     SMESH_GroupBase_i* aGroupImpl;
4804     TopoDS_Shape       shape;
4805     if ( SMESHDS_GroupOnGeom* groupOnGeom =
4806          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
4807     {
4808       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
4809       shape      = groupOnGeom->GetShape();
4810     }
4811     else {
4812       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
4813     }
4814
4815     SMESH::SMESH_GroupBase_var groupVar = aGroupImpl->_this();
4816     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
4817     aGroupImpl->Register();
4818
4819     // register CORBA object for persistence
4820     int nextId = _gen_i->RegisterObject( groupVar );
4821     if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
4822     else        { nextId = 0; } // avoid "unused variable" warning in release mode
4823
4824     // publishing the groups in the study
4825     if ( !aStudy->_is_nil() ) {
4826       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
4827       _gen_i->PublishGroup( aStudy, aMesh, groupVar, shapeVar, group->GetName());
4828     }
4829   }
4830   if ( !addedIDs.empty() )
4831   {
4832     // python dump
4833     set<int>::iterator id = addedIDs.begin();
4834     for ( ; id != addedIDs.end(); ++id )
4835     {
4836       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(*id);
4837       int i = std::distance( _mapGroups.begin(), it );
4838       TPythonDump() << it->second << " = " << aMesh << ".GetGroups()[ "<< i << " ]";
4839     }
4840   }
4841 }
4842
4843 //=============================================================================
4844 /*!
4845  * \brief Return groups cantained in _mapGroups by their IDs
4846  */
4847 //=============================================================================
4848
4849 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
4850 {
4851   int nbGroups = groupIDs.size();
4852   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
4853   aList->length( nbGroups );
4854
4855   list<int>::const_iterator ids = groupIDs.begin();
4856   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
4857   {
4858     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
4859     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
4860       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
4861   }
4862   aList->length( nbGroups );
4863   return aList._retn();
4864 }
4865
4866 //=============================================================================
4867 /*!
4868  * \brief Return information about imported file
4869  */
4870 //=============================================================================
4871
4872 SMESH::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
4873 {
4874   SMESH::MedFileInfo_var res( _medFileInfo );
4875   if ( !res.operator->() ) {
4876     res = new SMESH::MedFileInfo;
4877     res->fileName = "";
4878     res->fileSize = res->major = res->minor = res->release = -1;
4879   }
4880   return res._retn();
4881 }
4882
4883 //=============================================================================
4884 /*!
4885  * \brief Pass names of mesh groups from study to mesh DS
4886  */
4887 //=============================================================================
4888
4889 void SMESH_Mesh_i::checkGroupNames()
4890 {
4891   int nbGrp = NbGroups();
4892   if ( !nbGrp )
4893     return;
4894
4895   SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
4896   if ( aStudy->_is_nil() )
4897     return; // nothing to do
4898   
4899   SMESH::ListOfGroups* grpList = 0;
4900   // avoid dump of "GetGroups"
4901   {
4902     // store python dump into a local variable inside local scope
4903     SMESH::TPythonDump pDump; // do not delete this line of code
4904     grpList = GetGroups();
4905   }
4906
4907   for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
4908     SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
4909     if ( !aGrp )
4910       continue;
4911     SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aStudy, aGrp );
4912     if ( aGrpSO->_is_nil() )
4913       continue;
4914     // correct name of the mesh group if necessary
4915     const char* guiName = aGrpSO->GetName();
4916     if ( strcmp(guiName, aGrp->GetName()) )
4917       aGrp->SetName( guiName );
4918   }
4919 }
4920
4921 //=============================================================================
4922 /*!
4923  * \brief Sets list of notebook variables used for Mesh operations separated by ":" symbol
4924  */
4925 //=============================================================================
4926 void SMESH_Mesh_i::SetParameters(const char* theParameters)
4927 {
4928   SMESH_Gen_i::GetSMESHGen()->UpdateParameters( CORBA::Object_var( _this() ).in(),
4929                                                 theParameters );
4930 }
4931
4932 //=============================================================================
4933 /*!
4934  * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
4935  */
4936 //=============================================================================
4937
4938 char* SMESH_Mesh_i::GetParameters()
4939 {
4940   return SMESH_Gen_i::GetSMESHGen()->GetParameters( SMESH::SMESH_Mesh_var( _this()) );
4941 }
4942
4943 //=============================================================================
4944 /*!
4945  * \brief Returns list of notebook variables used for last Mesh operation
4946  */
4947 //=============================================================================
4948 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
4949 {
4950   SMESH::string_array_var aResult = new SMESH::string_array();
4951   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
4952   if(gen) {
4953     CORBA::String_var aParameters = GetParameters();
4954     SALOMEDS::Study_var    aStudy = gen->GetCurrentStudy();
4955     if ( !aStudy->_is_nil()) {
4956       SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters); 
4957       if(aSections->length() > 0) {
4958         SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1];
4959         aResult->length(aVars.length());
4960         for(int i = 0;i < aVars.length();i++)
4961           aResult[i] = CORBA::string_dup( aVars[i]);
4962       }
4963     }
4964   }
4965   return aResult._retn();
4966 }
4967
4968 //=======================================================================
4969 //function : GetTypes
4970 //purpose  : Returns types of elements it contains
4971 //=======================================================================
4972
4973 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
4974 {
4975   if ( _preMeshInfo )
4976     return _preMeshInfo->GetTypes();
4977
4978   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
4979
4980   types->length( 5 );
4981   int nbTypes = 0;
4982   if (_impl->NbEdges())      types[nbTypes++] = SMESH::EDGE;
4983   if (_impl->NbFaces())      types[nbTypes++] = SMESH::FACE;
4984   if (_impl->NbVolumes())    types[nbTypes++] = SMESH::VOLUME;
4985   if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
4986   if (_impl->NbBalls())      types[nbTypes++] = SMESH::BALL;
4987   types->length( nbTypes );
4988
4989   return types._retn();
4990 }
4991
4992 //=======================================================================
4993 //function : GetMesh
4994 //purpose  : Returns self
4995 //=======================================================================
4996
4997 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
4998 {
4999   return SMESH::SMESH_Mesh::_duplicate( _this() );
5000 }
5001
5002 //=======================================================================
5003 //function : IsMeshInfoCorrect
5004 //purpose  : * Returns false if GetMeshInfo() returns incorrect information that may
5005 //           * happen if mesh data is not yet fully loaded from the file of study.
5006 //=======================================================================
5007
5008 bool SMESH_Mesh_i::IsMeshInfoCorrect()
5009 {
5010   return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
5011 }
5012
5013 //=============================================================================
5014 /*!
5015  * \brief Returns number of mesh elements per each \a EntityType
5016  */
5017 //=============================================================================
5018
5019 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
5020 {
5021   if ( _preMeshInfo )
5022     return _preMeshInfo->GetMeshInfo();
5023
5024   SMESH::long_array_var aRes = new SMESH::long_array();
5025   aRes->length(SMESH::Entity_Last);
5026   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
5027     aRes[i] = 0;
5028   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5029   if (!aMeshDS)
5030     return aRes._retn();
5031   const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
5032   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
5033     aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
5034   return aRes._retn();
5035 }
5036
5037 //=============================================================================
5038 /*!
5039  * \brief Returns number of mesh elements per each \a ElementType
5040  */
5041 //=============================================================================
5042
5043 SMESH::long_array* SMESH_Mesh_i::GetNbElementsByType()
5044 {
5045   SMESH::long_array_var aRes = new SMESH::long_array();
5046   aRes->length(SMESH::NB_ELEMENT_TYPES);
5047   for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
5048     aRes[ i ] = 0;
5049
5050   const SMDS_MeshInfo* meshInfo = 0;
5051   if ( _preMeshInfo )
5052     meshInfo = _preMeshInfo;
5053   else if ( SMESHDS_Mesh* meshDS = _impl->GetMeshDS() )
5054     meshInfo = & meshDS->GetMeshInfo();
5055
5056   if (meshInfo)
5057     for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
5058       aRes[i] = meshInfo->NbElements((SMDSAbs_ElementType)i);
5059
5060   return aRes._retn();
5061 }
5062
5063 //=============================================================================
5064 /*
5065  * Collect statistic of mesh elements given by iterator
5066  */
5067 //=============================================================================
5068
5069 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
5070                                    SMESH::long_array&         theInfo)
5071 {
5072   if (!theItr) return;
5073   while (theItr->more())
5074     theInfo[ theItr->next()->GetEntityType() ]++;
5075 }
5076
5077 //=============================================================================
5078 namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
5079            *                                             SMESH::ElementType        type) */
5080 {
5081   using namespace SMESH::Controls;
5082   //-----------------------------------------------------------------------------
5083   struct PredicateIterator : public SMDS_ElemIterator
5084   {
5085     SMDS_ElemIteratorPtr    _elemIter;
5086     PredicatePtr            _predicate;
5087     const SMDS_MeshElement* _elem;
5088
5089     PredicateIterator( SMDS_ElemIteratorPtr   iterator,
5090                        PredicatePtr predicate):
5091       _elemIter(iterator), _predicate(predicate)
5092     {
5093       next();
5094     }
5095     virtual bool more()
5096     {
5097       return _elem;
5098     }
5099     virtual const SMDS_MeshElement* next()
5100     {
5101       const SMDS_MeshElement* res = _elem;
5102       _elem = 0;
5103       while ( _elemIter->more() && !_elem )
5104       {
5105         _elem = _elemIter->next();
5106         if ( _elem && ( !_predicate->IsSatisfy( _elem->GetID() )))
5107           _elem = 0;
5108       }
5109       return res;
5110     }
5111   };
5112
5113   //-----------------------------------------------------------------------------
5114   struct IDSourceIterator : public SMDS_ElemIterator
5115   {
5116     const CORBA::Long*        _idPtr;
5117     const CORBA::Long*        _idEndPtr;
5118     SMESH::long_array_var     _idArray;
5119     const SMDS_Mesh*          _mesh;
5120     const SMDSAbs_ElementType _type;
5121     const SMDS_MeshElement*   _elem;
5122
5123     IDSourceIterator( const SMDS_Mesh*    mesh,
5124                       const CORBA::Long*  ids,
5125                       const int           nbIds,
5126                       SMDSAbs_ElementType type):
5127       _idPtr( ids ), _idEndPtr( ids + nbIds ), _mesh( mesh ), _type( type ), _elem( 0 )
5128     {
5129       if ( _idPtr && nbIds && _mesh )
5130         next();
5131     }
5132     IDSourceIterator( const SMDS_Mesh*    mesh,
5133                       SMESH::long_array*  idArray,
5134                       SMDSAbs_ElementType type):
5135       _idPtr( 0 ), _idEndPtr( 0 ), _idArray( idArray), _mesh( mesh ), _type( type ), _elem( 0 )
5136     {
5137       if ( idArray && _mesh )
5138       {
5139         _idPtr    = &_idArray[0];
5140         _idEndPtr = _idPtr + _idArray->length();
5141         next();
5142       }
5143     }
5144     virtual bool more()
5145     {
5146       return _elem;
5147     }
5148     virtual const SMDS_MeshElement* next()
5149     {
5150       const SMDS_MeshElement* res = _elem;
5151       _elem = 0;
5152       while ( _idPtr < _idEndPtr && !_elem )
5153       {
5154         if ( _type == SMDSAbs_Node )
5155         {
5156           _elem = _mesh->FindNode( *_idPtr++ );
5157         }
5158         else if ((_elem = _mesh->FindElement( *_idPtr++ )) &&
5159                  _elem->GetType() != _type )
5160         {
5161           _elem = 0;
5162         }
5163       }
5164       return res;
5165     }
5166   };
5167   //-----------------------------------------------------------------------------
5168
5169   struct NodeOfElemIterator : public SMDS_ElemIterator
5170   {
5171     TColStd_MapOfInteger    _checkedNodeIDs;
5172     SMDS_ElemIteratorPtr    _elemIter;
5173     SMDS_ElemIteratorPtr    _nodeIter;
5174     const SMDS_MeshElement* _node;
5175
5176     NodeOfElemIterator( SMDS_ElemIteratorPtr iter ): _elemIter( iter ), _node( 0 )
5177     {
5178       if ( _elemIter && _elemIter->more() )
5179       {
5180         _nodeIter = _elemIter->next()->nodesIterator();
5181         next();
5182       }
5183     }
5184     virtual bool more()
5185     {
5186       return _node;
5187     }
5188     virtual const SMDS_MeshElement* next()
5189     {
5190       const SMDS_MeshElement* res = _node;
5191       _node = 0;
5192       while (( _elemIter->more() || _nodeIter->more() ) && !_node )
5193       {
5194         if ( _nodeIter->more() )
5195         {
5196           _node = _nodeIter->next();
5197           if ( !_checkedNodeIDs.Add( _node->GetID() ))
5198             _node = 0;
5199         }
5200         else
5201         {
5202           _nodeIter = _elemIter->next()->nodesIterator();
5203         }
5204       }
5205       return res;
5206     }
5207   };
5208 }
5209
5210 //=============================================================================
5211 /*
5212  * Return iterator on elements of given type in given object
5213  */
5214 //=============================================================================
5215
5216 SMDS_ElemIteratorPtr SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_ptr theObject,
5217                                                SMESH::ElementType        theType)
5218 {
5219   SMDS_ElemIteratorPtr  elemIt;
5220   bool                  typeOK = false;
5221   SMDSAbs_ElementType elemType = SMDSAbs_ElementType( theType );
5222
5223   SMESH::SMESH_Mesh_var meshVar = theObject->GetMesh();
5224   SMESH_Mesh_i*          mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( meshVar );
5225   if ( !mesh_i ) return elemIt;
5226   SMESHDS_Mesh*          meshDS = mesh_i->GetImpl().GetMeshDS();
5227
5228   if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
5229   {
5230     elemIt = meshDS->elementsIterator( elemType );
5231     typeOK = true;
5232   }
5233   else if ( SMESH_subMesh_i* submesh_i = SMESH::DownCast<SMESH_subMesh_i*>( theObject ))
5234   {
5235     SMESHDS_SubMesh* sm = ((SMESHDS_Mesh*) meshDS)->MeshElements( submesh_i->GetId() );
5236     if ( sm )
5237     {
5238       elemIt = sm->GetElements();
5239       if ( elemType != SMDSAbs_Node )
5240       {
5241         typeOK = ( elemIt && elemIt->more() && elemIt->next()->GetType() == elemType );
5242         elemIt = typeOK ? sm->GetElements() : SMDS_ElemIteratorPtr();
5243       }
5244     }
5245   }
5246   else if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( theObject ))
5247   {
5248     SMESHDS_GroupBase* groupDS = group_i->GetGroupDS();
5249     if ( groupDS && ( groupDS->GetType() == elemType || elemType == SMDSAbs_Node ))
5250     {
5251       elemIt = groupDS->GetElements();
5252       typeOK = ( groupDS->GetType() == elemType );
5253     }
5254   }
5255   else if ( SMESH::Filter_i* filter_i = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5256   {
5257     if ( filter_i->GetElementType() == theType || elemType == SMDSAbs_Node )
5258     {
5259       SMESH::Predicate_i* pred_i = filter_i->GetPredicate_i();
5260       if ( pred_i && pred_i->GetPredicate() )
5261       {
5262         SMDSAbs_ElementType filterType = SMDSAbs_ElementType( filter_i->GetElementType() );
5263         SMDS_ElemIteratorPtr allElemIt = meshDS->elementsIterator( filterType );
5264         elemIt = SMDS_ElemIteratorPtr( new PredicateIterator( allElemIt, pred_i->GetPredicate() ));
5265         typeOK = ( filterType == elemType );
5266       }
5267     }
5268   }
5269   else
5270   {
5271     SMESH::array_of_ElementType_var types = theObject->GetTypes();
5272     const bool                    isNodes = ( types->length() == 1 && types[0] == SMESH::NODE );
5273     if ( isNodes && elemType != SMDSAbs_Node )
5274       return elemIt;
5275     if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theObject ))
5276     {
5277       int nbIds;
5278       if ( CORBA::Long* ids = SMESH_MeshEditor_i::GetTemporaryIDs( theObject, nbIds ))
5279         elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids, nbIds, elemType ));
5280     }
5281     else
5282     {
5283       SMESH::long_array_var ids = theObject->GetIDs();
5284       elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids._retn(), elemType ));
5285     }
5286     typeOK = ( isNodes == ( elemType == SMDSAbs_Node ));
5287   }
5288
5289   if ( elemIt && elemIt->more() && !typeOK )
5290   {
5291     if ( elemType == SMDSAbs_Node )
5292     {
5293       elemIt = SMDS_ElemIteratorPtr( new NodeOfElemIterator( elemIt ));
5294     }
5295     else
5296     {
5297       elemIt = SMDS_ElemIteratorPtr();
5298     }
5299   }
5300   return elemIt;
5301 }
5302
5303 //=============================================================================
5304 namespace // Finding concurrent hypotheses
5305 //=============================================================================
5306 {
5307
5308 /*!
5309  * \brief mapping of mesh dimension into shape type
5310  */
5311 TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
5312 {
5313   TopAbs_ShapeEnum aType = TopAbs_SOLID;
5314   switch ( theDim ) {
5315   case 0: aType = TopAbs_VERTEX; break;
5316   case 1: aType = TopAbs_EDGE; break;
5317   case 2: aType = TopAbs_FACE; break;
5318   case 3:
5319   default:aType = TopAbs_SOLID; break;
5320   }
5321   return aType;
5322 }
5323
5324 //-----------------------------------------------------------------------------
5325 /*!
5326  * \brief Internal structure used to find concurent submeshes
5327  *
5328  * It represents a pair < submesh, concurent dimension >, where
5329  * 'concurrent dimension' is dimension of shape where the submesh can concurent
5330  *  with another submesh. In other words, it is dimension of a hypothesis assigned
5331  *  to submesh.
5332  */
5333 class SMESH_DimHyp
5334 {
5335  public:
5336   //! fileds
5337   int _dim;    //!< a dimension the algo can build (concurrent dimension)
5338   int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
5339   TopTools_MapOfShape _shapeMap;
5340   SMESH_subMesh*      _subMesh;
5341   list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
5342
5343   //-----------------------------------------------------------------------------
5344   // Return the algorithm
5345   const SMESH_Algo* GetAlgo() const
5346   { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
5347
5348   //-----------------------------------------------------------------------------
5349   //! Constructors
5350   SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
5351                const int            theDim,
5352                const TopoDS_Shape&  theShape)
5353   {
5354     _subMesh = (SMESH_subMesh*)theSubMesh;
5355     SetShape( theDim, theShape );
5356   }
5357
5358   //-----------------------------------------------------------------------------
5359   //! set shape
5360   void SetShape(const int           theDim,
5361                 const TopoDS_Shape& theShape)
5362   {
5363     _dim = theDim;
5364     _ownDim = SMESH_Gen::GetShapeDim(theShape);
5365     if (_dim >= _ownDim)
5366       _shapeMap.Add( theShape );
5367     else {
5368       TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
5369       for( ; anExp.More(); anExp.Next() )
5370         _shapeMap.Add( anExp.Current() );
5371     }
5372   }
5373
5374   //-----------------------------------------------------------------------------
5375   //! Check sharing of sub-shapes
5376   static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
5377                                const TopTools_MapOfShape& theToFind,
5378                                const TopAbs_ShapeEnum     theType)
5379   {
5380     bool isShared = false;
5381     TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
5382     for (; !isShared && anItr.More(); anItr.Next() )
5383     {
5384       const TopoDS_Shape aSubSh = anItr.Key();
5385       // check for case when concurrent dimensions are same
5386       isShared = theToFind.Contains( aSubSh );
5387       // check for sub-shape with concurrent dimension
5388       TopExp_Explorer anExp( aSubSh, theType );
5389       for ( ; !isShared && anExp.More(); anExp.Next() )
5390         isShared = theToFind.Contains( anExp.Current() );
5391     }
5392     return isShared;
5393   }
5394   
5395   //-----------------------------------------------------------------------------
5396   //! check algorithms
5397   static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
5398                         const SMESHDS_Hypothesis* theA2)
5399   {
5400     if ( !theA1 || !theA2 ||
5401          theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
5402          theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
5403       return false; // one of the hypothesis is not algorithm
5404     // check algorithm names (should be equal)
5405     return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
5406   }
5407
5408   
5409   //-----------------------------------------------------------------------------
5410   //! Check if sub-shape hypotheses are concurrent
5411   bool IsConcurrent(const SMESH_DimHyp* theOther) const
5412   {
5413     if ( _subMesh == theOther->_subMesh )
5414       return false; // same sub-shape - should not be
5415
5416     // if ( <own dim of either of submeshes> == <concurrent dim> &&
5417     //      any of the two submeshes is not on COMPOUND shape )
5418     //  -> no concurrency
5419     bool meIsCompound    = (_subMesh->GetSubMeshDS() &&
5420                             _subMesh->GetSubMeshDS()->IsComplexSubmesh());
5421     bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
5422                             theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
5423     if ( (_ownDim == _dim  || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
5424       return false;
5425
5426 //     bool checkSubShape = ( _dim >= theOther->_dim )
5427 //       ? isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(theOther->_dim) )
5428 //       : isShareSubShapes( theOther->_shapeMap, _shapeMap, shapeTypeByDim(_dim) ) ;
5429     bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
5430     if ( !checkSubShape )
5431         return false;
5432
5433     // check algorithms to be same
5434     if ( !checkAlgo( this->GetAlgo(), theOther->GetAlgo() ))
5435       return true; // different algorithms -> concurrency !
5436
5437     // check hypothesises for concurrence (skip first as algorithm)
5438     int nbSame = 0;
5439     // pointers should be same, because it is referened from mesh hypothesis partition
5440     list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
5441     list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
5442     for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
5443       if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
5444         nbSame++;
5445     // the submeshes are concurrent if their algorithms has different parameters
5446     return nbSame != theOther->_hypotheses.size() - 1;
5447   }
5448
5449   // Return true if algorithm of this SMESH_DimHyp is used if no
5450   // sub-mesh order is imposed by the user
5451   bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
5452   {
5453     // NeedDiscreteBoundary() algo has a higher priority
5454     if ( this    ->GetAlgo()->NeedDiscreteBoundary() !=
5455          theOther->GetAlgo()->NeedDiscreteBoundary() )
5456       return !this->GetAlgo()->NeedDiscreteBoundary();
5457
5458     return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
5459   }
5460   
5461 }; // end of SMESH_DimHyp
5462 //-----------------------------------------------------------------------------
5463
5464 typedef list<const SMESH_DimHyp*> TDimHypList;
5465
5466 //-----------------------------------------------------------------------------
5467
5468 void addDimHypInstance(const int                               theDim, 
5469                        const TopoDS_Shape&                     theShape,
5470                        const SMESH_Algo*                       theAlgo,
5471                        const SMESH_subMesh*                    theSubMesh,
5472                        const list <const SMESHDS_Hypothesis*>& theHypList,
5473                        TDimHypList*                            theDimHypListArr )
5474 {
5475   TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
5476   if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) {
5477     SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
5478     dimHyp->_hypotheses.push_front(theAlgo);
5479     listOfdimHyp.push_back( dimHyp );
5480   }
5481   
5482   SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
5483   dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
5484                               theHypList.begin(), theHypList.end() );
5485 }
5486
5487 //-----------------------------------------------------------------------------
5488 void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
5489                            TDimHypList&        theListOfConcurr)
5490 {
5491   if ( theListOfConcurr.empty() )
5492   {
5493     theListOfConcurr.push_back( theDimHyp );
5494   }
5495   else
5496   {
5497     TDimHypList::iterator hypIt = theListOfConcurr.begin();
5498     while ( hypIt != theListOfConcurr.end() &&
5499             !theDimHyp->IsHigherPriorityThan( *hypIt ))
5500       ++hypIt;
5501     theListOfConcurr.insert( hypIt, theDimHyp );
5502   }
5503 }
5504
5505 //-----------------------------------------------------------------------------
5506 void findConcurrents(const SMESH_DimHyp* theDimHyp,
5507                      const TDimHypList&  theListOfDimHyp,
5508                      TDimHypList&        theListOfConcurrHyp,
5509                      set<int>&           theSetOfConcurrId )
5510 {
5511   TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
5512   for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
5513   {
5514     const SMESH_DimHyp* curDimHyp = *rIt;
5515     if ( curDimHyp == theDimHyp )
5516       break; // meet own dimHyp pointer in same dimension
5517
5518     if ( theDimHyp->IsConcurrent( curDimHyp ) &&
5519          theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
5520     {
5521       addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
5522     }
5523   }
5524 }
5525
5526 //-----------------------------------------------------------------------------
5527 void unionLists(TListOfInt&       theListOfId,
5528                 TListOfListOfInt& theListOfListOfId,
5529                 const int         theIndx )
5530 {
5531   TListOfListOfInt::iterator it = theListOfListOfId.begin();
5532   for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) {
5533     if ( i < theIndx )
5534       continue; //skip already treated lists
5535     // check if other list has any same submesh object
5536     TListOfInt& otherListOfId = *it;
5537     if ( find_first_of( theListOfId.begin(), theListOfId.end(),
5538                         otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
5539       continue;
5540          
5541     // union two lists (from source into target)
5542     TListOfInt::iterator it2 = otherListOfId.begin();
5543     for ( ; it2 != otherListOfId.end(); it2++ ) {
5544       if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
5545         theListOfId.push_back(*it2);
5546     }
5547     // clear source list
5548     otherListOfId.clear();
5549   }
5550 }
5551 //-----------------------------------------------------------------------------
5552
5553 //! free memory allocated for dimension-hypothesis objects
5554 void removeDimHyps( TDimHypList* theArrOfList )
5555 {
5556   for (int i = 0; i < 4; i++ ) {
5557     TDimHypList& listOfdimHyp = theArrOfList[i];
5558     TDimHypList::const_iterator it = listOfdimHyp.begin();
5559     for ( ; it != listOfdimHyp.end(); it++ )
5560       delete (*it);
5561   }
5562 }
5563
5564 //-----------------------------------------------------------------------------
5565 /*!
5566  * \brief find common submeshes with given submesh
5567  * \param theSubMeshList list of already collected submesh to check
5568  * \param theSubMesh given submesh to intersect with other
5569  * \param theCommonSubMeshes collected common submeshes
5570  */
5571 void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
5572                         const SMESH_subMesh*        theSubMesh,
5573                         set<const SMESH_subMesh*>&  theCommon )
5574 {
5575   if ( !theSubMesh )
5576     return;
5577   list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
5578   for ( ; it != theSubMeshList.end(); it++ )
5579     theSubMesh->FindIntersection( *it, theCommon );
5580   theSubMeshList.push_back( theSubMesh );
5581   //theCommon.insert( theSubMesh );
5582 }
5583
5584 //-----------------------------------------------------------------------------
5585 bool isSubMeshInList ( int smID, const TListOfListOfInt& smLists )
5586 {
5587   TListOfListOfInt::const_iterator listsIt = smLists.begin();
5588   for ( ; listsIt != smLists.end(); ++listsIt )
5589   {
5590     const TListOfInt& smIDs = *listsIt;
5591     if ( std::find( smIDs.begin(), smIDs.end(), smID ) != smIDs.end() )
5592       return true;
5593   }
5594   return false;
5595 }
5596
5597 } // namespace
5598
5599 //=============================================================================
5600 /*!
5601  * \brief Return \c true if a meshing order not yet set for a concurrent sub-mesh
5602  */
5603 //=============================================================================
5604
5605 CORBA::Boolean SMESH_Mesh_i::IsUnorderedSubMesh(CORBA::Long submeshID)
5606 {
5607   TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
5608   if ( isSubMeshInList( submeshID, anOrder ))
5609     return false;
5610
5611   TListOfListOfInt allConurrent = findConcurrentSubMeshes();
5612   return isSubMeshInList( submeshID, allConurrent );
5613 }
5614
5615 //=============================================================================
5616 /*!
5617  * \brief Return submesh objects list in meshing order
5618  */
5619 //=============================================================================
5620
5621 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
5622 {
5623   SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
5624
5625   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5626   if ( !aMeshDS )
5627     return aResult._retn();
5628
5629   TListOfListOfInt      anOrder = GetImpl().GetMeshOrder(); // already defined order
5630   TListOfListOfInt allConurrent = findConcurrentSubMeshes();
5631   anOrder.splice( anOrder.end(), allConurrent );
5632
5633   int listIndx = 0;
5634   TListOfListOfInt::iterator listIt = anOrder.begin();
5635   for(; listIt != anOrder.end(); listIt++, listIndx++ )
5636     unionLists( *listIt,  anOrder, listIndx + 1 );
5637
5638   // convert submesh ids into interface instances
5639   //  and dump command into python
5640   convertMeshOrder( anOrder, aResult, false );
5641
5642   return aResult._retn();
5643 }
5644
5645 //=============================================================================
5646 /*!
5647  * \brief Finds concurrent sub-meshes
5648  */
5649 //=============================================================================
5650
5651 TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes()
5652 {
5653   TListOfListOfInt anOrder;
5654   ::SMESH_Mesh& mesh = GetImpl();
5655   {
5656     // collect submeshes and detect concurrent algorithms and hypothesises
5657     TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
5658
5659     map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
5660     for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) {
5661       ::SMESH_subMesh* sm = (*i_sm).second;
5662       // shape of submesh
5663       const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
5664
5665       // list of assigned hypothesises
5666       const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
5667       // Find out dimensions where the submesh can be concurrent.
5668       // We define the dimensions by algo of each of hypotheses in hypList
5669       list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
5670       for( ; hypIt != hypList.end(); hypIt++ ) {
5671         SMESH_Algo* anAlgo = 0;
5672         const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
5673         if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
5674           // hyp it-self is algo
5675           anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
5676         else {
5677           // try to find algorithm with help of sub-shapes
5678           TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
5679           for ( ; !anAlgo && anExp.More(); anExp.Next() )
5680             anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
5681         }
5682         if (!anAlgo)
5683           continue; // no algorithm assigned to a current submesh
5684
5685         int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
5686         // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary())
5687
5688         // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
5689         for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
5690           addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
5691       }
5692     } // end iterations on submesh
5693     
5694     // iterate on created dimension-hypotheses and check for concurrents
5695     for ( int i = 0; i < 4; i++ ) {
5696       const TDimHypList& listOfDimHyp = dimHypListArr[i];
5697       // check for concurrents in own and other dimensions (step-by-step)
5698       TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
5699       for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) {
5700         const SMESH_DimHyp* dimHyp = *dhIt;
5701         TDimHypList listOfConcurr;
5702         set<int>    setOfConcurrIds;
5703         // looking for concurrents and collect into own list
5704         for ( int j = i; j < 4; j++ )
5705           findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
5706         // check if any concurrents found
5707         if ( listOfConcurr.size() > 0 ) {
5708           // add own submesh to list of concurrent
5709           addInOrderOfPriority( dimHyp, listOfConcurr );
5710           list<int> listOfConcurrIds;
5711           TDimHypList::iterator hypIt = listOfConcurr.begin();
5712           for ( ; hypIt != listOfConcurr.end(); ++hypIt )
5713             listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
5714           anOrder.push_back( listOfConcurrIds );
5715         }
5716       }
5717     }
5718     
5719     removeDimHyps(dimHypListArr);
5720     
5721     // now, minimise the number of concurrent groups
5722     // Here we assume that lists of submeshes can have same submesh
5723     // in case of multi-dimension algorithms, as result
5724     //  list with common submesh has to be united into one list
5725     int listIndx = 0;
5726     TListOfListOfInt::iterator listIt = anOrder.begin();
5727     for(; listIt != anOrder.end(); listIt++, listIndx++ )
5728       unionLists( *listIt,  anOrder, listIndx + 1 );
5729   }
5730
5731   return anOrder;
5732 }
5733
5734 //=============================================================================
5735 /*!
5736  * \brief Set submesh object order
5737  * \param theSubMeshArray submesh array order
5738  */
5739 //=============================================================================
5740
5741 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
5742 {
5743   if ( _preMeshInfo )
5744     _preMeshInfo->ForgetOrLoad();
5745
5746   bool res = false;
5747   ::SMESH_Mesh& mesh = GetImpl();
5748
5749   TPythonDump aPythonDump; // prevent dump of called methods
5750   aPythonDump << "isDone = " << SMESH::SMESH_Mesh_var(_this()) << ".SetMeshOrder( [ ";
5751
5752   TListOfListOfInt subMeshOrder;
5753   for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
5754   {
5755     const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
5756     TListOfInt subMeshIds;
5757     aPythonDump << "[ ";
5758     // Collect subMeshes which should be clear
5759     //  do it list-by-list, because modification of submesh order
5760     //  take effect between concurrent submeshes only
5761     set<const SMESH_subMesh*> subMeshToClear;
5762     list<const SMESH_subMesh*> subMeshList;
5763     for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
5764     {
5765       const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
5766       if ( j > 0 )
5767         aPythonDump << ", ";
5768       aPythonDump << subMesh;
5769       subMeshIds.push_back( subMesh->GetId() );
5770       // detect common parts of submeshes
5771       if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
5772         findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
5773     }
5774     aPythonDump << " ]";
5775     subMeshOrder.push_back( subMeshIds );
5776
5777     // clear collected submeshes
5778     set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
5779     for ( ; clrIt != subMeshToClear.end(); clrIt++ )
5780       if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
5781         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
5782   }
5783   aPythonDump << " ])";
5784
5785   mesh.SetMeshOrder( subMeshOrder );
5786   res = true;
5787   
5788   return res;
5789 }
5790
5791 //=============================================================================
5792 /*!
5793  * \brief Convert submesh ids into submesh interfaces
5794  */
5795 //=============================================================================
5796
5797 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt&     theIdsOrder,
5798                                      SMESH::submesh_array_array& theResOrder,
5799                                      const bool                  theIsDump)
5800 {
5801   int nbSet = theIdsOrder.size();
5802   TPythonDump aPythonDump; // prevent dump of called methods
5803   if ( theIsDump )
5804     aPythonDump << "[ ";
5805   theResOrder.length(nbSet);
5806   TListOfListOfInt::const_iterator it = theIdsOrder.begin();
5807   int listIndx = 0;
5808   for( ; it != theIdsOrder.end(); it++ ) {
5809     // translate submesh identificators into submesh objects
5810     //  takeing into account real number of concurrent lists
5811     const TListOfInt& aSubOrder = (*it);
5812     if (!aSubOrder.size())
5813       continue;
5814     if ( theIsDump )
5815       aPythonDump << "[ ";
5816     // convert shape indeces into interfaces
5817     SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
5818     aResSubSet->length(aSubOrder.size());
5819     TListOfInt::const_iterator subIt = aSubOrder.begin();
5820     int j;
5821     for( j = 0; subIt != aSubOrder.end(); subIt++ ) {
5822       if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
5823         continue;
5824       SMESH::SMESH_subMesh_var subMesh =
5825         SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
5826       if ( theIsDump ) {
5827         if ( j > 0 )
5828           aPythonDump << ", ";
5829         aPythonDump << subMesh;
5830       }
5831       aResSubSet[ j++ ] = subMesh;
5832     }
5833     if ( theIsDump )
5834       aPythonDump << " ]";
5835     if ( j > 1 )
5836       theResOrder[ listIndx++ ] = aResSubSet;
5837   }
5838   // correct number of lists
5839   theResOrder.length( listIndx );
5840
5841   if ( theIsDump ) {
5842     // finilise python dump
5843     aPythonDump << " ]";
5844     aPythonDump << " = " << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshOrder()";
5845   }
5846 }
5847
5848 //================================================================================
5849 //
5850 // Implementation of SMESH_MeshPartDS
5851 //
5852 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
5853   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
5854 {
5855   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
5856   SMESH_Mesh_i*       mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
5857
5858   _meshDS = mesh_i->GetImpl().GetMeshDS();
5859
5860   SetPersistentId( _meshDS->GetPersistentId() );
5861
5862   if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
5863   {
5864     // <meshPart> is the whole mesh
5865     myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
5866     // copy groups
5867     set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
5868     myGroupSet = _meshDS->GetGroups();
5869   }
5870   else
5871   {
5872     TMeshInfo tmpInfo;
5873     SMESH::long_array_var           anIDs = meshPart->GetIDs();
5874     SMESH::array_of_ElementType_var types = meshPart->GetTypes();
5875     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5876     {
5877       for (int i=0; i < anIDs->length(); i++)
5878         if ( const SMDS_MeshNode * n = _meshDS->FindNode(anIDs[i]))
5879           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
5880             tmpInfo.Add( n );
5881     }
5882     else
5883     {
5884       for (int i=0; i < anIDs->length(); i++)
5885         if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
5886           if ( _elements[ e->GetType() ].insert( e ).second )
5887           {
5888             tmpInfo.Add( e );
5889             SMDS_ElemIteratorPtr nIt = e->nodesIterator();
5890             while ( nIt->more() )
5891             {
5892               const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
5893               if ( _elements[ SMDSAbs_Node ].insert( n ).second )
5894                 tmpInfo.Add( n );
5895             }
5896           }
5897     }
5898     myInfo = tmpInfo;
5899
5900     _meshDS = 0; // to enforce iteration on _elements and _nodes
5901   }
5902 }
5903 // -------------------------------------------------------------------------------------
5904 SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
5905   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
5906 {
5907   TMeshInfo tmpInfo;
5908   list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
5909   for ( ; partIt != meshPart.end(); ++partIt )
5910     if ( const SMDS_MeshElement * e = *partIt )
5911       if ( _elements[ e->GetType() ].insert( e ).second )
5912       {
5913         tmpInfo.Add( e );
5914         SMDS_ElemIteratorPtr nIt = e->nodesIterator();
5915         while ( nIt->more() )
5916         {
5917           const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
5918           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
5919             tmpInfo.Add( n );
5920         }
5921       }
5922   myInfo = tmpInfo;
5923 }
5924 // -------------------------------------------------------------------------------------
5925 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
5926 {
5927   if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
5928
5929   typedef SMDS_SetIterator
5930     <const SMDS_MeshElement*,
5931     TIDSortedElemSet::const_iterator,
5932     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
5933     SMDS_MeshElement::GeomFilter
5934     > TIter;
5935
5936   SMDSAbs_ElementType type = SMDS_MeshCell::toSmdsType( geomType );
5937
5938   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
5939                                           _elements[type].end(),
5940                                           SMDS_MeshElement::GeomFilter( geomType )));
5941 }
5942 // -------------------------------------------------------------------------------------
5943 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
5944 {
5945   if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
5946
5947   typedef SMDS_SetIterator
5948     <const SMDS_MeshElement*,
5949     TIDSortedElemSet::const_iterator,
5950     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
5951     SMDS_MeshElement::EntityFilter
5952     > TIter;
5953
5954   SMDSAbs_ElementType type = SMDS_MeshCell::toSmdsType( entity );
5955
5956   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
5957                                           _elements[type].end(),
5958                                           SMDS_MeshElement::EntityFilter( entity )));
5959 }
5960 // -------------------------------------------------------------------------------------
5961 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
5962 {
5963   typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
5964   if ( type == SMDSAbs_All && !_meshDS )
5965   {
5966     typedef vector< SMDS_ElemIteratorPtr > TIterVec;
5967     TIterVec iterVec;
5968     for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
5969       if ( !_elements[i].empty() && i != SMDSAbs_Node )
5970         iterVec.push_back
5971           ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
5972
5973     typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
5974     return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
5975   }
5976   return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
5977       ( new TIter( _elements[type].begin(), _elements[type].end() ));
5978 }
5979 // -------------------------------------------------------------------------------------
5980 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType)                       \
5981   iterType SMESH_MeshPartDS::methName( bool idInceasingOrder) const                 \
5982   {                                                                                 \
5983     typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
5984     return _meshDS ? _meshDS->methName(idInceasingOrder) : iterType                 \
5985       ( new TIter( _elements[elemType].begin(), _elements[elemType].end() ));       \
5986   }
5987 // -------------------------------------------------------------------------------------
5988 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
5989 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
5990 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
5991 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
5992 #undef _GET_ITER_DEFINE
5993 //
5994 // END Implementation of SMESH_MeshPartDS
5995 //
5996 //================================================================================
5997
5998