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   const bool isOnFilter = ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ));
1953
1954   int anId = aGroupToRem->GetLocalID();
1955   if ( !_impl->ConvertToStandalone( anId ) )
1956     return aGroup._retn();
1957   removeGeomGroupData( theGroup );
1958
1959   SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
1960
1961   // remove old instance of group from own map
1962   _mapGroups.erase( anId );
1963
1964   SALOMEDS::StudyBuilder_var builder;
1965   SALOMEDS::SObject_var aGroupSO;
1966   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1967   if ( !aStudy->_is_nil() )  {
1968     builder = aStudy->NewBuilder();
1969     aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
1970     if ( !aGroupSO->_is_nil() ) {
1971
1972       // remove reference to geometry
1973       SALOMEDS::ChildIterator_var chItr = aStudy->NewChildIterator(aGroupSO);
1974       for ( ; chItr->More(); chItr->Next() )
1975         // Remove group's child SObject
1976         builder->RemoveObject( chItr->Value() );
1977
1978       // Update Python script
1979       TPythonDump() << aGroupSO << " = " << _this() << ".ConvertToStandalone( "
1980                     << aGroupSO << " )";
1981
1982       // change icon of Group on Filter
1983       if ( isOnFilter )
1984       {
1985         SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
1986         const int isEmpty = ( elemTypes->length() == 0 );
1987         if ( !isEmpty )
1988         {
1989           SALOMEDS::GenericAttribute_var anAttr =
1990             builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
1991           SALOMEDS::AttributePixMap_var pm = SALOMEDS::AttributePixMap::_narrow( anAttr );
1992           pm->SetPixMap( "ICON_SMESH_TREE_GROUP" );
1993         }
1994       }
1995     }
1996   }
1997
1998   // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1999   SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
2000   aGroupImpl->Register();
2001   // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
2002
2003   // remember new group in own map
2004   aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
2005   _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2006
2007   // register CORBA object for persistence
2008   /*int nextId =*/ _gen_i->RegisterObject( aGroup );
2009
2010   builder->SetIOR( aGroupSO, _gen_i->GetORB()->object_to_string( aGroup ) );
2011
2012   return aGroup._retn();
2013 }
2014
2015 //=============================================================================
2016 /*!
2017  *
2018  */
2019 //=============================================================================
2020
2021 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
2022 {
2023   if(MYDEBUG) MESSAGE( "createSubMesh" );
2024   TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
2025
2026   ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
2027   int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
2028   SMESH_subMesh_i *subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
2029   SMESH::SMESH_subMesh_var subMesh
2030     = SMESH::SMESH_subMesh::_narrow(subMeshServant->_this());
2031
2032   _mapSubMesh[subMeshId] = mySubMesh;
2033   _mapSubMesh_i[subMeshId] = subMeshServant;
2034   _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate(subMesh);
2035
2036   // register CORBA object for persistence
2037   int nextId = _gen_i->RegisterObject( subMesh );
2038   if(MYDEBUG) MESSAGE( "Add submesh to map with id = "<< nextId);
2039
2040   // to track changes of GEOM groups
2041   addGeomGroupData( theSubShapeObject, subMesh );
2042
2043   return subMesh._retn();
2044 }
2045
2046 //=======================================================================
2047 //function : getSubMesh
2048 //purpose  :
2049 //=======================================================================
2050
2051 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
2052 {
2053   map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
2054   if ( it == _mapSubMeshIor.end() )
2055     return SMESH::SMESH_subMesh::_nil();
2056
2057   return SMESH::SMESH_subMesh::_duplicate( (*it).second );
2058 }
2059
2060
2061 //=============================================================================
2062 /*!
2063  *
2064  */
2065 //=============================================================================
2066
2067 void SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
2068                                   GEOM::GEOM_Object_ptr    theSubShapeObject )
2069 {
2070   MESSAGE("SMESH_Mesh_i::removeSubMesh()");
2071   if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
2072     return;
2073
2074   if ( theSubShapeObject->_is_nil() )  // not published shape (IPAL13617)
2075   {
2076     CORBA::Long shapeId = theSubMesh->GetId();
2077     if ( _mapSubMesh.find( shapeId ) != _mapSubMesh.end())
2078     {
2079       TopoDS_Shape S = _mapSubMesh[ shapeId ]->GetSubShape();
2080       if ( !S.IsNull() )
2081       {
2082         list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
2083         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
2084         for ( ; hyp != hyps.end(); ++hyp )
2085           _impl->RemoveHypothesis(S, (*hyp)->GetID());
2086       }
2087     }
2088   }
2089   else
2090   {
2091     try {
2092       SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
2093       for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
2094         removeHypothesis( theSubShapeObject, aHypList[i] );
2095       }
2096     }
2097     catch( const SALOME::SALOME_Exception& ) {
2098       INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
2099     }
2100     removeGeomGroupData( theSubShapeObject );
2101   }
2102   int subMeshId = theSubMesh->GetId();
2103
2104   _mapSubMesh.erase(subMeshId);
2105   _mapSubMesh_i.erase(subMeshId);
2106   _mapSubMeshIor.erase(subMeshId);
2107   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeSubMesh() completed");
2108 }
2109
2110 //=============================================================================
2111 /*!
2112  *
2113  */
2114 //=============================================================================
2115
2116 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType        theElemType,
2117                                                       const char*               theName,
2118                                                       const TopoDS_Shape&       theShape,
2119                                                       const SMESH_PredicatePtr& thePredicate )
2120 {
2121   std::string newName;
2122   if ( !theName || strlen( theName ) == 0 )
2123   {
2124     std::set< std::string > presentNames;
2125     std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
2126     for ( ; i_gr != _mapGroups.end(); ++i_gr )
2127       presentNames.insert( i_gr->second->GetName() );
2128     do {
2129       newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
2130     } while ( !presentNames.insert( newName ).second );
2131     theName = newName.c_str();
2132   }
2133   int anId;
2134   SMESH::SMESH_GroupBase_var aGroup;
2135   if ( _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName, anId, theShape, thePredicate ))
2136   {
2137     SMESH_GroupBase_i* aGroupImpl;
2138     if ( !theShape.IsNull() )
2139       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
2140     else if ( thePredicate )
2141       aGroupImpl = new SMESH_GroupOnFilter_i( SMESH_Gen_i::GetPOA(), this, anId );
2142     else
2143       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2144
2145     // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
2146     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
2147     aGroupImpl->Register();
2148     // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
2149
2150     aGroup = SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
2151     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2152
2153     // register CORBA object for persistence
2154     int nextId = _gen_i->RegisterObject( aGroup );
2155     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
2156
2157     // to track changes of GEOM groups
2158     if ( !theShape.IsNull() ) {
2159       GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
2160       addGeomGroupData( geom, aGroup );
2161     }
2162   }
2163   return aGroup._retn();
2164 }
2165
2166 //=============================================================================
2167 /*!
2168  * SMESH_Mesh_i::removeGroup
2169  *
2170  * Should be called by ~SMESH_Group_i()
2171  */
2172 //=============================================================================
2173
2174 void SMESH_Mesh_i::removeGroup( const int theId )
2175 {
2176   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
2177   if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
2178     SMESH::SMESH_GroupBase_ptr group = _mapGroups[theId];
2179     _mapGroups.erase( theId );
2180     removeGeomGroupData( group );
2181     if (! _impl->RemoveGroup( theId ))
2182     {
2183       // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
2184       RemoveGroup( group );
2185     }
2186   }
2187 }
2188
2189 //=============================================================================
2190 /*!
2191  *
2192  */
2193 //=============================================================================
2194
2195 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
2196 throw(SALOME::SALOME_Exception)
2197 {
2198   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetLog");
2199
2200   SMESH::log_array_var aLog;
2201   try{
2202     list < SMESHDS_Command * >logDS = _impl->GetLog();
2203     aLog = new SMESH::log_array;
2204     int indexLog = 0;
2205     int lg = logDS.size();
2206     SCRUTE(lg);
2207     aLog->length(lg);
2208     list < SMESHDS_Command * >::iterator its = logDS.begin();
2209     while(its != logDS.end()){
2210       SMESHDS_Command *com = *its;
2211       int comType = com->GetType();
2212       //SCRUTE(comType);
2213       int lgcom = com->GetNumber();
2214       //SCRUTE(lgcom);
2215       const list < int >&intList = com->GetIndexes();
2216       int inum = intList.size();
2217       //SCRUTE(inum);
2218       list < int >::const_iterator ii = intList.begin();
2219       const list < double >&coordList = com->GetCoords();
2220       int rnum = coordList.size();
2221       //SCRUTE(rnum);
2222       list < double >::const_iterator ir = coordList.begin();
2223       aLog[indexLog].commandType = comType;
2224       aLog[indexLog].number = lgcom;
2225       aLog[indexLog].coords.length(rnum);
2226       aLog[indexLog].indexes.length(inum);
2227       for(int i = 0; i < rnum; i++){
2228         aLog[indexLog].coords[i] = *ir;
2229         //MESSAGE(" "<<i<<" "<<ir.Value());
2230         ir++;
2231       }
2232       for(int i = 0; i < inum; i++){
2233         aLog[indexLog].indexes[i] = *ii;
2234         //MESSAGE(" "<<i<<" "<<ii.Value());
2235         ii++;
2236       }
2237       indexLog++;
2238       its++;
2239     }
2240     if(clearAfterGet)
2241       _impl->ClearLog();
2242   }
2243   catch(SALOME_Exception & S_ex){
2244     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
2245   }
2246   return aLog._retn();
2247 }
2248
2249
2250 //=============================================================================
2251 /*!
2252  *
2253  */
2254 //=============================================================================
2255
2256 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
2257 {
2258   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::ClearLog");
2259   _impl->ClearLog();
2260 }
2261
2262 //=============================================================================
2263 /*!
2264  *
2265  */
2266 //=============================================================================
2267
2268 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
2269 {
2270   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetId");
2271   return _id;
2272 }
2273
2274 //=============================================================================
2275 /*!
2276  *
2277  */
2278 //=============================================================================
2279
2280 CORBA::Long SMESH_Mesh_i::GetStudyId()throw(SALOME::SALOME_Exception)
2281 {
2282   return _studyId;
2283 }
2284
2285 //=============================================================================
2286 namespace
2287 {
2288   //!< implementation of struct used to call SMESH_Mesh_i::removeGroup() from
2289   // SMESH_Mesh::RemoveGroup() (issue 0020918)
2290   struct TRmGroupCallUp_i : public SMESH_Mesh::TRmGroupCallUp
2291   {
2292     SMESH_Mesh_i* _mesh;
2293     TRmGroupCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
2294     virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); }
2295   };
2296 }
2297
2298 //=============================================================================
2299 /*!
2300  *
2301  */
2302 //=============================================================================
2303
2304 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
2305 {
2306   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
2307   _impl = impl;
2308   if ( _impl )
2309     _impl->SetRemoveGroupCallUp( new TRmGroupCallUp_i(this));
2310 }
2311
2312 //=============================================================================
2313 /*!
2314  *
2315  */
2316 //=============================================================================
2317
2318 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
2319 {
2320   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
2321   return *_impl;
2322 }
2323
2324 //=============================================================================
2325 /*!
2326  * Return mesh editor
2327  */
2328 //=============================================================================
2329
2330 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
2331 {
2332   // Create MeshEditor
2333   SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, false );
2334   SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
2335
2336   // Update Python script
2337   TPythonDump() << aMeshEditor << " = " << _this() << ".GetMeshEditor()";
2338
2339   return aMesh._retn();
2340 }
2341
2342 //=============================================================================
2343 /*!
2344  * Return mesh edition previewer
2345  */
2346 //=============================================================================
2347
2348 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
2349 {
2350   SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, true );
2351   SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
2352   return aMesh._retn();
2353 }
2354
2355 //================================================================================
2356 /*!
2357  * \brief Return true if the mesh has been edited since a last total re-compute
2358  *        and those modifications may prevent successful partial re-compute
2359  */
2360 //================================================================================
2361
2362 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard() throw(SALOME::SALOME_Exception)
2363 {
2364   Unexpect aCatch(SALOME_SalomeException);
2365   return _impl->HasModificationsToDiscard();
2366 }
2367
2368 static SALOMEDS::Color getUniqueColor( const std::list<SALOMEDS::Color>& theReservedColors )
2369 {
2370   const int MAX_ATTEMPTS = 100;
2371   int cnt = 0;
2372   double tolerance = 0.5;
2373   SALOMEDS::Color col;
2374
2375   bool ok = false;
2376   while ( !ok ) {
2377     // generate random color
2378     double red    = (double)rand() / RAND_MAX;
2379     double green  = (double)rand() / RAND_MAX;
2380     double blue   = (double)rand() / RAND_MAX;
2381     // check existence in the list of the existing colors
2382     bool matched = false;
2383     std::list<SALOMEDS::Color>::const_iterator it;
2384     for ( it = theReservedColors.begin(); it != theReservedColors.end() && !matched; ++it ) {
2385       SALOMEDS::Color color = *it;
2386       double tol = fabs( color.R - red ) + fabs( color.G - green ) + fabs( color.B  - blue  );
2387       matched = tol < tolerance;
2388     }
2389     if ( (cnt+1) % 20 == 0 ) tolerance = tolerance/2;
2390     ok = ( ++cnt == MAX_ATTEMPTS ) || !matched;
2391     col.R = red;
2392     col.G = green;
2393     col.B = blue;
2394   }
2395   return col;
2396 }
2397
2398 //=============================================================================
2399 /*!
2400  *
2401  */
2402 //=============================================================================
2403 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOME_Exception)
2404 {
2405   Unexpect aCatch(SALOME_SalomeException);
2406   _impl->SetAutoColor(theAutoColor);
2407
2408   TPythonDump pyDump; // not to dump group->SetColor() from below code
2409   pyDump<<_this()<<".SetAutoColor( "<<theAutoColor<<" )";
2410
2411   std::list<SALOMEDS::Color> aReservedColors;
2412   map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
2413   for ( ; it != _mapGroups.end(); it++ ) {
2414     if ( CORBA::is_nil( it->second )) continue;
2415     SALOMEDS::Color aColor = getUniqueColor( aReservedColors );
2416     it->second->SetColor( aColor );
2417     aReservedColors.push_back( aColor );
2418   }
2419 }
2420
2421 //=============================================================================
2422 /*!
2423  *
2424  */
2425 //=============================================================================
2426 CORBA::Boolean SMESH_Mesh_i::GetAutoColor() throw(SALOME::SALOME_Exception)
2427 {
2428   Unexpect aCatch(SALOME_SalomeException);
2429   return _impl->GetAutoColor();
2430 }
2431
2432
2433 //=============================================================================
2434 /*!
2435  *  Export in different formats
2436  */
2437 //=============================================================================
2438
2439 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
2440 {
2441   return _impl->HasDuplicatedGroupNamesMED();
2442 }
2443
2444 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
2445 {
2446   TCollection_AsciiString aFullName ((char*)file);
2447   OSD_Path aPath (aFullName);
2448   OSD_File aFile (aPath);
2449   if (aFile.Exists()) {
2450     // existing filesystem node
2451     if (aFile.KindOfFile() == OSD_FILE) {
2452       if (aFile.IsWriteable()) {
2453         if (overwrite) {
2454           aFile.Reset();
2455           aFile.Remove();
2456         }
2457         if (aFile.Failed()) {
2458           TCollection_AsciiString msg ("File ");
2459           msg += aFullName + " cannot be replaced.";
2460           THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2461         }
2462       } else {
2463         TCollection_AsciiString msg ("File ");
2464         msg += aFullName + " cannot be overwritten.";
2465         THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2466       }
2467     } else {
2468       TCollection_AsciiString msg ("Location ");
2469       msg += aFullName + " is not a file.";
2470       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2471     }
2472   } else {
2473     // nonexisting file; check if it can be created
2474     aFile.Reset();
2475     aFile.Build(OSD_WriteOnly, OSD_Protection());
2476     if (aFile.Failed()) {
2477       TCollection_AsciiString msg ("You cannot create the file ");
2478       msg += aFullName + ". Check the directory existance and access rights.";
2479       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
2480     } else {
2481       aFile.Close();
2482       aFile.Remove();
2483     }
2484   }
2485 }
2486
2487 void SMESH_Mesh_i::ExportToMEDX (const char* file,
2488                                  CORBA::Boolean auto_groups,
2489                                  SMESH::MED_VERSION theVersion,
2490                                  CORBA::Boolean overwrite)
2491   throw(SALOME::SALOME_Exception)
2492 {
2493   Unexpect aCatch(SALOME_SalomeException);
2494
2495   // Perform Export
2496   PrepareForWriting(file, overwrite);
2497   string aMeshName = "Mesh";
2498   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
2499   if ( !aStudy->_is_nil() ) {
2500     SALOMEDS::SObject_var aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
2501     if ( !aMeshSO->_is_nil() ) {
2502       CORBA::String_var name = aMeshSO->GetName();
2503       aMeshName = name;
2504       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
2505       if ( !aStudy->GetProperties()->IsLocked() )
2506       {
2507         SALOMEDS::GenericAttribute_var anAttr;
2508         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
2509         SALOMEDS::AttributeExternalFileDef_var aFileName;
2510         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
2511         aFileName = SALOMEDS::AttributeExternalFileDef::_narrow(anAttr);
2512         ASSERT(!aFileName->_is_nil());
2513         aFileName->SetValue(file);
2514         SALOMEDS::AttributeFileType_var aFileType;
2515         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
2516         aFileType = SALOMEDS::AttributeFileType::_narrow(anAttr);
2517         ASSERT(!aFileType->_is_nil());
2518         aFileType->SetValue("FICHIERMED");
2519       }
2520     }
2521   }
2522   // Update Python script
2523   // set name of mesh before export
2524   TPythonDump() << _gen_i << ".SetName(" << _this() << ", '" << aMeshName.c_str() << "')";
2525
2526   // check names of groups
2527   checkGroupNames();
2528
2529   TPythonDump() << _this() << ".ExportToMEDX( r'"
2530                 << file << "', " << auto_groups << ", " << theVersion << ", " << overwrite << " )";
2531
2532   _impl->ExportMED( file, aMeshName.c_str(), auto_groups, theVersion );
2533 }
2534
2535 //================================================================================
2536 /*!
2537  * \brief Export a mesh to a med file
2538  */
2539 //================================================================================
2540
2541 void SMESH_Mesh_i::ExportToMED (const char* file,
2542                                 CORBA::Boolean auto_groups,
2543                                 SMESH::MED_VERSION theVersion)
2544   throw(SALOME::SALOME_Exception)
2545 {
2546   ExportToMEDX(file,auto_groups,theVersion,true);
2547 }
2548
2549 //================================================================================
2550 /*!
2551  * \brief Export a mesh to a med file
2552  */
2553 //================================================================================
2554
2555 void SMESH_Mesh_i::ExportMED (const char* file,
2556                               CORBA::Boolean auto_groups)
2557   throw(SALOME::SALOME_Exception)
2558 {
2559   ExportToMEDX(file,auto_groups,SMESH::MED_V2_2,true);
2560 }
2561
2562 //================================================================================
2563 /*!
2564  * \brief Export a mesh to a DAT file
2565  */
2566 //================================================================================
2567
2568 void SMESH_Mesh_i::ExportDAT (const char *file)
2569   throw(SALOME::SALOME_Exception)
2570 {
2571   Unexpect aCatch(SALOME_SalomeException);
2572
2573   // Update Python script
2574   // check names of groups
2575   checkGroupNames();
2576   TPythonDump() << _this() << ".ExportDAT( r'" << file << "' )";
2577
2578   // Perform Export
2579   PrepareForWriting(file);
2580   _impl->ExportDAT(file);
2581 }
2582
2583 //================================================================================
2584 /*!
2585  * \brief Export a mesh to an UNV file
2586  */
2587 //================================================================================
2588
2589 void SMESH_Mesh_i::ExportUNV (const char *file)
2590   throw(SALOME::SALOME_Exception)
2591 {
2592   Unexpect aCatch(SALOME_SalomeException);
2593
2594   // Update Python script
2595   // check names of groups
2596   checkGroupNames();
2597   TPythonDump() << _this() << ".ExportUNV( r'" << file << "' )";
2598
2599   // Perform Export
2600   PrepareForWriting(file);
2601   _impl->ExportUNV(file);
2602 }
2603
2604 //================================================================================
2605 /*!
2606  * \brief Export a mesh to an STL file
2607  */
2608 //================================================================================
2609
2610 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
2611   throw(SALOME::SALOME_Exception)
2612 {
2613   Unexpect aCatch(SALOME_SalomeException);
2614
2615   // Update Python script
2616   // check names of groups
2617   checkGroupNames();
2618   TPythonDump() << _this() << ".ExportSTL( r'" << file << "', " << isascii << " )";
2619
2620   // Perform Export
2621   PrepareForWriting(file);
2622   _impl->ExportSTL(file, isascii);
2623 }
2624
2625 //=============================================================================
2626 /*!
2627  * \brief Class providing SMESHDS_Mesh API to SMESH_IDSource. 
2628  *        It is used to export a part of mesh as a whole mesh.
2629  */
2630 class SMESH_MeshPartDS : public SMESHDS_Mesh
2631 {
2632 public:
2633   SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart);
2634
2635   virtual SMDS_NodeIteratorPtr      nodesIterator     (bool idInceasingOrder=false) const;
2636   virtual SMDS_0DElementIteratorPtr elements0dIterator(bool idInceasingOrder=false) const;
2637   virtual SMDS_EdgeIteratorPtr      edgesIterator     (bool idInceasingOrder=false) const;
2638   virtual SMDS_FaceIteratorPtr      facesIterator     (bool idInceasingOrder=false) const;
2639   virtual SMDS_VolumeIteratorPtr    volumesIterator   (bool idInceasingOrder=false) const;
2640
2641   virtual SMDS_ElemIteratorPtr elementsIterator(SMDSAbs_ElementType type=SMDSAbs_All) const;
2642
2643 private:
2644   TIDSortedElemSet _elements[ SMDSAbs_NbElementTypes ];
2645   SMESHDS_Mesh*    _meshDS;
2646   /*!
2647    * \brief Class used to access to protected data of SMDS_MeshInfo
2648    */
2649   struct TMeshInfo : public SMDS_MeshInfo
2650   {
2651     void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); }
2652   };
2653 };
2654
2655 //================================================================================
2656 /*!
2657  * \brief Export a part of mesh to a med file
2658  */
2659 //================================================================================
2660
2661 void SMESH_Mesh_i::ExportPartToMED(::SMESH::SMESH_IDSource_ptr meshPart,
2662                                    const char*                 file,
2663                                    CORBA::Boolean              auto_groups,
2664                                    ::SMESH::MED_VERSION        version,
2665                                    ::CORBA::Boolean            overwrite)
2666   throw (SALOME::SALOME_Exception)
2667 {
2668   Unexpect aCatch(SALOME_SalomeException);
2669
2670   PrepareForWriting(file, overwrite);
2671
2672   string aMeshName = "Mesh";
2673   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
2674   if ( !aStudy->_is_nil() ) {
2675     SALOMEDS::SObject_var SO = _gen_i->ObjectToSObject( aStudy, meshPart );
2676     if ( !SO->_is_nil() ) {
2677       CORBA::String_var name = SO->GetName();
2678       aMeshName = name;
2679     }
2680   }
2681   SMESH_MeshPartDS partDS( meshPart );
2682   _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version, &partDS );
2683
2684   TPythonDump() << _this() << ".ExportPartToMED( " << meshPart << ", r'" << file << "', "
2685                 << auto_groups << ", " << version << ", " << overwrite << " )";
2686 }
2687
2688 //================================================================================
2689 /*!
2690  * \brief Export a part of mesh to a DAT file
2691  */
2692 //================================================================================
2693
2694 void SMESH_Mesh_i::ExportPartToDAT(::SMESH::SMESH_IDSource_ptr meshPart,
2695                                    const char*                 file)
2696   throw (SALOME::SALOME_Exception)
2697 {
2698   Unexpect aCatch(SALOME_SalomeException);
2699
2700   PrepareForWriting(file);
2701
2702   SMESH_MeshPartDS partDS( meshPart );
2703   _impl->ExportDAT(file,&partDS);
2704
2705   TPythonDump() << _this() << ".ExportPartToDAT( " << meshPart << ", r'" << file << "' )";
2706 }
2707 //================================================================================
2708 /*!
2709  * \brief Export a part of mesh to an UNV file
2710  */
2711 //================================================================================
2712
2713 void SMESH_Mesh_i::ExportPartToUNV(::SMESH::SMESH_IDSource_ptr meshPart,
2714                                    const char*                 file)
2715   throw (SALOME::SALOME_Exception)
2716 {
2717   Unexpect aCatch(SALOME_SalomeException);
2718
2719   PrepareForWriting(file);
2720
2721   SMESH_MeshPartDS partDS( meshPart );
2722   _impl->ExportUNV(file, &partDS);
2723
2724   TPythonDump() << _this() << ".ExportPartToUNV( " << meshPart<< ", r'" << file << "' )";
2725 }
2726 //================================================================================
2727 /*!
2728  * \brief Export a part of mesh to an STL file
2729  */
2730 //================================================================================
2731
2732 void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
2733                                    const char*                 file,
2734                                    ::CORBA::Boolean            isascii)
2735   throw (SALOME::SALOME_Exception)
2736 {
2737   Unexpect aCatch(SALOME_SalomeException);
2738
2739   PrepareForWriting(file);
2740
2741   SMESH_MeshPartDS partDS( meshPart );
2742   _impl->ExportSTL(file, isascii, &partDS);
2743
2744   TPythonDump() << _this() << ".ExportPartToSTL( "
2745                 << meshPart<< ", r'" << file << "', " << isascii << ")";
2746 }
2747
2748 //=============================================================================
2749 /*!
2750  *
2751  */
2752 //=============================================================================
2753
2754 SALOME_MED::MESH_ptr SMESH_Mesh_i::GetMEDMesh()throw(SALOME::SALOME_Exception)
2755 {
2756   Unexpect aCatch(SALOME_SalomeException);
2757   SMESH_MEDMesh_i *aMedMesh = new SMESH_MEDMesh_i(this);
2758   SALOME_MED::MESH_var aMesh = aMedMesh->_this();
2759   return aMesh._retn();
2760 }
2761
2762 //=============================================================================
2763 /*!
2764  *
2765  */
2766 //=============================================================================
2767 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
2768 {
2769   Unexpect aCatch(SALOME_SalomeException);
2770   return _impl->NbNodes();
2771 }
2772
2773 //=============================================================================
2774 /*!
2775  *
2776  */
2777 //=============================================================================
2778 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
2779 {
2780   Unexpect aCatch(SALOME_SalomeException);
2781   return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes();
2782 }
2783
2784 //=============================================================================
2785 /*!
2786  *
2787  */
2788 //=============================================================================
2789 CORBA::Long SMESH_Mesh_i::Nb0DElements()throw (SALOME::SALOME_Exception)
2790 {
2791   Unexpect aCatch(SALOME_SalomeException);
2792   return _impl->Nb0DElements();
2793 }
2794
2795 //=============================================================================
2796 /*!
2797  *
2798  */
2799 //=============================================================================
2800 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
2801 {
2802   Unexpect aCatch(SALOME_SalomeException);
2803   return _impl->NbEdges();
2804 }
2805
2806 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
2807   throw(SALOME::SALOME_Exception)
2808 {
2809   Unexpect aCatch(SALOME_SalomeException);
2810   return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
2811 }
2812
2813 //=============================================================================
2814 /*!
2815  *
2816  */
2817 //=============================================================================
2818 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
2819 {
2820   Unexpect aCatch(SALOME_SalomeException);
2821   return _impl->NbFaces();
2822 }
2823
2824 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
2825 {
2826   Unexpect aCatch(SALOME_SalomeException);
2827   return _impl->NbTriangles();
2828 }
2829
2830 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
2831 {
2832   Unexpect aCatch(SALOME_SalomeException);
2833   return _impl->NbQuadrangles();
2834 }
2835
2836 CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
2837 {
2838   Unexpect aCatch(SALOME_SalomeException);
2839   return _impl->NbPolygons();
2840 }
2841
2842 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
2843   throw(SALOME::SALOME_Exception)
2844 {
2845   Unexpect aCatch(SALOME_SalomeException);
2846   return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
2847 }
2848
2849 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
2850   throw(SALOME::SALOME_Exception)
2851 {
2852   Unexpect aCatch(SALOME_SalomeException);
2853   return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
2854 }
2855
2856 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
2857   throw(SALOME::SALOME_Exception)
2858 {
2859   Unexpect aCatch(SALOME_SalomeException);
2860   return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
2861 }
2862
2863 //=============================================================================
2864 /*!
2865  *
2866  */
2867 //=============================================================================
2868 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
2869 {
2870   Unexpect aCatch(SALOME_SalomeException);
2871   return _impl->NbVolumes();
2872 }
2873
2874 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
2875 {
2876   Unexpect aCatch(SALOME_SalomeException);
2877   return _impl->NbTetras();
2878 }
2879
2880 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
2881 {
2882   Unexpect aCatch(SALOME_SalomeException);
2883   return _impl->NbHexas();
2884 }
2885
2886 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
2887 {
2888   Unexpect aCatch(SALOME_SalomeException);
2889   return _impl->NbPyramids();
2890 }
2891
2892 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
2893 {
2894   Unexpect aCatch(SALOME_SalomeException);
2895   return _impl->NbPrisms();
2896 }
2897
2898 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
2899 {
2900   Unexpect aCatch(SALOME_SalomeException);
2901   return _impl->NbPolyhedrons();
2902 }
2903
2904 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
2905   throw(SALOME::SALOME_Exception)
2906 {
2907   Unexpect aCatch(SALOME_SalomeException);
2908   return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
2909 }
2910
2911 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
2912   throw(SALOME::SALOME_Exception)
2913 {
2914   Unexpect aCatch(SALOME_SalomeException);
2915   return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
2916 }
2917
2918 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
2919   throw(SALOME::SALOME_Exception)
2920 {
2921   Unexpect aCatch(SALOME_SalomeException);
2922   return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
2923 }
2924
2925 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
2926   throw(SALOME::SALOME_Exception)
2927 {
2928   Unexpect aCatch(SALOME_SalomeException);
2929   return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
2930 }
2931
2932 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
2933   throw(SALOME::SALOME_Exception)
2934 {
2935   Unexpect aCatch(SALOME_SalomeException);
2936   return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
2937 }
2938
2939 //=============================================================================
2940 /*!
2941  *
2942  */
2943 //=============================================================================
2944 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
2945 {
2946   Unexpect aCatch(SALOME_SalomeException);
2947   return _mapSubMesh_i.size();
2948 }
2949
2950 //=============================================================================
2951 /*!
2952  *
2953  */
2954 //=============================================================================
2955 char* SMESH_Mesh_i::Dump()
2956 {
2957   ostringstream os;
2958   _impl->Dump( os );
2959   return CORBA::string_dup( os.str().c_str() );
2960 }
2961
2962 //=============================================================================
2963 /*!
2964  *
2965  */
2966 //=============================================================================
2967 SMESH::long_array* SMESH_Mesh_i::GetIDs()
2968 {
2969 //   SMESH::long_array_var aResult = new SMESH::long_array();
2970 //   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2971 //   int aMinId = aSMESHDS_Mesh->MinElementID();
2972 //   int aMaxId =  aSMESHDS_Mesh->MaxElementID();
2973
2974 //   aResult->length(aMaxId - aMinId + 1);
2975
2976 //   for (int i = 0, id = aMinId; id <= aMaxId; id++  )
2977 //     aResult[i++] = id;
2978
2979 //   return aResult._retn();
2980   // PAL12398
2981   return GetElementsId();
2982 }
2983
2984 //=============================================================================
2985 /*!
2986  *
2987  */
2988 //=============================================================================
2989
2990 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
2991      throw (SALOME::SALOME_Exception)
2992 {
2993   Unexpect aCatch(SALOME_SalomeException);
2994   MESSAGE("SMESH_Mesh_i::GetElementsId");
2995   SMESH::long_array_var aResult = new SMESH::long_array();
2996   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2997
2998   if ( aSMESHDS_Mesh == NULL )
2999     return aResult._retn();
3000
3001   long nbElements = NbElements();
3002   aResult->length( nbElements );
3003   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
3004   for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
3005     aResult[i] = anIt->next()->GetID();
3006
3007   return aResult._retn();
3008 }
3009
3010
3011 //=============================================================================
3012 /*!
3013  *
3014  */
3015 //=============================================================================
3016
3017 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
3018     throw (SALOME::SALOME_Exception)
3019 {
3020   Unexpect aCatch(SALOME_SalomeException);
3021   MESSAGE("SMESH_subMesh_i::GetElementsByType");
3022   SMESH::long_array_var aResult = new SMESH::long_array();
3023   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3024
3025   if ( aSMESHDS_Mesh == NULL )
3026     return aResult._retn();
3027
3028   long nbElements = NbElements();
3029
3030   // No sense in returning ids of elements along with ids of nodes:
3031   // when theElemType == SMESH::ALL, return node ids only if
3032   // there are no elements
3033   if ( theElemType == SMESH::NODE || (theElemType == SMESH::ALL && nbElements == 0) )
3034     return GetNodesId();
3035
3036   aResult->length( nbElements );
3037
3038   int i = 0;
3039
3040   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
3041   while ( i < nbElements && anIt->more() ) {
3042     const SMDS_MeshElement* anElem = anIt->next();
3043     if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
3044       aResult[i++] = anElem->GetID();
3045   }
3046
3047   aResult->length( i );
3048
3049   return aResult._retn();
3050 }
3051
3052 //=============================================================================
3053 /*!
3054  *
3055  */
3056 //=============================================================================
3057
3058 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
3059   throw (SALOME::SALOME_Exception)
3060 {
3061   Unexpect aCatch(SALOME_SalomeException);
3062   MESSAGE("SMESH_subMesh_i::GetNodesId");
3063   SMESH::long_array_var aResult = new SMESH::long_array();
3064   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3065
3066   if ( aSMESHDS_Mesh == NULL )
3067     return aResult._retn();
3068
3069   long nbNodes = NbNodes();
3070   aResult->length( nbNodes );
3071   SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator(/*idInceasingOrder=*/true);
3072   for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
3073     aResult[i] = anIt->next()->GetID();
3074
3075   return aResult._retn();
3076 }
3077
3078 //=============================================================================
3079 /*!
3080  *
3081  */
3082 //=============================================================================
3083
3084 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
3085   throw (SALOME::SALOME_Exception)
3086 {
3087   return ( SMESH::ElementType )_impl->GetElementType( id, iselem );
3088 }
3089
3090 //=============================================================================
3091 /*!
3092  *
3093  */
3094 //=============================================================================
3095
3096 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id )
3097   throw (SALOME::SALOME_Exception)
3098 {
3099   const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
3100   if ( !e )
3101     THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
3102
3103   return ( SMESH::EntityType ) e->GetEntityType();
3104 }
3105
3106 //=============================================================================
3107 /*!
3108  * Returns ID of elements for given submesh
3109  */
3110 //=============================================================================
3111 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
3112      throw (SALOME::SALOME_Exception)
3113 {
3114   SMESH::long_array_var aResult = new SMESH::long_array();
3115
3116   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
3117   if(!SM) return aResult._retn();
3118
3119   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
3120   if(!SDSM) return aResult._retn();
3121
3122   aResult->length(SDSM->NbElements());
3123
3124   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
3125   int i = 0;
3126   while ( eIt->more() ) {
3127     aResult[i++] = eIt->next()->GetID();
3128   }
3129
3130   return aResult._retn();
3131 }
3132
3133
3134 //=============================================================================
3135 /*!
3136  * Returns ID of nodes for given submesh
3137  * If param all==true - returns all nodes, else -
3138  * returns only nodes on shapes.
3139  */
3140 //=============================================================================
3141 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID, CORBA::Boolean all)
3142      throw (SALOME::SALOME_Exception)
3143 {
3144   SMESH::long_array_var aResult = new SMESH::long_array();
3145
3146   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
3147   if(!SM) return aResult._retn();
3148
3149   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
3150   if(!SDSM) return aResult._retn();
3151
3152   set<int> theElems;
3153   if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
3154     SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
3155     while ( nIt->more() ) {
3156       const SMDS_MeshNode* elem = nIt->next();
3157       theElems.insert( elem->GetID() );
3158     }
3159   }
3160   else { // all nodes of submesh elements
3161     SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
3162     while ( eIt->more() ) {
3163       const SMDS_MeshElement* anElem = eIt->next();
3164       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
3165       while ( nIt->more() ) {
3166         const SMDS_MeshElement* elem = nIt->next();
3167         theElems.insert( elem->GetID() );
3168       }
3169     }
3170   }
3171
3172   aResult->length(theElems.size());
3173   set<int>::iterator itElem;
3174   int i = 0;
3175   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
3176     aResult[i++] = *itElem;
3177
3178   return aResult._retn();
3179 }
3180   
3181
3182 //=============================================================================
3183 /*!
3184  * Returns type of elements for given submesh
3185  */
3186 //=============================================================================
3187 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
3188      throw (SALOME::SALOME_Exception)
3189 {
3190   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
3191   if(!SM) return SMESH::ALL;
3192
3193   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
3194   if(!SDSM) return SMESH::ALL;
3195
3196   if(SDSM->NbElements()==0)
3197     return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
3198
3199   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
3200   const SMDS_MeshElement* anElem = eIt->next();
3201   return ( SMESH::ElementType ) anElem->GetType();
3202 }
3203   
3204
3205 //=============================================================================
3206 /*!
3207  *
3208  */
3209 //=============================================================================
3210
3211 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
3212 {
3213   CORBA::LongLong pointeur = CORBA::LongLong(_impl);
3214   if ( MYDEBUG )
3215     MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
3216   return pointeur;
3217 }
3218
3219
3220 //=============================================================================
3221 /*!
3222  * Get XYZ coordinates of node as list of double
3223  * If there is not node for given ID - returns empty list
3224  */
3225 //=============================================================================
3226
3227 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
3228 {
3229   SMESH::double_array_var aResult = new SMESH::double_array();
3230   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3231   if ( aSMESHDS_Mesh == NULL )
3232     return aResult._retn();
3233
3234   // find node
3235   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3236   if(!aNode)
3237     return aResult._retn();
3238
3239   // add coordinates
3240   aResult->length(3);
3241   aResult[0] = aNode->X();
3242   aResult[1] = aNode->Y();
3243   aResult[2] = aNode->Z();
3244   return aResult._retn();
3245 }
3246
3247
3248 //=============================================================================
3249 /*!
3250  * For given node returns list of IDs of inverse elements
3251  * If there is not node for given ID - returns empty list
3252  */
3253 //=============================================================================
3254
3255 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
3256 {
3257   SMESH::long_array_var aResult = new SMESH::long_array();
3258   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3259   if ( aSMESHDS_Mesh == NULL )
3260     return aResult._retn();
3261
3262   // find node
3263   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3264   if(!aNode)
3265     return aResult._retn();
3266
3267   // find inverse elements
3268   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
3269   TColStd_SequenceOfInteger IDs;
3270   while(eIt->more()) {
3271     const SMDS_MeshElement* elem = eIt->next();
3272     IDs.Append(elem->GetID());
3273   }
3274   if(IDs.Length()>0) {
3275     aResult->length(IDs.Length());
3276     int i = 1;
3277     for(; i<=IDs.Length(); i++) {
3278       aResult[i-1] = IDs.Value(i);
3279     }
3280   }
3281   return aResult._retn();
3282 }
3283
3284 //=============================================================================
3285 /*!
3286  * \brief Return position of a node on shape
3287  */
3288 //=============================================================================
3289
3290 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
3291 {
3292   SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
3293   aNodePosition->shapeID = 0;
3294   aNodePosition->shapeType = GEOM::SHAPE;
3295
3296   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
3297   if ( !mesh ) return aNodePosition;
3298
3299   if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
3300   {
3301     if ( SMDS_PositionPtr pos = aNode->GetPosition() )
3302     {
3303       aNodePosition->shapeID = aNode->getshapeId();
3304       switch ( pos->GetTypeOfPosition() ) {
3305       case SMDS_TOP_EDGE:
3306         aNodePosition->shapeType = GEOM::EDGE;
3307         aNodePosition->params.length(1);
3308         aNodePosition->params[0] =
3309           static_cast<SMDS_EdgePosition*>( pos )->GetUParameter();
3310         break;
3311       case SMDS_TOP_FACE:
3312         aNodePosition->shapeType = GEOM::FACE;
3313         aNodePosition->params.length(2);
3314         aNodePosition->params[0] =
3315           static_cast<SMDS_FacePosition*>( pos )->GetUParameter();
3316         aNodePosition->params[1] =
3317           static_cast<SMDS_FacePosition*>( pos )->GetVParameter();
3318         break;
3319       case SMDS_TOP_VERTEX:
3320         aNodePosition->shapeType = GEOM::VERTEX;
3321         break;
3322       case SMDS_TOP_3DSPACE:
3323         if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
3324           aNodePosition->shapeType = GEOM::SOLID;
3325         else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
3326           aNodePosition->shapeType = GEOM::SHELL;
3327         break;
3328       default:;
3329       }
3330     }
3331   }
3332   return aNodePosition;
3333 }
3334
3335 //=============================================================================
3336 /*!
3337  * If given element is node returns IDs of shape from position
3338  * If there is not node for given ID - returns -1
3339  */
3340 //=============================================================================
3341
3342 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
3343 {
3344   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3345   if ( aSMESHDS_Mesh == NULL )
3346     return -1;
3347
3348   // try to find node
3349   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3350   if(aNode) {
3351     return aNode->getshapeId();
3352   }
3353
3354   return -1;
3355 }
3356
3357
3358 //=============================================================================
3359 /*!
3360  * For given element returns ID of result shape after 
3361  * ::FindShape() from SMESH_MeshEditor
3362  * If there is not element for given ID - returns -1
3363  */
3364 //=============================================================================
3365
3366 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
3367 {
3368   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3369   if ( aSMESHDS_Mesh == NULL )
3370     return -1;
3371
3372   // try to find element
3373   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3374   if(!elem)
3375     return -1;
3376
3377   //SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
3378   ::SMESH_MeshEditor aMeshEditor(_impl);
3379   int index = aMeshEditor.FindShape( elem );
3380   if(index>0)
3381     return index;
3382
3383   return -1;
3384 }
3385
3386
3387 //=============================================================================
3388 /*!
3389  * Returns number of nodes for given element
3390  * If there is not element for given ID - returns -1
3391  */
3392 //=============================================================================
3393
3394 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
3395 {
3396   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3397   if ( aSMESHDS_Mesh == NULL ) return -1;
3398   // try to find element
3399   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3400   if(!elem) return -1;
3401   return elem->NbNodes();
3402 }
3403
3404
3405 //=============================================================================
3406 /*!
3407  * Returns ID of node by given index for given element
3408  * If there is not element for given ID - returns -1
3409  * If there is not node for given index - returns -2
3410  */
3411 //=============================================================================
3412
3413 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
3414 {
3415   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3416   if ( aSMESHDS_Mesh == NULL ) return -1;
3417   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3418   if(!elem) return -1;
3419   if( index>=elem->NbNodes() || index<0 ) return -1;
3420   return elem->GetNode(index)->GetID();
3421 }
3422
3423 //=============================================================================
3424 /*!
3425  * Returns IDs of nodes of given element
3426  */
3427 //=============================================================================
3428
3429 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
3430 {
3431   SMESH::long_array_var aResult = new SMESH::long_array();
3432   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
3433   {
3434     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id) )
3435     {
3436       aResult->length( elem->NbNodes() );
3437       for ( int i = 0; i < elem->NbNodes(); ++i )
3438         aResult[ i ] = elem->GetNode( i )->GetID();
3439     }
3440   }
3441   return aResult._retn();
3442 }
3443
3444 //=============================================================================
3445 /*!
3446  * Returns true if given node is medium node
3447  * in given quadratic element
3448  */
3449 //=============================================================================
3450
3451 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
3452 {
3453   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3454   if ( aSMESHDS_Mesh == NULL ) return false;
3455   // try to find node
3456   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
3457   if(!aNode) return false;
3458   // try to find element
3459   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(ide);
3460   if(!elem) return false;
3461
3462   return elem->IsMediumNode(aNode);
3463 }
3464
3465
3466 //=============================================================================
3467 /*!
3468  * Returns true if given node is medium node
3469  * in one of quadratic elements
3470  */
3471 //=============================================================================
3472
3473 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
3474                                                    SMESH::ElementType theElemType)
3475 {
3476   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3477   if ( aSMESHDS_Mesh == NULL ) return false;
3478
3479   // try to find node
3480   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
3481   if(!aNode) return false;
3482
3483   SMESH_MesherHelper aHelper( *(_impl) );
3484
3485   SMDSAbs_ElementType aType;
3486   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
3487   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
3488   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
3489   else aType = SMDSAbs_All;
3490
3491   return aHelper.IsMedium(aNode,aType);
3492 }
3493
3494
3495 //=============================================================================
3496 /*!
3497  * Returns number of edges for given element
3498  */
3499 //=============================================================================
3500
3501 CORBA::Long SMESH_Mesh_i::ElemNbEdges(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->NbEdges();
3508 }
3509
3510
3511 //=============================================================================
3512 /*!
3513  * Returns number of faces for given element
3514  */
3515 //=============================================================================
3516
3517 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
3518 {
3519   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3520   if ( aSMESHDS_Mesh == NULL ) return -1;
3521   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3522   if(!elem) return -1;
3523   return elem->NbFaces();
3524 }
3525
3526 //=======================================================================
3527 //function : GetElemFaceNodes
3528 //purpose  : Returns nodes of given face (counted from zero) for given element.
3529 //=======================================================================
3530
3531 SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long  elemId,
3532                                                   CORBA::Short faceIndex)
3533 {
3534   SMESH::long_array_var aResult = new SMESH::long_array();
3535   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
3536   {
3537     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(elemId) )
3538     {
3539       SMDS_VolumeTool vtool( elem );
3540       if ( faceIndex < vtool.NbFaces() )
3541       {
3542         aResult->length( vtool.NbFaceNodes( faceIndex ));
3543         const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
3544         for ( int i = 0; i < aResult->length(); ++i )
3545           aResult[ i ] = nn[ i ]->GetID();
3546       }
3547     }
3548   }
3549   return aResult._retn();
3550 }
3551
3552 //=======================================================================
3553 //function : FindElementByNodes
3554 //purpose  : Returns an element based on all given nodes.
3555 //=======================================================================
3556
3557 CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
3558 {
3559   CORBA::Long elemID(0);
3560   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
3561   {
3562     vector< const SMDS_MeshNode * > nn( nodes.length() );
3563     for ( int i = 0; i < nodes.length(); ++i )
3564       if ( !( nn[i] = mesh->FindNode( nodes[i] )))
3565         return elemID;
3566
3567     const SMDS_MeshElement* elem = mesh->FindElement( nn );
3568     if ( !elem && ( _impl->NbEdges( ORDER_QUADRATIC ) ||
3569                     _impl->NbFaces( ORDER_QUADRATIC ) ||
3570                     _impl->NbVolumes( ORDER_QUADRATIC )))
3571       elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
3572
3573     if ( elem ) elemID = CORBA::Long( elem->GetID() );
3574   }
3575   return elemID;
3576 }
3577
3578 //=============================================================================
3579 /*!
3580  * Returns true if given element is polygon
3581  */
3582 //=============================================================================
3583
3584 CORBA::Boolean SMESH_Mesh_i::IsPoly(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->IsPoly();
3591 }
3592
3593
3594 //=============================================================================
3595 /*!
3596  * Returns true if given element is quadratic
3597  */
3598 //=============================================================================
3599
3600 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
3601 {
3602   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3603   if ( aSMESHDS_Mesh == NULL ) return false;
3604   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3605   if(!elem) return false;
3606   return elem->IsQuadratic();
3607 }
3608
3609
3610 //=============================================================================
3611 /*!
3612  * Returns bary center for given element
3613  */
3614 //=============================================================================
3615
3616 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
3617 {
3618   SMESH::double_array_var aResult = new SMESH::double_array();
3619   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3620   if ( aSMESHDS_Mesh == NULL )
3621     return aResult._retn();
3622
3623   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3624   if(!elem)
3625     return aResult._retn();
3626
3627   if(elem->GetType()==SMDSAbs_Volume) {
3628     SMDS_VolumeTool aTool;
3629     if(aTool.Set(elem)) {
3630       aResult->length(3);
3631       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
3632         aResult->length(0);
3633     }
3634   }
3635   else {
3636     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
3637     int nbn = 0;
3638     double x=0., y=0., z=0.;
3639     for(; anIt->more(); ) {
3640       nbn++;
3641       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
3642       x += aNode->X();
3643       y += aNode->Y();
3644       z += aNode->Z();
3645     }
3646     if(nbn>0) {
3647       // add coordinates
3648       aResult->length(3);
3649       aResult[0] = x/nbn;
3650       aResult[1] = y/nbn;
3651       aResult[2] = z/nbn;
3652     }
3653   }
3654
3655   return aResult._retn();
3656 }
3657
3658
3659 //=============================================================================
3660 /*!
3661  * Create and publish group servants if any groups were imported or created anyhow
3662  */
3663 //=============================================================================
3664
3665 void SMESH_Mesh_i::CreateGroupServants() 
3666 {
3667   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
3668
3669   set<int> addedIDs;
3670   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
3671   while ( groupIt->more() )
3672   {
3673     ::SMESH_Group* group = groupIt->next();
3674     int            anId = group->GetGroupDS()->GetID();
3675
3676     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
3677     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
3678       continue;
3679     addedIDs.insert( anId );
3680
3681     SMESH_GroupBase_i* aGroupImpl;
3682     TopoDS_Shape       shape;
3683     if ( SMESHDS_GroupOnGeom* groupOnGeom =
3684          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
3685     {
3686       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
3687       shape      = groupOnGeom->GetShape();
3688     }
3689     else {
3690       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3691     }
3692
3693     // To ensure correct mapping of servant and correct reference counting in GenericObj_i
3694     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
3695     aGroupImpl->Register();
3696
3697     SMESH::SMESH_GroupBase_var groupVar =
3698       SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
3699     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
3700
3701     // register CORBA object for persistence
3702     int nextId = _gen_i->RegisterObject( groupVar );
3703     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
3704
3705     // publishing the groups in the study
3706     if ( !aStudy->_is_nil() ) {
3707       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
3708       _gen_i->PublishGroup( aStudy, _this(), groupVar, shapeVar, groupVar->GetName());
3709     }
3710   }
3711   if ( !addedIDs.empty() )
3712   {
3713     // python dump
3714     set<int>::iterator id = addedIDs.begin();
3715     for ( ; id != addedIDs.end(); ++id )
3716     {
3717       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(*id);
3718       int i = std::distance( _mapGroups.begin(), it );
3719       TPythonDump() << it->second << " = " << _this() << ".GetGroups()[ "<< i << " ]";
3720     }
3721   }
3722 }
3723
3724 //=============================================================================
3725 /*!
3726  * \brief Return groups cantained in _mapGroups by their IDs
3727  */
3728 //=============================================================================
3729
3730 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
3731 {
3732   int nbGroups = groupIDs.size();
3733   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
3734   aList->length( nbGroups );
3735
3736   list<int>::const_iterator ids = groupIDs.begin();
3737   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
3738   {
3739     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
3740     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
3741       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
3742   }
3743   aList->length( nbGroups );
3744   return aList._retn();
3745 }
3746
3747 //=============================================================================
3748 /*!
3749  * \brief Return information about imported file
3750  */
3751 //=============================================================================
3752
3753 SALOME_MED::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
3754 {
3755   SALOME_MED::MedFileInfo_var res( myFileInfo );
3756   if ( !res.operator->() ) {
3757     res = new SALOME_MED::MedFileInfo;
3758     res->fileName = "";
3759     res->fileSize = res->major = res->minor = res->release = -1;
3760   }
3761   return res._retn();
3762 }
3763
3764 //=============================================================================
3765 /*!
3766  * \brief Check and correct names of mesh groups
3767  */
3768 //=============================================================================
3769
3770 void SMESH_Mesh_i::checkGroupNames()
3771 {
3772   int nbGrp = NbGroups();
3773   if ( !nbGrp )
3774     return;
3775
3776   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
3777   if ( aStudy->_is_nil() )
3778     return; // nothing to do
3779   
3780   SMESH::ListOfGroups* grpList = 0;
3781   // avoid dump of "GetGroups"
3782   {
3783     // store python dump into a local variable inside local scope
3784     SMESH::TPythonDump pDump; // do not delete this line of code
3785     grpList = GetGroups();
3786   }
3787
3788   for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
3789     SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
3790     if ( !aGrp )
3791       continue;
3792     SALOMEDS::SObject_var aGrpSO = _gen_i->ObjectToSObject( aStudy, aGrp );
3793     if ( aGrpSO->_is_nil() )
3794       continue;
3795     // correct name of the mesh group if necessary
3796     const char* guiName = aGrpSO->GetName();
3797     if ( strcmp(guiName, aGrp->GetName()) )
3798       aGrp->SetName( guiName );
3799   }
3800 }
3801
3802 //=============================================================================
3803 /*!
3804  * \brief Sets list of notebook variables used for Mesh operations separated by ":" symbol
3805  */
3806 //=============================================================================
3807 void SMESH_Mesh_i::SetParameters(const char* theParameters)
3808 {
3809   SMESH_Gen_i::GetSMESHGen()->UpdateParameters(SMESH::SMESH_Mesh::_narrow(_this()),
3810                                                CORBA::string_dup(theParameters));
3811 }
3812
3813 //=============================================================================
3814 /*!
3815  * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
3816  */
3817 //=============================================================================
3818 char* SMESH_Mesh_i::GetParameters()
3819 {
3820   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
3821   return CORBA::string_dup(gen->GetParameters(SMESH::SMESH_Mesh::_narrow(_this())));
3822 }
3823
3824 //=============================================================================
3825 /*!
3826  * \brief Returns list of notebook variables used for last Mesh operation
3827  */
3828 //=============================================================================
3829 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
3830 {
3831   SMESH::string_array_var aResult = new SMESH::string_array();
3832   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
3833   if(gen) {
3834     char *aParameters = GetParameters();
3835     SALOMEDS::Study_ptr aStudy = gen->GetCurrentStudy();
3836     if(!aStudy->_is_nil()) {
3837       SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters); 
3838       if(aSections->length() > 0) {
3839         SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1];
3840         aResult->length(aVars.length());
3841         for(int i = 0;i < aVars.length();i++)
3842           aResult[i] = CORBA::string_dup( aVars[i]);
3843       }
3844     }
3845   }
3846   return aResult._retn();
3847 }
3848
3849 //=======================================================================
3850 //function : GetTypes
3851 //purpose  : Returns types of elements it contains
3852 //=======================================================================
3853
3854 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
3855 {
3856   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
3857
3858   types->length( 4 );
3859   int nbTypes = 0;
3860   if (_impl->NbEdges())
3861     types[nbTypes++] = SMESH::EDGE;
3862   if (_impl->NbFaces())
3863     types[nbTypes++] = SMESH::FACE;
3864   if (_impl->NbVolumes())
3865     types[nbTypes++] = SMESH::VOLUME;
3866   if (_impl->Nb0DElements())
3867     types[nbTypes++] = SMESH::ELEM0D;
3868   types->length( nbTypes );
3869
3870   return types._retn();
3871 }
3872
3873 //=======================================================================
3874 //function : GetMesh
3875 //purpose  : Returns self
3876 //=======================================================================
3877
3878 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
3879 {
3880   return SMESH::SMESH_Mesh::_duplicate( _this() );
3881 }
3882
3883 //=============================================================================
3884 /*!
3885  * \brief Returns statistic of mesh elements
3886  */
3887 //=============================================================================
3888 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
3889 {
3890   SMESH::long_array_var aRes = new SMESH::long_array();
3891   aRes->length(SMESH::Entity_Last);
3892   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
3893     aRes[i] = 0;
3894   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
3895   if (!aMeshDS)
3896     return aRes._retn();
3897   const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
3898   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
3899     aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
3900   return aRes._retn();
3901 }
3902
3903 //=============================================================================
3904 /*!
3905  * \brief Collect statistic of mesh elements given by iterator
3906  */
3907 //=============================================================================
3908 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
3909                                    SMESH::long_array&         theInfo)
3910 {
3911   if (!theItr) return;
3912   while (theItr->more())
3913     theInfo[ theItr->next()->GetEntityType() ]++;
3914 }
3915
3916 //=============================================================================
3917 /*!
3918  * \brief mapping of mesh dimension into shape type
3919  */
3920 //=============================================================================
3921 static TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
3922 {
3923   TopAbs_ShapeEnum aType = TopAbs_SOLID;
3924   switch ( theDim ) {
3925   case 0: aType = TopAbs_VERTEX; break;
3926   case 1: aType = TopAbs_EDGE; break;
3927   case 2: aType = TopAbs_FACE; break;
3928   case 3:
3929   default:aType = TopAbs_SOLID; break;
3930   }
3931   return aType;
3932 }
3933
3934 //=============================================================================
3935 /*!
3936  * \brief Internal structure used to find concurent submeshes
3937  *
3938  * It represents a pair < submesh, concurent dimension >, where
3939  * 'concurrent dimension' is dimension of shape where the submesh can concurent
3940  *  with another submesh. In other words, it is dimension of a hypothesis assigned
3941  *  to submesh.
3942  */
3943 //=============================================================================
3944
3945 class SMESH_DimHyp
3946 {
3947  public:
3948   //! fileds
3949   int _dim;    //!< a dimension the algo can build (concurrent dimension)
3950   int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
3951   TopTools_MapOfShape _shapeMap;
3952   SMESH_subMesh*      _subMesh;
3953   list<const SMESHDS_Hypothesis*> _hypothesises; //!< algo is first, then its parameters
3954
3955   //! Constructors
3956   SMESH_DimHyp(const SMESH_subMesh*  theSubMesh,
3957                const int             theDim,
3958                const TopoDS_Shape&   theShape)
3959   {
3960     _subMesh = (SMESH_subMesh*)theSubMesh;
3961     SetShape( theDim, theShape );
3962   }
3963
3964   //! set shape
3965   void SetShape(const int theDim,
3966                 const TopoDS_Shape& theShape)
3967   {
3968     _dim = theDim;
3969     _ownDim = (int)SMESH_Gen::GetShapeDim(theShape);
3970     if (_dim >= _ownDim)
3971       _shapeMap.Add( theShape );
3972     else {
3973       TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
3974       for( ; anExp.More(); anExp.Next() )
3975         _shapeMap.Add( anExp.Current() );
3976     }
3977   }
3978
3979   //! Check sharing of sub shapes
3980   static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
3981                                const TopTools_MapOfShape& theToFind,
3982                                const TopAbs_ShapeEnum     theType)
3983   {
3984     bool isShared = false;
3985     TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
3986     for (; !isShared && anItr.More(); anItr.Next() ) {
3987       const TopoDS_Shape aSubSh = anItr.Key();
3988       // check for case when concurrent dimensions are same
3989       isShared = theToFind.Contains( aSubSh );
3990       // check for subshape with concurrent dimension
3991       TopExp_Explorer anExp( aSubSh, theType );
3992       for ( ; !isShared && anExp.More(); anExp.Next() )
3993         isShared = theToFind.Contains( anExp.Current() );
3994     }
3995     return isShared;
3996   }
3997   
3998   //! check algorithms
3999   static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
4000                         const SMESHDS_Hypothesis* theA2)
4001   {
4002     if ( theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
4003          theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
4004       return false; // one of the hypothesis is not algorithm
4005     // check algorithm names (should be equal)
4006     return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
4007   }
4008
4009   
4010   //! Check if subshape hypotheses are concurrent
4011   bool IsConcurrent(const SMESH_DimHyp* theOther) const
4012   {
4013     if ( _subMesh == theOther->_subMesh )
4014       return false; // same subshape - should not be
4015
4016     // if ( <own dim of either of submeshes> == <concurrent dim> &&
4017     //      any of the two submeshes is not on COMPOUND shape )
4018     //  -> no concurrency
4019     bool meIsCompound = (_subMesh->GetSubMeshDS() && _subMesh->GetSubMeshDS()->IsComplexSubmesh());
4020     bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() && theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
4021     if ( (_ownDim == _dim  || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
4022       return false;
4023
4024 //     bool checkSubShape = ( _dim >= theOther->_dim )
4025 //       ? isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(theOther->_dim) )
4026 //       : isShareSubShapes( theOther->_shapeMap, _shapeMap, shapeTypeByDim(_dim) ) ;
4027     bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
4028     if ( !checkSubShape )
4029         return false;
4030
4031     // check algorithms to be same
4032     if (!checkAlgo( _hypothesises.front(), theOther->_hypothesises.front() ))
4033       return true; // different algorithms
4034     
4035     // check hypothesises for concurrence (skip first as algorithm)
4036     int nbSame = 0;
4037     // pointers should be same, becase it is referenes from mesh hypothesis partition
4038     list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypothesises.begin();
4039     list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypothesises.end();
4040     for ( hypIt++ /*skip first as algo*/; hypIt != _hypothesises.end(); hypIt++ )
4041       if ( find( theOther->_hypothesises.begin(), otheEndIt, *hypIt ) != otheEndIt )
4042         nbSame++;
4043     // the submeshes are concurrent if their algorithms has different parameters
4044     return nbSame != theOther->_hypothesises.size() - 1;
4045   }
4046   
4047 }; // end of SMESH_DimHyp
4048
4049 typedef list<SMESH_DimHyp*> TDimHypList;
4050
4051 static void addDimHypInstance(const int               theDim, 
4052                               const TopoDS_Shape&     theShape,
4053                               const SMESH_Algo*       theAlgo,
4054                               const SMESH_subMesh*    theSubMesh,
4055                               const list <const SMESHDS_Hypothesis*>& theHypList,
4056                               TDimHypList*            theDimHypListArr )
4057 {
4058   TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
4059   if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) {
4060     SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
4061     listOfdimHyp.push_back( dimHyp );
4062   }
4063   
4064   SMESH_DimHyp* dimHyp = listOfdimHyp.back();
4065   dimHyp->_hypothesises.push_front(theAlgo);
4066   list <const SMESHDS_Hypothesis*>::const_iterator hypIt = theHypList.begin();
4067   for( ; hypIt != theHypList.end(); hypIt++ )
4068     dimHyp->_hypothesises.push_back( *hypIt );
4069 }
4070
4071 static void findConcurrents(const SMESH_DimHyp* theDimHyp,
4072                             const TDimHypList&  theListOfDimHyp,
4073                             TListOfInt&         theListOfConcurr )
4074 {
4075   TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
4076   for ( ; rIt != theListOfDimHyp.rend(); rIt++ ) {
4077     const SMESH_DimHyp* curDimHyp = *rIt;
4078     if ( curDimHyp == theDimHyp )
4079       break; // meet own dimHyp pointer in same dimension
4080     else if ( theDimHyp->IsConcurrent( curDimHyp ) )
4081       if ( find( theListOfConcurr.begin(),
4082                  theListOfConcurr.end(),
4083                  curDimHyp->_subMesh->GetId() ) == theListOfConcurr.end() )
4084         theListOfConcurr.push_back( curDimHyp->_subMesh->GetId() );
4085   }
4086 }
4087
4088 static void unionLists(TListOfInt&       theListOfId,
4089                        TListOfListOfInt& theListOfListOfId,
4090                        const int         theIndx )
4091 {
4092   TListOfListOfInt::iterator it = theListOfListOfId.begin();
4093   for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) {
4094     if ( i < theIndx )
4095       continue; //skip already treated lists
4096     // check if other list has any same submesh object
4097     TListOfInt& otherListOfId = *it;
4098     if ( find_first_of( theListOfId.begin(), theListOfId.end(),
4099                         otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
4100       continue;
4101          
4102     // union two lists (from source into target)
4103     TListOfInt::iterator it2 = otherListOfId.begin();
4104     for ( ; it2 != otherListOfId.end(); it2++ ) {
4105       if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
4106         theListOfId.push_back(*it2);
4107     }
4108     // clear source list
4109     otherListOfId.clear();
4110   }
4111 }
4112
4113 //! free memory allocated for dimension-hypothesis objects
4114 static void removeDimHyps( TDimHypList* theArrOfList )
4115 {
4116   for (int i = 0; i < 4; i++ ) {
4117     TDimHypList& listOfdimHyp = theArrOfList[i];
4118     TDimHypList::const_iterator it = listOfdimHyp.begin();
4119     for ( ; it != listOfdimHyp.end(); it++ )
4120       delete (*it);
4121   }
4122 }
4123
4124 //=============================================================================
4125 /*!
4126  * \brief Return submesh objects list in meshing order
4127  */
4128 //=============================================================================
4129
4130 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
4131 {
4132   SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
4133
4134   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4135   if ( !aMeshDS )
4136     return aResult._retn();
4137   
4138   ::SMESH_Mesh& mesh = GetImpl();
4139   TListOfListOfInt anOrder = mesh.GetMeshOrder(); // is there already defined order?
4140   if ( !anOrder.size() ) {
4141
4142     // collect submeshes detecting concurrent algorithms and hypothesises
4143     TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
4144     
4145     map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
4146     for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) {
4147       ::SMESH_subMesh* sm = (*i_sm).second;
4148       // shape of submesh
4149       const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
4150       
4151       // list of assigned hypothesises
4152       const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
4153       // Find out dimensions where the submesh can be concurrent.
4154       // We define the dimensions by algo of each of hypotheses in hypList
4155       list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
4156       for( ; hypIt != hypList.end(); hypIt++ ) {
4157         SMESH_Algo* anAlgo = 0;
4158         const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
4159         if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
4160           // hyp it-self is algo
4161           anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
4162         else {
4163           // try to find algorithm with help of subshapes
4164           TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
4165           for ( ; !anAlgo && anExp.More(); anExp.Next() )
4166             anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
4167         }
4168         if (!anAlgo)
4169           continue; // no assigned algorithm to current submesh
4170
4171         int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
4172         // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDescretBoundary())
4173
4174         // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
4175         for ( int j = anAlgo->NeedDescretBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
4176           addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
4177       }
4178     } // end iterations on submesh
4179     
4180     // iterate on created dimension-hypotheses and check for concurrents
4181     for ( int i = 0; i < 4; i++ ) {
4182       const list<SMESH_DimHyp*>& listOfDimHyp = dimHypListArr[i];
4183       // check for concurrents in own and other dimensions (step-by-step)
4184       TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
4185       for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) {
4186         const SMESH_DimHyp* dimHyp = *dhIt;
4187         TListOfInt listOfConcurr;
4188         // looking for concurrents and collect into own list
4189         for ( int j = i; j < 4; j++ )
4190           findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr );
4191         // check if any concurrents found
4192         if ( listOfConcurr.size() > 0 ) {
4193           // add own submesh to list of concurrent
4194           listOfConcurr.push_front( dimHyp->_subMesh->GetId() );
4195           anOrder.push_back( listOfConcurr );
4196         }
4197       }
4198     }
4199     
4200     removeDimHyps(dimHypListArr);
4201     
4202     // now, minimise the number of concurrent groups
4203     // Here we assume that lists of submhes can has same submesh
4204     // in case of multi-dimension algorithms, as result
4205     //  list with common submesh have to be union into one list
4206     int listIndx = 0;
4207     TListOfListOfInt::iterator listIt = anOrder.begin();
4208     for(; listIt != anOrder.end(); listIt++, listIndx++ )
4209       unionLists( *listIt,  anOrder, listIndx + 1 );
4210   }
4211   // convert submesh ids into interface instances
4212   //  and dump command into python
4213   convertMeshOrder( anOrder, aResult, true );
4214
4215   return aResult._retn();
4216 }
4217
4218 //=============================================================================
4219 /*!
4220  * \brief find common submeshes with given submesh
4221  * \param theSubMeshList list of already collected submesh to check
4222  * \param theSubMesh given submesh to intersect with other
4223  * \param theCommonSubMeshes collected common submeshes
4224  */
4225 //=============================================================================
4226
4227 static void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
4228                                const SMESH_subMesh*        theSubMesh,
4229                                set<const SMESH_subMesh*>&  theCommon )
4230 {
4231   if ( !theSubMesh )
4232     return;
4233   list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
4234   for ( ; it != theSubMeshList.end(); it++ )
4235     theSubMesh->FindIntersection( *it, theCommon );
4236   theSubMeshList.push_back( theSubMesh );
4237   //theCommon.insert( theSubMesh );
4238 }
4239
4240 //=============================================================================
4241 /*!
4242  * \brief Set submesh object order
4243  * \param theSubMeshArray submesh array order
4244  */
4245 //=============================================================================
4246
4247 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
4248 {
4249   bool res = false;
4250   ::SMESH_Mesh& mesh = GetImpl();
4251
4252   TPythonDump aPythonDump; // prevent dump of called methods
4253   aPythonDump << "isDone = " << _this() << ".SetMeshOrder( [ ";
4254
4255   TListOfListOfInt subMeshOrder;
4256   for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
4257   {
4258     const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
4259     TListOfInt subMeshIds;
4260     aPythonDump << "[ ";
4261     // Collect subMeshes which should be clear
4262     //  do it list-by-list, because modification of submesh order
4263     //  take effect between concurrent submeshes only
4264     set<const SMESH_subMesh*> subMeshToClear;
4265     list<const SMESH_subMesh*> subMeshList;
4266     for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
4267     {
4268       const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
4269       if ( j > 0 )
4270         aPythonDump << ", ";
4271       aPythonDump << subMesh;
4272       subMeshIds.push_back( subMesh->GetId() );
4273       // detect common parts of submeshes
4274       if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
4275         findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
4276     }
4277     aPythonDump << " ]";
4278     subMeshOrder.push_back( subMeshIds );
4279
4280     // clear collected submeshes
4281     set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
4282     for ( ; clrIt != subMeshToClear.end(); clrIt++ ) {
4283       SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt;
4284         if ( sm )
4285           sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
4286         // ClearSubMesh( *clrIt );
4287       }
4288   }
4289   aPythonDump << " ])";
4290
4291   mesh.SetMeshOrder( subMeshOrder );
4292   res = true;
4293   
4294   return res;
4295 }
4296
4297 //=============================================================================
4298 /*!
4299  * \brief Convert submesh ids into submesh interfaces
4300  */
4301 //=============================================================================
4302
4303 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt&     theIdsOrder,
4304                                      SMESH::submesh_array_array& theResOrder,
4305                                      const bool                  theIsDump)
4306 {
4307   int nbSet = theIdsOrder.size();
4308   TPythonDump aPythonDump; // prevent dump of called methods
4309   if ( theIsDump )
4310     aPythonDump << "[ ";
4311   theResOrder.length(nbSet);
4312   TListOfListOfInt::const_iterator it = theIdsOrder.begin();
4313   int listIndx = 0;
4314   for( ; it != theIdsOrder.end(); it++ ) {
4315     // translate submesh identificators into submesh objects
4316     //  takeing into account real number of concurrent lists
4317     const TListOfInt& aSubOrder = (*it);
4318     if (!aSubOrder.size())
4319       continue;
4320     if ( theIsDump )
4321       aPythonDump << "[ ";
4322     // convert shape indeces into interfaces
4323     SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
4324     aResSubSet->length(aSubOrder.size());
4325     TListOfInt::const_iterator subIt = aSubOrder.begin();
4326     for( int j = 0; subIt != aSubOrder.end(); subIt++ ) {
4327       if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
4328         continue;
4329       SMESH::SMESH_subMesh_var subMesh =
4330         SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
4331       if ( theIsDump ) {
4332         if ( j > 0 )
4333           aPythonDump << ", ";
4334         aPythonDump << subMesh;
4335       }
4336       aResSubSet[ j++ ] = subMesh;
4337     }
4338     if ( theIsDump )
4339       aPythonDump << " ]";
4340     theResOrder[ listIndx++ ] = aResSubSet;
4341   }
4342   // correct number of lists
4343   theResOrder.length( listIndx );
4344
4345   if ( theIsDump ) {
4346     // finilise python dump
4347     aPythonDump << " ]";
4348     aPythonDump << " = " << _this() << ".GetMeshOrder()";
4349   }
4350 }
4351
4352 //================================================================================
4353 //
4354 // Implementation of SMESH_MeshPartDS
4355 //
4356 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
4357   SMESHDS_Mesh( /*theMeshID=*/-1, /*theIsEmbeddedMode=*/true)
4358 {
4359   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
4360   SMESH_Mesh_i*       mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4361
4362   _meshDS = mesh_i->GetImpl().GetMeshDS();
4363
4364   if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
4365   {
4366     // <meshPart> is the whole mesh
4367     myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
4368   }
4369   else
4370   {
4371     TMeshInfo tmpInfo;
4372     SMESH::long_array_var           anIDs = meshPart->GetIDs();
4373     SMESH::array_of_ElementType_var types = meshPart->GetTypes();
4374     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
4375     {
4376       for (int i=0; i < anIDs->length(); i++)
4377         if ( const SMDS_MeshNode * n = _meshDS->FindNode(anIDs[i]))
4378           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
4379             tmpInfo.Add( n );
4380     }
4381     else
4382     {
4383       for (int i=0; i < anIDs->length(); i++)
4384         if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
4385           if ( _elements[ e->GetType() ].insert( e ).second )
4386           {
4387             tmpInfo.Add( e );
4388             SMDS_ElemIteratorPtr nIt = e->nodesIterator();
4389             while ( nIt->more() )
4390             {
4391               const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
4392               if ( _elements[ SMDSAbs_Node ].insert( n ).second )
4393                 tmpInfo.Add( n );
4394             }
4395           }
4396     }
4397     myInfo = tmpInfo;
4398
4399     _meshDS = 0; // to enforce iteration on _elements and _nodes
4400   }
4401 }
4402 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
4403 {
4404   typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4405   return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
4406     ( new TIter( _elements[type].begin(), _elements[type].end() ));
4407 }
4408 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType)                       \
4409   iterType SMESH_MeshPartDS::methName( bool idInceasingOrder) const                 \
4410   {                                                                                 \
4411     typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
4412     return _meshDS ? _meshDS->methName(idInceasingOrder) : iterType                 \
4413       ( new TIter( _elements[elemType].begin(), _elements[elemType].end() ));       \
4414   }
4415 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
4416 _GET_ITER_DEFINE( SMDS_0DElementIteratorPtr, elements0dIterator, SMDS_Mesh0DElement, SMDSAbs_0DElement)
4417 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
4418 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
4419 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
4420 #undef _GET_ITER_DEFINE
4421 //
4422 // END Implementation of SMESH_MeshPartDS
4423 //
4424 //================================================================================