summaryrefslogtreecommitdiffstats
path: root/server/src/geo/wgs84.cppm
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/geo/wgs84.cppm')
-rw-r--r--server/src/geo/wgs84.cppm115
1 files changed, 115 insertions, 0 deletions
diff --git a/server/src/geo/wgs84.cppm b/server/src/geo/wgs84.cppm
new file mode 100644
index 0000000..d574d39
--- /dev/null
+++ b/server/src/geo/wgs84.cppm
@@ -0,0 +1,115 @@
1module;
2
3#include <boost/geometry.hpp>
4
5export module routemon:geo.wgs84;
6
7import :geo;
8
9namespace routemon::geo::wgs84 {
10
11using cs = bgeo::cs::geographic<bgeo::degree>;
12using point = bgeo::model::point<double, 2, cs>;
13// TODO: guarantee that linestring provides non-static member
14// auto reserve(std::size_t) -> void
15// Perhaps better yet: guarantee that the backing container is a std::vector.
16using linestring = bgeo::model::linestring<point, std::vector /* the default */>;
17using box = bgeo::model::box<point>;
18using stype = bgeo::srs::spheroid<double>;
19using vincenty_strategy = bgeo::strategy::distance::vincenty<stype>;
20
21auto from_lat_lon(double lat, double lon) -> point
22{
23 return point{lon, lat};
24}
25
26auto lat(point p) -> double
27{
28 return bgeo::get<1>(p);
29}
30
31auto lon(point p) -> double
32{
33 return bgeo::get<0>(p);
34}
35
36// Point p with latitude in [-90, 90] and longitude in [-180, 180)
37auto normalize(point p) -> point
38{
39 // Equivalent degrees in the range [0, 360)
40 auto nonneg_mod360 = [](double t) -> double
41 { return std::remainder(std::remainder(t, 360.0) + 360.0, 360.0); };
42
43 auto p_lon = lon(p);
44 auto p_lat = nonneg_mod360(lat(p)) - 90.0;
45 if (90.0 < p_lat)
46 {
47 assert(p_lat < 270.0); // by nonneg_mod360
48 p_lon += 180.0;
49 p_lat -= 180.0;
50 }
51 p_lon = nonneg_mod360(p_lon + 180.0) - 180.0;
52
53 return from_lat_lon(p_lat, p_lon);
54}
55
56auto is_normalized(point p) -> bool
57{
58 return -90 <= lat(p) && lat(p) <= 90 && -180 <= lon(p) && lon(p) < 180;
59}
60
61class normalized_point
62{
63 point p_;
64
65public:
66 normalized_point(point p)
67 : p_{is_normalized(p) ? p : normalize(p)}
68 {}
69
70 normalized_point()
71 : p_{}
72 {}
73
74 auto lat() const -> double
75 {
76 return bgeo::get<1>(p_);
77 }
78
79 auto lon() const -> double
80 {
81 return bgeo::get<0>(p_);
82 }
83
84 auto lat(double lat) -> void
85 {
86 if (lat < -90 || lat > 90)
87 throw std::range_error{"latitude out of range"};
88 bgeo::set<1>(p_, lat);
89 }
90
91 auto lon(double lon) -> void
92 {
93 if (lon < -180 || lon > 180)
94 throw std::range_error{"longitude out of range"};
95 bgeo::set<0>(p_, lon);
96 }
97};
98
99class normalized_linestring
100{
101 std::vector<normalized_point> ls_;
102
103public:
104 auto empty() const -> bool
105 {
106 return ls_.empty();
107 }
108
109 auto push_back(normalized_point p) -> void
110 {
111 ls_.push_back(p);
112 }
113};
114
115} // namespace routemon::geo::wgs84