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