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