// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma // de Barcelona (UAB). // // This work is licensed under the terms of the MIT license. // For a copy, see . #include "carla/geom/GeoLocation.h" #include "carla/geom/Location.h" #include "carla/geom/Math.h" #include #if defined(_WIN32) && !defined(_USE_MATH_DEFINES) # define _USE_MATH_DEFINES # include // cmath is not enough for MSVC #endif namespace carla { namespace geom { /// Earth radius at equator [m]. static constexpr double EARTH_RADIUS_EQUA = 6378137.0; /// Convert latitude to scale, which is needed by mercator /// transformations /// @param lat latitude in degrees (DEG) /// @return scale factor /// @note when converting from lat/lon -> mercator and back again, /// or vice versa, use the same scale in both transformations! static double LatToScale(double lat) { return std::cos(Math::ToRadians(lat)); } /// Converts lat/lon/scale to mx/my (mx/my in meters if correct scale /// is given). template static void LatLonToMercator(double lat, double lon, double scale, float_type &mx, float_type &my) { mx = scale * Math::ToRadians(lon) * EARTH_RADIUS_EQUA; my = scale * EARTH_RADIUS_EQUA * std::log(std::tan((90.0 + lat) * Math::Pi() / 360.0)); } /// Converts mx/my/scale to lat/lon (mx/my in meters if correct scale /// is given). static void MercatorToLatLon(double mx, double my, double scale, double &lat, double &lon) { lon = mx * 180.0 / (Math::Pi() * EARTH_RADIUS_EQUA * scale); lat = 360.0 * std::atan(std::exp(my / (EARTH_RADIUS_EQUA * scale))) / Math::Pi() - 90.0; } /// Adds meters dx/dy to given lat/lon and returns new lat/lon. static void LatLonAddMeters( double lat_start, double lon_start, double dx, double dy, double &lat_end, double &lon_end) { double scale = LatToScale(lat_start); double mx, my; LatLonToMercator(lat_start, lon_start, scale, mx, my); mx += dx; my += dy; MercatorToLatLon(mx, my, scale, lat_end, lon_end); } GeoLocation GeoLocation::Transform(const Location &location) const { GeoLocation result{0.0, 0.0, altitude + location.z}; LatLonAddMeters( latitude, longitude, location.x, -location.y, // Invert y axis to have increasing latitudes northward result.latitude, result.longitude); return result; } } // namespace geom } // namespace carla