Salome HOME
c61a7da9d1784f2cee95b971d614325730e920d2
[modules/smesh.git] / src / SMESH_I / SMESH_Mesh_i.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : SMESH_Mesh_i.cxx
23 //  Author : Paul RASCLE, EDF
24 //  Module : SMESH
25
26 #include "SMESH_Mesh_i.hxx"
27
28 #include "DriverMED_R_SMESHDS_Mesh.h"
29 #include "DriverMED_W_Field.h"
30 #include "DriverMED_W_SMESHDS_Mesh.h"
31 #include "MED_Factory.hxx"
32 #include "SMDS_LinearEdge.hxx"
33 #include "SMDS_EdgePosition.hxx"
34 #include "SMDS_ElemIterator.hxx"
35 #include "SMDS_FacePosition.hxx"
36 #include "SMDS_IteratorOnIterators.hxx"
37 #include "SMDS_MeshGroup.hxx"
38 #include "SMDS_SetIterator.hxx"
39 #include "SMDS_StdIterator.hxx"
40 #include "SMDS_VolumeTool.hxx"
41 #include "SMESHDS_Command.hxx"
42 #include "SMESHDS_CommandType.hxx"
43 #include "SMESHDS_Group.hxx"
44 #include "SMESHDS_GroupOnGeom.hxx"
45 #include "SMESH_Controls.hxx"
46 #include "SMESH_File.hxx"
47 #include "SMESH_Filter_i.hxx"
48 #include "SMESH_Gen_i.hxx"
49 #include "SMESH_Group.hxx"
50 #include "SMESH_Group_i.hxx"
51 #include "SMESH_Mesh.hxx"
52 #include "SMESH_MeshAlgos.hxx"
53 #include "SMESH_MeshEditor.hxx"
54 #include "SMESH_MeshEditor_i.hxx"
55 #include "SMESH_MeshPartDS.hxx"
56 #include "SMESH_MesherHelper.hxx"
57 #include "SMESH_PreMeshInfo.hxx"
58 #include "SMESH_PythonDump.hxx"
59 #include "SMESH_subMesh_i.hxx"
60
61 #include <SALOMEDS_Attributes_wrap.hxx>
62 #include <SALOMEDS_wrap.hxx>
63 #include <Utils_ExceptHandlers.hxx>
64 #include <utilities.h>
65
66 #include <GEOMImpl_Types.hxx>
67 #include <GEOM_wrap.hxx>
68
69 // OCCT Includes
70 #include <BRep_Builder.hxx>
71 #include <Standard_ErrorHandler.hxx>
72 #include <TColStd_MapOfInteger.hxx>
73 #include <TopExp.hxx>
74 #include <TopExp_Explorer.hxx>
75 #include <TopTools_MapIteratorOfMapOfShape.hxx>
76 #include <TopTools_MapOfShape.hxx>
77 #include <TopoDS_Compound.hxx>
78
79 // STL Includes
80 #include <algorithm>
81 #include <iostream>
82 #include <sstream>
83
84 #include <vtkUnstructuredGridWriter.h>
85
86 // to pass CORBA exception through SMESH_TRY
87 #define SMY_OWN_CATCH catch( SALOME::SALOME_Exception& se ) { throw se; }
88
89 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
90
91 #ifdef _DEBUG_
92 static int MYDEBUG = 0;
93 #else
94 static int MYDEBUG = 0;
95 #endif
96
97 using namespace std;
98 using SMESH::TPythonDump;
99 using SMESH::TVar;
100
101 int SMESH_Mesh_i::_idGenerator = 0;
102
103 //=============================================================================
104 /*!
105  *  Constructor
106  */
107 //=============================================================================
108
109 SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
110                             SMESH_Gen_i*            gen_i )
111 : SALOME::GenericObj_i( thePOA )
112 {
113   _impl          = NULL;
114   _gen_i         = gen_i;
115   _id            = _idGenerator++;
116   _editor        = NULL;
117   _previewEditor = NULL;
118   _preMeshInfo   = NULL;
119   _mainShapeTick = 0;
120 }
121
122 //=============================================================================
123 /*!
124  *  Destructor
125  */
126 //=============================================================================
127
128 SMESH_Mesh_i::~SMESH_Mesh_i()
129 {
130   // destroy groups
131   map<int, SMESH::SMESH_GroupBase_ptr>::iterator itGr;
132   for (itGr = _mapGroups.begin(); itGr != _mapGroups.end(); itGr++)
133     if (SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>(itGr->second))
134     {
135       aGroup->UnRegister();
136       SMESH::SMESH_GroupBase_var( itGr->second );
137     }
138   _mapGroups.clear();
139
140   // destroy submeshes
141   map<int, SMESH::SMESH_subMesh_ptr>::iterator itSM;
142   for ( itSM = _mapSubMeshIor.begin(); itSM != _mapSubMeshIor.end(); itSM++ )
143     if ( SMESH_subMesh_i* aSubMesh = SMESH::DownCast<SMESH_subMesh_i*>( itSM->second ))
144     {
145       aSubMesh->UnRegister();
146       SMESH::SMESH_subMesh_var( itSM->second );
147     }
148   _mapSubMeshIor.clear();
149
150   // destroy hypotheses. _mapHypo contains all hyps ever been assigned
151   map<int, SMESH::SMESH_Hypothesis_ptr>::iterator itH;
152   for ( itH = _mapHypo.begin(); itH != _mapHypo.end(); itH++ ) {
153     if ( SMESH_Hypothesis_i* hyp_i = SMESH::DownCast<SMESH_Hypothesis_i*>( itH->second ))
154       if ( SMESH_Hypothesis * smHyp = _impl->GetHypothesis( itH->first ))
155         if ( _impl->GetMeshDS()->IsUsedHypothesis( smHyp ))
156           hyp_i->UnRegister();
157
158     SMESH::SMESH_Hypothesis_var( itH->second ); // decref CORBA object
159   }
160   _mapHypo.clear();
161
162   // clear cached shapes if no more meshes remain; (the cache is blame,
163   // together with publishing, of spent time increasing in issue 22874)
164   if ( _impl->NbMeshes() == 1 )
165     _gen_i->GetShapeReader()->ClearClientBuffer();
166
167   delete _editor; _editor = NULL;
168   delete _previewEditor; _previewEditor = NULL;
169   delete _impl; _impl = NULL;
170   delete _preMeshInfo; _preMeshInfo = NULL;
171 }
172
173 //=============================================================================
174 /*!
175  *  SetShape
176  *
177  *  Associates <this> mesh with <theShape> and puts a reference
178  *  to <theShape> into the current study;
179  *  the previous shape is substituted by the new one.
180  */
181 //=============================================================================
182
183 void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
184     throw (SALOME::SALOME_Exception)
185 {
186   Unexpect aCatch(SALOME_SalomeException);
187   try {
188     _impl->ShapeToMesh( _gen_i->GeomObjectToShape( theShapeObject ));
189   }
190   catch(SALOME_Exception & S_ex) {
191     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
192   }
193   // to track changes of GEOM groups
194   SMESH::SMESH_Mesh_var mesh = _this();
195   addGeomGroupData( theShapeObject, mesh );
196   if ( !CORBA::is_nil( theShapeObject ))
197     _mainShapeTick = theShapeObject->GetTick();
198 }
199
200 //================================================================================
201 /*!
202  * \brief return true if mesh has a shape to build a shape on
203  */
204 //================================================================================
205
206 CORBA::Boolean SMESH_Mesh_i::HasShapeToMesh()
207   throw (SALOME::SALOME_Exception)
208 {
209   Unexpect aCatch(SALOME_SalomeException);
210   bool res = false;
211   try {
212     res = _impl->HasShapeToMesh();
213   }
214   catch(SALOME_Exception & S_ex) {
215     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
216   }
217   return res;
218 }
219
220 //=======================================================================
221 //function : GetShapeToMesh
222 //purpose  :
223 //=======================================================================
224
225 GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
226   throw (SALOME::SALOME_Exception)
227 {
228   Unexpect aCatch(SALOME_SalomeException);
229   GEOM::GEOM_Object_var aShapeObj;
230   try {
231     TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
232     if ( !S.IsNull() )
233     {
234       aShapeObj = _gen_i->ShapeToGeomObject( S );
235       if ( aShapeObj->_is_nil() )
236       {
237         // S was removed from GEOM_Client by newGroupShape() called by other mesh;
238         // find GEOM_Object by entry (IPAL52735)
239         list<TGeomGroupData>::iterator data = _geomGroupData.begin();
240         for ( ; data != _geomGroupData.end(); ++data )
241           if ( data->_smeshObject->_is_equivalent( _this() ))
242           {
243             SALOMEDS::SObject_wrap so = SMESH_Gen_i::getStudyServant()->FindObjectID( data->_groupEntry.c_str() );
244             CORBA::Object_var     obj = _gen_i->SObjectToObject( so );
245             aShapeObj = GEOM::GEOM_Object::_narrow( obj );
246             break;
247           }
248       }
249     }
250   }
251   catch(SALOME_Exception & S_ex) {
252     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
253   }
254   return aShapeObj._retn();
255 }
256
257 //================================================================================
258 /*!
259  * \brief Return false if the mesh is not yet fully loaded from the study file
260  */
261 //================================================================================
262
263 CORBA::Boolean SMESH_Mesh_i::IsLoaded() throw (SALOME::SALOME_Exception)
264 {
265   Unexpect aCatch(SALOME_SalomeException);
266   return !_preMeshInfo;
267 }
268
269 //================================================================================
270 /*!
271  * \brief Load full mesh data from the study file
272  */
273 //================================================================================
274
275 void SMESH_Mesh_i::Load() throw (SALOME::SALOME_Exception)
276 {
277   Unexpect aCatch(SALOME_SalomeException);
278   if ( _preMeshInfo )
279     _preMeshInfo->FullLoadFromFile();
280 }
281
282 //================================================================================
283 /*!
284  * \brief Remove all nodes and elements
285  */
286 //================================================================================
287
288 void SMESH_Mesh_i::Clear() throw (SALOME::SALOME_Exception)
289 {
290   Unexpect aCatch(SALOME_SalomeException);
291   if ( _preMeshInfo )
292     _preMeshInfo->ForgetOrLoad(); // load in case if !HasShapeToMesh()
293
294   try {
295     _impl->Clear();
296     //CheckGeomGroupModif(); // issue 20145
297   }
298   catch(SALOME_Exception & S_ex) {
299     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
300   }
301
302   TPythonDump() <<  SMESH::SMESH_Mesh_var(_this()) << ".Clear()";
303
304   SMESH::SMESH_Mesh_var mesh = _this();
305   _gen_i->UpdateIcons( mesh );
306 }
307
308 //================================================================================
309 /*!
310  * \brief Remove all nodes and elements for indicated shape
311  */
312 //================================================================================
313
314 void SMESH_Mesh_i::ClearSubMesh(CORBA::Long ShapeID)
315   throw (SALOME::SALOME_Exception)
316 {
317   Unexpect aCatch(SALOME_SalomeException);
318   if ( _preMeshInfo )
319     _preMeshInfo->FullLoadFromFile();
320
321   try {
322     _impl->ClearSubMesh( ShapeID );
323   }
324   catch(SALOME_Exception & S_ex) {
325     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
326   }
327   _impl->GetMeshDS()->Modified();
328
329   TPythonDump() <<  SMESH::SMESH_Mesh_var(_this()) << ".ClearSubMesh( " << ShapeID << " )";
330 }
331
332 //=============================================================================
333 /*!
334  * Convert enum Driver_Mesh::Status to SMESH::DriverMED_ReadStatus
335  */
336 //=============================================================================
337
338 static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
339 {
340   SMESH::DriverMED_ReadStatus res;
341   switch (theStatus)
342   {
343   case DriverMED_R_SMESHDS_Mesh::DRS_OK:
344     res = SMESH::DRS_OK; break;
345   case DriverMED_R_SMESHDS_Mesh::DRS_EMPTY:
346     res = SMESH::DRS_EMPTY; break;
347   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_RENUMBER:
348     res = SMESH::DRS_WARN_RENUMBER; break;
349   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
350     res = SMESH::DRS_WARN_SKIP_ELEM; break;
351   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_DESCENDING:
352     res = SMESH::DRS_WARN_DESCENDING; break;
353   case DriverMED_R_SMESHDS_Mesh::DRS_FAIL:
354   default:
355     res = SMESH::DRS_FAIL; break;
356   }
357   return res;
358 }
359
360 //=============================================================================
361 /*!
362  * Convert ::SMESH_ComputeError to SMESH::ComputeError
363  */
364 //=============================================================================
365
366 static SMESH::ComputeError* ConvertComputeError( SMESH_ComputeErrorPtr errorPtr )
367 {
368   SMESH::ComputeError_var errVar = new SMESH::ComputeError();
369   errVar->subShapeID = -1;
370   errVar->hasBadMesh = false;
371
372   if ( !errorPtr || errorPtr->IsOK() )
373   {
374     errVar->code = SMESH::COMPERR_OK;
375   }
376   else
377   {
378     errVar->code    = ConvertDriverMEDReadStatus( errorPtr->myName );
379     errVar->comment = errorPtr->myComment.c_str();
380   }
381   return errVar._retn();
382 }
383
384 //=============================================================================
385 /*!
386  *  ImportMEDFile
387  *
388  *  Imports mesh data from MED file
389  */
390 //=============================================================================
391
392 SMESH::DriverMED_ReadStatus
393 SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
394   throw ( SALOME::SALOME_Exception )
395 {
396   Unexpect aCatch(SALOME_SalomeException);
397   int status;
398   try {
399     status = _impl->MEDToMesh( theFileName, theMeshName );
400   }
401   catch( SALOME_Exception& S_ex ) {
402     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
403   }
404   catch ( ... ) {
405     THROW_SALOME_CORBA_EXCEPTION("ImportMEDFile(): unknown exception", SALOME::BAD_PARAM);
406   }
407
408   CreateGroupServants();
409
410   int major, minor, release;
411   major = minor = release = 0;
412   MED::GetMEDVersion(theFileName, major, minor, release);
413   _medFileInfo           = new SMESH::MedFileInfo();
414   _medFileInfo->fileName = theFileName;
415   _medFileInfo->fileSize = 0;
416   _medFileInfo->major    = major;
417   _medFileInfo->minor    = minor;
418   _medFileInfo->release  = release;
419   _medFileInfo->fileSize = SMESH_File( theFileName ).size();
420
421   return ConvertDriverMEDReadStatus(status);
422 }
423
424 //================================================================================
425 /*!
426  * \brief Imports mesh data from the CGNS file
427  */
428 //================================================================================
429
430 SMESH::DriverMED_ReadStatus SMESH_Mesh_i::ImportCGNSFile( const char*  theFileName,
431                                                           const int    theMeshIndex,
432                                                           std::string& theMeshName )
433   throw ( SALOME::SALOME_Exception )
434 {
435   Unexpect aCatch(SALOME_SalomeException);
436   int status;
437   try {
438     status = _impl->CGNSToMesh( theFileName, theMeshIndex, theMeshName );
439   }
440   catch( SALOME_Exception& S_ex ) {
441     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
442   }
443   catch ( ... ) {
444     THROW_SALOME_CORBA_EXCEPTION("ImportCGNSFile(): unknown exception", SALOME::BAD_PARAM);
445   }
446
447   CreateGroupServants();
448
449   _medFileInfo           = new SMESH::MedFileInfo();
450   _medFileInfo->fileName = theFileName;
451   _medFileInfo->major    = 0;
452   _medFileInfo->minor    = 0;
453   _medFileInfo->release  = 0;
454   _medFileInfo->fileSize = SMESH_File( theFileName ).size();
455
456   return ConvertDriverMEDReadStatus(status);
457 }
458
459 //================================================================================
460 /*!
461  * \brief Return string representation of a MED file version comprising nbDigits
462  */
463 //================================================================================
464
465 char* SMESH_Mesh_i::GetVersionString(CORBA::Long minor, CORBA::Short nbDigits)
466 {
467   string ver = DriverMED_W_SMESHDS_Mesh::GetVersionString(minor,
468                                                           nbDigits);
469   return CORBA::string_dup( ver.c_str() );
470 }
471
472 //================================================================================
473 /*!
474  *  Return the list of med versions compatibles for write/append,
475  *  encoded in 10*major+minor (for instance, code for med 3.2.1 is 32)
476  */
477 //================================================================================
478 SMESH::long_array* SMESH_Mesh_i::GetMEDVersionsCompatibleForAppend()
479 {
480   SMESH::long_array_var aResult = new SMESH::long_array();
481   std::vector<int> mvok = MED::GetMEDVersionsAppendCompatible();
482   long nbver = mvok.size();
483   aResult->length( nbver );
484   for ( int i = 0; i < nbver; i++ )
485     aResult[i] = mvok[i];
486   return aResult._retn();
487 }
488
489 //=============================================================================
490 /*!
491  *  ImportUNVFile
492  *
493  *  Imports mesh data from MED file
494  */
495 //=============================================================================
496
497 int SMESH_Mesh_i::ImportUNVFile( const char* theFileName )
498   throw ( SALOME::SALOME_Exception )
499 {
500   SMESH_TRY;
501
502   // Read mesh with name = <theMeshName> into SMESH_Mesh
503   _impl->UNVToMesh( theFileName );
504
505   CreateGroupServants();
506
507   _medFileInfo           = new SMESH::MedFileInfo();
508   _medFileInfo->fileName = theFileName;
509   _medFileInfo->major    = 0;
510   _medFileInfo->minor    = 0;
511   _medFileInfo->release  = 0;
512   _medFileInfo->fileSize = SMESH_File( theFileName ).size();
513
514   SMESH_CATCH( SMESH::throwCorbaException );
515
516   return 1;
517 }
518
519 //=============================================================================
520 /*!
521  *  ImportSTLFile
522  *
523  *  Imports mesh data from STL file
524  */
525 //=============================================================================
526 int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
527   throw ( SALOME::SALOME_Exception )
528 {
529   SMESH_TRY;
530
531   // Read mesh with name = <theMeshName> into SMESH_Mesh
532   std::string name = _impl->STLToMesh( theFileName );
533   if ( !name.empty() )
534   {
535     SALOMEDS::SObject_wrap meshSO = _gen_i->ObjectToSObject( _this() );
536     _gen_i->SetName( meshSO, name.c_str() );
537   }
538   _medFileInfo           = new SMESH::MedFileInfo();
539   _medFileInfo->fileName = theFileName;
540   _medFileInfo->major    = 0;
541   _medFileInfo->minor    = 0;
542   _medFileInfo->release  = 0;
543   _medFileInfo->fileSize = SMESH_File( theFileName ).size();
544
545   SMESH_CATCH( SMESH::throwCorbaException );
546
547   return 1;
548 }
549
550 //================================================================================
551 /*!
552  * \brief Function used in SMESH_CATCH by ImportGMFFile()
553  */
554 //================================================================================
555
556 namespace
557 {
558   SMESH_ComputeErrorPtr exceptionToComputeError(const char* excText)
559   {
560     return SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, excText );
561   }
562 }
563
564 //================================================================================
565 /*!
566  * \brief Imports data from a GMF file and returns an error description
567  */
568 //================================================================================
569
570 SMESH::ComputeError* SMESH_Mesh_i::ImportGMFFile( const char* theFileName,
571                                                   bool        theMakeRequiredGroups )
572   throw (SALOME::SALOME_Exception)
573 {
574   SMESH_ComputeErrorPtr error;
575
576 #undef SMESH_CAUGHT
577 #define SMESH_CAUGHT error =
578   SMESH_TRY;
579
580   error = _impl->GMFToMesh( theFileName, theMakeRequiredGroups );
581
582   _medFileInfo           = new SMESH::MedFileInfo();
583   _medFileInfo->fileName = theFileName;
584   _medFileInfo->major    = 0;
585   _medFileInfo->minor    = 0;
586   _medFileInfo->release  = 0;
587   _medFileInfo->fileSize = SMESH_File( theFileName ).size();
588
589   SMESH_CATCH( exceptionToComputeError );
590 #undef SMESH_CAUGHT
591 #define SMESH_CAUGHT
592
593   CreateGroupServants();
594
595   return ConvertComputeError( error );
596 }
597
598 //=============================================================================
599 /*!
600  *
601  */
602 //=============================================================================
603
604 #define RETURNCASE(hyp_stat) case SMESH_Hypothesis::hyp_stat: return SMESH::hyp_stat;
605
606 SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
607                          (SMESH_Hypothesis::Hypothesis_Status theStatus)
608 {
609   switch (theStatus) {
610   RETURNCASE( HYP_OK            );
611   RETURNCASE( HYP_MISSING       );
612   RETURNCASE( HYP_CONCURRENT    );
613   RETURNCASE( HYP_BAD_PARAMETER );
614   RETURNCASE( HYP_HIDDEN_ALGO   );
615   RETURNCASE( HYP_HIDING_ALGO   );
616   RETURNCASE( HYP_UNKNOWN_FATAL );
617   RETURNCASE( HYP_INCOMPATIBLE  );
618   RETURNCASE( HYP_NOTCONFORM    );
619   RETURNCASE( HYP_ALREADY_EXIST );
620   RETURNCASE( HYP_BAD_DIM       );
621   RETURNCASE( HYP_BAD_SUBSHAPE  );
622   RETURNCASE( HYP_BAD_GEOMETRY  );
623   RETURNCASE( HYP_NEED_SHAPE    );
624   RETURNCASE( HYP_INCOMPAT_HYPS );
625   default:;
626   }
627   return SMESH::HYP_UNKNOWN_FATAL;
628 }
629
630 //=============================================================================
631 /*!
632  *  AddHypothesis
633  *
634  *  calls internal addHypothesis() and then adds a reference to <anHyp> under
635  *  the SObject actually having a reference to <aSubShape>.
636  *  NB: For this method to work, it is necessary to add a reference to sub-shape first.
637  */
638 //=============================================================================
639
640 SMESH::Hypothesis_Status
641 SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
642                             SMESH::SMESH_Hypothesis_ptr anHyp,
643                             CORBA::String_out           anErrorText)
644   throw(SALOME::SALOME_Exception)
645 {
646   Unexpect aCatch(SALOME_SalomeException);
647   if ( _preMeshInfo )
648     _preMeshInfo->ForgetOrLoad();
649
650   std::string error;
651   SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShape, anHyp, &error );
652   anErrorText = error.c_str();
653
654   SMESH::SMESH_Mesh_var mesh( _this() );
655   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
656   {
657     _gen_i->AddHypothesisToShape( mesh, aSubShape, anHyp );
658     _gen_i->UpdateIcons( mesh );
659   }
660   if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
661
662   // Update Python script
663   TPythonDump() << "status = " << mesh << ".AddHypothesis( "
664                 << aSubShape << ", " << anHyp << " )";
665
666   return ConvertHypothesisStatus(status);
667 }
668
669 //=============================================================================
670 /*!
671  *
672  */
673 //=============================================================================
674
675 SMESH_Hypothesis::Hypothesis_Status
676 SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
677                             SMESH::SMESH_Hypothesis_ptr anHyp,
678                             std::string*                anErrorText)
679 {
680   if(MYDEBUG) MESSAGE("addHypothesis");
681
682   if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
683     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",SALOME::BAD_PARAM);
684
685   if (CORBA::is_nil( anHyp ))
686     THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",SALOME::BAD_PARAM);
687
688   SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
689   try
690   {
691     TopoDS_Shape myLocSubShape;
692     //use PseudoShape in case if mesh has no shape
693     if(HasShapeToMesh())
694       myLocSubShape = _gen_i->GeomObjectToShape( aSubShape);
695     else
696       myLocSubShape = _impl->GetShapeToMesh();
697
698     const int hypId = anHyp->GetId();
699     std::string error;
700     status = _impl->AddHypothesis( myLocSubShape, hypId, &error );
701     if ( !SMESH_Hypothesis::IsStatusFatal(status) )
702     {
703       _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( anHyp );
704       anHyp->Register();
705       // assure there is a corresponding submesh
706       if ( !_impl->IsMainShape( myLocSubShape )) {
707         int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
708         if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
709           SMESH::SMESH_subMesh_var( createSubMesh( aSubShape ));
710       }
711     }
712     else if ( anErrorText )
713     {
714       *anErrorText = error;
715     }
716   }
717   catch(SALOME_Exception & S_ex)
718   {
719     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
720   }
721   return status;
722 }
723
724 //=============================================================================
725 /*!
726  *
727  */
728 //=============================================================================
729
730 SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShape,
731                                                         SMESH::SMESH_Hypothesis_ptr anHyp)
732   throw(SALOME::SALOME_Exception)
733 {
734   Unexpect aCatch(SALOME_SalomeException);
735   if ( _preMeshInfo )
736     _preMeshInfo->ForgetOrLoad();
737
738   SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShape, anHyp );
739   SMESH::SMESH_Mesh_var mesh = _this();
740
741   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
742   {
743     _gen_i->RemoveHypothesisFromShape( mesh, aSubShape, anHyp );
744     _gen_i->UpdateIcons( mesh );
745   }
746   // Update Python script
747   if(_impl->HasShapeToMesh())
748     TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
749                   << aSubShape << ", " << anHyp << " )";
750   else
751     TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
752                   << anHyp << " )";
753
754   return ConvertHypothesisStatus(status);
755 }
756
757 //=============================================================================
758 /*!
759  *
760  */
761 //=============================================================================
762
763 SMESH_Hypothesis::Hypothesis_Status
764 SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
765                                SMESH::SMESH_Hypothesis_ptr anHyp)
766 {
767   if(MYDEBUG) MESSAGE("removeHypothesis()");
768
769   if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
770     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
771
772   if (CORBA::is_nil( anHyp ))
773     THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference", SALOME::BAD_PARAM);
774
775   SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
776   try
777   {
778     TopoDS_Shape myLocSubShape;
779     //use PseudoShape in case if mesh has no shape
780     if( _impl->HasShapeToMesh() )
781       myLocSubShape = _gen_i->GeomObjectToShape( aSubShape );
782     else
783       myLocSubShape = _impl->GetShapeToMesh();
784
785     const int hypId = anHyp->GetId();
786     status = _impl->RemoveHypothesis(myLocSubShape, hypId);
787     if ( !SMESH_Hypothesis::IsStatusFatal(status) )
788     {
789       // _mapHypo.erase( hypId ); EAP: hyp can be used on many sub-shapes
790       anHyp->UnRegister();
791     }
792   }
793   catch(SALOME_Exception & S_ex)
794   {
795     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
796   }
797   return status;
798 }
799
800 //=============================================================================
801 /*!
802  *
803  */
804 //=============================================================================
805
806 SMESH::ListOfHypothesis *
807 SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShape)
808 throw(SALOME::SALOME_Exception)
809 {
810   Unexpect aCatch(SALOME_SalomeException);
811   if (MYDEBUG) MESSAGE("GetHypothesisList");
812   if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShape))
813     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
814
815   SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
816
817   try {
818     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
819     if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() )
820       myLocSubShape = _impl->GetShapeToMesh();
821     const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
822     int i = 0, n = aLocalList.size();
823     aList->length( n );
824
825     list<const SMESHDS_Hypothesis*>::const_iterator aHyp = aLocalList.begin();
826     std::map<int, SMESH::SMESH_Hypothesis_ptr>::iterator id_hypptr;
827     for ( ; i < n && aHyp != aLocalList.end(); aHyp++ )
828     {
829       id_hypptr = _mapHypo.find( (*aHyp)->GetID() );
830       if ( id_hypptr != _mapHypo.end() )
831         aList[i++] = SMESH::SMESH_Hypothesis::_narrow( id_hypptr->second );
832     }
833     aList->length( i );
834   }
835   catch(SALOME_Exception & S_ex) {
836     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
837   }
838
839   return aList._retn();
840 }
841
842 SMESH::submesh_array* SMESH_Mesh_i::GetSubMeshes() throw (SALOME::SALOME_Exception)
843 {
844   Unexpect aCatch(SALOME_SalomeException);
845   if (MYDEBUG) MESSAGE("GetSubMeshes");
846
847   SMESH::submesh_array_var aList = new SMESH::submesh_array();
848
849   // Python Dump
850   TPythonDump aPythonDump;
851   if ( !_mapSubMeshIor.empty() )
852     aPythonDump << "[ ";
853
854   try {
855     aList->length( _mapSubMeshIor.size() );
856     int i = 0;
857     map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.begin();
858     for ( ; it != _mapSubMeshIor.end(); it++ ) {
859       if ( CORBA::is_nil( it->second )) continue;
860       aList[i++] = SMESH::SMESH_subMesh::_duplicate( it->second );
861       // Python Dump
862       if (i > 1) aPythonDump << ", ";
863       aPythonDump << it->second;
864     }
865     aList->length( i );
866   }
867   catch(SALOME_Exception & S_ex) {
868     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
869   }
870
871   // Update Python script
872   if ( !_mapSubMeshIor.empty() )
873     aPythonDump << " ] = " << SMESH::SMESH_Mesh_var( _this() ) << ".GetSubMeshes()";
874
875   return aList._retn();
876 }
877
878 //=============================================================================
879 /*!
880  *
881  */
882 //=============================================================================
883
884 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShape,
885                                                   const char*           theName )
886      throw(SALOME::SALOME_Exception)
887 {
888   Unexpect aCatch(SALOME_SalomeException);
889   if (CORBA::is_nil(aSubShape))
890     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
891
892   SMESH::SMESH_subMesh_var subMesh;
893   SMESH::SMESH_Mesh_var    aMesh = _this();
894   try {
895     TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
896
897     //Get or Create the SMESH_subMesh object implementation
898
899     int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
900
901     if ( !subMeshId && ! _impl->GetMeshDS()->IsGroupOfSubShapes( myLocSubShape ))
902     {
903       TopoDS_Iterator it( myLocSubShape );
904       if ( it.More() )
905         THROW_SALOME_CORBA_EXCEPTION("not sub-shape of the main shape", SALOME::BAD_PARAM);
906     }
907     subMesh = getSubMesh( subMeshId );
908
909     // create a new subMesh object servant if there is none for the shape
910     if ( subMesh->_is_nil() )
911       subMesh = createSubMesh( aSubShape );
912     if ( _gen_i->CanPublishInStudy( subMesh ))
913     {
914       SALOMEDS::SObject_wrap aSO =
915         _gen_i->PublishSubMesh( aMesh, subMesh, aSubShape, theName );
916       if ( !aSO->_is_nil()) {
917         // Update Python script
918         TPythonDump() << aSO << " = " << aMesh << ".GetSubMesh( "
919                       << aSubShape << ", '" << theName << "' )";
920       }
921     }
922   }
923   catch(SALOME_Exception & S_ex) {
924     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
925   }
926   return subMesh._retn();
927 }
928
929 //=============================================================================
930 /*!
931  *
932  */
933 //=============================================================================
934
935 void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
936   throw (SALOME::SALOME_Exception)
937 {
938   SMESH_TRY;
939
940   if ( theSubMesh->_is_nil() )
941     return;
942
943   GEOM::GEOM_Object_var aSubShape;
944   // Remove submesh's SObject
945   SALOMEDS::SObject_wrap anSO = _gen_i->ObjectToSObject( theSubMesh );
946   if ( !anSO->_is_nil() ) {
947     long aTag = SMESH_Gen_i::GetRefOnShapeTag();
948     SALOMEDS::SObject_wrap anObj, aRef;
949     if ( anSO->FindSubObject( aTag, anObj.inout() ) &&
950          anObj->ReferencedObject( aRef.inout() ))
951     {
952       CORBA::Object_var obj = aRef->GetObject();
953       aSubShape = GEOM::GEOM_Object::_narrow( obj );
954     }
955     // if ( aSubShape->_is_nil() ) // not published shape (IPAL13617)
956     //   aSubShape = theSubMesh->GetSubShape();
957
958     SALOMEDS::StudyBuilder_var builder = SMESH_Gen_i::getStudyServant()->NewBuilder();
959     builder->RemoveObjectWithChildren( anSO );
960
961     // Update Python script
962     TPythonDump() << SMESH::SMESH_Mesh_var( _this() ) << ".RemoveSubMesh( " << anSO << " )";
963   }
964
965   if ( removeSubMesh( theSubMesh, aSubShape.in() ))
966     if ( _preMeshInfo )
967       _preMeshInfo->ForgetOrLoad();
968
969   SMESH_CATCH( SMESH::throwCorbaException );
970 }
971
972 //=============================================================================
973 /*!
974  *
975  */
976 //=============================================================================
977
978 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType,
979                                                   const char*        theName )
980   throw(SALOME::SALOME_Exception)
981 {
982   Unexpect aCatch(SALOME_SalomeException);
983   if ( _preMeshInfo )
984     _preMeshInfo->FullLoadFromFile();
985
986   SMESH::SMESH_Group_var aNewGroup =
987     SMESH::SMESH_Group::_narrow( createGroup( theElemType, theName ));
988
989   if ( _gen_i->CanPublishInStudy( aNewGroup ) )
990   {
991     SMESH::SMESH_Mesh_var mesh = _this();
992     SALOMEDS::SObject_wrap aSO =
993       _gen_i->PublishGroup( mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName);
994     if ( !aSO->_is_nil())
995       // Update Python script
996       TPythonDump() << aSO << " = " << mesh << ".CreateGroup( "
997                     << theElemType << ", '" << theName << "' )";
998   }
999   return aNewGroup._retn();
1000 }
1001
1002 //=============================================================================
1003 /*!
1004  *
1005  */
1006 //=============================================================================
1007 SMESH::SMESH_GroupOnGeom_ptr
1008 SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType    theElemType,
1009                                    const char*           theName,
1010                                    GEOM::GEOM_Object_ptr theGeomObj)
1011   throw(SALOME::SALOME_Exception)
1012 {
1013   Unexpect aCatch(SALOME_SalomeException);
1014   if ( _preMeshInfo )
1015     _preMeshInfo->FullLoadFromFile();
1016
1017   SMESH::SMESH_GroupOnGeom_var aNewGroup;
1018
1019   TopoDS_Shape aShape = _gen_i->GeomObjectToShape( theGeomObj );
1020   if ( !aShape.IsNull() )
1021   {
1022     aNewGroup =
1023       SMESH::SMESH_GroupOnGeom::_narrow( createGroup( theElemType, theName, /*id=*/-1, aShape ));
1024
1025     if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1026     {
1027       SMESH::SMESH_Mesh_var mesh = _this();
1028       SALOMEDS::SObject_wrap aSO =
1029         _gen_i->PublishGroup( mesh, aNewGroup, theGeomObj, theName );
1030       if ( !aSO->_is_nil())
1031         TPythonDump() << aSO << " = " << mesh << ".CreateGroupFromGEOM( "
1032                       << theElemType << ", '" << theName << "', " << theGeomObj << " )";
1033     }
1034   }
1035
1036   return aNewGroup._retn();
1037 }
1038
1039 //================================================================================
1040 /*!
1041  * \brief Creates a group whose contents is defined by filter
1042  *  \param theElemType - group type
1043  *  \param theName - group name
1044  *  \param theFilter - the filter
1045  *  \retval SMESH::SMESH_GroupOnFilter_ptr - group defined by filter
1046  */
1047 //================================================================================
1048
1049 SMESH::SMESH_GroupOnFilter_ptr
1050 SMESH_Mesh_i::CreateGroupFromFilter(SMESH::ElementType theElemType,
1051                                     const char*        theName,
1052                                     SMESH::Filter_ptr  theFilter )
1053   throw (SALOME::SALOME_Exception)
1054 {
1055   Unexpect aCatch(SALOME_SalomeException);
1056   if ( _preMeshInfo )
1057     _preMeshInfo->FullLoadFromFile();
1058
1059   if ( CORBA::is_nil( theFilter ))
1060     THROW_SALOME_CORBA_EXCEPTION("NULL filter", SALOME::BAD_PARAM);
1061
1062   SMESH_PredicatePtr predicate = SMESH_GroupOnFilter_i::GetPredicate( theFilter );
1063   if ( !predicate )
1064     THROW_SALOME_CORBA_EXCEPTION("Invalid filter", SALOME::BAD_PARAM);
1065
1066   SMESH::SMESH_GroupOnFilter_var aNewGroup = SMESH::SMESH_GroupOnFilter::_narrow
1067     ( createGroup( theElemType, theName, /*id=*/-1, TopoDS_Shape(), predicate ));
1068
1069   TPythonDump pd;
1070   if ( !aNewGroup->_is_nil() )
1071     aNewGroup->SetFilter( theFilter );
1072
1073   if ( _gen_i->CanPublishInStudy( aNewGroup ) )
1074   {
1075     SMESH::SMESH_Mesh_var mesh = _this();
1076     SALOMEDS::SObject_wrap aSO =
1077       _gen_i->PublishGroup( mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName );
1078
1079     if ( !aSO->_is_nil())
1080       pd << aSO << " = " << mesh << ".CreateGroupFromFilter( "
1081          << theElemType << ", '" << theName << "', " << theFilter << " )";
1082   }
1083   return aNewGroup._retn();
1084 }
1085
1086 //=============================================================================
1087 /*!
1088  *
1089  */
1090 //=============================================================================
1091
1092 void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
1093   throw (SALOME::SALOME_Exception)
1094 {
1095   if ( theGroup->_is_nil() )
1096     return;
1097
1098   SMESH_TRY;
1099
1100   SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
1101   if ( !aGroup )
1102     return;
1103
1104   SALOMEDS::SObject_wrap aGroupSO = _gen_i->ObjectToSObject( theGroup );
1105   if ( !aGroupSO->_is_nil() )
1106   {
1107     // Update Python script
1108     TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".RemoveGroup( " << aGroupSO << " )";
1109
1110     // Remove group's SObject
1111     SALOMEDS::StudyBuilder_var builder = SMESH_Gen_i::getStudyServant()->NewBuilder();
1112     builder->RemoveObjectWithChildren( aGroupSO );
1113   }
1114   aGroup->Modified(/*removed=*/true); // notify dependent Filter with FT_BelongToMeshGroup criterion
1115
1116   // Remove the group from SMESH data structures
1117   removeGroup( aGroup->GetLocalID() );
1118
1119   SMESH_CATCH( SMESH::throwCorbaException );
1120 }
1121
1122 //=============================================================================
1123 /*!
1124  *  Remove group with its contents
1125  */
1126 //=============================================================================
1127
1128 void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup )
1129   throw (SALOME::SALOME_Exception)
1130 {
1131   SMESH_TRY;
1132   if ( _preMeshInfo )
1133     _preMeshInfo->FullLoadFromFile();
1134
1135   if ( theGroup->_is_nil() )
1136     return;
1137
1138   vector<int> nodeIds; // to remove nodes becoming free
1139   bool isNodal = ( theGroup->GetType() == SMESH::NODE );
1140   if ( !isNodal && !theGroup->IsEmpty() )
1141   {
1142     CORBA::Long elemID = theGroup->GetID( 1 );
1143     int nbElemNodes = GetElemNbNodes( elemID );
1144     if ( nbElemNodes > 0 )
1145       nodeIds.reserve( theGroup->Size() * nbElemNodes );
1146   }
1147
1148   // Retrieve contents
1149   SMESH::SMESH_IDSource_var idSrc = SMESH::SMESH_IDSource::_narrow( theGroup );
1150   SMDS_ElemIteratorPtr     elemIt = GetElements( idSrc, theGroup->GetType() );
1151   SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > elemBeg( elemIt ), elemEnd;
1152   std::vector< const SMDS_MeshElement* > elems( theGroup->Size() );
1153   elems.assign( elemBeg, elemEnd );
1154
1155   TPythonDump pyDump; // Suppress dump from RemoveGroup()
1156
1157   // Remove group
1158   RemoveGroup( theGroup );
1159
1160   // Remove contents
1161   for ( size_t i = 0; i < elems.size(); ++i )
1162   {
1163     // if ( !_impl->GetMeshDS()->Contains( elems[i] ))
1164     //   continue;
1165     if ( !isNodal )
1166     {
1167       for ( SMDS_ElemIteratorPtr nIt = elems[i]->nodesIterator(); nIt->more(); )
1168         nodeIds.push_back( nIt->next()->GetID() );
1169
1170       _impl->GetMeshDS()->RemoveFreeElement( elems[i], /*sm=*/0 );
1171     }
1172     else
1173     {
1174       _impl->GetMeshDS()->RemoveElement( elems[i] );
1175     }
1176   }
1177
1178   // Remove free nodes
1179   for ( size_t i = 0 ; i < nodeIds.size(); ++i )
1180     if ( const SMDS_MeshNode* n = _impl->GetMeshDS()->FindNode( nodeIds[i] ))
1181       if ( n->NbInverseElements() == 0 )
1182         _impl->GetMeshDS()->RemoveFreeNode( n, /*sm=*/0 );
1183
1184   // Update Python script (theGroup must be alive for this)
1185   pyDump << SMESH::SMESH_Mesh_var(_this())
1186          << ".RemoveGroupWithContents( " << theGroup << " )";
1187
1188   SMESH_CATCH( SMESH::throwCorbaException );
1189 }
1190
1191 //================================================================================
1192 /*!
1193  * \brief Get the list of groups existing in the mesh
1194  *  \retval SMESH::ListOfGroups * - list of groups
1195  */
1196 //================================================================================
1197
1198 SMESH::ListOfGroups * SMESH_Mesh_i::GetGroups() throw(SALOME::SALOME_Exception)
1199 {
1200   Unexpect aCatch(SALOME_SalomeException);
1201   if (MYDEBUG) MESSAGE("GetGroups");
1202
1203   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
1204
1205   // Python Dump
1206   TPythonDump aPythonDump;
1207   if ( !_mapGroups.empty() )
1208   {
1209     aPythonDump << "[ ";
1210     try {
1211       aList->length( _mapGroups.size() );
1212       int i = 0;
1213       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
1214       for ( ; it != _mapGroups.end(); it++ ) {
1215         if ( CORBA::is_nil( it->second )) continue;
1216         aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
1217         // Python Dump
1218         if (i > 1) aPythonDump << ", ";
1219         aPythonDump << it->second;
1220       }
1221       aList->length( i );
1222     }
1223     catch(SALOME_Exception & S_ex) {
1224       THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
1225     }
1226     aPythonDump << " ] = " << SMESH::SMESH_Mesh_var(_this()) << ".GetGroups()";
1227   }
1228   return aList._retn();
1229 }
1230
1231 //=============================================================================
1232 /*!
1233  *  Get number of groups existing in the mesh
1234  */
1235 //=============================================================================
1236
1237 CORBA::Long SMESH_Mesh_i::NbGroups() throw (SALOME::SALOME_Exception)
1238 {
1239   Unexpect aCatch(SALOME_SalomeException);
1240   return _mapGroups.size();
1241 }
1242
1243 //=============================================================================
1244 /*!
1245  * New group including all mesh elements present in initial groups is created.
1246  */
1247 //=============================================================================
1248
1249 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1250                                                   SMESH::SMESH_GroupBase_ptr theGroup2,
1251                                                   const char*                theName )
1252   throw (SALOME::SALOME_Exception)
1253 {
1254   SMESH::SMESH_Group_var aResGrp;
1255
1256   SMESH_TRY;
1257   if ( _preMeshInfo )
1258     _preMeshInfo->FullLoadFromFile();
1259
1260   if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1261     THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): NULL Group",
1262                                  SALOME::BAD_PARAM);
1263   if ( theGroup1->GetType() != theGroup2->GetType() )
1264     THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): different group types",
1265                                  SALOME::BAD_PARAM);
1266   TPythonDump pyDump;
1267
1268   // Create Union
1269   aResGrp = CreateGroup( theGroup1->GetType(), theName );
1270   if ( aResGrp->_is_nil() )
1271     return SMESH::SMESH_Group::_nil();
1272
1273   aResGrp->AddFrom( theGroup1 );
1274   aResGrp->AddFrom( theGroup2 );
1275
1276   // Update Python script
1277   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this())
1278          << ".UnionGroups( " << theGroup1 << ", " << theGroup2 << ", '" << theName << "' )";
1279
1280   SMESH_CATCH( SMESH::throwCorbaException );
1281
1282   return aResGrp._retn();
1283 }
1284
1285 //=============================================================================
1286 /*!
1287  * \brief New group including all mesh elements present in initial groups is created.
1288  *  \param theGroups list of groups
1289  *  \param theName name of group to be created
1290  *  \return pointer to the new group
1291  */
1292 //=============================================================================
1293
1294 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionListOfGroups(const SMESH::ListOfGroups& theGroups,
1295                                                        const char*                theName )
1296   throw (SALOME::SALOME_Exception)
1297 {
1298   SMESH::SMESH_Group_var aResGrp;
1299
1300   if ( _preMeshInfo )
1301     _preMeshInfo->FullLoadFromFile();
1302
1303   if ( !theName )
1304     return SMESH::SMESH_Group::_nil();
1305
1306   SMESH_TRY;
1307
1308   // check types
1309   SMESH::ElementType aType = SMESH::ALL;
1310   for ( int g = 0, n = theGroups.length(); g < n; g++ )
1311   {
1312     SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1313     if ( CORBA::is_nil( aGrp ) )
1314       continue;
1315     if ( aType == SMESH::ALL )
1316       aType = aGrp->GetType();
1317     else if ( aType != aGrp->GetType() )
1318       THROW_SALOME_CORBA_EXCEPTION("UnionListOfGroups(): different group types",
1319                                    SALOME::BAD_PARAM);
1320   }
1321   if ( aType == SMESH::ALL )
1322     return SMESH::SMESH_Group::_nil();
1323
1324   TPythonDump pyDump;
1325
1326   // Create Union
1327   aResGrp = CreateGroup( aType, theName );
1328   if ( aResGrp->_is_nil() )
1329     return SMESH::SMESH_Group::_nil();
1330
1331   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".UnionListOfGroups([ ";
1332   for ( int g = 0, n = theGroups.length(); g < n; g++ )
1333   {
1334     SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1335     if ( !CORBA::is_nil( aGrp ) )
1336     {
1337       aResGrp->AddFrom( aGrp );
1338       if ( g > 0 ) pyDump << ", ";
1339       pyDump << aGrp;
1340     }
1341   }
1342   pyDump << " ], '" << theName << "' )";
1343
1344   SMESH_CATCH( SMESH::throwCorbaException );
1345
1346   return aResGrp._retn();
1347 }
1348
1349 //=============================================================================
1350 /*!
1351  *  New group is created. All mesh elements that are
1352  *  present in both initial groups are added to the new one.
1353  */
1354 //=============================================================================
1355
1356 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1357                                                       SMESH::SMESH_GroupBase_ptr theGroup2,
1358                                                       const char*                theName )
1359   throw (SALOME::SALOME_Exception)
1360 {
1361   SMESH::SMESH_Group_var aResGrp;
1362
1363   SMESH_TRY;
1364
1365   if ( _preMeshInfo )
1366     _preMeshInfo->FullLoadFromFile();
1367
1368   if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1369     THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): NULL Group",
1370                                  SALOME::BAD_PARAM);
1371   if ( theGroup1->GetType() != theGroup2->GetType() )
1372     THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): different group types",
1373                                  SALOME::BAD_PARAM);
1374   TPythonDump pyDump;
1375
1376   // Create Intersection
1377   aResGrp = CreateGroup( theGroup1->GetType(), theName );
1378   if ( aResGrp->_is_nil() )
1379     return aResGrp._retn();
1380
1381   SMESHDS_GroupBase* groupDS1 = 0;
1382   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1383     groupDS1 = grp_i->GetGroupDS();
1384
1385   SMESHDS_GroupBase* groupDS2 = 0;
1386   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1387     groupDS2 = grp_i->GetGroupDS();
1388
1389   SMESHDS_Group* resGroupDS = 0;
1390   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1391     resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1392
1393   if ( groupDS1 && groupDS2 && resGroupDS && !groupDS2->IsEmpty() )
1394   {
1395     SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1396     while ( elemIt1->more() )
1397     {
1398       const SMDS_MeshElement* e = elemIt1->next();
1399       if ( groupDS2->Contains( e ))
1400         resGroupDS->SMDSGroup().Add( e );
1401     }
1402   }
1403   // Update Python script
1404   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".IntersectGroups( "
1405          << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1406
1407   SMESH_CATCH( SMESH::throwCorbaException );
1408
1409   return aResGrp._retn();
1410 }
1411
1412 //=============================================================================
1413 /*!
1414   \brief Intersect list of groups. New group is created. All mesh elements that
1415   are present in all initial groups simultaneously are added to the new one.
1416   \param theGroups list of groups
1417   \param theName name of group to be created
1418   \return pointer on the group
1419 */
1420 //=============================================================================
1421 SMESH::SMESH_Group_ptr
1422 SMESH_Mesh_i::IntersectListOfGroups(const SMESH::ListOfGroups& theGroups,
1423                                     const char*                theName )
1424   throw (SALOME::SALOME_Exception)
1425 {
1426   SMESH::SMESH_Group_var aResGrp;
1427
1428   SMESH_TRY;
1429
1430   if ( _preMeshInfo )
1431     _preMeshInfo->FullLoadFromFile();
1432
1433   if ( !theName )
1434     return SMESH::SMESH_Group::_nil();
1435
1436   // check types and get SMESHDS_GroupBase's
1437   SMESH::ElementType aType = SMESH::ALL;
1438   vector< SMESHDS_GroupBase* > groupVec;
1439   for ( int g = 0, n = theGroups.length(); g < n; g++ )
1440   {
1441     SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
1442     if ( CORBA::is_nil( aGrp ) )
1443       continue;
1444     if ( aType == SMESH::ALL )
1445       aType = aGrp->GetType();
1446     else if ( aType != aGrp->GetType() )
1447       THROW_SALOME_CORBA_EXCEPTION("IntersectListOfGroups(): different group types",
1448                                    SALOME::BAD_PARAM);
1449
1450     if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1451       if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1452       {
1453         if ( grpDS->IsEmpty() )
1454         {
1455           groupVec.clear();
1456           break;
1457         }
1458         groupVec.push_back( grpDS );
1459       }
1460   }
1461   if ( aType == SMESH::ALL ) // all groups are nil
1462     return SMESH::SMESH_Group::_nil();
1463
1464   TPythonDump pyDump;
1465
1466   // Create a group
1467   aResGrp = CreateGroup( aType, theName );
1468
1469   SMESHDS_Group* resGroupDS = 0;
1470   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1471     resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1472   if ( !resGroupDS || groupVec.empty() )
1473     return aResGrp._retn();
1474
1475   // Fill the group
1476   size_t i, nb = groupVec.size();
1477   SMDS_ElemIteratorPtr elemIt1 = groupVec[0]->GetElements();
1478   while ( elemIt1->more() )
1479   {
1480     const SMDS_MeshElement* e = elemIt1->next();
1481     bool inAll = true;
1482     for ( i = 1; ( i < nb && inAll ); ++i )
1483       inAll = groupVec[i]->Contains( e );
1484
1485     if ( inAll )
1486       resGroupDS->SMDSGroup().Add( e );
1487   }
1488
1489   // Update Python script
1490   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1491          << ".IntersectListOfGroups( " << theGroups << ", '" << theName << "' )";
1492
1493   SMESH_CATCH( SMESH::throwCorbaException );
1494
1495   return aResGrp._retn();
1496 }
1497
1498 //=============================================================================
1499 /*!
1500  *  New group is created. All mesh elements that are present in
1501  *  a main group but is not present in a tool group are added to the new one
1502  */
1503 //=============================================================================
1504
1505 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
1506                                                 SMESH::SMESH_GroupBase_ptr theGroup2,
1507                                                 const char*                theName )
1508   throw (SALOME::SALOME_Exception)
1509 {
1510   SMESH::SMESH_Group_var aResGrp;
1511
1512   SMESH_TRY;
1513
1514   if ( _preMeshInfo )
1515     _preMeshInfo->FullLoadFromFile();
1516
1517   if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
1518     THROW_SALOME_CORBA_EXCEPTION("CutGroups(): NULL Group",
1519                                  SALOME::BAD_PARAM);
1520   if ( theGroup1->GetType() != theGroup2->GetType() )
1521     THROW_SALOME_CORBA_EXCEPTION("CutGroups(): different group types",
1522                                  SALOME::BAD_PARAM);
1523   TPythonDump pyDump;
1524
1525   aResGrp = CreateGroup( theGroup1->GetType(), theName );
1526   if ( aResGrp->_is_nil() )
1527     return aResGrp._retn();
1528
1529   SMESHDS_GroupBase* groupDS1 = 0;
1530   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
1531     groupDS1 = grp_i->GetGroupDS();
1532
1533   SMESHDS_GroupBase* groupDS2 = 0;
1534   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
1535     groupDS2 = grp_i->GetGroupDS();
1536
1537   SMESHDS_Group* resGroupDS = 0;
1538   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1539     resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1540
1541   if ( groupDS1 && groupDS2 && resGroupDS )
1542   {
1543     SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
1544     while ( elemIt1->more() )
1545     {
1546       const SMDS_MeshElement* e = elemIt1->next();
1547       if ( !groupDS2->Contains( e ))
1548         resGroupDS->SMDSGroup().Add( e );
1549     }
1550   }
1551   // Update Python script
1552   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".CutGroups( "
1553          << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
1554
1555   SMESH_CATCH( SMESH::throwCorbaException );
1556
1557   return aResGrp._retn();
1558 }
1559
1560 //=============================================================================
1561 /*!
1562   \brief Cut lists of groups. New group is created. All mesh elements that are
1563   present in main groups but do not present in tool groups are added to the new one
1564   \param theMainGroups list of main groups
1565   \param theToolGroups list of tool groups
1566   \param theName name of group to be created
1567   \return pointer on the group
1568 */
1569 //=============================================================================
1570 SMESH::SMESH_Group_ptr
1571 SMESH_Mesh_i::CutListOfGroups(const SMESH::ListOfGroups& theMainGroups,
1572                               const SMESH::ListOfGroups& theToolGroups,
1573                               const char*                theName )
1574   throw (SALOME::SALOME_Exception)
1575 {
1576   SMESH::SMESH_Group_var aResGrp;
1577
1578   SMESH_TRY;
1579
1580   if ( _preMeshInfo )
1581     _preMeshInfo->FullLoadFromFile();
1582
1583   if ( !theName )
1584     return SMESH::SMESH_Group::_nil();
1585
1586   // check types and get SMESHDS_GroupBase's
1587   SMESH::ElementType aType = SMESH::ALL;
1588   vector< SMESHDS_GroupBase* >   toolGroupVec;
1589   vector< SMDS_ElemIteratorPtr > mainIterVec;
1590
1591   for ( int g = 0, n = theMainGroups.length(); g < n; g++ )
1592   {
1593     SMESH::SMESH_GroupBase_var aGrp = theMainGroups[ g ];
1594     if ( CORBA::is_nil( aGrp ) )
1595       continue;
1596     if ( aType == SMESH::ALL )
1597       aType = aGrp->GetType();
1598     else if ( aType != aGrp->GetType() )
1599       THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
1600                                    SALOME::BAD_PARAM);
1601     if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1602       if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1603         if ( !grpDS->IsEmpty() )
1604           mainIterVec.push_back( grpDS->GetElements() );
1605   }
1606   if ( aType == SMESH::ALL ) // all main groups are nil
1607     return SMESH::SMESH_Group::_nil();
1608   if ( mainIterVec.empty() ) // all main groups are empty
1609     return aResGrp._retn();
1610
1611   for ( int g = 0, n = theToolGroups.length(); g < n; g++ )
1612   {
1613     SMESH::SMESH_GroupBase_var aGrp = theToolGroups[ g ];
1614     if ( CORBA::is_nil( aGrp ) )
1615       continue;
1616     if ( aType != aGrp->GetType() )
1617       THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
1618                                    SALOME::BAD_PARAM);
1619     if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
1620       if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
1621         toolGroupVec.push_back( grpDS );
1622   }
1623
1624   TPythonDump pyDump;
1625
1626   // Create a group
1627   aResGrp = CreateGroup( aType, theName );
1628
1629   SMESHDS_Group* resGroupDS = 0;
1630   if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
1631     resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
1632   if ( !resGroupDS )
1633     return aResGrp._retn();
1634
1635   // Fill the group
1636   size_t i, nb = toolGroupVec.size();
1637   SMDS_ElemIteratorPtr mainElemIt
1638     ( new SMDS_IteratorOnIterators
1639       < const SMDS_MeshElement*, vector< SMDS_ElemIteratorPtr > >( mainIterVec ));
1640   while ( mainElemIt->more() )
1641   {
1642     const SMDS_MeshElement* e = mainElemIt->next();
1643     bool isIn = false;
1644     for ( i = 0; ( i < nb && !isIn ); ++i )
1645       isIn = toolGroupVec[i]->Contains( e );
1646
1647     if ( !isIn )
1648       resGroupDS->SMDSGroup().Add( e );
1649   }
1650
1651   // Update Python script
1652   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
1653          << ".CutListOfGroups( " << theMainGroups << ", "
1654          << theToolGroups << ", '" << theName << "' )";
1655
1656   SMESH_CATCH( SMESH::throwCorbaException );
1657
1658   return aResGrp._retn();
1659 }
1660
1661 namespace // functions making checks according to SMESH::NB_COMMON_NODES_ENUM
1662 {
1663   bool isAllNodesCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
1664                         bool & toStopChecking )
1665   {
1666     toStopChecking = ( nbCommon < nbChecked );
1667     return nbCommon == nbNodes;
1668   }
1669   bool isMainNodesCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
1670                          bool & toStopChecking )
1671   {
1672     toStopChecking = ( nbCommon < nbChecked || nbChecked >= nbCorners );
1673     return nbCommon == nbCorners;
1674   }
1675   bool isAtLeastOneNodeCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
1676                               bool & toStopChecking )
1677   {
1678     return nbCommon > 0;
1679   }
1680   bool isMajorityOfNodesCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
1681                                bool & toStopChecking )
1682   {
1683     return nbCommon >= (nbNodes+1) / 2;
1684   }
1685 }
1686
1687 //=============================================================================
1688 /*!
1689  * Create a group of entities basing on nodes of other groups.
1690  *  \param [in] theGroups - list of either groups, sub-meshes or filters.
1691  *  \param [in] anElemType - a type of elements to include to the new group.
1692  *  \param [in] theName - a name of the new group.
1693  *  \param [in] theNbCommonNodes - criterion of inclusion of an element to the new group.
1694  *  \param [in] theUnderlyingOnly - if \c True, an element is included to the
1695  *         new group provided that it is based on nodes of an element of \a aListOfGroups
1696  *  \return SMESH_Group - the created group
1697 */
1698 // IMP 19939, bug 22010, IMP 22635
1699 //=============================================================================
1700
1701 SMESH::SMESH_Group_ptr
1702 SMESH_Mesh_i::CreateDimGroup(const SMESH::ListOfIDSources& theGroups,
1703                              SMESH::ElementType            theElemType,
1704                              const char*                   theName,
1705                              SMESH::NB_COMMON_NODES_ENUM   theNbCommonNodes,
1706                              CORBA::Boolean                theUnderlyingOnly)
1707   throw (SALOME::SALOME_Exception)
1708 {
1709   SMESH::SMESH_Group_var aResGrp;
1710
1711   SMESH_TRY;
1712   if ( _preMeshInfo )
1713     _preMeshInfo->FullLoadFromFile();
1714
1715   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
1716
1717   if ( !theName || !aMeshDS )
1718     return SMESH::SMESH_Group::_nil();
1719
1720   SMDSAbs_ElementType anElemType = (SMDSAbs_ElementType)theElemType;
1721
1722   bool (*isToInclude)(int nbChecked, int nbCommon, int nbNodes, int nbCorners, bool & toStop);
1723   SMESH_Comment nbCoNoStr( "SMESH.");
1724   switch ( theNbCommonNodes ) {
1725   case SMESH::ALL_NODES   : isToInclude = isAllNodesCommon;        nbCoNoStr<<"ALL_NODES"   ;break;
1726   case SMESH::MAIN        : isToInclude = isMainNodesCommon;       nbCoNoStr<<"MAIN"        ;break;
1727   case SMESH::AT_LEAST_ONE: isToInclude = isAtLeastOneNodeCommon;  nbCoNoStr<<"AT_LEAST_ONE";break;
1728   case SMESH::MAJORITY    : isToInclude = isMajorityOfNodesCommon; nbCoNoStr<<"MAJORITY"    ;break;
1729   default: return aResGrp._retn();
1730   }
1731   int nbChecked, nbCommon, nbNodes, nbCorners;
1732
1733   // Create a group
1734
1735   TPythonDump pyDump;
1736
1737   aResGrp = CreateGroup( theElemType, theName );
1738   if ( aResGrp->_is_nil() )
1739     return SMESH::SMESH_Group::_nil();
1740
1741   SMESHDS_GroupBase* groupBaseDS =
1742     SMESH::DownCast<SMESH_GroupBase_i*>( aResGrp )->GetGroupDS();
1743   SMDS_MeshGroup& resGroupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
1744
1745   vector<bool> isNodeInGroups;
1746
1747   for ( int g = 0, n = theGroups.length(); g < n; g++ ) // loop on theGroups
1748   {
1749     SMESH::SMESH_IDSource_var aGrp = theGroups[ g ];
1750     if ( CORBA::is_nil( aGrp ) )
1751       continue;
1752     SMESH::SMESH_Mesh_var mesh = aGrp->GetMesh();
1753     if ( mesh->_is_nil() || mesh->GetId() != this->GetId() )
1754       continue;
1755
1756     SMDS_ElemIteratorPtr elIt = GetElements( aGrp, SMESH::ALL );
1757     if ( !elIt ) continue;
1758
1759     if ( theElemType == SMESH::NODE ) // get all nodes of elements
1760     {
1761       while ( elIt->more() ) {
1762         const SMDS_MeshElement* el = elIt->next();
1763         SMDS_ElemIteratorPtr nIt = el->nodesIterator();
1764         while ( nIt->more() )
1765           resGroupCore.Add( nIt->next() );
1766       }
1767     }
1768     // get elements of theElemType based on nodes of every element of group
1769     else if ( theUnderlyingOnly )
1770     {
1771       while ( elIt->more() )
1772       {
1773         const SMDS_MeshElement* el = elIt->next(); // an element of ref group
1774         TIDSortedElemSet elNodes( el->begin_nodes(), el->end_nodes() );
1775         TIDSortedElemSet checkedElems;
1776         SMDS_NodeIteratorPtr nIt = el->nodeIterator();
1777         while ( nIt->more() )
1778         {
1779           const SMDS_MeshNode* n = nIt->next();
1780           SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
1781           // check nodes of elements of theElemType around el
1782           while ( elOfTypeIt->more() )
1783           {
1784             const SMDS_MeshElement* elOfType = elOfTypeIt->next();
1785             if ( !checkedElems.insert( elOfType ).second ) continue;
1786             nbNodes   = elOfType->NbNodes();
1787             nbCorners = elOfType->NbCornerNodes();
1788             nbCommon  = 0;
1789             bool toStopChecking = false;
1790             SMDS_ElemIteratorPtr nIt2 = elOfType->nodesIterator();
1791             for ( nbChecked = 1; nIt2->more() && !toStopChecking; ++nbChecked )
1792               if ( elNodes.count( nIt2->next() ) &&
1793                    isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
1794               {
1795                 resGroupCore.Add( elOfType );
1796                 break;
1797               }
1798           }
1799         }
1800       }
1801     }
1802     // get all nodes of elements of groups
1803     else
1804     {
1805       while ( elIt->more() )
1806       {
1807         const SMDS_MeshElement* el = elIt->next(); // an element of group
1808         SMDS_NodeIteratorPtr nIt = el->nodeIterator();
1809         while ( nIt->more() )
1810         {
1811           const SMDS_MeshNode* n = nIt->next();
1812           if ( n->GetID() >= (int) isNodeInGroups.size() )
1813             isNodeInGroups.resize( n->GetID() + 1, false );
1814           isNodeInGroups[ n->GetID() ] = true;
1815         }
1816       }
1817     }
1818   }
1819
1820   // Get elements of theElemType based on a certain number of nodes of elements of groups
1821   if ( !theUnderlyingOnly && !isNodeInGroups.empty() )
1822   {
1823     const SMDS_MeshNode* n;
1824     vector<bool> isElemChecked( aMeshDS->MaxElementID() + 1 );
1825     const int isNodeInGroupsSize = isNodeInGroups.size();
1826     for ( int iN = 0; iN < isNodeInGroupsSize; ++iN )
1827     {
1828       if ( !isNodeInGroups[ iN ] ||
1829            !( n = aMeshDS->FindNode( iN )))
1830         continue;
1831
1832       // check nodes of elements of theElemType around n
1833       SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
1834       while ( elOfTypeIt->more() )
1835       {
1836         const SMDS_MeshElement*  elOfType = elOfTypeIt->next();
1837         vector<bool>::reference isChecked = isElemChecked[ elOfType->GetID() ];
1838         if ( isChecked )
1839           continue;
1840         isChecked = true;
1841
1842         nbNodes   = elOfType->NbNodes();
1843         nbCorners = elOfType->NbCornerNodes();
1844         nbCommon  = 0;
1845         bool toStopChecking = false;
1846         SMDS_ElemIteratorPtr nIt = elOfType->nodesIterator();
1847         for ( nbChecked = 1; nIt->more() && !toStopChecking; ++nbChecked )
1848         {
1849           const int nID = nIt->next()->GetID();
1850           if ( nID < isNodeInGroupsSize && isNodeInGroups[ nID ] &&
1851                isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
1852           {
1853             resGroupCore.Add( elOfType );
1854             break;
1855           }
1856         }
1857       }
1858     }
1859   }
1860
1861   // Update Python script
1862   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this())
1863          << ".CreateDimGroup( "
1864          << theGroups << ", " << theElemType << ", '" << theName << "', "
1865          << nbCoNoStr << ", " << theUnderlyingOnly << ")";
1866
1867   SMESH_CATCH( SMESH::throwCorbaException );
1868
1869   return aResGrp._retn();
1870 }
1871
1872 //================================================================================
1873 /*!
1874  * \brief Distribute all faces of the mesh between groups using sharp edges and optionally
1875  *        existing 1D elements as group boundaries.
1876  *  \param [in] theSharpAngle - edge is considered sharp if an angle between normals of
1877  *              adjacent faces is more than \a sharpAngle in degrees.
1878  *  \param [in] theCreateEdges - to create 1D elements for detected sharp edges.
1879  *  \param [in] theUseExistingEdges - to use existing edges as group boundaries
1880  *  \return ListOfGroups - the created groups
1881  */
1882 //================================================================================
1883
1884 SMESH::ListOfGroups*
1885 SMESH_Mesh_i::FaceGroupsSeparatedByEdges( CORBA::Double  theSharpAngle,
1886                                           CORBA::Boolean theCreateEdges,
1887                                           CORBA::Boolean theUseExistingEdges )
1888   throw (SALOME::SALOME_Exception)
1889 {
1890   if ( theSharpAngle < 0 || theSharpAngle > 180 )
1891     THROW_SALOME_CORBA_EXCEPTION("Invalid sharp angle, it must be between 0 and 180 degrees",
1892                                  SALOME::BAD_PARAM);
1893
1894   SMESH::ListOfGroups_var resultGroups = new SMESH::ListOfGroups;
1895
1896   TPythonDump pyDump;
1897
1898   SMESH_TRY;
1899   if ( _preMeshInfo )
1900     _preMeshInfo->FullLoadFromFile();
1901
1902   SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
1903
1904   std::vector< SMESH_MeshAlgos::Edge > edges =
1905     SMESH_MeshAlgos::FindSharpEdges( meshDS, theSharpAngle, theUseExistingEdges );
1906
1907   if ( theCreateEdges )
1908   {
1909     std::vector<const SMDS_MeshNode *> nodes(2);
1910     for ( size_t i = 0; i < edges.size(); ++i )
1911     {
1912       nodes[0] = edges[i]._node1;
1913       nodes[1] = edges[i]._node2;
1914       if ( meshDS->FindElement( nodes, SMDSAbs_Edge ))
1915         continue;
1916       if ( edges[i]._medium )
1917         meshDS->AddEdge( edges[i]._node1, edges[i]._node2, edges[i]._medium );
1918       else
1919         meshDS->AddEdge( edges[i]._node1, edges[i]._node2 );
1920     }
1921   }
1922
1923   std::vector< std::vector< const SMDS_MeshElement* > > faceGroups =
1924     SMESH_MeshAlgos::SeparateFacesByEdges( meshDS, edges );
1925
1926   SMESH::SMESH_MeshEditor_var editor = GetMeshEditor(); // create _editor
1927
1928   resultGroups->length( faceGroups.size() );
1929   for ( size_t iG = 0; iG < faceGroups.size(); ++iG )
1930   {
1931     SMESH::SMESH_Group_var group = CreateGroup( SMESH::FACE,
1932                                                 _editor->GenerateGroupName("Group").c_str());
1933     resultGroups[iG] = SMESH::SMESH_Group::_duplicate( group );
1934
1935     SMESHDS_GroupBase* groupBaseDS =
1936       SMESH::DownCast<SMESH_GroupBase_i*>( group )->GetGroupDS();
1937     SMDS_MeshGroup& groupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
1938
1939     std::vector< const SMDS_MeshElement* >& faces = faceGroups[ iG ];
1940     for ( size_t i = 0; i < faces.size(); ++i )
1941       groupCore.Add( faces[i] );
1942   }
1943
1944   pyDump << resultGroups << " = " << SMESH::SMESH_Mesh_var(_this())
1945          << ".FaceGroupsSeparatedByEdges( "
1946          << TVar( theSharpAngle ) << ", "
1947          << theCreateEdges << ", "
1948          << theUseExistingEdges << " )";
1949
1950   SMESH_CATCH( SMESH::throwCorbaException );
1951   return resultGroups._retn();
1952
1953 }
1954
1955 //================================================================================
1956 /*!
1957  * \brief Remember GEOM group data
1958  */
1959 //================================================================================
1960
1961 void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj,
1962                                     CORBA::Object_ptr     theSmeshObj)
1963 {
1964   if ( CORBA::is_nil( theGeomObj ) || theGeomObj->GetType() != GEOM_GROUP )
1965     return;
1966   // group SO
1967   SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( theGeomObj );
1968   if ( groupSO->_is_nil() )
1969     return;
1970   // group indices
1971   GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
1972   GEOM::GEOM_IGroupOperations_wrap groupOp =
1973     geomGen->GetIGroupOperations();
1974   GEOM::ListOfLong_var ids = groupOp->GetObjects( theGeomObj );
1975
1976   // store data
1977   _geomGroupData.push_back( TGeomGroupData() );
1978   TGeomGroupData & groupData = _geomGroupData.back();
1979   // entry
1980   CORBA::String_var entry = groupSO->GetID();
1981   groupData._groupEntry = entry.in();
1982   // indices
1983   for ( CORBA::ULong i = 0; i < ids->length(); ++i )
1984     groupData._indices.insert( ids[i] );
1985   // SMESH object
1986   groupData._smeshObject = CORBA::Object::_duplicate( theSmeshObj );
1987   // shape index in SMESHDS
1988   // TopoDS_Shape shape = _gen_i->GeomObjectToShape( theGeomObj );
1989   // groupData._dsID = shape.IsNull() ? 0 : _impl->GetSubMesh( shape )->GetId();
1990 }
1991
1992 //================================================================================
1993 /*!
1994  * Remove GEOM group data relating to removed smesh object
1995  */
1996 //================================================================================
1997
1998 void SMESH_Mesh_i::removeGeomGroupData(CORBA::Object_ptr theSmeshObj)
1999 {
2000   list<TGeomGroupData>::iterator
2001     data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2002   for ( ; data != dataEnd; ++data ) {
2003     if ( theSmeshObj->_is_equivalent( data->_smeshObject )) {
2004       _geomGroupData.erase( data );
2005       return;
2006     }
2007   }
2008 }
2009
2010 //================================================================================
2011 /*!
2012  * \brief Return new group contents if it has been changed and update group data
2013  */
2014 //================================================================================
2015
2016 TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData)
2017 {
2018   TopoDS_Shape newShape;
2019
2020   // get geom group
2021   SALOMEDS::SObject_wrap groupSO = SMESH_Gen_i::getStudyServant()->FindObjectID( groupData._groupEntry.c_str() );
2022   if ( !groupSO->_is_nil() )
2023   {
2024     CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO );
2025     if ( CORBA::is_nil( groupObj )) return newShape;
2026     GEOM::GEOM_Object_var geomGroup = GEOM::GEOM_Object::_narrow( groupObj );
2027
2028     // get indices of group items
2029     set<int> curIndices;
2030     GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
2031     GEOM::GEOM_IGroupOperations_wrap groupOp =
2032       geomGen->GetIGroupOperations();
2033     GEOM::ListOfLong_var   ids = groupOp->GetObjects( geomGroup );
2034     for ( CORBA::ULong i = 0; i < ids->length(); ++i )
2035       curIndices.insert( ids[i] );
2036
2037     if ( groupData._indices == curIndices )
2038       return newShape; // group not changed
2039
2040     // update data
2041     groupData._indices = curIndices;
2042
2043     GEOM_Client* geomClient = _gen_i->GetShapeReader();
2044     if ( !geomClient ) return newShape;
2045     CORBA::String_var groupIOR = geomGen->GetStringFromIOR( geomGroup );
2046     geomClient->RemoveShapeFromBuffer( groupIOR.in() );
2047     newShape = _gen_i->GeomObjectToShape( geomGroup );
2048   }
2049
2050   if ( newShape.IsNull() ) {
2051     // geom group becomes empty - return empty compound
2052     TopoDS_Compound compound;
2053     BRep_Builder().MakeCompound(compound);
2054     newShape = compound;
2055   }
2056   return newShape;
2057 }
2058
2059 namespace
2060 {
2061   //-----------------------------------------------------------------------------
2062   /*!
2063    * \brief Storage of shape and index used in CheckGeomGroupModif()
2064    */
2065   struct TIndexedShape
2066   {
2067     int          _index;
2068     TopoDS_Shape _shape;
2069     TIndexedShape( int i, const TopoDS_Shape& s ):_index(i), _shape(s) {}
2070   };
2071   //-----------------------------------------------------------------------------
2072   /*!
2073    * \brief Data to re-create a group on geometry
2074    */
2075   struct TGroupOnGeomData
2076   {
2077     int                 _oldID;
2078     int                 _shapeID;
2079     SMDSAbs_ElementType _type;
2080     std::string         _name;
2081     Quantity_Color      _color;
2082   };
2083 }
2084
2085 //=============================================================================
2086 /*!
2087  * \brief Update data if geometry changes
2088  *
2089  * Issue 0022501
2090  */
2091 //=============================================================================
2092
2093 void SMESH_Mesh_i::CheckGeomModif()
2094 {
2095   if ( !_impl->HasShapeToMesh() ) return;
2096
2097   GEOM::GEOM_Object_var mainGO = _gen_i->ShapeToGeomObject( _impl->GetShapeToMesh() );
2098   //if ( mainGO->_is_nil() ) return;
2099
2100   // Update after group modification
2101
2102   if ( mainGO->_is_nil() || /* shape was removed from GEOM_Client by newGroupShape()
2103                                called by other mesh (IPAL52735) */
2104        mainGO->GetType() == GEOM_GROUP ||
2105        mainGO->GetTick() == _mainShapeTick )
2106   {
2107     CheckGeomGroupModif();
2108     return;
2109   }
2110
2111   // Update after shape transformation like Translate
2112
2113   GEOM_Client* geomClient = _gen_i->GetShapeReader();
2114   if ( !geomClient ) return;
2115   GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
2116   if ( geomGen->_is_nil() ) return;
2117
2118   CORBA::String_var ior = geomGen->GetStringFromIOR( mainGO );
2119   geomClient->RemoveShapeFromBuffer( ior.in() );
2120
2121   // Update data taking into account that
2122   // all sub-shapes change but IDs of sub-shapes remain (except for geom groups)
2123
2124   _impl->Clear();
2125   TopoDS_Shape newShape = _gen_i->GeomObjectToShape( mainGO );
2126   if ( newShape.IsNull() )
2127     return;
2128
2129   _mainShapeTick = mainGO->GetTick();
2130
2131   SMESHDS_Mesh * meshDS = _impl->GetMeshDS();
2132
2133   // store data of groups on geometry
2134   vector< TGroupOnGeomData > groupsData;
2135   const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2136   groupsData.reserve( groups.size() );
2137   set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
2138   for ( ; g != groups.end(); ++g )
2139     if ( const SMESHDS_GroupOnGeom* group = dynamic_cast< SMESHDS_GroupOnGeom* >( *g ))
2140     {
2141       TGroupOnGeomData data;
2142       data._oldID   = group->GetID();
2143       data._shapeID = meshDS->ShapeToIndex( group->GetShape() );
2144       data._type    = group->GetType();
2145       data._name    = group->GetStoreName();
2146       data._color   = group->GetColor();
2147       groupsData.push_back( data );
2148     }
2149   // store assigned hypotheses
2150   vector< pair< int, THypList > > ids2Hyps;
2151   const ShapeToHypothesis & hyps = meshDS->GetHypotheses();
2152   for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() )
2153   {
2154     const TopoDS_Shape& s = s2hyps.Key();
2155     const THypList&  hyps = s2hyps.ChangeValue();
2156     ids2Hyps.push_back( make_pair( meshDS->ShapeToIndex( s ), hyps ));
2157   }
2158
2159   // change shape to mesh
2160   int oldNbSubShapes = meshDS->MaxShapeIndex();
2161   _impl->ShapeToMesh( TopoDS_Shape() );
2162   _impl->ShapeToMesh( newShape );
2163
2164   // re-add shapes of geom groups
2165   list<TGeomGroupData>::iterator data = _geomGroupData.begin();
2166   for ( ; data != _geomGroupData.end(); ++data )
2167   {
2168     TopoDS_Shape newShape = newGroupShape( *data );
2169     if ( !newShape.IsNull() )
2170     {
2171       if ( meshDS->ShapeToIndex( newShape ) > 0 ) // a group reduced to one sub-shape
2172       {
2173         TopoDS_Compound compound;
2174         BRep_Builder().MakeCompound( compound );
2175         BRep_Builder().Add( compound, newShape );
2176         newShape = compound;
2177       }
2178       _impl->GetSubMesh( newShape );
2179     }
2180   }
2181   if ( oldNbSubShapes != meshDS->MaxShapeIndex() )
2182     THROW_SALOME_CORBA_EXCEPTION( "SMESH_Mesh_i::CheckGeomModif() bug",
2183                                   SALOME::INTERNAL_ERROR );
2184
2185   // re-assign hypotheses
2186   for ( size_t i = 0; i < ids2Hyps.size(); ++i )
2187   {
2188     const TopoDS_Shape& s = meshDS->IndexToShape( ids2Hyps[i].first );
2189     const THypList&  hyps = ids2Hyps[i].second;
2190     THypList::const_iterator h = hyps.begin();
2191     for ( ; h != hyps.end(); ++h )
2192       _impl->AddHypothesis( s, (*h)->GetID() );
2193   }
2194
2195   // restore groups
2196   for ( size_t i = 0; i < groupsData.size(); ++i )
2197   {
2198     const TGroupOnGeomData& data = groupsData[i];
2199
2200     map<int, SMESH::SMESH_GroupBase_ptr>::iterator i2g = _mapGroups.find( data._oldID );
2201     if ( i2g == _mapGroups.end() ) continue;
2202
2203     SMESH_GroupBase_i* gr_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2g->second );
2204     if ( !gr_i ) continue;
2205
2206     int id;
2207     SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), id,
2208                                       meshDS->IndexToShape( data._shapeID ));
2209     if ( !g )
2210     {
2211       _mapGroups.erase( i2g );
2212     }
2213     else
2214     {
2215       g->GetGroupDS()->SetColor( data._color );
2216       gr_i->changeLocalId( id );
2217       _mapGroups[ id ] = i2g->second;
2218       if ( data._oldID != id )
2219         _mapGroups.erase( i2g );
2220     }
2221   }
2222
2223   // update _mapSubMesh
2224   map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
2225   for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
2226     i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first ));
2227
2228 }
2229
2230 //=============================================================================
2231 /*!
2232  * \brief Update objects depending on changed geom groups
2233  *
2234  * NPAL16168: geometrical group edition from a submesh don't modify mesh computation
2235  * issue 0020210: Update of a smesh group after modification of the associated geom group
2236  */
2237 //=============================================================================
2238
2239 void SMESH_Mesh_i::CheckGeomGroupModif()
2240 {
2241   if ( !_impl->HasShapeToMesh() ) return;
2242
2243   CORBA::Long nbEntities = NbNodes() + NbElements();
2244
2245   // Check if group contents changed
2246
2247   typedef map< string, TopoDS_Shape > TEntry2Geom;
2248   TEntry2Geom newGroupContents;
2249
2250   list<TGeomGroupData>::iterator
2251     data = _geomGroupData.begin(), dataEnd = _geomGroupData.end();
2252   for ( ; data != dataEnd; ++data )
2253   {
2254     pair< TEntry2Geom::iterator, bool > it_new =
2255       newGroupContents.insert( make_pair( data->_groupEntry, TopoDS_Shape() ));
2256     bool processedGroup    = !it_new.second;
2257     TopoDS_Shape& newShape = it_new.first->second;
2258     if ( !processedGroup )
2259       newShape = newGroupShape( *data );
2260     if ( newShape.IsNull() )
2261       continue; // no changes
2262
2263     if ( _preMeshInfo )
2264       _preMeshInfo->ForgetOrLoad();
2265
2266     if ( processedGroup ) { // update group indices
2267       list<TGeomGroupData>::iterator data2 = data;
2268       for ( --data2; data2->_groupEntry != data->_groupEntry; --data2) {}
2269       data->_indices = data2->_indices;
2270     }
2271
2272     // Update SMESH objects according to new GEOM group contents
2273
2274     SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow( data->_smeshObject );
2275     if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
2276     {
2277       int oldID = submesh->GetId();
2278       if ( !_mapSubMeshIor.count( oldID ))
2279         continue;
2280       TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
2281
2282       // update hypotheses
2283       list <const SMESHDS_Hypothesis * > hyps = _impl->GetHypothesisList(oldShape);
2284       list <const SMESHDS_Hypothesis * >::iterator hypIt;
2285       for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2286       {
2287         _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2288         _impl->AddHypothesis   ( newShape, (*hypIt)->GetID());
2289       }
2290       // care of submeshes
2291       SMESH_subMesh* newSubmesh = _impl->GetSubMesh( newShape );
2292       int newID = newSubmesh->GetId();
2293       if ( newID != oldID ) {
2294         _mapSubMesh   [ newID ] = newSubmesh;
2295         _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2296         _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2297         _mapSubMesh.   erase(oldID);
2298         _mapSubMesh_i. erase(oldID);
2299         _mapSubMeshIor.erase(oldID);
2300         _mapSubMesh_i [ newID ]->changeLocalId( newID );
2301       }
2302       continue;
2303     }
2304
2305     SMESH::SMESH_GroupOnGeom_var smeshGroup =
2306       SMESH::SMESH_GroupOnGeom::_narrow( data->_smeshObject );
2307     if ( !smeshGroup->_is_nil() ) // ------------ GROUP -----------------------
2308     {
2309       SMESH_GroupOnGeom_i* group_i = SMESH::DownCast<SMESH_GroupOnGeom_i*>( smeshGroup );
2310       if ( group_i ) {
2311         ::SMESH_Group* group = _impl->GetGroup( group_i->GetLocalID() );
2312         SMESHDS_GroupOnGeom* ds = static_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() );
2313         ds->SetShape( newShape );
2314       }
2315       continue;
2316     }
2317
2318     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( data->_smeshObject );
2319     if ( !mesh->_is_nil() ) // -------------- MESH ----------------------------
2320     {
2321       // Remove groups and submeshes basing on removed sub-shapes
2322
2323       TopTools_MapOfShape newShapeMap;
2324       TopoDS_Iterator shapeIt( newShape );
2325       for ( ; shapeIt.More(); shapeIt.Next() )
2326         newShapeMap.Add( shapeIt.Value() );
2327
2328       SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
2329       for ( shapeIt.Initialize( meshDS->ShapeToMesh() ); shapeIt.More(); shapeIt.Next() )
2330       {
2331         if ( newShapeMap.Contains( shapeIt.Value() ))
2332           continue;
2333         TopTools_IndexedMapOfShape oldShapeMap;
2334         TopExp::MapShapes( shapeIt.Value(), oldShapeMap );
2335         for ( int i = 1; i <= oldShapeMap.Extent(); ++i )
2336         {
2337           const TopoDS_Shape& oldShape = oldShapeMap(i);
2338           int oldInd = meshDS->ShapeToIndex( oldShape );
2339           // -- submeshes --
2340           map<int, SMESH::SMESH_subMesh_ptr>::iterator i_smIor = _mapSubMeshIor.find( oldInd );
2341           if ( i_smIor != _mapSubMeshIor.end() ) {
2342             RemoveSubMesh( i_smIor->second ); // one submesh per shape index
2343           }
2344           // --- groups ---
2345           map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_grp = _mapGroups.begin();
2346           for ( ; i_grp != _mapGroups.end(); ++i_grp )
2347           {
2348             // check if a group bases on oldInd shape
2349             SMESHDS_GroupOnGeom* grpOnGeom = 0;
2350             if ( ::SMESH_Group* g = _impl->GetGroup( i_grp->first ))
2351               grpOnGeom = dynamic_cast<SMESHDS_GroupOnGeom*>( g->GetGroupDS() );
2352             if ( grpOnGeom && oldShape.IsSame( grpOnGeom->GetShape() ))
2353             { // remove
2354               RemoveGroup( i_grp->second ); // several groups can base on same shape
2355               i_grp = _mapGroups.begin(); // _mapGroups changed - restart iteration
2356             }
2357           }
2358         }
2359       }
2360       // Reassign hypotheses and update groups after setting the new shape to mesh
2361
2362       // collect anassigned hypotheses
2363       typedef list< pair< TIndexedShape, list<const SMESHDS_Hypothesis*> > > TShapeHypList;
2364       list <const SMESHDS_Hypothesis * >::const_iterator hypIt;
2365       TShapeHypList assignedHyps;
2366       for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i )
2367       {
2368         const TopoDS_Shape& oldShape = meshDS->IndexToShape(i);
2369         list<const SMESHDS_Hypothesis*> hyps = meshDS->GetHypothesis( oldShape );// copy
2370         if ( !hyps.empty() ) {
2371           assignedHyps.push_back( make_pair( TIndexedShape(i,oldShape), hyps ));
2372           for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2373             _impl->RemoveHypothesis( oldShape, (*hypIt)->GetID());
2374         }
2375       }
2376       // collect shapes supporting groups
2377       typedef list < pair< TIndexedShape, SMDSAbs_ElementType > > TShapeTypeList;
2378       TShapeTypeList groupData;
2379       const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
2380       set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
2381       for ( ; grIt != groups.end(); ++grIt )
2382       {
2383         if ( SMESHDS_GroupOnGeom* gog = dynamic_cast<SMESHDS_GroupOnGeom*>( *grIt ))
2384           groupData.push_back
2385             ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
2386       }
2387       // set new shape to mesh -> DS of sub-meshes and geom groups are deleted
2388       _impl->Clear();
2389       _impl->ShapeToMesh( TopoDS_Shape() ); // IPAL52730
2390       _impl->ShapeToMesh( newShape );
2391
2392       // reassign hypotheses
2393       TShapeHypList::iterator indS_hyps = assignedHyps.begin();
2394       for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
2395       {
2396         TIndexedShape&                   geom = indS_hyps->first;
2397         list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
2398         int oldID = geom._index;
2399         int newID = meshDS->ShapeToIndex( geom._shape );
2400         if ( oldID == 1 ) { // main shape
2401           newID = 1;
2402           geom._shape = newShape;
2403         }
2404         if ( !newID )
2405           continue;
2406         for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
2407           _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
2408         // care of sub-meshes
2409         SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
2410         if ( newID != oldID ) {
2411           _mapSubMesh   [ newID ] = newSubmesh;
2412           _mapSubMesh_i [ newID ] = _mapSubMesh_i [ oldID ];
2413           _mapSubMeshIor[ newID ] = _mapSubMeshIor[ oldID ];
2414           _mapSubMesh.   erase(oldID);
2415           _mapSubMesh_i. erase(oldID);
2416           _mapSubMeshIor.erase(oldID);
2417           _mapSubMesh_i [ newID ]->changeLocalId( newID );
2418         }
2419       }
2420       // recreate groups
2421       TShapeTypeList::iterator geomType = groupData.begin();
2422       for ( ; geomType != groupData.end(); ++geomType )
2423       {
2424         const TIndexedShape& geom = geomType->first;
2425         int oldID = geom._index;
2426         if ( _mapGroups.find( oldID ) == _mapGroups.end() )
2427           continue;
2428         // get group name
2429         SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( _mapGroups[oldID] );
2430         CORBA::String_var      name    = groupSO->GetName();
2431         // update
2432         if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID]))
2433           if ( SMESH_Group* group = _impl->AddGroup( geomType->second, name.in(),
2434                                                      /*id=*/-1, geom._shape ))
2435             group_i->changeLocalId( group->GetID() );
2436       }
2437
2438       break; // everything has been updated
2439
2440     } // update mesh
2441   } // loop on group data
2442
2443   // Update icons
2444
2445   CORBA::Long newNbEntities = NbNodes() + NbElements();
2446   list< SALOMEDS::SObject_wrap > soToUpdateIcons;
2447   if ( newNbEntities != nbEntities )
2448   {
2449     // Add all SObjects with icons to soToUpdateIcons
2450     soToUpdateIcons.push_back( _gen_i->ObjectToSObject( _this() )); // mesh
2451
2452     for (map<int, SMESH::SMESH_subMesh_ptr>::iterator i_sm = _mapSubMeshIor.begin();
2453          i_sm != _mapSubMeshIor.end(); ++i_sm ) // submeshes
2454       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_sm->second ));
2455
2456     for ( map<int, SMESH::SMESH_GroupBase_ptr>::iterator i_gr = _mapGroups.begin();
2457           i_gr != _mapGroups.end(); ++i_gr ) // groups
2458       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( i_gr->second ));
2459   }
2460
2461   list< SALOMEDS::SObject_wrap >::iterator so = soToUpdateIcons.begin();
2462   for ( ; so != soToUpdateIcons.end(); ++so )
2463     _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
2464 }
2465
2466 //=============================================================================
2467 /*!
2468  * \brief Create standalone group from a group on geometry or filter
2469  */
2470 //=============================================================================
2471
2472 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase_ptr theGroup )
2473   throw (SALOME::SALOME_Exception)
2474 {
2475   SMESH::SMESH_Group_var aGroup;
2476
2477   SMESH_TRY;
2478
2479   if ( _preMeshInfo )
2480     _preMeshInfo->FullLoadFromFile();
2481
2482   if ( theGroup->_is_nil() )
2483     return aGroup._retn();
2484
2485   SMESH_GroupBase_i* aGroupToRem = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
2486   if ( !aGroupToRem )
2487     return aGroup._retn();
2488
2489   const bool isOnFilter = ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ));
2490
2491   const int anId = aGroupToRem->GetLocalID();
2492   if ( !_impl->ConvertToStandalone( anId ) )
2493     return aGroup._retn();
2494   removeGeomGroupData( theGroup );
2495
2496   SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2497
2498   // remove old instance of group from own map
2499   { SMESH::SMESH_GroupBase_var var( _mapGroups[anId] ); } // decref CORBA object
2500   _mapGroups.erase( anId );
2501
2502   SALOMEDS::StudyBuilder_var builder;
2503   SALOMEDS::SObject_wrap     aGroupSO;
2504   SALOMEDS::Study_var        aStudy = SMESH_Gen_i::getStudyServant();
2505   if ( !aStudy->_is_nil() ) {
2506     builder  = aStudy->NewBuilder();
2507     aGroupSO = _gen_i->ObjectToSObject( theGroup );
2508     if ( !aGroupSO->_is_nil() )
2509     {
2510       // remove reference to geometry
2511       SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO);
2512       for ( ; chItr->More(); chItr->Next() )
2513         // Remove group's child SObject
2514         builder->RemoveObject( chItr->Value() );
2515
2516       // Update Python script
2517       TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this())
2518                     << ".ConvertToStandalone( " << aGroupSO << " )";
2519
2520       // change icon of Group on Filter
2521       if ( isOnFilter )
2522       {
2523         SMESH::array_of_ElementType_var elemTypes = aGroupImpl->GetTypes();
2524         const int isEmpty = ( elemTypes->length() == 0 );
2525         if ( !isEmpty )
2526         {
2527           SALOMEDS::GenericAttribute_wrap anAttr =
2528             builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
2529           SALOMEDS::AttributePixMap_wrap pm = anAttr;
2530           pm->SetPixMap( "ICON_SMESH_TREE_GROUP" );
2531         }
2532       }
2533     }
2534   }
2535
2536   // remember new group in own map
2537   aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
2538   _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2539
2540   // register CORBA object for persistence
2541   _gen_i->RegisterObject( aGroup );
2542
2543   CORBA::String_var ior = _gen_i->GetORB()->object_to_string( aGroup );
2544   builder->SetIOR( aGroupSO, ior.in() ); //  == aGroup->Register();
2545   //aGroup->Register();
2546   aGroupToRem->UnRegister();
2547
2548   SMESH_CATCH( SMESH::throwCorbaException );
2549
2550   return aGroup._retn();
2551 }
2552
2553 //=============================================================================
2554 /*!
2555  *
2556  */
2557 //=============================================================================
2558
2559 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
2560 {
2561   if(MYDEBUG) MESSAGE( "createSubMesh" );
2562   TopoDS_Shape  myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
2563   ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
2564   int               subMeshId = 0;
2565
2566   SMESH_subMesh_i * subMeshServant;
2567   if ( mySubMesh )
2568   {
2569     subMeshId = mySubMesh->GetId();
2570     subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
2571   }
2572   else // "invalid sub-mesh"
2573   {
2574     // The invalid sub-mesh is created for the case where a valid sub-shape not found
2575     // by SMESH_Gen_i::CopyMeshWithGeom(). The invalid sub-mesh has GetId() < 0.
2576     if ( _mapSubMesh.empty() )
2577       subMeshId = -1;
2578     else
2579       subMeshId = _mapSubMesh.begin()->first - 1;
2580     subMeshServant = new SMESH_Invalid_subMesh_i(myPOA, _gen_i, this, subMeshId, theSubShapeObject);
2581   }
2582
2583   SMESH::SMESH_subMesh_var subMesh = subMeshServant->_this();
2584
2585   _mapSubMesh   [subMeshId] = mySubMesh;
2586   _mapSubMesh_i [subMeshId] = subMeshServant;
2587   _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate( subMesh );
2588
2589   subMeshServant->Register();
2590
2591   // register CORBA object for persistence
2592   int nextId = _gen_i->RegisterObject( subMesh );
2593   if(MYDEBUG) { MESSAGE( "Add submesh to map with id = "<< nextId); }
2594   else        { nextId = 0; } // avoid "unused variable" warning
2595
2596   // to track changes of GEOM groups
2597   if ( subMeshId > 0 )
2598     addGeomGroupData( theSubShapeObject, subMesh );
2599
2600   return subMesh._retn();
2601 }
2602
2603 //=======================================================================
2604 //function : getSubMesh
2605 //purpose  :
2606 //=======================================================================
2607
2608 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
2609 {
2610   map<int, SMESH::SMESH_subMesh_ptr>::iterator it = _mapSubMeshIor.find( shapeID );
2611   if ( it == _mapSubMeshIor.end() )
2612     return SMESH::SMESH_subMesh::_nil();
2613
2614   return SMESH::SMESH_subMesh::_duplicate( (*it).second );
2615 }
2616
2617 //=============================================================================
2618 /*!
2619  *
2620  */
2621 //=============================================================================
2622
2623 bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
2624                                   GEOM::GEOM_Object_ptr    theSubShapeObject )
2625 {
2626   bool isHypChanged = false;
2627   if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
2628     return isHypChanged;
2629
2630   const int subMeshId = theSubMesh->GetId();
2631
2632   if ( theSubShapeObject->_is_nil() )  // not published shape (IPAL13617)
2633   {
2634     if ( _mapSubMesh.find( subMeshId ) != _mapSubMesh.end() &&
2635          _mapSubMesh[ subMeshId ])
2636     {
2637       TopoDS_Shape S = _mapSubMesh[ subMeshId ]->GetSubShape();
2638       if ( !S.IsNull() )
2639       {
2640         list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
2641         isHypChanged = !hyps.empty();
2642         list<const SMESHDS_Hypothesis*>::const_iterator hyp = hyps.begin();
2643         for ( ; hyp != hyps.end(); ++hyp )
2644           _impl->RemoveHypothesis(S, (*hyp)->GetID());
2645       }
2646     }
2647   }
2648   else
2649   {
2650     try {
2651       SMESH::ListOfHypothesis_var aHypList = GetHypothesisList( theSubShapeObject );
2652       isHypChanged = ( aHypList->length() > 0 );
2653       for ( int i = 0, n = aHypList->length(); i < n; i++ ) {
2654         removeHypothesis( theSubShapeObject, aHypList[i] );
2655       }
2656     }
2657     catch( const SALOME::SALOME_Exception& ) {
2658       INFOS("SMESH_Mesh_i::removeSubMesh(): exception caught!");
2659     }
2660     removeGeomGroupData( theSubShapeObject );
2661   }
2662
2663   // remove a servant
2664   std::map<int, SMESH_subMesh_i*>::iterator id_smi = _mapSubMesh_i.find( subMeshId );
2665   if ( id_smi != _mapSubMesh_i.end() )
2666     id_smi->second->UnRegister();
2667
2668   // remove a CORBA object
2669   std::map<int, SMESH::SMESH_subMesh_ptr>::iterator id_smptr = _mapSubMeshIor.find( subMeshId );
2670   if ( id_smptr != _mapSubMeshIor.end() )
2671     SMESH::SMESH_subMesh_var( id_smptr->second );
2672
2673   _mapSubMesh.erase(subMeshId);
2674   _mapSubMesh_i.erase(subMeshId);
2675   _mapSubMeshIor.erase(subMeshId);
2676
2677   return isHypChanged;
2678 }
2679
2680 //=============================================================================
2681 /*!
2682  *
2683  */
2684 //=============================================================================
2685
2686 SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType        theElemType,
2687                                                       const char*               theName,
2688                                                       const int                 theID,
2689                                                       const TopoDS_Shape&       theShape,
2690                                                       const SMESH_PredicatePtr& thePredicate )
2691 {
2692   std::string newName;
2693   if ( !theName || !theName[0] )
2694   {
2695     std::set< std::string > presentNames;
2696     std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
2697     for ( ; i_gr != _mapGroups.end(); ++i_gr )
2698     {
2699       CORBA::String_var name = i_gr->second->GetName();
2700       presentNames.insert( name.in() );
2701     }
2702     do {
2703       newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
2704     } while ( !presentNames.insert( newName ).second );
2705     theName = newName.c_str();
2706   }
2707   SMESH::SMESH_GroupBase_var aGroup;
2708   if ( SMESH_Group* g = _impl->AddGroup( (SMDSAbs_ElementType)theElemType, theName,
2709                                          theID, theShape, thePredicate ))
2710   {
2711     int anId = g->GetID();
2712     SMESH_GroupBase_i* aGroupImpl;
2713     if ( !theShape.IsNull() )
2714       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
2715     else if ( thePredicate )
2716       aGroupImpl = new SMESH_GroupOnFilter_i( SMESH_Gen_i::GetPOA(), this, anId );
2717     else
2718       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
2719
2720     aGroup = aGroupImpl->_this();
2721     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
2722     aGroupImpl->Register();
2723
2724     // register CORBA object for persistence
2725     int nextId = _gen_i->RegisterObject( aGroup );
2726     if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
2727     else        { nextId = ( nextId > 0 ); } // avoid "unused variable" warning in release mode
2728
2729     // to track changes of GEOM groups
2730     if ( !theShape.IsNull() ) {
2731       GEOM::GEOM_Object_var geom = _gen_i->ShapeToGeomObject( theShape );
2732       addGeomGroupData( geom, aGroup );
2733     }
2734   }
2735   return aGroup._retn();
2736 }
2737
2738 //=============================================================================
2739 /*!
2740  * SMESH_Mesh_i::removeGroup
2741  *
2742  * Should be called by ~SMESH_Group_i()
2743  */
2744 //=============================================================================
2745
2746 void SMESH_Mesh_i::removeGroup( const int theId )
2747 {
2748   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
2749   if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
2750     SMESH::SMESH_GroupBase_var group = _mapGroups[theId];
2751     _mapGroups.erase( theId );
2752     removeGeomGroupData( group );
2753     if ( !_impl->RemoveGroup( theId ))
2754     {
2755       // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
2756       RemoveGroup( group );
2757     }
2758     group->UnRegister();
2759   }
2760 }
2761
2762 //=============================================================================
2763 /*!
2764  *
2765  */
2766 //=============================================================================
2767
2768 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
2769   throw(SALOME::SALOME_Exception)
2770 {
2771   SMESH::log_array_var aLog;
2772
2773   SMESH_TRY;
2774   if ( _preMeshInfo )
2775     _preMeshInfo->FullLoadFromFile();
2776
2777   list < SMESHDS_Command * >logDS = _impl->GetLog();
2778   aLog = new SMESH::log_array;
2779   int indexLog = 0;
2780   int lg = logDS.size();
2781   SCRUTE(lg);
2782   aLog->length(lg);
2783   list < SMESHDS_Command * >::iterator its = logDS.begin();
2784   while(its != logDS.end()){
2785     SMESHDS_Command *com = *its;
2786     int comType = com->GetType();
2787     //SCRUTE(comType);
2788     int lgcom = com->GetNumber();
2789     //SCRUTE(lgcom);
2790     const list < int >&intList = com->GetIndexes();
2791     int inum = intList.size();
2792     //SCRUTE(inum);
2793     list < int >::const_iterator ii = intList.begin();
2794     const list < double >&coordList = com->GetCoords();
2795     int rnum = coordList.size();
2796     //SCRUTE(rnum);
2797     list < double >::const_iterator ir = coordList.begin();
2798     aLog[indexLog].commandType = comType;
2799     aLog[indexLog].number = lgcom;
2800     aLog[indexLog].coords.length(rnum);
2801     aLog[indexLog].indexes.length(inum);
2802     for(int i = 0; i < rnum; i++){
2803       aLog[indexLog].coords[i] = *ir;
2804       //MESSAGE(" "<<i<<" "<<ir.Value());
2805       ir++;
2806     }
2807     for(int i = 0; i < inum; i++){
2808       aLog[indexLog].indexes[i] = *ii;
2809       //MESSAGE(" "<<i<<" "<<ii.Value());
2810       ii++;
2811     }
2812     indexLog++;
2813     its++;
2814   }
2815   if(clearAfterGet)
2816     _impl->ClearLog();
2817
2818   SMESH_CATCH( SMESH::throwCorbaException );
2819
2820   return aLog._retn();
2821 }
2822
2823
2824 //=============================================================================
2825 /*!
2826  *
2827  */
2828 //=============================================================================
2829
2830 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
2831 {
2832   SMESH_TRY;
2833   _impl->ClearLog();
2834   SMESH_CATCH( SMESH::throwCorbaException );
2835 }
2836
2837 //=============================================================================
2838 /*!
2839  *
2840  */
2841 //=============================================================================
2842
2843 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
2844 {
2845   return _id;
2846 }
2847
2848 //=============================================================================
2849 namespace
2850 {
2851   //!< implementation of struct used to call methods of SMESH_Mesh_i from SMESH_Mesh
2852   // issue 0020918: groups removal is caused by hyp modification
2853   // issue 0021208: to forget not loaded mesh data at hyp modification
2854   struct TCallUp_i : public SMESH_Mesh::TCallUp
2855   {
2856     SMESH_Mesh_i* _mesh;
2857     TCallUp_i(SMESH_Mesh_i* mesh):_mesh(mesh) {}
2858     virtual void RemoveGroup (const int theGroupID) { _mesh->removeGroup( theGroupID ); }
2859     virtual void HypothesisModified (int theHypID)  { _mesh->onHypothesisModified( theHypID ); }
2860     virtual void Load ()                            { _mesh->Load(); }
2861   };
2862 }
2863
2864 //================================================================================
2865 /*!
2866  * \brief callback from _impl to forget not loaded mesh data (issue 0021208)
2867  */
2868 //================================================================================
2869
2870 void SMESH_Mesh_i::onHypothesisModified(int theHypID)
2871 {
2872   if ( _preMeshInfo )
2873     _preMeshInfo->ForgetOrLoad();
2874
2875   SMESH::SMESH_Mesh_var mesh = _this();
2876   _gen_i->UpdateIcons( mesh );
2877
2878   // mark a hypothesis as valid after edition
2879   SALOMEDS::SComponent_wrap smeshComp = _gen_i->PublishComponent();
2880   SALOMEDS::SObject_wrap hypRoot;
2881   if ( !smeshComp->_is_nil() && 
2882        smeshComp->FindSubObject( _gen_i->GetHypothesisRootTag(), hypRoot.inout() ))
2883   {
2884     SALOMEDS::ChildIterator_wrap anIter = _gen_i->getStudyServant()->NewChildIterator( hypRoot );
2885     for ( ; anIter->More(); anIter->Next() )
2886     {
2887       SALOMEDS::SObject_wrap    hypSO = anIter->Value();
2888       CORBA::Object_var           obj = _gen_i->SObjectToObject( hypSO );
2889       SMESH::SMESH_Hypothesis_var hyp = SMESH::SMESH_Hypothesis::_narrow( obj );
2890       if ( !hyp->_is_nil() && hyp->GetId() == theHypID )
2891         _gen_i->HighLightInvalid( hyp, false );
2892     }
2893   }
2894 }
2895
2896 //=============================================================================
2897 /*!
2898  *
2899  */
2900 //=============================================================================
2901
2902 void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
2903 {
2904   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::SetImpl");
2905   _impl = impl;
2906   if ( _impl )
2907     _impl->SetCallUp( new TCallUp_i(this));
2908 }
2909
2910 //=============================================================================
2911 /*!
2912  *
2913  */
2914 //=============================================================================
2915
2916 ::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
2917 {
2918   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetImpl()");
2919   return *_impl;
2920 }
2921
2922 //=============================================================================
2923 /*!
2924  * Return mesh editor
2925  */
2926 //=============================================================================
2927
2928 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
2929   throw (SALOME::SALOME_Exception)
2930 {
2931   SMESH::SMESH_MeshEditor_var aMeshEdVar;
2932
2933   SMESH_TRY;
2934   if ( _preMeshInfo )
2935     _preMeshInfo->FullLoadFromFile();
2936
2937   // Create MeshEditor
2938   if ( !_editor )
2939     _editor = new SMESH_MeshEditor_i( this, false );
2940   aMeshEdVar = _editor->_this();
2941
2942   // Update Python script
2943   TPythonDump() << _editor << " = "
2944                 << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshEditor()";
2945
2946   SMESH_CATCH( SMESH::throwCorbaException );
2947
2948   return aMeshEdVar._retn();
2949 }
2950
2951 //=============================================================================
2952 /*!
2953  * Return mesh edition previewer
2954  */
2955 //=============================================================================
2956
2957 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
2958   throw (SALOME::SALOME_Exception)
2959 {
2960   SMESH::SMESH_MeshEditor_var aMeshEdVar;
2961
2962   SMESH_TRY;
2963   if ( _preMeshInfo )
2964     _preMeshInfo->FullLoadFromFile();
2965
2966   if ( !_previewEditor )
2967     _previewEditor = new SMESH_MeshEditor_i( this, true );
2968   aMeshEdVar = _previewEditor->_this();
2969
2970   SMESH_CATCH( SMESH::throwCorbaException );
2971
2972   return aMeshEdVar._retn();
2973 }
2974
2975 //================================================================================
2976 /*!
2977  * \brief Return true if the mesh has been edited since a last total re-compute
2978  *        and those modifications may prevent successful partial re-compute
2979  */
2980 //================================================================================
2981
2982 CORBA::Boolean SMESH_Mesh_i::HasModificationsToDiscard() throw(SALOME::SALOME_Exception)
2983 {
2984   Unexpect aCatch(SALOME_SalomeException);
2985   return _impl->HasModificationsToDiscard();
2986 }
2987
2988 //================================================================================
2989 /*!
2990  * \brief Returns a random unique color
2991  */
2992 //================================================================================
2993
2994 static SALOMEDS::Color getUniqueColor( const std::list<SALOMEDS::Color>& theReservedColors )
2995 {
2996   const int MAX_ATTEMPTS = 100;
2997   int cnt = 0;
2998   double tolerance = 0.5;
2999   SALOMEDS::Color col;
3000
3001   bool ok = false;
3002   while ( !ok ) {
3003     // generate random color
3004     double red    = (double)rand() / RAND_MAX;
3005     double green  = (double)rand() / RAND_MAX;
3006     double blue   = (double)rand() / RAND_MAX;
3007     // check existence in the list of the existing colors
3008     bool matched = false;
3009     std::list<SALOMEDS::Color>::const_iterator it;
3010     for ( it = theReservedColors.begin(); it != theReservedColors.end() && !matched; ++it ) {
3011       SALOMEDS::Color color = *it;
3012       double tol = fabs( color.R - red ) + fabs( color.G - green ) + fabs( color.B  - blue  );
3013       matched = tol < tolerance;
3014     }
3015     if ( (cnt+1) % 20 == 0 ) tolerance = tolerance/2;
3016     ok = ( ++cnt == MAX_ATTEMPTS ) || !matched;
3017     col.R = red;
3018     col.G = green;
3019     col.B = blue;
3020   }
3021   return col;
3022 }
3023
3024 //=============================================================================
3025 /*!
3026  * Sets auto-color mode. If it is on, groups get unique random colors
3027  */
3028 //=============================================================================
3029
3030 void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOME_Exception)
3031 {
3032   Unexpect aCatch(SALOME_SalomeException);
3033   _impl->SetAutoColor(theAutoColor);
3034
3035   TPythonDump pyDump; // not to dump group->SetColor() from below code
3036   pyDump << SMESH::SMESH_Mesh_var(_this()) <<".SetAutoColor( "<<theAutoColor<<" )";
3037
3038   std::list<SALOMEDS::Color> aReservedColors;
3039   map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
3040   for ( ; it != _mapGroups.end(); it++ ) {
3041     if ( CORBA::is_nil( it->second )) continue;
3042     SALOMEDS::Color aColor = getUniqueColor( aReservedColors );
3043     it->second->SetColor( aColor );
3044     aReservedColors.push_back( aColor );
3045   }
3046 }
3047
3048 //=============================================================================
3049 /*!
3050  * Returns true if auto-color mode is on
3051  */
3052 //=============================================================================
3053
3054 CORBA::Boolean SMESH_Mesh_i::GetAutoColor() throw(SALOME::SALOME_Exception)
3055 {
3056   Unexpect aCatch(SALOME_SalomeException);
3057   return _impl->GetAutoColor();
3058 }
3059
3060 //=============================================================================
3061 /*!
3062  *  Checks if there are groups with equal names
3063  */
3064 //=============================================================================
3065
3066 CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
3067 {
3068   return _impl->HasDuplicatedGroupNamesMED();
3069 }
3070
3071 //================================================================================
3072 /*!
3073  * \brief Care of a file before exporting mesh into it
3074  */
3075 //================================================================================
3076
3077 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
3078 {
3079   SMESH_File aFile( file );
3080   SMESH_Comment msg;
3081   if (aFile.exists()) {
3082     // existing filesystem node
3083     if ( !aFile.isDirectory() ) {
3084       if ( aFile.openForWriting() ) {
3085         if ( overwrite && ! aFile.remove()) {
3086           msg << "Can't replace " << aFile.getName();
3087         }
3088       } else {
3089         msg << "Can't write into " << aFile.getName();
3090       }
3091     } else {
3092       msg << "Location " << aFile.getName() << " is not a file";
3093     }
3094   }
3095   else {
3096     // nonexisting file; check if it can be created
3097     if ( !aFile.openForWriting() ) {
3098       msg << "You cannot create the file "
3099           << aFile.getName()
3100           << ". Check the directory existence and access rights";
3101     }
3102     aFile.remove();
3103   }
3104
3105   if ( !msg.empty() )
3106   {
3107     msg << ".";
3108     THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::BAD_PARAM);
3109   }
3110 }
3111
3112 //================================================================================
3113 /*!
3114  * \brief Prepares a file for export and pass names of mesh groups from study to mesh DS
3115  *  \param file - file name
3116  *  \param overwrite - to erase the file or not
3117  *  \retval string - mesh name
3118  */
3119 //================================================================================
3120
3121 string SMESH_Mesh_i::prepareMeshNameAndGroups(const char*    file,
3122                                               CORBA::Boolean overwrite)
3123 {
3124   // Perform Export
3125   PrepareForWriting(file, overwrite);
3126   string aMeshName = "Mesh";
3127   SALOMEDS::Study_var aStudy = SMESH_Gen_i::getStudyServant();
3128   if ( !aStudy->_is_nil() ) {
3129     SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject(  _this() );
3130     if ( !aMeshSO->_is_nil() ) {
3131       CORBA::String_var name = aMeshSO->GetName();
3132       aMeshName = name;
3133       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
3134       if ( !aStudy->GetProperties()->IsLocked() )
3135       {
3136         SALOMEDS::GenericAttribute_wrap anAttr;
3137         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
3138         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
3139         SALOMEDS::AttributeExternalFileDef_wrap aFileName = anAttr;
3140         ASSERT(!aFileName->_is_nil());
3141         aFileName->SetValue(file);
3142         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
3143         SALOMEDS::AttributeFileType_wrap aFileType = anAttr;
3144         ASSERT(!aFileType->_is_nil());
3145         aFileType->SetValue("FICHIERMED");
3146       }
3147     }
3148   }
3149   // Update Python script
3150   // set name of mesh before export
3151   TPythonDump() << _gen_i << ".SetName("
3152                 << SMESH::SMESH_Mesh_var(_this()) << ", '" << aMeshName.c_str() << "')";
3153
3154   // check names of groups
3155   checkGroupNames();
3156
3157   return aMeshName;
3158 }
3159
3160 //================================================================================
3161 /*!
3162  * \brief Export to MED file
3163  */
3164 //================================================================================
3165
3166 void SMESH_Mesh_i::ExportMED(const char*        file,
3167                              CORBA::Boolean     auto_groups,
3168                              CORBA::Long        version,
3169                              CORBA::Boolean     overwrite,
3170                              CORBA::Boolean     autoDimension)
3171   throw(SALOME::SALOME_Exception)
3172 {
3173   //MESSAGE("MED minor version: "<< minor);
3174   SMESH_TRY;
3175   if ( _preMeshInfo )
3176     _preMeshInfo->FullLoadFromFile();
3177
3178   string aMeshName = prepareMeshNameAndGroups(file, overwrite);
3179   _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version, 0, autoDimension );
3180
3181   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportMED( r'"
3182                 << file << "', "
3183                 << "auto_groups=" <<auto_groups << ", "
3184                 << "minor=" << version <<  ", "
3185                 << "overwrite=" << overwrite << ", "
3186                 << "meshPart=None, "
3187                 << "autoDimension=" << autoDimension << " )";
3188
3189   SMESH_CATCH( SMESH::throwCorbaException );
3190 }
3191
3192 //================================================================================
3193 /*!
3194  * \brief Export a mesh to a SAUV file
3195  */
3196 //================================================================================
3197
3198 void SMESH_Mesh_i::ExportSAUV (const char* file,
3199                                CORBA::Boolean auto_groups)
3200   throw(SALOME::SALOME_Exception)
3201 {
3202   Unexpect aCatch(SALOME_SalomeException);
3203   if ( _preMeshInfo )
3204     _preMeshInfo->FullLoadFromFile();
3205
3206   string aMeshName = prepareMeshNameAndGroups(file, true);
3207   TPythonDump() << SMESH::SMESH_Mesh_var( _this())
3208                 << ".ExportSAUV( r'" << file << "', " << auto_groups << " )";
3209   _impl->ExportSAUV(file, aMeshName.c_str(), auto_groups);
3210 }
3211
3212
3213 //================================================================================
3214 /*!
3215  * \brief Export a mesh to a DAT file
3216  */
3217 //================================================================================
3218
3219 void SMESH_Mesh_i::ExportDAT (const char *file)
3220   throw(SALOME::SALOME_Exception)
3221 {
3222   Unexpect aCatch(SALOME_SalomeException);
3223   if ( _preMeshInfo )
3224     _preMeshInfo->FullLoadFromFile();
3225
3226   // Update Python script
3227   // check names of groups
3228   checkGroupNames();
3229   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportDAT( r'" << file << "' )";
3230
3231   // Perform Export
3232   PrepareForWriting(file);
3233   _impl->ExportDAT(file);
3234 }
3235
3236 //================================================================================
3237 /*!
3238  * \brief Export a mesh to an UNV file
3239  */
3240 //================================================================================
3241
3242 void SMESH_Mesh_i::ExportUNV (const char *file)
3243   throw(SALOME::SALOME_Exception)
3244 {
3245   Unexpect aCatch(SALOME_SalomeException);
3246   if ( _preMeshInfo )
3247     _preMeshInfo->FullLoadFromFile();
3248
3249   // Update Python script
3250   // check names of groups
3251   checkGroupNames();
3252   TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportUNV( r'" << file << "' )";
3253
3254   // Perform Export
3255   PrepareForWriting(file);
3256   _impl->ExportUNV(file);
3257 }
3258
3259 //================================================================================
3260 /*!
3261  * \brief Export a mesh to an STL file
3262  */
3263 //================================================================================
3264
3265 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
3266   throw(SALOME::SALOME_Exception)
3267 {
3268   Unexpect aCatch(SALOME_SalomeException);
3269   if ( _preMeshInfo )
3270     _preMeshInfo->FullLoadFromFile();
3271
3272   // Update Python script
3273   // check names of groups
3274   checkGroupNames();
3275   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3276                 << ".ExportSTL( r'" << file << "', " << isascii << " )";
3277
3278   CORBA::String_var name;
3279   SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( _this() );
3280   if ( !so->_is_nil() )
3281     name = so->GetName();
3282
3283   // Perform Export
3284   PrepareForWriting( file );
3285   _impl->ExportSTL( file, isascii, name.in() );
3286 }
3287
3288 //================================================================================
3289 /*!
3290  * \brief Export a part of mesh to a med file
3291  */
3292 //================================================================================
3293
3294 void SMESH_Mesh_i::ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart,
3295                                    const char*               file,
3296                                    CORBA::Boolean            auto_groups,
3297                                    CORBA::Long               version,
3298                                    CORBA::Boolean            overwrite,
3299                                    CORBA::Boolean            autoDimension,
3300                                    const GEOM::ListOfFields& fields,
3301                                    const char*               geomAssocFields,
3302                                    CORBA::Double             ZTolerance)
3303   throw (SALOME::SALOME_Exception)
3304 {
3305   MESSAGE("MED version: "<< version);
3306   SMESH_TRY;
3307   if ( _preMeshInfo )
3308     _preMeshInfo->FullLoadFromFile();
3309
3310   // check fields
3311   bool have0dField = false;
3312   if ( fields.length() > 0 )
3313   {
3314     GEOM::GEOM_Object_var shapeToMesh = GetShapeToMesh();
3315     if ( shapeToMesh->_is_nil() )
3316       THROW_SALOME_CORBA_EXCEPTION( "No shape to mesh", SALOME::INTERNAL_ERROR );
3317
3318     for ( size_t i = 0; i < fields.length(); ++i )
3319     {
3320       if ( fields[i]->GetDataType() == GEOM::FDT_String )
3321         THROW_SALOME_CORBA_EXCEPTION
3322           ( "Export of string fields is not supported", SALOME::BAD_PARAM);
3323       GEOM::GEOM_Object_var fieldShape = fields[i]->GetShape();
3324       if ( fieldShape->_is_nil() )
3325         THROW_SALOME_CORBA_EXCEPTION( "Null shape under a field", SALOME::INTERNAL_ERROR );
3326       if ( !fieldShape->IsSame( shapeToMesh ) )
3327         THROW_SALOME_CORBA_EXCEPTION
3328           ( "Field defined not on shape", SALOME::BAD_PARAM);
3329       if ( fields[i]->GetDimension() == 0 )
3330         have0dField = true;
3331     }
3332     if ( geomAssocFields )
3333       for ( int i = 0; geomAssocFields[i]; ++i )
3334         switch ( geomAssocFields[i] ) {
3335         case 'v':case 'e':case 'f':case 's': break;
3336         case 'V':case 'E':case 'F':case 'S': break;
3337         default: THROW_SALOME_CORBA_EXCEPTION
3338             ( "geomAssocFields can include only [vefs] characters", SALOME::BAD_PARAM);
3339         }
3340   }
3341
3342   SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
3343
3344   // write mesh
3345
3346   string aMeshName = "Mesh";
3347   SMESHUtils::Deleter< SMESH_MeshPartDS > tmpDSDeleter(0);
3348   if ( CORBA::is_nil( meshPart ) ||
3349        SMESH::DownCast< SMESH_Mesh_i* >( meshPart ))
3350   {
3351     aMeshName = prepareMeshNameAndGroups(file, overwrite);
3352     _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version,
3353                       0, autoDimension, /*addODOnVertices=*/have0dField,
3354                       ZTolerance);
3355     meshDS = _impl->GetMeshDS();
3356   }
3357   else
3358   {
3359     if ( _preMeshInfo )
3360       _preMeshInfo->FullLoadFromFile();
3361
3362     PrepareForWriting(file, overwrite);
3363
3364     SALOMEDS::SObject_wrap SO = _gen_i->ObjectToSObject( meshPart );
3365     if ( !SO->_is_nil() ) {
3366       CORBA::String_var name = SO->GetName();
3367       aMeshName = name;
3368     }
3369
3370     SMESH_MeshPartDS* partDS = new SMESH_MeshPartDS( meshPart );
3371     _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version,
3372                       partDS, autoDimension, /*addODOnVertices=*/have0dField, ZTolerance);
3373     meshDS = tmpDSDeleter._obj = partDS;
3374   }
3375
3376   // write fields
3377
3378   if ( _impl->HasShapeToMesh() )
3379   {
3380     DriverMED_W_Field fieldWriter;
3381     fieldWriter.SetFile( file );
3382     fieldWriter.SetMeshName( aMeshName );
3383     fieldWriter.AddODOnVertices( have0dField );
3384
3385     exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
3386   }
3387
3388   // dump
3389   GEOM::ListOfGBO_var goList = new GEOM::ListOfGBO;
3390   goList->length( fields.length() );
3391   for ( size_t i = 0; i < fields.length(); ++i )
3392   {
3393     GEOM::GEOM_BaseObject_var gbo = GEOM::GEOM_BaseObject::_narrow( fields[i] );
3394     goList[i] = gbo;
3395   }
3396   TPythonDump() << _this() << ".ExportPartToMED( "
3397                 << meshPart << ", r'"
3398                 << file << "', "
3399                 << auto_groups << ", "
3400                 << version << ", "
3401                 << overwrite << ", "
3402                 << autoDimension << ", "
3403                 << goList << ", '"
3404                 << ( geomAssocFields ? geomAssocFields : "" ) << "',"
3405                 << TVar( ZTolerance )
3406                 << " )";
3407
3408   SMESH_CATCH( SMESH::throwCorbaException );
3409 }
3410
3411 //================================================================================
3412 /*!
3413  * Write GEOM fields to MED file
3414  */
3415 //================================================================================
3416
3417 void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field&        fieldWriter,
3418                                     SMESHDS_Mesh*             meshDS,
3419                                     const GEOM::ListOfFields& fields,
3420                                     const char*               geomAssocFields)
3421 {
3422 #define METH "SMESH_Mesh_i::exportMEDFields() "
3423
3424   if (( fields.length() < 1 ) &&
3425       ( !geomAssocFields || !geomAssocFields[0] ))
3426     return;
3427
3428   std::vector< std::vector< double > > dblVals;
3429   std::vector< std::vector< int > >    intVals;
3430   std::vector< int >                   subIdsByDim[ 4 ];
3431   const double noneDblValue = 0.;
3432   const double noneIntValue = 0;
3433
3434   for ( size_t iF = 0; iF < fields.length(); ++iF )
3435   {
3436     // set field data
3437
3438     int dim = fields[ iF ]->GetDimension();
3439     SMDSAbs_ElementType elemType;
3440     TopAbs_ShapeEnum    shapeType;
3441     switch ( dim ) {
3442     case 0: elemType = SMDSAbs_0DElement; shapeType = TopAbs_VERTEX; break;
3443     case 1: elemType = SMDSAbs_Edge;      shapeType = TopAbs_EDGE;   break;
3444     case 2: elemType = SMDSAbs_Face;      shapeType = TopAbs_FACE;   break;
3445     case 3: elemType = SMDSAbs_Volume;    shapeType = TopAbs_SOLID;  break;
3446     default:
3447       continue; // skip fields on whole shape
3448     }
3449     GEOM::field_data_type dataType = fields[ iF ]->GetDataType();
3450     if ( dataType == GEOM::FDT_String )
3451       continue;
3452     GEOM::ListOfLong_var stepIDs = fields[ iF ]->GetSteps();
3453     if ( stepIDs->length() < 1 )
3454       continue;
3455     GEOM::string_array_var comps = fields[ iF ]->GetComponents();
3456     if ( comps->length() < 1 )
3457       continue;
3458     CORBA::String_var       name = fields[ iF ]->GetName();
3459
3460     if ( !fieldWriter.Set( meshDS,
3461                            name.in(),
3462                            elemType,
3463                            comps->length(),
3464                            /*isIntData=*/false ))//( dataType == GEOM::FDT_Int )))
3465       continue;
3466
3467     for ( size_t iC = 0; iC < comps->length(); ++iC )
3468       fieldWriter.SetCompName( iC, comps[ iC ].in() );
3469
3470     dblVals.resize( comps->length() );
3471     intVals.resize( comps->length() );
3472
3473     // find sub-shape IDs
3474
3475     std::vector< int >& subIds = subIdsByDim[ dim ];
3476     if ( subIds.empty() )
3477       for ( int id = 1; id <= meshDS->MaxShapeIndex(); ++id )
3478         if ( meshDS->IndexToShape( id ).ShapeType() == shapeType )
3479           subIds.push_back( id );
3480
3481     // write steps
3482
3483     SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
3484     if ( !elemIt )
3485       continue;
3486
3487     for ( size_t iS = 0; iS < stepIDs->length(); ++iS )
3488     {
3489       GEOM::GEOM_FieldStep_var step = fields[ iF ]->GetStep( stepIDs[ iS ]);
3490       if ( step->_is_nil() )
3491         continue;
3492
3493       CORBA::Long stamp = step->GetStamp();
3494       CORBA::Long id    = step->GetID();
3495       fieldWriter.SetDtIt( int( stamp ), int( id ));
3496
3497       // fill dblVals or intVals
3498       for ( size_t iC = 0; iC < comps->length(); ++iC )
3499         if ( dataType == GEOM::FDT_Double )
3500         {
3501           dblVals[ iC ].clear();
3502           dblVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
3503         }
3504         else
3505         {
3506           intVals[ iC ].clear();
3507           intVals[ iC ].resize( meshDS->MaxShapeIndex()+1, 0 );
3508         }
3509       switch ( dataType )
3510       {
3511       case GEOM::FDT_Double:
3512       {
3513         GEOM::GEOM_DoubleFieldStep_var dblStep = GEOM::GEOM_DoubleFieldStep::_narrow( step );
3514         if ( dblStep->_is_nil() ) continue;
3515         GEOM::ListOfDouble_var vv = dblStep->GetValues();
3516         if ( vv->length() != subIds.size() * comps->length() )
3517           THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
3518         for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
3519           for ( size_t iC = 0; iC < comps->length(); ++iC )
3520             dblVals[ iC ][ subIds[ iS ]] = vv[ iV++ ];
3521         break;
3522       }
3523       case GEOM::FDT_Int:
3524       {
3525         GEOM::GEOM_IntFieldStep_var intStep = GEOM::GEOM_IntFieldStep::_narrow( step );
3526         if ( intStep->_is_nil() ) continue;
3527         GEOM::ListOfLong_var vv = intStep->GetValues();
3528         if ( vv->length() != subIds.size() * comps->length() )
3529           THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
3530         for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
3531           for ( size_t iC = 0; iC < comps->length(); ++iC )
3532             intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
3533         break;
3534       }
3535       case GEOM::FDT_Bool:
3536       {
3537         GEOM::GEOM_BoolFieldStep_var boolStep = GEOM::GEOM_BoolFieldStep::_narrow( step );
3538         if ( boolStep->_is_nil() ) continue;
3539         GEOM::short_array_var vv = boolStep->GetValues();
3540         if ( vv->length() != subIds.size() * comps->length() )
3541           THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
3542         for ( size_t iS = 0, iV = 0; iS < subIds.size(); ++iS )
3543           for ( size_t iC = 0; iC < comps->length(); ++iC )
3544             intVals[ iC ][ subIds[ iS ]] = (int) vv[ iV++ ];
3545         break;
3546       }
3547       default: continue;
3548       }
3549
3550       // pass values to fieldWriter
3551       elemIt = fieldWriter.GetOrderedElems();
3552       if ( dataType == GEOM::FDT_Double )
3553         while ( elemIt->more() )
3554         {
3555           const SMDS_MeshElement* e = elemIt->next();
3556           const int shapeID = e->getshapeId();
3557           if ( shapeID < 1 || shapeID >= (int) dblVals[0].size() )
3558             for ( size_t iC = 0; iC < comps->length(); ++iC )
3559               fieldWriter.AddValue( noneDblValue );
3560           else
3561             for ( size_t iC = 0; iC < comps->length(); ++iC )
3562               fieldWriter.AddValue( dblVals[ iC ][ shapeID ]);
3563         }
3564       else
3565         while ( elemIt->more() )
3566         {
3567           const SMDS_MeshElement* e = elemIt->next();
3568           const int shapeID = e->getshapeId();
3569           if ( shapeID < 1 || shapeID >= (int) intVals[0].size() )
3570             for ( size_t iC = 0; iC < comps->length(); ++iC )
3571               fieldWriter.AddValue( (double) noneIntValue );
3572           else
3573             for ( size_t iC = 0; iC < comps->length(); ++iC )
3574               fieldWriter.AddValue( (double) intVals[ iC ][ shapeID ]);
3575         }
3576
3577       // write a step
3578       fieldWriter.Perform();
3579       SMESH_ComputeErrorPtr res = fieldWriter.GetError();
3580       if ( res && res->IsKO() )
3581       {
3582         if ( res->myComment.empty() )
3583         { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
3584         else
3585         { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
3586       }
3587
3588     } // loop on steps
3589   } // loop on fields
3590
3591   if ( !geomAssocFields || !geomAssocFields[0] )
3592     return;
3593
3594   // write geomAssocFields
3595
3596   std::vector< int > shapeDim( TopAbs_SHAPE + 1 );
3597   shapeDim[ TopAbs_COMPOUND  ] = 3;
3598   shapeDim[ TopAbs_COMPSOLID ] = 3;
3599   shapeDim[ TopAbs_SOLID     ] = 3;
3600   shapeDim[ TopAbs_SHELL     ] = 2;
3601   shapeDim[ TopAbs_FACE      ] = 2;
3602   shapeDim[ TopAbs_WIRE      ] = 1;
3603   shapeDim[ TopAbs_EDGE      ] = 1;
3604   shapeDim[ TopAbs_VERTEX    ] = 0;
3605   shapeDim[ TopAbs_SHAPE     ] = 3;
3606
3607   for ( int iF = 0; geomAssocFields[ iF ]; ++iF )
3608   {
3609     std::vector< std::string > compNames;
3610     switch ( geomAssocFields[ iF ]) {
3611     case 'v': case 'V':
3612       fieldWriter.Set( meshDS, "_vertices_", SMDSAbs_Node, /*nbComps=*/2, /*isInt=*/false );
3613       compNames.push_back( "dim" );
3614       break;
3615     case 'e': case 'E':
3616       fieldWriter.Set( meshDS, "_edges_", SMDSAbs_Edge, /*nbComps=*/1, /*isInt=*/false );
3617       break;
3618     case 'f': case 'F':
3619       fieldWriter.Set( meshDS, "_faces_", SMDSAbs_Face, /*nbComps=*/1, /*isInt=*/false );
3620       break;
3621     case 's': case 'S':
3622       fieldWriter.Set( meshDS, "_solids_", SMDSAbs_Volume, /*nbComps=*/1, /*isInt=*/false );
3623       break;
3624     default: continue;
3625     }
3626     compNames.push_back( "id" );
3627     for ( size_t iC = 0; iC < compNames.size(); ++iC )
3628       fieldWriter.SetCompName( iC, compNames[ iC ].c_str() );
3629
3630     fieldWriter.SetDtIt( -1, -1 );
3631
3632     SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
3633     if ( !elemIt )
3634       continue;
3635
3636     if ( compNames.size() == 2 ) // _vertices_
3637       while ( elemIt->more() )
3638       {
3639         const SMDS_MeshElement* e = elemIt->next();
3640         const int shapeID = e->getshapeId();
3641         if ( shapeID < 1 )
3642         {
3643           fieldWriter.AddValue( (double) -1 );
3644           fieldWriter.AddValue( (double) -1 );
3645         }
3646         else
3647         {
3648           const TopoDS_Shape& S = meshDS->IndexToShape( shapeID );
3649           fieldWriter.AddValue( (double) ( S.IsNull() ? -1 : shapeDim[ S.ShapeType() ]));
3650           fieldWriter.AddValue( (double) shapeID );
3651         }
3652       }
3653     else
3654       while ( elemIt->more() )
3655       {
3656         const SMDS_MeshElement* e = elemIt->next();
3657         const int shapeID = e->getshapeId();
3658         if ( shapeID < 1 )
3659           fieldWriter.AddValue( (double) -1 );
3660         else
3661           fieldWriter.AddValue( (double) shapeID );
3662       }
3663
3664     // write a step
3665     fieldWriter.Perform();
3666     SMESH_ComputeErrorPtr res = fieldWriter.GetError();
3667     if ( res && res->IsKO() )
3668     {
3669       if ( res->myComment.empty() )
3670       { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
3671       else
3672       { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
3673     }
3674
3675   } // loop on geomAssocFields
3676
3677 #undef METH
3678 }
3679
3680 //================================================================================
3681 /*!
3682  * \brief Export a part of mesh to a DAT file
3683  */
3684 //================================================================================
3685
3686 void SMESH_Mesh_i::ExportPartToDAT(::SMESH::SMESH_IDSource_ptr meshPart,
3687                                    const char*                 file)
3688   throw (SALOME::SALOME_Exception)
3689 {
3690   Unexpect aCatch(SALOME_SalomeException);
3691   if ( _preMeshInfo )
3692     _preMeshInfo->FullLoadFromFile();
3693
3694   PrepareForWriting(file);
3695
3696   SMESH_MeshPartDS partDS( meshPart );
3697   _impl->ExportDAT(file,&partDS);
3698
3699   TPythonDump() << SMESH::SMESH_Mesh_var(_this())
3700                 << ".ExportPartToDAT( " << meshPart << ", r'" << file << "' )";
3701 }
3702 //================================================================================
3703 /*!
3704  * \brief Export a part of mesh to an UNV file
3705  */