mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-09 23:24:02 +00:00
[copy_segment_point] change offset with modulo, add to box, update unit test
This commit is contained in:
parent
abaa211d3a
commit
324249bb2d
@ -42,6 +42,16 @@ namespace boost { namespace geometry
|
|||||||
namespace detail { namespace copy_segments
|
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 <typename Range, bool Reverse, typename SegmentIdentifier, typename PointOut>
|
template <typename Range, bool Reverse, typename SegmentIdentifier, typename PointOut>
|
||||||
struct copy_segment_point_range
|
struct copy_segment_point_range
|
||||||
@ -66,12 +76,11 @@ struct copy_segment_point_range
|
|||||||
rview_type view(cview);
|
rview_type view(cview);
|
||||||
|
|
||||||
std::size_t const segment_count = boost::size(view) - 1;
|
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; }
|
BOOST_GEOMETRY_ASSERT(target >= 0);
|
||||||
|
BOOST_GEOMETRY_ASSERT(target < boost::size(view));
|
||||||
signed_size_type const target = (seg_id.segment_index + offset) % segment_count;
|
geometry::convert(range::at(view, target), point);
|
||||||
|
|
||||||
geometry::convert(*(boost::begin(view) + target), point);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -111,15 +120,14 @@ struct copy_segment_point_box
|
|||||||
SegmentIdentifier const& seg_id, signed_size_type offset,
|
SegmentIdentifier const& seg_id, signed_size_type offset,
|
||||||
PointOut& point)
|
PointOut& point)
|
||||||
{
|
{
|
||||||
signed_size_type index = seg_id.segment_index;
|
|
||||||
for (int i = 0; i < offset; i++)
|
|
||||||
{
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::array<typename point_type<Box>::type, 4> bp;
|
boost::array<typename point_type<Box>::type, 4> bp;
|
||||||
assign_box_corners_oriented<Reverse>(box, bp);
|
assign_box_corners_oriented<Reverse>(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;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -138,7 +146,6 @@ struct copy_segment_point_multi
|
|||||||
SegmentIdentifier const& seg_id, signed_size_type offset,
|
SegmentIdentifier const& seg_id, signed_size_type offset,
|
||||||
PointOut& point)
|
PointOut& point)
|
||||||
{
|
{
|
||||||
|
|
||||||
BOOST_GEOMETRY_ASSERT
|
BOOST_GEOMETRY_ASSERT
|
||||||
(
|
(
|
||||||
seg_id.multi_index >= 0
|
seg_id.multi_index >= 0
|
||||||
@ -276,9 +283,6 @@ struct copy_segment_point
|
|||||||
#endif // DOXYGEN_NO_DISPATCH
|
#endif // DOXYGEN_NO_DISPATCH
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Helper function, copies a point from a segment
|
\brief Helper function, copies a point from a segment
|
||||||
\ingroup overlay
|
\ingroup overlay
|
||||||
|
@ -16,22 +16,21 @@
|
|||||||
#include <boost/geometry/geometries/geometries.hpp>
|
#include <boost/geometry/geometries/geometries.hpp>
|
||||||
#include <boost/geometry/io/wkt/wkt.hpp>
|
#include <boost/geometry/io/wkt/wkt.hpp>
|
||||||
|
|
||||||
template <typename T, bool Closed>
|
template <typename Geometry, typename GetRing>
|
||||||
void test_basic(std::string const& case_id, int line,
|
void test_basic(GetRing get_ring, std::string const& case_id, int line,
|
||||||
std::string const& wkt, bg::segment_identifier const& id,
|
std::string const& wkt, bg::segment_identifier const& id,
|
||||||
int offset, std::size_t expected_index)
|
int offset, std::size_t expected_index)
|
||||||
{
|
{
|
||||||
using point_type = bg::model::point<T, 2, bg::cs::cartesian>;
|
using point_type = typename bg::point_type<Geometry>::type;
|
||||||
using polygon_type = bg::model::polygon<point_type, true, Closed>;
|
|
||||||
|
|
||||||
polygon_type polygon;
|
Geometry geometry;
|
||||||
bg::read_wkt(wkt, polygon);
|
bg::read_wkt(wkt, geometry);
|
||||||
|
|
||||||
// Check the result
|
// Check the result
|
||||||
auto const& ring = bg::exterior_ring(polygon);
|
auto ring = get_ring(geometry);
|
||||||
|
|
||||||
point_type point;
|
point_type point;
|
||||||
bg::copy_segment_point<false>(polygon, id, offset, point);
|
bg::copy_segment_point<false>(geometry, id, offset, point);
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
bool const expectation_in_range = expected_index < ring.size();
|
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));
|
<< bg::wkt(point) << " vs " << bg::wkt(expected_point));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, bool Closed>
|
template <typename Geometry, typename GetRing>
|
||||||
void test_all(std::string const& case_id, std::string const& wkt)
|
void test_geometry(std::string const& case_id, std::string const& wkt, GetRing get_ring)
|
||||||
{
|
{
|
||||||
// Check zero offset, all segment ids
|
// Check zero offset, all segment ids
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, {0, 0, -1, 0}, 0, 0);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 0}, 0, 0);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, {0, 0, -1, 1}, 0, 1);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 1}, 0, 1);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, {0, 0, -1, 2}, 0, 2);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, {0, 0, -1, 2}, 0, 2);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, {0, 0, -1, 3}, 0, 3);
|
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
|
// Check positive offsets, it should endlessly loop around, regardless of direction or closure
|
||||||
bg::segment_identifier const start{0, 0, -1, 0};
|
bg::segment_identifier const start{0, 0, -1, 0};
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, 1, 1);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 1, 1);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, 2, 2);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 2, 2);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, 3, 3);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 3, 3);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, 4, 0);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 4, 0);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, 5, 1);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 5, 1);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, 6, 2);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 6, 2);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, 7, 3);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, 7, 3);
|
||||||
|
|
||||||
// Check negative offsets
|
// Check negative offsets
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, -1, 3);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, -1, 3);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, -2, 2);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, -2, 2);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, -3, 1);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, -3, 1);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, -4, 0);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, -4, 0);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, -5, 3);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, -5, 3);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, -6, 2);
|
test_basic<Geometry>(get_ring, case_id, __LINE__, wkt, start, -6, 2);
|
||||||
test_basic<T, Closed>(case_id, __LINE__, wkt, start, -7, 1);
|
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* [])
|
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, 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_all<double, false>("open", "POLYGON((0 2,1 2,1 1,0 1))");
|
||||||
|
test_box<double>("box", "BOX(0 0,5 5)");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,6 @@ struct count_set
|
|||||||
{
|
{
|
||||||
m_values.insert(static_cast<std::size_t>(value));
|
m_values.insert(static_cast<std::size_t>(value));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "EMPTY" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
count_set(std::size_t value1, std::size_t value2)
|
count_set(std::size_t value1, std::size_t value2)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user