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