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