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