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