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
19template <typename Geometry, typename GetRing>
20void 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
53template <typename Geometry, typename GetRing>
54void 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
82template <typename T, bool Closed>
83void 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
94template <typename T>
95void 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
109void 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
124int 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

source code of boost/libs/geometry/test/algorithms/overlay/copy_segment_point.cpp