Salome HOME
Merge from V6_3_BR 15/07/2011
[modules/smesh.git] / src / SMESH_I / SMESH_Group_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
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
41 #include CORBA_SERVER_HEADER(SMESH_Filter)
42
43 #include "utilities.h"
44
45 using namespace SMESH;
46
47 //=============================================================================
48 /*!
49  *  
50  */
51 //=============================================================================
52
53 SMESH_GroupBase_i::SMESH_GroupBase_i( PortableServer::POA_ptr thePOA,
54                                       SMESH_Mesh_i*           theMeshServant,
55                                       const int               theLocalID )
56 : SALOME::GenericObj_i( thePOA ),
57   myMeshServant( theMeshServant ), 
58   myLocalID( theLocalID )
59 {
60   // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i,
61   // servant activation is performed by SMESH_Mesh_i::createGroup()
62   // thePOA->activate_object( this );
63 }
64
65 SMESH_Group_i::SMESH_Group_i( PortableServer::POA_ptr thePOA,
66                               SMESH_Mesh_i*           theMeshServant,
67                               const int               theLocalID )
68      : SALOME::GenericObj_i( thePOA ),
69        SMESH_GroupBase_i( thePOA, theMeshServant, theLocalID )
70 {
71   //MESSAGE("SMESH_Group_i; this = "<<this );
72 }
73
74 SMESH_GroupOnGeom_i::SMESH_GroupOnGeom_i( PortableServer::POA_ptr thePOA,
75                                           SMESH_Mesh_i*           theMeshServant,
76                                           const int               theLocalID )
77      : SALOME::GenericObj_i( thePOA ),
78        SMESH_GroupBase_i( thePOA, theMeshServant, theLocalID )
79 {
80   //MESSAGE("SMESH_GroupOnGeom_i; this = "<<this );
81 }
82
83 SMESH_GroupOnFilter_i::SMESH_GroupOnFilter_i( PortableServer::POA_ptr thePOA,
84                                               SMESH_Mesh_i*           theMeshServant,
85                                               const int               theLocalID )
86   : SALOME::GenericObj_i( thePOA ),
87     SMESH_GroupBase_i( thePOA, theMeshServant, theLocalID )
88 {
89   //MESSAGE("SMESH_GroupOnGeom_i; this = "<<this );
90 }
91
92 //=============================================================================
93 /*!
94  *  
95  */
96 //=============================================================================
97
98 SMESH_GroupBase_i::~SMESH_GroupBase_i()
99 {
100   MESSAGE("~SMESH_GroupBase_i; this = "<<this );
101   if ( myMeshServant )
102     myMeshServant->removeGroup(myLocalID);
103 }
104
105 //=======================================================================
106 //function : GetSmeshGroup
107 //purpose  : 
108 //=======================================================================
109
110 ::SMESH_Group* SMESH_GroupBase_i::GetSmeshGroup() const
111 {
112   if ( myMeshServant ) {
113     ::SMESH_Mesh& aMesh = myMeshServant->GetImpl();
114     return aMesh.GetGroup(myLocalID);
115   }
116   return 0;
117 }
118
119 //=======================================================================
120 //function : GetGroupDS
121 //purpose  : 
122 //=======================================================================
123
124 SMESHDS_GroupBase* SMESH_GroupBase_i::GetGroupDS() const
125 {
126   ::SMESH_Group* aGroup = GetSmeshGroup();
127   if ( aGroup )
128     return aGroup->GetGroupDS();
129   return 0;
130 }
131
132 //=============================================================================
133 /*!
134  *  
135  */
136 //=============================================================================
137
138 void SMESH_GroupBase_i::SetName( const char* theName )
139 {
140   // Perform renaming
141   ::SMESH_Group* aGroup = GetSmeshGroup();
142   if (!aGroup) {
143     MESSAGE("can't set name of a vague group");
144     return;
145   }
146
147   if ( aGroup->GetName() && !strcmp( aGroup->GetName(), theName ) )
148     return; // nothing to rename
149
150   aGroup->SetName(theName);
151
152   // Update group name in a study
153   SMESH_Gen_i* aGen = myMeshServant->GetGen();
154   aGen->SetName( aGen->ObjectToSObject( aGen->GetCurrentStudy(), _this() ), theName );
155   
156   // Update Python script
157   TPythonDump() <<  _this() << ".SetName( '" << theName << "' )";
158 }
159
160 //=============================================================================
161 /*!
162  *  
163  */
164 //=============================================================================
165
166 char* SMESH_GroupBase_i::GetName()
167 {
168   ::SMESH_Group* aGroup = GetSmeshGroup();
169   if (aGroup)
170     return CORBA::string_dup (aGroup->GetName());
171   MESSAGE("get name of a vague group");
172   return CORBA::string_dup( "NO_NAME" );
173 }
174
175 //=============================================================================
176 /*!
177  *  
178  */
179 //=============================================================================
180
181 SMESH::ElementType SMESH_GroupBase_i::GetType()
182 {
183   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
184   if (aGroupDS) {
185     SMDSAbs_ElementType aSMDSType = aGroupDS->GetType();
186     SMESH::ElementType aType;
187     switch (aSMDSType) {
188     case SMDSAbs_Node:      aType = SMESH::NODE;   break;
189     case SMDSAbs_Edge:      aType = SMESH::EDGE;   break;
190     case SMDSAbs_Face:      aType = SMESH::FACE;   break;
191     case SMDSAbs_Volume:    aType = SMESH::VOLUME; break;
192     case SMDSAbs_0DElement: aType = SMESH::ELEM0D; break;
193     default:                aType = SMESH::ALL;    break;
194     }
195     return aType;
196   }
197   MESSAGE("get type of a vague group");
198   return SMESH::ALL;
199 }
200
201
202 //=============================================================================
203 /*!
204  *  
205  */
206 //=============================================================================
207
208 CORBA::Long SMESH_GroupBase_i::Size()
209 {
210   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
211   if (aGroupDS)
212     return aGroupDS->Extent();
213   MESSAGE("get size of a vague group");
214   return 0;
215 }
216
217 //=============================================================================
218 /*!
219  *  
220  */
221 //=============================================================================
222
223 CORBA::Boolean SMESH_GroupBase_i::IsEmpty()
224 {
225   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
226   if (aGroupDS)
227     return aGroupDS->IsEmpty();
228   MESSAGE("checking IsEmpty of a vague group");
229   return true;
230 }
231
232 //=============================================================================
233 /*!
234  *  
235  */
236 //=============================================================================
237
238 void SMESH_Group_i::Clear()
239 {
240   // Update Python script
241   TPythonDump() << _this() << ".Clear()";
242
243   // Clear the group
244   SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( GetGroupDS() );
245   if (aGroupDS) {
246     aGroupDS->Clear();
247     return;
248   }
249   MESSAGE("attempt to clear a vague group");
250 }
251
252 //=============================================================================
253 /*!
254  *  
255  */
256 //=============================================================================
257
258 CORBA::Boolean SMESH_GroupBase_i::Contains( CORBA::Long theID )
259 {
260   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
261   if (aGroupDS)
262     return aGroupDS->Contains(theID);
263   MESSAGE("attempt to check contents of a vague group");
264   return false;
265 }
266
267 //=============================================================================
268 /*!
269  *  
270  */
271 //=============================================================================
272
273 CORBA::Long SMESH_Group_i::Add( const SMESH::long_array& theIDs )
274 {
275   // Update Python script
276   TPythonDump() << "nbAdd = " << _this() << ".Add( " << theIDs << " )";
277
278   // Add elements to the group
279   SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( GetGroupDS() );
280   if (aGroupDS) {
281     int nbAdd = 0;
282     for (int i = 0; i < theIDs.length(); i++) {
283       int anID = (int) theIDs[i];
284       if (aGroupDS->Add(anID))
285         nbAdd++;
286     }
287     return nbAdd;
288   }
289   MESSAGE("attempt to add elements to a vague group");
290   return 0;
291 }
292
293 //=============================================================================
294 /*!
295  *  
296  */
297 //=============================================================================
298
299 CORBA::Long SMESH_Group_i::Remove( const SMESH::long_array& theIDs )
300 {
301   // Update Python script
302   TPythonDump() << "nbDel = " << _this() << ".Remove( " << theIDs << " )";
303
304   // Remove elements from the group
305   SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( GetGroupDS() );
306   if (aGroupDS) {
307     int nbDel = 0;
308     for (int i = 0; i < theIDs.length(); i++) {
309       int anID = (int) theIDs[i];
310       if (aGroupDS->Remove(anID))
311         nbDel++;
312     }
313     return nbDel;
314   }
315   MESSAGE("attempt to remove elements from a vague group");
316   return 0;
317 }
318
319 //=============================================================================
320 /*!
321  *  
322  */
323 //=============================================================================
324
325 typedef bool (SMESHDS_Group::*TFunChangeGroup)(const int);
326
327 CORBA::Long 
328 ChangeByPredicate( SMESH::Predicate_i* thePredicate,
329                    SMESHDS_GroupBase* theGroupBase,
330                    TFunChangeGroup theFun)
331 {
332   CORBA::Long aNb = 0;
333   if(SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>(theGroupBase)){
334     SMESH::Controls::Filter::TIdSequence aSequence;
335     const SMDS_Mesh* aMesh = theGroupBase->GetMesh();
336     SMESH::Filter_i::GetElementsId(thePredicate,aMesh,aSequence);
337     
338     CORBA::Long i = 0, iEnd = aSequence.size();
339     for(; i < iEnd; i++)
340       if((aGroupDS->*theFun)(aSequence[i]))
341         aNb++;
342     return aNb;
343   }
344   return aNb;
345 }
346
347 CORBA::Long 
348 SMESH_Group_i::
349 AddByPredicate( SMESH::Predicate_ptr thePredicate )
350 {
351   if(SMESH::Predicate_i* aPredicate = SMESH::GetPredicate(thePredicate)){
352     TPythonDump()<<_this()<<".AddByPredicate("<<aPredicate<<")";
353     return ChangeByPredicate(aPredicate,GetGroupDS(),&SMESHDS_Group::Add);
354   }
355   return 0;
356 }
357
358 CORBA::Long 
359 SMESH_Group_i::
360 RemoveByPredicate( SMESH::Predicate_ptr thePredicate )
361 {
362   if(SMESH::Predicate_i* aPredicate = SMESH::GetPredicate(thePredicate)){
363     TPythonDump()<<_this()<<".RemoveByPredicate("<<aPredicate<<")";
364     return ChangeByPredicate(aPredicate,GetGroupDS(),&SMESHDS_Group::Remove);
365   }
366   return 0;
367 }
368
369 CORBA::Long SMESH_Group_i::AddFrom( SMESH::SMESH_IDSource_ptr theSource )
370 {
371   TPythonDump pd;
372   long nbAdd = 0;
373   SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( GetGroupDS() );
374   if (aGroupDS) {
375     SMESH::long_array_var anIds;
376     SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theSource);
377     SMESH::SMESH_Mesh_var mesh       = SMESH::SMESH_Mesh::_narrow(theSource);
378     SMESH::SMESH_subMesh_var submesh = SMESH::SMESH_subMesh::_narrow(theSource);
379     SMESH::Filter_var filter         = SMESH::Filter::_narrow(theSource);
380     if ( !group->_is_nil())
381       anIds = group->GetType()==GetType() ? theSource->GetIDs() :  new SMESH::long_array();
382     else if ( !mesh->_is_nil() )
383       anIds = mesh->GetElementsByType( GetType() );
384     else if ( !submesh->_is_nil())
385       anIds = submesh->GetElementsByType( GetType() );
386     else if ( !filter->_is_nil() ) {
387       filter->SetMesh( GetMeshServant()->_this() );
388       anIds = filter->GetElementType()==GetType() ? theSource->GetIDs() : new SMESH::long_array();
389     }
390     else 
391       anIds = theSource->GetIDs();
392     for ( int i = 0, total = anIds->length(); i < total; i++ ) {
393       if ( aGroupDS->Add((int)anIds[i]) ) nbAdd++;
394     }
395   }
396
397   // Update Python script
398   pd << "nbAdd = " << _this() << ".AddFrom( " << theSource << " )";
399
400   return nbAdd;
401 }
402
403 //=============================================================================
404 /*!
405  *  
406  */
407 //=============================================================================
408
409 CORBA::Long SMESH_GroupBase_i::GetID( CORBA::Long theIndex )
410 {
411   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
412   if (aGroupDS)
413     return aGroupDS->GetID(theIndex);
414   MESSAGE("attempt to iterate on a vague group");
415   return -1;
416 }
417
418 //=============================================================================
419 /*!
420  *  
421  */
422 //=============================================================================
423
424 SMESH::long_array* SMESH_GroupBase_i::GetListOfID()
425 {
426   SMESH::long_array_var aRes = new SMESH::long_array();
427   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
428   if (aGroupDS) {
429     int aSize = aGroupDS->Extent();
430     aRes->length(aSize);
431     for (int i = 0; i < aSize; i++)
432       aRes[i] = aGroupDS->GetID(i+1);
433     return aRes._retn();
434   }
435   MESSAGE("get list of IDs of a vague group");
436   return aRes._retn();
437 }
438
439 //=============================================================================
440 /*!
441  *  
442  */
443 //=============================================================================
444 SMESH::SMESH_Mesh_ptr SMESH_GroupBase_i::GetMesh()
445 {
446   SMESH::SMESH_Mesh_var aMesh;
447   if ( myMeshServant )
448     aMesh = SMESH::SMESH_Mesh::_narrow( myMeshServant->_this() );
449   return aMesh._retn();
450 }
451
452 //=======================================================================
453 //function : GetShape
454 //purpose  : 
455 //=======================================================================
456
457 GEOM::GEOM_Object_ptr SMESH_GroupOnGeom_i::GetShape()
458 {
459   GEOM::GEOM_Object_var aGeomObj;
460   SMESHDS_GroupOnGeom* aGroupDS = dynamic_cast<SMESHDS_GroupOnGeom*>( GetGroupDS() );
461   if ( aGroupDS ) {
462     SMESH_Gen_i* aGen = GetMeshServant()->GetGen();
463     aGeomObj = aGen->ShapeToGeomObject( aGroupDS->GetShape() );
464   }
465   return aGeomObj._retn();
466 }
467
468 //=============================================================================
469 /*!
470  *
471  */
472 //=============================================================================
473 SALOMEDS::Color SMESH_GroupBase_i::GetColor()
474 {
475   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
476   if (aGroupDS)
477   {
478     Quantity_Color aQColor = aGroupDS->GetColor();
479     SALOMEDS::Color aColor;
480     aColor.R = aQColor.Red();
481     aColor.G = aQColor.Green();
482     aColor.B = aQColor.Blue();
483
484     return aColor;
485   }
486   MESSAGE("get color of a group");
487   return SALOMEDS::Color();
488 }
489
490 //=============================================================================
491 /*!
492  *
493  */
494 //=============================================================================
495 void SMESH_GroupBase_i::SetColor(const SALOMEDS::Color& color)
496 {
497   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
498   if (aGroupDS)
499   {
500     Quantity_Color aQColor( color.R, color.G, color.B, Quantity_TOC_RGB );
501     aGroupDS->SetColor(aQColor);
502     TPythonDump()<<_this()<<".SetColor( SALOMEDS.Color( "<<color.R<<", "<<color.G<<", "<<color.B<<" ))";
503   }
504 }
505
506 //=============================================================================
507 /*!
508  *
509  */
510 //=============================================================================
511 CORBA::Long SMESH_GroupBase_i::GetColorNumber()
512 {
513   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
514   if (aGroupDS)
515     return aGroupDS->GetColorGroup();
516   MESSAGE("get color number of a group");
517   return 0;
518 }
519
520 //=============================================================================
521 /*!
522  *
523  */
524 //=============================================================================
525 void SMESH_GroupBase_i::SetColorNumber(CORBA::Long color)
526 {
527   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
528   if (aGroupDS)
529   {
530     aGroupDS->SetColorGroup(color);
531     TPythonDump()<<_this()<<".SetColorNumber( "<<color<<" )";
532   }
533   MESSAGE("set color number of a group");
534   return ;
535 }
536
537 //=============================================================================
538 /*!
539  * Returns statistic of mesh elements
540  * Result array of number enityties
541  * Inherited from SMESH_IDSource
542  */
543 //=============================================================================
544 SMESH::long_array* SMESH_GroupBase_i::GetMeshInfo()
545 {
546   SMESH::long_array_var aRes = new SMESH::long_array();
547   aRes->length(SMESH::Entity_Last);
548   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
549     aRes[i] = 0;
550
551   SMESHDS_GroupBase* aGrpDS = GetGroupDS();
552   if ( !aGrpDS )
553     return aRes._retn();
554   if ( GetType() == NODE )
555     aRes[ SMESH::Entity_Node ] = aGrpDS->Extent();
556   else
557     SMESH_Mesh_i::CollectMeshInfo( aGrpDS->GetElements(), aRes);
558
559 //   SMDS_ElemIteratorPtr it = aGrpDS->GetElements();
560 //   if ( it->more() )
561 //   {
562 //     cout << "START" << endl;
563 //     set< const SMDS_MeshElement* > nodes;
564 //     const SMDS_MeshElement* e = it->next();
565 //     for ( int i = 0; i < 1000000; ++i)
566 //     {
567 //       SMDS_ElemIteratorPtr it = e->nodesIterator();
568 //       nodes.insert( e + i );
569 //     }
570 //     cout << "END "<< nodes.size() << endl;
571 //   }
572  
573   return aRes._retn();
574 }
575
576 //=======================================================================
577 //function : GetIDs
578 //purpose  : Returns ids of members
579 //=======================================================================
580
581 SMESH::long_array* SMESH_GroupBase_i::GetIDs()
582 {
583   SMESH::long_array_var aResult = GetListOfID();
584   return aResult._retn();
585 }
586
587 //=======================================================================
588 //function : GetTypes
589 //purpose  : Returns types of elements it contains
590 //=======================================================================
591
592 SMESH::array_of_ElementType* SMESH_GroupBase_i::GetTypes()
593 {
594   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
595   if ( SMESHDS_GroupBase* ds = GetGroupDS() )
596     if ( !ds->IsEmpty() )
597     {
598       types->length( 1 );
599       types[0] = GetType();
600     }
601   return types._retn();
602 }
603
604 //================================================================================
605 /*!
606  * \brief Retrieves the predicate from the filter
607  */
608 //================================================================================
609
610 SMESH_PredicatePtr SMESH_GroupOnFilter_i::GetPredicate( SMESH::Filter_ptr filter )
611 {
612   SMESH_PredicatePtr predicate;
613
614   if ( SMESH::Filter_i* filt_i = SMESH::DownCast< SMESH::Filter_i* >( filter ))
615     if ( SMESH::Predicate_i* predic_i= filt_i->GetPredicate_i() )
616       predicate = predic_i->GetPredicate();
617
618   return predicate;
619 }
620
621 //================================================================================
622 /*!
623  * \brief Sets the filter defining group contents
624  */
625 //================================================================================
626
627 void SMESH_GroupOnFilter_i::SetFilter(SMESH::Filter_ptr theFilter)
628 {
629   if ( ! myFilter->_is_nil() )
630     myFilter->UnRegister();
631
632   myFilter = SMESH::Filter::_duplicate( theFilter );
633
634   if ( SMESHDS_GroupOnFilter* grDS = dynamic_cast< SMESHDS_GroupOnFilter*>( GetGroupDS() ))
635     grDS->SetPredicate( GetPredicate( myFilter ));
636
637   TPythonDump()<< _this() <<".SetFilter( "<<theFilter<<" )";
638
639   if ( myFilter )
640   {
641     myFilter->Register();
642     SMESH::DownCast< SMESH::Filter_i* >( myFilter )->AddWaiter( this );
643   }
644 }
645
646 //================================================================================
647 /*!
648  * \brief Returns the filter defining group contents
649  */
650 //================================================================================
651
652 SMESH::Filter_ptr SMESH_GroupOnFilter_i::GetFilter()
653 {
654   SMESH::Filter_var f = myFilter;
655   TPythonDump() << f << " = " << _this() << ".GetFilter()";
656   return f._retn();
657 }
658
659 #define SEPAR '^'
660
661 //================================================================================
662 /*!
663  * \brief Return a string to be used to store group definition in the study
664  */
665 //================================================================================
666
667 std::string SMESH_GroupOnFilter_i::FilterToString() const
668 {
669   SMESH_Comment result;
670   SMESH::Filter::Criteria_var criteria;
671   if ( !myFilter->_is_nil() && myFilter->GetCriteria( criteria.out() ))
672   {
673     result << criteria->length() << SEPAR;
674     for ( unsigned i = 0; i < criteria->length(); ++i )
675     {
676       // write FunctorType as string but not as number to assure correct
677       // persistence if enum FunctorType is modified by insertion in the middle
678       SMESH::Filter::Criterion& crit = criteria[ i ];
679       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.Type ))    << SEPAR;
680       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.Compare )) << SEPAR;
681       result << crit.Threshold                                                  << SEPAR;
682       result << crit.ThresholdStr                                               << SEPAR;
683       result << crit.ThresholdID                                                << SEPAR;
684       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.UnaryOp )) << SEPAR;
685       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.BinaryOp ))<< SEPAR;
686       result << crit.Tolerance                                                  << SEPAR;
687       result << crit.TypeOfElement                                              << SEPAR;
688       result << crit.Precision                                                  << SEPAR;
689     }
690   }
691   return result;
692 }
693
694 //================================================================================
695 /*!
696  * \brief Restore the filter by the persistent string
697  */
698 //================================================================================
699
700 SMESH::Filter_ptr SMESH_GroupOnFilter_i::StringToFilter(const std::string& thePersistStr )
701 {
702   SMESH::Filter_var filter;
703
704   // divide thePersistStr into sub-strings
705   std::vector< std::string > strVec;
706   std::string::size_type from = 0, to;
707   while ( from < thePersistStr.size() )
708   {
709     to = thePersistStr.find( SEPAR, from );
710     if ( to == std::string::npos )
711       break;
712     strVec.push_back( thePersistStr.substr( from, to-from ));
713     from = to+1;
714   }
715   if ( strVec.empty() || strVec[0] == "0" )
716     return filter._retn();
717 #undef SEPAR
718
719   // create Criteria
720   int nbCrit = atoi( strVec[0].c_str() );
721   SMESH::Filter::Criteria_var criteria = new SMESH::Filter::Criteria;
722   criteria->length( nbCrit );
723   int nbStrPerCrit = ( strVec.size() - 1 ) / nbCrit;
724   for ( int i = 0; i < nbCrit; ++i )
725   {
726     SMESH::Filter::Criterion& crit = criteria[ i ];
727     int iStr = 1 + i * nbStrPerCrit;
728     crit.Type         = SMESH::StringToFunctorType( strVec[ iStr++ ].c_str() );
729     crit.Compare      = SMESH::StringToFunctorType( strVec[ iStr++ ].c_str() );
730     crit.Threshold    = atof(                       strVec[ iStr++ ].c_str() );
731     crit.ThresholdStr =                             strVec[ iStr++ ].c_str();
732     crit.ThresholdID  =                             strVec[ iStr++ ].c_str();
733     crit.UnaryOp      = SMESH::StringToFunctorType( strVec[ iStr++ ].c_str() );
734     crit.BinaryOp     = SMESH::StringToFunctorType( strVec[ iStr++ ].c_str() );
735     crit.Tolerance    = atof(                       strVec[ iStr++ ].c_str() );
736     crit.TypeOfElement= SMESH::ElementType( atoi(   strVec[ iStr++ ].c_str() ));
737     crit.Precision    = atoi(                       strVec[ iStr++ ].c_str() );
738   }
739
740   // create a filter
741   TPythonDump pd;
742   SMESH::FilterManager_i* aFilterMgr = new SMESH::FilterManager_i();
743   filter = aFilterMgr->CreateFilter();
744   filter->SetCriteria( criteria.inout() );
745   
746   aFilterMgr->UnRegister();
747
748   pd << ""; // to avoid optimizing pd out
749
750   return filter._retn();
751 }
752
753 SMESH_GroupOnFilter_i::~SMESH_GroupOnFilter_i()
754 {
755   if ( ! myFilter->_is_nil() )
756   {
757     SMESH::DownCast< SMESH::Filter_i* >( myFilter )->RemoveWaiter( this );
758     myFilter->UnRegister();
759   }
760 }
761
762 void SMESH_GroupOnFilter_i::PredicateChanged()
763 {
764   if ( SMESHDS_GroupOnFilter* grDS = dynamic_cast< SMESHDS_GroupOnFilter*>( GetGroupDS() ))
765     grDS->SetPredicate( GetPredicate( myFilter ));
766 }