Salome HOME
2ebee967b349dd51be3955a617565978dd49d94c
[modules/smesh.git] / src / SMESH_I / SMESH_Mesh_i.cxx
1 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //
23 //
24 //  File   : SMESH_Mesh_i.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SMESH
27 //  $Header$
28
29 #include "SMESH_Mesh_i.hxx"
30
31 #include "SMESH_Filter_i.hxx"
32 #include "SMESH_Gen_i.hxx"
33 #include "SMESH_Group_i.hxx"
34 #include "SMESH_MEDMesh_i.hxx"
35 #include "SMESH_MeshEditor_i.hxx"
36 #include "SMESH_PythonDump.hxx"
37 #include "SMESH_subMesh_i.hxx"
38
39 #include "DriverMED_R_SMESHDS_Mesh.h"
40 #include "SMDS_VolumeTool.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
48 #include "OpUtil.hxx"
49 #include "SALOME_NamingService.hxx"
50 #include "Utils_CorbaException.hxx"
51 #include "Utils_ExceptHandlers.hxx"
52 #include "Utils_SINGLETON.hxx"
53 #include "utilities.h"
54
55 // OCCT Includes
56 #include <BRep_Builder.hxx>
57 #include <OSD_Path.hxx>
58 #include <OSD_File.hxx>
59 #include <OSD_Directory.hxx>
60 #include <OSD_Protection.hxx>
61 #include <TColStd_MapOfInteger.hxx>
62 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
63 #include <TColStd_SequenceOfInteger.hxx>
64 #include <TCollection_AsciiString.hxx>
65 #include <TopoDS_Compound.hxx>
66
67 // STL Includes
68 #include <string>
69 #include <iostream>
70 #include <sstream>
71
72 #ifdef _DEBUG_
73 static int MYDEBUG = 0;
74 #else
75 static int MYDEBUG = 0;
76 #endif
77
78 using namespace std;
79 using SMESH::TPythonDump;
80
81 int SMESH_Mesh_i::myIdGenerator = 0;
82
83
84
85 //=============================================================================
86 /*!
87  *  Constructor
88  */
89 //=============================================================================
90
91 SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
92                             SMESH_Gen_i*            gen_i,
93                             CORBA::Long studyId )
94 : SALOME::GenericObj_i( thePOA )
95 {
96   MESSAGE("SMESH_Mesh_i");
97   _impl = NULL;
98   _gen_i = gen_i;
99   _id = myIdGenerator++;
100   _studyId = studyId;
101 }
102
103 //=============================================================================
104 /*!
105  *  Destructor
106  */
107 //=============================================================================
108
109 SMESH_Mesh_i::~SMESH_Mesh_i()
110 {
111   INFOS("~SMESH_Mesh_i");
112   map<int, SMESH::SMESH_GroupBase_ptr>::iterator it;
113   for ( it = _mapGroups.begin(); it != _mapGroups.end(); it++ ) {
114     SMESH_GroupBase_i* aGroup = dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( it->second ).in() );
115     if ( aGroup ) {
116
117       // this method is colled from destructor of group (PAL6331)
118       //_impl->RemoveGroup( aGroup->GetLocalID() );
119
120       aGroup->Destroy();
121     }
122   }
123   _mapGroups.clear();
124 }
125
126 //=============================================================================
127 /*!
128  *  SetShape
129  *
130  *  Associates <this> mesh with <theShape> and puts a reference
131  *  to <theShape> into the current study;
132  *  the previous shape is substituted by the new one.
133  */
134 //=============================================================================
135
136 void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
137     throw (SALOME::SALOME_Exception)
138 {
139   Unexpect aCatch(SALOME_SalomeException);
140   try {
141     _impl->ShapeToMesh( _gen_i->GeomObjectToShape( theShapeObject ));
142   }
143   catch(SALOME_Exception & S_ex) {
144     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
145   }
146 }
147
148 //================================================================================
149 /*!
150  * \brief return true if mesh has a shape to build a shape on
151  */
152 //================================================================================
153
154 CORBA::Boolean SMESH_Mesh_i::HasShapeToMesh()
155   throw (SALOME::SALOME_Exception)
156 {
157   Unexpect aCatch(SALOME_SalomeException);
158   bool res = false;
159   try {
160     res = _impl->HasShapeToMesh();
161   }
162   catch(SALOME_Exception & S_ex) {
163     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
164   }
165   return res;
166 }
167
168 //=======================================================================
169 //function : GetShapeToMesh
170 //purpose  :
171 //=======================================================================
172
173 GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
174     throw (SALOME::SALOME_Exception)
175 {
176   Unexpect aCatch(SALOME_SalomeException);
177   GEOM::GEOM_Object_var aShapeObj;
178   try {
179     TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
180     if ( !S.IsNull() )
181       aShapeObj = _gen_i->ShapeToGeomObject( S );
182   }
183   catch(SALOME_Exception & S_ex) {
184     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
185   }
186   return aShapeObj._retn();
187 }
188
189 //=============================================================================
190 /*!
191  *
192  */
193 //=============================================================================
194
195 static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
196 {
197   SMESH::DriverMED_ReadStatus res;
198   switch (theStatus)
199   {
200   case DriverMED_R_SMESHDS_Mesh::DRS_OK:
201     res = SMESH::DRS_OK; break;
202   case DriverMED_R_SMESHDS_Mesh::DRS_EMPTY:
203     res = SMESH::DRS_EMPTY; break;
204   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_RENUMBER:
205     res = SMESH::DRS_WARN_RENUMBER; break;
206   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
207     res = SMESH::DRS_WARN_SKIP_ELEM; break;
208   case DriverMED_R_SMESHDS_Mesh::DRS_FAIL:
209   default:
210     res = SMESH::DRS_FAIL; break;
211   }
212   return res;
213 }
214
215 //=============================================================================
216 /*!
217  *  ImportMEDFile
218  *
219  *  Imports mesh data from MED file
220  */
221 //=============================================================================
222
223 SMESH::DriverMED_ReadStatus
224 SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
225   throw ( SALOME::SALOME_Exception )
226 {
227   Unexpect aCatch(SALOME_SalomeException);
228   int status;
229   try {
230     status = _impl->MEDToMesh( theFileName, theMeshName );
231   }
232   catch( SALOME_Exception& S_ex ) {
233     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
234   }
235   catch ( ... ) {
236     THROW_SALOME_CORBA_EXCEPTION("ImportMEDFile(): unknown exception", SALOME::BAD_PARAM);
237   }
238
239   CreateGroupServants();
240
241   return ConvertDriverMEDReadStatus(status);
242 }
243
244 //=============================================================================
245 /*!
246  *  ImportUNVFile
247  *
248  *  Imports mesh data from MED file
249  */
250 //=============================================================================
251
252 int SMESH_Mesh_i::ImportUNVFile( const char* theFileName )
253   throw ( SALOME::SALOME_Exception )
254 {
255   // Read mesh with name = <theMeshName> into SMESH_Mesh
256   _impl->UNVToMesh( theFileName );
257
258   CreateGroupServants();
259
260   return 1;
261 }
262
263 //=============================================================================
264 /*!
265  *  ImportSTLFile
266  *
267  *  Imports mesh data from STL file
268  */
269 //=============================================================================
270 int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
271   throw ( SALOME::SALOME_Exception )
272 {
273   // Read mesh with name = <theMeshName> into SMESH_Mesh
274   _impl->STLToMesh( theFileName );
275
276   return 1;
277 }
278
279 //=============================================================================
280 /*!
281  *  importMEDFile
282  *
283  *  Imports mesh data from MED file
284  */
285 //=============================================================================
286
287 // int SMESH_Mesh_i::importMEDFile( const char* theFileName, const char* theMeshName )
288 // {
289 //   // Read mesh with name = <theMeshName> and all its groups into SMESH_Mesh
290 //   int status = _impl->MEDToMesh( theFileName, theMeshName );
291 //   CreateGroupServants();
292
293 //   return status;
294 // }
295
296 //=============================================================================
297 /*!
298  *
299  */
300 //=============================================================================
301
302 #define RETURNCASE(hyp_stat) case SMESH_Hypothesis::hyp_stat: return SMESH::hyp_stat;
303
304 SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
305                          (SMESH_Hypothesis::Hypothesis_Status theStatus)
306 {
307   switch (theStatus) {
308   RETURNCASE( HYP_OK            );
309   RETURNCASE( HYP_MISSING       );
310   RETURNCASE( HYP_CONCURENT     );
311   RETURNCASE( HYP_BAD_PARAMETER );
312   RETURNCASE( HYP_HIDDEN_ALGO   );
313   RETURNCASE( HYP_HIDING_ALGO   );
314   RETURNCASE( HYP_UNKNOWN_FATAL );
315   RETURNCASE( HYP_INCOMPATIBLE  );
316   RETURNCASE( HYP_NOTCONFORM    );
317   RETURNCASE( HYP_ALREADY_EXIST );
318   RETURNCASE( HYP_BAD_DIM       );
319   RETURNCASE( HYP_BAD_SUBSHAPE  );
320   RETURNCASE( HYP_BAD_GEOMETRY  );
321   default:;
322   }
323   return SMESH::HYP_UNKNOWN_FATAL;
324 }
325
326 //=============================================================================
327 /*!
328  *  AddHypothesis
329  *
330  *  calls internal addHypothesis() and then adds a reference to <anHyp> under
331  *  the SObject actually having a reference to <aSubShape>.
332  *  NB: For this method to work, it is necessary to add a reference to sub-shape first.
333  */
334 //=============================================================================
335
336 SMESH::Hypothesis_Status SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
337                                                      SMESH::SMESH_Hypothesis_ptr anHyp)
338   throw(SALOME::SALOME_Exception)
339 {
340   Unexpect aCatch(SALOME_SalomeException);
341   SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShapeObject, anHyp );
342
343   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
344     _gen_i->AddHypothesisToShape(_gen_i->GetCurrentStudy(), _this(),
345                                  aSubShapeObject, anHyp );
346
347   if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
348
349   // Update Python script
350   if(_impl->HasShapeToMesh()) {
351     TPythonDump() << "status = " << _this() << ".AddHypothesis( "
352                   << aSubShapeObject << ", " << anHyp << " )";
353   }
354   else {
355     TPythonDump() << "status = " << _this() << ".AddHypothesis( "<< anHyp << " )";
356   }
357   
358   return ConvertHypothesisStatus(status);
359 }
360
361 //=============================================================================
362 /*!
363  *
364  */
365 //=============================================================================
366
367 SMESH_Hypothesis::Hypothesis_Status
368   SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
369                               SMESH::SMESH_Hypothesis_ptr anHyp)
370 {
371   if(MYDEBUG) MESSAGE("addHypothesis");
372
373   if (CORBA::is_nil(aSubShapeObject) && HasShapeToMesh())
374     THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
375                                  SALOME::BAD_PARAM);
376
377   SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp);
378   if (CORBA::is_nil(myHyp))
379     THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",
380                                  SALOME::BAD_PARAM);
381
382   SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
383   try
384   {
385     TopoDS_Shape myLocSubShape;
386     //use PseudoShape in case if mesh has no shape
387     if(HasShapeToMesh())
388       myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject);
389     else              
390       myLocSubShape = _impl->GetShapeToMesh();
391     
392     int hypId = myHyp->GetId();
393     status = _impl->AddHypothesis(myLocSubShape, hypId);
394     if ( !SMESH_Hypothesis::IsStatusFatal(status) ) {
395       _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( myHyp );
396       // assure there is a corresponding submesh
397       if ( !_impl->IsMainShape( myLocSubShape )) {
398         int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
399         if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
400           createSubMesh( aSubShapeObject );
401       }
402     }
403   }
404   catch(SALOME_Exception & S_ex)
405   {
406     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
407   }
408   return status;
409 }
410
411 //=============================================================================
412 /*!
413  *
414  */
415 //=============================================================================
416
417 SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
418                                                         SMESH::SMESH_Hypothesis_ptr anHyp)
419      throw(SALOME::SALOME_Exception)
420 {
421   Unexpect aCatch(SALOME_SalomeException);
422   SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShapeObject, anHyp );
423
424   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
425     _gen_i->RemoveHypothesisFromShape(_gen_i->GetCurrentStudy(), _this(),
426                                       aSubShapeObject, anHyp );
427
428   // Update Python script
429     // Update Python script
430   if(_impl->HasShapeToMesh()) {
431   TPythonDump() << "status = " << _this() << ".RemoveHypothesis( "
432                 << aSubShapeObject << ", " << anHyp << " )";
433   }
434   else {
435     TPythonDump() << "status = " << _this() << ".RemoveHypothesis( "
436                   << anHyp << " )";
437   }
438
439   return ConvertHypothesisStatus(status);
440 }
441
442 //=============================================================================
443 /*!
444  *
445  */
446 //=============================================================================
447
448 SMESH_Hypothesis::Hypothesis_Status SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
449                                  SMESH::SMESH_Hypothesis_ptr anHyp)
450 {
451         if(MYDEBUG) MESSAGE("removeHypothesis()");
452         // **** proposer liste de subShape (selection multiple)
453
454         if (CORBA::is_nil(aSubShapeObject) && HasShapeToMesh())
455                 THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
456                         SALOME::BAD_PARAM);
457
458         SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp);
459         if (CORBA::is_nil(myHyp))
460           THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",
461                         SALOME::BAD_PARAM);
462
463         SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
464         try
465         {
466                 TopoDS_Shape myLocSubShape;
467                 //use PseudoShape in case if mesh has no shape
468                 if(HasShapeToMesh())
469                   myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject);
470                 else
471                   myLocSubShape = _impl->GetShapeToMesh();
472                 
473                 int hypId = myHyp->GetId();
474                 status = _impl->RemoveHypothesis(myLocSubShape, hypId);
475                 if ( !SMESH_Hypothesis::IsStatusFatal(status) )
476                   _mapHypo.erase( hypId );
477         }
478         catch(SALOME_Exception & S_ex)
479         {
480                 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
481         }
482         return status;
483 }
484
485 //=============================================================================
486 /*!
487  *
488  */
489 //=============================================================================
490
491 SMESH::ListOfHypothesis *
492         SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShapeObject)
493 throw(SALOME::SALOME_Exception)
494 {
495   Unexpect aCatch(SALOME_SalomeException);
496   if (MYDEBUG) MESSAGE("GetHypothesisList");
497   if (CORBA::is_nil(aSubShapeObject))
498     THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
499                                  SALOME::BAD_PARAM);
500
501   SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
502
503   try {
504     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
505     const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
506     int i = 0, n = aLocalList.size();
507     aList->length( n );
508
509     for ( list<const SMESHDS_Hypothesis*>::const_iterator anIt = aLocalList.begin(); i < n && anIt != aLocalList.end(); anIt++ ) {
510       SMESHDS_Hypothesis* aHyp = (SMESHDS_Hypothesis*)(*anIt);
511       if ( _mapHypo.find( aHyp->GetID() ) != _mapHypo.end() )
512         aList[i++] = SMESH::SMESH_Hypothesis::_narrow( _mapHypo[aHyp->GetID()] );
513     }
514
515     aList->length( i );
516   }
517   catch(SALOME_Exception & S_ex) {
518     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
519   }
520
521   return aList._retn();
522 }
523
524 //=============================================================================
525 /*!
526  *
527  */
528 //=============================================================================
529 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShapeObject,
530                                                   const char*           theName )
531      throw(SALOME::SALOME_Exception)
532 {
533   Unexpect aCatch(SALOME_SalomeException);
534   MESSAGE("SMESH_Mesh_i::GetSubMesh");
535   if (CORBA::is_nil(aSubShapeObject))
536     THROW_SALOME_CORBA_EXCEPTION("bad subShape reference",
537                                  SALOME::BAD_PARAM);
538
539   SMESH::SMESH_subMesh_var subMesh;
540   SMESH::SMESH_Mesh_var    aMesh = SMESH::SMESH_Mesh::_narrow(_this());
541   try {
542     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
543
544     //Get or Create the SMESH_subMesh object implementation
545
546     int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
547     subMesh = getSubMesh( subMeshId );
548
549     // create a new subMesh object servant if there is none for the shape
550     if ( subMesh->_is_nil() )
551       subMesh = createSubMesh( aSubShapeObject );
552
553     if ( _gen_i->CanPublishInStudy( subMesh )) {
554       SALOMEDS::SObject_var aSO =
555         _gen_i->PublishSubMesh(_gen_i->GetCurrentStudy(), aMesh,
556                                subMesh, aSubShapeObject, theName );
557       if ( !aSO->_is_nil()) {
558         // Update Python script
559         TPythonDump() << aSO << " = " << _this() << ".GetSubMesh( "
560                       << aSubShapeObject << ", '" << theName << "' )";
561       }
562     }
563   }
564   catch(SALOME_Exception & S_ex) {
565     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
566   }
567   return subMesh._retn();
568 }
569
570 //=============================================================================
571 /*!
572  *
573  */
574 //=============================================================================
575
576 void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
577      throw (SALOME::SALOME_Exception)
578 {
579   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::RemoveSubMesh");
580   if ( theSubMesh->_is_nil() )
581     return;
582
583   GEOM::GEOM_Object_var aSubShapeObject;
584   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
585   if ( !aStudy->_is_nil() )  {
586     // Remove submesh's SObject
587     SALOMEDS::SObject_var anSO = _gen_i->ObjectToSObject( aStudy, theSubMesh );
588     if ( !anSO->_is_nil() ) {
589       long aTag = SMESH_Gen_i::GetRefOnShapeTag();
590       SALOMEDS::SObject_var anObj, aRef;
591       if ( anSO->FindSubObject( aTag, anObj ) && anObj->ReferencedObject( aRef ) )
592         aSubShapeObject = GEOM::GEOM_Object::_narrow( aRef->GetObject() );
593
594       aStudy->NewBuilder()->RemoveObjectWithChildren( anSO );
595
596       // Update Python script
597       TPythonDump() << _this() << ".RemoveSubMesh( " << anSO << " )";
598     }
599   }
600
601   removeSubMesh( theSubMesh, aSubShapeObject.in() );
602 }
603
604 //=============================================================================
605 /*!
606  *  ElementTypeString
607  */
608 //=============================================================================
609 #define CASE2STRING(enum) case SMESH::enum: return "SMESH."#enum;
610 inline TCollection_AsciiString ElementTypeString (SMESH::ElementType theElemType)
611 {
612   switch (theElemType) {
613     CASE2STRING( ALL );
614     CASE2STRING( NODE );
615     CASE2STRING( EDGE );
616     CASE2STRING( FACE );
617     CASE2STRING( VOLUME );
618   default:;
619   }
620   return "";
621 }
622
623 //=============================================================================
624 /*!
625  *
626  */
627 //=============================================================================
628
629 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType,
630                                                  const char*         theName )
631      throw(SALOME::SALOME_Exception)
632 {
633   Unexpect aCatch(SALOME_SalomeException);
634   SMESH::SMESH_Group_var aNewGroup =
635     SMESH::SMESH_Group::_narrow( createGroup( theElemType, theName ));
636
637   if ( _gen_i->CanPublishInStudy( aNewGroup ) ) {
638     SALOMEDS::SObject_var aSO =
639       _gen_i->PublishGroup(_gen_i->GetCurrentStudy(), _this(),
640                            aNewGroup, GEOM::GEOM_Object::_nil(), theName);
641     if ( !aSO->_is_nil()) {
642       // Update Python script
643       TPythonDump() << aSO << " = " << _this() << ".CreateGroup( "
644                     << ElementTypeString(theElemType) << ", '" << theName << "' )";
645     }
646   }
647   return aNewGroup._retn();
648 }
649
650
651 //=============================================================================
652 /*!
653  *
654  */
655 //=============================================================================
656 SMESH::SMESH_GroupOnGeom_ptr SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType    theElemType,
657                                                                 const char*           theName,
658                                                                 GEOM::GEOM_Object_ptr theGeomObj)
659      throw(SALOME::SALOME_Exception)
660 {
661   Unexpect aCatch(SALOME_SalomeException);
662   SMESH::SMESH_GroupOnGeom_var aNewGroup;
663
664   TopoDS_Shape aShape = _gen_i->GeomObjectToShape( theGeomObj );
665   if ( !aShape.IsNull() ) {
666     aNewGroup = SMESH::SMESH_GroupOnGeom::_narrow
667       ( createGroup( theElemType, theName, aShape ));
668     if ( _gen_i->CanPublishInStudy( aNewGroup ) ) {
669       SALOMEDS::SObject_var aSO =
670         _gen_i->PublishGroup(_gen_i->GetCurrentStudy(), _this(),
671                              aNewGroup, theGeomObj, theName);
672       if ( !aSO->_is_nil()) {
673         // Update Python script
674         TPythonDump() << aSO << " = " << _this() << ".CreateGroupFromGEOM("
675                       << ElementTypeString(theElemType) << ", '" << theName << "', "
676                       << theGeomObj << " )";
677       }
678     }
679   }
680
681   return aNewGroup._retn();
682 }
683
684 //=============================================================================
685 /*!
686  *
687  */
688 //=============================================================================
689
690 void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
691      throw (SALOME::SALOME_Exception)
692 {
693   if ( theGroup->_is_nil() )
694     return;
695
696   SMESH_GroupBase_i* aGroup =
697     dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
698   if ( !aGroup )
699     return;
700
701   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
702   if ( !aStudy->_is_nil() )  {
703     SALOMEDS::SObject_var aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
704
705     if ( !aGroupSO->_is_nil() ) {
706       // Update Python script
707       TPythonDump() << _this() << ".RemoveGroup( " << aGroupSO << " )";
708
709       // Remove group's SObject
710       aStudy->NewBuilder()->RemoveObject( aGroupSO );
711     }
712   }
713
714   // Remove the group from SMESH data structures
715   removeGroup( aGroup->GetLocalID() );
716 }
717
718 //=============================================================================
719 /*! RemoveGroupWithContents
720  *  Remove group with its contents
721  */
722 //=============================================================================
723 void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup )
724   throw (SALOME::SALOME_Exception)
725 {
726   if ( theGroup->_is_nil() )
727     return;
728
729   SMESH_GroupBase_i* aGroup =
730     dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
731   if ( !aGroup )
732     return;
733
734   SMESH::long_array_var anIds = aGroup->GetListOfID();
735   SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
736
737   // Update Python script
738   TPythonDump() << _this() << ".RemoveGroupWithContents( " << theGroup << " )";
739
740   // Remove contents
741   if ( aGroup->GetType() == SMESH::NODE )
742     aMeshEditor->RemoveNodes( anIds );
743   else
744     aMeshEditor->RemoveElements( anIds );
745
746   // Remove group
747   RemoveGroup( theGroup );
748
749   // Clear python lines, created by RemoveNodes/Elements() and RemoveGroup()
750   _gen_i->RemoveLastFromPythonScript(_gen_i->GetCurrentStudy()->StudyId());
751   _gen_i->RemoveLastFromPythonScript(_gen_i->GetCurrentStudy()->StudyId());
752 }
753
754
755 //================================================================================
756 /*!
757  * \brief Get the list of groups existing in the mesh
758   * \retval SMESH::ListOfGroups * - list of groups
759  */
760 //================================================================================
761
762 SMESH::ListOfGroups * SMESH_Mesh_i::GetGroups() throw(SALOME::SALOME_Exception)
763 {
764   Unexpect aCatch(SALOME_SalomeException);
765   if (MYDEBUG) MESSAGE("GetGroups");
766
767   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
768
769   // Python Dump
770   TPythonDump aPythonDump;
771   if ( !_mapGroups.empty() ) // (IMP13463) avoid "SyntaxError: can't assign to []"
772     aPythonDump << "[ ";
773
774   try {
775     aList->length( _mapGroups.size() );
776     int i = 0;
777     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
778     for ( ; it != _mapGroups.end(); it++ ) {
779       if ( CORBA::is_nil( it->second )) continue;
780       aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
781       // Python Dump
782       if (i > 1) aPythonDump << ", ";
783       aPythonDump << it->second;
784     }
785     aList->length( i );
786   }
787   catch(SALOME_Exception & S_ex) {
788     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
789   }
790
791   // Update Python script
792   if ( !_mapGroups.empty() ) // (IMP13463) avoid "SyntaxError: can't assign to []"
793     aPythonDump << " ] = " << _this() << ".GetGroups()";
794
795   return aList._retn();
796 }
797 //=============================================================================
798 /*!
799  *  Get number of groups existing in the mesh
800  */
801 //=============================================================================
802
803 CORBA::Long SMESH_Mesh_i::NbGroups() throw (SALOME::SALOME_Exception)
804 {
805   Unexpect aCatch(SALOME_SalomeException);
806   return _mapGroups.size();
807 }
808
809 //=============================================================================
810 /*! UnionGroups
811  *  New group is created. All mesh elements that are
812  *  present in initial groups are added to the new one
813  */
814 //=============================================================================
815 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
816                                                   SMESH::SMESH_GroupBase_ptr theGroup2,
817                                                   const char* theName )
818   throw (SALOME::SALOME_Exception)
819 {
820   try
821   {
822     if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
823          theGroup1->GetType() != theGroup2->GetType() )
824       return SMESH::SMESH_Group::_nil();
825
826     // Create Union
827     SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
828     if ( aResGrp->_is_nil() )
829       return SMESH::SMESH_Group::_nil();
830
831     SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
832     SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
833
834     TColStd_MapOfInteger aResMap;
835
836     for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
837       aResMap.Add( anIds1[ i1 ] );
838
839     for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
840       aResMap.Add( anIds2[ i2 ] );
841
842     SMESH::long_array_var aResIds = new SMESH::long_array;
843     aResIds->length( aResMap.Extent() );
844
845     int resI = 0;
846     TColStd_MapIteratorOfMapOfInteger anIter( aResMap );
847     for( ; anIter.More(); anIter.Next() )
848       aResIds[ resI++ ] = anIter.Key();
849
850     aResGrp->Add( aResIds );
851
852     // Clear python lines, created by CreateGroup() and Add()
853     SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
854     _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
855     _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
856
857     // Update Python script
858     TPythonDump() << aResGrp << " = " << _this() << ".UnionGroups( "
859                   << theGroup1 << ", " << theGroup2 << ", '"
860                   << theName << "' )";
861
862     return aResGrp._retn();
863   }
864   catch( ... )
865   {
866     return SMESH::SMESH_Group::_nil();
867   }
868 }
869
870 //=============================================================================
871 /*! IntersectGroups
872  *  New group is created. All mesh elements that are
873  *  present in both initial groups are added to the new one.
874  */
875 //=============================================================================
876 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
877                                                       SMESH::SMESH_GroupBase_ptr theGroup2,
878                                                       const char* theName )
879   throw (SALOME::SALOME_Exception)
880 {
881   if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
882        theGroup1->GetType() != theGroup2->GetType() )
883     return SMESH::SMESH_Group::_nil();
884
885   // Create Intersection
886   SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
887   if ( aResGrp->_is_nil() )
888     return aResGrp;
889
890   SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
891   SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
892
893   TColStd_MapOfInteger aMap1;
894
895   for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
896     aMap1.Add( anIds1[ i1 ] );
897
898   TColStd_SequenceOfInteger aSeq;
899
900   for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
901     if ( aMap1.Contains( anIds2[ i2 ] ) )
902       aSeq.Append( anIds2[ i2 ] );
903
904   SMESH::long_array_var aResIds = new SMESH::long_array;
905   aResIds->length( aSeq.Length() );
906
907   for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
908     aResIds[ resI ] = aSeq( resI + 1 );
909
910   aResGrp->Add( aResIds );
911
912   // Clear python lines, created by CreateGroup() and Add()
913   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
914   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
915   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
916
917   // Update Python script
918   TPythonDump() << aResGrp << " = " << _this() << ".IntersectGroups( "
919                 << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
920
921   return aResGrp._retn();
922 }
923
924 //=============================================================================
925 /*! CutGroups
926  *  New group is created. All mesh elements that are present in
927  *  main group but do not present in tool group are added to the new one
928  */
929 //=============================================================================
930 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
931                                                 SMESH::SMESH_GroupBase_ptr theGroup2,
932                                                 const char* theName )
933   throw (SALOME::SALOME_Exception)
934 {
935   if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
936        theGroup1->GetType() != theGroup2->GetType() )
937     return SMESH::SMESH_Group::_nil();
938
939   // Perform Cutting
940   SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
941   if ( aResGrp->_is_nil() )
942     return aResGrp;
943
944   SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
945   SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
946
947   TColStd_MapOfInteger aMap2;
948
949   for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
950     aMap2.Add( anIds2[ i2 ] );
951
952
953   TColStd_SequenceOfInteger aSeq;
954   for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
955     if ( !aMap2.Contains( anIds1[ i1 ] ) )
956       aSeq.Append( anIds1[ i1 ] );
957
958   SMESH::long_array_var aResIds = new SMESH::long_array;
959   aResIds->length( aSeq.Length() );
960
961   for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
962     aResIds[ resI ] = aSeq( resI + 1 );
963
964   aResGrp->Add( aResIds );
965
966   // Clear python lines, created by CreateGroup() and Add()
967   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
968   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
969   _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
970
971   // Update Python script
972   TPythonDump() << aResGrp << " = " << _this() << ".CutGroups( "
973                 << theGroup1 << ", " << theGroup2 << ", '"
974                 << theName << "' )";
975
976   return aResGrp._retn();
977 }
978
979 //================================================================================
980 /*!
981  * \brief Return group items of a group present in a study
982  */
983 //================================================================================
984
985 static GEOM::GEOM_Object_ptr getGroupItemsFromStudy(CORBA::Object_ptr    theMesh,
986                                                     SMESH_Gen_i*         theGen,
987                                                     list<TopoDS_Shape> & theItems)
988 {
989   GEOM::GEOM_Object_var groupObj;
990   SALOMEDS::Study_var  study = theGen->GetCurrentStudy();
991   GEOM::GEOM_Gen_var geomGen = theGen->GetGeomEngine();
992   if ( study->_is_nil() || geomGen->_is_nil() )
993     return groupObj._retn();
994   
995   GEOM::GEOM_IGroupOperations_var groupOp =
996     geomGen->GetIGroupOperations( theGen->GetCurrentStudyID() );
997   GEOM::GEOM_IShapesOperations_var shapeOp =
998     geomGen->GetIShapesOperations( theGen->GetCurrentStudyID() );
999
1000   SALOMEDS::SObject_var meshOS = theGen->ObjectToSObject(study, theMesh);
1001   if ( meshOS->_is_nil() || groupOp->_is_nil() || shapeOp->_is_nil() )
1002     return groupObj._retn();
1003   SALOMEDS::SObject_var fatherSO = meshOS->GetFather();
1004   if ( fatherSO->_is_nil() || fatherSO->Tag() != theGen->GetSubMeshOnCompoundTag() )
1005     return groupObj._retn(); // keep only submeshes on groups
1006
1007   SALOMEDS::ChildIterator_var anIter = study->NewChildIterator(meshOS);
1008   if ( anIter->_is_nil() ) return groupObj._retn();
1009   for ( ; anIter->More(); anIter->Next())
1010   {
1011     SALOMEDS::SObject_var aSObject = anIter->Value();
1012     SALOMEDS::SObject_var aRefSO;
1013     if ( !aSObject->_is_nil() && aSObject->ReferencedObject(aRefSO) )
1014     {
1015       groupObj = GEOM::GEOM_Object::_narrow(aRefSO->GetObject());
1016       if ( groupObj->_is_nil() ) break;
1017       GEOM::ListOfLong_var  ids = groupOp->GetObjects( groupObj );
1018       GEOM::GEOM_Object_var mainShape = groupObj->GetMainShape();
1019       for ( int i = 0; i < ids->length(); ++i ) {
1020         GEOM::GEOM_Object_var subShape = shapeOp->GetSubShape( mainShape, ids[i] );
1021         TopoDS_Shape S = theGen->GeomObjectToShape( subShape );
1022         if ( !S.IsNull() )
1023           theItems.push_back( S );
1024       }
1025       break;
1026     }
1027   }
1028   return groupObj._retn();
1029 }
1030
1031 //=============================================================================
1032 /*!
1033  * \brief Update hypotheses assigned to geom groups if the latter change
1034  * 
1035  * NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
1036  */
1037 //=============================================================================
1038
1039 void SMESH_Mesh_i::CheckGeomGroupModif()
1040 {
1041   if ( !_impl->HasShapeToMesh() ) return;
1042
1043   SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
1044   if ( study->_is_nil() ) return;
1045
1046   // check if items of groups changed
1047   map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
1048   for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
1049   {
1050     const TopoDS_Shape & oldGroupShape = i_sm->second->GetSubShape();
1051     SMESHDS_SubMesh * oldDS = i_sm->second->GetSubMeshDS();
1052     if ( !oldDS /*|| !oldDS->IsComplexSubmesh()*/ )
1053       continue;
1054     int oldID = i_sm->first;
1055     map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldID );
1056     if ( i_smIor == _mapSubMeshIor.end() )
1057       continue;
1058     list< TopoDS_Shape> newItems;
1059     GEOM::GEOM_Object_var groupObj = getGroupItemsFromStudy ( i_smIor->second, _gen_i, newItems );
1060     if ( groupObj->_is_nil() )
1061       continue;
1062
1063     int nbOldItems = oldDS->IsComplexSubmesh() ? oldDS->NbSubMeshes() : 1;
1064     int nbNewItems = newItems.size();
1065     bool groupChanged = ( nbOldItems != nbNewItems);
1066     if ( !groupChanged ) {
1067       if ( !oldDS->IsComplexSubmesh() ) { // old group has one item
1068         groupChanged = ( oldGroupShape != newItems.front() );
1069       }
1070       else {
1071         list<TopoDS_Shape>::iterator item = newItems.begin();
1072         for ( ; item != newItems.end() && !groupChanged; ++item )
1073         {
1074           SMESHDS_SubMesh * itemDS = _impl->GetMeshDS()->MeshElements( *item );
1075           groupChanged = ( !itemDS || !oldDS->ContainsSubMesh( itemDS ));
1076         }
1077       }
1078     }
1079     // update hypotheses and submeshes if necessary
1080     if ( groupChanged )
1081     {
1082       // get a new group shape
1083       GEOM_Client* geomClient = _gen_i->GetShapeReader();
1084       if ( !geomClient ) continue;
1085       TCollection_AsciiString groupIOR = _gen_i->GetGeomEngine()->GetStringFromIOR( groupObj );
1086       geomClient->RemoveShapeFromBuffer( groupIOR );
1087       TopoDS_Shape newGroupShape = _gen_i->GeomObjectToShape( groupObj );
1088       // update hypotheses
1089       list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldGroupShape);
1090       list <const SMESHDS_Hypothesis * >::iterator hypIt;
1091       for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
1092       {
1093         _impl->RemoveHypothesis( oldGroupShape, (*hypIt)->GetID());
1094         _impl->AddHypothesis   ( newGroupShape, (*hypIt)->GetID());
1095       }
1096       // care of submeshes
1097       SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newGroupShape );
1098       int newID = newSubmesh->GetId();
1099       if ( newID != oldID ) {
1100         _mapSubMesh   [ newID ] = newSubmesh;
1101         _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
1102         _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
1103         _mapSubMesh.erase   (oldID);
1104         _mapSubMesh_i.erase (oldID);
1105         _mapSubMeshIor.erase(oldID);
1106         _mapSubMesh_i [ newID ]->changeLocalId( newID );
1107       }
1108     }
1109   }
1110 }
1111
1112 //=============================================================================
1113 /*!
1114  *
1115  */
1116 //=============================================================================
1117
1118 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
1119 {
1120   if(MYDEBUG) MESSAGE( "createSubMesh" );
1121   TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
1122
1123   ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
1124   int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
1125   SMESH_subMesh_i *subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
1126   SMESH::SMESH_subMesh_var subMesh
1127     = SMESH::SMESH_subMesh::_narrow(subMeshServant->_this());
1128
1129   _mapSubMesh[subMeshId] = mySubMesh;
1130   _mapSubMesh_i[subMeshId] = subMeshServant;
1131   _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate(subMesh);
1132
1133   // register CORBA object for persistence
1134   int nextId = _gen_i->RegisterObject( subMesh );
1135   if(MYDEBUG) MESSAGE( "Add submesh to map with id = "<< nextId);
1136
1137   return subMesh._retn();
1138 }
1139
1140 //=======================================================================
1141 //function : getSubMesh
1142 //purpose  :
1143 //=======================================================================
1144
1145 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
1146 {
1147   map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
1148   if ( it == _mapSubMeshIor.end() )
1149     return SMESH::SMESH_subMesh::_nil();
1150
1151   return SMESH::SMESH_subMesh::_duplicate( (*it).second );
1152 }
1153
1154
1155 //=============================================================================
1156 /*!
1157  *
1158  */
1159 //=============================================================================
1160
1161 void SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
1162                                   GEOM::GEOM_Object_ptr    theSubShapeObject )
1163 {
1164   MESSAGE("SMESH_Mesh_i::removeSubMesh()");
1165   if ( theSubMesh->_is_nil() || theSubShapeObject->_is_nil() )
1166     return;
1167
1168   try {
1169     SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
1170     for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
1171       removeHypothesis( theSubShapeObject, aHypList[i] );
1172     }
1173   }
1174   catch( const SALOME::SALOME_Exception& ) {
1175     INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
1176   }
1177
1178   int subMeshId = theSubMesh->GetId();
1179
1180   _mapSubMesh.erase(subMeshId);
1181   _mapSubMesh_i.erase(subMeshId);
1182   _mapSubMeshIor.erase(subMeshId);
1183   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeSubMesh() completed");
1184 }
1185
1186 //=============================================================================
1187 /*!
1188  *
1189  */
1190 //=============================================================================
1191
1192 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType theElemType,
1193                                                       const char*         theName,
1194                                                       const TopoDS_Shape& theShape )
1195 {
1196   int anId;
1197   SMESH::SMESH_GroupBase_var aGroup;
1198   if ( _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName, anId, theShape )) {
1199     SMESH_GroupBase_i* aGroupImpl;
1200     if ( !theShape.IsNull() )
1201       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
1202     else
1203       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
1204
1205     // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1206     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
1207     aGroupImpl->Register();
1208     // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
1209
1210     aGroup = SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
1211     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
1212
1213     // register CORBA object for persistence
1214     int nextId = _gen_i->RegisterObject( aGroup );
1215     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
1216   }
1217   return aGroup._retn();
1218 }
1219
1220 //=============================================================================
1221 /*!
1222  * SMESH_Mesh_i::removeGroup
1223  *
1224  * Should be called by ~SMESH_Group_i()
1225  */
1226 //=============================================================================
1227
1228 void SMESH_Mesh_i::removeGroup( const int theId )
1229 {
1230   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
1231   if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
1232     _mapGroups.erase( theId );
1233     _impl->RemoveGroup( theId );
1234   }
1235 }
1236
1237
1238 //=============================================================================
1239 /*!
1240  *
1241  */
1242 //=============================================================================
1243
1244 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
1245 throw(SALOME::SALOME_Exception)
1246 {
1247   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetLog");
1248
1249   SMESH::log_array_var aLog;
1250   try{
1251     list < SMESHDS_Command * >logDS = _impl->GetLog();
1252     aLog = new SMESH::log_array;
1253     int indexLog = 0;
1254     int lg = logDS.size();
1255     SCRUTE(lg);
1256     aLog->length(lg);
1257     list < SMESHDS_Command * >::iterator its = logDS.begin();
1258     while(its != logDS.end()){
1259       SMESHDS_Command *com = *its;
1260       int comType = com->GetType();
1261       //SCRUTE(comType);
1262       int lgcom = com->GetNumber();
1263       //SCRUTE(lgcom);
1264       const list < int >&intList = com->GetIndexes();
1265       int inum = intList.size();
1266       //SCRUTE(inum);
1267       list < int >::const_iterator ii = intList.begin();
1268       const list < double >&coordList = com->GetCoords();
1269       int rnum = coordList.size();
1270       //SCRUTE(rnum);
1271       list < double >::const_iterator ir = coordList.begin();
1272       aLog[indexLog].commandType = comType;
1273       aLog[indexLog].number = lgcom;
1274       aLog[indexLog].coords.length(rnum);
1275       aLog[indexLog].indexes.length(inum);
1276       for(int i = 0; i < rnum; i++){
1277         aLog[indexLog].coords[i] = *ir;
1278         //MESSAGE(" "<<i<<" "<<ir.Value());
1279         ir++;
1280       }
1281       for(int i = 0; i < inum; i++){
1282         aLog[indexLog].indexes[i] = *ii;
1283         //MESSAGE(" "<<i<<" "<<ii.Value());
1284         ii++;
1285       }
1286       indexLog++;
1287       its++;
1288     }
1289     if(clearAfterGet)
1290       _impl->ClearLog();
1291   }
1292   catch(SALOME_Exception & S_ex){
1293     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
1294   }
1295   return aLog._retn();
1296 }
1297
1298
1299 //=============================================================================
1300 /*!
1301  *
1302  */
1303 //=============================================================================
1304
1305 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
1306 {
1307   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::ClearLog");
1308   // ****
1309 }
1310
1311 //=============================================================================
1312 /*!
1313  *
1314  */
1315 //=============================================================================
1316
1317 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
1318 {
1319   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetId");
1320   return _id;
1321 }
1322
1323 //=============================================================================
1324 /*!
1325  *
1326  */
1327 //=============================================================================
1328
1329 CORBA::Long SMESH_Mesh_i::GetStudyId()throw(SALOME::SALOME_Exception)
1330 {
1331   return _studyId;
1332 }
1333
1334 //=============================================================================
1335 /*!
1336  *
1337  */
1338 //=============================================================================
1339
1340 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
1341 {
1342   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
1343   _impl = impl;
1344 }
1345
1346 //=============================================================================
1347 /*!
1348  *
1349  */
1350 //=============================================================================
1351
1352 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
1353 {
1354   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
1355   return *_impl;
1356 }
1357
1358 //=============================================================================
1359 /*!
1360  * Return mesh editor
1361  */
1362 //=============================================================================
1363
1364 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
1365 {
1366   // Create MeshEditor
1367   SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, false );
1368   SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
1369
1370   // Update Python script
1371   TPythonDump() << aMeshEditor << " = " << _this() << ".GetMeshEditor()";
1372
1373   return aMesh._retn();
1374 }
1375
1376 //=============================================================================
1377 /*!
1378  * Return mesh edition previewer
1379  */
1380 //=============================================================================
1381
1382 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
1383 {
1384   SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, true );
1385   SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
1386   return aMesh._retn();
1387 }
1388
1389 //=============================================================================
1390 /*!
1391  *
1392  */
1393 //=============================================================================
1394 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOME_Exception)
1395 {
1396   Unexpect aCatch(SALOME_SalomeException);
1397   _impl->SetAutoColor(theAutoColor);
1398 }
1399
1400 //=============================================================================
1401 /*!
1402  *
1403  */
1404 //=============================================================================
1405 CORBA::Boolean SMESH_Mesh_i::GetAutoColor() throw(SALOME::SALOME_Exception)
1406 {
1407   Unexpect aCatch(SALOME_SalomeException);
1408   return _impl->GetAutoColor();
1409 }
1410
1411
1412 //=============================================================================
1413 /*!
1414  *  Export in different formats
1415  */
1416 //=============================================================================
1417
1418 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
1419 {
1420   return _impl->HasDuplicatedGroupNamesMED();
1421 }
1422
1423 static void PrepareForWriting (const char* file)
1424 {
1425   TCollection_AsciiString aFullName ((char*)file);
1426   OSD_Path aPath (aFullName);
1427   OSD_File aFile (aPath);
1428   if (aFile.Exists()) {
1429     // existing filesystem node
1430     if (aFile.KindOfFile() == OSD_FILE) {
1431       if (aFile.IsWriteable()) {
1432         aFile.Reset();
1433         aFile.Remove();
1434         if (aFile.Failed()) {
1435           TCollection_AsciiString msg ("File ");
1436           msg += aFullName + " cannot be replaced.";
1437           THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
1438         }
1439       } else {
1440         TCollection_AsciiString msg ("File ");
1441         msg += aFullName + " cannot be overwritten.";
1442         THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
1443       }
1444     } else {
1445       TCollection_AsciiString msg ("Location ");
1446       msg += aFullName + " is not a file.";
1447       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
1448     }
1449   } else {
1450     // nonexisting file; check if it can be created
1451     aFile.Reset();
1452     aFile.Build(OSD_WriteOnly, OSD_Protection());
1453     if (aFile.Failed()) {
1454       TCollection_AsciiString msg ("You cannot create the file ");
1455       msg += aFullName + ". Check the directory existance and access rights.";
1456       THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
1457     } else {
1458       aFile.Close();
1459       aFile.Remove();
1460     }
1461   }
1462 }
1463
1464 void SMESH_Mesh_i::ExportToMED (const char* file,
1465                                 CORBA::Boolean auto_groups,
1466                                 SMESH::MED_VERSION theVersion)
1467   throw(SALOME::SALOME_Exception)
1468 {
1469   Unexpect aCatch(SALOME_SalomeException);
1470
1471   // Update Python script
1472   TPythonDump() << _this() << ".ExportToMED( '"
1473                 << file << "', " << auto_groups << ", " << theVersion << " )";
1474
1475   // Perform Export
1476   PrepareForWriting(file);
1477   char* aMeshName = "Mesh";
1478   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
1479   if ( !aStudy->_is_nil() ) {
1480     SALOMEDS::SObject_var aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
1481     if ( !aMeshSO->_is_nil() ) {
1482       aMeshName = aMeshSO->GetName();
1483       //SCRUTE(file);
1484       //SCRUTE(aMeshName);
1485       //SCRUTE(aMeshSO->GetID());
1486
1487       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
1488       if ( !aStudy->GetProperties()->IsLocked() )
1489         {
1490         SALOMEDS::GenericAttribute_var anAttr;
1491         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
1492         SALOMEDS::AttributeExternalFileDef_var aFileName;
1493         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
1494         aFileName = SALOMEDS::AttributeExternalFileDef::_narrow(anAttr);
1495         ASSERT(!aFileName->_is_nil());
1496         aFileName->SetValue(file);
1497         SALOMEDS::AttributeFileType_var aFileType;
1498         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
1499         aFileType = SALOMEDS::AttributeFileType::_narrow(anAttr);
1500         ASSERT(!aFileType->_is_nil());
1501         aFileType->SetValue("FICHIERMED");
1502         }
1503     }
1504   }
1505   _impl->ExportMED( file, aMeshName, auto_groups, theVersion );
1506 }
1507
1508 void SMESH_Mesh_i::ExportMED (const char* file,
1509                               CORBA::Boolean auto_groups)
1510   throw(SALOME::SALOME_Exception)
1511 {
1512   ExportToMED(file,auto_groups,SMESH::MED_V2_1);
1513 }
1514
1515 void SMESH_Mesh_i::ExportDAT (const char *file)
1516   throw(SALOME::SALOME_Exception)
1517 {
1518   Unexpect aCatch(SALOME_SalomeException);
1519
1520   // Update Python script
1521   TPythonDump() << _this() << ".ExportDAT( '" << file << "' )";
1522
1523   // Perform Export
1524   PrepareForWriting(file);
1525   _impl->ExportDAT(file);
1526 }
1527
1528 void SMESH_Mesh_i::ExportUNV (const char *file)
1529   throw(SALOME::SALOME_Exception)
1530 {
1531   Unexpect aCatch(SALOME_SalomeException);
1532
1533   // Update Python script
1534   TPythonDump() << _this() << ".ExportUNV( '" << file << "' )";
1535
1536   // Perform Export
1537   PrepareForWriting(file);
1538   _impl->ExportUNV(file);
1539 }
1540
1541 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
1542   throw(SALOME::SALOME_Exception)
1543 {
1544   Unexpect aCatch(SALOME_SalomeException);
1545
1546   // Update Python script
1547   TPythonDump() << _this() << ".ExportSTL( '" << file << "', " << isascii << " )";
1548
1549   // Perform Export
1550   PrepareForWriting(file);
1551   _impl->ExportSTL(file, isascii);
1552 }
1553
1554 //=============================================================================
1555 /*!
1556  *
1557  */
1558 //=============================================================================
1559
1560 SALOME_MED::MESH_ptr SMESH_Mesh_i::GetMEDMesh()throw(SALOME::SALOME_Exception)
1561 {
1562   Unexpect aCatch(SALOME_SalomeException);
1563   SMESH_MEDMesh_i *aMedMesh = new SMESH_MEDMesh_i(this);
1564   SALOME_MED::MESH_var aMesh = aMedMesh->_this();
1565   return aMesh._retn();
1566 }
1567
1568 //=============================================================================
1569 /*!
1570  *
1571  */
1572 //=============================================================================
1573 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
1574 {
1575   Unexpect aCatch(SALOME_SalomeException);
1576   return _impl->NbNodes();
1577 }
1578
1579 //=============================================================================
1580 /*!
1581  *
1582  */
1583 //=============================================================================
1584 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
1585 {
1586   Unexpect aCatch(SALOME_SalomeException);
1587   return NbEdges() + NbFaces() + NbVolumes();
1588 }
1589
1590 //=============================================================================
1591 /*!
1592  *
1593  */
1594 //=============================================================================
1595 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
1596 {
1597   Unexpect aCatch(SALOME_SalomeException);
1598   return _impl->NbEdges();
1599 }
1600
1601 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
1602   throw(SALOME::SALOME_Exception)
1603 {
1604   Unexpect aCatch(SALOME_SalomeException);
1605   return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
1606 }
1607
1608 //=============================================================================
1609 /*!
1610  *
1611  */
1612 //=============================================================================
1613 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
1614 {
1615   Unexpect aCatch(SALOME_SalomeException);
1616   return _impl->NbFaces();
1617 }
1618
1619 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
1620 {
1621   Unexpect aCatch(SALOME_SalomeException);
1622   return _impl->NbTriangles();
1623 }
1624
1625 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
1626 {
1627   Unexpect aCatch(SALOME_SalomeException);
1628   return _impl->NbQuadrangles();
1629 }
1630
1631 CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
1632 {
1633   Unexpect aCatch(SALOME_SalomeException);
1634   return _impl->NbPolygons();
1635 }
1636
1637 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
1638   throw(SALOME::SALOME_Exception)
1639 {
1640   Unexpect aCatch(SALOME_SalomeException);
1641   return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
1642 }
1643
1644 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
1645   throw(SALOME::SALOME_Exception)
1646 {
1647   Unexpect aCatch(SALOME_SalomeException);
1648   return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
1649 }
1650
1651 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
1652   throw(SALOME::SALOME_Exception)
1653 {
1654   Unexpect aCatch(SALOME_SalomeException);
1655   return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
1656 }
1657
1658 //=============================================================================
1659 /*!
1660  *
1661  */
1662 //=============================================================================
1663 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
1664 {
1665   Unexpect aCatch(SALOME_SalomeException);
1666   return _impl->NbVolumes();
1667 }
1668
1669 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
1670 {
1671   Unexpect aCatch(SALOME_SalomeException);
1672   return _impl->NbTetras();
1673 }
1674
1675 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
1676 {
1677   Unexpect aCatch(SALOME_SalomeException);
1678   return _impl->NbHexas();
1679 }
1680
1681 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
1682 {
1683   Unexpect aCatch(SALOME_SalomeException);
1684   return _impl->NbPyramids();
1685 }
1686
1687 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
1688 {
1689   Unexpect aCatch(SALOME_SalomeException);
1690   return _impl->NbPrisms();
1691 }
1692
1693 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
1694 {
1695   Unexpect aCatch(SALOME_SalomeException);
1696   return _impl->NbPolyhedrons();
1697 }
1698
1699 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
1700   throw(SALOME::SALOME_Exception)
1701 {
1702   Unexpect aCatch(SALOME_SalomeException);
1703   return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
1704 }
1705
1706 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
1707   throw(SALOME::SALOME_Exception)
1708 {
1709   Unexpect aCatch(SALOME_SalomeException);
1710   return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
1711 }
1712
1713 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
1714   throw(SALOME::SALOME_Exception)
1715 {
1716   Unexpect aCatch(SALOME_SalomeException);
1717   return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
1718 }
1719
1720 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
1721   throw(SALOME::SALOME_Exception)
1722 {
1723   Unexpect aCatch(SALOME_SalomeException);
1724   return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
1725 }
1726
1727 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
1728   throw(SALOME::SALOME_Exception)
1729 {
1730   Unexpect aCatch(SALOME_SalomeException);
1731   return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
1732 }
1733
1734 //=============================================================================
1735 /*!
1736  *
1737  */
1738 //=============================================================================
1739 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
1740 {
1741   Unexpect aCatch(SALOME_SalomeException);
1742   return _impl->NbSubMesh();
1743 }
1744
1745 //=============================================================================
1746 /*!
1747  *
1748  */
1749 //=============================================================================
1750 char* SMESH_Mesh_i::Dump()
1751 {
1752   std::ostringstream os;
1753   _impl->Dump( os );
1754   return CORBA::string_dup( os.str().c_str() );
1755 }
1756
1757 //=============================================================================
1758 /*!
1759  *
1760  */
1761 //=============================================================================
1762 SMESH::long_array* SMESH_Mesh_i::GetIDs()
1763 {
1764 //   SMESH::long_array_var aResult = new SMESH::long_array();
1765 //   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
1766 //   int aMinId = aSMESHDS_Mesh->MinElementID();
1767 //   int aMaxId =  aSMESHDS_Mesh->MaxElementID();
1768
1769 //   aResult->length(aMaxId - aMinId + 1);
1770
1771 //   for (int i = 0, id = aMinId; id <= aMaxId; id++  )
1772 //     aResult[i++] = id;
1773
1774 //   return aResult._retn();
1775   // PAL12398
1776   return GetElementsId();
1777 }
1778
1779 //=============================================================================
1780 /*!
1781  *
1782  */
1783 //=============================================================================
1784
1785 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
1786      throw (SALOME::SALOME_Exception)
1787 {
1788   Unexpect aCatch(SALOME_SalomeException);
1789   MESSAGE("SMESH_Mesh_i::GetElementsId");
1790   SMESH::long_array_var aResult = new SMESH::long_array();
1791   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
1792
1793   if ( aSMESHDS_Mesh == NULL )
1794     return aResult._retn();
1795
1796   long nbElements = NbElements();
1797   aResult->length( nbElements );
1798   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
1799   for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
1800     aResult[i] = anIt->next()->GetID();
1801
1802   return aResult._retn();
1803 }
1804
1805
1806 //=============================================================================
1807 /*!
1808  *
1809  */
1810 //=============================================================================
1811
1812 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
1813     throw (SALOME::SALOME_Exception)
1814 {
1815   Unexpect aCatch(SALOME_SalomeException);
1816   MESSAGE("SMESH_subMesh_i::GetElementsByType");
1817   SMESH::long_array_var aResult = new SMESH::long_array();
1818   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
1819
1820   if ( aSMESHDS_Mesh == NULL )
1821     return aResult._retn();
1822
1823   long nbElements = NbElements();
1824
1825   // No sense in returning ids of elements along with ids of nodes:
1826   // when theElemType == SMESH::ALL, return node ids only if
1827   // there are no elements
1828   if ( theElemType == SMESH::NODE || theElemType == SMESH::ALL && nbElements == 0 )
1829     return GetNodesId();
1830
1831   aResult->length( nbElements );
1832
1833   int i = 0;
1834
1835   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
1836   while ( i < nbElements && anIt->more() ) {
1837     const SMDS_MeshElement* anElem = anIt->next();
1838     if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
1839       aResult[i++] = anElem->GetID();
1840   }
1841
1842   aResult->length( i );
1843
1844   return aResult._retn();
1845 }
1846
1847 //=============================================================================
1848 /*!
1849  *
1850  */
1851 //=============================================================================
1852
1853 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
1854   throw (SALOME::SALOME_Exception)
1855 {
1856   Unexpect aCatch(SALOME_SalomeException);
1857   MESSAGE("SMESH_subMesh_i::GetNodesId");
1858   SMESH::long_array_var aResult = new SMESH::long_array();
1859   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
1860
1861   if ( aSMESHDS_Mesh == NULL )
1862     return aResult._retn();
1863
1864   long nbNodes = NbNodes();
1865   aResult->length( nbNodes );
1866   SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator();
1867   for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
1868     aResult[i] = anIt->next()->GetID();
1869
1870   return aResult._retn();
1871 }
1872
1873 //=============================================================================
1874 /*!
1875  *
1876  */
1877 //=============================================================================
1878
1879 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
1880   throw (SALOME::SALOME_Exception)
1881 {
1882   return ( SMESH::ElementType )_impl->GetElementType( id, iselem );
1883 }
1884
1885
1886 //=============================================================================
1887 /*!
1888  * Returns ID of elements for given submesh
1889  */
1890 //=============================================================================
1891 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
1892      throw (SALOME::SALOME_Exception)
1893 {
1894   SMESH::long_array_var aResult = new SMESH::long_array();
1895
1896   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
1897   if(!SM) return aResult._retn();
1898
1899   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
1900   if(!SDSM) return aResult._retn();
1901
1902   aResult->length(SDSM->NbElements());
1903
1904   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
1905   int i = 0;
1906   while ( eIt->more() ) {
1907     aResult[i++] = eIt->next()->GetID();
1908   }
1909
1910   return aResult._retn();
1911 }
1912
1913
1914 //=============================================================================
1915 /*!
1916  * Returns ID of nodes for given submesh
1917  * If param all==true - returns all nodes, else -
1918  * returns only nodes on shapes.
1919  */
1920 //=============================================================================
1921 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID, CORBA::Boolean all)
1922      throw (SALOME::SALOME_Exception)
1923 {
1924   SMESH::long_array_var aResult = new SMESH::long_array();
1925
1926   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
1927   if(!SM) return aResult._retn();
1928
1929   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
1930   if(!SDSM) return aResult._retn();
1931
1932   map<int,const SMDS_MeshElement*> theElems;
1933   if( !all || (SDSM->NbElements()==0 && SDSM->NbNodes()==1) ) {
1934     SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
1935     while ( nIt->more() ) {
1936       const SMDS_MeshNode* elem = nIt->next();
1937       theElems.insert( make_pair(elem->GetID(),elem) );
1938     }
1939   }
1940   else { // all nodes of submesh elements
1941     SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
1942     while ( eIt->more() ) {
1943       const SMDS_MeshElement* anElem = eIt->next();
1944       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
1945       while ( nIt->more() ) {
1946         const SMDS_MeshElement* elem = nIt->next();
1947         theElems.insert( make_pair(elem->GetID(),elem) );
1948       }
1949     }
1950   }
1951
1952   aResult->length(theElems.size());
1953   map<int, const SMDS_MeshElement * >::iterator itElem;
1954   int i = 0;
1955   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
1956     aResult[i++] = (*itElem).first;
1957
1958   return aResult._retn();
1959 }
1960   
1961
1962 //=============================================================================
1963 /*!
1964  * Returns type of elements for given submesh
1965  */
1966 //=============================================================================
1967 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
1968      throw (SALOME::SALOME_Exception)
1969 {
1970   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
1971   if(!SM) return SMESH::ALL;
1972
1973   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
1974   if(!SDSM) return SMESH::ALL;
1975
1976   if(SDSM->NbElements()==0)
1977     return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
1978
1979   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
1980   const SMDS_MeshElement* anElem = eIt->next();
1981   return ( SMESH::ElementType ) anElem->GetType();
1982 }
1983   
1984
1985 //=============================================================================
1986 /*!
1987  *
1988  */
1989 //=============================================================================
1990
1991 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
1992 {
1993   CORBA::LongLong pointeur = CORBA::LongLong(_impl);
1994   cerr << "CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() " << pointeur << endl;
1995   return pointeur;
1996 }
1997
1998
1999 //=============================================================================
2000 /*!
2001  * Get XYZ coordinates of node as list of double
2002  * If there is not node for given ID - returns empty list
2003  */
2004 //=============================================================================
2005
2006 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
2007 {
2008   SMESH::double_array_var aResult = new SMESH::double_array();
2009   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2010   if ( aSMESHDS_Mesh == NULL )
2011     return aResult._retn();
2012
2013   // find node
2014   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2015   if(!aNode)
2016     return aResult._retn();
2017
2018   // add coordinates
2019   aResult->length(3);
2020   aResult[0] = aNode->X();
2021   aResult[1] = aNode->Y();
2022   aResult[2] = aNode->Z();
2023   return aResult._retn();
2024 }
2025
2026
2027 //=============================================================================
2028 /*!
2029  * For given node returns list of IDs of inverse elements
2030  * If there is not node for given ID - returns empty list
2031  */
2032 //=============================================================================
2033
2034 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
2035 {
2036   SMESH::long_array_var aResult = new SMESH::long_array();
2037   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2038   if ( aSMESHDS_Mesh == NULL )
2039     return aResult._retn();
2040
2041   // find node
2042   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2043   if(!aNode)
2044     return aResult._retn();
2045
2046   // find inverse elements
2047   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
2048   TColStd_SequenceOfInteger IDs;
2049   while(eIt->more()) {
2050     const SMDS_MeshElement* elem = eIt->next();
2051     IDs.Append(elem->GetID());
2052   }
2053   if(IDs.Length()>0) {
2054     aResult->length(IDs.Length());
2055     int i = 1;
2056     for(; i<=IDs.Length(); i++) {
2057       aResult[i-1] = IDs.Value(i);
2058     }
2059   }
2060   return aResult._retn();
2061 }
2062
2063
2064 //=============================================================================
2065 /*!
2066  * If given element is node returns IDs of shape from position
2067  * If there is not node for given ID - returns -1
2068  */
2069 //=============================================================================
2070
2071 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
2072 {
2073   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2074   if ( aSMESHDS_Mesh == NULL )
2075     return -1;
2076
2077   // try to find node
2078   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
2079   if(aNode) {
2080     SMDS_PositionPtr pos = aNode->GetPosition();
2081     if(!pos)
2082       return -1;
2083     else
2084       return pos->GetShapeId();
2085   }
2086
2087   return -1;
2088 }
2089
2090
2091 //=============================================================================
2092 /*!
2093  * For given element returns ID of result shape after 
2094  * ::FindShape() from SMESH_MeshEditor
2095  * If there is not element for given ID - returns -1
2096  */
2097 //=============================================================================
2098
2099 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
2100 {
2101   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2102   if ( aSMESHDS_Mesh == NULL )
2103     return -1;
2104
2105   // try to find element
2106   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2107   if(!elem)
2108     return -1;
2109
2110   //SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
2111   ::SMESH_MeshEditor aMeshEditor(_impl);
2112   int index = aMeshEditor.FindShape( elem );
2113   if(index>0)
2114     return index;
2115
2116   return -1;
2117 }
2118
2119
2120 //=============================================================================
2121 /*!
2122  * Returns number of nodes for given element
2123  * If there is not element for given ID - returns -1
2124  */
2125 //=============================================================================
2126
2127 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
2128 {
2129   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2130   if ( aSMESHDS_Mesh == NULL ) return -1;
2131   // try to find element
2132   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2133   if(!elem) return -1;
2134   return elem->NbNodes();
2135 }
2136
2137
2138 //=============================================================================
2139 /*!
2140  * Returns ID of node by given index for given element
2141  * If there is not element for given ID - returns -1
2142  * If there is not node for given index - returns -2
2143  */
2144 //=============================================================================
2145
2146 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
2147 {
2148   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2149   if ( aSMESHDS_Mesh == NULL ) return -1;
2150   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2151   if(!elem) return -1;
2152   if( index>=elem->NbNodes() || index<0 ) return -1;
2153   return elem->GetNode(index)->GetID();
2154 }
2155
2156 //=============================================================================
2157 /*!
2158  * Returns IDs of nodes of given element
2159  */
2160 //=============================================================================
2161
2162 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
2163 {
2164   SMESH::long_array_var aResult = new SMESH::long_array();
2165   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
2166   {
2167     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id) )
2168     {
2169       aResult->length( elem->NbNodes() );
2170       for ( int i = 0; i < elem->NbNodes(); ++i )
2171         aResult[ i ] = elem->GetNode( i )->GetID();
2172     }
2173   }
2174   return aResult._retn();
2175 }
2176
2177 //=============================================================================
2178 /*!
2179  * Returns true if given node is medium node
2180  * in given quadratic element
2181  */
2182 //=============================================================================
2183
2184 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
2185 {
2186   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2187   if ( aSMESHDS_Mesh == NULL ) return false;
2188   // try to find node
2189   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
2190   if(!aNode) return false;
2191   // try to find element
2192   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(ide);
2193   if(!elem) return false;
2194
2195   return elem->IsMediumNode(aNode);
2196 }
2197
2198
2199 //=============================================================================
2200 /*!
2201  * Returns true if given node is medium node
2202  * in one of quadratic elements
2203  */
2204 //=============================================================================
2205
2206 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
2207                                                    SMESH::ElementType theElemType)
2208 {
2209   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2210   if ( aSMESHDS_Mesh == NULL ) return false;
2211
2212   // try to find node
2213   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
2214   if(!aNode) return false;
2215
2216   SMESH_MesherHelper aHelper( *(_impl) );
2217
2218   SMDSAbs_ElementType aType;
2219   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
2220   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
2221   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
2222   else aType = SMDSAbs_All;
2223
2224   return aHelper.IsMedium(aNode,aType);
2225 }
2226
2227
2228 //=============================================================================
2229 /*!
2230  * Returns number of edges for given element
2231  */
2232 //=============================================================================
2233
2234 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
2235 {
2236   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2237   if ( aSMESHDS_Mesh == NULL ) return -1;
2238   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2239   if(!elem) return -1;
2240   return elem->NbEdges();
2241 }
2242
2243
2244 //=============================================================================
2245 /*!
2246  * Returns number of faces for given element
2247  */
2248 //=============================================================================
2249
2250 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
2251 {
2252   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2253   if ( aSMESHDS_Mesh == NULL ) return -1;
2254   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2255   if(!elem) return -1;
2256   return elem->NbFaces();
2257 }
2258
2259
2260 //=============================================================================
2261 /*!
2262  * Returns true if given element is polygon
2263  */
2264 //=============================================================================
2265
2266 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
2267 {
2268   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2269   if ( aSMESHDS_Mesh == NULL ) return false;
2270   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2271   if(!elem) return false;
2272   return elem->IsPoly();
2273 }
2274
2275
2276 //=============================================================================
2277 /*!
2278  * Returns true if given element is quadratic
2279  */
2280 //=============================================================================
2281
2282 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
2283 {
2284   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2285   if ( aSMESHDS_Mesh == NULL ) return false;
2286   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2287   if(!elem) return false;
2288   return elem->IsQuadratic();
2289 }
2290
2291
2292 //=============================================================================
2293 /*!
2294  * Returns bary center for given element
2295  */
2296 //=============================================================================
2297
2298 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
2299 {
2300   SMESH::double_array_var aResult = new SMESH::double_array();
2301   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
2302   if ( aSMESHDS_Mesh == NULL )
2303     return aResult._retn();
2304
2305   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
2306   if(!elem)
2307     return aResult._retn();
2308
2309   if(elem->GetType()==SMDSAbs_Volume) {
2310     SMDS_VolumeTool aTool;
2311     if(aTool.Set(elem)) {
2312       aResult->length(3);
2313       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
2314         aResult->length(0);
2315     }
2316   }
2317   else {
2318     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
2319     int nbn = 0;
2320     double x=0., y=0., z=0.;
2321     for(; anIt->more(); ) {
2322       nbn++;
2323       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
2324       x += aNode->X();
2325       y += aNode->Y();
2326       z += aNode->Z();
2327     }
2328     if(nbn>0) {
2329       // add coordinates
2330       aResult->length(3);
2331       aResult[0] = x/nbn;
2332       aResult[1] = y/nbn;
2333       aResult[2] = z/nbn;
2334     }
2335   }
2336
2337   return aResult._retn();
2338 }
2339
2340
2341 //=============================================================================
2342 /*!
2343  * Create and publish group servants if any groups were imported or created anyhow
2344  */
2345 //=============================================================================
2346
2347 void SMESH_Mesh_i::CreateGroupServants() 
2348 {
2349   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
2350
2351   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
2352   while ( groupIt->more() )
2353   {
2354     ::SMESH_Group* group = groupIt->next();
2355     int            anId = group->GetGroupDS()->GetID();
2356
2357     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
2358     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
2359       continue;
2360
2361     SMESH_GroupBase_i* aGroupImpl;
2362     TopoDS_Shape       shape;
2363     if ( SMESHDS_GroupOnGeom* groupOnGeom =
2364          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
2365     {
2366       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
2367       shape      = groupOnGeom->GetShape();
2368     }
2369     else {
2370       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2371     }
2372
2373     // To ensure correct mapping of servant and correct reference counting in GenericObj_i
2374     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
2375     aGroupImpl->Register();
2376
2377     SMESH::SMESH_GroupBase_var groupVar =
2378       SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
2379     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
2380
2381     // register CORBA object for persistence
2382     int nextId = _gen_i->RegisterObject( groupVar );
2383     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
2384
2385     // publishing of the groups in the study
2386     if ( !aStudy->_is_nil() ) {
2387       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
2388       _gen_i->PublishGroup( aStudy, _this(), groupVar, shapeVar, groupVar->GetName());
2389     }
2390   }
2391 }
2392
2393 //=============================================================================
2394 /*!
2395  * \brief Return groups cantained in _mapGroups by their IDs
2396  */
2397 //=============================================================================
2398
2399 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
2400 {
2401   int nbGroups = groupIDs.size();
2402   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
2403   aList->length( nbGroups );
2404
2405   list<int>::const_iterator ids = groupIDs.begin();
2406   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
2407   {
2408     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
2409     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
2410       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
2411   }
2412   aList->length( nbGroups );
2413   return aList._retn();
2414 }