From 90da11db6830444581e2df58c0f9d5a2a28fb245 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Tue, 15 Mar 2022 12:26:18 +0100 Subject: [PATCH] Added Vector2 --- CMakeLists.txt | 3 +- include/Vector2.h | 222 ++++++++++++++++++++++ src/Vector2.cpp | 126 +++++++++++++ test/Vector2_test.cc | 424 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 774 insertions(+), 1 deletion(-) create mode 100644 include/Vector2.h create mode 100644 src/Vector2.cpp create mode 100644 test/Vector2_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 777d4cf..7968141 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,12 +15,13 @@ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) include_directories(include) -add_library(VectorAlgebra STATIC "src/Vector3.cpp" "src/Quaternion.cpp") +add_library(VectorAlgebra STATIC "src/Vector2.cpp" "src/Vector3.cpp" "src/Quaternion.cpp" ) enable_testing() add_executable( VectorAlgebraTest + "test/Vector2_test.cc" "test/Vector3_test.cc" "test/Quaternion_test.cc" ) diff --git a/include/Vector2.h b/include/Vector2.h new file mode 100644 index 0000000..ec8d274 --- /dev/null +++ b/include/Vector2.h @@ -0,0 +1,222 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0.If a copy of the MPL was not distributed with this +// file, You can obtain one at https ://mozilla.org/MPL/2.0/. + +#ifndef VECTOR2_H +#define VECTOR2_H + +extern "C" { + /// + /// 2-dimensional Vector representation + /// + /// This is a C-style implementation + /// This uses the right-handed coordinate system. + typedef struct Vec2 { + /// + /// The right axis of the vector + /// + float x; + /// + /// The upward/forward axis of the vector + /// + float y; + + } Vec2; +} + +/// +/// A 2-dimensional vector +/// +/// This uses the right-handed coordinate system. +struct Vector2 : Vec2 { +public: + /// + /// Create a new 2-dimensinal zero vector + /// + Vector2(); + /// + /// Create a new 2-dimensional vector + /// + /// x axis value + /// y axis value + Vector2(float x, float y); + /// + /// Create a vector from C-style Vec2 + /// + /// The C-style Vec + Vector2(Vec2 v); + + ~Vector2(); + + /// + /// A vector with zero for all axis + /// + const static Vector2 zero; + /// + /// A vector with values (1, 0) + /// + const static Vector2 right; + /// + /// A vector3 with values (-1, 0) + /// + const static Vector2 left; + /// + /// A vector with values (0, 1) + /// + const static Vector2 up; + /// + /// A vector with values (0, -1) + /// + const static Vector2 down; + /// + /// A vector with values (0, 1) + /// + const static Vector2 forward; + /// + /// A vector with values (0, -1) + /// + const static Vector2 back; + + /// + /// The length of a vector + /// + /// The vector for which you need the length + /// The length of the given vector + static float Magnitude(const Vector2& vector); + /// + /// The length of this vector + /// + /// The length of this vector + float magnitude() const; + /// + /// The squared length of a vector + /// + /// The vector for which you need the squared length + /// The squatred length + /// The squared length is computationally simpler than the real length. + /// Think of Pythagoras A^2 + B^2 = C^2. + /// This leaves out the calculation of the squared root of C. + static float SqrMagnitude(const Vector2& vector); + /// + /// The squared length of this vector + /// + /// The squared length + /// The squared length is computationally simpler than the real length. + /// Think of Pythagoras A^2 + B^2 = C^2. + /// This leaves out the calculation of the squared root of C. + float sqrMagnitude() const; + /// + /// Connvert a vector to a length of 1 + /// + /// The vector to convert + /// The vector with length 1 + static Vector2 Normalize(Vector2 vector); + /// + /// Convert the vector to a length of a + /// + /// The vector with length 1 + Vector2 normalized() const; + + /// + /// Negate the vector + /// + /// The negated vector + /// This will result in a vector pointing in the opposite direction + Vector2 operator -(); + /// + /// Subtract a vector from this vector + /// + /// The vector to subtract from this vector + /// The result of the subtraction + Vector2 operator -(const Vector2& vector) const; + + /// + /// Add another vector to this vector + /// + /// The vector to add + /// The result of adding the vector + Vector2 operator +(const Vector2& vector2) const; + + /// + /// Scale a vector using another vector + /// + /// The vector to scale + /// A vector with scaling factors + /// The scaled vector + /// Each component of the vector v1 will be multiplied with the + /// component from the scaling vector v2. + static Vector2 Scale(const Vector2& vector1, const Vector2& vector2); + /// + /// Scale a vector uniformly up + /// + /// The scaling factor + /// The scaled vector + /// Each component of the vector will be multipled with the same factor. + Vector2 operator *(float factor) const; + /// + /// Scale a vector uniformy down + /// + /// The scaling factor + /// The scaled vector + /// Each componet of the vector will be divided by the same factor. + Vector2 operator /(const float& factor); + + /// + /// The dot product of two vectors + /// + /// The first vector + /// The second vector + /// The dot product of the two vectors + static float Dot(const Vector2& vector1, const Vector2& vector2); + + /// + /// Check is this vector is equal to the given vector + /// + /// The vector to check against + /// True if it is identical to the given vector + /// Note this uses float comparison to check equality which + /// may have strange effects. Equality on float should be avoided. + bool operator ==(const Vector2& vector); + + /// + /// The distance between two vectors + /// + /// The first vector + /// The second vectors + /// The distance between the two vectors + static float Distance(const Vector2& vector1, const Vector2& vector2); + + /// + /// Calculate the angle between two vectors + /// + /// The first vector + /// The second vector + /// + /// This reterns an unsigned angle which is the shortest distance + /// between the two vectors. Use Vector3::SignedAngle if a + /// signed angle is needed. + static float Angle(Vector2 vector1, Vector2 vector2); + + /// + /// Calculate the angle between two vectors rotation around an axis. + /// + /// The starting vector + /// The ending vector + /// The axis to rotate around + /// The signed angle + static float SignedAngle(Vector2 from, Vector2 to); + + /// + /// Lerp between two vectors + /// + /// The from vector + /// The to vector + /// The interpolation distance (0..1) + /// The lerped vector + /// The factor f is unclamped. Value 0 matches the *from* vector, Value 1 matches the *to* vector + /// Value -1 is *from* vector minus the difference between *from* and *to* etc. + static Vector2 Lerp(Vector2 from, Vector2 to, float f); + +}; + +#endif \ No newline at end of file diff --git a/src/Vector2.cpp b/src/Vector2.cpp new file mode 100644 index 0000000..971ecab --- /dev/null +++ b/src/Vector2.cpp @@ -0,0 +1,126 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0.If a copy of the MPL was not distributed with this +// file, You can obtain one at https ://mozilla.org/MPL/2.0/. + +#include +#include "Vector2.h" + +const float Deg2Rad = 0.0174532924F; +const float Rad2Deg = 57.29578F; +const float epsilon = 1E-05f; + +Vector2::Vector2() { + x = 0; + y = 0; +} + +Vector2::Vector2(float _x, float _y) { + x = _x; + y = _y; +} + +Vector2::Vector2(Vec2 v) { + x = v.x; + y = v.y; +} + +Vector2::~Vector2() { +} + +const Vector2 Vector2::zero = Vector2(0, 0); +const Vector2 Vector2::right = Vector2(1, 0); +const Vector2 Vector2::left = Vector2(-1, 0); +const Vector2 Vector2::up = Vector2(0, 1); +const Vector2 Vector2::down = Vector2(0, -1); +const Vector2 Vector2::forward = Vector2(0, 1); +const Vector2 Vector2::back = Vector2(0, -1); + +float Vector2::Magnitude(const Vector2& a) { + return sqrtf(a.x * a.x + a.y * a.y); +} +float Vector2::magnitude() const { + return (float)sqrtf(x * x + y * y); +} + +float Vector2::SqrMagnitude(const Vector2& a) { + return a.x * a.x + a.y * a.y; +} +float Vector2::sqrMagnitude() const { + return(x * x + y * y); +} + +Vector2 Vector2::Normalize(Vector2 v) { + float num = Vector2::Magnitude(v); + Vector2 result = Vector2::zero; + if (num > epsilon) { + result = v / num; + } + return result; +} +Vector2 Vector2::normalized() const { + float num = this->magnitude(); + Vector2 result = Vector2::zero; + if (num > epsilon) { + result = ((Vector2)*this) / num; + } + return result; +} + +Vector2 Vector2::operator -(const Vector2& v2) const { + return Vector2(this->x - v2.x, this->y - v2.y); +} + +Vector2 Vector2::operator -() { + return Vector2(-this->x, -this->y); +} + +Vector2 Vector2::operator +(const Vector2& v2) const { + return Vector2(this->x + v2.x, this->y + v2.y); +} + +Vector2 Vector2::Scale(const Vector2& p1, const Vector2& p2) { + return Vector2(p1.x * p2.x, p1.y * p2.y); +} + +Vector2 Vector2::operator *(float f) const { + return Vector2(this->x * f, this->y * f); +} + +Vector2 Vector2::operator/(const float& d) { + return Vector2(this->x / d, this->y / d); +} + +float Vector2::Dot(const Vector2& v1, const Vector2& v2) { + return v1.x * v2.x + v1.y * v2.y; +} + +bool Vector2::operator==(const Vector2& v) { + return (this->x == v.x && this->y == v.y); +} + +float Vector2::Distance(const Vector2& p1, const Vector2& p2) { + return Magnitude(p1 - p2); +} + +float Vector2::Angle(Vector2 from, Vector2 to) { + return (float) fabs(SignedAngle(from, to)); +} + +float Vector2::SignedAngle(Vector2 from, Vector2 to) { + float sqrMagFrom = from.sqrMagnitude(); + float sqrMagTo = to.sqrMagnitude(); + + if (sqrMagFrom == 0 || sqrMagTo == 0) + return 0; + if (!isfinite(sqrMagFrom) || !isfinite(sqrMagTo)) + return nanf(""); + + float angleFrom = atan2(from.y, from.x); + float angleTo = atan2(to.y, to.x); + return (angleTo - angleFrom) * Rad2Deg; +} + +static Vector2 Lerp(Vector2 from, Vector2 to, float f) { + Vector2 v = from + (to - from) * f; + return v; +} diff --git a/test/Vector2_test.cc b/test/Vector2_test.cc new file mode 100644 index 0000000..45b2871 --- /dev/null +++ b/test/Vector2_test.cc @@ -0,0 +1,424 @@ +#if GTEST +#include +#include +#include + +#include "Vector2.h" + +#define FLOAT_INFINITY std::numeric_limits::infinity() + +TEST(Vector2, Magnitude) { + Vector2 v = Vector2(1, 2); + float m = 0; + + m = v.magnitude(); + EXPECT_FLOAT_EQ(m, 2.236068F) << "v.magnitude 1 2"; + + m = Vector2::Magnitude(v); + EXPECT_FLOAT_EQ(m, 2.236068F) << "Vector2::Magnitude 1 2"; + + v = Vector2(-1, -2); + m = v.magnitude(); + EXPECT_FLOAT_EQ(m, 2.236068F) << "v.magnitude -1 -2"; + + v = Vector2(0, 0); + m = v.magnitude(); + EXPECT_FLOAT_EQ(m, 0) << "v.magnitude 0 0 "; + + if (std::numeric_limits::is_iec559) { + v = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); + m = v.magnitude(); + EXPECT_FLOAT_EQ(m, FLOAT_INFINITY) << "v.magnitude INFINITY INFINITY "; + + v = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); + m = v.magnitude(); + EXPECT_FLOAT_EQ(m, FLOAT_INFINITY) << "v.magnitude -INFINITY -INFINITY "; + } +} + +TEST(Vector2, SqrMagnitude) { + Vector2 v = Vector2(1, 2); + float m = 0; + + m = v.sqrMagnitude(); + EXPECT_FLOAT_EQ(m, 5) << "v.sqrMagnitude 1 2"; + + m = Vector2::SqrMagnitude(v); + EXPECT_FLOAT_EQ(m, 5) << "Vector2::SqrMagnitude 1 2"; + + v = Vector2(-1, -2); + m = v.sqrMagnitude(); + EXPECT_FLOAT_EQ(m, 5) << "v.sqrMagnitude -1 -2"; + + v = Vector2(0, 0); + m = v.sqrMagnitude(); + EXPECT_FLOAT_EQ(m, 0) << "v.sqrMagnitude 0 0 "; + + if (std::numeric_limits::is_iec559) { + v = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); + m = v.sqrMagnitude(); + EXPECT_FLOAT_EQ(m, FLOAT_INFINITY) << "v.sqrMagnitude INFINITY INFINITY "; + + v = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); + m = v.sqrMagnitude(); + EXPECT_FLOAT_EQ(m, FLOAT_INFINITY) << "v.sqrMagnitude -INFINITY -INFINITY "; + } +} + + +TEST(Vector2, Normalize) { + bool r = false; + + Vector2 v1 = Vector2(0, 2); + Vector2 v = Vector2::zero; + + v = v1.normalized(); + EXPECT_TRUE(v == Vector2(0, 1)) << "v.normalized 0 2"; + + v = Vector2::Normalize(v1); + EXPECT_TRUE(v == Vector2(0, 1)) << "Vector3::Normalize 0 2"; + + v1 = Vector2(0, -2); + v = v1.normalized(); + EXPECT_TRUE(v == Vector2(0, -1)) << "v.normalized 0 -2"; + + v1 = Vector2(0, 0); + v = v1.normalized(); + EXPECT_TRUE(v == Vector2(0, 0)) << "v.normalized 0 0"; + + if (std::numeric_limits::is_iec559) { + v1 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); + v = v1.normalized(); + r = isnan(v.x) && isnan(v.y); + EXPECT_TRUE(r) << "v.normalized INFINITY INFINITY"; + + v1 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); + v = v1.normalized(); + r = isnan(v.x) && isnan(v.y); + EXPECT_TRUE(r) << "v.normalized -INFINITY -INFINITY"; + + } +} + +TEST(Vector2, Negate) { + bool r = false; + + Vector2 v1 = Vector2(4, 5); + Vector2 v = Vector2::zero; + + v = -v1; + EXPECT_TRUE(v == Vector2(-4, -5)) << "- 4 5"; + + v1 = Vector2(-4, -5); + v = -v1; + EXPECT_TRUE(v == Vector2(4, 5)) << "- -4 -5"; + + v1 = Vector2(0, 0); + v = -v1; + EXPECT_TRUE(v == Vector2(0, 0)) << "- 0 0"; + + if (std::numeric_limits::is_iec559) { + v1 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); + v = -v1; + EXPECT_TRUE(v == Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY)) << "- INFINITY INFINITY"; + + v1 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); + v = -v1; + EXPECT_TRUE(v == Vector2(FLOAT_INFINITY, FLOAT_INFINITY)) << "- -INFINITY -INFINITY"; + } +} + +TEST(Vector2, Subtract) { + bool r = false; + + Vector2 v1 = Vector2(4, 5); + Vector2 v2 = Vector2(1, 2); + Vector2 v = Vector2::zero; + + v = v1 - v2; + EXPECT_TRUE(v == Vector2(3, 3)) << "4 5 - 1 2"; + + v2 = Vector2(-1, -2); + v = v1 - v2; + EXPECT_TRUE(v == Vector2(5, 7)) << "4 5 - -1 -2"; + + v2 = Vector2(4, 5); + v = v1 - v2; + EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 - 4 5"; + + v2 = Vector2(0, 0); + v = v1 - v2; + EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 - 0 0"; + + if (std::numeric_limits::is_iec559) { + v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); + v = v1 - v2; + EXPECT_TRUE(v == Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY)) << "4 5 - INFINITY INFINITY"; + + v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); + v = v1 - v2; + EXPECT_TRUE(v == Vector2(FLOAT_INFINITY, FLOAT_INFINITY)) << "4 5 - -INFINITY -INFINITY"; + } +} + +TEST(Vector2, Addition) { + + Vector2 v1 = Vector2(4, 5); + Vector2 v2 = Vector2(1, 2); + Vector2 v = Vector2::zero; + bool r = false; + + v = v1 + v2; + EXPECT_TRUE(v == Vector2(5, 7)) << "4 5 + 1 2"; + + v2 = Vector2(-1, -2); + v = v1 + v2; + EXPECT_TRUE(v == Vector2(3, 3)) << "4 5 + -1 -2"; + + v2 = Vector2(0, 0); + v = v1 + v2; + EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 + 0 0"; + + if (std::numeric_limits::is_iec559) { + v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); + v = v1 + v2; + EXPECT_TRUE(v == Vector2(FLOAT_INFINITY, FLOAT_INFINITY)) << "4 5 + INFINITY INFINITY"; + + v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); + v = v1 + v2; + EXPECT_TRUE(v == Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY)) << "4 5 + -INFINITY -INFINITY"; + } + +} + +TEST(Vector2, Scale) { + bool r = false; + + Vector2 v1 = Vector2(4, 5); + Vector2 v2 = Vector2(1, 2); + Vector2 v = Vector2::zero; + + v = Vector2::Scale(v1, v2); + EXPECT_TRUE(v == Vector2(4, 10)) << "Scale 4 5 , 1 2"; + + v2 = Vector2(-1, -2); + v = Vector2::Scale(v1, v2); + EXPECT_TRUE(v == Vector2(-4, -10)) << "Scale 4 5 , -1 -2"; + + v2 = Vector2(0, 0); + v = Vector2::Scale(v1, v2); + EXPECT_TRUE(v == Vector2(0, 0)) << "Scale 4 5 , 0 0"; + + if (std::numeric_limits::is_iec559) { + v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); + v = Vector2::Scale(v1, v2); + EXPECT_TRUE(v == Vector2(FLOAT_INFINITY, FLOAT_INFINITY)) << "4 5 + INFINITY INFINITY"; + + v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); + v = Vector2::Scale(v1, v2); + EXPECT_TRUE(v == Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY)) << "4 5 + -INFINITY -INFINITY"; + } +} + +TEST(Vector2, Multiply) { + bool r = false; + + Vector2 v1 = Vector2(4, 5); + float f = 3; + Vector2 v = Vector2::zero; + + v = v1 * f; + EXPECT_TRUE(v == Vector2(12, 15)) << "4 5 * 3"; + + f = -3; + v = v1 * f; + EXPECT_TRUE(v == Vector2(-12, -15)) << "4 5 * -3"; + + f = 0; + v = v1 * f; + EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 * 0"; + + if (std::numeric_limits::is_iec559) { + f = FLOAT_INFINITY; + v = v1 * f; + EXPECT_TRUE(v == Vector2(FLOAT_INFINITY, FLOAT_INFINITY)) << "4 5 * INFINITY"; + + f = -FLOAT_INFINITY; + v = v1 * f; + EXPECT_TRUE(v == Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY)) << "4 5 * -INFINITY"; + } +} + +TEST(Vector2, Divide) { + bool r = false; + + Vector2 v1 = Vector2(4, 5); + float f = 2; + Vector2 v = Vector2::zero; + + v = v1 / f; + EXPECT_TRUE(v == Vector2(2, 2.5F)) << "4 5 / 3"; + + f = -2; + v = v1 / f; + EXPECT_TRUE(v == Vector2(-2, -2.5F)) << "4 5 / -3"; + + if (std::numeric_limits::is_iec559) { + f = 0; + v = v1 / f; + EXPECT_TRUE(v == Vector2(FLOAT_INFINITY, FLOAT_INFINITY)) << "4 5 / 0"; + + f = FLOAT_INFINITY; + v = v1 / f; + EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 / INFINITY"; + + f = -FLOAT_INFINITY; + v = v1 / f; + EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 / -INFINITY"; + } +} + +TEST(Vector2, Dot) { + Vector2 v1 = Vector2(4, 5); + Vector2 v2 = Vector2(1, 2); + float f = 0; + + f = Vector2::Dot(v1, v2); + EXPECT_FLOAT_EQ(f, 14) << "Dot(4 5, 1 2)"; + + v2 = Vector2(-1, -2); + f = Vector2::Dot(v1, v2); + EXPECT_FLOAT_EQ(f, -14) << "Dot(4 5, -1 -2)"; + + v2 = Vector2(0, 0); + f = Vector2::Dot(v1, v2); + EXPECT_FLOAT_EQ(f, 0) << "Dot(4 5, 0 0)"; + + if (std::numeric_limits::is_iec559) { + v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); + f = Vector2::Dot(v1, v2); + EXPECT_FLOAT_EQ(f, FLOAT_INFINITY) << "Dot(4 5, INFINITY INFINITY)"; + + v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); + f = Vector2::Dot(v1, v2); + EXPECT_FLOAT_EQ(f, -FLOAT_INFINITY) << "Dot(4 5, -INFINITY -INFINITY)"; + } +} + +TEST(Vector2, Equality) { + Vector2 v1 = Vector2(4, 5); + Vector2 v2 = Vector2(1, 2); + bool r = false; + + r = v1 == v2; + EXPECT_FALSE(r) << "4 5 == 1 2"; + + v2 = Vector2(4, 5); + r = v1 == v2; + EXPECT_TRUE(r) << "4 5 == 1 2"; + + if (std::numeric_limits::is_iec559) { + v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); + r = v1 == v2; + EXPECT_FALSE(r) << "4 5 == INFINITY INFINITY"; + + v1 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); + r = v1 == v2; + EXPECT_FALSE(r) << "-INFINITY -INFINITY == INFINITY INFINITY"; + } +} + +TEST(Vector2, Distance) { + Vector2 v1 = Vector2(4, 5); + Vector2 v2 = Vector2(1, 2); + float f = 0; + + f = Vector2::Distance(v1, v2); + EXPECT_FLOAT_EQ(f, 4.24264F) << "Distance(4 5, 1 2)"; + + v2 = Vector2(-1, -2); + f = Vector2::Distance(v1, v2); + EXPECT_FLOAT_EQ(f, 8.602325F) << "Distance(4 5, -1 -2)"; + + v2 = Vector2(0, 0); + f = Vector2::Distance(v1, v2); + EXPECT_FLOAT_EQ(f, 6.403124F) << "Distance(4 5, 0 0)"; + + if (std::numeric_limits::is_iec559) { + v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); + f = Vector2::Distance(v1, v2); + EXPECT_FLOAT_EQ(f, FLOAT_INFINITY) << "Distance(4 5, INFINITY INFINITY)"; + + v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); + f = Vector2::Distance(v1, v2); + EXPECT_FLOAT_EQ(f, FLOAT_INFINITY) << "Distance(4 5, -INFINITY -INFINITY)"; + } +} + +TEST(Vector2, Angle) { + Vector2 v1 = Vector2(4, 5); + Vector2 v2 = Vector2(1, 2); + float f = 0; + bool r = false; + + f = Vector2::Angle(v1, v2); + EXPECT_FLOAT_EQ(f, 12.09476F) << "Angle(4 5, 1 2)"; + + v2 = Vector2(-1, -2); + f = Vector2::Angle(v1, v2); + EXPECT_FLOAT_EQ(f, 167.9052F) << "Angle(4 5, -1 -2)"; + + v2 = Vector2(0, 0); + f = Vector2::Angle(v1, v2); + EXPECT_FLOAT_EQ(f, 0) << "Angle(4 5, 0 0)"; + + if (std::numeric_limits::is_iec559) { + v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); + f = Vector2::Angle(v1, v2); + r = isnan(f); + EXPECT_TRUE(r) << "Angle(4 5, INFINITY INFINITY)"; + + v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); + f = Vector2::Angle(v1, v2); + r = isnan(f); + EXPECT_TRUE(r) << "Angle(4 5, -INFINITY -INFINITY)"; + + } +} + +TEST(Vector2, SignedAngle) { + Vector2 v1 = Vector2(4, 5); + Vector2 v2 = Vector2(1, 2); + float f = 0; + bool r = false; + + f = Vector2::SignedAngle(v1, v2); + EXPECT_FLOAT_EQ(f, 12.09476F) << "SignedAngle(4 5, 1 2)"; + + v2 = Vector2(-1, -2); + f = Vector2::SignedAngle(v1, v2); + EXPECT_FLOAT_EQ(f, -167.9052F) << "SignedAngle(4 5, -1 -2)"; + + v2 = Vector2(0, 0); + f = Vector2::SignedAngle(v1, v2); + EXPECT_FLOAT_EQ(f, 0) << "SignedAngle(4 5, 0 0)"; + + if (std::numeric_limits::is_iec559) { + v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); + f = Vector2::SignedAngle(v1, v2); + r = isnan(f); + EXPECT_TRUE(r) << "SignedAngle(4 5, INFINITY INFINITY)"; + + v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); + f = Vector2::SignedAngle(v1, v2); + r = isnan(f); + EXPECT_TRUE(r) << "SignedAngle(4 5, -INFINITY -INFINITY)"; + + } +} + +//TEST(Vector2, DISABLED_Lerp) { +// +//} + +#endif \ No newline at end of file