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