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