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