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