Salome HOME
Improve ReplaceShape interface
[modules/smesh.git] / src / SMESH_I / SMESH_Mesh_i.cxx
1 // Copyright (C) 2007-2019  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, or (at your option) any later version.
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_Field.h"
30 #include "DriverMED_W_SMESHDS_Mesh.h"
31 #include "MED_Factory.hxx"
32 #include "SMDS_LinearEdge.hxx"
33 #include "SMDS_EdgePosition.hxx"
34 #include "SMDS_ElemIterator.hxx"
35 #include "SMDS_FacePosition.hxx"
36 #include "SMDS_IteratorOnIterators.hxx"
37 #include "SMDS_MeshGroup.hxx"
38 #include "SMDS_SetIterator.hxx"
39 #include "SMDS_StdIterator.hxx"
40 #include "SMDS_VolumeTool.hxx"
41 #include "SMESHDS_Command.hxx"
42 #include "SMESHDS_CommandType.hxx"
43 #include "SMESHDS_Group.hxx"
44 #include "SMESHDS_GroupOnGeom.hxx"
45 #include "SMESH_Controls.hxx"
46 #include "SMESH_File.hxx"
47 #include "SMESH_Filter_i.hxx"
48 #include "SMESH_Gen_i.hxx"
49 #include "SMESH_Group.hxx"
50 #include "SMESH_Group_i.hxx"
51 #include "SMESH_Mesh.hxx"
52 #include "SMESH_MeshAlgos.hxx"
53 #include "SMESH_MeshEditor.hxx"
54 #include "SMESH_MeshEditor_i.hxx"
55 #include "SMESH_MeshPartDS.hxx"
56 #include "SMESH_MesherHelper.hxx"
57 #include "SMESH_PreMeshInfo.hxx"
58 #include "SMESH_PythonDump.hxx"
59 #include "SMESH_subMesh_i.hxx"
60
61 #include <SALOMEDS_Attributes_wrap.hxx>
62 #include <SALOMEDS_wrap.hxx>
63 #include <Utils_ExceptHandlers.hxx>
64 #include <utilities.h>
65
66 #include <GEOMImpl_Types.hxx>
67 #include <GEOM_wrap.hxx>
68
69 // OCCT Includes
70 #include <BRep_Builder.hxx>
71 #include <Standard_ErrorHandler.hxx>
72 #include <TColStd_MapOfInteger.hxx>
73 #include <TopExp.hxx>
74 #include <TopExp_Explorer.hxx>
75 #include <TopTools_MapIteratorOfMapOfShape.hxx>
76 #include <TopTools_MapOfShape.hxx>
77 #include <TopoDS_Compound.hxx>
78
79 // STL Includes
80 #include <algorithm>
81 #include <iostream>
82 #include <sstream>
83
84 #include <vtkUnstructuredGridWriter.h>
85
86 // to pass CORBA exception through SMESH_TRY
87 #define SMY_OWN_CATCH catch( SALOME::SALOME_Exception& se ) { throw se; }
88
89 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
90
91 #ifdef _DEBUG_
92 static int MYDEBUG = 0;
93 #else
94 static int MYDEBUG = 0;
95 #endif
96
97 using namespace std;
98 using SMESH::TPythonDump;
99 using SMESH::TVar;
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 : SALOME::GenericObj_i( thePOA )
112 {
113   _impl          = NULL;
114   _gen_i         = gen_i;
115   _id            = _idGenerator++;
116   _editor        = NULL;
117   _previewEditor = NULL;
118   _preMeshInfo   = NULL;
119   _mainShapeTick = 0;
120 }
121
122 //=============================================================================
123 /*!
124  *  Destructor
125  */
126 //=============================================================================
127
128 SMESH_Mesh_i::~SMESH_Mesh_i()
129 {
130   // destroy groups
131   map<int, SMESH::SMESH_GroupBase_ptr>::iterator itGr;
132   for (itGr = _mapGroups.begin(); itGr != _mapGroups.end(); itGr++)
133     if (SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>(itGr->second))
134     {
135       aGroup->UnRegister();
136       SMESH::SMESH_GroupBase_var( itGr->second );
137     }
138   _mapGroups.clear();
139
140   // destroy submeshes
141   map<int, SMESH::SMESH_subMesh_ptr>::iterator itSM;
142   for ( itSM = _mapSubMeshIor.begin(); itSM != _mapSubMeshIor.end(); itSM++ )
143     if ( SMESH_subMesh_i* aSubMesh = SMESH::DownCast<SMESH_subMesh_i*>( itSM->second ))
144     {
145       aSubMesh->UnRegister();
146       SMESH::SMESH_subMesh_var( itSM->second );
147     }
148   _mapSubMeshIor.clear();
149
150   // destroy hypotheses. _mapHypo contains all hyps ever been assigned
151   map<int, SMESH::SMESH_Hypothesis_ptr>::iterator itH;
152   for ( itH = _mapHypo.begin(); itH != _mapHypo.end(); itH++ ) {
153     if ( SMESH_Hypothesis_i* hyp_i = SMESH::DownCast<SMESH_Hypothesis_i*>( itH->second ))
154       if ( SMESH_Hypothesis * smHyp = _impl->GetHypothesis( itH->first ))
155         if ( _impl->GetMeshDS()->IsUsedHypothesis( smHyp ))
156           hyp_i->UnRegister();
157
158     SMESH::SMESH_Hypothesis_var( itH->second ); // decref CORBA object
159   }
160   _mapHypo.clear();
161
162   // clear cached shapes if no more meshes remain; (the cache is blame,
163   // together with publishing, of spent time increasing in issue 22874)
164   if ( _impl->NbMeshes() == 1 )
165     _gen_i->GetShapeReader()->ClearClientBuffer();
166
167   delete _editor; _editor = NULL;
168   delete _previewEditor; _previewEditor = NULL;
169   delete _impl; _impl = NULL;
170   delete _preMeshInfo; _preMeshInfo = NULL;
171 }
172
173 //=============================================================================
174 /*!
175  *  SetShape
176  *
177  *  Associates <this> mesh with <theShape> and puts a reference
178  *  to <theShape> into the current study;
179  *  the previous shape is substituted by the new one.
180  */
181 //=============================================================================
182
183 void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
184     throw (SALOME::SALOME_Exception)
185 {
186   Unexpect aCatch(SALOME_SalomeException);
187   try {
188     _impl->ShapeToMesh( _gen_i->GeomObjectToShape( theShapeObject ));
189   }
190   catch(SALOME_Exception & S_ex) {
191     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
192   }
193   // to track changes of GEOM groups
194   SMESH::SMESH_Mesh_var mesh = _this();
195   addGeomGroupData( theShapeObject, mesh );
196   if ( !CORBA::is_nil( theShapeObject ))
197     _mainShapeTick = theShapeObject->GetTick();
198 }
199
200 //================================================================================
201 /*!
202  * \brief return true if mesh has a shape to build a shape on
203  */
204 //================================================================================
205
206 CORBA::Boolean SMESH_Mesh_i::HasShapeToMesh()
207   throw (SALOME::SALOME_Exception)
208 {
209   Unexpect aCatch(SALOME_SalomeException);
210   bool res = false;
211   try {
212     res = _impl->HasShapeToMesh();
213   }
214   catch(SALOME_Exception & S_ex) {
215     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
216   }
217   return res;
218 }
219
220 //=======================================================================
221 //function : GetShapeToMesh
222 //purpose  :
223 //=======================================================================
224
225 GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
226   throw (SALOME::SALOME_Exception)
227 {
228   Unexpect aCatch(SALOME_SalomeException);
229   GEOM::GEOM_Object_var aShapeObj;
230   try {
231     TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
232     if ( !S.IsNull() )
233     {
234       aShapeObj = _gen_i->ShapeToGeomObject( S );
235       if ( aShapeObj->_is_nil() )
236       {
237         // S was removed from GEOM_Client by newGroupShape() called by other mesh;
238         // find GEOM_Object by entry (IPAL52735)
239         list<TGeomGroupData>::iterator data = _geomGroupData.begin();
240         for ( ; data != _geomGroupData.end(); ++data )
241           if ( data->_smeshObject->_is_equivalent( _this() ))
242           {
243             SALOMEDS::SObject_wrap so = _gen_i->getStudyServant()->FindObjectID( data->_groupEntry.c_str() );
244             CORBA::Object_var     obj = _gen_i->SObjectToObject( so );
245             aShapeObj = GEOM::GEOM_Object::_narrow( obj );
246             break;
247           }
248       }
249     }
250   }
251   catch(SALOME_Exception & S_ex) {
252     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
253   }
254   return aShapeObj._retn();
255 }
256
257 //================================================================================
258 /*!
259 * \brief Replaces a shape in the mesh
260 */
261 //================================================================================
262 void SMESH_Mesh_i::ReplaceShape(GEOM::GEOM_Object_ptr theNewGeom)
263   throw (SALOME::SALOME_Exception)
264 {
265   TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
266   GEOM_Client* geomClient = _gen_i->GetShapeReader();
267   TCollection_AsciiString aIOR;
268   if (geomClient->Find(S, aIOR)) {
269     geomClient->RemoveShapeFromBuffer(aIOR);
270   }
271   _impl->UndefShapeToMesh();
272   SetShape(theNewGeom);
273 }
274
275 //================================================================================
276 /*!
277  * \brief Return false if the mesh is not yet fully loaded from the study file
278  */
279 //================================================================================
280
281 CORBA::Boolean SMESH_Mesh_i::IsLoaded() throw (SALOME::SALOME_Exception)
282 {
283   Unexpect aCatch(SALOME_SalomeException);
284   return !_preMeshInfo;
285 }
286
287 //================================================================================
288 /*!
289  * \brief Load full mesh data from the study file
290  */
291 //================================================================================
292
293 void SMESH_Mesh_i::Load() throw (SALOME::SALOME_Exception)
294 {
295   Unexpect aCatch(SALOME_SalomeException);
296   if ( _preMeshInfo )
297     _preMeshInfo->FullLoadFromFile();
298 }
299
300 //================================================================================
301 /*!
302  * \brief Remove all nodes and elements
303  */
304 //================================================================================
305
306 void SMESH_Mesh_i::Clear() throw (SALOME::SALOME_Exception)
307 {
308   Unexpect aCatch(SALOME_SalomeException);
309   if ( _preMeshInfo )
310     _preMeshInfo->ForgetOrLoad(); // load in case if !HasShapeToMesh()
311
312   try {
313     _impl->Clear();
314     //CheckGeomGroupModif(); // issue 20145
315   }
316   catch(SALOME_Exception & S_ex) {
317     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
318   }
319
320   TPythonDump() <<  SMESH::SMESH_Mesh_var(_this()) << ".Clear()";
321
322   SMESH::SMESH_Mesh_var mesh = _this();
323   _gen_i->UpdateIcons( mesh );
324 }
325
326 //================================================================================
327 /*!
328  * \brief Remove all nodes and elements for indicated shape
329  */
330 //================================================================================
331
332 void SMESH_Mesh_i::ClearSubMesh(CORBA::Long ShapeID)
333   throw (SALOME::SALOME_Exception)
334 {
335   Unexpect aCatch(SALOME_SalomeException);
336   if ( _preMeshInfo )
337     _preMeshInfo->FullLoadFromFile();
338
339   try {
340     _impl->ClearSubMesh( ShapeID );
341   }
342   catch(SALOME_Exception & S_ex) {
343     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
344   }
345   _impl->GetMeshDS()->Modified();
346
347   TPythonDump() <<  SMESH::SMESH_Mesh_var(_this()) << ".ClearSubMesh( " << ShapeID << " )";
348 }
349
350 //=============================================================================
351 /*!
352  * Convert enum Driver_Mesh::Status to SMESH::DriverMED_ReadStatus
353  */
354 //=============================================================================
355
356 static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
357 {
358   SMESH::DriverMED_ReadStatus res;
359   switch (theStatus)
360   {
361   case DriverMED_R_SMESHDS_Mesh::DRS_OK:
362     res = SMESH::DRS_OK; break;
363   case DriverMED_R_SMESHDS_Mesh::DRS_EMPTY:
364     res = SMESH::DRS_EMPTY; break;
365   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_RENUMBER:
366     res = SMESH::DRS_WARN_RENUMBER; break;
367   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
368     res = SMESH::DRS_WARN_SKIP_ELEM; break;
369   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_DESCENDING:
370     res = SMESH::DRS_WARN_DESCENDING; break;
371   case DriverMED_R_SMESHDS_Mesh::DRS_FAIL:
372   default:
373     res = SMESH::DRS_FAIL; break;
374   }
375   return res;
376 }
377
378 //=============================================================================
379 /*!
380  * Convert ::SMESH_ComputeError to SMESH::ComputeError
381  */
382 //=============================================================================
383
384 static SMESH::ComputeError* ConvertComputeError( SMESH_ComputeErrorPtr errorPtr )
385 {
386   SMESH::ComputeError_var errVar = new SMESH::ComputeError();
387   errVar->subShapeID = -1;
388   errVar->hasBadMesh = false;
389
390   if ( !errorPtr || errorPtr->IsOK() )
391   {
392     errVar->code = SMESH::COMPERR_OK;
393   }
394   else
395   {
396     errVar->code    = ConvertDriverMEDReadStatus( errorPtr->myName );
397     errVar->comment = errorPtr->myComment.c_str();
398   }
399   return errVar._retn();
400 }
401
402 //=============================================================================
403 /*!
404  *  ImportMEDFile
405  *
406  *  Imports mesh data from MED file
407  */
408 //=============================================================================
409
410 SMESH::DriverMED_ReadStatus
411 SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
412   throw ( SALOME::SALOME_Exception )
413 {
414   Unexpect aCatch(SALOME_SalomeException);
415   int status;
416   try {
417     status = _impl->MEDToMesh( theFileName, 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("ImportMEDFile(): unknown exception", SALOME::BAD_PARAM);
424   }
425
426   CreateGroupServants();
427
428   int major, minor, release;
429   major = minor = release = 0;
430   MED::GetMEDVersion(theFileName, major, minor, release);
431   _medFileInfo           = new SMESH::MedFileInfo();
432   _medFileInfo->fileName = theFileName;
433   _medFileInfo->fileSize = 0;
434   _medFileInfo->major    = major;
435   _medFileInfo->minor    = minor;
436   _medFileInfo->release  = release;
437   _medFileInfo->fileSize = SMESH_File( theFileName ).size();
438
439   return ConvertDriverMEDReadStatus(status);
440 }
441
442 //================================================================================
443 /*!
444  * \brief Imports mesh data from the CGNS file
445  */
446 //================================================================================
447
448 SMESH::DriverMED_ReadStatus SMESH_Mesh_i::ImportCGNSFile( const char*  theFileName,
449                                                           const int    theMeshIndex,
450                                                           std::string& theMeshName )
451   throw ( SALOME::SALOME_Exception )
452 {
453   Unexpect aCatch(SALOME_SalomeException);
454   int status;
455   try {
456     status = _impl->CGNSToMesh( theFileName, theMeshIndex, theMeshName );
457   }
458   catch( SALOME_Exception& S_ex ) {
459     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
460   }
461   catch ( ... ) {
462     THROW_SALOME_CORBA_EXCEPTION("ImportCGNSFile(): unknown exception", SALOME::BAD_PARAM);
463   }
464
465   CreateGroupServants();
466
467   _medFileInfo           = new SMESH::MedFileInfo();
468   _medFileInfo->fileName = theFileName;
469   _medFileInfo->major    = 0;
470   _medFileInfo->minor    = 0;
471   _medFileInfo->release  = 0;
472   _medFileInfo->fileSize = SMESH_File( theFileName ).size();
473
474   return ConvertDriverMEDReadStatus(status);
475 }
476
477 //================================================================================
478 /*!
479  * \brief Return string representation of a MED file version comprising nbDigits
480  */
481 //================================================================================
482
483 char* SMESH_Mesh_i::GetVersionString(CORBA::Long minor, CORBA::Short nbDigits)
484 {
485   string ver = DriverMED_W_SMESHDS_Mesh::GetVersionString(minor,
486                                                           nbDigits);
487   return CORBA::string_dup( ver.c_str() );
488 }
489
490 //================================================================================
491 /*!
492  *  Return the list of med versions compatibles for write/append,
493  *  encoded in 10*major+minor (for instance, code for med 3.2.1 is 32)
494  */
495 //================================================================================
496 SMESH::long_array* SMESH_Mesh_i::GetMEDVersionsCompatibleForAppend()
497 {
498   SMESH::long_array_var aResult = new SMESH::long_array();
499   std::vector<int> mvok = MED::GetMEDVersionsAppendCompatible();
500   long nbver = mvok.size();
501   aResult->length( nbver );
502   for ( int i = 0; i < nbver; i++ )
503     aResult[i] = mvok[i];
504   return aResult._retn();
505 }
506
507 //=============================================================================
508 /*!
509  *  ImportUNVFile
510  *
511  *  Imports mesh data from MED file
512  */
513 //=============================================================================
514
515 int SMESH_Mesh_i::ImportUNVFile( const char* theFileName )
516   throw ( SALOME::SALOME_Exception )
517 {
518   SMESH_TRY;
519
520   // Read mesh with name = <theMeshName> into SMESH_Mesh
521   _impl->UNVToMesh( theFileName );
522
523   CreateGroupServants();
524
525   _medFileInfo           = new SMESH::MedFileInfo();
526   _medFileInfo->fileName = theFileName;
527   _medFileInfo->major    = 0;
528   _medFileInfo->minor    = 0;
529   _medFileInfo->release  = 0;
530   _medFileInfo->fileSize = SMESH_File( theFileName ).size();
531
532   SMESH_CATCH( SMESH::throwCorbaException );
533
534   return 1;
535 }
536
537 //=============================================================================
538 /*!
539  *  ImportSTLFile
540  *
541  *  Imports mesh data from STL file
542  */
543 //=============================================================================
544 int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
545   throw ( SALOME::SALOME_Exception )
546 {
547   SMESH_TRY;
548
549   // Read mesh with name = <theMeshName> into SMESH_Mesh
550   std::string name = _impl->STLToMesh( theFileName );
551   if ( !name.empty() )
552   {
553     SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( _this() );
554     _gen_i->SetName( meshSO, name.c_str() );
555   }
556   _medFileInfo           = new SMESH::MedFileInfo();
557   _medFileInfo->fileName = theFileName;
558   _medFileInfo->major    = 0;
559   _medFileInfo->minor    = 0;
560   _medFileInfo->release  = 0;
561   _medFileInfo->fileSize = SMESH_File( theFileName ).size();
562
563   SMESH_CATCH( SMESH::throwCorbaException );
564
565   return 1;
566 }
567
568 //================================================================================
569 /*!
570  * \brief Function used in SMESH_CATCH by ImportGMFFile()
571  */
572 //================================================================================
573
574 namespace
575 {
576   SMESH_ComputeErrorPtr exceptionToComputeError(const char* excText)
577   {
578     return SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, excText );
579   }
580 }
581
582 //================================================================================
583 /*!
584  * \brief Imports data from a GMF file and returns an error description
585  */
586 //================================================================================
587
588 SMESH::ComputeError* SMESH_Mesh_i::ImportGMFFile( const char* theFileName,
589                                                   bool        theMakeRequiredGroups )
590   throw (SALOME::SALOME_Exception)
591 {
592   SMESH_ComputeErrorPtr error;
593
594 #undef SMESH_CAUGHT
595 #define SMESH_CAUGHT error =
596   SMESH_TRY;
597
598   error = _impl->GMFToMesh( theFileName, theMakeRequiredGroups );
599
600   _medFileInfo           = new SMESH::MedFileInfo();
601   _medFileInfo->fileName = theFileName;
602   _medFileInfo->major    = 0;
603   _medFileInfo->minor    = 0;
604   _medFileInfo->release  = 0;
605   _medFileInfo->fileSize = SMESH_File( theFileName ).size();
606
607   SMESH_CATCH( exceptionToComputeError );
608 #undef SMESH_CAUGHT
609 #define SMESH_CAUGHT
610
611   CreateGroupServants();
612
613   return ConvertComputeError( error );
614 }
615
616 //=============================================================================
617 /*!
618  *
619  */
620 //=============================================================================
621
622 #define RETURNCASE(hyp_stat) case SMESH_Hypothesis::hyp_stat: return SMESH::hyp_stat;
623
624 SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
625                          (SMESH_Hypothesis::Hypothesis_Status theStatus)
626 {
627   switch (theStatus) {
628   RETURNCASE( HYP_OK            );
629   RETURNCASE( HYP_MISSING       );
630   RETURNCASE( HYP_CONCURRENT    );
631   RETURNCASE( HYP_BAD_PARAMETER );
632   RETURNCASE( HYP_HIDDEN_ALGO   );
633   RETURNCASE( HYP_HIDING_ALGO   );
634   RETURNCASE( HYP_UNKNOWN_FATAL );
635   RETURNCASE( HYP_INCOMPATIBLE  );
636   RETURNCASE( HYP_NOTCONFORM    );
637   RETURNCASE( HYP_ALREADY_EXIST );
638   RETURNCASE( HYP_BAD_DIM       );
639   RETURNCASE( HYP_BAD_SUBSHAPE  );
640   RETURNCASE( HYP_BAD_GEOMETRY  );
641   RETURNCASE( HYP_NEED_SHAPE    );
642   RETURNCASE( HYP_INCOMPAT_HYPS );
643   default:;
644   }
645   return SMESH::HYP_UNKNOWN_FATAL;
646 }
647
648 //=============================================================================
649 /*!
650  *  AddHypothesis
651  *
652  *  calls internal addHypothesis() and then adds a reference to <anHyp> under
653  *  the SObject actually having a reference to <aSubShape>.
654  *  NB: For this method to work, it is necessary to add a reference to sub-shape first.
655  */
656 //=============================================================================
657
658 SMESH::Hypothesis_Status
659 SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
660                             SMESH::SMESH_Hypothesis_ptr anHyp,
661                             CORBA::String_out           anErrorText)
662   throw(SALOME::SALOME_Exception)
663 {
664   Unexpect aCatch(SALOME_SalomeException);
665   if ( _preMeshInfo )
666     _preMeshInfo->ForgetOrLoad();
667
668   std::string error;
669   SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShape, anHyp, &error );
670   anErrorText = error.c_str();
671
672   SMESH::SMESH_Mesh_var mesh( _this() );
673   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
674   {
675     _gen_i->AddHypothesisToShape( mesh, aSubShape, anHyp );
676     _gen_i->UpdateIcons( mesh );
677   }
678   if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
679
680   // Update Python script
681   TPythonDump() << "status = " << mesh << ".AddHypothesis( "
682                 << aSubShape << ", " << anHyp << " )";
683
684   return ConvertHypothesisStatus(status);
685 }
686
687 //=============================================================================
688 /*!
689  *
690  */
691 //=============================================================================
692
693 SMESH_Hypothesis::Hypothesis_Status
694 SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
695                             SMESH::SMESH_Hypothesis_ptr anHyp,
696                             std::string*                anErrorText)
697 {
698   if(MYDEBUG) MESSAGE("addHypothesis");
699
700   if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
701     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",SALOME::BAD_PARAM);
702
703   if (CORBA::is_nil( anHyp ))
704     THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",SALOME::BAD_PARAM);
705
706   SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
707   try
708   {
709     TopoDS_Shape myLocSubShape;
710     //use PseudoShape in case if mesh has no shape
711     if(HasShapeToMesh())
712       myLocSubShape = _gen_i->GeomObjectToShape( aSubShape);
713     else
714       myLocSubShape = _impl->GetShapeToMesh();
715
716     const int hypId = anHyp->GetId();
717     std::string error;
718     status = _impl->AddHypothesis( myLocSubShape, hypId, &error );
719     if ( !SMESH_Hypothesis::IsStatusFatal(status) )
720     {
721       _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( anHyp );
722       anHyp->Register();
723       // assure there is a corresponding submesh
724       if ( !_impl->IsMainShape( myLocSubShape )) {
725         int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
726         if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
727           SMESH::SMESH_subMesh_var( createSubMesh( aSubShape ));
728       }
729     }
730     else if ( anErrorText )
731     {
732       *anErrorText = error;
733     }
734   }
735   catch(SALOME_Exception & S_ex)
736   {
737     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
738   }
739   return status;
740 }
741
742 //=============================================================================
743 /*!
744  *
745  */
746 //=============================================================================
747
748 SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShape,
749                                                         SMESH::SMESH_Hypothesis_ptr anHyp)
750   throw(SALOME::SALOME_Exception)
751 {
752   Unexpect aCatch(SALOME_SalomeException);
753   if ( _preMeshInfo )
754     _preMeshInfo->ForgetOrLoad();
755
756   SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShape, anHyp );
757   SMESH::SMESH_Mesh_var mesh = _this();
758
759   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
760   {
761     _gen_i->RemoveHypothesisFromShape( mesh, aSubShape, anHyp );
762     _gen_i->UpdateIcons( mesh );
763   }
764   // Update Python script
765   if(_impl->HasShapeToMesh())
766     TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
767                   << aSubShape << ", " << anHyp << " )";
768   else
769     TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
770                   << anHyp << " )";
771
772   return ConvertHypothesisStatus(status);
773 }
774
775 //=============================================================================
776 /*!
777  *
778  */
779 //=============================================================================
780
781 SMESH_Hypothesis::Hypothesis_Status
782 SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
783                                SMESH::SMESH_Hypothesis_ptr anHyp)
784 {
785   if(MYDEBUG) MESSAGE("removeHypothesis()");
786
787   if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
788     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
789
790   if (CORBA::is_nil( anHyp ))
791     THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference", SALOME::BAD_PARAM);
792
793   if ( _preMeshInfo )
794     _preMeshInfo->ForgetOrLoad();
795
796   SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
797   try
798   {
799     TopoDS_Shape myLocSubShape;
800     //use PseudoShape in case if mesh has no shape
801     if( _impl->HasShapeToMesh() )
802       myLocSubShape = _gen_i->GeomObjectToShape( aSubShape );
803     else
804       myLocSubShape = _impl->GetShapeToMesh();
805
806     const int hypId = anHyp->GetId();
807     status = _impl->RemoveHypothesis(myLocSubShape, hypId);
808     if ( !SMESH_Hypothesis::IsStatusFatal(status) )
809     {
810       // _mapHypo.erase( hypId ); EAP: hyp can be used on many sub-shapes
811       anHyp->UnRegister();
812     }
813   }
814   catch(SALOME_Exception & S_ex)
815   {
816     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
817   }
818   return status;
819 }
820
821 //=============================================================================
822 /*!
823  *
824  */
825 //=============================================================================
826
827 SMESH::ListOfHypothesis *
828 SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShape)
829 throw(SALOME::SALOME_Exception)
830 {
831   Unexpect aCatch(SALOME_SalomeException);
832   if (MYDEBUG) MESSAGE("GetHypothesisList");
833   if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShape))
834     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
835
836   SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
837
838   try {
839     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
840     if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() )
841       myLocSubShape = _impl->GetShapeToMesh();
842     const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
843     int i = 0, n = aLocalList.size();
844     aList->length( n );
845
846     list<const SMESHDS_Hypothesis*>::const_iterator aHyp = aLocalList.begin();
847     std::map<int, SMESH::SMESH_Hypothesis_ptr>::iterator id_hypptr;
848     for ( ; i < n && aHyp != aLocalList.end(); aHyp++ )
849     {
850       id_hypptr = _mapHypo.find( (*aHyp)->GetID() );
851       if ( id_hypptr != _mapHypo.end() )
852         aList[i++] = SMESH::SMESH_Hypothesis::_narrow( id_hypptr->second );
853     }
854     aList->length( i );
855   }
856   catch(SALOME_Exception & S_ex) {
857     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
858   }
859
860   return aList._retn();
861 }
862
863 SMESH::submesh_array* SMESH_Mesh_i::GetSubMeshes() throw (SALOME::SALOME_Exception)
864 {
865   Unexpect aCatch(SALOME_SalomeException);
866   if (MYDEBUG) MESSAGE("GetSubMeshes");
867
868   SMESH::submesh_array_var aList = new SMESH::submesh_array();
869
870   // Python Dump
871   TPythonDump aPythonDump;
872   if ( !_mapSubMeshIor.empty() )
873     aPythonDump << "[ ";
874
875   try {
876     aList->length( _mapSubMeshIor.size() );
877     int i = 0;
878     map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.begin();
879     for ( ; it != _mapSubMeshIor.end(); it++ ) {
880       if ( CORBA::is_nil( it->second )) continue;
881       aList[i++] = SMESH::SMESH_subMesh::_duplicate( it->second );
882       // Python Dump
883       if (i > 1) aPythonDump << ", ";
884       aPythonDump << it->second;
885     }
886     aList->length( i );
887   }
888   catch(SALOME_Exception & S_ex) {
889     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
890   }
891
892   // Update Python script
893   if ( !_mapSubMeshIor.empty() )
894     aPythonDump << " ] = " << SMESH::SMESH_Mesh_var( _this() ) << ".GetSubMeshes()";
895
896   return aList._retn();
897 }
898
899 //=============================================================================
900 /*!
901  *
902  */
903 //=============================================================================
904
905 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShape,
906                                                   const char*           theName )
907      throw(SALOME::SALOME_Exception)
908 {
909   Unexpect aCatch(SALOME_SalomeException);
910   if (CORBA::is_nil(aSubShape))
911     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
912
913   SMESH::SMESH_subMesh_var subMesh;
914   SMESH::SMESH_Mesh_var    aMesh = _this();
915   try {
916     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
917
918     //Get or Create the SMESH_subMesh object implementation
919
920     int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
921
922     if ( !subMeshId && ! _impl->GetMeshDS()->IsGroupOfSubShapes( myLocSubShape ))
923     {
924       TopoDS_Iterator it( myLocSubShape );
925       if ( it.More() )
926         THROW_SALOME_CORBA_EXCEPTION("not sub-shape of the main shape", SALOME::BAD_PARAM);
927     }
928     subMesh = getSubMesh( subMeshId );
929
930     // create a new subMesh object servant if there is none for the shape
931     if ( subMesh->_is_nil() )
932       subMesh = createSubMesh( aSubShape );
933     if ( _gen_i->CanPublishInStudy( subMesh ))
934     {
935       SALOMEDS::SObject_wrap aSO =
936         _gen_i->PublishSubMesh( aMesh, subMesh, aSubShape, theName );
937       if ( !aSO->_is_nil()) {
938         // Update Python script
939         TPythonDump() << aSO << " = " << aMesh << ".GetSubMesh( "
940                       << aSubShape << ", '" << theName << "' )";
941       }
942     }
943   }
944   catch(SALOME_Exception & S_ex) {
945     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
946   }
947   return subMesh._retn();
948 }
949
950 //=============================================================================
951 /*!
952  *
953  */
954 //=============================================================================
955
956 void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
957   throw (SALOME::SALOME_Exception)
958 {
959   SMESH_TRY;
960
961   if ( theSubMesh->_is_nil() )
962     return;
963
964   GEOM::GEOM_Object_var aSubShape;
965   // Remove submesh's SObject
966   SALOMEDS::SObject_wrap anSO = _gen_i->ObjectToSObject( theSubMesh );
967   if ( !anSO->_is_nil() ) {
968     long aTag = SMESH_Gen_i::GetRefOnShapeTag();
969     SALOMEDS::SObject_wrap anObj, aRef;
970     if ( anSO->FindSubObject( aTag, anObj.inout() ) &&
971          anObj->ReferencedObject( aRef.inout() ))
972     {
973       CORBA::Object_var obj = aRef->GetObject();
974       aSubShape = GEOM::GEOM_Object::_narrow( obj );
975     }
976     // if ( aSubShape->_is_nil() ) // not published shape (IPAL13617)
977     //   aSubShape = theSubMesh->GetSubShape();
978
979     SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
980     builder->RemoveObjectWithChildren( anSO );
981
982     // Update Python script
983     TPythonDump() << SMESH::SMESH_Mesh_var( _this() ) << ".RemoveSubMesh( " << anSO << " )";
984   }
985
986   if ( removeSubMesh( theSubMesh, aSubShape.in() ))
987     if ( _preMeshInfo )
988       _preMeshInfo->ForgetOrLoad();
989
990   SMESH_CATCH( SMESH::throwCorbaException );
991 }
992
993 //=============================================================================
994 /*!
995  *
996  */
997 //=============================================================================
998
999 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType,
1000                                                   const char*        theName )
1001   throw(SALOME::SALOME_Exception)
1002 {
1003   Unexpect aCatch(SALOME_SalomeException);
1004   if ( _preMeshInfo )
1005     _preMeshInfo->FullLoadFromFile();
1006
1007   SMESH::SMESH_Group_var aNewGroup =
1008     SMESH::SMESH_Group::_narrow( createGroup( theElemType, theName ));
1009
1010   if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1011   {
1012     SMESH::SMESH_Mesh_var mesh = _this();
1013     SALOMEDS::SObject_wrap aSO =
1014       _gen_i->PublishGroup( mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName);
1015     if ( !aSO->_is_nil())
1016       // Update Python script
1017       TPythonDump() << aSO << " = " << mesh << ".CreateGroup( "
1018                     << theElemType << ", '" << theName << "' )";
1019   }
1020   return aNewGroup._retn();
1021 }
1022
1023 //=============================================================================
1024 /*!
1025  *
1026  */
1027 //=============================================================================
1028 SMESH::SMESH_GroupOnGeom_ptr
1029 SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType    theElemType,
1030                                    const char*           theName,
1031                                    GEOM::GEOM_Object_ptr theGeomObj)
1032   throw(SALOME::SALOME_Exception)
1033 {
1034   Unexpect aCatch(SALOME_SalomeException);
1035   if ( _preMeshInfo )
1036     _preMeshInfo->FullLoadFromFile();
1037
1038   SMESH::SMESH_GroupOnGeom_var aNewGroup;
1039
1040   TopoDS_Shape aShape = _gen_i->GeomObjectToShape( theGeomObj );
1041   if ( !aShape.IsNull() )
1042   {
1043     aNewGroup =
1044       SMESH::SMESH_GroupOnGeom::_narrow( createGroup( theElemType, theName, /*id=*/-1, aShape ));
1045
1046     if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1047     {
1048       SMESH::SMESH_Mesh_var mesh = _this();
1049       SALOMEDS::SObject_wrap aSO =
1050         _gen_i->PublishGroup( mesh, aNewGroup, theGeomObj, theName );
1051       if ( !aSO->_is_nil())
1052         TPythonDump() << aSO << " = " << mesh << ".CreateGroupFromGEOM( "
1053                       << theElemType << ", '" << theName << "', " << theGeomObj << " )";
1054     }
1055   }
1056
1057   return aNewGroup._retn();
1058 }
1059
1060 //================================================================================
1061 /*!
1062  * \brief Creates a group whose contents is defined by filter
1063  *  \param theElemType - group type
1064  *  \param theName - group name
1065  *  \param theFilter - the filter
1066  *  \retval SMESH::SMESH_GroupOnFilter_ptr - group defined by filter
1067  */
1068 //================================================================================
1069
1070 SMESH::SMESH_GroupOnFilter_ptr
1071 SMESH_Mesh_i::CreateGroupFromFilter(SMESH::ElementType theElemType,
1072                                     const char*        theName,
1073                                     SMESH::Filter_ptr  theFilter )
1074   throw (SALOME::SALOME_Exception)
1075 {
1076   Unexpect aCatch(SALOME_SalomeException);
1077   if ( _preMeshInfo )
1078     _preMeshInfo->FullLoadFromFile();
1079
1080   if ( CORBA::is_nil( theFilter ))
1081     THROW_SALOME_CORBA_EXCEPTION("NULL filter", SALOME::BAD_PARAM);
1082
1083   SMESH_PredicatePtr predicate = SMESH_GroupOnFilter_i::GetPredicate( theFilter );
1084   if ( !predicate )
1085     THROW_SALOME_CORBA_EXCEPTION("Invalid filter", SALOME::BAD_PARAM);
1086
1087   SMESH::SMESH_GroupOnFilter_var aNewGroup = SMESH::SMESH_GroupOnFilter::_narrow
1088     ( createGroup( theElemType, theName, /*id=*/-1, TopoDS_Shape(), predicate ));
1089
1090   TPythonDump pd;
1091   if ( !aNewGroup->_is_nil() )
1092     aNewGroup->SetFilter( theFilter );
1093
1094   if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1095   {
1096     SMESH::SMESH_Mesh_var mesh = _this();
1097     SALOMEDS::SObject_wrap aSO =
1098       _gen_i->PublishGroup( mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName );
1099
1100     if ( !aSO->_is_nil())
1101       pd << aSO << " = " << mesh << ".CreateGroupFromFilter( "
1102          << theElemType << ", '" << theName << "', " << theFilter << " )";
1103   }
1104   return aNewGroup._retn();
1105 }
1106
1107 //=============================================================================
1108 /*!
1109  *
1110  */
1111 //=============================================================================
1112
1113 void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
1114   throw (SALOME::SALOME_Exception)
1115 {
1116   if ( theGroup->_is_nil() )
1117     return;
1118
1119   SMESH_TRY;
1120
1121   SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
1122   if ( !aGroup )
1123     return;
1124
1125   if ( aGroup->GetMeshServant() != this )
1126     THROW_SALOME_CORBA_EXCEPTION( "RemoveGroup(): group does not belong to this mesh",
1127                                   SALOME::BAD_PARAM );
1128
1129   SALOMEDS::SObject_wrap aGroupSO = _gen_i->ObjectToSObject( theGroup );
1130   if ( !aGroupSO->_is_nil() )
1131   {
1132     // Update Python script
1133     TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".RemoveGroup( " << aGroupSO << " )";
1134
1135     // Remove group's SObject
1136     SALOMEDS::StudyBuilder_var builder = SMESH_Gen_i::getStudyServant()->NewBuilder();
1137     builder->RemoveObjectWithChildren( aGroupSO );
1138   }
1139   aGroup->Modified(/*removed=*/true); // notify dependent Filter with FT_BelongToMeshGroup criterion
1140
1141   // Remove the group from SMESH data structures
1142   removeGroup( aGroup->GetLocalID() );
1143
1144   SMESH_CATCH( SMESH::throwCorbaException );
1145 }
1146
1147 //=============================================================================
1148 /*!
1149  *  Remove group with its contents
1150  */
1151 //=============================================================================
1152
1153 void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup )
1154   throw (SALOME::SALOME_Exception)
1155 {
1156   SMESH_TRY;
1157   if ( _preMeshInfo )
1158     _preMeshInfo->FullLoadFromFile();
1159
1160   if ( theGroup->_is_nil() )
1161     return;
1162
1163   SMESH_GroupBase_i* groupImpl = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup );
1164   if ( !groupImpl || groupImpl->GetMeshServant() != this )
1165     THROW_SALOME_CORBA_EXCEPTION( "RemoveGroupWithContents(): group does not belong to this mesh",
1166                                   SALOME::BAD_PARAM);
1167
1168   vector<int> nodeIds; // to remove nodes becoming free
1169   bool isNodal = ( theGroup->GetType() == SMESH::NODE );
1170   if ( !isNodal && !theGroup->IsEmpty() )
1171   {
1172     CORBA::Long elemID = theGroup->GetID( 1 );
1173     int nbElemNodes = GetElemNbNodes( elemID );
1174     if ( nbElemNodes > 0 )
1175       nodeIds.reserve( theGroup->Size() * nbElemNodes );
1176   }
1177
1178   // Retrieve contents
1179   SMESH::SMESH_IDSource_var idSrc = SMESH::SMESH_IDSource::_narrow( theGroup );
1180   SMDS_ElemIteratorPtr     elemIt = GetElements( idSrc, theGroup->GetType() );
1181   SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > elemBeg( elemIt ), elemEnd;
1182   std::vector< const SMDS_MeshElement* > elems( theGroup->Size() );
1183   elems.assign( elemBeg, elemEnd );
1184
1185   TPythonDump pyDump; // Suppress dump from RemoveGroup()
1186
1187   // Remove group
1188   RemoveGroup( theGroup );
1189
1190   // Remove contents
1191   for ( size_t i = 0; i < elems.size(); ++i )
1192   {
1193     // if ( !_impl->GetMeshDS()->Contains( elems[i] ))
1194     //   continue;
1195     if ( !isNodal )
1196     {
1197       for ( SMDS_ElemIteratorPtr nIt = elems[i]->nodesIterator(); nIt->more(); )
1198         nodeIds.push_back( nIt->next()->GetID() );
1199
1200       _impl->GetMeshDS()->RemoveFreeElement( elems[i], /*sm=*/0 );
1201     }
1202     else
1203     {
1204       _impl->GetMeshDS()->RemoveElement( elems[i] );
1205     }
1206   }
1207
1208   // Remove free nodes
1209   for ( size_t i = 0 ; i < nodeIds.size(); ++i )
1210     if ( const SMDS_MeshNode* n = _impl->GetMeshDS()->FindNode( nodeIds[i] ))
1211       if ( n->NbInverseElements() == 0 )
1212         _impl->GetMeshDS()->RemoveFreeNode( n, /*sm=*/0 );
1213
1214   // Update Python script (theGroup must be alive for this)
1215   pyDump << SMESH::SMESH_Mesh_var(_this())
1216          << ".RemoveGroupWithContents( " << theGroup << " )";
1217
1218   SMESH_CATCH( SMESH::throwCorbaException );
1219 }
1220
1221 //================================================================================
1222 /*!
1223  * \brief Get the list of groups existing in the mesh
1224  *  \retval SMESH::ListOfGroups * - list of groups
1225  */
1226 //================================================================================
1227
1228 SMESH::ListOfGroups * SMESH_Mesh_i::GetGroups() throw(SALOME::SALOME_Exception)
1229 {
1230   Unexpect aCatch(SALOME_SalomeException);
1231   if (MYDEBUG) MESSAGE("GetGroups");
1232
1233   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
1234
1235   // Python Dump
1236   TPythonDump aPythonDump;
1237   if ( !_mapGroups.empty() )
1238   {
1239     aPythonDump << "[ ";
1240     try {
1241       aList->length( _mapGroups.size() );
1242       int i = 0;
1243       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
1244       for ( ; it != _mapGroups.end(); it++ ) {
1245         if ( CORBA::is_nil( it->second )) continue;
1246         aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
1247         // Python Dump
1248         if (i > 1) aPythonDump << ", ";
1249         aPythonDump << it->second;
1250       }
1251       aList->length( i );
1252     }
1253     catch(SALOME_Exception & S_ex) {
1254       THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
1255     }
1256     aPythonDump << " ] = " << SMESH::SMESH_Mesh_var(_this()) << ".GetGroups()";
1257   }
1258   return aList._retn();
1259 }
1260
1261 //=============================================================================
1262 /*!
1263  *  Get number of groups existing in the mesh
1264  */
1265 //=============================================================================
1266
1267 CORBA::Long SMESH_Mesh_i::NbGroups() throw (SALOME::SALOME_Exception)
1268 {
1269   Unexpect aCatch(SALOME_SalomeException);
1270   return _mapGroups.size();
1271 }
1272
1273 //=============================================================================
1274 /*!
1275  * New group including all mesh elements present in initial groups is created.
1276  */
1277 //=============================================================================
1278
1279 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1280                                                   SMESH::SMESH_GroupBase_ptr theGroup2,
1281                                                   const char*                theName )
1282   throw (SALOME::SALOME_Exception)
1283 {
1284   SMESH::SMESH_Group_var aResGrp;
1285
1286   SMESH_TRY;
1287   if ( _preMeshInfo )
1288     _preMeshInfo->FullLoadFromFile();
1289
1290   if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1291     THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): NULL Group",
1292                                  SALOME::BAD_PARAM);
1293   if ( theGroup1->GetType() != theGroup2->GetType() )
1294     THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): different group types",
1295                                  SALOME::BAD_PARAM);
1296   TPythonDump pyDump;
1297
1298   // Create Union
1299   aResGrp = CreateGroup( theGroup1->GetType(), theName );
1300   if ( aResGrp->_is_nil() )
1301     return SMESH::SMESH_Group::_nil();
1302
1303   aResGrp->AddFrom( theGroup1 );
1304   aResGrp->AddFrom( theGroup2 );
1305
1306   // Update Python script
1307   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this())
1308          << ".UnionGroups( " << theGroup1 << ", " << theGroup2 << ", '" << theName << "' )";
1309
1310   SMESH_CATCH( SMESH::throwCorbaException );
1311
1312   return aResGrp._retn();
1313 }
1314
1315 //=============================================================================
1316 /*!
1317  * \brief New group including all mesh elements present in initial groups is created.
1318  *  \param theGroups list of groups
1319  *  \param theName name of group to be created
1320  *  \return pointer to the new group
1321  */
1322 //=============================================================================
1323
1324 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionListOfGroups(const SMESH::ListOfGroups& theGroups,
1325                                                        const char*                theName )
1326   throw (SALOME::SALOME_Exception)
1327 {
1328   SMESH::SMESH_Group_var aResGrp;
1329
1330   if ( _preMeshInfo )
1331     _preMeshInfo->FullLoadFromFile();
1332
1333   if ( !theName )
1334     return SMESH::SMESH_Group::_nil();
1335
1336   SMESH_TRY;
1337
1338   // check types
1339   SMESH::ElementType aType = SMESH::ALL;
1340   for ( int g = 0, n = theGroups.length(); g < n; g++ )
1341   {
1342     SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1343     if ( CORBA::is_nil( aGrp ) )
1344       continue;
1345     if ( aType == SMESH::ALL )
1346       aType = aGrp->GetType();
1347     else if ( aType != aGrp->GetType() )
1348       THROW_SALOME_CORBA_EXCEPTION("UnionListOfGroups(): different group types",
1349                                    SALOME::BAD_PARAM);
1350   }
1351   if ( aType == SMESH::ALL )
1352     return SMESH::SMESH_Group::_nil();
1353
1354   TPythonDump pyDump;
1355
1356   // Create Union
1357   aResGrp = CreateGroup( aType, theName );
1358   if ( aResGrp->_is_nil() )
1359     return SMESH::SMESH_Group::_nil();
1360
1361   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".UnionListOfGroups([ ";
1362   for ( int g = 0, n = theGroups.length(); g < n; g++ )
1363   {
1364     SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1365     if ( !CORBA::is_nil( aGrp ) )
1366     {
1367       aResGrp->AddFrom( aGrp );
1368       if ( g > 0 ) pyDump << ", ";
1369       pyDump << aGrp;
1370     }
1371   }
1372   pyDump << " ], '" << theName << "' )";
1373
1374   SMESH_CATCH( SMESH::throwCorbaException );
1375
1376   return aResGrp._retn();
1377 }
1378
1379 //=============================================================================
1380 /*!
1381  *  New group is created. All mesh elements that are
1382  *  present in both initial groups are added to the new one.
1383  */
1384 //=============================================================================
1385
1386 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1387                                                       SMESH::SMESH_GroupBase_ptr theGroup2,
1388                                                       const char*                theName )
1389   throw (SALOME::SALOME_Exception)
1390 {
1391   SMESH::SMESH_Group_var aResGrp;
1392
1393   SMESH_TRY;
1394
1395   if ( _preMeshInfo )
1396     _preMeshInfo->FullLoadFromFile();
1397
1398   if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1399     THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): NULL Group",
1400                                  SALOME::BAD_PARAM);
1401   if ( theGroup1->GetType() != theGroup2->GetType() )
1402     THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): different group types",
1403                                  SALOME::BAD_PARAM);
1404   TPythonDump pyDump;
1405
1406   // Create Intersection
1407   aResGrp = CreateGroup( theGroup1->GetType(), theName );
1408   if ( aResGrp->_is_nil() )
1409     return aResGrp._retn();
1410
1411   SMESHDS_GroupBase* groupDS1 = 0;
1412   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1413     groupDS1 = grp_i->GetGroupDS();
1414
1415   SMESHDS_GroupBase* groupDS2 = 0;
1416   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1417     groupDS2 = grp_i->GetGroupDS();
1418
1419   SMESHDS_Group* resGroupDS = 0;
1420   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1421     resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1422
1423   if ( groupDS1 && groupDS2 && resGroupDS && !groupDS2->IsEmpty() )
1424   {
1425     SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1426     while ( elemIt1->more() )
1427     {
1428       const SMDS_MeshElement* e = elemIt1->next();
1429       if ( groupDS2->Contains( e ))
1430         resGroupDS->SMDSGroup().Add( e );
1431     }
1432   }
1433   // Update Python script
1434   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".IntersectGroups( "
1435          << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1436
1437   SMESH_CATCH( SMESH::throwCorbaException );
1438
1439   return aResGrp._retn();
1440 }
1441
1442 //=============================================================================
1443 /*!
1444   \brief Intersect list of groups. New group is created. All mesh elements that
1445   are present in all initial groups simultaneously are added to the new one.
1446   \param theGroups list of groups
1447   \param theName name of group to be created
1448   \return pointer on the group
1449 */
1450 //=============================================================================
1451 SMESH::SMESH_Group_ptr
1452 SMESH_Mesh_i::IntersectListOfGroups(const SMESH::ListOfGroups& theGroups,
1453                                     const char*                theName )
1454   throw (SALOME::SALOME_Exception)
1455 {
1456   SMESH::SMESH_Group_var aResGrp;
1457
1458   SMESH_TRY;
1459
1460   if ( _preMeshInfo )
1461     _preMeshInfo->FullLoadFromFile();
1462
1463   if ( !theName )
1464     return SMESH::SMESH_Group::_nil();
1465
1466   // check types and get SMESHDS_GroupBase's
1467   SMESH::ElementType aType = SMESH::ALL;
1468   vector< SMESHDS_GroupBase* > groupVec;
1469   for ( int g = 0, n = theGroups.length(); g < n; g++ )
1470   {
1471     SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1472     if ( CORBA::is_nil( aGrp ) )
1473       continue;
1474     if ( aType == SMESH::ALL )
1475       aType = aGrp->GetType();
1476     else if ( aType != aGrp->GetType() )
1477       THROW_SALOME_CORBA_EXCEPTION("IntersectListOfGroups(): different group types",
1478                                    SALOME::BAD_PARAM);
1479
1480     if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1481       if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1482       {
1483         if ( grpDS->IsEmpty() )
1484         {
1485           groupVec.clear();
1486           break;
1487         }
1488         groupVec.push_back( grpDS );
1489       }
1490   }
1491   if ( aType == SMESH::ALL ) // all groups are nil
1492     return SMESH::SMESH_Group::_nil();
1493
1494   TPythonDump pyDump;
1495
1496   // Create a group
1497   aResGrp = CreateGroup( aType, theName );
1498
1499   SMESHDS_Group* resGroupDS = 0;
1500   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1501     resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1502   if ( !resGroupDS || groupVec.empty() )
1503     return aResGrp._retn();
1504
1505   // Fill the group
1506   size_t i, nb = groupVec.size();
1507   SMDS_ElemIteratorPtr elemIt1 = groupVec[0]->GetElements();
1508   while ( elemIt1->more() )
1509   {
1510     const SMDS_MeshElement* e = elemIt1->next();
1511     bool inAll = true;
1512     for ( i = 1; ( i < nb && inAll ); ++i )
1513       inAll = groupVec[i]->Contains( e );
1514
1515     if ( inAll )
1516       resGroupDS->SMDSGroup().Add( e );
1517   }
1518
1519   // Update Python script
1520   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1521          << ".IntersectListOfGroups( " << theGroups << ", '" << theName << "' )";
1522
1523   SMESH_CATCH( SMESH::throwCorbaException );
1524
1525   return aResGrp._retn();
1526 }
1527
1528 //=============================================================================
1529 /*!
1530  *  New group is created. All mesh elements that are present in
1531  *  a main group but is not present in a tool group are added to the new one
1532  */
1533 //=============================================================================
1534
1535 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1536                                                 SMESH::SMESH_GroupBase_ptr theGroup2,
1537                                                 const char*                theName )
1538   throw (SALOME::SALOME_Exception)
1539 {
1540   SMESH::SMESH_Group_var aResGrp;
1541
1542   SMESH_TRY;
1543
1544   if ( _preMeshInfo )
1545     _preMeshInfo->FullLoadFromFile();
1546
1547   if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1548     THROW_SALOME_CORBA_EXCEPTION("CutGroups(): NULL Group",
1549                                  SALOME::BAD_PARAM);
1550   if ( theGroup1->GetType() != theGroup2->GetType() )
1551     THROW_SALOME_CORBA_EXCEPTION("CutGroups(): different group types",
1552                                  SALOME::BAD_PARAM);
1553   TPythonDump pyDump;
1554
1555   aResGrp = CreateGroup( theGroup1->GetType(), theName );
1556   if ( aResGrp->_is_nil() )
1557     return aResGrp._retn();
1558
1559   SMESHDS_GroupBase* groupDS1 = 0;
1560   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1561     groupDS1 = grp_i->GetGroupDS();
1562
1563   SMESHDS_GroupBase* groupDS2 = 0;
1564   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1565     groupDS2 = grp_i->GetGroupDS();
1566
1567   SMESHDS_Group* resGroupDS = 0;
1568   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1569     resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1570
1571   if ( groupDS1 && groupDS2 && resGroupDS )
1572   {
1573     SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1574     while ( elemIt1->more() )
1575     {
1576       const SMDS_MeshElement* e = elemIt1->next();
1577       if ( !groupDS2->Contains( e ))
1578         resGroupDS->SMDSGroup().Add( e );
1579     }
1580   }
1581   // Update Python script
1582   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".CutGroups( "
1583          << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1584
1585   SMESH_CATCH( SMESH::throwCorbaException );
1586
1587   return aResGrp._retn();
1588 }
1589
1590 //=============================================================================
1591 /*!
1592   \brief Cut lists of groups. New group is created. All mesh elements that are
1593   present in main groups but do not present in tool groups are added to the new one
1594   \param theMainGroups list of main groups
1595   \param theToolGroups list of tool groups
1596   \param theName name of group to be created
1597   \return pointer on the group
1598 */
1599 //=============================================================================
1600 SMESH::SMESH_Group_ptr
1601 SMESH_Mesh_i::CutListOfGroups(const SMESH::ListOfGroups& theMainGroups,
1602                               const SMESH::ListOfGroups& theToolGroups,
1603                               const char*                theName )
1604   throw (SALOME::SALOME_Exception)
1605 {
1606   SMESH::SMESH_Group_var aResGrp;
1607
1608   SMESH_TRY;
1609
1610   if ( _preMeshInfo )
1611     _preMeshInfo->FullLoadFromFile();
1612
1613   if ( !theName )
1614     return SMESH::SMESH_Group::_nil();
1615
1616   // check types and get SMESHDS_GroupBase's
1617   SMESH::ElementType aType = SMESH::ALL;
1618   vector< SMESHDS_GroupBase* >   toolGroupVec;
1619   vector< SMDS_ElemIteratorPtr > mainIterVec;
1620
1621   for ( int g = 0, n = theMainGroups.length(); g < n; g++ )
1622   {
1623     SMESH::SMESH_GroupBase_var aGrp = theMainGroups[ g ];
1624     if ( CORBA::is_nil( aGrp ) )
1625       continue;
1626     if ( aType == SMESH::ALL )
1627       aType = aGrp->GetType();
1628     else if ( aType != aGrp->GetType() )
1629       THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
1630                                    SALOME::BAD_PARAM);
1631     if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1632       if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1633         if ( !grpDS->IsEmpty() )
1634           mainIterVec.push_back( grpDS->GetElements() );
1635   }
1636   if ( aType == SMESH::ALL ) // all main groups are nil
1637     return SMESH::SMESH_Group::_nil();
1638   if ( mainIterVec.empty() ) // all main groups are empty
1639     return aResGrp._retn();
1640
1641   for ( int g = 0, n = theToolGroups.length(); g < n; g++ )
1642   {
1643     SMESH::SMESH_GroupBase_var aGrp = theToolGroups[ g ];
1644     if ( CORBA::is_nil( aGrp ) )
1645       continue;
1646     if ( aType != aGrp->GetType() )
1647       THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
1648                                    SALOME::BAD_PARAM);
1649     if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1650       if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1651         toolGroupVec.push_back( grpDS );
1652   }
1653
1654   TPythonDump pyDump;
1655
1656   // Create a group
1657   aResGrp = CreateGroup( aType, theName );
1658
1659   SMESHDS_Group* resGroupDS = 0;
1660   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1661     resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1662   if ( !resGroupDS )
1663     return aResGrp._retn();
1664
1665   // Fill the group
1666   size_t i, nb = toolGroupVec.size();
1667   SMDS_ElemIteratorPtr mainElemIt
1668     ( new SMDS_IteratorOnIterators
1669       < const SMDS_MeshElement*, vector< SMDS_ElemIteratorPtr > >( mainIterVec ));
1670   while ( mainElemIt->more() )
1671   {
1672     const SMDS_MeshElement* e = mainElemIt->next();
1673     bool isIn = false;
1674     for ( i = 0; ( i < nb && !isIn ); ++i )
1675       isIn = toolGroupVec[i]->Contains( e );
1676
1677     if ( !isIn )
1678       resGroupDS->SMDSGroup().Add( e );
1679   }
1680
1681   // Update Python script
1682   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1683          << ".CutListOfGroups( " << theMainGroups << ", "
1684          << theToolGroups << ", '" << theName << "' )";
1685
1686   SMESH_CATCH( SMESH::throwCorbaException );
1687
1688   return aResGrp._retn();
1689 }
1690
1691 namespace // functions making checks according to SMESH::NB_COMMON_NODES_ENUM
1692 {
1693   bool isAllNodesCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
1694                         bool & toStopChecking )
1695   {
1696     toStopChecking = ( nbCommon < nbChecked );
1697     return nbCommon == nbNodes;
1698   }
1699   bool isMainNodesCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
1700                          bool & toStopChecking )
1701   {
1702     toStopChecking = ( nbCommon < nbChecked || nbChecked >= nbCorners );
1703     return nbCommon == nbCorners;
1704   }
1705   bool isAtLeastOneNodeCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
1706                               bool & toStopChecking )
1707   {
1708     return nbCommon > 0;
1709   }
1710   bool isMajorityOfNodesCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
1711                                bool & toStopChecking )
1712   {
1713     return nbCommon >= (nbNodes+1) / 2;
1714   }
1715 }
1716
1717 //=============================================================================
1718 /*!
1719  * Create a group of entities basing on nodes of other groups.
1720  *  \param [in] theGroups - list of either groups, sub-meshes or filters.
1721  *  \param [in] anElemType - a type of elements to include to the new group.
1722  *  \param [in] theName - a name of the new group.
1723  *  \param [in] theNbCommonNodes - criterion of inclusion of an element to the new group.
1724  *  \param [in] theUnderlyingOnly - if \c True, an element is included to the
1725  *         new group provided that it is based on nodes of an element of \a aListOfGroups
1726  *  \return SMESH_Group - the created group
1727 */
1728 // IMP 19939, bug 22010, IMP 22635
1729 //=============================================================================
1730
1731 SMESH::SMESH_Group_ptr
1732 SMESH_Mesh_i::CreateDimGroup(const SMESH::ListOfIDSources& theGroups,
1733                              SMESH::ElementType            theElemType,
1734                              const char*                   theName,
1735                              SMESH::NB_COMMON_NODES_ENUM   theNbCommonNodes,
1736                              CORBA::Boolean                theUnderlyingOnly)
1737   throw (SALOME::SALOME_Exception)
1738 {
1739   SMESH::SMESH_Group_var aResGrp;
1740
1741   SMESH_TRY;
1742   if ( _preMeshInfo )
1743     _preMeshInfo->FullLoadFromFile();
1744
1745   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
1746
1747   if ( !theName || !aMeshDS )
1748     return SMESH::SMESH_Group::_nil();
1749
1750   SMDSAbs_ElementType anElemType = (SMDSAbs_ElementType)theElemType;
1751
1752   bool (*isToInclude)(int nbChecked, int nbCommon, int nbNodes, int nbCorners, bool & toStop);
1753   SMESH_Comment nbCoNoStr( "SMESH.");
1754   switch ( theNbCommonNodes ) {
1755   case SMESH::ALL_NODES   : isToInclude = isAllNodesCommon;        nbCoNoStr<<"ALL_NODES"   ;break;
1756   case SMESH::MAIN        : isToInclude = isMainNodesCommon;       nbCoNoStr<<"MAIN"        ;break;
1757   case SMESH::AT_LEAST_ONE: isToInclude = isAtLeastOneNodeCommon;  nbCoNoStr<<"AT_LEAST_ONE";break;
1758   case SMESH::MAJORITY    : isToInclude = isMajorityOfNodesCommon; nbCoNoStr<<"MAJORITY"    ;break;
1759   default: return aResGrp._retn();
1760   }
1761   int nbChecked, nbCommon, nbNodes, nbCorners;
1762
1763   // Create a group
1764
1765   TPythonDump pyDump;
1766
1767   aResGrp = CreateGroup( theElemType, theName );
1768   if ( aResGrp->_is_nil() )
1769     return SMESH::SMESH_Group::_nil();
1770
1771   SMESHDS_GroupBase* groupBaseDS =
1772     SMESH::DownCast<SMESH_GroupBase_i*>( aResGrp )->GetGroupDS();
1773   SMDS_MeshGroup& resGroupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
1774
1775   vector<bool> isNodeInGroups;
1776
1777   for ( int g = 0, n = theGroups.length(); g < n; g++ ) // loop on theGroups
1778   {
1779     SMESH::SMESH_IDSource_var aGrp = theGroups[ g ];
1780     if ( CORBA::is_nil( aGrp ) )
1781       continue;
1782     SMESH::SMESH_Mesh_var mesh = aGrp->GetMesh();
1783     if ( mesh->_is_nil() || mesh->GetId() != this->GetId() )
1784       continue;
1785
1786     SMDS_ElemIteratorPtr elIt = GetElements( aGrp, SMESH::ALL );
1787     if ( !elIt ) continue;
1788
1789     if ( theElemType == SMESH::NODE ) // get all nodes of elements
1790     {
1791       while ( elIt->more() ) {
1792         const SMDS_MeshElement* el = elIt->next();
1793         SMDS_ElemIteratorPtr nIt = el->nodesIterator();
1794         while ( nIt->more() )
1795           resGroupCore.Add( nIt->next() );
1796       }
1797     }
1798     // get elements of theElemType based on nodes of every element of group
1799     else if ( theUnderlyingOnly )
1800     {
1801       while ( elIt->more() )
1802       {
1803         const SMDS_MeshElement* el = elIt->next(); // an element of ref group
1804         TIDSortedElemSet elNodes( el->begin_nodes(), el->end_nodes() );
1805         TIDSortedElemSet checkedElems;
1806         SMDS_NodeIteratorPtr nIt = el->nodeIterator();
1807         while ( nIt->more() )
1808         {
1809           const SMDS_MeshNode* n = nIt->next();
1810           SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
1811           // check nodes of elements of theElemType around el
1812           while ( elOfTypeIt->more() )
1813           {
1814             const SMDS_MeshElement* elOfType = elOfTypeIt->next();
1815             if ( !checkedElems.insert( elOfType ).second ) continue;
1816             nbNodes   = elOfType->NbNodes();
1817             nbCorners = elOfType->NbCornerNodes();
1818             nbCommon  = 0;
1819             bool toStopChecking = false;
1820             SMDS_ElemIteratorPtr nIt2 = elOfType->nodesIterator();
1821             for ( nbChecked = 1; nIt2->more() && !toStopChecking; ++nbChecked )
1822               if ( elNodes.count( nIt2->next() ) &&
1823                    isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
1824               {
1825                 resGroupCore.Add( elOfType );
1826                 break;
1827               }
1828           }
1829         }
1830       }
1831     }
1832     // get all nodes of elements of groups
1833     else
1834     {
1835       while ( elIt->more() )
1836       {
1837         const SMDS_MeshElement* el = elIt->next(); // an element of group
1838         SMDS_NodeIteratorPtr nIt = el->nodeIterator();
1839         while ( nIt->more() )
1840         {
1841           const SMDS_MeshNode* n = nIt->next();
1842           if ( n->GetID() >= (int) isNodeInGroups.size() )
1843             isNodeInGroups.resize( n->GetID() + 1, false );
1844           isNodeInGroups[ n->GetID() ] = true;
1845         }
1846       }
1847     }
1848   }
1849
1850   // Get elements of theElemType based on a certain number of nodes of elements of groups
1851   if ( !theUnderlyingOnly && !isNodeInGroups.empty() )
1852   {
1853     const SMDS_MeshNode* n;
1854     vector<bool> isElemChecked( aMeshDS->MaxElementID() + 1 );
1855     const int isNodeInGroupsSize = isNodeInGroups.size();
1856     for ( int iN = 0; iN < isNodeInGroupsSize; ++iN )
1857     {
1858       if ( !isNodeInGroups[ iN ] ||
1859            !( n = aMeshDS->FindNode( iN )))
1860         continue;
1861
1862       // check nodes of elements of theElemType around n
1863       SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
1864       while ( elOfTypeIt->more() )
1865       {
1866         const SMDS_MeshElement*  elOfType = elOfTypeIt->next();
1867         vector<bool>::reference isChecked = isElemChecked[ elOfType->GetID() ];
1868         if ( isChecked )
1869           continue;
1870         isChecked = true;
1871
1872         nbNodes   = elOfType->NbNodes();
1873         nbCorners = elOfType->NbCornerNodes();
1874         nbCommon  = 0;
1875         bool toStopChecking = false;
1876         SMDS_ElemIteratorPtr nIt = elOfType->nodesIterator();
1877         for ( nbChecked = 1; nIt->more() && !toStopChecking; ++nbChecked )
1878         {
1879           const int nID = nIt->next()->GetID();
1880           if ( nID < isNodeInGroupsSize && isNodeInGroups[ nID ] &&
1881                isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
1882           {
1883             resGroupCore.Add( elOfType );
1884             break;
1885           }
1886         }
1887       }
1888     }
1889   }
1890
1891   // Update Python script
1892   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this())
1893          << ".CreateDimGroup( "
1894          << theGroups << ", " << theElemType << ", '" << theName << "', "
1895          << nbCoNoStr << ", " << theUnderlyingOnly << ")";
1896
1897   SMESH_CATCH( SMESH::throwCorbaException );
1898
1899   return aResGrp._retn();
1900 }
1901
1902 //================================================================================
1903 /*!
1904  * \brief Distribute all faces of the mesh between groups using sharp edges and optionally
1905  *        existing 1D elements as group boundaries.
1906  *  \param [in] theSharpAngle - edge is considered sharp if an angle between normals of
1907  *              adjacent faces is more than \a sharpAngle in degrees.
1908  *  \param [in] theCreateEdges - to create 1D elements for detected sharp edges.
1909  *  \param [in] theUseExistingEdges - to use existing edges as group boundaries
1910  *  \return ListOfGroups - the created groups
1911  */
1912 //================================================================================
1913
1914 SMESH::ListOfGroups*
1915 SMESH_Mesh_i::FaceGroupsSeparatedByEdges( CORBA::Double  theSharpAngle,
1916                                           CORBA::Boolean theCreateEdges,
1917                                           CORBA::Boolean theUseExistingEdges )
1918   throw (SALOME::SALOME_Exception)
1919 {
1920   if ( theSharpAngle < 0 || theSharpAngle > 180 )
1921     THROW_SALOME_CORBA_EXCEPTION("Invalid sharp angle, it must be between 0 and 180 degrees",
1922                                  SALOME::BAD_PARAM);
1923
1924   SMESH::ListOfGroups_var resultGroups = new SMESH::ListOfGroups;
1925
1926   TPythonDump pyDump;
1927
1928   SMESH_TRY;
1929   if ( _preMeshInfo )
1930     _preMeshInfo->FullLoadFromFile();
1931
1932   SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
1933
1934   std::vector< SMESH_MeshAlgos::Edge > edges =
1935     SMESH_MeshAlgos::FindSharpEdges( meshDS, theSharpAngle, theUseExistingEdges );
1936
1937   if ( theCreateEdges )
1938   {
1939     std::vector<const SMDS_MeshNode *> nodes(2);
1940     for ( size_t i = 0; i < edges.size(); ++i )
1941     {
1942       nodes[0] = edges[i]._node1;
1943       nodes[1] = edges[i]._node2;
1944       if ( meshDS->FindElement( nodes, SMDSAbs_Edge ))
1945         continue;
1946       if ( edges[i]._medium )
1947         meshDS->AddEdge( edges[i]._node1, edges[i]._node2, edges[i]._medium );
1948       else
1949         meshDS->AddEdge( edges[i]._node1, edges[i]._node2 );
1950     }
1951   }
1952
1953   std::vector< std::vector< const SMDS_MeshElement* > > faceGroups =
1954     SMESH_MeshAlgos::SeparateFacesByEdges( meshDS, edges );
1955
1956   SMESH::SMESH_MeshEditor_var editor = GetMeshEditor(); // create _editor
1957
1958   resultGroups->length( faceGroups.size() );
1959   for ( size_t iG = 0; iG < faceGroups.size(); ++iG )
1960   {
1961     SMESH::SMESH_Group_var group = CreateGroup( SMESH::FACE,
1962                                                 _editor->GenerateGroupName("Group").c_str());
1963     resultGroups[iG] = SMESH::SMESH_Group::_duplicate( group );
1964
1965     SMESHDS_GroupBase* groupBaseDS =
1966       SMESH::DownCast<SMESH_GroupBase_i*>( group )->GetGroupDS();
1967     SMDS_MeshGroup& groupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
1968
1969     std::vector< const SMDS_MeshElement* >& faces = faceGroups[ iG ];
1970     for ( size_t i = 0; i < faces.size(); ++i )
1971       groupCore.Add( faces[i] );
1972   }
1973
1974   pyDump << resultGroups << " = " << SMESH::SMESH_Mesh_var(_this())
1975          << ".FaceGroupsSeparatedByEdges( "
1976          << TVar( theSharpAngle ) << ", "
1977          << theCreateEdges << ", "
1978          << theUseExistingEdges << " )";
1979
1980   SMESH_CATCH( SMESH::throwCorbaException );
1981   return resultGroups._retn();
1982
1983 }
1984
1985 //================================================================================
1986 /*!
1987  * \brief Remember GEOM group data
1988  */
1989 //================================================================================
1990
1991 void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj,
1992                                     CORBA::Object_ptr     theSmeshObj)
1993 {
1994   if ( CORBA::is_nil( theGeomObj ) || theGeomObj->GetType() != GEOM_GROUP )
1995     return;
1996   // group SO
1997   SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( theGeomObj );
1998   if ( groupSO->_is_nil() )
1999     return;
2000   // group indices
2001   GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( theGeomObj );
2002   GEOM::GEOM_IGroupOperations_wrap groupOp =
2003     geomGen->GetIGroupOperations();
2004   GEOM::ListOfLong_var ids = groupOp->GetObjects( theGeomObj );
2005
2006   // store data
2007   _geomGroupData.push_back( TGeomGroupData() );
2008   TGeomGroupData & groupData = _geomGroupData.back();
2009   // entry
2010   CORBA::String_var entry = groupSO->GetID();
2011   groupData._groupEntry = entry.in();
2012   // indices
2013   for ( CORBA::ULong i = 0; i < ids->length(); ++i )
2014     groupData._indices.insert( ids[i] );
2015   // SMESH object
2016   groupData._smeshObject = CORBA::Object::_duplicate( theSmeshObj );
2017   // shape index in SMESHDS
2018   // TopoDS_Shape shape = _gen_i->GeomObjectToShape( theGeomObj );
2019   // groupData._dsID = shape.IsNull() ? 0 : _impl->GetSubMesh( shape )->GetId();
2020 }
2021
2022 //================================================================================
2023 /*!
2024  * Remove GEOM group data relating to removed smesh object
2025  */
2026 //================================================================================
2027
2028 void SMESH_Mesh_i::removeGeomGroupData(CORBA::Object_ptr theSmeshObj)
2029 {
2030   list<TGeomGroupData>::iterator
2031     data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2032   for ( ; data != dataEnd; ++data ) {
2033     if ( theSmeshObj->_is_equivalent( data->_smeshObject )) {
2034       _geomGroupData.erase( data );
2035       return;
2036     }
2037   }
2038 }
2039
2040 //================================================================================
2041 /*!
2042  * \brief Return new group contents if it has been changed and update group data
2043  */
2044 //================================================================================
2045
2046 TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData)
2047 {
2048   TopoDS_Shape newShape;
2049
2050   // get geom group
2051   SALOMEDS::SObject_wrap groupSO = SMESH_Gen_i::getStudyServant()->FindObjectID( groupData._groupEntry.c_str() );
2052   if ( !groupSO->_is_nil() )
2053   {
2054     CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO );
2055     if ( CORBA::is_nil( groupObj )) return newShape;
2056     GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj );
2057
2058     // get indices of group items
2059     set<int> curIndices;
2060     GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( geomGroup );
2061     GEOM::GEOM_IGroupOperations_wrap groupOp =
2062       geomGen->GetIGroupOperations();
2063     GEOM::ListOfLong_var   ids = groupOp->GetObjects( geomGroup );
2064     for ( CORBA::ULong i = 0; i < ids->length(); ++i )
2065       curIndices.insert( ids[i] );
2066
2067     if ( groupData._indices == curIndices )
2068       return newShape; // group not changed
2069
2070     // update data
2071     groupData._indices = curIndices;
2072
2073     GEOM_Client* geomClient = _gen_i->GetShapeReader();
2074     if ( !geomClient ) return newShape;
2075     CORBA::String_var groupIOR = geomGen->GetStringFromIOR( geomGroup );
2076     geomClient->RemoveShapeFromBuffer( groupIOR.in() );
2077     newShape = _gen_i->GeomObjectToShape( geomGroup );
2078   }
2079
2080   if ( newShape.IsNull() ) {
2081     // geom group becomes empty - return empty compound
2082     TopoDS_Compound compound;
2083     BRep_Builder().MakeCompound(compound);
2084     newShape = compound;
2085   }
2086   return newShape;
2087 }
2088
2089 namespace
2090 {
2091   //-----------------------------------------------------------------------------
2092   /*!
2093    * \brief Storage of shape and index used in CheckGeomGroupModif()
2094    */
2095   struct TIndexedShape
2096   {
2097     int          _index;
2098     TopoDS_Shape _shape;
2099     TIndexedShape( int i, const TopoDS_Shape& s ):_index(i), _shape(s) {}
2100   };
2101   //-----------------------------------------------------------------------------
2102   /*!
2103    * \brief Data to re-create a group on geometry
2104    */
2105   struct TGroupOnGeomData
2106   {
2107     int                 _oldID;
2108     TopoDS_Shape        _shape;
2109     SMDSAbs_ElementType _type;
2110     std::string         _name;
2111     Quantity_Color      _color;
2112
2113     TGroupOnGeomData( const SMESHDS_GroupOnGeom* group )
2114     {
2115       _oldID = group->GetID();
2116       _type  = group->GetType();
2117       _name  = group->GetStoreName();
2118       _color = group->GetColor();
2119     }
2120   };
2121
2122   //-----------------------------------------------------------------------------
2123   /*!
2124    * \brief Check if a filter is still valid after geometry removal
2125    */
2126   bool isValidGeomFilter( SMESH::Filter_var theFilter )
2127   {
2128     if ( theFilter->_is_nil() )
2129       return false;
2130     SMESH::Filter::Criteria_var criteria;
2131     theFilter->GetCriteria( criteria.out() );
2132
2133     for ( CORBA::ULong iCr = 0; iCr < criteria->length(); ++iCr )
2134     {
2135       const char* thresholdID = criteria[ iCr ].ThresholdID.in();
2136       std::string entry;
2137       switch ( criteria[ iCr ].Type )
2138       {
2139       case SMESH::FT_BelongToGeom:
2140       case SMESH::FT_BelongToPlane:
2141       case SMESH::FT_BelongToCylinder:
2142       case SMESH::FT_BelongToGenSurface:
2143       case SMESH::FT_LyingOnGeom:
2144         entry = thresholdID;
2145         break;
2146       case SMESH::FT_ConnectedElements:
2147         if ( thresholdID )
2148         {
2149           entry = thresholdID;
2150           break;
2151         }
2152       default:
2153         continue;
2154       }
2155       SMESH_Gen_i*           gen = SMESH_Gen_i::GetSMESHGen();
2156       SALOMEDS::SObject_wrap  so = gen->getStudyServant()->FindObjectID( entry.c_str() );
2157       if ( so->_is_nil() )
2158         return false;
2159       CORBA::Object_var      obj = so->GetObject();
2160       GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( obj );
2161       if ( gen->GeomObjectToShape( geom ).IsNull() )
2162         return false;
2163
2164     } // loop on criteria
2165
2166     return true;
2167   }
2168 }
2169
2170 //=============================================================================
2171 /*!
2172  * \brief Update data if geometry changes
2173  *
2174  * Issue 0022501
2175  */
2176 //=============================================================================
2177
2178 void SMESH_Mesh_i::CheckGeomModif()
2179 {
2180   SMESH::SMESH_Mesh_var me = _this();
2181   GEOM::GEOM_Object_var mainGO = GetShapeToMesh();
2182
2183   //bool removedFromClient = false;
2184
2185   if ( mainGO->_is_nil() ) // GEOM_Client cleared or geometry removed? (IPAL52735, PAL23636)
2186   {
2187     //removedFromClient = _impl->HasShapeToMesh();
2188
2189     // try to find geometry by study reference
2190     SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
2191     SALOMEDS::SObject_wrap geomRefSO, geomSO;
2192     if ( !meshSO->_is_nil() &&
2193          meshSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2194          geomRefSO->ReferencedObject( geomSO.inout() ))
2195     {
2196       CORBA::Object_var geomObj = _gen_i->SObjectToObject( geomSO );
2197       mainGO = GEOM::GEOM_Object::_narrow( geomObj );
2198     }
2199
2200     if ( mainGO->_is_nil() &&    // geometry removed ==>
2201          !geomRefSO->_is_nil() ) // remove geom dependent data: sub-meshes etc.
2202     {
2203       // convert geom dependent groups into standalone ones
2204       CheckGeomGroupModif();
2205
2206       _impl->ShapeToMesh( TopoDS_Shape() );
2207
2208       // remove sub-meshes
2209       std::map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
2210       while ( i_sm != _mapSubMeshIor.end() )
2211       {
2212         SMESH::SMESH_subMesh_ptr sm = i_sm->second;
2213         ++i_sm;
2214         RemoveSubMesh( sm );
2215       }
2216       // remove all children except groups in the study
2217       SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2218       SALOMEDS::SObject_wrap so;
2219       for ( CORBA::Long tag = SMESH::Tag_RefOnShape; tag <= SMESH::Tag_LastSubMesh; ++tag )
2220         if ( meshSO->FindSubObject( tag, so.inout() ))
2221           builder->RemoveObjectWithChildren( so );
2222
2223       _gen_i->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED" );
2224
2225       return;
2226     }
2227   }
2228
2229   if ( !_impl->HasShapeToMesh() ) return;
2230
2231
2232   // Update after group modification
2233
2234   if ( mainGO->GetType() == GEOM_GROUP ||    // is group or not modified
2235        mainGO->GetTick() == _mainShapeTick )
2236   {
2237     int nb = NbNodes() + NbElements();
2238     CheckGeomGroupModif();
2239     if ( nb != NbNodes() + NbElements() ) // something removed due to hypotheses change
2240       _gen_i->UpdateIcons( me );
2241     return;
2242   }
2243
2244   // Update after shape transformation like Translate
2245
2246   GEOM_Client* geomClient = _gen_i->GetShapeReader();
2247   if ( !geomClient ) return;
2248   GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine( mainGO );
2249   if ( geomGen->_is_nil() ) return;
2250
2251   CORBA::String_var ior = geomGen->GetStringFromIOR( mainGO );
2252   geomClient->RemoveShapeFromBuffer( ior.in() );
2253
2254   // Update data taking into account that
2255   // all sub-shapes change but IDs of sub-shapes remain (except for geom groups)
2256
2257   _impl->Clear();
2258   TopoDS_Shape newShape = _gen_i->GeomObjectToShape( mainGO );
2259   if ( newShape.IsNull() )
2260     return;
2261
2262   // for the SHAPER-STUDY: the geometry may be updated, so, add a warning icon
2263   if (_mainShapeTick != mainGO->GetTick()) {
2264     SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( me );
2265     if ( !meshSO->_is_nil())
2266       _gen_i->SetPixMap(meshSO, "ICON_SMESH_TREE_MESH_WARN");
2267   }
2268
2269   _mainShapeTick = mainGO->GetTick();
2270
2271   SMESHDS_Mesh * meshDS = _impl->GetMeshDS();
2272
2273   // store data of groups on geometry
2274   std::vector< TGroupOnGeomData > groupsData;
2275   const std::set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2276   groupsData.reserve( groups.size() );
2277   std::set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
2278   for ( ; g != groups.end(); ++g )
2279   {
2280     if ( const SMESHDS_GroupOnGeom* group = dynamic_cast< SMESHDS_GroupOnGeom* >( *g ))
2281     {
2282       groupsData.push_back( TGroupOnGeomData( group ));
2283
2284       // get a new shape
2285       SMESH::SMESH_GroupOnGeom_var gog;
2286       std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.find( group->GetID() );
2287       if ( i_grp != _mapGroups.end() )
2288         gog = SMESH::SMESH_GroupOnGeom::_narrow( i_grp->second );
2289
2290       GEOM::GEOM_Object_var geom;
2291       if ( !gog->_is_nil() )
2292         geom = gog->GetShape();
2293       if ( !geom->_is_nil() )
2294       {
2295         CORBA::String_var ior = geomGen->GetStringFromIOR( geom );
2296         geomClient->RemoveShapeFromBuffer( ior.in() );
2297         groupsData.back()._shape = _gen_i->GeomObjectToShape( geom );
2298       }
2299     }
2300   }
2301   // store assigned hypotheses
2302   std::vector< pair< int, THypList > > ids2Hyps;
2303   const ShapeToHypothesis & hyps = meshDS->GetHypotheses();
2304   for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() )
2305   {
2306     const TopoDS_Shape& s = s2hyps.Key();
2307     const THypList&  hyps = s2hyps.ChangeValue();
2308     ids2Hyps.push_back( make_pair( meshDS->ShapeToIndex( s ), hyps ));
2309   }
2310
2311   // change shape to mesh
2312   int oldNbSubShapes = meshDS->MaxShapeIndex();
2313   _impl->ShapeToMesh( TopoDS_Shape() );
2314   _impl->ShapeToMesh( newShape );
2315
2316   // re-add shapes of geom groups
2317   std::list<TGeomGroupData>::iterator data = _geomGroupData.begin();
2318   for ( ; data != _geomGroupData.end(); ++data )
2319   {
2320     TopoDS_Shape newShape = newGroupShape( *data );
2321     if ( !newShape.IsNull() )
2322     {
2323       if ( meshDS->ShapeToIndex( newShape ) > 0 ) // a group reduced to one sub-shape
2324       {
2325         TopoDS_Compound compound;
2326         BRep_Builder().MakeCompound( compound );
2327         BRep_Builder().Add( compound, newShape );
2328         newShape = compound;
2329       }
2330       _impl->GetSubMesh( newShape );
2331     }
2332   }
2333   if ( oldNbSubShapes != meshDS->MaxShapeIndex() )
2334     THROW_SALOME_CORBA_EXCEPTION( "SMESH_Mesh_i::CheckGeomModif() bug",
2335                                   SALOME::INTERNAL_ERROR );
2336
2337   // re-assign hypotheses
2338   for ( size_t i = 0; i < ids2Hyps.size(); ++i )
2339   {
2340     const TopoDS_Shape& s = meshDS->IndexToShape( ids2Hyps[i].first );
2341     const THypList&  hyps = ids2Hyps[i].second;
2342     THypList::const_iterator h = hyps.begin();
2343     for ( ; h != hyps.end(); ++h )
2344       _impl->AddHypothesis( s, (*h)->GetID() );
2345   }
2346
2347   // restore groups on geometry
2348   for ( size_t i = 0; i < groupsData.size(); ++i )
2349   {
2350     const TGroupOnGeomData& data = groupsData[i];
2351     if ( data._shape.IsNull() )
2352       continue;
2353
2354     std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i2g = _mapGroups.find( data._oldID );
2355     if ( i2g == _mapGroups.end() ) continue;
2356
2357     SMESH_GroupBase_i* gr_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2g->second );
2358     if ( !gr_i ) continue;
2359
2360     SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), data._oldID, data._shape );
2361     if ( !g )
2362       _mapGroups.erase( i2g );
2363     else
2364       g->GetGroupDS()->SetColor( data._color );
2365   }
2366
2367   // update _mapSubMesh
2368   std::map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
2369   for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
2370     i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first ));
2371
2372 }
2373
2374 //=============================================================================
2375 /*!
2376  * \brief Update objects depending on changed geom groups
2377  *
2378  * NPAL16168: geometrical group edition from a submesh don't modify mesh computation
2379  * issue 0020210: Update of a smesh group after modification of the associated geom group
2380  */
2381 //=============================================================================
2382
2383 void SMESH_Mesh_i::CheckGeomGroupModif()
2384 {
2385   // remove sub-meshes referring a removed sub-shapes (if main shape still exists)
2386   SALOMEDS::StudyBuilder_var builder = _gen_i->getStudyServant()->NewBuilder();
2387   GEOM::GEOM_Object_var  mainGO = GetShapeToMesh();
2388   SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( SMESH::SMESH_Mesh_var( _this() ));
2389   if ( !mainGO->_is_nil() && !meshSO->_is_nil() )
2390   {
2391     SALOMEDS::SObject_wrap rootSO, geomRefSO, geomSO;
2392     for ( CORBA::Long tag = SMESH::Tag_FirstSubMesh; tag <= SMESH::Tag_LastSubMesh; ++tag )
2393       if ( meshSO->FindSubObject( tag, rootSO.inout() ))
2394       {
2395         int nbValid = 0, nbRemoved = 0;
2396         SALOMEDS::ChildIterator_wrap chItr = _gen_i->getStudyServant()->NewChildIterator( rootSO );
2397         for ( ; chItr->More(); chItr->Next() )
2398         {
2399           SALOMEDS::SObject_wrap smSO = chItr->Value(); // sub-mesh SO
2400           if ( !smSO->_is_nil() &&
2401                smSO->FindSubObject( SMESH::Tag_RefOnShape, geomRefSO.inout() ) &&
2402                geomRefSO->ReferencedObject( geomSO.inout() )) // find geometry by reference
2403           {
2404             CORBA::Object_var  geomObj = _gen_i->SObjectToObject( geomSO );
2405             GEOM::GEOM_Object_var geom = GEOM::GEOM_Object::_narrow( geomObj );
2406             if ( !geom->_non_existent() )
2407             {
2408               ++nbValid;
2409               continue; // keep the sub-mesh
2410             }
2411           }
2412           CORBA::Object_var     smObj = _gen_i->SObjectToObject( smSO );
2413           SMESH::SMESH_subMesh_var sm = SMESH::SMESH_subMesh::_narrow( smObj );
2414           if ( !sm->_is_nil() && !sm->_non_existent() )
2415           {
2416             GEOM::GEOM_Object_var smGeom = sm->GetSubShape();
2417             if ( smGeom->_is_nil() )
2418             {
2419               RemoveSubMesh( sm );
2420               ++nbRemoved;
2421             }
2422           }
2423           else
2424           {
2425             if ( _preMeshInfo )
2426               _preMeshInfo->ForgetAllData(); // unknown hypothesis modified
2427             builder->RemoveObjectWithChildren( smSO ); // sub-shape removed before loading SMESH
2428             ++nbRemoved;
2429           }
2430         }
2431         if ( /*nbRemoved > 0 &&*/ nbValid == 0 )
2432           builder->RemoveObjectWithChildren( rootSO );
2433       }
2434   }
2435
2436   // check for removed sub-shapes and convert geom dependent groups into standalone ones
2437   std::map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
2438   while ( i_gr != _mapGroups.end())
2439   {
2440     SMESH::SMESH_GroupBase_ptr group = i_gr->second;
2441     ++i_gr;
2442     SALOMEDS::SObject_wrap        groupSO = _gen_i->ObjectToSObject( group ), refSO;
2443     SMESH::SMESH_GroupOnGeom_var   onGeom = SMESH::SMESH_GroupOnGeom::_narrow  ( group );
2444     SMESH::SMESH_GroupOnFilter_var onFilt = SMESH::SMESH_GroupOnFilter::_narrow( group );
2445     bool isValidGeom = false;
2446     if ( !onGeom->_is_nil() )
2447     {
2448       isValidGeom = ( ! GEOM::GEOM_Object_var( onGeom->GetShape() )->_is_nil() );
2449     }
2450     else if ( !onFilt->_is_nil() )
2451     {
2452       isValidGeom = isValidGeomFilter( onFilt->GetFilter() );
2453     }
2454     else // standalone
2455     {
2456       isValidGeom = ( !groupSO->_is_nil() &&
2457                       !groupSO->FindSubObject( SMESH::Tag_RefOnShape, refSO.inout() ));
2458     }
2459     if ( !isValidGeom )
2460     {
2461       if ( !IsLoaded() || group->IsEmpty() )
2462       {
2463         RemoveGroup( group );
2464       }
2465       else if ( !onGeom->_is_nil() || !onFilt->_is_nil() )
2466       {
2467         SMESH::SMESH_Group_var ( ConvertToStandalone( group ));
2468       }
2469       else // is it possible?
2470       {
2471         builder->RemoveObjectWithChildren( refSO );
2472       }
2473     }
2474   }
2475
2476
2477   if ( !_impl->HasShapeToMesh() ) return;
2478
2479   CORBA::Long nbEntities = NbNodes() + NbElements();
2480
2481   // Check if group contents changed
2482
2483   typedef map< string, TopoDS_Shape > TEntry2Geom;
2484   TEntry2Geom newGroupContents;
2485
2486   list<TGeomGroupData>::iterator
2487     data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2488   for ( ; data != dataEnd; ++data )
2489   {
2490     pair< TEntry2Geom::iterator, bool > it_new =
2491       newGroupContents.insert( make_pair( data->_groupEntry, TopoDS_Shape() ));
2492     bool processedGroup    = !it_new.second;
2493     TopoDS_Shape& newShape = it_new.first->second;
2494     if ( !processedGroup )
2495       newShape = newGroupShape( *data );
2496     if ( newShape.IsNull() )
2497       continue; // no changes
2498
2499     if ( _preMeshInfo )
2500       _preMeshInfo->ForgetOrLoad();
2501
2502     if ( processedGroup ) { // update group indices
2503       list<TGeomGroupData>::iterator data2 = data;
2504       for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) {}
2505       data->_indices = data2->_indices;
2506     }
2507
2508     // Update SMESH objects according to new GEOM group contents
2509
2510     SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject );
2511     if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
2512     {
2513       int oldID = submesh->GetId();
2514       if ( !_mapSubMeshIor.count( oldID ))
2515         continue;
2516       TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
2517
2518       // update hypotheses
2519       list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldShape);
2520       list <const SMESHDS_Hypothesis * >::iterator hypIt;
2521       for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2522       {
2523         _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2524         _impl->AddHypothesis   ( newShape, (*hypIt)->GetID());
2525       }
2526       // care of submeshes
2527       SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newShape );
2528       int newID = newSubmesh->GetId();
2529       if ( newID != oldID ) {
2530         _mapSubMesh   [ newID ] = newSubmesh;
2531         _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2532         _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2533         _mapSubMesh.   erase(oldID);
2534         _mapSubMesh_i. erase(oldID);
2535         _mapSubMeshIor.erase(oldID);
2536         _mapSubMesh_i [ newID ]->changeLocalId( newID );
2537       }
2538       continue;
2539     }
2540
2541     SMESH::SMESH_GroupOnGeom_var smeshGroup =
2542       SMESH::SMESH_GroupOnGeom::_narrow( data->_smeshObject );
2543     if ( !smeshGroup->_is_nil() ) // ------------ GROUP -----------------------
2544     {
2545       SMESH_GroupOnGeom_i* group_i = SMESH::DownCast<SMESH_GroupOnGeom_i*>( smeshGroup );
2546       if ( group_i ) {
2547         ::SMESH_Group* group = _impl->GetGroup( group_i->GetLocalID() );
2548         SMESHDS_GroupOnGeom* ds = static_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() );
2549         ds->SetShape( newShape );
2550       }
2551       continue;
2552     }
2553
2554     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject );
2555     if ( !mesh->_is_nil() ) // -------------- MESH ----------------------------
2556     {
2557       // Remove groups and submeshes basing on removed sub-shapes
2558
2559       TopTools_MapOfShape newShapeMap;
2560       TopoDS_Iterator shapeIt( newShape );
2561       for ( ; shapeIt.More(); shapeIt.Next() )
2562         newShapeMap.Add( shapeIt.Value() );
2563
2564       SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2565       for ( shapeIt.Initialize( meshDS->ShapeToMesh() ); shapeIt.More(); shapeIt.Next() )
2566       {
2567         if ( newShapeMap.Contains( shapeIt.Value() ))
2568           continue;
2569         TopTools_IndexedMapOfShape oldShapeMap;
2570         TopExp::MapShapes( shapeIt.Value(), oldShapeMap );
2571         for ( int i = 1; i <= oldShapeMap.Extent(); ++i )
2572         {
2573           const TopoDS_Shape& oldShape = oldShapeMap(i);
2574           int oldInd = meshDS->ShapeToIndex( oldShape );
2575           // -- submeshes --
2576           map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldInd );
2577           if ( i_smIor != _mapSubMeshIor.end() ) {
2578             RemoveSubMesh( i_smIor->second ); // one submesh per shape index
2579           }
2580           // --- groups ---
2581           map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
2582           for ( ; i_grp != _mapGroups.end(); ++i_grp )
2583           {
2584             // check if a group bases on oldInd shape
2585             SMESHDS_GroupOnGeom* grpOnGeom = 0;
2586             if ( ::SMESH_Group* g = _impl->GetGroup( i_grp->first ))
2587               grpOnGeom = dynamic_cast<SMESHDS_GroupOnGeom*>( g->GetGroupDS() );
2588             if ( grpOnGeom && oldShape.IsSame( grpOnGeom->GetShape() ))
2589             { // remove
2590               RemoveGroup( i_grp->second ); // several groups can base on same shape
2591               i_grp = _mapGroups.begin(); // _mapGroups changed - restart iteration
2592             }
2593           }
2594         }
2595       }
2596       // Reassign hypotheses and update groups after setting the new shape to mesh
2597
2598       // collect anassigned hypotheses
2599       typedef list< pair< TIndexedShape, list<const SMESHDS_Hypothesis*> > > TShapeHypList;
2600       list <const SMESHDS_Hypothesis * >::const_iterator hypIt;
2601       TShapeHypList assignedHyps;
2602       for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i )
2603       {
2604         const TopoDS_Shape& oldShape = meshDS->IndexToShape(i);
2605         list<const SMESHDS_Hypothesis*> hyps = meshDS->GetHypothesis( oldShape );// copy
2606         if ( !hyps.empty() ) {
2607           assignedHyps.push_back( make_pair( TIndexedShape(i,oldShape), hyps ));
2608           for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2609             _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2610         }
2611       }
2612       // collect shapes supporting groups
2613       typedef list < pair< TIndexedShape, SMDSAbs_ElementType > > TShapeTypeList;
2614       TShapeTypeList groupData;
2615       const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2616       set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
2617       for ( ; grIt != groups.end(); ++grIt )
2618       {
2619         if ( SMESHDS_GroupOnGeom* gog = dynamic_cast<SMESHDS_GroupOnGeom*>( *grIt ))
2620           groupData.push_back
2621             ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
2622       }
2623       // set new shape to mesh -> DS of sub-meshes and geom groups is deleted
2624       _impl->Clear();
2625       _impl->ShapeToMesh( TopoDS_Shape() ); // IPAL52730
2626       _impl->ShapeToMesh( newShape );
2627
2628       // reassign hypotheses
2629       TShapeHypList::iterator indS_hyps = assignedHyps.begin();
2630       for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
2631       {
2632         TIndexedShape&                   geom = indS_hyps->first;
2633         list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
2634         int oldID = geom._index;
2635         int newID = meshDS->ShapeToIndex( geom._shape );
2636         if ( oldID == 1 ) { // main shape
2637           newID = 1;
2638           geom._shape = newShape;
2639         }
2640         if ( !newID )
2641           continue;
2642         for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2643           _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
2644         // care of sub-meshes
2645         SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
2646         if ( newID != oldID ) {
2647           _mapSubMesh   [ newID ] = newSubmesh;
2648           _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2649           _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2650           _mapSubMesh.   erase(oldID);
2651           _mapSubMesh_i. erase(oldID);
2652           _mapSubMeshIor.erase(oldID);
2653           _mapSubMesh_i [ newID ]->changeLocalId( newID );
2654         }
2655       }
2656       // recreate groups
2657       TShapeTypeList::iterator geomType = groupData.begin();
2658       for ( ; geomType != groupData.end(); ++geomType )
2659       {
2660         const TIndexedShape& geom = geomType->first;
2661         int oldID = geom._index;
2662         if ( _mapGroups.find( oldID ) == _mapGroups.end() )
2663           continue;
2664         // get group name
2665         SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( _mapGroups[oldID] );
2666         CORBA::String_var      name    = groupSO->GetName();
2667         // update
2668         if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID]))
2669           if ( SMESH_Group* group = _impl->AddGroup( geomType->second, name.in(),
2670                                                      /*id=*/-1, geom._shape ))
2671             group_i->changeLocalId( group->GetID() );
2672       }
2673
2674       break; // everything has been updated
2675
2676     } // update mesh
2677   } // loop on group data
2678
2679   // Update icons
2680
2681   CORBA::Long newNbEntities = NbNodes() + NbElements();
2682   list< SALOMEDS::SObject_wrap > soToUpdateIcons;
2683   if ( newNbEntities != nbEntities )
2684   {
2685     // Add all SObjects with icons to soToUpdateIcons
2686     soToUpdateIcons.push_back( _gen_i->ObjectToSObject( _this() )); // mesh
2687
2688     for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
2689          i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
2690       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_sm->second ));
2691
2692     for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
2693           i_gr != _mapGroups.end(); ++i_gr ) // groups
2694       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_gr->second ));
2695   }
2696
2697   list< SALOMEDS::SObject_wrap >::iterator so = soToUpdateIcons.begin();
2698   for ( ; so != soToUpdateIcons.end(); ++so )
2699     _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
2700 }
2701
2702 //=============================================================================
2703 /*!
2704  * \brief Create standalone group from a group on geometry or filter
2705  */
2706 //=============================================================================
2707
2708 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase_ptr theGroup )
2709   throw (SALOME::SALOME_Exception)
2710 {
2711   SMESH::SMESH_Group_var aGroup;
2712
2713   SMESH_TRY;
2714
2715   if ( _preMeshInfo )
2716     _preMeshInfo->FullLoadFromFile();
2717
2718   if ( theGroup->_is_nil() )
2719     return aGroup._retn();
2720
2721   SMESH_GroupBase_i* aGroupToRem = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
2722   if ( !aGroupToRem )
2723     return aGroup._retn();
2724
2725   const bool isOnFilter = ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ));
2726
2727   const int anId = aGroupToRem->GetLocalID();
2728   if ( !_impl->ConvertToStandalone( anId ) )
2729     return aGroup._retn();
2730   removeGeomGroupData( theGroup );
2731
2732   SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2733
2734   // remove old instance of group from own map
2735   { SMESH::SMESH_GroupBase_var var( _mapGroups[anId] ); } // decref CORBA object
2736   _mapGroups.erase( anId );
2737
2738   SALOMEDS::StudyBuilder_var builder;
2739   SALOMEDS::SObject_wrap     aGroupSO;
2740   SALOMEDS::Study_var        aStudy = SMESH_Gen_i::getStudyServant();
2741   if ( !aStudy->_is_nil() ) {
2742     builder  = aStudy->NewBuilder();
2743     aGroupSO = _gen_i->ObjectToSObject( theGroup );
2744     if ( !aGroupSO->_is_nil() )
2745     {
2746       // remove reference to geometry
2747       SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO);
2748       for ( ; chItr->More(); chItr->Next() )
2749       {
2750         // Remove group's child SObject
2751         SALOMEDS::SObject_wrap so = chItr->Value();
2752         builder->RemoveObject( so );
2753       }
2754       // Update Python script
2755       TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this())
2756                     << ".ConvertToStandalone( " << aGroupSO << " )";
2757
2758       // change icon of Group on Filter
2759       if ( isOnFilter )
2760       {
2761         // SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
2762         // const int isEmpty = ( elemTypes->length() == 0 );
2763         // if ( !isEmpty )
2764         {
2765           SALOMEDS::GenericAttribute_wrap anAttr =
2766             builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
2767           SALOMEDS::AttributePixMap_wrap pm = anAttr;
2768           pm->SetPixMap( "ICON_SMESH_TREE_GROUP" );
2769         }
2770       }
2771     }
2772   }
2773
2774   // remember new group in own map
2775   aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
2776   _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2777
2778   // register CORBA object for persistence
2779   _gen_i->RegisterObject( aGroup );
2780
2781   CORBA::String_var ior = _gen_i->GetORB()->object_to_string( aGroup );
2782   builder->SetIOR( aGroupSO, ior.in() ); //  == aGroup->Register();
2783   //aGroup->Register();
2784   aGroupToRem->UnRegister();
2785
2786   SMESH_CATCH( SMESH::throwCorbaException );
2787
2788   return aGroup._retn();
2789 }
2790
2791 //=============================================================================
2792 /*!
2793  *
2794  */
2795 //=============================================================================
2796
2797 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
2798 {
2799   if(MYDEBUG) MESSAGE( "createSubMesh" );
2800   TopoDS_Shape  myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
2801   ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
2802   int               subMeshId = 0;
2803
2804   SMESH_subMesh_i * subMeshServant;
2805   if ( mySubMesh )
2806   {
2807     subMeshId = mySubMesh->GetId();
2808     subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
2809   }
2810   else // "invalid sub-mesh"
2811   {
2812     // The invalid sub-mesh is created for the case where a valid sub-shape not found
2813     // by SMESH_Gen_i::CopyMeshWithGeom(). The invalid sub-mesh has GetId() < 0.
2814     if ( _mapSubMesh.empty() )
2815       subMeshId = -1;
2816     else
2817       subMeshId = _mapSubMesh.begin()->first - 1;
2818     subMeshServant = new SMESH_Invalid_subMesh_i(myPOA, _gen_i, this, subMeshId, theSubShapeObject);
2819   }
2820
2821   SMESH::SMESH_subMesh_var subMesh = subMeshServant->_this();
2822
2823   _mapSubMesh   [subMeshId] = mySubMesh;
2824   _mapSubMesh_i [subMeshId] = subMeshServant;
2825   _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate( subMesh );
2826
2827   subMeshServant->Register();
2828
2829   // register CORBA object for persistence
2830   int nextId = _gen_i->RegisterObject( subMesh );
2831   if(MYDEBUG) { MESSAGE( "Add submesh to map with id = "<< nextId); }
2832   else        { nextId = 0; } // avoid "unused variable" warning
2833
2834   // to track changes of GEOM groups
2835   if ( subMeshId > 0 )
2836     addGeomGroupData( theSubShapeObject, subMesh );
2837
2838   return subMesh._retn();
2839 }
2840
2841 //=======================================================================
2842 //function : getSubMesh
2843 //purpose  :
2844 //=======================================================================
2845
2846 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
2847 {
2848   map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
2849   if ( it == _mapSubMeshIor.end() )
2850     return SMESH::SMESH_subMesh::_nil();
2851
2852   return SMESH::SMESH_subMesh::_duplicate( (*it).second );
2853 }
2854
2855 //=============================================================================
2856 /*!
2857  *
2858  */
2859 //=============================================================================
2860
2861 bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
2862                                   GEOM::GEOM_Object_ptr    theSubShapeObject )
2863 {
2864   bool isHypChanged = false;
2865   if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
2866     return isHypChanged;
2867
2868   const int subMeshId = theSubMesh->GetId();
2869
2870   if ( theSubShapeObject->_is_nil() )  // not published shape (IPAL13617)
2871   {
2872     SMESH_subMesh* sm;
2873     if (( _mapSubMesh.count( subMeshId )) &&
2874         ( sm = _impl->GetSubMeshContaining( subMeshId )))
2875     {
2876       TopoDS_Shape S = sm->GetSubShape();
2877       if ( !S.IsNull() )
2878       {
2879         list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
2880         isHypChanged = !hyps.empty();
2881         if ( isHypChanged && _preMeshInfo )
2882           _preMeshInfo->ForgetOrLoad();
2883         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
2884         for ( ; hyp != hyps.end(); ++hyp )
2885           _impl->RemoveHypothesis(S, (*hyp)->GetID());
2886       }
2887     }
2888   }
2889   else
2890   {
2891     try {
2892       SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
2893       isHypChanged = ( aHypList->length() > 0 );
2894       for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
2895         removeHypothesis( theSubShapeObject, aHypList[i] );
2896       }
2897     }
2898     catch( const SALOME::SALOME_Exception& ) {
2899       INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
2900     }
2901     removeGeomGroupData( theSubShapeObject );
2902   }
2903
2904   // remove a servant
2905   std::map<int, SMESH_subMesh_i*>::iterator id_smi = _mapSubMesh_i.find( subMeshId );
2906   if ( id_smi != _mapSubMesh_i.end() )
2907     id_smi->second->UnRegister();
2908
2909   // remove a CORBA object
2910   std::map<int, SMESH::SMESH_subMesh_ptr>::iterator id_smptr = _mapSubMeshIor.find( subMeshId );
2911   if ( id_smptr != _mapSubMeshIor.end() )
2912     SMESH::SMESH_subMesh_var( id_smptr->second );
2913
2914   _mapSubMesh.erase(subMeshId);
2915   _mapSubMesh_i.erase(subMeshId);
2916   _mapSubMeshIor.erase(subMeshId);
2917
2918   return isHypChanged;
2919 }
2920
2921 //=============================================================================
2922 /*!
2923  *
2924  */
2925 //=============================================================================
2926
2927 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType        theElemType,
2928                                                       const char*               theName,
2929                                                       const int                 theID,
2930                                                       const TopoDS_Shape&       theShape,
2931                                                       const SMESH_PredicatePtr& thePredicate )
2932 {
2933   std::string newName;
2934   if ( !theName || !theName[0] )
2935   {
2936     std::set< std::string > presentNames;
2937     std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
2938     for ( ; i_gr != _mapGroups.end(); ++i_gr )
2939     {
2940       CORBA::String_var name = i_gr->second->GetName();
2941       presentNames.insert( name.in() );
2942     }
2943     do {
2944       newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
2945     } while ( !presentNames.insert( newName ).second );
2946     theName = newName.c_str();
2947   }
2948   SMESH::SMESH_GroupBase_var aGroup;
2949   if ( SMESH_Group* g = _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName,
2950                                          theID, theShape, thePredicate ))
2951   {
2952     int anId = g->GetID();
2953     SMESH_GroupBase_i* aGroupImpl;
2954     if ( !theShape.IsNull() )
2955       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
2956     else if ( thePredicate )
2957       aGroupImpl = new SMESH_GroupOnFilter_i( SMESH_Gen_i::GetPOA(), this, anId );
2958     else
2959       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2960
2961     aGroup = aGroupImpl->_this();
2962     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2963     aGroupImpl->Register();
2964
2965     // register CORBA object for persistence
2966     int nextId = _gen_i->RegisterObject( aGroup );
2967     if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
2968     else        { nextId = ( nextId > 0 ); } // avoid "unused variable" warning in release mode
2969
2970     // to track changes of GEOM groups
2971     if ( !theShape.IsNull() ) {
2972       GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
2973       addGeomGroupData( geom, aGroup );
2974     }
2975   }
2976   return aGroup._retn();
2977 }
2978
2979 //=============================================================================
2980 /*!
2981  * SMESH_Mesh_i::removeGroup
2982  *
2983  * Should be called by ~SMESH_Group_i()
2984  */
2985 //=============================================================================
2986
2987 void SMESH_Mesh_i::removeGroup( const int theId )
2988 {
2989   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
2990   if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
2991     SMESH::SMESH_GroupBase_var group = _mapGroups[theId];
2992     _mapGroups.erase( theId );
2993     removeGeomGroupData( group );
2994     if ( !_impl->RemoveGroup( theId ))
2995     {
2996       // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
2997       RemoveGroup( group );
2998     }
2999     group->UnRegister();
3000   }
3001 }
3002
3003 //=============================================================================
3004 /*!
3005  *
3006  */
3007 //=============================================================================
3008
3009 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
3010   throw(SALOME::SALOME_Exception)
3011 {
3012   SMESH::log_array_var aLog;
3013
3014   SMESH_TRY;
3015   if ( _preMeshInfo )
3016     _preMeshInfo->FullLoadFromFile();
3017
3018   list < SMESHDS_Command * >logDS = _impl->GetLog();
3019   aLog = new SMESH::log_array;
3020   int indexLog = 0;
3021   int lg = logDS.size();
3022   SCRUTE(lg);
3023   aLog->length(lg);
3024   list < SMESHDS_Command * >::iterator its = logDS.begin();
3025   while(its != logDS.end()){
3026     SMESHDS_Command *com = *its;
3027     int comType = com->GetType();
3028     //SCRUTE(comType);
3029     int lgcom = com->GetNumber();
3030     //SCRUTE(lgcom);
3031     const list < int >&intList = com->GetIndexes();
3032     int inum = intList.size();
3033     //SCRUTE(inum);
3034     list < int >::const_iterator ii = intList.begin();
3035     const list < double >&coordList = com->GetCoords();
3036     int rnum = coordList.size();
3037     //SCRUTE(rnum);
3038     list < double >::const_iterator ir = coordList.begin();
3039     aLog[indexLog].commandType = comType;
3040     aLog[indexLog].number = lgcom;
3041     aLog[indexLog].coords.length(rnum);
3042     aLog[indexLog].indexes.length(inum);
3043     for(int i = 0; i < rnum; i++){
3044       aLog[indexLog].coords[i] = *ir;
3045       //MESSAGE(" "<<i<<" "<<ir.Value());
3046       ir++;
3047     }
3048     for(int i = 0; i < inum; i++){
3049       aLog[indexLog].indexes[i] = *ii;
3050       //MESSAGE(" "<<i<<" "<<ii.Value());
3051       ii++;
3052     }
3053     indexLog++;
3054     its++;
3055   }
3056   if(clearAfterGet)
3057     _impl->ClearLog();
3058
3059   SMESH_CATCH( SMESH::throwCorbaException );
3060
3061   return aLog._retn();
3062 }
3063
3064
3065 //=============================================================================
3066 /*!
3067  *
3068  */
3069 //=============================================================================
3070
3071 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
3072 {
3073   SMESH_TRY;
3074   _impl->ClearLog();
3075   SMESH_CATCH( SMESH::throwCorbaException );
3076 }
3077
3078 //=============================================================================
3079 /*!
3080  *
3081  */
3082 //=============================================================================
3083
3084 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
3085 {
3086   return _id;
3087 }
3088
3089 //=============================================================================
3090 namespace
3091 {
3092   //!< implementation of struct used to call methods of SMESH_Mesh_i from SMESH_Mesh
3093   // issue 0020918: groups removal is caused by hyp modification
3094   // issue 0021208: to forget not loaded mesh data at hyp modification
3095   struct TCallUp_i : public SMESH_Mesh::TCallUp
3096   {
3097     SMESH_Mesh_i* _mesh;
3098     TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
3099     virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); }
3100     virtual void HypothesisModified (int theHypID)  { _mesh->onHypothesisModified( theHypID ); }
3101     virtual void Load ()                            { _mesh->Load(); }
3102   };
3103 }
3104
3105 //================================================================================
3106 /*!
3107  * \brief callback from _impl to forget not loaded mesh data (issue 0021208)
3108  */
3109 //================================================================================
3110
3111 void SMESH_Mesh_i::onHypothesisModified(int theHypID)
3112 {
3113   if ( _preMeshInfo )
3114     _preMeshInfo->ForgetOrLoad();
3115
3116   SMESH::SMESH_Mesh_var mesh = _this();
3117   _gen_i->UpdateIcons( mesh );
3118
3119   // mark a hypothesis as valid after edition
3120   SALOMEDS::SComponent_wrap smeshComp = _gen_i->PublishComponent();
3121   SALOMEDS::SObject_wrap hypRoot;
3122   if ( !smeshComp->_is_nil() && 
3123        smeshComp->FindSubObject( _gen_i->GetHypothesisRootTag(), hypRoot.inout() ))
3124   {
3125     SALOMEDS::ChildIterator_wrap anIter = _gen_i->getStudyServant()->NewChildIterator( hypRoot );
3126     for ( ; anIter->More(); anIter->Next() )
3127     {
3128       SALOMEDS::SObject_wrap    hypSO = anIter->Value();
3129       CORBA::Object_var           obj = _gen_i->SObjectToObject( hypSO );
3130       SMESH::SMESH_Hypothesis_var hyp = SMESH::SMESH_Hypothesis::_narrow( obj );
3131       if ( !hyp->_is_nil() && hyp->GetId() == theHypID )
3132         _gen_i->HighLightInvalid( hyp, false );
3133     }
3134   }
3135 }
3136
3137 //=============================================================================
3138 /*!
3139  *
3140  */
3141 //=============================================================================
3142
3143 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
3144 {
3145   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
3146   _impl = impl;
3147   if ( _impl )
3148     _impl->SetCallUp( new TCallUp_i(this));
3149 }
3150
3151 //=============================================================================
3152 /*!
3153  *
3154  */
3155 //=============================================================================
3156
3157 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
3158 {
3159   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
3160   return *_impl;
3161 }
3162
3163 //=============================================================================
3164 /*!
3165  * Return mesh editor
3166  */
3167 //=============================================================================
3168
3169 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
3170   throw (SALOME::SALOME_Exception)
3171 {
3172   SMESH::SMESH_MeshEditor_var aMeshEdVar;
3173
3174   SMESH_TRY;
3175   if ( _preMeshInfo )
3176     _preMeshInfo->FullLoadFromFile();
3177
3178   // Create MeshEditor
3179   if ( !_editor )
3180     _editor = new SMESH_MeshEditor_i( this, false );
3181   aMeshEdVar = _editor->_this();
3182
3183   // Update Python script
3184   TPythonDump() << _editor << " = "
3185                 << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshEditor()";
3186
3187   SMESH_CATCH( SMESH::throwCorbaException );
3188
3189   return aMeshEdVar._retn();
3190 }
3191
3192 //=============================================================================
3193 /*!
3194  * Return mesh edition previewer
3195  */
3196 //=============================================================================
3197
3198 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
3199   throw (SALOME::SALOME_Exception)
3200 {
3201   SMESH::SMESH_MeshEditor_var aMeshEdVar;
3202
3203   SMESH_TRY;
3204   if ( _preMeshInfo )
3205     _preMeshInfo->FullLoadFromFile();
3206
3207   if ( !_previewEditor )
3208     _previewEditor = new SMESH_MeshEditor_i( this, true );
3209   aMeshEdVar = _previewEditor->_this();
3210
3211   SMESH_CATCH( SMESH::throwCorbaException );
3212
3213   return aMeshEdVar._retn();
3214 }
3215
3216 //================================================================================
3217 /*!
3218  * \brief Return true if the mesh has been edited since a last total re-compute
3219  *        and those modifications may prevent successful partial re-compute
3220  */
3221 //================================================================================
3222
3223 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard() throw(SALOME::SALOME_Exception)
3224 {
3225   Unexpect aCatch(SALOME_SalomeException);
3226   return _impl->HasModificationsToDiscard();
3227 }
3228
3229 //================================================================================
3230 /*!
3231  * \brief Returns a random unique color
3232  */
3233 //================================================================================
3234
3235 static SALOMEDS::Color getUniqueColor( const std::list<SALOMEDS::Color>& theReservedColors )
3236 {
3237   const int MAX_ATTEMPTS = 100;
3238   int cnt = 0;
3239   double tolerance = 0.5;
3240   SALOMEDS::Color col;
3241
3242   bool ok = false;
3243   while ( !ok ) {
3244     // generate random color
3245     double red    = (double)rand() / RAND_MAX;
3246     double green  = (double)rand() / RAND_MAX;
3247     double blue   = (double)rand() / RAND_MAX;
3248     // check existence in the list of the existing colors
3249     bool matched = false;
3250     std::list<SALOMEDS::Color>::const_iterator it;
3251     for ( it = theReservedColors.begin(); it != theReservedColors.end() && !matched; ++it ) {
3252       SALOMEDS::Color color = *it;
3253       double tol = fabs( color.R - red ) + fabs( color.G - green ) + fabs( color.B  - blue  );
3254       matched = tol < tolerance;
3255     }
3256     if ( (cnt+1) % 20 == 0 ) tolerance = tolerance/2;
3257     ok = ( ++cnt == MAX_ATTEMPTS ) || !matched;
3258     col.R = red;
3259     col.G = green;
3260     col.B = blue;
3261   }
3262   return col;
3263 }
3264
3265 //=============================================================================
3266 /*!
3267  * Sets auto-color mode. If it is on, groups get unique random colors
3268  */
3269 //=============================================================================
3270
3271 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOME_Exception)
3272 {
3273   Unexpect aCatch(SALOME_SalomeException);
3274   _impl->SetAutoColor(theAutoColor);
3275
3276   TPythonDump pyDump; // not to dump group->SetColor() from below code
3277   pyDump << SMESH::SMESH_Mesh_var(_this()) <<".SetAutoColor( "<<theAutoColor<<" )";
3278
3279   std::list<SALOMEDS::Color> aReservedColors;
3280   map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
3281   for ( ; it != _mapGroups.end(); it++ ) {
3282     if ( CORBA::is_nil( it->second )) continue;
3283     SALOMEDS::Color aColor = getUniqueColor( aReservedColors );
3284     it->second->SetColor( aColor );
3285     aReservedColors.push_back( aColor );
3286   }
3287 }
3288
3289 //=============================================================================
3290 /*!
3291  * Returns true if auto-color mode is on
3292  */
3293 //=============================================================================
3294
3295 CORBA::Boolean SMESH_Mesh_i::GetAutoColor() throw(SALOME::SALOME_Exception)
3296 {
3297   Unexpect aCatch(SALOME_SalomeException);
3298   return _impl->GetAutoColor();
3299 }
3300
3301 //=============================================================================
3302 /*!
3303  *  Checks if there are groups with equal names
3304  */
3305 //=============================================================================
3306
3307 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
3308 {
3309   return _impl->HasDuplicatedGroupNamesMED();
3310 }
3311
3312 //================================================================================
3313 /*!
3314  * \brief Care of a file before exporting mesh into it
3315  */
3316 //================================================================================
3317
3318 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
3319 {
3320   SMESH_File aFile( file, false );
3321   SMESH_Comment msg;
3322   if ( aFile.exists() ) {
3323     // existing filesystem node
3324     if ( !aFile.isDirectory() ) {
3325       if ( aFile.openForWriting() ) {
3326         if ( overwrite && ! aFile.remove()) {
3327           msg << "Can't replace " << aFile.getName();
3328         }
3329       } else {
3330         msg << "Can't write into " << aFile.getName();
3331       }
3332     } else {
3333       msg << "Location " << aFile.getName() << " is not a file";
3334     }
3335   }
3336   else {
3337     // nonexisting file; check if it can be created
3338     if ( !aFile.openForWriting() ) {
3339       msg << "You cannot create the file "
3340           << aFile.getName()
3341           << ". Check the directory existence and access rights";
3342     }
3343     aFile.remove();
3344   }
3345
3346   if ( !msg.empty() )
3347   {
3348     msg << ".";
3349     THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::BAD_PARAM);
3350   }
3351 }
3352
3353 //================================================================================
3354 /*!
3355  * \brief Prepares a file for export and pass names of mesh groups from study to mesh DS
3356  *  \param file - file name
3357  *  \param overwrite - to erase the file or not
3358  *  \retval string - mesh name
3359  */
3360 //================================================================================
3361
3362 string SMESH_Mesh_i::prepareMeshNameAndGroups(const char*    file,
3363                                               CORBA::Boolean overwrite)
3364 {
3365   // Perform Export
3366   PrepareForWriting(file, overwrite);
3367   string aMeshName = "Mesh";
3368   SALOMEDS::Study_var aStudy = SMESH_Gen_i::getStudyServant();
3369   if ( !aStudy->_is_nil() ) {
3370     SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject(  _this() );
3371     if ( !aMeshSO->_is_nil() ) {
3372       CORBA::String_var name = aMeshSO->GetName();
3373       aMeshName = name;
3374       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
3375       if ( !aStudy->GetProperties()->IsLocked() )
3376       {
3377         SALOMEDS::GenericAttribute_wrap anAttr;
3378         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
3379         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
3380         SALOMEDS::AttributeExternalFileDef_wrap aFileName = anAttr;
3381         ASSERT(!aFileName->_is_nil());
3382         aFileName->SetValue(file);
3383         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
3384         SALOMEDS::AttributeFileType_wrap aFileType = anAttr;
3385         ASSERT(!aFileType->_is_nil());
3386         aFileType->SetValue("FICHIERMED");
3387       }
3388     }
3389   }
3390   // Update Python script
3391   // set name of mesh before export
3392   TPythonDump() << _gen_i << ".SetName("
3393                 << SMESH::SMESH_Mesh_var(_this()) << ", '" << aMeshName.c_str() << "')";
3394
3395   // check names of groups
3396   checkGroupNames();
3397
3398   return aMeshName;
3399 }
3400
3401 //================================================================================
3402 /*!
3403  * \brief Export to MED file
3404  */
3405 //================================================================================
3406
3407 void SMESH_Mesh_i::ExportMED(const char*        file,
3408                              CORBA::Boolean     auto_groups,
3409                              CORBA::Long        version,
3410                              CORBA::Boolean     overwrite,
3411                              CORBA::Boolean     autoDimension)
3412   throw(SALOME::SALOME_Exception)
3413 {
3414   //MESSAGE("MED minor version: "<< minor);
3415   SMESH_TRY;
3416   if ( _preMeshInfo )
3417     _preMeshInfo->FullLoadFromFile();
3418
3419   string aMeshName = prepareMeshNameAndGroups(file, overwrite);
3420   _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version, 0, autoDimension );
3421
3422   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportMED( r'"
3423                 << file << "', "
3424                 << "auto_groups=" <<auto_groups << ", "
3425                 << "minor=" << version <<  ", "
3426                 << "overwrite=" << overwrite << ", "
3427                 << "meshPart=None, "
3428                 << "autoDimension=" << autoDimension << " )";
3429
3430   SMESH_CATCH( SMESH::throwCorbaException );
3431 }
3432
3433 //================================================================================
3434 /*!
3435  * \brief Export a mesh to a SAUV file
3436  */
3437 //================================================================================
3438
3439 void SMESH_Mesh_i::ExportSAUV (const char* file,
3440                                CORBA::Boolean auto_groups)
3441   throw(SALOME::SALOME_Exception)
3442 {
3443   Unexpect aCatch(SALOME_SalomeException);
3444   if ( _preMeshInfo )
3445     _preMeshInfo->FullLoadFromFile();
3446
3447   string aMeshName = prepareMeshNameAndGroups(file, true);
3448   TPythonDump() << SMESH::SMESH_Mesh_var( _this())
3449                 << ".ExportSAUV( r'" << file << "', " << auto_groups << " )";
3450   _impl->ExportSAUV(file, aMeshName.c_str(), auto_groups);
3451 }
3452
3453
3454 //================================================================================
3455 /*!
3456  * \brief Export a mesh to a DAT file
3457  */
3458 //================================================================================
3459
3460 void SMESH_Mesh_i::ExportDAT (const char *file)
3461   throw(SALOME::SALOME_Exception)
3462 {
3463   Unexpect aCatch(SALOME_SalomeException);
3464   if ( _preMeshInfo )
3465     _preMeshInfo->FullLoadFromFile();
3466
3467   // Update Python script
3468   // check names of groups
3469   checkGroupNames();
3470   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportDAT( r'" << file << "' )";
3471
3472   // Perform Export
3473   PrepareForWriting(file);
3474   _impl->ExportDAT(file);
3475 }
3476
3477 //================================================================================
3478 /*!
3479  * \brief Export a mesh to an UNV file
3480  */
3481 //================================================================================
3482
3483 void SMESH_Mesh_i::ExportUNV (const char *file)
3484   throw(SALOME::SALOME_Exception)
3485 {
3486   Unexpect aCatch(SALOME_SalomeException);
3487   if ( _preMeshInfo )
3488     _preMeshInfo->FullLoadFromFile();
3489
3490   // Update Python script
3491   // check names of groups
3492   checkGroupNames();
3493   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportUNV( r'" << file << "' )";
3494
3495   // Perform Export
3496   PrepareForWriting(file);
3497   _impl->ExportUNV(file);
3498 }
3499
3500 //================================================================================
3501 /*!
3502  * \brief Export a mesh to an STL file
3503  */
3504 //================================================================================
3505
3506 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
3507   throw(SALOME::SALOME_Exception)
3508 {
3509   Unexpect aCatch(SALOME_SalomeException);
3510   if ( _preMeshInfo )
3511     _preMeshInfo->FullLoadFromFile();
3512
3513   // Update Python script
3514   // check names of groups
3515   checkGroupNames();
3516   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3517                 << ".ExportSTL( r'" << file << "', " << isascii << " )";
3518
3519   CORBA::String_var name;
3520   SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( _this() );
3521   if ( !so->_is_nil() )
3522     name = so->GetName();
3523
3524   // Perform Export
3525   PrepareForWriting( file );
3526   _impl->ExportSTL( file, isascii, name.in() );
3527 }
3528
3529 //================================================================================
3530 /*!
3531  * \brief Export a part of mesh to a med file
3532  */
3533 //================================================================================
3534
3535 void SMESH_Mesh_i::ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart,
3536                                    const char*               file,
3537                                    CORBA::Boolean            auto_groups,
3538                                    CORBA::Long               version,
3539                                    CORBA::Boolean            overwrite,
3540                                    CORBA::Boolean            autoDimension,
3541                                    const GEOM::ListOfFields& fields,
3542                                    const char*               geomAssocFields,
3543                                    CORBA::Double             ZTolerance)
3544   throw (SALOME::SALOME_Exception)
3545 {
3546   MESSAGE("MED version: "<< version);
3547   SMESH_TRY;
3548   if ( _preMeshInfo )
3549     _preMeshInfo->FullLoadFromFile();
3550
3551   // check fields
3552   bool have0dField = false;
3553   if ( fields.length() > 0 )
3554   {
3555     GEOM::GEOM_Object_var shapeToMesh = GetShapeToMesh();
3556     if ( shapeToMesh->_is_nil() )
3557       THROW_SALOME_CORBA_EXCEPTION( "No shape to mesh", SALOME::INTERNAL_ERROR );
3558
3559     for ( size_t i = 0; i < fields.length(); ++i )
3560     {
3561       if ( fields[i]->GetDataType() == GEOM::FDT_String )
3562         THROW_SALOME_CORBA_EXCEPTION
3563           ( "Export of string fields is not supported", SALOME::BAD_PARAM);
3564       GEOM::GEOM_Object_var fieldShape = fields[i]->GetShape();
3565       if ( fieldShape->_is_nil() )
3566         THROW_SALOME_CORBA_EXCEPTION( "Null shape under a field", SALOME::INTERNAL_ERROR );
3567       if ( !fieldShape->IsSame( shapeToMesh ) )
3568         THROW_SALOME_CORBA_EXCEPTION
3569           ( "Field defined not on shape", SALOME::BAD_PARAM);
3570       if ( fields[i]->GetDimension() == 0 )
3571         have0dField = true;
3572     }
3573     if ( geomAssocFields )
3574       for ( int i = 0; geomAssocFields[i]; ++i )
3575         switch ( geomAssocFields[i] ) {
3576         case 'v':case 'e':case 'f':case 's': break;
3577         case 'V':case 'E':case 'F':case 'S': break;
3578         default: THROW_SALOME_CORBA_EXCEPTION
3579             ( "geomAssocFields can include only [vefs] characters", SALOME::BAD_PARAM);
3580         }
3581   }
3582
3583   SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
3584
3585   // write mesh
3586
3587   string aMeshName = "Mesh";
3588   SMESHUtils::Deleter< SMESH_MeshPartDS > tmpDSDeleter(0);
3589   if ( CORBA::is_nil( meshPart ) ||
3590        SMESH::DownCast< SMESH_Mesh_i* >( meshPart ))
3591   {
3592     aMeshName = prepareMeshNameAndGroups(file, overwrite);
3593     _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version,
3594                       0, autoDimension, /*addODOnVertices=*/have0dField,
3595                       ZTolerance);
3596     meshDS = _impl->GetMeshDS();
3597   }
3598   else
3599   {
3600     if ( _preMeshInfo )
3601       _preMeshInfo->FullLoadFromFile();
3602
3603     PrepareForWriting(file, overwrite);
3604
3605     SALOMEDS::SObject_wrap SO = _gen_i->ObjectToSObject( meshPart );
3606     if ( !SO->_is_nil() ) {
3607       CORBA::String_var name = SO->GetName();
3608       aMeshName = name;
3609     }
3610
3611     SMESH_MeshPartDS* partDS = new SMESH_MeshPartDS( meshPart );
3612     _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version,
3613                       partDS, autoDimension, /*addODOnVertices=*/have0dField, ZTolerance);
3614     meshDS = tmpDSDeleter._obj = partDS;
3615   }
3616
3617   // write fields
3618
3619   if ( _impl->HasShapeToMesh() )
3620   {
3621     DriverMED_W_Field fieldWriter;
3622     fieldWriter.SetFile( file );
3623     fieldWriter.SetMeshName( aMeshName );
3624     fieldWriter.AddODOnVertices( have0dField );
3625
3626     exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
3627   }
3628
3629   // dump
3630   GEOM::ListOfGBO_var goList = new GEOM::ListOfGBO;
3631   goList->length( fields.length() );
3632   for ( size_t i = 0; i < fields.length(); ++i )
3633   {
3634     GEOM::GEOM_BaseObject_var gbo = GEOM::GEOM_BaseObject::_narrow( fields[i] );
3635     goList[i] = gbo;
3636   }
3637   TPythonDump() << _this() << ".ExportPartToMED( "
3638                 << meshPart << ", r'"
3639                 << file << "', "
3640                 << auto_groups << ", "
3641                 << version << ", "
3642                 << overwrite << ", "
3643                 << autoDimension << ", "
3644                 << goList << ", '"
3645                 << ( geomAssocFields ? geomAssocFields : "" ) << "',"
3646                 << TVar( ZTolerance )
3647                 << " )";
3648
3649   SMESH_CATCH( SMESH::throwCorbaException );
3650 }
3651
3652 //================================================================================
3653 /*!
3654  * Write GEOM fields to MED file
3655  */
3656 //================================================================================
3657
3658 void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field&        fieldWriter,
3659                                     SMESHDS_Mesh*             meshDS,
3660                                     const GEOM::ListOfFields& fields,
3661                                     const char*               geomAssocFields)
3662 {
3663 #define METH "SMESH_Mesh_i::exportMEDFields() "
3664
3665   if (( fields.length() < 1 ) &&
3666       ( !geomAssocFields || !geomAssocFields[0] ))
3667     return;
3668
3669   std::vector< std::vector< double > > dblVals;
3670   std::vector< std::vector< int > >    intVals;
3671   std::vector< int >                   subIdsByDim[ 4 ];
3672   const double noneDblValue = 0.;
3673   const double noneIntValue = 0;
3674
3675   for ( size_t iF = 0; iF < fields.length(); ++iF )
3676   {
3677     // set field data
3678
3679     int dim = fields[ iF ]->GetDimension();
3680     SMDSAbs_ElementType elemType;
3681     TopAbs_ShapeEnum    shapeType;
3682     switch ( dim ) {
3683     case 0: elemType = SMDSAbs_0DElement; shapeType = TopAbs_VERTEX; break;
3684     case 1: elemType = SMDSAbs_Edge;      shapeType = TopAbs_EDGE;   break;
3685     case 2: elemType = SMDSAbs_Face;      shapeType = TopAbs_FACE;   break;
3686     case 3: elemType = SMDSAbs_Volume;    shapeType = TopAbs_SOLID;  break;
3687     default:
3688       continue; // skip fields on whole shape
3689     }
3690     GEOM::field_data_type dataType = fields[ iF ]->GetDataType();
3691     if ( dataType == GEOM::FDT_String )
3692       continue;
3693     GEOM::ListOfLong_var stepIDs = fields[ iF ]->GetSteps();
3694     if ( stepIDs->length() < 1 )
3695       continue;
3696     GEOM::string_array_var comps = fields[ iF ]->GetComponents();
3697     if ( comps->length() < 1 )
3698       continue;
3699     CORBA::String_var       name = fields[ iF ]->GetName();
3700
3701     if ( !fieldWriter.Set( meshDS,
3702                            name.in(),
3703                            elemType,
3704                            comps->length(),
3705                            /*isIntData=*/false ))//( dataType == GEOM::FDT_Int )))
3706       continue;
3707
3708     for ( size_t iC = 0; iC < comps->length(); ++iC )
3709       fieldWriter.SetCompName( iC, comps[ iC ].in() );
3710
3711     dblVals.resize( comps->length() );
3712     intVals.resize( comps->length() );
3713
3714     // find sub-shape IDs
3715
3716     std::vector< int >& subIds = subIdsByDim[ dim ];
3717     if ( subIds.empty() )
3718       for ( int id = 1; id <= meshDS->MaxShapeIndex(); ++id )
3719         if ( meshDS->IndexToShape( id ).ShapeType() == shapeType )
3720           subIds.push_back( id );
3721
3722     // write steps
3723
3724     SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
3725     if ( !elemIt )
3726       continue;
3727
3728     for ( size_t iS = 0; iS < stepIDs->length(); ++iS )
3729     {
3730       GEOM::GEOM_FieldStep_var step = fields[ iF ]->GetStep( stepIDs[ iS ]);
3731       if ( step->_is_nil() )
3732         continue;
3733
3734       CORBA::Long stamp = step->GetStamp();
3735       CORBA::Long id    = step->GetID();
3736       fieldWriter.SetDtIt( int( stamp ), int( id ));
3737
3738       // fill dblVals or intVals
3739       for ( size_t iC = 0; iC < comps->length(); ++iC )
3740         if ( dataType == GEOM::FDT_Double )
3741         {
3742           dblVals[ iC ].clear();
3743           dblVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
3744         }
3745         else
3746         {
3747           intVals[ iC ].clear();
3748           intVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
3749         }
3750       switch ( dataType )
3751       {
3752       case GEOM::FDT_Double:
3753       {
3754         GEOM::GEOM_DoubleFieldStep_var dblStep = GEOM::GEOM_DoubleFieldStep::_narrow( step );
3755         if ( dblStep->_is_nil() ) continue;
3756         GEOM::ListOfDouble_var vv = dblStep->GetValues();
3757         if ( vv->length() != subIds.size() * comps->length() )
3758           THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
3759         for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
3760           for ( size_t iC = 0; iC < comps->length(); ++iC )
3761             dblVals[ iC ][ subIds[ iS ]] = vv[ iV++ ];
3762         break;
3763       }
3764       case GEOM::FDT_Int:
3765       {
3766         GEOM::GEOM_IntFieldStep_var intStep = GEOM::GEOM_IntFieldStep::_narrow( step );
3767         if ( intStep->_is_nil() ) continue;
3768         GEOM::ListOfLong_var vv = intStep->GetValues();
3769         if ( vv->length() != subIds.size() * comps->length() )
3770           THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
3771         for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
3772           for ( size_t iC = 0; iC < comps->length(); ++iC )
3773             intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
3774         break;
3775       }
3776       case GEOM::FDT_Bool:
3777       {
3778         GEOM::GEOM_BoolFieldStep_var boolStep = GEOM::GEOM_BoolFieldStep::_narrow( step );
3779         if ( boolStep->_is_nil() ) continue;
3780         GEOM::short_array_var vv = boolStep->GetValues();
3781         if ( vv->length() != subIds.size() * comps->length() )
3782           THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
3783         for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
3784           for ( size_t iC = 0; iC < comps->length(); ++iC )
3785             intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
3786         break;
3787       }
3788       default: continue;
3789       }
3790
3791       // pass values to fieldWriter
3792       elemIt = fieldWriter.GetOrderedElems();
3793       if ( dataType == GEOM::FDT_Double )
3794         while ( elemIt->more() )
3795         {
3796           const SMDS_MeshElement* e = elemIt->next();
3797           const int shapeID = e->getshapeId();
3798           if ( shapeID < 1 || shapeID >= (int) dblVals[0].size() )
3799             for ( size_t iC = 0; iC < comps->length(); ++iC )
3800               fieldWriter.AddValue( noneDblValue );
3801           else
3802             for ( size_t iC = 0; iC < comps->length(); ++iC )
3803               fieldWriter.AddValue( dblVals[ iC ][ shapeID ]);
3804         }
3805       else
3806         while ( elemIt->more() )
3807         {
3808           const SMDS_MeshElement* e = elemIt->next();
3809           const int shapeID = e->getshapeId();
3810           if ( shapeID < 1 || shapeID >= (int) intVals[0].size() )
3811             for ( size_t iC = 0; iC < comps->length(); ++iC )
3812               fieldWriter.AddValue( (double) noneIntValue );
3813           else
3814             for ( size_t iC = 0; iC < comps->length(); ++iC )
3815               fieldWriter.AddValue( (double) intVals[ iC ][ shapeID ]);
3816         }
3817
3818       // write a step
3819       fieldWriter.Perform();
3820       SMESH_ComputeErrorPtr res = fieldWriter.GetError();
3821       if ( res && res->IsKO() )
3822       {
3823         if ( res->myComment.empty() )
3824         { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
3825         else
3826         { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
3827       }
3828
3829     } // loop on steps
3830   } // loop on fields
3831
3832   if ( !geomAssocFields || !geomAssocFields[0] )
3833     return;
3834
3835   // write geomAssocFields
3836
3837   std::vector< int > shapeDim( TopAbs_SHAPE + 1 );
3838   shapeDim[ TopAbs_COMPOUND  ] = 3;
3839   shapeDim[ TopAbs_COMPSOLID ] = 3;
3840   shapeDim[ TopAbs_SOLID     ] = 3;
3841   shapeDim[ TopAbs_SHELL     ] = 2;
3842   shapeDim[ TopAbs_FACE      ] = 2;
3843   shapeDim[ TopAbs_WIRE      ] = 1;
3844   shapeDim[ TopAbs_EDGE      ] = 1;
3845   shapeDim[ TopAbs_VERTEX    ] = 0;
3846   shapeDim[ TopAbs_SHAPE     ] = 3;
3847
3848   for ( int iF = 0; geomAssocFields[ iF ]; ++iF )
3849   {
3850     std::vector< std::string > compNames;
3851     switch ( geomAssocFields[ iF ]) {
3852     case 'v': case 'V':
3853       fieldWriter.Set( meshDS, "_vertices_", SMDSAbs_Node, /*nbComps=*/2, /*isInt=*/false );
3854       compNames.push_back( "dim" );
3855       break;
3856     case 'e': case 'E':
3857       fieldWriter.Set( meshDS, "_edges_", SMDSAbs_Edge, /*nbComps=*/1, /*isInt=*/false );
3858       break;
3859     case 'f': case 'F':
3860       fieldWriter.Set( meshDS, "_faces_", SMDSAbs_Face, /*nbComps=*/1, /*isInt=*/false );
3861       break;
3862     case 's': case 'S':
3863       fieldWriter.Set( meshDS, "_solids_", SMDSAbs_Volume, /*nbComps=*/1, /*isInt=*/false );
3864       break;
3865     default: continue;
3866     }
3867     compNames.push_back( "id" );
3868     for ( size_t iC = 0; iC < compNames.size(); ++iC )
3869       fieldWriter.SetCompName( iC, compNames[ iC ].c_str() );
3870
3871     fieldWriter.SetDtIt( -1, -1 );
3872
3873     SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
3874     if ( !elemIt )
3875       continue;
3876
3877     if ( compNames.size() == 2 ) // _vertices_
3878       while ( elemIt->more() )
3879       {
3880         const SMDS_MeshElement* e = elemIt->next();
3881         const int shapeID = e->getshapeId();
3882         if ( shapeID < 1 )
3883         {
3884           fieldWriter.AddValue( (double) -1 );
3885           fieldWriter.AddValue( (double) -1 );
3886         }
3887         else
3888         {
3889           const TopoDS_Shape& S = meshDS->IndexToShape( shapeID );
3890           fieldWriter.AddValue( (double) ( S.IsNull() ? -1 : shapeDim[ S.ShapeType() ]));
3891           fieldWriter.AddValue( (double) shapeID );
3892         }
3893       }
3894     else
3895       while ( elemIt->more() )
3896       {
3897         const SMDS_MeshElement* e = elemIt->next();
3898         const int shapeID = e->getshapeId();
3899         if ( shapeID < 1 )
3900           fieldWriter.AddValue( (double) -1 );
3901         else
3902           fieldWriter.AddValue( (double) shapeID );
3903       }
3904
3905     // write a step
3906     fieldWriter.Perform();
3907     SMESH_ComputeErrorPtr res = fieldWriter.GetError();
3908     if ( res && res->IsKO() )
3909     {
3910       if ( res->myComment.empty() )
3911       { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
3912       else
3913       { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
3914     }
3915
3916   } // loop on geomAssocFields
3917
3918 #undef METH
3919 }
3920
3921 //================================================================================
3922 /*!
3923  * \brief Export a part of mesh to a DAT file
3924  */
3925 //================================================================================
3926
3927 void SMESH_Mesh_i::ExportPartToDAT(::SMESH::SMESH_IDSource_ptr meshPart,
3928                                    const char*                 file)
3929   throw (SALOME::SALOME_Exception)
3930 {
3931   Unexpect aCatch(SALOME_SalomeException);
3932   if ( _preMeshInfo )
3933     _preMeshInfo->FullLoadFromFile();
3934
3935   PrepareForWriting(file);
3936
3937   SMESH_MeshPartDS partDS( meshPart );
3938   _impl->ExportDAT(file,&partDS);
3939
3940   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3941                 << ".ExportPartToDAT( " << meshPart << ", r'" << file << "' )";
3942 }
3943 //================================================================================
3944 /*!
3945  * \brief Export a part of mesh to an UNV file
3946  */
3947 //================================================================================
3948
3949 void SMESH_Mesh_i::ExportPartToUNV(::SMESH::SMESH_IDSource_ptr meshPart,
3950                                    const char*                 file)
3951   throw (SALOME::SALOME_Exception)
3952 {
3953   Unexpect aCatch(SALOME_SalomeException);
3954   if ( _preMeshInfo )
3955     _preMeshInfo->FullLoadFromFile();
3956
3957   PrepareForWriting(file);
3958
3959   SMESH_MeshPartDS partDS( meshPart );
3960   _impl->ExportUNV(file, &partDS);
3961
3962   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3963                 << ".ExportPartToUNV( " << meshPart<< ", r'" << file << "' )";
3964 }
3965 //================================================================================
3966 /*!
3967  * \brief Export a part of mesh to an STL file
3968  */
3969 //================================================================================
3970
3971 void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
3972                                    const char*                 file,
3973                                    ::CORBA::Boolean            isascii)
3974   throw (SALOME::SALOME_Exception)
3975 {
3976   Unexpect aCatch(SALOME_SalomeException);
3977   if ( _preMeshInfo )
3978     _preMeshInfo->FullLoadFromFile();
3979
3980   PrepareForWriting(file);
3981
3982   CORBA::String_var name;
3983   SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
3984   if ( !so->_is_nil() )
3985     name = so->GetName();
3986
3987   SMESH_MeshPartDS partDS( meshPart );
3988   _impl->ExportSTL( file, isascii, name.in(), &partDS );
3989
3990   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( "
3991                 << meshPart<< ", r'" << file << "', " << isascii << ")";
3992 }
3993
3994 //================================================================================
3995 /*!
3996  * \brief Export a part of mesh to an STL file
3997  */
3998 //================================================================================
3999
4000 void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart,
4001                               const char*                 file,
4002                               CORBA::Boolean              overwrite,
4003                               CORBA::Boolean              groupElemsByType)
4004   throw (SALOME::SALOME_Exception)
4005 {
4006 #ifdef WITH_CGNS
4007   Unexpect aCatch(SALOME_SalomeException);
4008   if ( _preMeshInfo )
4009     _preMeshInfo->FullLoadFromFile();
4010
4011   PrepareForWriting(file,overwrite);
4012
4013   std::string meshName("");
4014   SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
4015   if ( !so->_is_nil() )
4016   {
4017     CORBA::String_var name = so->GetName();
4018     meshName = name.in();
4019   }
4020   SMESH_TRY;
4021
4022   SMESH_MeshPartDS partDS( meshPart );
4023   _impl->ExportCGNS(file, &partDS, meshName.c_str(), groupElemsByType );
4024
4025   SMESH_CATCH( SMESH::throwCorbaException );
4026
4027   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportCGNS( "
4028                 << meshPart<< ", r'" << file << "', " << overwrite << ")";
4029 #else
4030   THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
4031 #endif
4032 }
4033
4034 //================================================================================
4035 /*!
4036  * \brief Export a part of mesh to a GMF file
4037  */
4038 //================================================================================
4039
4040 void SMESH_Mesh_i::ExportGMF(::SMESH::SMESH_IDSource_ptr meshPart,
4041                              const char*                 file,
4042                              bool                        withRequiredGroups)
4043   throw (SALOME::SALOME_Exception)
4044 {
4045   Unexpect aCatch(SALOME_SalomeException);
4046   if ( _preMeshInfo )
4047     _preMeshInfo->FullLoadFromFile();
4048
4049   PrepareForWriting(file,/*overwrite=*/true);
4050
4051   SMESH_MeshPartDS partDS( meshPart );
4052   _impl->ExportGMF(file, &partDS, withRequiredGroups);
4053
4054   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportGMF( "
4055                 << meshPart<< ", r'"
4056                 << file << "', "
4057                 << withRequiredGroups << ")";
4058 }
4059
4060 //=============================================================================
4061 /*!
4062  * Return computation progress [0.,1]
4063  */
4064 //=============================================================================
4065
4066 CORBA::Double SMESH_Mesh_i::GetComputeProgress()
4067 {
4068   SMESH_TRY;
4069
4070   return _impl->GetComputeProgress();
4071
4072   SMESH_CATCH( SMESH::doNothing );
4073   return 0.;
4074 }
4075
4076 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
4077 {
4078   Unexpect aCatch(SALOME_SalomeException);
4079   if ( _preMeshInfo )
4080     return _preMeshInfo->NbNodes();
4081
4082   return _impl->NbNodes();
4083 }
4084
4085 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
4086 {
4087   Unexpect aCatch(SALOME_SalomeException);
4088   if ( _preMeshInfo )
4089     return _preMeshInfo->NbElements();
4090
4091   return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes() + NbBalls();
4092 }
4093
4094 CORBA::Long SMESH_Mesh_i::Nb0DElements()throw (SALOME::SALOME_Exception)
4095 {
4096   Unexpect aCatch(SALOME_SalomeException);
4097   if ( _preMeshInfo )
4098     return _preMeshInfo->Nb0DElements();
4099
4100   return _impl->Nb0DElements();
4101 }
4102
4103 CORBA::Long SMESH_Mesh_i::NbBalls() throw (SALOME::SALOME_Exception)
4104 {
4105   Unexpect aCatch(SALOME_SalomeException);
4106   if ( _preMeshInfo )
4107     return _preMeshInfo->NbBalls();
4108
4109   return _impl->NbBalls();
4110 }
4111
4112 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
4113 {
4114   Unexpect aCatch(SALOME_SalomeException);
4115   if ( _preMeshInfo )
4116     return _preMeshInfo->NbEdges();
4117
4118   return _impl->NbEdges();
4119 }
4120
4121 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
4122   throw(SALOME::SALOME_Exception)
4123 {
4124   Unexpect aCatch(SALOME_SalomeException);
4125   if ( _preMeshInfo )
4126     return _preMeshInfo->NbEdges( (SMDSAbs_ElementOrder) order );
4127
4128   return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
4129 }
4130
4131 //=============================================================================
4132
4133 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
4134 {
4135   Unexpect aCatch(SALOME_SalomeException);
4136   if ( _preMeshInfo )
4137     return _preMeshInfo->NbFaces();
4138
4139   return _impl->NbFaces();
4140 }
4141
4142 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
4143 {
4144   Unexpect aCatch(SALOME_SalomeException);
4145   if ( _preMeshInfo )
4146     return _preMeshInfo->NbTriangles();
4147
4148   return _impl->NbTriangles();
4149 }
4150
4151 CORBA::Long SMESH_Mesh_i::NbBiQuadTriangles()throw(SALOME::SALOME_Exception)
4152 {
4153   Unexpect aCatch(SALOME_SalomeException);
4154   if ( _preMeshInfo )
4155     return _preMeshInfo->NbBiQuadTriangles();
4156
4157   return _impl->NbBiQuadTriangles();
4158 }
4159
4160 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
4161 {
4162   Unexpect aCatch(SALOME_SalomeException);
4163   if ( _preMeshInfo )
4164     return _preMeshInfo->NbQuadrangles();
4165
4166   return _impl->NbQuadrangles();
4167 }
4168
4169 CORBA::Long SMESH_Mesh_i::NbBiQuadQuadrangles()throw(SALOME::SALOME_Exception)
4170 {
4171   Unexpect aCatch(SALOME_SalomeException);
4172   if ( _preMeshInfo )
4173     return _preMeshInfo->NbBiQuadQuadrangles();
4174
4175   return _impl->NbBiQuadQuadrangles();
4176 }
4177
4178 CORBA::Long SMESH_Mesh_i::NbPolygons() throw(SALOME::SALOME_Exception)
4179 {
4180   Unexpect aCatch(SALOME_SalomeException);
4181   if ( _preMeshInfo )
4182     return _preMeshInfo->NbPolygons();
4183
4184   return _impl->NbPolygons();
4185 }
4186
4187 CORBA::Long SMESH_Mesh_i::NbPolygonsOfOrder(SMESH::ElementOrder order) throw(SALOME::SALOME_Exception)
4188 {
4189   Unexpect aCatch(SALOME_SalomeException);
4190   if ( _preMeshInfo )
4191     return _preMeshInfo->NbPolygons((SMDSAbs_ElementOrder) order);
4192
4193   return _impl->NbPolygons((SMDSAbs_ElementOrder)order);
4194 }
4195
4196 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
4197   throw(SALOME::SALOME_Exception)
4198 {
4199   Unexpect aCatch(SALOME_SalomeException);
4200   if ( _preMeshInfo )
4201     return _preMeshInfo->NbFaces( (SMDSAbs_ElementOrder) order );
4202
4203   return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
4204 }
4205
4206 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
4207   throw(SALOME::SALOME_Exception)
4208 {
4209   Unexpect aCatch(SALOME_SalomeException);
4210   if ( _preMeshInfo )
4211     return _preMeshInfo->NbTriangles( (SMDSAbs_ElementOrder) order );
4212
4213   return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
4214 }
4215
4216 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
4217   throw(SALOME::SALOME_Exception)
4218 {
4219   Unexpect aCatch(SALOME_SalomeException);
4220   if ( _preMeshInfo )
4221     return _preMeshInfo->NbQuadrangles( (SMDSAbs_ElementOrder) order );
4222
4223   return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
4224 }
4225
4226 //=============================================================================
4227
4228 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
4229 {
4230   Unexpect aCatch(SALOME_SalomeException);
4231   if ( _preMeshInfo )
4232     return _preMeshInfo->NbVolumes();
4233
4234   return _impl->NbVolumes();
4235 }
4236
4237 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
4238 {
4239   Unexpect aCatch(SALOME_SalomeException);
4240   if ( _preMeshInfo )
4241     return _preMeshInfo->NbTetras();
4242
4243   return _impl->NbTetras();
4244 }
4245
4246 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
4247 {
4248   Unexpect aCatch(SALOME_SalomeException);
4249   if ( _preMeshInfo )
4250     return _preMeshInfo->NbHexas();
4251
4252   return _impl->NbHexas();
4253 }
4254
4255 CORBA::Long SMESH_Mesh_i::NbTriQuadraticHexas()throw(SALOME::SALOME_Exception)
4256 {
4257   Unexpect aCatch(SALOME_SalomeException);
4258   if ( _preMeshInfo )
4259     return _preMeshInfo->NbTriQuadHexas();
4260
4261   return _impl->NbTriQuadraticHexas();
4262 }
4263
4264 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
4265 {
4266   Unexpect aCatch(SALOME_SalomeException);
4267   if ( _preMeshInfo )
4268     return _preMeshInfo->NbPyramids();
4269
4270   return _impl->NbPyramids();
4271 }
4272
4273 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
4274 {
4275   Unexpect aCatch(SALOME_SalomeException);
4276   if ( _preMeshInfo )
4277     return _preMeshInfo->NbPrisms();
4278
4279   return _impl->NbPrisms();
4280 }
4281
4282 CORBA::Long SMESH_Mesh_i::NbHexagonalPrisms()throw(SALOME::SALOME_Exception)
4283 {
4284   Unexpect aCatch(SALOME_SalomeException);
4285   if ( _preMeshInfo )
4286     return _preMeshInfo->NbHexPrisms();
4287
4288   return _impl->NbHexagonalPrisms();
4289 }
4290
4291 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
4292 {
4293   Unexpect aCatch(SALOME_SalomeException);
4294   if ( _preMeshInfo )
4295     return _preMeshInfo->NbPolyhedrons();
4296
4297   return _impl->NbPolyhedrons();
4298 }
4299
4300 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
4301   throw(SALOME::SALOME_Exception)
4302 {
4303   Unexpect aCatch(SALOME_SalomeException);
4304   if ( _preMeshInfo )
4305     return _preMeshInfo->NbVolumes( (SMDSAbs_ElementOrder) order );
4306
4307   return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
4308 }
4309
4310 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
4311   throw(SALOME::SALOME_Exception)
4312 {
4313   Unexpect aCatch(SALOME_SalomeException);
4314   if ( _preMeshInfo )
4315     return _preMeshInfo->NbTetras( (SMDSAbs_ElementOrder) order);
4316
4317   return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
4318 }
4319
4320 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
4321   throw(SALOME::SALOME_Exception)
4322 {
4323   Unexpect aCatch(SALOME_SalomeException);
4324   if ( _preMeshInfo )
4325     return _preMeshInfo->NbHexas( (SMDSAbs_ElementOrder) order);
4326
4327   return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
4328 }
4329
4330 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
4331   throw(SALOME::SALOME_Exception)
4332 {
4333   Unexpect aCatch(SALOME_SalomeException);
4334   if ( _preMeshInfo )
4335     return _preMeshInfo->NbPyramids( (SMDSAbs_ElementOrder) order);
4336
4337   return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
4338 }
4339
4340 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
4341   throw(SALOME::SALOME_Exception)
4342 {
4343   Unexpect aCatch(SALOME_SalomeException);
4344   if ( _preMeshInfo )
4345     return _preMeshInfo->NbPrisms( (SMDSAbs_ElementOrder) order);
4346
4347   return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
4348 }
4349
4350 //=============================================================================
4351 /*!
4352  * Returns nb of published sub-meshes
4353  */
4354 //=============================================================================
4355
4356 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
4357 {
4358   Unexpect aCatch(SALOME_SalomeException);
4359   return _mapSubMesh_i.size();
4360 }
4361
4362 //=============================================================================
4363 /*!
4364  * Dumps mesh into a string
4365  */
4366 //=============================================================================
4367
4368 char* SMESH_Mesh_i::Dump()
4369 {
4370   ostringstream os;
4371   _impl->Dump( os );
4372   return CORBA::string_dup( os.str().c_str() );
4373 }
4374
4375 //=============================================================================
4376 /*!
4377  * Method of SMESH_IDSource interface
4378  */
4379 //=============================================================================
4380
4381 SMESH::long_array* SMESH_Mesh_i::GetIDs()
4382 {
4383   return GetElementsId();
4384 }
4385
4386 //=============================================================================
4387 /*!
4388  * Returns ids of all elements
4389  */
4390 //=============================================================================
4391
4392 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
4393   throw (SALOME::SALOME_Exception)
4394 {
4395   Unexpect aCatch(SALOME_SalomeException);
4396   if ( _preMeshInfo )
4397     _preMeshInfo->FullLoadFromFile();
4398
4399   SMESH::long_array_var aResult = new SMESH::long_array();
4400   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4401
4402   if ( aSMESHDS_Mesh == NULL )
4403     return aResult._retn();
4404
4405   long nbElements = NbElements();
4406   aResult->length( nbElements );
4407   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
4408   for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
4409     aResult[i] = anIt->next()->GetID();
4410
4411   return aResult._retn();
4412 }
4413
4414
4415 //=============================================================================
4416 /*!
4417  * Returns ids of all elements of given type
4418  */
4419 //=============================================================================
4420
4421 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
4422     throw (SALOME::SALOME_Exception)
4423 {
4424   Unexpect aCatch(SALOME_SalomeException);
4425   if ( _preMeshInfo )
4426     _preMeshInfo->FullLoadFromFile();
4427
4428   SMESH::long_array_var aResult = new SMESH::long_array();
4429   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
4430
4431   if ( aSMESHDS_Mesh == NULL )
4432     return aResult._retn();
4433
4434   long nbElements = NbElements();
4435
4436   // No sense in returning ids of elements along with ids of nodes:
4437   // when theElemType == SMESH::ALL, return node ids only if
4438   // there are no elements
4439   if ( theElemType == SMESH::NODE || (theElemType == SMESH::ALL && nbElements == 0) )
4440     return GetNodesId();
4441
4442   aResult->length( nbElements );
4443
4444   int i = 0;
4445
4446   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator( (SMDSAbs_ElementType)theElemType );
4447   while ( i < nbElements && anIt->more() )
4448     aResult[i++] = anIt->next()->GetID();
4449
4450   aResult->length( i );
4451
4452   return aResult._retn();
4453 }
4454
4455 //=============================================================================
4456 /*!
4457  * Returns ids of all nodes
4458  */
4459 //=============================================================================
4460
4461 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
4462   throw (SALOME::SALOME_Exception)
4463 {
4464   Unexpect aCatch(SALOME_SalomeException);
4465   if ( _preMeshInfo )
4466     _preMeshInfo->FullLoadFromFile();
4467
4468   SMESH::long_array_var aResult = new SMESH::long_array();
4469   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4470
4471   if ( aMeshDS == NULL )
4472     return aResult._retn();
4473
4474   long nbNodes = NbNodes();
4475   aResult->length( nbNodes );
4476   SMDS_NodeIteratorPtr anIt = aMeshDS->nodesIterator();
4477   for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
4478     aResult[i] = anIt->next()->GetID();
4479
4480   return aResult._retn();
4481 }
4482
4483 //=============================================================================
4484 /*!
4485  *
4486  */
4487 //=============================================================================
4488
4489 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
4490   throw (SALOME::SALOME_Exception)
4491 {
4492   SMESH::ElementType type = SMESH::ALL;
4493   SMESH_TRY;
4494
4495   if ( _preMeshInfo )
4496     _preMeshInfo->FullLoadFromFile();
4497
4498   type = ( SMESH::ElementType ) _impl->GetElementType( id, iselem );
4499
4500   SMESH_CATCH( SMESH::throwCorbaException );
4501
4502   return type;
4503 }
4504
4505 //=============================================================================
4506 /*!
4507  *
4508  */
4509 //=============================================================================
4510
4511 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id )
4512   throw (SALOME::SALOME_Exception)
4513 {
4514   if ( _preMeshInfo )
4515     _preMeshInfo->FullLoadFromFile();
4516
4517   const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
4518   if ( !e )
4519     THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
4520
4521   return ( SMESH::EntityType ) e->GetEntityType();
4522 }
4523
4524 //=============================================================================
4525 /*!
4526  *
4527  */
4528 //=============================================================================
4529
4530 SMESH::GeometryType SMESH_Mesh_i::GetElementShape( const CORBA::Long id )
4531   throw (SALOME::SALOME_Exception)
4532 {
4533   if ( _preMeshInfo )
4534     _preMeshInfo->FullLoadFromFile();
4535
4536   const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
4537   if ( !e )
4538     THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
4539
4540   return ( SMESH::GeometryType ) e->GetGeomType();
4541 }
4542
4543 //=============================================================================
4544 /*!
4545  * Returns ID of elements for given submesh
4546  */
4547 //=============================================================================
4548 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
4549      throw (SALOME::SALOME_Exception)
4550 {
4551   SMESH::long_array_var aResult = new SMESH::long_array();
4552
4553   SMESH_TRY;
4554   if ( _preMeshInfo )
4555     _preMeshInfo->FullLoadFromFile();
4556
4557   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4558   if(!SM) return aResult._retn();
4559
4560   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
4561   if(!SDSM) return aResult._retn();
4562
4563   aResult->length(SDSM->NbElements());
4564
4565   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
4566   int i = 0;
4567   while ( eIt->more() ) {
4568     aResult[i++] = eIt->next()->GetID();
4569   }
4570
4571   SMESH_CATCH( SMESH::throwCorbaException );
4572
4573   return aResult._retn();
4574 }
4575
4576 //=============================================================================
4577 /*!
4578  * Returns ID of nodes for given submesh
4579  * If param all==true - returns all nodes, else -
4580  * returns only nodes on shapes.
4581  */
4582 //=============================================================================
4583
4584 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
4585                                                    CORBA::Boolean    all)
4586   throw (SALOME::SALOME_Exception)
4587 {
4588   SMESH::long_array_var aResult = new SMESH::long_array();
4589
4590   SMESH_TRY;
4591   if ( _preMeshInfo )
4592     _preMeshInfo->FullLoadFromFile();
4593
4594   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4595   if(!SM) return aResult._retn();
4596
4597   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
4598   if(!SDSM) return aResult._retn();
4599
4600   set<int> theElems;
4601   if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
4602     SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
4603     while ( nIt->more() ) {
4604       const SMDS_MeshNode* elem = nIt->next();
4605       theElems.insert( elem->GetID() );
4606     }
4607   }
4608   else { // all nodes of submesh elements
4609     SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
4610     while ( eIt->more() ) {
4611       const SMDS_MeshElement* anElem = eIt->next();
4612       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
4613       while ( nIt->more() ) {
4614         const SMDS_MeshElement* elem = nIt->next();
4615         theElems.insert( elem->GetID() );
4616       }
4617     }
4618   }
4619
4620   aResult->length(theElems.size());
4621   set<int>::iterator itElem;
4622   int i = 0;
4623   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
4624     aResult[i++] = *itElem;
4625
4626   SMESH_CATCH( SMESH::throwCorbaException );
4627
4628   return aResult._retn();
4629 }
4630
4631 //=============================================================================
4632 /*!
4633  * Returns type of elements for given submesh
4634  */
4635 //=============================================================================
4636
4637 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
4638   throw (SALOME::SALOME_Exception)
4639 {
4640   SMESH::ElementType type = SMESH::ALL;
4641
4642   SMESH_TRY;
4643   if ( _preMeshInfo )
4644     _preMeshInfo->FullLoadFromFile();
4645
4646   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
4647   if(!SM) return SMESH::ALL;
4648
4649   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
4650   if(!SDSM) return SMESH::ALL;
4651
4652   if(SDSM->NbElements()==0)
4653     return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
4654
4655   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
4656   const SMDS_MeshElement* anElem = eIt->next();
4657
4658   type = ( SMESH::ElementType ) anElem->GetType();
4659
4660   SMESH_CATCH( SMESH::throwCorbaException );
4661
4662   return type;
4663 }
4664
4665
4666 //=============================================================================
4667 /*!
4668  * Returns pointer to _impl as an integer value. Is called from constructor of SMESH_Client
4669  */
4670 //=============================================================================
4671
4672 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
4673 {
4674   if ( _preMeshInfo )
4675     _preMeshInfo->FullLoadFromFile();
4676
4677   CORBA::LongLong pointeur = CORBA::LongLong(_impl);
4678   if ( MYDEBUG ) MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
4679   return pointeur;
4680 }
4681
4682
4683 //=============================================================================
4684 /*!
4685  * Get XYZ coordinates of node as list of double
4686  * If there is not node for given ID - returns empty list
4687  */
4688 //=============================================================================
4689
4690 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
4691 {
4692   if ( _preMeshInfo )
4693     _preMeshInfo->FullLoadFromFile();
4694
4695   SMESH::double_array_var aResult = new SMESH::double_array();
4696   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4697   if ( aMeshDS == NULL )
4698     return aResult._retn();
4699
4700   // find node
4701   const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
4702   if(!aNode)
4703     return aResult._retn();
4704
4705   // add coordinates
4706   aResult->length(3);
4707   aResult[0] = aNode->X();
4708   aResult[1] = aNode->Y();
4709   aResult[2] = aNode->Z();
4710   return aResult._retn();
4711 }
4712
4713
4714 //=============================================================================
4715 /*!
4716  * For given node returns list of IDs of inverse elements
4717  * If there is not node for given ID - returns empty list
4718  */
4719 //=============================================================================
4720
4721 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long  id,
4722                                                         SMESH::ElementType elemType)
4723 {
4724   if ( _preMeshInfo )
4725     _preMeshInfo->FullLoadFromFile();
4726
4727   SMESH::long_array_var aResult = new SMESH::long_array();
4728   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4729   if ( aMeshDS == NULL )
4730     return aResult._retn();
4731
4732   // find node
4733   const SMDS_MeshNode* aNode = aMeshDS->FindNode( id );
4734   if ( !aNode )
4735     return aResult._retn();
4736
4737   // find inverse elements
4738   SMDSAbs_ElementType type = SMDSAbs_ElementType( elemType );
4739   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator( type );
4740   aResult->length( aNode->NbInverseElements( type ));
4741   for( int i = 0; eIt->more(); ++i )
4742   {
4743     const SMDS_MeshElement* elem = eIt->next();
4744     aResult[ i ] = elem->GetID();
4745   }
4746   return aResult._retn();
4747 }
4748
4749 //=============================================================================
4750 /*!
4751  * \brief Return position of a node on shape
4752  */
4753 //=============================================================================
4754
4755 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
4756 {
4757   if ( _preMeshInfo )
4758     _preMeshInfo->FullLoadFromFile();
4759
4760   SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
4761   aNodePosition->shapeID = 0;
4762   aNodePosition->shapeType = GEOM::SHAPE;
4763
4764   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
4765   if ( !mesh ) return aNodePosition;
4766
4767   if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
4768   {
4769     if ( SMDS_PositionPtr pos = aNode->GetPosition() )
4770     {
4771       aNodePosition->shapeID = aNode->getshapeId();
4772       switch ( pos->GetTypeOfPosition() ) {
4773       case SMDS_TOP_EDGE:
4774         aNodePosition->shapeType = GEOM::EDGE;
4775         aNodePosition->params.length(1);
4776         aNodePosition->params[0] = SMDS_EdgePositionPtr( pos )->GetUParameter();
4777         break;
4778       case SMDS_TOP_FACE: {
4779         SMDS_FacePositionPtr fPos = pos;
4780         aNodePosition->shapeType = GEOM::FACE;
4781         aNodePosition->params.length(2);
4782         aNodePosition->params[0] = fPos->GetUParameter();
4783         aNodePosition->params[1] = fPos->GetVParameter();
4784         break;
4785       }
4786       case SMDS_TOP_VERTEX:
4787         aNodePosition->shapeType = GEOM::VERTEX;
4788         break;
4789       case SMDS_TOP_3DSPACE:
4790         if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
4791           aNodePosition->shapeType = GEOM::SOLID;
4792         else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
4793           aNodePosition->shapeType = GEOM::SHELL;
4794         break;
4795       default:;
4796       }
4797     }
4798   }
4799   return aNodePosition;
4800 }
4801
4802 //=============================================================================
4803 /*!
4804  * \brief Return position of an element on shape
4805  */
4806 //=============================================================================
4807
4808 SMESH::ElementPosition SMESH_Mesh_i::GetElementPosition(CORBA::Long ElemID)
4809 {
4810   if ( _preMeshInfo )
4811     _preMeshInfo->FullLoadFromFile();
4812
4813   SMESH::ElementPosition anElementPosition;
4814   anElementPosition.shapeID = 0;
4815   anElementPosition.shapeType = GEOM::SHAPE;
4816
4817   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
4818   if ( !mesh ) return anElementPosition;
4819
4820   if ( const SMDS_MeshElement* anElem = mesh->FindElement( ElemID ) )
4821   {
4822     anElementPosition.shapeID = anElem->getshapeId();
4823     const TopoDS_Shape& aSp = mesh->IndexToShape( anElem->getshapeId() );
4824     if ( !aSp.IsNull() ) {
4825       switch ( aSp.ShapeType() ) {
4826       case TopAbs_EDGE:
4827         anElementPosition.shapeType = GEOM::EDGE;
4828         break;
4829       case TopAbs_FACE:
4830         anElementPosition.shapeType = GEOM::FACE;
4831         break;
4832       case TopAbs_VERTEX:
4833         anElementPosition.shapeType = GEOM::VERTEX;
4834         break;
4835       case TopAbs_SOLID:
4836         anElementPosition.shapeType = GEOM::SOLID;
4837         break;
4838       case TopAbs_SHELL:
4839         anElementPosition.shapeType = GEOM::SHELL;
4840         break;
4841       default:;
4842       }
4843     }
4844   }
4845   return anElementPosition;
4846 }
4847
4848 //=============================================================================
4849 /*!
4850  * If given element is node returns IDs of shape from position
4851  * If there is not node for given ID - returns -1
4852  */
4853 //=============================================================================
4854
4855 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
4856 {
4857   if ( _preMeshInfo )
4858     _preMeshInfo->FullLoadFromFile();
4859
4860   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4861   if ( aMeshDS == NULL )
4862     return -1;
4863
4864   // try to find node
4865   const SMDS_MeshNode* aNode = aMeshDS->FindNode(id);
4866   if(aNode) {
4867     return aNode->getshapeId();
4868   }
4869
4870   return -1;
4871 }
4872
4873
4874 //=============================================================================
4875 /*!
4876  * For given element returns ID of result shape after
4877  * ::FindShape() from SMESH_MeshEditor
4878  * If there is not element for given ID - returns -1
4879  */
4880 //=============================================================================
4881
4882 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
4883 {
4884   if ( _preMeshInfo )
4885     _preMeshInfo->FullLoadFromFile();
4886
4887   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4888   if ( aMeshDS == NULL )
4889     return -1;
4890
4891   // try to find element
4892   const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
4893   if(!elem)
4894     return -1;
4895
4896   ::SMESH_MeshEditor aMeshEditor(_impl);
4897   int index = aMeshEditor.FindShape( elem );
4898   if(index>0)
4899     return index;
4900
4901   return -1;
4902 }
4903
4904
4905 //=============================================================================
4906 /*!
4907  * Returns number of nodes for given element
4908  * If there is not element for given ID - returns -1
4909  */
4910 //=============================================================================
4911
4912 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
4913 {
4914   if ( _preMeshInfo )
4915     _preMeshInfo->FullLoadFromFile();
4916
4917   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4918   if ( aMeshDS == NULL ) return -1;
4919   // try to find element
4920   const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
4921   if(!elem) return -1;
4922   return elem->NbNodes();
4923 }
4924
4925
4926 //=============================================================================
4927 /*!
4928  * Returns ID of node by given index for given element
4929  * If there is not element for given ID - returns -1
4930  * If there is not node for given index - returns -2
4931  */
4932 //=============================================================================
4933
4934 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
4935 {
4936   if ( _preMeshInfo )
4937     _preMeshInfo->FullLoadFromFile();
4938
4939   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4940   if ( aMeshDS == NULL ) return -1;
4941   const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
4942   if(!elem) return -1;
4943   if( index>=elem->NbNodes() || index<0 ) return -1;
4944   return elem->GetNode(index)->GetID();
4945 }
4946
4947 //=============================================================================
4948 /*!
4949  * Returns IDs of nodes of given element
4950  */
4951 //=============================================================================
4952
4953 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
4954 {
4955   if ( _preMeshInfo )
4956     _preMeshInfo->FullLoadFromFile();
4957
4958   SMESH::long_array_var aResult = new SMESH::long_array();
4959   if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
4960   {
4961     if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(id) )
4962     {
4963       aResult->length( elem->NbNodes() );
4964       for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
4965         if ( const SMDS_MeshNode* n = elem->GetNode( i ))
4966           aResult[ i ] = n->GetID();
4967     }
4968   }
4969   return aResult._retn();
4970 }
4971
4972 //=============================================================================
4973 /*!
4974  * Returns true if given node is medium node
4975  * in given quadratic element
4976  */
4977 //=============================================================================
4978
4979 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
4980 {
4981   if ( _preMeshInfo )
4982     _preMeshInfo->FullLoadFromFile();
4983
4984   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4985   if ( aMeshDS == NULL ) return false;
4986   // try to find node
4987   const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
4988   if(!aNode) return false;
4989   // try to find element
4990   const SMDS_MeshElement* elem = aMeshDS->FindElement(ide);
4991   if(!elem) return false;
4992
4993   return elem->IsMediumNode(aNode);
4994 }
4995
4996
4997 //=============================================================================
4998 /*!
4999  * Returns true if given node is medium node
5000  * in one of quadratic elements
5001  */
5002 //=============================================================================
5003
5004 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
5005                                                    SMESH::ElementType theElemType)
5006 {
5007   if ( _preMeshInfo )
5008     _preMeshInfo->FullLoadFromFile();
5009
5010   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5011   if ( aMeshDS == NULL ) return false;
5012
5013   // try to find node
5014   const SMDS_MeshNode* aNode = aMeshDS->FindNode(idn);
5015   if(!aNode) return false;
5016
5017   SMESH_MesherHelper aHelper( *(_impl) );
5018
5019   SMDSAbs_ElementType aType;
5020   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
5021   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
5022   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
5023   else aType = SMDSAbs_All;
5024
5025   return aHelper.IsMedium(aNode,aType);
5026 }
5027
5028
5029 //=============================================================================
5030 /*!
5031  * Returns number of edges for given element
5032  */
5033 //=============================================================================
5034
5035 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
5036 {
5037   if ( _preMeshInfo )
5038     _preMeshInfo->FullLoadFromFile();
5039
5040   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5041   if ( aMeshDS == NULL ) return -1;
5042   const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5043   if(!elem) return -1;
5044   return elem->NbEdges();
5045 }
5046
5047
5048 //=============================================================================
5049 /*!
5050  * Returns number of faces for given element
5051  */
5052 //=============================================================================
5053
5054 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
5055 {
5056   if ( _preMeshInfo )
5057     _preMeshInfo->FullLoadFromFile();
5058
5059   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5060   if ( aMeshDS == NULL ) return -1;
5061   const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5062   if(!elem) return -1;
5063   return elem->NbFaces();
5064 }
5065
5066 //=======================================================================
5067 //function : GetElemFaceNodes
5068 //purpose  : Returns nodes of given face (counted from zero) for given element.
5069 //=======================================================================
5070
5071 SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long  elemId,
5072                                                   CORBA::Short faceIndex)
5073 {
5074   if ( _preMeshInfo )
5075     _preMeshInfo->FullLoadFromFile();
5076
5077   SMESH::long_array_var aResult = new SMESH::long_array();
5078   if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() )
5079   {
5080     if ( const SMDS_MeshElement* elem = aMeshDS->FindElement(elemId) )
5081     {
5082       SMDS_VolumeTool vtool( elem, /*skipCentralNodes = */false );
5083       if ( faceIndex < vtool.NbFaces() )
5084       {
5085         aResult->length( vtool.NbFaceNodes( faceIndex ));
5086         const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
5087         for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
5088           aResult[ i ] = nn[ i ]->GetID();
5089       }
5090     }
5091   }
5092   return aResult._retn();
5093 }
5094
5095 //=======================================================================
5096 //function : GetFaceNormal
5097 //purpose  : Returns three components of normal of given mesh face.
5098 //=======================================================================
5099
5100 SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long    elemId,
5101                                                  CORBA::Boolean normalized)
5102 {
5103   if ( _preMeshInfo )
5104     _preMeshInfo->FullLoadFromFile();
5105
5106   SMESH::double_array_var aResult = new SMESH::double_array();
5107
5108   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5109   {
5110     gp_XYZ normal;
5111     if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, normalized ))
5112     {
5113       aResult->length( 3 );
5114       aResult[ 0 ] = normal.X();
5115       aResult[ 1 ] = normal.Y();
5116       aResult[ 2 ] = normal.Z();
5117     }
5118   }
5119   return aResult._retn();
5120 }
5121
5122 //=======================================================================
5123 //function : FindElementByNodes
5124 //purpose  : Returns an element based on all given nodes.
5125 //=======================================================================
5126
5127 CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
5128 {
5129   if ( _preMeshInfo )
5130     _preMeshInfo->FullLoadFromFile();
5131
5132   CORBA::Long elemID(0);
5133   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5134   {
5135     vector< const SMDS_MeshNode * > nn( nodes.length() );
5136     for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5137       if ( !( nn[i] = mesh->FindNode( nodes[i] )))
5138         return elemID;
5139
5140     const SMDS_MeshElement* elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/false );
5141     if ( !elem && ( _impl->NbEdges  ( ORDER_QUADRATIC ) ||
5142                     _impl->NbFaces  ( ORDER_QUADRATIC ) ||
5143                     _impl->NbVolumes( ORDER_QUADRATIC )))
5144       elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
5145
5146     if ( elem ) elemID = CORBA::Long( elem->GetID() );
5147   }
5148   return elemID;
5149 }
5150
5151 //================================================================================
5152 /*!
5153  * \brief Return elements including all given nodes.
5154  */
5155 //================================================================================
5156
5157 SMESH::long_array* SMESH_Mesh_i::GetElementsByNodes(const SMESH::long_array& nodes,
5158                                                     SMESH::ElementType       elemType)
5159 {
5160   if ( _preMeshInfo )
5161     _preMeshInfo->FullLoadFromFile();
5162
5163   SMESH::long_array_var result = new SMESH::long_array();
5164
5165   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
5166   {
5167     vector< const SMDS_MeshNode * > nn( nodes.length() );
5168     for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
5169       nn[i] = mesh->FindNode( nodes[i] );
5170
5171     std::vector<const SMDS_MeshElement *> elems;
5172     mesh->GetElementsByNodes( nn, elems, (SMDSAbs_ElementType) elemType );
5173     result->length( elems.size() );
5174     for ( size_t i = 0; i < elems.size(); ++i )
5175       result[i] = elems[i]->GetID();
5176   }
5177   return result._retn();
5178 }
5179
5180 //=============================================================================
5181 /*!
5182  * Returns true if given element is polygon
5183  */
5184 //=============================================================================
5185
5186 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
5187 {
5188   if ( _preMeshInfo )
5189     _preMeshInfo->FullLoadFromFile();
5190
5191   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5192   if ( aMeshDS == NULL ) return false;
5193   const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5194   if(!elem) return false;
5195   return elem->IsPoly();
5196 }
5197
5198
5199 //=============================================================================
5200 /*!
5201  * Returns true if given element is quadratic
5202  */
5203 //=============================================================================
5204
5205 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
5206 {
5207   if ( _preMeshInfo )
5208     _preMeshInfo->FullLoadFromFile();
5209
5210   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5211   if ( aMeshDS == NULL ) return false;
5212   const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5213   if(!elem) return false;
5214   return elem->IsQuadratic();
5215 }
5216
5217 //=============================================================================
5218 /*!
5219  * Returns diameter of ball discrete element or zero in case of an invalid \a id
5220  */
5221 //=============================================================================
5222
5223 CORBA::Double SMESH_Mesh_i::GetBallDiameter(CORBA::Long id)
5224 {
5225   if ( _preMeshInfo )
5226     _preMeshInfo->FullLoadFromFile();
5227
5228   if ( const SMDS_BallElement* ball =
5229        SMDS_Mesh::DownCast<SMDS_BallElement>( _impl->GetMeshDS()->FindElement( id )))
5230     return ball->GetDiameter();
5231
5232   return 0;
5233 }
5234
5235 //=============================================================================
5236 /*!
5237  * Returns bary center for given element
5238  */
5239 //=============================================================================
5240
5241 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
5242 {
5243   if ( _preMeshInfo )
5244     _preMeshInfo->FullLoadFromFile();
5245
5246   SMESH::double_array_var aResult = new SMESH::double_array();
5247   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5248   if ( aMeshDS == NULL )
5249     return aResult._retn();
5250
5251   const SMDS_MeshElement* elem = aMeshDS->FindElement(id);
5252   if(!elem)
5253     return aResult._retn();
5254
5255   if(elem->GetType()==SMDSAbs_Volume) {
5256     SMDS_VolumeTool aTool;
5257     if(aTool.Set(elem)) {
5258       aResult->length(3);
5259       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
5260         aResult->length(0);
5261     }
5262   }
5263   else {
5264     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
5265     int nbn = 0;
5266     double x=0., y=0., z=0.;
5267     for(; anIt->more(); ) {
5268       nbn++;
5269       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
5270       x += aNode->X();
5271       y += aNode->Y();
5272       z += aNode->Z();
5273     }
5274     if(nbn>0) {
5275       // add coordinates
5276       aResult->length(3);
5277       aResult[0] = x/nbn;
5278       aResult[1] = y/nbn;
5279       aResult[2] = z/nbn;
5280     }
5281   }
5282
5283   return aResult._retn();
5284 }
5285
5286 //================================================================================
5287 /*!
5288  * \brief Create a group of elements preventing computation of a sub-shape
5289  */
5290 //================================================================================
5291
5292 SMESH::ListOfGroups*
5293 SMESH_Mesh_i::MakeGroupsOfBadInputElements( int         theSubShapeID,
5294                                             const char* theGroupName )
5295   throw ( SALOME::SALOME_Exception )
5296 {
5297   Unexpect aCatch(SALOME_SalomeException);
5298
5299   if ( !theGroupName || strlen( theGroupName) == 0 )
5300     THROW_SALOME_CORBA_EXCEPTION( "empty group name",SALOME::BAD_PARAM );
5301
5302   SMESH::ListOfGroups_var groups = new SMESH::ListOfGroups;
5303   ::SMESH_MeshEditor::ElemFeatures elemType;
5304
5305   // submesh by subshape id
5306   if ( !_impl->HasShapeToMesh() ) theSubShapeID = 1;
5307   if ( SMESH_subMesh * sm = _impl->GetSubMeshContaining( theSubShapeID ))
5308   {
5309     // compute error
5310     SMESH_ComputeErrorPtr error = sm->GetComputeError();
5311     if ( error && error->HasBadElems() )
5312     {
5313       // sort bad elements by type
5314       vector< const SMDS_MeshElement* > elemsByType[ SMDSAbs_NbElementTypes ];
5315       const list<const SMDS_MeshElement*>& badElems =
5316         static_cast<SMESH_BadInputElements*>( error.get() )->myBadElements;
5317       list<const SMDS_MeshElement*>::const_iterator elemIt  = badElems.begin();
5318       list<const SMDS_MeshElement*>::const_iterator elemEnd = badElems.end();
5319       for ( ; elemIt != elemEnd; ++elemIt )
5320       {
5321         const SMDS_MeshElement* elem = *elemIt;
5322         if ( !elem ) continue;
5323
5324         if ( elem->GetID() < 1 )
5325         {
5326           // elem is a temporary element, make a real element
5327           vector< const SMDS_MeshNode* > nodes;
5328           SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
5329           while ( nIt->more() && elem )
5330           {
5331             nodes.push_back( nIt->next() );
5332             if ( nodes.back()->GetID() < 1 )
5333               elem = 0;  // a temporary element on temporary nodes
5334           }
5335           if ( elem )
5336           {
5337             ::SMESH_MeshEditor editor( _impl );
5338             elem = editor.AddElement( nodes, elemType.Init( elem ));
5339           }
5340         }
5341         if ( elem )
5342           elemsByType[ elem->GetType() ].push_back( elem );
5343       }
5344
5345       // how many groups to create?
5346       int nbTypes = 0;
5347       for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
5348         nbTypes += int( !elemsByType[ i ].empty() );
5349       groups->length( nbTypes );
5350
5351       // create groups
5352       for ( int i = 0, iG = -1; i < SMDSAbs_NbElementTypes; ++i )
5353       {
5354         vector< const SMDS_MeshElement* >& elems = elemsByType[ i ];
5355         if ( elems.empty() ) continue;
5356
5357         groups[ ++iG ] = createGroup( SMESH::ElementType(i), theGroupName );
5358         if ( _gen_i->CanPublishInStudy( groups[ iG ] ))
5359         {
5360           SMESH::SMESH_Mesh_var mesh = _this();
5361           SALOMEDS::SObject_wrap aSO =
5362             _gen_i->PublishGroup( mesh, groups[ iG ],
5363                                  GEOM::GEOM_Object::_nil(), theGroupName);
5364         }
5365         SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
5366         if ( !grp_i ) continue;
5367
5368         if ( SMESHDS_Group*  grpDS = dynamic_cast< SMESHDS_Group* >( grp_i->GetGroupDS() ))
5369           for ( size_t iE = 0; iE < elems.size(); ++iE )
5370             grpDS->SMDSGroup().Add( elems[ iE ]);
5371       }
5372     }
5373   }
5374
5375   return groups._retn();
5376 }
5377
5378 //=============================================================================
5379 /*!
5380  * Create and publish group servants if any groups were imported or created anyhow
5381  */
5382 //=============================================================================
5383
5384 void SMESH_Mesh_i::CreateGroupServants()
5385 {
5386   SMESH::SMESH_Mesh_var aMesh = _this();
5387
5388   set<int> addedIDs;
5389   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
5390   while ( groupIt->more() )
5391   {
5392     ::SMESH_Group* group = groupIt->next();
5393     int             anId = group->GetID();
5394
5395     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
5396     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5397       continue;
5398     addedIDs.insert( anId );
5399
5400     SMESH_GroupBase_i* aGroupImpl;
5401     TopoDS_Shape       shape;
5402     if ( SMESHDS_GroupOnGeom* groupOnGeom =
5403          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
5404     {
5405       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
5406       shape      = groupOnGeom->GetShape();
5407     }
5408     else {
5409       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
5410     }
5411
5412     SMESH::SMESH_GroupBase_var groupVar = aGroupImpl->_this();
5413     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
5414     aGroupImpl->Register();
5415
5416     // register CORBA object for persistence
5417     int nextId = _gen_i->RegisterObject( groupVar );
5418     if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
5419     else        { nextId = 0; } // avoid "unused variable" warning in release mode
5420
5421     // publishing the groups in the study
5422     GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
5423     _gen_i->PublishGroup( aMesh, groupVar, shapeVar, group->GetName());
5424   }
5425   if ( !addedIDs.empty() )
5426   {
5427     // python dump
5428     set<int>::iterator id = addedIDs.begin();
5429     for ( ; id != addedIDs.end(); ++id )
5430     {
5431       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(*id);
5432       int i = std::distance( _mapGroups.begin(), it );
5433       TPythonDump() << it->second << " = " << aMesh << ".GetGroups()[ "<< i << " ]";
5434     }
5435   }
5436 }
5437
5438 //=============================================================================
5439 /*!
5440  * \brief Return true if all sub-meshes are computed OK - to update an icon
5441  */
5442 //=============================================================================
5443
5444 bool SMESH_Mesh_i::IsComputedOK()
5445 {
5446   return _impl->IsComputedOK();
5447 }
5448
5449 //=============================================================================
5450 /*!
5451  * \brief Return groups cantained in _mapGroups by their IDs
5452  */
5453 //=============================================================================
5454
5455 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
5456 {
5457   int nbGroups = groupIDs.size();
5458   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
5459   aList->length( nbGroups );
5460
5461   list<int>::const_iterator ids = groupIDs.begin();
5462   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
5463   {
5464     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
5465     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
5466       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
5467   }
5468   aList->length( nbGroups );
5469   return aList._retn();
5470 }
5471
5472 //=============================================================================
5473 /*!
5474  * \brief Return information about imported file
5475  */
5476 //=============================================================================
5477
5478 SMESH::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
5479 {
5480   SMESH::MedFileInfo_var res( _medFileInfo );
5481   if ( !res.operator->() ) {
5482     res = new SMESH::MedFileInfo;
5483     res->fileName = "";
5484     res->fileSize = res->major = res->minor = res->release = -1;
5485   }
5486   return res._retn();
5487 }
5488
5489 //=======================================================================
5490 //function : FileInfoToString
5491 //purpose  : Persistence of file info
5492 //=======================================================================
5493
5494 std::string SMESH_Mesh_i::FileInfoToString()
5495 {
5496   std::string s;
5497   if ( &_medFileInfo.in() && _medFileInfo->fileName[0] )
5498   {
5499     s = SMESH_Comment( _medFileInfo->fileSize )
5500       << " " << _medFileInfo->major
5501       << " " << _medFileInfo->minor
5502       << " " << _medFileInfo->release
5503       << " " << _medFileInfo->fileName;
5504   }
5505   return s;
5506 }
5507
5508 //=======================================================================
5509 //function : FileInfoFromString
5510 //purpose  : Persistence of file info
5511 //=======================================================================
5512
5513 void SMESH_Mesh_i::FileInfoFromString(const std::string& info)
5514 {
5515   std::string size, major, minor, release, fileName;
5516   std::istringstream is(info);
5517   is >> size >> major >> minor >> release;
5518   fileName = info.data() + ( size.size()   + 1 +
5519                              major.size()  + 1 +
5520                              minor.size()  + 1 +
5521                              release.size()+ 1 );
5522
5523   _medFileInfo           = new SMESH::MedFileInfo();
5524   _medFileInfo->fileName = fileName.c_str();
5525   _medFileInfo->fileSize = atoi( size.c_str() );
5526   _medFileInfo->major    = atoi( major.c_str() );
5527   _medFileInfo->minor    = atoi( minor.c_str() );
5528   _medFileInfo->release  = atoi( release.c_str() );
5529 }
5530
5531 //=============================================================================
5532 /*!
5533  * \brief Pass names of mesh groups from study to mesh DS
5534  */
5535 //=============================================================================
5536
5537 void SMESH_Mesh_i::checkGroupNames()
5538 {
5539   int nbGrp = NbGroups();
5540   if ( !nbGrp )
5541     return;
5542
5543   SMESH::ListOfGroups* grpList = 0;
5544   // avoid dump of "GetGroups"
5545   {
5546     // store python dump into a local variable inside local scope
5547     SMESH::TPythonDump pDump; // do not delete this line of code
5548     grpList = GetGroups();
5549   }
5550
5551   for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
5552     SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
5553     if ( !aGrp )
5554       continue;
5555     SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aGrp );
5556     if ( aGrpSO->_is_nil() )
5557       continue;
5558     // correct name of the mesh group if necessary
5559     const char* guiName = aGrpSO->GetName();
5560     if ( strcmp(guiName, aGrp->GetName()) )
5561       aGrp->SetName( guiName );
5562   }
5563 }
5564
5565 //=============================================================================
5566 /*!
5567  * \brief Sets list of notebook variables used for Mesh operations separated by ":" symbol
5568  */
5569 //=============================================================================
5570 void SMESH_Mesh_i::SetParameters(const char* theParameters)
5571 {
5572   SMESH_Gen_i::GetSMESHGen()->UpdateParameters( CORBA::Object_var( _this() ).in(),
5573                                                 theParameters );
5574 }
5575
5576 //=============================================================================
5577 /*!
5578  * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
5579  */
5580 //=============================================================================
5581
5582 char* SMESH_Mesh_i::GetParameters()
5583 {
5584   return SMESH_Gen_i::GetSMESHGen()->GetParameters( SMESH::SMESH_Mesh_var( _this()) );
5585 }
5586
5587 //=============================================================================
5588 /*!
5589  * \brief Returns list of notebook variables used for last Mesh operation
5590  */
5591 //=============================================================================
5592 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
5593 {
5594   SMESH::string_array_var aResult = new SMESH::string_array();
5595   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
5596   if(gen) {
5597     CORBA::String_var aParameters = GetParameters();
5598     SALOMEDS::ListOfListOfStrings_var aSections = SMESH_Gen_i::getStudyServant()->ParseVariables(aParameters);
5599     if ( aSections->length() > 0 ) {
5600       SALOMEDS::ListOfStrings aVars = aSections[ aSections->length() - 1 ];
5601       aResult->length( aVars.length() );
5602       for ( CORBA::ULong i = 0;i < aVars.length(); i++ )
5603         aResult[i] = CORBA::string_dup( aVars[i] );
5604     }
5605   }
5606   return aResult._retn();
5607 }
5608
5609 //=======================================================================
5610 //function : GetTypes
5611 //purpose  : Returns types of elements it contains
5612 //=======================================================================
5613
5614 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
5615 {
5616   if ( _preMeshInfo )
5617     return _preMeshInfo->GetTypes();
5618
5619   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
5620
5621   types->length( 5 );
5622   int nbTypes = 0;
5623   if (_impl->NbEdges())      types[nbTypes++] = SMESH::EDGE;
5624   if (_impl->NbFaces())      types[nbTypes++] = SMESH::FACE;
5625   if (_impl->NbVolumes())    types[nbTypes++] = SMESH::VOLUME;
5626   if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
5627   if (_impl->NbBalls())      types[nbTypes++] = SMESH::BALL;
5628   if (_impl->NbNodes() &&
5629       nbTypes == 0 )         types[nbTypes++] = SMESH::NODE;
5630   types->length( nbTypes );
5631
5632   return types._retn();
5633 }
5634
5635 //=======================================================================
5636 //function : GetMesh
5637 //purpose  : Returns self
5638 //=======================================================================
5639
5640 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
5641 {
5642   return SMESH::SMESH_Mesh::_duplicate( _this() );
5643 }
5644
5645 //=======================================================================
5646 //function : IsMeshInfoCorrect
5647 //purpose  : * Returns false if GetMeshInfo() returns incorrect information that may
5648 //           * happen if mesh data is not yet fully loaded from the file of study.
5649 //=======================================================================
5650
5651 bool SMESH_Mesh_i::IsMeshInfoCorrect()
5652 {
5653   return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
5654 }
5655
5656 //=============================================================================
5657 /*!
5658  * \brief Returns number of mesh elements per each \a EntityType
5659  */
5660 //=============================================================================
5661
5662 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
5663 {
5664   if ( _preMeshInfo )
5665     return _preMeshInfo->GetMeshInfo();
5666
5667   SMESH::long_array_var aRes = new SMESH::long_array();
5668   aRes->length(SMESH::Entity_Last);
5669   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
5670     aRes[i] = 0;
5671   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
5672   if (!aMeshDS)
5673     return aRes._retn();
5674   const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
5675   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
5676     aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
5677   return aRes._retn();
5678 }
5679
5680 //=============================================================================
5681 /*!
5682  * \brief Returns number of mesh elements per each \a ElementType
5683  */
5684 //=============================================================================
5685
5686 SMESH::long_array* SMESH_Mesh_i::GetNbElementsByType()
5687 {
5688   SMESH::long_array_var aRes = new SMESH::long_array();
5689   aRes->length(SMESH::NB_ELEMENT_TYPES);
5690   for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
5691     aRes[ i ] = 0;
5692
5693   const SMDS_MeshInfo* meshInfo = 0;
5694   if ( _preMeshInfo )
5695     meshInfo = _preMeshInfo;
5696   else if ( SMESHDS_Mesh* meshDS = _impl->GetMeshDS() )
5697     meshInfo = & meshDS->GetMeshInfo();
5698
5699   if (meshInfo)
5700     for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
5701       aRes[i] = meshInfo->NbElements((SMDSAbs_ElementType)i);
5702
5703   return aRes._retn();
5704 }
5705
5706 //=============================================================================
5707 /*
5708  * Collect statistic of mesh elements given by iterator
5709  */
5710 //=============================================================================
5711
5712 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
5713                                    SMESH::long_array&         theInfo)
5714 {
5715   if (!theItr) return;
5716   while (theItr->more())
5717     theInfo[ theItr->next()->GetEntityType() ]++;
5718 }
5719 //=============================================================================
5720 /*
5721  * Returns mesh unstructed grid information.
5722  */
5723 //=============================================================================
5724
5725 SALOMEDS::TMPFile* SMESH_Mesh_i::GetVtkUgStream()
5726 {
5727   SALOMEDS::TMPFile_var SeqFile;
5728   if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() ) {
5729     SMDS_UnstructuredGrid* aGrid = aMeshDS->GetGrid();
5730     if(aGrid) {
5731       vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
5732       aWriter->WriteToOutputStringOn();
5733       aWriter->SetInputData(aGrid);
5734       aWriter->SetFileTypeToBinary();
5735       aWriter->Write();
5736       char* str = aWriter->GetOutputString();
5737       int size = aWriter->GetOutputStringLength();
5738
5739       //Allocate octet buffer of required size
5740       CORBA::Octet* OctetBuf = SALOMEDS::TMPFile::allocbuf(size);
5741       //Copy ostrstream content to the octet buffer
5742       memcpy(OctetBuf, str, size);
5743       //Create and return TMPFile
5744       SeqFile = new SALOMEDS::TMPFile(size, size, OctetBuf, 1);
5745       aWriter->Delete();
5746     }
5747   }
5748   return SeqFile._retn();
5749 }
5750
5751 //=============================================================================
5752 namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
5753            *                                             SMESH::ElementType        type) */
5754 {
5755   using namespace SMESH::Controls;
5756   //-----------------------------------------------------------------------------
5757   struct PredicateIterator : public SMDS_ElemIterator
5758   {
5759     SMDS_ElemIteratorPtr    _elemIter;
5760     PredicatePtr            _predicate;
5761     const SMDS_MeshElement* _elem;
5762     SMDSAbs_ElementType     _type;
5763
5764     PredicateIterator( SMDS_ElemIteratorPtr iterator,
5765                        PredicatePtr         predicate,
5766                        SMDSAbs_ElementType  type):
5767       _elemIter(iterator), _predicate(predicate), _type(type)
5768     {
5769       next();
5770     }
5771     virtual bool more()
5772     {
5773       return _elem;
5774     }
5775     virtual const SMDS_MeshElement* next()
5776     {
5777       const SMDS_MeshElement* res = _elem;
5778       _elem = 0;
5779       while ( _elemIter->more() && !_elem )
5780       {
5781         if ((_elem = _elemIter->next()) &&
5782             (( _type != SMDSAbs_All && _type != _elem->GetType() ) ||
5783              ( !_predicate->IsSatisfy( _elem->GetID() ))))
5784           _elem = 0;
5785       }
5786       return res;
5787     }
5788   };
5789
5790   //-----------------------------------------------------------------------------
5791   struct IDSourceIterator : public SMDS_ElemIterator
5792   {
5793     const CORBA::Long*        _idPtr;
5794     const CORBA::Long*        _idEndPtr;
5795     SMESH::long_array_var     _idArray;
5796     const SMDS_Mesh*          _mesh;
5797     const SMDSAbs_ElementType _type;
5798     const SMDS_MeshElement*   _elem;
5799
5800     IDSourceIterator( const SMDS_Mesh*    mesh,
5801                       const CORBA::Long*  ids,
5802                       const int           nbIds,
5803                       SMDSAbs_ElementType type):
5804       _idPtr( ids ), _idEndPtr( ids + nbIds ), _mesh( mesh ), _type( type ), _elem( 0 )
5805     {
5806       if ( _idPtr && nbIds && _mesh )
5807         next();
5808     }
5809     IDSourceIterator( const SMDS_Mesh*    mesh,
5810                       SMESH::long_array*  idArray,
5811                       SMDSAbs_ElementType type):
5812       _idPtr( 0 ), _idEndPtr( 0 ), _idArray( idArray), _mesh( mesh ), _type( type ), _elem( 0 )
5813     {
5814       if ( idArray && _mesh )
5815       {
5816         _idPtr    = &_idArray[0];
5817         _idEndPtr = _idPtr + _idArray->length();
5818         next();
5819       }
5820     }
5821     virtual bool more()
5822     {
5823       return _elem;
5824     }
5825     virtual const SMDS_MeshElement* next()
5826     {
5827       const SMDS_MeshElement* res = _elem;
5828       _elem = 0;
5829       while ( _idPtr < _idEndPtr && !_elem )
5830       {
5831         if ( _type == SMDSAbs_Node )
5832         {
5833           _elem = _mesh->FindNode( *_idPtr++ );
5834         }
5835         else if ((_elem = _mesh->FindElement( *_idPtr++ )) &&
5836                  (_elem->GetType() != _type && _type != SMDSAbs_All ))
5837         {
5838           _elem = 0;
5839         }
5840       }
5841       return res;
5842     }
5843   };
5844   //-----------------------------------------------------------------------------
5845
5846   struct NodeOfElemIterator : public SMDS_ElemIterator
5847   {
5848     TColStd_MapOfInteger    _checkedNodeIDs;
5849     SMDS_ElemIteratorPtr    _elemIter;
5850     SMDS_ElemIteratorPtr    _nodeIter;
5851     const SMDS_MeshElement* _node;
5852
5853     NodeOfElemIterator( SMDS_ElemIteratorPtr iter ): _elemIter( iter ), _node( 0 )
5854     {
5855       if ( _elemIter && _elemIter->more() )
5856       {
5857         _nodeIter = _elemIter->next()->nodesIterator();
5858         next();
5859       }
5860     }
5861     virtual bool more()
5862     {
5863       return _node;
5864     }
5865     virtual const SMDS_MeshElement* next()
5866     {
5867       const SMDS_MeshElement* res = _node;
5868       _node = 0;
5869       while ( !_node && ( _elemIter->more() || _nodeIter->more() ))
5870       {
5871         if ( _nodeIter->more() )
5872         {
5873           _node = _nodeIter->next();
5874           if ( !_checkedNodeIDs.Add( _node->GetID() ))
5875             _node = 0;
5876         }
5877         else
5878         {
5879           _nodeIter = _elemIter->next()->nodesIterator();
5880         }
5881       }
5882       return res;
5883     }
5884   };
5885 }
5886
5887 //=============================================================================
5888 /*
5889  * Return iterator on elements of given type in given object
5890  */
5891 //=============================================================================
5892
5893 SMDS_ElemIteratorPtr SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_ptr theObject,
5894                                                SMESH::ElementType        theType)
5895 {
5896   SMDS_ElemIteratorPtr  elemIt;
5897   bool                  typeOK = ( theType == SMESH::ALL );
5898   SMDSAbs_ElementType elemType = SMDSAbs_ElementType( theType );
5899
5900   SMESH::SMESH_Mesh_var meshVar = theObject->GetMesh();
5901   SMESH_Mesh_i*          mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( meshVar );
5902   if ( !mesh_i ) return elemIt;
5903   SMESHDS_Mesh*          meshDS = mesh_i->GetImpl().GetMeshDS();
5904
5905   if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
5906   {
5907     elemIt = meshDS->elementsIterator( elemType );
5908     typeOK = true;
5909   }
5910   else if ( SMESH_subMesh_i* submesh_i = SMESH::DownCast<SMESH_subMesh_i*>( theObject ))
5911   {
5912     SMESHDS_SubMesh* sm = ((SMESHDS_Mesh*) meshDS)->MeshElements( submesh_i->GetId() );
5913     if ( sm )
5914     {
5915       elemIt = sm->GetElements();
5916       if ( elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
5917       {
5918         typeOK = ( elemIt && elemIt->more() && elemIt->next()->GetType() == elemType );
5919         elemIt = typeOK ? sm->GetElements() : SMDS_ElemIteratorPtr();
5920       }
5921     }
5922   }
5923   else if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( theObject ))
5924   {
5925     SMESHDS_GroupBase* groupDS = group_i->GetGroupDS();
5926     if ( groupDS && ( elemType == groupDS->GetType()  ||
5927                       elemType == SMDSAbs_Node ||
5928                       elemType == SMDSAbs_All ))
5929     {
5930       elemIt = groupDS->GetElements();
5931       typeOK = ( groupDS->GetType() == elemType || elemType == SMDSAbs_All );
5932     }
5933   }
5934   else if ( SMESH::Filter_i* filter_i = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
5935   {
5936     if ( filter_i->GetElementType() == theType ||
5937          filter_i->GetElementType() == SMESH::ALL ||
5938          elemType == SMDSAbs_Node ||
5939          elemType == SMDSAbs_All)
5940     {
5941       SMESH::Predicate_i* pred_i = filter_i->GetPredicate_i();
5942       if ( pred_i && pred_i->GetPredicate() )
5943       {
5944         SMDSAbs_ElementType filterType = SMDSAbs_ElementType( filter_i->GetElementType() );
5945         SMDS_ElemIteratorPtr allElemIt = meshDS->elementsIterator( filterType );
5946         SMDSAbs_ElementType   iterType = elemType == SMDSAbs_Node ? filterType : elemType;
5947         elemIt = SMDS_ElemIteratorPtr
5948           ( new PredicateIterator( allElemIt, pred_i->GetPredicate(), iterType ));
5949         typeOK = ( elemType == SMDSAbs_Node ? filterType == SMDSAbs_Node : elemIt->more() );
5950       }
5951     }
5952   }
5953   else
5954   {
5955     SMESH::array_of_ElementType_var types = theObject->GetTypes();
5956     const bool                    isNodes = ( types->length() == 1 && types[0] == SMESH::NODE );
5957     if ( isNodes && elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
5958       return elemIt;
5959     SMDSAbs_ElementType iterType = isNodes ? SMDSAbs_Node : elemType;
5960     if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theObject ))
5961     {
5962       int nbIds;
5963       if ( CORBA::Long* ids = SMESH_MeshEditor_i::GetTemporaryIDs( theObject, nbIds ))
5964         elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids, nbIds, iterType ));
5965     }
5966     else
5967     {
5968       SMESH::long_array_var ids = theObject->GetIDs();
5969       elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids._retn(), iterType ));
5970     }
5971     typeOK = ( isNodes == ( elemType == SMDSAbs_Node )) || ( elemType == SMDSAbs_All );
5972   }
5973
5974   if ( elemIt && elemIt->more() && !typeOK )
5975   {
5976     if ( elemType == SMDSAbs_Node )
5977     {
5978       elemIt = SMDS_ElemIteratorPtr( new NodeOfElemIterator( elemIt ));
5979     }
5980     else
5981     {
5982       elemIt = SMDS_ElemIteratorPtr();
5983     }
5984   }
5985   return elemIt;
5986 }
5987
5988 //=============================================================================
5989 namespace // Finding concurrent hypotheses
5990 //=============================================================================
5991 {
5992
5993 /*!
5994  * \brief mapping of mesh dimension into shape type
5995  */
5996 TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
5997 {
5998   TopAbs_ShapeEnum aType = TopAbs_SOLID;
5999   switch ( theDim ) {
6000   case 0: aType = TopAbs_VERTEX; break;
6001   case 1: aType = TopAbs_EDGE; break;
6002   case 2: aType = TopAbs_FACE; break;
6003   case 3:
6004   default:aType = TopAbs_SOLID; break;
6005   }
6006   return aType;
6007 }
6008
6009 //-----------------------------------------------------------------------------
6010 /*!
6011  * \brief Internal structure used to find concurrent submeshes
6012  *
6013  * It represents a pair < submesh, concurrent dimension >, where
6014  * 'concurrent dimension' is dimension of shape where the submesh can concurrent
6015  *  with another submesh. In other words, it is dimension of a hypothesis assigned
6016  *  to submesh.
6017  */
6018 class SMESH_DimHyp
6019 {
6020  public:
6021   //! fields
6022   int _dim;    //!< a dimension the algo can build (concurrent dimension)
6023   int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
6024   TopTools_MapOfShape _shapeMap;
6025   SMESH_subMesh*      _subMesh;
6026   list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
6027
6028   //-----------------------------------------------------------------------------
6029   // Return the algorithm
6030   const SMESH_Algo* GetAlgo() const
6031   { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
6032
6033   //-----------------------------------------------------------------------------
6034   //! Constructors
6035   SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
6036                const int            theDim,
6037                const TopoDS_Shape&  theShape)
6038   {
6039     _subMesh = (SMESH_subMesh*)theSubMesh;
6040     SetShape( theDim, theShape );
6041   }
6042
6043   //-----------------------------------------------------------------------------
6044   //! set shape
6045   void SetShape(const int           theDim,
6046                 const TopoDS_Shape& theShape)
6047   {
6048     _dim = theDim;
6049     _ownDim = SMESH_Gen::GetShapeDim(theShape);
6050     if (_dim >= _ownDim)
6051       _shapeMap.Add( theShape );
6052     else {
6053       TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
6054       for( ; anExp.More(); anExp.Next() )
6055         _shapeMap.Add( anExp.Current() );
6056     }
6057   }
6058
6059   //-----------------------------------------------------------------------------
6060   //! Check sharing of sub-shapes
6061   static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
6062                                const TopTools_MapOfShape& theToFind,
6063                                const TopAbs_ShapeEnum     theType)
6064   {
6065     bool isShared = false;
6066     TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
6067     for (; !isShared && anItr.More(); anItr.Next() )
6068     {
6069       const TopoDS_Shape aSubSh = anItr.Key();
6070       // check for case when concurrent dimensions are same
6071       isShared = theToFind.Contains( aSubSh );
6072       // check for sub-shape with concurrent dimension
6073       TopExp_Explorer anExp( aSubSh, theType );
6074       for ( ; !isShared && anExp.More(); anExp.Next() )
6075         isShared = theToFind.Contains( anExp.Current() );
6076     }
6077     return isShared;
6078   }
6079
6080   //-----------------------------------------------------------------------------
6081   //! check algorithms
6082   static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
6083                         const SMESHDS_Hypothesis* theA2)
6084   {
6085     if ( !theA1 || !theA2 ||
6086          theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
6087          theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
6088       return false; // one of the hypothesis is not algorithm
6089     // check algorithm names (should be equal)
6090     return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
6091   }
6092
6093
6094   //-----------------------------------------------------------------------------
6095   //! Check if sub-shape hypotheses are concurrent
6096   bool IsConcurrent(const SMESH_DimHyp* theOther) const
6097   {
6098     if ( _subMesh == theOther->_subMesh )
6099       return false; // same sub-shape - should not be
6100
6101     // if ( <own dim of either of submeshes> == <concurrent dim> &&
6102     //      any of the two submeshes is not on COMPOUND shape )
6103     //  -> no concurrency
6104     bool meIsCompound    = (_subMesh->GetSubMeshDS() &&
6105                             _subMesh->GetSubMeshDS()->IsComplexSubmesh());
6106     bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
6107                             theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
6108     if ( (_ownDim == _dim  || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
6109       return false;
6110
6111     bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
6112     if ( !checkSubShape )
6113       return false;
6114
6115     // check algorithms to be same
6116     const SMESH_Algo* a1 = this->GetAlgo();
6117     const SMESH_Algo* a2 = theOther->GetAlgo();
6118     bool isSame = checkAlgo( a1, a2 );
6119     if ( !isSame )
6120     {
6121       if ( !a1 || !a2 )
6122         return false; // pb?
6123       return a1->GetDim() == a2->GetDim(); // different algorithms of same dim -> concurrency !
6124     }
6125
6126     // check hypothesises for concurrence (skip first as algorithm)
6127     size_t nbSame = 0;
6128     // pointers should be same, because it is referened from mesh hypothesis partition
6129     list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
6130     list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
6131     for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
6132       if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
6133         nbSame++;
6134     // the submeshes are concurrent if their algorithms has different parameters
6135     return nbSame != theOther->_hypotheses.size() - 1;
6136   }
6137
6138   // Return true if algorithm of this SMESH_DimHyp is used if no
6139   // sub-mesh order is imposed by the user
6140   bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
6141   {
6142     // NeedDiscreteBoundary() algo has a higher priority
6143     if ( this    ->GetAlgo()->NeedDiscreteBoundary() !=
6144          theOther->GetAlgo()->NeedDiscreteBoundary() )
6145       return !this->GetAlgo()->NeedDiscreteBoundary();
6146
6147     return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
6148   }
6149
6150 }; // end of SMESH_DimHyp
6151 //-----------------------------------------------------------------------------
6152
6153 typedef list<const SMESH_DimHyp*> TDimHypList;
6154
6155 //-----------------------------------------------------------------------------
6156
6157 void addDimHypInstance(const int                               theDim,
6158                        const TopoDS_Shape&                     theShape,
6159                        const SMESH_Algo*                       theAlgo,
6160                        const SMESH_subMesh*                    theSubMesh,
6161                        const list <const SMESHDS_Hypothesis*>& theHypList,
6162                        TDimHypList*                            theDimHypListArr )
6163 {
6164   TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
6165   if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) {
6166     SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
6167     dimHyp->_hypotheses.push_front(theAlgo);
6168     listOfdimHyp.push_back( dimHyp );
6169   }
6170
6171   SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
6172   dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
6173                               theHypList.begin(), theHypList.end() );
6174 }
6175
6176 //-----------------------------------------------------------------------------
6177 void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
6178                            TDimHypList&        theListOfConcurr)
6179 {
6180   if ( theListOfConcurr.empty() )
6181   {
6182     theListOfConcurr.push_back( theDimHyp );
6183   }
6184   else
6185   {
6186     TDimHypList::iterator hypIt = theListOfConcurr.begin();
6187     while ( hypIt != theListOfConcurr.end() &&
6188             !theDimHyp->IsHigherPriorityThan( *hypIt ))
6189       ++hypIt;
6190     theListOfConcurr.insert( hypIt, theDimHyp );
6191   }
6192 }
6193
6194 //-----------------------------------------------------------------------------
6195 void findConcurrents(const SMESH_DimHyp* theDimHyp,
6196                      const TDimHypList&  theListOfDimHyp,
6197                      TDimHypList&        theListOfConcurrHyp,
6198                      set<int>&           theSetOfConcurrId )
6199 {
6200   TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
6201   for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
6202   {
6203     const SMESH_DimHyp* curDimHyp = *rIt;
6204     if ( curDimHyp == theDimHyp )
6205       break; // meet own dimHyp pointer in same dimension
6206
6207     if ( theDimHyp->IsConcurrent( curDimHyp ) &&
6208          theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
6209     {
6210       addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
6211     }
6212   }
6213 }
6214
6215 //-----------------------------------------------------------------------------
6216 void unionLists(TListOfInt&       theListOfId,
6217                 TListOfListOfInt& theListOfListOfId,
6218                 const int         theIndx )
6219 {
6220   TListOfListOfInt::iterator it = theListOfListOfId.begin();
6221   for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) {
6222     if ( i < theIndx )
6223       continue; //skip already treated lists
6224     // check if other list has any same submesh object
6225     TListOfInt& otherListOfId = *it;
6226     if ( find_first_of( theListOfId.begin(), theListOfId.end(),
6227                         otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
6228       continue;
6229
6230     // union two lists (from source into target)
6231     TListOfInt::iterator it2 = otherListOfId.begin();
6232     for ( ; it2 != otherListOfId.end(); it2++ ) {
6233       if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
6234         theListOfId.push_back(*it2);
6235     }
6236     // clear source list
6237     otherListOfId.clear();
6238   }
6239 }
6240 //-----------------------------------------------------------------------------
6241
6242 //! free memory allocated for dimension-hypothesis objects
6243 void removeDimHyps( TDimHypList* theArrOfList )
6244 {
6245   for (int i = 0; i < 4; i++ ) {
6246     TDimHypList& listOfdimHyp = theArrOfList[i];
6247     TDimHypList::const_iterator it = listOfdimHyp.begin();
6248     for ( ; it != listOfdimHyp.end(); it++ )
6249       delete (*it);
6250   }
6251 }
6252
6253 //-----------------------------------------------------------------------------
6254 /*!
6255  * \brief find common submeshes with given submesh
6256  * \param theSubMeshList list of already collected submesh to check
6257  * \param theSubMesh given submesh to intersect with other
6258  * \param theCommonSubMeshes collected common submeshes
6259  */
6260 void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
6261                         const SMESH_subMesh*        theSubMesh,
6262                         set<const SMESH_subMesh*>&  theCommon )
6263 {
6264   if ( !theSubMesh )
6265     return;
6266   list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
6267   for ( ; it != theSubMeshList.end(); it++ )
6268     theSubMesh->FindIntersection( *it, theCommon );
6269   theSubMeshList.push_back( theSubMesh );
6270   //theCommon.insert( theSubMesh );
6271 }
6272
6273 //-----------------------------------------------------------------------------
6274 bool isSubMeshInList ( int smID, const TListOfListOfInt& smLists )
6275 {
6276   TListOfListOfInt::const_iterator listsIt = smLists.begin();
6277   for ( ; listsIt != smLists.end(); ++listsIt )
6278   {
6279     const TListOfInt& smIDs = *listsIt;
6280     if ( std::find( smIDs.begin(), smIDs.end(), smID ) != smIDs.end() )
6281       return true;
6282   }
6283   return false;
6284 }
6285
6286 } // namespace
6287
6288 //=============================================================================
6289 /*!
6290  * \brief Return \c true if a meshing order not yet set for a concurrent sub-mesh
6291  */
6292 //=============================================================================
6293
6294 CORBA::Boolean SMESH_Mesh_i::IsUnorderedSubMesh(CORBA::Long submeshID)
6295 {
6296   TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
6297   if ( isSubMeshInList( submeshID, anOrder ))
6298     return false;
6299
6300   TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6301   return isSubMeshInList( submeshID, allConurrent );
6302 }
6303
6304 //=============================================================================
6305 /*!
6306  * \brief Return submesh objects list in meshing order
6307  */
6308 //=============================================================================
6309
6310 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
6311 {
6312   SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
6313
6314   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
6315   if ( !aMeshDS )
6316     return aResult._retn();
6317
6318   TListOfListOfInt      anOrder = GetImpl().GetMeshOrder(); // already defined order
6319   TListOfListOfInt allConurrent = findConcurrentSubMeshes();
6320   anOrder.splice( anOrder.end(), allConurrent );
6321
6322   int listIndx = 0;
6323   TListOfListOfInt::iterator listIt = anOrder.begin();
6324   for(; listIt != anOrder.end(); listIt++, listIndx++ )
6325     unionLists( *listIt,  anOrder, listIndx + 1 );
6326
6327   // convert submesh ids into interface instances
6328   //  and dump command into python
6329   convertMeshOrder( anOrder, aResult, false );
6330
6331   return aResult._retn();
6332 }
6333
6334 //=============================================================================
6335 /*!
6336  * \brief Finds concurrent sub-meshes
6337  */
6338 //=============================================================================
6339
6340 TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes()
6341 {
6342   TListOfListOfInt anOrder;
6343   ::SMESH_Mesh& mesh = GetImpl();
6344   {
6345     // collect submeshes and detect concurrent algorithms and hypothesises
6346     TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
6347
6348     map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
6349     for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) {
6350       ::SMESH_subMesh* sm = (*i_sm).second;
6351       // shape of submesh
6352       const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
6353
6354       // list of assigned hypothesises
6355       const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
6356       // Find out dimensions where the submesh can be concurrent.
6357       // We define the dimensions by algo of each of hypotheses in hypList
6358       list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
6359       for( ; hypIt != hypList.end(); hypIt++ ) {
6360         SMESH_Algo* anAlgo = 0;
6361         const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
6362         if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
6363           // hyp it-self is algo
6364           anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
6365         else {
6366           // try to find algorithm with help of sub-shapes
6367           TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
6368           for ( ; !anAlgo && anExp.More(); anExp.Next() )
6369             anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
6370         }
6371         if (!anAlgo)
6372           continue; // no algorithm assigned to a current submesh
6373
6374         int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
6375         // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary())
6376
6377         // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
6378         for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
6379           addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
6380       }
6381     } // end iterations on submesh
6382
6383     // iterate on created dimension-hypotheses and check for concurrents
6384     for ( int i = 0; i < 4; i++ ) {
6385       const TDimHypList& listOfDimHyp = dimHypListArr[i];
6386       // check for concurrents in own and other dimensions (step-by-step)
6387       TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
6388       for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) {
6389         const SMESH_DimHyp* dimHyp = *dhIt;
6390         TDimHypList listOfConcurr;
6391         set<int>    setOfConcurrIds;
6392         // looking for concurrents and collect into own list
6393         for ( int j = i; j < 4; j++ )
6394           findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
6395         // check if any concurrents found
6396         if ( listOfConcurr.size() > 0 ) {
6397           // add own submesh to list of concurrent
6398           addInOrderOfPriority( dimHyp, listOfConcurr );
6399           list<int> listOfConcurrIds;
6400           TDimHypList::iterator hypIt = listOfConcurr.begin();
6401           for ( ; hypIt != listOfConcurr.end(); ++hypIt )
6402             listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
6403           anOrder.push_back( listOfConcurrIds );
6404         }
6405       }
6406     }
6407
6408     removeDimHyps(dimHypListArr);
6409
6410     // now, minimize the number of concurrent groups
6411     // Here we assume that lists of submeshes can have same submesh
6412     // in case of multi-dimension algorithms, as result
6413     //  list with common submesh has to be united into one list
6414     int listIndx = 0;
6415     TListOfListOfInt::iterator listIt = anOrder.begin();
6416     for(; listIt != anOrder.end(); listIt++, listIndx++ )
6417       unionLists( *listIt,  anOrder, listIndx + 1 );
6418   }
6419
6420   return anOrder;
6421 }
6422
6423 //=============================================================================
6424 /*!
6425  * \brief Set submesh object order
6426  * \param theSubMeshArray submesh array order
6427  */
6428 //=============================================================================
6429
6430 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
6431 {
6432   if ( _preMeshInfo )
6433     _preMeshInfo->ForgetOrLoad();
6434
6435   bool res = false;
6436   ::SMESH_Mesh& mesh = GetImpl();
6437
6438   TPythonDump aPythonDump; // prevent dump of called methods
6439   aPythonDump << "isDone = " << SMESH::SMESH_Mesh_var(_this()) << ".SetMeshOrder( [ ";
6440
6441   TListOfListOfInt subMeshOrder;
6442   for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
6443   {
6444     const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
6445     TListOfInt subMeshIds;
6446     if ( i > 0 )
6447       aPythonDump << ", ";
6448     aPythonDump << "[ ";
6449     // Collect subMeshes which should be clear
6450     //  do it list-by-list, because modification of submesh order
6451     //  take effect between concurrent submeshes only
6452     set<const SMESH_subMesh*> subMeshToClear;
6453     list<const SMESH_subMesh*> subMeshList;
6454     for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
6455     {
6456       const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
6457       if ( j > 0 )
6458         aPythonDump << ", ";
6459       aPythonDump << subMesh;
6460       subMeshIds.push_back( subMesh->GetId() );
6461       // detect common parts of submeshes
6462       if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
6463         findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
6464     }
6465     aPythonDump << " ]";
6466     subMeshOrder.push_back( subMeshIds );
6467
6468     // clear collected sub-meshes
6469     set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
6470     for ( ; clrIt != subMeshToClear.end(); clrIt++ )
6471       if ( SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt )
6472       {
6473         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
6474         if ( SMESH_Algo* algo = sm->GetAlgo() ) // #16748
6475           sm->AlgoStateEngine( SMESH_subMesh::MODIF_HYP, algo ); // to clear a cached algo
6476       }
6477   }
6478   aPythonDump << " ])";
6479
6480   mesh.SetMeshOrder( subMeshOrder );
6481   res = true;
6482
6483   SMESH::SMESH_Mesh_var me = _this();
6484   _gen_i->UpdateIcons( me );
6485
6486   return res;
6487 }
6488
6489 //=============================================================================
6490 /*!
6491  * \brief Convert submesh ids into submesh interfaces
6492  */
6493 //=============================================================================
6494
6495 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt&     theIdsOrder,
6496                                      SMESH::submesh_array_array& theResOrder,
6497                                      const bool                  theIsDump)
6498 {
6499   int nbSet = theIdsOrder.size();
6500   TPythonDump aPythonDump; // prevent dump of called methods
6501   if ( theIsDump )
6502     aPythonDump << "[ ";
6503   theResOrder.length(nbSet);
6504   TListOfListOfInt::const_iterator it = theIdsOrder.begin();
6505   int listIndx = 0;
6506   for( ; it != theIdsOrder.end(); it++ ) {
6507     // translate submesh identificators into submesh objects
6508     //  takeing into account real number of concurrent lists
6509     const TListOfInt& aSubOrder = (*it);
6510     if (!aSubOrder.size())
6511       continue;
6512     if ( theIsDump )
6513       aPythonDump << "[ ";
6514     // convert shape indices into interfaces
6515     SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
6516     aResSubSet->length(aSubOrder.size());
6517     TListOfInt::const_iterator subIt = aSubOrder.begin();
6518     int j;
6519     for( j = 0; subIt != aSubOrder.end(); subIt++ ) {
6520       if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
6521         continue;
6522       SMESH::SMESH_subMesh_var subMesh =
6523         SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
6524       if ( theIsDump ) {
6525         if ( j > 0 )
6526           aPythonDump << ", ";
6527         aPythonDump << subMesh;
6528       }
6529       aResSubSet[ j++ ] = subMesh;
6530     }
6531     if ( theIsDump )
6532       aPythonDump << " ]";
6533     if ( j > 1 )
6534       theResOrder[ listIndx++ ] = aResSubSet;
6535   }
6536   // correct number of lists
6537   theResOrder.length( listIndx );
6538
6539   if ( theIsDump ) {
6540     // finilise python dump
6541     aPythonDump << " ]";
6542     aPythonDump << " = " << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshOrder()";
6543   }
6544 }
6545
6546 namespace // utils used by SMESH_MeshPartDS
6547 {
6548   /*!
6549    * \brief Class used to access to protected data of SMDS_MeshInfo
6550    */
6551   struct TMeshInfo : public SMDS_MeshInfo
6552   {
6553     void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); }
6554   };
6555   /*!
6556    * \brief Element holing its ID only
6557    */
6558   struct TElemID : public SMDS_LinearEdge
6559   {
6560     TElemID(int ID) : SMDS_LinearEdge(0,0) { setID( ID ); }
6561   };
6562 }
6563
6564 //================================================================================
6565 //
6566 // Implementation of SMESH_MeshPartDS
6567 //
6568 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
6569   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true)
6570 {
6571   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
6572   SMESH_Mesh_i*       mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
6573
6574   mesh_i->Load();
6575   _meshDS = mesh_i->GetImpl().GetMeshDS();
6576
6577   SetPersistentId( _meshDS->GetPersistentId() );
6578
6579   if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
6580   {
6581     // <meshPart> is the whole mesh
6582     myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
6583     // copy groups
6584     set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
6585     myGroupSet = _meshDS->GetGroups();
6586   }
6587   else
6588   {
6589     TMeshInfo tmpInfo;
6590     SMESH::long_array_var           anIDs = meshPart->GetIDs();
6591     SMESH::array_of_ElementType_var types = meshPart->GetTypes();
6592     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
6593     {
6594       for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
6595         if ( const SMDS_MeshNode * n = _meshDS->FindNode( anIDs[i] ))
6596           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
6597             tmpInfo.Add( n );
6598     }
6599     else
6600     {
6601       for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
6602         if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
6603           if ( _elements[ e->GetType() ].insert( e ).second )
6604           {
6605             tmpInfo.Add( e );
6606             SMDS_ElemIteratorPtr nIt = e->nodesIterator();
6607             while ( nIt->more() )
6608             {
6609               const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
6610               if ( _elements[ SMDSAbs_Node ].insert( n ).second )
6611                 tmpInfo.Add( n );
6612             }
6613           }
6614     }
6615     myInfo = tmpInfo;
6616
6617     ShapeToMesh( _meshDS->ShapeToMesh() );
6618
6619     _meshDS = 0; // to enforce iteration on _elements and _nodes
6620   }
6621 }
6622 // -------------------------------------------------------------------------------------
6623 SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
6624   SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
6625 {
6626   TMeshInfo tmpInfo;
6627   list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
6628   for ( ; partIt != meshPart.end(); ++partIt )
6629     if ( const SMDS_MeshElement * e = *partIt )
6630       if ( _elements[ e->GetType() ].insert( e ).second )
6631       {
6632         tmpInfo.Add( e );
6633         SMDS_ElemIteratorPtr nIt = e->nodesIterator();
6634         while ( nIt->more() )
6635         {
6636           const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
6637           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
6638             tmpInfo.Add( n );
6639         }
6640       }
6641   myInfo = tmpInfo;
6642 }
6643 // -------------------------------------------------------------------------------------
6644 const SMDS_MeshElement * SMESH_MeshPartDS::FindElement(int IDelem) const
6645 {
6646   if ( _meshDS ) return _meshDS->FindElement( IDelem );
6647
6648   TElemID elem( IDelem );
6649   for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
6650     if ( !_elements[ iType ].empty() )
6651     {
6652       TIDSortedElemSet::const_iterator it = _elements[ iType ].find( &elem );
6653       if ( it != _elements[ iType ].end() )
6654         return *it;
6655     }
6656   return 0;
6657 }
6658 // -------------------------------------------------------------------------------------
6659 bool SMESH_MeshPartDS::HasNumerationHoles()
6660 {
6661   if ( _meshDS ) return _meshDS->HasNumerationHoles();
6662
6663   return ( MinNodeID() != 1 ||
6664            MaxNodeID() != NbNodes() ||
6665            MinElementID() != 1 ||
6666            MaxElementID() != NbElements() );
6667 }
6668 // -------------------------------------------------------------------------------------
6669 int SMESH_MeshPartDS::MaxNodeID() const
6670 {
6671   if ( _meshDS ) return _meshDS->MaxNodeID();
6672   return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].rbegin())->GetID();
6673 }
6674 // -------------------------------------------------------------------------------------
6675 int SMESH_MeshPartDS::MinNodeID() const
6676 {
6677   if ( _meshDS ) return _meshDS->MinNodeID();
6678   return NbNodes() == 0 ? 0 : (*_elements[ SMDSAbs_Node ].begin())->GetID();
6679 }  
6680 // -------------------------------------------------------------------------------------
6681 int SMESH_MeshPartDS::MaxElementID() const
6682 {
6683   if ( _meshDS ) return _meshDS->MaxElementID();
6684   int maxID = 0;
6685   for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
6686     if ( !_elements[ iType ].empty() )
6687       maxID = Max( maxID, (*_elements[ iType ].rbegin())->GetID() );
6688   return maxID;
6689 }
6690 // -------------------------------------------------------------------------------------
6691 int SMESH_MeshPartDS::MinElementID() const
6692 {
6693   if ( _meshDS ) return _meshDS->MinElementID();
6694   int minID = 0;
6695   for ( int iType = SMDSAbs_Edge; iType < SMDSAbs_NbElementTypes; ++iType )
6696     if ( !_elements[ iType ].empty() )
6697       minID = Min( minID, (*_elements[ iType ].begin())->GetID() );
6698   return minID;
6699 }
6700 // -------------------------------------------------------------------------------------
6701 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
6702 {
6703   if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
6704
6705   typedef SMDS_SetIterator
6706     <const SMDS_MeshElement*,
6707     TIDSortedElemSet::const_iterator,
6708     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
6709     SMDS_MeshElement::GeomFilter
6710     > TIter;
6711
6712   SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( geomType );
6713
6714   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
6715                                           _elements[type].end(),
6716                                           SMDS_MeshElement::GeomFilter( geomType )));
6717 }
6718 // -------------------------------------------------------------------------------------
6719 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementEntityIterator(SMDSAbs_EntityType entity) const
6720 {
6721   if ( _meshDS ) return _meshDS->elementEntityIterator( entity );
6722
6723   typedef SMDS_SetIterator
6724     <const SMDS_MeshElement*,
6725     TIDSortedElemSet::const_iterator,
6726     SMDS::SimpleAccessor<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator>,
6727     SMDS_MeshElement::EntityFilter
6728     > TIter;
6729
6730   SMDSAbs_ElementType type = SMDS_MeshCell::ElemType( entity );
6731
6732   return SMDS_ElemIteratorPtr( new TIter( _elements[type].begin(),
6733                                           _elements[type].end(),
6734                                           SMDS_MeshElement::EntityFilter( entity )));
6735 }
6736 // -------------------------------------------------------------------------------------
6737 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
6738 {
6739   typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
6740   if ( type == SMDSAbs_All && !_meshDS )
6741   {
6742     typedef vector< SMDS_ElemIteratorPtr > TIterVec;
6743     TIterVec iterVec;
6744     for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
6745       if ( !_elements[i].empty() && i != SMDSAbs_Node )
6746         iterVec.push_back
6747           ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
6748
6749     typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
6750     return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
6751   }
6752   return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
6753       ( new TIter( _elements[type].begin(), _elements[type].end() ));
6754 }
6755 // -------------------------------------------------------------------------------------
6756 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType)                       \
6757   iterType SMESH_MeshPartDS::methName() const                 \
6758   {                                                                                 \
6759     typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
6760     return _meshDS ? _meshDS->methName() : iterType                 \
6761       ( new TIter( _elements[elemType].begin(), _elements[elemType].end() ));       \
6762   }
6763 // -------------------------------------------------------------------------------------
6764 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
6765 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
6766 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
6767 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
6768 #undef _GET_ITER_DEFINE
6769 //
6770 // END Implementation of SMESH_MeshPartDS
6771 //
6772 //================================================================================