summaryrefslogtreecommitdiff
path: root/src/mbgl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl')
-rw-r--r--src/mbgl/algorithm/update_renderables.hpp6
-rw-r--r--src/mbgl/annotation/render_annotation_source.cpp1
-rw-r--r--src/mbgl/renderer/sources/render_custom_geometry_source.cpp1
-rw-r--r--src/mbgl/renderer/sources/render_geojson_source.cpp1
-rw-r--r--src/mbgl/renderer/sources/render_raster_source.cpp1
-rw-r--r--src/mbgl/renderer/sources/render_vector_source.cpp1
-rw-r--r--src/mbgl/renderer/tile_pyramid.cpp11
-rw-r--r--src/mbgl/renderer/tile_pyramid.hpp1
-rw-r--r--src/mbgl/style/conversion/tileset.cpp31
-rw-r--r--src/mbgl/style/custom_tile_loader.cpp11
-rw-r--r--src/mbgl/util/geo.cpp82
-rw-r--r--src/mbgl/util/tile_range.hpp47
12 files changed, 191 insertions, 3 deletions
diff --git a/src/mbgl/algorithm/update_renderables.hpp b/src/mbgl/algorithm/update_renderables.hpp
index c583b6b2b6..5fbe0d943f 100644
--- a/src/mbgl/algorithm/update_renderables.hpp
+++ b/src/mbgl/algorithm/update_renderables.hpp
@@ -35,7 +35,11 @@ void updateRenderables(GetTileFn getTile,
auto tile = getTile(idealDataTileID);
if (!tile) {
tile = createTile(idealDataTileID);
- assert(tile);
+ // For source types where TileJSON.bounds is set, tiles outside the
+ // bounds are not created
+ if(tile == nullptr) {
+ continue;
+ }
}
// if (source has the tile and bucket is loaded) {
diff --git a/src/mbgl/annotation/render_annotation_source.cpp b/src/mbgl/annotation/render_annotation_source.cpp
index a0b69af8d5..38ca5ccd0b 100644
--- a/src/mbgl/annotation/render_annotation_source.cpp
+++ b/src/mbgl/annotation/render_annotation_source.cpp
@@ -41,6 +41,7 @@ void RenderAnnotationSource::update(Immutable<style::Source::Impl> baseImpl_,
// Zoom level 16 is typically sufficient for annotations.
// See https://github.com/mapbox/mapbox-gl-native/issues/10197
{ 0, 16 },
+ optional<LatLngBounds> {},
[&] (const OverscaledTileID& tileID) {
return std::make_unique<AnnotationTile>(tileID, parameters);
});
diff --git a/src/mbgl/renderer/sources/render_custom_geometry_source.cpp b/src/mbgl/renderer/sources/render_custom_geometry_source.cpp
index 111f0234ed..df615a7e20 100644
--- a/src/mbgl/renderer/sources/render_custom_geometry_source.cpp
+++ b/src/mbgl/renderer/sources/render_custom_geometry_source.cpp
@@ -44,6 +44,7 @@ void RenderCustomGeometrySource::update(Immutable<style::Source::Impl> baseImpl_
SourceType::CustomVector,
util::tileSize,
impl().getZoomRange(),
+ {},
[&] (const OverscaledTileID& tileID) {
return std::make_unique<CustomGeometryTile>(tileID, impl().id, parameters, impl().getTileOptions(), *tileLoader);
});
diff --git a/src/mbgl/renderer/sources/render_geojson_source.cpp b/src/mbgl/renderer/sources/render_geojson_source.cpp
index d07cfcdc41..8ea80cd813 100644
--- a/src/mbgl/renderer/sources/render_geojson_source.cpp
+++ b/src/mbgl/renderer/sources/render_geojson_source.cpp
@@ -62,6 +62,7 @@ void RenderGeoJSONSource::update(Immutable<style::Source::Impl> baseImpl_,
SourceType::GeoJSON,
util::tileSize,
impl().getZoomRange(),
+ optional<LatLngBounds>{},
[&] (const OverscaledTileID& tileID) {
return std::make_unique<GeoJSONTile>(tileID, impl().id, parameters, data->getTile(tileID.canonical));
});
diff --git a/src/mbgl/renderer/sources/render_raster_source.cpp b/src/mbgl/renderer/sources/render_raster_source.cpp
index f11f9b7aed..e99cd040e9 100644
--- a/src/mbgl/renderer/sources/render_raster_source.cpp
+++ b/src/mbgl/renderer/sources/render_raster_source.cpp
@@ -52,6 +52,7 @@ void RenderRasterSource::update(Immutable<style::Source::Impl> baseImpl_,
SourceType::Raster,
impl().getTileSize(),
tileset->zoomRange,
+ tileset->bounds,
[&] (const OverscaledTileID& tileID) {
return std::make_unique<RasterTile>(tileID, parameters, *tileset);
});
diff --git a/src/mbgl/renderer/sources/render_vector_source.cpp b/src/mbgl/renderer/sources/render_vector_source.cpp
index 49f8fdff2c..d53023e4d0 100644
--- a/src/mbgl/renderer/sources/render_vector_source.cpp
+++ b/src/mbgl/renderer/sources/render_vector_source.cpp
@@ -55,6 +55,7 @@ void RenderVectorSource::update(Immutable<style::Source::Impl> baseImpl_,
SourceType::Vector,
util::tileSize,
tileset->zoomRange,
+ tileset->bounds,
[&] (const OverscaledTileID& tileID) {
return std::make_unique<VectorTile>(tileID, impl().id, parameters, *tileset);
});
diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp
index 6a711fb6d5..e474737f8d 100644
--- a/src/mbgl/renderer/tile_pyramid.cpp
+++ b/src/mbgl/renderer/tile_pyramid.cpp
@@ -7,6 +7,7 @@
#include <mbgl/map/transform.hpp>
#include <mbgl/math/clamp.hpp>
#include <mbgl/util/tile_cover.hpp>
+#include <mbgl/util/tile_range.hpp>
#include <mbgl/util/enum.hpp>
#include <mbgl/util/logging.hpp>
@@ -14,6 +15,7 @@
#include <mapbox/geometry/envelope.hpp>
+#include <cmath>
#include <algorithm>
namespace mbgl {
@@ -61,6 +63,7 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
const SourceType type,
const uint16_t tileSize,
const Range<uint8_t> zoomRange,
+ optional<LatLngBounds> bounds,
std::function<std::unique_ptr<Tile> (const OverscaledTileID&)> createTile) {
// If we need a relayout, abandon any cached tiles; they're now stale.
if (needsRelayout) {
@@ -135,7 +138,15 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
auto it = tiles.find(tileID);
return it == tiles.end() ? nullptr : it->second.get();
};
+
+ optional<util::TileRange> tileRange = {};
+ if (bounds) {
+ tileRange = util::TileRange::fromLatLngBounds(*bounds, std::min(tileZoom, (int32_t)zoomRange.max));
+ }
auto createTileFn = [&](const OverscaledTileID& tileID) -> Tile* {
+ if (tileRange && !tileRange->contains(tileID.canonical)) {
+ return nullptr;
+ }
std::unique_ptr<Tile> tile = cache.get(tileID);
if (!tile) {
tile = createTile(tileID);
diff --git a/src/mbgl/renderer/tile_pyramid.hpp b/src/mbgl/renderer/tile_pyramid.hpp
index feab8a838c..3755cee06d 100644
--- a/src/mbgl/renderer/tile_pyramid.hpp
+++ b/src/mbgl/renderer/tile_pyramid.hpp
@@ -40,6 +40,7 @@ public:
style::SourceType type,
uint16_t tileSize,
Range<uint8_t> zoomRange,
+ optional<LatLngBounds> bounds,
std::function<std::unique_ptr<Tile> (const OverscaledTileID&)> createTile);
void startRender(PaintParameters&);
diff --git a/src/mbgl/style/conversion/tileset.cpp b/src/mbgl/style/conversion/tileset.cpp
index b9383c41b8..6e559c0cac 100644
--- a/src/mbgl/style/conversion/tileset.cpp
+++ b/src/mbgl/style/conversion/tileset.cpp
@@ -1,9 +1,14 @@
#include <mbgl/style/conversion/tileset.hpp>
+#include <mbgl/util/geo.hpp>
namespace mbgl {
namespace style {
namespace conversion {
+bool validateLatitude(const double lat) {
+ return lat < 90 && lat > -90;
+}
+
optional<Tileset> Converter<Tileset>::operator()(const Convertible& value, Error& error) const {
Tileset result;
@@ -65,6 +70,32 @@ optional<Tileset> Converter<Tileset>::operator()(const Convertible& value, Error
result.attribution = std::move(*attribution);
}
+ auto boundsValue = objectMember(value, "bounds");
+ if (boundsValue) {
+ if (!isArray(*boundsValue) || arrayLength(*boundsValue) != 4) {
+ error = { "bounds must be an array with left, bottom, top, and right values" };
+ return {};
+ }
+ optional<double> left = toDouble(arrayMember(*boundsValue, 0));
+ optional<double> bottom = toDouble(arrayMember(*boundsValue, 1));
+ optional<double> right = toDouble(arrayMember(*boundsValue, 2));
+ optional<double> top = toDouble(arrayMember(*boundsValue, 3));
+
+ if (!left || !right || !bottom || !top) {
+ error = { "bounds array must contain numeric longitude and latitude values" };
+ return {};
+ }
+ if (!validateLatitude(*bottom) || !validateLatitude(*top) || top <= bottom){
+ error = { "bounds latitude values must be between -90 and 90 with bottom less than top" };
+ return {};
+ }
+ if(*left >= *right) {
+ error = { "bounds left longitude should be less than right longitude" };
+ return {};
+ }
+ result.bounds = LatLngBounds::hull({ *bottom, *left }, { *top, *right });
+ }
+
return result;
}
diff --git a/src/mbgl/style/custom_tile_loader.cpp b/src/mbgl/style/custom_tile_loader.cpp
index 76248b84bd..1c587302b8 100644
--- a/src/mbgl/style/custom_tile_loader.cpp
+++ b/src/mbgl/style/custom_tile_loader.cpp
@@ -1,5 +1,6 @@
#include <mbgl/style/custom_tile_loader.hpp>
#include <mbgl/tile/custom_geometry_tile.hpp>
+#include <mbgl/util/tile_range.hpp>
namespace mbgl {
namespace style {
@@ -79,9 +80,15 @@ void CustomTileLoader::invalidateTile(const CanonicalTileID& tileID) {
}
void CustomTileLoader::invalidateRegion(const LatLngBounds& bounds, Range<uint8_t> ) {
+ std::map<uint8_t, util::TileRange> tileRanges;
+
for (auto idtuple= tileCallbackMap.begin(); idtuple != tileCallbackMap.end(); idtuple++) {
- const LatLngBounds tileBounds(idtuple->first);
- if (tileBounds.intersects(bounds, LatLng::Wrapped) || bounds.contains(tileBounds, LatLng::Wrapped) || tileBounds.contains(bounds, LatLng::Wrapped)) {
+ auto zoom = idtuple->first.z;
+ auto tileRange = tileRanges.find(zoom);
+ if(tileRange == tileRanges.end()) {
+ tileRange = tileRanges.emplace(std::make_pair(zoom, util::TileRange::fromLatLngBounds(bounds, zoom))).first;
+ }
+ if (tileRange->second.contains(idtuple->first)) {
for (auto iter = idtuple->second.begin(); iter != idtuple->second.end(); iter++) {
auto actor = std::get<2>(*iter);
actor.invoke(&CustomGeometryTile::invalidateTileData);
diff --git a/src/mbgl/util/geo.cpp b/src/mbgl/util/geo.cpp
index f38aba20c4..a04e2c5355 100644
--- a/src/mbgl/util/geo.cpp
+++ b/src/mbgl/util/geo.cpp
@@ -1,6 +1,8 @@
#include <mbgl/util/geo.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/math/clamp.hpp>
+#include <mbgl/util/tile_range.hpp>
#include <cmath>
@@ -32,6 +34,86 @@ LatLngBounds::LatLngBounds(const CanonicalTileID& id)
ne({ lat_(id.z, id.y), lon_(id.z, id.x + 1) }) {
}
+bool LatLngBounds::contains(const CanonicalTileID& tileID) const {
+ return util::TileRange::fromLatLngBounds(*this, tileID.z).contains(tileID);
+}
+
+bool LatLngBounds::contains(const LatLng& point, LatLng::WrapMode wrap /*= LatLng::Unwrapped*/) const {
+ bool containsLatitude = point.latitude() >= sw.latitude() &&
+ point.latitude() <= ne.latitude();
+ if (!containsLatitude) {
+ return false;
+ }
+
+ bool containsUnwrappedLongitude = point.longitude() >= sw.longitude() &&
+ point.longitude() <= ne.longitude();
+ if (containsUnwrappedLongitude) {
+ return true;
+ } else if (wrap == LatLng::Wrapped) {
+ LatLngBounds wrapped(sw.wrapped(), ne.wrapped());
+ auto ptLon = point.wrapped().longitude();
+ if (crossesAntimeridian()) {
+ return (ptLon >= wrapped.sw.longitude() &&
+ ptLon <= util::LONGITUDE_MAX) ||
+ (ptLon <= wrapped.ne.longitude() &&
+ ptLon >= -util::LONGITUDE_MAX);
+ } else {
+ return (ptLon >= wrapped.sw.longitude() &&
+ ptLon <= wrapped.ne.longitude());
+ }
+ }
+ return false;
+}
+
+bool LatLngBounds::contains(const LatLngBounds& area, LatLng::WrapMode wrap /*= LatLng::Unwrapped*/) const {
+ bool containsLatitude = area.north() <= north() && area.south() >= south();
+ if (!containsLatitude) {
+ return false;
+ }
+
+ bool containsUnwrapped = area.east() <= east() && area.west() >= west();
+ if(containsUnwrapped) {
+ return true;
+ } else if (wrap == LatLng::Wrapped) {
+ LatLngBounds wrapped(sw.wrapped(), ne.wrapped());
+ LatLngBounds other(area.sw.wrapped(), area.ne.wrapped());
+ if (crossesAntimeridian() & !area.crossesAntimeridian()) {
+ return (other.east() <= util::LONGITUDE_MAX && other.west() >= wrapped.west()) ||
+ (other.east() <= wrapped.east() && other.west() >= -util::LONGITUDE_MAX);
+ } else {
+ return other.east() <= wrapped.east() && other.west() >= wrapped.west();
+ }
+ }
+ return false;
+}
+
+bool LatLngBounds::intersects(const LatLngBounds area, LatLng::WrapMode wrap /*= LatLng::Unwrapped*/) const {
+ bool latitudeIntersects = area.north() > south() && area.south() < north();
+ if (!latitudeIntersects) {
+ return false;
+ }
+
+ bool longitudeIntersects = area.east() > west() && area.west() < east();
+ if (longitudeIntersects) {
+ return true;
+ } else if (wrap == LatLng::Wrapped) {
+ LatLngBounds wrapped(sw.wrapped(), ne.wrapped());
+ LatLngBounds other(area.sw.wrapped(), area.ne.wrapped());
+ if (crossesAntimeridian()) {
+ return area.crossesAntimeridian() ||
+ other.east() > wrapped.west() ||
+ other.west() < wrapped.east();
+ } else if (other.crossesAntimeridian()){
+ return other.east() > wrapped.west() ||
+ other.west() < wrapped.east();
+ } else {
+ return other.east() > wrapped.west() &&
+ other.west() < wrapped.east();
+ }
+ }
+ return false;
+}
+
ScreenCoordinate EdgeInsets::getCenter(uint16_t width, uint16_t height) const {
return {
(width - left() - right()) / 2.0 + left(),
diff --git a/src/mbgl/util/tile_range.hpp b/src/mbgl/util/tile_range.hpp
new file mode 100644
index 0000000000..f630a49078
--- /dev/null
+++ b/src/mbgl/util/tile_range.hpp
@@ -0,0 +1,47 @@
+#pragma once
+
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/util/range.hpp>
+#include <mbgl/util/geo.hpp>
+#include <mbgl/util/projection.hpp>
+
+namespace mbgl {
+
+namespace util {
+
+class TileRange {
+public:
+ Range<Point<double>> range;
+ uint8_t z;
+
+ // Compute the range of tiles covered by the bounds.
+ static TileRange fromLatLngBounds(const LatLngBounds& bounds, uint8_t z) {
+ auto swProj = Projection::project(bounds.southwest().wrapped(), z);
+ auto ne = bounds.northeast();
+ auto neProj = Projection::project(ne.longitude() > util::LONGITUDE_MAX ? ne.wrapped() : ne , z);
+ const auto minX = std::floor(swProj.x);
+ const auto maxX = std::ceil(neProj.x);
+ const auto minY = std::floor(neProj.y);
+ const auto maxY = std::ceil(swProj.y);
+ return TileRange({ {minX, minY}, {maxX, maxY} }, z);
+ }
+
+ bool contains(const CanonicalTileID& tileID) {
+ return z == tileID.z &&
+ (range.min.x >= range.max.x ? //For wrapped bounds
+ tileID.x >= range.min.x || tileID.x < range.max.x :
+ tileID.x < range.max.x && tileID.x >= range.min.x) &&
+ tileID.y < range.max.y &&
+ tileID.y >= range.min.y;
+ }
+
+private:
+ TileRange(Range<Point<double>> range_, uint8_t z_)
+ : range(range_),
+ z(z_) {
+ }
+
+};
+
+} // namespace util
+} // namespace mbgl