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