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