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