Skip to content

Commit

Permalink
[buffer] add spheroid to buffer strategies as an optional constructor…
Browse files Browse the repository at this point in the history
… parameter
  • Loading branch information
barendgehrels committed Dec 27, 2022
1 parent bc001fb commit 6a7224e
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ class geographic_end_round
{
public :

//! \brief Constructs the strategy with a spheroid
//! \param spheroid The spheroid to be used
//! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
explicit inline geographic_end_round(Spheroid const& spheroid,
std::size_t points_per_circle = default_points_per_circle)
: m_spheroid(spheroid)
, m_points_per_circle(get_point_count_for_end(points_per_circle))
{}

//! \brief Constructs the strategy
//! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
explicit inline geographic_end_round(std::size_t points_per_circle = default_points_per_circle)
Expand Down Expand Up @@ -133,8 +142,8 @@ public :
#endif // DOXYGEN_SHOULD_SKIP_THIS

private :
std::size_t m_points_per_circle;
Spheroid m_spheroid;
std::size_t m_points_per_circle;
};

}} // namespace strategy::buffer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ class geographic_join_miter
{
public :

//! \brief Constructs the strategy with a spheroid
//! \param spheroid The spheroid to be used
//! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
explicit inline geographic_join_miter(Spheroid const& spheroid,
double miter_limit = 5.0)
: m_spheroid(spheroid)
, m_miter_limit(valid_limit(miter_limit))
{}

//! \brief Constructs the strategy
//! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
explicit inline geographic_join_miter(double miter_limit = 5.0)
Expand Down Expand Up @@ -112,8 +121,8 @@ private :
return miter_limit;
}

double m_miter_limit;
Spheroid m_spheroid;
double m_miter_limit;
};

}} // namespace strategy::buffer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ class geographic_join_round
{
public :

//! \brief Constructs the strategy with a spheroid
//! \param spheroid The spheroid to be used
//! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
explicit inline geographic_join_round(Spheroid const& spheroid,
std::size_t points_per_circle = default_points_per_circle)
: m_spheroid(spheroid)
, m_points_per_circle(get_point_count_for_join(points_per_circle))
{}

//! \brief Constructs the strategy
//! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
explicit inline geographic_join_round(std::size_t points_per_circle = default_points_per_circle)
Expand Down Expand Up @@ -102,8 +111,8 @@ public :
#endif // DOXYGEN_SHOULD_SKIP_THIS

private :
std::size_t m_points_per_circle;
Spheroid m_spheroid;
std::size_t m_points_per_circle;
};

}} // namespace strategy::buffer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,18 @@ class geographic_point_circle
{
public :

//! \brief Constructs the strategy with a spheroid
//! \param spheroid The spheroid to be used
//! \param count Number of points (minimum 3) for the created circle
explicit inline geographic_point_circle(Spheroid const& spheroid,
std::size_t count = default_points_per_circle)
: m_spheroid(spheroid)
, m_count(get_point_count_for_circle(count))
{}

//! \brief Constructs the strategy
//! \param count Number of points (minimum 3) for the created circle
explicit geographic_point_circle(std::size_t count = default_points_per_circle)
explicit inline geographic_point_circle(std::size_t count = default_points_per_circle)
: m_count(get_point_count_for_circle(count))
{}

Expand Down Expand Up @@ -115,8 +124,8 @@ public :
#endif // DOXYGEN_SHOULD_SKIP_THIS

private :
std::size_t m_count;
Spheroid m_spheroid;
std::size_t m_count;
};

}} // namespace strategy::buffer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ template
class geographic_side_straight
{
public :
//! \brief Constructs the strategy with a spheroid
//! \param spheroid The spheroid to be used
explicit inline geographic_side_straight(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}

//! \brief Constructs the strategy
inline geographic_side_straight()
{}

#ifndef DOXYGEN_SHOULD_SKIP_THIS
// Returns true if the buffer distance is always the same
static inline bool equidistant()
Expand Down
1 change: 1 addition & 0 deletions test/algorithms/buffer/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ test-suite boost-geometry-algorithms-buffer
[ run buffer_multi_linestring_geo.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_multi_linestring_geo ]
[ run buffer_multi_polygon.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_multi_polygon ]
[ run buffer_multi_polygon_geo.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_multi_polygon_geo ]
[ run buffer_geo_spheroid.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_geo_spheroid ]
[ run buffer_linestring_aimes.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_linestring_aimes ]
[ run buffer_linestring.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_ROBUSTNESS_ALTERNATIVE : algorithms_buffer_linestring_alternative ]
[ run buffer_multi_linestring.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_ROBUSTNESS_ALTERNATIVE : algorithms_buffer_multi_linestring_alternative ]
Expand Down
80 changes: 80 additions & 0 deletions test/algorithms/buffer/buffer_geo_spheroid.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Boost.Geometry
// Unit Test

// Copyright (c) 2022 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 "test_buffer_geo.hpp"

namespace
{
int const points_per_circle = 360;
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)";
std::string const torg = "POINT(10.3937759 63.4302323)";
}

