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