Salome HOME
0021275: EDF 1681 SMESH: Find the number of nodes of any group
[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 void SMESH_Mesh_i::ExportToMEDX (const char* file,
2552                                  CORBA::Boolean auto_groups,
2553                                  SMESH::MED_VERSION theVersion,
2554                                  CORBA::Boolean overwrite)
2555   throw(SALOME::SALOME_Exception)
2556 {
2557   Unexpect aCatch(SALOME_SalomeException);
2558
2559   // Perform Export
2560   PrepareForWriting(file, overwrite);
2561   string aMeshName = "Mesh";
2562   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
2563   if ( !aStudy->_is_nil() ) {
2564     SALOMEDS::SObject_var aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
2565     if ( !aMeshSO->_is_nil() ) {
2566       CORBA::String_var name = aMeshSO->GetName();
2567       aMeshName = name;
2568       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
2569       if ( !aStudy->GetProperties()->IsLocked() )
2570       {
2571         SALOMEDS::GenericAttribute_var anAttr;
2572         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
2573         SALOMEDS::AttributeExternalFileDef_var aFileName;
2574         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
2575         aFileName = SALOMEDS::AttributeExternalFileDef::_narrow(anAttr);
2576         ASSERT(!aFileName->_is_nil());
2577         aFileName->SetValue(file);
2578         SALOMEDS::AttributeFileType_var aFileType;
2579         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
2580         aFileType = SALOMEDS::AttributeFileType::_narrow(anAttr);
2581         ASSERT(!aFileType->_is_nil());
2582         aFileType->SetValue("FICHIERMED");
2583       }
2584     }
2585   }
2586   // Update Python script
2587   // set name of mesh before export
2588   TPythonDump() << _gen_i << ".SetName(" << _this() << ", '" << aMeshName.c_str() << "')";
2589
2590   // check names of groups
2591   checkGroupNames();
2592
2593   TPythonDump() << _this() << ".ExportToMEDX( r'"
2594                 << file << "', " << auto_groups << ", " << theVersion << ", " << overwrite << " )";
2595
2596   _impl->ExportMED( file, aMeshName.c_str(), auto_groups, theVersion );
2597 }
2598
2599 //================================================================================
2600 /*!
2601  * \brief Export a mesh to a med file
2602  */
2603 //================================================================================
2604
2605 void SMESH_Mesh_i::ExportToMED (const char* file,
2606                                 CORBA::Boolean auto_groups,
2607                                 SMESH::MED_VERSION theVersion)
2608   throw(SALOME::SALOME_Exception)
2609 {
2610   ExportToMEDX(file,auto_groups,theVersion,true);
2611 }
2612
2613 //================================================================================
2614 /*!
2615  * \brief Export a mesh to a med file
2616  */
2617 //================================================================================
2618
2619 void SMESH_Mesh_i::ExportMED (const char* file,
2620                               CORBA::Boolean auto_groups)
2621   throw(SALOME::SALOME_Exception)
2622 {
2623   ExportToMEDX(file,auto_groups,SMESH::MED_V2_2,true);
2624 }
2625
2626 //================================================================================
2627 /*!
2628  * \brief Export a mesh to a DAT file
2629  */
2630 //================================================================================
2631
2632 void SMESH_Mesh_i::ExportDAT (const char *file)
2633   throw(SALOME::SALOME_Exception)
2634 {
2635   Unexpect aCatch(SALOME_SalomeException);
2636
2637   // Update Python script
2638   // check names of groups
2639   checkGroupNames();
2640   TPythonDump() << _this() << ".ExportDAT( r'" << file << "' )";
2641
2642   // Perform Export
2643   PrepareForWriting(file);
2644   _impl->ExportDAT(file);
2645 }
2646
2647 //================================================================================
2648 /*!
2649  * \brief Export a mesh to an UNV file
2650  */
2651 //================================================================================
2652
2653 void SMESH_Mesh_i::ExportUNV (const char *file)
2654   throw(SALOME::SALOME_Exception)
2655 {
2656   Unexpect aCatch(SALOME_SalomeException);
2657
2658   // Update Python script
2659   // check names of groups
2660   checkGroupNames();
2661   TPythonDump() << _this() << ".ExportUNV( r'" << file << "' )";
2662
2663   // Perform Export
2664   PrepareForWriting(file);
2665   _impl->ExportUNV(file);
2666 }
2667
2668 //================================================================================
2669 /*!
2670  * \brief Export a mesh to an STL file
2671  */
2672 //================================================================================
2673
2674 void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
2675   throw(SALOME::SALOME_Exception)
2676 {
2677   Unexpect aCatch(SALOME_SalomeException);
2678
2679   // Update Python script
2680   // check names of groups
2681   checkGroupNames();
2682   TPythonDump() << _this() << ".ExportSTL( r'" << file << "', " << isascii << " )";
2683
2684   // Perform Export
2685   PrepareForWriting(file);
2686   _impl->ExportSTL(file, isascii);
2687 }
2688
2689 //=============================================================================
2690 /*!
2691  * \brief Class providing SMESHDS_Mesh API to SMESH_IDSource. 
2692  *        It is used to export a part of mesh as a whole mesh.
2693  */
2694 class SMESH_MeshPartDS : public SMESHDS_Mesh
2695 {
2696 public:
2697   SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart);
2698
2699   virtual SMDS_NodeIteratorPtr      nodesIterator     (bool idInceasingOrder=false) const;
2700   virtual SMDS_0DElementIteratorPtr elements0dIterator(bool idInceasingOrder=false) const;
2701   virtual SMDS_EdgeIteratorPtr      edgesIterator     (bool idInceasingOrder=false) const;
2702   virtual SMDS_FaceIteratorPtr      facesIterator     (bool idInceasingOrder=false) const;
2703   virtual SMDS_VolumeIteratorPtr    volumesIterator   (bool idInceasingOrder=false) const;
2704
2705   virtual SMDS_ElemIteratorPtr elementsIterator(SMDSAbs_ElementType type=SMDSAbs_All) const;
2706
2707 private:
2708   TIDSortedElemSet _elements[ SMDSAbs_NbElementTypes ];
2709   SMESHDS_Mesh*    _meshDS;
2710   /*!
2711    * \brief Class used to access to protected data of SMDS_MeshInfo
2712    */
2713   struct TMeshInfo : public SMDS_MeshInfo
2714   {
2715     void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); }
2716   };
2717 };
2718
2719 //================================================================================
2720 /*!
2721  * \brief Export a part of mesh to a med file
2722  */
2723 //================================================================================
2724
2725 void SMESH_Mesh_i::ExportPartToMED(::SMESH::SMESH_IDSource_ptr meshPart,
2726                                    const char*                 file,
2727                                    CORBA::Boolean              auto_groups,
2728                                    ::SMESH::MED_VERSION        version,
2729                                    ::CORBA::Boolean            overwrite)
2730   throw (SALOME::SALOME_Exception)
2731 {
2732   Unexpect aCatch(SALOME_SalomeException);
2733
2734   PrepareForWriting(file, overwrite);
2735
2736   string aMeshName = "Mesh";
2737   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
2738   if ( !aStudy->_is_nil() ) {
2739     SALOMEDS::SObject_var SO = _gen_i->ObjectToSObject( aStudy, meshPart );
2740     if ( !SO->_is_nil() ) {
2741       CORBA::String_var name = SO->GetName();
2742       aMeshName = name;
2743     }
2744   }
2745   SMESH_MeshPartDS partDS( meshPart );
2746   _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version, &partDS );
2747
2748   TPythonDump() << _this() << ".ExportPartToMED( " << meshPart << ", r'" << file << "', "
2749                 << auto_groups << ", " << version << ", " << overwrite << " )";
2750 }
2751
2752 //================================================================================
2753 /*!
2754  * \brief Export a part of mesh to a DAT file
2755  */
2756 //================================================================================
2757
2758 void SMESH_Mesh_i::ExportPartToDAT(::SMESH::SMESH_IDSource_ptr meshPart,
2759                                    const char*                 file)
2760   throw (SALOME::SALOME_Exception)
2761 {
2762   Unexpect aCatch(SALOME_SalomeException);
2763
2764   PrepareForWriting(file);
2765
2766   SMESH_MeshPartDS partDS( meshPart );
2767   _impl->ExportDAT(file,&partDS);
2768
2769   TPythonDump() << _this() << ".ExportPartToDAT( " << meshPart << ", r'" << file << "' )";
2770 }
2771 //================================================================================
2772 /*!
2773  * \brief Export a part of mesh to an UNV file
2774  */
2775 //================================================================================
2776
2777 void SMESH_Mesh_i::ExportPartToUNV(::SMESH::SMESH_IDSource_ptr meshPart,
2778                                    const char*                 file)
2779   throw (SALOME::SALOME_Exception)
2780 {
2781   Unexpect aCatch(SALOME_SalomeException);
2782
2783   PrepareForWriting(file);
2784
2785   SMESH_MeshPartDS partDS( meshPart );
2786   _impl->ExportUNV(file, &partDS);
2787
2788   TPythonDump() << _this() << ".ExportPartToUNV( " << meshPart<< ", r'" << file << "' )";
2789 }
2790 //================================================================================
2791 /*!
2792  * \brief Export a part of mesh to an STL file
2793  */
2794 //================================================================================
2795
2796 void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
2797                                    const char*                 file,
2798                                    ::CORBA::Boolean            isascii)
2799   throw (SALOME::SALOME_Exception)
2800 {
2801   Unexpect aCatch(SALOME_SalomeException);
2802
2803   PrepareForWriting(file);
2804
2805   SMESH_MeshPartDS partDS( meshPart );
2806   _impl->ExportSTL(file, isascii, &partDS);
2807
2808   TPythonDump() << _this() << ".ExportPartToSTL( "
2809                 << meshPart<< ", r'" << file << "', " << isascii << ")";
2810 }
2811
2812 //================================================================================
2813 /*!
2814  * \brief Export a part of mesh to an STL file
2815  */
2816 //================================================================================
2817
2818 void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart,
2819                               const char*                 file,
2820                               CORBA::Boolean              overwrite)
2821   throw (SALOME::SALOME_Exception)
2822 {
2823 #ifdef WITH_CGNS
2824   Unexpect aCatch(SALOME_SalomeException);
2825
2826   PrepareForWriting(file,overwrite);
2827
2828   SMESH_MeshPartDS partDS( meshPart );
2829   _impl->ExportCGNS(file, &partDS);
2830
2831   TPythonDump() << _this() << ".ExportCGNS( "
2832                 << meshPart<< ", r'" << file << "', " << overwrite << ")";
2833 #else
2834   THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
2835 #endif
2836 }
2837
2838 //=============================================================================
2839 /*!
2840  *
2841  */
2842 //=============================================================================
2843
2844 SALOME_MED::MESH_ptr SMESH_Mesh_i::GetMEDMesh()throw(SALOME::SALOME_Exception)
2845 {
2846   Unexpect aCatch(SALOME_SalomeException);
2847   SMESH_MEDMesh_i *aMedMesh = new SMESH_MEDMesh_i(this);
2848   SALOME_MED::MESH_var aMesh = aMedMesh->_this();
2849   return aMesh._retn();
2850 }
2851
2852 //=============================================================================
2853 /*!
2854  *
2855  */
2856 //=============================================================================
2857 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
2858 {
2859   Unexpect aCatch(SALOME_SalomeException);
2860   return _impl->NbNodes();
2861 }
2862
2863 //=============================================================================
2864 /*!
2865  *
2866  */
2867 //=============================================================================
2868 CORBA::Long SMESH_Mesh_i::NbElements()throw (SALOME::SALOME_Exception)
2869 {
2870   Unexpect aCatch(SALOME_SalomeException);
2871   return Nb0DElements() + NbEdges() + NbFaces() + NbVolumes();
2872 }
2873
2874 //=============================================================================
2875 /*!
2876  *
2877  */
2878 //=============================================================================
2879 CORBA::Long SMESH_Mesh_i::Nb0DElements()throw (SALOME::SALOME_Exception)
2880 {
2881   Unexpect aCatch(SALOME_SalomeException);
2882   return _impl->Nb0DElements();
2883 }
2884
2885 //=============================================================================
2886 /*!
2887  *
2888  */
2889 //=============================================================================
2890 CORBA::Long SMESH_Mesh_i::NbEdges()throw(SALOME::SALOME_Exception)
2891 {
2892   Unexpect aCatch(SALOME_SalomeException);
2893   return _impl->NbEdges();
2894 }
2895
2896 CORBA::Long SMESH_Mesh_i::NbEdgesOfOrder(SMESH::ElementOrder order)
2897   throw(SALOME::SALOME_Exception)
2898 {
2899   Unexpect aCatch(SALOME_SalomeException);
2900   return _impl->NbEdges( (SMDSAbs_ElementOrder) order);
2901 }
2902
2903 //=============================================================================
2904 /*!
2905  *
2906  */
2907 //=============================================================================
2908 CORBA::Long SMESH_Mesh_i::NbFaces()throw(SALOME::SALOME_Exception)
2909 {
2910   Unexpect aCatch(SALOME_SalomeException);
2911   return _impl->NbFaces();
2912 }
2913
2914 CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
2915 {
2916   Unexpect aCatch(SALOME_SalomeException);
2917   return _impl->NbTriangles();
2918 }
2919
2920 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
2921 {
2922   Unexpect aCatch(SALOME_SalomeException);
2923   return _impl->NbQuadrangles();
2924 }
2925
2926 CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
2927 {
2928   Unexpect aCatch(SALOME_SalomeException);
2929   return _impl->NbPolygons();
2930 }
2931
2932 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
2933   throw(SALOME::SALOME_Exception)
2934 {
2935   Unexpect aCatch(SALOME_SalomeException);
2936   return _impl->NbFaces( (SMDSAbs_ElementOrder) order);
2937 }
2938
2939 CORBA::Long SMESH_Mesh_i::NbTrianglesOfOrder(SMESH::ElementOrder order)
2940   throw(SALOME::SALOME_Exception)
2941 {
2942   Unexpect aCatch(SALOME_SalomeException);
2943   return _impl->NbTriangles( (SMDSAbs_ElementOrder) order);
2944 }
2945
2946 CORBA::Long SMESH_Mesh_i::NbQuadranglesOfOrder(SMESH::ElementOrder order)
2947   throw(SALOME::SALOME_Exception)
2948 {
2949   Unexpect aCatch(SALOME_SalomeException);
2950   return _impl->NbQuadrangles( (SMDSAbs_ElementOrder) order);
2951 }
2952
2953 //=============================================================================
2954 /*!
2955  *
2956  */
2957 //=============================================================================
2958 CORBA::Long SMESH_Mesh_i::NbVolumes()throw(SALOME::SALOME_Exception)
2959 {
2960   Unexpect aCatch(SALOME_SalomeException);
2961   return _impl->NbVolumes();
2962 }
2963
2964 CORBA::Long SMESH_Mesh_i::NbTetras()throw(SALOME::SALOME_Exception)
2965 {
2966   Unexpect aCatch(SALOME_SalomeException);
2967   return _impl->NbTetras();
2968 }
2969
2970 CORBA::Long SMESH_Mesh_i::NbHexas()throw(SALOME::SALOME_Exception)
2971 {
2972   Unexpect aCatch(SALOME_SalomeException);
2973   return _impl->NbHexas();
2974 }
2975
2976 CORBA::Long SMESH_Mesh_i::NbPyramids()throw(SALOME::SALOME_Exception)
2977 {
2978   Unexpect aCatch(SALOME_SalomeException);
2979   return _impl->NbPyramids();
2980 }
2981
2982 CORBA::Long SMESH_Mesh_i::NbPrisms()throw(SALOME::SALOME_Exception)
2983 {
2984   Unexpect aCatch(SALOME_SalomeException);
2985   return _impl->NbPrisms();
2986 }
2987
2988 CORBA::Long SMESH_Mesh_i::NbPolyhedrons()throw(SALOME::SALOME_Exception)
2989 {
2990   Unexpect aCatch(SALOME_SalomeException);
2991   return _impl->NbPolyhedrons();
2992 }
2993
2994 CORBA::Long SMESH_Mesh_i::NbVolumesOfOrder(SMESH::ElementOrder order)
2995   throw(SALOME::SALOME_Exception)
2996 {
2997   Unexpect aCatch(SALOME_SalomeException);
2998   return _impl->NbVolumes( (SMDSAbs_ElementOrder) order);
2999 }
3000
3001 CORBA::Long SMESH_Mesh_i::NbTetrasOfOrder(SMESH::ElementOrder order)
3002   throw(SALOME::SALOME_Exception)
3003 {
3004   Unexpect aCatch(SALOME_SalomeException);
3005   return _impl->NbTetras( (SMDSAbs_ElementOrder) order);
3006 }
3007
3008 CORBA::Long SMESH_Mesh_i::NbHexasOfOrder(SMESH::ElementOrder order)
3009   throw(SALOME::SALOME_Exception)
3010 {
3011   Unexpect aCatch(SALOME_SalomeException);
3012   return _impl->NbHexas( (SMDSAbs_ElementOrder) order);
3013 }
3014
3015 CORBA::Long SMESH_Mesh_i::NbPyramidsOfOrder(SMESH::ElementOrder order)
3016   throw(SALOME::SALOME_Exception)
3017 {
3018   Unexpect aCatch(SALOME_SalomeException);
3019   return _impl->NbPyramids( (SMDSAbs_ElementOrder) order);
3020 }
3021
3022 CORBA::Long SMESH_Mesh_i::NbPrismsOfOrder(SMESH::ElementOrder order)
3023   throw(SALOME::SALOME_Exception)
3024 {
3025   Unexpect aCatch(SALOME_SalomeException);
3026   return _impl->NbPrisms( (SMDSAbs_ElementOrder) order);
3027 }
3028
3029 //=============================================================================
3030 /*!
3031  *
3032  */
3033 //=============================================================================
3034 CORBA::Long SMESH_Mesh_i::NbSubMesh()throw(SALOME::SALOME_Exception)
3035 {
3036   Unexpect aCatch(SALOME_SalomeException);
3037   return _mapSubMesh_i.size();
3038 }
3039
3040 //=============================================================================
3041 /*!
3042  *
3043  */
3044 //=============================================================================
3045 char* SMESH_Mesh_i::Dump()
3046 {
3047   ostringstream os;
3048   _impl->Dump( os );
3049   return CORBA::string_dup( os.str().c_str() );
3050 }
3051
3052 //=============================================================================
3053 /*!
3054  *
3055  */
3056 //=============================================================================
3057 SMESH::long_array* SMESH_Mesh_i::GetIDs()
3058 {
3059 //   SMESH::long_array_var aResult = new SMESH::long_array();
3060 //   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3061 //   int aMinId = aSMESHDS_Mesh->MinElementID();
3062 //   int aMaxId =  aSMESHDS_Mesh->MaxElementID();
3063
3064 //   aResult->length(aMaxId - aMinId + 1);
3065
3066 //   for (int i = 0, id = aMinId; id <= aMaxId; id++  )
3067 //     aResult[i++] = id;
3068
3069 //   return aResult._retn();
3070   // PAL12398
3071   return GetElementsId();
3072 }
3073
3074 //=============================================================================
3075 /*!
3076  *
3077  */
3078 //=============================================================================
3079
3080 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
3081      throw (SALOME::SALOME_Exception)
3082 {
3083   Unexpect aCatch(SALOME_SalomeException);
3084   MESSAGE("SMESH_Mesh_i::GetElementsId");
3085   SMESH::long_array_var aResult = new SMESH::long_array();
3086   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3087
3088   if ( aSMESHDS_Mesh == NULL )
3089     return aResult._retn();
3090
3091   long nbElements = NbElements();
3092   aResult->length( nbElements );
3093   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
3094   for ( int i = 0, n = nbElements; i < n && anIt->more(); i++ )
3095     aResult[i] = anIt->next()->GetID();
3096
3097   return aResult._retn();
3098 }
3099
3100
3101 //=============================================================================
3102 /*!
3103  *
3104  */
3105 //=============================================================================
3106
3107 SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemType )
3108     throw (SALOME::SALOME_Exception)
3109 {
3110   Unexpect aCatch(SALOME_SalomeException);
3111   MESSAGE("SMESH_subMesh_i::GetElementsByType");
3112   SMESH::long_array_var aResult = new SMESH::long_array();
3113   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3114
3115   if ( aSMESHDS_Mesh == NULL )
3116     return aResult._retn();
3117
3118   long nbElements = NbElements();
3119
3120   // No sense in returning ids of elements along with ids of nodes:
3121   // when theElemType == SMESH::ALL, return node ids only if
3122   // there are no elements
3123   if ( theElemType == SMESH::NODE || (theElemType == SMESH::ALL && nbElements == 0) )
3124     return GetNodesId();
3125
3126   aResult->length( nbElements );
3127
3128   int i = 0;
3129
3130   SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
3131   while ( i < nbElements && anIt->more() ) {
3132     const SMDS_MeshElement* anElem = anIt->next();
3133     if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
3134       aResult[i++] = anElem->GetID();
3135   }
3136
3137   aResult->length( i );
3138
3139   return aResult._retn();
3140 }
3141
3142 //=============================================================================
3143 /*!
3144  *
3145  */
3146 //=============================================================================
3147
3148 SMESH::long_array* SMESH_Mesh_i::GetNodesId()
3149   throw (SALOME::SALOME_Exception)
3150 {
3151   Unexpect aCatch(SALOME_SalomeException);
3152   MESSAGE("SMESH_subMesh_i::GetNodesId");
3153   SMESH::long_array_var aResult = new SMESH::long_array();
3154   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3155
3156   if ( aSMESHDS_Mesh == NULL )
3157     return aResult._retn();
3158
3159   long nbNodes = NbNodes();
3160   aResult->length( nbNodes );
3161   SMDS_NodeIteratorPtr anIt = aSMESHDS_Mesh->nodesIterator(/*idInceasingOrder=*/true);
3162   for ( int i = 0, n = nbNodes; i < n && anIt->more(); i++ )
3163     aResult[i] = anIt->next()->GetID();
3164
3165   return aResult._retn();
3166 }
3167
3168 //=============================================================================
3169 /*!
3170  *
3171  */
3172 //=============================================================================
3173
3174 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
3175   throw (SALOME::SALOME_Exception)
3176 {
3177   return ( SMESH::ElementType )_impl->GetElementType( id, iselem );
3178 }
3179
3180 //=============================================================================
3181 /*!
3182  *
3183  */
3184 //=============================================================================
3185
3186 SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id )
3187   throw (SALOME::SALOME_Exception)
3188 {
3189   const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
3190   if ( !e )
3191     THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
3192
3193   return ( SMESH::EntityType ) e->GetEntityType();
3194 }
3195
3196 //=============================================================================
3197 /*!
3198  * Returns ID of elements for given submesh
3199  */
3200 //=============================================================================
3201 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
3202      throw (SALOME::SALOME_Exception)
3203 {
3204   SMESH::long_array_var aResult = new SMESH::long_array();
3205
3206   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
3207   if(!SM) return aResult._retn();
3208
3209   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
3210   if(!SDSM) return aResult._retn();
3211
3212   aResult->length(SDSM->NbElements());
3213
3214   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
3215   int i = 0;
3216   while ( eIt->more() ) {
3217     aResult[i++] = eIt->next()->GetID();
3218   }
3219
3220   return aResult._retn();
3221 }
3222
3223
3224 //=============================================================================
3225 /*!
3226  * Returns ID of nodes for given submesh
3227  * If param all==true - returns all nodes, else -
3228  * returns only nodes on shapes.
3229  */
3230 //=============================================================================
3231 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID, CORBA::Boolean all)
3232      throw (SALOME::SALOME_Exception)
3233 {
3234   SMESH::long_array_var aResult = new SMESH::long_array();
3235
3236   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
3237   if(!SM) return aResult._retn();
3238
3239   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
3240   if(!SDSM) return aResult._retn();
3241
3242   set<int> theElems;
3243   if( !all || (SDSM->NbElements()==0) ) { // internal nodes or vertex submesh
3244     SMDS_NodeIteratorPtr nIt = SDSM->GetNodes();
3245     while ( nIt->more() ) {
3246       const SMDS_MeshNode* elem = nIt->next();
3247       theElems.insert( elem->GetID() );
3248     }
3249   }
3250   else { // all nodes of submesh elements
3251     SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
3252     while ( eIt->more() ) {
3253       const SMDS_MeshElement* anElem = eIt->next();
3254       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
3255       while ( nIt->more() ) {
3256         const SMDS_MeshElement* elem = nIt->next();
3257         theElems.insert( elem->GetID() );
3258       }
3259     }
3260   }
3261
3262   aResult->length(theElems.size());
3263   set<int>::iterator itElem;
3264   int i = 0;
3265   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
3266     aResult[i++] = *itElem;
3267
3268   return aResult._retn();
3269 }
3270   
3271
3272 //=============================================================================
3273 /*!
3274  * Returns type of elements for given submesh
3275  */
3276 //=============================================================================
3277 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
3278      throw (SALOME::SALOME_Exception)
3279 {
3280   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
3281   if(!SM) return SMESH::ALL;
3282
3283   SMESHDS_SubMesh* SDSM = SM->GetSubMeshDS();
3284   if(!SDSM) return SMESH::ALL;
3285
3286   if(SDSM->NbElements()==0)
3287     return (SM->GetSubShape().ShapeType() == TopAbs_VERTEX) ? SMESH::NODE : SMESH::ALL;
3288
3289   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
3290   const SMDS_MeshElement* anElem = eIt->next();
3291   return ( SMESH::ElementType ) anElem->GetType();
3292 }
3293   
3294
3295 //=============================================================================
3296 /*!
3297  *
3298  */
3299 //=============================================================================
3300
3301 CORBA::LongLong SMESH_Mesh_i::GetMeshPtr()
3302 {
3303   CORBA::LongLong pointeur = CORBA::LongLong(_impl);
3304   if ( MYDEBUG )
3305     MESSAGE("CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() "<<pointeur);
3306   return pointeur;
3307 }
3308
3309
3310 //=============================================================================
3311 /*!
3312  * Get XYZ coordinates of node as list of double
3313  * If there is not node for given ID - returns empty list
3314  */
3315 //=============================================================================
3316
3317 SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id)
3318 {
3319   SMESH::double_array_var aResult = new SMESH::double_array();
3320   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3321   if ( aSMESHDS_Mesh == NULL )
3322     return aResult._retn();
3323
3324   // find node
3325   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3326   if(!aNode)
3327     return aResult._retn();
3328
3329   // add coordinates
3330   aResult->length(3);
3331   aResult[0] = aNode->X();
3332   aResult[1] = aNode->Y();
3333   aResult[2] = aNode->Z();
3334   return aResult._retn();
3335 }
3336
3337
3338 //=============================================================================
3339 /*!
3340  * For given node returns list of IDs of inverse elements
3341  * If there is not node for given ID - returns empty list
3342  */
3343 //=============================================================================
3344
3345 SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
3346 {
3347   SMESH::long_array_var aResult = new SMESH::long_array();
3348   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3349   if ( aSMESHDS_Mesh == NULL )
3350     return aResult._retn();
3351
3352   // find node
3353   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3354   if(!aNode)
3355     return aResult._retn();
3356
3357   // find inverse elements
3358   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
3359   TColStd_SequenceOfInteger IDs;
3360   while(eIt->more()) {
3361     const SMDS_MeshElement* elem = eIt->next();
3362     IDs.Append(elem->GetID());
3363   }
3364   if(IDs.Length()>0) {
3365     aResult->length(IDs.Length());
3366     int i = 1;
3367     for(; i<=IDs.Length(); i++) {
3368       aResult[i-1] = IDs.Value(i);
3369     }
3370   }
3371   return aResult._retn();
3372 }
3373
3374 //=============================================================================
3375 /*!
3376  * \brief Return position of a node on shape
3377  */
3378 //=============================================================================
3379
3380 SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
3381 {
3382   SMESH::NodePosition* aNodePosition = new SMESH::NodePosition();
3383   aNodePosition->shapeID = 0;
3384   aNodePosition->shapeType = GEOM::SHAPE;
3385
3386   SMESHDS_Mesh* mesh = _impl->GetMeshDS();
3387   if ( !mesh ) return aNodePosition;
3388
3389   if ( const SMDS_MeshNode* aNode = mesh->FindNode(NodeID) )
3390   {
3391     if ( SMDS_PositionPtr pos = aNode->GetPosition() )
3392     {
3393       aNodePosition->shapeID = aNode->getshapeId();
3394       switch ( pos->GetTypeOfPosition() ) {
3395       case SMDS_TOP_EDGE:
3396         aNodePosition->shapeType = GEOM::EDGE;
3397         aNodePosition->params.length(1);
3398         aNodePosition->params[0] =
3399           static_cast<SMDS_EdgePosition*>( pos )->GetUParameter();
3400         break;
3401       case SMDS_TOP_FACE:
3402         aNodePosition->shapeType = GEOM::FACE;
3403         aNodePosition->params.length(2);
3404         aNodePosition->params[0] =
3405           static_cast<SMDS_FacePosition*>( pos )->GetUParameter();
3406         aNodePosition->params[1] =
3407           static_cast<SMDS_FacePosition*>( pos )->GetVParameter();
3408         break;
3409       case SMDS_TOP_VERTEX:
3410         aNodePosition->shapeType = GEOM::VERTEX;
3411         break;
3412       case SMDS_TOP_3DSPACE:
3413         if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SOLID).More() )
3414           aNodePosition->shapeType = GEOM::SOLID;
3415         else if ( TopExp_Explorer(_impl->GetShapeToMesh(), TopAbs_SHELL).More() )
3416           aNodePosition->shapeType = GEOM::SHELL;
3417         break;
3418       default:;
3419       }
3420     }
3421   }
3422   return aNodePosition;
3423 }
3424
3425 //=============================================================================
3426 /*!
3427  * If given element is node returns IDs of shape from position
3428  * If there is not node for given ID - returns -1
3429  */
3430 //=============================================================================
3431
3432 CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id)
3433 {
3434   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3435   if ( aSMESHDS_Mesh == NULL )
3436     return -1;
3437
3438   // try to find node
3439   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(id);
3440   if(aNode) {
3441     return aNode->getshapeId();
3442   }
3443
3444   return -1;
3445 }
3446
3447
3448 //=============================================================================
3449 /*!
3450  * For given element returns ID of result shape after 
3451  * ::FindShape() from SMESH_MeshEditor
3452  * If there is not element for given ID - returns -1
3453  */
3454 //=============================================================================
3455
3456 CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
3457 {
3458   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3459   if ( aSMESHDS_Mesh == NULL )
3460     return -1;
3461
3462   // try to find element
3463   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3464   if(!elem)
3465     return -1;
3466
3467   //SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
3468   ::SMESH_MeshEditor aMeshEditor(_impl);
3469   int index = aMeshEditor.FindShape( elem );
3470   if(index>0)
3471     return index;
3472
3473   return -1;
3474 }
3475
3476
3477 //=============================================================================
3478 /*!
3479  * Returns number of nodes for given element
3480  * If there is not element for given ID - returns -1
3481  */
3482 //=============================================================================
3483
3484 CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id)
3485 {
3486   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3487   if ( aSMESHDS_Mesh == NULL ) return -1;
3488   // try to find element
3489   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3490   if(!elem) return -1;
3491   return elem->NbNodes();
3492 }
3493
3494
3495 //=============================================================================
3496 /*!
3497  * Returns ID of node by given index for given element
3498  * If there is not element for given ID - returns -1
3499  * If there is not node for given index - returns -2
3500  */
3501 //=============================================================================
3502
3503 CORBA::Long SMESH_Mesh_i::GetElemNode(const CORBA::Long id, const CORBA::Long index)
3504 {
3505   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3506   if ( aSMESHDS_Mesh == NULL ) return -1;
3507   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3508   if(!elem) return -1;
3509   if( index>=elem->NbNodes() || index<0 ) return -1;
3510   return elem->GetNode(index)->GetID();
3511 }
3512
3513 //=============================================================================
3514 /*!
3515  * Returns IDs of nodes of given element
3516  */
3517 //=============================================================================
3518
3519 SMESH::long_array* SMESH_Mesh_i::GetElemNodes(const CORBA::Long id)
3520 {
3521   SMESH::long_array_var aResult = new SMESH::long_array();
3522   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
3523   {
3524     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id) )
3525     {
3526       aResult->length( elem->NbNodes() );
3527       for ( int i = 0; i < elem->NbNodes(); ++i )
3528         aResult[ i ] = elem->GetNode( i )->GetID();
3529     }
3530   }
3531   return aResult._retn();
3532 }
3533
3534 //=============================================================================
3535 /*!
3536  * Returns true if given node is medium node
3537  * in given quadratic element
3538  */
3539 //=============================================================================
3540
3541 CORBA::Boolean SMESH_Mesh_i::IsMediumNode(const CORBA::Long ide, const CORBA::Long idn)
3542 {
3543   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3544   if ( aSMESHDS_Mesh == NULL ) return false;
3545   // try to find node
3546   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
3547   if(!aNode) return false;
3548   // try to find element
3549   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(ide);
3550   if(!elem) return false;
3551
3552   return elem->IsMediumNode(aNode);
3553 }
3554
3555
3556 //=============================================================================
3557 /*!
3558  * Returns true if given node is medium node
3559  * in one of quadratic elements
3560  */
3561 //=============================================================================
3562
3563 CORBA::Boolean SMESH_Mesh_i::IsMediumNodeOfAnyElem(const CORBA::Long idn,
3564                                                    SMESH::ElementType theElemType)
3565 {
3566   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3567   if ( aSMESHDS_Mesh == NULL ) return false;
3568
3569   // try to find node
3570   const SMDS_MeshNode* aNode = aSMESHDS_Mesh->FindNode(idn);
3571   if(!aNode) return false;
3572
3573   SMESH_MesherHelper aHelper( *(_impl) );
3574
3575   SMDSAbs_ElementType aType;
3576   if(theElemType==SMESH::EDGE) aType = SMDSAbs_Edge;
3577   else if(theElemType==SMESH::FACE) aType = SMDSAbs_Face;
3578   else if(theElemType==SMESH::VOLUME) aType = SMDSAbs_Volume;
3579   else aType = SMDSAbs_All;
3580
3581   return aHelper.IsMedium(aNode,aType);
3582 }
3583
3584
3585 //=============================================================================
3586 /*!
3587  * Returns number of edges for given element
3588  */
3589 //=============================================================================
3590
3591 CORBA::Long SMESH_Mesh_i::ElemNbEdges(const CORBA::Long id)
3592 {
3593   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3594   if ( aSMESHDS_Mesh == NULL ) return -1;
3595   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3596   if(!elem) return -1;
3597   return elem->NbEdges();
3598 }
3599
3600
3601 //=============================================================================
3602 /*!
3603  * Returns number of faces for given element
3604  */
3605 //=============================================================================
3606
3607 CORBA::Long SMESH_Mesh_i::ElemNbFaces(const CORBA::Long id)
3608 {
3609   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3610   if ( aSMESHDS_Mesh == NULL ) return -1;
3611   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3612   if(!elem) return -1;
3613   return elem->NbFaces();
3614 }
3615
3616 //=======================================================================
3617 //function : GetElemFaceNodes
3618 //purpose  : Returns nodes of given face (counted from zero) for given element.
3619 //=======================================================================
3620
3621 SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long  elemId,
3622                                                   CORBA::Short faceIndex)
3623 {
3624   SMESH::long_array_var aResult = new SMESH::long_array();
3625   if ( SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS() )
3626   {
3627     if ( const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(elemId) )
3628     {
3629       SMDS_VolumeTool vtool( elem );
3630       if ( faceIndex < vtool.NbFaces() )
3631       {
3632         aResult->length( vtool.NbFaceNodes( faceIndex ));
3633         const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
3634         for ( int i = 0; i < aResult->length(); ++i )
3635           aResult[ i ] = nn[ i ]->GetID();
3636       }
3637     }
3638   }
3639   return aResult._retn();
3640 }
3641
3642 //=======================================================================
3643 //function : FindElementByNodes
3644 //purpose  : Returns an element based on all given nodes.
3645 //=======================================================================
3646
3647 CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
3648 {
3649   CORBA::Long elemID(0);
3650   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
3651   {
3652     vector< const SMDS_MeshNode * > nn( nodes.length() );
3653     for ( int i = 0; i < nodes.length(); ++i )
3654       if ( !( nn[i] = mesh->FindNode( nodes[i] )))
3655         return elemID;
3656
3657     const SMDS_MeshElement* elem = mesh->FindElement( nn );
3658     if ( !elem && ( _impl->NbEdges( ORDER_QUADRATIC ) ||
3659                     _impl->NbFaces( ORDER_QUADRATIC ) ||
3660                     _impl->NbVolumes( ORDER_QUADRATIC )))
3661       elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/true );
3662
3663     if ( elem ) elemID = CORBA::Long( elem->GetID() );
3664   }
3665   return elemID;
3666 }
3667
3668 //=============================================================================
3669 /*!
3670  * Returns true if given element is polygon
3671  */
3672 //=============================================================================
3673
3674 CORBA::Boolean SMESH_Mesh_i::IsPoly(const CORBA::Long id)
3675 {
3676   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3677   if ( aSMESHDS_Mesh == NULL ) return false;
3678   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3679   if(!elem) return false;
3680   return elem->IsPoly();
3681 }
3682
3683
3684 //=============================================================================
3685 /*!
3686  * Returns true if given element is quadratic
3687  */
3688 //=============================================================================
3689
3690 CORBA::Boolean SMESH_Mesh_i::IsQuadratic(const CORBA::Long id)
3691 {
3692   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3693   if ( aSMESHDS_Mesh == NULL ) return false;
3694   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3695   if(!elem) return false;
3696   return elem->IsQuadratic();
3697 }
3698
3699
3700 //=============================================================================
3701 /*!
3702  * Returns bary center for given element
3703  */
3704 //=============================================================================
3705
3706 SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
3707 {
3708   SMESH::double_array_var aResult = new SMESH::double_array();
3709   SMESHDS_Mesh* aSMESHDS_Mesh = _impl->GetMeshDS();
3710   if ( aSMESHDS_Mesh == NULL )
3711     return aResult._retn();
3712
3713   const SMDS_MeshElement* elem = aSMESHDS_Mesh->FindElement(id);
3714   if(!elem)
3715     return aResult._retn();
3716
3717   if(elem->GetType()==SMDSAbs_Volume) {
3718     SMDS_VolumeTool aTool;
3719     if(aTool.Set(elem)) {
3720       aResult->length(3);
3721       if (!aTool.GetBaryCenter( aResult[0], aResult[1], aResult[2]) )
3722         aResult->length(0);
3723     }
3724   }
3725   else {
3726     SMDS_ElemIteratorPtr anIt = elem->nodesIterator();
3727     int nbn = 0;
3728     double x=0., y=0., z=0.;
3729     for(; anIt->more(); ) {
3730       nbn++;
3731       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIt->next());
3732       x += aNode->X();
3733       y += aNode->Y();
3734       z += aNode->Z();
3735     }
3736     if(nbn>0) {
3737       // add coordinates
3738       aResult->length(3);
3739       aResult[0] = x/nbn;
3740       aResult[1] = y/nbn;
3741       aResult[2] = z/nbn;
3742     }
3743   }
3744
3745   return aResult._retn();
3746 }
3747
3748
3749 //=============================================================================
3750 /*!
3751  * Create and publish group servants if any groups were imported or created anyhow
3752  */
3753 //=============================================================================
3754
3755 void SMESH_Mesh_i::CreateGroupServants() 
3756 {
3757   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
3758
3759   set<int> addedIDs;
3760   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
3761   while ( groupIt->more() )
3762   {
3763     ::SMESH_Group* group = groupIt->next();
3764     int            anId = group->GetGroupDS()->GetID();
3765
3766     map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(anId);
3767     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
3768       continue;
3769     addedIDs.insert( anId );
3770
3771     SMESH_GroupBase_i* aGroupImpl;
3772     TopoDS_Shape       shape;
3773     if ( SMESHDS_GroupOnGeom* groupOnGeom =
3774          dynamic_cast<SMESHDS_GroupOnGeom*>( group->GetGroupDS() ))
3775     {
3776       aGroupImpl = new SMESH_GroupOnGeom_i( SMESH_Gen_i::GetPOA(), this, anId );
3777       shape      = groupOnGeom->GetShape();
3778     }
3779     else {
3780       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
3781     }
3782
3783     // To ensure correct mapping of servant and correct reference counting in GenericObj_i
3784     SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
3785     aGroupImpl->Register();
3786
3787     SMESH::SMESH_GroupBase_var groupVar =
3788       SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
3789     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
3790
3791     // register CORBA object for persistence
3792     int nextId = _gen_i->RegisterObject( groupVar );
3793     if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
3794
3795     // publishing the groups in the study
3796     if ( !aStudy->_is_nil() ) {
3797       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
3798       _gen_i->PublishGroup( aStudy, _this(), groupVar, shapeVar, groupVar->GetName());
3799     }
3800   }
3801   if ( !addedIDs.empty() )
3802   {
3803     // python dump
3804     set<int>::iterator id = addedIDs.begin();
3805     for ( ; id != addedIDs.end(); ++id )
3806     {
3807       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(*id);
3808       int i = std::distance( _mapGroups.begin(), it );
3809       TPythonDump() << it->second << " = " << _this() << ".GetGroups()[ "<< i << " ]";
3810     }
3811   }
3812 }
3813
3814 //=============================================================================
3815 /*!
3816  * \brief Return groups cantained in _mapGroups by their IDs
3817  */
3818 //=============================================================================
3819
3820 SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
3821 {
3822   int nbGroups = groupIDs.size();
3823   SMESH::ListOfGroups_var aList = new SMESH::ListOfGroups();
3824   aList->length( nbGroups );
3825
3826   list<int>::const_iterator ids = groupIDs.begin();
3827   for ( nbGroups = 0; ids != groupIDs.end(); ++ids )
3828   {
3829     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator it = _mapGroups.find( *ids );
3830     if ( it != _mapGroups.end() && !CORBA::is_nil( it->second ))
3831       aList[nbGroups++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
3832   }
3833   aList->length( nbGroups );
3834   return aList._retn();
3835 }
3836
3837 //=============================================================================
3838 /*!
3839  * \brief Return information about imported file
3840  */
3841 //=============================================================================
3842
3843 SALOME_MED::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
3844 {
3845   SALOME_MED::MedFileInfo_var res( myFileInfo );
3846   if ( !res.operator->() ) {
3847     res = new SALOME_MED::MedFileInfo;
3848     res->fileName = "";
3849     res->fileSize = res->major = res->minor = res->release = -1;
3850   }
3851   return res._retn();
3852 }
3853
3854 //=============================================================================
3855 /*!
3856  * \brief Check and correct names of mesh groups
3857  */
3858 //=============================================================================
3859
3860 void SMESH_Mesh_i::checkGroupNames()
3861 {
3862   int nbGrp = NbGroups();
3863   if ( !nbGrp )
3864     return;
3865
3866   SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
3867   if ( aStudy->_is_nil() )
3868     return; // nothing to do
3869   
3870   SMESH::ListOfGroups* grpList = 0;
3871   // avoid dump of "GetGroups"
3872   {
3873     // store python dump into a local variable inside local scope
3874     SMESH::TPythonDump pDump; // do not delete this line of code
3875     grpList = GetGroups();
3876   }
3877
3878   for ( int gIndx = 0; gIndx < nbGrp; gIndx++ ) {
3879     SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
3880     if ( !aGrp )
3881       continue;
3882     SALOMEDS::SObject_var aGrpSO = _gen_i->ObjectToSObject( aStudy, aGrp );
3883     if ( aGrpSO->_is_nil() )
3884       continue;
3885     // correct name of the mesh group if necessary
3886     const char* guiName = aGrpSO->GetName();
3887     if ( strcmp(guiName, aGrp->GetName()) )
3888       aGrp->SetName( guiName );
3889   }
3890 }
3891
3892 //=============================================================================
3893 /*!
3894  * \brief Sets list of notebook variables used for Mesh operations separated by ":" symbol
3895  */
3896 //=============================================================================
3897 void SMESH_Mesh_i::SetParameters(const char* theParameters)
3898 {
3899   SMESH_Gen_i::GetSMESHGen()->UpdateParameters(SMESH::SMESH_Mesh::_narrow(_this()),
3900                                                CORBA::string_dup(theParameters));
3901 }
3902
3903 //=============================================================================
3904 /*!
3905  * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
3906  */
3907 //=============================================================================
3908 char* SMESH_Mesh_i::GetParameters()
3909 {
3910   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
3911   return CORBA::string_dup(gen->GetParameters(SMESH::SMESH_Mesh::_narrow(_this())));
3912 }
3913
3914 //=============================================================================
3915 /*!
3916  * \brief Returns list of notebook variables used for last Mesh operation
3917  */
3918 //=============================================================================
3919 SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
3920 {
3921   SMESH::string_array_var aResult = new SMESH::string_array();
3922   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
3923   if(gen) {
3924     char *aParameters = GetParameters();
3925     SALOMEDS::Study_ptr aStudy = gen->GetCurrentStudy();
3926     if(!aStudy->_is_nil()) {
3927       SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters); 
3928       if(aSections->length() > 0) {
3929         SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1];
3930         aResult->length(aVars.length());
3931         for(int i = 0;i < aVars.length();i++)
3932           aResult[i] = CORBA::string_dup( aVars[i]);
3933       }
3934     }
3935   }
3936   return aResult._retn();
3937 }
3938
3939 //=======================================================================
3940 //function : GetTypes
3941 //purpose  : Returns types of elements it contains
3942 //=======================================================================
3943
3944 SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
3945 {
3946   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
3947
3948   types->length( 4 );
3949   int nbTypes = 0;
3950   if (_impl->NbEdges())
3951     types[nbTypes++] = SMESH::EDGE;
3952   if (_impl->NbFaces())
3953     types[nbTypes++] = SMESH::FACE;
3954   if (_impl->NbVolumes())
3955     types[nbTypes++] = SMESH::VOLUME;
3956   if (_impl->Nb0DElements())
3957     types[nbTypes++] = SMESH::ELEM0D;
3958   types->length( nbTypes );
3959
3960   return types._retn();
3961 }
3962
3963 //=======================================================================
3964 //function : GetMesh
3965 //purpose  : Returns self
3966 //=======================================================================
3967
3968 SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh()
3969 {
3970   return SMESH::SMESH_Mesh::_duplicate( _this() );
3971 }
3972
3973 //=============================================================================
3974 /*!
3975  * \brief Returns statistic of mesh elements
3976  */
3977 //=============================================================================
3978 SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
3979 {
3980   SMESH::long_array_var aRes = new SMESH::long_array();
3981   aRes->length(SMESH::Entity_Last);
3982   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
3983     aRes[i] = 0;
3984   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
3985   if (!aMeshDS)
3986     return aRes._retn();
3987   const SMDS_MeshInfo& aMeshInfo = aMeshDS->GetMeshInfo();
3988   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
3989     aRes[i] = aMeshInfo.NbEntities((SMDSAbs_EntityType)i);
3990   return aRes._retn();
3991 }
3992
3993 //=============================================================================
3994 /*!
3995  * \brief Collect statistic of mesh elements given by iterator
3996  */
3997 //=============================================================================
3998 void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
3999                                    SMESH::long_array&         theInfo)
4000 {
4001   if (!theItr) return;
4002   while (theItr->more())
4003     theInfo[ theItr->next()->GetEntityType() ]++;
4004 }
4005
4006 //=============================================================================
4007 /*!
4008  * \brief mapping of mesh dimension into shape type
4009  */
4010 //=============================================================================
4011 static TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
4012 {
4013   TopAbs_ShapeEnum aType = TopAbs_SOLID;
4014   switch ( theDim ) {
4015   case 0: aType = TopAbs_VERTEX; break;
4016   case 1: aType = TopAbs_EDGE; break;
4017   case 2: aType = TopAbs_FACE; break;
4018   case 3:
4019   default:aType = TopAbs_SOLID; break;
4020   }
4021   return aType;
4022 }
4023
4024 //=============================================================================
4025 /*!
4026  * \brief Internal structure used to find concurent submeshes
4027  *
4028  * It represents a pair < submesh, concurent dimension >, where
4029  * 'concurrent dimension' is dimension of shape where the submesh can concurent
4030  *  with another submesh. In other words, it is dimension of a hypothesis assigned
4031  *  to submesh.
4032  */
4033 //=============================================================================
4034
4035 class SMESH_DimHyp
4036 {
4037  public:
4038   //! fileds
4039   int _dim;    //!< a dimension the algo can build (concurrent dimension)
4040   int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
4041   TopTools_MapOfShape _shapeMap;
4042   SMESH_subMesh*      _subMesh;
4043   list<const SMESHDS_Hypothesis*> _hypothesises; //!< algo is first, then its parameters
4044
4045   //! Constructors
4046   SMESH_DimHyp(const SMESH_subMesh*  theSubMesh,
4047                const int             theDim,
4048                const TopoDS_Shape&   theShape)
4049   {
4050     _subMesh = (SMESH_subMesh*)theSubMesh;
4051     SetShape( theDim, theShape );
4052   }
4053
4054   //! set shape
4055   void SetShape(const int theDim,
4056                 const TopoDS_Shape& theShape)
4057   {
4058     _dim = theDim;
4059     _ownDim = (int)SMESH_Gen::GetShapeDim(theShape);
4060     if (_dim >= _ownDim)
4061       _shapeMap.Add( theShape );
4062     else {
4063       TopExp_Explorer anExp( theShape, shapeTypeByDim(theDim) );
4064       for( ; anExp.More(); anExp.Next() )
4065         _shapeMap.Add( anExp.Current() );
4066     }
4067   }
4068
4069   //! Check sharing of sub shapes
4070   static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
4071                                const TopTools_MapOfShape& theToFind,
4072                                const TopAbs_ShapeEnum     theType)
4073   {
4074     bool isShared = false;
4075     TopTools_MapIteratorOfMapOfShape anItr( theToCheck );
4076     for (; !isShared && anItr.More(); anItr.Next() ) {
4077       const TopoDS_Shape aSubSh = anItr.Key();
4078       // check for case when concurrent dimensions are same
4079       isShared = theToFind.Contains( aSubSh );
4080       // check for subshape with concurrent dimension
4081       TopExp_Explorer anExp( aSubSh, theType );
4082       for ( ; !isShared && anExp.More(); anExp.Next() )
4083         isShared = theToFind.Contains( anExp.Current() );
4084     }
4085     return isShared;
4086   }
4087   
4088   //! check algorithms
4089   static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
4090                         const SMESHDS_Hypothesis* theA2)
4091   {
4092     if ( theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
4093          theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
4094       return false; // one of the hypothesis is not algorithm
4095     // check algorithm names (should be equal)
4096     return strcmp( theA1->GetName(), theA2->GetName() ) == 0;
4097   }
4098
4099   
4100   //! Check if subshape hypotheses are concurrent
4101   bool IsConcurrent(const SMESH_DimHyp* theOther) const
4102   {
4103     if ( _subMesh == theOther->_subMesh )
4104       return false; // same subshape - should not be
4105
4106     // if ( <own dim of either of submeshes> == <concurrent dim> &&
4107     //      any of the two submeshes is not on COMPOUND shape )
4108     //  -> no concurrency
4109     bool meIsCompound = (_subMesh->GetSubMeshDS() && _subMesh->GetSubMeshDS()->IsComplexSubmesh());
4110     bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() && theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
4111     if ( (_ownDim == _dim  || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
4112       return false;
4113
4114 //     bool checkSubShape = ( _dim >= theOther->_dim )
4115 //       ? isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(theOther->_dim) )
4116 //       : isShareSubShapes( theOther->_shapeMap, _shapeMap, shapeTypeByDim(_dim) ) ;
4117     bool checkSubShape = isShareSubShapes( _shapeMap, theOther->_shapeMap, shapeTypeByDim(_dim));
4118     if ( !checkSubShape )
4119         return false;
4120
4121     // check algorithms to be same
4122     if (!checkAlgo( _hypothesises.front(), theOther->_hypothesises.front() ))
4123       return true; // different algorithms
4124     
4125     // check hypothesises for concurrence (skip first as algorithm)
4126     int nbSame = 0;
4127     // pointers should be same, becase it is referenes from mesh hypothesis partition
4128     list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypothesises.begin();
4129     list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypothesises.end();
4130     for ( hypIt++ /*skip first as algo*/; hypIt != _hypothesises.end(); hypIt++ )
4131       if ( find( theOther->_hypothesises.begin(), otheEndIt, *hypIt ) != otheEndIt )
4132         nbSame++;
4133     // the submeshes are concurrent if their algorithms has different parameters
4134     return nbSame != theOther->_hypothesises.size() - 1;
4135   }
4136   
4137 }; // end of SMESH_DimHyp
4138
4139 typedef list<SMESH_DimHyp*> TDimHypList;
4140
4141 static void addDimHypInstance(const int               theDim, 
4142                               const TopoDS_Shape&     theShape,
4143                               const SMESH_Algo*       theAlgo,
4144                               const SMESH_subMesh*    theSubMesh,
4145                               const list <const SMESHDS_Hypothesis*>& theHypList,
4146                               TDimHypList*            theDimHypListArr )
4147 {
4148   TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
4149   if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) {
4150     SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
4151     listOfdimHyp.push_back( dimHyp );
4152   }
4153   
4154   SMESH_DimHyp* dimHyp = listOfdimHyp.back();
4155   dimHyp->_hypothesises.push_front(theAlgo);
4156   list <const SMESHDS_Hypothesis*>::const_iterator hypIt = theHypList.begin();
4157   for( ; hypIt != theHypList.end(); hypIt++ )
4158     dimHyp->_hypothesises.push_back( *hypIt );
4159 }
4160
4161 static void findConcurrents(const SMESH_DimHyp* theDimHyp,
4162                             const TDimHypList&  theListOfDimHyp,
4163                             TListOfInt&         theListOfConcurr )
4164 {
4165   TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
4166   for ( ; rIt != theListOfDimHyp.rend(); rIt++ ) {
4167     const SMESH_DimHyp* curDimHyp = *rIt;
4168     if ( curDimHyp == theDimHyp )
4169       break; // meet own dimHyp pointer in same dimension
4170     else if ( theDimHyp->IsConcurrent( curDimHyp ) )
4171       if ( find( theListOfConcurr.begin(),
4172                  theListOfConcurr.end(),
4173                  curDimHyp->_subMesh->GetId() ) == theListOfConcurr.end() )
4174         theListOfConcurr.push_back( curDimHyp->_subMesh->GetId() );
4175   }
4176 }
4177
4178 static void unionLists(TListOfInt&       theListOfId,
4179                        TListOfListOfInt& theListOfListOfId,
4180                        const int         theIndx )
4181 {
4182   TListOfListOfInt::iterator it = theListOfListOfId.begin();
4183   for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) {
4184     if ( i < theIndx )
4185       continue; //skip already treated lists
4186     // check if other list has any same submesh object
4187     TListOfInt& otherListOfId = *it;
4188     if ( find_first_of( theListOfId.begin(), theListOfId.end(),
4189                         otherListOfId.begin(), otherListOfId.end() ) == theListOfId.end() )
4190       continue;
4191          
4192     // union two lists (from source into target)
4193     TListOfInt::iterator it2 = otherListOfId.begin();
4194     for ( ; it2 != otherListOfId.end(); it2++ ) {
4195       if ( find( theListOfId.begin(), theListOfId.end(), (*it2) ) == theListOfId.end() )
4196         theListOfId.push_back(*it2);
4197     }
4198     // clear source list
4199     otherListOfId.clear();
4200   }
4201 }
4202
4203 //! free memory allocated for dimension-hypothesis objects
4204 static void removeDimHyps( TDimHypList* theArrOfList )
4205 {
4206   for (int i = 0; i < 4; i++ ) {
4207     TDimHypList& listOfdimHyp = theArrOfList[i];
4208     TDimHypList::const_iterator it = listOfdimHyp.begin();
4209     for ( ; it != listOfdimHyp.end(); it++ )
4210       delete (*it);
4211   }
4212 }
4213
4214 //=============================================================================
4215 /*!
4216  * \brief Return submesh objects list in meshing order
4217  */
4218 //=============================================================================
4219
4220 SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
4221 {
4222   SMESH::submesh_array_array_var aResult = new SMESH::submesh_array_array();
4223
4224   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
4225   if ( !aMeshDS )
4226     return aResult._retn();
4227   
4228   ::SMESH_Mesh& mesh = GetImpl();
4229   TListOfListOfInt anOrder = mesh.GetMeshOrder(); // is there already defined order?
4230   if ( !anOrder.size() ) {
4231
4232     // collect submeshes detecting concurrent algorithms and hypothesises
4233     TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
4234     
4235     map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
4236     for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) {
4237       ::SMESH_subMesh* sm = (*i_sm).second;
4238       // shape of submesh
4239       const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
4240       
4241       // list of assigned hypothesises
4242       const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
4243       // Find out dimensions where the submesh can be concurrent.
4244       // We define the dimensions by algo of each of hypotheses in hypList
4245       list <const SMESHDS_Hypothesis*>::const_iterator hypIt = hypList.begin();
4246       for( ; hypIt != hypList.end(); hypIt++ ) {
4247         SMESH_Algo* anAlgo = 0;
4248         const SMESH_Hypothesis* hyp = dynamic_cast<const SMESH_Hypothesis*>(*hypIt);
4249         if ( hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
4250           // hyp it-self is algo
4251           anAlgo = (SMESH_Algo*)dynamic_cast<const SMESH_Algo*>(hyp);
4252         else {
4253           // try to find algorithm with help of subshapes
4254           TopExp_Explorer anExp( aSubMeshShape, shapeTypeByDim(hyp->GetDim()) );
4255           for ( ; !anAlgo && anExp.More(); anExp.Next() )
4256             anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
4257         }
4258         if (!anAlgo)
4259           continue; // no assigned algorithm to current submesh
4260
4261         int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
4262         // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDescretBoundary())
4263
4264         // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm
4265         for ( int j = anAlgo->NeedDescretBoundary() ? dim : 1, jn = dim; j <= jn; j++ )
4266           addDimHypInstance( j, aSubMeshShape, anAlgo, sm, hypList, dimHypListArr );
4267       }
4268     } // end iterations on submesh
4269     
4270     // iterate on created dimension-hypotheses and check for concurrents
4271     for ( int i = 0; i < 4; i++ ) {
4272       const list<SMESH_DimHyp*>& listOfDimHyp = dimHypListArr[i];
4273       // check for concurrents in own and other dimensions (step-by-step)
4274       TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
4275       for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) {
4276         const SMESH_DimHyp* dimHyp = *dhIt;
4277         TListOfInt listOfConcurr;
4278         // looking for concurrents and collect into own list
4279         for ( int j = i; j < 4; j++ )
4280           findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr );
4281         // check if any concurrents found
4282         if ( listOfConcurr.size() > 0 ) {
4283           // add own submesh to list of concurrent
4284           listOfConcurr.push_front( dimHyp->_subMesh->GetId() );
4285           anOrder.push_back( listOfConcurr );
4286         }
4287       }
4288     }
4289     
4290     removeDimHyps(dimHypListArr);
4291     
4292     // now, minimise the number of concurrent groups
4293     // Here we assume that lists of submhes can has same submesh
4294     // in case of multi-dimension algorithms, as result
4295     //  list with common submesh have to be union into one list
4296     int listIndx = 0;
4297     TListOfListOfInt::iterator listIt = anOrder.begin();
4298     for(; listIt != anOrder.end(); listIt++, listIndx++ )
4299       unionLists( *listIt,  anOrder, listIndx + 1 );
4300   }
4301   // convert submesh ids into interface instances
4302   //  and dump command into python
4303   convertMeshOrder( anOrder, aResult, true );
4304
4305   return aResult._retn();
4306 }
4307
4308 //=============================================================================
4309 /*!
4310  * \brief find common submeshes with given submesh
4311  * \param theSubMeshList list of already collected submesh to check
4312  * \param theSubMesh given submesh to intersect with other
4313  * \param theCommonSubMeshes collected common submeshes
4314  */
4315 //=============================================================================
4316
4317 static void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
4318                                const SMESH_subMesh*        theSubMesh,
4319                                set<const SMESH_subMesh*>&  theCommon )
4320 {
4321   if ( !theSubMesh )
4322     return;
4323   list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
4324   for ( ; it != theSubMeshList.end(); it++ )
4325     theSubMesh->FindIntersection( *it, theCommon );
4326   theSubMeshList.push_back( theSubMesh );
4327   //theCommon.insert( theSubMesh );
4328 }
4329
4330 //=============================================================================
4331 /*!
4332  * \brief Set submesh object order
4333  * \param theSubMeshArray submesh array order
4334  */
4335 //=============================================================================
4336
4337 ::CORBA::Boolean SMESH_Mesh_i::SetMeshOrder(const SMESH::submesh_array_array& theSubMeshArray)
4338 {
4339   bool res = false;
4340   ::SMESH_Mesh& mesh = GetImpl();
4341
4342   TPythonDump aPythonDump; // prevent dump of called methods
4343   aPythonDump << "isDone = " << _this() << ".SetMeshOrder( [ ";
4344
4345   TListOfListOfInt subMeshOrder;
4346   for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
4347   {
4348     const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
4349     TListOfInt subMeshIds;
4350     aPythonDump << "[ ";
4351     // Collect subMeshes which should be clear
4352     //  do it list-by-list, because modification of submesh order
4353     //  take effect between concurrent submeshes only
4354     set<const SMESH_subMesh*> subMeshToClear;
4355     list<const SMESH_subMesh*> subMeshList;
4356     for ( int j = 0, jn = aSMArray.length(); j < jn; j++ )
4357     {
4358       const SMESH::SMESH_subMesh_var subMesh = SMESH::SMESH_subMesh::_duplicate(aSMArray[j]);
4359       if ( j > 0 )
4360         aPythonDump << ", ";
4361       aPythonDump << subMesh;
4362       subMeshIds.push_back( subMesh->GetId() );
4363       // detect common parts of submeshes
4364       if ( _mapSubMesh.find(subMesh->GetId()) != _mapSubMesh.end() )
4365         findCommonSubMesh( subMeshList, _mapSubMesh[ subMesh->GetId() ], subMeshToClear );
4366     }
4367     aPythonDump << " ]";
4368     subMeshOrder.push_back( subMeshIds );
4369
4370     // clear collected submeshes
4371     set<const SMESH_subMesh*>::iterator clrIt = subMeshToClear.begin();
4372     for ( ; clrIt != subMeshToClear.end(); clrIt++ ) {
4373       SMESH_subMesh* sm = (SMESH_subMesh*)*clrIt;
4374         if ( sm )
4375           sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
4376         // ClearSubMesh( *clrIt );
4377       }
4378   }
4379   aPythonDump << " ])";
4380
4381   mesh.SetMeshOrder( subMeshOrder );
4382   res = true;
4383   
4384   return res;
4385 }
4386
4387 //=============================================================================
4388 /*!
4389  * \brief Convert submesh ids into submesh interfaces
4390  */
4391 //=============================================================================
4392
4393 void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt&     theIdsOrder,
4394                                      SMESH::submesh_array_array& theResOrder,
4395                                      const bool                  theIsDump)
4396 {
4397   int nbSet = theIdsOrder.size();
4398   TPythonDump aPythonDump; // prevent dump of called methods
4399   if ( theIsDump )
4400     aPythonDump << "[ ";
4401   theResOrder.length(nbSet);
4402   TListOfListOfInt::const_iterator it = theIdsOrder.begin();
4403   int listIndx = 0;
4404   for( ; it != theIdsOrder.end(); it++ ) {
4405     // translate submesh identificators into submesh objects
4406     //  takeing into account real number of concurrent lists
4407     const TListOfInt& aSubOrder = (*it);
4408     if (!aSubOrder.size())
4409       continue;
4410     if ( theIsDump )
4411       aPythonDump << "[ ";
4412     // convert shape indeces into interfaces
4413     SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
4414     aResSubSet->length(aSubOrder.size());
4415     TListOfInt::const_iterator subIt = aSubOrder.begin();
4416     for( int j = 0; subIt != aSubOrder.end(); subIt++ ) {
4417       if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
4418         continue;
4419       SMESH::SMESH_subMesh_var subMesh =
4420         SMESH::SMESH_subMesh::_duplicate( _mapSubMeshIor[*subIt] );
4421       if ( theIsDump ) {
4422         if ( j > 0 )
4423           aPythonDump << ", ";
4424         aPythonDump << subMesh;
4425       }
4426       aResSubSet[ j++ ] = subMesh;
4427     }
4428     if ( theIsDump )
4429       aPythonDump << " ]";
4430     theResOrder[ listIndx++ ] = aResSubSet;
4431   }
4432   // correct number of lists
4433   theResOrder.length( listIndx );
4434
4435   if ( theIsDump ) {
4436     // finilise python dump
4437     aPythonDump << " ]";
4438     aPythonDump << " = " << _this() << ".GetMeshOrder()";
4439   }
4440 }
4441
4442 //================================================================================
4443 //
4444 // Implementation of SMESH_MeshPartDS
4445 //
4446 SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
4447   SMESHDS_Mesh( /*theMeshID=*/-1, /*theIsEmbeddedMode=*/true)
4448 {
4449   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
4450   SMESH_Mesh_i*       mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
4451
4452   _meshDS = mesh_i->GetImpl().GetMeshDS();
4453
4454   SetPersistentId( _meshDS->GetPersistentId() );
4455
4456   if ( mesh_i == SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
4457   {
4458     // <meshPart> is the whole mesh
4459     myInfo = _meshDS->GetMeshInfo(); // copy mesh info;
4460     // copy groups
4461     set<SMESHDS_GroupBase*>& myGroupSet = const_cast<set<SMESHDS_GroupBase*>&>( GetGroups() );
4462     myGroupSet = _meshDS->GetGroups();
4463   }
4464   else
4465   {
4466     TMeshInfo tmpInfo;
4467     SMESH::long_array_var           anIDs = meshPart->GetIDs();
4468     SMESH::array_of_ElementType_var types = meshPart->GetTypes();
4469     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
4470     {
4471       for (int i=0; i < anIDs->length(); i++)
4472         if ( const SMDS_MeshNode * n = _meshDS->FindNode(anIDs[i]))
4473           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
4474             tmpInfo.Add( n );
4475     }
4476     else
4477     {
4478       for (int i=0; i < anIDs->length(); i++)
4479         if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
4480           if ( _elements[ e->GetType() ].insert( e ).second )
4481           {
4482             tmpInfo.Add( e );
4483             SMDS_ElemIteratorPtr nIt = e->nodesIterator();
4484             while ( nIt->more() )
4485             {
4486               const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
4487               if ( _elements[ SMDSAbs_Node ].insert( n ).second )
4488                 tmpInfo.Add( n );
4489             }
4490           }
4491     }
4492     myInfo = tmpInfo;
4493
4494     _meshDS = 0; // to enforce iteration on _elements and _nodes
4495   }
4496 }
4497 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementsIterator(SMDSAbs_ElementType type) const
4498 {
4499   typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
4500   if ( type == SMDSAbs_All && !_meshDS )
4501   {
4502     typedef vector< SMDS_ElemIteratorPtr > TIterVec;
4503     TIterVec iterVec;
4504     for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
4505       if ( !_elements[i].empty() && i != SMDSAbs_Node )
4506         iterVec.push_back
4507           ( SMDS_ElemIteratorPtr( new TIter( _elements[i].begin(), _elements[i].end() )));
4508
4509     typedef SMDS_IteratorOnIterators<const SMDS_MeshElement*, TIterVec > TIterOnIters;
4510     return SMDS_ElemIteratorPtr( new TIterOnIters( iterVec ));
4511   }
4512   return _meshDS ? _meshDS->elementsIterator(type) : SMDS_ElemIteratorPtr
4513       ( new TIter( _elements[type].begin(), _elements[type].end() ));
4514 }
4515 #define _GET_ITER_DEFINE( iterType, methName, elem, elemType)                       \
4516   iterType SMESH_MeshPartDS::methName( bool idInceasingOrder) const                 \
4517   {                                                                                 \
4518     typedef SMDS_SetIterator<const elem*, TIDSortedElemSet::const_iterator > TIter; \
4519     return _meshDS ? _meshDS->methName(idInceasingOrder) : iterType                 \
4520       ( new TIter( _elements[elemType].begin(), _elements[elemType].end() ));       \
4521   }
4522 _GET_ITER_DEFINE( SMDS_NodeIteratorPtr, nodesIterator, SMDS_MeshNode, SMDSAbs_Node )
4523 _GET_ITER_DEFINE( SMDS_0DElementIteratorPtr, elements0dIterator, SMDS_Mesh0DElement, SMDSAbs_0DElement)
4524 _GET_ITER_DEFINE( SMDS_EdgeIteratorPtr, edgesIterator, SMDS_MeshEdge, SMDSAbs_Edge )
4525 _GET_ITER_DEFINE( SMDS_FaceIteratorPtr, facesIterator, SMDS_MeshFace, SMDSAbs_Face )
4526 _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDSAbs_Volume)
4527 #undef _GET_ITER_DEFINE
4528 //
4529 // END Implementation of SMESH_MeshPartDS
4530 //
4531 //================================================================================