diff --git a/libs/geom/CMakeLists.txt b/libs/geom/CMakeLists.txt index eb1c67b7..eb6413d8 100644 --- a/libs/geom/CMakeLists.txt +++ b/libs/geom/CMakeLists.txt @@ -15,3 +15,5 @@ if(PSEMEK_GEOM_ROBUST_PREDICATES) target_link_libraries(psemek-geom PUBLIC Boost::boost GMP) target_compile_definitions(psemek-geom PUBLIC -DPSEMEK_GEOM_ROBUST_PREDICATES=1) endif() + +psemek_glob_tests(psemek-geom tests) diff --git a/libs/geom/tests/point.cpp b/libs/geom/tests/point.cpp new file mode 100644 index 00000000..48fb3770 --- /dev/null +++ b/libs/geom/tests/point.cpp @@ -0,0 +1,107 @@ +#include + +#include + +using namespace psemek::geom; + +test_case(geom_point_empty) +{ + point pi; + point pf; + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + expect_equal(pi.dimension, 0); + expect_equal(pf.dimension, 0); + expect_throw(pi[0], detail::empty_array_exception); + expect_throw(pf[0], detail::empty_array_exception); +} + +test_case(geom_point_init) +{ + point pi{1, 2}; + point pf{3.f, 4.f, 5.f}; + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + expect_equal(pi[0], 1); + expect_equal(pi[1], 2); + expect_equal(pf[0], 3.f); + expect_equal(pf[1], 4.f); + expect_equal(pf[2], 5.f); +} + +test_case(geom_point_deduce) +{ + point pi{1, 2}; + point pf{3.f, 4.f, 5.f}; + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + expect_equal(pi[0], 1); + expect_equal(pi[1], 2); + expect_equal(pf[0], 3.f); + expect_equal(pf[1], 4.f); + expect_equal(pf[2], 5.f); +} + +test_case(geom_point_arithmetic) +{ + point pi1{1, 2}; + point pi2{3, 4}; + vector vi{5, 6}; + + expect_equal(pi1 + vi, (point{6, 8})); + expect_equal(pi2 + vi, (point{8, 10})); + expect_equal(pi1 - vi, (point{-4, -4})); + expect_equal(pi2 - vi, (point{-2, -2})); + expect_equal(pi2 - pi1, (vector{2, 2})); + expect_equal(pi1 - pi2, (vector{-2, -2})); + + point pf1{1.f, 2.f, 3.f}; + point pf2{4.f, 5.f, 6.f}; + vector vf{7.f, 8.f, 9.f}; + + expect_equal(pf1 + vf, (point{8.f, 10.f, 12.f})); + expect_equal(pf2 + vf, (point{11.f, 13.f, 15.f})); + expect_equal(pf1 - vf, (point{-6.f, -6.f, -6.f})); + expect_equal(pf2 - vf, (point{-3.f, -3.f, -3.f})); + expect_equal(pf2 - pf1, (vector{3.f, 3.f, 3.f})); + expect_equal(pf1 - pf2, (vector{-3.f, -3.f, -3.f})); +} + +test_case(geom_point_compare) +{ + point pi1{1, 2}; + point pi2{3, 4}; + + expect_equal(pi1, pi1); + expect_equal(pi2, pi2); + expect_different(pi1, pi2); + expect_different(pi2, pi1); + expect_less(pi1, pi2); + expect_lequal(pi1, pi2); + expect_greater(pi2, pi1); + expect_gequal(pi2, pi1); +} + +test_case(geom_point_cast) +{ + point pi{1, 2}; + point pf{3.f, 4.f, 5.f}; + + expect_equal(cast(pi), (point{1.f, 2.f})); + expect_equal(cast(pf), (point{3, 4, 5})); +} + +test_case(geom_point_distance) +{ + point p1{2.f, 5.f}; + point p2{7.f, 17.f}; + + expect_equal(distance_sqr(p1, p2), 169.f); + expect_close(distance(p1, p2), 13.f, 1e-6); +} diff --git a/libs/geom/tests/vector.cpp b/libs/geom/tests/vector.cpp new file mode 100644 index 00000000..97340e3d --- /dev/null +++ b/libs/geom/tests/vector.cpp @@ -0,0 +1,149 @@ +#include + +#include + +using namespace psemek::geom; + +test_case(geom_vector_empty) +{ + vector pi; + vector pf; + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + expect_equal(pi.dimension, 0); + expect_equal(pf.dimension, 0); + expect_throw(pi[0], detail::empty_array_exception); + expect_throw(pf[0], detail::empty_array_exception); +} + +test_case(geom_vector_init) +{ + vector pi{1, 2}; + vector pf{3.f, 4.f, 5.f}; + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + expect_equal(pi[0], 1); + expect_equal(pi[1], 2); + expect_equal(pf[0], 3.f); + expect_equal(pf[1], 4.f); + expect_equal(pf[2], 5.f); +} + +test_case(geom_vector_deduce) +{ + vector pi{1, 2}; + vector pf{3.f, 4.f, 5.f}; + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + expect_equal(pi[0], 1); + expect_equal(pi[1], 2); + expect_equal(pf[0], 3.f); + expect_equal(pf[1], 4.f); + expect_equal(pf[2], 5.f); +} + +test_case(geom_vector_arithmetic) +{ + vector vi1{1, 2}; + vector vi2{3, 4}; + + expect_equal(-vi1, (vector{-1, -2})); + expect_equal(5 * vi1, (vector{5, 10})); + expect_equal(vi1 * 5, (vector{5, 10})); + expect_equal(vi1 + vi2, (vector{4, 6})); + expect_equal(vi1 - vi2, (vector{-2, -2})); + expect_equal(2 * vi1 - 3 * vi2, (vector{-7, -8})); + + vector vf1{5.f, 6.f, 7.f}; + vector vf2{8.f, 9.f, 10.f}; + + expect_equal(-vf1, (vector{-5.f, -6.f, -7.f})); + expect_equal(5.f * vf1, (vector{25.f, 30.f, 35.f})); + expect_equal(vf1 * 5.f, (vector{25.f, 30.f, 35.f})); + expect_equal(vf1 + vf2, (vector{13.f, 15.f, 17.f})); + expect_equal(vf1 - vf2, (vector{-3.f, -3.f, -3.f})); + expect_equal(2.f * vf1 - 3.f * vf2, (vector{-14.f, -15.f, -16.f})); +} + +test_case(geom_vector_dot) +{ + vector vi1{1, 2}; + vector vi2{3, 4}; + + expect_equal((dot(vi1, vi2)), 11); + + vector vf1{5.f, 6.f, 7.f}; + vector vf2{8.f, 9.f, 10.f}; + + expect_equal((dot(vf1, vf2)), 164.f); +} + +test_case(geom_vector_det) +{ + vector vi1{1, 2}; + vector vi2{3, 4}; + + expect_equal((det(vi1, vi2)), -2); + + vector vf1{5.f, 6.f, 7.f}; + vector vf2{8.f, 9.f, 10.f}; + vector vf3{11.f, 12.f, 14.f}; + + expect_equal((det(vf1, vf2, vf3)), -3.f); +} + +test_case(geom_vector_compare) +{ + vector vi1{1, 2}; + vector vi2{3, 4}; + + expect_equal(vi1, vi1); + expect_equal(vi2, vi2); + expect_different(vi1, vi2); + expect_different(vi2, vi1); + expect_less(vi1, vi2); + expect_lequal(vi1, vi2); + expect_greater(vi2, vi1); + expect_gequal(vi2, vi1); +} + +test_case(geom_vector_cast) +{ + vector pi{1, 2}; + vector pf{3.f, 4.f, 5.f}; + + expect_equal(cast(pi), (vector{1.f, 2.f})); + expect_equal(cast(pf), (vector{3, 4, 5})); +} + +test_case(geom_vector_ort) +{ + vector v1{1.f, 2.f}; + vector v2{3.f, 4.f, 5.f}; + + expect_small((dot(v1, ort(v1))), 1e-6); + expect_small((dot(v2, ort(v2))), 1e-6); +} + +test_case(geom_vector_cross) +{ + vector v1{1.f, 2.f, 3.f}; + vector v2{4.f, 5.f, 6.f}; + + expect_small((dot(v1, cross(v1, v2))), 1e-6); + expect_small((dot(v2, cross(v1, v2))), 1e-6); +} + +test_case(geom_vector_length) +{ + vector v{5.f, 12.f}; + + expect_equal(length_sqr(v), 169.f); + expect_close(length(v), 13.f, 1e-6); +} diff --git a/tools/test/include/psemek/test/test.hpp b/tools/test/include/psemek/test/test.hpp index 40da501a..12acc1ee 100644 --- a/tools/test/include/psemek/test/test.hpp +++ b/tools/test/include/psemek/test/test.hpp @@ -88,6 +88,9 @@ void name ## _test_case ([[maybe_unused]] ::psemek::test::context & _ctx) #define expect_greater(expr1, expr2) if ((expr1) <= (expr2)) fail(#expr1, " (", (expr1), ") <= ", #expr2, " (", (expr2), ")") #define expect_gequal(expr1, expr2) if ((expr1) < (expr2)) fail(#expr1, " (", (expr1), ") < ", #expr2, " (", (expr2), ")") +#define expect_small(expr1, expr2) if (std::abs((expr1)) > (expr2)) fail("abs(", #expr1, ") (", std::abs((expr1)), ") >= ", #expr2, " (", (expr2), ")") +#define expect_close(expr1, expr2, expr3) if (std::abs((expr1) - (expr2)) > (expr3)) fail("abs(", #expr1, " - ", #expr2, ") (", std::abs((expr1) - (expr2)), ") >= ", #expr3, " (", (expr3), ")") + #define expect_throw(expr, type) do { bool thrown = false; try { (void)(expr); } catch (type const &) { thrown = true; } if (!thrown) fail(#expr, " didn't throw ", #type); } while (false) #define test_profile(name) \