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