boat
C++23 geospatial library
Loading...
Searching...
No Matches
algorithm.hpp
Go to the documentation of this file.
1// Andrew Naplavkov
2
3#ifndef BOAT_GEOMETRY_ALGORITHM_HPP
4#define BOAT_GEOMETRY_ALGORITHM_HPP
5
6#include <boat/detail/numbers.hpp>
8#include <boost/geometry.hpp>
9
10namespace boat::geometry {
11
12template <box T>
13auto box_area_interpolate(T const& mbr, size_t num_points)
14{
15 auto a = mbr.min_corner(), b = mbr.max_corner();
16 return std::views::iota(0uz, num_points) |
17 std::views::transform([=](auto n) -> d2_of<T>::point {
18 return {std::lerp(a.x(), b.x(), frac(n * numbers::inv_phi)),
19 std::lerp(a.y(), b.y(), (n + .5) / num_points)};
20 });
21}
22
23template <box T>
24multi_point auto box_border_interpolate(T const& mbr, size_t num_points)
25{
26 auto ret = typename d2_of<T>::multi_point{};
27 auto num_per_edge = num_points >= 4 ? (num_points / 4 - 1) : 0;
28 for (auto tup : boost::geometry::box_view{mbr} | std::views::pairwise) {
29 auto a = std::get<0>(tup), b = std::get<1>(tup);
30 ret.push_back(a);
31 for (auto n : std::views::iota(0uz, num_per_edge)) {
32 auto t = (n + 1.) / (num_per_edge + 1.);
33 ret.emplace_back(std::lerp(a.x(), b.x(), t),
34 std::lerp(a.y(), b.y(), t));
35 }
36 }
37 return ret;
38}
39
40inline auto buffer(double distance, size_t num_points)
41{
42 return [=]<single T>(T const& geom) -> polygon auto {
43 namespace strategy = boost::geometry::strategy::buffer;
44 using strategy_point_circle = std::conditional_t<
45 std::same_as<typename boost::geometry::cs_tag<T>::type,
46 boost::geometry::geographic_tag>,
47 strategy::geographic_point_circle<>,
48 strategy::point_circle>;
49 auto out = typename d2_of<T>::multi_polygon{};
50 boost::geometry::buffer( //
51 geom,
52 out,
53 strategy::distance_symmetric{distance},
54 strategy::side_straight{},
55 strategy::join_round{num_points},
56 strategy::end_round{num_points},
57 strategy_point_circle{num_points});
58 return std::move(out.at(0));
59 };
60}
61
63constexpr auto meter = overloaded{
64 [] { return numbers::radian / numbers::earth::mean_radius; },
65 [](this auto&& self, double lat) {
66 auto den = std::cos(lat * numbers::degree);
67 return den ? self() / den : 0.;
68 },
69};
70
71constexpr auto minmax = []<tagged T>(T const& geom) -> box auto {
72 double xmin = INFINITY;
73 double ymin = INFINITY;
74 double xmax = -INFINITY;
75 double ymax = -INFINITY;
76 overloaded{
77 [&](single auto& g) {
78 boost::geometry::for_each_point(g, [&](point auto& p) {
79 xmin = std::min<>(xmin, p.x());
80 ymin = std::min<>(ymin, p.y());
81 xmax = std::max<>(xmax, p.x());
82 ymax = std::max<>(ymax, p.y());
83 });
84 },
85 [](this auto&& self, multi auto& g) -> void {
86 std::ranges::for_each(g, self);
87 },
88 [](this auto&& self, dynamic auto& var) -> void {
89 std::visit(self, var);
90 },
91 }(geom);
92 return typename d2_of<T>::box{{xmin, ymin}, {xmax, ymax}};
93};
94
95template <box T>
96polygon auto to_polygon(T const& geom)
97{
98 typename d2_of<T>::polygon ret;
99 boost::geometry::convert(geom, ret);
100 return ret;
101}
102
105{
106 auto [y, reflected] = reflect(p.y(), -90., 90.);
107 auto x = boat::wrap(p.x() + 180 * reflected, -180., 180.);
108 return {x, y};
109}
110
112 geographic::point const& p,
113 double eastward,
114 double northward)
115{
116 auto dx = eastward * meter(p.y());
117 auto dy = northward * meter();
118 return wrap(geographic::point{p.x() + dx, p.y() + dy});
119}
120
121} // namespace boat::geometry
122
123#endif // BOAT_GEOMETRY_ALGORITHM_HPP
Definition vocabulary.hpp:29
Definition vocabulary.hpp:32
Definition vocabulary.hpp:41
Definition vocabulary.hpp:38
Definition vocabulary.hpp:44
Definition vocabulary.hpp:47
Definition vocabulary.hpp:53
Definition vocabulary.hpp:26
Definition algorithm.hpp:10
polygon auto to_polygon(T const &geom)
Definition algorithm.hpp:96
geographic::point wrap(geographic::point const &p)
Wraps at the poles and antimeridian.
Definition algorithm.hpp:104
geographic::point add_meters(geographic::point const &p, double eastward, double northward)
Definition algorithm.hpp:111
auto buffer(double distance, size_t num_points)
Definition algorithm.hpp:40
constexpr auto meter
Approximate degrees per meter of latitude, or longitude at a given latitude.
Definition algorithm.hpp:63
multi_point auto box_border_interpolate(T const &mbr, size_t num_points)
Definition algorithm.hpp:24
auto box_area_interpolate(T const &mbr, size_t num_points)
Definition algorithm.hpp:13
constexpr auto minmax
Definition algorithm.hpp:71
model::multi_polygon< polygon > multi_polygon
Definition vocabulary.hpp:65
model::multi_point< point > multi_point
Definition vocabulary.hpp:63
model::d2::point_xy< double, CoordSys > point
Definition vocabulary.hpp:60
model::polygon< point, false, true > polygon
Definition vocabulary.hpp:62
model::box< point > box
Definition vocabulary.hpp:66