Salome HOME
INT PAL 0052683: Parameter "Color group" in the "Create Group" dialog box is empty
[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 submeshes and geom groups is deleted
2243       _impl->ShapeToMesh( newShape );
2244       
2245       // reassign hypotheses
2246       TShapeHypList::iterator indS_hyps = assignedHyps.begin();
2247       for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
2248       {
2249         TIndexedShape&                   geom = indS_hyps->first;
2250         list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
2251         int oldID = geom._index;
2252         int newID = meshDS->ShapeToIndex( geom._shape );
2253         if ( oldID == 1 ) { // main shape
2254           newID = 1;
2255           geom._shape = newShape;
2256         }
2257         if ( !newID )
2258           continue;
2259         for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2260           _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
2261         // care of submeshes
2262         SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
2263         if ( newID != oldID ) {
2264           _mapSubMesh   [ newID ] = newSubmesh;
2265           _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2266           _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2267           _mapSubMesh.   erase(oldID);
2268           _mapSubMesh_i. erase(oldID);
2269           _mapSubMeshIor.erase(oldID);
2270           _mapSubMesh_i [ newID ]->changeLocalId( newID );
2271         }
2272       }
2273       // recreate groups
2274       TShapeTypeList::iterator geomType = groupData.begin();
2275       for ( ; geomType != groupData.end(); ++geomType )
2276       {
2277         const TIndexedShape& geom = geomType->first;
2278         int oldID = geom._index;
2279         if ( _mapGroups.find( oldID ) == _mapGroups.end() )
2280           continue;
2281         // get group name
2282         SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( study,_mapGroups[oldID] );
2283         CORBA::String_var      name    = groupSO->GetName();
2284         // update
2285         SMESH_GroupBase_i*  group_i    = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID] );
2286         int newID;
2287         if ( group_i && _impl->AddGroup( geomType->second, name.in(), newID, geom._shape ))
2288           group_i->changeLocalId( newID );
2289       }
2290
2291       break; // everything has been updated
2292
2293     } // update mesh
2294   } // loop on group data
2295
2296   // Update icons
2297
2298   CORBA::Long newNbEntities = NbNodes() + NbElements();
2299   list< SALOMEDS::SObject_wrap > soToUpdateIcons;
2300   if ( newNbEntities != nbEntities )
2301   {
2302     // Add all SObjects with icons to soToUpdateIcons
2303     soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, _this() )); // mesh
2304
2305     for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
2306          i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
2307       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, i_sm->second ));
2308
2309     for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
2310           i_gr != _mapGroups.end(); ++i_gr ) // groups
2311       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, i_gr->second ));
2312   }
2313
2314   list< SALOMEDS::SObject_wrap >::iterator so = soToUpdateIcons.begin();
2315   for ( ; so != soToUpdateIcons.end(); ++so )
2316     _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
2317 }
2318
2319 //=============================================================================
2320 /*!
2321  * \brief Create standalone group from a group on geometry or filter
2322  */
2323 //=============================================================================
2324
2325 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase_ptr theGroup )
2326   throw (SALOME::SALOME_Exception)
2327 {
2328   SMESH::SMESH_Group_var aGroup;
2329
2330   SMESH_TRY;
2331
2332   if ( _preMeshInfo )
2333     _preMeshInfo->FullLoadFromFile();
2334
2335   if ( theGroup->_is_nil() )
2336     return aGroup._retn();
2337
2338   SMESH_GroupBase_i* aGroupToRem = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
2339   if ( !aGroupToRem )
2340     return aGroup._retn();
2341
2342   const bool isOnFilter = ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ));
2343
2344   const int anId = aGroupToRem->GetLocalID();
2345   if ( !_impl->ConvertToStandalone( anId ) )
2346     return aGroup._retn();
2347   removeGeomGroupData( theGroup );
2348
2349   SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2350
2351   // remove old instance of group from own map
2352   { SMESH::SMESH_GroupBase_var var( _mapGroups[anId] ); } // decref CORBA object
2353   _mapGroups.erase( anId );
2354
2355   SALOMEDS::StudyBuilder_var builder;
2356   SALOMEDS::SObject_wrap     aGroupSO;
2357   SALOMEDS::Study_var        aStudy = _gen_i->GetCurrentStudy();
2358   if ( !aStudy->_is_nil() ) {
2359     builder  = aStudy->NewBuilder();
2360     aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
2361     if ( !aGroupSO->_is_nil() )
2362     {
2363       // remove reference to geometry
2364       SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO);
2365       for ( ; chItr->More(); chItr->Next() )
2366         // Remove group's child SObject
2367         builder->RemoveObject( chItr->Value() );
2368
2369       // Update Python script
2370       TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this())
2371                     << ".ConvertToStandalone( " << aGroupSO << " )";
2372
2373       // change icon of Group on Filter
2374       if ( isOnFilter )
2375       {
2376         SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
2377         const int isEmpty = ( elemTypes->length() == 0 );
2378         if ( !isEmpty )
2379         {
2380           SALOMEDS::GenericAttribute_wrap anAttr =
2381             builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
2382           SALOMEDS::AttributePixMap_wrap pm = anAttr;
2383           pm->SetPixMap( "ICON_SMESH_TREE_GROUP" );
2384         }
2385       }
2386     }
2387   }
2388
2389   // remember new group in own map
2390   aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
2391   _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2392
2393   // register CORBA object for persistence
2394   _gen_i->RegisterObject( aGroup );
2395
2396   CORBA::String_var ior = _gen_i->GetORB()->object_to_string( aGroup );
2397   builder->SetIOR( aGroupSO, ior.in() ); //  == aGroup->Register();
2398   //aGroup->Register();
2399   aGroupToRem->UnRegister();
2400
2401   SMESH_CATCH( SMESH::throwCorbaException );
2402
2403   return aGroup._retn();
2404 }
2405
2406 //=============================================================================
2407 /*!
2408  *
2409  */
2410 //=============================================================================
2411
2412 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
2413 {
2414   if(MYDEBUG) MESSAGE( "createSubMesh" );
2415   TopoDS_Shape  myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
2416   ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
2417   const int         subMeshId = mySubMesh->GetId();
2418
2419   SMESH_subMesh_i * subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
2420   SMESH::SMESH_subMesh_var subMesh = subMeshServant->_this();
2421
2422   _mapSubMesh   [subMeshId] = mySubMesh;
2423   _mapSubMesh_i [subMeshId] = subMeshServant;
2424   _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate( subMesh );
2425
2426   subMeshServant->Register();
2427
2428   // register CORBA object for persistence
2429   int nextId = _gen_i->RegisterObject( subMesh );
2430   if(MYDEBUG) { MESSAGE( "Add submesh to map with id = "<< nextId); }
2431   else        { nextId = 0; } // avoid "unused variable" warning
2432
2433   // to track changes of GEOM groups
2434   addGeomGroupData( theSubShapeObject, subMesh );
2435
2436   return subMesh._retn();
2437 }
2438
2439 //=======================================================================
2440 //function : getSubMesh
2441 //purpose  :
2442 //=======================================================================
2443
2444 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
2445 {
2446   map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
2447   if ( it == _mapSubMeshIor.end() )
2448     return SMESH::SMESH_subMesh::_nil();
2449
2450   return SMESH::SMESH_subMesh::_duplicate( (*it).second );
2451 }
2452
2453 //=============================================================================
2454 /*!
2455  *
2456  */
2457 //=============================================================================
2458
2459 bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
2460                                   GEOM::GEOM_Object_ptr    theSubShapeObject )
2461 {
2462   bool isHypChanged = false;
2463   if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
2464     return isHypChanged;
2465
2466   const int subMeshId = theSubMesh->GetId();
2467
2468   if ( theSubShapeObject->_is_nil() )  // not published shape (IPAL13617)
2469   {
2470     if ( _mapSubMesh.find( subMeshId ) != _mapSubMesh.end())
2471     {
2472       TopoDS_Shape S = _mapSubMesh[ subMeshId ]->GetSubShape();
2473       if ( !S.IsNull() )
2474       {
2475         list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
2476         isHypChanged = !hyps.empty();
2477         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
2478         for ( ; hyp != hyps.end(); ++hyp )
2479           _impl->RemoveHypothesis(S, (*hyp)->GetID());
2480       }
2481     }
2482   }
2483   else
2484   {
2485     try {
2486       SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
2487       isHypChanged = ( aHypList->length() > 0 );
2488       for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
2489         removeHypothesis( theSubShapeObject, aHypList[i] );
2490       }
2491     }
2492     catch( const SALOME::SALOME_Exception& ) {
2493       INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
2494     }
2495     removeGeomGroupData( theSubShapeObject );
2496   }
2497
2498   // remove a servant
2499   std::map<int, SMESH_subMesh_i*>::iterator id_smi = _mapSubMesh_i.find( subMeshId );
2500   if ( id_smi != _mapSubMesh_i.end() )
2501     id_smi->second->UnRegister();
2502
2503   // remove a CORBA object
2504   std::map<int, SMESH::SMESH_subMesh_ptr>::iterator id_smptr = _mapSubMeshIor.find( subMeshId );
2505   if ( id_smptr != _mapSubMeshIor.end() )
2506     SMESH::SMESH_subMesh_var( id_smptr->second );
2507
2508   _mapSubMesh.erase(subMeshId);
2509   _mapSubMesh_i.erase(subMeshId);
2510   _mapSubMeshIor.erase(subMeshId);
2511
2512   return isHypChanged;
2513 }
2514
2515 //=============================================================================
2516 /*!
2517  *
2518  */
2519 //=============================================================================
2520
2521 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType        theElemType,
2522                                                       const char*               theName,
2523                                                       const TopoDS_Shape&       theShape,
2524                                                       const SMESH_PredicatePtr& thePredicate )
2525 {
2526   std::string newName;
2527   if ( !theName || strlen( theName ) == 0 )
2528   {
2529     std::set< std::string > presentNames;
2530     std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
2531     for ( ; i_gr != _mapGroups.end(); ++i_gr )
2532     {
2533       CORBA::String_var name = i_gr->second->GetName();
2534       presentNames.insert( name.in() );
2535     }
2536     do {
2537       newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
2538     } while ( !presentNames.insert( newName ).second );
2539     theName = newName.c_str();
2540   }
2541   int anId;
2542   SMESH::SMESH_GroupBase_var aGroup;
2543   if ( _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName, anId, theShape, thePredicate ))
2544   {
2545     SMESH_GroupBase_i* aGroupImpl;
2546     if ( !theShape.IsNull() )
2547       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
2548     else if ( thePredicate )
2549       aGroupImpl = new SMESH_GroupOnFilter_i( SMESH_Gen_i::GetPOA(), this, anId );
2550     else
2551       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2552
2553     aGroup = aGroupImpl->_this();
2554     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2555     aGroupImpl->Register();
2556
2557     // register CORBA object for persistence
2558     int nextId = _gen_i->RegisterObject( aGroup );
2559     if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
2560     else        { nextId = 0; } // avoid "unused variable" warning in release mode
2561
2562     // to track changes of GEOM groups
2563     if ( !theShape.IsNull() ) {
2564       GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
2565       addGeomGroupData( geom, aGroup );
2566     }
2567   }
2568   return aGroup._retn();
2569 }
2570
2571 //=============================================================================
2572 /*!
2573  * SMESH_Mesh_i::removeGroup
2574  *
2575  * Should be called by ~SMESH_Group_i()
2576  */
2577 //=============================================================================
2578
2579 void SMESH_Mesh_i::removeGroup( const int theId )
2580 {
2581   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
2582   if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
2583     SMESH::SMESH_GroupBase_var group = _mapGroups[theId];
2584     _mapGroups.erase( theId );
2585     removeGeomGroupData( group );
2586     if ( !_impl->RemoveGroup( theId ))
2587     {
2588       // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
2589       RemoveGroup( group );
2590     }
2591     group->UnRegister();
2592   }
2593 }
2594
2595 //=============================================================================
2596 /*!
2597  *
2598  */
2599 //=============================================================================
2600
2601 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
2602   throw(SALOME::SALOME_Exception)
2603 {
2604   SMESH::log_array_var aLog;
2605
2606   SMESH_TRY;
2607   if ( _preMeshInfo )
2608     _preMeshInfo->FullLoadFromFile();
2609
2610   list < SMESHDS_Command * >logDS = _impl->GetLog();
2611   aLog = new SMESH::log_array;
2612   int indexLog = 0;
2613   int lg = logDS.size();
2614   SCRUTE(lg);
2615   aLog->length(lg);
2616   list < SMESHDS_Command * >::iterator its = logDS.begin();
2617   while(its != logDS.end()){
2618     SMESHDS_Command *com = *its;
2619     int comType = com->GetType();
2620     //SCRUTE(comType);
2621     int lgcom = com->GetNumber();
2622     //SCRUTE(lgcom);
2623     const list < int >&intList = com->GetIndexes();
2624     int inum = intList.size();
2625     //SCRUTE(inum);
2626     list < int >::const_iterator ii = intList.begin();
2627     const list < double >&coordList = com->GetCoords();
2628     int rnum = coordList.size();
2629     //SCRUTE(rnum);
2630     list < double >::const_iterator ir = coordList.begin();
2631     aLog[indexLog].commandType = comType;
2632     aLog[indexLog].number = lgcom;
2633     aLog[indexLog].coords.length(rnum);
2634     aLog[indexLog].indexes.length(inum);
2635     for(int i = 0; i < rnum; i++){
2636       aLog[indexLog].coords[i] = *ir;
2637       //MESSAGE(" "<<i<<" "<<ir.Value());
2638       ir++;
2639     }
2640     for(int i = 0; i < inum; i++){
2641       aLog[indexLog].indexes[i] = *ii;
2642       //MESSAGE(" "<<i<<" "<<ii.Value());
2643       ii++;
2644     }
2645     indexLog++;
2646     its++;
2647   }
2648   if(clearAfterGet)
2649     _impl->ClearLog();
2650
2651   SMESH_CATCH( SMESH::throwCorbaException );
2652
2653   return aLog._retn();
2654 }
2655
2656
2657 //=============================================================================
2658 /*!
2659  *
2660  */
2661 //=============================================================================
2662
2663 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
2664 {
2665   SMESH_TRY;
2666   _impl->ClearLog();
2667   SMESH_CATCH( SMESH::throwCorbaException );
2668 }
2669
2670 //=============================================================================
2671 /*!
2672  *
2673  */
2674 //=============================================================================
2675
2676 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
2677 {
2678   return _id;
2679 }
2680
2681 //=============================================================================
2682 /*!
2683  *
2684  */
2685 //=============================================================================
2686
2687 CORBA::Long SMESH_Mesh_i::GetStudyId()throw(SALOME::SALOME_Exception)
2688 {
2689   return _studyId;
2690 }
2691
2692 //=============================================================================
2693 namespace
2694 {
2695   //!< implementation of struct used to call methods of SMESH_Mesh_i from SMESH_Mesh
2696   // issue 0020918: groups removal is caused by hyp modification
2697   // issue 0021208: to forget not loaded mesh data at hyp modification
2698   struct TCallUp_i : public SMESH_Mesh::TCallUp
2699   {
2700     SMESH_Mesh_i* _mesh;
2701     TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
2702     virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); }
2703     virtual void HypothesisModified ()              { _mesh->onHypothesisModified(); }
2704     virtual void Load ()                            { _mesh->Load(); }
2705   };
2706 }
2707
2708 //================================================================================
2709 /*!
2710  * \brief callback from _impl to forget not loaded mesh data (issue 0021208)
2711  */
2712 //================================================================================
2713
2714 void SMESH_Mesh_i::onHypothesisModified()
2715 {
2716   if ( _preMeshInfo )
2717     _preMeshInfo->ForgetOrLoad();
2718 }
2719
2720 //=============================================================================
2721 /*!
2722  *
2723  */
2724 //=============================================================================
2725
2726 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
2727 {
2728   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
2729   _impl = impl;
2730   if ( _impl )
2731     _impl->SetCallUp( new TCallUp_i(this));
2732 }
2733
2734 //=============================================================================
2735 /*!
2736  *
2737  */
2738 //=============================================================================
2739
2740 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
2741 {
2742   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
2743   return *_impl;
2744 }
2745
2746 //=============================================================================
2747 /*!
2748  * Return mesh editor
2749  */
2750 //=============================================================================
2751
2752 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
2753   throw (SALOME::SALOME_Exception)
2754 {
2755   SMESH::SMESH_MeshEditor_var aMeshEdVar;
2756
2757   SMESH_TRY;
2758   if ( _preMeshInfo )
2759     _preMeshInfo->FullLoadFromFile();
2760
2761   // Create MeshEditor
2762   if ( !_editor )
2763     _editor = new SMESH_MeshEditor_i( this, false );
2764   aMeshEdVar = _editor->_this();
2765
2766   // Update Python script
2767   TPythonDump() << _editor << " = "
2768                 << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshEditor()";
2769
2770   SMESH_CATCH( SMESH::throwCorbaException );
2771
2772   return aMeshEdVar._retn();
2773 }
2774
2775 //=============================================================================
2776 /*!
2777  * Return mesh edition previewer
2778  */
2779 //=============================================================================
2780
2781 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
2782   throw (SALOME::SALOME_Exception)
2783 {
2784   SMESH::SMESH_MeshEditor_var aMeshEdVar;
2785
2786   SMESH_TRY;
2787   if ( _preMeshInfo )
2788     _preMeshInfo->FullLoadFromFile();
2789
2790   if ( !_previewEditor )
2791     _previewEditor = new SMESH_MeshEditor_i( this, true );
2792   aMeshEdVar = _previewEditor->_this();
2793
2794   SMESH_CATCH( SMESH::throwCorbaException );
2795
2796   return aMeshEdVar._retn();
2797 }
2798
2799 //================================================================================
2800 /*!
2801  * \brief Return true if the mesh has been edited since a last total re-compute
2802  *        and those modifications may prevent successful partial re-compute
2803  */
2804 //================================================================================
2805
2806 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard() throw(SALOME::SALOME_Exception)
2807 {
2808   Unexpect aCatch(SALOME_SalomeException);
2809   return _impl->HasModificationsToDiscard();
2810 }
2811
2812 //================================================================================
2813 /*!
2814  * \brief Returns a random unique color
2815  */
2816 //================================================================================
2817
2818 static SALOMEDS::Color getUniqueColor( const std::list<SALOMEDS::Color>& theReservedColors )
2819 {
2820   const int MAX_ATTEMPTS = 100;
2821   int cnt = 0;
2822   double tolerance = 0.5;
2823   SALOMEDS::Color col;
2824
2825   bool ok = false;
2826   while ( !ok ) {
2827     // generate random color
2828     double red    = (double)rand() / RAND_MAX;
2829     double green  = (double)rand() / RAND_MAX;
2830     double blue   = (double)rand() / RAND_MAX;
2831     // check existence in the list of the existing colors
2832     bool matched = false;
2833     std::list<SALOMEDS::Color>::const_iterator it;
2834     for ( it = theReservedColors.begin(); it != theReservedColors.end() && !matched; ++it ) {
2835       SALOMEDS::Color color = *it;
2836       double tol = fabs( color.R - red ) + fabs( color.G - green ) + fabs( color.B  - blue  );
2837       matched = tol < tolerance;
2838     }
2839     if ( (cnt+1) % 20 == 0 ) tolerance = tolerance/2;
2840     ok = ( ++cnt == MAX_ATTEMPTS ) || !matched;
2841     col.R = red;
2842     col.G = green;
2843     col.B = blue;
2844   }
2845   return col;
2846 }
2847
2848 //=============================================================================
2849 /*!
2850  * Sets auto-color mode. If it is on, groups get unique random colors
2851  */
2852 //=============================================================================
2853
2854 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOME_Exception)
2855 {
2856   Unexpect aCatch(SALOME_SalomeException);
2857   _impl->SetAutoColor(theAutoColor);
2858
2859   TPythonDump pyDump; // not to dump group->SetColor() from below code
2860   pyDump << SMESH::SMESH_Mesh_var(_this()) <<".SetAutoColor( "<<theAutoColor<<" )";
2861
2862   std::list<SALOMEDS::Color> aReservedColors;
2863   map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
2864   for ( ; it != _mapGroups.end(); it++ ) {
2865     if ( CORBA::is_nil( it->second )) continue;
2866     SALOMEDS::Color aColor = getUniqueColor( aReservedColors );
2867     it->second->SetColor( aColor );
2868     aReservedColors.push_back( aColor );
2869   }
2870 }
2871
2872 //=============================================================================
2873 /*!
2874  * Returns true if auto-color mode is on
2875  */
2876 //=============================================================================
2877
2878 CORBA::Boolean SMESH_Mesh_i::GetAutoColor() throw(SALOME::SALOME_Exception)
2879 {
2880   Unexpect aCatch(SALOME_SalomeException);
2881   return _impl->GetAutoColor();
2882 }
2883
2884 //=============================================================================
2885 /*!
2886  *  Checks if there are groups with equal names
2887  */
2888 //=============================================================================
2889
2890 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
2891 {
2892   return _impl->HasDuplicatedGroupNamesMED();
2893 }
2894
2895 //================================================================================
2896 /*!
2897  * \brief Care of a file before exporting mesh into it
2898  */
2899 //================================================================================
2900
2901 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
2902 {
2903   SMESH_File aFile( file );
2904   SMESH_Comment msg;
2905   if (aFile.exists()) {
2906     // existing filesystem node
2907     if ( !aFile.isDirectory() ) {
2908       if ( aFile.openForWriting() ) {
2909         if ( overwrite && ! aFile.remove()) {
2910           msg << "Can't replace " << aFile.getName();
2911         }
2912       } else {
2913         msg << "Can't write into " << aFile.getName();
2914       }
2915     } else {
2916       msg << "Location " << aFile.getName() << " is not a file";
2917     }
2918   }
2919   else {
2920     // nonexisting file; check if it can be created
2921     if ( !aFile.openForWriting() ) {
2922       msg << "You cannot create the file "
2923           << aFile.getName()
2924           << ". Check the directory existance and access rights";
2925     }
2926     aFile.remove();
2927   }
2928
2929   if ( !msg.empty() )
2930   {
2931     msg << ".";
2932     THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::BAD_PARAM);
2933   }
2934 }
2935
2936 //================================================================================
2937 /*!
2938  * \brief Prepares a file for export and pass names of mesh groups from study to mesh DS
2939  *  \param file - file name
2940  *  \param overwrite - to erase the file or not
2941  *  \retval string - mesh name
2942  */
2943 //================================================================================
2944
2945 string SMESH_Mesh_i::prepareMeshNameAndGroups(const char*    file,
2946                                               CORBA::Boolean overwrite)
2947 {
2948   // Perform Export
2949   PrepareForWriting(file, overwrite);
2950   string aMeshName = "Mesh";
2951   SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
2952   if ( !aStudy->_is_nil() ) {
2953     SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
2954     if ( !aMeshSO->_is_nil() ) {
2955       CORBA::String_var name = aMeshSO->GetName();
2956       aMeshName = name;
2957       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
2958       if ( !aStudy->GetProperties()->IsLocked() )
2959       {
2960         SALOMEDS::GenericAttribute_wrap anAttr;
2961         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
2962         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
2963         SALOMEDS::AttributeExternalFileDef_wrap aFileName = anAttr;
2964         ASSERT(!aFileName->_is_nil());
2965         aFileName->SetValue(file);
2966         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
2967         SALOMEDS::AttributeFileType_wrap aFileType = anAttr;
2968         ASSERT(!aFileType->_is_nil());
2969         aFileType->SetValue("FICHIERMED");
2970       }
2971     }
2972   }
2973   // Update Python script
2974   // set name of mesh before export
2975   TPythonDump() << _gen_i << ".SetName("
2976                 << SMESH::SMESH_Mesh_var(_this()) << ", '" << aMeshName.c_str() << "')";
2977
2978   // check names of groups
2979   checkGroupNames();
2980
2981   return aMeshName;
2982 }
2983
2984 //================================================================================
2985 /*!
2986  * \brief Export to med file
2987  */
2988 //================================================================================
2989
2990 void SMESH_Mesh_i::ExportToMEDX (const char*        file,
2991                                  CORBA::Boolean     auto_groups,
2992                                  SMESH::MED_VERSION theVersion,
2993                                  CORBA::Boolean     overwrite,
2994                                  CORBA::Boolean     autoDimension)
2995   throw(SALOME::SALOME_Exception)
2996 {
2997   SMESH_TRY;
2998   if ( _preMeshInfo )
2999     _preMeshInfo->FullLoadFromFile();
3000
3001   string aMeshName = prepareMeshNameAndGroups(file, overwrite);
3002   _impl->ExportMED( file, aMeshName.c_str(), auto_groups, theVersion, 0, autoDimension );
3003
3004   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportToMEDX( r'"
3005                 << file << "', " << auto_groups << ", "
3006                 << theVersion << ", " << overwrite << ", "
3007                 << autoDimension << " )";
3008
3009   SMESH_CATCH( SMESH::throwCorbaException );
3010 }
3011
3012 //================================================================================
3013 /*!
3014  * \brief Export a mesh to a med file
3015  */
3016 //================================================================================
3017
3018 void SMESH_Mesh_i::ExportToMED (const char*        file,
3019                                 CORBA::Boolean     auto_groups,
3020                                 SMESH::MED_VERSION theVersion)
3021   throw(SALOME::SALOME_Exception)
3022 {
3023   ExportToMEDX(file,auto_groups,theVersion,true);
3024 }
3025
3026 //================================================================================
3027 /*!
3028  * \brief Export a mesh to a med file
3029  */
3030 //================================================================================
3031
3032 void SMESH_Mesh_i::ExportMED (const char* file,
3033                               CORBA::Boolean auto_groups)
3034   throw(SALOME::SALOME_Exception)
3035 {
3036   ExportToMEDX(file,auto_groups,SMESH::MED_V2_2,true);
3037 }
3038
3039 //================================================================================
3040 /*!
3041  * \brief Export a mesh to a SAUV file
3042  */
3043 //================================================================================
3044
3045 void SMESH_Mesh_i::ExportSAUV (const char* file,
3046                                CORBA::Boolean auto_groups)
3047   throw(SALOME::SALOME_Exception)
3048 {
3049   Unexpect aCatch(SALOME_SalomeException);
3050   if ( _preMeshInfo )
3051     _preMeshInfo->FullLoadFromFile();
3052
3053   string aMeshName = prepareMeshNameAndGroups(file, true);
3054   TPythonDump() << SMESH::SMESH_Mesh_var( _this())
3055                 << ".ExportSAUV( r'" << file << "', " << auto_groups << " )";
3056   _impl->ExportSAUV(file, aMeshName.c_str(), auto_groups);
3057 }
3058
3059
3060 //================================================================================
3061 /*!
3062  * \brief Export a mesh to a DAT file
3063  */
3064 //================================================================================
3065
3066 void SMESH_Mesh_i::ExportDAT (const char *file)
3067   throw(SALOME::SALOME_Exception)
3068 {
3069   Unexpect aCatch(SALOME_SalomeException);
3070   if ( _preMeshInfo )
3071     _preMeshInfo->FullLoadFromFile();
3072
3073   // Update Python script
3074   // check names of groups
3075   checkGroupNames();
3076   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportDAT( r'" << file << "' )";
3077
3078   // Perform Export
3079   PrepareForWriting(file);
3080   _impl->ExportDAT(file);
3081 }
3082
3083 //================================================================================
3084 /*!
3085  * \brief Export a mesh to an UNV file
3086  */
3087 //================================================================================
3088
3089 void SMESH_Mesh_i::ExportUNV (const char *file)
3090   throw(SALOME::SALOME_Exception)
3091 {
3092   Unexpect aCatch(SALOME_SalomeException);
3093   if ( _preMeshInfo )
3094     _preMeshInfo->FullLoadFromFile();
3095
3096   // Update Python script
3097   // check names of groups
3098   checkGroupNames();
3099   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportUNV( r'" << file << "' )";
3100
3101   // Perform Export
3102   PrepareForWriting(file);
3103   _impl->ExportUNV(file);
3104 }
3105
3106 //================================================================================
3107 /*!
3108  * \brief Export a mesh to an STL file
3109  */
3110 //================================================================================
3111
3112 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
3113   throw(SALOME::SALOME_Exception)
3114 {
3115   Unexpect aCatch(SALOME_SalomeException);
3116   if ( _preMeshInfo )
3117     _preMeshInfo->FullLoadFromFile();
3118
3119   // Update Python script
3120   // check names of groups
3121   checkGroupNames();
3122   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3123                 << ".ExportSTL( r'" << file << "', " << isascii << " )";
3124
3125   // Perform Export
3126   PrepareForWriting(file);
3127   _impl->ExportSTL(file, isascii);
3128 }
3129
3130 //================================================================================
3131 /*!
3132  * \brief Export a part of mesh to a med file
3133  */
3134 //================================================================================
3135
3136 void SMESH_Mesh_i::ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart,
3137                                    const char*               file,
3138                                    CORBA::Boolean            auto_groups,
3139                                    SMESH::MED_VERSION        version,
3140                                    CORBA::Boolean            overwrite,
3141                                    CORBA::Boolean            autoDimension,
3142                                    const GEOM::ListOfFields& fields,
3143                                    const char*               geomAssocFields)
3144   throw (SALOME::SALOME_Exception)
3145 {
3146   SMESH_TRY;
3147   if ( _preMeshInfo )
3148     _preMeshInfo->FullLoadFromFile();
3149
3150   // check fields
3151   bool have0dField = false;
3152   if ( fields.length() > 0 )
3153   {
3154     GEOM::GEOM_Object_var shapeToMesh = GetShapeToMesh();
3155     if ( shapeToMesh->_is_nil() )
3156       THROW_SALOME_CORBA_EXCEPTION( "No shape to mesh", SALOME::INTERNAL_ERROR );
3157
3158     for ( size_t i = 0; i < fields.length(); ++i )
3159     {
3160       if ( fields[i]->GetDataType() == GEOM::FDT_String )
3161         THROW_SALOME_CORBA_EXCEPTION
3162           ( "Export of string fields is not supported", SALOME::BAD_PARAM);
3163       GEOM::GEOM_Object_var fieldShape = fields[i]->GetShape();
3164       if ( fieldShape->_is_nil() )
3165         THROW_SALOME_CORBA_EXCEPTION( "Null shape under a field", SALOME::INTERNAL_ERROR );
3166       if ( !fieldShape->IsSame( shapeToMesh ) )
3167         THROW_SALOME_CORBA_EXCEPTION
3168           ( "Field defined not on shape", SALOME::BAD_PARAM);
3169       if ( fields[i]->GetDimension() == 0 )
3170         have0dField = true;
3171     }
3172     if ( geomAssocFields )
3173       for ( int i = 0; geomAssocFields[i]; ++i )
3174         switch ( geomAssocFields[i] ) {
3175         case 'v':case 'e':case 'f':case 's': break;
3176         case 'V':case 'E':case 'F':case 'S': break;
3177         default: THROW_SALOME_CORBA_EXCEPTION
3178             ( "geomAssocFields can include only [vefs] characters", SALOME::BAD_PARAM);
3179         }
3180   }
3181
3182   SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
3183
3184   // write mesh
3185
3186   string aMeshName = "Mesh";
3187   SMESHUtils::Deleter< SMESH_MeshPartDS > tmpDSDeleter(0);
3188   if ( CORBA::is_nil( meshPart ) ||
3189        SMESH::DownCast< SMESH_Mesh_i* >( meshPart ))
3190   {
3191     aMeshName = prepareMeshNameAndGroups(file, overwrite);
3192     _impl->ExportMED( file, aMeshName.c_str(), auto_groups,
3193                       version, 0, autoDimension, /*addODOnVertices=*/have0dField);
3194     meshDS = _impl->GetMeshDS();
3195   }
3196   else
3197   {
3198     if ( _preMeshInfo )
3199       _preMeshInfo->FullLoadFromFile();
3200
3201     PrepareForWriting(file, overwrite);
3202
3203     SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
3204     if ( !aStudy->_is_nil() ) {
3205       SALOMEDS::SObject_wrap SO = _gen_i->ObjectToSObject( aStudy, meshPart );
3206       if ( !SO->_is_nil() ) {
3207         CORBA::String_var name = SO->GetName();
3208         aMeshName = name;
3209       }
3210     }
3211     SMESH_MeshPartDS* partDS = new SMESH_MeshPartDS( meshPart );
3212     _impl->ExportMED( file, aMeshName.c_str(), auto_groups,
3213                       version, partDS, autoDimension, /*addODOnVertices=*/have0dField);
3214     meshDS = tmpDSDeleter._obj = partDS;
3215   }
3216
3217   // write fields
3218
3219   if ( _impl->HasShapeToMesh() )
3220   {
3221     DriverMED_W_Field fieldWriter;
3222     fieldWriter.SetFile( file );
3223     fieldWriter.SetMeshName( aMeshName );
3224     fieldWriter.AddODOnVertices( have0dField );
3225
3226     exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
3227   }
3228
3229   // dump
3230   GEOM::ListOfGBO_var goList = new GEOM::ListOfGBO;
3231   goList->length( fields.length() );
3232   for ( size_t i = 0; i < fields.length(); ++i )
3233   {
3234     GEOM::GEOM_BaseObject_var gbo = GEOM::GEOM_BaseObject::_narrow( fields[i] );
3235     goList[i] = gbo;
3236   }
3237   TPythonDump() << _this() << ".ExportPartToMED( "
3238                 << meshPart << ", r'" << file << "', "
3239                 << auto_groups << ", " << version << ", " << overwrite << ", "
3240                 << autoDimension << ", " << goList
3241                 << ", '" << ( geomAssocFields ? geomAssocFields : "" ) << "'" << " )";
3242
3243   SMESH_CATCH( SMESH::throwCorbaException );
3244 }
3245
3246 //================================================================================
3247 /*!
3248  * Write GEOM fields to MED file
3249  */
3250 //================================================================================
3251
3252 void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field&        fieldWriter,
3253                                     SMESHDS_Mesh*             meshDS,
3254                                     const GEOM::ListOfFields& fields,
3255                                     const char*               geomAssocFields)
3256 {
3257 #define METH "SMESH_Mesh_i::exportMEDFields() "
3258
3259   if (( fields.length() < 1 ) &&
3260       ( !geomAssocFields || !geomAssocFields[0] ))
3261     return;
3262
3263   std::vector< double > dblVals( meshDS->MaxShapeIndex()+1 );
3264   std::vector< int >    intVals( meshDS->MaxShapeIndex()+1 );
3265   std::vector< int >    subIdsByDim[ 4 ];
3266   const double noneDblValue = 0.;
3267   const double noneIntValue = 0;
3268
3269   for ( size_t iF = 0; iF < fields.length(); ++iF )
3270   {
3271     // set field data
3272
3273     int dim = fields[ iF ]->GetDimension();
3274     SMDSAbs_ElementType elemType;
3275     TopAbs_ShapeEnum    shapeType;
3276     switch ( dim ) {
3277     case 0: elemType = SMDSAbs_0DElement; shapeType = TopAbs_VERTEX; break;
3278     case 1: elemType = SMDSAbs_Edge;      shapeType = TopAbs_EDGE;   break;
3279     case 2: elemType = SMDSAbs_Face;      shapeType = TopAbs_FACE;   break;
3280     case 3: elemType = SMDSAbs_Volume;    shapeType = TopAbs_SOLID;  break;
3281     default:
3282       continue; // skip fields on whole shape
3283     }
3284     GEOM::field_data_type dataType = fields[ iF ]->GetDataType();
3285     if ( dataType == GEOM::FDT_String )
3286       continue;
3287     GEOM::ListOfLong_var stepIDs = fields[ iF ]->GetSteps();
3288     if ( stepIDs->length() < 1 )
3289       continue;
3290     GEOM::string_array_var comps = fields[ iF ]->GetComponents();
3291     if ( comps->length() < 1 )
3292       continue;
3293     CORBA::String_var       name = fields[ iF ]->GetName();
3294
3295     if ( !fieldWriter.Set( meshDS,
3296                            name.in(),
3297                            elemType,
3298                            comps->length(),
3299                            /*isIntData=*/false ))//( dataType == GEOM::FDT_Int )))
3300       continue;
3301
3302     for ( size_t iC = 0; iC < comps->length(); ++iC )
3303       fieldWriter.SetCompName( iC, comps[ iC ].in() );
3304
3305     // find sub-shape IDs
3306
3307     std::vector< int >& subIds = subIdsByDim[ dim ];
3308     if ( subIds.empty() )
3309       for ( int id = 1; id <= meshDS->MaxShapeIndex(); ++id )
3310         if ( meshDS->IndexToShape( id ).ShapeType() == shapeType )
3311           subIds.push_back( id );
3312
3313     // write steps
3314
3315     SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
3316     if ( !elemIt )
3317       continue;
3318
3319     for ( size_t iS = 0; iS < stepIDs->length(); ++iS )
3320     {
3321       GEOM::GEOM_FieldStep_var step = fields[ iF ]->GetStep( stepIDs[ iS ]);
3322       if ( step->_is_nil() )
3323         continue;
3324
3325       CORBA::Long stamp = step->GetStamp();
3326       CORBA::Long id    = step->GetID();
3327       fieldWriter.SetDtIt( int( stamp ), int( id ));
3328
3329       // fill dblVals or intVals
3330       switch ( dataType )
3331       {
3332       case GEOM::FDT_Double:
3333       {
3334         GEOM::GEOM_DoubleFieldStep_var dblStep = GEOM::GEOM_DoubleFieldStep::_narrow( step );
3335         if ( dblStep->_is_nil() ) continue;
3336         GEOM::ListOfDouble_var vv = dblStep->GetValues();
3337         if ( vv->length() != subIds.size() )
3338           THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
3339         for ( size_t i = 0; i < vv->length(); ++i )
3340           dblVals[ subIds[ i ]] = vv[ i ];
3341         break;
3342       }
3343       case GEOM::FDT_Int:
3344       {
3345         GEOM::GEOM_IntFieldStep_var intStep = GEOM::GEOM_IntFieldStep::_narrow( step );
3346         if ( intStep->_is_nil() ) continue;
3347         GEOM::ListOfLong_var vv = intStep->GetValues();
3348         if ( vv->length() != subIds.size() )
3349           THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
3350         for ( size_t i = 0; i < vv->length(); ++i )
3351           intVals[ subIds[ i ]] = (int) vv[ i ];
3352         break;
3353       }
3354       case GEOM::FDT_Bool:
3355       {
3356         GEOM::GEOM_BoolFieldStep_var boolStep = GEOM::GEOM_BoolFieldStep::_narrow( step );
3357         if ( boolStep->_is_nil() ) continue;
3358         GEOM::short_array_var vv = boolStep->GetValues();
3359         if ( vv->length() != subIds.size() )
3360           THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
3361         for ( size_t i = 0; i < vv->length(); ++i )
3362           intVals[ subIds[ i ]] = (int) vv[ i ];
3363         break;
3364       }
3365       default: continue;
3366       }
3367
3368       // pass values to fieldWriter
3369       elemIt = fieldWriter.GetOrderedElems();
3370       if ( dataType == GEOM::FDT_Double )
3371         while ( elemIt->more() )
3372         {
3373           const SMDS_MeshElement* e = elemIt->next();
3374           const int shapeID = e->getshapeId();
3375           if ( shapeID < 1 || shapeID >= dblVals.size() )
3376             fieldWriter.AddValue( noneDblValue );
3377           else
3378             fieldWriter.AddValue( dblVals[ shapeID ]);
3379         }
3380       else
3381         while ( elemIt->more() )
3382         {
3383           const SMDS_MeshElement* e = elemIt->next();
3384           const int shapeID = e->getshapeId();
3385           if ( shapeID < 1 || shapeID >= intVals.size() )
3386             fieldWriter.AddValue( (double) noneIntValue );
3387           else
3388             fieldWriter.AddValue( (double) intVals[ shapeID ]);
3389         }
3390
3391       // write a step
3392       fieldWriter.Perform();
3393       SMESH_ComputeErrorPtr res = fieldWriter.GetError();
3394       if ( res && res->IsKO() )
3395       {
3396         if ( res->myComment.empty() )
3397         { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
3398         else
3399         { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
3400       }
3401
3402     } // loop on steps
3403   } // loop on fields
3404
3405   if ( !geomAssocFields || !geomAssocFields[0] )
3406     return;
3407
3408   // write geomAssocFields
3409
3410   std::vector< int > shapeDim( TopAbs_SHAPE + 1 );
3411   shapeDim[ TopAbs_COMPOUND  ] = 3;
3412   shapeDim[ TopAbs_COMPSOLID ] = 3;
3413   shapeDim[ TopAbs_SOLID     ] = 3;
3414   shapeDim[ TopAbs_SHELL     ] = 2;
3415   shapeDim[ TopAbs_FACE      ] = 2;
3416   shapeDim[ TopAbs_WIRE      ] = 1;
3417   shapeDim[ TopAbs_EDGE      ] = 1;
3418   shapeDim[ TopAbs_VERTEX    ] = 0;
3419   shapeDim[ TopAbs_SHAPE     ] = 3;
3420
3421   for ( int iF = 0; geomAssocFields[ iF ]; ++iF )
3422   {
3423     std::vector< std::string > compNames;
3424     switch ( geomAssocFields[ iF ]) {
3425     case 'v': case 'V':
3426       fieldWriter.Set( meshDS, "_vertices_", SMDSAbs_Node, /*nbComps=*/2, /*isInt=*/false );
3427       compNames.push_back( "dim" );
3428       break;
3429     case 'e': case 'E':
3430       fieldWriter.Set( meshDS, "_edges_", SMDSAbs_Edge, /*nbComps=*/1, /*isInt=*/false );
3431       break;
3432     case 'f': case 'F':
3433       fieldWriter.Set( meshDS, "_faces_", SMDSAbs_Face, /*nbComps=*/1, /*isInt=*/false );
3434       break;
3435     case 's': case 'S':
3436       fieldWriter.Set( meshDS, "_solids_", SMDSAbs_Volume, /*nbComps=*/1, /*isInt=*/false );
3437       break;
3438     default: continue;
3439     }
3440     compNames.push_back( "id" );
3441     for ( size_t iC = 0; iC < compNames.size(); ++iC )
3442       fieldWriter.SetCompName( iC, compNames[ iC ].c_str() );
3443
3444     fieldWriter.SetDtIt( -1, -1 );
3445
3446     SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
3447     if ( !elemIt )
3448       continue;
3449
3450     if ( compNames.size() == 2 ) // _vertices_
3451       while ( elemIt->more() )
3452       {
3453         const SMDS_MeshElement* e = elemIt->next();
3454         const int shapeID = e->getshapeId();
3455         if ( shapeID < 1 )
3456         {
3457           fieldWriter.AddValue( (double) -1 );
3458           fieldWriter.AddValue( (double) -1 );
3459         }
3460         else
3461         {
3462           const TopoDS_Shape& S = meshDS->IndexToShape( shapeID );
3463           fieldWriter.AddValue( (double) ( S.IsNull() ? -1 : shapeDim[ S.ShapeType() ]));
3464           fieldWriter.AddValue( (double) shapeID );
3465         }
3466       }
3467     else
3468       while ( elemIt->more() )
3469       {
3470         const SMDS_MeshElement* e = elemIt->next();
3471         const int shapeID = e->getshapeId();
3472         if ( shapeID < 1 )
3473           fieldWriter.AddValue( (double) -1 );
3474         else
3475           fieldWriter.AddValue( (double) shapeID );
3476       }
3477
3478     // write a step
3479     fieldWriter.Perform();
3480     SMESH_ComputeErrorPtr res = fieldWriter.GetError();
3481     if ( res && res->IsKO() )
3482     {
3483       if ( res->myComment.empty() )
3484       { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
3485       else
3486       { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
3487     }
3488
3489   } // loop on geomAssocFields
3490
3491 #undef METH
3492 }
3493
3494 //================================================================================
3495 /*!
3496  * \brief Export a part of mesh to a DAT file
3497  */
3498 //================================================================================
3499
3500 void SMESH_Mesh_i::ExportPartToDAT(::SMESH::SMESH_IDSource_ptr meshPart,
3501                                    const char*                 file)
3502   throw (SALOME::SALOME_Exception)
3503 {
3504   Unexpect aCatch(SALOME_SalomeException);
3505   if ( _preMeshInfo )
3506     _preMeshInfo->FullLoadFromFile();
3507
3508   PrepareForWriting(file);
3509
3510   SMESH_MeshPartDS partDS( meshPart );
3511   _impl->ExportDAT(file,&partDS);
3512
3513   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3514                 << ".ExportPartToDAT( " << meshPart << ", r'" << file << "' )";
3515 }
3516 //================================================================================
3517 /*!
3518  * \brief Export a part of mesh to an UNV file
3519  */
3520 //================================================================================
3521
3522 void SMESH_Mesh_i::ExportPartToUNV(::SMESH::SMESH_IDSource_ptr meshPart,
3523                                    const char*                 file)
3524   throw (SALOME::SALOME_Exception)
3525 {
3526   Unexpect aCatch(SALOME_SalomeException);
3527   if ( _preMeshInfo )
3528     _preMeshInfo->FullLoadFromFile();
3529
3530   PrepareForWriting(file);
3531
3532   SMESH_MeshPartDS partDS( meshPart );
3533   _impl->ExportUNV(file, &partDS);
3534
3535   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3536                 << ".ExportPartToUNV( " << meshPart<< ", r'" << file << "' )";
3537 }
3538 //================================================================================
3539 /*!
3540  * \brief Export a part of mesh to an STL file
3541  */
3542 //================================================================================
3543
3544 void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
3545                                    const char*                 file,
3546                                    ::CORBA::Boolean            isascii)
3547   throw (SALOME::SALOME_Exception)
3548 {
3549   Unexpect aCatch(SALOME_SalomeException);
3550   if ( _preMeshInfo )
3551     _preMeshInfo->FullLoadFromFile();
3552
3553   PrepareForWriting(file);
3554
3555   SMESH_MeshPartDS partDS( meshPart );
3556   _impl->ExportSTL(file, isascii, &partDS);
3557
3558   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( "
3559                 << meshPart<< ", r'" << file << "', " << isascii << ")";
3560 }
3561
3562 //================================================================================
3563 /*!
3564  * \brief Export a part of mesh to an STL file
3565  */
3566 //================================================================================
3567
3568 void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart,
3569                               const char*                 file,
3570                               CORBA::Boolean              overwrite)
3571   throw (SALOME::SALOME_Exception)
3572 {
3573 #ifdef WITH_CGNS
3574   Unexpect aCatch(SALOME_SalomeException);
3575   if ( _preMeshInfo )
3576     _preMeshInfo->FullLoadFromFile();
3577
3578   PrepareForWriting(file,overwrite);
3579
3580   SMESH_MeshPartDS partDS( meshPart );
3581   _impl->ExportCGNS(file, &partDS);
3582
3583   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportCGNS( "
3584                 << meshPart<< ", r'" << file << "', " << overwrite << ")";
3585 #else
3586   THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
3587 #endif
3588 }
3589
3590 //================================================================================
3591 /*!
3592  * \brief Export a part of mesh to a GMF file
3593  */
3594 //================================================================================
3595
3596 void SMESH_Mesh_i::ExportGMF(::SMESH::SMESH_IDSource_ptr meshPart,
3597                              const char*                 file,
3598                              bool                        withRequiredGroups)
3599   throw (SALOME::SALOME_Exception)
3600 {
3601   Unexpect aCatch(SALOME_SalomeException);
3602   if ( _preMeshInfo )
3603     _preMeshInfo->FullLoadFromFile();
3604
3605   PrepareForWriting(file,/*overwrite=*/true);
3606
3607   SMESH_MeshPartDS partDS( meshPart );
3608   _impl->ExportGMF(file, &partDS, withRequiredGroups);
3609
3610   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportGMF( "
3611                 << meshPart<< ", r'"
3612                 << file << "', "
3613                 << withRequiredGroups << ")";
3614 }
3615
3616 //=============================================================================
3617 /*!
3618  * Return computation progress [0.,1]
3619  */
3620 //=============================================================================
3621
3622 CORBA::Double SMESH_Mesh_i::GetComputeProgress()
3623 {
3624   SMESH_TRY;
3625
3626   return _impl->GetComputeProgress();
3627
3628   SMESH_CATCH( SMESH::doNothing );
3629   return 0.;
3630 }
3631
3632 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
3633 {
3634   Unexpect aCatch(SALOME_SalomeException);
3635   if ( _preMeshInfo )
3636     return _preMeshInfo->NbNodes();
3637
3638   return _impl->NbNodes();
3639 }
3640
3641 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
3642 {
3643   Unexpect aCatch(SALOME_SalomeException);
3644   if ( _preMeshInfo )
3645     return _preMeshInfo->NbElements();
3646
3647   return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes() + NbBalls();
3648 }
3649
3650 CORBA::Long SMESH_Mesh_i::Nb0DElements()throw (SALOME::SALOME_Exception)
3651 {
3652   Unexpect aCatch(SALOME_SalomeException);
3653   if ( _preMeshInfo )
3654     return _preMeshInfo->Nb0DElements();
3655
3656   return _impl->Nb0DElements();
3657 }
3658
3659 CORBA::Long SMESH_Mesh_i::NbBalls() throw (SALOME::SALOME_Exception)
3660 {
3661   Unexpect aCatch(SALOME_SalomeException);
3662   if ( _preMeshInfo )
3663     return _preMeshInfo->NbBalls();
3664
3665   return _impl->NbBalls();
3666 }
3667
3668 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
3669 {
3670   Unexpect aCatch(SALOME_SalomeException);
3671   if ( _preMeshInfo )
3672     return _preMeshInfo->NbEdges();
3673
3674   return _impl->NbEdges();
3675 }
3676
3677 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
3678   throw(SALOME::SALOME_Exception)
3679 {
3680   Unexpect aCatch(SALOME_SalomeException);
3681   if ( _preMeshInfo )
3682     return _preMeshInfo->NbEdges( (SMDSAbs_ElementOrder) order );
3683
3684   return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
3685 }
3686
3687 //=============================================================================
3688
3689 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
3690 {
3691   Unexpect aCatch(SALOME_SalomeException);
3692   if ( _preMeshInfo )
3693     return _preMeshInfo->NbFaces();
3694
3695   return _impl->NbFaces();
3696 }
3697
3698 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
3699 {
3700   Unexpect aCatch(SALOME_SalomeException);
3701   if ( _preMeshInfo )
3702     return _preMeshInfo->NbTriangles();
3703
3704   return _impl->NbTriangles();
3705 }
3706
3707 CORBA::Long SMESH_Mesh_i::NbBiQuadTriangles()throw(SALOME::SALOME_Exception)
3708 {
3709   Unexpect aCatch(SALOME_SalomeException);
3710   if ( _preMeshInfo )
3711     return _preMeshInfo->NbBiQuadTriangles();
3712
3713   return _impl->NbBiQuadTriangles();
3714 }
3715
3716 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
3717 {
3718   Unexpect aCatch(SALOME_SalomeException);
3719   if ( _preMeshInfo )
3720     return _preMeshInfo->NbQuadrangles();
3721
3722   return _impl->NbQuadrangles();
3723 }
3724
3725 CORBA::Long SMESH_Mesh_i::NbBiQuadQuadrangles()throw(SALOME::SALOME_Exception)
3726 {
3727   Unexpect aCatch(SALOME_SalomeException);
3728   if ( _preMeshInfo )
3729     return _preMeshInfo->NbBiQuadQuadrangles();
3730
3731   return _impl->NbBiQuadQuadrangles();
3732 }
3733
3734 CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
3735 {
3736   Unexpect aCatch(SALOME_SalomeException);
3737   if ( _preMeshInfo )
3738     return _preMeshInfo->NbPolygons();
3739
3740   return _impl->NbPolygons();
3741 }
3742
3743 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
3744   throw(SALOME::SALOME_Exception)
3745 {
3746   Unexpect aCatch(SALOME_SalomeException);
3747   if ( _preMeshInfo )
3748     return _preMeshInfo->NbFaces( (SMDSAbs_ElementOrder) order );
3749
3750   return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
3751 }
3752
3753 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
3754   throw(SALOME::SALOME_Exception)
3755 {
3756   Unexpect aCatch(SALOME_SalomeException);
3757   if ( _preMeshInfo )
3758     return _preMeshInfo->NbTriangles( (SMDSAbs_ElementOrder) order );
3759
3760   return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
3761 }
3762
3763 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
3764   throw(SALOME::SALOME_Exception)
3765 {
3766   Unexpect aCatch(SALOME_SalomeException);
3767   if ( _preMeshInfo )
3768     return _preMeshInfo->NbQuadrangles( (SMDSAbs_ElementOrder) order );
3769
3770   return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
3771 }
3772
3773 //=============================================================================
3774
3775 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
3776 {
3777   Unexpect aCatch(SALOME_SalomeException);
3778   if ( _preMeshInfo )
3779     return _preMeshInfo->NbVolumes();
3780
3781   return _impl->NbVolumes();
3782 }
3783
3784 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
3785 {
3786   Unexpect aCatch(SALOME_SalomeException);
3787   if ( _preMeshInfo )
3788     return _preMeshInfo->NbTetras();
3789
3790   return _impl->NbTetras();
3791 }
3792
3793 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
3794 {
3795   Unexpect aCatch(SALOME_SalomeException);
3796   if ( _preMeshInfo )
3797     return _preMeshInfo->NbHexas();
3798
3799   return _impl->NbHexas();
3800 }
3801
3802 CORBA::Long SMESH_Mesh_i::NbTriQuadraticHexas()throw(SALOME::SALOME_Exception)
3803 {
3804   Unexpect aCatch(SALOME_SalomeException);
3805   if ( _preMeshInfo )
3806     return _preMeshInfo->NbTriQuadHexas();
3807
3808   return _impl->NbTriQuadraticHexas();
3809 }
3810
3811 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
3812 {
3813   Unexpect aCatch(SALOME_SalomeException);
3814   if ( _preMeshInfo )
3815     return _preMeshInfo->NbPyramids();
3816
3817   return _impl->NbPyramids();
3818 }
3819
3820 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
3821 {
3822   Unexpect aCatch(SALOME_SalomeException);
3823   if ( _preMeshInfo )
3824     return _preMeshInfo->NbPrisms();
3825
3826   return _impl->NbPrisms();
3827 }
3828
3829 CORBA::Long SMESH_Mesh_i::NbHexagonalPrisms()throw(SALOME::SALOME_Exception)
3830 {
3831   Unexpect aCatch(SALOME_SalomeException);
3832   if ( _preMeshInfo )
3833     return _preMeshInfo->NbHexPrisms();
3834
3835   return _impl->NbHexagonalPrisms();
3836 }
3837
3838 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
3839 {
3840   Unexpect aCatch(SALOME_SalomeException);
3841   if ( _preMeshInfo )
3842     return _preMeshInfo->NbPolyhedrons();
3843
3844   return _impl->NbPolyhedrons();
3845 }
3846
3847 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
3848   throw(SALOME::SALOME_Exception)
3849 {
3850   Unexpect aCatch(SALOME_SalomeException);
3851   if ( _preMeshInfo )
3852     return _preMeshInfo->NbVolumes( (SMDSAbs_ElementOrder) order );
3853
3854   return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
3855 }
3856
3857 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
3858   throw(SALOME::SALOME_Exception)
3859 {
3860   Unexpect aCatch(SALOME_SalomeException);
3861   if ( _preMeshInfo )
3862     return _preMeshInfo->NbTetras( (SMDSAbs_ElementOrder) order);
3863
3864   return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
3865 }
3866
3867 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
3868   throw(SALOME::SALOME_Exception)
3869 {
3870   Unexpect aCatch(SALOME_SalomeException);
3871   if ( _preMeshInfo )
3872     return _preMeshInfo->NbHexas( (SMDSAbs_ElementOrder) order);
3873
3874   return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
3875 }
3876
3877 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
3878   throw(SALOME::SALOME_Exception)
3879 {
3880   Unexpect aCatch(SALOME_SalomeException);
3881   if ( _preMeshInfo )
3882     return _preMeshInfo->NbPyramids( (SMDSAbs_ElementOrder) order);
3883
3884   return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
3885 }
3886
3887 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
3888   throw(SALOME::SALOME_Exception)
3889 {
3890   Unexpect aCatch(SALOME_SalomeException);
3891   if ( _preMeshInfo )
3892     return _preMeshInfo->NbPrisms( (SMDSAbs_ElementOrder) order);
3893
3894   return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
3895 }
3896
3897 //=============================================================================
3898 /*!
3899  * Returns nb of published sub-meshes
3900  */
3901 //=============================================================================
3902
3903 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
3904 {
3905   Unexpect aCatch(SALOME_SalomeException);
3906   return _mapSubMesh_i.size();
3907 }
3908
3909 //=============================================================================
3910 /*!
3911  * Dumps mesh into a string
3912  */
3913 //=============================================================================
3914
3915 char* SMESH_Mesh_i::Dump()
3916 {
3917   ostringstream os;
3918   _impl->Dump( os );
3919   return CORBA::string_dup( os.str().c_str() );
3920 }
3921
3922 //=============================================================================
3923 /*!
3924  * Method of SMESH_IDSource interface
3925  */
3926 //=============================================================================
3927
3928 SMESH::long_array* SMESH_Mesh_i::GetIDs()
3929 {
3930   return GetElementsId();
3931 }
3932
3933 //=============================================================================
3934 /*!
3935  * Returns ids of all elements
3936  */
3937 //=============================================================================
3938
3939 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
3940   throw (SALOME::SALOME_Exception)
3941 {
3942   Unexpect aCatch(SALOME_SalomeException);
3943   if ( _preMeshInfo )
3944     _preMeshInfo->FullLoadFromFile();
3945
3946   SMESH::long_array_var aResult = new SMESH::long_array();
3947   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3948
3949   if ( aSMESHDS_Mesh == NULL )
3950     return aResult._retn();
3951
3952   long nbElements = NbElements();
3953   aResult->length( nbElements );
3954   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
3955   for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
3956     aResult[i] = anIt->next()->GetID();
3957
3958   return aResult._retn();
3959 }
3960
3961
3962 //=============================================================================
3963 /*!
3964  * Returns ids of all elements of given type
3965  */
3966 //=============================================================================
3967
3968 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
3969     throw (SALOME::SALOME_Exception)
3970 {
3971   Unexpect aCatch(SALOME_SalomeException);
3972   if ( _preMeshInfo )
3973     _preMeshInfo->FullLoadFromFile();
3974
3975   SMESH::long_array_var aResult = new SMESH::long_array();
3976   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3977
3978   if ( aSMESHDS_Mesh == NULL )
3979     return aResult._retn();
3980
3981   long nbElements = NbElements();
3982
3983   // No sense in returning ids of elements along with ids of nodes:
3984   // when theElemType == SMESH::ALL, return node ids only if
3985   // there are no elements
3986   if ( theElemType == SMESH::NODE || (theElemType == SMESH::ALL && nbElements == 0) )
3987     return GetNodesId();
3988
3989   aResult->length( nbElements );
3990
3991   int i = 0;
3992
3993   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator( (SMDSAbs_ElementType)theElemType );
3994   while ( i < nbElements && anIt->more() )
3995     aResult[i++] = anIt->next()->GetID();
3996
3997   aResult->length( i );
3998
3999   return aResult._retn();
4000 }
4001
4002 //=============================================================================
4003 /*!
4004  * Returns ids of all nodes
4005  */
4006 //=============================================================================
4007
4008 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
4009   throw (SALOME::SALOME_Exception)
4010 {
4011   Unexpect aCatch(SALOME_SalomeException);
4012   if ( _preMeshInfo )
4013     _preMeshInfo->FullLoadFromFile();
4014
4015   SMESH::long_array_var aResult = new SMESH::long_array();
4016   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4017
4018   if ( aSMESHDS_Mesh == NULL )
4019     return aResult._retn();
4020
4021   long nbNodes = NbNodes();
4022   aResult->length( nbNodes );
4023   SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator(/*idInceasingOrder=*/true);
4024   for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
4025     aResult[i] = anIt->next()->GetID();
4026
4027   return aResult._retn();
4028 }
4029
4030 //=============================================================================
4031 /*!
4032  *
4033  */
4034 //=============================================================================
4035
4036 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
4037   throw (SALOME::SALOME_Exception)
4038 {
4039   SMESH::ElementType type;
4040   SMESH_TRY;
4041
4042   if ( _preMeshInfo )
4043     _preMeshInfo->FullLoadFromFile();
4044
4045   type = ( SMESH::ElementType ) _impl->GetElementType( id, iselem );
4046
4047   SMESH_CATCH( SMESH::throwCorbaException );
4048
4049   return type;
4050 }
4051
4052 //=============================================================================
4053 /*!
4054  *
4055  */
4056 //=============================================================================
4057
4058 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id )
4059   throw (SALOME::SALOME_Exception)
4060 {
4061   if ( _preMeshInfo )
4062     _preMeshInfo->FullLoadFromFile();
4063
4064   const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
4065   if ( !e )
4066     THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
4067
4068   return ( SMESH::EntityType ) e->GetEntityType();
4069 }
4070
4071 //=============================================================================
4072 /*!
4073  *
4074  */
4075 //=============================================================================
4076
4077 SMESH::GeometryType SMESH_Mesh_i::GetElementShape( const CORBA::Long id )
4078   throw (SALOME::SALOME_Exception)
4079 {
4080   if ( _preMeshInfo )
4081     _preMeshInfo->FullLoadFromFile();
4082
4083   const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
4084   if ( !e )
4085     THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
4086
4087   return ( SMESH::GeometryType ) e->GetGeomType();
4088 }
4089
4090 //=============================================================================
4091 /*!
4092  * Returns ID of elements for given submesh
4093  */
4094 //=============================================================================
4095 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
4096      throw (SALOME::SALOME_Exception)
4097 {
4098   SMESH::long_array_var aResult = new SMESH::long_array();
4099
4100   SMESH_TRY;
4101   if ( _preMeshInfo )
4102     _preMeshInfo->FullLoadFromFile();
4103
4104   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4105   if(!SM) return aResult._retn();
4106
4107   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
4108   if(!SDSM) return aResult._retn();
4109
4110   aResult->length(SDSM->NbElements());
4111
4112   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
4113   int i = 0;
4114   while ( eIt->more() ) {
4115     aResult[i++] = eIt->next()->GetID();
4116   }
4117
4118   SMESH_CATCH( SMESH::throwCorbaException );
4119
4120   return aResult._retn();
4121 }
4122
4123 //=============================================================================
4124 /*!
4125  * Returns ID of nodes for given submesh
4126  * If param all==true - returns all nodes, else -
4127  * returns only nodes on shapes.
4128  */
4129 //=============================================================================
4130
4131 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
4132                                                    CORBA::Boolean    all)
4133   throw (SALOME::SALOME_Exception)
4134 {
4135   SMESH::long_array_var aResult = new SMESH::long_array();
4136
4137   SMESH_TRY;
4138   if ( _preMeshInfo )
4139     _preMeshInfo->FullLoadFromFile();
4140
4141   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4142   if(!SM) return aResult._retn();
4143
4144   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
4145   if(!SDSM) return aResult._retn();
4146
4147   set<int> theElems;
4148   if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
4149     SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
4150     while ( nIt->more() ) {
4151       const SMDS_MeshNode* elem = nIt->next();
4152       theElems.insert( elem->GetID() );
4153     }
4154   }
4155   else { // all nodes of submesh elements
4156     SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
4157     while ( eIt->more() ) {
4158       const SMDS_MeshElement* anElem = eIt->next();
4159       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
4160       while ( nIt->more() ) {
4161         const SMDS_MeshElement* elem = nIt->next();
4162         theElems.insert( elem->GetID() );
4163       }
4164     }
4165   }
4166
4167   aResult->length(theElems.size());
4168   set<int>::iterator itElem;
4169   int i = 0;
4170   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
4171     aResult[i++] = *itElem;
4172
4173   SMESH_CATCH( SMESH::throwCorbaException );
4174
4175   return aResult._retn();
4176 }
4177   
4178 //=============================================================================
4179 /*!
4180  * Returns type of elements for given submesh
4181  */
4182 //=============================================================================
4183
4184 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
4185   throw (SALOME::SALOME_Exception)
4186 {
4187   SMESH::ElementType type;
4188
4189   SMESH_TRY;
4190   if ( _preMeshInfo )
4191     _preMeshInfo->FullLoadFromFile();
4192
4193   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4194   if(!SM) return SMESH::ALL;
4195
4196   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
4197   if(!SDSM) return SMESH::ALL;
4198
4199   if(SDSM->NbElements()==0)
4200     return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
4201
4202   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
4203   const SMDS_MeshElement* anElem = eIt->next();
4204
4205   type = ( SMESH::ElementType ) anElem->GetType();
4206
4207   SMESH_CATCH( SMESH::throwCorbaException );
4208
4209   return type; 
4210 }
4211   
4212
4213 //=============================================================================
4214 /*!
4215  * Returns pointer to _impl as an integer value. Is called from constructor of SMESH_Client
4216  */
4217 //=============================================================================
4218
4219 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
4220 {
4221   if ( _preMeshInfo )
4222     _preMeshInfo->FullLoadFromFile();
4223
4224   CORBA::LongLong pointeur = CORBA::LongLong(_impl);
4225   if ( MYDEBUG )
4226     MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
4227   return pointeur;
4228 }
4229
4230
4231 //=============================================================================
4232 /*!
4233  * Get XYZ coordinates of node as list of double
4234  * If there is not node for given ID - returns empty list
4235  */
4236 //=============================================================================
4237
4238 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
4239 {
4240   if ( _preMeshInfo )
4241     _preMeshInfo->FullLoadFromFile();
4242
4243   SMESH::double_array_var aResult = new SMESH::double_array();
4244   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4245   if ( aSMESHDS_Mesh == NULL )
4246     return aResult._retn();
4247
4248   // find node
4249   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
4250   if(!aNode)
4251     return aResult._retn();
4252
4253   // add coordinates
4254   aResult->length(3);
4255   aResult[0] = aNode->X();
4256   aResult[1] = aNode->Y();
4257   aResult[2] = aNode->Z();
4258   return aResult._retn();
4259 }
4260
4261
4262 //=============================================================================
4263 /*!
4264  * For given node returns list of IDs of inverse elements
4265  * If there is not node for given ID - returns empty list
4266  */
4267 //=============================================================================
4268
4269 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
4270 {
4271   if ( _preMeshInfo )
4272     _preMeshInfo->FullLoadFromFile();
4273
4274   SMESH::long_array_var aResult = new SMESH::long_array();
4275   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4276   if ( aSMESHDS_Mesh == NULL )
4277     return aResult._retn();
4278
4279   // find node
4280   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
4281   if(!aNode)
4282     return aResult._retn();
4283
4284   // find inverse elements
4285   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
4286   aResult->length( aNode->NbInverseElements() );  
4287   for( int i = 0; eIt->more(); ++i )
4288   {
4289     const SMDS_MeshElement* elem = eIt->next();
4290     aResult[ i ] = elem->GetID();
4291   }
4292   return aResult._retn();
4293 }
4294
4295 //=============================================================================
4296 /*!
4297  * \brief Return position of a node on shape
4298  */
4299 //=============================================================================
4300
4301 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
4302 {
4303   if ( _preMeshInfo )
4304     _preMeshInfo->FullLoadFromFile();
4305
4306   SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
4307   aNodePosition->shapeID = 0;
4308   aNodePosition->shapeType = GEOM::SHAPE;
4309
4310   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
4311   if ( !mesh ) return aNodePosition;
4312
4313   if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
4314   {
4315     if ( SMDS_PositionPtr pos = aNode->GetPosition() )
4316     {
4317       aNodePosition->shapeID = aNode->getshapeId();
4318       switch ( pos->GetTypeOfPosition() ) {
4319       case SMDS_TOP_EDGE:
4320         aNodePosition->shapeType = GEOM::EDGE;
4321         aNodePosition->params.length(1);
4322         aNodePosition->params[0] =
4323           static_cast<SMDS_EdgePosition*>( pos )->GetUParameter();
4324         break;
4325       case SMDS_TOP_FACE:
4326         aNodePosition->shapeType = GEOM::FACE;
4327         aNodePosition->params.length(2);
4328         aNodePosition->params[0] =
4329           static_cast<SMDS_FacePosition*>( pos )->GetUParameter();
4330         aNodePosition->params[1] =
4331           static_cast<SMDS_FacePosition*>( pos )->GetVParameter();
4332         break;
4333       case SMDS_TOP_VERTEX:
4334         aNodePosition->shapeType = GEOM::VERTEX;
4335         break;
4336       case SMDS_TOP_3DSPACE:
4337         if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
4338           aNodePosition->shapeType = GEOM::SOLID;
4339         else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
4340           aNodePosition->shapeType = GEOM::SHELL;
4341         break;
4342       default:;
4343       }
4344     }
4345   }
4346   return aNodePosition;
4347 }
4348
4349 //=============================================================================
4350 /*!
4351  * \brief Return position of an element on shape
4352  */
4353 //=============================================================================
4354
4355 SMESH::ElementPosition SMESH_Mesh_i::GetElementPosition(CORBA::Long ElemID)
4356 {
4357   if ( _preMeshInfo )
4358     _preMeshInfo->FullLoadFromFile();
4359
4360   SMESH::ElementPosition anElementPosition;
4361   anElementPosition.shapeID = 0;
4362   anElementPosition.shapeType = GEOM::SHAPE;
4363
4364   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
4365   if ( !mesh ) return anElementPosition;
4366
4367   if ( const SMDS_MeshElement* anElem = mesh->FindElement( ElemID ) )
4368   {
4369     anElementPosition.shapeID = anElem->getshapeId();
4370     const TopoDS_Shape& aSp = mesh->IndexToShape( anElem->getshapeId() );
4371     if ( !aSp.IsNull() ) {
4372       switch ( aSp.ShapeType() ) {
4373       case TopAbs_EDGE:
4374         anElementPosition.shapeType = GEOM::EDGE;
4375         break;
4376       case TopAbs_FACE:
4377         anElementPosition.shapeType = GEOM::FACE;
4378         break;
4379       case TopAbs_VERTEX:
4380         anElementPosition.shapeType = GEOM::VERTEX;
4381         break;
4382       case TopAbs_SOLID:
4383         anElementPosition.shapeType = GEOM::SOLID;
4384         break;
4385       case TopAbs_SHELL:
4386         anElementPosition.shapeType = GEOM::SHELL;
4387         break;
4388       default:;
4389       }
4390     }
4391   }
4392   return anElementPosition;
4393 }
4394
4395 //=============================================================================
4396 /*!
4397  * If given element is node returns IDs of shape from position
4398  * If there is not node for given ID - returns -1
4399  */
4400 //=============================================================================
4401
4402 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
4403 {
4404   if ( _preMeshInfo )
4405     _preMeshInfo->FullLoadFromFile();
4406
4407   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4408   if ( aSMESHDS_Mesh == NULL )
4409     return -1;
4410
4411   // try to find node
4412   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
4413   if(aNode) {
4414     return aNode->getshapeId();
4415   }
4416
4417   return -1;
4418 }
4419
4420
4421 //=============================================================================
4422 /*!
4423  * For given element returns ID of result shape after 
4424  * ::FindShape() from SMESH_MeshEditor
4425  * If there is not element for given ID - returns -1
4426  */
4427 //=============================================================================
4428
4429 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
4430 {
4431   if ( _preMeshInfo )
4432     _preMeshInfo->FullLoadFromFile();
4433
4434   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4435   if ( aSMESHDS_Mesh == NULL )
4436     return -1;
4437
4438   // try to find element
4439   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4440   if(!elem)
4441     return -1;
4442
4443   ::SMESH_MeshEditor aMeshEditor(_impl);
4444   int index = aMeshEditor.FindShape( elem );
4445   if(index>0)
4446     return index;
4447
4448   return -1;
4449 }
4450
4451
4452 //=============================================================================
4453 /*!
4454  * Returns number of nodes for given element
4455  * If there is not element for given ID - returns -1
4456  */
4457 //=============================================================================
4458
4459 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
4460 {
4461   if ( _preMeshInfo )
4462     _preMeshInfo->FullLoadFromFile();
4463
4464   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4465   if ( aSMESHDS_Mesh == NULL ) return -1;
4466   // try to find element
4467   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4468   if(!elem) return -1;
4469   return elem->NbNodes();
4470 }
4471
4472
4473 //=============================================================================
4474 /*!
4475  * Returns ID of node by given index for given element
4476  * If there is not element for given ID - returns -1
4477  * If there is not node for given index - returns -2
4478  */
4479 //=============================================================================
4480
4481 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
4482 {
4483   if ( _preMeshInfo )
4484     _preMeshInfo->FullLoadFromFile();
4485
4486   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4487   if ( aSMESHDS_Mesh == NULL ) return -1;
4488   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4489   if(!elem) return -1;
4490   if( index>=elem->NbNodes() || index<0 ) return -1;
4491   return elem->GetNode(index)->GetID();
4492 }
4493
4494 //=============================================================================
4495 /*!
4496  * Returns IDs of nodes of given element
4497  */
4498 //=============================================================================
4499
4500 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
4501 {
4502   if ( _preMeshInfo )
4503     _preMeshInfo->FullLoadFromFile();
4504
4505   SMESH::long_array_var aResult = new SMESH::long_array();
4506   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
4507   {
4508     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id) )
4509     {
4510       aResult->length( elem->NbNodes() );
4511       for ( int i = 0; i < elem->NbNodes(); ++i )
4512         aResult[ i ] = elem->GetNode( i )->GetID();
4513     }
4514   }
4515   return aResult._retn();
4516 }
4517
4518 //=============================================================================
4519 /*!
4520  * Returns true if given node is medium node
4521  * in given quadratic element
4522  */
4523 //=============================================================================
4524
4525 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
4526 {
4527   if ( _preMeshInfo )
4528     _preMeshInfo->FullLoadFromFile();
4529
4530   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4531   if ( aSMESHDS_Mesh == NULL ) return false;
4532   // try to find node
4533   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
4534   if(!aNode) return false;
4535   // try to find element
4536   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(ide);
4537   if(!elem) return false;
4538
4539   return elem->IsMediumNode(aNode);
4540 }
4541
4542
4543 //=============================================================================
4544 /*!
4545  * Returns true if given node is medium node
4546  * in one of quadratic elements
4547  */
4548 //=============================================================================
4549
4550 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
4551                                                    SMESH::ElementType theElemType)
4552 {
4553   if ( _preMeshInfo )
4554     _preMeshInfo->FullLoadFromFile();
4555
4556   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4557   if ( aSMESHDS_Mesh == NULL ) return false;
4558
4559   // try to find node
4560   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
4561   if(!aNode) return false;
4562
4563   SMESH_MesherHelper aHelper( *(_impl) );
4564
4565   SMDSAbs_ElementType aType;
4566   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
4567   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
4568   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
4569   else aType = SMDSAbs_All;
4570
4571   return aHelper.IsMedium(aNode,aType);
4572 }
4573
4574
4575 //=============================================================================
4576 /*!
4577  * Returns number of edges for given element
4578  */
4579 //=============================================================================
4580
4581 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
4582 {
4583   if ( _preMeshInfo )
4584     _preMeshInfo->FullLoadFromFile();
4585
4586   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4587   if ( aSMESHDS_Mesh == NULL ) return -1;
4588   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4589   if(!elem) return -1;
4590   return elem->NbEdges();
4591 }
4592
4593
4594 //=============================================================================
4595 /*!
4596  * Returns number of faces for given element
4597  */
4598 //=============================================================================
4599
4600 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
4601 {
4602   if ( _preMeshInfo )
4603     _preMeshInfo->FullLoadFromFile();
4604
4605   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4606   if ( aSMESHDS_Mesh == NULL ) return -1;
4607   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4608   if(!elem) return -1;
4609   return elem->NbFaces();
4610 }
4611
4612 //=======================================================================
4613 //function : GetElemFaceNodes
4614 //purpose  : Returns nodes of given face (counted from zero) for given element.
4615 //=======================================================================
4616
4617 SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long  elemId,
4618                                                   CORBA::Short faceIndex)
4619 {
4620   if ( _preMeshInfo )
4621     _preMeshInfo->FullLoadFromFile();
4622
4623   SMESH::long_array_var aResult = new SMESH::long_array();
4624   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
4625   {
4626     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(elemId) )
4627     {
4628       SMDS_VolumeTool vtool( elem );
4629       if ( faceIndex < vtool.NbFaces() )
4630       {
4631         aResult->length( vtool.NbFaceNodes( faceIndex ));
4632         const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
4633         for ( int i = 0; i < aResult->length(); ++i )
4634           aResult[ i ] = nn[ i ]->GetID();
4635       }
4636     }
4637   }
4638   return aResult._retn();
4639 }
4640
4641 //=======================================================================
4642 //function : GetElemFaceNodes
4643 //purpose  : Returns three components of normal of given mesh face.
4644 //=======================================================================
4645
4646 SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long    elemId,
4647                                                  CORBA::Boolean normalized)
4648 {
4649   if ( _preMeshInfo )
4650     _preMeshInfo->FullLoadFromFile();
4651
4652   SMESH::double_array_var aResult = new SMESH::double_array();
4653
4654   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
4655   {
4656     gp_XYZ normal;
4657     if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, normalized ))
4658     {
4659       aResult->length( 3 );
4660       aResult[ 0 ] = normal.X();
4661       aResult[ 1 ] = normal.Y();
4662       aResult[ 2 ] = normal.Z();
4663     }
4664   }
4665   return aResult._retn();
4666 }
4667
4668 //=======================================================================
4669 //function : FindElementByNodes
4670 //purpose  : Returns an element based on all given nodes.
4671 //=======================================================================
4672
4673 CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
4674 {
4675   if ( _preMeshInfo )
4676     _preMeshInfo->FullLoadFromFile();
4677
4678   CORBA::Long elemID(0);
4679   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
4680   {
4681     vector< const SMDS_MeshNode * > nn( nodes.length() );
4682     for ( int i = 0; i < nodes.length(); ++i )
4683       if ( !( nn[i] = mesh->FindNode( nodes[i] )))
4684         return elemID;
4685
4686     const SMDS_MeshElement* elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/false );
4687     if ( !elem && ( _impl->NbEdges  ( ORDER_QUADRATIC ) ||
4688                     _impl->NbFaces  ( ORDER_QUADRATIC ) ||
4689                     _impl->NbVolumes( ORDER_QUADRATIC )))
4690       elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
4691
4692     if ( elem ) elemID = CORBA::Long( elem->GetID() );
4693   }
4694   return elemID;
4695 }
4696
4697 //=============================================================================
4698 /*!
4699  * Returns true if given element is polygon
4700  */
4701 //=============================================================================
4702
4703 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
4704 {
4705   if ( _preMeshInfo )
4706     _preMeshInfo->FullLoadFromFile();
4707
4708   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4709   if ( aSMESHDS_Mesh == NULL ) return false;
4710   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4711   if(!elem) return false;
4712   return elem->IsPoly();
4713 }
4714
4715
4716 //=============================================================================
4717 /*!
4718  * Returns true if given element is quadratic
4719  */
4720 //=============================================================================
4721
4722 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
4723 {
4724   if ( _preMeshInfo )
4725     _preMeshInfo->FullLoadFromFile();
4726
4727   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4728   if ( aSMESHDS_Mesh == NULL ) return false;
4729   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4730   if(!elem) return false;
4731   return elem->IsQuadratic();
4732 }
4733
4734 //=============================================================================
4735 /*!
4736  * Returns diameter of ball discrete element or zero in case of an invalid \a id
4737  */
4738 //=============================================================================
4739
4740 CORBA::Double SMESH_Mesh_i::GetBallDiameter(CORBA::Long id)
4741 {
4742   if ( _preMeshInfo )
4743     _preMeshInfo->FullLoadFromFile();
4744
4745   if ( const SMDS_BallElement* ball =
4746        dynamic_cast<const SMDS_BallElement*>( _impl->GetMeshDS()->FindElement( id )))
4747     return ball->GetDiameter();
4748
4749   return 0;
4750 }
4751
4752 //=============================================================================
4753 /*!
4754  * Returns bary center for given element
4755  */
4756 //=============================================================================
4757
4758 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
4759 {
4760   if ( _preMeshInfo )
4761     _preMeshInfo->FullLoadFromFile();
4762
4763   SMESH::double_array_var aResult = new SMESH::double_array();
4764   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4765   if ( aSMESHDS_Mesh == NULL )
4766     return aResult._retn();
4767
4768   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4769   if(!elem)
4770     return aResult._retn();
4771
4772   if(elem->GetType()==SMDSAbs_Volume) {
4773     SMDS_VolumeTool aTool;
4774     if(aTool.Set(elem)) {
4775       aResult->length(3);
4776       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
4777         aResult->length(0);
4778     }
4779   }
4780   else {
4781     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
4782     int nbn = 0;
4783     double x=0., y=0., z=0.;
4784     for(; anIt->more(); ) {
4785       nbn++;
4786       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
4787       x += aNode->X();
4788       y += aNode->Y();
4789       z += aNode->Z();
4790     }
4791     if(nbn>0) {
4792       // add coordinates
4793       aResult->length(3);
4794       aResult[0] = x/nbn;
4795       aResult[1] = y/nbn;
4796       aResult[2] = z/nbn;
4797     }
4798   }
4799
4800   return aResult._retn();
4801 }
4802
4803 //================================================================================
4804 /*!
4805  * \brief Create a group of elements preventing computation of a sub-shape
4806  */
4807 //================================================================================
4808
4809 SMESH::ListOfGroups*
4810 SMESH_Mesh_i::MakeGroupsOfBadInputElements( int         theSubShapeID,
4811                                             const char* theGroupName )
4812   throw ( SALOME::SALOME_Exception )
4813 {
4814   Unexpect aCatch(SALOME_SalomeException);
4815
4816   if ( !theGroupName || strlen( theGroupName) == 0 )
4817     THROW_SALOME_CORBA_EXCEPTION( "empty group name",SALOME::BAD_PARAM );
4818
4819   SMESH::ListOfGroups_var groups = new SMESH::ListOfGroups;
4820
4821   // submesh by subshape id
4822   if ( !_impl->HasShapeToMesh() ) theSubShapeID = 1;
4823   if ( SMESH_subMesh * sm = _impl->GetSubMeshContaining( theSubShapeID ))
4824   {
4825     // compute error
4826     SMESH_ComputeErrorPtr error = sm->GetComputeError();
4827     if ( error && !error->myBadElements.empty())
4828     {
4829       // sort bad elements by type
4830       vector< const SMDS_MeshElement* > elemsByType[ SMDSAbs_NbElementTypes ];
4831       list<const SMDS_MeshElement*>::iterator elemIt  = error->myBadElements.begin();
4832       list<const SMDS_MeshElement*>::iterator elemEnd = error->myBadElements.end();
4833       for ( ; elemIt != elemEnd; ++elemIt )
4834       {
4835         const SMDS_MeshElement* elem = *elemIt;
4836         if ( !elem ) continue;
4837
4838         if ( elem->GetID() < 1 )
4839         {
4840           // elem is a temporary element, make a real element
4841           vector< const SMDS_MeshNode* > nodes;
4842           SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
4843           while ( nIt->more() && elem )
4844           {
4845             nodes.push_back( nIt->next() );
4846             if ( nodes.back()->GetID() < 1 )
4847               elem = 0;  // a temporary element on temporary nodes
4848           }
4849           if ( elem )
4850           {
4851             ::SMESH_MeshEditor editor( _impl );
4852             elem = editor.AddElement( nodes, elem->GetType(), elem->IsPoly() );
4853           }
4854         }
4855         if ( elem )
4856           elemsByType[ elem->GetType() ].push_back( elem );
4857       }
4858
4859       // how many groups to create?
4860       int nbTypes = 0;
4861       for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
4862         nbTypes += int( !elemsByType[ i ].empty() );
4863       groups->length( nbTypes );
4864
4865       // create groups
4866       for ( int i = 0, iG = -1; i < SMDSAbs_NbElementTypes; ++i )
4867       {
4868         vector< const SMDS_MeshElement* >& elems = elemsByType[ i ];
4869         if ( elems.empty() ) continue;
4870
4871         groups[ ++iG ] = createGroup( SMESH::ElementType(i), theGroupName );
4872         if ( _gen_i->CanPublishInStudy( groups[ iG ] ))
4873         {
4874           SALOMEDS::Study_var  study = _gen_i->GetCurrentStudy();
4875           SMESH::SMESH_Mesh_var mesh = _this();
4876           SALOMEDS::SObject_wrap aSO =
4877             _gen_i->PublishGroup( study, mesh, groups[ iG ],
4878                                  GEOM::GEOM_Object::_nil(), theGroupName);
4879         }
4880         SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
4881         if ( !grp_i ) continue;
4882
4883         if ( SMESHDS_Group*  grpDS = dynamic_cast< SMESHDS_Group* >( grp_i->GetGroupDS() ))
4884           for ( size_t iE = 0; iE < elems.size(); ++iE )
4885             grpDS->SMDSGroup().Add( elems[ iE ]);
4886       }
4887     }
4888   }
4889
4890   return groups._retn();
4891 }
4892
4893 //=============================================================================
4894 /*!
4895  * Create and publish group servants if any groups were imported or created anyhow
4896  */
4897 //=============================================================================
4898
4899 void SMESH_Mesh_i::CreateGroupServants()
4900 {
4901   SALOMEDS::Study_var  aStudy = _gen_i->GetCurrentStudy();
4902   SMESH::SMESH_Mesh_var aMesh = _this();
4903
4904   set<int> addedIDs;
4905   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
4906   while ( groupIt->more() )
4907   {
4908     ::SMESH_Group* group = groupIt->next();
4909     int            anId = group->GetGroupDS()->GetID();
4910
4911     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
4912     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
4913       continue;
4914     addedIDs.insert( anId );
4915
4916     SMESH_GroupBase_i* aGroupImpl;
4917     TopoDS_Shape       shape;
4918     if ( SMESHDS_GroupOnGeom* groupOnGeom =
4919          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
4920     {
4921       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
4922       shape      = groupOnGeom->GetShape();
4923     }
4924     else {
4925       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
4926     }
4927
4928     SMESH::SMESH_GroupBase_var groupVar = aGroupImpl->_this();
4929     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
4930     aGroupImpl->Register();
4931
4932     // register CORBA object for persistence
4933     int nextId = _gen_i->RegisterObject( groupVar );
4934     if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
4935     else        { nextId = 0; } // avoid "unused variable" warning in release mode
4936
4937     // publishing the groups in the study
4938     if ( !aStudy->_is_nil() ) {
4939       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
4940       _gen_i->PublishGroup( aStudy, aMesh, groupVar, shapeVar, group->GetName());
4941     }
4942   }
4943   if ( !addedIDs.empty() )
4944   {
4945     // python dump
4946     set<int>::iterator id = addedIDs.begin();
4947     for ( ; id != addedIDs.end(); ++id )
4948     {
4949       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(*id);
4950       int i = std::distance( _mapGroups.begin(), it );
4951       TPythonDump() << it->second << " = " << aMesh << ".GetGroups()[ "<< i << " ]";
4952     }
4953   }
4954 }
4955
4956 //=============================================================================
4957 /*!
4958  * \brief Return groups cantained in _mapGroups by their IDs
4959  */
4960 //=============================================================================
4961
4962 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
4963 {
4964   int nbGroups = groupIDs.size();
4965   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
4966   aList->length( nbGroups );
4967
4968   list<int>::const_iterator ids = groupIDs.begin();
4969   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
4970   {
4971     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
4972     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
4973       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
4974   }
4975   aList->length( nbGroups );
4976   return aList._retn();
4977 }
4978
4979 //=============================================================================
4980 /*!
4981  * \brief Return information about imported file
4982  */
4983 //=============================================================================
4984
4985 SMESH::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
4986 {
4987   SMESH::MedFileInfo_var res( _medFileInfo );
4988   if ( !res.operator->() ) {
4989     res = new SMESH::MedFileInfo;
4990     res->fileName = "";
4991     res->fileSize = res->major = res->minor = res->release = -1;
4992   }
4993   return res._retn();
4994 }
4995
4996 //=============================================================================
4997 /*!
4998  * \brief Pass names of mesh groups from study to mesh DS
4999  */
5000 //=============================================================================
5001
5002 void SMESH_Mesh_i::checkGroupNames()
5003 {
5004   int nbGrp = NbGroups();
5005   if ( !nbGrp )
5006     return;
5007
5008   SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
5009   if ( aStudy->_is_nil() )
5010     return; // nothing to do
5011   
5012   SMESH::ListOfGroups* grpList = 0;
5013   // avoid dump of "GetGroups"
5014   {
5015     // store python dump into a local variable inside local scope
5016     SMESH::TPythonDump pDump; // do not delete this line of code
5017     grpList = GetGroups();
5018   }
5019
5020   for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
5021     SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
5022     if ( !aGrp )
5023       continue;
5024     SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aStudy, aGrp );
5025     if ( aGrpSO->_is_nil() )
5026       continue;
5027     // correct name of the mesh group if necessary
5028     const char* guiName = aGrpSO->GetName();
5029     if ( strcmp(guiName, aGrp->GetName()) )
5030       aGrp->SetName( guiName );
5031   }
5032 }
5033
5034 //=============================================================================
5035 /*!
5036  * \brief Sets list of notebook variables used for Mesh operations separated by ":" symbol
5037  */
5038 //=============================================================================
5039 void SMESH_Mesh_i::SetParameters(const char* theParameters)
5040 {
5041   SMESH_Gen_i::GetSMESHGen()->UpdateParameters( CORBA::Object_var( _this() ).in(),
5042                                                 theParameters );
5043 }
5044
5045 //=============================================================================
5046 /*!
5047  * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
5048  */
5049 //=============================================================================
5050
5051 char* SMESH_Mesh_i::GetParameters()
5052 {
5053   return SMESH_Gen_i::GetSMESHGen()->GetParameters( SMESH::SMESH_Mesh_var( _this()) );
5054 }
5055
5056 //=============================================================================
5057 /*!
5058  * \brief Returns list of notebook variables used for last Mesh operation
5059  */
5060 //=============================================================================
5061 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
5062 {
5063   SMESH::string_array_var aResult = new SMESH::string_array();
5064   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
5065   if(gen) {
5066     CORBA::String_var aParameters = GetParameters();
5067     SALOMEDS::Study_var    aStudy = gen->GetCurrentStudy();
5068     if ( !aStudy->_is_nil()) {
5069       SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters); 
5070       if(aSections->length() > 0) {
5071         SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1];
5072         aResult->length(aVars.length());
5073         for(int i = 0;i < aVars.length();i++)
5074           aResult[i] = CORBA::string_dup( aVars[i]);
5075       }
5076     }
5077   }
5078   return aResult._retn();
5079 }
5080
5081 //=======================================================================
5082 //function : GetTypes
5083 //purpose  : Returns types of elements it contains
5084 //=======================================================================
5085
5086 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
5087 {
5088   if ( _preMeshInfo )
5089     return _preMeshInfo->GetTypes();
5090
5091   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
5092
5093   types->length( 5 );
5094   int nbTypes = 0;
5095   if (_impl->NbEdges())      types[nbTypes++] = SMESH::EDGE;
5096   if (_impl->NbFaces())      types[nbTypes++] = SMESH::FACE;
5097   if (_impl->NbVolumes())    types[nbTypes++] = SMESH::VOLUME;
5098   if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
5099   if (_impl->NbBalls())      types[nbTypes++] = SMESH::BALL;
5100   types->length( nbTypes );
5101
5102   return types._retn();
5103 }
5104
5105 //=======================================================================
5106 //function : GetMesh
5107 //purpose  : Returns self
5108 //=======================================================================
5109
5110 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
5111 {
5112   return SMESH::SMESH_Mesh::_duplicate( _this() );
5113 }
5114
5115 //=======================================================================
5116 //function : IsMeshInfoCorrect
5117 //purpose  : * Returns false if GetMeshInfo() returns incorrect information that may
5118 //           * happen if mesh data is not yet fully loaded from the file of study.
5119 //=======================================================================
5120
5121 bool SMESH_Mesh_i::IsMeshInfoCorrect()
5122 {
5123   return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
5124 }
5125
5126 //=============================================================================
5127 /*!
5128  * \brief Returns number of mesh elements per each \a EntityType
5129  */
5130 //=============================================================================
5131
5132 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
5133 {
5134   if ( _preMeshInfo )
5135     return _preMeshInfo->GetMeshInfo();
5136
5137   SMESH::long_array_var aRes = new SMESH::long_array();
5138   aRes->length(SMESH::Entity_Last);
5139   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
5140     aRes[i] = 0;
5141   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5142   if (!aMeshDS)
5143     return aRes._retn();
5144   const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
5145   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
5146     aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
5147   return aRes._retn();
5148 }
5149
5150 //=============================================================================
5151 /*!
5152  * \brief Returns number of mesh elements per each \a ElementType
5153  */
5154 //=============================================================================
5155
5156 SMESH::long_array* SMESH_Mesh_i::GetNbElementsByType()
5157 {
5158   SMESH::long_array_var aRes = new SMESH::long_array();
5159   aRes->length(SMESH::NB_ELEMENT_TYPES);
5160   for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
5161     aRes[ i ] = 0;
5162
5163   const SMDS_MeshInfo* meshInfo = 0;
5164   if ( _preMeshInfo )
5165     meshInfo = _preMeshInfo;
5166   else if ( SMESHDS_Mesh* meshDS = _impl->GetMeshDS() )
5167     meshInfo = & meshDS->GetMeshInfo();
5168
5169   if (meshInfo)
5170     for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
5171       aRes[i] = meshInfo->NbElements((SMDSAbs_ElementType)i);
5172
5173   return aRes._retn();
5174 }
5175
5176 //=============================================================================
5177 /*
5178  * Collect statistic of mesh elements given by iterator
5179  */
5180 //=============================================================================
5181
5182 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
5183                                    SMESH::long_array&         theInfo)
5184 {
5185   if (!theItr) return;
5186   while (theItr->more())
5187     theInfo[ theItr->next()->GetEntityType() ]++;
5188 }
5189 //=============================================================================
5190 /*
5191  * Returns mesh unstructed grid information.
5192  */
5193 //=============================================================================
5194
5195 SALOMEDS::TMPFile* SMESH_Mesh_i::GetVtkUgStream()
5196 {
5197   SALOMEDS::TMPFile_var SeqFile;
5198   if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() ) {
5199     SMDS_UnstructuredGrid* aGrid = aMeshDS->getGrid();
5200     if(aGrid) {
5201       vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
5202       aWriter->WriteToOutputStringOn();
5203       aWriter->SetInputData(aGrid);
5204       aWriter->SetFileTypeToBinary();
5205       aWriter->Write();
5206       char* str = aWriter->GetOutputString();
5207       int size = aWriter->GetOutputStringLength();
5208       
5209       //Allocate octect buffer of required size
5210       CORBA::Octet* OctetBuf = SALOMEDS::TMPFile::allocbuf(size);
5211       //Copy ostrstream content to the octect buffer
5212       memcpy(OctetBuf, str, size);
5213       //Create and return TMPFile
5214       SeqFile = new SALOMEDS::TMPFile(size, size, OctetBuf, 1);
5215       aWriter->Delete();
5216     }
5217   }
5218   return SeqFile._retn();
5219 }
5220
5221 //=============================================================================
5222 namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
5223            *                                             SMESH::ElementType        type) */
5224 {
5225   using namespace SMESH::Controls;
5226   //-----------------------------------------------------------------------------
5227   struct PredicateIterator : public SMDS_ElemIterator
5228   {
5229     SMDS_ElemIteratorPtr    _elemIter;
5230     PredicatePtr            _predicate;
5231     const SMDS_MeshElement* _elem;
5232
5233     PredicateIterator( SMDS_ElemIteratorPtr   iterator,
5234                        PredicatePtr predicate):
5235       _elemIter(iterator), _predicate(predicate)
5236     {
5237       next();
5238     }
5239     virtual bool more()
5240     {
5241       return _elem;
5242     }
5243     virtual const SMDS_MeshElement* next()
5244     {
5245       const SMDS_MeshElement* res = _elem;
5246       _elem = 0;
5247       while ( _elemIter->more() && !_elem )
5248       {
5249         _elem = _elemIter->next();
5250         if ( _elem && ( !_predicate->IsSatisfy( _elem->GetID() )))
5251           _elem = 0;
5252       }
5253       return res;
5254     }
5255   };
5256
5257   //-----------------------------------------------------------------------------
5258   struct IDSourceIterator : public SMDS_ElemIterator
5259   {
5260     const CORBA::Long*        _idPtr;
5261     const CORBA::Long*        _idEndPtr;
5262     SMESH::long_array_var     _idArray;
5263     const SMDS_Mesh*          _mesh;
5264     const SMDSAbs_ElementType _type;
5265     const SMDS_MeshElement*   _elem;
5266
5267     IDSourceIterator( const SMDS_Mesh*    mesh,
5268                       const CORBA::Long*  ids,
5269                       const int           nbIds,
5270                       SMDSAbs_ElementType type):
5271       _idPtr( ids ), _idEndPtr( ids + nbIds ), _mesh( mesh ), _type( type ), _elem( 0 )
5272     {
5273       if ( _idPtr && nbIds && _mesh )
5274         next();
5275     }
5276     IDSourceIterator( const SMDS_Mesh*    mesh,
5277                       SMESH::long_array*  idArray,
5278                       SMDSAbs_ElementType type):
5279       _idPtr( 0 ), _idEndPtr( 0 ), _idArray( idArray), _mesh( mesh ), _type( type ), _elem( 0 )
5280     {
5281       if ( idArray && _mesh )
5282       {
5283         _idPtr    = &_idArray[0];
5284         _idEndPtr = _idPtr + _idArray->length();
5285         next();
5286       }
5287     }
5288     virtual bool more()
5289     {
5290       return _elem;
5291     }
5292     virtual const SMDS_MeshElement* next()
5293     {
5294       const SMDS_MeshElement* res = _elem;
5295       _elem = 0;
5296       while ( _idPtr < _idEndPtr && !_elem )
5297       {
5298         if ( _type == SMDSAbs_Node )
5299         {
5300           _elem = _mesh->FindNode( *_idPtr++ );
5301         }
5302         else if ((_elem = _mesh->FindElement( *_idPtr++ )) &&
5303                  (_elem->GetType() != _type && _type != SMDSAbs_All ))
5304         {
5305           _elem = 0;
5306         }
5307       }
5308       return res;
5309     }
5310   };
5311   //-----------------------------------------------------------------------------
5312
5313   struct NodeOfElemIterator : public SMDS_ElemIterator
5314   {
5315     TColStd_MapOfInteger    _checkedNodeIDs;
5316     SMDS_ElemIteratorPtr    _elemIter;
5317     SMDS_ElemIteratorPtr    _nodeIter;
5318     const SMDS_MeshElement* _node;
5319
5320     NodeOfElemIterator( SMDS_ElemIteratorPtr iter ): _elemIter( iter ), _node( 0 )
5321     {
5322       if ( _elemIter && _elemIter->more() )
5323       {
5324         _nodeIter = _elemIter->next()->nodesIterator();
5325         next();
5326       }
5327     }
5328     virtual bool more()
5329     {
5330       return _node;
5331     }
5332     virtual const SMDS_MeshElement* next()
5333     {
5334       const SMDS_MeshElement* res = _node;
5335       _node = 0;
5336       while (( _elemIter->more() || _nodeIter->more() ) && !_node )
5337       {
5338         if ( _nodeIter->more() )
5339         {
5340           _node = _nodeIter->next();
5341           if ( !_checkedNodeIDs.Add( _node->GetID() ))
5342             _node = 0;
5343         }
5344         else
5345         {
5346           _nodeIter = _elemIter->next()->nodesIterator();
5347         }
5348       }
5349       return res;
5350     }
5351   };
5352 }
5353
5354 //=============================================================================
5355 /*
5356  * Return iterator on elements of given type in given object
5357  */
5358 //=============================================================================
5359
5360 SMDS_ElemIteratorPtr SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_ptr theObject,
5361                                                SMESH::ElementType        theType)
5362 {
5363   SMDS_ElemIteratorPtr  elemIt;
5364   bool                  typeOK = false;
5365   SMDSAbs_ElementType elemType = SMDSAbs_ElementType( theType );
5366
5367   SMESH::SMESH_Mesh_var meshVar = theObject->GetMesh();
5368   SMESH_Mesh_i*          mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( meshVar );
5369   if ( !mesh_i ) return elemIt;
5370   SMESHDS_Mesh*          meshDS = mesh_i->GetImpl().GetMeshDS();
5371
5372   if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
5373   {
5374     elemIt = meshDS->elementsIterator( elemType );
5375     typeOK = true;
5376   }
5377   else if ( SMESH_subMesh_i* submesh_i = SMESH::DownCast<SMESH_subMesh_i*>( theObject ))
5378   {
5379     SMESHDS_SubMesh* sm = ((SMESHDS_Mesh*) meshDS)->MeshElements( submesh_i->GetId() );
5380     if ( sm )
5381     {
5382       elemIt = sm->GetElements();
5383       if ( elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
5384       {
5385         typeOK = ( elemIt && elemIt->more() && elemIt->next()->GetType() == elemType );
5386         elemIt = typeOK ? sm->GetElements() : SMDS_ElemIteratorPtr();
5387       }
5388     }
5389   }
5390   else if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( theObject ))
5391   {
5392     SMESHDS_GroupBase* groupDS = group_i->GetGroupDS();
5393     if ( groupDS && ( elemType == groupDS->GetType()  ||
5394                       elemType == SMDSAbs_Node ||
5395                       elemType == SMDSAbs_All ))
5396     {
5397       elemIt = groupDS->GetElements();
5398       typeOK = ( groupDS->GetType() == elemType || elemType == SMDSAbs_All );
5399     }
5400   }
5401   else if ( SMESH::Filter_i* filter_i = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5402   {
5403     if ( filter_i->GetElementType() == theType ||
5404          elemType == SMDSAbs_Node ||
5405          elemType == SMDSAbs_All)
5406     {
5407       SMESH::Predicate_i* pred_i = filter_i->GetPredicate_i();
5408       if ( pred_i && pred_i->GetPredicate() )
5409       {
5410         SMDSAbs_ElementType filterType = SMDSAbs_ElementType( filter_i->GetElementType() );
5411         SMDS_ElemIteratorPtr allElemIt = meshDS->elementsIterator( filterType );
5412         elemIt = SMDS_ElemIteratorPtr( new PredicateIterator( allElemIt, pred_i->GetPredicate() ));
5413         typeOK = ( filterType == elemType || elemType == SMDSAbs_All );
5414       }
5415     }
5416   }
5417   else
5418   {
5419     SMESH::array_of_ElementType_var types = theObject->GetTypes();
5420     const bool                    isNodes = ( types->length() == 1 && types[0] == SMESH::NODE );
5421     if ( isNodes && elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
5422       return elemIt;
5423     if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theObject ))
5424     {
5425       int nbIds;
5426       if ( CORBA::Long* ids = SMESH_MeshEditor_i::GetTemporaryIDs( theObject, nbIds ))
5427         elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids, nbIds, elemType ));
5428     }
5429     else
5430     {
5431       SMESH::long_array_var ids = theObject->GetIDs();
5432       elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids._retn(), elemType ));
5433     }
5434     typeOK = ( isNodes == ( elemType == SMDSAbs_Node )) || ( elemType == SMDSAbs_All );
5435   }
5436
5437   if ( elemIt && elemIt->more() && !typeOK )
5438   {
5439     if ( elemType == SMDSAbs_Node )
5440     {
5441       elemIt = SMDS_ElemIteratorPtr( new NodeOfElemIterator( elemIt ));
5442     }
5443     else
5444     {
5445       elemIt = SMDS_ElemIteratorPtr();
5446     }
5447   }
5448   return elemIt;
5449 }
5450
5451 //=============================================================================
5452 namespace // Finding concurrent hypotheses
5453 //=============================================================================
5454 {
5455
5456 /*!
5457  * \brief mapping of mesh dimension into shape type
5458  */
5459 TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
5460 {
5461   TopAbs_ShapeEnum aType = TopAbs_SOLID;
5462   switch ( theDim ) {
5463   case 0: aType = TopAbs_VERTEX; break;
5464   case 1: aType = TopAbs_EDGE; break;
5465   case 2: aType = TopAbs_FACE; break;
5466   case 3:
5467   default:aType = TopAbs_SOLID; break;
5468   }
5469   return aType;
5470 }
5471
5472 //-----------------------------------------------------------------------------
5473 /*!
5474  * \brief Internal structure used to find concurent submeshes
5475  *
5476  * It represents a pair < submesh, concurent dimension >, where
5477  * 'concurrent dimension' is dimension of shape where the submesh can concurent
5478  *  with another submesh. In other words, it is dimension of a hypothesis assigned
5479  *  to submesh.
5480  */
5481 class SMESH_DimHyp
5482 {
5483  public:
5484   //! fileds
5485   int _dim;    //!< a dimension the algo can build (concurrent dimension)
5486   int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
5487   TopTools_MapOfShape _shapeMap;
5488   SMESH_subMesh*      _subMesh;
5489   list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
5490
5491   //-----------------------------------------------------------------------------
5492   // Return the algorithm
5493   const SMESH_Algo* GetAlgo() const
5494   { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
5495
5496   //-----------------------------------------------------------------------------
5497   //! Constructors
5498   SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
5499                const int            theDim,
5500                const TopoDS_Shape&  theShape)
5501   {
5502     _subMesh = (SMESH_subMesh*)theSubMesh;
5503     SetShape( theDim, theShape );
5504   }
5505
5506   //-----------------------------------------------------------------------------
5507   //! set shape
5508   void SetShape(const int           theDim,
5509                 const TopoDS_Shape& theShape)
5510   {
5511     _dim = theDim;
5512     _ownDim = SMESH_Gen::GetShapeDim(theShape);
5513     if (_dim >= _ownDim)
5514       _shapeMap.Add( theShape );
5515     else {
5516       TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
5517       for( ; anExp.More(); anExp.Next() )
5518         _shapeMap.Add( anExp.Current() );
5519     }
5520   }
5521
5522   //-----------------------------------------------------------------------------
5523   //! Check sharing of sub-shapes
5524   static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
5525                                const TopTools_MapOfShape& theToFind,
5526                                const TopAbs_ShapeEnum     theType)
5527   {
5528     bool isShared = false;
5529     TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
5530     for (; !isShared && anItr.More(); anItr.Next() )
5531     {
5532       const TopoDS_Shape aSubSh = anItr.Key();
5533       // check for case when concurrent dimensions are same
5534       isShared = theToFind.Contains( aSubSh );
5535       // check for sub-shape with concurrent dimension
5536       TopExp_Explorer anExp( aSubSh, theType );
5537       for ( ; !isShared && anExp.More(); anExp.Next() )
5538         isShared = theToFind.Contains( anExp.Current() );
5539     }
5540     return isShared;
5541   }
5542   
5543   //-----------------------------------------------------------------------------
5544   //! check algorithms
5545   static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
5546                         const SMESHDS_Hypothesis* theA2)
5547   {
5548     if ( !theA1 || !theA2 ||
5549          theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
5550          theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
5551       return false; // one of the hypothesis is not algorithm
5552     // check algorithm names (should be equal)
5553     return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
5554   }
5555
5556   
5557   //-----------------------------------------------------------------------------
5558   //! Check if sub-shape hypotheses are concurrent
5559   bool IsConcurrent(const SMESH_DimHyp* theOther) const
5560   {
5561     if ( _subMesh == theOther->_subMesh )
5562       return false; // same sub-shape - should not be
5563
5564     // if ( <own dim of either of submeshes> == <concurrent dim> &&
5565     //      any of the two submeshes is not on COMPOUND shape )
5566     //  -> no concurrency
5567     bool meIsCompound    = (_subMesh->GetSubMeshDS() &&
5568                             _subMesh->GetSubMeshDS()->IsComplexSubmesh());
5569     bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
5570                             theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
5571     if ( (_ownDim == _dim  || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
5572       return false;
5573
5574 //     bool checkSubShape = ( _dim >= theOther->_dim )
5575 //       ? isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(theOther->_dim) )
5576 //       : isShareSubShapes( theOther->_shapeMap, _shapeMap, shapeTypeByDim(_dim) ) ;
5577     bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
5578     if ( !checkSubShape )
5579         return false;
5580
5581     // check algorithms to be same
5582     if ( !checkAlgo( this->GetAlgo(), theOther->GetAlgo() ))
5583       return true; // different algorithms -> concurrency !
5584
5585     // check hypothesises for concurrence (skip first as algorithm)
5586     int nbSame = 0;
5587     // pointers should be same, because it is referened from mesh hypothesis partition
5588     list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
5589     list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
5590     for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
5591       if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
5592         nbSame++;
5593     // the submeshes are concurrent if their algorithms has different parameters
5594     return nbSame != theOther->_hypotheses.size() - 1;
5595   }
5596
5597   // Return true if algorithm of this SMESH_DimHyp is used if no
5598   // sub-mesh order is imposed by the user
5599   bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
5600   {
5601     // NeedDiscreteBoundary() algo has a higher priority
5602     if ( this    ->GetAlgo()->NeedDiscreteBoundary() !=
5603          theOther->GetAlgo()->NeedDiscreteBoundary() )
5604       return !this->GetAlgo()->NeedDiscreteBoundary();
5605
5606     return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
5607   }
5608   
5609 }; // end of SMESH_DimHyp
5610 //-----------------------------------------------------------------------------
5611
5612 typedef list<const SMESH_DimHyp*> TDimHypList;
5613
5614 //-----------------------------------------------------------------------------
5615
5616 void addDimHypInstance(const int                               theDim, 
5617                        const TopoDS_Shape&                     theShape,
5618                        const SMESH_Algo*                       theAlgo,
5619                        const SMESH_subMesh*                    theSubMesh,
5620                        const list <const SMESHDS_Hypothesis*>& theHypList,
5621                        TDimHypList*                            theDimHypListArr )
5622 {
5623   TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
5624   if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) {
5625     SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
5626     dimHyp->_hypotheses.push_front(theAlgo);
5627     listOfdimHyp.push_back( dimHyp );
5628   }
5629   
5630   SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
5631   dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
5632                               theHypList.begin(), theHypList.end() );
5633 }
5634
5635 //-----------------------------------------------------------------------------
5636 void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
5637                            TDimHypList&        theListOfConcurr)
5638 {
5639   if ( theListOfConcurr.empty() )
5640   {
5641     theListOfConcurr.push_back( theDimHyp );
5642   }
5643   else
5644   {
5645     TDimHypList::iterator hypIt = theListOfConcurr.begin();
5646     while ( hypIt != theListOfConcurr.end() &&
5647             !theDimHyp->IsHigherPriorityThan( *hypIt ))
5648       ++hypIt;
5649     theListOfConcurr.insert( hypIt, theDimHyp );
5650   }
5651 }
5652
5653 //-----------------------------------------------------------------------------
5654 void findConcurrents(const SMESH_DimHyp* theDimHyp,
5655                      const TDimHypList&  theListOfDimHyp,
5656                      TDimHypList&        theListOfConcurrHyp,
5657                      set<int>&           theSetOfConcurrId )
5658 {
5659   TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
5660   for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
5661   {
5662     const SMESH_DimHyp* curDimHyp = *rIt;
5663     if ( curDimHyp == theDimHyp )
5664       break; // meet own dimHyp pointer in same dimension
5665
5666     if ( theDimHyp->IsConcurrent( curDimHyp ) &&
5667          theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
5668     {
5669       addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
5670     }
5671   }
5672 }
5673
5674 //-----------------------------------------------------------------------------
5675 void unionLists(TListOfInt&       theListOfId,
5676                 TListOfListOfInt& theListOfListOfId,
5677                 const int         theIndx )
5678 {
5679   TListOfListOfInt::iterator it = theListOfListOfId.begin();
5680   for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) {
5681     if ( i < theIndx )
5682       continue; //skip already treated lists
5683     // check if other list has any same submesh object
5684     TListOfInt& otherListOfId = *it;
5685     if ( find_first_of( theListOfId.begin(), theListOfId.end(),
5686                         otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
5687       continue;
5688          
5689     // union two lists (from source into target)
5690     TListOfInt::iterator it2 = otherListOfId.begin();
5691     for ( ; it2 != otherListOfId.end(); it2++ ) {
5692       if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
5693         theListOfId.push_back(*it2);
5694     }
5695     // clear source list
5696     otherListOfId.clear();
5697   }
5698 }
5699 //-----------------------------------------------------------------------------
5700
5701 //! free memory allocated for dimension-hypothesis objects
5702 void removeDimHyps( TDimHypList* theArrOfList )
5703 {
5704   for (int i = 0; i < 4; i++ ) {
5705     TDimHypList& listOfdimHyp = theArrOfList[i];
5706     TDimHypList::const_iterator it = listOfdimHyp.begin();
5707     for ( ; it != listOfdimHyp.end(); it++ )
5708       delete (*it);
5709   }
5710 }
5711
5712 //-----------------------------------------------------------------------------
5713 /*!
5714  * \brief find common submeshes with given submesh
5715  * \param theSubMeshList list of already collected submesh to check
5716  * \param theSubMesh given submesh to intersect with other
5717  * \param theCommonSubMeshes collected common submeshes
5718  */
5719 void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
5720                         const SMESH_subMesh*        theSubMesh,
5721                         set<const SMESH_subMesh*>&  theCommon )
5722 {
5723   if ( !theSubMesh )
5724     return;
5725   list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
5726   for ( ; it != theSubMeshList.end(); it++ )
5727     theSubMesh->FindIntersection( *it, theCommon );
5728   theSubMeshList.push_back( theSubMesh );
5729   //theCommon.insert( theSubMesh );
5730 }
5731
5732 //-----------------------------------------------------------------------------
5733 bool isSubMeshInList ( int smID, const TListOfListOfInt& smLists )
5734 {
5735   TListOfListOfInt::const_iterator listsIt = smLists.begin();
5736   for ( ; listsIt != smLists.end(); ++listsIt )
5737   {
5738     const TListOfInt& smIDs = *listsIt;
5739     if ( std::find( smIDs.begin(), smIDs.end(), smID ) != smIDs.end() )
5740       return true;
5741   }
5742   return false;
5743 }
5744
5745 } // namespace
5746
5747 //=============================================================================
5748 /*!
5749  * \brief Return \c true if a meshing order not yet set for a concurrent sub-mesh
5750  */
5751 //=============================================================================
5752
5753 CORBA::Boolean SMESH_Mesh_i::IsUnorderedSubMesh(CORBA::Long submeshID)
5754 {
5755   TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
5756   if ( isSubMeshInList( submeshID, anOrder ))
5757     return false;
5758
5759   TListOfListOfInt allConurrent = findConcurrentSubMeshes();
5760   return isSubMeshInList( submeshID, allConurrent );
5761 }
5762
5763 //=============================================================================
5764 /*!
5765  * \brief Return submesh objects list in meshing order
5766  */
5767 //=============================================================================
5768
5769 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
5770 {
5771   SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
5772
5773   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5774   if ( !aMeshDS )
5775     return aResult._retn();
5776
5777   TListOfListOfInt      anOrder = GetImpl().GetMeshOrder(); // already defined order
5778   TListOfListOfInt allConurrent = findConcurrentSubMeshes();
5779   anOrder.splice( anOrder.end(), allConurrent );
5780
5781   int listIndx = 0;
5782   TListOfListOfInt::iterator listIt = anOrder.begin();
5783   for(; listIt != anOrder.end(); listIt++, listIndx++ )
5784     unionLists( *listIt,  anOrder, listIndx + 1 );
5785
5786   // convert submesh ids into interface instances
5787   //  and dump command into python
5788   convertMeshOrder( anOrder, aResult, false );
5789
5790   return aResult._retn();
5791 }
5792
5793 //=============================================================================
5794 /*!
5795  * \brief Finds concurrent sub-meshes
5796  */
5797 //=============================================================================
5798
5799 TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes()
5800 {
5801   TListOfListOfInt anOrder;
5802   ::SMESH_Mesh& mesh = GetImpl();
5803   {
5804     // collect submeshes and detect concurrent algorithms and hypothesises
5805     TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
5806
5807     map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
5808     for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) {
5809       ::SMESH_subMesh* sm = (*i_sm).second;
5810       // shape of submesh
5811       const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
5812
5813       // list of assigned hypothesises
5814       const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
5815       // Find out dimensions where the submesh can be concurrent.
5816       // We define the dimensions by algo of each of hypotheses in hypList
5817       list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
5818       for( ; hypIt != hypList.end(); hypIt++ ) {
5819         SMESH_Algo* anAlgo = 0;
5820         const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
5821         if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
5822           // hyp it-self is algo
5823           anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
5824         else {
5825           // try to find algorithm with help of sub-shapes
5826           TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
5827           for ( ; !anAlgo && anExp.More(); anExp.Next() )
5828             anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
5829         }
5830         if (!anAlgo)
5831           continue; // no algorithm assigned to a current submesh
5832
5833         int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
5834         // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary())
5835
5836         // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
5837         for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
5838           addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
5839       }
5840     } // end iterations on submesh
5841     
5842     // iterate on created dimension-hypotheses and check for concurrents
5843     for ( int i = 0; i < 4; i++ ) {
5844       const TDimHypList& listOfDimHyp = dimHypListArr[i];
5845       // check for concurrents in own and other dimensions (step-by-step)
5846       TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
5847       for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) {
5848         const SMESH_DimHyp* dimHyp = *dhIt;
5849         TDimHypList listOfConcurr;
5850         set<int>    setOfConcurrIds;
5851         // looking for concurrents and collect into own list
5852         for ( int j = i; j < 4; j++ )
5853           findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
5854         // check if any concurrents found
5855         if ( listOfConcurr.size() > 0 ) {
5856           // add own submesh to list of concurrent
5857           addInOrderOfPriority( dimHyp, listOfConcurr );
5858           list<int> listOfConcurrIds;
5859           TDimHypList::iterator hypIt = listOfConcurr.begin();
5860           for ( ; hypIt != listOfConcurr.end(); ++hypIt )
5861             listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
5862           anOrder.push_back( listOfConcurrIds );
5863         }
5864       }
5865     }
5866     
5867     removeDimHyps(dimHypListArr);
5868     
5869     // now, minimise the number of concurrent groups
5870     // Here we assume that lists of submeshes can have same submesh
5871     // in case of multi-dimension algorithms, as result
5872     //  list with common submesh has to be united into one list
5873     int listIndx = 0;
5874     TListOfListOfInt::iterator listIt = anOrder.begin();
5875     for(; listIt != anOrder.end(); listIt++, listIndx++ )
5876       unionLists( *listIt,  anOrder, listIndx + 1 );
5877   }
5878
5879   return anOrder;
5880 }
5881
5882 //=============================================================================
5883 /*!
5884  * \brief Set submesh object order
5885  * \param theSubMeshArray submesh array order
5886  */
5887 //=============================================================================
5888
5889 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
5890 {
5891   if ( _preMeshInfo )
5892     _preMeshInfo->ForgetOrLoad();
5893
5894   bool res = false;
5895   ::SMESH_Mesh& mesh = GetImpl();
5896
5897   TPythonDump aPythonDump; // prevent dump of called methods
5898   aPythonDump << "isDone = " << SMESH::SMESH_Mesh_var(_this()) << ".SetMeshOrder( [ ";
5899
5900   TListOfListOfInt subMeshOrder;
5901   for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
5902   {
5903     const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
5904     TListOfInt subMeshIds;
5905     if ( i > 0 )
5906       aPythonDump << ", ";
5907     aPythonDump << "[ ";
5908     // Collect subMeshes which should be clear
5909     //  do it list-by-list, because modification of submesh order
5910     //  take effect between concurrent submeshes only
5911     set<const SMESH_subMesh*> subMeshToClear;
5912     list<const SMESH_subMesh*> subMeshList;
5913     for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
5914     {
5915       const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
5916       if ( j > 0 )
5917         aPythonDump << ", ";
5918       aPythonDump << subMesh;
5919       subMeshIds.push_back( subMesh->GetId() );
5920       // detect common parts of submeshes
5921       if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
5922         findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
5923     }
5924     aPythonDump << " ]";
5925     subMeshOrder.push_back( subMeshIds );
5926
5927     // clear collected submeshes
5928     set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
5929     for ( ; clrIt != subMeshToClear.end(); clrIt++ )
5930       if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
5931         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
5932   }
5933   aPythonDump << " ])";
5934
5935   mesh.SetMeshOrder( subMeshOrder );
5936   res = true;
5937   
5938   return res;
5939 }
5940
5941 //=============================================================================
5942 /*!
5943  * \brief Convert submesh ids into submesh interfaces
5944  */
5945 //=============================================================================
5946
5947 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt&     theIdsOrder,
5948                                      SMESH::submesh_array_array& theResOrder,
5949                                      const bool                  theIsDump)
5950 {
5951   int nbSet = theIdsOrder.size();
5952   TPythonDump aPythonDump; // prevent dump of called methods
5953   if ( theIsDump )
5954     aPythonDump << "[ ";
5955   theResOrder.length(nbSet);
5956   TListOfListOfInt::const_iterator it = theIdsOrder.begin();
5957   int listIndx = 0;
5958   for( ; it != theIdsOrder.end(); it++ ) {
5959     // translate submesh identificators into submesh objects
5960     //  takeing into account real number of concurrent lists
5961     const TListOfInt& aSubOrder = (*it);
5962     if (!aSubOrder.size())
5963       continue;
5964     if ( theIsDump )
5965       aPythonDump << "[ ";
5966     // convert shape indeces into interfaces
5967     SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
5968     aResSubSet->length(aSubOrder.size());
5969     TListOfInt::const_iterator subIt = aSubOrder.begin();
5970     int j;
5971     for( j = 0; subIt != aSubOrder.end(); subIt++ ) {
5972       if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
5973         continue;
5974       SMESH::SMESH_subMesh_var subMesh =
5975         SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
5976       if ( theIsDump ) {
5977         if ( j > 0 )
5978           aPythonDump << ", ";
5979         aPythonDump << subMesh;
5980       }
5981       aResSubSet[ j++ ] = subMesh;
5982     }
5983     if ( theIsDump )
5984       aPythonDump << " ]";
5985     if ( j > 1 )
5986       theResOrder[ listIndx++ ] = aResSubSet;
5987   }
5988   // correct number of lists
5989   theResOrder.length( listIndx );
5990
5991   if ( theIsDump ) {
5992     // finilise python dump
5993     aPythonDump << " ]";
5994     aPythonDump << " = " << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshOrder()";
5995   }
5996 }
5997
5998 //================================================================================
5999 //
6000 // Implementation of SMESH_MeshPartDS
6001 //
6002 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
6003   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
6004 {
6005   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
6006   SMESH_Mesh_i*       mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
6007
6008   _meshDS = mesh_i->GetImpl().GetMeshDS();
6009
6010   SetPersistentId( _meshDS->GetPersistentId() );
6011
6012   if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
6013   {
6014     // <meshPart> is the whole mesh
6015     myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
6016     // copy groups
6017     set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
6018     myGroupSet = _meshDS->GetGroups();
6019   }
6020   else
6021   {
6022     TMeshInfo tmpInfo;
6023     SMESH::long_array_var           anIDs = meshPart->GetIDs();
6024     SMESH::array_of_ElementType_var types = meshPart->GetTypes();
6025     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
6026     {
6027       for (int i=0; i < anIDs->length(); i++)
6028         if ( const SMDS_MeshNode * n = _meshDS->FindNode(anIDs[i]))
6029           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
6030             tmpInfo.Add( n );
6031     }
6032     else
6033     {
6034       for (int i=0; i < anIDs->length(); i++)
6035         if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
6036           if ( _elements[ e->GetType() ].insert( e ).second )
6037           {
6038             tmpInfo.Add( e );
6039             SMDS_ElemIteratorPtr nIt = e->nodesIterator();
6040             while ( nIt->more() )
6041             {
6042               const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
6043               if ( _elements[ SMDSAbs_Node ].insert( n ).second )
6044                 tmpInfo.Add( n );
6045             }
6046           }
6047     }
6048     myInfo = tmpInfo;
6049
6050     ShapeToMesh( _meshDS->ShapeToMesh() );
6051
6052     _meshDS = 0; // to enforce iteration on _elements and _nodes
6053   }
6054 }
6055 // -------------------------------------------------------------------------------------
6056 SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
6057   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
6058 {
6059   TMeshInfo tmpInfo;
6060   list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
6061   for ( ; partIt != meshPart.end(); ++partIt )
6062     if ( const SMDS_MeshElement * e = *partIt )
6063       if ( _elements[ e->GetType() ].insert( e ).second )
6064       {
6065         tmpInfo.Add( e );
6066         SMDS_ElemIteratorPtr nIt = e->nodesIterator();
6067         while ( nIt->more() )
6068         {
6069           const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
6070           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
6071             tmpInfo.Add( n );
6072         }
6073       }
6074   myInfo = tmpInfo;
6075 }
6076 // -------------------------------------------------------------------------------------
6077 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
6078 {
6079   if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
6080
6081   typedef SMDS_SetIterator
6082     <const SMDS_MeshElement*,
6083     TIDSortedElemSet::const_iterator,
6084     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
6085     SMDS_MeshElement::GeomFilter
6086     > TIter;
6087
6088   SMDSAbs_ElementType type = SMDS_MeshCell::toSmdsType( geomType );
6089
6090   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
6091                                           _elements[type].end(),
6092                                           SMDS_MeshElement::GeomFilter( geomType )));
6093 }
6094 // -------------------------------------------------------------------------------------
6095 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
6096 {
6097   if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
6098
6099   typedef SMDS_SetIterator
6100     <const SMDS_MeshElement*,
6101     TIDSortedElemSet::const_iterator,
6102     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
6103     SMDS_MeshElement::EntityFilter
6104     > TIter;
6105
6106   SMDSAbs_ElementType type = SMDS_MeshCell::toSmdsType( entity );
6107
6108   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
6109                                           _elements[type].end(),
6110                                           SMDS_MeshElement::EntityFilter( entity )));
6111 }
6112 // -------------------------------------------------------------------------------------
6113 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
6114 {
6115   typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
6116   if ( type == SMDSAbs_All && !_meshDS )
6117   {
6118     typedef vector< SMDS_ElemIteratorPtr > TIterVec;
6119     TIterVec iterVec;
6120     for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
6121       if ( !_elements[i].empty() && i != SMDSAbs_Node )
6122         iterVec.push_back
6123           ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
6124
6125     typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
6126     return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
6127   }
6128   return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
6129       ( new TIter( _elements[type].begin(), _elements[type].end() ));
6130 }
6131 // -------------------------------------------------------------------------------------
6132 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType)                       \
6133   iterType SMESH_MeshPartDS::methName( bool idInceasingOrder) const                 \
6134   {                                                                                 \
6135     typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
6136     return _meshDS ? _meshDS->methName(idInceasingOrder) : iterType                 \
6137       ( new TIter( _elements[elemType].begin(), _elements[elemType].end() ));       \
6138   }
6139 // -------------------------------------------------------------------------------------
6140 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
6141 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
6142 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
6143 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
6144 #undef _GET_ITER_DEFINE
6145 //
6146 // END Implementation of SMESH_MeshPartDS
6147 //
6148 //================================================================================
6149
6150