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