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