From 3e8ce840c70ee00925210b96738696d1dc445f8f Mon Sep 17 00:00:00 2001 From: Rutger Broekhoff Date: Tue, 8 Sep 2026 01:36:38 +0200 Subject: UTM projection --- server/src/geo/wgs84.cppm | 115 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 server/src/geo/wgs84.cppm (limited to 'server/src/geo/wgs84.cppm') 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 @@ +module; + +#include + +export module routemon:geo.wgs84; + +import :geo; + +namespace routemon::geo::wgs84 { + +using cs = bgeo::cs::geographic; +using point = bgeo::model::point; +// TODO: guarantee that linestring provides non-static member +// auto reserve(std::size_t) -> void +// Perhaps better yet: guarantee that the backing container is a std::vector. +using linestring = bgeo::model::linestring; +using box = bgeo::model::box; +using stype = bgeo::srs::spheroid; +using vincenty_strategy = bgeo::strategy::distance::vincenty; + +auto from_lat_lon(double lat, double lon) -> point +{ + return point{lon, lat}; +} + +auto lat(point p) -> double +{ + return bgeo::get<1>(p); +} + +auto lon(point p) -> double +{ + return bgeo::get<0>(p); +} + +// Point p with latitude in [-90, 90] and longitude in [-180, 180) +auto normalize(point p) -> point +{ + // Equivalent degrees in the range [0, 360) + auto nonneg_mod360 = [](double t) -> double + { return std::remainder(std::remainder(t, 360.0) + 360.0, 360.0); }; + + auto p_lon = lon(p); + auto p_lat = nonneg_mod360(lat(p)) - 90.0; + if (90.0 < p_lat) + { + assert(p_lat < 270.0); // by nonneg_mod360 + p_lon += 180.0; + p_lat -= 180.0; + } + p_lon = nonneg_mod360(p_lon + 180.0) - 180.0; + + return from_lat_lon(p_lat, p_lon); +} + +auto is_normalized(point p) -> bool +{ + return -90 <= lat(p) && lat(p) <= 90 && -180 <= lon(p) && lon(p) < 180; +} + +class normalized_point +{ + point p_; + +public: + normalized_point(point p) + : p_{is_normalized(p) ? p : normalize(p)} + {} + + normalized_point() + : p_{} + {} + + auto lat() const -> double + { + return bgeo::get<1>(p_); + } + + auto lon() const -> double + { + return bgeo::get<0>(p_); + } + + auto lat(double lat) -> void + { + if (lat < -90 || lat > 90) + throw std::range_error{"latitude out of range"}; + bgeo::set<1>(p_, lat); + } + + auto lon(double lon) -> void + { + if (lon < -180 || lon > 180) + throw std::range_error{"longitude out of range"}; + bgeo::set<0>(p_, lon); + } +}; + +class normalized_linestring +{ + std::vector ls_; + +public: + auto empty() const -> bool + { + return ls_.empty(); + } + + auto push_back(normalized_point p) -> void + { + ls_.push_back(p); + } +}; + +} // namespace routemon::geo::wgs84 -- cgit v1.3