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