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