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