Salome HOME
0e298af615634bafdb57df3e949399806c94070b
[modules/smesh.git] / src / SMESH_I / SMESH_Mesh_i.cxx
1 // Copyright (C) 2007-2015  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         }
4743         SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
4744         if ( !grp_i ) continue;
4745
4746         if ( SMESHDS_Group*  grpDS = dynamic_cast< SMESHDS_Group* >( grp_i->GetGroupDS() ))
4747           for ( size_t iE = 0; iE < elems.size(); ++iE )
4748             grpDS->SMDSGroup().Add( elems[ iE ]);
4749       }
4750     }
4751   }
4752
4753   return groups._retn();
4754 }
4755
4756 //=============================================================================
4757 /*!
4758  * Create and publish group servants if any groups were imported or created anyhow
4759  */
4760 //=============================================================================
4761
4762 void SMESH_Mesh_i::CreateGroupServants()
4763 {
4764   SALOMEDS::Study_var  aStudy = _gen_i->GetCurrentStudy();
4765   SMESH::SMESH_Mesh_var aMesh = _this();
4766
4767   set<int> addedIDs;
4768   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
4769   while ( groupIt->more() )
4770   {
4771     ::SMESH_Group* group = groupIt->next();
4772     int            anId = group->GetGroupDS()->GetID();
4773
4774     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
4775     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
4776       continue;
4777     addedIDs.insert( anId );
4778
4779     SMESH_GroupBase_i* aGroupImpl;
4780     TopoDS_Shape       shape;
4781     if ( SMESHDS_GroupOnGeom* groupOnGeom =
4782          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
4783     {
4784       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
4785       shape      = groupOnGeom->GetShape();
4786     }
4787     else {
4788       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
4789     }
4790
4791     SMESH::SMESH_GroupBase_var groupVar = aGroupImpl->_this();
4792     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
4793     aGroupImpl->Register();
4794
4795     // register CORBA object for persistence
4796     int nextId = _gen_i->RegisterObject( groupVar );
4797     if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
4798     else        { nextId = 0; } // avoid "unused variable" warning in release mode
4799
4800     // publishing the groups in the study
4801     if ( !aStudy->_is_nil() ) {
4802       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
4803       _gen_i->PublishGroup( aStudy, aMesh, groupVar, shapeVar, group->GetName());
4804     }
4805   }
4806   if ( !addedIDs.empty() )
4807   {
4808     // python dump
4809     set<int>::iterator id = addedIDs.begin();
4810     for ( ; id != addedIDs.end(); ++id )
4811     {
4812       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(*id);
4813       int i = std::distance( _mapGroups.begin(), it );
4814       TPythonDump() << it->second << " = " << aMesh << ".GetGroups()[ "<< i << " ]";
4815     }
4816   }
4817 }
4818
4819 //=============================================================================
4820 /*!
4821  * \brief Return groups cantained in _mapGroups by their IDs
4822  */
4823 //=============================================================================
4824
4825 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
4826 {
4827   int nbGroups = groupIDs.size();
4828   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
4829   aList->length( nbGroups );
4830
4831   list<int>::const_iterator ids = groupIDs.begin();
4832   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
4833   {
4834     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
4835     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
4836       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
4837   }
4838   aList->length( nbGroups );
4839   return aList._retn();
4840 }
4841
4842 //=============================================================================
4843 /*!
4844  * \brief Return information about imported file
4845  */
4846 //=============================================================================
4847
4848 SMESH::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
4849 {
4850   SMESH::MedFileInfo_var res( _medFileInfo );
4851   if ( !res.operator->() ) {
4852     res = new SMESH::MedFileInfo;
4853     res->fileName = "";
4854     res->fileSize = res->major = res->minor = res->release = -1;
4855   }
4856   return res._retn();
4857 }
4858
4859 //=============================================================================
4860 /*!
4861  * \brief Pass names of mesh groups from study to mesh DS
4862  */
4863 //=============================================================================
4864
4865 void SMESH_Mesh_i::checkGroupNames()
4866 {
4867   int nbGrp = NbGroups();
4868   if ( !nbGrp )
4869     return;
4870
4871   SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
4872   if ( aStudy->_is_nil() )
4873     return; // nothing to do
4874   
4875   SMESH::ListOfGroups* grpList = 0;
4876   // avoid dump of "GetGroups"
4877   {
4878     // store python dump into a local variable inside local scope
4879     SMESH::TPythonDump pDump; // do not delete this line of code
4880     grpList = GetGroups();
4881   }
4882
4883   for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
4884     SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
4885     if ( !aGrp )
4886       continue;
4887     SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aStudy, aGrp );
4888     if ( aGrpSO->_is_nil() )
4889       continue;
4890     // correct name of the mesh group if necessary
4891     const char* guiName = aGrpSO->GetName();
4892     if ( strcmp(guiName, aGrp->GetName()) )
4893       aGrp->SetName( guiName );
4894   }
4895 }
4896
4897 //=============================================================================
4898 /*!
4899  * \brief Sets list of notebook variables used for Mesh operations separated by ":" symbol
4900  */
4901 //=============================================================================
4902 void SMESH_Mesh_i::SetParameters(const char* theParameters)
4903 {
4904   SMESH_Gen_i::GetSMESHGen()->UpdateParameters( CORBA::Object_var( _this() ).in(),
4905                                                 theParameters );
4906 }
4907
4908 //=============================================================================
4909 /*!
4910  * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
4911  */
4912 //=============================================================================
4913
4914 char* SMESH_Mesh_i::GetParameters()
4915 {
4916   return SMESH_Gen_i::GetSMESHGen()->GetParameters( SMESH::SMESH_Mesh_var( _this()) );
4917 }
4918
4919 //=============================================================================
4920 /*!
4921  * \brief Returns list of notebook variables used for last Mesh operation
4922  */
4923 //=============================================================================
4924 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
4925 {
4926   SMESH::string_array_var aResult = new SMESH::string_array();
4927   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
4928   if(gen) {
4929     CORBA::String_var aParameters = GetParameters();
4930     SALOMEDS::Study_var    aStudy = gen->GetCurrentStudy();
4931     if ( !aStudy->_is_nil()) {
4932       SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters); 
4933       if(aSections->length() > 0) {
4934         SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1];
4935         aResult->length(aVars.length());
4936         for(int i = 0;i < aVars.length();i++)
4937           aResult[i] = CORBA::string_dup( aVars[i]);
4938       }
4939     }
4940   }
4941   return aResult._retn();
4942 }
4943
4944 //=======================================================================
4945 //function : GetTypes
4946 //purpose  : Returns types of elements it contains
4947 //=======================================================================
4948
4949 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
4950 {
4951   if ( _preMeshInfo )
4952     return _preMeshInfo->GetTypes();
4953
4954   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
4955
4956   types->length( 5 );
4957   int nbTypes = 0;
4958   if (_impl->NbEdges())      types[nbTypes++] = SMESH::EDGE;
4959   if (_impl->NbFaces())      types[nbTypes++] = SMESH::FACE;
4960   if (_impl->NbVolumes())    types[nbTypes++] = SMESH::VOLUME;
4961   if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
4962   if (_impl->NbBalls())      types[nbTypes++] = SMESH::BALL;
4963   types->length( nbTypes );
4964
4965   return types._retn();
4966 }
4967
4968 //=======================================================================
4969 //function : GetMesh
4970 //purpose  : Returns self
4971 //=======================================================================
4972
4973 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
4974 {
4975   return SMESH::SMESH_Mesh::_duplicate( _this() );
4976 }
4977
4978 //=======================================================================
4979 //function : IsMeshInfoCorrect
4980 //purpose  : * Returns false if GetMeshInfo() returns incorrect information that may
4981 //           * happen if mesh data is not yet fully loaded from the file of study.
4982 //=======================================================================
4983
4984 bool SMESH_Mesh_i::IsMeshInfoCorrect()
4985 {
4986   return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
4987 }
4988
4989 //=============================================================================
4990 /*!
4991  * \brief Returns number of mesh elements per each \a EntityType
4992  */
4993 //=============================================================================
4994
4995 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
4996 {
4997   if ( _preMeshInfo )
4998     return _preMeshInfo->GetMeshInfo();
4999
5000   SMESH::long_array_var aRes = new SMESH::long_array();
5001   aRes->length(SMESH::Entity_Last);
5002   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
5003     aRes[i] = 0;
5004   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5005   if (!aMeshDS)
5006     return aRes._retn();
5007   const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
5008   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
5009     aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
5010   return aRes._retn();
5011 }
5012
5013 //=============================================================================
5014 /*!
5015  * \brief Returns number of mesh elements per each \a ElementType
5016  */
5017 //=============================================================================
5018
5019 SMESH::long_array* SMESH_Mesh_i::GetNbElementsByType()
5020 {
5021   SMESH::long_array_var aRes = new SMESH::long_array();
5022   aRes->length(SMESH::NB_ELEMENT_TYPES);
5023   for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
5024     aRes[ i ] = 0;
5025
5026   const SMDS_MeshInfo* meshInfo = 0;
5027   if ( _preMeshInfo )
5028     meshInfo = _preMeshInfo;
5029   else if ( SMESHDS_Mesh* meshDS = _impl->GetMeshDS() )
5030     meshInfo = & meshDS->GetMeshInfo();
5031
5032   if (meshInfo)
5033     for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
5034       aRes[i] = meshInfo->NbElements((SMDSAbs_ElementType)i);
5035
5036   return aRes._retn();
5037 }
5038
5039 //=============================================================================
5040 /*
5041  * Collect statistic of mesh elements given by iterator
5042  */
5043 //=============================================================================
5044
5045 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
5046                                    SMESH::long_array&         theInfo)
5047 {
5048   if (!theItr) return;
5049   while (theItr->more())
5050     theInfo[ theItr->next()->GetEntityType() ]++;
5051 }
5052 //=============================================================================
5053 /*
5054  * Returns mesh unstructed grid information.
5055  */
5056 //=============================================================================
5057
5058 SALOMEDS::TMPFile* SMESH_Mesh_i::GetVtkUgStream()
5059 {
5060   SALOMEDS::TMPFile_var SeqFile;
5061   if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() ) {
5062     SMDS_UnstructuredGrid* aGrid = aMeshDS->getGrid();
5063     if(aGrid) {
5064       vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
5065       aWriter->WriteToOutputStringOn();
5066       aWriter->SetInputData(aGrid);
5067       aWriter->SetFileTypeToBinary();
5068       aWriter->Write();
5069       char* str = aWriter->GetOutputString();
5070       int size = aWriter->GetOutputStringLength();
5071       
5072       //Allocate octect buffer of required size
5073       CORBA::Octet* OctetBuf = SALOMEDS::TMPFile::allocbuf(size);
5074       //Copy ostrstream content to the octect buffer
5075       memcpy(OctetBuf, str, size);
5076       //Create and return TMPFile
5077       SeqFile = new SALOMEDS::TMPFile(size, size, OctetBuf, 1);
5078       aWriter->Delete();
5079     }
5080   }
5081   return SeqFile._retn();
5082 }
5083
5084 //=============================================================================
5085 namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
5086            *                                             SMESH::ElementType        type) */
5087 {
5088   using namespace SMESH::Controls;
5089   //-----------------------------------------------------------------------------
5090   struct PredicateIterator : public SMDS_ElemIterator
5091   {
5092     SMDS_ElemIteratorPtr    _elemIter;
5093     PredicatePtr            _predicate;
5094     const SMDS_MeshElement* _elem;
5095
5096     PredicateIterator( SMDS_ElemIteratorPtr   iterator,
5097                        PredicatePtr predicate):
5098       _elemIter(iterator), _predicate(predicate)
5099     {
5100       next();
5101     }
5102     virtual bool more()
5103     {
5104       return _elem;
5105     }
5106     virtual const SMDS_MeshElement* next()
5107     {
5108       const SMDS_MeshElement* res = _elem;
5109       _elem = 0;
5110       while ( _elemIter->more() && !_elem )
5111       {
5112         _elem = _elemIter->next();
5113         if ( _elem && ( !_predicate->IsSatisfy( _elem->GetID() )))
5114           _elem = 0;
5115       }
5116       return res;
5117     }
5118   };
5119
5120   //-----------------------------------------------------------------------------
5121   struct IDSourceIterator : public SMDS_ElemIterator
5122   {
5123     const CORBA::Long*        _idPtr;
5124     const CORBA::Long*        _idEndPtr;
5125     SMESH::long_array_var     _idArray;
5126     const SMDS_Mesh*          _mesh;
5127     const SMDSAbs_ElementType _type;
5128     const SMDS_MeshElement*   _elem;
5129
5130     IDSourceIterator( const SMDS_Mesh*    mesh,
5131                       const CORBA::Long*  ids,
5132                       const int           nbIds,
5133                       SMDSAbs_ElementType type):
5134       _idPtr( ids ), _idEndPtr( ids + nbIds ), _mesh( mesh ), _type( type ), _elem( 0 )
5135     {
5136       if ( _idPtr && nbIds && _mesh )
5137         next();
5138     }
5139     IDSourceIterator( const SMDS_Mesh*    mesh,
5140                       SMESH::long_array*  idArray,
5141                       SMDSAbs_ElementType type):
5142       _idPtr( 0 ), _idEndPtr( 0 ), _idArray( idArray), _mesh( mesh ), _type( type ), _elem( 0 )
5143     {
5144       if ( idArray && _mesh )
5145       {
5146         _idPtr    = &_idArray[0];
5147         _idEndPtr = _idPtr + _idArray->length();
5148         next();
5149       }
5150     }
5151     virtual bool more()
5152     {
5153       return _elem;
5154     }
5155     virtual const SMDS_MeshElement* next()
5156     {
5157       const SMDS_MeshElement* res = _elem;
5158       _elem = 0;
5159       while ( _idPtr < _idEndPtr && !_elem )
5160       {
5161         if ( _type == SMDSAbs_Node )
5162         {
5163           _elem = _mesh->FindNode( *_idPtr++ );
5164         }
5165         else if ((_elem = _mesh->FindElement( *_idPtr++ )) &&
5166                  _elem->GetType() != _type )
5167         {
5168           _elem = 0;
5169         }
5170       }
5171       return res;
5172     }
5173   };
5174   //-----------------------------------------------------------------------------
5175
5176   struct NodeOfElemIterator : public SMDS_ElemIterator
5177   {
5178     TColStd_MapOfInteger    _checkedNodeIDs;
5179     SMDS_ElemIteratorPtr    _elemIter;
5180     SMDS_ElemIteratorPtr    _nodeIter;
5181     const SMDS_MeshElement* _node;
5182
5183     NodeOfElemIterator( SMDS_ElemIteratorPtr iter ): _elemIter( iter ), _node( 0 )
5184     {
5185       if ( _elemIter && _elemIter->more() )
5186       {
5187         _nodeIter = _elemIter->next()->nodesIterator();
5188         next();
5189       }
5190     }
5191     virtual bool more()
5192     {
5193       return _node;
5194     }
5195     virtual const SMDS_MeshElement* next()
5196     {
5197       const SMDS_MeshElement* res = _node;
5198       _node = 0;
5199       while (( _elemIter->more() || _nodeIter->more() ) && !_node )
5200       {
5201         if ( _nodeIter->more() )
5202         {
5203           _node = _nodeIter->next();
5204           if ( !_checkedNodeIDs.Add( _node->GetID() ))
5205             _node = 0;
5206         }
5207         else
5208         {
5209           _nodeIter = _elemIter->next()->nodesIterator();
5210         }
5211       }
5212       return res;
5213     }
5214   };
5215 }
5216
5217 //=============================================================================
5218 /*
5219  * Return iterator on elements of given type in given object
5220  */
5221 //=============================================================================
5222
5223 SMDS_ElemIteratorPtr SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_ptr theObject,
5224                                                SMESH::ElementType        theType)
5225 {
5226   SMDS_ElemIteratorPtr  elemIt;
5227   bool                  typeOK = false;
5228   SMDSAbs_ElementType elemType = SMDSAbs_ElementType( theType );
5229
5230   SMESH::SMESH_Mesh_var meshVar = theObject->GetMesh();
5231   SMESH_Mesh_i*          mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( meshVar );
5232   if ( !mesh_i ) return elemIt;
5233   SMESHDS_Mesh*          meshDS = mesh_i->GetImpl().GetMeshDS();
5234
5235   if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
5236   {
5237     elemIt = meshDS->elementsIterator( elemType );
5238     typeOK = true;
5239   }
5240   else if ( SMESH_subMesh_i* submesh_i = SMESH::DownCast<SMESH_subMesh_i*>( theObject ))
5241   {
5242     SMESHDS_SubMesh* sm = ((SMESHDS_Mesh*) meshDS)->MeshElements( submesh_i->GetId() );
5243     if ( sm )
5244     {
5245       elemIt = sm->GetElements();
5246       if ( elemType != SMDSAbs_Node )
5247       {
5248         typeOK = ( elemIt && elemIt->more() && elemIt->next()->GetType() == elemType );
5249         elemIt = typeOK ? sm->GetElements() : SMDS_ElemIteratorPtr();
5250       }
5251     }
5252   }
5253   else if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( theObject ))
5254   {
5255     SMESHDS_GroupBase* groupDS = group_i->GetGroupDS();
5256     if ( groupDS && ( groupDS->GetType() == elemType || elemType == SMDSAbs_Node ))
5257     {
5258       elemIt = groupDS->GetElements();
5259       typeOK = ( groupDS->GetType() == elemType );
5260     }
5261   }
5262   else if ( SMESH::Filter_i* filter_i = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5263   {
5264     if ( filter_i->GetElementType() == theType || elemType == SMDSAbs_Node )
5265     {
5266       SMESH::Predicate_i* pred_i = filter_i->GetPredicate_i();
5267       if ( pred_i && pred_i->GetPredicate() )
5268       {
5269         SMDSAbs_ElementType filterType = SMDSAbs_ElementType( filter_i->GetElementType() );
5270         SMDS_ElemIteratorPtr allElemIt = meshDS->elementsIterator( filterType );
5271         elemIt = SMDS_ElemIteratorPtr( new PredicateIterator( allElemIt, pred_i->GetPredicate() ));
5272         typeOK = ( filterType == elemType );
5273       }
5274     }
5275   }
5276   else
5277   {
5278     SMESH::array_of_ElementType_var types = theObject->GetTypes();
5279     const bool                    isNodes = ( types->length() == 1 && types[0] == SMESH::NODE );
5280     if ( isNodes && elemType != SMDSAbs_Node )
5281       return elemIt;
5282     if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theObject ))
5283     {
5284       int nbIds;
5285       if ( CORBA::Long* ids = SMESH_MeshEditor_i::GetTemporaryIDs( theObject, nbIds ))
5286         elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids, nbIds, elemType ));
5287     }
5288     else
5289     {
5290       SMESH::long_array_var ids = theObject->GetIDs();
5291       elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids._retn(), elemType ));
5292     }
5293     typeOK = ( isNodes == ( elemType == SMDSAbs_Node ));
5294   }
5295
5296   if ( elemIt && elemIt->more() && !typeOK )
5297   {
5298     if ( elemType == SMDSAbs_Node )
5299     {
5300       elemIt = SMDS_ElemIteratorPtr( new NodeOfElemIterator( elemIt ));
5301     }
5302     else
5303     {
5304       elemIt = SMDS_ElemIteratorPtr();
5305     }
5306   }
5307   return elemIt;
5308 }
5309
5310 //=============================================================================
5311 namespace // Finding concurrent hypotheses
5312 //=============================================================================
5313 {
5314
5315 /*!
5316  * \brief mapping of mesh dimension into shape type
5317  */
5318 TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
5319 {
5320   TopAbs_ShapeEnum aType = TopAbs_SOLID;
5321   switch ( theDim ) {
5322   case 0: aType = TopAbs_VERTEX; break;
5323   case 1: aType = TopAbs_EDGE; break;
5324   case 2: aType = TopAbs_FACE; break;
5325   case 3:
5326   default:aType = TopAbs_SOLID; break;
5327   }
5328   return aType;
5329 }
5330
5331 //-----------------------------------------------------------------------------
5332 /*!
5333  * \brief Internal structure used to find concurent submeshes
5334  *
5335  * It represents a pair < submesh, concurent dimension >, where
5336  * 'concurrent dimension' is dimension of shape where the submesh can concurent
5337  *  with another submesh. In other words, it is dimension of a hypothesis assigned
5338  *  to submesh.
5339  */
5340 class SMESH_DimHyp
5341 {
5342  public:
5343   //! fileds
5344   int _dim;    //!< a dimension the algo can build (concurrent dimension)
5345   int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
5346   TopTools_MapOfShape _shapeMap;
5347   SMESH_subMesh*      _subMesh;
5348   list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
5349
5350   //-----------------------------------------------------------------------------
5351   // Return the algorithm
5352   const SMESH_Algo* GetAlgo() const
5353   { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
5354
5355   //-----------------------------------------------------------------------------
5356   //! Constructors
5357   SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
5358                const int            theDim,
5359                const TopoDS_Shape&  theShape)
5360   {
5361     _subMesh = (SMESH_subMesh*)theSubMesh;
5362     SetShape( theDim, theShape );
5363   }
5364
5365   //-----------------------------------------------------------------------------
5366   //! set shape
5367   void SetShape(const int           theDim,
5368                 const TopoDS_Shape& theShape)
5369   {
5370     _dim = theDim;
5371     _ownDim = SMESH_Gen::GetShapeDim(theShape);
5372     if (_dim >= _ownDim)
5373       _shapeMap.Add( theShape );
5374     else {
5375       TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
5376       for( ; anExp.More(); anExp.Next() )
5377         _shapeMap.Add( anExp.Current() );
5378     }
5379   }
5380
5381   //-----------------------------------------------------------------------------
5382   //! Check sharing of sub-shapes
5383   static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
5384                                const TopTools_MapOfShape& theToFind,
5385                                const TopAbs_ShapeEnum     theType)
5386   {
5387     bool isShared = false;
5388     TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
5389     for (; !isShared && anItr.More(); anItr.Next() )
5390     {
5391       const TopoDS_Shape aSubSh = anItr.Key();
5392       // check for case when concurrent dimensions are same
5393       isShared = theToFind.Contains( aSubSh );
5394       // check for sub-shape with concurrent dimension
5395       TopExp_Explorer anExp( aSubSh, theType );
5396       for ( ; !isShared && anExp.More(); anExp.Next() )
5397         isShared = theToFind.Contains( anExp.Current() );
5398     }
5399     return isShared;
5400   }
5401   
5402   //-----------------------------------------------------------------------------
5403   //! check algorithms
5404   static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
5405                         const SMESHDS_Hypothesis* theA2)
5406   {
5407     if ( !theA1 || !theA2 ||
5408          theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
5409          theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
5410       return false; // one of the hypothesis is not algorithm
5411     // check algorithm names (should be equal)
5412     return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
5413   }
5414
5415   
5416   //-----------------------------------------------------------------------------
5417   //! Check if sub-shape hypotheses are concurrent
5418   bool IsConcurrent(const SMESH_DimHyp* theOther) const
5419   {
5420     if ( _subMesh == theOther->_subMesh )
5421       return false; // same sub-shape - should not be
5422
5423     // if ( <own dim of either of submeshes> == <concurrent dim> &&
5424     //      any of the two submeshes is not on COMPOUND shape )
5425     //  -> no concurrency
5426     bool meIsCompound    = (_subMesh->GetSubMeshDS() &&
5427                             _subMesh->GetSubMeshDS()->IsComplexSubmesh());
5428     bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
5429                             theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
5430     if ( (_ownDim == _dim  || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
5431       return false;
5432
5433 //     bool checkSubShape = ( _dim >= theOther->_dim )
5434 //       ? isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(theOther->_dim) )
5435 //       : isShareSubShapes( theOther->_shapeMap, _shapeMap, shapeTypeByDim(_dim) ) ;
5436     bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
5437     if ( !checkSubShape )
5438         return false;
5439
5440     // check algorithms to be same
5441     if ( !checkAlgo( this->GetAlgo(), theOther->GetAlgo() ))
5442       return true; // different algorithms -> concurrency !
5443
5444     // check hypothesises for concurrence (skip first as algorithm)
5445     int nbSame = 0;
5446     // pointers should be same, because it is referened from mesh hypothesis partition
5447     list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
5448     list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
5449     for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
5450       if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
5451         nbSame++;
5452     // the submeshes are concurrent if their algorithms has different parameters
5453     return nbSame != theOther->_hypotheses.size() - 1;
5454   }
5455
5456   // Return true if algorithm of this SMESH_DimHyp is used if no
5457   // sub-mesh order is imposed by the user
5458   bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
5459   {
5460     // NeedDiscreteBoundary() algo has a higher priority
5461     if ( this    ->GetAlgo()->NeedDiscreteBoundary() !=
5462          theOther->GetAlgo()->NeedDiscreteBoundary() )
5463       return !this->GetAlgo()->NeedDiscreteBoundary();
5464
5465     return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
5466   }
5467   
5468 }; // end of SMESH_DimHyp
5469 //-----------------------------------------------------------------------------
5470
5471 typedef list<const SMESH_DimHyp*> TDimHypList;
5472
5473 //-----------------------------------------------------------------------------
5474
5475 void addDimHypInstance(const int                               theDim, 
5476                        const TopoDS_Shape&                     theShape,
5477                        const SMESH_Algo*                       theAlgo,
5478                        const SMESH_subMesh*                    theSubMesh,
5479                        const list <const SMESHDS_Hypothesis*>& theHypList,
5480                        TDimHypList*                            theDimHypListArr )
5481 {
5482   TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
5483   if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) {
5484     SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
5485     dimHyp->_hypotheses.push_front(theAlgo);
5486     listOfdimHyp.push_back( dimHyp );
5487   }
5488   
5489   SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
5490   dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
5491                               theHypList.begin(), theHypList.end() );
5492 }
5493
5494 //-----------------------------------------------------------------------------
5495 void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
5496                            TDimHypList&        theListOfConcurr)
5497 {
5498   if ( theListOfConcurr.empty() )
5499   {
5500     theListOfConcurr.push_back( theDimHyp );
5501   }
5502   else
5503   {
5504     TDimHypList::iterator hypIt = theListOfConcurr.begin();
5505     while ( hypIt != theListOfConcurr.end() &&
5506             !theDimHyp->IsHigherPriorityThan( *hypIt ))
5507       ++hypIt;
5508     theListOfConcurr.insert( hypIt, theDimHyp );
5509   }
5510 }
5511
5512 //-----------------------------------------------------------------------------
5513 void findConcurrents(const SMESH_DimHyp* theDimHyp,
5514                      const TDimHypList&  theListOfDimHyp,
5515                      TDimHypList&        theListOfConcurrHyp,
5516                      set<int>&           theSetOfConcurrId )
5517 {
5518   TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
5519   for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
5520   {
5521     const SMESH_DimHyp* curDimHyp = *rIt;
5522     if ( curDimHyp == theDimHyp )
5523       break; // meet own dimHyp pointer in same dimension
5524
5525     if ( theDimHyp->IsConcurrent( curDimHyp ) &&
5526          theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
5527     {
5528       addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
5529     }
5530   }
5531 }
5532
5533 //-----------------------------------------------------------------------------
5534 void unionLists(TListOfInt&       theListOfId,
5535                 TListOfListOfInt& theListOfListOfId,
5536                 const int         theIndx )
5537 {
5538   TListOfListOfInt::iterator it = theListOfListOfId.begin();
5539   for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) {
5540     if ( i < theIndx )
5541       continue; //skip already treated lists
5542     // check if other list has any same submesh object
5543     TListOfInt& otherListOfId = *it;
5544     if ( find_first_of( theListOfId.begin(), theListOfId.end(),
5545                         otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
5546       continue;
5547          
5548     // union two lists (from source into target)
5549     TListOfInt::iterator it2 = otherListOfId.begin();
5550     for ( ; it2 != otherListOfId.end(); it2++ ) {
5551       if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
5552         theListOfId.push_back(*it2);
5553     }
5554     // clear source list
5555     otherListOfId.clear();
5556   }
5557 }
5558 //-----------------------------------------------------------------------------
5559
5560 //! free memory allocated for dimension-hypothesis objects
5561 void removeDimHyps( TDimHypList* theArrOfList )
5562 {
5563   for (int i = 0; i < 4; i++ ) {
5564     TDimHypList& listOfdimHyp = theArrOfList[i];
5565     TDimHypList::const_iterator it = listOfdimHyp.begin();
5566     for ( ; it != listOfdimHyp.end(); it++ )
5567       delete (*it);
5568   }
5569 }
5570
5571 //-----------------------------------------------------------------------------
5572 /*!
5573  * \brief find common submeshes with given submesh
5574  * \param theSubMeshList list of already collected submesh to check
5575  * \param theSubMesh given submesh to intersect with other
5576  * \param theCommonSubMeshes collected common submeshes
5577  */
5578 void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
5579                         const SMESH_subMesh*        theSubMesh,
5580                         set<const SMESH_subMesh*>&  theCommon )
5581 {
5582   if ( !theSubMesh )
5583     return;
5584   list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
5585   for ( ; it != theSubMeshList.end(); it++ )
5586     theSubMesh->FindIntersection( *it, theCommon );
5587   theSubMeshList.push_back( theSubMesh );
5588   //theCommon.insert( theSubMesh );
5589 }
5590
5591 //-----------------------------------------------------------------------------
5592 bool isSubMeshInList ( int smID, const TListOfListOfInt& smLists )
5593 {
5594   TListOfListOfInt::const_iterator listsIt = smLists.begin();
5595   for ( ; listsIt != smLists.end(); ++listsIt )
5596   {
5597     const TListOfInt& smIDs = *listsIt;
5598     if ( std::find( smIDs.begin(), smIDs.end(), smID ) != smIDs.end() )
5599       return true;
5600   }
5601   return false;
5602 }
5603
5604 } // namespace
5605
5606 //=============================================================================
5607 /*!
5608  * \brief Return \c true if a meshing order not yet set for a concurrent sub-mesh
5609  */
5610 //=============================================================================
5611
5612 CORBA::Boolean SMESH_Mesh_i::IsUnorderedSubMesh(CORBA::Long submeshID)
5613 {
5614   TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
5615   if ( isSubMeshInList( submeshID, anOrder ))
5616     return false;
5617
5618   TListOfListOfInt allConurrent = findConcurrentSubMeshes();
5619   return isSubMeshInList( submeshID, allConurrent );
5620 }
5621
5622 //=============================================================================
5623 /*!
5624  * \brief Return submesh objects list in meshing order
5625  */
5626 //=============================================================================
5627
5628 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
5629 {
5630   SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
5631
5632   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5633   if ( !aMeshDS )
5634     return aResult._retn();
5635
5636   TListOfListOfInt      anOrder = GetImpl().GetMeshOrder(); // already defined order
5637   TListOfListOfInt allConurrent = findConcurrentSubMeshes();
5638   anOrder.splice( anOrder.end(), allConurrent );
5639
5640   int listIndx = 0;
5641   TListOfListOfInt::iterator listIt = anOrder.begin();
5642   for(; listIt != anOrder.end(); listIt++, listIndx++ )
5643     unionLists( *listIt,  anOrder, listIndx + 1 );
5644
5645   // convert submesh ids into interface instances
5646   //  and dump command into python
5647   convertMeshOrder( anOrder, aResult, false );
5648
5649   return aResult._retn();
5650 }
5651
5652 //=============================================================================
5653 /*!
5654  * \brief Finds concurrent sub-meshes
5655  */
5656 //=============================================================================
5657
5658 TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes()
5659 {
5660   TListOfListOfInt anOrder;
5661   ::SMESH_Mesh& mesh = GetImpl();
5662   {
5663     // collect submeshes and detect concurrent algorithms and hypothesises
5664     TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
5665
5666     map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
5667     for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) {
5668       ::SMESH_subMesh* sm = (*i_sm).second;
5669       // shape of submesh
5670       const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
5671
5672       // list of assigned hypothesises
5673       const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
5674       // Find out dimensions where the submesh can be concurrent.
5675       // We define the dimensions by algo of each of hypotheses in hypList
5676       list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
5677       for( ; hypIt != hypList.end(); hypIt++ ) {
5678         SMESH_Algo* anAlgo = 0;
5679         const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
5680         if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
5681           // hyp it-self is algo
5682           anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
5683         else {
5684           // try to find algorithm with help of sub-shapes
5685           TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
5686           for ( ; !anAlgo && anExp.More(); anExp.Next() )
5687             anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
5688         }
5689         if (!anAlgo)
5690           continue; // no algorithm assigned to a current submesh
5691
5692         int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
5693         // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary())
5694
5695         // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
5696         for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
5697           addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
5698       }
5699     } // end iterations on submesh
5700     
5701     // iterate on created dimension-hypotheses and check for concurrents
5702     for ( int i = 0; i < 4; i++ ) {
5703       const TDimHypList& listOfDimHyp = dimHypListArr[i];
5704       // check for concurrents in own and other dimensions (step-by-step)
5705       TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
5706       for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) {
5707         const SMESH_DimHyp* dimHyp = *dhIt;
5708         TDimHypList listOfConcurr;
5709         set<int>    setOfConcurrIds;
5710         // looking for concurrents and collect into own list
5711         for ( int j = i; j < 4; j++ )
5712           findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
5713         // check if any concurrents found
5714         if ( listOfConcurr.size() > 0 ) {
5715           // add own submesh to list of concurrent
5716           addInOrderOfPriority( dimHyp, listOfConcurr );
5717           list<int> listOfConcurrIds;
5718           TDimHypList::iterator hypIt = listOfConcurr.begin();
5719           for ( ; hypIt != listOfConcurr.end(); ++hypIt )
5720             listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
5721           anOrder.push_back( listOfConcurrIds );
5722         }
5723       }
5724     }
5725     
5726     removeDimHyps(dimHypListArr);
5727     
5728     // now, minimise the number of concurrent groups
5729     // Here we assume that lists of submeshes can have same submesh
5730     // in case of multi-dimension algorithms, as result
5731     //  list with common submesh has to be united into one list
5732     int listIndx = 0;
5733     TListOfListOfInt::iterator listIt = anOrder.begin();
5734     for(; listIt != anOrder.end(); listIt++, listIndx++ )
5735       unionLists( *listIt,  anOrder, listIndx + 1 );
5736   }
5737
5738   return anOrder;
5739 }
5740
5741 //=============================================================================
5742 /*!
5743  * \brief Set submesh object order
5744  * \param theSubMeshArray submesh array order
5745  */
5746 //=============================================================================
5747
5748 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
5749 {
5750   if ( _preMeshInfo )
5751     _preMeshInfo->ForgetOrLoad();
5752
5753   bool res = false;
5754   ::SMESH_Mesh& mesh = GetImpl();
5755
5756   TPythonDump aPythonDump; // prevent dump of called methods
5757   aPythonDump << "isDone = " << SMESH::SMESH_Mesh_var(_this()) << ".SetMeshOrder( [ ";
5758
5759   TListOfListOfInt subMeshOrder;
5760   for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
5761   {
5762     const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
5763     TListOfInt subMeshIds;
5764     if ( i > 0 )
5765       aPythonDump << ", ";
5766     aPythonDump << "[ ";
5767     // Collect subMeshes which should be clear
5768     //  do it list-by-list, because modification of submesh order
5769     //  take effect between concurrent submeshes only
5770     set<const SMESH_subMesh*> subMeshToClear;
5771     list<const SMESH_subMesh*> subMeshList;
5772     for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
5773     {
5774       const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
5775       if ( j > 0 )
5776         aPythonDump << ", ";
5777       aPythonDump << subMesh;
5778       subMeshIds.push_back( subMesh->GetId() );
5779       // detect common parts of submeshes
5780       if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
5781         findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
5782     }
5783     aPythonDump << " ]";
5784     subMeshOrder.push_back( subMeshIds );
5785
5786     // clear collected submeshes
5787     set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
5788     for ( ; clrIt != subMeshToClear.end(); clrIt++ )
5789       if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
5790         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
5791   }
5792   aPythonDump << " ])";
5793
5794   mesh.SetMeshOrder( subMeshOrder );
5795   res = true;
5796   
5797   return res;
5798 }
5799
5800 //=============================================================================
5801 /*!
5802  * \brief Convert submesh ids into submesh interfaces
5803  */
5804 //=============================================================================
5805
5806 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt&     theIdsOrder,
5807                                      SMESH::submesh_array_array& theResOrder,
5808                                      const bool                  theIsDump)
5809 {
5810   int nbSet = theIdsOrder.size();
5811   TPythonDump aPythonDump; // prevent dump of called methods
5812   if ( theIsDump )
5813     aPythonDump << "[ ";
5814   theResOrder.length(nbSet);
5815   TListOfListOfInt::const_iterator it = theIdsOrder.begin();
5816   int listIndx = 0;
5817   for( ; it != theIdsOrder.end(); it++ ) {
5818     // translate submesh identificators into submesh objects
5819     //  takeing into account real number of concurrent lists
5820     const TListOfInt& aSubOrder = (*it);
5821     if (!aSubOrder.size())
5822       continue;
5823     if ( theIsDump )
5824       aPythonDump << "[ ";
5825     // convert shape indeces into interfaces
5826     SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
5827     aResSubSet->length(aSubOrder.size());
5828     TListOfInt::const_iterator subIt = aSubOrder.begin();
5829     int j;
5830     for( j = 0; subIt != aSubOrder.end(); subIt++ ) {
5831       if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
5832         continue;
5833       SMESH::SMESH_subMesh_var subMesh =
5834         SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
5835       if ( theIsDump ) {
5836         if ( j > 0 )
5837           aPythonDump << ", ";
5838         aPythonDump << subMesh;
5839       }
5840       aResSubSet[ j++ ] = subMesh;
5841     }
5842     if ( theIsDump )
5843       aPythonDump << " ]";
5844     if ( j > 1 )
5845       theResOrder[ listIndx++ ] = aResSubSet;
5846   }
5847   // correct number of lists
5848   theResOrder.length( listIndx );
5849
5850   if ( theIsDump ) {
5851     // finilise python dump
5852     aPythonDump << " ]";
5853     aPythonDump << " = " << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshOrder()";
5854   }
5855 }
5856
5857 //================================================================================
5858 //
5859 // Implementation of SMESH_MeshPartDS
5860 //
5861 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
5862   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
5863 {
5864   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
5865   SMESH_Mesh_i*       mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
5866
5867   _meshDS = mesh_i->GetImpl().GetMeshDS();
5868
5869   SetPersistentId( _meshDS->GetPersistentId() );
5870
5871   if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
5872   {
5873     // <meshPart> is the whole mesh
5874     myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
5875     // copy groups
5876     set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
5877     myGroupSet = _meshDS->GetGroups();
5878   }
5879   else
5880   {
5881     TMeshInfo tmpInfo;
5882     SMESH::long_array_var           anIDs = meshPart->GetIDs();
5883     SMESH::array_of_ElementType_var types = meshPart->GetTypes();
5884     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5885     {
5886       for (int i=0; i < anIDs->length(); i++)
5887         if ( const SMDS_MeshNode * n = _meshDS->FindNode(anIDs[i]))
5888           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
5889             tmpInfo.Add( n );
5890     }
5891     else
5892     {
5893       for (int i=0; i < anIDs->length(); i++)
5894         if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
5895           if ( _elements[ e->GetType() ].insert( e ).second )
5896           {
5897             tmpInfo.Add( e );
5898             SMDS_ElemIteratorPtr nIt = e->nodesIterator();
5899             while ( nIt->more() )
5900             {
5901               const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
5902               if ( _elements[ SMDSAbs_Node ].insert( n ).second )
5903                 tmpInfo.Add( n );
5904             }
5905           }
5906     }
5907     myInfo = tmpInfo;
5908
5909     _meshDS = 0; // to enforce iteration on _elements and _nodes
5910   }
5911 }
5912 // -------------------------------------------------------------------------------------
5913 SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
5914   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
5915 {
5916   TMeshInfo tmpInfo;
5917   list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
5918   for ( ; partIt != meshPart.end(); ++partIt )
5919     if ( const SMDS_MeshElement * e = *partIt )
5920       if ( _elements[ e->GetType() ].insert( e ).second )
5921       {
5922         tmpInfo.Add( e );
5923         SMDS_ElemIteratorPtr nIt = e->nodesIterator();
5924         while ( nIt->more() )
5925         {
5926           const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
5927           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
5928             tmpInfo.Add( n );
5929         }
5930       }
5931   myInfo = tmpInfo;
5932 }
5933 // -------------------------------------------------------------------------------------
5934 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
5935 {
5936   if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
5937
5938   typedef SMDS_SetIterator
5939     <const SMDS_MeshElement*,
5940     TIDSortedElemSet::const_iterator,
5941     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
5942     SMDS_MeshElement::GeomFilter
5943     > TIter;
5944
5945   SMDSAbs_ElementType type = SMDS_MeshCell::toSmdsType( geomType );
5946
5947   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
5948                                           _elements[type].end(),
5949                                           SMDS_MeshElement::GeomFilter( geomType )));
5950 }
5951 // -------------------------------------------------------------------------------------
5952 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
5953 {
5954   if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
5955
5956   typedef SMDS_SetIterator
5957     <const SMDS_MeshElement*,
5958     TIDSortedElemSet::const_iterator,
5959     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
5960     SMDS_MeshElement::EntityFilter
5961     > TIter;
5962
5963   SMDSAbs_ElementType type = SMDS_MeshCell::toSmdsType( entity );
5964
5965   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
5966                                           _elements[type].end(),
5967                                           SMDS_MeshElement::EntityFilter( entity )));
5968 }
5969 // -------------------------------------------------------------------------------------
5970 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
5971 {
5972   typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
5973   if ( type == SMDSAbs_All && !_meshDS )
5974   {
5975     typedef vector< SMDS_ElemIteratorPtr > TIterVec;
5976     TIterVec iterVec;
5977     for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
5978       if ( !_elements[i].empty() && i != SMDSAbs_Node )
5979         iterVec.push_back
5980           ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
5981
5982     typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
5983     return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
5984   }
5985   return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
5986       ( new TIter( _elements[type].begin(), _elements[type].end() ));
5987 }
5988 // -------------------------------------------------------------------------------------
5989 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType)                       \
5990   iterType SMESH_MeshPartDS::methName( bool idInceasingOrder) const                 \
5991   {                                                                                 \
5992     typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
5993     return _meshDS ? _meshDS->methName(idInceasingOrder) : iterType                 \
5994       ( new TIter( _elements[elemType].begin(), _elements[elemType].end() ));       \
5995   }
5996 // -------------------------------------------------------------------------------------
5997 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
5998 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
5999 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
6000 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
6001 #undef _GET_ITER_DEFINE
6002 //
6003 // END Implementation of SMESH_MeshPartDS
6004 //
6005 //================================================================================
6006
6007