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