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