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