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