Files
FESADev/tests/unit/math/vector3_test.cpp
T

117 lines
3.6 KiB
C++

#include "fesa/math/vector3.h"
#include <gtest/gtest.h>
#include <array>
#include <cmath>
#include <limits>
#include <optional>
namespace fesa {
namespace {
TEST(Vector3, StoresComponentsWithExactArithmetic) {
constexpr Vector3 zero;
static_assert(zero.X() == 0.0);
static_assert(zero.Y() == 0.0);
static_assert(zero.Z() == 0.0);
constexpr Vector3 lhs{1.0, -2.0, 3.0};
constexpr Vector3 rhs{-4.0, 5.0, 6.0};
constexpr Vector3 sum = lhs + rhs;
constexpr Vector3 difference = lhs - rhs;
constexpr Vector3 scaled = lhs * -2.0;
constexpr Vector3 divided = lhs / -2.0;
EXPECT_DOUBLE_EQ(lhs.X(), 1.0);
EXPECT_DOUBLE_EQ(lhs.Y(), -2.0);
EXPECT_DOUBLE_EQ(lhs.Z(), 3.0);
EXPECT_DOUBLE_EQ(lhs[0], 1.0);
EXPECT_DOUBLE_EQ(lhs[1], -2.0);
EXPECT_DOUBLE_EQ(lhs[2], 3.0);
EXPECT_DOUBLE_EQ(sum[0], -3.0);
EXPECT_DOUBLE_EQ(sum[1], 3.0);
EXPECT_DOUBLE_EQ(sum[2], 9.0);
EXPECT_DOUBLE_EQ(difference[0], 5.0);
EXPECT_DOUBLE_EQ(difference[1], -7.0);
EXPECT_DOUBLE_EQ(difference[2], -3.0);
EXPECT_DOUBLE_EQ(scaled[0], -2.0);
EXPECT_DOUBLE_EQ(scaled[1], 4.0);
EXPECT_DOUBLE_EQ(scaled[2], -6.0);
EXPECT_DOUBLE_EQ(divided[0], -0.5);
EXPECT_DOUBLE_EQ(divided[1], 1.0);
EXPECT_DOUBLE_EQ(divided[2], -1.5);
}
TEST(Vector3, ConvertsArrayAndPreservesScalarLeftEvaluationOrder) {
constexpr std::array<double, 3> kComponents{1.25, -2.5, 5.0};
constexpr Vector3 value{kComponents};
constexpr Vector3 scaled = -2.0 * value;
EXPECT_TRUE(value == Vector3(1.25, -2.5, 5.0));
EXPECT_FALSE(value == Vector3(1.25, -2.5, 4.0));
EXPECT_EQ(value.Components(), kComponents);
EXPECT_DOUBLE_EQ(scaled.X(), -2.5);
EXPECT_DOUBLE_EQ(scaled.Y(), 5.0);
EXPECT_DOUBLE_EQ(scaled.Z(), -10.0);
}
TEST(Vector3, ComputesDotProduct) {
const Vector3 lhs{1.0, 2.0, 3.0};
const Vector3 rhs{4.0, -5.0, 6.0};
EXPECT_DOUBLE_EQ(lhs.Dot(rhs), 12.0);
}
TEST(Vector3, UsesRightHandedCrossProductOrientation) {
const Vector3 x_axis{1.0, 0.0, 0.0};
const Vector3 y_axis{0.0, 1.0, 0.0};
const Vector3 positive_z = x_axis.Cross(y_axis);
const Vector3 negative_z = y_axis.Cross(x_axis);
EXPECT_DOUBLE_EQ(positive_z.X(), 0.0);
EXPECT_DOUBLE_EQ(positive_z.Y(), 0.0);
EXPECT_DOUBLE_EQ(positive_z.Z(), 1.0);
EXPECT_DOUBLE_EQ(negative_z.X(), 0.0);
EXPECT_DOUBLE_EQ(negative_z.Y(), 0.0);
EXPECT_DOUBLE_EQ(negative_z.Z(), -1.0);
}
TEST(Vector3, ComputesEuclideanNorm) {
EXPECT_DOUBLE_EQ(Vector3(2.0, -3.0, 6.0).Norm(), 7.0);
const double expected = std::hypot(1.0e308, 1.0e308, 0.0);
EXPECT_DOUBLE_EQ(Vector3(1.0e308, 1.0e308, 0.0).Norm(), expected);
}
TEST(Vector3, NormalizesNonzeroVectors) {
const std::optional<Vector3> normalized = Vector3(3.0, 0.0, 4.0).Normalized();
ASSERT_TRUE(normalized.has_value());
EXPECT_DOUBLE_EQ(normalized->X(), 0.6);
EXPECT_DOUBLE_EQ(normalized->Y(), 0.0);
EXPECT_DOUBLE_EQ(normalized->Z(), 0.8);
}
TEST(Vector3, ReportsFiniteComponents) {
const double infinity = std::numeric_limits<double>::infinity();
const double not_a_number = std::numeric_limits<double>::quiet_NaN();
EXPECT_TRUE(Vector3(1.0, -2.0, 3.0).IsFinite());
EXPECT_FALSE(Vector3(infinity, 0.0, 0.0).IsFinite());
EXPECT_FALSE(Vector3(0.0, not_a_number, 0.0).IsFinite());
}
TEST(Vector3, RejectsZeroAndNonfiniteNormalization) {
const double infinity = std::numeric_limits<double>::infinity();
const double not_a_number = std::numeric_limits<double>::quiet_NaN();
EXPECT_FALSE(Vector3().Normalized().has_value());
EXPECT_FALSE(Vector3(infinity, 0.0, 0.0).Normalized().has_value());
EXPECT_FALSE(Vector3(0.0, not_a_number, 0.0).Normalized().has_value());
}
} // namespace
} // namespace fesa