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