Skip to content

Commit 6a7224e

Browse files
committed
[buffer] add spheroid to buffer strategies as an optional constructor parameter
1 parent bc001fb commit 6a7224e

File tree

7 files changed

+132
-5
lines changed

7 files changed

+132
-5
lines changed

include/boost/geometry/strategies/geographic/buffer_end_round.hpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ class geographic_end_round
3737
{
3838
public :
3939

40+
//! \brief Constructs the strategy with a spheroid
41+
//! \param spheroid The spheroid to be used
42+
//! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
43+
explicit inline geographic_end_round(Spheroid const& spheroid,
44+
std::size_t points_per_circle = default_points_per_circle)
45+
: m_spheroid(spheroid)
46+
, m_points_per_circle(get_point_count_for_end(points_per_circle))
47+
{}
48+
4049
//! \brief Constructs the strategy
4150
//! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
4251
explicit inline geographic_end_round(std::size_t points_per_circle = default_points_per_circle)
@@ -133,8 +142,8 @@ public :
133142
#endif // DOXYGEN_SHOULD_SKIP_THIS
134143

135144
private :
136-
std::size_t m_points_per_circle;
137145
Spheroid m_spheroid;
146+
std::size_t m_points_per_circle;
138147
};
139148

140149
}} // namespace strategy::buffer

include/boost/geometry/strategies/geographic/buffer_join_miter.hpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ class geographic_join_miter
3737
{
3838
public :
3939

40+
//! \brief Constructs the strategy with a spheroid
41+
//! \param spheroid The spheroid to be used
42+
//! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
43+
explicit inline geographic_join_miter(Spheroid const& spheroid,
44+
double miter_limit = 5.0)
45+
: m_spheroid(spheroid)
46+
, m_miter_limit(valid_limit(miter_limit))
47+
{}
48+
4049
//! \brief Constructs the strategy
4150
//! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
4251
explicit inline geographic_join_miter(double miter_limit = 5.0)
@@ -112,8 +121,8 @@ private :
112121
return miter_limit;
113122
}
114123

115-
double m_miter_limit;
116124
Spheroid m_spheroid;
125+
double m_miter_limit;
117126
};
118127

119128
}} // namespace strategy::buffer

include/boost/geometry/strategies/geographic/buffer_join_round.hpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ class geographic_join_round
3737
{
3838
public :
3939

40+
//! \brief Constructs the strategy with a spheroid
41+
//! \param spheroid The spheroid to be used
42+
//! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
43+
explicit inline geographic_join_round(Spheroid const& spheroid,
44+
std::size_t points_per_circle = default_points_per_circle)
45+
: m_spheroid(spheroid)
46+
, m_points_per_circle(get_point_count_for_join(points_per_circle))
47+
{}
48+
4049
//! \brief Constructs the strategy
4150
//! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
4251
explicit inline geographic_join_round(std::size_t points_per_circle = default_points_per_circle)
@@ -102,8 +111,8 @@ public :
102111
#endif // DOXYGEN_SHOULD_SKIP_THIS
103112

104113
private :
105-
std::size_t m_points_per_circle;
106114
Spheroid m_spheroid;
115+
std::size_t m_points_per_circle;
107116
};
108117

109118
}} // namespace strategy::buffer

include/boost/geometry/strategies/geographic/buffer_point_circle.hpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,18 @@ class geographic_point_circle
6060
{
6161
public :
6262

63+
//! \brief Constructs the strategy with a spheroid
64+
//! \param spheroid The spheroid to be used
65+
//! \param count Number of points (minimum 3) for the created circle
66+
explicit inline geographic_point_circle(Spheroid const& spheroid,
67+
std::size_t count = default_points_per_circle)
68+
: m_spheroid(spheroid)
69+
, m_count(get_point_count_for_circle(count))
70+
{}
71+
6372
//! \brief Constructs the strategy
6473
//! \param count Number of points (minimum 3) for the created circle
65-
explicit geographic_point_circle(std::size_t count = default_points_per_circle)
74+
explicit inline geographic_point_circle(std::size_t count = default_points_per_circle)
6675
: m_count(get_point_count_for_circle(count))
6776
{}
6877

@@ -115,8 +124,8 @@ public :
115124
#endif // DOXYGEN_SHOULD_SKIP_THIS
116125

117126
private :
118-
std::size_t m_count;
119127
Spheroid m_spheroid;
128+
std::size_t m_count;
120129
};
121130

122131
}} // namespace strategy::buffer

