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