Salome HOME
dde636000a0009209bdfe78a2b7a62d9b30d66a7
[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_wrap.hxx>
64
65 // OCCT Includes
66 #include <BRep_Builder.hxx>
67 #include <OSD_Directory.hxx>
68 #include <OSD_File.hxx>
69 #include <OSD_Path.hxx>
70 #include <OSD_Protection.hxx>
71 #include <Standard_OutOfMemory.hxx>
72 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
73 #include <TColStd_MapOfInteger.hxx>
74 #include <TColStd_SequenceOfInteger.hxx>
75 #include <TCollection_AsciiString.hxx>
76 #include <TopExp.hxx>
77 #include <TopExp_Explorer.hxx>
78 #include <TopTools_MapIteratorOfMapOfShape.hxx>
79 #include <TopTools_MapOfShape.hxx>
80 #include <TopoDS_Compound.hxx>
81
82 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
83
84 // STL Includes
85 #include <algorithm>
86 #include <string>
87 #include <iostream>
88 #include <sstream>
89
90 #include <sys/stat.h>
91
92 #ifdef _DEBUG_
93 static int MYDEBUG = 0;
94 #else
95 static int MYDEBUG = 0;
96 #endif
97
98 using namespace std;
99 using SMESH::TPythonDump;
100
101 int SMESH_Mesh_i::_idGenerator = 0;
102
103 //=============================================================================
104 /*!
105  *  Constructor
106  */
107 //=============================================================================
108
109 SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
110                             SMESH_Gen_i*            gen_i,
111                             CORBA::Long studyId )
112 : SALOME::GenericObj_i( thePOA )
113 {
114   MESSAGE("SMESH_Mesh_i");
115   _impl        = NULL;
116   _gen_i       = gen_i;
117   _id          = _idGenerator++;
118   _studyId     = studyId;
119   _preMeshInfo = NULL;
120 }
121
122 //=============================================================================
123 /*!
124  *  Destructor
125  */
126 //=============================================================================
127
128 SMESH_Mesh_i::~SMESH_Mesh_i()
129 {
130   MESSAGE("~SMESH_Mesh_i");
131
132   // destroy groups
133   map<int, SMESH::SMESH_GroupBase_ptr>::iterator itGr;
134   for (itGr = _mapGroups.begin(); itGr != _mapGroups.end(); itGr++)
135     if (SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>(itGr->second))
136     {
137       // _impl->RemoveGroup() is called by ~SMESH_GroupBase_i() (PAL6331)
138       //_impl->RemoveGroup( aGroup->GetLocalID() );
139       aGroup->myMeshServant = 0;
140       aGroup->UnRegister();
141     }
142   _mapGroups.clear();
143
144   // destroy submeshes
145   map<int, SMESH::SMESH_subMesh_ptr>::iterator itSM;
146   for ( itSM = _mapSubMeshIor.begin(); itSM != _mapSubMeshIor.end(); itSM++ )
147     if ( SMESH_subMesh_i* aSubMesh = SMESH::DownCast<SMESH_subMesh_i*>( itSM->second ))
148     {
149       aSubMesh->UnRegister();
150     }
151   _mapSubMeshIor.clear();
152
153   // destroy hypotheses
154   map<int, SMESH::SMESH_Hypothesis_ptr>::iterator itH;
155   for ( itH = _mapHypo.begin(); itH != _mapHypo.end(); itH++ )
156     if ( SMESH_Hypothesis_i* aHypo = SMESH::DownCast<SMESH_Hypothesis_i*>( itH->second ))
157     {
158       aHypo->UnRegister();
159     }
160   _mapHypo.clear();
161
162   delete _impl; _impl = NULL;
163   delete _preMeshInfo; _preMeshInfo = NULL;
164 }
165
166 //=============================================================================
167 /*!
168  *  SetShape
169  *
170  *  Associates <this> mesh with <theShape> and puts a reference
171  *  to <theShape> into the current study;
172  *  the previous shape is substituted by the new one.
173  */
174 //=============================================================================
175
176 void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
177     throw (SALOME::SALOME_Exception)
178 {
179   Unexpect aCatch(SALOME_SalomeException);
180   try {
181     _impl->ShapeToMesh( _gen_i->GeomObjectToShape( theShapeObject ));
182   }
183   catch(SALOME_Exception & S_ex) {
184     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
185   }
186   // to track changes of GEOM groups
187   addGeomGroupData( theShapeObject, _this() );
188 }
189
190 //================================================================================
191 /*!
192  * \brief return true if mesh has a shape to build a shape on
193  */
194 //================================================================================
195
196 CORBA::Boolean SMESH_Mesh_i::HasShapeToMesh()
197   throw (SALOME::SALOME_Exception)
198 {
199   Unexpect aCatch(SALOME_SalomeException);
200   bool res = false;
201   try {
202     res = _impl->HasShapeToMesh();
203   }
204   catch(SALOME_Exception & S_ex) {
205     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
206   }
207   return res;
208 }
209
210 //=======================================================================
211 //function : GetShapeToMesh
212 //purpose  :
213 //=======================================================================
214
215 GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
216   throw (SALOME::SALOME_Exception)
217 {
218   Unexpect aCatch(SALOME_SalomeException);
219   GEOM::GEOM_Object_var aShapeObj;
220   try {
221     TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
222     if ( !S.IsNull() )
223       aShapeObj = _gen_i->ShapeToGeomObject( S );
224   }
225   catch(SALOME_Exception & S_ex) {
226     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
227   }
228   return aShapeObj._retn();
229 }
230
231 //================================================================================
232 /*!
233  * \brief Return false if the mesh is not yet fully loaded from the study file
234  */
235 //================================================================================
236
237 CORBA::Boolean SMESH_Mesh_i::IsLoaded() throw (SALOME::SALOME_Exception)
238 {
239   Unexpect aCatch(SALOME_SalomeException);
240   return !_preMeshInfo;
241 }
242
243 //================================================================================
244 /*!
245  * \brief Load full mesh data from the study file
246  */
247 //================================================================================
248
249 void SMESH_Mesh_i::Load() throw (SALOME::SALOME_Exception)
250 {
251   Unexpect aCatch(SALOME_SalomeException);
252   if ( _preMeshInfo )
253     _preMeshInfo->FullLoadFromFile();
254 }
255
256 //================================================================================
257 /*!
258  * \brief Remove all nodes and elements
259  */
260 //================================================================================
261
262 void SMESH_Mesh_i::Clear() throw (SALOME::SALOME_Exception)
263 {
264   Unexpect aCatch(SALOME_SalomeException);
265   if ( _preMeshInfo )
266     _preMeshInfo->ForgetAllData();
267
268   try {
269     _impl->Clear();
270     CheckGeomGroupModif(); // issue 20145
271   }
272   catch(SALOME_Exception & S_ex) {
273     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
274   }
275   _impl->GetMeshDS()->Modified();
276
277   TPythonDump() <<  _this() << ".Clear()";
278 }
279
280 //================================================================================
281 /*!
282  * \brief Remove all nodes and elements for indicated shape
283  */
284 //================================================================================
285
286 void SMESH_Mesh_i::ClearSubMesh(CORBA::Long ShapeID)
287   throw (SALOME::SALOME_Exception)
288 {
289   Unexpect aCatch(SALOME_SalomeException);
290   if ( _preMeshInfo )
291     _preMeshInfo->FullLoadFromFile();
292
293   try {
294     _impl->ClearSubMesh( ShapeID );
295   }
296   catch(SALOME_Exception & S_ex) {
297     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
298   }
299   _impl->GetMeshDS()->Modified();
300
301   TPythonDump() <<  _this() << ".ClearSubMesh( " << ShapeID << " )";
302 }
303
304 //=============================================================================
305 /*!
306  * Convert enum Driver_Mesh::Status to SMESH::DriverMED_ReadStatus
307  */
308 //=============================================================================
309
310 static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
311 {
312   SMESH::DriverMED_ReadStatus res;
313   switch (theStatus)
314   {
315   case DriverMED_R_SMESHDS_Mesh::DRS_OK:
316     res = SMESH::DRS_OK; break;
317   case DriverMED_R_SMESHDS_Mesh::DRS_EMPTY:
318     res = SMESH::DRS_EMPTY; break;
319   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_RENUMBER:
320     res = SMESH::DRS_WARN_RENUMBER; break;
321   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
322     res = SMESH::DRS_WARN_SKIP_ELEM; break;
323   case DriverMED_R_SMESHDS_Mesh::DRS_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 //=============================================================================
3713 /*!
3714  * \brief Return position of an element on shape
3715  */
3716 //=============================================================================
3717
3718 SMESH::ElementPosition SMESH_Mesh_i::GetElementPosition(CORBA::Long ElemID)
3719 {
3720   if ( _preMeshInfo )
3721     _preMeshInfo->FullLoadFromFile();
3722
3723   SMESH::ElementPosition anElementPosition;
3724   anElementPosition.shapeID = 0;
3725   anElementPosition.shapeType = GEOM::SHAPE;
3726
3727   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
3728   if ( !mesh ) return anElementPosition;
3729
3730   if ( const SMDS_MeshElement* anElem = mesh->FindElement( ElemID ) )
3731   {
3732     anElementPosition.shapeID = anElem->getshapeId();
3733     const TopoDS_Shape& aSp = mesh->IndexToShape( anElem->getshapeId() );
3734     if ( !aSp.IsNull() ) {
3735       switch ( aSp.ShapeType() ) {
3736       case TopAbs_EDGE:
3737         anElementPosition.shapeType = GEOM::EDGE;
3738         break;
3739       case TopAbs_FACE:
3740         anElementPosition.shapeType = GEOM::FACE;
3741         break;
3742       case TopAbs_VERTEX:
3743         anElementPosition.shapeType = GEOM::VERTEX;
3744         break;
3745       case TopAbs_SOLID:
3746         anElementPosition.shapeType = GEOM::SOLID;
3747         break;
3748       case TopAbs_SHELL:
3749         anElementPosition.shapeType = GEOM::SHELL;
3750         break;
3751       default:;
3752       }
3753     }
3754   }
3755   return anElementPosition;
3756 }
3757
3758 //=============================================================================
3759 /*!
3760  * If given element is node returns IDs of shape from position
3761  * If there is not node for given ID - returns -1
3762  */
3763 //=============================================================================
3764
3765 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
3766 {
3767   if ( _preMeshInfo )
3768     _preMeshInfo->FullLoadFromFile();
3769
3770   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3771   if ( aSMESHDS_Mesh == NULL )
3772     return -1;
3773
3774   // try to find node
3775   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3776   if(aNode) {
3777     return aNode->getshapeId();
3778   }
3779
3780   return -1;
3781 }
3782
3783
3784 //=============================================================================
3785 /*!
3786  * For given element returns ID of result shape after 
3787  * ::FindShape() from SMESH_MeshEditor
3788  * If there is not element for given ID - returns -1
3789  */
3790 //=============================================================================
3791
3792 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
3793 {
3794   if ( _preMeshInfo )
3795     _preMeshInfo->FullLoadFromFile();
3796
3797   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3798   if ( aSMESHDS_Mesh == NULL )
3799     return -1;
3800
3801   // try to find element
3802   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3803   if(!elem)
3804     return -1;
3805
3806   ::SMESH_MeshEditor aMeshEditor(_impl);
3807   int index = aMeshEditor.FindShape( elem );
3808   if(index>0)
3809     return index;
3810
3811   return -1;
3812 }
3813
3814
3815 //=============================================================================
3816 /*!
3817  * Returns number of nodes for given element
3818  * If there is not element for given ID - returns -1
3819  */
3820 //=============================================================================
3821
3822 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
3823 {
3824   if ( _preMeshInfo )
3825     _preMeshInfo->FullLoadFromFile();
3826
3827   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3828   if ( aSMESHDS_Mesh == NULL ) return -1;
3829   // try to find element
3830   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3831   if(!elem) return -1;
3832   return elem->NbNodes();
3833 }
3834
3835
3836 //=============================================================================
3837 /*!
3838  * Returns ID of node by given index for given element
3839  * If there is not element for given ID - returns -1
3840  * If there is not node for given index - returns -2
3841  */
3842 //=============================================================================
3843
3844 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
3845 {
3846   if ( _preMeshInfo )
3847     _preMeshInfo->FullLoadFromFile();
3848
3849   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3850   if ( aSMESHDS_Mesh == NULL ) return -1;
3851   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3852   if(!elem) return -1;
3853   if( index>=elem->NbNodes() || index<0 ) return -1;
3854   return elem->GetNode(index)->GetID();
3855 }
3856
3857 //=============================================================================
3858 /*!
3859  * Returns IDs of nodes of given element
3860  */
3861 //=============================================================================
3862
3863 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
3864 {
3865   if ( _preMeshInfo )
3866     _preMeshInfo->FullLoadFromFile();
3867
3868   SMESH::long_array_var aResult = new SMESH::long_array();
3869   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
3870   {
3871     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id) )
3872     {
3873       aResult->length( elem->NbNodes() );
3874       for ( int i = 0; i < elem->NbNodes(); ++i )
3875         aResult[ i ] = elem->GetNode( i )->GetID();
3876     }
3877   }
3878   return aResult._retn();
3879 }
3880
3881 //=============================================================================
3882 /*!
3883  * Returns true if given node is medium node
3884  * in given quadratic element
3885  */
3886 //=============================================================================
3887
3888 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
3889 {
3890   if ( _preMeshInfo )
3891     _preMeshInfo->FullLoadFromFile();
3892
3893   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3894   if ( aSMESHDS_Mesh == NULL ) return false;
3895   // try to find node
3896   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
3897   if(!aNode) return false;
3898   // try to find element
3899   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(ide);
3900   if(!elem) return false;
3901
3902   return elem->IsMediumNode(aNode);
3903 }
3904
3905
3906 //=============================================================================
3907 /*!
3908  * Returns true if given node is medium node
3909  * in one of quadratic elements
3910  */
3911 //=============================================================================
3912
3913 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
3914                                                    SMESH::ElementType theElemType)
3915 {
3916   if ( _preMeshInfo )
3917     _preMeshInfo->FullLoadFromFile();
3918
3919   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3920   if ( aSMESHDS_Mesh == NULL ) return false;
3921
3922   // try to find node
3923   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
3924   if(!aNode) return false;
3925
3926   SMESH_MesherHelper aHelper( *(_impl) );
3927
3928   SMDSAbs_ElementType aType;
3929   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
3930   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
3931   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
3932   else aType = SMDSAbs_All;
3933
3934   return aHelper.IsMedium(aNode,aType);
3935 }
3936
3937
3938 //=============================================================================
3939 /*!
3940  * Returns number of edges for given element
3941  */
3942 //=============================================================================
3943
3944 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
3945 {
3946   if ( _preMeshInfo )
3947     _preMeshInfo->FullLoadFromFile();
3948
3949   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3950   if ( aSMESHDS_Mesh == NULL ) return -1;
3951   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3952   if(!elem) return -1;
3953   return elem->NbEdges();
3954 }
3955
3956
3957 //=============================================================================
3958 /*!
3959  * Returns number of faces for given element
3960  */
3961 //=============================================================================
3962
3963 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
3964 {
3965   if ( _preMeshInfo )
3966     _preMeshInfo->FullLoadFromFile();
3967
3968   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3969   if ( aSMESHDS_Mesh == NULL ) return -1;
3970   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3971   if(!elem) return -1;
3972   return elem->NbFaces();
3973 }
3974
3975 //=======================================================================
3976 //function : GetElemFaceNodes
3977 //purpose  : Returns nodes of given face (counted from zero) for given element.
3978 //=======================================================================
3979
3980 SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long  elemId,
3981                                                   CORBA::Short faceIndex)
3982 {
3983   if ( _preMeshInfo )
3984     _preMeshInfo->FullLoadFromFile();
3985
3986   SMESH::long_array_var aResult = new SMESH::long_array();
3987   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
3988   {
3989     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(elemId) )
3990     {
3991       SMDS_VolumeTool vtool( elem );
3992       if ( faceIndex < vtool.NbFaces() )
3993       {
3994         aResult->length( vtool.NbFaceNodes( faceIndex ));
3995         const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
3996         for ( int i = 0; i < aResult->length(); ++i )
3997           aResult[ i ] = nn[ i ]->GetID();
3998       }
3999     }
4000   }
4001   return aResult._retn();
4002 }
4003
4004 //=======================================================================
4005 //function : FindElementByNodes
4006 //purpose  : Returns an element based on all given nodes.
4007 //=======================================================================
4008
4009 CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
4010 {
4011   if ( _preMeshInfo )
4012     _preMeshInfo->FullLoadFromFile();
4013
4014   CORBA::Long elemID(0);
4015   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
4016   {
4017     vector< const SMDS_MeshNode * > nn( nodes.length() );
4018     for ( int i = 0; i < nodes.length(); ++i )
4019       if ( !( nn[i] = mesh->FindNode( nodes[i] )))
4020         return elemID;
4021
4022     const SMDS_MeshElement* elem = mesh->FindElement( nn );
4023     if ( !elem && ( _impl->NbEdges  ( ORDER_QUADRATIC ) ||
4024                     _impl->NbFaces  ( ORDER_QUADRATIC ) ||
4025                     _impl->NbVolumes( ORDER_QUADRATIC )))
4026       elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
4027
4028     if ( elem ) elemID = CORBA::Long( elem->GetID() );
4029   }
4030   return elemID;
4031 }
4032
4033 //=============================================================================
4034 /*!
4035  * Returns true if given element is polygon
4036  */
4037 //=============================================================================
4038
4039 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
4040 {
4041   if ( _preMeshInfo )
4042     _preMeshInfo->FullLoadFromFile();
4043
4044   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4045   if ( aSMESHDS_Mesh == NULL ) return false;
4046   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4047   if(!elem) return false;
4048   return elem->IsPoly();
4049 }
4050
4051
4052 //=============================================================================
4053 /*!
4054  * Returns true if given element is quadratic
4055  */
4056 //=============================================================================
4057
4058 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
4059 {
4060   if ( _preMeshInfo )
4061     _preMeshInfo->FullLoadFromFile();
4062
4063   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4064   if ( aSMESHDS_Mesh == NULL ) return false;
4065   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4066   if(!elem) return false;
4067   return elem->IsQuadratic();
4068 }
4069
4070 //=============================================================================
4071 /*!
4072  * Returns diameter of ball discrete element or zero in case of an invalid \a id
4073  */
4074 //=============================================================================
4075
4076 CORBA::Double SMESH_Mesh_i::GetBallDiameter(CORBA::Long id)
4077 {
4078   if ( _preMeshInfo )
4079     _preMeshInfo->FullLoadFromFile();
4080
4081   if ( const SMDS_BallElement* ball =
4082        dynamic_cast<const SMDS_BallElement*>( _impl->GetMeshDS()->FindElement( id )))
4083     return ball->GetDiameter();
4084
4085   return 0;
4086 }
4087
4088 //=============================================================================
4089 /*!
4090  * Returns bary center for given element
4091  */
4092 //=============================================================================
4093
4094 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
4095 {
4096   if ( _preMeshInfo )
4097     _preMeshInfo->FullLoadFromFile();
4098
4099   SMESH::double_array_var aResult = new SMESH::double_array();
4100   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4101   if ( aSMESHDS_Mesh == NULL )
4102     return aResult._retn();
4103
4104   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4105   if(!elem)
4106     return aResult._retn();
4107
4108   if(elem->GetType()==SMDSAbs_Volume) {
4109     SMDS_VolumeTool aTool;
4110     if(aTool.Set(elem)) {
4111       aResult->length(3);
4112       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
4113         aResult->length(0);
4114     }
4115   }
4116   else {
4117     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
4118     int nbn = 0;
4119     double x=0., y=0., z=0.;
4120     for(; anIt->more(); ) {
4121       nbn++;
4122       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
4123       x += aNode->X();
4124       y += aNode->Y();
4125       z += aNode->Z();
4126     }
4127     if(nbn>0) {
4128       // add coordinates
4129       aResult->length(3);
4130       aResult[0] = x/nbn;
4131       aResult[1] = y/nbn;
4132       aResult[2] = z/nbn;
4133     }
4134   }
4135
4136   return aResult._retn();
4137 }
4138
4139
4140 //=============================================================================
4141 /*!
4142  * Create and publish group servants if any groups were imported or created anyhow
4143  */
4144 //=============================================================================
4145
4146 void SMESH_Mesh_i::CreateGroupServants()
4147 {
4148   SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
4149
4150   set<int> addedIDs;
4151   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
4152   while ( groupIt->more() )
4153   {
4154     ::SMESH_Group* group = groupIt->next();
4155     int            anId = group->GetGroupDS()->GetID();
4156
4157     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
4158     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
4159       continue;
4160     addedIDs.insert( anId );
4161
4162     SMESH_GroupBase_i* aGroupImpl;
4163     TopoDS_Shape       shape;
4164     if ( SMESHDS_GroupOnGeom* groupOnGeom =
4165          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
4166     {
4167       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
4168       shape      = groupOnGeom->GetShape();
4169     }
4170     else {
4171       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
4172     }
4173
4174     SMESH::SMESH_GroupBase_var groupVar =
4175       SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
4176     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
4177
4178     // register CORBA object for persistence
4179     int nextId = _gen_i->RegisterObject( groupVar );
4180     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
4181
4182     // publishing the groups in the study
4183     if ( !aStudy->_is_nil() ) {
4184       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
4185       _gen_i->PublishGroup( aStudy, _this(), groupVar, shapeVar, groupVar->GetName());
4186     }
4187   }
4188   if ( !addedIDs.empty() )
4189   {
4190     // python dump
4191     set<int>::iterator id = addedIDs.begin();
4192     for ( ; id != addedIDs.end(); ++id )
4193     {
4194       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(*id);
4195       int i = std::distance( _mapGroups.begin(), it );
4196       TPythonDump() << it->second << " = " << _this() << ".GetGroups()[ "<< i << " ]";
4197     }
4198   }
4199 }
4200
4201 //=============================================================================
4202 /*!
4203  * \brief Return groups cantained in _mapGroups by their IDs
4204  */
4205 //=============================================================================
4206
4207 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
4208 {
4209   int nbGroups = groupIDs.size();
4210   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
4211   aList->length( nbGroups );
4212
4213   list<int>::const_iterator ids = groupIDs.begin();
4214   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
4215   {
4216     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
4217     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
4218       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
4219   }
4220   aList->length( nbGroups );
4221   return aList._retn();
4222 }
4223
4224 //=============================================================================
4225 /*!
4226  * \brief Return information about imported file
4227  */
4228 //=============================================================================
4229
4230 SALOME_MED::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
4231 {
4232   SALOME_MED::MedFileInfo_var res( _medFileInfo );
4233   if ( !res.operator->() ) {
4234     res = new SALOME_MED::MedFileInfo;
4235     res->fileName = "";
4236     res->fileSize = res->major = res->minor = res->release = -1;
4237   }
4238   return res._retn();
4239 }
4240
4241 //=============================================================================
4242 /*!
4243  * \brief Pass names of mesh groups from study to mesh DS
4244  */
4245 //=============================================================================
4246
4247 void SMESH_Mesh_i::checkGroupNames()
4248 {
4249   int nbGrp = NbGroups();
4250   if ( !nbGrp )
4251     return;
4252
4253   SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
4254   if ( aStudy->_is_nil() )
4255     return; // nothing to do
4256   
4257   SMESH::ListOfGroups* grpList = 0;
4258   // avoid dump of "GetGroups"
4259   {
4260     // store python dump into a local variable inside local scope
4261     SMESH::TPythonDump pDump; // do not delete this line of code
4262     grpList = GetGroups();
4263   }
4264
4265   for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
4266     SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
4267     if ( !aGrp )
4268       continue;
4269     SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aStudy, aGrp );
4270     if ( aGrpSO->_is_nil() )
4271       continue;
4272     // correct name of the mesh group if necessary
4273     const char* guiName = aGrpSO->GetName();
4274     if ( strcmp(guiName, aGrp->GetName()) )
4275       aGrp->SetName( guiName );
4276   }
4277 }
4278
4279 //=============================================================================
4280 /*!
4281  * \brief Sets list of notebook variables used for Mesh operations separated by ":" symbol
4282  */
4283 //=============================================================================
4284 void SMESH_Mesh_i::SetParameters(const char* theParameters)
4285 {
4286   // SMESH_Gen_i::GetSMESHGen()->UpdateParameters(SMESH::SMESH_Mesh::_narrow(_this()),
4287   //                                              CORBA::string_dup(theParameters));
4288   SMESH_Gen_i::GetSMESHGen()->UpdateParameters(theParameters);
4289 }
4290
4291 //=============================================================================
4292 /*!
4293  * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
4294  */
4295 //=============================================================================
4296 char* SMESH_Mesh_i::GetParameters()
4297 {
4298   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
4299   return CORBA::string_dup(gen->GetParameters(SMESH::SMESH_Mesh::_narrow(_this())));
4300 }
4301
4302 //=============================================================================
4303 /*!
4304  * \brief Returns list of notebook variables used for last Mesh operation
4305  */
4306 //=============================================================================
4307 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
4308 {
4309   SMESH::string_array_var aResult = new SMESH::string_array();
4310   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
4311   if(gen) {
4312     char *aParameters = GetParameters();
4313     SALOMEDS::Study_var aStudy = gen->GetCurrentStudy();
4314     if(!aStudy->_is_nil()) {
4315       SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters); 
4316       if(aSections->length() > 0) {
4317         SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1];
4318         aResult->length(aVars.length());
4319         for(int i = 0;i < aVars.length();i++)
4320           aResult[i] = CORBA::string_dup( aVars[i]);
4321       }
4322     }
4323   }
4324   return aResult._retn();
4325 }
4326
4327 //=======================================================================
4328 //function : GetTypes
4329 //purpose  : Returns types of elements it contains
4330 //=======================================================================
4331
4332 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
4333 {
4334   if ( _preMeshInfo )
4335     return _preMeshInfo->GetTypes();
4336
4337   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
4338
4339   types->length( 5 );
4340   int nbTypes = 0;
4341   if (_impl->NbEdges())      types[nbTypes++] = SMESH::EDGE;
4342   if (_impl->NbFaces())      types[nbTypes++] = SMESH::FACE;
4343   if (_impl->NbVolumes())    types[nbTypes++] = SMESH::VOLUME;
4344   if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
4345   if (_impl->NbBalls())      types[nbTypes++] = SMESH::BALL;
4346   types->length( nbTypes );
4347
4348   return types._retn();
4349 }
4350
4351 //=======================================================================
4352 //function : GetMesh
4353 //purpose  : Returns self
4354 //=======================================================================
4355
4356 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
4357 {
4358   return SMESH::SMESH_Mesh::_duplicate( _this() );
4359 }
4360
4361 //=======================================================================
4362 //function : IsMeshInfoCorrect
4363 //purpose  : * Returns false if GetMeshInfo() returns incorrect information that may
4364 //           * happen if mesh data is not yet fully loaded from the file of study.
4365 //=======================================================================
4366
4367 bool SMESH_Mesh_i::IsMeshInfoCorrect()
4368 {
4369   return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
4370 }
4371
4372 //=============================================================================
4373 /*!
4374  * \brief Returns statistic of mesh elements
4375  */
4376 //=============================================================================
4377
4378 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
4379 {
4380   if ( _preMeshInfo )
4381     return _preMeshInfo->GetMeshInfo();
4382
4383   SMESH::long_array_var aRes = new SMESH::long_array();
4384   aRes->length(SMESH::Entity_Last);
4385   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
4386     aRes[i] = 0;
4387   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4388   if (!aMeshDS)
4389     return aRes._retn();
4390   const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
4391   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
4392     aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
4393   return aRes._retn();
4394 }
4395
4396 //=============================================================================
4397 /*!
4398  * \brief Collect statistic of mesh elements given by iterator
4399  */
4400 //=============================================================================
4401
4402 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
4403                                    SMESH::long_array&         theInfo)
4404 {
4405   if (!theItr) return;
4406   while (theItr->more())
4407     theInfo[ theItr->next()->GetEntityType() ]++;
4408 }
4409
4410 //=============================================================================
4411 namespace // Finding concurrent hypotheses
4412 //=============================================================================
4413 {
4414
4415 /*!
4416  * \brief mapping of mesh dimension into shape type
4417  */
4418 TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
4419 {
4420   TopAbs_ShapeEnum aType = TopAbs_SOLID;
4421   switch ( theDim ) {
4422   case 0: aType = TopAbs_VERTEX; break;
4423   case 1: aType = TopAbs_EDGE; break;
4424   case 2: aType = TopAbs_FACE; break;
4425   case 3:
4426   default:aType = TopAbs_SOLID; break;
4427   }
4428   return aType;
4429 }
4430
4431 //-----------------------------------------------------------------------------
4432 /*!
4433  * \brief Internal structure used to find concurent submeshes
4434  *
4435  * It represents a pair < submesh, concurent dimension >, where
4436  * 'concurrent dimension' is dimension of shape where the submesh can concurent
4437  *  with another submesh. In other words, it is dimension of a hypothesis assigned
4438  *  to submesh.
4439  */
4440 class SMESH_DimHyp
4441 {
4442  public:
4443   //! fileds
4444   int _dim;    //!< a dimension the algo can build (concurrent dimension)
4445   int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
4446   TopTools_MapOfShape _shapeMap;
4447   SMESH_subMesh*      _subMesh;
4448   list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
4449
4450   //-----------------------------------------------------------------------------
4451   // Return the algorithm
4452   const SMESH_Algo* GetAlgo() const
4453   { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
4454
4455   //-----------------------------------------------------------------------------
4456   //! Constructors
4457   SMESH_DimHyp(const SMESH_subMesh*  theSubMesh,
4458                const int             theDim,
4459                const TopoDS_Shape&   theShape)
4460   {
4461     _subMesh = (SMESH_subMesh*)theSubMesh;
4462     SetShape( theDim, theShape );
4463   }
4464
4465   //-----------------------------------------------------------------------------
4466   //! set shape
4467   void SetShape(const int           theDim,
4468                 const TopoDS_Shape& theShape)
4469   {
4470     _dim = theDim;
4471     _ownDim = (int)SMESH_Gen::GetShapeDim(theShape);
4472     if (_dim >= _ownDim)
4473       _shapeMap.Add( theShape );
4474     else {
4475       TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
4476       for( ; anExp.More(); anExp.Next() )
4477         _shapeMap.Add( anExp.Current() );
4478     }
4479   }
4480
4481   //-----------------------------------------------------------------------------
4482   //! Check sharing of sub-shapes
4483   static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
4484                                const TopTools_MapOfShape& theToFind,
4485                                const TopAbs_ShapeEnum     theType)
4486   {
4487     bool isShared = false;
4488     TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
4489     for (; !isShared && anItr.More(); anItr.Next() )
4490     {
4491       const TopoDS_Shape aSubSh = anItr.Key();
4492       // check for case when concurrent dimensions are same
4493       isShared = theToFind.Contains( aSubSh );
4494       // check for sub-shape with concurrent dimension
4495       TopExp_Explorer anExp( aSubSh, theType );
4496       for ( ; !isShared && anExp.More(); anExp.Next() )
4497         isShared = theToFind.Contains( anExp.Current() );
4498     }
4499     return isShared;
4500   }
4501   
4502   //-----------------------------------------------------------------------------
4503   //! check algorithms
4504   static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
4505                         const SMESHDS_Hypothesis* theA2)
4506   {
4507     if ( !theA1 || !theA2 ||
4508          theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
4509          theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
4510       return false; // one of the hypothesis is not algorithm
4511     // check algorithm names (should be equal)
4512     return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
4513   }
4514
4515   
4516   //-----------------------------------------------------------------------------
4517   //! Check if sub-shape hypotheses are concurrent
4518   bool IsConcurrent(const SMESH_DimHyp* theOther) const
4519   {
4520     if ( _subMesh == theOther->_subMesh )
4521       return false; // same sub-shape - should not be
4522
4523     // if ( <own dim of either of submeshes> == <concurrent dim> &&
4524     //      any of the two submeshes is not on COMPOUND shape )
4525     //  -> no concurrency
4526     bool meIsCompound    = (_subMesh->GetSubMeshDS() &&
4527                             _subMesh->GetSubMeshDS()->IsComplexSubmesh());
4528     bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
4529                             theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
4530     if ( (_ownDim == _dim  || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
4531       return false;
4532
4533 //     bool checkSubShape = ( _dim >= theOther->_dim )
4534 //       ? isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(theOther->_dim) )
4535 //       : isShareSubShapes( theOther->_shapeMap, _shapeMap, shapeTypeByDim(_dim) ) ;
4536     bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
4537     if ( !checkSubShape )
4538         return false;
4539
4540     // check algorithms to be same
4541     if ( !checkAlgo( this->GetAlgo(), theOther->GetAlgo() ))
4542       return true; // different algorithms -> concurrency !
4543
4544     // check hypothesises for concurrence (skip first as algorithm)
4545     int nbSame = 0;
4546     // pointers should be same, because it is referened from mesh hypothesis partition
4547     list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
4548     list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
4549     for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
4550       if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
4551         nbSame++;
4552     // the submeshes are concurrent if their algorithms has different parameters
4553     return nbSame != theOther->_hypotheses.size() - 1;
4554   }
4555
4556   // Return true if algorithm of this SMESH_DimHyp is used if no
4557   // sub-mesh order is imposed by the user
4558   bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
4559   {
4560     // NeedDiscreteBoundary() algo has a higher priority
4561     if ( this    ->GetAlgo()->NeedDiscreteBoundary() !=
4562          theOther->GetAlgo()->NeedDiscreteBoundary() )
4563       return !this->GetAlgo()->NeedDiscreteBoundary();
4564
4565     return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
4566   }
4567   
4568 }; // end of SMESH_DimHyp
4569 //-----------------------------------------------------------------------------
4570
4571 typedef list<const SMESH_DimHyp*> TDimHypList;
4572
4573 //-----------------------------------------------------------------------------
4574
4575 void addDimHypInstance(const int                               theDim, 
4576                        const TopoDS_Shape&                     theShape,
4577                        const SMESH_Algo*                       theAlgo,
4578                        const SMESH_subMesh*                    theSubMesh,
4579                        const list <const SMESHDS_Hypothesis*>& theHypList,
4580                        TDimHypList*                            theDimHypListArr )
4581 {
4582   TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
4583   if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) {
4584     SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
4585     dimHyp->_hypotheses.push_front(theAlgo);
4586     listOfdimHyp.push_back( dimHyp );
4587   }
4588   
4589   SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
4590   dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
4591                               theHypList.begin(), theHypList.end() );
4592 }
4593
4594 //-----------------------------------------------------------------------------
4595 void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
4596                            TDimHypList&        theListOfConcurr)
4597 {
4598   if ( theListOfConcurr.empty() )
4599   {
4600     theListOfConcurr.push_back( theDimHyp );
4601   }
4602   else
4603   {
4604     TDimHypList::iterator hypIt = theListOfConcurr.begin();
4605     while ( hypIt != theListOfConcurr.end() &&
4606             !theDimHyp->IsHigherPriorityThan( *hypIt ))
4607       ++hypIt;
4608     theListOfConcurr.insert( hypIt, theDimHyp );
4609   }
4610 }
4611
4612 //-----------------------------------------------------------------------------
4613 void findConcurrents(const SMESH_DimHyp* theDimHyp,
4614                      const TDimHypList&  theListOfDimHyp,
4615                      TDimHypList&        theListOfConcurrHyp,
4616                      set<int>&           theSetOfConcurrId )
4617 {
4618   TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
4619   for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
4620   {
4621     const SMESH_DimHyp* curDimHyp = *rIt;
4622     if ( curDimHyp == theDimHyp )
4623       break; // meet own dimHyp pointer in same dimension
4624
4625     if ( theDimHyp->IsConcurrent( curDimHyp ) &&
4626          theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
4627     {
4628       addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
4629     }
4630   }
4631 }
4632
4633 //-----------------------------------------------------------------------------
4634 void unionLists(TListOfInt&       theListOfId,
4635                 TListOfListOfInt& theListOfListOfId,
4636                 const int         theIndx )
4637 {
4638   TListOfListOfInt::iterator it = theListOfListOfId.begin();
4639   for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) {
4640     if ( i < theIndx )
4641       continue; //skip already treated lists
4642     // check if other list has any same submesh object
4643     TListOfInt& otherListOfId = *it;
4644     if ( find_first_of( theListOfId.begin(), theListOfId.end(),
4645                         otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
4646       continue;
4647          
4648     // union two lists (from source into target)
4649     TListOfInt::iterator it2 = otherListOfId.begin();
4650     for ( ; it2 != otherListOfId.end(); it2++ ) {
4651       if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
4652         theListOfId.push_back(*it2);
4653     }
4654     // clear source list
4655     otherListOfId.clear();
4656   }
4657 }
4658 //-----------------------------------------------------------------------------
4659
4660 //! free memory allocated for dimension-hypothesis objects
4661 void removeDimHyps( TDimHypList* theArrOfList )
4662 {
4663   for (int i = 0; i < 4; i++ ) {
4664     TDimHypList& listOfdimHyp = theArrOfList[i];
4665     TDimHypList::const_iterator it = listOfdimHyp.begin();
4666     for ( ; it != listOfdimHyp.end(); it++ )
4667       delete (*it);
4668   }
4669 }
4670
4671 //-----------------------------------------------------------------------------
4672 /*!
4673  * \brief find common submeshes with given submesh
4674  * \param theSubMeshList list of already collected submesh to check
4675  * \param theSubMesh given submesh to intersect with other
4676  * \param theCommonSubMeshes collected common submeshes
4677  */
4678 void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
4679                         const SMESH_subMesh*        theSubMesh,
4680                         set<const SMESH_subMesh*>&  theCommon )
4681 {
4682   if ( !theSubMesh )
4683     return;
4684   list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
4685   for ( ; it != theSubMeshList.end(); it++ )
4686     theSubMesh->FindIntersection( *it, theCommon );
4687   theSubMeshList.push_back( theSubMesh );
4688   //theCommon.insert( theSubMesh );
4689 }
4690
4691 } // namespace
4692
4693 //=============================================================================
4694 /*!
4695  * \brief Return submesh objects list in meshing order
4696  */
4697 //=============================================================================
4698
4699 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
4700 {
4701   SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
4702
4703   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4704   if ( !aMeshDS )
4705     return aResult._retn();
4706   
4707   ::SMESH_Mesh& mesh = GetImpl();
4708   TListOfListOfInt anOrder = mesh.GetMeshOrder(); // is there already defined order?
4709   if ( !anOrder.size() ) {
4710
4711     // collect submeshes and detect concurrent algorithms and hypothesises
4712     TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
4713     
4714     map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
4715     for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) {
4716       ::SMESH_subMesh* sm = (*i_sm).second;
4717       // shape of submesh
4718       const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
4719
4720       // list of assigned hypothesises
4721       const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
4722       // Find out dimensions where the submesh can be concurrent.
4723       // We define the dimensions by algo of each of hypotheses in hypList
4724       list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
4725       for( ; hypIt != hypList.end(); hypIt++ ) {
4726         SMESH_Algo* anAlgo = 0;
4727         const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
4728         if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
4729           // hyp it-self is algo
4730           anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
4731         else {
4732           // try to find algorithm with help of sub-shapes
4733           TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
4734           for ( ; !anAlgo && anExp.More(); anExp.Next() )
4735             anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
4736         }
4737         if (!anAlgo)
4738           continue; // no algorithm assigned to a current submesh
4739
4740         int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
4741         // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary())
4742
4743         // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
4744         for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
4745           addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
4746       }
4747     } // end iterations on submesh
4748     
4749     // iterate on created dimension-hypotheses and check for concurrents
4750     for ( int i = 0; i < 4; i++ ) {
4751       const TDimHypList& listOfDimHyp = dimHypListArr[i];
4752       // check for concurrents in own and other dimensions (step-by-step)
4753       TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
4754       for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) {
4755         const SMESH_DimHyp* dimHyp = *dhIt;
4756         TDimHypList listOfConcurr;
4757         set<int>    setOfConcurrIds;
4758         // looking for concurrents and collect into own list
4759         for ( int j = i; j < 4; j++ )
4760           findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
4761         // check if any concurrents found
4762         if ( listOfConcurr.size() > 0 ) {
4763           // add own submesh to list of concurrent
4764           addInOrderOfPriority( dimHyp, listOfConcurr );
4765           list<int> listOfConcurrIds;
4766           TDimHypList::iterator hypIt = listOfConcurr.begin();
4767           for ( ; hypIt != listOfConcurr.end(); ++hypIt )
4768             listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
4769           anOrder.push_back( listOfConcurrIds );
4770         }
4771       }
4772     }
4773     
4774     removeDimHyps(dimHypListArr);
4775     
4776     // now, minimise the number of concurrent groups
4777     // Here we assume that lists of submeshes can have same submesh
4778     // in case of multi-dimension algorithms, as result
4779     //  list with common submesh has to be united into one list
4780     int listIndx = 0;
4781     TListOfListOfInt::iterator listIt = anOrder.begin();
4782     for(; listIt != anOrder.end(); listIt++, listIndx++ )
4783       unionLists( *listIt,  anOrder, listIndx + 1 );
4784   }
4785   // convert submesh ids into interface instances
4786   //  and dump command into python
4787   convertMeshOrder( anOrder, aResult, false );
4788
4789   return aResult._retn();
4790 }
4791
4792 //=============================================================================
4793 /*!
4794  * \brief Set submesh object order
4795  * \param theSubMeshArray submesh array order
4796  */
4797 //=============================================================================
4798
4799 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
4800 {
4801   if ( _preMeshInfo )
4802     _preMeshInfo->ForgetOrLoad();
4803
4804   bool res = false;
4805   ::SMESH_Mesh& mesh = GetImpl();
4806
4807   TPythonDump aPythonDump; // prevent dump of called methods
4808   aPythonDump << "isDone = " << _this() << ".SetMeshOrder( [ ";
4809
4810   TListOfListOfInt subMeshOrder;
4811   for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
4812   {
4813     const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
4814     TListOfInt subMeshIds;
4815     aPythonDump << "[ ";
4816     // Collect subMeshes which should be clear
4817     //  do it list-by-list, because modification of submesh order
4818     //  take effect between concurrent submeshes only
4819     set<const SMESH_subMesh*> subMeshToClear;
4820     list<const SMESH_subMesh*> subMeshList;
4821     for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
4822     {
4823       const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
4824       if ( j > 0 )
4825         aPythonDump << ", ";
4826       aPythonDump << subMesh;
4827       subMeshIds.push_back( subMesh->GetId() );
4828       // detect common parts of submeshes
4829       if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
4830         findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
4831     }
4832     aPythonDump << " ]";
4833     subMeshOrder.push_back( subMeshIds );
4834
4835     // clear collected submeshes
4836     set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
4837     for ( ; clrIt != subMeshToClear.end(); clrIt++ )
4838       if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
4839         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
4840   }
4841   aPythonDump << " ])";
4842
4843   mesh.SetMeshOrder( subMeshOrder );
4844   res = true;
4845   
4846   return res;
4847 }
4848
4849 //=============================================================================
4850 /*!
4851  * \brief Convert submesh ids into submesh interfaces
4852  */
4853 //=============================================================================
4854
4855 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt&     theIdsOrder,
4856                                      SMESH::submesh_array_array& theResOrder,
4857                                      const bool                  theIsDump)
4858 {
4859   int nbSet = theIdsOrder.size();
4860   TPythonDump aPythonDump; // prevent dump of called methods
4861   if ( theIsDump )
4862     aPythonDump << "[ ";
4863   theResOrder.length(nbSet);
4864   TListOfListOfInt::const_iterator it = theIdsOrder.begin();
4865   int listIndx = 0;
4866   for( ; it != theIdsOrder.end(); it++ ) {
4867     // translate submesh identificators into submesh objects
4868     //  takeing into account real number of concurrent lists
4869     const TListOfInt& aSubOrder = (*it);
4870     if (!aSubOrder.size())
4871       continue;
4872     if ( theIsDump )
4873       aPythonDump << "[ ";
4874     // convert shape indeces into interfaces
4875     SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
4876     aResSubSet->length(aSubOrder.size());
4877     TListOfInt::const_iterator subIt = aSubOrder.begin();
4878     for( int j = 0; subIt != aSubOrder.end(); subIt++ ) {
4879       if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
4880         continue;
4881       SMESH::SMESH_subMesh_var subMesh =
4882         SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
4883       if ( theIsDump ) {
4884         if ( j > 0 )
4885           aPythonDump << ", ";
4886         aPythonDump << subMesh;
4887       }
4888       aResSubSet[ j++ ] = subMesh;
4889     }
4890     if ( theIsDump )
4891       aPythonDump << " ]";
4892     theResOrder[ listIndx++ ] = aResSubSet;
4893   }
4894   // correct number of lists
4895   theResOrder.length( listIndx );
4896
4897   if ( theIsDump ) {
4898     // finilise python dump
4899     aPythonDump << " ]";
4900     aPythonDump << " = " << _this() << ".GetMeshOrder()";
4901   }
4902 }
4903
4904 //================================================================================
4905 //
4906 // Implementation of SMESH_MeshPartDS
4907 //
4908 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
4909   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
4910 {
4911   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
4912   SMESH_Mesh_i*       mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4913
4914   _meshDS = mesh_i->GetImpl().GetMeshDS();
4915
4916   SetPersistentId( _meshDS->GetPersistentId() );
4917
4918   if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
4919   {
4920     // <meshPart> is the whole mesh
4921     myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
4922     // copy groups
4923     set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
4924     myGroupSet = _meshDS->GetGroups();
4925   }
4926   else
4927   {
4928     TMeshInfo tmpInfo;
4929     SMESH::long_array_var           anIDs = meshPart->GetIDs();
4930     SMESH::array_of_ElementType_var types = meshPart->GetTypes();
4931     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
4932     {
4933       for (int i=0; i < anIDs->length(); i++)
4934         if ( const SMDS_MeshNode * n = _meshDS->FindNode(anIDs[i]))
4935           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
4936             tmpInfo.Add( n );
4937     }
4938     else
4939     {
4940       for (int i=0; i < anIDs->length(); i++)
4941         if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
4942           if ( _elements[ e->GetType() ].insert( e ).second )
4943           {
4944             tmpInfo.Add( e );
4945             SMDS_ElemIteratorPtr nIt = e->nodesIterator();
4946             while ( nIt->more() )
4947             {
4948               const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
4949               if ( _elements[ SMDSAbs_Node ].insert( n ).second )
4950                 tmpInfo.Add( n );
4951             }
4952           }
4953     }
4954     myInfo = tmpInfo;
4955
4956     _meshDS = 0; // to enforce iteration on _elements and _nodes
4957   }
4958 }
4959 // -------------------------------------------------------------------------------------
4960 SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
4961   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
4962 {
4963   TMeshInfo tmpInfo;
4964   list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
4965   for ( ; partIt != meshPart.end(); ++partIt )
4966     if ( const SMDS_MeshElement * e = *partIt )
4967       if ( _elements[ e->GetType() ].insert( e ).second )
4968       {
4969         tmpInfo.Add( e );
4970         SMDS_ElemIteratorPtr nIt = e->nodesIterator();
4971         while ( nIt->more() )
4972         {
4973           const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
4974           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
4975             tmpInfo.Add( n );
4976         }
4977       }
4978   myInfo = tmpInfo;
4979 }
4980 // -------------------------------------------------------------------------------------
4981 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
4982 {
4983   if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
4984
4985   typedef SMDS_SetIterator
4986     <const SMDS_MeshElement*,
4987     TIDSortedElemSet::const_iterator,
4988     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
4989     SMDS_MeshElement::GeomFilter
4990     > TIter;
4991
4992   SMDSAbs_ElementType type = SMDS_MeshCell::toSmdsType( geomType );
4993
4994   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
4995                                           _elements[type].end(),
4996                                           SMDS_MeshElement::GeomFilter( geomType )));
4997 }
4998 // -------------------------------------------------------------------------------------
4999 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
5000 {
5001   if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
5002
5003   typedef SMDS_SetIterator
5004     <const SMDS_MeshElement*,
5005     TIDSortedElemSet::const_iterator,
5006     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
5007     SMDS_MeshElement::EntityFilter
5008     > TIter;
5009
5010   SMDSAbs_ElementType type = SMDS_MeshCell::toSmdsType( entity );
5011
5012   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
5013                                           _elements[type].end(),
5014                                           SMDS_MeshElement::EntityFilter( entity )));
5015 }
5016 // -------------------------------------------------------------------------------------
5017 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
5018 {
5019   typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
5020   if ( type == SMDSAbs_All && !_meshDS )
5021   {
5022     typedef vector< SMDS_ElemIteratorPtr > TIterVec;
5023     TIterVec iterVec;
5024     for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
5025       if ( !_elements[i].empty() && i != SMDSAbs_Node )
5026         iterVec.push_back
5027           ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
5028
5029     typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
5030     return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
5031   }
5032   return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
5033       ( new TIter( _elements[type].begin(), _elements[type].end() ));
5034 }
5035 // -------------------------------------------------------------------------------------
5036 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType)                       \
5037   iterType SMESH_MeshPartDS::methName( bool idInceasingOrder) const                 \
5038   {                                                                                 \
5039     typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
5040     return _meshDS ? _meshDS->methName(idInceasingOrder) : iterType                 \
5041       ( new TIter( _elements[elemType].begin(), _elements[elemType].end() ));       \
5042   }
5043 // -------------------------------------------------------------------------------------
5044 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
5045 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
5046 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
5047 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
5048 #undef _GET_ITER_DEFINE
5049 //
5050 // END Implementation of SMESH_MeshPartDS
5051 //
5052 //================================================================================
5053
5054