#include #include #include using namespace psemek; using namespace psemek::ui::impl; namespace { size_polygon normalize(size_polygon p) { if (p.empty()) return p; auto it = std::min_element(p.begin(), p.end()); std::rotate(p.begin(), it, p.end()); return p; } void check_polygon_cut(size_polygon & polygon, int dimension, geom::interval const & range, size_polygon const & result) { for (int i = 0; i < polygon.size(); ++i) { expect_equal(normalize(cut(polygon, dimension, range)), normalize(result)); std::rotate(polygon.begin(), polygon.end() - 1, polygon.end()); } } void check_polygon_sum(size_polygon & polygon1, size_polygon & polygon2, size_polygon const & result_x, size_polygon const & result_y) { for (int i1 = 0; i1 < polygon1.size(); ++i1) { for (int i2 = 0; i2 < polygon2.size(); ++i2) { expect_equal(normalize(sum_along(polygon1, polygon2, 0)), normalize(result_x)); expect_equal(normalize(sum_along(polygon1, polygon2, 1)), normalize(result_y)); std::rotate(polygon2.begin(), polygon2.end() - 1, polygon2.end()); } std::rotate(polygon1.begin(), polygon1.end() - 1, polygon1.end()); } } } test_case(ui_impl_size__polygon_cut_empty) { expect_equal(cut(size_polygon{}, 0, {0.f, 10.f}), size_polygon{}); } test_case(ui_impl_size__polygon_cut_point__x) { size_polygon polygon{{0.f, 0.f}}; check_polygon_cut(polygon, 0, {-5.f, -5.f}, size_polygon{}); check_polygon_cut(polygon, 0, {-5.f, 0.f}, polygon); check_polygon_cut(polygon, 0, {-5.f, 5.f}, polygon); check_polygon_cut(polygon, 0, {0.f, 0.f}, polygon); check_polygon_cut(polygon, 0, {0.f, 5.f}, polygon); check_polygon_cut(polygon, 0, {5.f, 5.f}, size_polygon{}); } test_case(ui_impl_size__polygon_cut_point__y) { size_polygon polygon{{0.f, 0.f}}; check_polygon_cut(polygon, 1, {-5.f, -5.f}, size_polygon{}); check_polygon_cut(polygon, 1, {-5.f, 0.f}, polygon); check_polygon_cut(polygon, 1, {-5.f, 5.f}, polygon); check_polygon_cut(polygon, 1, {0.f, 0.f}, polygon); check_polygon_cut(polygon, 1, {0.f, 5.f}, polygon); check_polygon_cut(polygon, 1, {5.f, 5.f}, size_polygon{}); } test_case(ui_impl_size__polygon_cut_segmentx__x__simple) { size_polygon polygon{{0.f, 0.f}, {10.f, 0.f}}; check_polygon_cut(polygon, 0, {-5.f, -5.f}, size_polygon{}); check_polygon_cut(polygon, 0, {-5.f, 5.f}, size_polygon{{0.f, 0.f}, {5.f, 0.f}}); check_polygon_cut(polygon, 0, {-5.f, 15.f}, polygon); check_polygon_cut(polygon, 0, {5.f, 15.f}, size_polygon{{5.f, 0.f}, {10.f, 0.f}}); check_polygon_cut(polygon, 0, {15.f, 15.f}, size_polygon{}); } test_case(ui_impl_size__polygon_cut_square__x__simple) { size_polygon polygon{{0.f, 0.f}, {10.f, 0.f}, {10.f, 10.f}, {0.f, 10.f}}; check_polygon_cut(polygon, 0, {-10.f, -2.f}, size_polygon{}); check_polygon_cut(polygon, 0, {-2.f, -2.f}, size_polygon{}); check_polygon_cut(polygon, 0, {-2.f, 2.f}, size_polygon{{0.f, 0.f}, {2.f, 0.f}, {2.f, 10.f}, {0.f, 10.f}}); check_polygon_cut(polygon, 0, {2.f, 8.f}, size_polygon{{2.f, 0.f}, {8.f, 0.f}, {8.f, 10.f}, {2.f, 10.f}}); check_polygon_cut(polygon, 0, {5.f, 5.f}, size_polygon{{5.f, 0.f}, {5.f, 10.f}}); check_polygon_cut(polygon, 0, {8.f, 12.f}, size_polygon{{8.f, 0.f}, {10.f, 0.f}, {10.f, 10.f}, {8.f, 10.f}}); check_polygon_cut(polygon, 0, {12.f, 20.f}, size_polygon{}); check_polygon_cut(polygon, 0, {12.f, 12.f}, size_polygon{}); check_polygon_cut(polygon, 0, {-2.f, 12.f}, polygon); } test_case(ui_impl_size__polygon_cut_square__x__degenerate) { size_polygon polygon{{0.f, 0.f}, {10.f, 0.f}, {10.f, 10.f}, {0.f, 10.f}}; check_polygon_cut(polygon, 0, {-10.f, 0.f}, size_polygon{{0.f, 0.f}, {0.f, 10.f}}); check_polygon_cut(polygon, 0, {0.f, 0.f}, size_polygon{{0.f, 0.f}, {0.f, 10.f}}); check_polygon_cut(polygon, 0, {-2.f, 10.f}, polygon); check_polygon_cut(polygon, 0, {0.f, 10.f}, polygon); check_polygon_cut(polygon, 0, {0.f, 12.f}, polygon); check_polygon_cut(polygon, 0, {10.f, 10.f}, size_polygon{{10.f, 0.f}, {10.f, 10.f}}); check_polygon_cut(polygon, 0, {10.f, 20.f}, size_polygon{{10.f, 0.f}, {10.f, 10.f}}); } test_case(ui_impl_size__polygon_cut_square__y__simple) { size_polygon polygon{{0.f, 0.f}, {10.f, 0.f}, {10.f, 10.f}, {0.f, 10.f}}; check_polygon_cut(polygon, 1, {-10.f, -2.f}, size_polygon{}); check_polygon_cut(polygon, 1, {-2.f, -2.f}, size_polygon{}); check_polygon_cut(polygon, 1, {-2.f, 2.f}, size_polygon{{0.f, 0.f}, {10.f, 0.f}, {10.f, 2.f}, {0.f, 2.f}}); check_polygon_cut(polygon, 1, {2.f, 8.f}, size_polygon{{0.f, 2.f}, {10.f, 2.f}, {10.f, 8.f}, {0.f, 8.f}}); check_polygon_cut(polygon, 1, {5.f, 5.f}, size_polygon{{0.f, 5.f}, {10.f, 5.f}}); check_polygon_cut(polygon, 1, {8.f, 12.f}, size_polygon{{0.f, 8.f}, {10.f, 8.f}, {10.f, 10.f}, {0.f, 10.f}}); check_polygon_cut(polygon, 1, {12.f, 20.f}, size_polygon{}); check_polygon_cut(polygon, 1, {12.f, 12.f}, size_polygon{}); check_polygon_cut(polygon, 1, {-2.f, 12.f}, polygon); } test_case(ui_impl_size__polygon_cut_square__y__degenerate) { size_polygon polygon{{0.f, 0.f}, {10.f, 0.f}, {10.f, 10.f}, {0.f, 10.f}}; check_polygon_cut(polygon, 1, {-10.f, 0.f}, size_polygon{{0.f, 0.f}, {10.f, 0.f}}); check_polygon_cut(polygon, 1, {0.f, 0.f}, size_polygon{{0.f, 0.f}, {10.f, 0.f}}); check_polygon_cut(polygon, 1, {-2.f, 10.f}, polygon); check_polygon_cut(polygon, 1, {0.f, 10.f}, polygon); check_polygon_cut(polygon, 1, {0.f, 12.f}, polygon); check_polygon_cut(polygon, 1, {10.f, 10.f}, size_polygon{{0.f, 10.f}, {10.f, 10.f}}); check_polygon_cut(polygon, 1, {10.f, 20.f}, size_polygon{{0.f, 10.f}, {10.f, 10.f}}); } test_case(ui_impl_size__polygon_cut_diamond__x__simple) { size_polygon polygon{{10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}, {0.f, 10.f}}; check_polygon_cut(polygon, 0, {-10.f, -5.f}, size_polygon{}); check_polygon_cut(polygon, 0, {-10.f, 5.f}, size_polygon{{0.f, 10.f}, {5.f, 5.f}, {5.f, 15.f}}); check_polygon_cut(polygon, 0, {-10.f, 15.f}, size_polygon{{0.f, 10.f}, {10.f, 0.f}, {15.f, 5.f}, {15.f, 15.f}, {10.f, 20.f}}); check_polygon_cut(polygon, 0, {5.f, 5.f}, size_polygon{{5.f, 5.f}, {5.f, 15.f}}); check_polygon_cut(polygon, 0, {5.f, 15.f}, size_polygon{{5.f, 15.f}, {5.f, 5.f}, {10.f, 0.f}, {15.f, 5.f}, {15.f, 15.f}, {10.f, 20.f}}); check_polygon_cut(polygon, 0, {5.f, 25.f}, size_polygon{{5.f, 15.f}, {5.f, 5.f}, {10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}}); check_polygon_cut(polygon, 0, {15.f, 15.f}, size_polygon{{15.f, 5.f}, {15.f, 15.f}}); check_polygon_cut(polygon, 0, {15.f, 25.f}, size_polygon{{15.f, 5.f}, {20.f, 10.f}, {15.f, 15.f}}); check_polygon_cut(polygon, 0, {25.f, 30.f}, size_polygon{}); check_polygon_cut(polygon, 0, {-5.f, 25.f}, polygon); } test_case(ui_impl_size__polygon_cut_diamond__x__degenerate) { size_polygon polygon{{10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}, {0.f, 10.f}}; check_polygon_cut(polygon, 0, {-10.f, 0.f}, size_polygon{{0.f, 10.f}}); check_polygon_cut(polygon, 0, {-10.f, 10.f}, size_polygon{{0.f, 10.f}, {10.f, 0.f}, {10.f, 20.f}}); check_polygon_cut(polygon, 0, {-10.f, 20.f}, polygon); check_polygon_cut(polygon, 0, {0.f, 0.f}, size_polygon{{0.f, 10.f}}); check_polygon_cut(polygon, 0, {0.f, 5.f}, size_polygon{{0.f, 10.f}, {5.f, 5.f}, {5.f, 15.f}}); check_polygon_cut(polygon, 0, {0.f, 10.f}, size_polygon{{0.f, 10.f}, {10.f, 0.f}, {10.f, 20.f}}); check_polygon_cut(polygon, 0, {0.f, 15.f}, size_polygon{{0.f, 10.f}, {10.f, 0.f}, {15.f, 5.f}, {15.f, 15.f}, {10.f, 20.f}}); check_polygon_cut(polygon, 0, {0.f, 20.f}, polygon); check_polygon_cut(polygon, 0, {0.f, 25.f}, polygon); check_polygon_cut(polygon, 0, {5.f, 10.f}, size_polygon{{5.f, 5.f}, {10.f, 0.f}, {10.f, 20.f}, {5.f, 15.f}}); check_polygon_cut(polygon, 0, {5.f, 20.f}, size_polygon{{5.f, 5.f}, {10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}, {5.f, 15.f}}); check_polygon_cut(polygon, 0, {10.f, 10.f}, size_polygon{{10.f, 0.f}, {10.f, 20.f}}); check_polygon_cut(polygon, 0, {10.f, 15.f}, size_polygon{{10.f, 0.f}, {15.f, 5.f}, {15.f, 15.f}, {10.f, 20.f}}); check_polygon_cut(polygon, 0, {10.f, 20.f}, size_polygon{{10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}}); check_polygon_cut(polygon, 0, {10.f, 25.f}, size_polygon{{10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}}); check_polygon_cut(polygon, 0, {15.f, 20.f}, size_polygon{{15.f, 5.f}, {20.f, 10.f}, {15.f, 15.f}}); check_polygon_cut(polygon, 0, {20.f, 20.f}, size_polygon{{20.f, 10.f}}); check_polygon_cut(polygon, 0, {20.f, 25.f}, size_polygon{{20.f, 10.f}}); } test_case(ui_impl_size__polygon_cut_diamond__y__simple) { size_polygon polygon{{10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}, {0.f, 10.f}}; check_polygon_cut(polygon, 1, {-10.f, -5.f}, size_polygon{}); check_polygon_cut(polygon, 1, {-10.f, 5.f}, size_polygon{{15.f, 5.f}, {5.f, 5.f}, {10.f, 0.f}}); check_polygon_cut(polygon, 1, {-10.f, 15.f}, size_polygon{{20.f, 10.f}, {15.f, 15.f}, {5.f, 15.f}, {0.f, 10.f}, {10.f, 0.f}}); check_polygon_cut(polygon, 1, {5.f, 5.f}, size_polygon{{15.f, 5.f}, {5.f, 5.f}}); check_polygon_cut(polygon, 1, {5.f, 15.f}, size_polygon{{20.f, 10.f}, {15.f, 15.f}, {5.f, 15.f}, {0.f, 10.f}, {5.f, 5.f}, {15.f, 5.f}}); check_polygon_cut(polygon, 1, {5.f, 25.f}, size_polygon{{20.f, 10.f}, {10.f, 20.f}, {0.f, 10.f}, {5.f, 5.f}, {15.f, 5.f}}); check_polygon_cut(polygon, 1, {15.f, 15.f}, size_polygon{{15.f, 15.f}, {5.f, 15.f}}); check_polygon_cut(polygon, 1, {15.f, 25.f}, size_polygon{{15.f, 15.f}, {10.f, 20.f}, {5.f, 15.f}}); check_polygon_cut(polygon, 1, {25.f, 30.f}, size_polygon{}); check_polygon_cut(polygon, 1, {-5.f, 25.f}, polygon); } test_case(ui_impl_size__polygon_cut_diamond__y__degenerate) { size_polygon polygon{{10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}, {0.f, 10.f}}; check_polygon_cut(polygon, 1, {-10.f, 0.f}, size_polygon{{10.f, 0.f}}); check_polygon_cut(polygon, 1, {-10.f, 10.f}, size_polygon{{20.f, 10.f}, {0.f, 10.f}, {10.f, 0.f}}); check_polygon_cut(polygon, 1, {-10.f, 20.f}, polygon); check_polygon_cut(polygon, 1, {0.f, 0.f}, size_polygon{{10.f, 0.f}}); check_polygon_cut(polygon, 1, {0.f, 5.f}, size_polygon{{10.f, 0.f}, {15.f, 5.f}, {5.f, 5.f}}); check_polygon_cut(polygon, 1, {0.f, 10.f}, size_polygon{{0.f, 10.f}, {10.f, 0.f}, {20.f, 10.f}}); check_polygon_cut(polygon, 1, {0.f, 15.f}, size_polygon{{0.f, 10.f}, {10.f, 0.f}, {20.f, 10.f}, {15.f, 15.f}, {5.f, 15.f}}); check_polygon_cut(polygon, 1, {0.f, 20.f}, polygon); check_polygon_cut(polygon, 1, {0.f, 25.f}, polygon); check_polygon_cut(polygon, 1, {5.f, 10.f}, size_polygon{{5.f, 5.f}, {15.f, 5.f}, {20.f, 10.f}, {0.f, 10.f}}); check_polygon_cut(polygon, 1, {5.f, 20.f}, size_polygon{{5.f, 5.f}, {15.f, 5.f}, {20.f, 10.f}, {10.f, 20.f}, {0.f, 10.f}}); check_polygon_cut(polygon, 1, {10.f, 10.f}, size_polygon{{0.f, 10.f}, {20.f, 10.f}}); check_polygon_cut(polygon, 1, {10.f, 15.f}, size_polygon{{0.f, 10.f}, {20.f, 10.f}, {15.f, 15.f}, {5.f, 15.f}}); check_polygon_cut(polygon, 1, {10.f, 20.f}, size_polygon{{0.f, 10.f}, {20.f, 10.f}, {10.f, 20.f}}); check_polygon_cut(polygon, 1, {10.f, 25.f}, size_polygon{{0.f, 10.f}, {20.f, 10.f}, {10.f, 20.f}}); check_polygon_cut(polygon, 1, {15.f, 20.f}, size_polygon{{5.f, 15.f}, {15.f, 15.f}, {10.f, 20.f}}); check_polygon_cut(polygon, 1, {20.f, 20.f}, size_polygon{{10.f, 20.f}}); check_polygon_cut(polygon, 1, {20.f, 25.f}, size_polygon{{10.f, 20.f}}); } test_case(ui_impl_size__polygon_sum_empty) { size_polygon polygon; expect_equal(sum_along(polygon, polygon, 0), polygon); expect_equal(sum_along(polygon, polygon, 1), polygon); (void)check_polygon_sum; }