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