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