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