1 /* $Id: RCouple.h,v 1.7 2012/07/14 03:44:21 sarrazip Exp $
2 RCouple.h - Class representing a couple of integers.
3
4 flatzebra - Generic 2D Game Engine library
5 Copyright (C) 1999-2012 Pierre Sarrazin <http://sarrazip.com/>
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA.
21 */
22
23 #ifndef _H_RCouple
24 #define _H_RCouple
25
26 #include <flatzebra/Couple.h>
27
28 #include <assert.h>
29 #include <math.h>
30
31
32 namespace flatzebra {
33
34
35 class RCouple
36 /* Class representing a RCouple of floating point numbers.
37 */
38 {
39 public:
40 double x, y;
41 /* The components.
42 */
43
44 RCouple();
45 /* Builds a RCouple with ZERO values for the components.
46 */
47
48 RCouple(double a, double b);
49 /* Initiliazes a RCouple with x equal to a and y equal to b.
50 */
51
52 RCouple(const RCouple &c);
53 /* Copies the components of the RCouple 'c' into the current RCouple.
54 */
55
56 RCouple(const Couple &c);
57 /* Converts the integer couple 'c' into the current floating
58 point RCouple.
59 */
60
61 RCouple &operator = (const RCouple &c);
62 /* Replaces the components of the current RCouple by those of 'c'.
63 */
64
65 RCouple &operator = (const Couple &c);
66 /* Replaces the components of the current RCouple by a conversion
67 of the integer couple 'c' into a floating point couple.
68 */
69
70 ~RCouple();
71 /* Does nothing.
72 */
73
74 RCouple &zero();
75 /* Assign zero to both components.
76 Returns a reference to this object.
77 Was void until version 0.1.
78 */
79
80 bool isZero() const;
81 /* Returns true iff both components are zero.
82 */
83
84 bool isNonZero() const;
85 /* Returns true iff one or both components differ from zero.
86 */
87
88 double squaredLength() const;
89 /* Returns the square of the length of the vector represented by the RCouple.
90 */
91
92 double length() const;
93 /* Returns the length of the vector represented by the RCouple.
94 */
95
96 RCouple normalize() const;
97 /* Returns a vector with the same direction as this one, but of length 1.
98 If this vector is the origin, the origin is returned.
99 */
100
101 RCouple setLength(double newLength) const;
102 /* Returns a vector with the same direction as this one, but of the
103 specified length.
104 If this vector is the origin, the origin is returned.
105 */
106
107 Couple round() const;
108 /* Returns an integer couple created from the rounded values of
109 this floating point couple.
110 */
111
112 Couple floor() const;
113 /* Returns an integer couple created from the floored values of
114 this floating point couple.
115 */
116
117 Couple ceil() const;
118 /* Returns an integer couple created from the ceiled values of
119 this floating point couple.
120 */
121
122 RCouple &operator += (const RCouple &c);
123 RCouple &operator -= (const RCouple &c);
124 RCouple &operator *= (double n);
125 RCouple &operator /= (double n);
126 /* Return the current object as modified.
127 */
128
129 friend RCouple operator + (const RCouple &c1, const RCouple &c2);
130 friend RCouple operator - (const RCouple &c1, const RCouple &c2);
131 friend RCouple operator * (const RCouple &c1, double n);
132 friend RCouple operator * (double n, const RCouple &c1);
133 friend RCouple operator / (const RCouple &c1, double n);
134 friend bool operator == (const RCouple &c1, const RCouple &c2);
135 friend bool operator != (const RCouple &c1, const RCouple &c2);
136
137 static bool rectangleCollision(const RCouple &pos1,
138 const RCouple &rect1,
139 const RCouple &pos2,
140 const RCouple &size2);
141 /* Indicates if the two specified rectangles collide.
142 They collide if they have an intersection that has a non-zero surface.
143 pos1 and pos2 must be the upper-left coordinates of the rectangles.
144 */
145
146 double dotProduct(const RCouple &c) const;
147 /* Returns the scalar product of this couple with the given one.
148 */
149
150 RCouple project(const RCouple &c) const;
151 /* Returns the projection of vector 'c' on this vector.
152 This vector must not be zero. (See isZero() and isNonZero().)
153 */
154
155 RCouple getClosestPointOnSegment(const RCouple &segStart,
156 const RCouple &segEnd) const;
157 /* Returns the point on the given segment that is closest to this point.
158 segStart and segEnd give the end points of the segment, and must not
159 be equal.
160 If the projection of *this on the segment lies "before" segStart,
161 then segStart is returned; if the projection lies "after" segEnd,
162 then segEnd is returned.
163 */
164
165 bool isOnSegment(const RCouple &segStart,
166 const RCouple &segEnd) const;
167 /* Return true if this point lies on the given segment.
168 segStart and segEnd give the end points of the segment, and must not
169 be equal.
170 */
171
172 static const double tolerance;
173 /* Tolerance used in floating point comparisons when determining
174 if two values are "extremely" close.
175 */
176
177 bool safeEqual(const RCouple &c) const;
178 /* Indicates if this vector is "extremely" close to 'c'.
179 */
180
181 static bool safeEqual(double a, double b);
182 /* Indicates if the two numbers are "extremely" close.
183 */
184
185 static bool safeLower(double a, double b);
186 /* Indicates if the two numbers are a < b and not "extremely" close.
187 */
188
189 static bool safeLowerOrEqual(double a, double b);
190 /* Indicates if a < b or the two numbers are "extremely" close.
191 */
192
193 static bool safeGreater(double a, double b);
194 /* Indicates if the two numbers are a > b and not "extremely" close.
195 */
196
197 static bool safeGreaterOrEqual(double a, double b);
198 /* Indicates if a > b or the two numbers are "extremely" close.
199 */
200
201 };
202
203
204 //
205 // IMPLEMENTATION (inline functions)
206 //
207
208
RCouple()209 inline RCouple::RCouple()
210 : x(0), y(0)
211 {
212 }
213
214
RCouple(double a,double b)215 inline RCouple::RCouple(double a, double b)
216 : x(a), y(b)
217 {
218 }
219
220
RCouple(const RCouple & c)221 inline RCouple::RCouple(const RCouple &c)
222 : x(c.x), y(c.y)
223 {
224 }
225
226
RCouple(const Couple & c)227 inline RCouple::RCouple(const Couple &c)
228 : x(c.x), y(c.y)
229 {
230 }
231
232
233 inline RCouple &RCouple::operator = (const RCouple &c)
234 {
235 x = c.x;
236 y = c.y;
237 return *this;
238 }
239
240
241 inline RCouple &RCouple::operator = (const Couple &c)
242 {
243 x = c.x;
244 y = c.y;
245 return *this;
246 }
247
248
~RCouple()249 inline RCouple::~RCouple()
250 {
251 }
252
253
zero()254 inline RCouple &RCouple::zero()
255 {
256 x = y = 0;
257 return *this;
258 }
259
260
isZero()261 inline bool RCouple::isZero() const
262 {
263 return (x == 0 && y == 0);
264 }
265
266
isNonZero()267 inline bool RCouple::isNonZero() const
268 {
269 return (x != 0 || y != 0);
270 }
271
272
273 inline RCouple &RCouple::operator += (const RCouple &c)
274 {
275 x += c.x;
276 y += c.y;
277 return *this;
278 }
279
280
281 inline RCouple &RCouple::operator -= (const RCouple &c)
282 {
283 x -= c.x;
284 y -= c.y;
285 return *this;
286 }
287
288
289 inline RCouple &RCouple::operator *= (double n)
290 {
291 x *= n;
292 y *= n;
293 return *this;
294 }
295
296
297 inline RCouple &RCouple::operator /= (double n)
298 {
299 x /= n;
300 y /= n;
301 return *this;
302 }
303
304
305 inline RCouple operator + (const RCouple &c1, const RCouple &c2)
306 {
307 RCouple c(c1);
308 return c += c2;
309 }
310
311
312 inline RCouple operator - (const RCouple &c1, const RCouple &c2)
313 {
314 RCouple c(c1);
315 return c -= c2;
316 }
317
318
319 inline RCouple operator * (const RCouple &c1, double n)
320 {
321 RCouple c(c1);
322 return c *= n;
323 }
324
325
326 inline RCouple operator * (double n, const RCouple &c1)
327 {
328 RCouple c(c1);
329 return c *= n;
330 }
331
332
333 inline RCouple operator / (const RCouple &c1, double n)
334 {
335 RCouple c(c1);
336 return c /= n;
337 }
338
339
340 inline bool operator == (const RCouple &c1, const RCouple &c2)
341 {
342 return (c1.x == c2.x && c1.y == c2.y);
343 }
344
345
346 inline bool operator != (const RCouple &c1, const RCouple &c2)
347 {
348 return !(c1 == c2);
349 }
350
351
squaredLength()352 inline double RCouple::squaredLength() const
353 {
354 return x * x + y * y;
355 }
356
357
length()358 inline double RCouple::length() const
359 {
360 return hypot(x, y);
361 }
362
363
normalize()364 inline RCouple RCouple::normalize() const
365 {
366 if (isZero())
367 return RCouple();
368 return *this / length();
369 }
370
371
setLength(double newLength)372 inline RCouple RCouple::setLength(double newLength) const
373 {
374 if (isZero())
375 return RCouple();
376 return *this / length() * newLength;
377 }
378
379
round()380 inline Couple RCouple::round() const
381 {
382 return Couple(
383 int(x >= 0 ? (x + 0.5) : (x - 0.5)),
384 int(y >= 0 ? (y + 0.5) : (y - 0.5)));
385 }
386
387
floor()388 inline Couple RCouple::floor() const
389 {
390 return Couple(static_cast<int>(::floor(x)), static_cast<int>(::floor(y)));
391 }
392
ceil()393 inline Couple RCouple::ceil() const
394 {
395 return Couple(static_cast<int>(::ceil(x)), static_cast<int>(::ceil(y)));
396 }
397
398
dotProduct(const RCouple & c)399 inline double RCouple::dotProduct(const RCouple &c) const
400 {
401 return x * c.x + y * c.y;
402 }
403
404
project(const RCouple & c)405 inline RCouple RCouple::project(const RCouple &c) const
406 {
407 assert(isNonZero());
408 return (dotProduct(c) / dotProduct(*this)) * *this;
409 }
410
411
safeEqual(const RCouple & c)412 inline bool RCouple::safeEqual(const RCouple &c) const
413 {
414 return fabs(x - c.x) < tolerance && fabs(y - c.y) < tolerance;
415 }
416
417
safeEqual(double a,double b)418 inline bool RCouple::safeEqual(double a, double b)
419 {
420 return fabs(a - b) < tolerance;
421 }
422
423
safeLower(double a,double b)424 inline bool RCouple::safeLower(double a, double b)
425 {
426 return !safeEqual(a, b) && a < b;
427 }
428
429
safeLowerOrEqual(double a,double b)430 inline bool RCouple::safeLowerOrEqual(double a, double b)
431 {
432 return safeEqual(a, b) || a < b;
433 }
434
435
safeGreater(double a,double b)436 inline bool RCouple::safeGreater(double a, double b)
437 {
438 return !safeEqual(a, b) && a > b;
439 }
440
441
safeGreaterOrEqual(double a,double b)442 inline bool RCouple::safeGreaterOrEqual(double a, double b)
443 {
444 return safeEqual(a, b) || a > b;
445 }
446
447
448 } // namespace flatzebra
449
450
451 #endif /* _H_RCouple */
452