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