diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp index 10d12085b..e9b9a2f04 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp @@ -42,6 +42,16 @@ namespace boost { namespace geometry namespace detail { namespace copy_segments { +inline signed_size_type circular_offset(signed_size_type segment_count, signed_size_type index, + signed_size_type offset) +{ + signed_size_type result = (index + offset) % segment_count; + if (result < 0) + { + result += segment_count; + } + return result; +} template struct copy_segment_point_range @@ -66,12 +76,11 @@ struct copy_segment_point_range rview_type view(cview); std::size_t const segment_count = boost::size(view) - 1; + signed_size_type const target = circular_offset(segment_count, seg_id.segment_index, offset); - while (offset < 0) { offset += segment_count; } - - signed_size_type const target = (seg_id.segment_index + offset) % segment_count; - - geometry::convert(*(boost::begin(view) + target), point); + BOOST_GEOMETRY_ASSERT(target >= 0); + BOOST_GEOMETRY_ASSERT(target < boost::size(view)); + geometry::convert(range::at(view, target), point); return true; } @@ -111,15 +120,14 @@ struct copy_segment_point_box SegmentIdentifier const& seg_id, signed_size_type offset, PointOut& point) { - signed_size_type index = seg_id.segment_index; - for (int i = 0; i < offset; i++) - { - index++; - } - boost::array::type, 4> bp; assign_box_corners_oriented(box, bp); - point = bp[index % 4]; + + signed_size_type const target = circular_offset(4, seg_id.segment_index, offset); + BOOST_GEOMETRY_ASSERT(target >= 0); + BOOST_GEOMETRY_ASSERT(target < bp.size()); + + point = bp[target]; return true; } }; @@ -138,7 +146,6 @@ struct copy_segment_point_multi SegmentIdentifier const& seg_id, signed_size_type offset, PointOut& point) { - BOOST_GEOMETRY_ASSERT ( seg_id.multi_index >= 0 @@ -276,9 +283,6 @@ struct copy_segment_point #endif // DOXYGEN_NO_DISPATCH - - - /*! \brief Helper function, copies a point from a segment \ingroup overlay diff --git a/test/algorithms/overlay/copy_segment_point.cpp b/test/algorithms/overlay/copy_segment_point.cpp index 101908906..33c3f9536 100644 --- a/test/algorithms/overlay/copy_segment_point.cpp +++ b/test/algorithms/overlay/copy_segment_point.cpp @@ -16,22 +16,21 @@ #include #include -template -void test_basic(std::string const& case_id, int line, +template +void test_basic(GetRing get_ring, std::string const& case_id, int line, std::string const& wkt, bg::segment_identifier const& id, int offset, std::size_t expected_index) { - using point_type = bg::model::point; - using polygon_type = bg::model::polygon; + using point_type = typename bg::point_type::type; - polygon_type polygon; - bg::read_wkt(wkt, polygon); + Geometry geometry; + bg::read_wkt(wkt, geometry); // Check the result - auto const& ring = bg::exterior_ring(polygon); + auto ring = get_ring(geometry); point_type point; - bg::copy_segment_point(polygon, id, offset, point); + bg::copy_segment_point(geometry, id, offset, point); // Sanity check bool const expectation_in_range = expected_index < ring.size(); @@ -51,38 +50,83 @@ void test_basic(std::string const& case_id, int line, << bg::wkt(point) << " vs " << bg::wkt(expected_point)); } -template -void test_all(std::string const& case_id, std::string const& wkt) +template +void test_geometry(std::string const& case_id, std::string const& wkt, GetRing get_ring) { // Check zero offset, all segment ids - test_basic(case_id, __LINE__, wkt, {0, 0, -1, 0}, 0, 0); - test_basic(case_id, __LINE__, wkt, {0, 0, -1, 1}, 0, 1); - test_basic(case_id, __LINE__, wkt, {0, 0, -1, 2}, 0, 2); - test_basic(case_id, __LINE__, wkt, {0, 0, -1, 3}, 0, 3); + test_basic(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 0}, 0, 0); + test_basic(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 1}, 0, 1); + test_basic(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 2}, 0, 2); + test_basic(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 3}, 0, 3); // Check positive offsets, it should endlessly loop around, regardless of direction or closure bg::segment_identifier const start{0, 0, -1, 0}; - test_basic(case_id, __LINE__, wkt, start, 1, 1); - test_basic(case_id, __LINE__, wkt, start, 2, 2); - test_basic(case_id, __LINE__, wkt, start, 3, 3); - test_basic(case_id, __LINE__, wkt, start, 4, 0); - test_basic(case_id, __LINE__, wkt, start, 5, 1); - test_basic(case_id, __LINE__, wkt, start, 6, 2); - test_basic(case_id, __LINE__, wkt, start, 7, 3); + test_basic(get_ring, case_id, __LINE__, wkt, start, 1, 1); + test_basic(get_ring, case_id, __LINE__, wkt, start, 2, 2); + test_basic(get_ring, case_id, __LINE__, wkt, start, 3, 3); + test_basic(get_ring, case_id, __LINE__, wkt, start, 4, 0); + test_basic(get_ring, case_id, __LINE__, wkt, start, 5, 1); + test_basic(get_ring, case_id, __LINE__, wkt, start, 6, 2); + test_basic(get_ring, case_id, __LINE__, wkt, start, 7, 3); // Check negative offsets - test_basic(case_id, __LINE__, wkt, start, -1, 3); - test_basic(case_id, __LINE__, wkt, start, -2, 2); - test_basic(case_id, __LINE__, wkt, start, -3, 1); - test_basic(case_id, __LINE__, wkt, start, -4, 0); - test_basic(case_id, __LINE__, wkt, start, -5, 3); - test_basic(case_id, __LINE__, wkt, start, -6, 2); - test_basic(case_id, __LINE__, wkt, start, -7, 1); + test_basic(get_ring, case_id, __LINE__, wkt, start, -1, 3); + test_basic(get_ring, case_id, __LINE__, wkt, start, -2, 2); + test_basic(get_ring, case_id, __LINE__, wkt, start, -3, 1); + test_basic(get_ring, case_id, __LINE__, wkt, start, -4, 0); + test_basic(get_ring, case_id, __LINE__, wkt, start, -5, 3); + test_basic(get_ring, case_id, __LINE__, wkt, start, -6, 2); + test_basic(get_ring, case_id, __LINE__, wkt, start, -7, 1); +} + +template +void test_all(std::string const& case_id, std::string const& wkt) +{ + using point_type = bg::model::point; + using polygon_type = bg::model::polygon; + + test_geometry(case_id, wkt, [](polygon_type const& polygon) + { + return bg::exterior_ring(polygon); + }); +} + +template +void test_box(std::string const& case_id, std::string const& wkt) +{ + using point_type = bg::model::point; + using box_type = bg::model::box; + + test_geometry(case_id, wkt, [](box_type const& box) + { + boost::array ring; + bg::detail::assign_box_corners_oriented(box, ring); + return ring; + }); + +} + +void test_circular_offset() +{ + BOOST_CHECK_EQUAL(3, bg::detail::copy_segments::circular_offset(4, 0, -1)); + BOOST_CHECK_EQUAL(2, bg::detail::copy_segments::circular_offset(4, 0, -2)); + BOOST_CHECK_EQUAL(1, bg::detail::copy_segments::circular_offset(4, 0, -3)); + + BOOST_CHECK_EQUAL(6, bg::detail::copy_segments::circular_offset(10, 5, 1)); + BOOST_CHECK_EQUAL(6, bg::detail::copy_segments::circular_offset(10, 5, 11)); + BOOST_CHECK_EQUAL(6, bg::detail::copy_segments::circular_offset(10, 5, 21)); + + BOOST_CHECK_EQUAL(4, bg::detail::copy_segments::circular_offset(10, 5, -1)); + BOOST_CHECK_EQUAL(4, bg::detail::copy_segments::circular_offset(10, 5, -11)); + BOOST_CHECK_EQUAL(4, bg::detail::copy_segments::circular_offset(10, 5, -21)); } int test_main(int, char* []) { + test_circular_offset(); + test_all("closed", "POLYGON((0 2,1 2,1 1,0 1,0 2))"); test_all("open", "POLYGON((0 2,1 2,1 1,0 1))"); + test_box("box", "BOX(0 0,5 5)"); return 0; } diff --git a/test/count_set.hpp b/test/count_set.hpp index 751649171..3d69b5ca4 100644 --- a/test/count_set.hpp +++ b/test/count_set.hpp @@ -29,10 +29,6 @@ struct count_set { m_values.insert(static_cast(value)); } - else - { - std::cout << "EMPTY" << std::endl; - } } count_set(std::size_t value1, std::size_t value2)