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