MapLibre Native Core
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
geo.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <mbgl/math/clamp.hpp>
4 #include <mbgl/math/wrap.hpp>
6 
7 #include <mapbox/geometry/point.hpp>
8 #include <mapbox/geometry/point_arithmetic.hpp>
9 #include <mapbox/geometry/line_string.hpp>
10 #include <mapbox/geometry/box.hpp>
11 
12 #include <cmath>
13 #include <stdexcept>
14 
15 namespace mbgl {
16 
17 class CanonicalTileID;
18 class UnwrappedTileID;
19 
20 using ScreenCoordinate = mapbox::geometry::point<double>;
21 using ScreenLineString = mapbox::geometry::line_string<double>;
22 using ScreenBox = mapbox::geometry::box<double>;
23 
24 class LatLng {
25 private:
26  double lat;
27  double lon;
28 
29 public:
30  enum WrapMode : bool { Unwrapped, Wrapped };
31 
32  LatLng(double lat_ = 0, double lon_ = 0, WrapMode mode = Unwrapped)
33  : lat(lat_), lon(lon_) {
34  if (std::isnan(lat)) {
35  throw std::domain_error("latitude must not be NaN");
36  }
37  if (std::isnan(lon)) {
38  throw std::domain_error("longitude must not be NaN");
39  }
40  if (std::abs(lat) > 90.0) {
41  throw std::domain_error("latitude must be between -90 and 90");
42  }
43  if (!std::isfinite(lon)) {
44  throw std::domain_error("longitude must not be infinite");
45  }
46  if (mode == Wrapped) {
47  wrap();
48  }
49  }
50 
51  double latitude() const { return lat; }
52  double longitude() const { return lon; }
53 
54  LatLng wrapped() const { return { lat, lon, Wrapped }; }
55 
56  void wrap() {
58  }
59 
60  // If the distance from start to end longitudes is between half and full
61  // world, unwrap the start longitude to ensure the shortest path is taken.
62  void unwrapForShortestPath(const LatLng& end) {
63  const double delta = std::abs(end.lon - lon);
64  if (delta <= util::LONGITUDE_MAX || delta >= util::DEGREES_MAX) return;
65  if (lon > 0 && end.lon < 0) lon -= util::DEGREES_MAX;
66  else if (lon < 0 && end.lon > 0) lon += util::DEGREES_MAX;
67  }
68 
69  // Constructs a LatLng object with the top left position of the specified tile.
70  LatLng(const CanonicalTileID& id);
71  LatLng(const UnwrappedTileID& id);
72 
73  friend bool operator==(const LatLng& a, const LatLng& b) {
74  return a.lat == b.lat && a.lon == b.lon;
75  }
76 
77  friend bool operator!=(const LatLng& a, const LatLng& b) {
78  return !(a == b);
79  }
80 };
81 
82 class LatLngBounds {
83 public:
84  // Return a bounds covering the entire (unwrapped) world.
85  static LatLngBounds world() { return {{-90, -180}, {90, 180}}; }
86 
87  // Return the bounds consisting of the single point.
88  static LatLngBounds singleton(const LatLng& a) { return {a, a}; }
89 
90  // Return the convex hull of two points; the smallest bounds that contains both.
91  static LatLngBounds hull(const LatLng& a, const LatLng& b) {
92  LatLngBounds bounds(a, a);
93  bounds.extend(b);
94  return bounds;
95  }
96 
97  // Return a bounds that may serve as the identity element for the extend operation.
98  static LatLngBounds empty() {
99  LatLngBounds bounds = world();
100  std::swap(bounds.sw, bounds.ne);
101  return bounds;
102  }
103 
109  LatLngBounds() : sw({-90, -180}), ne({90, 180}), bounded(false) {}
110 
111  // Constructs a LatLngBounds object with the tile's exact boundaries.
113 
114  bool valid() const {
115  return (sw.latitude() <= ne.latitude()) && (sw.longitude() <= ne.longitude());
116  }
117 
118  double south() const { return sw.latitude(); }
119  double west() const { return sw.longitude(); }
120  double north() const { return ne.latitude(); }
121  double east() const { return ne.longitude(); }
122 
123  LatLng southwest() const { return sw; }
124  LatLng northeast() const { return ne; }
125  LatLng southeast() const { return {south(), east()}; }
126  LatLng northwest() const { return {north(), west()}; }
127 
128  LatLng center() const { return {(sw.latitude() + ne.latitude()) / 2, (sw.longitude() + ne.longitude()) / 2}; }
129 
130  LatLng constrain(const LatLng& p) const;
131 
132  void extend(const LatLng& point) {
133  sw = LatLng(std::min(point.latitude(), sw.latitude()),
134  std::min(point.longitude(), sw.longitude()));
135  ne = LatLng(std::max(point.latitude(), ne.latitude()),
136  std::max(point.longitude(), ne.longitude()));
137  }
138 
139  void extend(const LatLngBounds& bounds) {
140  extend(bounds.sw);
141  extend(bounds.ne);
142  }
143 
144  bool isEmpty() const {
145  return sw.latitude() > ne.latitude() ||
146  sw.longitude() > ne.longitude();
147  }
148 
149  bool crossesAntimeridian() const {
150  return (sw.wrapped().longitude() > ne.wrapped().longitude());
151  }
152 
153  bool contains(const CanonicalTileID& tileID) const;
156 
158 
159 private:
160  LatLng sw;
161  LatLng ne;
162  bool bounded = true;
163 
164  LatLngBounds(LatLng sw_, LatLng ne_) : sw(sw_), ne(ne_) {}
165 
166  bool containsLatitude(double latitude) const;
167  bool containsLongitude(double longitude, LatLng::WrapMode wrap) const;
168 
169  friend bool operator==(const LatLngBounds& a, const LatLngBounds& b) {
170  return (!a.bounded && !b.bounded) || (a.bounded && b.bounded && a.sw == b.sw && a.ne == b.ne);
171  }
172 
173  friend bool operator!=(const LatLngBounds& a, const LatLngBounds& b) {
174  return !(a == b);
175  }
176 };
177 
178 // Determines the orientation of the map.
179 enum class NorthOrientation : uint8_t {
180  Upwards, // Default
181  Rightwards,
182  Downwards,
183  Leftwards,
184 };
185 
187 class EdgeInsets {
188 private:
189  double _top; // Number of pixels inset from the top edge.
190  double _left; // Number of pixels inset from the left edge.
191  double _bottom; // Number of pixels inset from the bottom edge.
192  double _right; // Number of pixels inset from the right edge.
193 
194 public:
195  EdgeInsets(double t_ = 0, double l_ = 0, double b_ = 0, double r_ = 0)
196  : _top(t_), _left(l_), _bottom(b_), _right(r_) {
197  if (std::isnan(_top)) {
198  throw std::domain_error("top must not be NaN");
199  }
200  if (std::isnan(_left)) {
201  throw std::domain_error("left must not be NaN");
202  }
203  if (std::isnan(_bottom)) {
204  throw std::domain_error("bottom must not be NaN");
205  }
206  if (std::isnan(_right)) {
207  throw std::domain_error("right must not be NaN");
208  }
209  }
210 
211  double top() const { return _top; }
212  double left() const { return _left; }
213  double bottom() const { return _bottom; }
214  double right() const { return _right; }
215 
216  bool isFlush() const {
217  return _top == 0 && _left == 0 && _bottom == 0 && _right == 0;
218  }
219 
220  void operator+=(const EdgeInsets& o) {
221  _top += o._top;
222  _left += o._left;
223  _bottom += o._bottom;
224  _right += o._right;
225  }
226 
227  EdgeInsets operator+(const EdgeInsets& o) const {
228  return {
229  _top + o._top, _left + o._left, _bottom + o._bottom, _right + o._right,
230  };
231  }
232 
233  ScreenCoordinate getCenter(uint16_t width, uint16_t height) const;
234 
235  friend bool operator==(const EdgeInsets& a, const EdgeInsets& b) {
236  return a._top == b._top && a._left == b._left && a._bottom == b._bottom && a._right == b._right;
237  }
238 
239  friend bool operator!=(const EdgeInsets& a, const EdgeInsets& b) {
240  return !(a == b);
241  }
242 };
243 
245  LatLng location = {0.0, 0.0};
246  double altitude = 0.0;
247 };
248 
249 } // namespace mbgl
The distance on each side between a rectangle and a rectangle within.
Definition: geo.hpp:187
double bottom() const
Definition: geo.hpp:213
bool isFlush() const
Definition: geo.hpp:216
void operator+=(const EdgeInsets &o)
Definition: geo.hpp:220
ScreenCoordinate getCenter(uint16_t width, uint16_t height) const
friend bool operator==(const EdgeInsets &a, const EdgeInsets &b)
Definition: geo.hpp:235
EdgeInsets operator+(const EdgeInsets &o) const
Definition: geo.hpp:227
double top() const
Definition: geo.hpp:211
friend bool operator!=(const EdgeInsets &a, const EdgeInsets &b)
Definition: geo.hpp:239
double left() const
Definition: geo.hpp:212
double right() const
Definition: geo.hpp:214
EdgeInsets(double t_=0, double l_=0, double b_=0, double r_=0)
Definition: geo.hpp:195
friend bool operator!=(const LatLngBounds &a, const LatLngBounds &b)
Definition: geo.hpp:173
LatLng center() const
Definition: geo.hpp:128
bool valid() const
Definition: geo.hpp:114
bool crossesAntimeridian() const
Definition: geo.hpp:149
static LatLngBounds hull(const LatLng &a, const LatLng &b)
Definition: geo.hpp:91
LatLngBounds(const CanonicalTileID &)
double south() const
Definition: geo.hpp:118
double north() const
Definition: geo.hpp:120
bool isEmpty() const
Definition: geo.hpp:144
bool contains(const LatLngBounds &area, LatLng::WrapMode wrap=LatLng::Unwrapped) const
static LatLngBounds singleton(const LatLng &a)
Definition: geo.hpp:88
LatLng southwest() const
Definition: geo.hpp:123
void extend(const LatLng &point)
Definition: geo.hpp:132
LatLng northwest() const
Definition: geo.hpp:126
double west() const
Definition: geo.hpp:119
void extend(const LatLngBounds &bounds)
Definition: geo.hpp:139
static LatLngBounds world()
Definition: geo.hpp:85
bool intersects(LatLngBounds area, LatLng::WrapMode wrap=LatLng::Unwrapped) const
LatLng northeast() const
Definition: geo.hpp:124
bool contains(const CanonicalTileID &tileID) const
double east() const
Definition: geo.hpp:121
friend bool operator==(const LatLngBounds &a, const LatLngBounds &b)
Definition: geo.hpp:169
LatLng constrain(const LatLng &p) const
static LatLngBounds empty()
Definition: geo.hpp:98
LatLng southeast() const
Definition: geo.hpp:125
bool contains(const LatLng &point, LatLng::WrapMode wrap=LatLng::Unwrapped) const
void wrap()
Definition: geo.hpp:56
friend bool operator!=(const LatLng &a, const LatLng &b)
Definition: geo.hpp:77
double longitude() const
Definition: geo.hpp:52
void unwrapForShortestPath(const LatLng &end)
Definition: geo.hpp:62
@ Wrapped
Definition: geo.hpp:30
@ Unwrapped
Definition: geo.hpp:30
double latitude() const
Definition: geo.hpp:51
LatLng(double lat_=0, double lon_=0, WrapMode mode=Unwrapped)
Definition: geo.hpp:32
friend bool operator==(const LatLng &a, const LatLng &b)
Definition: geo.hpp:73
LatLng(const UnwrappedTileID &id)
LatLng(const CanonicalTileID &id)
LatLng wrapped() const
Definition: geo.hpp:54
std::enable_if_t< std::is_integral_v< T >, T > max(T a, T b)
Definition: minmax.hpp:11
constexpr double DEGREES_MAX
Definition: constants.hpp:33
std::enable_if_t< std::is_integral_v< T >, T > min(T a, T b)
Definition: minmax.hpp:26
constexpr double LONGITUDE_MAX
Definition: constants.hpp:32
T wrap(T value, T min, T max)
Definition: wrap.hpp:11
Definition: actor.hpp:15
mapbox::geometry::box< double > ScreenBox
Definition: geo.hpp:22
mapbox::geometry::point< double > ScreenCoordinate
Definition: geo.hpp:20
mapbox::geometry::line_string< double > ScreenLineString
Definition: geo.hpp:21
NorthOrientation
Definition: geo.hpp:179