1#pragma once
2
3#include <mbgl/math/clamp.hpp>
4#include <mbgl/math/wrap.hpp>
5#include <mbgl/util/constants.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
15namespace mbgl {
16
17class CanonicalTileID;
18class UnwrappedTileID;
19
20using ScreenCoordinate = mapbox::geometry::point<double>;
21using ScreenLineString = mapbox::geometry::line_string<double>;
22using ScreenBox = mapbox::geometry::box<double>;
23
24class LatLng {
25private:
26 double lat;
27 double lon;
28
29public:
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(x: lat)) {
35 throw std::domain_error("latitude must not be NaN");
36 }
37 if (std::isnan(x: lon)) {
38 throw std::domain_error("longitude must not be NaN");
39 }
40 if (std::abs(x: lat) > 90.0) {
41 throw std::domain_error("latitude must be between -90 and 90");
42 }
43 if (!std::isfinite(x: 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() {
57 lon = util::wrap(value: lon, min: -util::LONGITUDE_MAX, max: util::LONGITUDE_MAX);
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(x: 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
82class LatLngBounds {
83public:
84 // Return a bounds covering the entire (unwrapped) world.
85 static LatLngBounds world() {
86 return LatLngBounds({-90, -180}, {90, 180});
87 }
88
89 // Return the bounds consisting of the single point.
90 static LatLngBounds singleton(const LatLng& a) {
91 return LatLngBounds(a, a);
92 }
93
94 // Return the convex hull of two points; the smallest bounds that contains both.
95 static LatLngBounds hull(const LatLng& a, const LatLng& b) {
96 LatLngBounds bounds(a, a);
97 bounds.extend(point: b);
98 return bounds;
99 }
100
101 // Return a bounds that may serve as the identity element for the extend operation.
102 static LatLngBounds empty() {
103 LatLngBounds bounds = world();
104 std::swap(a&: bounds.sw, b&: bounds.ne);
105 return bounds;
106 }
107
108 // Constructs a LatLngBounds object with the tile's exact boundaries.
109 LatLngBounds(const CanonicalTileID&);
110
111 bool valid() const {
112 return (sw.latitude() <= ne.latitude()) && (sw.longitude() <= ne.longitude());
113 }
114
115 double south() const { return sw.latitude(); }
116 double west() const { return sw.longitude(); }
117 double north() const { return ne.latitude(); }
118 double east() const { return ne.longitude(); }
119
120 LatLng southwest() const { return sw; }
121 LatLng northeast() const { return ne; }
122 LatLng southeast() const { return LatLng(south(), east()); }
123 LatLng northwest() const { return LatLng(north(), west()); }
124
125 LatLng center() const {
126 return LatLng((sw.latitude() + ne.latitude()) / 2,
127 (sw.longitude() + ne.longitude()) / 2);
128 }
129
130 LatLng constrain(const LatLng& p) const {
131 if (contains(point: p)) {
132 return p;
133 }
134 return LatLng {
135 util::clamp(value: p.latitude(), min_: sw.latitude(), max_: ne.latitude()),
136 util::clamp(value: p.longitude(), min_: sw.longitude(), max_: ne.longitude())
137 };
138 }
139
140 void extend(const LatLng& point) {
141 sw = LatLng(std::min(a: point.latitude(), b: sw.latitude()),
142 std::min(a: point.longitude(), b: sw.longitude()));
143 ne = LatLng(std::max(a: point.latitude(), b: ne.latitude()),
144 std::max(a: point.longitude(), b: ne.longitude()));
145 }
146
147 void extend(const LatLngBounds& bounds) {
148 extend(point: bounds.sw);
149 extend(point: bounds.ne);
150 }
151
152 bool isEmpty() const {
153 return sw.latitude() > ne.latitude() ||
154 sw.longitude() > ne.longitude();
155 }
156
157 bool crossesAntimeridian() const {
158 return (sw.wrapped().longitude() > ne.wrapped().longitude());
159 }
160
161 bool contains(const CanonicalTileID& tileID) const;
162 bool contains(const LatLng& point, LatLng::WrapMode wrap = LatLng::Unwrapped) const;
163 bool contains(const LatLngBounds& area, LatLng::WrapMode wrap = LatLng::Unwrapped) const;
164
165 bool intersects(const LatLngBounds area, LatLng::WrapMode wrap = LatLng::Unwrapped) const;
166
167private:
168 LatLng sw;
169 LatLng ne;
170
171 LatLngBounds(LatLng sw_, LatLng ne_)
172 : sw(std::move(sw_)), ne(std::move(ne_)) {}
173
174 friend bool operator==(const LatLngBounds& a, const LatLngBounds& b) {
175 return a.sw == b.sw && a.ne == b.ne;
176 }
177
178 friend bool operator!=(const LatLngBounds& a, const LatLngBounds& b) {
179 return !(a == b);
180 }
181};
182
183// Determines the orientation of the map.
184enum class NorthOrientation : uint8_t {
185 Upwards, // Default
186 Rightwards,
187 Downwards,
188 Leftwards,
189};
190
191/// The distance on each side between a rectangle and a rectangle within.
192class EdgeInsets {
193private:
194 double _top; // Number of pixels inset from the top edge.
195 double _left; // Number of pixels inset from the left edge.
196 double _bottom; // Number of pixels inset from the bottom edge.
197 double _right; // Number of pixels inset from the right edge.
198
199public:
200 EdgeInsets(double t_ = 0, double l_ = 0, double b_ = 0, double r_ = 0)
201 : _top(t_), _left(l_), _bottom(b_), _right(r_) {
202 if (std::isnan(x: _top)) {
203 throw std::domain_error("top must not be NaN");
204 }
205 if (std::isnan(x: _left)) {
206 throw std::domain_error("left must not be NaN");
207 }
208 if (std::isnan(x: _bottom)) {
209 throw std::domain_error("bottom must not be NaN");
210 }
211 if (std::isnan(x: _right)) {
212 throw std::domain_error("right must not be NaN");
213 }
214 }
215
216 double top() const { return _top; }
217 double left() const { return _left; }
218 double bottom() const { return _bottom; }
219 double right() const { return _right; }
220
221 bool isFlush() const {
222 return _top == 0 && _left == 0 && _bottom == 0 && _right == 0;
223 }
224
225 void operator+=(const EdgeInsets& o) {
226 _top += o._top;
227 _left += o._left;
228 _bottom += o._bottom;
229 _right += o._right;
230 }
231
232 EdgeInsets operator+(const EdgeInsets& o) const {
233 return {
234 _top + o._top, _left + o._left, _bottom + o._bottom, _right + o._right,
235 };
236 }
237
238 ScreenCoordinate getCenter(uint16_t width, uint16_t height) const;
239
240 friend bool operator==(const EdgeInsets& a, const EdgeInsets& b) {
241 return a._top == b._top && a._left == b._left && a._bottom == b._bottom && a._right == b._right;
242 }
243
244 friend bool operator!=(const EdgeInsets& a, const EdgeInsets& b) {
245 return !(a == b);
246 }
247};
248
249} // namespace mbgl
250

source code of qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/util/geo.hpp