Salome HOME
23627: [IMACS] ASERIS: project point to the mesh and create a slot
[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 ( int i = 0; i < elem->NbNodes(); ++i )
4724         aResult[ i ] = elem->GetNode( i )->GetID();
4725     }
4726   }
4727   return aResult._retn();
4728 }
4729
4730 //=============================================================================
4731 /*!
4732  * Returns true if given node is medium node
4733  * in given quadratic element
4734  */
4735 //=============================================================================
4736
4737 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
4738 {
4739   if ( _preMeshInfo )
4740     _preMeshInfo->FullLoadFromFile();
4741
4742   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4743   if ( aMeshDS == NULL ) return false;
4744   // try to find node
4745   const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
4746   if(!aNode) return false;
4747   // try to find element
4748   const SMDS_MeshElement* elem = aMeshDS->FindElement(ide);
4749   if(!elem) return false;
4750
4751   return elem->IsMediumNode(aNode);
4752 }
4753
4754
4755 //=============================================================================
4756 /*!
4757  * Returns true if given node is medium node
4758  * in one of quadratic elements
4759  */
4760 //=============================================================================
4761
4762 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
4763                                                    SMESH::ElementType theElemType)
4764 {
4765   if ( _preMeshInfo )
4766     _preMeshInfo->FullLoadFromFile();
4767
4768   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4769   if ( aMeshDS == NULL ) return false;
4770
4771   // try to find node
4772   const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
4773   if(!aNode) return false;
4774
4775   SMESH_MesherHelper aHelper( *(_impl) );
4776
4777   SMDSAbs_ElementType aType;
4778   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
4779   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
4780   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
4781   else aType = SMDSAbs_All;
4782
4783   return aHelper.IsMedium(aNode,aType);
4784 }
4785
4786
4787 //=============================================================================
4788 /*!
4789  * Returns number of edges for given element
4790  */
4791 //=============================================================================
4792
4793 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
4794 {
4795   if ( _preMeshInfo )
4796     _preMeshInfo->FullLoadFromFile();
4797
4798   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4799   if ( aMeshDS == NULL ) return -1;
4800   const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
4801   if(!elem) return -1;
4802   return elem->NbEdges();
4803 }
4804
4805
4806 //=============================================================================
4807 /*!
4808  * Returns number of faces for given element
4809  */
4810 //=============================================================================
4811
4812 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
4813 {
4814   if ( _preMeshInfo )
4815     _preMeshInfo->FullLoadFromFile();
4816
4817   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4818   if ( aMeshDS == NULL ) return -1;
4819   const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
4820   if(!elem) return -1;
4821   return elem->NbFaces();
4822 }
4823
4824 //=======================================================================
4825 //function : GetElemFaceNodes
4826 //purpose  : Returns nodes of given face (counted from zero) for given element.
4827 //=======================================================================
4828
4829 SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long  elemId,
4830                                                   CORBA::Short faceIndex)
4831 {
4832   if ( _preMeshInfo )
4833     _preMeshInfo->FullLoadFromFile();
4834
4835   SMESH::long_array_var aResult = new SMESH::long_array();
4836   if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
4837   {
4838     if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(elemId) )
4839     {
4840       SMDS_VolumeTool vtool( elem );
4841       if ( faceIndex < vtool.NbFaces() )
4842       {
4843         aResult->length( vtool.NbFaceNodes( faceIndex ));
4844         const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
4845         for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
4846           aResult[ i ] = nn[ i ]->GetID();
4847       }
4848     }
4849   }
4850   return aResult._retn();
4851 }
4852
4853 //=======================================================================
4854 //function : GetElemFaceNodes
4855 //purpose  : Returns three components of normal of given mesh face.
4856 //=======================================================================
4857
4858 SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long    elemId,
4859                                                  CORBA::Boolean normalized)
4860 {
4861   if ( _preMeshInfo )
4862     _preMeshInfo->FullLoadFromFile();
4863
4864   SMESH::double_array_var aResult = new SMESH::double_array();
4865
4866   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
4867   {
4868     gp_XYZ normal;
4869     if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, normalized ))
4870     {
4871       aResult->length( 3 );
4872       aResult[ 0 ] = normal.X();
4873       aResult[ 1 ] = normal.Y();
4874       aResult[ 2 ] = normal.Z();
4875     }
4876   }
4877   return aResult._retn();
4878 }
4879
4880 //=======================================================================
4881 //function : FindElementByNodes
4882 //purpose  : Returns an element based on all given nodes.
4883 //=======================================================================
4884
4885 CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
4886 {
4887   if ( _preMeshInfo )
4888     _preMeshInfo->FullLoadFromFile();
4889
4890   CORBA::Long elemID(0);
4891   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
4892   {
4893     vector< const SMDS_MeshNode * > nn( nodes.length() );
4894     for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
4895       if ( !( nn[i] = mesh->FindNode( nodes[i] )))
4896         return elemID;
4897
4898     const SMDS_MeshElement* elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/false );
4899     if ( !elem && ( _impl->NbEdges  ( ORDER_QUADRATIC ) ||
4900                     _impl->NbFaces  ( ORDER_QUADRATIC ) ||
4901                     _impl->NbVolumes( ORDER_QUADRATIC )))
4902       elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
4903
4904     if ( elem ) elemID = CORBA::Long( elem->GetID() );
4905   }
4906   return elemID;
4907 }
4908
4909 //================================================================================
4910 /*!
4911  * \brief Return elements including all given nodes.
4912  */
4913 //================================================================================
4914
4915 SMESH::long_array* SMESH_Mesh_i::GetElementsByNodes(const SMESH::long_array& nodes,
4916                                                     SMESH::ElementType       elemType)
4917 {
4918   if ( _preMeshInfo )
4919     _preMeshInfo->FullLoadFromFile();
4920
4921   SMESH::long_array_var result = new SMESH::long_array();
4922
4923   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
4924   {
4925     vector< const SMDS_MeshNode * > nn( nodes.length() );
4926     for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
4927       nn[i] = mesh->FindNode( nodes[i] );
4928
4929     std::vector<const SMDS_MeshElement *> elems;
4930     mesh->GetElementsByNodes( nn, elems, (SMDSAbs_ElementType) elemType );
4931     result->length( elems.size() );
4932     for ( size_t i = 0; i < elems.size(); ++i )
4933       result[i] = elems[i]->GetID();
4934   }
4935   return result._retn();
4936 }
4937
4938 //=============================================================================
4939 /*!
4940  * Returns true if given element is polygon
4941  */
4942 //=============================================================================
4943
4944 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
4945 {
4946   if ( _preMeshInfo )
4947     _preMeshInfo->FullLoadFromFile();
4948
4949   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4950   if ( aMeshDS == NULL ) return false;
4951   const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
4952   if(!elem) return false;
4953   return elem->IsPoly();
4954 }
4955
4956
4957 //=============================================================================
4958 /*!
4959  * Returns true if given element is quadratic
4960  */
4961 //=============================================================================
4962
4963 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
4964 {
4965   if ( _preMeshInfo )
4966     _preMeshInfo->FullLoadFromFile();
4967
4968   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4969   if ( aMeshDS == NULL ) return false;
4970   const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
4971   if(!elem) return false;
4972   return elem->IsQuadratic();
4973 }
4974
4975 //=============================================================================
4976 /*!
4977  * Returns diameter of ball discrete element or zero in case of an invalid \a id
4978  */
4979 //=============================================================================
4980
4981 CORBA::Double SMESH_Mesh_i::GetBallDiameter(CORBA::Long id)
4982 {
4983   if ( _preMeshInfo )
4984     _preMeshInfo->FullLoadFromFile();
4985
4986   if ( const SMDS_BallElement* ball =
4987        SMDS_Mesh::DownCast<SMDS_BallElement>( _impl->GetMeshDS()->FindElement( id )))
4988     return ball->GetDiameter();
4989
4990   return 0;
4991 }
4992
4993 //=============================================================================
4994 /*!
4995  * Returns bary center for given element
4996  */
4997 //=============================================================================
4998
4999 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
5000 {
5001   if ( _preMeshInfo )
5002     _preMeshInfo->FullLoadFromFile();
5003
5004   SMESH::double_array_var aResult = new SMESH::double_array();
5005   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5006   if ( aMeshDS == NULL )
5007     return aResult._retn();
5008
5009   const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5010   if(!elem)
5011     return aResult._retn();
5012
5013   if(elem->GetType()==SMDSAbs_Volume) {
5014     SMDS_VolumeTool aTool;
5015     if(aTool.Set(elem)) {
5016       aResult->length(3);
5017       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
5018         aResult->length(0);
5019     }
5020   }
5021   else {
5022     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
5023     int nbn = 0;
5024     double x=0., y=0., z=0.;
5025     for(; anIt->more(); ) {
5026       nbn++;
5027       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
5028       x += aNode->X();
5029       y += aNode->Y();
5030       z += aNode->Z();
5031     }
5032     if(nbn>0) {
5033       // add coordinates
5034       aResult->length(3);
5035       aResult[0] = x/nbn;
5036       aResult[1] = y/nbn;
5037       aResult[2] = z/nbn;
5038     }
5039   }
5040
5041   return aResult._retn();
5042 }
5043
5044 //================================================================================
5045 /*!
5046  * \brief Create a group of elements preventing computation of a sub-shape
5047  */
5048 //================================================================================
5049
5050 SMESH::ListOfGroups*
5051 SMESH_Mesh_i::MakeGroupsOfBadInputElements( int         theSubShapeID,
5052                                             const char* theGroupName )
5053   throw ( SALOME::SALOME_Exception )
5054 {
5055   Unexpect aCatch(SALOME_SalomeException);
5056
5057   if ( !theGroupName || strlen( theGroupName) == 0 )
5058     THROW_SALOME_CORBA_EXCEPTION( "empty group name",SALOME::BAD_PARAM );
5059
5060   SMESH::ListOfGroups_var groups = new SMESH::ListOfGroups;
5061   ::SMESH_MeshEditor::ElemFeatures elemType;
5062
5063   // submesh by subshape id
5064   if ( !_impl->HasShapeToMesh() ) theSubShapeID = 1;
5065   if ( SMESH_subMesh * sm = _impl->GetSubMeshContaining( theSubShapeID ))
5066   {
5067     // compute error
5068     SMESH_ComputeErrorPtr error = sm->GetComputeError();
5069     if ( error && error->HasBadElems() )
5070     {
5071       // sort bad elements by type
5072       vector< const SMDS_MeshElement* > elemsByType[ SMDSAbs_NbElementTypes ];
5073       const list<const SMDS_MeshElement*>& badElems =
5074         static_cast<SMESH_BadInputElements*>( error.get() )->myBadElements;
5075       list<const SMDS_MeshElement*>::const_iterator elemIt  = badElems.begin();
5076       list<const SMDS_MeshElement*>::const_iterator elemEnd = badElems.end();
5077       for ( ; elemIt != elemEnd; ++elemIt )
5078       {
5079         const SMDS_MeshElement* elem = *elemIt;
5080         if ( !elem ) continue;
5081
5082         if ( elem->GetID() < 1 )
5083         {
5084           // elem is a temporary element, make a real element
5085           vector< const SMDS_MeshNode* > nodes;
5086           SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
5087           while ( nIt->more() && elem )
5088           {
5089             nodes.push_back( nIt->next() );
5090             if ( nodes.back()->GetID() < 1 )
5091               elem = 0;  // a temporary element on temporary nodes
5092           }
5093           if ( elem )
5094           {
5095             ::SMESH_MeshEditor editor( _impl );
5096             elem = editor.AddElement( nodes, elemType.Init( elem ));
5097           }
5098         }
5099         if ( elem )
5100           elemsByType[ elem->GetType() ].push_back( elem );
5101       }
5102
5103       // how many groups to create?
5104       int nbTypes = 0;
5105       for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
5106         nbTypes += int( !elemsByType[ i ].empty() );
5107       groups->length( nbTypes );
5108
5109       // create groups
5110       for ( int i = 0, iG = -1; i < SMDSAbs_NbElementTypes; ++i )
5111       {
5112         vector< const SMDS_MeshElement* >& elems = elemsByType[ i ];
5113         if ( elems.empty() ) continue;
5114
5115         groups[ ++iG ] = createGroup( SMESH::ElementType(i), theGroupName );
5116         if ( _gen_i->CanPublishInStudy( groups[ iG ] ))
5117         {
5118           SMESH::SMESH_Mesh_var mesh = _this();
5119           SALOMEDS::SObject_wrap aSO =
5120             _gen_i->PublishGroup( mesh, groups[ iG ],
5121                                  GEOM::GEOM_Object::_nil(), theGroupName);
5122         }
5123         SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
5124         if ( !grp_i ) continue;
5125
5126         if ( SMESHDS_Group*  grpDS = dynamic_cast< SMESHDS_Group* >( grp_i->GetGroupDS() ))
5127           for ( size_t iE = 0; iE < elems.size(); ++iE )
5128             grpDS->SMDSGroup().Add( elems[ iE ]);
5129       }
5130     }
5131   }
5132
5133   return groups._retn();
5134 }
5135
5136 //=============================================================================
5137 /*!
5138  * Create and publish group servants if any groups were imported or created anyhow
5139  */
5140 //=============================================================================
5141
5142 void SMESH_Mesh_i::CreateGroupServants()
5143 {
5144   SMESH::SMESH_Mesh_var aMesh = _this();
5145
5146   set<int> addedIDs;
5147   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
5148   while ( groupIt->more() )
5149   {
5150     ::SMESH_Group* group = groupIt->next();
5151     int            anId = group->GetGroupDS()->GetID();
5152
5153     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
5154     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5155       continue;
5156     addedIDs.insert( anId );
5157
5158     SMESH_GroupBase_i* aGroupImpl;
5159     TopoDS_Shape       shape;
5160     if ( SMESHDS_GroupOnGeom* groupOnGeom =
5161          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
5162     {
5163       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
5164       shape      = groupOnGeom->GetShape();
5165     }
5166     else {
5167       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
5168     }
5169
5170     SMESH::SMESH_GroupBase_var groupVar = aGroupImpl->_this();
5171     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
5172     aGroupImpl->Register();
5173
5174     // register CORBA object for persistence
5175     int nextId = _gen_i->RegisterObject( groupVar );
5176     if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
5177     else        { nextId = 0; } // avoid "unused variable" warning in release mode
5178
5179     // publishing the groups in the study
5180     GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
5181     _gen_i->PublishGroup( aMesh, groupVar, shapeVar, group->GetName());
5182   }
5183   if ( !addedIDs.empty() )
5184   {
5185     // python dump
5186     set<int>::iterator id = addedIDs.begin();
5187     for ( ; id != addedIDs.end(); ++id )
5188     {
5189       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(*id);
5190       int i = std::distance( _mapGroups.begin(), it );
5191       TPythonDump() << it->second << " = " << aMesh << ".GetGroups()[ "<< i << " ]";
5192     }
5193   }
5194 }
5195
5196 //=============================================================================
5197 /*!
5198  * \brief Return true if all sub-meshes are computed OK - to update an icon
5199  */
5200 //=============================================================================
5201
5202 bool SMESH_Mesh_i::IsComputedOK()
5203 {
5204   return _impl->IsComputedOK();
5205 }
5206
5207 //=============================================================================
5208 /*!
5209  * \brief Return groups cantained in _mapGroups by their IDs
5210  */
5211 //=============================================================================
5212
5213 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
5214 {
5215   int nbGroups = groupIDs.size();
5216   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
5217   aList->length( nbGroups );
5218
5219   list<int>::const_iterator ids = groupIDs.begin();
5220   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
5221   {
5222     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
5223     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5224       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
5225   }
5226   aList->length( nbGroups );
5227   return aList._retn();
5228 }
5229
5230 //=============================================================================
5231 /*!
5232  * \brief Return information about imported file
5233  */
5234 //=============================================================================
5235
5236 SMESH::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
5237 {
5238   SMESH::MedFileInfo_var res( _medFileInfo );
5239   if ( !res.operator->() ) {
5240     res = new SMESH::MedFileInfo;
5241     res->fileName = "";
5242     res->fileSize = res->major = res->minor = res->release = -1;
5243   }
5244   return res._retn();
5245 }
5246
5247 //=======================================================================
5248 //function : FileInfoToString
5249 //purpose  : Persistence of file info
5250 //=======================================================================
5251
5252 std::string SMESH_Mesh_i::FileInfoToString()
5253 {
5254   std::string s;
5255   if ( &_medFileInfo.in() && _medFileInfo->fileName[0] )
5256   {
5257     s = SMESH_Comment( _medFileInfo->fileSize )
5258       << " " << _medFileInfo->major
5259       << " " << _medFileInfo->minor
5260       << " " << _medFileInfo->release
5261       << " " << _medFileInfo->fileName;
5262   }
5263   return s;
5264 }
5265
5266 //=======================================================================
5267 //function : FileInfoFromString
5268 //purpose  : Persistence of file info
5269 //=======================================================================
5270
5271 void SMESH_Mesh_i::FileInfoFromString(const std::string& info)
5272 {
5273   std::string size, major, minor, release, fileName;
5274   std::istringstream is(info);
5275   is >> size >> major >> minor >> release;
5276   fileName = info.data() + ( size.size()   + 1 +
5277                              major.size()  + 1 +
5278                              minor.size()  + 1 +
5279                              release.size()+ 1 );
5280
5281   _medFileInfo           = new SMESH::MedFileInfo();
5282   _medFileInfo->fileName = fileName.c_str();
5283   _medFileInfo->fileSize = atoi( size.c_str() );
5284   _medFileInfo->major    = atoi( major.c_str() );
5285   _medFileInfo->minor    = atoi( minor.c_str() );
5286   _medFileInfo->release  = atoi( release.c_str() );
5287 }
5288
5289 //=============================================================================
5290 /*!
5291  * \brief Pass names of mesh groups from study to mesh DS
5292  */
5293 //=============================================================================
5294
5295 void SMESH_Mesh_i::checkGroupNames()
5296 {
5297   int nbGrp = NbGroups();
5298   if ( !nbGrp )
5299     return;
5300
5301   SMESH::ListOfGroups* grpList = 0;
5302   // avoid dump of "GetGroups"
5303   {
5304     // store python dump into a local variable inside local scope
5305     SMESH::TPythonDump pDump; // do not delete this line of code
5306     grpList = GetGroups();
5307   }
5308
5309   for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
5310     SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
5311     if ( !aGrp )
5312       continue;
5313     SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aGrp );
5314     if ( aGrpSO->_is_nil() )
5315       continue;
5316     // correct name of the mesh group if necessary
5317     const char* guiName = aGrpSO->GetName();
5318     if ( strcmp(guiName, aGrp->GetName()) )
5319       aGrp->SetName( guiName );
5320   }
5321 }
5322
5323 //=============================================================================
5324 /*!
5325  * \brief Sets list of notebook variables used for Mesh operations separated by ":" symbol
5326  */
5327 //=============================================================================
5328 void SMESH_Mesh_i::SetParameters(const char* theParameters)
5329 {
5330   SMESH_Gen_i::GetSMESHGen()->UpdateParameters( CORBA::Object_var( _this() ).in(),
5331                                                 theParameters );
5332 }
5333
5334 //=============================================================================
5335 /*!
5336  * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
5337  */
5338 //=============================================================================
5339
5340 char* SMESH_Mesh_i::GetParameters()
5341 {
5342   return SMESH_Gen_i::GetSMESHGen()->GetParameters( SMESH::SMESH_Mesh_var( _this()) );
5343 }
5344
5345 //=============================================================================
5346 /*!
5347  * \brief Returns list of notebook variables used for last Mesh operation
5348  */
5349 //=============================================================================
5350 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
5351 {
5352   SMESH::string_array_var aResult = new SMESH::string_array();
5353   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
5354   if(gen) {
5355     CORBA::String_var aParameters = GetParameters();
5356     SALOMEDS::ListOfListOfStrings_var aSections = SMESH_Gen_i::getStudyServant()->ParseVariables(aParameters);
5357     if ( aSections->length() > 0 ) {
5358       SALOMEDS::ListOfStrings aVars = aSections[ aSections->length() - 1 ];
5359       aResult->length( aVars.length() );
5360       for ( CORBA::ULong i = 0;i < aVars.length(); i++ )
5361         aResult[i] = CORBA::string_dup( aVars[i] );
5362     }
5363   }
5364   return aResult._retn();
5365 }
5366
5367 //=======================================================================
5368 //function : GetTypes
5369 //purpose  : Returns types of elements it contains
5370 //=======================================================================
5371
5372 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
5373 {
5374   if ( _preMeshInfo )
5375     return _preMeshInfo->GetTypes();
5376
5377   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
5378
5379   types->length( 5 );
5380   int nbTypes = 0;
5381   if (_impl->NbEdges())      types[nbTypes++] = SMESH::EDGE;
5382   if (_impl->NbFaces())      types[nbTypes++] = SMESH::FACE;
5383   if (_impl->NbVolumes())    types[nbTypes++] = SMESH::VOLUME;
5384   if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
5385   if (_impl->NbBalls())      types[nbTypes++] = SMESH::BALL;
5386   if (_impl->NbNodes() &&
5387       nbTypes == 0 )         types[nbTypes++] = SMESH::NODE;
5388   types->length( nbTypes );
5389
5390   return types._retn();
5391 }
5392
5393 //=======================================================================
5394 //function : GetMesh
5395 //purpose  : Returns self
5396 //=======================================================================
5397
5398 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
5399 {
5400   return SMESH::SMESH_Mesh::_duplicate( _this() );
5401 }
5402
5403 //=======================================================================
5404 //function : IsMeshInfoCorrect
5405 //purpose  : * Returns false if GetMeshInfo() returns incorrect information that may
5406 //           * happen if mesh data is not yet fully loaded from the file of study.
5407 //=======================================================================
5408
5409 bool SMESH_Mesh_i::IsMeshInfoCorrect()
5410 {
5411   return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
5412 }
5413
5414 //=============================================================================
5415 /*!
5416  * \brief Returns number of mesh elements per each \a EntityType
5417  */
5418 //=============================================================================
5419
5420 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
5421 {
5422   if ( _preMeshInfo )
5423     return _preMeshInfo->GetMeshInfo();
5424
5425   SMESH::long_array_var aRes = new SMESH::long_array();
5426   aRes->length(SMESH::Entity_Last);
5427   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
5428     aRes[i] = 0;
5429   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5430   if (!aMeshDS)
5431     return aRes._retn();
5432   const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
5433   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
5434     aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
5435   return aRes._retn();
5436 }
5437
5438 //=============================================================================
5439 /*!
5440  * \brief Returns number of mesh elements per each \a ElementType
5441  */
5442 //=============================================================================
5443
5444 SMESH::long_array* SMESH_Mesh_i::GetNbElementsByType()
5445 {
5446   SMESH::long_array_var aRes = new SMESH::long_array();
5447   aRes->length(SMESH::NB_ELEMENT_TYPES);
5448   for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
5449     aRes[ i ] = 0;
5450
5451   const SMDS_MeshInfo* meshInfo = 0;
5452   if ( _preMeshInfo )
5453     meshInfo = _preMeshInfo;
5454   else if ( SMESHDS_Mesh* meshDS = _impl->GetMeshDS() )
5455     meshInfo = & meshDS->GetMeshInfo();
5456
5457   if (meshInfo)
5458     for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
5459       aRes[i] = meshInfo->NbElements((SMDSAbs_ElementType)i);
5460
5461   return aRes._retn();
5462 }
5463
5464 //=============================================================================
5465 /*
5466  * Collect statistic of mesh elements given by iterator
5467  */
5468 //=============================================================================
5469
5470 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
5471                                    SMESH::long_array&         theInfo)
5472 {
5473   if (!theItr) return;
5474   while (theItr->more())
5475     theInfo[ theItr->next()->GetEntityType() ]++;
5476 }
5477 //=============================================================================
5478 /*
5479  * Returns mesh unstructed grid information.
5480  */
5481 //=============================================================================
5482
5483 SALOMEDS::TMPFile* SMESH_Mesh_i::GetVtkUgStream()
5484 {
5485   SALOMEDS::TMPFile_var SeqFile;
5486   if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() ) {
5487     SMDS_UnstructuredGrid* aGrid = aMeshDS->GetGrid();
5488     if(aGrid) {
5489       vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
5490       aWriter->WriteToOutputStringOn();
5491       aWriter->SetInputData(aGrid);
5492       aWriter->SetFileTypeToBinary();
5493       aWriter->Write();
5494       char* str = aWriter->GetOutputString();
5495       int size = aWriter->GetOutputStringLength();
5496
5497       //Allocate octet buffer of required size
5498       CORBA::Octet* OctetBuf = SALOMEDS::TMPFile::allocbuf(size);
5499       //Copy ostrstream content to the octet buffer
5500       memcpy(OctetBuf, str, size);
5501       //Create and return TMPFile
5502       SeqFile = new SALOMEDS::TMPFile(size, size, OctetBuf, 1);
5503       aWriter->Delete();
5504     }
5505   }
5506   return SeqFile._retn();
5507 }
5508
5509 //=============================================================================
5510 namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
5511            *                                             SMESH::ElementType        type) */
5512 {
5513   using namespace SMESH::Controls;
5514   //-----------------------------------------------------------------------------
5515   struct PredicateIterator : public SMDS_ElemIterator
5516   {
5517     SMDS_ElemIteratorPtr    _elemIter;
5518     PredicatePtr            _predicate;
5519     const SMDS_MeshElement* _elem;
5520     SMDSAbs_ElementType     _type;
5521
5522     PredicateIterator( SMDS_ElemIteratorPtr iterator,
5523                        PredicatePtr         predicate,
5524                        SMDSAbs_ElementType  type):
5525       _elemIter(iterator), _predicate(predicate), _type(type)
5526     {
5527       next();
5528     }
5529     virtual bool more()
5530     {
5531       return _elem;
5532     }
5533     virtual const SMDS_MeshElement* next()
5534     {
5535       const SMDS_MeshElement* res = _elem;
5536       _elem = 0;
5537       while ( _elemIter->more() && !_elem )
5538       {
5539         if ((_elem = _elemIter->next()) &&
5540             (( _type != SMDSAbs_All && _type != _elem->GetType() ) ||
5541              ( !_predicate->IsSatisfy( _elem->GetID() ))))
5542           _elem = 0;
5543       }
5544       return res;
5545     }
5546   };
5547
5548   //-----------------------------------------------------------------------------
5549   struct IDSourceIterator : public SMDS_ElemIterator
5550   {
5551     const CORBA::Long*        _idPtr;
5552     const CORBA::Long*        _idEndPtr;
5553     SMESH::long_array_var     _idArray;
5554     const SMDS_Mesh*          _mesh;
5555     const SMDSAbs_ElementType _type;
5556     const SMDS_MeshElement*   _elem;
5557
5558     IDSourceIterator( const SMDS_Mesh*    mesh,
5559                       const CORBA::Long*  ids,
5560                       const int           nbIds,
5561                       SMDSAbs_ElementType type):
5562       _idPtr( ids ), _idEndPtr( ids + nbIds ), _mesh( mesh ), _type( type ), _elem( 0 )
5563     {
5564       if ( _idPtr && nbIds && _mesh )
5565         next();
5566     }
5567     IDSourceIterator( const SMDS_Mesh*    mesh,
5568                       SMESH::long_array*  idArray,
5569                       SMDSAbs_ElementType type):
5570       _idPtr( 0 ), _idEndPtr( 0 ), _idArray( idArray), _mesh( mesh ), _type( type ), _elem( 0 )
5571     {
5572       if ( idArray && _mesh )
5573       {
5574         _idPtr    = &_idArray[0];
5575         _idEndPtr = _idPtr + _idArray->length();
5576         next();
5577       }
5578     }
5579     virtual bool more()
5580     {
5581       return _elem;
5582     }
5583     virtual const SMDS_MeshElement* next()
5584     {
5585       const SMDS_MeshElement* res = _elem;
5586       _elem = 0;
5587       while ( _idPtr < _idEndPtr && !_elem )
5588       {
5589         if ( _type == SMDSAbs_Node )
5590         {
5591           _elem = _mesh->FindNode( *_idPtr++ );
5592         }
5593         else if ((_elem = _mesh->FindElement( *_idPtr++ )) &&
5594                  (_elem->GetType() != _type && _type != SMDSAbs_All ))
5595         {
5596           _elem = 0;
5597         }
5598       }
5599       return res;
5600     }
5601   };
5602   //-----------------------------------------------------------------------------
5603
5604   struct NodeOfElemIterator : public SMDS_ElemIterator
5605   {
5606     TColStd_MapOfInteger    _checkedNodeIDs;
5607     SMDS_ElemIteratorPtr    _elemIter;
5608     SMDS_ElemIteratorPtr    _nodeIter;
5609     const SMDS_MeshElement* _node;
5610
5611     NodeOfElemIterator( SMDS_ElemIteratorPtr iter ): _elemIter( iter ), _node( 0 )
5612     {
5613       if ( _elemIter && _elemIter->more() )
5614       {
5615         _nodeIter = _elemIter->next()->nodesIterator();
5616         next();
5617       }
5618     }
5619     virtual bool more()
5620     {
5621       return _node;
5622     }
5623     virtual const SMDS_MeshElement* next()
5624     {
5625       const SMDS_MeshElement* res = _node;
5626       _node = 0;
5627       while ( !_node && ( _elemIter->more() || _nodeIter->more() ))
5628       {
5629         if ( _nodeIter->more() )
5630         {
5631           _node = _nodeIter->next();
5632           if ( !_checkedNodeIDs.Add( _node->GetID() ))
5633             _node = 0;
5634         }
5635         else
5636         {
5637           _nodeIter = _elemIter->next()->nodesIterator();
5638         }
5639       }
5640       return res;
5641     }
5642   };
5643 }
5644
5645 //=============================================================================
5646 /*
5647  * Return iterator on elements of given type in given object
5648  */
5649 //=============================================================================
5650
5651 SMDS_ElemIteratorPtr SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_ptr theObject,
5652                                                SMESH::ElementType        theType)
5653 {
5654   SMDS_ElemIteratorPtr  elemIt;
5655   bool                  typeOK = ( theType == SMESH::ALL );
5656   SMDSAbs_ElementType elemType = SMDSAbs_ElementType( theType );
5657
5658   SMESH::SMESH_Mesh_var meshVar = theObject->GetMesh();
5659   SMESH_Mesh_i*          mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( meshVar );
5660   if ( !mesh_i ) return elemIt;
5661   SMESHDS_Mesh*          meshDS = mesh_i->GetImpl().GetMeshDS();
5662
5663   if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
5664   {
5665     elemIt = meshDS->elementsIterator( elemType );
5666     typeOK = true;
5667   }
5668   else if ( SMESH_subMesh_i* submesh_i = SMESH::DownCast<SMESH_subMesh_i*>( theObject ))
5669   {
5670     SMESHDS_SubMesh* sm = ((SMESHDS_Mesh*) meshDS)->MeshElements( submesh_i->GetId() );
5671     if ( sm )
5672     {
5673       elemIt = sm->GetElements();
5674       if ( elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
5675       {
5676         typeOK = ( elemIt && elemIt->more() && elemIt->next()->GetType() == elemType );
5677         elemIt = typeOK ? sm->GetElements() : SMDS_ElemIteratorPtr();
5678       }
5679     }
5680   }
5681   else if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( theObject ))
5682   {
5683     SMESHDS_GroupBase* groupDS = group_i->GetGroupDS();
5684     if ( groupDS && ( elemType == groupDS->GetType()  ||
5685                       elemType == SMDSAbs_Node ||
5686                       elemType == SMDSAbs_All ))
5687     {
5688       elemIt = groupDS->GetElements();
5689       typeOK = ( groupDS->GetType() == elemType || elemType == SMDSAbs_All );
5690     }
5691   }
5692   else if ( SMESH::Filter_i* filter_i = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5693   {
5694     if ( filter_i->GetElementType() == theType ||
5695          filter_i->GetElementType() == SMESH::ALL ||
5696          elemType == SMDSAbs_Node ||
5697          elemType == SMDSAbs_All)
5698     {
5699       SMESH::Predicate_i* pred_i = filter_i->GetPredicate_i();
5700       if ( pred_i && pred_i->GetPredicate() )
5701       {
5702         SMDSAbs_ElementType filterType = SMDSAbs_ElementType( filter_i->GetElementType() );
5703         SMDS_ElemIteratorPtr allElemIt = meshDS->elementsIterator( filterType );
5704         SMDSAbs_ElementType   iterType = elemType == SMDSAbs_Node ? filterType : elemType;
5705         elemIt = SMDS_ElemIteratorPtr
5706           ( new PredicateIterator( allElemIt, pred_i->GetPredicate(), iterType ));
5707         typeOK = ( elemType == SMDSAbs_Node ? filterType == SMDSAbs_Node : elemIt->more() );
5708       }
5709     }
5710   }
5711   else
5712   {
5713     SMESH::array_of_ElementType_var types = theObject->GetTypes();
5714     const bool                    isNodes = ( types->length() == 1 && types[0] == SMESH::NODE );
5715     if ( isNodes && elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
5716       return elemIt;
5717     SMDSAbs_ElementType iterType = isNodes ? SMDSAbs_Node : elemType;
5718     if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theObject ))
5719     {
5720       int nbIds;
5721       if ( CORBA::Long* ids = SMESH_MeshEditor_i::GetTemporaryIDs( theObject, nbIds ))
5722         elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids, nbIds, iterType ));
5723     }
5724     else
5725     {
5726       SMESH::long_array_var ids = theObject->GetIDs();
5727       elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids._retn(), iterType ));
5728     }
5729     typeOK = ( isNodes == ( elemType == SMDSAbs_Node )) || ( elemType == SMDSAbs_All );
5730   }
5731
5732   if ( elemIt && elemIt->more() && !typeOK )
5733   {
5734     if ( elemType == SMDSAbs_Node )
5735     {
5736       elemIt = SMDS_ElemIteratorPtr( new NodeOfElemIterator( elemIt ));
5737     }
5738     else
5739     {
5740       elemIt = SMDS_ElemIteratorPtr();
5741     }
5742   }
5743   return elemIt;
5744 }
5745
5746 //=============================================================================
5747 namespace // Finding concurrent hypotheses
5748 //=============================================================================
5749 {
5750
5751 /*!
5752  * \brief mapping of mesh dimension into shape type
5753  */
5754 TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
5755 {
5756   TopAbs_ShapeEnum aType = TopAbs_SOLID;
5757   switch ( theDim ) {
5758   case 0: aType = TopAbs_VERTEX; break;
5759   case 1: aType = TopAbs_EDGE; break;
5760   case 2: aType = TopAbs_FACE; break;
5761   case 3:
5762   default:aType = TopAbs_SOLID; break;
5763   }
5764   return aType;
5765 }
5766
5767 //-----------------------------------------------------------------------------
5768 /*!
5769  * \brief Internal structure used to find concurrent submeshes
5770  *
5771  * It represents a pair < submesh, concurrent dimension >, where
5772  * 'concurrent dimension' is dimension of shape where the submesh can concurrent
5773  *  with another submesh. In other words, it is dimension of a hypothesis assigned
5774  *  to submesh.
5775  */
5776 class SMESH_DimHyp
5777 {
5778  public:
5779   //! fields
5780   int _dim;    //!< a dimension the algo can build (concurrent dimension)
5781   int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
5782   TopTools_MapOfShape _shapeMap;
5783   SMESH_subMesh*      _subMesh;
5784   list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
5785
5786   //-----------------------------------------------------------------------------
5787   // Return the algorithm
5788   const SMESH_Algo* GetAlgo() const
5789   { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
5790
5791   //-----------------------------------------------------------------------------
5792   //! Constructors
5793   SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
5794                const int            theDim,
5795                const TopoDS_Shape&  theShape)
5796   {
5797     _subMesh = (SMESH_subMesh*)theSubMesh;
5798     SetShape( theDim, theShape );
5799   }
5800
5801   //-----------------------------------------------------------------------------
5802   //! set shape
5803   void SetShape(const int           theDim,
5804                 const TopoDS_Shape& theShape)
5805   {
5806     _dim = theDim;
5807     _ownDim = SMESH_Gen::GetShapeDim(theShape);
5808     if (_dim >= _ownDim)
5809       _shapeMap.Add( theShape );
5810     else {
5811       TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
5812       for( ; anExp.More(); anExp.Next() )
5813         _shapeMap.Add( anExp.Current() );
5814     }
5815   }
5816
5817   //-----------------------------------------------------------------------------
5818   //! Check sharing of sub-shapes
5819   static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
5820                                const TopTools_MapOfShape& theToFind,
5821                                const TopAbs_ShapeEnum     theType)
5822   {
5823     bool isShared = false;
5824     TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
5825     for (; !isShared && anItr.More(); anItr.Next() )
5826     {
5827       const TopoDS_Shape aSubSh = anItr.Key();
5828       // check for case when concurrent dimensions are same
5829       isShared = theToFind.Contains( aSubSh );
5830       // check for sub-shape with concurrent dimension
5831       TopExp_Explorer anExp( aSubSh, theType );
5832       for ( ; !isShared && anExp.More(); anExp.Next() )
5833         isShared = theToFind.Contains( anExp.Current() );
5834     }
5835     return isShared;
5836   }
5837
5838   //-----------------------------------------------------------------------------
5839   //! check algorithms
5840   static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
5841                         const SMESHDS_Hypothesis* theA2)
5842   {
5843     if ( !theA1 || !theA2 ||
5844          theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
5845          theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
5846       return false; // one of the hypothesis is not algorithm
5847     // check algorithm names (should be equal)
5848     return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
5849   }
5850
5851
5852   //-----------------------------------------------------------------------------
5853   //! Check if sub-shape hypotheses are concurrent
5854   bool IsConcurrent(const SMESH_DimHyp* theOther) const
5855   {
5856     if ( _subMesh == theOther->_subMesh )
5857       return false; // same sub-shape - should not be
5858
5859     // if ( <own dim of either of submeshes> == <concurrent dim> &&
5860     //      any of the two submeshes is not on COMPOUND shape )
5861     //  -> no concurrency
5862     bool meIsCompound    = (_subMesh->GetSubMeshDS() &&
5863                             _subMesh->GetSubMeshDS()->IsComplexSubmesh());
5864     bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
5865                             theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
5866     if ( (_ownDim == _dim  || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
5867       return false;
5868
5869 //     bool checkSubShape = ( _dim >= theOther->_dim )
5870 //       ? isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(theOther->_dim) )
5871 //       : isShareSubShapes( theOther->_shapeMap, _shapeMap, shapeTypeByDim(_dim) ) ;
5872     bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
5873     if ( !checkSubShape )
5874         return false;
5875
5876     // check algorithms to be same
5877     if ( !checkAlgo( this->GetAlgo(), theOther->GetAlgo() ))
5878       return true; // different algorithms -> concurrency !
5879
5880     // check hypothesises for concurrence (skip first as algorithm)
5881     int nbSame = 0;
5882     // pointers should be same, because it is referened from mesh hypothesis partition
5883     list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
5884     list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
5885     for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
5886       if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
5887         nbSame++;
5888     // the submeshes are concurrent if their algorithms has different parameters
5889     return nbSame != (int)theOther->_hypotheses.size() - 1;
5890   }
5891
5892   // Return true if algorithm of this SMESH_DimHyp is used if no
5893   // sub-mesh order is imposed by the user
5894   bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
5895   {
5896     // NeedDiscreteBoundary() algo has a higher priority
5897     if ( this    ->GetAlgo()->NeedDiscreteBoundary() !=
5898          theOther->GetAlgo()->NeedDiscreteBoundary() )
5899       return !this->GetAlgo()->NeedDiscreteBoundary();
5900
5901     return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
5902   }
5903
5904 }; // end of SMESH_DimHyp
5905 //-----------------------------------------------------------------------------
5906
5907 typedef list<const SMESH_DimHyp*> TDimHypList;
5908
5909 //-----------------------------------------------------------------------------
5910
5911 void addDimHypInstance(const int                               theDim,
5912                        const TopoDS_Shape&                     theShape,
5913                        const SMESH_Algo*                       theAlgo,
5914                        const SMESH_subMesh*                    theSubMesh,
5915                        const list <const SMESHDS_Hypothesis*>& theHypList,
5916                        TDimHypList*                            theDimHypListArr )
5917 {
5918   TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
5919   if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) {
5920     SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
5921     dimHyp->_hypotheses.push_front(theAlgo);
5922     listOfdimHyp.push_back( dimHyp );
5923   }
5924
5925   SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
5926   dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
5927                               theHypList.begin(), theHypList.end() );
5928 }
5929
5930 //-----------------------------------------------------------------------------
5931 void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
5932                            TDimHypList&        theListOfConcurr)
5933 {
5934   if ( theListOfConcurr.empty() )
5935   {
5936     theListOfConcurr.push_back( theDimHyp );
5937   }
5938   else
5939   {
5940     TDimHypList::iterator hypIt = theListOfConcurr.begin();
5941     while ( hypIt != theListOfConcurr.end() &&
5942             !theDimHyp->IsHigherPriorityThan( *hypIt ))
5943       ++hypIt;
5944     theListOfConcurr.insert( hypIt, theDimHyp );
5945   }
5946 }
5947
5948 //-----------------------------------------------------------------------------
5949 void findConcurrents(const SMESH_DimHyp* theDimHyp,
5950                      const TDimHypList&  theListOfDimHyp,
5951                      TDimHypList&        theListOfConcurrHyp,
5952                      set<int>&           theSetOfConcurrId )
5953 {
5954   TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
5955   for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
5956   {
5957     const SMESH_DimHyp* curDimHyp = *rIt;
5958     if ( curDimHyp == theDimHyp )
5959       break; // meet own dimHyp pointer in same dimension
5960
5961     if ( theDimHyp->IsConcurrent( curDimHyp ) &&
5962          theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
5963     {
5964       addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
5965     }
5966   }
5967 }
5968
5969 //-----------------------------------------------------------------------------
5970 void unionLists(TListOfInt&       theListOfId,
5971                 TListOfListOfInt& theListOfListOfId,
5972                 const int         theIndx )
5973 {
5974   TListOfListOfInt::iterator it = theListOfListOfId.begin();
5975   for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) {
5976     if ( i < theIndx )
5977       continue; //skip already treated lists
5978     // check if other list has any same submesh object
5979     TListOfInt& otherListOfId = *it;
5980     if ( find_first_of( theListOfId.begin(), theListOfId.end(),
5981                         otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
5982       continue;
5983
5984     // union two lists (from source into target)
5985     TListOfInt::iterator it2 = otherListOfId.begin();
5986     for ( ; it2 != otherListOfId.end(); it2++ ) {
5987       if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
5988         theListOfId.push_back(*it2);
5989     }
5990     // clear source list
5991     otherListOfId.clear();
5992   }
5993 }
5994 //-----------------------------------------------------------------------------
5995
5996 //! free memory allocated for dimension-hypothesis objects
5997 void removeDimHyps( TDimHypList* theArrOfList )
5998 {
5999   for (int i = 0; i < 4; i++ ) {
6000     TDimHypList& listOfdimHyp = theArrOfList[i];
6001     TDimHypList::const_iterator it = listOfdimHyp.begin();
6002     for ( ; it != listOfdimHyp.end(); it++ )
6003       delete (*it);
6004   }
6005 }
6006
6007 //-----------------------------------------------------------------------------
6008 /*!
6009  * \brief find common submeshes with given submesh
6010  * \param theSubMeshList list of already collected submesh to check
6011  * \param theSubMesh given submesh to intersect with other
6012  * \param theCommonSubMeshes collected common submeshes
6013  */
6014 void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
6015                         const SMESH_subMesh*        theSubMesh,
6016                         set<const SMESH_subMesh*>&  theCommon )
6017 {
6018   if ( !theSubMesh )
6019     return;
6020   list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
6021   for ( ; it != theSubMeshList.end(); it++ )
6022     theSubMesh->FindIntersection( *it, theCommon );
6023   theSubMeshList.push_back( theSubMesh );
6024   //theCommon.insert( theSubMesh );
6025 }
6026
6027 //-----------------------------------------------------------------------------
6028 bool isSubMeshInList ( int smID, const TListOfListOfInt& smLists )
6029 {
6030   TListOfListOfInt::const_iterator listsIt = smLists.begin();
6031   for ( ; listsIt != smLists.end(); ++listsIt )
6032   {
6033     const TListOfInt& smIDs = *listsIt;
6034     if ( std::find( smIDs.begin(), smIDs.end(), smID ) != smIDs.end() )
6035       return true;
6036   }
6037   return false;
6038 }
6039
6040 } // namespace
6041
6042 //=============================================================================
6043 /*!
6044  * \brief Return \c true if a meshing order not yet set for a concurrent sub-mesh
6045  */
6046 //=============================================================================
6047
6048 CORBA::Boolean SMESH_Mesh_i::IsUnorderedSubMesh(CORBA::Long submeshID)
6049 {
6050   TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6051   if ( isSubMeshInList( submeshID, anOrder ))
6052     return false;
6053
6054   TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6055   return isSubMeshInList( submeshID, allConurrent );
6056 }
6057
6058 //=============================================================================
6059 /*!
6060  * \brief Return submesh objects list in meshing order
6061  */
6062 //=============================================================================
6063
6064 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
6065 {
6066   SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
6067
6068   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6069   if ( !aMeshDS )
6070     return aResult._retn();
6071
6072   TListOfListOfInt      anOrder = GetImpl().GetMeshOrder(); // already defined order
6073   TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6074   anOrder.splice( anOrder.end(), allConurrent );
6075
6076   int listIndx = 0;
6077   TListOfListOfInt::iterator listIt = anOrder.begin();
6078   for(; listIt != anOrder.end(); listIt++, listIndx++ )
6079     unionLists( *listIt,  anOrder, listIndx + 1 );
6080
6081   // convert submesh ids into interface instances
6082   //  and dump command into python
6083   convertMeshOrder( anOrder, aResult, false );
6084
6085   return aResult._retn();
6086 }
6087
6088 //=============================================================================
6089 /*!
6090  * \brief Finds concurrent sub-meshes
6091  */
6092 //=============================================================================
6093
6094 TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes()
6095 {
6096   TListOfListOfInt anOrder;
6097   ::SMESH_Mesh& mesh = GetImpl();
6098   {
6099     // collect submeshes and detect concurrent algorithms and hypothesises
6100     TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
6101
6102     map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
6103     for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) {
6104       ::SMESH_subMesh* sm = (*i_sm).second;
6105       // shape of submesh
6106       const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
6107
6108       // list of assigned hypothesises
6109       const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
6110       // Find out dimensions where the submesh can be concurrent.
6111       // We define the dimensions by algo of each of hypotheses in hypList
6112       list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
6113       for( ; hypIt != hypList.end(); hypIt++ ) {
6114         SMESH_Algo* anAlgo = 0;
6115         const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
6116         if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
6117           // hyp it-self is algo
6118           anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
6119         else {
6120           // try to find algorithm with help of sub-shapes
6121           TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
6122           for ( ; !anAlgo && anExp.More(); anExp.Next() )
6123             anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
6124         }
6125         if (!anAlgo)
6126           continue; // no algorithm assigned to a current submesh
6127
6128         int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
6129         // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary())
6130
6131         // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
6132         for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
6133           addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
6134       }
6135     } // end iterations on submesh
6136
6137     // iterate on created dimension-hypotheses and check for concurrents
6138     for ( int i = 0; i < 4; i++ ) {
6139       const TDimHypList& listOfDimHyp = dimHypListArr[i];
6140       // check for concurrents in own and other dimensions (step-by-step)
6141       TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
6142       for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) {
6143         const SMESH_DimHyp* dimHyp = *dhIt;
6144         TDimHypList listOfConcurr;
6145         set<int>    setOfConcurrIds;
6146         // looking for concurrents and collect into own list
6147         for ( int j = i; j < 4; j++ )
6148           findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
6149         // check if any concurrents found
6150         if ( listOfConcurr.size() > 0 ) {
6151           // add own submesh to list of concurrent
6152           addInOrderOfPriority( dimHyp, listOfConcurr );
6153           list<int> listOfConcurrIds;
6154           TDimHypList::iterator hypIt = listOfConcurr.begin();
6155           for ( ; hypIt != listOfConcurr.end(); ++hypIt )
6156             listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
6157           anOrder.push_back( listOfConcurrIds );
6158         }
6159       }
6160     }
6161
6162     removeDimHyps(dimHypListArr);
6163
6164     // now, minimize the number of concurrent groups
6165     // Here we assume that lists of submeshes can have same submesh
6166     // in case of multi-dimension algorithms, as result
6167     //  list with common submesh has to be united into one list
6168     int listIndx = 0;
6169     TListOfListOfInt::iterator listIt = anOrder.begin();
6170     for(; listIt != anOrder.end(); listIt++, listIndx++ )
6171       unionLists( *listIt,  anOrder, listIndx + 1 );
6172   }
6173
6174   return anOrder;
6175 }
6176
6177 //=============================================================================
6178 /*!
6179  * \brief Set submesh object order
6180  * \param theSubMeshArray submesh array order
6181  */
6182 //=============================================================================
6183
6184 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
6185 {
6186   if ( _preMeshInfo )
6187     _preMeshInfo->ForgetOrLoad();
6188
6189   bool res = false;
6190   ::SMESH_Mesh& mesh = GetImpl();
6191
6192   TPythonDump aPythonDump; // prevent dump of called methods
6193   aPythonDump << "isDone = " << SMESH::SMESH_Mesh_var(_this()) << ".SetMeshOrder( [ ";
6194
6195   TListOfListOfInt subMeshOrder;
6196   for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
6197   {
6198     const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
6199     TListOfInt subMeshIds;
6200     if ( i > 0 )
6201       aPythonDump << ", ";
6202     aPythonDump << "[ ";
6203     // Collect subMeshes which should be clear
6204     //  do it list-by-list, because modification of submesh order
6205     //  take effect between concurrent submeshes only
6206     set<const SMESH_subMesh*> subMeshToClear;
6207     list<const SMESH_subMesh*> subMeshList;
6208     for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
6209     {
6210       const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
6211       if ( j > 0 )
6212         aPythonDump << ", ";
6213       aPythonDump << subMesh;
6214       subMeshIds.push_back( subMesh->GetId() );
6215       // detect common parts of submeshes
6216       if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
6217         findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
6218     }
6219     aPythonDump << " ]";
6220     subMeshOrder.push_back( subMeshIds );
6221
6222     // clear collected submeshes
6223     set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
6224     for ( ; clrIt != subMeshToClear.end(); clrIt++ )
6225       if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
6226         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
6227   }
6228   aPythonDump << " ])";
6229
6230   mesh.SetMeshOrder( subMeshOrder );
6231   res = true;
6232
6233   SMESH::SMESH_Mesh_var me = _this();
6234   _gen_i->UpdateIcons( me );
6235
6236   return res;
6237 }
6238
6239 //=============================================================================
6240 /*!
6241  * \brief Convert submesh ids into submesh interfaces
6242  */
6243 //=============================================================================
6244
6245 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt&     theIdsOrder,
6246                                      SMESH::submesh_array_array& theResOrder,
6247                                      const bool                  theIsDump)
6248 {
6249   int nbSet = theIdsOrder.size();
6250   TPythonDump aPythonDump; // prevent dump of called methods
6251   if ( theIsDump )
6252     aPythonDump << "[ ";
6253   theResOrder.length(nbSet);
6254   TListOfListOfInt::const_iterator it = theIdsOrder.begin();
6255   int listIndx = 0;
6256   for( ; it != theIdsOrder.end(); it++ ) {
6257     // translate submesh identificators into submesh objects
6258     //  takeing into account real number of concurrent lists
6259     const TListOfInt& aSubOrder = (*it);
6260     if (!aSubOrder.size())
6261       continue;
6262     if ( theIsDump )
6263       aPythonDump << "[ ";
6264     // convert shape indices into interfaces
6265     SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
6266     aResSubSet->length(aSubOrder.size());
6267     TListOfInt::const_iterator subIt = aSubOrder.begin();
6268     int j;
6269     for( j = 0; subIt != aSubOrder.end(); subIt++ ) {
6270       if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
6271         continue;
6272       SMESH::SMESH_subMesh_var subMesh =
6273         SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
6274       if ( theIsDump ) {
6275         if ( j > 0 )
6276           aPythonDump << ", ";
6277         aPythonDump << subMesh;
6278       }
6279       aResSubSet[ j++ ] = subMesh;
6280     }
6281     if ( theIsDump )
6282       aPythonDump << " ]";
6283     if ( j > 1 )
6284       theResOrder[ listIndx++ ] = aResSubSet;
6285   }
6286   // correct number of lists
6287   theResOrder.length( listIndx );
6288
6289   if ( theIsDump ) {
6290     // finilise python dump
6291     aPythonDump << " ]";
6292     aPythonDump << " = " << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshOrder()";
6293   }
6294 }
6295
6296 namespace // utils used by SMESH_MeshPartDS
6297 {
6298   /*!
6299    * \brief Class used to access to protected data of SMDS_MeshInfo
6300    */
6301   struct TMeshInfo : public SMDS_MeshInfo
6302   {
6303     void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); }
6304   };
6305   /*!
6306    * \brief Element holing its ID only
6307    */
6308   struct TElemID : public SMDS_LinearEdge
6309   {
6310     TElemID(int ID) : SMDS_LinearEdge(0,0) { setID( ID ); }
6311   };
6312 }
6313
6314 //================================================================================
6315 //
6316 // Implementation of SMESH_MeshPartDS
6317 //
6318 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
6319   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
6320 {
6321   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
6322   SMESH_Mesh_i*       mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
6323
6324   mesh_i->Load();
6325   _meshDS = mesh_i->GetImpl().GetMeshDS();
6326
6327   SetPersistentId( _meshDS->GetPersistentId() );
6328
6329   if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
6330   {
6331     // <meshPart> is the whole mesh
6332     myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
6333     // copy groups
6334     set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
6335     myGroupSet = _meshDS->GetGroups();
6336   }
6337   else
6338   {
6339     TMeshInfo tmpInfo;
6340     SMESH::long_array_var           anIDs = meshPart->GetIDs();
6341     SMESH::array_of_ElementType_var types = meshPart->GetTypes();
6342     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
6343     {
6344       for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
6345         if ( const SMDS_MeshNode * n = _meshDS->FindNode( anIDs[i] ))
6346           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
6347             tmpInfo.Add( n );
6348     }
6349     else
6350     {
6351       for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
6352         if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
6353           if ( _elements[ e->GetType() ].insert( e ).second )
6354           {
6355             tmpInfo.Add( e );
6356             SMDS_ElemIteratorPtr nIt = e->nodesIterator();
6357             while ( nIt->more() )
6358             {
6359               const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
6360               if ( _elements[ SMDSAbs_Node ].insert( n ).second )
6361                 tmpInfo.Add( n );
6362             }
6363           }
6364     }
6365     myInfo = tmpInfo;
6366
6367     ShapeToMesh( _meshDS->ShapeToMesh() );
6368
6369     _meshDS = 0; // to enforce iteration on _elements and _nodes
6370   }
6371 }
6372 // -------------------------------------------------------------------------------------
6373 SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
6374   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
6375 {
6376   TMeshInfo tmpInfo;
6377   list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
6378   for ( ; partIt != meshPart.end(); ++partIt )
6379     if ( const SMDS_MeshElement * e = *partIt )
6380       if ( _elements[ e->GetType() ].insert( e ).second )
6381       {
6382         tmpInfo.Add( e );
6383         SMDS_ElemIteratorPtr nIt = e->nodesIterator();
6384         while ( nIt->more() )
6385         {
6386           const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
6387           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
6388             tmpInfo.Add( n );
6389         }
6390       }
6391   myInfo = tmpInfo;
6392 }
6393 // -------------------------------------------------------------------------------------
6394 const SMDS_MeshElement * SMESH_MeshPartDS::FindElement(int IDelem) const
6395 {
6396   if ( _meshDS ) return _meshDS->FindElement( IDelem );
6397
6398   TElemID elem( IDelem );
6399   for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
6400     if ( !_elements[ iType ].empty() )
6401     {
6402       TIDSortedElemSet::const_iterator it = _elements[ iType ].find( &elem );
6403       if ( it != _elements[ iType ].end() )
6404         return *it;
6405     }
6406   return 0;
6407 }
6408 // -------------------------------------------------------------------------------------
6409 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
6410 {
6411   if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
6412
6413   typedef SMDS_SetIterator
6414     <const SMDS_MeshElement*,
6415     TIDSortedElemSet::const_iterator,
6416     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
6417     SMDS_MeshElement::GeomFilter
6418     > TIter;
6419
6420   SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( geomType );
6421
6422   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
6423                                           _elements[type].end(),
6424                                           SMDS_MeshElement::GeomFilter( geomType )));
6425 }
6426 // -------------------------------------------------------------------------------------
6427 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
6428 {
6429   if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
6430
6431   typedef SMDS_SetIterator
6432     <const SMDS_MeshElement*,
6433     TIDSortedElemSet::const_iterator,
6434     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
6435     SMDS_MeshElement::EntityFilter
6436     > TIter;
6437
6438   SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( entity );
6439
6440   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
6441                                           _elements[type].end(),
6442                                           SMDS_MeshElement::EntityFilter( entity )));
6443 }
6444 // -------------------------------------------------------------------------------------
6445 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
6446 {
6447   typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
6448   if ( type == SMDSAbs_All && !_meshDS )
6449   {
6450     typedef vector< SMDS_ElemIteratorPtr > TIterVec;
6451     TIterVec iterVec;
6452     for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
6453       if ( !_elements[i].empty() && i != SMDSAbs_Node )
6454         iterVec.push_back
6455           ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
6456
6457     typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
6458     return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
6459   }
6460   return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
6461       ( new TIter( _elements[type].begin(), _elements[type].end() ));
6462 }
6463 // -------------------------------------------------------------------------------------
6464 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType)                       \
6465   iterType SMESH_MeshPartDS::methName() const                 \
6466   {                                                                                 \
6467     typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
6468     return _meshDS ? _meshDS->methName() : iterType                 \
6469       ( new TIter( _elements[elemType].begin(), _elements[elemType].end() ));       \
6470   }
6471 // -------------------------------------------------------------------------------------
6472 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
6473 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
6474 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
6475 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
6476 #undef _GET_ITER_DEFINE
6477 //
6478 // END Implementation of SMESH_MeshPartDS
6479 //
6480 //================================================================================