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