Salome HOME
no message
[modules/gui.git] / src / GLViewer / GLViewer_Detector.cxx
1 // File:      GLViewer_Detector.cxx
2 // Created:   11/16/2004 14:19:07
3 // Author:    Sergey ANIKIN
4 // Copyright: CEA 2004
5
6 #include <GLViewer_Detector.h>
7
8 #define FAR_POINT 1e10  // Value used as a "very distant" co-ordinate
9 #define TOLERANCE 1e-3
10
11 //================================================================
12 // Class       : GLViewer_Segment
13 // Description : 
14 //================================================================
15
16 //================================================================
17 // Function : GLViewer_Segment
18 // Purpose  : constructs a real segment bounded by two points
19 //================================================================
20 GLViewer_Segment::GLViewer_Segment( const GLViewer_Pnt& thePnt1, 
21                                     const GLViewer_Pnt& thePnt2 )
22 : myPnt1( thePnt1 ), 
23   myPnt2( thePnt2 )
24 {
25   myA = myPnt1.y() - myPnt2.y();
26   myB = myPnt2.x() - myPnt1.x();
27   myC = myPnt1.x() * myPnt2.y() - myPnt2.x() * myPnt1.y();
28 }
29
30 //================================================================
31 // Function : GLViewer_Segment
32 // Purpose  : constructs a ray starting at <thePnt> and directed
33 //            along positive X axis direction (or Y axis if vertical )
34 //================================================================
35 GLViewer_Segment::GLViewer_Segment( const GLViewer_Pnt& thePnt, 
36                                     const GLfloat theA, 
37                                     const GLfloat theB,
38                                     const GLfloat theC )
39 : myPnt1( thePnt ),
40   myA( theA ),
41   myB( theB ), 
42   myC( theC )
43 {
44   if ( fabs( myB ) < TOLERANCE )
45     myPnt2 = GLViewer_Pnt( myPnt1.x(), FAR_POINT );
46   else
47     myPnt2 = GLViewer_Pnt( FAR_POINT, - myA / myB * FAR_POINT - myC / myB );
48 }
49
50 //================================================================
51 // Function : GLViewer_Segment
52 // Purpose  : destructor, does nothing
53 //================================================================
54 GLViewer_Segment::~GLViewer_Segment()
55 {
56 }
57
58 //================================================================
59 // Function : HasIntersection
60 // Purpose  : detects intersection with segment <theOther>
61 //================================================================
62 bool GLViewer_Segment::HasIntersection( const GLViewer_Segment& theOther ) const
63 {
64   bool aRes = false;
65   GLfloat aDiv = myA * theOther.myB - myB * theOther.myA;
66   if ( fabs( aDiv ) > TOLERANCE )
67   {
68     GLfloat aX  = ( myB * theOther.myC - theOther.myB * myC ) / aDiv;
69     GLfloat aX11 = myPnt1.x() > myPnt2.x() ? myPnt2.x() : myPnt1.x();
70     GLfloat aX12 = myPnt1.x() > myPnt2.x() ? myPnt1.x() : myPnt2.x();
71     GLfloat aX21 = theOther.myPnt1.x() > theOther.myPnt2.x() ? theOther.myPnt2.x() : theOther.myPnt1.x();
72     GLfloat aX22 = theOther.myPnt1.x() > theOther.myPnt2.x() ? theOther.myPnt1.x() : theOther.myPnt2.x();
73
74     GLfloat aY  = ( myC * theOther.myA - theOther.myC * myA ) / aDiv;
75     GLfloat aY11 = myPnt1.y() > myPnt2.y() ? myPnt2.y() : myPnt1.y();
76     GLfloat aY12 = myPnt1.y() > myPnt2.y() ? myPnt1.y() : myPnt2.y();
77     GLfloat aY21 = theOther.myPnt1.y() > theOther.myPnt2.y() ? theOther.myPnt2.y() : theOther.myPnt1.y();
78     GLfloat aY22 = theOther.myPnt1.y() > theOther.myPnt2.y() ? theOther.myPnt1.y() : theOther.myPnt2.y();
79
80     if ( fabs( aX11 - aX12 ) > TOLERANCE )
81       aRes = aX11 < aX && aX < aX12;
82     else
83       aRes = aY11 < aY && aY < aY12;
84
85     if ( aRes )
86     {
87       if ( fabs( aX21 - aX22 ) > TOLERANCE )
88         aRes = aX21 < aX && aX < aX22;
89       else
90         aRes = aY21 < aY && aY < aY22;
91     }
92   }
93
94   return aRes;
95 }
96
97 //================================================================
98 // Class       : GLViewer_Poly
99 // Description : 
100 //================================================================
101
102 //================================================================
103 // Function : GLViewer_Poly
104 // Purpose  : constructs a closed polygon from the given ordered list of points
105 //================================================================
106 GLViewer_Poly::GLViewer_Poly( const GLViewer_PntList* thePoints )
107 : myPoints( (GLViewer_PntList*)thePoints )
108 {
109 }
110
111 //================================================================
112 // Function : ~GLViewer_Poly
113 // Purpose  : destructor, <myPoints> mustn't be deleted here!
114 //================================================================
115 GLViewer_Poly::~GLViewer_Poly()
116 {
117 }
118
119 //================================================================
120 // Function : IsIn
121 // Purpose  : returns true if <thePnt> lies within this polygon
122 //================================================================
123 bool GLViewer_Poly::IsIn( const GLViewer_Pnt& thePnt ) const
124 {
125   if ( !myPoints )
126     return false;
127
128   int aNbInter = 0;
129   GLViewer_Segment aRay( thePnt, 0., 1., -thePnt.y() );
130
131   GLViewer_PntList::const_iterator it1 = myPoints->begin();
132   GLViewer_PntList::const_iterator it2 = myPoints->begin();
133   ++it2;
134   for ( ; it1 != myPoints->end(); ++it1, ++it2 )
135   {
136     if ( it2 == myPoints->end() )
137       it2 = myPoints->begin();
138     
139     if ( aRay.HasIntersection( GLViewer_Segment( *it1, *it2 ) ) )
140       aNbInter++;
141   }
142
143   return ( aNbInter % 2 == 1 );
144 }
145
146 //================================================================
147 // Function : IsCovers
148 // Purpose  : returns true if <thePoly> covers this polygon
149 //================================================================
150 bool GLViewer_Poly::IsCovers( const GLViewer_Poly& thePoly ) const
151 {
152     if ( !myPoints || !thePoly.Count() )
153         return false;
154
155     GLViewer_PntList::const_iterator it = myPoints->begin();
156     
157     for ( ; it != myPoints->end(); ++it )
158     {
159         if( !thePoly.IsIn( *it ) )
160             return false;
161     }
162
163     return true;
164 }
165
166 //================================================================
167 // Function : IsCovers
168 // Purpose  : returns true if <theRect> covers this polygon
169 //================================================================
170 bool GLViewer_Poly::IsCovers( const GLViewer_Rect& theRect ) const
171 {
172     if ( !myPoints ) //needs check for <theRect>
173         return false;
174
175     GLViewer_PntList aList;    
176     GLViewer_PntList::iterator it = aList.begin();
177     
178     aList.insert( it, GLViewer_Pnt( theRect.left(), theRect.top() ) );
179     aList.insert( it, GLViewer_Pnt( theRect.right(), theRect.top() ) );
180     aList.insert( it, GLViewer_Pnt( theRect.right(), theRect.bottom() ) );
181     aList.insert( it, GLViewer_Pnt( theRect.left(), theRect.bottom() ) );
182
183     return IsCovers( GLViewer_Poly( &aList ) );
184 }
185
186 //================================================================
187 // Function : HasIntersection
188 // Purpose  : looks for any 
189 //================================================================
190 bool GLViewer_Poly::HasIntersection( const GLViewer_Segment& theSegment ) const
191 {
192   if ( !myPoints )
193     return false;
194
195   bool aRes = false;
196   GLViewer_PntList::const_iterator it1 = myPoints->begin();
197   GLViewer_PntList::const_iterator it2 = myPoints->begin();
198   ++it2;
199   for ( ; !aRes && it1 != myPoints->end(); ++it1, ++it2 )
200   {
201     if ( it2 == myPoints->end() )
202       it2 = myPoints->begin();
203     
204     aRes = theSegment.HasIntersection( GLViewer_Segment( *it1, *it2 ) );
205   }
206
207   return aRes;
208 }
209
210