Add wxEventLoop::ScheduleExit().
[wxWidgets.git] / src / common / geometry.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/geometry.cpp
3 // Purpose: Common Geometry Classes
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 08/05/99
7 // RCS-ID: $Id$
8 // Copyright: (c) 1999 Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_GEOMETRY
20
21 #include "wx/geometry.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/log.h"
25 #endif
26
27 #include <string.h>
28
29 #include "wx/datstrm.h"
30
31 //
32 // wxPoint2D
33 //
34
35 //
36 // wxRect2D
37 //
38
39 // wxDouble version
40
41 // for the following calculations always remember
42 // that the right and bottom edges are not part of a rect
43
44 bool wxRect2DDouble::Intersects( const wxRect2DDouble &rect ) const
45 {
46 wxDouble left,right,bottom,top;
47 left = wxMax ( m_x , rect.m_x );
48 right = wxMin ( m_x+m_width, rect.m_x + rect.m_width );
49 top = wxMax ( m_y , rect.m_y );
50 bottom = wxMin ( m_y+m_height, rect.m_y + rect.m_height );
51
52 if ( left < right && top < bottom )
53 {
54 return true;
55 }
56 return false;
57 }
58
59 void wxRect2DDouble::Intersect( const wxRect2DDouble &src1 , const wxRect2DDouble &src2 , wxRect2DDouble *dest )
60 {
61 wxDouble left,right,bottom,top;
62 left = wxMax ( src1.m_x , src2.m_x );
63 right = wxMin ( src1.m_x+src1.m_width, src2.m_x + src2.m_width );
64 top = wxMax ( src1.m_y , src2.m_y );
65 bottom = wxMin ( src1.m_y+src1.m_height, src2.m_y + src2.m_height );
66
67 if ( left < right && top < bottom )
68 {
69 dest->m_x = left;
70 dest->m_y = top;
71 dest->m_width = right - left;
72 dest->m_height = bottom - top;
73 }
74 else
75 {
76 dest->m_width = dest->m_height = 0;
77 }
78 }
79
80 void wxRect2DDouble::Union( const wxRect2DDouble &src1 , const wxRect2DDouble &src2 , wxRect2DDouble *dest )
81 {
82 wxDouble left,right,bottom,top;
83
84 left = wxMin ( src1.m_x , src2.m_x );
85 right = wxMax ( src1.m_x+src1.m_width, src2.m_x + src2.m_width );
86 top = wxMin ( src1.m_y , src2.m_y );
87 bottom = wxMax ( src1.m_y+src1.m_height, src2.m_y + src2.m_height );
88
89 dest->m_x = left;
90 dest->m_y = top;
91 dest->m_width = right - left;
92 dest->m_height = bottom - top;
93 }
94
95 void wxRect2DDouble::Union( const wxPoint2DDouble &pt )
96 {
97 wxDouble x = pt.m_x;
98 wxDouble y = pt.m_y;
99
100 if ( x < m_x )
101 {
102 SetLeft( x );
103 }
104 else if ( x < m_x + m_width )
105 {
106 // contained
107 }
108 else
109 {
110 SetRight( x );
111 }
112
113 if ( y < m_y )
114 {
115 SetTop( y );
116 }
117 else if ( y < m_y + m_height )
118 {
119 // contained
120 }
121 else
122 {
123 SetBottom( y );
124 }
125 }
126
127 void wxRect2DDouble::ConstrainTo( const wxRect2DDouble &rect )
128 {
129 if ( GetLeft() < rect.GetLeft() )
130 SetLeft( rect.GetLeft() );
131
132 if ( GetRight() > rect.GetRight() )
133 SetRight( rect.GetRight() );
134
135 if ( GetBottom() > rect.GetBottom() )
136 SetBottom( rect.GetBottom() );
137
138 if ( GetTop() < rect.GetTop() )
139 SetTop( rect.GetTop() );
140 }
141
142 wxRect2DDouble& wxRect2DDouble::operator=( const wxRect2DDouble &r )
143 {
144 m_x = r.m_x;
145 m_y = r.m_y;
146 m_width = r.m_width;
147 m_height = r.m_height;
148 return *this;
149 }
150
151 // integer version
152
153 // for the following calculations always remember
154 // that the right and bottom edges are not part of a rect
155
156 // wxPoint2D
157
158 #if wxUSE_STREAMS
159 void wxPoint2DInt::WriteTo( wxDataOutputStream &stream ) const
160 {
161 stream.Write32( m_x );
162 stream.Write32( m_y );
163 }
164
165 void wxPoint2DInt::ReadFrom( wxDataInputStream &stream )
166 {
167 m_x = stream.Read32();
168 m_y = stream.Read32();
169 }
170 #endif // wxUSE_STREAMS
171
172 wxDouble wxPoint2DInt::GetVectorAngle() const
173 {
174 if ( m_x == 0 )
175 {
176 if ( m_y >= 0 )
177 return 90;
178 else
179 return 270;
180 }
181 if ( m_y == 0 )
182 {
183 if ( m_x >= 0 )
184 return 0;
185 else
186 return 180;
187 }
188
189 // casts needed for MIPSpro compiler under SGI
190 wxDouble deg = atan2( (double)m_y , (double)m_x ) * 180 / M_PI;
191 if ( deg < 0 )
192 {
193 deg += 360;
194 }
195 return deg;
196 }
197
198
199 void wxPoint2DInt::SetVectorAngle( wxDouble degrees )
200 {
201 wxDouble length = GetVectorLength();
202 m_x = (int)(length * cos( degrees / 180 * M_PI ));
203 m_y = (int)(length * sin( degrees / 180 * M_PI ));
204 }
205
206 wxDouble wxPoint2DDouble::GetVectorAngle() const
207 {
208 if ( wxIsNullDouble(m_x) )
209 {
210 if ( m_y >= 0 )
211 return 90;
212 else
213 return 270;
214 }
215 if ( wxIsNullDouble(m_y) )
216 {
217 if ( m_x >= 0 )
218 return 0;
219 else
220 return 180;
221 }
222 wxDouble deg = atan2( m_y , m_x ) * 180 / M_PI;
223 if ( deg < 0 )
224 {
225 deg += 360;
226 }
227 return deg;
228 }
229
230 void wxPoint2DDouble::SetVectorAngle( wxDouble degrees )
231 {
232 wxDouble length = GetVectorLength();
233 m_x = length * cos( degrees / 180 * M_PI );
234 m_y = length * sin( degrees / 180 * M_PI );
235 }
236
237 // wxRect2D
238
239 bool wxRect2DInt::Intersects( const wxRect2DInt &rect ) const
240 {
241 wxInt32 left,right,bottom,top;
242 left = wxMax ( m_x , rect.m_x );
243 right = wxMin ( m_x+m_width, rect.m_x + rect.m_width );
244 top = wxMax ( m_y , rect.m_y );
245 bottom = wxMin ( m_y+m_height, rect.m_y + rect.m_height );
246
247 if ( left < right && top < bottom )
248 {
249 return true;
250 }
251 return false;
252 }
253
254 void wxRect2DInt::Intersect( const wxRect2DInt &src1 , const wxRect2DInt &src2 , wxRect2DInt *dest )
255 {
256 wxInt32 left,right,bottom,top;
257 left = wxMax ( src1.m_x , src2.m_x );
258 right = wxMin ( src1.m_x+src1.m_width, src2.m_x + src2.m_width );
259 top = wxMax ( src1.m_y , src2.m_y );
260 bottom = wxMin ( src1.m_y+src1.m_height, src2.m_y + src2.m_height );
261
262 if ( left < right && top < bottom )
263 {
264 dest->m_x = left;
265 dest->m_y = top;
266 dest->m_width = right - left;
267 dest->m_height = bottom - top;
268 }
269 else
270 {
271 dest->m_width = dest->m_height = 0;
272 }
273 }
274
275 void wxRect2DInt::Union( const wxRect2DInt &src1 , const wxRect2DInt &src2 , wxRect2DInt *dest )
276 {
277 wxInt32 left,right,bottom,top;
278
279 left = wxMin ( src1.m_x , src2.m_x );
280 right = wxMax ( src1.m_x+src1.m_width, src2.m_x + src2.m_width );
281 top = wxMin ( src1.m_y , src2.m_y );
282 bottom = wxMax ( src1.m_y+src1.m_height, src2.m_y + src2.m_height );
283
284 dest->m_x = left;
285 dest->m_y = top;
286 dest->m_width = right - left;
287 dest->m_height = bottom - top;
288 }
289
290 void wxRect2DInt::Union( const wxPoint2DInt &pt )
291 {
292 wxInt32 x = pt.m_x;
293 wxInt32 y = pt.m_y;
294
295 if ( x < m_x )
296 {
297 SetLeft( x );
298 }
299 else if ( x < m_x + m_width )
300 {
301 // contained
302 }
303 else
304 {
305 SetRight( x );
306 }
307
308 if ( y < m_y )
309 {
310 SetTop( y );
311 }
312 else if ( y < m_y + m_height )
313 {
314 // contained
315 }
316 else
317 {
318 SetBottom( y );
319 }
320 }
321
322 void wxRect2DInt::ConstrainTo( const wxRect2DInt &rect )
323 {
324 if ( GetLeft() < rect.GetLeft() )
325 SetLeft( rect.GetLeft() );
326
327 if ( GetRight() > rect.GetRight() )
328 SetRight( rect.GetRight() );
329
330 if ( GetBottom() > rect.GetBottom() )
331 SetBottom( rect.GetBottom() );
332
333 if ( GetTop() < rect.GetTop() )
334 SetTop( rect.GetTop() );
335 }
336
337 wxRect2DInt& wxRect2DInt::operator=( const wxRect2DInt &r )
338 {
339 m_x = r.m_x;
340 m_y = r.m_y;
341 m_width = r.m_width;
342 m_height = r.m_height;
343 return *this;
344 }
345
346 #if wxUSE_STREAMS
347 void wxRect2DInt::WriteTo( wxDataOutputStream &stream ) const
348 {
349 stream.Write32( m_x );
350 stream.Write32( m_y );
351 stream.Write32( m_width );
352 stream.Write32( m_height );
353 }
354
355 void wxRect2DInt::ReadFrom( wxDataInputStream &stream )
356 {
357 m_x = stream.Read32();
358 m_y = stream.Read32();
359 m_width = stream.Read32();
360 m_height = stream.Read32();
361 }
362 #endif // wxUSE_STREAMS
363
364
365 // wxTransform2D
366
367 void wxTransform2D::Transform( wxRect2DInt* r ) const
368 {
369 wxPoint2DInt a = r->GetLeftTop(), b = r->GetRightBottom();
370 Transform( &a );
371 Transform( &b );
372 *r = wxRect2DInt( a, b );
373 }
374
375 wxPoint2DInt wxTransform2D::Transform( const wxPoint2DInt &pt ) const
376 {
377 wxPoint2DInt res = pt;
378 Transform( &res );
379 return res;
380 }
381
382 wxRect2DInt wxTransform2D::Transform( const wxRect2DInt &r ) const
383 {
384 wxRect2DInt res = r;
385 Transform( &res );
386 return res;
387 }
388
389 void wxTransform2D::InverseTransform( wxRect2DInt* r ) const
390 {
391 wxPoint2DInt a = r->GetLeftTop(), b = r->GetRightBottom();
392 InverseTransform( &a );
393 InverseTransform( &b );
394 *r = wxRect2DInt( a , b );
395 }
396
397 wxPoint2DInt wxTransform2D::InverseTransform( const wxPoint2DInt &pt ) const
398 {
399 wxPoint2DInt res = pt;
400 InverseTransform( &res );
401 return res;
402 }
403
404 wxRect2DInt wxTransform2D::InverseTransform( const wxRect2DInt &r ) const
405 {
406 wxRect2DInt res = r;
407 InverseTransform( &res );
408 return res;
409 }
410
411 #endif // wxUSE_GEOMETRY