From 29629a737d287a2700d039f787993b9e89fdb176 Mon Sep 17 00:00:00 2001 From: Orange Date: Mon, 6 Jan 2025 05:08:32 +0300 Subject: [PATCH] added some methods --- include/omath/Triangle.hpp | 24 +++++- tests/general/UnitTestLineTrace.cpp | 6 +- tests/general/UnitTestTriangle.cpp | 129 ++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+), 7 deletions(-) diff --git a/include/omath/Triangle.hpp b/include/omath/Triangle.hpp index 68a8894..77c1532 100644 --- a/include/omath/Triangle.hpp +++ b/include/omath/Triangle.hpp @@ -10,6 +10,7 @@ namespace omath class Triangle final { public: + constexpr Triangle() = default; constexpr Triangle(const Vector& vertex1, const Vector& vertex2, const Vector& vertex3) : m_vertex1(vertex1), m_vertex2(vertex2), m_vertex3(vertex3) { @@ -23,17 +24,19 @@ namespace omath [[nodiscard]] constexpr Vector3 CalculateNormal() const { - return (m_vertex1 - m_vertex2).Cross(m_vertex3 - m_vertex1).Normalized(); + const auto b = SideBVector(); + const auto a = SideAVector(); + return b.Cross(a).Normalized(); } [[nodiscard]] - constexpr float SideALength() const + float SideALength() const { return m_vertex1.DistTo(m_vertex2); } [[nodiscard]] - constexpr float SideBLength() const + float SideBLength() const { return m_vertex3.DistTo(m_vertex2); } @@ -44,12 +47,25 @@ namespace omath return m_vertex1 - m_vertex2; } + [[nodiscard]] + constexpr float Hypot() const + { + return m_vertex1.DistTo(m_vertex3); + } + [[nodiscard]] + constexpr bool IsRectangular() const + { + const auto sideA = SideALength(); + const auto sideB = SideBLength(); + const auto hypot = Hypot(); + + return sideA*sideA + sideB*sideB == hypot*hypot; + } [[nodiscard]] constexpr Vector3 SideBVector() const { return m_vertex3 - m_vertex2; } - [[nodiscard]] constexpr Vector3 MidPoint() const { diff --git a/tests/general/UnitTestLineTrace.cpp b/tests/general/UnitTestLineTrace.cpp index 67884d9..4e37916 100644 --- a/tests/general/UnitTestLineTrace.cpp +++ b/tests/general/UnitTestLineTrace.cpp @@ -1,6 +1,6 @@ #include "gtest/gtest.h" #include "omath/collision/LineTracer.hpp" -#include "omath/Triangle3d.hpp" +#include "omath/Triangle.hpp" #include "omath/Vector3.hpp" using namespace omath; @@ -13,7 +13,7 @@ protected: Vector3 vertex1{0.0f, 0.0f, 0.0f}; Vector3 vertex2{1.0f, 0.0f, 0.0f}; Vector3 vertex3{0.0f, 1.0f, 0.0f}; - Triangle3d triangle{vertex1, vertex2, vertex3}; + Triangle triangle{vertex1, vertex2, vertex3}; }; // Test that a ray intersecting the triangle returns false for CanTraceLine @@ -71,7 +71,7 @@ TEST_F(LineTracerTest, TriangleFarBeyondRayEndPoint) constexpr Ray ray{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}}; // Define a triangle far beyond the ray's endpoint - const Triangle3d distantTriangle{ + constexpr Triangle distantTriangle{ {1000.0f, 1000.0f, 1000.0f}, {1001.0f, 1000.0f, 1000.0f}, {1000.0f, 1001.0f, 1000.0f} }; diff --git a/tests/general/UnitTestTriangle.cpp b/tests/general/UnitTestTriangle.cpp index b7f486f..8fc1aa6 100644 --- a/tests/general/UnitTestTriangle.cpp +++ b/tests/general/UnitTestTriangle.cpp @@ -2,3 +2,132 @@ // Created by Orange on 1/6/2025. // #include "omath/Triangle.hpp" +#include +#include +#include // For std::sqrt, std::isinf, std::isnan + + +using namespace omath; + +class UnitTestTriangle : public ::testing::Test +{ +protected: + // Define some Triangles to use in tests + Triangle t1; + Triangle t2; + Triangle t3; + + constexpr void SetUp() override + { + // Triangle with vertices (0, 0, 0), (1, 0, 0), (0, 1, 0) + t1 = Triangle( + Vector3(0.0f, 0.0f, 0.0f), + Vector3(1.0f, 0.0f, 0.0f), + Vector3(0.0f, 1.0f, 0.0f) + ); + + // Triangle with vertices (1, 2, 3), (4, 5, 6), (7, 8, 9) + t2 = Triangle( + Vector3(1.0f, 2.0f, 3.0f), + Vector3(4.0f, 5.0f, 6.0f), + Vector3(7.0f, 8.0f, 9.0f) + ); + + // An isosceles right triangle + t3 = Triangle( + Vector3(0.0f, 0.0f, 0.0f), + Vector3(2.0f, 0.0f, 0.0f), + Vector3(0.0f, 2.0f, 0.0f) + ); + } +}; + +// Test constructor and vertices +TEST_F(UnitTestTriangle, Constructor) +{ + constexpr Triangle t( + Vector3(1.0f, 2.0f, 3.0f), + Vector3(4.0f, 5.0f, 6.0f), + Vector3(7.0f, 8.0f, 9.0f) + ); + + EXPECT_FLOAT_EQ(t.m_vertex1.x, 1.0f); + EXPECT_FLOAT_EQ(t.m_vertex1.y, 2.0f); + EXPECT_FLOAT_EQ(t.m_vertex1.z, 3.0f); + + EXPECT_FLOAT_EQ(t.m_vertex2.x, 4.0f); + EXPECT_FLOAT_EQ(t.m_vertex2.y, 5.0f); + EXPECT_FLOAT_EQ(t.m_vertex2.z, 6.0f); + + EXPECT_FLOAT_EQ(t.m_vertex3.x, 7.0f); + EXPECT_FLOAT_EQ(t.m_vertex3.y, 8.0f); + EXPECT_FLOAT_EQ(t.m_vertex3.z, 9.0f); +} + +// Test CalculateNormal +TEST_F(UnitTestTriangle, CalculateNormal) +{ + // For t1, the normal should point in the +Z direction (0, 0, 1) or (0, 0, -1) + const Vector3 normal_t1 = t1.CalculateNormal(); + // Check if it's normalized and pointed along Z (sign can differ, so use absolute check) + EXPECT_NEAR(std::fabs(normal_t1.z), 1.0f, 1e-5f); + EXPECT_NEAR(normal_t1.Length(), 1.0f, 1e-5f); + + + // For t3, we expect the normal to be along +Z as well + const Vector3 normal_t3 = t3.CalculateNormal(); + EXPECT_NEAR(std::fabs(normal_t3.z), 1.0f, 1e-5f); +} + +// Test side lengths +TEST_F(UnitTestTriangle, SideLengths) +{ + // For t1 side lengths + EXPECT_FLOAT_EQ(t1.SideALength(), std::sqrt(1.0f)); // distance between (0,0,0) and (1,0,0) + EXPECT_FLOAT_EQ(t1.SideBLength(), std::sqrt(1.0f + 1.0f)); // distance between (4,5,6) & (7,8,9)... but we are testing t1, so let's be accurate: + // Actually, for t1: vertex2=(1,0,0), vertex3=(0,1,0) + // Dist between (0,1,0) and (1,0,0) = sqrt((1-0)^2 + (0-1)^2) = sqrt(1 + 1) = sqrt(2) + EXPECT_FLOAT_EQ(t1.SideBLength(), std::sqrt(2.0f)); + + // For t3, side a = distance between vertex1=(0,0,0) and vertex2=(2,0,0), which is 2 + // side b = distance between vertex3=(0,2,0) and vertex2=(2,0,0), which is sqrt(2^2 + (-2)^2)= sqrt(8)= 2.828... + // We'll just check side a first: + EXPECT_FLOAT_EQ(t3.SideALength(), 2.0f); + // Then side b: + EXPECT_FLOAT_EQ(t3.SideBLength(), std::sqrt(8.0f)); +} + +// Test side vectors +TEST_F(UnitTestTriangle, SideVectors) +{ + const Vector3 sideA_t1 = t1.SideAVector(); // m_vertex1 - m_vertex2 + EXPECT_FLOAT_EQ(sideA_t1.x, 0.0f - 1.0f); + EXPECT_FLOAT_EQ(sideA_t1.y, 0.0f - 0.0f); + EXPECT_FLOAT_EQ(sideA_t1.z, 0.0f - 0.0f); + + const Vector3 sideB_t1 = t1.SideBVector(); // m_vertex3 - m_vertex2 + EXPECT_FLOAT_EQ(sideB_t1.x, 0.0f - 1.0f); + EXPECT_FLOAT_EQ(sideB_t1.y, 1.0f - 0.0f); + EXPECT_FLOAT_EQ(sideB_t1.z, 0.0f - 0.0f); +} + +TEST_F(UnitTestTriangle, IsRectangular) +{ + EXPECT_TRUE(t1.IsRectangular()); + EXPECT_TRUE(t3.IsRectangular()); +} +// Test midpoint +TEST_F(UnitTestTriangle, MidPoint) +{ + // For t1, midpoint of (0,0,0), (1,0,0), (0,1,0) + const Vector3 mid1 = t1.MidPoint(); + EXPECT_FLOAT_EQ(mid1.x, (0.0f + 1.0f + 0.0f) / 3.0f); + EXPECT_FLOAT_EQ(mid1.y, (0.0f + 0.0f + 1.0f) / 3.0f); + EXPECT_FLOAT_EQ(mid1.z, 0.0f); + + // For t2, midpoint of (1,2,3), (4,5,6), (7,8,9) + const Vector3 mid2 = t2.MidPoint(); + EXPECT_FLOAT_EQ(mid2.x, (1.0f + 4.0f + 7.0f) / 3.0f); + EXPECT_FLOAT_EQ(mid2.y, (2.0f + 5.0f + 8.0f) / 3.0f); + EXPECT_FLOAT_EQ(mid2.z, (3.0f + 6.0f + 9.0f) / 3.0f); +}