Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
FixedVector2D.h
Go to the documentation of this file.
1/* Copyright (C) 2020 Wildfire Games.
2 * This file is part of 0 A.D.
3 *
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef INCLUDED_FIXED_VECTOR2D
19#define INCLUDED_FIXED_VECTOR2D
20
21#include "maths/Fixed.h"
22#include "maths/Sqrt.h"
23
25{
26public:
28
31
32 /// Vector equality
33 bool operator==(const CFixedVector2D& v) const
34 {
35 return (X == v.X && Y == v.Y);
36 }
37
38 /// Vector inequality
39 bool operator!=(const CFixedVector2D& v) const
40 {
41 return (X != v.X || Y != v.Y);
42 }
43
44 /// Vector addition
46 {
47 return CFixedVector2D(X + v.X, Y + v.Y);
48 }
49
50 /// Vector subtraction
52 {
53 return CFixedVector2D(X - v.X, Y - v.Y);
54 }
55
56 /// Negation
58 {
59 return CFixedVector2D(-X, -Y);
60 }
61
62 /// Vector addition
64 {
65 *this = *this + v;
66 return *this;
67 }
68
69 /// Vector subtraction
71 {
72 *this = *this - v;
73 return *this;
74 }
75
76 /// Scalar multiplication by an integer
78 {
79 return CFixedVector2D(X*n, Y*n);
80 }
81
82 /// Scalar division by an integer. Must not have n == 0.
84 {
85 return CFixedVector2D(X/n, Y/n);
86 }
87
88 /**
89 * Multiply by a CFixed. Likely to overflow if both numbers are large,
90 * so we use an ugly name instead of operator* to make it obvious.
91 */
93 {
94 return CFixedVector2D(X.Multiply(n), Y.Multiply(n));
95 }
96
97 /**
98 * Returns the length of the vector.
99 * Will not overflow if the result can be represented as type 'fixed'.
100 */
101 fixed Length() const
102 {
103 // Do intermediate calculations with 64-bit ints to avoid overflows
104 u64 xx = SQUARE_U64_FIXED(X);
105 u64 yy = SQUARE_U64_FIXED(Y);
106 u64 d2 = xx + yy;
107 CheckUnsignedAdditionOverflow(d2, xx, L"Overflow in CFixedVector2D::Length() part 1")
108
109 u32 d = isqrt64(d2);
110
111 CheckU32CastOverflow(d, i32, L"Overflow in CFixedVector2D::Length() part 2")
112 fixed r;
113 r.SetInternalValue(static_cast<i32>(d));
114 return r;
115 }
116
117 /**
118 * Returns -1, 0, +1 depending on whether length is less/equal/greater
119 * than the argument.
120 * Avoids sqrting and overflowing.
121 */
122 int CompareLength(fixed cmp) const
123 {
124 u64 d2 = SQUARE_U64_FIXED(X) + SQUARE_U64_FIXED(Y); // d2 <= 2^63 (no overflow)
125 u64 cmpSquared = SQUARE_U64_FIXED(cmp);
126
127 if (d2 < cmpSquared)
128 return -1;
129
130 if (d2 > cmpSquared)
131 return +1;
132
133 return 0;
134 }
135
136 /**
137 * Same as above, but avoids squaring the compared value.
138 * The argument must be the result of an SQUARE_U64_FIXED operation.
139 */
140 int CompareLengthSquared(u64 cmpSquared) const
141 {
142 u64 d2 = SQUARE_U64_FIXED(X) + SQUARE_U64_FIXED(Y); // d2 <= 2^63 (no overflow)
143
144 if (d2 < cmpSquared)
145 return -1;
146
147 if (d2 > cmpSquared)
148 return +1;
149
150 return 0;
151 }
152
153 /**
154 * Returns -1, 0, +1 depending on whether length is less/equal/greater
155 * than the argument's length.
156 * Avoids sqrting and overflowing.
157 */
158 int CompareLength(const CFixedVector2D& other) const
159 {
161 u64 od2 = SQUARE_U64_FIXED(other.X) + SQUARE_U64_FIXED(other.Y);
162
163 if (d2 < od2)
164 return -1;
165
166 if (d2 > od2)
167 return +1;
168
169 return 0;
170 }
171
172 bool IsZero() const
173 {
174 return X.IsZero() && Y.IsZero();
175 }
176
177 /**
178 * Normalize the vector so that length is close to 1.
179 * If length is 0, does nothing.
180 */
182 {
183 if (!IsZero())
184 {
185 fixed l = Length();
186 X = X / l;
187 Y = Y / l;
188 }
189 }
190
191 /**
192 * Normalize the vector so that length is close to n.
193 * If length is 0, does nothing.
194 */
196 {
197 fixed l = Length();
198 if (!l.IsZero())
199 {
200 X = X.MulDiv(n, l);
201 Y = Y.MulDiv(n, l);
202 }
203 }
204
205 /**
206 * Compute the dot product of this vector with another.
207 * Likely to overflow if both vectors are large-ish (around the 200 range).
208 */
209 fixed Dot(const CFixedVector2D& v) const
210 {
213 CheckSignedAdditionOverflow(i64, x, y, L"Overflow in CFixedVector2D::Dot() part 1", L"Underflow in CFixedVector2D::Dot() part 1")
214 i64 sum = x + y;
215 sum >>= fixed::fract_bits;
216
217 CheckCastOverflow(sum, i32, L"Overflow in CFixedVector2D::Dot() part 2", L"Underflow in CFixedVector2D::Dot() part 2")
218 fixed ret;
219 ret.SetInternalValue(static_cast<i32>(sum));
220 return ret;
221 }
222
223 /**
224 * @return -1, 0 or 1 if this and @v face respectively opposite directions, perpendicular, or same directions.
225 */
227 {
230 return x > -y ? 1 : x < -y ? -1 : 0;
231 }
232
234 {
235 return CFixedVector2D(Y, -X);
236 }
237
238 /**
239 * Rotate the vector by the given angle (anticlockwise).
240 */
242 {
243 fixed s, c;
244 sincos_approx(angle, s, c);
245 return CFixedVector2D(X.Multiply(c) + Y.Multiply(s), Y.Multiply(c) - X.Multiply(s));
246 }
247};
248
249#endif // INCLUDED_FIXED_VECTOR2D
void sincos_approx(CFixed_15_16 a, CFixed_15_16 &sin_out, CFixed_15_16 &cos_out)
Compute sin(a) and cos(a).
Definition: Fixed.cpp:187
#define SQUARE_U64_FIXED(a)
Definition: Fixed.h:39
#define MUL_I64_I32_I32(a, b)
Definition: Fixed.h:37
#define CheckCastOverflow(var, targetType, overflowWarning, underflowWarning)
Definition: Fixed.h:70
#define CheckSignedAdditionOverflow(type, left, right, overflowWarning, underflowWarning)
Definition: Fixed.h:64
#define CheckUnsignedAdditionOverflow(result, operand, overflowWarning)
Definition: Fixed.h:80
#define CheckU32CastOverflow(var, targetType, overflowWarning)
Definition: Fixed.h:76
u32 isqrt64(u64 n)
64-bit integer square root.
Definition: Sqrt.cpp:23
Definition: FixedVector2D.h:25
fixed X
Definition: FixedVector2D.h:27
CFixedVector2D operator+(const CFixedVector2D &v) const
Vector addition.
Definition: FixedVector2D.h:45
int RelativeOrientation(const CFixedVector2D &v) const
Definition: FixedVector2D.h:226
CFixedVector2D & operator-=(const CFixedVector2D &v)
Vector subtraction.
Definition: FixedVector2D.h:70
void Normalize(fixed n)
Normalize the vector so that length is close to n.
Definition: FixedVector2D.h:195
CFixedVector2D operator-() const
Negation.
Definition: FixedVector2D.h:57
int CompareLength(fixed cmp) const
Returns -1, 0, +1 depending on whether length is less/equal/greater than the argument.
Definition: FixedVector2D.h:122
fixed Dot(const CFixedVector2D &v) const
Compute the dot product of this vector with another.
Definition: FixedVector2D.h:209
int CompareLength(const CFixedVector2D &other) const
Returns -1, 0, +1 depending on whether length is less/equal/greater than the argument's length.
Definition: FixedVector2D.h:158
CFixedVector2D operator*(int n) const
Scalar multiplication by an integer.
Definition: FixedVector2D.h:77
CFixedVector2D Multiply(fixed n) const
Multiply by a CFixed.
Definition: FixedVector2D.h:92
bool operator!=(const CFixedVector2D &v) const
Vector inequality.
Definition: FixedVector2D.h:39
CFixedVector2D Perpendicular() const
Definition: FixedVector2D.h:233
CFixedVector2D Rotate(fixed angle) const
Rotate the vector by the given angle (anticlockwise).
Definition: FixedVector2D.h:241
fixed Length() const
Returns the length of the vector.
Definition: FixedVector2D.h:101
fixed Y
Definition: FixedVector2D.h:27
CFixedVector2D()
Definition: FixedVector2D.h:29
CFixedVector2D(fixed X, fixed Y)
Definition: FixedVector2D.h:30
CFixedVector2D operator/(int n) const
Scalar division by an integer. Must not have n == 0.
Definition: FixedVector2D.h:83
bool IsZero() const
Definition: FixedVector2D.h:172
CFixedVector2D & operator+=(const CFixedVector2D &v)
Vector addition.
Definition: FixedVector2D.h:63
bool operator==(const CFixedVector2D &v) const
Vector equality.
Definition: FixedVector2D.h:33
int CompareLengthSquared(u64 cmpSquared) const
Same as above, but avoids squaring the compared value.
Definition: FixedVector2D.h:140
void Normalize()
Normalize the vector so that length is close to 1.
Definition: FixedVector2D.h:181
CFixedVector2D operator-(const CFixedVector2D &v) const
Vector subtraction.
Definition: FixedVector2D.h:51
A simple fixed-point number class.
Definition: Fixed.h:120
void SetInternalValue(T n)
Definition: Fixed.h:136
CFixed Multiply(CFixed n) const
Multiply by a CFixed.
Definition: Fixed.h:321
CFixed MulDiv(CFixed m, CFixed d) const
Compute this*m/d.
Definition: Fixed.h:341
constexpr bool IsZero() const
Returns true if the number is precisely 0.
Definition: Fixed.h:209
T GetInternalValue() const
Definition: Fixed.h:135
@ fract_bits
Definition: Fixed.h:127
uint64_t u64
Definition: types.h:40
int32_t i32
Definition: types.h:34
int64_t i64
Definition: types.h:35
uint32_t u32
Definition: types.h:39