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