]> SALOME platform Git repositories - modules/smesh.git/blob - src/SMESH_I/SMESH_Group_i.cxx
Salome HOME
speed up NotifySubMeshesHypothesisModification()
[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     aGroupDS->SetColor(aQColor);
586     TPythonDump()<<_this()<<".SetColor( SALOMEDS.Color( "<<color.R<<", "<<color.G<<", "<<color.B<<" ))";
587   }
588 }
589
590 //=============================================================================
591 /*!
592  *
593  */
594 //=============================================================================
595 CORBA::Long SMESH_GroupBase_i::GetColorNumber()
596 {
597   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
598   if (aGroupDS)
599     return aGroupDS->GetColorGroup();
600   MESSAGE("get color number of a group");
601   return 0;
602 }
603
604 //=============================================================================
605 /*!
606  *
607  */
608 //=============================================================================
609 void SMESH_GroupBase_i::SetColorNumber(CORBA::Long color)
610 {
611   SMESHDS_GroupBase* aGroupDS = GetGroupDS();
612   if (aGroupDS)
613   {
614     aGroupDS->SetColorGroup(color);
615     TPythonDump()<<_this()<<".SetColorNumber( "<<color<<" )";
616   }
617   MESSAGE("set color number of a group");
618   return ;
619 }
620
621 //=============================================================================
622 /*!
623  * Returns statistic of mesh elements
624  * Result array of number enityties
625  * Inherited from SMESH_IDSource
626  */
627 //=============================================================================
628 SMESH::long_array* SMESH_GroupBase_i::GetMeshInfo()
629 {
630   SMESH::long_array_var aRes = new SMESH::long_array();
631   aRes->length(SMESH::Entity_Last);
632   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
633     aRes[i] = 0;
634
635   SMESHDS_GroupBase* aGrpDS = GetGroupDS();
636   if ( !aGrpDS )
637     return aRes._retn();
638   if ( GetType() == NODE )
639     aRes[ SMESH::Entity_Node ] = aGrpDS->Extent();
640   else
641     SMESH_Mesh_i::CollectMeshInfo( aGrpDS->GetElements(), aRes);
642
643 //   SMDS_ElemIteratorPtr it = aGrpDS->GetElements();
644 //   if ( it->more() )
645 //   {
646 //     cout << "START" << endl;
647 //     set< const SMDS_MeshElement* > nodes;
648 //     const SMDS_MeshElement* e = it->next();
649 //     for ( int i = 0; i < 1000000; ++i)
650 //     {
651 //       SMDS_ElemIteratorPtr it = e->nodesIterator();
652 //       nodes.insert( e + i );
653 //     }
654 //     cout << "END "<< nodes.size() << endl;
655 //   }
656  
657   return aRes._retn();
658 }
659
660 //=======================================================================
661 //function : GetIDs
662 //purpose  : Returns ids of members
663 //=======================================================================
664
665 SMESH::long_array* SMESH_GroupBase_i::GetIDs()
666 {
667   SMESH::long_array_var aResult = GetListOfID();
668   return aResult._retn();
669 }
670
671 //=======================================================================
672 //function : GetTypes
673 //purpose  : Returns types of elements it contains
674 //=======================================================================
675
676 SMESH::array_of_ElementType* SMESH_GroupBase_i::GetTypes()
677 {
678   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
679   if ( SMESHDS_GroupBase* ds = GetGroupDS() )
680     if ( !ds->IsEmpty() )
681     {
682       types->length( 1 );
683       types[0] = GetType();
684     }
685   return types._retn();
686 }
687
688 //================================================================================
689 /*!
690  * \brief Retrieves the predicate from the filter
691  */
692 //================================================================================
693
694 SMESH_PredicatePtr SMESH_GroupOnFilter_i::GetPredicate( SMESH::Filter_ptr filter )
695 {
696   SMESH_PredicatePtr predicate;
697
698   if ( SMESH::Filter_i* filt_i = SMESH::DownCast< SMESH::Filter_i* >( filter ))
699     if ( SMESH::Predicate_i* predic_i= filt_i->GetPredicate_i() )
700       predicate = predic_i->GetPredicate();
701
702   return predicate;
703 }
704
705 //================================================================================
706 /*!
707  * \brief Sets the filter defining group contents
708  */
709 //================================================================================
710
711 void SMESH_GroupOnFilter_i::SetFilter(SMESH::Filter_ptr theFilter)
712 {
713   if ( ! myFilter->_is_nil() )
714     myFilter->UnRegister();
715
716   myFilter = SMESH::Filter::_duplicate( theFilter );
717
718   if ( SMESHDS_GroupOnFilter* grDS = dynamic_cast< SMESHDS_GroupOnFilter*>( GetGroupDS() ))
719     grDS->SetPredicate( GetPredicate( myFilter ));
720
721   TPythonDump()<< _this() <<".SetFilter( "<<theFilter<<" )";
722
723   if ( myFilter )
724   {
725     myFilter->Register();
726     SMESH::DownCast< SMESH::Filter_i* >( myFilter )->AddWaiter( this );
727   }
728 }
729
730 //================================================================================
731 /*!
732  * \brief Returns the filter defining group contents
733  */
734 //================================================================================
735
736 SMESH::Filter_ptr SMESH_GroupOnFilter_i::GetFilter()
737 {
738   SMESH::Filter_var f = myFilter;
739   TPythonDump() << f << " = " << _this() << ".GetFilter()";
740   return f._retn();
741 }
742
743 #define SEPAR '^'
744
745 //================================================================================
746 /*!
747  * \brief Return a string to be used to store group definition in the study
748  */
749 //================================================================================
750
751 std::string SMESH_GroupOnFilter_i::FilterToString() const
752 {
753   SMESH_Comment result;
754   SMESH::Filter::Criteria_var criteria;
755   if ( !myFilter->_is_nil() && myFilter->GetCriteria( criteria.out() ))
756   {
757     result << criteria->length() << SEPAR;
758     for ( unsigned i = 0; i < criteria->length(); ++i )
759     {
760       // write FunctorType as string but not as number to assure correct
761       // persistence if enum FunctorType is modified by insertion in the middle
762       SMESH::Filter::Criterion& crit = criteria[ i ];
763       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.Type ))    << SEPAR;
764       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.Compare )) << SEPAR;
765       result << crit.Threshold                                                  << SEPAR;
766       result << crit.ThresholdStr                                               << SEPAR;
767       result << crit.ThresholdID                                                << SEPAR;
768       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.UnaryOp )) << SEPAR;
769       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.BinaryOp ))<< SEPAR;
770       result << crit.Tolerance                                                  << SEPAR;
771       result << crit.TypeOfElement                                              << SEPAR;
772       result << crit.Precision                                                  << SEPAR;
773     }
774   }
775   return result;
776 }
777
778 //================================================================================
779 /*!
780  * \brief Restore the filter by the persistent string
781  */
782 //================================================================================
783
784 SMESH::Filter_ptr SMESH_GroupOnFilter_i::StringToFilter(const std::string& thePersistStr )
785 {
786   SMESH::Filter_var filter;
787
788   // divide thePersistStr into sub-strings
789   std::vector< std::string > strVec;
790   std::string::size_type from = 0, to;
791   while ( from < thePersistStr.size() )
792   {
793     to = thePersistStr.find( SEPAR, from );
794     if ( to == std::string::npos )
795       break;
796     strVec.push_back( thePersistStr.substr( from, to-from ));
797     from = to+1;
798   }
799   if ( strVec.empty() || strVec[0] == "0" )
800     return filter._retn();
801 #undef SEPAR
802
803   // create Criteria
804   int nbCrit = atoi( strVec[0].c_str() );
805   SMESH::Filter::Criteria_var criteria = new SMESH::Filter::Criteria;
806   criteria->length( nbCrit );
807   int nbStrPerCrit = ( strVec.size() - 1 ) / nbCrit;
808   for ( int i = 0; i < nbCrit; ++i )
809   {
810     SMESH::Filter::Criterion& crit = criteria[ i ];
811     int iStr = 1 + i * nbStrPerCrit;
812     crit.Type         = SMESH::StringToFunctorType( strVec[ iStr++ ].c_str() );
813     crit.Compare      = SMESH::StringToFunctorType( strVec[ iStr++ ].c_str() );
814     crit.Threshold    = atof(                       strVec[ iStr++ ].c_str() );
815     crit.ThresholdStr =                             strVec[ iStr++ ].c_str();
816     crit.ThresholdID  =                             strVec[ iStr++ ].c_str();
817     crit.UnaryOp      = SMESH::StringToFunctorType( strVec[ iStr++ ].c_str() );
818     crit.BinaryOp     = SMESH::StringToFunctorType( strVec[ iStr++ ].c_str() );
819     crit.Tolerance    = atof(                       strVec[ iStr++ ].c_str() );
820     crit.TypeOfElement= SMESH::ElementType( atoi(   strVec[ iStr++ ].c_str() ));
821     crit.Precision    = atoi(                       strVec[ iStr++ ].c_str() );
822   }
823
824   // create a filter
825   TPythonDump pd;
826   SMESH::FilterManager_i* aFilterMgr = new SMESH::FilterManager_i();
827   filter = aFilterMgr->CreateFilter();
828   filter->SetCriteria( criteria.inout() );
829   
830   aFilterMgr->UnRegister();
831
832   pd << ""; // to avoid optimizing pd out
833
834   return filter._retn();
835 }
836
837 SMESH_GroupOnFilter_i::~SMESH_GroupOnFilter_i()
838 {
839   if ( ! myFilter->_is_nil() )
840   {
841     SMESH::DownCast< SMESH::Filter_i* >( myFilter )->RemoveWaiter( this );
842     myFilter->UnRegister();
843   }
844 }
845
846 void SMESH_GroupOnFilter_i::PredicateChanged()
847 {
848   if ( SMESHDS_GroupOnFilter* grDS = dynamic_cast< SMESHDS_GroupOnFilter*>( GetGroupDS() ))
849     grDS->SetPredicate( GetPredicate( myFilter ));
850 }