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