include/boost/geometry/strategies/geographic/buffer_side_straight.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ template
4343
class geographic_side_straight
4444
{
4545
public :
46+
//! \brief Constructs the strategy with a spheroid
47+
//! \param spheroid The spheroid to be used
48+
explicit inline geographic_side_straight(Spheroid const& spheroid)
49+
: m_spheroid(spheroid)
50+
{}
51+
52+
//! \brief Constructs the strategy
53+
inline geographic_side_straight()
54+
{}
55+
4656
#ifndef DOXYGEN_SHOULD_SKIP_THIS
4757
// Returns true if the buffer distance is always the same
4858
static inline bool equidistant()

test/algorithms/buffer/Jamfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ test-suite boost-geometry-algorithms-buffer
3030
[ run buffer_multi_linestring_geo.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_multi_linestring_geo ]
3131
[ run buffer_multi_polygon.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_multi_polygon ]
3232
[ run buffer_multi_polygon_geo.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_multi_polygon_geo ]
33+
[ run buffer_geo_spheroid.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_geo_spheroid ]
3334
[ run buffer_linestring_aimes.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_linestring_aimes ]
3435
[ run buffer_linestring.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_ROBUSTNESS_ALTERNATIVE : algorithms_buffer_linestring_alternative ]
3536
[ run buffer_multi_linestring.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_ROBUSTNESS_ALTERNATIVE : algorithms_buffer_multi_linestring_alternative ]
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Boost.Geometry
2+
// Unit Test
3+
4+
// Copyright (c) 2022 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 "test_buffer_geo.hpp"
11+
12+
namespace
13+
{
14+
int const points_per_circle = 360;
15+
std::string const road = "LINESTRING(10.3966569 63.4276957,10.3998059 63.4279182,10.4000859 63.4283889,10.3982915 63.4284015,10.3980902 63.4288772,10.3987772 63.4288520)";
16+
std::string const torg = "POINT(10.3937759 63.4302323)";
17+
}
18+
19+
template <typename Formula, bool Clockwise, typename Point, typename Spheroid>
20+
void test_linestring(std::string const& label, Spheroid const& spheroid,
21+
double expected_area_round, double expected_area_miter)
22+
{
23+
using linestring = bg::model::linestring<Point>;
24+
using polygon = bg::model::polygon<Point, Clockwise>;
25+
26+
ut_settings settings(0.1);
27+
28+
bg::strategies::buffer::geographic<Formula, Spheroid> strategy(spheroid);
29+
bg::strategy::buffer::geographic_side_straight<Formula, Spheroid> side(spheroid);
30+
bg::strategy::buffer::geographic_join_miter<Formula, Spheroid> join_miter(spheroid);
31+
bg::strategy::buffer::geographic_join_round<Formula, Spheroid> join_round(spheroid, points_per_circle);
32+
bg::strategy::buffer::geographic_end_round<Formula, Spheroid> end_round(spheroid, points_per_circle);
33+
34+
// Ignored for linear or areal features
35+
bg::strategy::buffer::geographic_point_circle<Formula, Spheroid> circle(spheroid, points_per_circle);
36+
37+
test_one_geo<linestring, polygon>(label + "_round", road, strategy, side, circle, join_round, end_round, expected_area_round, 10.0, settings);
38+
test_one_geo<linestring, polygon>(label + "_miter", road, strategy, side, circle, join_miter, end_round, expected_area_miter, 10.0, settings);
39+
}
40+
41+
template <typename Formula, bool Clockwise, typename Point, typename Spheroid>
42+
void test_point(std::string const& label, Spheroid const& spheroid, double expected_area)
43+
{
44+
using polygon = bg::model::polygon<Point, Clockwise>;
45+
46+
ut_settings settings(0.01);
47+
48+
bg::strategies::buffer::geographic<Formula, Spheroid> strategy(spheroid);
49+
bg::strategy::buffer::geographic_point_circle<Formula, Spheroid> circle(spheroid, points_per_circle);
50+
51+
// All are ignored for points
52+
bg::strategy::buffer::geographic_side_straight<Formula, Spheroid> side(spheroid);
53+
bg::strategy::buffer::geographic_join_miter<Formula, Spheroid> join_miter(spheroid);
54+
bg::strategy::buffer::geographic_join_round<Formula, Spheroid> join_round(spheroid);
55+
bg::strategy::buffer::geographic_end_round<Formula, Spheroid> end_round(spheroid);
56+
57+
test_one_geo<Point, polygon>(label, torg, strategy, side, circle, join_round, end_round, expected_area, 100.0, settings);
58+
}
59+
60+
int test_main(int, char* [])
61+
{
62+
BoostGeometryWriteTestConfiguration();
63+
64+
using test_type = default_test_type;
65+
66+
using point_t = bg::model::point<test_type, 2, bg::cs::geographic<bg::degree>>;
67+
68+
// Use the default spheroid
69+
bg::srs::spheroid<test_type> def_spheroid;
70+
test_linestring<bg::strategy::andoyer, true, point_t>("line_def", def_spheroid, 7996.0, 8093.0);
71+
test_point<bg::strategy::andoyer, true, point_t>("point_def", def_spheroid, 31450.0);
72+
73+
// Call it with a quite different spheroid (a near sphere), this changes internal geographic calculations
74+
// and should result in different areas. Using CSV creation, it's visible in QGis.
75+
bg::srs::spheroid<test_type> alt_spheroid(6378000.0, 6375000.0);
76+
test_linestring<bg::strategy::andoyer, true, point_t>("line_alt", alt_spheroid, 8097.0, 8115.3);
77+
test_point<bg::strategy::andoyer, true, point_t>("point_alt", alt_spheroid, 31409.0);
78+
79+
return 0;
80+
}

0 commit comments

Comments
 (0)