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