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