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