MapLibre Native Core
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
projection.hpp
Go to the documentation of this file.
1 #pragma once
2 
4 #include <mbgl/util/geo.hpp>
5 #include <mbgl/util/geometry.hpp>
6 #include <mbgl/math/angles.hpp>
7 #include <mbgl/math/clamp.hpp>
8 
9 namespace mbgl {
10 
12 private:
13  double _northing; // Distance measured northwards.
14  double _easting; // Distance measured eastwards.
15 
16 public:
17  ProjectedMeters(double n_ = 0, double e_ = 0)
18  : _northing(n_), _easting(e_) {
19  if (std::isnan(_northing)) {
20  throw std::domain_error("northing must not be NaN");
21  }
22  if (std::isnan(_easting)) {
23  throw std::domain_error("easting must not be NaN");
24  }
25  }
26 
27  double northing() const { return _northing; }
28  double easting() const { return _easting; }
29 
30  friend bool operator==(const ProjectedMeters& a, const ProjectedMeters& b) {
31  return a._northing == b._northing && a._easting == b._easting;
32  }
33 
34  friend bool operator!=(const ProjectedMeters& a, const ProjectedMeters& b) {
35  return !(a == b);
36  }
37 };
38 
41 class Projection {
42 public:
43  // Map pixel width at given scale.
44  static double worldSize(double scale) {
45  return scale * util::tileSize_D;
46  }
47 
48  static double getMetersPerPixelAtLatitude(double lat, double zoom) {
49  const double constrainedZoom = util::clamp(zoom, util::MIN_ZOOM, util::MAX_ZOOM);
50  const double constrainedScale = std::pow(2.0, constrainedZoom);
51  const double constrainedLatitude = util::clamp(lat, -util::LATITUDE_MAX, util::LATITUDE_MAX);
52  return std::cos(util::deg2rad(constrainedLatitude)) * util::M2PI * util::EARTH_RADIUS_M / worldSize(constrainedScale);
53  }
54 
56  const double constrainedLatitude = util::clamp(latLng.latitude(), -util::LATITUDE_MAX, util::LATITUDE_MAX);
57  const double constrainedLongitude = util::clamp(latLng.longitude(), -util::LONGITUDE_MAX, util::LONGITUDE_MAX);
58 
59  const double m = 1 - 1e-15;
60  const double f = util::clamp(std::sin(util::deg2rad(constrainedLatitude)), -m, m);
61 
62  const double easting = util::deg2rad(util::EARTH_RADIUS_M * constrainedLongitude);
63  const double northing = 0.5 * util::EARTH_RADIUS_M * std::log((1 + f) / (1 - f));
64 
65  return {northing, easting};
66  }
67 
68  static LatLng latLngForProjectedMeters(const ProjectedMeters& projectedMeters) {
69  double latitude = util::rad2deg(2 * std::atan(std::exp(projectedMeters.northing() / util::EARTH_RADIUS_M)) - (M_PI / 2.0));
70  double longitude = util::rad2deg(projectedMeters.easting()) / util::EARTH_RADIUS_M;
71 
72  latitude = util::clamp(latitude, -util::LATITUDE_MAX, util::LATITUDE_MAX);
73  longitude = util::clamp(longitude, -util::LONGITUDE_MAX, util::LONGITUDE_MAX);
74 
75  return {latitude, longitude};
76  }
77 
78  static Point<double> project(const LatLng& latLng, double scale) {
79  return project_(latLng, worldSize(scale));
80  }
81 
83  static Point<double> project(const LatLng& latLng, int32_t zoom) {
84  return project_(latLng, 1 << zoom);
85  }
86 
87  static LatLng unproject(const Point<double>& p, double scale, LatLng::WrapMode wrapMode = LatLng::Unwrapped) {
88  auto p2 = p * util::DEGREES_MAX / worldSize(scale);
89  return LatLng {
90  std::atan(std::exp(util::deg2rad(util::LONGITUDE_MAX - p2.y))) * util::DEGREES_MAX / M_PI - 90.0,
91  p2.x - util::LONGITUDE_MAX,
92  wrapMode
93  };
94  }
95 
96 private:
97  static Point<double> project_(const LatLng& latLng, double worldSize) {
98  const double latitude = util::clamp(latLng.latitude(), -util::LATITUDE_MAX, util::LATITUDE_MAX);
99  return Point<double> {
100  util::LONGITUDE_MAX + latLng.longitude(),
101  util::LONGITUDE_MAX - util::rad2deg(std::log(std::tan(M_PI / 4 + latitude * M_PI / util::DEGREES_MAX)))
103  }
104 };
105 
106 } // namespace mbgl
double longitude() const
Definition: geo.hpp:52
@ Unwrapped
Definition: geo.hpp:30
double latitude() const
Definition: geo.hpp:51
double easting() const
Definition: projection.hpp:28
double northing() const
Definition: projection.hpp:27
ProjectedMeters(double n_=0, double e_=0)
Definition: projection.hpp:17
friend bool operator==(const ProjectedMeters &a, const ProjectedMeters &b)
Definition: projection.hpp:30
friend bool operator!=(const ProjectedMeters &a, const ProjectedMeters &b)
Definition: projection.hpp:34
static ProjectedMeters projectedMetersForLatLng(const LatLng &latLng)
Definition: projection.hpp:55
static LatLng latLngForProjectedMeters(const ProjectedMeters &projectedMeters)
Definition: projection.hpp:68
static double worldSize(double scale)
Definition: projection.hpp:44
static Point< double > project(const LatLng &latLng, int32_t zoom)
Returns point on tile.
Definition: projection.hpp:83
static LatLng unproject(const Point< double > &p, double scale, LatLng::WrapMode wrapMode=LatLng::Unwrapped)
Definition: projection.hpp:87
static double getMetersPerPixelAtLatitude(double lat, double zoom)
Definition: projection.hpp:48
static Point< double > project(const LatLng &latLng, double scale)
Definition: projection.hpp:78
std::unique_ptr< Expression > zoom()
T clamp(T value, T min_, T max_)
Definition: clamp.hpp:9
constexpr double deg2rad(double deg) noexcept
Converts degrees to radians.
Definition: angles.hpp:14
constexpr double MAX_ZOOM
Definition: constants.hpp:37
constexpr double rad2deg(double rad) noexcept
Converts radians to degrees.
Definition: angles.hpp:34
constexpr double MIN_ZOOM
Definition: constants.hpp:36
constexpr double M2PI
Definition: constants.hpp:29
constexpr double DEGREES_MAX
Definition: constants.hpp:33
constexpr double LONGITUDE_MAX
Definition: constants.hpp:32
constexpr double EARTH_RADIUS_M
Definition: constants.hpp:30
constexpr double tileSize_D
Definition: constants.hpp:13
constexpr double LATITUDE_MAX
Definition: constants.hpp:31
Definition: actor.hpp:15
mapbox::geometry::point< T > Point
Definition: geometry.hpp:21