summaryrefslogtreecommitdiffstats
path: root/server/src/geo/utm.cppm
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/geo/utm.cppm')
-rw-r--r--server/src/geo/utm.cppm140
1 files changed, 72 insertions, 68 deletions
diff --git a/server/src/geo/utm.cppm b/server/src/geo/utm.cppm
index 83da222..c58ffb4 100644
--- a/server/src/geo/utm.cppm
+++ b/server/src/geo/utm.cppm
@@ -1,7 +1,7 @@
1module; 1module;
2 2
3#include <cassert>
4#include <boost/geometry/geometries/geometries.hpp> 3#include <boost/geometry/geometries/geometries.hpp>
4#include <cassert>
5 5
6export module routemon:geo.utm; 6export module routemon:geo.utm;
7 7
@@ -9,46 +9,32 @@ import std;
9import :geo; 9import :geo;
10import :geo.wgs84; 10import :geo.wgs84;
11 11
12namespace routemon::geo::utm 12namespace routemon::geo::utm {
13{
14 13
15class zonable_wgs84_point 14class zonable_wgs84_point
16{ 15{
17 wgs84::normalized_point p_; 16 wgs84::normalized_point p_;
18 17
19 explicit zonable_wgs84_point(wgs84::normalized_point p) 18 explicit inline zonable_wgs84_point(wgs84::normalized_point p) : p_{p} {}
20 : p_{p}
21 {}
22 19
23public: 20public:
24 zonable_wgs84_point() 21 inline zonable_wgs84_point() : p_{} {}
25 : p_{}
26 {
27 }
28 22
29 static auto from(wgs84::normalized_point p) -> std::optional<zonable_wgs84_point> 23 inline static auto from(wgs84::normalized_point p)
24 -> std::optional<zonable_wgs84_point>
30 { 25 {
31 if (p.lat() < -80 || p.lat() > 84) 26 if (p.lat() < -80 || p.lat() > 84)
32 return std::nullopt; 27 return std::nullopt;
33 return zonable_wgs84_point{p}; 28 return zonable_wgs84_point{p};
34 } 29 }
35 30
36 auto lat() const -> double 31 inline auto lat() const -> double { return p_.lat(); }
37 {
38 return p_.lat();
39 }
40 32
41 auto lon() const -> double 33 inline auto lon() const -> double { return p_.lon(); }
42 {
43 return p_.lon();
44 }
45 34
46 auto lon(double lon) -> void 35 inline auto lon(double lon) -> void { p_.lon(lon); }
47 {
48 p_.lon(lon);
49 }
50 36
51 auto lat(double lat) -> void 37 inline auto lat(double lat) -> void
52 { 38 {
53 if (lat < -80 || lat > 84) 39 if (lat < -80 || lat > 84)
54 throw std::range_error{"latitude out of range for UTM"}; 40 throw std::range_error{"latitude out of range for UTM"};
@@ -56,48 +42,69 @@ public:
56 } 42 }
57}; 43};
58 44
59} 45} // namespace routemon::geo::utm
60 46
61namespace boost::geometry::traits { 47namespace boost::geometry::traits {
62 48
63 namespace { 49namespace {
64 50
65 using zonable_wgs84_point = routemon::geo::utm::zonable_wgs84_point; 51using zonable_wgs84_point = routemon::geo::utm::zonable_wgs84_point;
66 52
67 } // namespace <anonymous> 53} // namespace
68 54
69 template<> struct tag<zonable_wgs84_point> { using type = point_tag; }; 55template <>
70 template<> struct dimension<zonable_wgs84_point> : boost::mpl::int_<2> {}; 56struct tag<zonable_wgs84_point>
71 template<> struct coordinate_type<zonable_wgs84_point> { using type = double; }; 57{
72 template<> struct coordinate_system<zonable_wgs84_point> { using type = routemon::geo::wgs84::cs; }; 58 using type = point_tag;
59};
73 60
74 template<std::size_t index> 61template <>
75 struct access<zonable_wgs84_point, index> { 62struct dimension<zonable_wgs84_point> : boost::mpl::int_<2>
76 static inline auto get(zonable_wgs84_point const& p) -> double 63{
77 { 64};
78 if constexpr (index == 0)
79 return p.lon();
80 else if constexpr (index == 1)
81 return p.lat();
82 else static_assert(false, "Out of range");
83 }
84 65
85 static inline auto set(zonable_wgs84_point& p, double v) -> void 66template <>
86 { 67struct coordinate_type<zonable_wgs84_point>
87 if constexpr (index == 0) 68{
88 p.lon(v); 69 using type = double;
89 else if constexpr (index == 1) 70};
90 p.lat(v);
91 else static_assert(false, "Out of range");
92 }
93 };
94 71
95} // namespace boost::geometry::traits 72template <>
73struct coordinate_system<zonable_wgs84_point>
74{
75 using type = routemon::geo::wgs84::cs;
76};
96 77
97namespace routemon::geo::utm 78template <std::size_t index>
79struct access<zonable_wgs84_point, index>
98{ 80{
81 static inline auto get(zonable_wgs84_point const& p) -> double
82 {
83 if constexpr (index == 0)
84 return p.lon();
85 else if constexpr (index == 1)
86 return p.lat();
87 else
88 static_assert(false, "Out of range");
89 }
90
91 static inline auto set(zonable_wgs84_point& p, double v) -> void
92 {
93 if constexpr (index == 0)
94 p.lon(v);
95 else if constexpr (index == 1)
96 p.lat(v);
97 else
98 static_assert(false, "Out of range");
99 }
100};
101
102} // namespace boost::geometry::traits
99 103
100using zonable_wgs84_linestring = bgeo::model::linestring<zonable_wgs84_point, std::vector>; 104namespace routemon::geo::utm {
105
106using zonable_wgs84_linestring =
107 bgeo::model::linestring<zonable_wgs84_point, std::vector>;
101 108
102// In the sense of the common WGS84 subdivisions by simple northing 109// In the sense of the common WGS84 subdivisions by simple northing
103// and easting (so no Norway/Svalbard exceptions). 110// and easting (so no Norway/Svalbard exceptions).
@@ -130,33 +137,30 @@ class zone
130public: 137public:
131 explicit constexpr zone(std::uint8_t zone_no, hemisphere h) 138 explicit constexpr zone(std::uint8_t zone_no, hemisphere h)
132 : zone_{from(zone_no, h)} 139 : zone_{from(zone_no, h)}
133 {} 140 {
141 }
134 142
135 auto hemisphere() const -> enum hemisphere 143 constexpr auto hemisphere() const -> enum hemisphere
136 { 144 {
137 return static_cast<enum hemisphere>(zone_ % 2); 145 return static_cast<enum hemisphere>(zone_ % 2);
138 } 146 }
139 147
140 // Return value in range [1, 60] 148 // Return value in range [1, 60]
141 auto zone_no() const -> std::uint8_t 149 constexpr auto zone_no() const -> std::uint8_t { return 1 + zone_ / 2; }
142 {
143 return 1 + zone_ / 2;
144 }
145 150
146 // Return value in range [min(), max()] 151 // Return value in range [min(), max()]
147 constexpr auto as_index() const -> std::uint8_t 152 constexpr auto as_index() const -> std::uint8_t { return zone_; }
148 {
149 return zone_;
150 }
151 153
152 static auto for_wgs84_point(zonable_wgs84_point p) noexcept -> zone 154 static auto for_wgs84_point(zonable_wgs84_point p) noexcept -> zone
153 { 155 {
154 auto zone_no = static_cast<std::uint8_t>(1 + (p.lon() + 180.0) / 6.0); 156 auto zone_no = static_cast<std::uint8_t>(1 + (p.lon() + 180.0) / 6.0);
155 auto northern = p.lat() >= 0.0; 157 auto northern = p.lat() >= 0.0;
156 return zone{zone_no, northern ? hemisphere::northern : hemisphere::southern}; 158 return zone{
159 zone_no, northern ? hemisphere::northern : hemisphere::southern
160 };
157 } 161 }
158 162
159 auto wgs84_proj_epsg() const -> int 163 constexpr auto wgs84_proj_epsg() const -> int
160 { 164 {
161 switch (hemisphere()) 165 switch (hemisphere())
162 { 166 {
@@ -178,7 +182,7 @@ public:
178 return zone{60, hemisphere::southern}; 182 return zone{60, hemisphere::southern};
179 } 183 }
180 184
181 auto next() const -> zone 185 constexpr auto next() const -> zone
182 { 186 {
183 assert(zone_ <= max().as_index()); 187 assert(zone_ <= max().as_index());
184 if (zone_ == max().as_index()) 188 if (zone_ == max().as_index())
@@ -188,7 +192,7 @@ public:
188 return copy; 192 return copy;
189 } 193 }
190 194
191 auto operator==(zone rhs) const -> bool 195 constexpr auto operator==(zone rhs) const -> bool
192 { 196 {
193 return zone_ == rhs.zone_; 197 return zone_ == rhs.zone_;
194 } 198 }