Fix possible division by zero by clamping latitude to 85.05°
Resolves #3530
This commit is contained in:
committed by
Patrick Niklaus
parent
f82740ed93
commit
1d4d3b80b5
@@ -20,7 +20,7 @@ const constexpr double EARTH_RADIUS_WGS84 = 6378137.0;
|
||||
// earth circumference devided by 2
|
||||
const constexpr double MAXEXTENT = EARTH_RADIUS_WGS84 * boost::math::constants::pi<double>();
|
||||
// ^ math functions are not constexpr since they have side-effects (setting errno) :(
|
||||
const constexpr double MAX_LATITUDE = 85.;
|
||||
const constexpr double EPSG3857_MAX_LATITUDE = 85.051128779806592378; // 90(4*atan(exp(pi))/pi-1)
|
||||
const constexpr double MAX_LONGITUDE = 180.0;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,18 @@ const constexpr double DEGREE_TO_PX = detail::MAXEXTENT / 180.0;
|
||||
// This is the global default tile size for all Mapbox Vector Tiles
|
||||
const constexpr double TILE_SIZE = 256.0;
|
||||
|
||||
inline FloatLatitude clamp(const FloatLatitude lat)
|
||||
{
|
||||
return std::max(std::min(lat, FloatLatitude{detail::EPSG3857_MAX_LATITUDE}),
|
||||
FloatLatitude{-detail::EPSG3857_MAX_LATITUDE});
|
||||
}
|
||||
|
||||
inline FloatLongitude clamp(const FloatLongitude lon)
|
||||
{
|
||||
return std::max(std::min(lon, FloatLongitude{detail::MAX_LONGITUDE}),
|
||||
FloatLongitude{-detail::MAX_LONGITUDE});
|
||||
}
|
||||
|
||||
inline FloatLatitude yToLat(const double y)
|
||||
{
|
||||
const auto clamped_y = std::max(-180., std::min(180., y));
|
||||
@@ -41,10 +53,9 @@ inline FloatLatitude yToLat(const double y)
|
||||
inline double latToY(const FloatLatitude latitude)
|
||||
{
|
||||
// apparently this is the (faster) version of the canonical log(tan()) version
|
||||
const double f = std::sin(detail::DEGREE_TO_RAD * static_cast<double>(latitude));
|
||||
const double y = detail::RAD_TO_DEGREE * 0.5 * std::log((1 + f) / (1 - f));
|
||||
const auto clamped_y = std::max(-180., std::min(180., y));
|
||||
return clamped_y;
|
||||
const auto clamped_latitude = clamp(latitude);
|
||||
const double f = std::sin(detail::DEGREE_TO_RAD * static_cast<double>(clamped_latitude));
|
||||
return detail::RAD_TO_DEGREE * 0.5 * std::log((1 + f) / (1 - f));
|
||||
}
|
||||
|
||||
template <typename T> constexpr double horner(double, T an) { return an; }
|
||||
@@ -91,18 +102,6 @@ inline double latToYapprox(const FloatLatitude latitude)
|
||||
-3.23083224835967391884404730e-28);
|
||||
}
|
||||
|
||||
inline FloatLatitude clamp(const FloatLatitude lat)
|
||||
{
|
||||
return std::max(std::min(lat, FloatLatitude{detail::MAX_LATITUDE}),
|
||||
FloatLatitude{-detail::MAX_LATITUDE});
|
||||
}
|
||||
|
||||
inline FloatLongitude clamp(const FloatLongitude lon)
|
||||
{
|
||||
return std::max(std::min(lon, FloatLongitude{detail::MAX_LONGITUDE}),
|
||||
FloatLongitude{-detail::MAX_LONGITUDE});
|
||||
}
|
||||
|
||||
inline void pixelToDegree(const double shift, double &x, double &y)
|
||||
{
|
||||
const double b = shift / 2.0;
|
||||
@@ -166,9 +165,9 @@ inline void xyzToMercator(
|
||||
xyzToWGS84(x, y, z, minx, miny, maxx, maxy);
|
||||
|
||||
minx = static_cast<double>(clamp(util::FloatLongitude{minx})) * DEGREE_TO_PX;
|
||||
miny = latToY(clamp(util::FloatLatitude{miny})) * DEGREE_TO_PX;
|
||||
miny = latToY(util::FloatLatitude{miny}) * DEGREE_TO_PX;
|
||||
maxx = static_cast<double>(clamp(util::FloatLongitude{maxx})) * DEGREE_TO_PX;
|
||||
maxy = latToY(clamp(util::FloatLatitude{maxy})) * DEGREE_TO_PX;
|
||||
maxy = latToY(util::FloatLatitude{maxy}) * DEGREE_TO_PX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user