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