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