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