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