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