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