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