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