diff --git a/include/omath/Vector2.h b/include/omath/Vector2.h new file mode 100644 index 0000000..a19e3b4 --- /dev/null +++ b/include/omath/Vector2.h @@ -0,0 +1,74 @@ +// +// Created by Vlad on 02.09.2024. +// + +#pragma once +#include + + +namespace omath +{ + class Vector2 + { + public: + float x = 0.f; + float y = 0.f; + + // Constructors + Vector2() = default; + Vector2(float x, float y); + + // Equality operators + bool operator==(const Vector2& src) const; + bool operator!=(const Vector2& src) const; + + // Compound assignment operators + Vector2& operator+=(const Vector2& v); + Vector2& operator-=(const Vector2& v); + Vector2& operator*=(const Vector2& v); + Vector2& operator/=(const Vector2& v); + + Vector2& operator*=(float fl); + Vector2& operator/=(float fl); + Vector2& operator+=(float fl); + Vector2& operator-=(float fl); + + // Basic vector operations + [[nodiscard]] float DistTo(const Vector2& vOther) const; + [[nodiscard]] float DistToSqr(const Vector2& vOther) const; + [[nodiscard]] float Dot(const Vector2& vOther) const; + [[nodiscard]] float Length() const; + [[nodiscard]] float LengthSqr() const; + Vector2& Abs(); + + template + const type& As() const + { + return *reinterpret_cast(this); + } + template + type& As() + { + return *reinterpret_cast(this); + } + + // Unary negation operator + Vector2 operator-() const; + + // Binary arithmetic operators + Vector2 operator+(const Vector2& v) const; + Vector2 operator-(const Vector2& v) const; + Vector2 operator*(float fl) const; + Vector2 operator/(float fl) const; + + + // Normalize the vector + [[nodiscard]] Vector2 Normalized() const; + + // Sum of elements + [[nodiscard]] float Sum() const; + + [[nodiscard]] + std::tuple AsTuple() const; + }; +} \ No newline at end of file diff --git a/include/omath/Vector3.h b/include/omath/Vector3.h index 1bb8807..b3cc2bf 100644 --- a/include/omath/Vector3.h +++ b/include/omath/Vector3.h @@ -6,20 +6,16 @@ #include #include +#include "omath/Vector2.h" + namespace omath { - class Vector3 { + class Vector3 : public Vector2 + { public: - float x = 0.f; - float y = 0.f; float z = 0.f; - Vector3(const float x, const float y, const float z) - { - this->x = x; - this->y = y; - this->z = z; - } + Vector3(float x, float y, float z); Vector3() = default; bool operator==(const Vector3& src) const; @@ -50,16 +46,6 @@ namespace omath Vector3 operator/(float fl) const; Vector3 operator/(const Vector3& v) const; - template - const type& As() const - { - return *reinterpret_cast(this); - } - template - type& As() - { - return *reinterpret_cast(this); - } [[nodiscard]] Vector3 Cross(const Vector3 &v) const; [[nodiscard]] static Vector3 CreateVelocity(float pitch, float yaw, float speed); @@ -74,6 +60,8 @@ namespace omath [[nodiscard]] Vector3 Normalized() const; + + [[nodiscard]] std::tuple AsTuple() const; }; } // ReSharper disable once CppRedundantNamespaceDefinition diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index c35e3a5..495eacc 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -2,7 +2,8 @@ target_sources(omath PRIVATE Vector3.cpp matrix.cpp color.cpp - Vector4.cpp) + Vector4.cpp + Vector2.cpp) add_subdirectory(prediction) add_subdirectory(pathfinding) diff --git a/source/Vector2.cpp b/source/Vector2.cpp new file mode 100644 index 0000000..bdba7af --- /dev/null +++ b/source/Vector2.cpp @@ -0,0 +1,163 @@ +// +// Created by Vlad on 02.09.2024. +// +#include "omath/Vector2.h" +#include + + +namespace omath +{ + // Constructors + Vector2::Vector2(const float x, const float y) : x(x), y(y) {} + + // Equality operators + bool Vector2::operator==(const Vector2& src) const + { + return x == src.x && y == src.y; + } + + bool Vector2::operator!=(const Vector2& src) const + { + return !(*this == src); + } + + // Compound assignment operators + Vector2& Vector2::operator+=(const Vector2& v) + { + x += v.x; + y += v.y; + return *this; + } + + Vector2& Vector2::operator-=(const Vector2& v) + { + x -= v.x; + y -= v.y; + return *this; + } + + Vector2& Vector2::operator*=(float fl) + { + x *= fl; + y *= fl; + return *this; + } + + Vector2& Vector2::operator/=(float fl) + { + x /= fl; + y /= fl; + return *this; + } + + Vector2& Vector2::operator+=(float fl) + { + x += fl; + y += fl; + return *this; + } + + Vector2& Vector2::operator-=(float fl) + { + x -= fl; + y -= fl; + return *this; + } + + // Basic vector operations + float Vector2::DistTo(const Vector2& vOther) const + { + return std::sqrt(DistToSqr(vOther)); + } + + float Vector2::DistToSqr(const Vector2& vOther) const + { + return (x - vOther.x) * (x - vOther.x) + (y - vOther.y) * (y - vOther.y); + } + + float Vector2::Dot(const Vector2& vOther) const + { + return x * vOther.x + y * vOther.y; + } + + float Vector2::Length() const + { + return std::sqrt(x * x + y * y); + } + + float Vector2::LengthSqr() const + { + return x * x + y * y; + } + + Vector2& Vector2::Abs() + { + x = std::abs(x); + y = std::abs(y); + return *this; + } + + // Unary negation operator + Vector2 Vector2::operator-() const + { + return {-x, -y}; + } + + // Binary arithmetic operators + Vector2 Vector2::operator+(const Vector2& v) const + { + return {x + v.x, y + v.y}; + } + + Vector2 Vector2::operator-(const Vector2& v) const + { + return {x - v.x, y - v.y}; + } + + Vector2 Vector2::operator*(float fl) const + { + return {x * fl, y * fl}; + } + + Vector2 Vector2::operator/(float fl) const + { + return {x / fl, y / fl}; + } + + // Normalize the vector + Vector2 Vector2::Normalized() const + { + float len = Length(); + if (len > 0.f) { + return {x / len, y / len}; + } + return {0.f, 0.f}; + } + + // Sum of elements + float Vector2::Sum() const + { + return x + y; + } + + Vector2 &Vector2::operator*=(const Vector2 &v) + { + x *= v.x; + y *= v.y; + + return *this; + } + + Vector2 &Vector2::operator/=(const Vector2 &v) + { + x /= v.x; + y /= v.y; + + return *this; + } + + std::tuple Vector2::AsTuple() const + { + return std::make_tuple(x, y); + } +} \ No newline at end of file diff --git a/source/Vector3.cpp b/source/Vector3.cpp index 40664cd..fcbd061 100644 --- a/source/Vector3.cpp +++ b/source/Vector3.cpp @@ -8,20 +8,25 @@ namespace omath { + + Vector3::Vector3(const float x, const float y, const float z) : Vector2(x, y), z(z) + { + + } + bool Vector3::operator==(const Vector3 &src) const { - return (src.x == x) and (src.y == y) and (src.z == z); + return Vector2::operator==(src) && (src.z == z); } bool Vector3::operator!=(const Vector3 &src) const { - return (src.x != x) or (src.y != y) or (src.z != z); + return !(*this == src); } Vector3 &Vector3::operator+=(const Vector3 &v) { - x += v.x; - y += v.y; + Vector2::operator+=(v); z += v.z; return *this; @@ -29,8 +34,7 @@ namespace omath Vector3 &Vector3::operator-=(const Vector3 &v) { - x -= v.x; - y -= v.y; + Vector2::operator-=(v); z -= v.z; return *this; @@ -38,8 +42,7 @@ namespace omath Vector3 &Vector3::operator*=(const float fl) { - x *= fl; - y *= fl; + Vector2::operator*=(fl); z *= fl; return *this; @@ -47,8 +50,7 @@ namespace omath Vector3 &Vector3::operator*=(const Vector3 &v) { - x *= v.x; - y *= v.y; + Vector2::operator*=(v); z *= v.z; return *this; @@ -56,8 +58,7 @@ namespace omath Vector3 &Vector3::operator/=(const Vector3 &v) { - x /= v.x; - y /= v.y; + Vector2::operator/=(v); z /= v.z; return *this; @@ -65,8 +66,7 @@ namespace omath Vector3 &Vector3::operator+=(const float fl) { - x += fl; - y += fl; + Vector2::operator+=(fl); z += fl; return *this; @@ -74,8 +74,7 @@ namespace omath Vector3 &Vector3::operator/=(const float fl) { - x /= fl; - y /= fl; + Vector2::operator/=(fl); z /= fl; return *this; @@ -83,8 +82,7 @@ namespace omath Vector3 &Vector3::operator-=(const float fl) { - x -= fl; - y -= fl; + Vector2::operator-=(fl); z -= fl; return *this; @@ -92,19 +90,12 @@ namespace omath float Vector3::DistTo(const Vector3 &vOther) const { - Vector3 delta; - - delta.x = x - vOther.x; - delta.y = y - vOther.y; - delta.z = z - vOther.z; - - return delta.Length(); + return (*this - vOther).Length(); } Vector3 &Vector3::Abs() { - x = std::abs(x); - y = std::abs(y); + Vector2::Abs(); z = std::abs(z); return *this; @@ -112,34 +103,27 @@ namespace omath float Vector3::DistToSqr(const Vector3 &vOther) const { - Vector3 delta; - - delta.x = x - vOther.x; - delta.y = y - vOther.y; - delta.z = z - vOther.z; - - return delta.LengthSqr(); + return (*this - vOther).LengthSqr(); } float Vector3::Dot(const Vector3 &vOther) const { - return (x * vOther.x + y * vOther.y + z * vOther.z); + return Vector2::Dot(vOther) + z * vOther.z; } float Vector3::Length() const { - return std::sqrt(x * x + y * y + z * z); + return std::sqrt(Vector2::LengthSqr() + z * z); } float Vector3::LengthSqr() const { - return (x * x + y * y + z * z); + return Vector2::LengthSqr() + z * z; } float Vector3::Length2D() const { - return std::sqrt(x * x + y * y); - + return Vector2::Length(); } Vector3 Vector3::operator-() const @@ -189,12 +173,12 @@ namespace omath float Vector3::Sum() const { - return x + y + z; + return Vector3::Sum2D() + z; } float Vector3::Sum2D() const { - return x + y; + return Vector2::Sum(); } Vector3 Vector3::ViewAngleTo(const Vector3 &other) const @@ -265,4 +249,9 @@ namespace omath return length != 0 ? *this / length : *this; } + + std::tuple Vector3::AsTuple() const + { + return std::make_tuple(x, y, z); + } } \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f2f2c9f..65c45d2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,6 +10,7 @@ add_executable(unit-tests UnitTestAstar.cpp UnitTestProjection.cpp UnitTestVector3.cpp + UnitTestVector2.cpp UnitTestColor.cpp) target_link_libraries(unit-tests PRIVATE gtest gtest_main omath) diff --git a/tests/UnitTestPrediction.cpp b/tests/UnitTestPrediction.cpp index d3ce5c2..c57d79b 100644 --- a/tests/UnitTestPrediction.cpp +++ b/tests/UnitTestPrediction.cpp @@ -7,7 +7,7 @@ TEST(UnitTestPrediction, PredictionTest) const omath::prediction::Projectile proj = {.m_origin = {3,2,1}, .m_launchSpeed = 5000, .m_gravityScale= 0.4}; const auto viewPoint = omath::prediction::Engine(400, 1.f / 1000.f, 50, 5.f).MaybeCalculateAimPoint(proj, target); - const auto [pitch, yaw, _] = proj.m_origin.ViewAngleTo(viewPoint.value()); + const auto [pitch, yaw, _] = proj.m_origin.ViewAngleTo(viewPoint.value()).AsTuple(); EXPECT_NEAR(42.547142, pitch, 0.0001f); EXPECT_NEAR(-1.181189, yaw, 0.0001f); diff --git a/tests/UnitTestVector2.cpp b/tests/UnitTestVector2.cpp new file mode 100644 index 0000000..b75cc3d --- /dev/null +++ b/tests/UnitTestVector2.cpp @@ -0,0 +1,170 @@ +// +// Created by Vlad on 02.09.2024. +// +// +// Created by Vlad on 01.09.2024. +// +#include +#include + +using namespace omath; + +class UnitTestVector2 : public ::testing::Test +{ +protected: + Vector2 v1; + Vector2 v2; + + void SetUp() override + { + v1 = Vector2(1.0f, 2.0f); + v2 = Vector2(4.0f, 5.0f); + } +}; + +// Test constructor and default values +TEST_F(UnitTestVector2, Constructor_Default) +{ + Vector2 v; + EXPECT_FLOAT_EQ(v.x, 0.0f); + EXPECT_FLOAT_EQ(v.y, 0.0f); +} + +TEST_F(UnitTestVector2, Constructor_Values) +{ + Vector2 v(1.0f, 2.0f); + EXPECT_FLOAT_EQ(v.x, 1.0f); + EXPECT_FLOAT_EQ(v.y, 2.0f); +} + +// Test equality operators +TEST_F(UnitTestVector2, EqualityOperator) +{ + Vector2 v3(1.0f, 2.0f); + EXPECT_TRUE(v1 == v3); + EXPECT_FALSE(v1 == v2); +} + +TEST_F(UnitTestVector2, InequalityOperator) +{ + Vector2 v3(1.0f, 2.0f); + EXPECT_FALSE(v1 != v3); + EXPECT_TRUE(v1 != v2); +} + +// Test arithmetic operators +TEST_F(UnitTestVector2, AdditionOperator) +{ + Vector2 v3 = v1 + v2; + EXPECT_FLOAT_EQ(v3.x, 5.0f); + EXPECT_FLOAT_EQ(v3.y, 7.0f); +} + +TEST_F(UnitTestVector2, SubtractionOperator) +{ + Vector2 v3 = v2 - v1; + EXPECT_FLOAT_EQ(v3.x, 3.0f); + EXPECT_FLOAT_EQ(v3.y, 3.0f); +} + +TEST_F(UnitTestVector2, MultiplicationOperator) +{ + Vector2 v3 = v1 * 2.0f; + EXPECT_FLOAT_EQ(v3.x, 2.0f); + EXPECT_FLOAT_EQ(v3.y, 4.0f); +} + +TEST_F(UnitTestVector2, DivisionOperator) +{ + Vector2 v3 = v2 / 2.0f; + EXPECT_FLOAT_EQ(v3.x, 2.0f); + EXPECT_FLOAT_EQ(v3.y, 2.5f); +} + +// Test compound assignment operators +TEST_F(UnitTestVector2, AdditionAssignmentOperator) +{ + v1 += v2; + EXPECT_FLOAT_EQ(v1.x, 5.0f); + EXPECT_FLOAT_EQ(v1.y, 7.0f); +} + +TEST_F(UnitTestVector2, SubtractionAssignmentOperator) +{ + v1 -= v2; + EXPECT_FLOAT_EQ(v1.x, -3.0f); + EXPECT_FLOAT_EQ(v1.y, -3.0f); +} + +TEST_F(UnitTestVector2, MultiplicationAssignmentOperator) +{ + v1 *= 2.0f; + EXPECT_FLOAT_EQ(v1.x, 2.0f); + EXPECT_FLOAT_EQ(v1.y, 4.0f); +} + +TEST_F(UnitTestVector2, DivisionAssignmentOperator) +{ + v1 /= 2.0f; + EXPECT_FLOAT_EQ(v1.x, 0.5f); + EXPECT_FLOAT_EQ(v1.y, 1.0f); +} + +TEST_F(UnitTestVector2, NegationOperator) +{ + Vector2 v3 = -v1; + EXPECT_FLOAT_EQ(v3.x, -1.0f); + EXPECT_FLOAT_EQ(v3.y, -2.0f); +} + +// Test other member functions +TEST_F(UnitTestVector2, DistTo) +{ + float dist = v1.DistTo(v2); + EXPECT_FLOAT_EQ(dist, sqrt(18.0f)); +} + +TEST_F(UnitTestVector2, DistToSqr) +{ + float distSqr = v1.DistToSqr(v2); + EXPECT_FLOAT_EQ(distSqr, 18.0f); +} + +TEST_F(UnitTestVector2, DotProduct) +{ + float dot = v1.Dot(v2); + EXPECT_FLOAT_EQ(dot, 14.0f); +} + +TEST_F(UnitTestVector2, Length) +{ + float length = v1.Length(); + EXPECT_FLOAT_EQ(length, sqrt(5.0f)); +} + +TEST_F(UnitTestVector2, LengthSqr) +{ + float lengthSqr = v1.LengthSqr(); + EXPECT_FLOAT_EQ(lengthSqr, 5.0f); +} + +TEST_F(UnitTestVector2, Abs) +{ + Vector2 v3(-1.0f, -2.0f); + v3.Abs(); + EXPECT_FLOAT_EQ(v3.x, 1.0f); + EXPECT_FLOAT_EQ(v3.y, 2.0f); +} + +TEST_F(UnitTestVector2, Sum) +{ + float sum = v1.Sum(); + EXPECT_FLOAT_EQ(sum, 3.0f); +} + +TEST_F(UnitTestVector2, Normalized) +{ + Vector2 v3 = v1.Normalized(); + EXPECT_NEAR(v3.x, 0.44721f, 0.0001f); + EXPECT_NEAR(v3.y, 0.89443f, 0.0001f); +}