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