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