template <typename Formula, bool Clockwise, typename Point, typename Spheroid>
void test_linestring(std::string const& label, Spheroid const& spheroid,
double expected_area_round, double expected_area_miter)
{
using linestring = bg::model::linestring<Point>;
using polygon = bg::model::polygon<Point, Clockwise>;

ut_settings settings(0.1);

bg::strategies::buffer::geographic<Formula, Spheroid> strategy(spheroid);
bg::strategy::buffer::geographic_side_straight<Formula, Spheroid> side(spheroid);
bg::strategy::buffer::geographic_join_miter<Formula, Spheroid> join_miter(spheroid);
bg::strategy::buffer::geographic_join_round<Formula, Spheroid> join_round(spheroid, points_per_circle);
bg::strategy::buffer::geographic_end_round<Formula, Spheroid> end_round(spheroid, points_per_circle);

// Ignored for linear or areal features
bg::strategy::buffer::geographic_point_circle<Formula, Spheroid> circle(spheroid, points_per_circle);

test_one_geo<linestring, polygon>(label + "_round", road, strategy, side, circle, join_round, end_round, expected_area_round, 10.0, settings);
test_one_geo<linestring, polygon>(label + "_miter", road, strategy, side, circle, join_miter, end_round, expected_area_miter, 10.0, settings);
}

template <typename Formula, bool Clockwise, typename Point, typename Spheroid>
void test_point(std::string const& label, Spheroid const& spheroid, double expected_area)
{
using polygon = bg::model::polygon<Point, Clockwise>;

ut_settings settings(0.01);

bg::strategies::buffer::geographic<Formula, Spheroid> strategy(spheroid);
bg::strategy::buffer::geographic_point_circle<Formula, Spheroid> circle(spheroid, points_per_circle);

// All are ignored for points
bg::strategy::buffer::geographic_side_straight<Formula, Spheroid> side(spheroid);
bg::strategy::buffer::geographic_join_miter<Formula, Spheroid> join_miter(spheroid);
bg::strategy::buffer::geographic_join_round<Formula, Spheroid> join_round(spheroid);
bg::strategy::buffer::geographic_end_round<Formula, Spheroid> end_round(spheroid);

test_one_geo<Point, polygon>(label, torg, strategy, side, circle, join_round, end_round, expected_area, 100.0, settings);
}

int test_main(int, char* [])
{
BoostGeometryWriteTestConfiguration();

using test_type = default_test_type;

using point_t = bg::model::point<test_type, 2, bg::cs::geographic<bg::degree>>;

// Use the default spheroid
bg::srs::spheroid<test_type> def_spheroid;
test_linestring<bg::strategy::andoyer, true, point_t>("line_def", def_spheroid, 7996.0, 8093.0);
test_point<bg::strategy::andoyer, true, point_t>("point_def", def_spheroid, 31450.0);

// Call it with a quite different spheroid (a near sphere), this changes internal geographic calculations
// and should result in different areas. Using CSV creation, it's visible in QGis.
bg::srs::spheroid<test_type> alt_spheroid(6378000.0, 6375000.0);
test_linestring<bg::strategy::andoyer, true, point_t>("line_alt", alt_spheroid, 8097.0, 8115.3);
test_point<bg::strategy::andoyer, true, point_t>("point_alt", alt_spheroid, 31409.0);

return 0;
}

0 comments on commit 6a7224e

Please sign in to comment.