Salome HOME
ebdd1052c2e599827517a3f5788f01985711aab8
[modules/smesh.git] / src / SMESH_I / SMESH_Group_i.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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
23 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's classes
24 //  File   : SMESH_Group_i.cxx
25 //  Author : Sergey ANIKIN, OCC
26 //  Module : SMESH
27 //
28 #include "SMESH_Group_i.hxx"
29
30 #include "SMDSAbs_ElementType.hxx"
31 #include "SMESHDS_Group.hxx"
32 #include "SMESHDS_GroupOnFilter.hxx"
33 #include "SMESHDS_GroupOnGeom.hxx"
34 #include "SMESH_Comment.hxx"
35 #include "SMESH_Filter_i.hxx"
36 #include "SMESH_Gen_i.hxx"
37 #include "SMESH_Group.hxx"
38 #include "SMESH_Mesh_i.hxx"
39 #include "SMESH_PythonDump.hxx"
40 #include "SMESH_PreMeshInfo.hxx"
41
42 #include CORBA_SERVER_HEADER(SMESH_Filter)
43
44 #include "utilities.h"
45
46 using namespace SMESH;
47
48 //=============================================================================
49 /*!
50  *  
51  */
52 //=============================================================================
53
54 SMESH_GroupBase_i::SMESH_GroupBase_i( PortableServer::POA_ptr thePOA,
55                                       SMESH_Mesh_i*           theMeshServant,
56                                       const int               theLocalID )
57 : SALOME::GenericObj_i( thePOA ),
58   myMeshServant( theMeshServant ), 
59   myLocalID( theLocalID ),
60   myNbNodes(-1),
61   myGroupDSTic(0),
62   myPreMeshInfo(NULL)
63 {
64   // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i,
65   // servant activation is performed by SMESH_Mesh_i::createGroup()
66   // thePOA->activate_object( this );
67 }
68
69 SMESH_Group_i::SMESH_Group_i( PortableServer::POA_ptr thePOA,
70                               SMESH_Mesh_i*           theMeshServant,
71                               const int               theLocalID )
72      : SALOME::GenericObj_i( thePOA ),
73        SMESH_GroupBase_i( thePOA, theMeshServant, theLocalID )
74 {
75   //MESSAGE("SMESH_Group_i; this = "<<this );
76 }
77
78 SMESH_GroupOnGeom_i::SMESH_GroupOnGeom_i( PortableServer::POA_ptr thePOA,
79                                           SMESH_Mesh_i*           theMeshServant,
80                                           const int               theLocalID )
81      : SALOME::GenericObj_i( thePOA ),
82        SMESH_GroupBase_i( thePOA, theMeshServant, theLocalID )
83 {
84   //MESSAGE("SMESH_GroupOnGeom_i; this = "<<this );
85 }
86
87 SMESH_GroupOnFilter_i::SMESH_GroupOnFilter_i( PortableServer::POA_ptr thePOA,
88                                               SMESH_Mesh_i*           theMeshServant,
89                                               const int               theLocalID )
90   : SALOME::GenericObj_i( thePOA ),
91     SMESH_GroupBase_i( thePOA, theMeshServant, theLocalID )
92 {
93   //MESSAGE("SMESH_GroupOnGeom_i; this = "<<this );
94 }
95
96 //=============================================================================
97 /*!
98  *  
99  */
100 //=============================================================================
101
102 SMESH_GroupBase_i::~SMESH_GroupBase_i()
103 {
104   if ( myPreMeshInfo ) delete myPreMeshInfo; myPreMeshInfo = NULL;
105 }
106
107 //=======================================================================
108 //function : GetSmeshGroup
109 //purpose  : 
110 //=======================================================================
111
112 ::SMESH_Group* SMESH_GroupBase_i::GetSmeshGroup() const
113 {
114   if ( myMeshServant ) {
115     ::SMESH_Mesh& aMesh = myMeshServant->GetImpl();
116     return aMesh.GetGroup(myLocalID);
117   }
118   return 0;
119 }
120
121 //=======================================================================
122 //function : GetGroupDS
123 //purpose  : 
124 //=======================================================================
125
126 SMESHDS_GroupBase* SMESH_GroupBase_i::GetGroupDS() const
127 {
128   ::SMESH_Group* aGroup = GetSmeshGroup();
129   if ( aGroup )
130     return aGroup->GetGroupDS();
131   return 0;
132 }
133
134 //=============================================================================
135 /*!
136  *  
137  */
138 //=============================================================================
139
140 void SMESH_GroupBase_i::SetName( const char* theName )
141 {
142   // Perform renaming
143   ::SMESH_Group* aGroup = GetSmeshGroup();
144   if (!aGroup) {
145     MESSAGE("can't set name of a vague group");
146     return;
147   }
148
149   if ( aGroup->GetName() && !strcmp( aGroup->GetName(), theName ) )
150     return; // nothing to rename
151
152   aGroup->SetName(theName);
153
154   // Update group name in a study
155   SMESH_Gen_i*              aGen = myMeshServant->GetGen();
156   SALOMEDS::Study_var      aStudy = aGen->GetCurrentStudy();
157   SMESH::SMESH_GroupBase_var aGrp = _this();
158   SALOMEDS::SObject_var      anSO = aGen->ObjectToSObject( aStudy, aGrp );
159   if ( !anSO->_is_nil() )
160   {
161     aGen->SetName( anSO, theName );
162
163     // Update Python script
164     TPythonDump() <<  anSO << ".SetName( '" << theName << "' )";
165   }
166 }
167
168 //=============================================================================
169 /*!
170  *  
171  */
172 //=============================================================================
173
174 char* SMESH_GroupBase_i::GetName()
175 {
176   ::SMESH_Group* aGroup = GetSmeshGroup();
177   if (aGroup)
178     return CORBA::string_dup (aGroup->GetName());
179   MESSAGE("get name of a vague group");
180   return CORBA::string_dup( "NO_NAME" );
181 }
182
183 //=============================================================================
184 /*!
185  *  
186  */
187 //=============================================================================
188
189 SMESH::ElementType SMESH_GroupBase_i::GetType()
190 {
191   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
192   if (aGroupDS) {
193     SMDSAbs_ElementType aSMDSType = aGroupDS->GetType();
194     SMESH::ElementType aType;
195     switch (aSMDSType) {
196     case SMDSAbs_Node:      aType = SMESH::NODE;   break;
197     case SMDSAbs_Edge:      aType = SMESH::EDGE;   break;
198     case SMDSAbs_Face:      aType = SMESH::FACE;   break;
199     case SMDSAbs_Volume:    aType = SMESH::VOLUME; break;
200     case SMDSAbs_0DElement: aType = SMESH::ELEM0D; break;
201     case SMDSAbs_Ball:      aType = SMESH::BALL;   break;
202     default:                aType = SMESH::ALL;    break;
203     }
204     return aType;
205   }
206   MESSAGE("get type of a vague group");
207   return SMESH::ALL;
208 }
209
210
211 //=============================================================================
212 /*!
213  *  
214  */
215 //=============================================================================
216
217 CORBA::Long SMESH_GroupBase_i::Size()
218 {
219   if ( myPreMeshInfo )
220     return GetType() == SMESH::NODE ? myPreMeshInfo->NbNodes() : myPreMeshInfo->NbElements();
221
222   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
223   if (aGroupDS)
224     return aGroupDS->Extent();
225   MESSAGE("get size of a vague group");
226   return 0;
227 }
228
229 //=============================================================================
230 /*!
231  *  
232  */
233 //=============================================================================
234
235 CORBA::Boolean SMESH_GroupBase_i::IsEmpty()
236 {
237   if ( myPreMeshInfo )
238     return Size() == 0;
239
240   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
241   if (aGroupDS)
242     return aGroupDS->IsEmpty();
243   MESSAGE("checking IsEmpty of a vague group");
244   return true;
245 }
246
247 //=============================================================================
248 /*!
249  *  
250  */
251 //=============================================================================
252
253 void SMESH_Group_i::Clear()
254 {
255   if ( myPreMeshInfo )
256     myPreMeshInfo->FullLoadFromFile();
257
258   // Update Python script
259   TPythonDump() << SMESH::SMESH_Group_var(_this()) << ".Clear()";
260
261   // Clear the group
262   SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( GetGroupDS() );
263   if (aGroupDS) {
264     aGroupDS->Clear();
265     return;
266   }
267   MESSAGE("attempt to clear a vague group");
268 }
269
270 //=============================================================================
271 /*!
272  *  
273  */
274 //=============================================================================
275
276 CORBA::Boolean SMESH_GroupBase_i::Contains( CORBA::Long theID )
277 {
278   if ( myPreMeshInfo )
279     myPreMeshInfo->FullLoadFromFile();
280
281   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
282   if (aGroupDS)
283     return aGroupDS->Contains(theID);
284   MESSAGE("attempt to check contents of a vague group");
285   return false;
286 }
287
288 //=============================================================================
289 /*!
290  *  
291  */
292 //=============================================================================
293
294 CORBA::Long SMESH_Group_i::Add( const SMESH::long_array& theIDs )
295 {
296   if ( myPreMeshInfo )
297     myPreMeshInfo->FullLoadFromFile();
298
299   // Update Python script
300   TPythonDump() << "nbAdd = " << SMESH::SMESH_Group_var(_this()) << ".Add( " << theIDs << " )";
301
302   // Add elements to the group
303   SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( GetGroupDS() );
304   if (aGroupDS) {
305     int nbAdd = 0;
306     for (int i = 0; i < theIDs.length(); i++) {
307       int anID = (int) theIDs[i];
308       if (aGroupDS->Add(anID))
309         nbAdd++;
310     }
311     return nbAdd;
312   }
313   MESSAGE("attempt to add elements to a vague group");
314   return 0;
315 }
316
317 //=============================================================================
318 /*!
319  *  
320  */
321 //=============================================================================
322
323 CORBA::Long SMESH_Group_i::Remove( const SMESH::long_array& theIDs )
324 {
325   if ( myPreMeshInfo )
326     myPreMeshInfo->FullLoadFromFile();
327
328   // Update Python script
329   TPythonDump() << "nbDel = " << SMESH::SMESH_Group_var(_this())
330                 << ".Remove( " << theIDs << " )";
331
332   // Remove elements from the group
333   SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( GetGroupDS() );
334   if (aGroupDS) {
335     int nbDel = 0;
336     for (int i = 0; i < theIDs.length(); i++) {
337       int anID = (int) theIDs[i];
338       if (aGroupDS->Remove(anID))
339         nbDel++;
340     }
341     return nbDel;
342   }
343   MESSAGE("attempt to remove elements from a vague group");
344   return 0;
345 }
346
347 //=============================================================================
348 /*!
349  *  
350  */
351 //=============================================================================
352
353 typedef bool (SMESHDS_Group::*TFunChangeGroup)(const int);
354
355 CORBA::Long 
356 ChangeByPredicate( SMESH::Predicate_i* thePredicate,
357                    SMESHDS_GroupBase*  theGroupBase,
358                    TFunChangeGroup     theFun)
359 {
360   CORBA::Long aNb = 0;
361   if(SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>(theGroupBase)){
362     SMESH::Controls::Filter::TIdSequence aSequence;
363     const SMDS_Mesh* aMesh = theGroupBase->GetMesh();
364     SMESH::Filter_i::GetElementsId(thePredicate,aMesh,aSequence);
365     
366     CORBA::Long i = 0, iEnd = aSequence.size();
367     for(; i < iEnd; i++)
368       if((aGroupDS->*theFun)(aSequence[i]))
369         aNb++;
370     return aNb;
371   }
372   return aNb;
373 }
374
375 CORBA::Long 
376 SMESH_Group_i::
377 AddByPredicate( SMESH::Predicate_ptr thePredicate )
378 {
379   if ( myPreMeshInfo )
380     myPreMeshInfo->FullLoadFromFile();
381
382   if(SMESH::Predicate_i* aPredicate = SMESH::GetPredicate(thePredicate)){
383     TPythonDump() << SMESH::SMESH_Group_var(_this())
384                   << ".AddByPredicate( " << aPredicate << " )";
385     return ChangeByPredicate( aPredicate, GetGroupDS(), &SMESHDS_Group::Add );
386   }
387   return 0;
388 }
389
390 CORBA::Long 
391 SMESH_Group_i::
392 RemoveByPredicate( SMESH::Predicate_ptr thePredicate )
393 {
394   if ( myPreMeshInfo )
395     myPreMeshInfo->FullLoadFromFile();
396
397   if(SMESH::Predicate_i* aPredicate = SMESH::GetPredicate(thePredicate)){
398     TPythonDump() << SMESH::SMESH_Group_var(_this())
399                   << ".RemoveByPredicate( " << aPredicate << " )";
400     return ChangeByPredicate(aPredicate,GetGroupDS(),&SMESHDS_Group::Remove);
401   }
402   return 0;
403 }
404
405 CORBA::Long SMESH_Group_i::AddFrom( SMESH::SMESH_IDSource_ptr theSource )
406 {
407   if ( myPreMeshInfo )
408     myPreMeshInfo->FullLoadFromFile();
409
410   TPythonDump pd;
411   long prevNb = Size();
412   SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( GetGroupDS() );
413   if (aGroupDS) {
414     if ( SMDS_ElemIteratorPtr elemIt = SMESH_Mesh_i::GetElements( theSource, GetType() ))
415       while ( elemIt->more() )
416         aGroupDS->SMDSGroup().Add( elemIt->next() );
417   }
418
419   // Update Python script
420   pd << "nbAdd = " << SMESH::SMESH_Group_var(_this()) << ".AddFrom( " << theSource << " )";
421
422   return prevNb - Size();
423 }
424
425 //=============================================================================
426 /*!
427  *  
428  */
429 //=============================================================================
430
431 CORBA::Long SMESH_GroupBase_i::GetID( CORBA::Long theIndex )
432 {
433   if ( myPreMeshInfo )
434     myPreMeshInfo->FullLoadFromFile();
435
436   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
437   if (aGroupDS)
438     return aGroupDS->GetID(theIndex);
439   MESSAGE("attempt to iterate on a vague group");
440   return -1;
441 }
442
443 //=============================================================================
444 /*!
445  *  
446  */
447 //=============================================================================
448
449 SMESH::long_array* SMESH_GroupBase_i::GetListOfID()
450 {
451   if ( myPreMeshInfo )
452     myPreMeshInfo->FullLoadFromFile();
453
454   SMESH::long_array_var aRes = new SMESH::long_array();
455   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
456   if (aGroupDS)
457   {
458     int aSize = aGroupDS->Extent();
459     aRes->length(aSize);
460     for (int i = 0; i < aSize; i++)
461       aRes[i] = aGroupDS->GetID(i+1);
462
463     if ( 0 < aSize && aSize < 100 ) // for comfortable testing ;)
464       std::sort( &aRes[0], &aRes[0]+aSize );
465   }
466   MESSAGE("get list of IDs of a vague group");
467   return aRes._retn();
468 }
469
470 namespace
471 {
472   //================================================================================
473   /*!
474    * \brief return nodes of elements pointered by iterator
475    */
476   //================================================================================
477
478   void getNodesOfElements(SMDS_ElemIteratorPtr        elemIt,
479                           set<const SMDS_MeshNode* >& nodes)
480   {
481     while ( elemIt->more() )
482     {
483       const SMDS_MeshElement* e = elemIt->next();
484       nodes.insert( e->begin_nodes(), e->end_nodes() );
485     }
486   }
487 }
488   
489 //================================================================================
490 /*!
491  * \brief return the number of nodes of cells included to the group
492  */
493 //================================================================================
494
495 CORBA::Long SMESH_GroupBase_i::GetNumberOfNodes()
496 {
497   if ( GetType() == SMESH::NODE )
498     return Size();
499
500   if ( myPreMeshInfo )
501     myPreMeshInfo->FullLoadFromFile();
502
503   if ( SMESHDS_GroupBase* g = GetGroupDS())
504   {
505     if ( myNbNodes < 0 || g->GetTic() != myGroupDSTic )
506     {      
507       set<const SMDS_MeshNode* > nodes;
508       getNodesOfElements( g->GetElements(), nodes );
509       myNbNodes = nodes.size();
510       myGroupDSTic = g->GetTic();
511     }
512   }
513   return myNbNodes;
514 }
515
516 //================================================================================
517 /*!
518  * \brief Return true if GetNumberOfNodes() won't take a long time for computation
519  */
520 //================================================================================
521
522 CORBA::Boolean SMESH_GroupBase_i::IsNodeInfoAvailable()
523 {
524   if ( GetType() == SMESH::NODE/* || Size() < 100000 */)
525     return true;
526   if ( myPreMeshInfo )
527     return false;
528   if ( SMESHDS_GroupBase* g = GetGroupDS())
529     return ( myNbNodes > -1 && g->GetTic() == myGroupDSTic);
530   return false;
531 }
532
533 //================================================================================
534 /*!
535  * \brief Return IDs of nodes of cells included to the group
536  */
537 //================================================================================
538
539 SMESH::long_array* SMESH_GroupBase_i::GetNodeIDs()
540 {
541   if ( GetType() == SMESH::NODE )
542     return GetListOfID();
543
544   if ( myPreMeshInfo )
545     myPreMeshInfo->FullLoadFromFile();
546
547   SMESH::long_array_var aRes = new SMESH::long_array();
548   if ( SMESHDS_GroupBase* g = GetGroupDS())
549   {
550     set<const SMDS_MeshNode* > nodes;
551     getNodesOfElements( g->GetElements(), nodes );
552     aRes->length( nodes.size() );
553     set<const SMDS_MeshNode*>::iterator nIt = nodes.begin(), nEnd = nodes.end();
554     for ( int i = 0; nIt != nEnd; ++nIt, ++i )
555       aRes[i] = (*nIt)->GetID();
556   }
557   return aRes._retn();
558 }
559
560 //=============================================================================
561 /*!
562  *  
563  */
564 //=============================================================================
565 SMESH::SMESH_Mesh_ptr SMESH_GroupBase_i::GetMesh()
566 {
567   SMESH::SMESH_Mesh_var aMesh;
568   if ( myMeshServant )
569     aMesh = myMeshServant->_this();
570   return aMesh._retn();
571 }
572
573 //=======================================================================
574 //function : GetShape
575 //purpose  : 
576 //=======================================================================
577
578 GEOM::GEOM_Object_ptr SMESH_GroupOnGeom_i::GetShape()
579 {
580   GEOM::GEOM_Object_var aGeomObj;
581   SMESHDS_GroupOnGeom* aGroupDS = dynamic_cast<SMESHDS_GroupOnGeom*>( GetGroupDS() );
582   if ( aGroupDS ) {
583     SMESH_Gen_i* aGen = GetMeshServant()->GetGen();
584     aGeomObj = aGen->ShapeToGeomObject( aGroupDS->GetShape() );
585   }
586   return aGeomObj._retn();
587 }
588
589 //=============================================================================
590 /*!
591  *
592  */
593 //=============================================================================
594 SALOMEDS::Color SMESH_GroupBase_i::GetColor()
595 {
596   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
597   if (aGroupDS)
598   {
599     Quantity_Color aQColor = aGroupDS->GetColor();
600     SALOMEDS::Color aColor;
601     aColor.R = aQColor.Red();
602     aColor.G = aQColor.Green();
603     aColor.B = aQColor.Blue();
604
605     return aColor;
606   }
607   MESSAGE("get color of a group");
608   return SALOMEDS::Color();
609 }
610
611 //=============================================================================
612 /*!
613  *
614  */
615 //=============================================================================
616 void SMESH_GroupBase_i::SetColor(const SALOMEDS::Color& color)
617 {
618   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
619   if (aGroupDS)
620   {
621     Quantity_Color aQColor( color.R, color.G, color.B, Quantity_TOC_RGB );
622     Quantity_Color oldColor = aGroupDS->GetColor();
623     if ( oldColor != aQColor )
624     {
625       aGroupDS->SetColor(aQColor);
626       TPythonDump()<< SMESH::SMESH_GroupBase_var(_this())
627                    << ".SetColor( SALOMEDS.Color( "
628                    <<color.R<<", "<<color.G<<", "<<color.B<<" ))";
629     }
630   }
631 }
632
633 //=============================================================================
634 /*!
635  *
636  */
637 //=============================================================================
638 CORBA::Long SMESH_GroupBase_i::GetColorNumber()
639 {
640   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
641   if (aGroupDS)
642     return aGroupDS->GetColorGroup();
643   MESSAGE("get color number of a group");
644   return 0;
645 }
646
647 //=============================================================================
648 /*!
649  *
650  */
651 //=============================================================================
652 void SMESH_GroupBase_i::SetColorNumber(CORBA::Long color)
653 {
654   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
655   if (aGroupDS)
656   {
657     aGroupDS->SetColorGroup(color);
658     TPythonDump()<<SMESH::SMESH_GroupBase_var(_this())<<".SetColorNumber( "<<color<<" )";
659   }
660   MESSAGE("set color number of a group");
661   return ;
662 }
663
664 //=============================================================================
665 /*
666  * Returns number of mesh elements of each \a SMESH::EntityType
667  * Result array of number of elements per \a SMESH::EntityType
668  * Inherited from SMESH_IDSource
669  */
670 //=============================================================================
671
672 SMESH::long_array* SMESH_GroupBase_i::GetMeshInfo()
673 {
674   if ( myPreMeshInfo )
675     return myPreMeshInfo->GetMeshInfo();
676
677   SMESH::long_array_var aRes = new SMESH::long_array();
678   aRes->length(SMESH::Entity_Last);
679   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
680     aRes[i] = 0;
681
682   if ( SMESHDS_GroupBase* g = GetGroupDS())
683   {
684     if ( g->GetType() == SMDSAbs_Node || ( myNbNodes > -1 && g->GetTic() == myGroupDSTic))
685       aRes[ SMDSEntity_Node ] = GetNumberOfNodes();
686
687     if ( g->GetType() != SMDSAbs_Node )
688       SMESH_Mesh_i::CollectMeshInfo( g->GetElements(), aRes);
689   }
690
691   return aRes._retn();
692 }
693
694 //=============================================================================
695 /*
696  * Returns number of mesh elements of each \a ElementType
697  */
698 //=============================================================================
699
700 SMESH::long_array* SMESH_GroupBase_i::GetNbElementsByType()
701 {
702   SMESH::long_array_var aRes = new SMESH::long_array();
703   aRes->length(SMESH::NB_ELEMENT_TYPES);
704   for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
705     aRes[ i ] = 0;
706
707   if ( myPreMeshInfo )
708     aRes[ GetType() ] = myPreMeshInfo->NbElements( SMDSAbs_ElementType( GetType() ));
709   else
710     aRes[ GetType() ] = Size();
711
712   return aRes._retn();  
713 }
714
715 //=======================================================================
716 //function : GetIDs
717 //purpose  : Returns ids of members
718 //=======================================================================
719
720 SMESH::long_array* SMESH_GroupBase_i::GetIDs()
721 {
722   return GetListOfID();
723 }
724
725 //=======================================================================
726 //function : GetTypes
727 //purpose  : Returns types of elements it contains
728 //=======================================================================
729
730 SMESH::array_of_ElementType* SMESH_GroupBase_i::GetTypes()
731 {
732   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
733   if ( !IsEmpty() )
734   {
735     types->length( 1 );
736     types[0] = GetType();
737   }
738   return types._retn();
739 }
740
741 //=======================================================================
742 //function : IsMeshInfoCorrect
743 //purpose  : * Returns false if GetMeshInfo() returns incorrect information that may
744 //           * happen if mesh data is not yet fully loaded from the file of study.
745 //=======================================================================
746
747 bool SMESH_GroupBase_i::IsMeshInfoCorrect()
748 {
749   return myPreMeshInfo ? myPreMeshInfo->IsMeshInfoCorrect() : true;
750 }
751
752 //================================================================================
753 /*!
754  * \brief Retrieves the predicate from the filter
755  */
756 //================================================================================
757
758 SMESH_PredicatePtr SMESH_GroupOnFilter_i::GetPredicate( SMESH::Filter_ptr filter )
759 {
760   SMESH_PredicatePtr predicate;
761
762   if ( SMESH::Filter_i* filt_i = SMESH::DownCast< SMESH::Filter_i* >( filter ))
763     if ( SMESH::Predicate_i* predic_i= filt_i->GetPredicate_i() )
764       predicate = predic_i->GetPredicate();
765
766   return predicate;
767 }
768
769 //================================================================================
770 /*!
771  * \brief Sets the filter defining group contents
772  */
773 //================================================================================
774
775 void SMESH_GroupOnFilter_i::SetFilter(SMESH::Filter_ptr theFilter)
776 {
777   if ( myPreMeshInfo )
778     myPreMeshInfo->FullLoadFromFile();
779
780   if ( ! myFilter->_is_nil() )
781     myFilter->UnRegister();
782
783   myFilter = SMESH::Filter::_duplicate( theFilter );
784
785   if ( SMESHDS_GroupOnFilter* grDS = dynamic_cast< SMESHDS_GroupOnFilter*>( GetGroupDS() ))
786     grDS->SetPredicate( GetPredicate( myFilter ));
787
788   TPythonDump()<< SMESH::SMESH_GroupOnFilter_var(_this()) <<".SetFilter( "<<theFilter<<" )";
789
790   if ( myFilter )
791   {
792     myFilter->SetMesh( SMESH::SMESH_Mesh::_nil() ); // to UnRegister() the mesh
793     myFilter->Register();
794     SMESH::DownCast< SMESH::Filter_i* >( myFilter )->AddWaiter( this );
795   }
796 }
797
798 //================================================================================
799 /*!
800  * \brief Returns the filter defining group contents
801  */
802 //================================================================================
803
804 SMESH::Filter_ptr SMESH_GroupOnFilter_i::GetFilter()
805 {
806   SMESH::Filter_var f = myFilter;
807   TPythonDump() << f << " = " << SMESH::SMESH_GroupOnFilter_var(_this()) << ".GetFilter()";
808   return f._retn();
809 }
810
811 //=======================================================================
812 //function : GetIDs
813 //purpose  : Returns ids of members
814 //=======================================================================
815
816 SMESH::long_array* SMESH_GroupOnFilter_i::GetListOfID()
817 {
818   if ( myPreMeshInfo )
819     myPreMeshInfo->FullLoadFromFile();
820
821   SMESH::long_array_var aRes = new SMESH::long_array();
822   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
823   if ( SMESHDS_GroupOnFilter* grDS = dynamic_cast< SMESHDS_GroupOnFilter*>( GetGroupDS() ))
824   {
825     const SMDS_MeshInfo& meshInfo = aGroupDS->GetMesh()->GetMeshInfo();
826     aRes->length( meshInfo.NbElements( aGroupDS->GetType() ));
827     if ( aRes->length() ) // else aRes[0] -> SIGSEGV
828       aRes->length( grDS->GetElementIds( &aRes[0] ));
829
830     if ( 0 < aRes->length() && aRes->length() < 100 ) // for comfortable testing ;)
831       std::sort( &aRes[0], &aRes[0] + aRes->length() );
832   }
833   MESSAGE("get list of IDs of a vague group");
834   return aRes._retn();
835 }
836
837 //=============================================================================
838 /*!
839  * Returns statistic of mesh elements
840  * Result array of number enityties
841  * Inherited from SMESH_IDSource
842  */
843 //=============================================================================
844
845 SMESH::long_array* SMESH_GroupOnFilter_i::GetMeshInfo()
846 {
847   if ( myPreMeshInfo )
848     return myPreMeshInfo->GetMeshInfo();
849
850   SMESH::long_array_var aRes = new SMESH::long_array();
851   aRes->length(SMESH::Entity_Last);
852   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
853     aRes[i] = 0;
854
855   if ( SMESHDS_GroupBase* g = GetGroupDS())
856   {
857     if ( g->GetType() == SMDSAbs_Node || ( myNbNodes > -1 && g->GetTic() == myGroupDSTic))
858       aRes[ SMDSEntity_Node ] = GetNumberOfNodes();
859
860     if ( g->GetType() != SMDSAbs_Node )
861     {
862       vector< int > nbElems = static_cast< SMESHDS_GroupOnFilter* >( g )->GetMeshInfo();
863       for ( size_t i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
864         if ( i < nbElems.size() )
865           aRes[i] = nbElems[ i ];
866     }
867   }
868
869   return aRes._retn();
870 }
871
872 #define SEPAR '^'
873
874 //================================================================================
875 /*!
876  * \brief Return a string to be used to store group definition in the study
877  */
878 //================================================================================
879
880 std::string SMESH_GroupOnFilter_i::FilterToString() const
881 {
882   SMESH_Comment result;
883   SMESH::Filter::Criteria_var criteria;
884   if ( !myFilter->_is_nil() && myFilter->GetCriteria( criteria.out() ))
885   {
886     result << criteria->length() << SEPAR;
887     for ( unsigned i = 0; i < criteria->length(); ++i )
888     {
889       // write FunctorType as string but not as number to assure correct
890       // persistence if enum FunctorType is modified by insertion in the middle
891       SMESH::Filter::Criterion& crit = criteria[ i ];
892       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.Type ))    << SEPAR;
893       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.Compare )) << SEPAR;
894       result << crit.Threshold                                                  << SEPAR;
895       result << crit.ThresholdStr                                               << SEPAR;
896       result << crit.ThresholdID                                                << SEPAR;
897       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.UnaryOp )) << SEPAR;
898       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.BinaryOp ))<< SEPAR;
899       result << crit.Tolerance                                                  << SEPAR;
900       result << crit.TypeOfElement                                              << SEPAR;
901       result << crit.Precision                                                  << SEPAR;
902     }
903   }
904   return result;
905 }
906
907 //================================================================================
908 /*!
909  * \brief Restore the filter by the persistent string
910  */
911 //================================================================================
912
913 SMESH::Filter_ptr SMESH_GroupOnFilter_i::StringToFilter(const std::string& thePersistStr )
914 {
915   SMESH::Filter_var filter;
916
917   // divide thePersistStr into sub-strings
918   std::vector< std::string > strVec;
919   std::string::size_type from = 0, to;
920   while ( from < thePersistStr.size() )
921   {
922     to = thePersistStr.find( SEPAR, from );
923     if ( to == std::string::npos )
924       break;
925     strVec.push_back( thePersistStr.substr( from, to-from ));
926     from = to+1;
927   }
928   if ( strVec.empty() || strVec[0] == "0" )
929     return filter._retn();
930 #undef SEPAR
931
932   // create Criteria
933   int nbCrit = atoi( strVec[0].c_str() );
934   SMESH::Filter::Criteria_var criteria = new SMESH::Filter::Criteria;
935   criteria->length( nbCrit );
936   int nbStrPerCrit = ( strVec.size() - 1 ) / nbCrit;
937   for ( int i = 0; i < nbCrit; ++i )
938   {
939     SMESH::Filter::Criterion& crit = criteria[ i ];
940     int iStr = 1 + i * nbStrPerCrit;
941     crit.Type         = SMESH::StringToFunctorType( strVec[ iStr++ ].c_str() );
942     crit.Compare      = SMESH::StringToFunctorType( strVec[ iStr++ ].c_str() );
943     crit.Threshold    = atof(                       strVec[ iStr++ ].c_str() );
944     crit.ThresholdStr =                             strVec[ iStr++ ].c_str();
945     crit.ThresholdID  =                             strVec[ iStr++ ].c_str();
946     crit.UnaryOp      = SMESH::StringToFunctorType( strVec[ iStr++ ].c_str() );
947     crit.BinaryOp     = SMESH::StringToFunctorType( strVec[ iStr++ ].c_str() );
948     crit.Tolerance    = atof(                       strVec[ iStr++ ].c_str() );
949     crit.TypeOfElement= SMESH::ElementType( atoi(   strVec[ iStr++ ].c_str() ));
950     crit.Precision    = atoi(                       strVec[ iStr++ ].c_str() );
951   }
952
953   // create a filter
954   TPythonDump pd;
955   SMESH::FilterManager_i* aFilterMgr = new SMESH::FilterManager_i();
956   filter = aFilterMgr->CreateFilter();
957   filter->SetCriteria( criteria.inout() );
958   
959   aFilterMgr->UnRegister();
960
961   pd << ""; // to avoid optimizing pd out
962
963   return filter._retn();
964 }
965
966 //================================================================================
967 /*!
968  * \brief Destructor of SMESH_GroupOnFilter_i
969  */
970 //================================================================================
971
972 SMESH_GroupOnFilter_i::~SMESH_GroupOnFilter_i()
973 {
974   if ( ! myFilter->_is_nil() )
975   {
976     SMESH::DownCast< SMESH::Filter_i* >( myFilter )->RemoveWaiter( this );
977     myFilter->UnRegister();
978   }
979 }
980
981 //================================================================================
982 /*!
983  * \brief Method calleds when a predicate of myFilter changes
984  */
985 //================================================================================
986
987 void SMESH_GroupOnFilter_i::PredicateChanged()
988 {
989   if ( myPreMeshInfo )
990     myPreMeshInfo->FullLoadFromFile();
991
992   if ( SMESHDS_GroupOnFilter* grDS = dynamic_cast< SMESHDS_GroupOnFilter*>( GetGroupDS() ))
993     grDS->SetPredicate( GetPredicate( myFilter ));
994 }