Salome HOME
22244: [CEA] Method to compute the normal to a mesh face
[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  *
3473  */
3474 //=============================================================================
3475
3476 SMESH::GeometryType SMESH_Mesh_i::GetElementShape( const CORBA::Long id )
3477   throw (SALOME::SALOME_Exception)
3478 {
3479   if ( _preMeshInfo )
3480     _preMeshInfo->FullLoadFromFile();
3481
3482   const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
3483   if ( !e )
3484     THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
3485
3486   return ( SMESH::GeometryType ) e->GetGeomType();
3487 }
3488
3489 //=============================================================================
3490 /*!
3491  * Returns ID of elements for given submesh
3492  */
3493 //=============================================================================
3494 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
3495      throw (SALOME::SALOME_Exception)
3496 {
3497   SMESH::long_array_var aResult = new SMESH::long_array();
3498
3499   SMESH_TRY;
3500   if ( _preMeshInfo )
3501     _preMeshInfo->FullLoadFromFile();
3502
3503   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
3504   if(!SM) return aResult._retn();
3505
3506   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
3507   if(!SDSM) return aResult._retn();
3508
3509   aResult->length(SDSM->NbElements());
3510
3511   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
3512   int i = 0;
3513   while ( eIt->more() ) {
3514     aResult[i++] = eIt->next()->GetID();
3515   }
3516
3517   SMESH_CATCH( SMESH::throwCorbaException );
3518
3519   return aResult._retn();
3520 }
3521
3522 //=============================================================================
3523 /*!
3524  * Returns ID of nodes for given submesh
3525  * If param all==true - returns all nodes, else -
3526  * returns only nodes on shapes.
3527  */
3528 //=============================================================================
3529
3530 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
3531                                                    CORBA::Boolean    all)
3532   throw (SALOME::SALOME_Exception)
3533 {
3534   SMESH::long_array_var aResult = new SMESH::long_array();
3535
3536   SMESH_TRY;
3537   if ( _preMeshInfo )
3538     _preMeshInfo->FullLoadFromFile();
3539
3540   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
3541   if(!SM) return aResult._retn();
3542
3543   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
3544   if(!SDSM) return aResult._retn();
3545
3546   set<int> theElems;
3547   if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
3548     SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
3549     while ( nIt->more() ) {
3550       const SMDS_MeshNode* elem = nIt->next();
3551       theElems.insert( elem->GetID() );
3552     }
3553   }
3554   else { // all nodes of submesh elements
3555     SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
3556     while ( eIt->more() ) {
3557       const SMDS_MeshElement* anElem = eIt->next();
3558       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
3559       while ( nIt->more() ) {
3560         const SMDS_MeshElement* elem = nIt->next();
3561         theElems.insert( elem->GetID() );
3562       }
3563     }
3564   }
3565
3566   aResult->length(theElems.size());
3567   set<int>::iterator itElem;
3568   int i = 0;
3569   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
3570     aResult[i++] = *itElem;
3571
3572   SMESH_CATCH( SMESH::throwCorbaException );
3573
3574   return aResult._retn();
3575 }
3576   
3577 //=============================================================================
3578 /*!
3579  * Returns type of elements for given submesh
3580  */
3581 //=============================================================================
3582
3583 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
3584   throw (SALOME::SALOME_Exception)
3585 {
3586   SMESH::ElementType type;
3587
3588   SMESH_TRY;
3589   if ( _preMeshInfo )
3590     _preMeshInfo->FullLoadFromFile();
3591
3592   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
3593   if(!SM) return SMESH::ALL;
3594
3595   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
3596   if(!SDSM) return SMESH::ALL;
3597
3598   if(SDSM->NbElements()==0)
3599     return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
3600
3601   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
3602   const SMDS_MeshElement* anElem = eIt->next();
3603
3604   type = ( SMESH::ElementType ) anElem->GetType();
3605
3606   SMESH_CATCH( SMESH::throwCorbaException );
3607
3608   return type; 
3609 }
3610   
3611
3612 //=============================================================================
3613 /*!
3614  * Returns pointer to _impl as an integer value. Is called from constructor of SMESH_Client
3615  */
3616 //=============================================================================
3617
3618 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
3619 {
3620   if ( _preMeshInfo )
3621     _preMeshInfo->FullLoadFromFile();
3622
3623   CORBA::LongLong pointeur = CORBA::LongLong(_impl);
3624   if ( MYDEBUG )
3625     MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
3626   return pointeur;
3627 }
3628
3629
3630 //=============================================================================
3631 /*!
3632  * Get XYZ coordinates of node as list of double
3633  * If there is not node for given ID - returns empty list
3634  */
3635 //=============================================================================
3636
3637 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
3638 {
3639   if ( _preMeshInfo )
3640     _preMeshInfo->FullLoadFromFile();
3641
3642   SMESH::double_array_var aResult = new SMESH::double_array();
3643   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3644   if ( aSMESHDS_Mesh == NULL )
3645     return aResult._retn();
3646
3647   // find node
3648   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3649   if(!aNode)
3650     return aResult._retn();
3651
3652   // add coordinates
3653   aResult->length(3);
3654   aResult[0] = aNode->X();
3655   aResult[1] = aNode->Y();
3656   aResult[2] = aNode->Z();
3657   return aResult._retn();
3658 }
3659
3660
3661 //=============================================================================
3662 /*!
3663  * For given node returns list of IDs of inverse elements
3664  * If there is not node for given ID - returns empty list
3665  */
3666 //=============================================================================
3667
3668 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
3669 {
3670   if ( _preMeshInfo )
3671     _preMeshInfo->FullLoadFromFile();
3672
3673   SMESH::long_array_var aResult = new SMESH::long_array();
3674   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3675   if ( aSMESHDS_Mesh == NULL )
3676     return aResult._retn();
3677
3678   // find node
3679   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3680   if(!aNode)
3681     return aResult._retn();
3682
3683   // find inverse elements
3684   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
3685   TColStd_SequenceOfInteger IDs;
3686   while(eIt->more()) {
3687     const SMDS_MeshElement* elem = eIt->next();
3688     IDs.Append(elem->GetID());
3689   }
3690   if(IDs.Length()>0) {
3691     aResult->length(IDs.Length());
3692     int i = 1;
3693     for(; i<=IDs.Length(); i++) {
3694       aResult[i-1] = IDs.Value(i);
3695     }
3696   }
3697   return aResult._retn();
3698 }
3699
3700 //=============================================================================
3701 /*!
3702  * \brief Return position of a node on shape
3703  */
3704 //=============================================================================
3705
3706 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
3707 {
3708   if ( _preMeshInfo )
3709     _preMeshInfo->FullLoadFromFile();
3710
3711   SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
3712   aNodePosition->shapeID = 0;
3713   aNodePosition->shapeType = GEOM::SHAPE;
3714
3715   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
3716   if ( !mesh ) return aNodePosition;
3717
3718   if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
3719   {
3720     if ( SMDS_PositionPtr pos = aNode->GetPosition() )
3721     {
3722       aNodePosition->shapeID = aNode->getshapeId();
3723       switch ( pos->GetTypeOfPosition() ) {
3724       case SMDS_TOP_EDGE:
3725         aNodePosition->shapeType = GEOM::EDGE;
3726         aNodePosition->params.length(1);
3727         aNodePosition->params[0] =
3728           static_cast<SMDS_EdgePosition*>( pos )->GetUParameter();
3729         break;
3730       case SMDS_TOP_FACE:
3731         aNodePosition->shapeType = GEOM::FACE;
3732         aNodePosition->params.length(2);
3733         aNodePosition->params[0] =
3734           static_cast<SMDS_FacePosition*>( pos )->GetUParameter();
3735         aNodePosition->params[1] =
3736           static_cast<SMDS_FacePosition*>( pos )->GetVParameter();
3737         break;
3738       case SMDS_TOP_VERTEX:
3739         aNodePosition->shapeType = GEOM::VERTEX;
3740         break;
3741       case SMDS_TOP_3DSPACE:
3742         if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
3743           aNodePosition->shapeType = GEOM::SOLID;
3744         else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
3745           aNodePosition->shapeType = GEOM::SHELL;
3746         break;
3747       default:;
3748       }
3749     }
3750   }
3751   return aNodePosition;
3752 }
3753
3754 //=============================================================================
3755 /*!
3756  * \brief Return position of an element on shape
3757  */
3758 //=============================================================================
3759
3760 SMESH::ElementPosition SMESH_Mesh_i::GetElementPosition(CORBA::Long ElemID)
3761 {
3762   if ( _preMeshInfo )
3763     _preMeshInfo->FullLoadFromFile();
3764
3765   SMESH::ElementPosition anElementPosition;
3766   anElementPosition.shapeID = 0;
3767   anElementPosition.shapeType = GEOM::SHAPE;
3768
3769   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
3770   if ( !mesh ) return anElementPosition;
3771
3772   if ( const SMDS_MeshElement* anElem = mesh->FindElement( ElemID ) )
3773   {
3774     anElementPosition.shapeID = anElem->getshapeId();
3775     const TopoDS_Shape& aSp = mesh->IndexToShape( anElem->getshapeId() );
3776     if ( !aSp.IsNull() ) {
3777       switch ( aSp.ShapeType() ) {
3778       case TopAbs_EDGE:
3779         anElementPosition.shapeType = GEOM::EDGE;
3780         break;
3781       case TopAbs_FACE:
3782         anElementPosition.shapeType = GEOM::FACE;
3783         break;
3784       case TopAbs_VERTEX:
3785         anElementPosition.shapeType = GEOM::VERTEX;
3786         break;
3787       case TopAbs_SOLID:
3788         anElementPosition.shapeType = GEOM::SOLID;
3789         break;
3790       case TopAbs_SHELL:
3791         anElementPosition.shapeType = GEOM::SHELL;
3792         break;
3793       default:;
3794       }
3795     }
3796   }
3797   return anElementPosition;
3798 }
3799
3800 //=============================================================================
3801 /*!
3802  * If given element is node returns IDs of shape from position
3803  * If there is not node for given ID - returns -1
3804  */
3805 //=============================================================================
3806
3807 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
3808 {
3809   if ( _preMeshInfo )
3810     _preMeshInfo->FullLoadFromFile();
3811
3812   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3813   if ( aSMESHDS_Mesh == NULL )
3814     return -1;
3815
3816   // try to find node
3817   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3818   if(aNode) {
3819     return aNode->getshapeId();
3820   }
3821
3822   return -1;
3823 }
3824
3825
3826 //=============================================================================
3827 /*!
3828  * For given element returns ID of result shape after 
3829  * ::FindShape() from SMESH_MeshEditor
3830  * If there is not element for given ID - returns -1
3831  */
3832 //=============================================================================
3833
3834 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
3835 {
3836   if ( _preMeshInfo )
3837     _preMeshInfo->FullLoadFromFile();
3838
3839   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3840   if ( aSMESHDS_Mesh == NULL )
3841     return -1;
3842
3843   // try to find element
3844   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3845   if(!elem)
3846     return -1;
3847
3848   ::SMESH_MeshEditor aMeshEditor(_impl);
3849   int index = aMeshEditor.FindShape( elem );
3850   if(index>0)
3851     return index;
3852
3853   return -1;
3854 }
3855
3856
3857 //=============================================================================
3858 /*!
3859  * Returns number of nodes for given element
3860  * If there is not element for given ID - returns -1
3861  */
3862 //=============================================================================
3863
3864 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
3865 {
3866   if ( _preMeshInfo )
3867     _preMeshInfo->FullLoadFromFile();
3868
3869   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3870   if ( aSMESHDS_Mesh == NULL ) return -1;
3871   // try to find element
3872   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3873   if(!elem) return -1;
3874   return elem->NbNodes();
3875 }
3876
3877
3878 //=============================================================================
3879 /*!
3880  * Returns ID of node by given index for given element
3881  * If there is not element for given ID - returns -1
3882  * If there is not node for given index - returns -2
3883  */
3884 //=============================================================================
3885
3886 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
3887 {
3888   if ( _preMeshInfo )
3889     _preMeshInfo->FullLoadFromFile();
3890
3891   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3892   if ( aSMESHDS_Mesh == NULL ) return -1;
3893   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3894   if(!elem) return -1;
3895   if( index>=elem->NbNodes() || index<0 ) return -1;
3896   return elem->GetNode(index)->GetID();
3897 }
3898
3899 //=============================================================================
3900 /*!
3901  * Returns IDs of nodes of given element
3902  */
3903 //=============================================================================
3904
3905 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
3906 {
3907   if ( _preMeshInfo )
3908     _preMeshInfo->FullLoadFromFile();
3909
3910   SMESH::long_array_var aResult = new SMESH::long_array();
3911   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
3912   {
3913     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id) )
3914     {
3915       aResult->length( elem->NbNodes() );
3916       for ( int i = 0; i < elem->NbNodes(); ++i )
3917         aResult[ i ] = elem->GetNode( i )->GetID();
3918     }
3919   }
3920   return aResult._retn();
3921 }
3922
3923 //=============================================================================
3924 /*!
3925  * Returns true if given node is medium node
3926  * in given quadratic element
3927  */
3928 //=============================================================================
3929
3930 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
3931 {
3932   if ( _preMeshInfo )
3933     _preMeshInfo->FullLoadFromFile();
3934
3935   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3936   if ( aSMESHDS_Mesh == NULL ) return false;
3937   // try to find node
3938   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
3939   if(!aNode) return false;
3940   // try to find element
3941   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(ide);
3942   if(!elem) return false;
3943
3944   return elem->IsMediumNode(aNode);
3945 }
3946
3947
3948 //=============================================================================
3949 /*!
3950  * Returns true if given node is medium node
3951  * in one of quadratic elements
3952  */
3953 //=============================================================================
3954
3955 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
3956                                                    SMESH::ElementType theElemType)
3957 {
3958   if ( _preMeshInfo )
3959     _preMeshInfo->FullLoadFromFile();
3960
3961   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3962   if ( aSMESHDS_Mesh == NULL ) return false;
3963
3964   // try to find node
3965   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
3966   if(!aNode) return false;
3967
3968   SMESH_MesherHelper aHelper( *(_impl) );
3969
3970   SMDSAbs_ElementType aType;
3971   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
3972   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
3973   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
3974   else aType = SMDSAbs_All;
3975
3976   return aHelper.IsMedium(aNode,aType);
3977 }
3978
3979
3980 //=============================================================================
3981 /*!
3982  * Returns number of edges for given element
3983  */
3984 //=============================================================================
3985
3986 CORBA::Long SMESH_Mesh_i::ElemNbEdges(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->NbEdges();
3996 }
3997
3998
3999 //=============================================================================
4000 /*!
4001  * Returns number of faces for given element
4002  */
4003 //=============================================================================
4004
4005 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
4006 {
4007   if ( _preMeshInfo )
4008     _preMeshInfo->FullLoadFromFile();
4009
4010   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4011   if ( aSMESHDS_Mesh == NULL ) return -1;
4012   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4013   if(!elem) return -1;
4014   return elem->NbFaces();
4015 }
4016
4017 //=======================================================================
4018 //function : GetElemFaceNodes
4019 //purpose  : Returns nodes of given face (counted from zero) for given element.
4020 //=======================================================================
4021
4022 SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long  elemId,
4023                                                   CORBA::Short faceIndex)
4024 {
4025   if ( _preMeshInfo )
4026     _preMeshInfo->FullLoadFromFile();
4027
4028   SMESH::long_array_var aResult = new SMESH::long_array();
4029   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
4030   {
4031     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(elemId) )
4032     {
4033       SMDS_VolumeTool vtool( elem );
4034       if ( faceIndex < vtool.NbFaces() )
4035       {
4036         aResult->length( vtool.NbFaceNodes( faceIndex ));
4037         const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
4038         for ( int i = 0; i < aResult->length(); ++i )
4039           aResult[ i ] = nn[ i ]->GetID();
4040       }
4041     }
4042   }
4043   return aResult._retn();
4044 }
4045
4046 //=======================================================================
4047 //function : GetElemFaceNodes
4048 //purpose  : Returns three components of normal of given mesh face.
4049 //=======================================================================
4050
4051 SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long    elemId,
4052                                                  CORBA::Boolean normalized)
4053 {
4054   if ( _preMeshInfo )
4055     _preMeshInfo->FullLoadFromFile();
4056
4057   SMESH::double_array_var aResult = new SMESH::double_array();
4058
4059   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
4060   {
4061     gp_XYZ normal;
4062     if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, normalized ))
4063     {
4064       aResult->length( 3 );
4065       aResult[ 0 ] = normal.X();
4066       aResult[ 1 ] = normal.Y();
4067       aResult[ 2 ] = normal.Z();
4068     }
4069   }
4070   return aResult._retn();
4071 }
4072
4073 //=======================================================================
4074 //function : FindElementByNodes
4075 //purpose  : Returns an element based on all given nodes.
4076 //=======================================================================
4077
4078 CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
4079 {
4080   if ( _preMeshInfo )
4081     _preMeshInfo->FullLoadFromFile();
4082
4083   CORBA::Long elemID(0);
4084   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
4085   {
4086     vector< const SMDS_MeshNode * > nn( nodes.length() );
4087     for ( int i = 0; i < nodes.length(); ++i )
4088       if ( !( nn[i] = mesh->FindNode( nodes[i] )))
4089         return elemID;
4090
4091     const SMDS_MeshElement* elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/false );
4092     if ( !elem && ( _impl->NbEdges  ( ORDER_QUADRATIC ) ||
4093                     _impl->NbFaces  ( ORDER_QUADRATIC ) ||
4094                     _impl->NbVolumes( ORDER_QUADRATIC )))
4095       elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
4096
4097     if ( elem ) elemID = CORBA::Long( elem->GetID() );
4098   }
4099   return elemID;
4100 }
4101
4102 //=============================================================================
4103 /*!
4104  * Returns true if given element is polygon
4105  */
4106 //=============================================================================
4107
4108 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
4109 {
4110   if ( _preMeshInfo )
4111     _preMeshInfo->FullLoadFromFile();
4112
4113   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4114   if ( aSMESHDS_Mesh == NULL ) return false;
4115   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4116   if(!elem) return false;
4117   return elem->IsPoly();
4118 }
4119
4120
4121 //=============================================================================
4122 /*!
4123  * Returns true if given element is quadratic
4124  */
4125 //=============================================================================
4126
4127 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
4128 {
4129   if ( _preMeshInfo )
4130     _preMeshInfo->FullLoadFromFile();
4131
4132   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4133   if ( aSMESHDS_Mesh == NULL ) return false;
4134   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4135   if(!elem) return false;
4136   return elem->IsQuadratic();
4137 }
4138
4139 //=============================================================================
4140 /*!
4141  * Returns diameter of ball discrete element or zero in case of an invalid \a id
4142  */
4143 //=============================================================================
4144
4145 CORBA::Double SMESH_Mesh_i::GetBallDiameter(CORBA::Long id)
4146 {
4147   if ( _preMeshInfo )
4148     _preMeshInfo->FullLoadFromFile();
4149
4150   if ( const SMDS_BallElement* ball =
4151        dynamic_cast<const SMDS_BallElement*>( _impl->GetMeshDS()->FindElement( id )))
4152     return ball->GetDiameter();
4153
4154   return 0;
4155 }
4156
4157 //=============================================================================
4158 /*!
4159  * Returns bary center for given element
4160  */
4161 //=============================================================================
4162
4163 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
4164 {
4165   if ( _preMeshInfo )
4166     _preMeshInfo->FullLoadFromFile();
4167
4168   SMESH::double_array_var aResult = new SMESH::double_array();
4169   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4170   if ( aSMESHDS_Mesh == NULL )
4171     return aResult._retn();
4172
4173   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4174   if(!elem)
4175     return aResult._retn();
4176
4177   if(elem->GetType()==SMDSAbs_Volume) {
4178     SMDS_VolumeTool aTool;
4179     if(aTool.Set(elem)) {
4180       aResult->length(3);
4181       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
4182         aResult->length(0);
4183     }
4184   }
4185   else {
4186     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
4187     int nbn = 0;
4188     double x=0., y=0., z=0.;
4189     for(; anIt->more(); ) {
4190       nbn++;
4191       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
4192       x += aNode->X();
4193       y += aNode->Y();
4194       z += aNode->Z();
4195     }
4196     if(nbn>0) {
4197       // add coordinates
4198       aResult->length(3);
4199       aResult[0] = x/nbn;
4200       aResult[1] = y/nbn;
4201       aResult[2] = z/nbn;
4202     }
4203   }
4204
4205   return aResult._retn();
4206 }
4207
4208 //================================================================================
4209 /*!
4210  * \brief Create a group of elements preventing computation of a sub-shape
4211  */
4212 //================================================================================
4213
4214 SMESH::ListOfGroups*
4215 SMESH_Mesh_i::MakeGroupsOfBadInputElements( int         theSubShapeID,
4216                                             const char* theGroupName )
4217   throw ( SALOME::SALOME_Exception )
4218 {
4219   Unexpect aCatch(SALOME_SalomeException);
4220
4221   if ( !theGroupName || strlen( theGroupName) == 0 )
4222     THROW_SALOME_CORBA_EXCEPTION( "empty group name",SALOME::BAD_PARAM );
4223
4224   SMESH::ListOfGroups_var groups = new SMESH::ListOfGroups;
4225
4226   // submesh by subshape id
4227   if ( !_impl->HasShapeToMesh() ) theSubShapeID = 1;
4228   if ( SMESH_subMesh * sm = _impl->GetSubMeshContaining( theSubShapeID ))
4229   {
4230     // compute error
4231     SMESH_ComputeErrorPtr error = sm->GetComputeError();
4232     if ( error && !error->myBadElements.empty())
4233     {
4234       // sort bad elements by type
4235       vector< const SMDS_MeshElement* > elemsByType[ SMDSAbs_NbElementTypes ];
4236       list<const SMDS_MeshElement*>::iterator elemIt  = error->myBadElements.begin();
4237       list<const SMDS_MeshElement*>::iterator elemEnd = error->myBadElements.end();
4238       for ( ; elemIt != elemEnd; ++elemIt )
4239       {
4240         const SMDS_MeshElement* elem = *elemIt;
4241         if ( !elem ) continue;
4242
4243         if ( elem->GetID() < 1 )
4244         {
4245           // elem is a temporary element, make a real element
4246           vector< const SMDS_MeshNode* > nodes;
4247           SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
4248           while ( nIt->more() && elem )
4249           {
4250             nodes.push_back( nIt->next() );
4251             if ( nodes.back()->GetID() < 1 )
4252               elem = 0;  // a temporary element on temporary nodes
4253           }
4254           if ( elem )
4255           {
4256             ::SMESH_MeshEditor editor( _impl );
4257             elem = editor.AddElement( nodes, elem->GetType(), elem->IsPoly() );
4258           }
4259         }
4260         if ( elem )
4261           elemsByType[ elem->GetType() ].push_back( elem );
4262       }
4263
4264       // how many groups to create?
4265       int nbTypes = 0;
4266       for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
4267         nbTypes += int( !elemsByType[ i ].empty() );
4268       groups->length( nbTypes );
4269
4270       // create groups
4271       for ( int i = 0, iG = -1; i < SMDSAbs_NbElementTypes; ++i )
4272       {
4273         vector< const SMDS_MeshElement* >& elems = elemsByType[ i ];
4274         if ( elems.empty() ) continue;
4275
4276         groups[ ++iG ] = createGroup( SMESH::ElementType(i), theGroupName );
4277         if ( _gen_i->CanPublishInStudy( groups[ iG ] ))
4278         {
4279           SALOMEDS::Study_var  study = _gen_i->GetCurrentStudy();
4280           SMESH::SMESH_Mesh_var mesh = _this();
4281           SALOMEDS::SObject_wrap aSO =
4282             _gen_i->PublishGroup( study, mesh, groups[ iG ],
4283                                  GEOM::GEOM_Object::_nil(), theGroupName);
4284           aSO->_is_nil(); // avoid "unused variable" warning
4285         }
4286         SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
4287         if ( !grp_i ) continue;
4288
4289         if ( SMESHDS_Group*  grpDS = dynamic_cast< SMESHDS_Group* >( grp_i->GetGroupDS() ))
4290           for ( size_t iE = 0; iE < elems.size(); ++iE )
4291             grpDS->SMDSGroup().Add( elems[ iE ]);
4292       }
4293     }
4294   }
4295
4296   return groups._retn();
4297 }
4298
4299 //=============================================================================
4300 /*!
4301  * Create and publish group servants if any groups were imported or created anyhow
4302  */
4303 //=============================================================================
4304
4305 void SMESH_Mesh_i::CreateGroupServants()
4306 {
4307   SALOMEDS::Study_var  aStudy = _gen_i->GetCurrentStudy();
4308   SMESH::SMESH_Mesh_var aMesh = _this();
4309
4310   set<int> addedIDs;
4311   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
4312   while ( groupIt->more() )
4313   {
4314     ::SMESH_Group* group = groupIt->next();
4315     int            anId = group->GetGroupDS()->GetID();
4316
4317     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
4318     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
4319       continue;
4320     addedIDs.insert( anId );
4321
4322     SMESH_GroupBase_i* aGroupImpl;
4323     TopoDS_Shape       shape;
4324     if ( SMESHDS_GroupOnGeom* groupOnGeom =
4325          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
4326     {
4327       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
4328       shape      = groupOnGeom->GetShape();
4329     }
4330     else {
4331       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
4332     }
4333
4334     SMESH::SMESH_GroupBase_var groupVar = aGroupImpl->_this();
4335     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
4336     aGroupImpl->Register();
4337
4338     // register CORBA object for persistence
4339     int nextId = _gen_i->RegisterObject( groupVar );
4340     if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
4341     else        { nextId = 0; } // avoid "unused variable" warning in release mode
4342
4343     // publishing the groups in the study
4344     if ( !aStudy->_is_nil() ) {
4345       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
4346       _gen_i->PublishGroup( aStudy, aMesh, groupVar, shapeVar, group->GetName());
4347     }
4348   }
4349   if ( !addedIDs.empty() )
4350   {
4351     // python dump
4352     set<int>::iterator id = addedIDs.begin();
4353     for ( ; id != addedIDs.end(); ++id )
4354     {
4355       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(*id);
4356       int i = std::distance( _mapGroups.begin(), it );
4357       TPythonDump() << it->second << " = " << aMesh << ".GetGroups()[ "<< i << " ]";
4358     }
4359   }
4360 }
4361
4362 //=============================================================================
4363 /*!
4364  * \brief Return groups cantained in _mapGroups by their IDs
4365  */
4366 //=============================================================================
4367
4368 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
4369 {
4370   int nbGroups = groupIDs.size();
4371   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
4372   aList->length( nbGroups );
4373
4374   list<int>::const_iterator ids = groupIDs.begin();
4375   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
4376   {
4377     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
4378     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
4379       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
4380   }
4381   aList->length( nbGroups );
4382   return aList._retn();
4383 }
4384
4385 //=============================================================================
4386 /*!
4387  * \brief Return information about imported file
4388  */
4389 //=============================================================================
4390
4391 SMESH::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
4392 {
4393   SMESH::MedFileInfo_var res( _medFileInfo );
4394   if ( !res.operator->() ) {
4395     res = new SMESH::MedFileInfo;
4396     res->fileName = "";
4397     res->fileSize = res->major = res->minor = res->release = -1;
4398   }
4399   return res._retn();
4400 }
4401
4402 //=============================================================================
4403 /*!
4404  * \brief Pass names of mesh groups from study to mesh DS
4405  */
4406 //=============================================================================
4407
4408 void SMESH_Mesh_i::checkGroupNames()
4409 {
4410   int nbGrp = NbGroups();
4411   if ( !nbGrp )
4412     return;
4413
4414   SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
4415   if ( aStudy->_is_nil() )
4416     return; // nothing to do
4417   
4418   SMESH::ListOfGroups* grpList = 0;
4419   // avoid dump of "GetGroups"
4420   {
4421     // store python dump into a local variable inside local scope
4422     SMESH::TPythonDump pDump; // do not delete this line of code
4423     grpList = GetGroups();
4424   }
4425
4426   for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
4427     SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
4428     if ( !aGrp )
4429       continue;
4430     SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aStudy, aGrp );
4431     if ( aGrpSO->_is_nil() )
4432       continue;
4433     // correct name of the mesh group if necessary
4434     const char* guiName = aGrpSO->GetName();
4435     if ( strcmp(guiName, aGrp->GetName()) )
4436       aGrp->SetName( guiName );
4437   }
4438 }
4439
4440 //=============================================================================
4441 /*!
4442  * \brief Sets list of notebook variables used for Mesh operations separated by ":" symbol
4443  */
4444 //=============================================================================
4445 void SMESH_Mesh_i::SetParameters(const char* theParameters)
4446 {
4447   SMESH_Gen_i::GetSMESHGen()->UpdateParameters( CORBA::Object_var( _this() ).in(),
4448                                                 theParameters );
4449 }
4450
4451 //=============================================================================
4452 /*!
4453  * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
4454  */
4455 //=============================================================================
4456
4457 char* SMESH_Mesh_i::GetParameters()
4458 {
4459   return SMESH_Gen_i::GetSMESHGen()->GetParameters( SMESH::SMESH_Mesh_var( _this()) );
4460 }
4461
4462 //=============================================================================
4463 /*!
4464  * \brief Returns list of notebook variables used for last Mesh operation
4465  */
4466 //=============================================================================
4467 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
4468 {
4469   SMESH::string_array_var aResult = new SMESH::string_array();
4470   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
4471   if(gen) {
4472     CORBA::String_var aParameters = GetParameters();
4473     SALOMEDS::Study_var    aStudy = gen->GetCurrentStudy();
4474     if ( !aStudy->_is_nil()) {
4475       SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters); 
4476       if(aSections->length() > 0) {
4477         SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1];
4478         aResult->length(aVars.length());
4479         for(int i = 0;i < aVars.length();i++)
4480           aResult[i] = CORBA::string_dup( aVars[i]);
4481       }
4482     }
4483   }
4484   return aResult._retn();
4485 }
4486
4487 //=======================================================================
4488 //function : GetTypes
4489 //purpose  : Returns types of elements it contains
4490 //=======================================================================
4491
4492 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
4493 {
4494   if ( _preMeshInfo )
4495     return _preMeshInfo->GetTypes();
4496
4497   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
4498
4499   types->length( 5 );
4500   int nbTypes = 0;
4501   if (_impl->NbEdges())      types[nbTypes++] = SMESH::EDGE;
4502   if (_impl->NbFaces())      types[nbTypes++] = SMESH::FACE;
4503   if (_impl->NbVolumes())    types[nbTypes++] = SMESH::VOLUME;
4504   if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
4505   if (_impl->NbBalls())      types[nbTypes++] = SMESH::BALL;
4506   types->length( nbTypes );
4507
4508   return types._retn();
4509 }
4510
4511 //=======================================================================
4512 //function : GetMesh
4513 //purpose  : Returns self
4514 //=======================================================================
4515
4516 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
4517 {
4518   return SMESH::SMESH_Mesh::_duplicate( _this() );
4519 }
4520
4521 //=======================================================================
4522 //function : IsMeshInfoCorrect
4523 //purpose  : * Returns false if GetMeshInfo() returns incorrect information that may
4524 //           * happen if mesh data is not yet fully loaded from the file of study.
4525 //=======================================================================
4526
4527 bool SMESH_Mesh_i::IsMeshInfoCorrect()
4528 {
4529   return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
4530 }
4531
4532 //=============================================================================
4533 /*!
4534  * \brief Returns number of mesh elements per each \a EntityType
4535  */
4536 //=============================================================================
4537
4538 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
4539 {
4540   if ( _preMeshInfo )
4541     return _preMeshInfo->GetMeshInfo();
4542
4543   SMESH::long_array_var aRes = new SMESH::long_array();
4544   aRes->length(SMESH::Entity_Last);
4545   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
4546     aRes[i] = 0;
4547   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4548   if (!aMeshDS)
4549     return aRes._retn();
4550   const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
4551   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
4552     aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
4553   return aRes._retn();
4554 }
4555
4556 //=============================================================================
4557 /*!
4558  * \brief Returns number of mesh elements per each \a ElementType
4559  */
4560 //=============================================================================
4561
4562 SMESH::long_array* SMESH_Mesh_i::GetNbElementsByType()
4563 {
4564   SMESH::long_array_var aRes = new SMESH::long_array();
4565   aRes->length(SMESH::NB_ELEMENT_TYPES);
4566   for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
4567     aRes[ i ] = 0;
4568
4569   const SMDS_MeshInfo* meshInfo = 0;
4570   if ( _preMeshInfo )
4571     meshInfo = _preMeshInfo;
4572   else if ( SMESHDS_Mesh* meshDS = _impl->GetMeshDS() )
4573     meshInfo = & meshDS->GetMeshInfo();
4574
4575   if (meshInfo)
4576     for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
4577       aRes[i] = meshInfo->NbElements((SMDSAbs_ElementType)i);
4578
4579   return aRes._retn();
4580 }
4581
4582 //=============================================================================
4583 /*
4584  * Collect statistic of mesh elements given by iterator
4585  */
4586 //=============================================================================
4587
4588 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
4589                                    SMESH::long_array&         theInfo)
4590 {
4591   if (!theItr) return;
4592   while (theItr->more())
4593     theInfo[ theItr->next()->GetEntityType() ]++;
4594 }
4595
4596 //=============================================================================
4597 namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
4598            *                                             SMESH::ElementType        type) */
4599 {
4600   using namespace SMESH::Controls;
4601   //-----------------------------------------------------------------------------
4602   struct PredicateIterator : public SMDS_ElemIterator
4603   {
4604     SMDS_ElemIteratorPtr    _elemIter;
4605     PredicatePtr            _predicate;
4606     const SMDS_MeshElement* _elem;
4607
4608     PredicateIterator( SMDS_ElemIteratorPtr   iterator,
4609                        PredicatePtr predicate):
4610       _elemIter(iterator), _predicate(predicate)
4611     {
4612       next();
4613     }
4614     virtual bool more()
4615     {
4616       return _elem;
4617     }
4618     virtual const SMDS_MeshElement* next()
4619     {
4620       const SMDS_MeshElement* res = _elem;
4621       _elem = 0;
4622       while ( _elemIter->more() && !_elem )
4623       {
4624         _elem = _elemIter->next();
4625         if ( _elem && ( !_predicate->IsSatisfy( _elem->GetID() )))
4626           _elem = 0;
4627       }
4628       return res;
4629     }
4630   };
4631
4632   //-----------------------------------------------------------------------------
4633   struct IDSourceIterator : public SMDS_ElemIterator
4634   {
4635     const CORBA::Long*        _idPtr;
4636     const CORBA::Long*        _idEndPtr;
4637     SMESH::long_array_var     _idArray;
4638     const SMDS_Mesh*          _mesh;
4639     const SMDSAbs_ElementType _type;
4640     const SMDS_MeshElement*   _elem;
4641
4642     IDSourceIterator( const SMDS_Mesh*    mesh,
4643                       const CORBA::Long*  ids,
4644                       const int           nbIds,
4645                       SMDSAbs_ElementType type):
4646       _idPtr( ids ), _idEndPtr( ids + nbIds ), _mesh( mesh ), _type( type ), _elem( 0 )
4647     {
4648       if ( _idPtr && nbIds && _mesh )
4649         next();
4650     }
4651     IDSourceIterator( const SMDS_Mesh*    mesh,
4652                       SMESH::long_array*  idArray,
4653                       SMDSAbs_ElementType type):
4654       _idPtr( 0 ), _idEndPtr( 0 ), _idArray( idArray), _mesh( mesh ), _type( type ), _elem( 0 )
4655     {
4656       if ( idArray && _mesh )
4657       {
4658         _idPtr    = &_idArray[0];
4659         _idEndPtr = _idPtr + _idArray->length();
4660         next();
4661       }
4662     }
4663     virtual bool more()
4664     {
4665       return _elem;
4666     }
4667     virtual const SMDS_MeshElement* next()
4668     {
4669       const SMDS_MeshElement* res = _elem;
4670       _elem = 0;
4671       while ( _idPtr < _idEndPtr && !_elem )
4672       {
4673         if ( _type == SMDSAbs_Node )
4674         {
4675           _elem = _mesh->FindNode( *_idPtr++ );
4676         }
4677         else if ((_elem = _mesh->FindElement( *_idPtr++ )) &&
4678                  _elem->GetType() != _type )
4679         {
4680           _elem = 0;
4681         }
4682       }
4683       return res;
4684     }
4685   };
4686   //-----------------------------------------------------------------------------
4687
4688   struct NodeOfElemIterator : public SMDS_ElemIterator
4689   {
4690     TColStd_MapOfInteger    _checkedNodeIDs;
4691     SMDS_ElemIteratorPtr    _elemIter;
4692     SMDS_ElemIteratorPtr    _nodeIter;
4693     const SMDS_MeshElement* _node;
4694
4695     NodeOfElemIterator( SMDS_ElemIteratorPtr iter ): _elemIter( iter ), _node( 0 )
4696     {
4697       if ( _elemIter && _elemIter->more() )
4698       {
4699         _nodeIter = _elemIter->next()->nodesIterator();
4700         next();
4701       }
4702     }
4703     virtual bool more()
4704     {
4705       return _node;
4706     }
4707     virtual const SMDS_MeshElement* next()
4708     {
4709       const SMDS_MeshElement* res = _node;
4710       _node = 0;
4711       while (( _elemIter->more() || _nodeIter->more() ) && !_node )
4712       {
4713         if ( _nodeIter->more() )
4714         {
4715           _node = _nodeIter->next();
4716           if ( !_checkedNodeIDs.Add( _node->GetID() ))
4717             _node = 0;
4718         }
4719         else
4720         {
4721           _nodeIter = _elemIter->next()->nodesIterator();
4722         }
4723       }
4724       return res;
4725     }
4726   };
4727 }
4728
4729 //=============================================================================
4730 /*
4731  * Return iterator on elements of given type in given object
4732  */
4733 //=============================================================================
4734
4735 SMDS_ElemIteratorPtr SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_ptr theObject,
4736                                                SMESH::ElementType        theType)
4737 {
4738   SMDS_ElemIteratorPtr  elemIt;
4739   bool                  typeOK = false;
4740   SMDSAbs_ElementType elemType = SMDSAbs_ElementType( theType );
4741
4742   SMESH::SMESH_Mesh_var meshVar = theObject->GetMesh();
4743   SMESH_Mesh_i*          mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( meshVar );
4744   if ( !mesh_i ) return elemIt;
4745   SMESHDS_Mesh*          meshDS = mesh_i->GetImpl().GetMeshDS();
4746
4747   if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
4748   {
4749     elemIt = meshDS->elementsIterator( elemType );
4750     typeOK = true;
4751   }
4752   else if ( SMESH_subMesh_i* submesh_i = SMESH::DownCast<SMESH_subMesh_i*>( theObject ))
4753   {
4754     SMESHDS_SubMesh* sm = ((SMESHDS_Mesh*) meshDS)->MeshElements( submesh_i->GetId() );
4755     if ( sm )
4756     {
4757       elemIt = sm->GetElements();
4758       if ( elemType != SMDSAbs_Node )
4759       {
4760         typeOK = ( elemIt && elemIt->more() && elemIt->next()->GetType() == elemType );
4761         elemIt = typeOK ? sm->GetElements() : SMDS_ElemIteratorPtr();
4762       }
4763     }
4764   }
4765   else if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( theObject ))
4766   {
4767     SMESHDS_GroupBase* groupDS = group_i->GetGroupDS();
4768     if ( groupDS && ( groupDS->GetType() == elemType || elemType == SMDSAbs_Node ))
4769     {
4770       elemIt = groupDS->GetElements();
4771       typeOK = ( groupDS->GetType() == elemType );
4772     }
4773   }
4774   else if ( SMESH::Filter_i* filter_i = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
4775   {
4776     if ( filter_i->GetElementType() == theType || elemType == SMDSAbs_Node )
4777     {
4778       SMESH::Predicate_i* pred_i = filter_i->GetPredicate_i();
4779       if ( pred_i && pred_i->GetPredicate() )
4780       {
4781         SMDSAbs_ElementType filterType = SMDSAbs_ElementType( filter_i->GetElementType() );
4782         SMDS_ElemIteratorPtr allElemIt = meshDS->elementsIterator( filterType );
4783         elemIt = SMDS_ElemIteratorPtr( new PredicateIterator( allElemIt, pred_i->GetPredicate() ));
4784         typeOK = ( filterType == elemType );
4785       }
4786     }
4787   }
4788   else
4789   {
4790     SMESH::array_of_ElementType_var types = theObject->GetTypes();
4791     const bool                    isNodes = ( types->length() == 1 && types[0] == SMESH::NODE );
4792     if ( isNodes && elemType != SMDSAbs_Node )
4793       return elemIt;
4794     if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theObject ))
4795     {
4796       int nbIds;
4797       if ( CORBA::Long* ids = SMESH_MeshEditor_i::GetTemporaryIDs( theObject, nbIds ))
4798         elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids, nbIds, elemType ));
4799     }
4800     else
4801     {
4802       SMESH::long_array_var ids = theObject->GetIDs();
4803       elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids._retn(), elemType ));
4804     }
4805     typeOK = ( isNodes == ( elemType == SMDSAbs_Node ));
4806   }
4807
4808   if ( elemIt && elemIt->more() && !typeOK )
4809   {
4810     if ( elemType == SMDSAbs_Node )
4811     {
4812       elemIt = SMDS_ElemIteratorPtr( new NodeOfElemIterator( elemIt ));
4813     }
4814     else
4815     {
4816       elemIt = SMDS_ElemIteratorPtr();
4817     }
4818   }
4819   return elemIt;
4820 }
4821
4822 //=============================================================================
4823 namespace // Finding concurrent hypotheses
4824 //=============================================================================
4825 {
4826
4827 /*!
4828  * \brief mapping of mesh dimension into shape type
4829  */
4830 TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
4831 {
4832   TopAbs_ShapeEnum aType = TopAbs_SOLID;
4833   switch ( theDim ) {
4834   case 0: aType = TopAbs_VERTEX; break;
4835   case 1: aType = TopAbs_EDGE; break;
4836   case 2: aType = TopAbs_FACE; break;
4837   case 3:
4838   default:aType = TopAbs_SOLID; break;
4839   }
4840   return aType;
4841 }
4842
4843 //-----------------------------------------------------------------------------
4844 /*!
4845  * \brief Internal structure used to find concurent submeshes
4846  *
4847  * It represents a pair < submesh, concurent dimension >, where
4848  * 'concurrent dimension' is dimension of shape where the submesh can concurent
4849  *  with another submesh. In other words, it is dimension of a hypothesis assigned
4850  *  to submesh.
4851  */
4852 class SMESH_DimHyp
4853 {
4854  public:
4855   //! fileds
4856   int _dim;    //!< a dimension the algo can build (concurrent dimension)
4857   int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
4858   TopTools_MapOfShape _shapeMap;
4859   SMESH_subMesh*      _subMesh;
4860   list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
4861
4862   //-----------------------------------------------------------------------------
4863   // Return the algorithm
4864   const SMESH_Algo* GetAlgo() const
4865   { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
4866
4867   //-----------------------------------------------------------------------------
4868   //! Constructors
4869   SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
4870                const int            theDim,
4871                const TopoDS_Shape&  theShape)
4872   {
4873     _subMesh = (SMESH_subMesh*)theSubMesh;
4874     SetShape( theDim, theShape );
4875   }
4876
4877   //-----------------------------------------------------------------------------
4878   //! set shape
4879   void SetShape(const int           theDim,
4880                 const TopoDS_Shape& theShape)
4881   {
4882     _dim = theDim;
4883     _ownDim = SMESH_Gen::GetShapeDim(theShape);
4884     if (_dim >= _ownDim)
4885       _shapeMap.Add( theShape );
4886     else {
4887       TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
4888       for( ; anExp.More(); anExp.Next() )
4889         _shapeMap.Add( anExp.Current() );
4890     }
4891   }
4892
4893   //-----------------------------------------------------------------------------
4894   //! Check sharing of sub-shapes
4895   static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
4896                                const TopTools_MapOfShape& theToFind,
4897                                const TopAbs_ShapeEnum     theType)
4898   {
4899     bool isShared = false;
4900     TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
4901     for (; !isShared && anItr.More(); anItr.Next() )
4902     {
4903       const TopoDS_Shape aSubSh = anItr.Key();
4904       // check for case when concurrent dimensions are same
4905       isShared = theToFind.Contains( aSubSh );
4906       // check for sub-shape with concurrent dimension
4907       TopExp_Explorer anExp( aSubSh, theType );
4908       for ( ; !isShared && anExp.More(); anExp.Next() )
4909         isShared = theToFind.Contains( anExp.Current() );
4910     }
4911     return isShared;
4912   }
4913   
4914   //-----------------------------------------------------------------------------
4915   //! check algorithms
4916   static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
4917                         const SMESHDS_Hypothesis* theA2)
4918   {
4919     if ( !theA1 || !theA2 ||
4920          theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
4921          theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
4922       return false; // one of the hypothesis is not algorithm
4923     // check algorithm names (should be equal)
4924     return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
4925   }
4926
4927   
4928   //-----------------------------------------------------------------------------
4929   //! Check if sub-shape hypotheses are concurrent
4930   bool IsConcurrent(const SMESH_DimHyp* theOther) const
4931   {
4932     if ( _subMesh == theOther->_subMesh )
4933       return false; // same sub-shape - should not be
4934
4935     // if ( <own dim of either of submeshes> == <concurrent dim> &&
4936     //      any of the two submeshes is not on COMPOUND shape )
4937     //  -> no concurrency
4938     bool meIsCompound    = (_subMesh->GetSubMeshDS() &&
4939                             _subMesh->GetSubMeshDS()->IsComplexSubmesh());
4940     bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
4941                             theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
4942     if ( (_ownDim == _dim  || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
4943       return false;
4944
4945 //     bool checkSubShape = ( _dim >= theOther->_dim )
4946 //       ? isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(theOther->_dim) )
4947 //       : isShareSubShapes( theOther->_shapeMap, _shapeMap, shapeTypeByDim(_dim) ) ;
4948     bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
4949     if ( !checkSubShape )
4950         return false;
4951
4952     // check algorithms to be same
4953     if ( !checkAlgo( this->GetAlgo(), theOther->GetAlgo() ))
4954       return true; // different algorithms -> concurrency !
4955
4956     // check hypothesises for concurrence (skip first as algorithm)
4957     int nbSame = 0;
4958     // pointers should be same, because it is referened from mesh hypothesis partition
4959     list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
4960     list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
4961     for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
4962       if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
4963         nbSame++;
4964     // the submeshes are concurrent if their algorithms has different parameters
4965     return nbSame != theOther->_hypotheses.size() - 1;
4966   }
4967
4968   // Return true if algorithm of this SMESH_DimHyp is used if no
4969   // sub-mesh order is imposed by the user
4970   bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
4971   {
4972     // NeedDiscreteBoundary() algo has a higher priority
4973     if ( this    ->GetAlgo()->NeedDiscreteBoundary() !=
4974          theOther->GetAlgo()->NeedDiscreteBoundary() )
4975       return !this->GetAlgo()->NeedDiscreteBoundary();
4976
4977     return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
4978   }
4979   
4980 }; // end of SMESH_DimHyp
4981 //-----------------------------------------------------------------------------
4982
4983 typedef list<const SMESH_DimHyp*> TDimHypList;
4984
4985 //-----------------------------------------------------------------------------
4986
4987 void addDimHypInstance(const int                               theDim, 
4988                        const TopoDS_Shape&                     theShape,
4989                        const SMESH_Algo*                       theAlgo,
4990                        const SMESH_subMesh*                    theSubMesh,
4991                        const list <const SMESHDS_Hypothesis*>& theHypList,
4992                        TDimHypList*                            theDimHypListArr )
4993 {
4994   TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
4995   if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) {
4996     SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
4997     dimHyp->_hypotheses.push_front(theAlgo);
4998     listOfdimHyp.push_back( dimHyp );
4999   }
5000   
5001   SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
5002   dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
5003                               theHypList.begin(), theHypList.end() );
5004 }
5005
5006 //-----------------------------------------------------------------------------
5007 void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
5008                            TDimHypList&        theListOfConcurr)
5009 {
5010   if ( theListOfConcurr.empty() )
5011   {
5012     theListOfConcurr.push_back( theDimHyp );
5013   }
5014   else
5015   {
5016     TDimHypList::iterator hypIt = theListOfConcurr.begin();
5017     while ( hypIt != theListOfConcurr.end() &&
5018             !theDimHyp->IsHigherPriorityThan( *hypIt ))
5019       ++hypIt;
5020     theListOfConcurr.insert( hypIt, theDimHyp );
5021   }
5022 }
5023
5024 //-----------------------------------------------------------------------------
5025 void findConcurrents(const SMESH_DimHyp* theDimHyp,
5026                      const TDimHypList&  theListOfDimHyp,
5027                      TDimHypList&        theListOfConcurrHyp,
5028                      set<int>&           theSetOfConcurrId )
5029 {
5030   TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
5031   for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
5032   {
5033     const SMESH_DimHyp* curDimHyp = *rIt;
5034     if ( curDimHyp == theDimHyp )
5035       break; // meet own dimHyp pointer in same dimension
5036
5037     if ( theDimHyp->IsConcurrent( curDimHyp ) &&
5038          theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
5039     {
5040       addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
5041     }
5042   }
5043 }
5044
5045 //-----------------------------------------------------------------------------
5046 void unionLists(TListOfInt&       theListOfId,
5047                 TListOfListOfInt& theListOfListOfId,
5048                 const int         theIndx )
5049 {
5050   TListOfListOfInt::iterator it = theListOfListOfId.begin();
5051   for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) {
5052     if ( i < theIndx )
5053       continue; //skip already treated lists
5054     // check if other list has any same submesh object
5055     TListOfInt& otherListOfId = *it;
5056     if ( find_first_of( theListOfId.begin(), theListOfId.end(),
5057                         otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
5058       continue;
5059          
5060     // union two lists (from source into target)
5061     TListOfInt::iterator it2 = otherListOfId.begin();
5062     for ( ; it2 != otherListOfId.end(); it2++ ) {
5063       if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
5064         theListOfId.push_back(*it2);
5065     }
5066     // clear source list
5067     otherListOfId.clear();
5068   }
5069 }
5070 //-----------------------------------------------------------------------------
5071
5072 //! free memory allocated for dimension-hypothesis objects
5073 void removeDimHyps( TDimHypList* theArrOfList )
5074 {
5075   for (int i = 0; i < 4; i++ ) {
5076     TDimHypList& listOfdimHyp = theArrOfList[i];
5077     TDimHypList::const_iterator it = listOfdimHyp.begin();
5078     for ( ; it != listOfdimHyp.end(); it++ )
5079       delete (*it);
5080   }
5081 }
5082
5083 //-----------------------------------------------------------------------------
5084 /*!
5085  * \brief find common submeshes with given submesh
5086  * \param theSubMeshList list of already collected submesh to check
5087  * \param theSubMesh given submesh to intersect with other
5088  * \param theCommonSubMeshes collected common submeshes
5089  */
5090 void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
5091                         const SMESH_subMesh*        theSubMesh,
5092                         set<const SMESH_subMesh*>&  theCommon )
5093 {
5094   if ( !theSubMesh )
5095     return;
5096   list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
5097   for ( ; it != theSubMeshList.end(); it++ )
5098     theSubMesh->FindIntersection( *it, theCommon );
5099   theSubMeshList.push_back( theSubMesh );
5100   //theCommon.insert( theSubMesh );
5101 }
5102
5103 } // namespace
5104
5105 //=============================================================================
5106 /*!
5107  * \brief Return submesh objects list in meshing order
5108  */
5109 //=============================================================================
5110
5111 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
5112 {
5113   SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
5114
5115   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5116   if ( !aMeshDS )
5117     return aResult._retn();
5118   
5119   ::SMESH_Mesh& mesh = GetImpl();
5120   TListOfListOfInt anOrder = mesh.GetMeshOrder(); // is there already defined order?
5121   if ( !anOrder.size() ) {
5122
5123     // collect submeshes and detect concurrent algorithms and hypothesises
5124     TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
5125     
5126     map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
5127     for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) {
5128       ::SMESH_subMesh* sm = (*i_sm).second;
5129       // shape of submesh
5130       const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
5131
5132       // list of assigned hypothesises
5133       const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
5134       // Find out dimensions where the submesh can be concurrent.
5135       // We define the dimensions by algo of each of hypotheses in hypList
5136       list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
5137       for( ; hypIt != hypList.end(); hypIt++ ) {
5138         SMESH_Algo* anAlgo = 0;
5139         const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
5140         if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
5141           // hyp it-self is algo
5142           anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
5143         else {
5144           // try to find algorithm with help of sub-shapes
5145           TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
5146           for ( ; !anAlgo && anExp.More(); anExp.Next() )
5147             anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
5148         }
5149         if (!anAlgo)
5150           continue; // no algorithm assigned to a current submesh
5151
5152         int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
5153         // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary())
5154
5155         // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
5156         for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
5157           addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
5158       }
5159     } // end iterations on submesh
5160     
5161     // iterate on created dimension-hypotheses and check for concurrents
5162     for ( int i = 0; i < 4; i++ ) {
5163       const TDimHypList& listOfDimHyp = dimHypListArr[i];
5164       // check for concurrents in own and other dimensions (step-by-step)
5165       TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
5166       for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) {
5167         const SMESH_DimHyp* dimHyp = *dhIt;
5168         TDimHypList listOfConcurr;
5169         set<int>    setOfConcurrIds;
5170         // looking for concurrents and collect into own list
5171         for ( int j = i; j < 4; j++ )
5172           findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
5173         // check if any concurrents found
5174         if ( listOfConcurr.size() > 0 ) {
5175           // add own submesh to list of concurrent
5176           addInOrderOfPriority( dimHyp, listOfConcurr );
5177           list<int> listOfConcurrIds;
5178           TDimHypList::iterator hypIt = listOfConcurr.begin();
5179           for ( ; hypIt != listOfConcurr.end(); ++hypIt )
5180             listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
5181           anOrder.push_back( listOfConcurrIds );
5182         }
5183       }
5184     }
5185     
5186     removeDimHyps(dimHypListArr);
5187     
5188     // now, minimise the number of concurrent groups
5189     // Here we assume that lists of submeshes can have same submesh
5190     // in case of multi-dimension algorithms, as result
5191     //  list with common submesh has to be united into one list
5192     int listIndx = 0;
5193     TListOfListOfInt::iterator listIt = anOrder.begin();
5194     for(; listIt != anOrder.end(); listIt++, listIndx++ )
5195       unionLists( *listIt,  anOrder, listIndx + 1 );
5196   }
5197   // convert submesh ids into interface instances
5198   //  and dump command into python
5199   convertMeshOrder( anOrder, aResult, false );
5200
5201   return aResult._retn();
5202 }
5203
5204 //=============================================================================
5205 /*!
5206  * \brief Set submesh object order
5207  * \param theSubMeshArray submesh array order
5208  */
5209 //=============================================================================
5210
5211 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
5212 {
5213   if ( _preMeshInfo )
5214     _preMeshInfo->ForgetOrLoad();
5215
5216   bool res = false;
5217   ::SMESH_Mesh& mesh = GetImpl();
5218
5219   TPythonDump aPythonDump; // prevent dump of called methods
5220   aPythonDump << "isDone = " << SMESH::SMESH_Mesh_var(_this()) << ".SetMeshOrder( [ ";
5221
5222   TListOfListOfInt subMeshOrder;
5223   for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
5224   {
5225     const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
5226     TListOfInt subMeshIds;
5227     aPythonDump << "[ ";
5228     // Collect subMeshes which should be clear
5229     //  do it list-by-list, because modification of submesh order
5230     //  take effect between concurrent submeshes only
5231     set<const SMESH_subMesh*> subMeshToClear;
5232     list<const SMESH_subMesh*> subMeshList;
5233     for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
5234     {
5235       const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
5236       if ( j > 0 )
5237         aPythonDump << ", ";
5238       aPythonDump << subMesh;
5239       subMeshIds.push_back( subMesh->GetId() );
5240       // detect common parts of submeshes
5241       if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
5242         findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
5243     }
5244     aPythonDump << " ]";
5245     subMeshOrder.push_back( subMeshIds );
5246
5247     // clear collected submeshes
5248     set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
5249     for ( ; clrIt != subMeshToClear.end(); clrIt++ )
5250       if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
5251         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
5252   }
5253   aPythonDump << " ])";
5254
5255   mesh.SetMeshOrder( subMeshOrder );
5256   res = true;
5257   
5258   return res;
5259 }
5260
5261 //=============================================================================
5262 /*!
5263  * \brief Convert submesh ids into submesh interfaces
5264  */
5265 //=============================================================================
5266
5267 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt&     theIdsOrder,
5268                                      SMESH::submesh_array_array& theResOrder,
5269                                      const bool                  theIsDump)
5270 {
5271   int nbSet = theIdsOrder.size();
5272   TPythonDump aPythonDump; // prevent dump of called methods
5273   if ( theIsDump )
5274     aPythonDump << "[ ";
5275   theResOrder.length(nbSet);
5276   TListOfListOfInt::const_iterator it = theIdsOrder.begin();
5277   int listIndx = 0;
5278   for( ; it != theIdsOrder.end(); it++ ) {
5279     // translate submesh identificators into submesh objects
5280     //  takeing into account real number of concurrent lists
5281     const TListOfInt& aSubOrder = (*it);
5282     if (!aSubOrder.size())
5283       continue;
5284     if ( theIsDump )
5285       aPythonDump << "[ ";
5286     // convert shape indeces into interfaces
5287     SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
5288     aResSubSet->length(aSubOrder.size());
5289     TListOfInt::const_iterator subIt = aSubOrder.begin();
5290     for( int j = 0; subIt != aSubOrder.end(); subIt++ ) {
5291       if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
5292         continue;
5293       SMESH::SMESH_subMesh_var subMesh =
5294         SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
5295       if ( theIsDump ) {
5296         if ( j > 0 )
5297           aPythonDump << ", ";
5298         aPythonDump << subMesh;
5299       }
5300       aResSubSet[ j++ ] = subMesh;
5301     }
5302     if ( theIsDump )
5303       aPythonDump << " ]";
5304     theResOrder[ listIndx++ ] = aResSubSet;
5305   }
5306   // correct number of lists
5307   theResOrder.length( listIndx );
5308
5309   if ( theIsDump ) {
5310     // finilise python dump
5311     aPythonDump << " ]";
5312     aPythonDump << " = " << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshOrder()";
5313   }
5314 }
5315
5316 //================================================================================
5317 //
5318 // Implementation of SMESH_MeshPartDS
5319 //
5320 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
5321   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
5322 {
5323   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
5324   SMESH_Mesh_i*       mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
5325
5326   _meshDS = mesh_i->GetImpl().GetMeshDS();
5327
5328   SetPersistentId( _meshDS->GetPersistentId() );
5329
5330   if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
5331   {
5332     // <meshPart> is the whole mesh
5333     myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
5334     // copy groups
5335     set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
5336     myGroupSet = _meshDS->GetGroups();
5337   }
5338   else
5339   {
5340     TMeshInfo tmpInfo;
5341     SMESH::long_array_var           anIDs = meshPart->GetIDs();
5342     SMESH::array_of_ElementType_var types = meshPart->GetTypes();
5343     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
5344     {
5345       for (int i=0; i < anIDs->length(); i++)
5346         if ( const SMDS_MeshNode * n = _meshDS->FindNode(anIDs[i]))
5347           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
5348             tmpInfo.Add( n );
5349     }
5350     else
5351     {
5352       for (int i=0; i < anIDs->length(); i++)
5353         if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
5354           if ( _elements[ e->GetType() ].insert( e ).second )
5355           {
5356             tmpInfo.Add( e );
5357             SMDS_ElemIteratorPtr nIt = e->nodesIterator();
5358             while ( nIt->more() )
5359             {
5360               const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
5361               if ( _elements[ SMDSAbs_Node ].insert( n ).second )
5362                 tmpInfo.Add( n );
5363             }
5364           }
5365     }
5366     myInfo = tmpInfo;
5367
5368     _meshDS = 0; // to enforce iteration on _elements and _nodes
5369   }
5370 }
5371 // -------------------------------------------------------------------------------------
5372 SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
5373   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
5374 {
5375   TMeshInfo tmpInfo;
5376   list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
5377   for ( ; partIt != meshPart.end(); ++partIt )
5378     if ( const SMDS_MeshElement * e = *partIt )
5379       if ( _elements[ e->GetType() ].insert( e ).second )
5380       {
5381         tmpInfo.Add( e );
5382         SMDS_ElemIteratorPtr nIt = e->nodesIterator();
5383         while ( nIt->more() )
5384         {
5385           const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
5386           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
5387             tmpInfo.Add( n );
5388         }
5389       }
5390   myInfo = tmpInfo;
5391 }
5392 // -------------------------------------------------------------------------------------
5393 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
5394 {
5395   if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
5396
5397   typedef SMDS_SetIterator
5398     <const SMDS_MeshElement*,
5399     TIDSortedElemSet::const_iterator,
5400     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
5401     SMDS_MeshElement::GeomFilter
5402     > TIter;
5403
5404   SMDSAbs_ElementType type = SMDS_MeshCell::toSmdsType( geomType );
5405
5406   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
5407                                           _elements[type].end(),
5408                                           SMDS_MeshElement::GeomFilter( geomType )));
5409 }
5410 // -------------------------------------------------------------------------------------
5411 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
5412 {
5413   if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
5414
5415   typedef SMDS_SetIterator
5416     <const SMDS_MeshElement*,
5417     TIDSortedElemSet::const_iterator,
5418     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
5419     SMDS_MeshElement::EntityFilter
5420     > TIter;
5421
5422   SMDSAbs_ElementType type = SMDS_MeshCell::toSmdsType( entity );
5423
5424   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
5425                                           _elements[type].end(),
5426                                           SMDS_MeshElement::EntityFilter( entity )));
5427 }
5428 // -------------------------------------------------------------------------------------
5429 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
5430 {
5431   typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
5432   if ( type == SMDSAbs_All && !_meshDS )
5433   {
5434     typedef vector< SMDS_ElemIteratorPtr > TIterVec;
5435     TIterVec iterVec;
5436     for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
5437       if ( !_elements[i].empty() && i != SMDSAbs_Node )
5438         iterVec.push_back
5439           ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
5440
5441     typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
5442     return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
5443   }
5444   return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
5445       ( new TIter( _elements[type].begin(), _elements[type].end() ));
5446 }
5447 // -------------------------------------------------------------------------------------
5448 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType)                       \
5449   iterType SMESH_MeshPartDS::methName( bool idInceasingOrder) const                 \
5450   {                                                                                 \
5451     typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
5452     return _meshDS ? _meshDS->methName(idInceasingOrder) : iterType                 \
5453       ( new TIter( _elements[elemType].begin(), _elements[elemType].end() ));       \
5454   }
5455 // -------------------------------------------------------------------------------------
5456 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
5457 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
5458 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
5459 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
5460 #undef _GET_ITER_DEFINE
5461 //
5462 // END Implementation of SMESH_MeshPartDS
5463 //
5464 //================================================================================
5465
5466