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