Salome HOME
Merge from V6_main_20120808 08Aug12
[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_EdgeIteratorPtr   edgesIterator     (bool idInceasingOrder=false) const;
2853   virtual SMDS_FaceIteratorPtr   facesIterator     (bool idInceasingOrder=false) const;
2854   virtual SMDS_VolumeIteratorPtr volumesIterator   (bool idInceasingOrder=false) const;
2855
2856   virtual SMDS_ElemIteratorPtr elementsIterator(SMDSAbs_ElementType type=SMDSAbs_All) const;
2857   virtual SMDS_ElemIteratorPtr elementGeomIterator(SMDSAbs_GeometryType type) const;
2858   virtual SMDS_ElemIteratorPtr elementEntityIterator(SMDSAbs_EntityType type) const;
2859
2860 private:
2861   TIDSortedElemSet _elements[ SMDSAbs_NbElementTypes ];
2862   SMESHDS_Mesh*    _meshDS;
2863   /*!
2864    * \brief Class used to access to protected data of SMDS_MeshInfo
2865    */
2866   struct TMeshInfo : public SMDS_MeshInfo
2867   {
2868     void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); }
2869   };
2870 };
2871
2872 //================================================================================
2873 /*!
2874  * \brief Export a part of mesh to a med file
2875  */
2876 //================================================================================
2877
2878 void SMESH_Mesh_i::ExportPartToMED(::SMESH::SMESH_IDSource_ptr meshPart,
2879                                    const char*                 file,
2880                                    CORBA::Boolean              auto_groups,
2881                                    ::SMESH::MED_VERSION        version,
2882                                    ::CORBA::Boolean            overwrite)
2883   throw (SALOME::SALOME_Exception)
2884 {
2885   Unexpect aCatch(SALOME_SalomeException);
2886   if ( _preMeshInfo )
2887     _preMeshInfo->FullLoadFromFile();
2888
2889   PrepareForWriting(file, overwrite);
2890
2891   string aMeshName = "Mesh";
2892   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
2893   if ( !aStudy->_is_nil() ) {
2894     SALOMEDS::SObject_var SO = _gen_i->ObjectToSObject( aStudy, meshPart );
2895     if ( !SO->_is_nil() ) {
2896       CORBA::String_var name = SO->GetName();
2897       aMeshName = name;
2898     }
2899   }
2900   SMESH_MeshPartDS partDS( meshPart );
2901   _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version, &partDS );
2902
2903   TPythonDump() << _this() << ".ExportPartToMED( " << meshPart << ", r'" << file << "', "
2904                 << auto_groups << ", " << version << ", " << overwrite << " )";
2905 }
2906
2907 //================================================================================
2908 /*!
2909  * \brief Export a part of mesh to a DAT file
2910  */
2911 //================================================================================
2912
2913 void SMESH_Mesh_i::ExportPartToDAT(::SMESH::SMESH_IDSource_ptr meshPart,
2914                                    const char*                 file)
2915   throw (SALOME::SALOME_Exception)
2916 {
2917   Unexpect aCatch(SALOME_SalomeException);
2918   if ( _preMeshInfo )
2919     _preMeshInfo->FullLoadFromFile();
2920
2921   PrepareForWriting(file);
2922
2923   SMESH_MeshPartDS partDS( meshPart );
2924   _impl->ExportDAT(file,&partDS);
2925
2926   TPythonDump() << _this() << ".ExportPartToDAT( " << meshPart << ", r'" << file << "' )";
2927 }
2928 //================================================================================
2929 /*!
2930  * \brief Export a part of mesh to an UNV file
2931  */
2932 //================================================================================
2933
2934 void SMESH_Mesh_i::ExportPartToUNV(::SMESH::SMESH_IDSource_ptr meshPart,
2935                                    const char*                 file)
2936   throw (SALOME::SALOME_Exception)
2937 {
2938   Unexpect aCatch(SALOME_SalomeException);
2939   if ( _preMeshInfo )
2940     _preMeshInfo->FullLoadFromFile();
2941
2942   PrepareForWriting(file);
2943
2944   SMESH_MeshPartDS partDS( meshPart );
2945   _impl->ExportUNV(file, &partDS);
2946
2947   TPythonDump() << _this() << ".ExportPartToUNV( " << meshPart<< ", r'" << file << "' )";
2948 }
2949 //================================================================================
2950 /*!
2951  * \brief Export a part of mesh to an STL file
2952  */
2953 //================================================================================
2954
2955 void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
2956                                    const char*                 file,
2957                                    ::CORBA::Boolean            isascii)
2958   throw (SALOME::SALOME_Exception)
2959 {
2960   Unexpect aCatch(SALOME_SalomeException);
2961   if ( _preMeshInfo )
2962     _preMeshInfo->FullLoadFromFile();
2963
2964   PrepareForWriting(file);
2965
2966   SMESH_MeshPartDS partDS( meshPart );
2967   _impl->ExportSTL(file, isascii, &partDS);
2968
2969   TPythonDump() << _this() << ".ExportPartToSTL( "
2970                 << meshPart<< ", r'" << file << "', " << isascii << ")";
2971 }
2972
2973 //================================================================================
2974 /*!
2975  * \brief Export a part of mesh to an STL file
2976  */
2977 //================================================================================
2978
2979 void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart,
2980                               const char*                 file,
2981                               CORBA::Boolean              overwrite)
2982   throw (SALOME::SALOME_Exception)
2983 {
2984 #ifdef WITH_CGNS
2985   Unexpect aCatch(SALOME_SalomeException);
2986   if ( _preMeshInfo )
2987     _preMeshInfo->FullLoadFromFile();
2988
2989   PrepareForWriting(file,overwrite);
2990
2991   SMESH_MeshPartDS partDS( meshPart );
2992   _impl->ExportCGNS(file, &partDS);
2993
2994   TPythonDump() << _this() << ".ExportCGNS( "
2995                 << meshPart<< ", r'" << file << "', " << overwrite << ")";
2996 #else
2997   THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
2998 #endif
2999 }
3000
3001 //=============================================================================
3002 /*!
3003  * Return implementation of SALOME_MED::MESH interfaces
3004  */
3005 //=============================================================================
3006
3007 SALOME_MED::MESH_ptr SMESH_Mesh_i::GetMEDMesh()throw(SALOME::SALOME_Exception)
3008 {
3009   Unexpect aCatch(SALOME_SalomeException);
3010   if ( _preMeshInfo )
3011     _preMeshInfo->FullLoadFromFile();
3012
3013   SMESH_MEDMesh_i *aMedMesh = new SMESH_MEDMesh_i(this);
3014   SALOME_MED::MESH_var aMesh = aMedMesh->_this();
3015   return aMesh._retn();
3016 }
3017
3018 //=============================================================================
3019
3020 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
3021 {
3022   Unexpect aCatch(SALOME_SalomeException);
3023   if ( _preMeshInfo )
3024     return _preMeshInfo->NbNodes();
3025
3026   return _impl->NbNodes();
3027 }
3028
3029 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
3030 {
3031   Unexpect aCatch(SALOME_SalomeException);
3032   if ( _preMeshInfo )
3033     return _preMeshInfo->NbElements();
3034
3035   return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes() + NbBalls();
3036 }
3037
3038 CORBA::Long SMESH_Mesh_i::Nb0DElements()throw (SALOME::SALOME_Exception)
3039 {
3040   Unexpect aCatch(SALOME_SalomeException);
3041   if ( _preMeshInfo )
3042     return _preMeshInfo->Nb0DElements();
3043
3044   return _impl->Nb0DElements();
3045 }
3046
3047 CORBA::Long SMESH_Mesh_i::NbBalls() throw (SALOME::SALOME_Exception)
3048 {
3049   Unexpect aCatch(SALOME_SalomeException);
3050   if ( _preMeshInfo )
3051     return _preMeshInfo->NbBalls();
3052
3053   return _impl->NbBalls();
3054 }
3055
3056 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
3057 {
3058   Unexpect aCatch(SALOME_SalomeException);
3059   if ( _preMeshInfo )
3060     return _preMeshInfo->NbEdges();
3061
3062   return _impl->NbEdges();
3063 }
3064
3065 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
3066   throw(SALOME::SALOME_Exception)
3067 {
3068   Unexpect aCatch(SALOME_SalomeException);
3069   if ( _preMeshInfo )
3070     return _preMeshInfo->NbEdges( (SMDSAbs_ElementOrder) order );
3071
3072   return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
3073 }
3074
3075 //=============================================================================
3076
3077 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
3078 {
3079   Unexpect aCatch(SALOME_SalomeException);
3080   if ( _preMeshInfo )
3081     return _preMeshInfo->NbFaces();
3082
3083   return _impl->NbFaces();
3084 }
3085
3086 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
3087 {
3088   Unexpect aCatch(SALOME_SalomeException);
3089   if ( _preMeshInfo )
3090     return _preMeshInfo->NbTriangles();
3091
3092   return _impl->NbTriangles();
3093 }
3094
3095 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
3096 {
3097   Unexpect aCatch(SALOME_SalomeException);
3098   if ( _preMeshInfo )
3099     return _preMeshInfo->NbQuadrangles();
3100
3101   return _impl->NbQuadrangles();
3102 }
3103
3104 CORBA::Long SMESH_Mesh_i::NbBiQuadQuadrangles()throw(SALOME::SALOME_Exception)
3105 {
3106   Unexpect aCatch(SALOME_SalomeException);
3107   if ( _preMeshInfo )
3108     return _preMeshInfo->NbBiQuadQuadrangles();
3109
3110   return _impl->NbBiQuadQuadrangles();
3111 }
3112
3113 CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
3114 {
3115   Unexpect aCatch(SALOME_SalomeException);
3116   if ( _preMeshInfo )
3117     return _preMeshInfo->NbPolygons();
3118
3119   return _impl->NbPolygons();
3120 }
3121
3122 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
3123   throw(SALOME::SALOME_Exception)
3124 {
3125   Unexpect aCatch(SALOME_SalomeException);
3126   if ( _preMeshInfo )
3127     return _preMeshInfo->NbFaces( (SMDSAbs_ElementOrder) order );
3128
3129   return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
3130 }
3131
3132 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
3133   throw(SALOME::SALOME_Exception)
3134 {
3135   Unexpect aCatch(SALOME_SalomeException);
3136   if ( _preMeshInfo )
3137     return _preMeshInfo->NbTriangles( (SMDSAbs_ElementOrder) order );
3138
3139   return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
3140 }
3141
3142 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
3143   throw(SALOME::SALOME_Exception)
3144 {
3145   Unexpect aCatch(SALOME_SalomeException);
3146   if ( _preMeshInfo )
3147     return _preMeshInfo->NbQuadrangles( (SMDSAbs_ElementOrder) order );
3148
3149   return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
3150 }
3151
3152 //=============================================================================
3153
3154 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
3155 {
3156   Unexpect aCatch(SALOME_SalomeException);
3157   if ( _preMeshInfo )
3158     return _preMeshInfo->NbVolumes();
3159
3160   return _impl->NbVolumes();
3161 }
3162
3163 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
3164 {
3165   Unexpect aCatch(SALOME_SalomeException);
3166   if ( _preMeshInfo )
3167     return _preMeshInfo->NbTetras();
3168
3169   return _impl->NbTetras();
3170 }
3171
3172 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
3173 {
3174   Unexpect aCatch(SALOME_SalomeException);
3175   if ( _preMeshInfo )
3176     return _preMeshInfo->NbHexas();
3177
3178   return _impl->NbHexas();
3179 }
3180
3181 CORBA::Long SMESH_Mesh_i::NbTriQuadraticHexas()throw(SALOME::SALOME_Exception)
3182 {
3183   Unexpect aCatch(SALOME_SalomeException);
3184   if ( _preMeshInfo )
3185     return _preMeshInfo->NbTriQuadHexas();
3186
3187   return _impl->NbTriQuadraticHexas();
3188 }
3189
3190 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
3191 {
3192   Unexpect aCatch(SALOME_SalomeException);
3193   if ( _preMeshInfo )
3194     return _preMeshInfo->NbPyramids();
3195
3196   return _impl->NbPyramids();
3197 }
3198
3199 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
3200 {
3201   Unexpect aCatch(SALOME_SalomeException);
3202   if ( _preMeshInfo )
3203     return _preMeshInfo->NbPrisms();
3204
3205   return _impl->NbPrisms();
3206 }
3207
3208 CORBA::Long SMESH_Mesh_i::NbHexagonalPrisms()throw(SALOME::SALOME_Exception)
3209 {
3210   Unexpect aCatch(SALOME_SalomeException);
3211   if ( _preMeshInfo )
3212     return _preMeshInfo->NbHexPrisms();
3213
3214   return _impl->NbHexagonalPrisms();
3215 }
3216
3217 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
3218 {
3219   Unexpect aCatch(SALOME_SalomeException);
3220   if ( _preMeshInfo )
3221     return _preMeshInfo->NbPolyhedrons();
3222
3223   return _impl->NbPolyhedrons();
3224 }
3225
3226 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
3227   throw(SALOME::SALOME_Exception)
3228 {
3229   Unexpect aCatch(SALOME_SalomeException);
3230   if ( _preMeshInfo )
3231     return _preMeshInfo->NbVolumes( (SMDSAbs_ElementOrder) order );
3232
3233   return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
3234 }
3235
3236 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
3237   throw(SALOME::SALOME_Exception)
3238 {
3239   Unexpect aCatch(SALOME_SalomeException);
3240   if ( _preMeshInfo )
3241     return _preMeshInfo->NbTetras( (SMDSAbs_ElementOrder) order);
3242
3243   return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
3244 }
3245
3246 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
3247   throw(SALOME::SALOME_Exception)
3248 {
3249   Unexpect aCatch(SALOME_SalomeException);
3250   if ( _preMeshInfo )
3251     return _preMeshInfo->NbHexas( (SMDSAbs_ElementOrder) order);
3252
3253   return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
3254 }
3255
3256 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
3257   throw(SALOME::SALOME_Exception)
3258 {
3259   Unexpect aCatch(SALOME_SalomeException);
3260   if ( _preMeshInfo )
3261     return _preMeshInfo->NbPyramids( (SMDSAbs_ElementOrder) order);
3262
3263   return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
3264 }
3265
3266 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
3267   throw(SALOME::SALOME_Exception)
3268 {
3269   Unexpect aCatch(SALOME_SalomeException);
3270   if ( _preMeshInfo )
3271     return _preMeshInfo->NbPrisms( (SMDSAbs_ElementOrder) order);
3272
3273   return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
3274 }
3275
3276 //=============================================================================
3277 /*!
3278  * Returns nb of published sub-meshes
3279  */
3280 //=============================================================================
3281
3282 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
3283 {
3284   Unexpect aCatch(SALOME_SalomeException);
3285   return _mapSubMesh_i.size();
3286 }
3287
3288 //=============================================================================
3289 /*!
3290  * Dumps mesh into a string
3291  */
3292 //=============================================================================
3293
3294 char* SMESH_Mesh_i::Dump()
3295 {
3296   ostringstream os;
3297   _impl->Dump( os );
3298   return CORBA::string_dup( os.str().c_str() );
3299 }
3300
3301 //=============================================================================
3302 /*!
3303  * Method of SMESH_IDSource interface
3304  */
3305 //=============================================================================
3306
3307 SMESH::long_array* SMESH_Mesh_i::GetIDs()
3308 {
3309   return GetElementsId();
3310 }
3311
3312 //=============================================================================
3313 /*!
3314  * Returns ids of all elements
3315  */
3316 //=============================================================================
3317
3318 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
3319      throw (SALOME::SALOME_Exception)
3320 {
3321   Unexpect aCatch(SALOME_SalomeException);
3322   if ( _preMeshInfo )
3323     _preMeshInfo->FullLoadFromFile();
3324
3325   SMESH::long_array_var aResult = new SMESH::long_array();
3326   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3327
3328   if ( aSMESHDS_Mesh == NULL )
3329     return aResult._retn();
3330
3331   long nbElements = NbElements();
3332   aResult->length( nbElements );
3333   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
3334   for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
3335     aResult[i] = anIt->next()->GetID();
3336
3337   return aResult._retn();
3338 }
3339
3340
3341 //=============================================================================
3342 /*!
3343  * Returns ids of all elements of given type
3344  */
3345 //=============================================================================
3346
3347 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
3348     throw (SALOME::SALOME_Exception)
3349 {
3350   Unexpect aCatch(SALOME_SalomeException);
3351   if ( _preMeshInfo )
3352     _preMeshInfo->FullLoadFromFile();
3353
3354   SMESH::long_array_var aResult = new SMESH::long_array();
3355   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3356
3357   if ( aSMESHDS_Mesh == NULL )
3358     return aResult._retn();
3359
3360   long nbElements = NbElements();
3361
3362   // No sense in returning ids of elements along with ids of nodes:
3363   // when theElemType == SMESH::ALL, return node ids only if
3364   // there are no elements
3365   if ( theElemType == SMESH::NODE || (theElemType == SMESH::ALL && nbElements == 0) )
3366     return GetNodesId();
3367
3368   aResult->length( nbElements );
3369
3370   int i = 0;
3371
3372   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
3373   while ( i < nbElements && anIt->more() ) {
3374     const SMDS_MeshElement* anElem = anIt->next();
3375     if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
3376       aResult[i++] = anElem->GetID();
3377   }
3378
3379   aResult->length( i );
3380
3381   return aResult._retn();
3382 }
3383
3384 //=============================================================================
3385 /*!
3386  * Returns ids of all nodes
3387  */
3388 //=============================================================================
3389
3390 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
3391   throw (SALOME::SALOME_Exception)
3392 {
3393   Unexpect aCatch(SALOME_SalomeException);
3394   if ( _preMeshInfo )
3395     _preMeshInfo->FullLoadFromFile();
3396
3397   SMESH::long_array_var aResult = new SMESH::long_array();
3398   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3399
3400   if ( aSMESHDS_Mesh == NULL )
3401     return aResult._retn();
3402
3403   long nbNodes = NbNodes();
3404   aResult->length( nbNodes );
3405   SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator(/*idInceasingOrder=*/true);
3406   for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
3407     aResult[i] = anIt->next()->GetID();
3408
3409   return aResult._retn();
3410 }
3411
3412 //=============================================================================
3413 /*!
3414  *
3415  */
3416 //=============================================================================
3417
3418 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
3419   throw (SALOME::SALOME_Exception)
3420 {
3421   if ( _preMeshInfo )
3422     _preMeshInfo->FullLoadFromFile();
3423
3424   return ( SMESH::ElementType )_impl->GetElementType( id, iselem );
3425 }
3426
3427 //=============================================================================
3428 /*!
3429  *
3430  */
3431 //=============================================================================
3432
3433 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id )
3434   throw (SALOME::SALOME_Exception)
3435 {
3436   if ( _preMeshInfo )
3437     _preMeshInfo->FullLoadFromFile();
3438
3439   const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
3440   if ( !e )
3441     THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
3442
3443   return ( SMESH::EntityType ) e->GetEntityType();
3444 }
3445
3446 //=============================================================================
3447 /*!
3448  * Returns ID of elements for given submesh
3449  */
3450 //=============================================================================
3451 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
3452      throw (SALOME::SALOME_Exception)
3453 {
3454   if ( _preMeshInfo )
3455     _preMeshInfo->FullLoadFromFile();
3456
3457   SMESH::long_array_var aResult = new SMESH::long_array();
3458
3459   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
3460   if(!SM) return aResult._retn();
3461
3462   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
3463   if(!SDSM) return aResult._retn();
3464
3465   aResult->length(SDSM->NbElements());
3466
3467   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
3468   int i = 0;
3469   while ( eIt->more() ) {
3470     aResult[i++] = eIt->next()->GetID();
3471   }
3472
3473   return aResult._retn();
3474 }
3475
3476
3477 //=============================================================================
3478 /*!
3479  * Returns ID of nodes for given submesh
3480  * If param all==true - returns all nodes, else -
3481  * returns only nodes on shapes.
3482  */
3483 //=============================================================================
3484 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
3485                                                    CORBA::Boolean    all)
3486   throw (SALOME::SALOME_Exception)
3487 {
3488   if ( _preMeshInfo )
3489     _preMeshInfo->FullLoadFromFile();
3490
3491   SMESH::long_array_var aResult = new SMESH::long_array();
3492
3493   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
3494   if(!SM) return aResult._retn();
3495
3496   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
3497   if(!SDSM) return aResult._retn();
3498
3499   set<int> theElems;
3500   if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
3501     SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
3502     while ( nIt->more() ) {
3503       const SMDS_MeshNode* elem = nIt->next();
3504       theElems.insert( elem->GetID() );
3505     }
3506   }
3507   else { // all nodes of submesh elements
3508     SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
3509     while ( eIt->more() ) {
3510       const SMDS_MeshElement* anElem = eIt->next();
3511       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
3512       while ( nIt->more() ) {
3513         const SMDS_MeshElement* elem = nIt->next();
3514         theElems.insert( elem->GetID() );
3515       }
3516     }
3517   }
3518
3519   aResult->length(theElems.size());
3520   set<int>::iterator itElem;
3521   int i = 0;
3522   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
3523     aResult[i++] = *itElem;
3524
3525   return aResult._retn();
3526 }
3527   
3528 //=============================================================================
3529 /*!
3530  * Returns type of elements for given submesh
3531  */
3532 //=============================================================================
3533
3534 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
3535   throw (SALOME::SALOME_Exception)
3536 {
3537   if ( _preMeshInfo )
3538     _preMeshInfo->FullLoadFromFile();
3539
3540   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
3541   if(!SM) return SMESH::ALL;
3542
3543   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
3544   if(!SDSM) return SMESH::ALL;
3545
3546   if(SDSM->NbElements()==0)
3547     return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
3548
3549   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
3550   const SMDS_MeshElement* anElem = eIt->next();
3551   return ( SMESH::ElementType ) anElem->GetType();
3552 }
3553   
3554
3555 //=============================================================================
3556 /*!
3557  * Returns pointer to _impl as an integer value. Is called from constructor of SMESH_Client
3558  */
3559 //=============================================================================
3560
3561 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
3562 {
3563   if ( _preMeshInfo )
3564     _preMeshInfo->FullLoadFromFile();
3565
3566   CORBA::LongLong pointeur = CORBA::LongLong(_impl);
3567   if ( MYDEBUG )
3568     MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
3569   return pointeur;
3570 }
3571
3572
3573 //=============================================================================
3574 /*!
3575  * Get XYZ coordinates of node as list of double
3576  * If there is not node for given ID - returns empty list
3577  */
3578 //=============================================================================
3579
3580 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
3581 {
3582   if ( _preMeshInfo )
3583     _preMeshInfo->FullLoadFromFile();
3584
3585   SMESH::double_array_var aResult = new SMESH::double_array();
3586   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3587   if ( aSMESHDS_Mesh == NULL )
3588     return aResult._retn();
3589
3590   // find node
3591   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3592   if(!aNode)
3593     return aResult._retn();
3594
3595   // add coordinates
3596   aResult->length(3);
3597   aResult[0] = aNode->X();
3598   aResult[1] = aNode->Y();
3599   aResult[2] = aNode->Z();
3600   return aResult._retn();
3601 }
3602
3603
3604 //=============================================================================
3605 /*!
3606  * For given node returns list of IDs of inverse elements
3607  * If there is not node for given ID - returns empty list
3608  */
3609 //=============================================================================
3610
3611 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
3612 {
3613   if ( _preMeshInfo )
3614     _preMeshInfo->FullLoadFromFile();
3615
3616   SMESH::long_array_var aResult = new SMESH::long_array();
3617   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3618   if ( aSMESHDS_Mesh == NULL )
3619     return aResult._retn();
3620
3621   // find node
3622   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3623   if(!aNode)
3624     return aResult._retn();
3625
3626   // find inverse elements
3627   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
3628   TColStd_SequenceOfInteger IDs;
3629   while(eIt->more()) {
3630     const SMDS_MeshElement* elem = eIt->next();
3631     IDs.Append(elem->GetID());
3632   }
3633   if(IDs.Length()>0) {
3634     aResult->length(IDs.Length());
3635     int i = 1;
3636     for(; i<=IDs.Length(); i++) {
3637       aResult[i-1] = IDs.Value(i);
3638     }
3639   }
3640   return aResult._retn();
3641 }
3642
3643 //=============================================================================
3644 /*!
3645  * \brief Return position of a node on shape
3646  */
3647 //=============================================================================
3648
3649 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
3650 {
3651   if ( _preMeshInfo )
3652     _preMeshInfo->FullLoadFromFile();
3653
3654   SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
3655   aNodePosition->shapeID = 0;
3656   aNodePosition->shapeType = GEOM::SHAPE;
3657
3658   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
3659   if ( !mesh ) return aNodePosition;
3660
3661   if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
3662   {
3663     if ( SMDS_PositionPtr pos = aNode->GetPosition() )
3664     {
3665       aNodePosition->shapeID = aNode->getshapeId();
3666       switch ( pos->GetTypeOfPosition() ) {
3667       case SMDS_TOP_EDGE:
3668         aNodePosition->shapeType = GEOM::EDGE;
3669         aNodePosition->params.length(1);
3670         aNodePosition->params[0] =
3671           static_cast<SMDS_EdgePosition*>( pos )->GetUParameter();
3672         break;
3673       case SMDS_TOP_FACE:
3674         aNodePosition->shapeType = GEOM::FACE;
3675         aNodePosition->params.length(2);
3676         aNodePosition->params[0] =
3677           static_cast<SMDS_FacePosition*>( pos )->GetUParameter();
3678         aNodePosition->params[1] =
3679           static_cast<SMDS_FacePosition*>( pos )->GetVParameter();
3680         break;
3681       case SMDS_TOP_VERTEX:
3682         aNodePosition->shapeType = GEOM::VERTEX;
3683         break;
3684       case SMDS_TOP_3DSPACE:
3685         if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
3686           aNodePosition->shapeType = GEOM::SOLID;
3687         else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
3688           aNodePosition->shapeType = GEOM::SHELL;
3689         break;
3690       default:;
3691       }
3692     }
3693   }
3694   return aNodePosition;
3695 }
3696
3697 //=============================================================================
3698 /*!
3699  * If given element is node returns IDs of shape from position
3700  * If there is not node for given ID - returns -1
3701  */
3702 //=============================================================================
3703
3704 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
3705 {
3706   if ( _preMeshInfo )
3707     _preMeshInfo->FullLoadFromFile();
3708
3709   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3710   if ( aSMESHDS_Mesh == NULL )
3711     return -1;
3712
3713   // try to find node
3714   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3715   if(aNode) {
3716     return aNode->getshapeId();
3717   }
3718
3719   return -1;
3720 }
3721
3722
3723 //=============================================================================
3724 /*!
3725  * For given element returns ID of result shape after 
3726  * ::FindShape() from SMESH_MeshEditor
3727  * If there is not element for given ID - returns -1
3728  */
3729 //=============================================================================
3730
3731 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
3732 {
3733   if ( _preMeshInfo )
3734     _preMeshInfo->FullLoadFromFile();
3735
3736   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3737   if ( aSMESHDS_Mesh == NULL )
3738     return -1;
3739
3740   // try to find element
3741   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3742   if(!elem)
3743     return -1;
3744
3745   //SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
3746   ::SMESH_MeshEditor aMeshEditor(_impl);
3747   int index = aMeshEditor.FindShape( elem );
3748   if(index>0)
3749     return index;
3750
3751   return -1;
3752 }
3753
3754
3755 //=============================================================================
3756 /*!
3757  * Returns number of nodes for given element
3758  * If there is not element for given ID - returns -1
3759  */
3760 //=============================================================================
3761
3762 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
3763 {
3764   if ( _preMeshInfo )
3765     _preMeshInfo->FullLoadFromFile();
3766
3767   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3768   if ( aSMESHDS_Mesh == NULL ) return -1;
3769   // try to find element
3770   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3771   if(!elem) return -1;
3772   return elem->NbNodes();
3773 }
3774
3775
3776 //=============================================================================
3777 /*!
3778  * Returns ID of node by given index for given element
3779  * If there is not element for given ID - returns -1
3780  * If there is not node for given index - returns -2
3781  */
3782 //=============================================================================
3783
3784 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
3785 {
3786   if ( _preMeshInfo )
3787     _preMeshInfo->FullLoadFromFile();
3788
3789   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3790   if ( aSMESHDS_Mesh == NULL ) return -1;
3791   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3792   if(!elem) return -1;
3793   if( index>=elem->NbNodes() || index<0 ) return -1;
3794   return elem->GetNode(index)->GetID();
3795 }
3796
3797 //=============================================================================
3798 /*!
3799  * Returns IDs of nodes of given element
3800  */
3801 //=============================================================================
3802
3803 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
3804 {
3805   if ( _preMeshInfo )
3806     _preMeshInfo->FullLoadFromFile();
3807
3808   SMESH::long_array_var aResult = new SMESH::long_array();
3809   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
3810   {
3811     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id) )
3812     {
3813       aResult->length( elem->NbNodes() );
3814       for ( int i = 0; i < elem->NbNodes(); ++i )
3815         aResult[ i ] = elem->GetNode( i )->GetID();
3816     }
3817   }
3818   return aResult._retn();
3819 }
3820
3821 //=============================================================================
3822 /*!
3823  * Returns true if given node is medium node
3824  * in given quadratic element
3825  */
3826 //=============================================================================
3827
3828 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
3829 {
3830   if ( _preMeshInfo )
3831     _preMeshInfo->FullLoadFromFile();
3832
3833   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3834   if ( aSMESHDS_Mesh == NULL ) return false;
3835   // try to find node
3836   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
3837   if(!aNode) return false;
3838   // try to find element
3839   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(ide);
3840   if(!elem) return false;
3841
3842   return elem->IsMediumNode(aNode);
3843 }
3844
3845
3846 //=============================================================================
3847 /*!
3848  * Returns true if given node is medium node
3849  * in one of quadratic elements
3850  */
3851 //=============================================================================
3852
3853 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
3854                                                    SMESH::ElementType theElemType)
3855 {
3856   if ( _preMeshInfo )
3857     _preMeshInfo->FullLoadFromFile();
3858
3859   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3860   if ( aSMESHDS_Mesh == NULL ) return false;
3861
3862   // try to find node
3863   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
3864   if(!aNode) return false;
3865
3866   SMESH_MesherHelper aHelper( *(_impl) );
3867
3868   SMDSAbs_ElementType aType;
3869   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
3870   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
3871   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
3872   else aType = SMDSAbs_All;
3873
3874   return aHelper.IsMedium(aNode,aType);
3875 }
3876
3877
3878 //=============================================================================
3879 /*!
3880  * Returns number of edges for given element
3881  */
3882 //=============================================================================
3883
3884 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
3885 {
3886   if ( _preMeshInfo )
3887     _preMeshInfo->FullLoadFromFile();
3888
3889   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3890   if ( aSMESHDS_Mesh == NULL ) return -1;
3891   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3892   if(!elem) return -1;
3893   return elem->NbEdges();
3894 }
3895
3896
3897 //=============================================================================
3898 /*!
3899  * Returns number of faces for given element
3900  */
3901 //=============================================================================
3902
3903 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
3904 {
3905   if ( _preMeshInfo )
3906     _preMeshInfo->FullLoadFromFile();
3907
3908   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3909   if ( aSMESHDS_Mesh == NULL ) return -1;
3910   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3911   if(!elem) return -1;
3912   return elem->NbFaces();
3913 }
3914
3915 //=======================================================================
3916 //function : GetElemFaceNodes
3917 //purpose  : Returns nodes of given face (counted from zero) for given element.
3918 //=======================================================================
3919
3920 SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long  elemId,
3921                                                   CORBA::Short faceIndex)
3922 {
3923   if ( _preMeshInfo )
3924     _preMeshInfo->FullLoadFromFile();
3925
3926   SMESH::long_array_var aResult = new SMESH::long_array();
3927   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
3928   {
3929     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(elemId) )
3930     {
3931       SMDS_VolumeTool vtool( elem );
3932       if ( faceIndex < vtool.NbFaces() )
3933       {
3934         aResult->length( vtool.NbFaceNodes( faceIndex ));
3935         const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
3936         for ( int i = 0; i < aResult->length(); ++i )
3937           aResult[ i ] = nn[ i ]->GetID();
3938       }
3939     }
3940   }
3941   return aResult._retn();
3942 }
3943
3944 //=======================================================================
3945 //function : FindElementByNodes
3946 //purpose  : Returns an element based on all given nodes.
3947 //=======================================================================
3948
3949 CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
3950 {
3951   if ( _preMeshInfo )
3952     _preMeshInfo->FullLoadFromFile();
3953
3954   CORBA::Long elemID(0);
3955   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
3956   {
3957     vector< const SMDS_MeshNode * > nn( nodes.length() );
3958     for ( int i = 0; i < nodes.length(); ++i )
3959       if ( !( nn[i] = mesh->FindNode( nodes[i] )))
3960         return elemID;
3961
3962     const SMDS_MeshElement* elem = mesh->FindElement( nn );
3963     if ( !elem && ( _impl->NbEdges  ( ORDER_QUADRATIC ) ||
3964                     _impl->NbFaces  ( ORDER_QUADRATIC ) ||
3965                     _impl->NbVolumes( ORDER_QUADRATIC )))
3966       elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
3967
3968     if ( elem ) elemID = CORBA::Long( elem->GetID() );
3969   }
3970   return elemID;
3971 }
3972
3973 //=============================================================================
3974 /*!
3975  * Returns true if given element is polygon
3976  */
3977 //=============================================================================
3978
3979 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
3980 {
3981   if ( _preMeshInfo )
3982     _preMeshInfo->FullLoadFromFile();
3983
3984   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3985   if ( aSMESHDS_Mesh == NULL ) return false;
3986   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3987   if(!elem) return false;
3988   return elem->IsPoly();
3989 }
3990
3991
3992 //=============================================================================
3993 /*!
3994  * Returns true if given element is quadratic
3995  */
3996 //=============================================================================
3997
3998 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
3999 {
4000   if ( _preMeshInfo )
4001     _preMeshInfo->FullLoadFromFile();
4002
4003   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4004   if ( aSMESHDS_Mesh == NULL ) return false;
4005   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4006   if(!elem) return false;
4007   return elem->IsQuadratic();
4008 }
4009
4010 //=============================================================================
4011 /*!
4012  * Returns diameter of ball discrete element or zero in case of an invalid \a id
4013  */
4014 //=============================================================================
4015
4016 CORBA::Double SMESH_Mesh_i::GetBallDiameter(CORBA::Long id)
4017 {
4018   if ( _preMeshInfo )
4019     _preMeshInfo->FullLoadFromFile();
4020
4021   if ( const SMDS_BallElement* ball =
4022        dynamic_cast<const SMDS_BallElement*>( _impl->GetMeshDS()->FindElement( id )))
4023     return ball->GetDiameter();
4024
4025   return 0;
4026 }
4027
4028 //=============================================================================
4029 /*!
4030  * Returns bary center for given element
4031  */
4032 //=============================================================================
4033
4034 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
4035 {
4036   if ( _preMeshInfo )
4037     _preMeshInfo->FullLoadFromFile();
4038
4039   SMESH::double_array_var aResult = new SMESH::double_array();
4040   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4041   if ( aSMESHDS_Mesh == NULL )
4042     return aResult._retn();
4043
4044   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
4045   if(!elem)
4046     return aResult._retn();
4047
4048   if(elem->GetType()==SMDSAbs_Volume) {
4049     SMDS_VolumeTool aTool;
4050     if(aTool.Set(elem)) {
4051       aResult->length(3);
4052       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
4053         aResult->length(0);
4054     }
4055   }
4056   else {
4057     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
4058     int nbn = 0;
4059     double x=0., y=0., z=0.;
4060     for(; anIt->more(); ) {
4061       nbn++;
4062       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
4063       x += aNode->X();
4064       y += aNode->Y();
4065       z += aNode->Z();
4066     }
4067     if(nbn>0) {
4068       // add coordinates
4069       aResult->length(3);
4070       aResult[0] = x/nbn;
4071       aResult[1] = y/nbn;
4072       aResult[2] = z/nbn;
4073     }
4074   }
4075
4076   return aResult._retn();
4077 }
4078
4079
4080 //=============================================================================
4081 /*!
4082  * Create and publish group servants if any groups were imported or created anyhow
4083  */
4084 //=============================================================================
4085
4086 void SMESH_Mesh_i::CreateGroupServants() 
4087 {
4088   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
4089
4090   set<int> addedIDs;
4091   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
4092   while ( groupIt->more() )
4093   {
4094     ::SMESH_Group* group = groupIt->next();
4095     int            anId = group->GetGroupDS()->GetID();
4096
4097     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
4098     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
4099       continue;
4100     addedIDs.insert( anId );
4101
4102     SMESH_GroupBase_i* aGroupImpl;
4103     TopoDS_Shape       shape;
4104     if ( SMESHDS_GroupOnGeom* groupOnGeom =
4105          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
4106     {
4107       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
4108       shape      = groupOnGeom->GetShape();
4109     }
4110     else {
4111       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
4112     }
4113
4114     // To ensure correct mapping of servant and correct reference counting in GenericObj_i
4115     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
4116     aGroupImpl->Register();
4117
4118     SMESH::SMESH_GroupBase_var groupVar =
4119       SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
4120     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
4121
4122     // register CORBA object for persistence
4123     int nextId = _gen_i->RegisterObject( groupVar );
4124     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
4125
4126     // publishing the groups in the study
4127     if ( !aStudy->_is_nil() ) {
4128       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
4129       _gen_i->PublishGroup( aStudy, _this(), groupVar, shapeVar, groupVar->GetName());
4130     }
4131   }
4132   if ( !addedIDs.empty() )
4133   {
4134     // python dump
4135     set<int>::iterator id = addedIDs.begin();
4136     for ( ; id != addedIDs.end(); ++id )
4137     {
4138       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(*id);
4139       int i = std::distance( _mapGroups.begin(), it );
4140       TPythonDump() << it->second << " = " << _this() << ".GetGroups()[ "<< i << " ]";
4141     }
4142   }
4143 }
4144
4145 //=============================================================================
4146 /*!
4147  * \brief Return groups cantained in _mapGroups by their IDs
4148  */
4149 //=============================================================================
4150
4151 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
4152 {
4153   int nbGroups = groupIDs.size();
4154   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
4155   aList->length( nbGroups );
4156
4157   list<int>::const_iterator ids = groupIDs.begin();
4158   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
4159   {
4160     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
4161     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
4162       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
4163   }
4164   aList->length( nbGroups );
4165   return aList._retn();
4166 }
4167
4168 //=============================================================================
4169 /*!
4170  * \brief Return information about imported file
4171  */
4172 //=============================================================================
4173
4174 SALOME_MED::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
4175 {
4176   SALOME_MED::MedFileInfo_var res( _medFileInfo );
4177   if ( !res.operator->() ) {
4178     res = new SALOME_MED::MedFileInfo;
4179     res->fileName = "";
4180     res->fileSize = res->major = res->minor = res->release = -1;
4181   }
4182   return res._retn();
4183 }
4184
4185 //=============================================================================
4186 /*!
4187  * \brief Pass names of mesh groups from study to mesh DS
4188  */
4189 //=============================================================================
4190
4191 void SMESH_Mesh_i::checkGroupNames()
4192 {
4193   int nbGrp = NbGroups();
4194   if ( !nbGrp )
4195     return;
4196
4197   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
4198   if ( aStudy->_is_nil() )
4199     return; // nothing to do
4200   
4201   SMESH::ListOfGroups* grpList = 0;
4202   // avoid dump of "GetGroups"
4203   {
4204     // store python dump into a local variable inside local scope
4205     SMESH::TPythonDump pDump; // do not delete this line of code
4206     grpList = GetGroups();
4207   }
4208
4209   for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
4210     SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
4211     if ( !aGrp )
4212       continue;
4213     SALOMEDS::SObject_var aGrpSO = _gen_i->ObjectToSObject( aStudy, aGrp );
4214     if ( aGrpSO->_is_nil() )
4215       continue;
4216     // correct name of the mesh group if necessary
4217     const char* guiName = aGrpSO->GetName();
4218     if ( strcmp(guiName, aGrp->GetName()) )
4219       aGrp->SetName( guiName );
4220   }
4221 }
4222
4223 //=============================================================================
4224 /*!
4225  * \brief Sets list of notebook variables used for Mesh operations separated by ":" symbol
4226  */
4227 //=============================================================================
4228 void SMESH_Mesh_i::SetParameters(const char* theParameters)
4229 {
4230   // SMESH_Gen_i::GetSMESHGen()->UpdateParameters(SMESH::SMESH_Mesh::_narrow(_this()),
4231   //                                              CORBA::string_dup(theParameters));
4232   SMESH_Gen_i::GetSMESHGen()->UpdateParameters(theParameters);
4233 }
4234
4235 //=============================================================================
4236 /*!
4237  * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
4238  */
4239 //=============================================================================
4240 char* SMESH_Mesh_i::GetParameters()
4241 {
4242   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
4243   return CORBA::string_dup(gen->GetParameters(SMESH::SMESH_Mesh::_narrow(_this())));
4244 }
4245
4246 //=============================================================================
4247 /*!
4248  * \brief Returns list of notebook variables used for last Mesh operation
4249  */
4250 //=============================================================================
4251 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
4252 {
4253   SMESH::string_array_var aResult = new SMESH::string_array();
4254   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
4255   if(gen) {
4256     char *aParameters = GetParameters();
4257     SALOMEDS::Study_ptr aStudy = gen->GetCurrentStudy();
4258     if(!aStudy->_is_nil()) {
4259       SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters); 
4260       if(aSections->length() > 0) {
4261         SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1];
4262         aResult->length(aVars.length());
4263         for(int i = 0;i < aVars.length();i++)
4264           aResult[i] = CORBA::string_dup( aVars[i]);
4265       }
4266     }
4267   }
4268   return aResult._retn();
4269 }
4270
4271 //=======================================================================
4272 //function : GetTypes
4273 //purpose  : Returns types of elements it contains
4274 //=======================================================================
4275
4276 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
4277 {
4278   if ( _preMeshInfo )
4279     return _preMeshInfo->GetTypes();
4280
4281   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
4282
4283   types->length( 5 );
4284   int nbTypes = 0;
4285   if (_impl->NbEdges())      types[nbTypes++] = SMESH::EDGE;
4286   if (_impl->NbFaces())      types[nbTypes++] = SMESH::FACE;
4287   if (_impl->NbVolumes())    types[nbTypes++] = SMESH::VOLUME;
4288   if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
4289   if (_impl->NbBalls())      types[nbTypes++] = SMESH::BALL;
4290   types->length( nbTypes );
4291
4292   return types._retn();
4293 }
4294
4295 //=======================================================================
4296 //function : GetMesh
4297 //purpose  : Returns self
4298 //=======================================================================
4299
4300 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
4301 {
4302   return SMESH::SMESH_Mesh::_duplicate( _this() );
4303 }
4304
4305 //=======================================================================
4306 //function : IsMeshInfoCorrect
4307 //purpose  : * Returns false if GetMeshInfo() returns incorrect information that may
4308 //           * happen if mesh data is not yet fully loaded from the file of study.
4309 //=======================================================================
4310
4311 bool SMESH_Mesh_i::IsMeshInfoCorrect()
4312 {
4313   return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
4314 }
4315
4316 //=============================================================================
4317 /*!
4318  * \brief Returns statistic of mesh elements
4319  */
4320 //=============================================================================
4321
4322 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
4323 {
4324   if ( _preMeshInfo )
4325     return _preMeshInfo->GetMeshInfo();
4326
4327   SMESH::long_array_var aRes = new SMESH::long_array();
4328   aRes->length(SMESH::Entity_Last);
4329   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
4330     aRes[i] = 0;
4331   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4332   if (!aMeshDS)
4333     return aRes._retn();
4334   const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
4335   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
4336     aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
4337   return aRes._retn();
4338 }
4339
4340 //=============================================================================
4341 /*!
4342  * \brief Collect statistic of mesh elements given by iterator
4343  */
4344 //=============================================================================
4345
4346 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
4347                                    SMESH::long_array&         theInfo)
4348 {
4349   if (!theItr) return;
4350   while (theItr->more())
4351     theInfo[ theItr->next()->GetEntityType() ]++;
4352 }
4353
4354 //=============================================================================
4355 /*!
4356  * \brief mapping of mesh dimension into shape type
4357  */
4358 //=============================================================================
4359
4360 static TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
4361 {
4362   TopAbs_ShapeEnum aType = TopAbs_SOLID;
4363   switch ( theDim ) {
4364   case 0: aType = TopAbs_VERTEX; break;
4365   case 1: aType = TopAbs_EDGE; break;
4366   case 2: aType = TopAbs_FACE; break;
4367   case 3:
4368   default:aType = TopAbs_SOLID; break;
4369   }
4370   return aType;
4371 }
4372
4373 //=============================================================================
4374 /*!
4375  * \brief Internal structure used to find concurent submeshes
4376  *
4377  * It represents a pair < submesh, concurent dimension >, where
4378  * 'concurrent dimension' is dimension of shape where the submesh can concurent
4379  *  with another submesh. In other words, it is dimension of a hypothesis assigned
4380  *  to submesh.
4381  */
4382 //=============================================================================
4383
4384 class SMESH_DimHyp
4385 {
4386  public:
4387   //! fileds
4388   int _dim;    //!< a dimension the algo can build (concurrent dimension)
4389   int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
4390   TopTools_MapOfShape _shapeMap;
4391   SMESH_subMesh*      _subMesh;
4392   list<const SMESHDS_Hypothesis*> _hypothesises; //!< algo is first, then its parameters
4393
4394   //! Constructors
4395   SMESH_DimHyp(const SMESH_subMesh*  theSubMesh,
4396                const int             theDim,
4397                const TopoDS_Shape&   theShape)
4398   {
4399     _subMesh = (SMESH_subMesh*)theSubMesh;
4400     SetShape( theDim, theShape );
4401   }
4402
4403   //! set shape
4404   void SetShape(const int           theDim,
4405                 const TopoDS_Shape& theShape)
4406   {
4407     _dim = theDim;
4408     _ownDim = (int)SMESH_Gen::GetShapeDim(theShape);
4409     if (_dim >= _ownDim)
4410       _shapeMap.Add( theShape );
4411     else {
4412       TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
4413       for( ; anExp.More(); anExp.Next() )
4414         _shapeMap.Add( anExp.Current() );
4415     }
4416   }
4417
4418   //! Check sharing of sub-shapes
4419   static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
4420                                const TopTools_MapOfShape& theToFind,
4421                                const TopAbs_ShapeEnum     theType)
4422   {
4423     bool isShared = false;
4424     TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
4425     for (; !isShared && anItr.More(); anItr.Next() )
4426     {
4427       const TopoDS_Shape aSubSh = anItr.Key();
4428       // check for case when concurrent dimensions are same
4429       isShared = theToFind.Contains( aSubSh );
4430       // check for sub-shape with concurrent dimension
4431       TopExp_Explorer anExp( aSubSh, theType );
4432       for ( ; !isShared && anExp.More(); anExp.Next() )
4433         isShared = theToFind.Contains( anExp.Current() );
4434     }
4435     return isShared;
4436   }
4437   
4438   //! check algorithms
4439   static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
4440                         const SMESHDS_Hypothesis* theA2)
4441   {
4442     if ( theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
4443          theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
4444       return false; // one of the hypothesis is not algorithm
4445     // check algorithm names (should be equal)
4446     return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
4447   }
4448
4449   
4450   //! Check if sub-shape hypotheses are concurrent
4451   bool IsConcurrent(const SMESH_DimHyp* theOther) const
4452   {
4453     if ( _subMesh == theOther->_subMesh )
4454       return false; // same sub-shape - should not be
4455
4456     // if ( <own dim of either of submeshes> == <concurrent dim> &&
4457     //      any of the two submeshes is not on COMPOUND shape )
4458     //  -> no concurrency
4459     bool meIsCompound = (_subMesh->GetSubMeshDS() && _subMesh->GetSubMeshDS()->IsComplexSubmesh());
4460     bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() && theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
4461     if ( (_ownDim == _dim  || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
4462       return false;
4463
4464 //     bool checkSubShape = ( _dim >= theOther->_dim )
4465 //       ? isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(theOther->_dim) )
4466 //       : isShareSubShapes( theOther->_shapeMap, _shapeMap, shapeTypeByDim(_dim) ) ;
4467     bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
4468     if ( !checkSubShape )
4469         return false;
4470
4471     // check algorithms to be same
4472     if (!checkAlgo( _hypothesises.front(), theOther->_hypothesises.front() ))
4473       return true; // different algorithms
4474     
4475     // check hypothesises for concurrence (skip first as algorithm)
4476     int nbSame = 0;
4477     // pointers should be same, becase it is referenes from mesh hypothesis partition
4478     list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypothesises.begin();
4479     list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypothesises.end();
4480     for ( hypIt++ /*skip first as algo*/; hypIt != _hypothesises.end(); hypIt++ )
4481       if ( find( theOther->_hypothesises.begin(), otheEndIt, *hypIt ) != otheEndIt )
4482         nbSame++;
4483     // the submeshes are concurrent if their algorithms has different parameters
4484     return nbSame != theOther->_hypothesises.size() - 1;
4485   }
4486   
4487 }; // end of SMESH_DimHyp
4488
4489 typedef list<SMESH_DimHyp*> TDimHypList;
4490
4491 static void addDimHypInstance(const int               theDim, 
4492                               const TopoDS_Shape&     theShape,
4493                               const SMESH_Algo*       theAlgo,
4494                               const SMESH_subMesh*    theSubMesh,
4495                               const list <const SMESHDS_Hypothesis*>& theHypList,
4496                               TDimHypList*            theDimHypListArr )
4497 {
4498   TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
4499   if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) {
4500     SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
4501     listOfdimHyp.push_back( dimHyp );
4502   }
4503   
4504   SMESH_DimHyp* dimHyp = listOfdimHyp.back();
4505   dimHyp->_hypothesises.push_front(theAlgo);
4506   list <const SMESHDS_Hypothesis*>::const_iterator hypIt = theHypList.begin();
4507   for( ; hypIt != theHypList.end(); hypIt++ )
4508     dimHyp->_hypothesises.push_back( *hypIt );
4509 }
4510
4511 static void findConcurrents(const SMESH_DimHyp* theDimHyp,
4512                             const TDimHypList&  theListOfDimHyp,
4513                             TListOfInt&         theListOfConcurr )
4514 {
4515   TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
4516   for ( ; rIt != theListOfDimHyp.rend(); rIt++ ) {
4517     const SMESH_DimHyp* curDimHyp = *rIt;
4518     if ( curDimHyp == theDimHyp )
4519       break; // meet own dimHyp pointer in same dimension
4520     else if ( theDimHyp->IsConcurrent( curDimHyp ) )
4521       if ( find( theListOfConcurr.begin(),
4522                  theListOfConcurr.end(),
4523                  curDimHyp->_subMesh->GetId() ) == theListOfConcurr.end() )
4524         theListOfConcurr.push_back( curDimHyp->_subMesh->GetId() );
4525   }
4526 }
4527
4528 static void unionLists(TListOfInt&       theListOfId,
4529                        TListOfListOfInt& theListOfListOfId,
4530                        const int         theIndx )
4531 {
4532   TListOfListOfInt::iterator it = theListOfListOfId.begin();
4533   for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) {
4534     if ( i < theIndx )
4535       continue; //skip already treated lists
4536     // check if other list has any same submesh object
4537     TListOfInt& otherListOfId = *it;
4538     if ( find_first_of( theListOfId.begin(), theListOfId.end(),
4539                         otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
4540       continue;
4541          
4542     // union two lists (from source into target)
4543     TListOfInt::iterator it2 = otherListOfId.begin();
4544     for ( ; it2 != otherListOfId.end(); it2++ ) {
4545       if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
4546         theListOfId.push_back(*it2);
4547     }
4548     // clear source list
4549     otherListOfId.clear();
4550   }
4551 }
4552
4553 //! free memory allocated for dimension-hypothesis objects
4554 static void removeDimHyps( TDimHypList* theArrOfList )
4555 {
4556   for (int i = 0; i < 4; i++ ) {
4557     TDimHypList& listOfdimHyp = theArrOfList[i];
4558     TDimHypList::const_iterator it = listOfdimHyp.begin();
4559     for ( ; it != listOfdimHyp.end(); it++ )
4560       delete (*it);
4561   }
4562 }
4563
4564 //=============================================================================
4565 /*!
4566  * \brief Return submesh objects list in meshing order
4567  */
4568 //=============================================================================
4569
4570 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
4571 {
4572   SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
4573
4574   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4575   if ( !aMeshDS )
4576     return aResult._retn();
4577   
4578   ::SMESH_Mesh& mesh = GetImpl();
4579   TListOfListOfInt anOrder = mesh.GetMeshOrder(); // is there already defined order?
4580   if ( !anOrder.size() ) {
4581
4582     // collect submeshes detecting concurrent algorithms and hypothesises
4583     TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
4584     
4585     map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
4586     for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) {
4587       ::SMESH_subMesh* sm = (*i_sm).second;
4588       // shape of submesh
4589       const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
4590       
4591       // list of assigned hypothesises
4592       const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
4593       // Find out dimensions where the submesh can be concurrent.
4594       // We define the dimensions by algo of each of hypotheses in hypList
4595       list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
4596       for( ; hypIt != hypList.end(); hypIt++ ) {
4597         SMESH_Algo* anAlgo = 0;
4598         const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
4599         if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
4600           // hyp it-self is algo
4601           anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
4602         else {
4603           // try to find algorithm with help of sub-shapes
4604           TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
4605           for ( ; !anAlgo && anExp.More(); anExp.Next() )
4606             anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
4607         }
4608         if (!anAlgo)
4609           continue; // no assigned algorithm to current submesh
4610
4611         int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
4612         // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary())
4613
4614         // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
4615         for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
4616           addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
4617       }
4618     } // end iterations on submesh
4619     
4620     // iterate on created dimension-hypotheses and check for concurrents
4621     for ( int i = 0; i < 4; i++ ) {
4622       const list<SMESH_DimHyp*>& listOfDimHyp = dimHypListArr[i];
4623       // check for concurrents in own and other dimensions (step-by-step)
4624       TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
4625       for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) {
4626         const SMESH_DimHyp* dimHyp = *dhIt;
4627         TListOfInt listOfConcurr;
4628         // looking for concurrents and collect into own list
4629         for ( int j = i; j < 4; j++ )
4630           findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr );
4631         // check if any concurrents found
4632         if ( listOfConcurr.size() > 0 ) {
4633           // add own submesh to list of concurrent
4634           listOfConcurr.push_front( dimHyp->_subMesh->GetId() );
4635           anOrder.push_back( listOfConcurr );
4636         }
4637       }
4638     }
4639     
4640     removeDimHyps(dimHypListArr);
4641     
4642     // now, minimise the number of concurrent groups
4643     // Here we assume that lists of submeshes can have same submesh
4644     // in case of multi-dimension algorithms, as result
4645     //  list with common submesh has to be united into one list
4646     int listIndx = 0;
4647     TListOfListOfInt::iterator listIt = anOrder.begin();
4648     for(; listIt != anOrder.end(); listIt++, listIndx++ )
4649       unionLists( *listIt,  anOrder, listIndx + 1 );
4650   }
4651   // convert submesh ids into interface instances
4652   //  and dump command into python
4653   convertMeshOrder( anOrder, aResult, false );
4654
4655   return aResult._retn();
4656 }
4657
4658 //=============================================================================
4659 /*!
4660  * \brief find common submeshes with given submesh
4661  * \param theSubMeshList list of already collected submesh to check
4662  * \param theSubMesh given submesh to intersect with other
4663  * \param theCommonSubMeshes collected common submeshes
4664  */
4665 //=============================================================================
4666
4667 static void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
4668                                const SMESH_subMesh*        theSubMesh,
4669                                set<const SMESH_subMesh*>&  theCommon )
4670 {
4671   if ( !theSubMesh )
4672     return;
4673   list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
4674   for ( ; it != theSubMeshList.end(); it++ )
4675     theSubMesh->FindIntersection( *it, theCommon );
4676   theSubMeshList.push_back( theSubMesh );
4677   //theCommon.insert( theSubMesh );
4678 }
4679
4680 //=============================================================================
4681 /*!
4682  * \brief Set submesh object order
4683  * \param theSubMeshArray submesh array order
4684  */
4685 //=============================================================================
4686
4687 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
4688 {
4689   if ( _preMeshInfo )
4690     _preMeshInfo->ForgetOrLoad();
4691
4692   bool res = false;
4693   ::SMESH_Mesh& mesh = GetImpl();
4694
4695   TPythonDump aPythonDump; // prevent dump of called methods
4696   aPythonDump << "isDone = " << _this() << ".SetMeshOrder( [ ";
4697
4698   TListOfListOfInt subMeshOrder;
4699   for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
4700   {
4701     const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
4702     TListOfInt subMeshIds;
4703     aPythonDump << "[ ";
4704     // Collect subMeshes which should be clear
4705     //  do it list-by-list, because modification of submesh order
4706     //  take effect between concurrent submeshes only
4707     set<const SMESH_subMesh*> subMeshToClear;
4708     list<const SMESH_subMesh*> subMeshList;
4709     for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
4710     {
4711       const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
4712       if ( j > 0 )
4713         aPythonDump << ", ";
4714       aPythonDump << subMesh;
4715       subMeshIds.push_back( subMesh->GetId() );
4716       // detect common parts of submeshes
4717       if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
4718         findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
4719     }
4720     aPythonDump << " ]";
4721     subMeshOrder.push_back( subMeshIds );
4722
4723     // clear collected submeshes
4724     set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
4725     for ( ; clrIt != subMeshToClear.end(); clrIt++ )
4726       if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
4727         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
4728   }
4729   aPythonDump << " ])";
4730
4731   mesh.SetMeshOrder( subMeshOrder );
4732   res = true;
4733   
4734   return res;
4735 }
4736
4737 //=============================================================================
4738 /*!
4739  * \brief Convert submesh ids into submesh interfaces
4740  */
4741 //=============================================================================
4742
4743 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt&     theIdsOrder,
4744                                      SMESH::submesh_array_array& theResOrder,
4745                                      const bool                  theIsDump)
4746 {
4747   int nbSet = theIdsOrder.size();
4748   TPythonDump aPythonDump; // prevent dump of called methods
4749   if ( theIsDump )
4750     aPythonDump << "[ ";
4751   theResOrder.length(nbSet);
4752   TListOfListOfInt::const_iterator it = theIdsOrder.begin();
4753   int listIndx = 0;
4754   for( ; it != theIdsOrder.end(); it++ ) {
4755     // translate submesh identificators into submesh objects
4756     //  takeing into account real number of concurrent lists
4757     const TListOfInt& aSubOrder = (*it);
4758     if (!aSubOrder.size())
4759       continue;
4760     if ( theIsDump )
4761       aPythonDump << "[ ";
4762     // convert shape indeces into interfaces
4763     SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
4764     aResSubSet->length(aSubOrder.size());
4765     TListOfInt::const_iterator subIt = aSubOrder.begin();
4766     for( int j = 0; subIt != aSubOrder.end(); subIt++ ) {
4767       if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
4768         continue;
4769       SMESH::SMESH_subMesh_var subMesh =
4770         SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
4771       if ( theIsDump ) {
4772         if ( j > 0 )
4773           aPythonDump << ", ";
4774         aPythonDump << subMesh;
4775       }
4776       aResSubSet[ j++ ] = subMesh;
4777     }
4778     if ( theIsDump )
4779       aPythonDump << " ]";
4780     theResOrder[ listIndx++ ] = aResSubSet;
4781   }
4782   // correct number of lists
4783   theResOrder.length( listIndx );
4784
4785   if ( theIsDump ) {
4786     // finilise python dump
4787     aPythonDump << " ]";
4788     aPythonDump << " = " << _this() << ".GetMeshOrder()";
4789   }
4790 }
4791
4792 //================================================================================
4793 //
4794 // Implementation of SMESH_MeshPartDS
4795 //
4796 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
4797   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
4798 {
4799   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
4800   SMESH_Mesh_i*       mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4801
4802   _meshDS = mesh_i->GetImpl().GetMeshDS();
4803
4804   SetPersistentId( _meshDS->GetPersistentId() );
4805
4806   if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
4807   {
4808     // <meshPart> is the whole mesh
4809     myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
4810     // copy groups
4811     set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
4812     myGroupSet = _meshDS->GetGroups();
4813   }
4814   else
4815   {
4816     TMeshInfo tmpInfo;
4817     SMESH::long_array_var           anIDs = meshPart->GetIDs();
4818     SMESH::array_of_ElementType_var types = meshPart->GetTypes();
4819     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
4820     {
4821       for (int i=0; i < anIDs->length(); i++)
4822         if ( const SMDS_MeshNode * n = _meshDS->FindNode(anIDs[i]))
4823           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
4824             tmpInfo.Add( n );
4825     }
4826     else
4827     {
4828       for (int i=0; i < anIDs->length(); i++)
4829         if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
4830           if ( _elements[ e->GetType() ].insert( e ).second )
4831           {
4832             tmpInfo.Add( e );
4833             SMDS_ElemIteratorPtr nIt = e->nodesIterator();
4834             while ( nIt->more() )
4835             {
4836               const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
4837               if ( _elements[ SMDSAbs_Node ].insert( n ).second )
4838                 tmpInfo.Add( n );
4839             }
4840           }
4841     }
4842     myInfo = tmpInfo;
4843
4844     _meshDS = 0; // to enforce iteration on _elements and _nodes
4845   }
4846 }
4847 // -------------------------------------------------------------------------------------
4848 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
4849 {
4850   if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
4851
4852   typedef SMDS_SetIterator
4853     <const SMDS_MeshElement*,
4854     TIDSortedElemSet::const_iterator,
4855     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
4856     SMDS_MeshElement::GeomFilter
4857     > TIter;
4858
4859   SMDSAbs_ElementType type = SMDS_MeshCell::toSmdsType( geomType );
4860
4861   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
4862                                           _elements[type].end(),
4863                                           SMDS_MeshElement::GeomFilter( geomType )));
4864 }
4865 // -------------------------------------------------------------------------------------
4866 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
4867 {
4868   if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
4869
4870   typedef SMDS_SetIterator
4871     <const SMDS_MeshElement*,
4872     TIDSortedElemSet::const_iterator,
4873     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
4874     SMDS_MeshElement::EntityFilter
4875     > TIter;
4876
4877   SMDSAbs_ElementType type = SMDS_MeshCell::toSmdsType( entity );
4878
4879   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
4880                                           _elements[type].end(),
4881                                           SMDS_MeshElement::EntityFilter( entity )));
4882 }
4883 // -------------------------------------------------------------------------------------
4884 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
4885 {
4886   typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4887   if ( type == SMDSAbs_All && !_meshDS )
4888   {
4889     typedef vector< SMDS_ElemIteratorPtr > TIterVec;
4890     TIterVec iterVec;
4891     for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
4892       if ( !_elements[i].empty() && i != SMDSAbs_Node )
4893         iterVec.push_back
4894           ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
4895
4896     typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
4897     return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
4898   }
4899   return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
4900       ( new TIter( _elements[type].begin(), _elements[type].end() ));
4901 }
4902 // -------------------------------------------------------------------------------------
4903 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType)                       \
4904   iterType SMESH_MeshPartDS::methName( bool idInceasingOrder) const                 \
4905   {                                                                                 \
4906     typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
4907     return _meshDS ? _meshDS->methName(idInceasingOrder) : iterType                 \
4908       ( new TIter( _elements[elemType].begin(), _elements[elemType].end() ));       \
4909   }
4910 // -------------------------------------------------------------------------------------
4911 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
4912 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
4913 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
4914 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
4915 #undef _GET_ITER_DEFINE
4916 //
4917 // END Implementation of SMESH_MeshPartDS
4918 //
4919 //================================================================================