Salome HOME
DCQ : Merge with Ecole_Ete_a6.
[modules/smesh.git] / src / Controls / SMESH_Controls.cxx
1 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
3 // 
4 //  This library is free software; you can redistribute it and/or 
5 //  modify it under the terms of the GNU Lesser General Public 
6 //  License as published by the Free Software Foundation; either
7 //  version 2.1 of the License. 
8 // 
9 //  This library is distributed in the hope that it will be useful, 
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 //  Lesser General Public License for more details.
13 // 
14 //  You should have received a copy of the GNU Lesser General Public 
15 //  License along with this library; if not, write to the Free Software 
16 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
17 // 
18 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
19
20 #include <set>
21
22 #include <gp_Pnt.hxx>
23 #include <gp_Vec.hxx>
24 #include <gp_XYZ.hxx>
25 #include <Precision.hxx>
26 #include <TColgp_SequenceOfXYZ.hxx>
27 #include <TColStd_MapOfInteger.hxx>
28
29 #include "SMDS_Mesh.hxx"
30 #include "SMDS_Iterator.hxx"
31 #include "SMDS_MeshElement.hxx"
32 #include "SMDS_MeshNode.hxx"
33
34 #include "SMESH_Controls.hxx"
35
36 /*
37                             AUXILIARY METHODS 
38 */
39
40 static inline double getAngle( const gp_XYZ& P1, const gp_XYZ& P2, const gp_XYZ& P3 )
41 {
42   return gp_Vec( P1 - P2 ).Angle( gp_Vec( P3 - P2 ) );
43 }
44
45 static inline double getArea( const gp_XYZ& P1, const gp_XYZ& P2, const gp_XYZ& P3 )
46 {
47   gp_Vec aVec1( P2 - P1 );
48   gp_Vec aVec2( P3 - P1 );
49   return ( aVec1 ^ aVec2 ).Magnitude() * 0.5;
50 }
51
52 static inline double getArea( const gp_Pnt& P1, const gp_Pnt& P2, const gp_Pnt& P3 )
53 {
54   return getArea( P1.XYZ(), P2.XYZ(), P3.XYZ() );
55 }
56
57 static inline double getDistance( const gp_XYZ& P1, const gp_XYZ& P2 )
58 {
59   double aDist = gp_Pnt( P1 ).Distance( gp_Pnt( P2 ) );
60   return aDist;
61 }
62
63 static int getNbMultiConnection( SMDS_Mesh* theMesh, const int theId )
64 {
65   if ( theMesh == 0 )
66     return 0;
67
68   const SMDS_MeshElement* anEdge = theMesh->FindElement( theId );
69   if ( anEdge == 0 || anEdge->GetType() != SMDSAbs_Edge || anEdge->NbNodes() != 2 )
70     return 0;
71
72   TColStd_MapOfInteger aMap;
73
74   int aResult = 0;
75   SMDS_ElemIteratorPtr anIter = anEdge->nodesIterator();
76   if ( anIter != 0 )
77   {
78     while( anIter->more() )
79     {
80       const SMDS_MeshNode* aNode = (SMDS_MeshNode*)anIter->next();
81       if ( aNode == 0 )
82         return 0;
83       SMDS_ElemIteratorPtr anElemIter = aNode->GetInverseElementIterator();
84       while( anElemIter->more() )
85       {
86         const SMDS_MeshElement* anElem = anElemIter->next();
87         if ( anElem != 0 && anElem->GetType() != SMDSAbs_Edge )
88         {
89           int anId = anElem->GetID();
90
91           if ( anIter->more() )              // i.e. first node
92             aMap.Add( anId );
93           else if ( aMap.Contains( anId ) )
94             aResult++;
95         }
96       }
97     }
98   }
99
100   return aResult;
101 }
102
103
104 using namespace SMESH::Controls;
105
106 /*
107                                 FUNCTORS
108 */
109
110 /*
111   Class       : NumericalFunctor
112   Description : Base class for numerical functors
113 */
114 NumericalFunctor::NumericalFunctor():
115   myMesh(NULL)
116 {}
117
118 void NumericalFunctor::SetMesh( SMDS_Mesh* theMesh )
119 {
120   myMesh = theMesh;
121 }
122
123 bool NumericalFunctor::getPoints( const int theId,
124                                                    TColgp_SequenceOfXYZ& theRes ) const
125 {
126   theRes.Clear();
127
128   if ( myMesh == 0 )
129     return false;
130
131   // Get nodes of the face
132   const SMDS_MeshElement* anElem = myMesh->FindElement( theId );
133   if ( anElem == 0 || anElem->GetType() != GetType() )
134     return false;
135
136   int nbNodes = anElem->NbNodes();
137
138   SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
139   if ( anIter != 0 )
140   {
141     while( anIter->more() )
142     {
143       const SMDS_MeshNode* aNode = (SMDS_MeshNode*)anIter->next();
144       if ( aNode != 0 )
145         theRes.Append( gp_XYZ( aNode->X(), aNode->Y(), aNode->Z() ) );
146     }
147   }
148
149   return true;
150 }
151
152
153 /*
154   Class       : MinimumAngle
155   Description : Functor for calculation of minimum angle
156 */
157 double MinimumAngle::GetValue( long theId )
158 {
159   TColgp_SequenceOfXYZ P;
160   if ( !getPoints( theId, P )  || P.Length() != 3 && P.Length() != 4 )
161     return 0;
162
163   double aMin;
164
165   if ( P.Length() == 3 )
166   {
167     double A0 = getAngle( P( 3 ), P( 1 ), P( 2 ) );
168     double A1 = getAngle( P( 1 ), P( 2 ), P( 3 ) );
169     double A2 = getAngle( P( 2 ), P( 3 ), P( 1 ) );
170
171     aMin = Min( A0, Min( A1, A2 ) );
172   }
173   else
174   {
175     double A0 = getAngle( P( 4 ), P( 1 ), P( 2 ) );
176     double A1 = getAngle( P( 1 ), P( 2 ), P( 3 ) );
177     double A2 = getAngle( P( 2 ), P( 3 ), P( 4 ) );
178     double A3 = getAngle( P( 3 ), P( 4 ), P( 1 ) );
179     
180     aMin = Min( Min( A0, A1 ), Min( A2, A3 ) );
181   }
182   
183   return aMin * 180 / PI;
184 }
185
186 SMDSAbs_ElementType MinimumAngle::GetType() const
187 {
188   return SMDSAbs_Face;
189 }
190
191
192 /*
193   Class       : AspectRatio
194   Description : Functor for calculating aspect ratio
195 */
196 double AspectRatio::GetValue( long theId )
197 {
198   TColgp_SequenceOfXYZ P;
199   if ( !getPoints( theId, P )  || P.Length() != 3 && P.Length() != 4 )
200     return 0;
201
202   int nbNodes = P.Length();
203
204   // Compute lengths of the sides
205
206   double aLen[ nbNodes ];
207   for ( int i = 0; i < nbNodes - 1; i++ )
208     aLen[ i ] = getDistance( P( i + 1 ), P( i + 2 ) );
209   aLen[ nbNodes - 1 ] = getDistance( P( 1 ), P( nbNodes ) );
210
211   // Compute aspect ratio
212
213   if ( nbNodes == 3 ) 
214   {
215     double aMaxLen = Max( aLen[ 0 ], Max( aLen[ 1 ], aLen[ 2 ] ) );
216     double anArea = getArea( P( 1 ), P( 2 ), P( 3 ) );
217     static double aCoef = sqrt( 3. ) / 4;
218
219     return anArea != 0 ? aCoef * aMaxLen * aMaxLen / anArea : 0;
220   }
221   else
222   {
223     double aMaxLen = Max( Max( aLen[ 0 ], aLen[ 1 ] ), Max( aLen[ 2 ], aLen[ 3 ] ) );
224     double aMinLen = Min( Min( aLen[ 0 ], aLen[ 1 ] ), Min( aLen[ 2 ], aLen[ 3 ] ) );
225     
226     return aMinLen != 0 ? aMaxLen / aMinLen : 0;
227   }
228 }
229
230 SMDSAbs_ElementType AspectRatio::GetType() const
231 {
232   return SMDSAbs_Face;
233 }
234
235
236 /*
237   Class       : Warping
238   Description : Functor for calculating warping
239 */
240 double Warping::GetValue( long theId )
241 {
242   TColgp_SequenceOfXYZ P;
243   if ( !getPoints( theId, P ) || P.Length() != 4 )
244     return 0;
245
246   gp_XYZ G = ( P( 1 ) + P( 2 ) + P( 3 ) + P( 4 ) ) / 4;
247
248   double A1 = ComputeA( P( 1 ), P( 2 ), P( 3 ), G );
249   double A2 = ComputeA( P( 2 ), P( 3 ), P( 4 ), G );
250   double A3 = ComputeA( P( 3 ), P( 4 ), P( 1 ), G );
251   double A4 = ComputeA( P( 4 ), P( 1 ), P( 2 ), G );
252
253   return Max( Max( A1, A2 ), Max( A3, A4 ) );
254 }
255
256 double Warping::ComputeA( const gp_XYZ& thePnt1,
257                                            const gp_XYZ& thePnt2,
258                                            const gp_XYZ& thePnt3,
259                                            const gp_XYZ& theG ) const
260 {
261   double aLen1 = gp_Pnt( thePnt1 ).Distance( gp_Pnt( thePnt2 ) );
262   double aLen2 = gp_Pnt( thePnt2 ).Distance( gp_Pnt( thePnt3 ) );
263   double L = Min( aLen1, aLen2 ) * 0.5;
264
265   gp_XYZ GI = ( thePnt2 - thePnt1 ) / 2. - theG;
266   gp_XYZ GJ = ( thePnt3 - thePnt2 ) / 2. - theG;
267   gp_XYZ N  = GI.Crossed( GJ );
268   N.Normalize();
269
270   double H = gp_Vec( thePnt2 - theG ).Dot( gp_Vec( N ) );
271   return asin( fabs( H / L ) ) * 180 / PI;
272 }
273
274 SMDSAbs_ElementType Warping::GetType() const
275 {
276   return SMDSAbs_Face;
277 }
278
279
280 /*
281   Class       : Taper
282   Description : Functor for calculating taper
283 */
284 double Taper::GetValue( long theId )
285 {
286   TColgp_SequenceOfXYZ P;
287   if ( !getPoints( theId, P ) || P.Length() != 4 )
288     return 0;
289
290   // Compute taper
291   double J1 = getArea( P( 4 ), P( 1 ), P( 2 ) ) / 2;
292   double J2 = getArea( P( 3 ), P( 1 ), P( 2 ) ) / 2;
293   double J3 = getArea( P( 2 ), P( 3 ), P( 4 ) ) / 2;
294   double J4 = getArea( P( 3 ), P( 4 ), P( 1 ) ) / 2;
295
296   double JA = 0.25 * ( J1 + J2 + J3 + J4 );
297
298   double T1 = fabs( ( J1 - JA ) / JA );
299   double T2 = fabs( ( J2 - JA ) / JA );
300   double T3 = fabs( ( J3 - JA ) / JA );
301   double T4 = fabs( ( J4 - JA ) / JA );
302
303   return Max( Max( T1, T2 ), Max( T3, T4 ) );
304 }
305
306 SMDSAbs_ElementType Taper::GetType() const
307 {
308   return SMDSAbs_Face;
309 }
310
311
312 /*
313   Class       : Skew
314   Description : Functor for calculating skew in degrees
315 */
316 static inline double skewAngle( const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ& p3 )
317 {
318   gp_XYZ p12 = ( p2 + p1 ) / 2;
319   gp_XYZ p23 = ( p3 + p2 ) / 2;
320   gp_XYZ p31 = ( p3 + p1 ) / 2;
321
322   return gp_Vec( p31 - p2 ).Angle( p12 - p23 );
323 }
324
325 double Skew::GetValue( long theId )
326 {
327   TColgp_SequenceOfXYZ P;
328   if ( !getPoints( theId, P )  || P.Length() != 3 && P.Length() != 4 )
329     return 0;
330
331   // Compute skew
332   static double PI2 = PI / 2;
333   if ( P.Length() == 3 )
334   {
335     double A0 = fabs( PI2 - skewAngle( P( 3 ), P( 1 ), P( 2 ) ) );
336     double A1 = fabs( PI2 - skewAngle( P( 1 ), P( 2 ), P( 3 ) ) );
337     double A2 = fabs( PI2 - skewAngle( P( 2 ), P( 3 ), P( 1 ) ) );
338
339     return Max( A0, Max( A1, A2 ) ) * 180 / PI;
340   }
341   else 
342   {
343     gp_XYZ p12 = ( P( 1 ) + P( 2 ) ) / 2;
344     gp_XYZ p23 = ( P( 2 ) + P( 3 ) ) / 2;
345     gp_XYZ p34 = ( P( 3 ) + P( 4 ) ) / 2;
346     gp_XYZ p41 = ( P( 4 ) + P( 1 ) ) / 2;
347     
348     double A = fabs( PI2 - gp_Vec( p34 - p12 ).Angle( p23 - p41 ) );
349
350     return A * 180 / PI;
351   }
352 }
353
354 SMDSAbs_ElementType Skew::GetType() const
355 {
356   return SMDSAbs_Face;
357 }
358
359
360 /*
361   Class       : Area
362   Description : Functor for calculating area
363 */
364 double Area::GetValue( long theId )
365 {
366   TColgp_SequenceOfXYZ P;
367   if ( !getPoints( theId, P )  || P.Length() != 3 && P.Length() != 4 )
368     return 0;
369
370   if ( P.Length() == 3 )
371     return getArea( P( 1 ), P( 2 ), P( 3 ) );
372   else
373     return getArea( P( 1 ), P( 2 ), P( 3 ) ) + getArea( P( 1 ), P( 3 ), P( 4 ) );
374 }
375
376 SMDSAbs_ElementType Area::GetType() const
377 {
378   return SMDSAbs_Face;
379 }
380
381
382 /*
383   Class       : Length
384   Description : Functor for calculating length off edge
385 */
386 double Length::GetValue( long theId )
387 {
388   TColgp_SequenceOfXYZ P;
389   return getPoints( theId, P ) && P.Length() == 2 ? getDistance( P( 1 ), P( 2 ) ) : 0;
390 }
391
392 SMDSAbs_ElementType Length::GetType() const
393 {
394   return SMDSAbs_Edge;
395 }
396
397
398 /*
399   Class       : MultiConnection
400   Description : Functor for calculating number of faces conneted to the edge
401 */
402 double MultiConnection::GetValue( long theId )
403 {
404   return getNbMultiConnection( myMesh, theId );
405 }
406
407 SMDSAbs_ElementType MultiConnection::GetType() const
408 {
409   return SMDSAbs_Edge;
410 }
411
412
413 /*
414                             PREDICATES
415 */
416
417 /*
418   Class       : FreeBorders
419   Description : Predicate for free borders
420 */
421
422 FreeBorders::FreeBorders()
423 {
424   myMesh = 0;
425 }
426
427 void FreeBorders::SetMesh( SMDS_Mesh* theMesh )
428 {
429   myMesh = theMesh;
430 }
431
432 bool FreeBorders::IsSatisfy( long theId )
433 {
434   return getNbMultiConnection( myMesh, theId ) == 1;
435 }
436
437 SMDSAbs_ElementType FreeBorders::GetType() const
438 {
439   return SMDSAbs_Edge;
440 }
441
442
443 /*
444   Class       : FreeEdges
445   Description : Predicate for free Edges
446 */
447 FreeEdges::FreeEdges()
448 {
449   myMesh = 0;
450 }
451
452 void FreeEdges::SetMesh( SMDS_Mesh* theMesh )
453 {
454   myMesh = theMesh;
455 }
456
457 bool FreeEdges::IsSatisfy( long theId )
458 {
459   return getNbMultiConnection( myMesh, theId ) == 1;
460 }
461
462 SMDSAbs_ElementType FreeEdges::GetType() const
463 {
464   return SMDSAbs_Face;
465 }
466
467 FreeEdges::Border::Border(long thePntId1, long thePntId2){
468   PntId[0] = thePntId1;  PntId[1] = thePntId2;
469   if(thePntId1 > thePntId2){
470     PntId[1] = thePntId1;  PntId[0] = thePntId2;
471   }
472 }
473
474 //bool operator<(const FreeEdges::Border& x, const FreeEdges::Border& y){
475 //  if(x.PntId[0] < y.PntId[0]) return true;
476 //  if(x.PntId[0] == y.PntId[0])
477 //    if(x.PntId[1] < y.PntId[1]) return true;
478 //  return false;
479 //}
480
481 namespace SMESH{
482   namespace Controls{
483     struct EdgeBorder: public FreeEdges::Border{
484       long ElemId;
485       EdgeBorder(long theElemId, long thePntId1, long thePntId2):
486         FreeEdges::Border(thePntId1,thePntId2), 
487         ElemId(theElemId)
488       {}
489     };
490     
491     bool operator<(const FreeEdges::Border& x, const FreeEdges::Border& y){
492       if(x.PntId[0] < y.PntId[0]) return true;
493       if(x.PntId[0] == y.PntId[0])
494         if(x.PntId[1] < y.PntId[1]) return true;
495       return false;
496     }
497
498     typedef std::set<EdgeBorder> EdgeBorderS;
499
500     inline void UpdateBorders(const EdgeBorder& theBorder,
501                               EdgeBorderS& theRegistry, 
502                               EdgeBorderS& theContainer)
503     {
504       if(theRegistry.find(theBorder) == theRegistry.end()){
505         theRegistry.insert(theBorder);
506         theContainer.insert(theBorder);
507       }else{
508         theContainer.erase(theBorder);
509       }
510     }
511
512   }
513 }
514
515 void FreeEdges::GetBoreders(Borders& theBorders)
516 {
517   EdgeBorderS aRegistry;
518   EdgeBorderS aContainer;
519   SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
520   for(; anIter->more(); ){
521     const SMDS_MeshFace* anElem = anIter->next();
522     long anElemId = anElem->GetID();
523     SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
524     long aNodeId[2];
525     const SMDS_MeshElement* aNode;
526     if(aNodesIter->more()){
527       aNode = aNodesIter->next();
528       aNodeId[0] = aNodeId[1] = aNode->GetID();
529     }   
530     for(; aNodesIter->more(); ){
531       aNode = aNodesIter->next();
532       EdgeBorder aBorder(anElemId,aNodeId[1],aNode->GetID());
533       aNodeId[1] = aNode->GetID();
534       //std::cout<<aBorder.PntId[0]<<"; "<<aBorder.PntId[1]<<"; "<<aBorder.ElemId<<"\n";
535       UpdateBorders(aBorder,aRegistry,aContainer);
536     }
537     EdgeBorder aBorder(anElemId,aNodeId[0],aNodeId[1]);
538     UpdateBorders(aBorder,aRegistry,aContainer);
539   }
540   //std::cout<<"aContainer.size() = "<<aContainer.size()<<"\n";
541   if(aContainer.size()){
542     EdgeBorderS::const_iterator anIter = aContainer.begin();
543     for(; anIter != aContainer.end(); anIter++){
544       const EdgeBorder& aBorder = *anIter;
545       //std::cout<<aBorder.PntId[0]<<"; "<<aBorder.PntId[1]<<"; "<<aBorder.ElemId<<"\n";
546       theBorders.insert(Borders::value_type(aBorder.ElemId,aBorder));
547     }
548   }
549 }
550
551
552 /*
553   Class       : Comparator
554   Description : Base class for comparators
555 */
556 Comparator::Comparator():
557   myMargin(0)
558 {}
559
560 Comparator::~Comparator()
561 {}
562
563 void Comparator::SetMesh( SMDS_Mesh* theMesh )
564 {
565   if ( myFunctor )
566     myFunctor->SetMesh( theMesh );
567 }
568
569 void Comparator::SetMargin( double theValue )
570 {
571   myMargin = theValue;
572 }
573
574 void Comparator::SetNumFunctor( NumericalFunctorPtr theFunct )
575 {
576   myFunctor = theFunct;
577 }
578
579 SMDSAbs_ElementType Comparator::GetType() const
580 {
581   return myFunctor ? myFunctor->GetType() : SMDSAbs_All;
582 }
583
584
585 /*
586   Class       : LessThan
587   Description : Comparator "<"
588 */
589 bool LessThan::IsSatisfy( long theId )
590 {
591   return myFunctor && myFunctor->GetValue( theId ) < myMargin;
592 }
593
594
595 /*
596   Class       : MoreThan
597   Description : Comparator ">"
598 */
599 bool MoreThan::IsSatisfy( long theId )
600 {
601   return myFunctor && myFunctor->GetValue( theId ) > myMargin;
602 }
603
604
605 /*
606   Class       : EqualTo
607   Description : Comparator "="
608 */
609 EqualTo::EqualTo():
610   myToler(Precision::Confusion())
611 {}
612
613 bool EqualTo::IsSatisfy( long theId )
614 {
615   return myFunctor && fabs( myFunctor->GetValue( theId ) - myMargin ) < myToler;
616 }
617
618 void EqualTo::SetTolerance( double theToler )
619 {
620   myToler = theToler;
621 }
622
623
624 /*
625   Class       : LogicalNOT
626   Description : Logical NOT predicate
627 */
628 LogicalNOT::LogicalNOT()
629 {}
630
631 LogicalNOT::~LogicalNOT()
632 {}
633
634 bool LogicalNOT::IsSatisfy( long theId )
635 {
636   return myPredicate && !myPredicate->IsSatisfy( theId );
637 }
638
639 void LogicalNOT::SetMesh( SMDS_Mesh* theMesh )
640 {
641   if ( myPredicate )
642     myPredicate->SetMesh( theMesh );
643 }
644
645 void LogicalNOT::SetPredicate( PredicatePtr thePred )
646 {
647   myPredicate = thePred;
648 }
649
650 SMDSAbs_ElementType LogicalNOT::GetType() const
651 {
652   return myPredicate ? myPredicate->GetType() : SMDSAbs_All;
653 }
654
655
656 /*
657   Class       : LogicalBinary
658   Description : Base class for binary logical predicate
659 */
660 LogicalBinary::LogicalBinary()
661 {}
662
663 LogicalBinary::~LogicalBinary()
664 {}
665
666 void LogicalBinary::SetMesh( SMDS_Mesh* theMesh )
667 {
668   if ( myPredicate1 )
669     myPredicate1->SetMesh( theMesh );
670
671   if ( myPredicate2 )
672     myPredicate2->SetMesh( theMesh );
673 }
674
675 void LogicalBinary::SetPredicate1( PredicatePtr thePredicate )
676 {
677   myPredicate1 = thePredicate;
678 }
679
680 void LogicalBinary::SetPredicate2( PredicatePtr thePredicate )
681 {
682   myPredicate2 = thePredicate;
683 }
684
685 SMDSAbs_ElementType LogicalBinary::GetType() const
686 {
687   if ( !myPredicate1 || !myPredicate2 )
688     return SMDSAbs_All;
689
690   SMDSAbs_ElementType aType1 = myPredicate1->GetType();
691   SMDSAbs_ElementType aType2 = myPredicate2->GetType();
692
693   return aType1 == aType2 ? aType1 : SMDSAbs_All;
694 }
695
696
697 /*
698   Class       : LogicalAND
699   Description : Logical AND
700 */
701 bool LogicalAND::IsSatisfy( long theId )
702 {
703   return 
704     myPredicate1 && 
705     myPredicate2 && 
706     myPredicate1->IsSatisfy( theId ) && 
707     myPredicate2->IsSatisfy( theId );
708 }
709
710
711 /*
712   Class       : LogicalOR
713   Description : Logical OR
714 */
715 bool LogicalOR::IsSatisfy( long theId )
716 {
717   return 
718     myPredicate1 && 
719     myPredicate2 && 
720     myPredicate1->IsSatisfy( theId ) || 
721     myPredicate2->IsSatisfy( theId );
722 }
723
724
725 /*
726                               FILTER
727 */
728
729 Filter::Filter()
730 {}
731
732 Filter::~Filter()
733 {}
734
735 void Filter::SetPredicate( PredicatePtr thePredicate )
736 {
737   myPredicate = thePredicate;
738 }
739
740 Filter::TIdSequence
741 Filter::GetElementsId( SMDS_Mesh* theMesh )
742 {
743   TIdSequence aSequence;
744   if ( !theMesh || !myPredicate ) return aSequence;
745
746   myPredicate->SetMesh( theMesh );
747
748   SMDSAbs_ElementType aType = myPredicate->GetType();
749   switch(aType){
750   case SMDSAbs_Edge:{
751     SMDS_EdgeIteratorPtr anIter = theMesh->edgesIterator();
752     if ( anIter != 0 ) {
753       while( anIter->more() ) {
754         const SMDS_MeshElement* anElem = anIter->next();
755         long anId = anElem->GetID();
756         if ( myPredicate->IsSatisfy( anId ) )
757           aSequence.push_back( anId );
758       }
759     }
760   }
761   case SMDSAbs_Face:{
762     SMDS_FaceIteratorPtr anIter = theMesh->facesIterator();
763     if ( anIter != 0 ) {
764       while( anIter->more() ) {
765         const SMDS_MeshElement* anElem = anIter->next();
766         long anId = anElem->GetID();
767         if ( myPredicate->IsSatisfy( anId ) )
768           aSequence.push_back( anId );
769       }
770     }
771   }
772   }
773   return aSequence;
774 }