| 1 | // Boost.Geometry |
| 2 | // Unit Test |
| 3 | |
| 4 | // Copyright (c) 2020 Barend Gehrels, Amsterdam, the Netherlands. |
| 5 | |
| 6 | // Use, modification and distribution is subject to the Boost Software License, |
| 7 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| 8 | // http://www.boost.org/LICENSE_1_0.txt) |
| 9 | |
| 10 | #include <geometry_test_common.hpp> |
| 11 | |
| 12 | #include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp> |
| 13 | |
| 14 | #include <boost/geometry/strategies/strategies.hpp> |
| 15 | #include <boost/geometry/algorithms/disjoint.hpp> |
| 16 | #include <boost/geometry/geometries/geometries.hpp> |
| 17 | #include <boost/geometry/io/wkt/wkt.hpp> |
| 18 | |
| 19 | template <typename Geometry, typename GetRing> |
| 20 | void test_basic(GetRing get_ring, std::string const& case_id, int line, |
| 21 | std::string const& wkt, bg::segment_identifier const& id, |
| 22 | int offset, std::size_t expected_index) |
| 23 | { |
| 24 | using point_type = typename bg::point_type<Geometry>::type; |
| 25 | |
| 26 | Geometry geometry; |
| 27 | bg::read_wkt(wkt, geometry); |
| 28 | |
| 29 | // Check the result |
| 30 | auto ring = get_ring(geometry); |
| 31 | |
| 32 | point_type point; |
| 33 | bg::copy_segment_point<false>(geometry, id, offset, point); |
| 34 | |
| 35 | // Sanity check |
| 36 | bool const expectation_in_range = expected_index < ring.size(); |
| 37 | BOOST_CHECK_MESSAGE(expectation_in_range, "Expectation out of range " << expected_index); |
| 38 | if (! expectation_in_range) |
| 39 | { |
| 40 | return; |
| 41 | } |
| 42 | |
| 43 | point_type const expected_point = ring[expected_index]; |
| 44 | |
| 45 | bool const equal = ! bg::disjoint(point, expected_point); |
| 46 | |
| 47 | BOOST_CHECK_MESSAGE(equal, "copy_segment_point: " << case_id |
| 48 | << " line " << line << " at index " << expected_index |
| 49 | << " not as expected: " |
| 50 | << bg::wkt(point) << " vs " << bg::wkt(expected_point)); |
| 51 | } |
| 52 | |
| 53 | template <typename Geometry, typename GetRing> |
| 54 | void test_geometry(std::string const& case_id, std::string const& wkt, GetRing get_ring) |
| 55 | { |
| 56 | // Check zero offset, all segment ids |
| 57 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 0}, 0, 0); |
| 58 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 1}, 0, 1); |
| 59 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 2}, 0, 2); |
| 60 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 3}, 0, 3); |
| 61 | |
| 62 | // Check positive offsets, it should endlessly loop around, regardless of direction or closure |
| 63 | bg::segment_identifier const start{0, 0, -1, 0}; |
| 64 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 1, 1); |
| 65 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 2, 2); |
| 66 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 3, 3); |
| 67 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 4, 0); |
| 68 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 5, 1); |
| 69 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 6, 2); |
| 70 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 7, 3); |
| 71 | |
| 72 | // Check negative offsets |
| 73 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, -1, 3); |
| 74 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, -2, 2); |
| 75 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, -3, 1); |
| 76 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, -4, 0); |
| 77 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, -5, 3); |
| 78 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, -6, 2); |
| 79 | test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, -7, 1); |
| 80 | } |
| 81 | |
| 82 | template <typename T, bool Closed> |
| 83 | void test_all(std::string const& case_id, std::string const& wkt) |
| 84 | { |
| 85 | using point_type = bg::model::point<T, 2, bg::cs::cartesian>; |
| 86 | using polygon_type = bg::model::polygon<point_type, true, Closed>; |
| 87 | |
| 88 | test_geometry<polygon_type>(case_id, wkt, [](polygon_type const& polygon) |
| 89 | { |
| 90 | return bg::exterior_ring(polygon); |
| 91 | }); |
| 92 | } |
| 93 | |
| 94 | template <typename T> |
| 95 | void test_box(std::string const& case_id, std::string const& wkt) |
| 96 | { |
| 97 | using point_type = bg::model::point<T, 2, bg::cs::cartesian>; |
| 98 | using box_type = bg::model::box<point_type>; |
| 99 | |
| 100 | test_geometry<box_type>(case_id, wkt, [](box_type const& box) |
| 101 | { |
| 102 | boost::array<point_type, 4> ring; |
| 103 | bg::detail::assign_box_corners_oriented<false>(box, ring); |
| 104 | return ring; |
| 105 | }); |
| 106 | |
| 107 | } |
| 108 | |
| 109 | void test_circular_offset() |
| 110 | { |
| 111 | BOOST_CHECK_EQUAL(3, bg::detail::copy_segments::circular_offset(4, 0, -1)); |
| 112 | BOOST_CHECK_EQUAL(2, bg::detail::copy_segments::circular_offset(4, 0, -2)); |
| 113 | BOOST_CHECK_EQUAL(1, bg::detail::copy_segments::circular_offset(4, 0, -3)); |
| 114 | |
| 115 | BOOST_CHECK_EQUAL(6, bg::detail::copy_segments::circular_offset(10, 5, 1)); |
| 116 | BOOST_CHECK_EQUAL(6, bg::detail::copy_segments::circular_offset(10, 5, 11)); |
| 117 | BOOST_CHECK_EQUAL(6, bg::detail::copy_segments::circular_offset(10, 5, 21)); |
| 118 | |
| 119 | BOOST_CHECK_EQUAL(4, bg::detail::copy_segments::circular_offset(10, 5, -1)); |
| 120 | BOOST_CHECK_EQUAL(4, bg::detail::copy_segments::circular_offset(10, 5, -11)); |
| 121 | BOOST_CHECK_EQUAL(4, bg::detail::copy_segments::circular_offset(10, 5, -21)); |
| 122 | } |
| 123 | |
| 124 | int test_main(int, char* []) |
| 125 | { |
| 126 | test_circular_offset(); |
| 127 | |
| 128 | test_all<double, true>(case_id: "closed" , wkt: "POLYGON((0 2,1 2,1 1,0 1,0 2))" ); |
| 129 | test_all<double, false>(case_id: "open" , wkt: "POLYGON((0 2,1 2,1 1,0 1))" ); |
| 130 | test_box<double>(case_id: "box" , wkt: "BOX(0 0,5 5)" ); |
| 131 | return 0; |
| 132 | } |
| 133 | |