1 #include <mbgl/util/geo.hpp>
2 #include <mbgl/util/constants.hpp>
3 #include <mbgl/tile/tile_id.hpp>
4 #include <mbgl/math/clamp.hpp>
5 #include <mbgl/util/tile_range.hpp>
6
7 #include <cmath>
8
9 namespace mbgl {
10
11 namespace {
12
lat_(const uint8_t z,const int64_t y)13 double lat_(const uint8_t z, const int64_t y) {
14 const double n = M_PI - 2.0 * M_PI * y / std::pow(2.0, z);
15 return util::RAD2DEG * std::atan(0.5 * (std::exp(n) - std::exp(-n)));
16 }
17
lon_(const uint8_t z,const int64_t x)18 double lon_(const uint8_t z, const int64_t x) {
19 return x / std::pow(2.0, z) * util::DEGREES_MAX - util::LONGITUDE_MAX;
20 }
21
22 } // end namespace
23
LatLng(const CanonicalTileID & id)24 LatLng::LatLng(const CanonicalTileID& id) : lat(lat_(id.z, id.y)), lon(lon_(id.z, id.x)) {
25 }
26
LatLng(const UnwrappedTileID & id)27 LatLng::LatLng(const UnwrappedTileID& id)
28 : lat(lat_(id.canonical.z, id.canonical.y)),
29 lon(lon_(id.canonical.z, id.canonical.x) + id.wrap * util::DEGREES_MAX) {
30 }
31
LatLngBounds(const CanonicalTileID & id)32 LatLngBounds::LatLngBounds(const CanonicalTileID& id)
33 : sw({ lat_(id.z, id.y + 1), lon_(id.z, id.x) }),
34 ne({ lat_(id.z, id.y), lon_(id.z, id.x + 1) }) {
35 }
36
contains(const CanonicalTileID & tileID) const37 bool LatLngBounds::contains(const CanonicalTileID& tileID) const {
38 return util::TileRange::fromLatLngBounds(*this, tileID.z).contains(tileID);
39 }
40
contains(const LatLng & point,LatLng::WrapMode wrap) const41 bool LatLngBounds::contains(const LatLng& point, LatLng::WrapMode wrap /*= LatLng::Unwrapped*/) const {
42 bool containsLatitude = point.latitude() >= sw.latitude() &&
43 point.latitude() <= ne.latitude();
44 if (!containsLatitude) {
45 return false;
46 }
47
48 bool containsUnwrappedLongitude = point.longitude() >= sw.longitude() &&
49 point.longitude() <= ne.longitude();
50 if (containsUnwrappedLongitude) {
51 return true;
52 } else if (wrap == LatLng::Wrapped) {
53 LatLngBounds wrapped(sw.wrapped(), ne.wrapped());
54 auto ptLon = point.wrapped().longitude();
55 if (crossesAntimeridian()) {
56 return (ptLon >= wrapped.sw.longitude() &&
57 ptLon <= util::LONGITUDE_MAX) ||
58 (ptLon <= wrapped.ne.longitude() &&
59 ptLon >= -util::LONGITUDE_MAX);
60 } else {
61 return (ptLon >= wrapped.sw.longitude() &&
62 ptLon <= wrapped.ne.longitude());
63 }
64 }
65 return false;
66 }
67
contains(const LatLngBounds & area,LatLng::WrapMode wrap) const68 bool LatLngBounds::contains(const LatLngBounds& area, LatLng::WrapMode wrap /*= LatLng::Unwrapped*/) const {
69 bool containsLatitude = area.north() <= north() && area.south() >= south();
70 if (!containsLatitude) {
71 return false;
72 }
73
74 bool containsUnwrapped = area.east() <= east() && area.west() >= west();
75 if(containsUnwrapped) {
76 return true;
77 } else if (wrap == LatLng::Wrapped) {
78 LatLngBounds wrapped(sw.wrapped(), ne.wrapped());
79 LatLngBounds other(area.sw.wrapped(), area.ne.wrapped());
80 if (crossesAntimeridian() & !area.crossesAntimeridian()) {
81 return (other.east() <= util::LONGITUDE_MAX && other.west() >= wrapped.west()) ||
82 (other.east() <= wrapped.east() && other.west() >= -util::LONGITUDE_MAX);
83 } else {
84 return other.east() <= wrapped.east() && other.west() >= wrapped.west();
85 }
86 }
87 return false;
88 }
89
intersects(const LatLngBounds area,LatLng::WrapMode wrap) const90 bool LatLngBounds::intersects(const LatLngBounds area, LatLng::WrapMode wrap /*= LatLng::Unwrapped*/) const {
91 bool latitudeIntersects = area.north() > south() && area.south() < north();
92 if (!latitudeIntersects) {
93 return false;
94 }
95
96 bool longitudeIntersects = area.east() > west() && area.west() < east();
97 if (longitudeIntersects) {
98 return true;
99 } else if (wrap == LatLng::Wrapped) {
100 LatLngBounds wrapped(sw.wrapped(), ne.wrapped());
101 LatLngBounds other(area.sw.wrapped(), area.ne.wrapped());
102 if (crossesAntimeridian()) {
103 return area.crossesAntimeridian() ||
104 other.east() > wrapped.west() ||
105 other.west() < wrapped.east();
106 } else if (other.crossesAntimeridian()){
107 return other.east() > wrapped.west() ||
108 other.west() < wrapped.east();
109 } else {
110 return other.east() > wrapped.west() &&
111 other.west() < wrapped.east();
112 }
113 }
114 return false;
115 }
116
getCenter(uint16_t width,uint16_t height) const117 ScreenCoordinate EdgeInsets::getCenter(uint16_t width, uint16_t height) const {
118 return {
119 (width - left() - right()) / 2.0 + left(),
120 (height - top() - bottom()) / 2.0 + top(),
121 };
122 }
123
124 } // end namespace mbgl
125