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