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