From 7e80dae59b36d95b694b6468d7e423c0a8300c73 Mon Sep 17 00:00:00 2001 From: Michael Krasnyk Date: Thu, 5 May 2016 11:04:44 +0200 Subject: [PATCH 1/2] Fix MSVS build. --- include/util/static_rtree.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/util/static_rtree.hpp b/include/util/static_rtree.hpp index a105dc941..2d9f63d0b 100644 --- a/include/util/static_rtree.hpp +++ b/include/util/static_rtree.hpp @@ -74,9 +74,9 @@ class StaticRTree struct LeafNode { LeafNode() : object_count(0), objects() {} - uint32_t object_count; + std::uint32_t object_count; std::array objects; - unsigned char leaf_page_padding[LEAF_PAGE_SIZE - sizeof(object_count) - sizeof(objects)]; + unsigned char leaf_page_padding[LEAF_PAGE_SIZE - sizeof(std::uint32_t) - sizeof(std::array)]; }; static_assert(sizeof(LeafNode) == LEAF_PAGE_SIZE, "LeafNode size does not fit the page size"); From 24a75d37fbcc6c8bfc6c69b8d1178eb00c4b213e Mon Sep 17 00:00:00 2001 From: Michael Krasnyk Date: Wed, 4 May 2016 00:37:53 +0200 Subject: [PATCH 2/2] =?UTF-8?q?Approximate=20inverse=20Gudermannian=20func?= =?UTF-8?q?tion=20by=20a=20Pad=C3=A9=20approximant?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/util/web_mercator.hpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/include/util/web_mercator.hpp b/include/util/web_mercator.hpp index 8c23de143..a2bea88d1 100644 --- a/include/util/web_mercator.hpp +++ b/include/util/web_mercator.hpp @@ -35,7 +35,7 @@ inline FloatLatitude yToLat(const double y) const double normalized_lat = detail::RAD_TO_DEGREE * 2. * std::atan(std::exp(clamped_y * detail::DEGREE_TO_RAD)); - return FloatLatitude(normalized_lat - 90.); + return FloatLatitude(std::round(normalized_lat * COORDINATE_PRECISION) / COORDINATE_PRECISION - 90.); } inline double latToY(const FloatLatitude latitude) @@ -47,6 +47,31 @@ inline double latToY(const FloatLatitude latitude) return clamped_y; } +template +constexpr double horner(double, T an) { return an; } + +template +constexpr double horner(double x, T an, U ...a) { return horner(x, a...) * x + an; } + +inline double latToYapprox(const FloatLatitude latitude) +{ + if (latitude < FloatLatitude(-70.) || latitude > FloatLatitude(70.)) + return latToY(latitude); + + // Approximate the inverse Gudermannian function with the Padé approximant [11/11]: deg → deg + // Coefficients are computed for the argument range [-70°,70°] by Remez algorithm |err|_∞=3.387e-12 + const auto x = static_cast(latitude); + return + horner(x, 0.00000000000000000000000000e+00, 1.00000000000089108431373566e+00, 2.34439410386997223035693483e-06, + -3.21291701673364717170998957e-04, -6.62778508496089940141103135e-10, 3.68188055470304769936079078e-08, + 6.31192702320492485752941578e-14, -1.77274453235716299127325443e-12, -2.24563810831776747318521450e-18, + 3.13524754818073129982475171e-17, 2.09014225025314211415458228e-23, -9.82938075991732185095509716e-23) / + horner(x, 1.00000000000000000000000000e+00, 2.34439410398970701719081061e-06, -3.72061271627251952928813333e-04, + -7.81802389685429267252612620e-10, 5.18418724186576447072888605e-08, 9.37468561198098681003717477e-14, + -3.30833288607921773936702558e-12, -4.78446279888774903983338274e-18, 9.32999229169156878168234191e-17, + 9.17695141954265959600965170e-23, -8.72130728982012387640166055e-22, -3.23083224835967391884404730e-28); +} + inline FloatLatitude clamp(const FloatLatitude lat) { return std::max(std::min(lat, FloatLatitude(detail::MAX_LATITUDE)), @@ -87,7 +112,7 @@ inline double degreeToPixel(FloatLatitude lat, unsigned zoom) inline FloatCoordinate fromWGS84(const FloatCoordinate &wgs84_coordinate) { - return {wgs84_coordinate.lon, FloatLatitude{latToY(wgs84_coordinate.lat)}}; + return {wgs84_coordinate.lon, FloatLatitude{latToYapprox(wgs84_coordinate.lat)}}; } inline FloatCoordinate toWGS84(const FloatCoordinate &mercator_coordinate)