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