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