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