// // common_test.cxx // math-test // // Created by Sam Jaffe on 5/5/19. // Copyright © 2019 Sam Jaffe. All rights reserved. // #include #include #include "game/math/angle.hpp" #include "game/math/common.hpp" #include "game/math/shape.hpp" #include "test_printers.h" using namespace math::dim2; using namespace testing; template decltype(auto) generate(T min, T max, T step, G && generator) { std::vector out; for (T val = min; val < max; val += step) { out.emplace_back(generator(val)); } return out; } template decltype(auto) generate(T min, T max, T step) { auto identity = [](T const & val) { return val; }; return generate(min, max, step, identity); } struct LineTest : TestWithParam> {}; TEST_P(LineTest, ExistsOnOriginLine) { point const end = std::get<0>(GetParam()); line const ln{{{0, 0}}, end}; point const pt = end * std::get<1>(GetParam()) / 100.f; EXPECT_TRUE(math::contains(ln, pt)); } TEST_P(LineTest, ColinearOutsideDoesNotContain) { point const end = std::get<0>(GetParam()); line const ln{end, end * 2}; point const pt = end * std::get<1>(GetParam()) / 100.f; EXPECT_FALSE(math::contains(ln, pt)); } std::vector const line_ends{{{1, 1}}, {{0, 1}}, {{1, 0}}, {{-1, -1}}, {{0, -1}}, {{-1, 0}}}; INSTANTIATE_TEST_CASE_P(Contains, LineTest, Combine(ValuesIn(line_ends), ValuesIn(generate(0, 100, 10)))); struct UnitCircleTest : TestWithParam {}; TEST_P(UnitCircleTest, ExistsInCircle) { circle unit{{{0, 0}}, 1}; EXPECT_TRUE(math::contains(unit, GetParam())); } TEST_P(UnitCircleTest, OutsideSmallerCircle) { circle subunit{{{0, 0}}, 0.9999}; EXPECT_FALSE(math::contains(subunit, GetParam())); } point unit_circle_angle(math::degree degs) { return point(make_vector(math::sin(degs), math::cos(degs))); } INSTANTIATE_TEST_CASE_P(Contains, UnitCircleTest, ValuesIn(generate(0.0, 360.0, 5.0, unit_circle_angle))); struct UnitSquareTest : TestWithParam> {}; TEST_P(UnitSquareTest, PointInSquare) { square unit{{{0, 0}}, 1}; point pt{{std::get<0>(GetParam()), std::get<1>(GetParam())}}; EXPECT_TRUE(math::contains(unit, pt)); } TEST_F(UnitSquareTest, PointOutsideSquare) { square unit{{{0, 0}}, 1}; EXPECT_FALSE(math::contains(unit, {{0.f, 1.1f}})); EXPECT_FALSE(math::contains(unit, {{0.f, -0.1f}})); EXPECT_FALSE(math::contains(unit, {{-0.1f, 0.0f}})); EXPECT_FALSE(math::contains(unit, {{1.1f, 0.0f}})); } INSTANTIATE_TEST_CASE_P(Contains, UnitSquareTest, Combine(ValuesIn(generate(0.f, 1.f, 0.25f)), ValuesIn(generate(0.f, 1.f, 0.25f)))); struct LineQuadTest : TestWithParam {}; TEST_P(LineQuadTest, OriginLineIntersectsUnitSquare) { square const unit{{{0, 0}}, 1}; line const ln{{{0, 0}}, GetParam()}; EXPECT_TRUE(math::intersects(ln, unit)); EXPECT_TRUE(math::intersects(unit, ln)); } TEST_P(LineQuadTest, CrossingLineIntersectsUnitSquare) { square const unit{{{0, 0}}, 1}; line const ln{{{0.5, 0.5}}, GetParam()}; EXPECT_TRUE(math::intersects(ln, unit)); EXPECT_TRUE(math::intersects(unit, ln)); } TEST_P(LineQuadTest, CrossingLineIntersectsSquare) { square const unit{{{0, 0}}, 0.9}; line const ln{{{0.5, 0.5}}, GetParam()}; EXPECT_TRUE(math::intersects(ln, unit)); EXPECT_TRUE(math::intersects(unit, ln)); } TEST_F(LineQuadTest, JustPointIntersection) { square const unit{{{0, 0}}, 1}; line const ln{{{1, 1}}, {{2, 1}}}; EXPECT_TRUE(math::intersects(ln, unit)); EXPECT_TRUE(math::intersects(unit, ln)); } TEST_F(LineQuadTest, EntirelyEncasedIntersection) { square const unit{{{0, 0}}, 1}; line const ln{{{0.5, 0.5}}, {{0.75, 0.75}}}; EXPECT_TRUE(math::intersects(ln, unit)); EXPECT_TRUE(math::intersects(unit, ln)); } TEST_F(LineQuadTest, OutsideByAnInch) { square const unit{{{0, 0}}, 1}; line const ln{{{1.001, 1}}, {{2, 1}}}; math::intersects(ln, unit); EXPECT_FALSE(math::intersects(ln, unit)); EXPECT_FALSE(math::intersects(unit, ln)); } INSTANTIATE_TEST_CASE_P(Intersects, LineQuadTest, ValuesIn(line_ends)); TEST(CircleTest, IntersectsSelf) { circle const c1{{{0, 0}}, 1}; circle const c2{{{0, 0}}, 1}; EXPECT_TRUE(math::intersects(c1, c2)); } TEST(CircleTest, IntersectsAtOnePoint) { circle const c1{{{0, 0}}, 1}; circle const c2{{{0, 2}}, 1}; EXPECT_TRUE(math::intersects(c1, c2)); } TEST(CircleTest, IntersectsWithChord) { circle const c1{{{0, 0}}, 0.5}; circle const c2{{{0, 1}}, 0.5}; EXPECT_TRUE(math::intersects(c1, c2)); } TEST(CircleTest, ContainedWithin) { circle const c1{{{0, 0}}, 2}; circle const c2{{{0, 1}}, 0.5}; EXPECT_TRUE(math::intersects(c1, c2)); } TEST(CircleTest, Outside) { circle const c1{{{0, 0}}, 1}; circle const c2{{{1.5, 1.5}}, 1}; EXPECT_FALSE(math::intersects(c1, c2)); }