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