1 /*************************************************************************/
2 /* vector2.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30
31 #include "vector2.h"
32
angle() const33 real_t Vector2::angle() const {
34
35 return Math::atan2(y, x);
36 }
37
length() const38 real_t Vector2::length() const {
39
40 return Math::sqrt(x * x + y * y);
41 }
42
length_squared() const43 real_t Vector2::length_squared() const {
44
45 return x * x + y * y;
46 }
47
normalize()48 void Vector2::normalize() {
49
50 real_t l = x * x + y * y;
51 if (l != 0) {
52
53 l = Math::sqrt(l);
54 x /= l;
55 y /= l;
56 }
57 }
58
normalized() const59 Vector2 Vector2::normalized() const {
60
61 Vector2 v = *this;
62 v.normalize();
63 return v;
64 }
65
is_normalized() const66 bool Vector2::is_normalized() const {
67 // use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
68 return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON);
69 }
70
distance_to(const Vector2 & p_vector2) const71 real_t Vector2::distance_to(const Vector2 &p_vector2) const {
72
73 return Math::sqrt((x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y));
74 }
75
distance_squared_to(const Vector2 & p_vector2) const76 real_t Vector2::distance_squared_to(const Vector2 &p_vector2) const {
77
78 return (x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y);
79 }
80
angle_to(const Vector2 & p_vector2) const81 real_t Vector2::angle_to(const Vector2 &p_vector2) const {
82
83 return Math::atan2(cross(p_vector2), dot(p_vector2));
84 }
85
angle_to_point(const Vector2 & p_vector2) const86 real_t Vector2::angle_to_point(const Vector2 &p_vector2) const {
87
88 return Math::atan2(y - p_vector2.y, x - p_vector2.x);
89 }
90
dot(const Vector2 & p_other) const91 real_t Vector2::dot(const Vector2 &p_other) const {
92
93 return x * p_other.x + y * p_other.y;
94 }
95
cross(const Vector2 & p_other) const96 real_t Vector2::cross(const Vector2 &p_other) const {
97
98 return x * p_other.y - y * p_other.x;
99 }
100
sign() const101 Vector2 Vector2::sign() const {
102
103 return Vector2(SGN(x), SGN(y));
104 }
105
floor() const106 Vector2 Vector2::floor() const {
107
108 return Vector2(Math::floor(x), Math::floor(y));
109 }
110
ceil() const111 Vector2 Vector2::ceil() const {
112
113 return Vector2(Math::ceil(x), Math::ceil(y));
114 }
115
round() const116 Vector2 Vector2::round() const {
117
118 return Vector2(Math::round(x), Math::round(y));
119 }
120
rotated(real_t p_by) const121 Vector2 Vector2::rotated(real_t p_by) const {
122
123 Vector2 v;
124 v.set_rotation(angle() + p_by);
125 v *= length();
126 return v;
127 }
128
posmod(const real_t p_mod) const129 Vector2 Vector2::posmod(const real_t p_mod) const {
130 return Vector2(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod));
131 }
132
posmodv(const Vector2 & p_modv) const133 Vector2 Vector2::posmodv(const Vector2 &p_modv) const {
134 return Vector2(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y));
135 }
136
project(const Vector2 & p_b) const137 Vector2 Vector2::project(const Vector2 &p_b) const {
138 return p_b * (dot(p_b) / p_b.length_squared());
139 }
140
snapped(const Vector2 & p_by) const141 Vector2 Vector2::snapped(const Vector2 &p_by) const {
142
143 return Vector2(
144 Math::stepify(x, p_by.x),
145 Math::stepify(y, p_by.y));
146 }
147
clamped(real_t p_len) const148 Vector2 Vector2::clamped(real_t p_len) const {
149
150 real_t l = length();
151 Vector2 v = *this;
152 if (l > 0 && p_len < l) {
153
154 v /= l;
155 v *= p_len;
156 }
157
158 return v;
159 }
160
cubic_interpolate(const Vector2 & p_b,const Vector2 & p_pre_a,const Vector2 & p_post_b,real_t p_t) const161 Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const {
162
163 Vector2 p0 = p_pre_a;
164 Vector2 p1 = *this;
165 Vector2 p2 = p_b;
166 Vector2 p3 = p_post_b;
167
168 real_t t = p_t;
169 real_t t2 = t * t;
170 real_t t3 = t2 * t;
171
172 Vector2 out;
173 out = 0.5 * ((p1 * 2.0) +
174 (-p0 + p2) * t +
175 (2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 +
176 (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3);
177 return out;
178 }
179
move_toward(const Vector2 & p_to,const real_t p_delta) const180 Vector2 Vector2::move_toward(const Vector2 &p_to, const real_t p_delta) const {
181 Vector2 v = *this;
182 Vector2 vd = p_to - v;
183 real_t len = vd.length();
184 return len <= p_delta || len < CMP_EPSILON ? p_to : v + vd / len * p_delta;
185 }
186
187 // slide returns the component of the vector along the given plane, specified by its normal vector.
slide(const Vector2 & p_normal) const188 Vector2 Vector2::slide(const Vector2 &p_normal) const {
189 #ifdef MATH_CHECKS
190 ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized.");
191 #endif
192 return *this - p_normal * this->dot(p_normal);
193 }
194
bounce(const Vector2 & p_normal) const195 Vector2 Vector2::bounce(const Vector2 &p_normal) const {
196 return -reflect(p_normal);
197 }
198
reflect(const Vector2 & p_normal) const199 Vector2 Vector2::reflect(const Vector2 &p_normal) const {
200 #ifdef MATH_CHECKS
201 ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized.");
202 #endif
203 return 2.0 * p_normal * this->dot(p_normal) - *this;
204 }
205
is_equal_approx(const Vector2 & p_v) const206 bool Vector2::is_equal_approx(const Vector2 &p_v) const {
207 return Math::is_equal_approx(x, p_v.x) && Math::is_equal_approx(y, p_v.y);
208 }
209
210 /* Vector2i */
211
operator +(const Vector2i & p_v) const212 Vector2i Vector2i::operator+(const Vector2i &p_v) const {
213
214 return Vector2i(x + p_v.x, y + p_v.y);
215 }
operator +=(const Vector2i & p_v)216 void Vector2i::operator+=(const Vector2i &p_v) {
217
218 x += p_v.x;
219 y += p_v.y;
220 }
operator -(const Vector2i & p_v) const221 Vector2i Vector2i::operator-(const Vector2i &p_v) const {
222
223 return Vector2i(x - p_v.x, y - p_v.y);
224 }
operator -=(const Vector2i & p_v)225 void Vector2i::operator-=(const Vector2i &p_v) {
226
227 x -= p_v.x;
228 y -= p_v.y;
229 }
230
operator *(const Vector2i & p_v1) const231 Vector2i Vector2i::operator*(const Vector2i &p_v1) const {
232
233 return Vector2i(x * p_v1.x, y * p_v1.y);
234 };
235
operator *(const int & rvalue) const236 Vector2i Vector2i::operator*(const int &rvalue) const {
237
238 return Vector2i(x * rvalue, y * rvalue);
239 };
operator *=(const int & rvalue)240 void Vector2i::operator*=(const int &rvalue) {
241
242 x *= rvalue;
243 y *= rvalue;
244 };
245
operator /(const Vector2i & p_v1) const246 Vector2i Vector2i::operator/(const Vector2i &p_v1) const {
247
248 return Vector2i(x / p_v1.x, y / p_v1.y);
249 };
250
operator /(const int & rvalue) const251 Vector2i Vector2i::operator/(const int &rvalue) const {
252
253 return Vector2i(x / rvalue, y / rvalue);
254 };
255
operator /=(const int & rvalue)256 void Vector2i::operator/=(const int &rvalue) {
257
258 x /= rvalue;
259 y /= rvalue;
260 };
261
operator -() const262 Vector2i Vector2i::operator-() const {
263
264 return Vector2i(-x, -y);
265 }
266
operator ==(const Vector2i & p_vec2) const267 bool Vector2i::operator==(const Vector2i &p_vec2) const {
268
269 return x == p_vec2.x && y == p_vec2.y;
270 }
operator !=(const Vector2i & p_vec2) const271 bool Vector2i::operator!=(const Vector2i &p_vec2) const {
272
273 return x != p_vec2.x || y != p_vec2.y;
274 }
275