diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2015-04-06 17:09:21 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2015-04-06 17:09:21 -0700 |
commit | 6262172034a439880f219b76a4e8c272ae4a2a44 (patch) | |
tree | dbeedb85d6a0beab0ce3839838805ec22c49ce2b | |
parent | 760c0f0f19aa00bdec063556d76ba5cceb150e93 (diff) | |
parent | c73309ef5f375956ec39cb6460f61b078536113b (diff) | |
download | qtlocation-mapboxgl-6262172034a439880f219b76a4e8c272ae4a2a44.tar.gz |
Merge pull request #1200 from mapbox/source
Eliminate StyleSource
54 files changed, 674 insertions, 725 deletions
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 764ff24ed8..129d463b25 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -30,7 +30,6 @@ class LayerDescription; class Sprite; class Style; class StyleLayer; -class StyleSource; class TexturePool; class FileSource; class View; @@ -175,7 +174,6 @@ private: void setup(); void updateTiles(); - void updateSources(); // Triggered by triggerUpdate(); void update(); @@ -194,7 +192,7 @@ private: void processTasks(); - void updateAnnotationTiles(const std::vector<Tile::ID>&); + void updateAnnotationTiles(const std::vector<TileID>&); enum class Mode : uint8_t { None, // we're not doing any processing @@ -249,8 +247,6 @@ private: const std::unique_ptr<MapData> data; - std::set<util::ptr<StyleSource>> activeSources; - std::atomic<UpdateType> updated; std::mutex mutexTask; diff --git a/include/mbgl/map/tile.hpp b/include/mbgl/map/tile.hpp deleted file mode 100644 index 146ebe6ad7..0000000000 --- a/include/mbgl/map/tile.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef MBGL_MAP_TILE -#define MBGL_MAP_TILE - -#include <mbgl/util/mat4.hpp> -#include <mbgl/util/noncopyable.hpp> -#include <mbgl/util/ptr.hpp> - -#include <cstdint> -#include <bitset> -#include <cmath> -#include <cstdint> -#include <forward_list> -#include <iosfwd> -#include <string> -#include <functional> - -namespace mbgl { - -class TileData; -struct box; - -struct ClipID { - inline ClipID() {} - inline ClipID(const std::string &mask_, const std::string &reference_) : mask(mask_), reference(reference_) {} - - std::bitset<8> mask; - std::bitset<8> reference; - - inline bool operator==(const ClipID &other) const { - return mask == other.mask && reference == other.reference; - } -}; - -class Tile : private util::noncopyable { -public: - struct ID { - const int16_t w = 0; - const int8_t z = 0; - const int32_t x = 0, y = 0; - - inline explicit ID(int8_t z_, int32_t x_, int32_t y_) - : w((x_ < 0 ? x_ - (1 << z_) + 1 : x_) / (1 << z_)), z(z_), x(x_), y(y_) {} - - inline uint64_t to_uint64() const { - return ((std::pow(2, z) * y + x) * 32) + z; - } - - struct Hash { - std::size_t operator()(ID const& i) const { - return std::hash<uint64_t>()(i.to_uint64()); - } - }; - - inline bool operator==(const ID& rhs) const { - return w == rhs.w && z == rhs.z && x == rhs.x && y == rhs.y; - } - - inline bool operator!=(const ID& rhs) const { - return !operator==(rhs); - } - - inline bool operator<(const ID &rhs) const { - if (w != rhs.w) return w < rhs.w; - if (z != rhs.z) return z < rhs.z; - if (x != rhs.x) return x < rhs.x; - return y < rhs.y; - } - - ID parent(int8_t z) const; - ID normalized() const; - std::forward_list<ID> children(int32_t z) const; - bool isChildOf(const Tile::ID &id) const; - operator std::string() const; - }; - - static std::forward_list<Tile::ID> cover(int8_t z, const box& bounds); - -public: - explicit Tile(const ID& id); - -public: - const Tile::ID id; - ClipID clip; - mat4 matrix; - util::ptr<TileData> data; -}; - -} - -#endif diff --git a/include/mbgl/map/transform_state.hpp b/include/mbgl/map/transform_state.hpp index c1a324a899..f6a00a4a3d 100644 --- a/include/mbgl/map/transform_state.hpp +++ b/include/mbgl/map/transform_state.hpp @@ -1,8 +1,6 @@ #ifndef MBGL_MAP_TRANSFORM_STATE #define MBGL_MAP_TRANSFORM_STATE -#include <mbgl/map/tile.hpp> - #include <mbgl/util/mat4.hpp> #include <mbgl/util/geo.hpp> #include <mbgl/util/vec.hpp> @@ -13,12 +11,15 @@ namespace mbgl { +class TileID; +struct box; + class TransformState { friend class Transform; public: // Matrix - void matrixFor(mat4& matrix, const Tile::ID& id) const; + void matrixFor(mat4& matrix, const TileID& id) const; box cornersToBox(uint32_t z) const; // Dimensions diff --git a/src/mbgl/map/annotation.cpp b/src/mbgl/map/annotation.cpp index fa26af785f..b921c08f74 100644 --- a/src/mbgl/map/annotation.cpp +++ b/src/mbgl/map/annotation.cpp @@ -1,5 +1,6 @@ #include <mbgl/map/annotation.hpp> #include <mbgl/map/map.hpp> +#include <mbgl/map/tile_id.hpp> #include <mbgl/map/live_tile.hpp> #include <mbgl/util/ptr.hpp> #include <mbgl/util/std.hpp> @@ -29,7 +30,7 @@ private: private: const AnnotationType type = AnnotationType::Point; const AnnotationSegments geometry; - std::unordered_map<Tile::ID, std::weak_ptr<const LiveTileFeature>, Tile::ID::Hash> tileFeatures; + std::unordered_map<TileID, std::weak_ptr<const LiveTileFeature>, TileID::Hash> tileFeatures; const LatLngBounds bounds; }; @@ -82,7 +83,7 @@ vec2<double> AnnotationManager::projectPoint(const LatLng& point) { return { x, y }; } -std::pair<std::vector<Tile::ID>, AnnotationIDs> AnnotationManager::addPointAnnotations( +std::pair<std::vector<TileID>, AnnotationIDs> AnnotationManager::addPointAnnotations( const std::vector<LatLng>& points, const std::vector<std::string>& symbols, const Map& map) { std::lock_guard<std::mutex> lock(mtx); @@ -97,7 +98,7 @@ std::pair<std::vector<Tile::ID>, AnnotationIDs> AnnotationManager::addPointAnnot std::vector<uint32_t> annotationIDs; annotationIDs.reserve(points.size()); - std::vector<Tile::ID> affectedTiles; + std::vector<TileID> affectedTiles; for (size_t i = 0; i < points.size(); ++i) { const uint32_t annotationID = nextID(); @@ -121,7 +122,7 @@ std::pair<std::vector<Tile::ID>, AnnotationIDs> AnnotationManager::addPointAnnot for (int8_t z = maxZoom; z >= 0; z--) { affectedTiles.emplace_back(z, x, y); - Tile::ID tileID = affectedTiles.back(); + TileID tileID = affectedTiles.back(); // calculate tile coordinate const Coordinate coordinate(extent * (p.x * z2 - x), extent * (p.y * z2 - y)); @@ -180,10 +181,10 @@ std::pair<std::vector<Tile::ID>, AnnotationIDs> AnnotationManager::addPointAnnot return std::make_pair(affectedTiles, annotationIDs); } -std::vector<Tile::ID> AnnotationManager::removeAnnotations(const AnnotationIDs& ids, const Map& map) { +std::vector<TileID> AnnotationManager::removeAnnotations(const AnnotationIDs& ids, const Map& map) { std::lock_guard<std::mutex> lock(mtx); - std::vector<Tile::ID> affectedTiles; + std::vector<TileID> affectedTiles; std::vector<uint32_t> z2s; uint8_t zoomCount = map.getMaxZoom() + 1; @@ -208,7 +209,7 @@ std::vector<Tile::ID> AnnotationManager::removeAnnotations(const AnnotationIDs& p = projectPoint(latLng); x = z2s[z] * p.x; y = z2s[z] * p.y; - Tile::ID tid(z, x, y); + TileID tid(z, x, y); // erase annotation from tile's list auto& tileAnnotations = tiles[tid].first; tileAnnotations.erase(annotationID); @@ -225,7 +226,7 @@ std::vector<Tile::ID> AnnotationManager::removeAnnotations(const AnnotationIDs& } } - // Tile::IDs for tiles that need refreshed. + // TileIDs for tiles that need refreshed. return affectedTiles; } @@ -239,13 +240,13 @@ std::vector<uint32_t> AnnotationManager::getAnnotationsInBounds(const LatLngBoun const vec2<double> nePoint = projectPoint(queryBounds.ne); // tiles number y from top down - const Tile::ID nwTile(z, swPoint.x * z2, nePoint.y * z2); - const Tile::ID seTile(z, nePoint.x * z2, swPoint.y * z2); + const TileID nwTile(z, swPoint.x * z2, nePoint.y * z2); + const TileID seTile(z, nePoint.x * z2, swPoint.y * z2); std::vector<uint32_t> matchingAnnotations; for (auto& tile : tiles) { - Tile::ID id = tile.first; + TileID id = tile.first; if (id.z == z) { if (id.x >= nwTile.x && id.x <= seTile.x && id.y >= nwTile.y && id.y <= seTile.y) { if (id.x > nwTile.x && id.x < seTile.x && id.y > nwTile.y && id.y < seTile.y) { @@ -292,7 +293,7 @@ LatLngBounds AnnotationManager::getBoundsForAnnotations(const AnnotationIDs& ids return bounds; } -const LiveTile* AnnotationManager::getTile(Tile::ID const& id) { +const LiveTile* AnnotationManager::getTile(const TileID& id) { std::lock_guard<std::mutex> lock(mtx); const auto tile_it = tiles.find(id); diff --git a/include/mbgl/map/annotation.hpp b/src/mbgl/map/annotation.hpp index efd91d9087..f1596dbdff 100644 --- a/include/mbgl/map/annotation.hpp +++ b/src/mbgl/map/annotation.hpp @@ -1,7 +1,7 @@ #ifndef MBGL_MAP_ANNOTATIONS #define MBGL_MAP_ANNOTATIONS -#include <mbgl/map/tile.hpp> +#include <mbgl/map/tile_id.hpp> #include <mbgl/util/geo.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/std.hpp> @@ -28,13 +28,13 @@ public: ~AnnotationManager(); void setDefaultPointAnnotationSymbol(const std::string& symbol); - std::pair<std::vector<Tile::ID>, AnnotationIDs> addPointAnnotations( + std::pair<std::vector<TileID>, AnnotationIDs> addPointAnnotations( const std::vector<LatLng>&, const std::vector<std::string>& symbols, const Map&); - std::vector<Tile::ID> removeAnnotations(const AnnotationIDs&, const Map&); + std::vector<TileID> removeAnnotations(const AnnotationIDs&, const Map&); AnnotationIDs getAnnotationsInBounds(const LatLngBounds&, const Map&) const; LatLngBounds getBoundsForAnnotations(const AnnotationIDs&) const; - const LiveTile* getTile(Tile::ID const& id); + const LiveTile* getTile(const TileID& id); static const std::string layerID; @@ -46,7 +46,7 @@ private: mutable std::mutex mtx; std::string defaultPointAnnotationSymbol; std::unordered_map<uint32_t, std::unique_ptr<Annotation>> annotations; - std::unordered_map<Tile::ID, std::pair<std::unordered_set<uint32_t>, std::unique_ptr<LiveTile>>, Tile::ID::Hash> tiles; + std::unordered_map<TileID, std::pair<std::unordered_set<uint32_t>, std::unique_ptr<LiveTile>>, TileID::Hash> tiles; uint32_t nextID_ = 0; }; diff --git a/src/mbgl/map/live_tile_data.cpp b/src/mbgl/map/live_tile_data.cpp index dd83ed4224..6456e51538 100644 --- a/src/mbgl/map/live_tile_data.cpp +++ b/src/mbgl/map/live_tile_data.cpp @@ -2,13 +2,13 @@ #include <mbgl/map/live_tile_data.hpp> #include <mbgl/map/live_tile.hpp> #include <mbgl/map/tile_parser.hpp> -#include <mbgl/style/style_source.hpp> +#include <mbgl/map/source.hpp> #include <mbgl/map/vector_tile.hpp> #include <mbgl/platform/log.hpp> using namespace mbgl; -LiveTileData::LiveTileData(Tile::ID const& id_, +LiveTileData::LiveTileData(const TileID& id_, AnnotationManager& annotationManager_, float mapMaxZoom, util::ptr<Style> style_, @@ -36,24 +36,19 @@ void LiveTileData::parse() { throw std::runtime_error("style isn't present in LiveTileData object anymore"); } - if (source.type == SourceType::Annotations) { - const LiveTile* tile = annotationManager.getTile(id); + const LiveTile* tile = annotationManager.getTile(id); + if (tile) { + // Parsing creates state that is encapsulated in TileParser. While parsing, + // the TileParser object writes results into this objects. All other state + // is going to be discarded afterwards. + TileParser parser(*tile, *this, style, glyphAtlas, glyphStore, spriteAtlas, sprite); - if (tile) { - // Parsing creates state that is encapsulated in TileParser. While parsing, - // the TileParser object writes results into this objects. All other state - // is going to be discarded afterwards. - TileParser parser(*tile, *this, style, glyphAtlas, glyphStore, spriteAtlas, sprite); + // Clear the style so that we don't have a cycle in the shared_ptr references. + style.reset(); - // Clear the style so that we don't have a cycle in the shared_ptr references. - style.reset(); - - parser.parse(); - } else { - state = State::obsolete; - } + parser.parse(); } else { - throw std::runtime_error("unknown live tile source type"); + state = State::obsolete; } } catch (const std::exception& ex) { Log::Error(Event::ParseTile, "Live-parsing [%d/%d/%d] failed: %s", id.z, id.x, id.y, ex.what()); diff --git a/src/mbgl/map/live_tile_data.hpp b/src/mbgl/map/live_tile_data.hpp index 7874d6ff55..d40cfdfd69 100644 --- a/src/mbgl/map/live_tile_data.hpp +++ b/src/mbgl/map/live_tile_data.hpp @@ -9,7 +9,7 @@ class AnnotationManager; class LiveTileData : public VectorTileData { public: - LiveTileData(Tile::ID const&, + LiveTileData(const TileID&, AnnotationManager&, float mapMaxZoom, util::ptr<Style>, diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index ac2be3f060..8697523ac1 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -90,7 +90,6 @@ Map::~Map() { "MapandMain"); // Explicitly reset all pointers. - activeSources.clear(); sprite.reset(); glyphStore.reset(); style.reset(); @@ -129,11 +128,6 @@ void Map::start(bool startPaused) { // Remove all of these to make sure they are destructed in the correct thread. style.reset(); - // Since we don't have a stylesheet anymore, this will disable all Sources and cancel - // their associated requests. - updateSources(); - assert(activeSources.empty()); - // It's now safe to destroy/join the workers since there won't be any more callbacks that // could dispatch to the worker pool. workers.reset(); @@ -622,14 +616,15 @@ LatLngBounds Map::getBoundsForAnnotations(const std::vector<uint32_t>& annotatio }); } -void Map::updateAnnotationTiles(const std::vector<Tile::ID>& ids) { +void Map::updateAnnotationTiles(const std::vector<TileID>& ids) { assert(Environment::currentlyOn(ThreadType::Map)); - for (const auto &source : activeSources) { + if (!style) return; + for (const auto &source : style->sources) { if (source->info.type == SourceType::Annotations) { - source->source->invalidateTiles(*this, ids); - return; + source->invalidateTiles(ids); } } + triggerUpdate(); } #pragma mark - Toggles @@ -689,45 +684,11 @@ Duration Map::getDefaultTransitionDuration() { return data->getDefaultTransitionDuration(); } -void Map::updateSources() { - assert(Environment::currentlyOn(ThreadType::Map)); - - // First, disable all existing sources. - for (const auto& source : activeSources) { - source->enabled = false; - } - - // Then, reenable all of those that we actually use when drawing this layer. - if (style) { - for (const auto& layer : style->layers) { - if (layer->bucket && layer->bucket->style_source) { - (*activeSources.emplace(layer->bucket->style_source).first)->enabled = true; - } - } - } - - // Then, construct or destroy the actual source object, depending on enabled state. - for (const auto& source : activeSources) { - if (source->enabled) { - if (!source->source) { - source->source = std::make_shared<Source>(source->info); - source->source->load(*this, *env); - } - } else { - source->source.reset(); - } - } - - // Finally, remove all sources that are disabled. - util::erase_if(activeSources, [](util::ptr<StyleSource> source){ - return !source->enabled; - }); -} - void Map::updateTiles() { assert(Environment::currentlyOn(ThreadType::Map)); - for (const auto& source : activeSources) { - source->source->update(*this, getWorker(), style, *glyphAtlas, *glyphStore, + if (!style) return; + for (const auto& source : style->sources) { + source->update(*this, getWorker(), style, *glyphAtlas, *glyphStore, *spriteAtlas, getSprite(), *texturePool, [this]() { assert(Environment::currentlyOn(ThreadType::Map)); triggerUpdate(); @@ -779,6 +740,13 @@ void Map::loadStyleJSON(const std::string& json, const std::string& base) { const std::string glyphURL = util::mapbox::normalizeGlyphsURL(style->glyph_url, getAccessToken()); glyphStore->setURL(glyphURL); + for (const auto& source : style->sources) { + source->load(getAccessToken(), *env, [this]() { + assert(Environment::currentlyOn(ThreadType::Map)); + triggerUpdate(); + }); + } + triggerUpdate(Update::Zoom); } @@ -821,8 +789,6 @@ void Map::prepare() { style->recalculate(state.getNormalizedZoom(), now); } - updateSources(); - // Allow the sprite atlas to potentially pull new sprite images if needed. spriteAtlas->resize(state.getPixelRatio()); spriteAtlas->setSprite(getSprite()); @@ -843,8 +809,8 @@ void Map::render() { assert(style); assert(painter); - painter->render(*style, activeSources, - state, data->getAnimationTime()); + + painter->render(*style, state, data->getAnimationTime()); // Schedule another rerender when we definitely need a next frame. if (transform.needsTransition() || style->hasTransitions()) { diff --git a/src/mbgl/map/raster_tile_data.cpp b/src/mbgl/map/raster_tile_data.cpp index b8862e6dd8..2531f5130b 100644 --- a/src/mbgl/map/raster_tile_data.cpp +++ b/src/mbgl/map/raster_tile_data.cpp @@ -4,7 +4,7 @@ using namespace mbgl; -RasterTileData::RasterTileData(Tile::ID const &id_, TexturePool &texturePool, +RasterTileData::RasterTileData(const TileID& id_, TexturePool &texturePool, const SourceInfo &source_) : TileData(id_, source_), bucket(texturePool, layout) { } diff --git a/src/mbgl/map/raster_tile_data.hpp b/src/mbgl/map/raster_tile_data.hpp index 76bc1bb5aa..dab2b7b842 100644 --- a/src/mbgl/map/raster_tile_data.hpp +++ b/src/mbgl/map/raster_tile_data.hpp @@ -1,7 +1,6 @@ #ifndef MBGL_MAP_RASTER_TILE_DATA #define MBGL_MAP_RASTER_TILE_DATA -#include <mbgl/map/tile.hpp> #include <mbgl/map/tile_data.hpp> #include <mbgl/style/style_layout.hpp> #include <mbgl/renderer/raster_bucket.hpp> @@ -17,7 +16,7 @@ class RasterTileData : public TileData { friend class TileParser; public: - RasterTileData(Tile::ID const &id, TexturePool &, const SourceInfo &); + RasterTileData(const TileID&, TexturePool&, const SourceInfo&); ~RasterTileData(); void parse() override; diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index dbe88e654d..fa7ab6b969 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -2,6 +2,7 @@ #include <mbgl/map/map.hpp> #include <mbgl/map/environment.hpp> #include <mbgl/map/transform.hpp> +#include <mbgl/map/tile.hpp> #include <mbgl/renderer/painter.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/raster.hpp> @@ -18,6 +19,8 @@ #include <mbgl/style/style_layer.hpp> #include <mbgl/platform/log.hpp> #include <mbgl/util/uv_detail.hpp> +#include <mbgl/util/token.hpp> +#include <mbgl/util/tile_cover.hpp> #include <mbgl/map/vector_tile_data.hpp> #include <mbgl/map/raster_tile_data.hpp> @@ -27,15 +30,105 @@ namespace mbgl { -Source::Source(SourceInfo& info_) - : info(info_) +void parse(const rapidjson::Value& value, std::vector<std::string>& target, const char *name) { + if (!value.HasMember(name)) + return; + + const rapidjson::Value& property = value[name]; + if (!property.IsArray()) + return; + + for (rapidjson::SizeType i = 0; i < property.Size(); i++) + if (!property[i].IsString()) + return; + + for (rapidjson::SizeType i = 0; i < property.Size(); i++) + target.emplace_back(std::string(property[i].GetString(), property[i].GetStringLength())); +} + +void parse(const rapidjson::Value& value, std::string& target, const char* name) { + if (!value.HasMember(name)) + return; + + const rapidjson::Value& property = value[name]; + if (!property.IsString()) + return; + + target = { property.GetString(), property.GetStringLength() }; +} + +void parse(const rapidjson::Value& value, uint16_t& target, const char* name) { + if (!value.HasMember(name)) + return; + + const rapidjson::Value& property = value[name]; + if (!property.IsUint()) + return; + + unsigned int uint = property.GetUint(); + if (uint > std::numeric_limits<uint16_t>::max()) + return; + + target = uint; +} + +template <size_t N> +void parse(const rapidjson::Value& value, std::array<float, N>& target, const char* name) { + if (!value.HasMember(name)) + return; + + const rapidjson::Value& property = value[name]; + if (!property.IsArray() || property.Size() != N) + return; + + for (rapidjson::SizeType i = 0; i < property.Size(); i++) + if (!property[i].IsNumber()) + return; + + for (rapidjson::SizeType i = 0; i < property.Size(); i++) + target[i] = property[i].GetDouble(); +} + +void SourceInfo::parseTileJSONProperties(const rapidjson::Value& value) { + parse(value, tiles, "tiles"); + parse(value, min_zoom, "minzoom"); + parse(value, max_zoom, "maxzoom"); + parse(value, attribution, "attribution"); + parse(value, center, "center"); + parse(value, bounds, "bounds"); +} + +std::string SourceInfo::tileURL(const TileID& id, float pixelRatio) const { + std::string result = tiles.at((id.x + id.y) % tiles.size()); + result = util::mapbox::normalizeTileURL(result, url, type); + result = util::replaceTokens(result, [&](const std::string &token) -> std::string { + if (token == "z") return util::toString(id.z); + if (token == "x") return util::toString(id.x); + if (token == "y") return util::toString(id.y); + if (token == "prefix") { + std::string prefix { 2 }; + prefix[0] = "0123456789abcdef"[id.x % 16]; + prefix[1] = "0123456789abcdef"[id.y % 16]; + return prefix; + } + if (token == "ratio") return pixelRatio > 1.0 ? "@2x" : ""; + return ""; + }); + return result; +} + +Source::Source() { } +Source::~Source() {} + // Note: This is a separate function that must be called exactly once after creation // The reason this isn't part of the constructor is that calling shared_from_this() in // the constructor fails. -void Source::load(Map &map, Environment &env) { +void Source::load(const std::string& accessToken, + Environment& env, + std::function<void()> callback) { if (info.url.empty()) { loaded = true; return; @@ -43,8 +136,8 @@ void Source::load(Map &map, Environment &env) { util::ptr<Source> source = shared_from_this(); - const std::string url = util::mapbox::normalizeSourceURL(info.url, map.getAccessToken()); - env.request({ Resource::Kind::JSON, url }, [source, &map](const Response &res) { + const std::string url = util::mapbox::normalizeSourceURL(info.url, accessToken); + env.request({ Resource::Kind::JSON, url }, [source, callback](const Response &res) { if (res.status != Response::Successful) { Log::Warning(Event::General, "Failed to load source TileJSON: %s", res.message.c_str()); return; @@ -61,19 +154,7 @@ void Source::load(Map &map, Environment &env) { source->info.parseTileJSONProperties(d); source->loaded = true; - map.triggerUpdate(); - }); -} - -void Source::updateClipIDs(const std::map<Tile::ID, ClipID> &mapping) { - std::for_each(tiles.begin(), tiles.end(), [&mapping](std::pair<const Tile::ID, std::unique_ptr<Tile>> &pair) { - Tile &tile = *pair.second; - auto it = mapping.find(tile.id); - if (it != mapping.end()) { - tile.clip = it->second; - } else { - tile.clip = ClipID {}; - } + callback(); }); } @@ -85,10 +166,6 @@ void Source::updateMatrices(const mat4 &projMatrix, const TransformState &transf } } -size_t Source::getTileCount() const { - return tiles.size(); -} - void Source::drawClippingMasks(Painter &painter) { for (const auto& pair : tiles) { Tile &tile = *pair.second; @@ -114,16 +191,6 @@ void Source::finishRender(Painter &painter) { } } -std::forward_list<Tile::ID> Source::getIDs() const { - std::forward_list<Tile::ID> ptrs; - - std::transform(tiles.begin(), tiles.end(), std::front_inserter(ptrs), [](const std::pair<const Tile::ID, std::unique_ptr<Tile>> &pair) { - Tile &tile = *pair.second; - return tile.id; - }); - return ptrs; -} - std::forward_list<Tile *> Source::getLoadedTiles() const { std::forward_list<Tile *> ptrs; auto it = ptrs.before_begin(); @@ -136,7 +203,7 @@ std::forward_list<Tile *> Source::getLoadedTiles() const { } -TileData::State Source::hasTile(const Tile::ID& id) { +TileData::State Source::hasTile(const TileID& id) { auto it = tiles.find(id); if (it != tiles.end()) { Tile &tile = *it->second; @@ -152,7 +219,7 @@ TileData::State Source::addTile(Map &map, uv::worker &worker, util::ptr<Style> style, GlyphAtlas &glyphAtlas, GlyphStore &glyphStore, SpriteAtlas &spriteAtlas, util::ptr<Sprite> sprite, TexturePool &texturePool, - const Tile::ID &id, std::function<void()> callback) { + const TileID &id, std::function<void()> callback) { const TileData::State state = hasTile(id); if (state != TileData::State::invalid) { @@ -164,7 +231,7 @@ TileData::State Source::addTile(Map &map, uv::worker &worker, // We couldn't find the tile in the list. Create a new one. // Try to find the associated TileData object. - const Tile::ID normalized_id = id.normalized(); + const TileID normalized_id = id.normalized(); auto it = tile_data.find(normalized_id); if (it != tile_data.end()) { @@ -211,7 +278,7 @@ int32_t Source::coveringZoomLevel(const TransformState& state) const { return std::floor(getZoom(state)); } -std::forward_list<Tile::ID> Source::coveringTiles(const TransformState& state) const { +std::forward_list<TileID> Source::coveringTiles(const TransformState& state) const { int32_t z = coveringZoomLevel(state); if (z < info.min_zoom) return {{}}; @@ -221,9 +288,9 @@ std::forward_list<Tile::ID> Source::coveringTiles(const TransformState& state) c box points = state.cornersToBox(z); const vec2<double>& center = points.center; - std::forward_list<Tile::ID> covering_tiles = Tile::cover(z, points); + std::forward_list<TileID> covering_tiles = tileCover(z, points); - covering_tiles.sort([¢er](const Tile::ID& a, const Tile::ID& b) { + covering_tiles.sort([¢er](const TileID& a, const TileID& b) { // Sorts by distance from the box center return std::fabs(a.x - center.x) + std::fabs(a.y - center.y) < std::fabs(b.x - center.x) + std::fabs(b.y - center.y); @@ -241,7 +308,7 @@ std::forward_list<Tile::ID> Source::coveringTiles(const TransformState& state) c * * @return boolean Whether the children found completely cover the tile. */ -bool Source::findLoadedChildren(const Tile::ID& id, int32_t maxCoveringZoom, std::forward_list<Tile::ID>& retain) { +bool Source::findLoadedChildren(const TileID& id, int32_t maxCoveringZoom, std::forward_list<TileID>& retain) { bool complete = true; int32_t z = id.z; auto ids = id.children(z + 1); @@ -269,9 +336,9 @@ bool Source::findLoadedChildren(const Tile::ID& id, int32_t maxCoveringZoom, std * * @return boolean Whether a parent was found. */ -bool Source::findLoadedParent(const Tile::ID& id, int32_t minCoveringZoom, std::forward_list<Tile::ID>& retain) { +bool Source::findLoadedParent(const TileID& id, int32_t minCoveringZoom, std::forward_list<TileID>& retain) { for (int32_t z = id.z - 1; z >= minCoveringZoom; --z) { - const Tile::ID parent_id = id.parent(z); + const TileID parent_id = id.parent(z); const TileData::State state = hasTile(parent_id); if (state == TileData::State::parsed) { retain.emplace_front(parent_id); @@ -295,7 +362,7 @@ void Source::update(Map &map, } int32_t zoom = std::floor(getZoom(map.getState())); - std::forward_list<Tile::ID> required = coveringTiles(map.getState()); + std::forward_list<TileID> required = coveringTiles(map.getState()); // Determine the overzooming/underzooming amounts. int32_t minCoveringZoom = util::clamp<int32_t>(zoom - 10, info.min_zoom, info.max_zoom); @@ -304,7 +371,7 @@ void Source::update(Map &map, // Retain is a list of tiles that we shouldn't delete, even if they are not // the most ideal tile for the current viewport. This may include tiles like // parent or child tiles that are *already* loaded. - std::forward_list<Tile::ID> retain(required); + std::forward_list<TileID> retain(required); // Add existing child/parent tiles if the actual tile is not yet loaded for (const auto& id : required) { @@ -329,8 +396,8 @@ void Source::update(Map &map, // Remove tiles that we definitely don't need, i.e. tiles that are not on // the required list. - std::set<Tile::ID> retain_data; - util::erase_if(tiles, [&retain, &retain_data](std::pair<const Tile::ID, std::unique_ptr<Tile>> &pair) { + std::set<TileID> retain_data; + util::erase_if(tiles, [&retain, &retain_data](std::pair<const TileID, std::unique_ptr<Tile>> &pair) { Tile &tile = *pair.second; bool obsolete = std::find(retain.begin(), retain.end(), tile.id) == retain.end(); if (!obsolete) { @@ -340,7 +407,7 @@ void Source::update(Map &map, }); // Remove all the expired pointers from the set. - util::erase_if(tile_data, [&retain_data](std::pair<const Tile::ID, std::weak_ptr<TileData>> &pair) { + util::erase_if(tile_data, [&retain_data](std::pair<const TileID, std::weak_ptr<TileData>> &pair) { const util::ptr<TileData> tile = pair.second.lock(); if (!tile) { return true; @@ -358,12 +425,11 @@ void Source::update(Map &map, updated = map.getTime(); } -void Source::invalidateTiles(Map& map, const std::vector<Tile::ID>& ids) { +void Source::invalidateTiles(const std::vector<TileID>& ids) { for (auto& id : ids) { tiles.erase(id); tile_data.erase(id); } - map.triggerUpdate(); } } diff --git a/src/mbgl/map/source.hpp b/src/mbgl/map/source.hpp index 5c38636a24..4a551cda5b 100644 --- a/src/mbgl/map/source.hpp +++ b/src/mbgl/map/source.hpp @@ -1,15 +1,17 @@ #ifndef MBGL_MAP_SOURCE #define MBGL_MAP_SOURCE -#include <mbgl/map/tile.hpp> +#include <mbgl/map/tile_id.hpp> #include <mbgl/map/tile_data.hpp> -#include <mbgl/style/style_source.hpp> +#include <mbgl/style/types.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/mat4.hpp> #include <mbgl/util/ptr.hpp> #include <mbgl/util/chrono.hpp> +#include <rapidjson/document.h> + #include <cstdint> #include <forward_list> #include <iosfwd> @@ -28,49 +30,71 @@ class Style; class Painter; class StyleLayer; class TransformState; +class Tile; +struct ClipID; struct box; +class SourceInfo : private util::noncopyable { +public: + SourceType type = SourceType::Vector; + std::string url; + std::vector<std::string> tiles; + uint16_t tile_size = 512; + uint16_t min_zoom = 0; + uint16_t max_zoom = 22; + std::string attribution; + std::array<float, 3> center = {{0, 0, 0}}; + std::array<float, 4> bounds = {{-180, -90, 180, 90}}; + + void parseTileJSONProperties(const rapidjson::Value&); + std::string tileURL(const TileID& id, float pixelRatio) const; +}; + class Source : public std::enable_shared_from_this<Source>, private util::noncopyable { public: - Source(SourceInfo&); + Source(); + ~Source(); + + void load(const std::string& accessToken, + Environment&, + std::function<void()> callback); - void load(Map &, Environment &); void update(Map &, uv::worker &, util::ptr<Style>, GlyphAtlas &, GlyphStore &, SpriteAtlas &, util::ptr<Sprite>, TexturePool &, std::function<void()> callback); - void invalidateTiles(Map&, const std::vector<Tile::ID>&); + + void invalidateTiles(const std::vector<TileID>&); void updateMatrices(const mat4 &projMatrix, const TransformState &transform); void drawClippingMasks(Painter &painter); - size_t getTileCount() const; void render(Painter &painter, const StyleLayer &layer_desc); void finishRender(Painter &painter); - std::forward_list<Tile::ID> getIDs() const; std::forward_list<Tile *> getLoadedTiles() const; - void updateClipIDs(const std::map<Tile::ID, ClipID> &mapping); + + SourceInfo info; + bool enabled; private: - bool findLoadedChildren(const Tile::ID& id, int32_t maxCoveringZoom, std::forward_list<Tile::ID>& retain); - bool findLoadedParent(const Tile::ID& id, int32_t minCoveringZoom, std::forward_list<Tile::ID>& retain); + bool findLoadedChildren(const TileID& id, int32_t maxCoveringZoom, std::forward_list<TileID>& retain); + bool findLoadedParent(const TileID& id, int32_t minCoveringZoom, std::forward_list<TileID>& retain); int32_t coveringZoomLevel(const TransformState&) const; - std::forward_list<Tile::ID> coveringTiles(const TransformState&) const; + std::forward_list<TileID> coveringTiles(const TransformState&) const; TileData::State addTile(Map &, uv::worker &, util::ptr<Style>, GlyphAtlas &, GlyphStore &, SpriteAtlas &, util::ptr<Sprite>, TexturePool &, - const Tile::ID &, std::function<void()> callback); + const TileID &, std::function<void()> callback); - TileData::State hasTile(const Tile::ID& id); + TileData::State hasTile(const TileID& id); double getZoom(const TransformState &state) const; - SourceInfo& info; bool loaded = false; // Stores the time when this source was most recently updated. TimePoint updated = TimePoint::min(); - std::map<Tile::ID, std::unique_ptr<Tile>> tiles; - std::map<Tile::ID, std::weak_ptr<TileData>> tile_data; + std::map<TileID, std::unique_ptr<Tile>> tiles; + std::map<TileID, std::weak_ptr<TileData>> tile_data; }; } diff --git a/src/mbgl/map/tile.cpp b/src/mbgl/map/tile.cpp index 9f31048857..408cdfaec5 100644 --- a/src/mbgl/map/tile.cpp +++ b/src/mbgl/map/tile.cpp @@ -1,147 +1,3 @@ #include <mbgl/map/tile.hpp> -#include <mbgl/util/vec.hpp> -#include <mbgl/util/string.hpp> -#include <mbgl/util/box.hpp> - - -#include <cassert> using namespace mbgl; - -#include <iostream> - -Tile::Tile(const ID& id_) - : id(id_) { -} - -Tile::ID Tile::ID::parent(int8_t parent_z) const { - assert(parent_z < z); - int32_t dim = std::pow(2, z - parent_z); - return Tile::ID{ - parent_z, - (x >= 0 ? x : x - dim + 1) / dim, - y / dim - }; -} - -std::forward_list<Tile::ID> Tile::ID::children(int32_t child_z) const { - assert(child_z > z); - int32_t factor = std::pow(2, child_z - z); - - std::forward_list<ID> child_ids; - for (int32_t ty = y * factor, y_max = (y + 1) * factor; ty < y_max; ++ty) { - for (int32_t tx = x * factor, x_max = (x + 1) * factor; tx < x_max; ++tx) { - child_ids.emplace_front(child_z, tx, ty); - } - } - return child_ids; -} - -Tile::ID Tile::ID::normalized() const { - int32_t dim = std::pow(2, z); - int32_t nx = x, ny = y; - while (nx < 0) nx += dim; - while (nx >= dim) nx -= dim; - return ID { z, nx, ny }; -} - -bool Tile::ID::isChildOf(const Tile::ID &parent_id) const { - if (parent_id.z >= z || parent_id.w != w) { - return false; - } - int32_t scale = std::pow(2, z - parent_id.z); - return parent_id.x == ((x < 0 ? x - scale + 1 : x) / scale) && - parent_id.y == y / scale; -} - - -Tile::ID::operator std::string() const { - return util::toString(z) + "/" + util::toString(x) + "/" + util::toString(y); -} - - -// Taken from polymaps src/Layer.js -// https://github.com/simplegeo/polymaps/blob/master/src/Layer.js#L333-L383 - -struct edge { - double x0 = 0, y0 = 0; - double x1 = 0, y1 = 0; - double dx = 0, dy = 0; - - edge(vec2<double> a, vec2<double> b) { - if (a.y > b.y) { std::swap(a, b); } - x0 = a.x; - y0 = a.y; - x1 = b.x; - y1 = b.y; - dx = b.x - a.x; - dy = b.y - a.y; - } -}; - -typedef const std::function<void(int32_t x0, int32_t x1, int32_t y)> ScanLine; - -// scan-line conversion -static void scanSpans(edge e0, edge e1, int32_t ymin, int32_t ymax, ScanLine scanLine) { - double y0 = std::fmax(ymin, std::floor(e1.y0)); - double y1 = std::fmin(ymax, std::ceil(e1.y1)); - - // sort edges by x-coordinate - if ((e0.x0 == e1.x0 && e0.y0 == e1.y0) ? - (e0.x0 + e1.dy / e0.dy * e0.dx < e1.x1) : - (e0.x1 - e1.dy / e0.dy * e0.dx < e1.x0)) { - std::swap(e0, e1); - } - - // scan lines! - double m0 = e0.dx / e0.dy; - double m1 = e1.dx / e1.dy; - double d0 = e0.dx > 0; // use y + 1 to compute x0 - double d1 = e1.dx < 0; // use y + 1 to compute x1 - for (int32_t y = y0; y < y1; y++) { - double x0 = m0 * std::fmax(0, std::fmin(e0.dy, y + d0 - e0.y0)) + e0.x0; - double x1 = m1 * std::fmax(0, std::fmin(e1.dy, y + d1 - e1.y0)) + e1.x0; - scanLine(std::floor(x1), std::ceil(x0), y); - } -} - -// scan-line conversion -static void scanTriangle(const mbgl::vec2<double> a, const mbgl::vec2<double> b, const mbgl::vec2<double> c, int32_t ymin, int32_t ymax, ScanLine& scanLine) { - edge ab = edge(a, b); - edge bc = edge(b, c); - edge ca = edge(c, a); - - // sort edges by y-length - if (ab.dy > bc.dy) { std::swap(ab, bc); } - if (ab.dy > ca.dy) { std::swap(ab, ca); } - if (bc.dy > ca.dy) { std::swap(bc, ca); } - - // scan span! scan span! - if (ab.dy) scanSpans(ca, ab, ymin, ymax, scanLine); - if (bc.dy) scanSpans(ca, bc, ymin, ymax, scanLine); -} - -std::forward_list<Tile::ID> Tile::cover(int8_t z, const mbgl::box &bounds) { - int32_t tiles = 1 << z; - std::forward_list<mbgl::Tile::ID> t; - - auto scanLine = [&](int32_t x0, int32_t x1, int32_t y) { - int32_t x; - if (y >= 0 && y <= tiles) { - for (x = x0; x < x1; x++) { - t.emplace_front(z, x, y); - } - } - }; - - // Divide the screen up in two triangles and scan each of them: - // \---+ - // | \ | - // +---\. - scanTriangle(bounds.tl, bounds.tr, bounds.br, 0, tiles, scanLine); - scanTriangle(bounds.br, bounds.bl, bounds.tl, 0, tiles, scanLine); - - t.unique(); - - return t; -} diff --git a/src/mbgl/map/tile.hpp b/src/mbgl/map/tile.hpp new file mode 100644 index 0000000000..d9ab5f1c6c --- /dev/null +++ b/src/mbgl/map/tile.hpp @@ -0,0 +1,42 @@ +#ifndef MBGL_MAP_TILE +#define MBGL_MAP_TILE + +#include <mbgl/util/mat4.hpp> +#include <mbgl/util/noncopyable.hpp> +#include <mbgl/util/ptr.hpp> +#include <mbgl/map/tile_id.hpp> + +#include <bitset> +#include <string> + +namespace mbgl { + +class TileData; +struct box; + +struct ClipID { + inline ClipID() {} + inline ClipID(const std::string &mask_, const std::string &reference_) : mask(mask_), reference(reference_) {} + + std::bitset<8> mask; + std::bitset<8> reference; + + inline bool operator==(const ClipID &other) const { + return mask == other.mask && reference == other.reference; + } +}; + +class Tile : private util::noncopyable { +public: + explicit Tile(const TileID& id_) + : id(id_) {} + + const TileID id; + ClipID clip; + mat4 matrix; + util::ptr<TileData> data; +}; + +} + +#endif diff --git a/src/mbgl/map/tile_data.cpp b/src/mbgl/map/tile_data.cpp index 1832bd8f0c..fdec759938 100644 --- a/src/mbgl/map/tile_data.cpp +++ b/src/mbgl/map/tile_data.cpp @@ -1,18 +1,14 @@ #include <mbgl/map/tile_data.hpp> -#include <mbgl/map/map.hpp> #include <mbgl/map/environment.hpp> -#include <mbgl/style/style_source.hpp> +#include <mbgl/map/source.hpp> -#include <mbgl/util/token.hpp> -#include <mbgl/util/string.hpp> -#include <mbgl/util/mapbox.hpp> #include <mbgl/storage/file_source.hpp> #include <mbgl/util/uv_detail.hpp> #include <mbgl/platform/log.hpp> using namespace mbgl; -TileData::TileData(Tile::ID const& id_, const SourceInfo& source_) +TileData::TileData(const TileID& id_, const SourceInfo& source_) : id(id_), name(id), state(State::initial), @@ -34,25 +30,7 @@ const std::string TileData::toString() const { } void TileData::request(uv::worker &worker, float pixelRatio, std::function<void()> callback) { - if (source.tiles.empty()) - return; - - std::string url = source.tiles[(id.x + id.y) % source.tiles.size()]; - url = util::mapbox::normalizeTileURL(url, source.url, source.type); - url = util::replaceTokens(url, [&](const std::string &token) -> std::string { - if (token == "z") return util::toString(id.z); - if (token == "x") return util::toString(id.x); - if (token == "y") return util::toString(id.y); - if (token == "prefix") { - std::string prefix { 2 }; - prefix[0] = "0123456789abcdef"[id.x % 16]; - prefix[1] = "0123456789abcdef"[id.y % 16]; - return prefix; - } - if (token == "ratio") return pixelRatio > 1.0 ? "@2x" : ""; - return ""; - }); - + std::string url = source.tileURL(id, pixelRatio); state = State::loading; std::weak_ptr<TileData> weak_tile = shared_from_this(); diff --git a/src/mbgl/map/tile_data.hpp b/src/mbgl/map/tile_data.hpp index a5598fee3b..6fbc9ec3fb 100644 --- a/src/mbgl/map/tile_data.hpp +++ b/src/mbgl/map/tile_data.hpp @@ -1,7 +1,7 @@ #ifndef MBGL_MAP_TILE_DATA #define MBGL_MAP_TILE_DATA -#include <mbgl/map/tile.hpp> +#include <mbgl/map/tile_id.hpp> #include <mbgl/renderer/debug_bucket.hpp> #include <mbgl/geometry/debug_font_buffer.hpp> @@ -38,7 +38,7 @@ public: obsolete }; - TileData(Tile::ID const &id, const SourceInfo &); + TileData(const TileID&, const SourceInfo&); ~TileData(); void request(uv::worker&, float pixelRatio, std::function<void ()> callback); @@ -55,7 +55,7 @@ public: virtual void render(Painter &painter, const StyleLayer &layer_desc, const mat4 &matrix) = 0; virtual bool hasData(StyleLayer const &layer_desc) const = 0; - const Tile::ID id; + const TileID id; const std::string name; std::atomic<State> state; diff --git a/src/mbgl/map/tile_id.cpp b/src/mbgl/map/tile_id.cpp new file mode 100644 index 0000000000..518ee14c42 --- /dev/null +++ b/src/mbgl/map/tile_id.cpp @@ -0,0 +1,52 @@ +#include <mbgl/map/tile_id.hpp> +#include <mbgl/util/string.hpp> + +#include <cassert> + +namespace mbgl { + +TileID TileID::parent(int8_t parent_z) const { + assert(parent_z < z); + int32_t dim = std::pow(2, z - parent_z); + return TileID{ + parent_z, + (x >= 0 ? x : x - dim + 1) / dim, + y / dim + }; +} + +std::forward_list<TileID> TileID::children(int32_t child_z) const { + assert(child_z > z); + int32_t factor = std::pow(2, child_z - z); + + std::forward_list<TileID> child_ids; + for (int32_t ty = y * factor, y_max = (y + 1) * factor; ty < y_max; ++ty) { + for (int32_t tx = x * factor, x_max = (x + 1) * factor; tx < x_max; ++tx) { + child_ids.emplace_front(child_z, tx, ty); + } + } + return child_ids; +} + +TileID TileID::normalized() const { + int32_t dim = std::pow(2, z); + int32_t nx = x, ny = y; + while (nx < 0) nx += dim; + while (nx >= dim) nx -= dim; + return TileID { z, nx, ny }; +} + +bool TileID::isChildOf(const TileID &parent_id) const { + if (parent_id.z >= z || parent_id.w != w) { + return false; + } + int32_t scale = std::pow(2, z - parent_id.z); + return parent_id.x == ((x < 0 ? x - scale + 1 : x) / scale) && + parent_id.y == y / scale; +} + +TileID::operator std::string() const { + return util::toString(z) + "/" + util::toString(x) + "/" + util::toString(y); +} + +} diff --git a/src/mbgl/map/tile_id.hpp b/src/mbgl/map/tile_id.hpp new file mode 100644 index 0000000000..056fcdbfa5 --- /dev/null +++ b/src/mbgl/map/tile_id.hpp @@ -0,0 +1,55 @@ +#ifndef MBGL_MAP_TILE_ID +#define MBGL_MAP_TILE_ID + +#include <cstdint> +#include <cmath> +#include <string> +#include <functional> +#include <forward_list> + +namespace mbgl { + +class TileID { +public: + const int16_t w = 0; + const int8_t z = 0; + const int32_t x = 0, y = 0; + + inline explicit TileID(int8_t z_, int32_t x_, int32_t y_) + : w((x_ < 0 ? x_ - (1 << z_) + 1 : x_) / (1 << z_)), z(z_), x(x_), y(y_) {} + + inline uint64_t to_uint64() const { + return ((std::pow(2, z) * y + x) * 32) + z; + } + + struct Hash { + std::size_t operator()(const TileID& id) const { + return std::hash<uint64_t>()(id.to_uint64()); + } + }; + + inline bool operator==(const TileID& rhs) const { + return w == rhs.w && z == rhs.z && x == rhs.x && y == rhs.y; + } + + inline bool operator!=(const TileID& rhs) const { + return !operator==(rhs); + } + + inline bool operator<(const TileID& rhs) const { + if (w != rhs.w) return w < rhs.w; + if (z != rhs.z) return z < rhs.z; + if (x != rhs.x) return x < rhs.x; + return y < rhs.y; + } + + TileID parent(int8_t z) const; + TileID normalized() const; + std::forward_list<TileID> children(int32_t z) const; + bool isChildOf(const TileID&) const; + operator std::string() const; +}; + +} + +#endif diff --git a/src/mbgl/map/tile_parser.cpp b/src/mbgl/map/tile_parser.cpp index bc6de40565..275b77be91 100644 --- a/src/mbgl/map/tile_parser.cpp +++ b/src/mbgl/map/tile_parser.cpp @@ -3,7 +3,7 @@ #include <mbgl/platform/log.hpp> #include <mbgl/style/style.hpp> #include <mbgl/style/style_layer.hpp> -#include <mbgl/style/style_source.hpp> +#include <mbgl/map/source.hpp> #include <mbgl/renderer/fill_bucket.hpp> #include <mbgl/renderer/line_bucket.hpp> #include <mbgl/renderer/symbol_bucket.hpp> diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 32ce184fa9..507e63f67e 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -1,4 +1,5 @@ #include <mbgl/map/transform_state.hpp> +#include <mbgl/map/tile_id.hpp> #include <mbgl/util/projection.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/box.hpp> @@ -7,7 +8,7 @@ using namespace mbgl; #pragma mark - Matrix -void TransformState::matrixFor(mat4& matrix, const Tile::ID& id) const { +void TransformState::matrixFor(mat4& matrix, const TileID& id) const { const double tile_scale = std::pow(2, id.z); const double tile_size = scale * util::tileSize / tile_scale; diff --git a/src/mbgl/map/vector_tile_data.cpp b/src/mbgl/map/vector_tile_data.cpp index 3bed7a1c32..39c2d9fce3 100644 --- a/src/mbgl/map/vector_tile_data.cpp +++ b/src/mbgl/map/vector_tile_data.cpp @@ -3,14 +3,14 @@ #include <mbgl/util/std.hpp> #include <mbgl/style/style_layer.hpp> #include <mbgl/style/style_bucket.hpp> -#include <mbgl/style/style_source.hpp> +#include <mbgl/map/source.hpp> #include <mbgl/geometry/glyph_atlas.hpp> #include <mbgl/platform/log.hpp> #include <mbgl/util/pbf.hpp> using namespace mbgl; -VectorTileData::VectorTileData(Tile::ID const& id_, +VectorTileData::VectorTileData(const TileID& id_, float mapMaxZoom, util::ptr<Style> style_, GlyphAtlas& glyphAtlas_, diff --git a/src/mbgl/map/vector_tile_data.hpp b/src/mbgl/map/vector_tile_data.hpp index 7ecad4ccec..4e2f252f85 100644 --- a/src/mbgl/map/vector_tile_data.hpp +++ b/src/mbgl/map/vector_tile_data.hpp @@ -1,7 +1,6 @@ #ifndef MBGL_MAP_VECTOR_TILE_DATA #define MBGL_MAP_VECTOR_TILE_DATA -#include <mbgl/map/tile.hpp> #include <mbgl/map/tile_data.hpp> #include <mbgl/geometry/elements_buffer.hpp> #include <mbgl/geometry/fill_buffer.hpp> @@ -30,7 +29,7 @@ class VectorTileData : public TileData { friend class TileParser; public: - VectorTileData(Tile::ID const&, + VectorTileData(const TileID&, float mapMaxZoom, util::ptr<Style>, GlyphAtlas&, diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp index f59ae65be0..a7b0f61a3b 100644 --- a/src/mbgl/renderer/bucket.hpp +++ b/src/mbgl/renderer/bucket.hpp @@ -1,20 +1,18 @@ #ifndef MBGL_RENDERER_BUCKET #define MBGL_RENDERER_BUCKET -#include <mbgl/map/tile.hpp> #include <mbgl/util/noncopyable.hpp> - -#include <string> +#include <mbgl/util/mat4.hpp> namespace mbgl { class Painter; class StyleLayer; +class TileID; class Bucket : private util::noncopyable { public: - virtual void render(Painter &painter, const StyleLayer &layer_desc, const Tile::ID &id, - const mat4 &matrix) = 0; + virtual void render(Painter&, const StyleLayer&, const TileID&, const mat4&) = 0; virtual bool hasData() const = 0; virtual ~Bucket() {} diff --git a/src/mbgl/renderer/debug_bucket.cpp b/src/mbgl/renderer/debug_bucket.cpp index 6104e2456b..ed03458dad 100644 --- a/src/mbgl/renderer/debug_bucket.cpp +++ b/src/mbgl/renderer/debug_bucket.cpp @@ -12,7 +12,7 @@ DebugBucket::DebugBucket(DebugFontBuffer& fontBuffer_) } void DebugBucket::render(Painter &painter, const StyleLayer & /*layer_desc*/, - const Tile::ID & /*id*/, const mat4 &matrix) { + const TileID & /*id*/, const mat4 &matrix) { painter.renderDebugText(*this, matrix); } diff --git a/src/mbgl/renderer/debug_bucket.hpp b/src/mbgl/renderer/debug_bucket.hpp index d23248841b..074d1d3991 100644 --- a/src/mbgl/renderer/debug_bucket.hpp +++ b/src/mbgl/renderer/debug_bucket.hpp @@ -19,7 +19,7 @@ class DebugBucket : public Bucket { public: DebugBucket(DebugFontBuffer& fontBuffer); - void render(Painter &painter, const StyleLayer &layer_desc, const Tile::ID &id, + void render(Painter &painter, const StyleLayer &layer_desc, const TileID &id, const mat4 &matrix) override; bool hasData() const override; diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp index c3e04db067..f5726690b1 100644 --- a/src/mbgl/renderer/fill_bucket.cpp +++ b/src/mbgl/renderer/fill_bucket.cpp @@ -195,7 +195,7 @@ void FillBucket::tessellate() { lineGroup.vertex_length += total_vertex_count; } -void FillBucket::render(Painter &painter, const StyleLayer &layer_desc, const Tile::ID &id, +void FillBucket::render(Painter &painter, const StyleLayer &layer_desc, const TileID &id, const mat4 &matrix) { painter.renderFill(*this, layer_desc, id, matrix); } diff --git a/src/mbgl/renderer/fill_bucket.hpp b/src/mbgl/renderer/fill_bucket.hpp index 5a51f17c4e..d28f849a2c 100644 --- a/src/mbgl/renderer/fill_bucket.hpp +++ b/src/mbgl/renderer/fill_bucket.hpp @@ -37,7 +37,7 @@ public: LineElementsBuffer &lineElementsBuffer); ~FillBucket() override; - void render(Painter &painter, const StyleLayer &layer_desc, const Tile::ID &id, + void render(Painter &painter, const StyleLayer &layer_desc, const TileID &id, const mat4 &matrix) override; bool hasData() const override; diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp index 5404398ca0..4e09b74640 100644 --- a/src/mbgl/renderer/line_bucket.cpp +++ b/src/mbgl/renderer/line_bucket.cpp @@ -326,7 +326,7 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) { } } -void LineBucket::render(Painter &painter, const StyleLayer &layer_desc, const Tile::ID &id, +void LineBucket::render(Painter &painter, const StyleLayer &layer_desc, const TileID &id, const mat4 &matrix) { painter.renderLine(*this, layer_desc, id, matrix); } diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp index e6e5f66d57..d70801e0bf 100644 --- a/src/mbgl/renderer/line_bucket.hpp +++ b/src/mbgl/renderer/line_bucket.hpp @@ -32,7 +32,7 @@ public: PointElementsBuffer &pointElementsBuffer); ~LineBucket() override; - void render(Painter &painter, const StyleLayer &layer_desc, const Tile::ID &id, + void render(Painter &painter, const StyleLayer &layer_desc, const TileID &id, const mat4 &matrix) override; bool hasData() const override; diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index f923cc8722..c05aab0ae5 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -10,6 +10,7 @@ #include <mbgl/util/mat3.hpp> #include <mbgl/geometry/sprite_atlas.hpp> #include <mbgl/map/source.hpp> +#include <mbgl/map/tile.hpp> #if defined(DEBUG) #include <mbgl/util/stopwatch.hpp> @@ -215,19 +216,25 @@ void Painter::prepareTile(const Tile& tile) { MBGL_CHECK_ERROR(glStencilFunc(GL_EQUAL, ref, mask)); } -void Painter::render(const Style& style, const std::set<util::ptr<StyleSource>>& sources, - TransformState state_, TimePoint time) { +void Painter::render(const Style& style, TransformState state_, TimePoint time) { state = state_; clear(); resize(); changeMatrix(); + std::set<Source*> sources; + for (const auto& source : style.sources) { + if (source->enabled) { + sources.insert(source.get()); + } + } + // Update all clipping IDs. ClipIDGenerator generator; for (const auto& source : sources) { - generator.update(source->source->getLoadedTiles()); - source->source->updateMatrices(projMatrix, state); + generator.update(source->getLoadedTiles()); + source->updateMatrices(projMatrix, state); } drawClippingMasks(sources); @@ -280,7 +287,7 @@ void Painter::render(const Style& style, const std::set<util::ptr<StyleSource>>& // When only rendering layers via the stylesheet, it's possible that we don't // ever visit a tile during rendering. for (const auto& source : sources) { - source->source->finishRender(*this); + source->finishRender(*this); } } @@ -302,18 +309,11 @@ void Painter::renderLayer(const StyleLayer &layer_desc) { return; } - if (!layer_desc.bucket->style_source) { + if (!layer_desc.bucket->source) { Log::Warning(Event::Render, "can't find source for layer '%s'", layer_desc.id.c_str()); return; } - StyleSource const& style_source = *layer_desc.bucket->style_source; - - // Skip this layer if there is no data. - if (!style_source.source) { - return; - } - // Skip this layer if it's outside the range of min/maxzoom. // This may occur when there /is/ a bucket created for this layer, but the min/max-zoom // is set to a fractional value, or value that is larger than the source maxzoom. @@ -350,7 +350,7 @@ void Painter::renderLayer(const StyleLayer &layer_desc) { StyleLayerTypeClass(layer_desc.type).c_str()); } - style_source.source->render(*this, layer_desc); + layer_desc.bucket->source->render(*this, layer_desc); } } @@ -443,7 +443,7 @@ void Painter::renderBackground(const StyleLayer &layer_desc) { MBGL_CHECK_ERROR(glEnable(GL_STENCIL_TEST)); } -mat4 Painter::translatedMatrix(const mat4& matrix, const std::array<float, 2> &translation, const Tile::ID &id, TranslateAnchorType anchor) { +mat4 Painter::translatedMatrix(const mat4& matrix, const std::array<float, 2> &translation, const TileID &id, TranslateAnchorType anchor) { if (translation[0] == 0 && translation[1] == 0) { return matrix; } else { diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 315059073d..cf01c03918 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -42,7 +42,6 @@ class SpriteAtlas; class GlyphAtlas; class LineAtlas; class Source; -class StyleSource; class FillBucket; class LineBucket; @@ -55,6 +54,7 @@ struct RasterProperties; class LayerDescription; class RasterTileData; +struct ClipID; class Painter : private util::noncopyable { public: @@ -76,7 +76,6 @@ public: void changeMatrix(); void render(const Style& style, - const std::set<util::ptr<StyleSource>>& sources, TransformState state, TimePoint time); @@ -93,10 +92,10 @@ public: void renderDebugText(DebugBucket& bucket, const mat4 &matrix); void renderDebugText(const std::vector<std::string> &strings); - void renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const Tile::ID& id, const mat4 &matrix); - void renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const Tile::ID& id, const mat4 &matrix); - void renderSymbol(SymbolBucket& bucket, const StyleLayer &layer_desc, const Tile::ID& id, const mat4 &matrix); - void renderRaster(RasterBucket& bucket, const StyleLayer &layer_desc, const Tile::ID& id, const mat4 &matrix); + void renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix); + void renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix); + void renderSymbol(SymbolBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix); + void renderRaster(RasterBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix); void renderBackground(const StyleLayer &layer_desc); float saturationFactor(float saturation); @@ -107,7 +106,7 @@ public: void renderPrerenderedTexture(RasterBucket &bucket, const mat4 &matrix, const RasterProperties& properties); - void createPrerendered(RasterBucket& bucket, const StyleLayer &layer_desc, const Tile::ID& id); + void createPrerendered(RasterBucket& bucket, const StyleLayer &layer_desc, const TileID& id); void resize(); @@ -121,7 +120,7 @@ public: // Configures the painter strata that is used for early z-culling of fragments. void setStrata(float strata); - void drawClippingMasks(const std::set<util::ptr<StyleSource>> &sources); + void drawClippingMasks(const std::set<Source*>&); void drawClippingMask(const mat4& matrix, const ClipID& clip); void resetFramebuffer(); @@ -135,13 +134,13 @@ public: private: void setupShaders(); void deleteShaders(); - mat4 translatedMatrix(const mat4& matrix, const std::array<float, 2> &translation, const Tile::ID &id, TranslateAnchorType anchor); + mat4 translatedMatrix(const mat4& matrix, const std::array<float, 2> &translation, const TileID &id, TranslateAnchorType anchor); void prepareTile(const Tile& tile); template <typename BucketProperties, typename StyleProperties> void renderSDF(SymbolBucket &bucket, - const Tile::ID &id, + const TileID &id, const mat4 &matrixSymbol, const BucketProperties& bucketProperties, const StyleProperties& styleProperties, diff --git a/src/mbgl/renderer/painter_clipping.cpp b/src/mbgl/renderer/painter_clipping.cpp index 574cbe50af..8b97bb5b69 100644 --- a/src/mbgl/renderer/painter_clipping.cpp +++ b/src/mbgl/renderer/painter_clipping.cpp @@ -1,12 +1,13 @@ #include <mbgl/renderer/painter.hpp> #include <mbgl/renderer/fill_bucket.hpp> #include <mbgl/map/map.hpp> +#include <mbgl/map/tile.hpp> #include <mbgl/map/source.hpp> #include <mbgl/util/clip_ids.hpp> using namespace mbgl; -void Painter::drawClippingMasks(const std::set<util::ptr<StyleSource>> &sources) { +void Painter::drawClippingMasks(const std::set<Source*>& sources) { gl::group group("clipping masks"); useProgram(plainShader->program); @@ -18,7 +19,7 @@ void Painter::drawClippingMasks(const std::set<util::ptr<StyleSource>> &sources) coveringPlainArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0)); for (const auto& source : sources) { - source->source->drawClippingMasks(*this); + source->drawClippingMasks(*this); } MBGL_CHECK_ERROR(glEnable(GL_DEPTH_TEST)); diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp index 7f9c990776..2931473283 100644 --- a/src/mbgl/renderer/painter_debug.cpp +++ b/src/mbgl/renderer/painter_debug.cpp @@ -1,6 +1,7 @@ #include <mbgl/renderer/painter.hpp> #include <mbgl/renderer/debug_bucket.hpp> #include <mbgl/map/map.hpp> +#include <mbgl/map/tile.hpp> #include <mbgl/util/string.hpp> using namespace mbgl; diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp index cadc9ab148..8025cf3469 100644 --- a/src/mbgl/renderer/painter_fill.cpp +++ b/src/mbgl/renderer/painter_fill.cpp @@ -11,7 +11,7 @@ using namespace mbgl; -void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const Tile::ID& id, const mat4 &matrix) { +void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix) { // Abort early. if (!bucket.hasData()) return; diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp index a19d9873af..2f8c3face3 100644 --- a/src/mbgl/renderer/painter_line.cpp +++ b/src/mbgl/renderer/painter_line.cpp @@ -10,7 +10,7 @@ using namespace mbgl; -void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const Tile::ID& id, const mat4 &matrix) { +void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix) { // Abort early. if (pass == RenderPass::Opaque) return; if (!bucket.hasData()) return; diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp index 72d15aabd0..5fac248ee6 100644 --- a/src/mbgl/renderer/painter_raster.cpp +++ b/src/mbgl/renderer/painter_raster.cpp @@ -7,7 +7,7 @@ using namespace mbgl; -void Painter::renderRaster(RasterBucket& bucket, const StyleLayer &layer_desc, const Tile::ID&, const mat4 &matrix) { +void Painter::renderRaster(RasterBucket& bucket, const StyleLayer &layer_desc, const TileID&, const mat4 &matrix) { if (pass != RenderPass::Translucent) return; const RasterProperties &properties = layer_desc.getProperties<RasterProperties>(); diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp index e1b4d88193..2785e8bae3 100644 --- a/src/mbgl/renderer/painter_symbol.cpp +++ b/src/mbgl/renderer/painter_symbol.cpp @@ -13,7 +13,7 @@ using namespace mbgl; template <typename BucketProperties, typename StyleProperties> void Painter::renderSDF(SymbolBucket &bucket, - const Tile::ID &id, + const TileID &id, const mat4 &matrix, const BucketProperties& bucketProperties, const StyleProperties& styleProperties, @@ -112,7 +112,7 @@ void Painter::renderSDF(SymbolBucket &bucket, } } -void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, const Tile::ID &id, const mat4 &matrix) { +void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, const TileID &id, const mat4 &matrix) { // Abort early. if (pass == RenderPass::Opaque) { return; diff --git a/src/mbgl/renderer/raster_bucket.cpp b/src/mbgl/renderer/raster_bucket.cpp index b16303c84f..b00933d24b 100644 --- a/src/mbgl/renderer/raster_bucket.cpp +++ b/src/mbgl/renderer/raster_bucket.cpp @@ -8,7 +8,7 @@ RasterBucket::RasterBucket(TexturePool& texturePool, const StyleLayoutRaster& la raster(texturePool) { } -void RasterBucket::render(Painter &painter, const StyleLayer &layer_desc, const Tile::ID &id, +void RasterBucket::render(Painter &painter, const StyleLayer &layer_desc, const TileID &id, const mat4 &matrix) { painter.renderRaster(*this, layer_desc, id, matrix); } diff --git a/src/mbgl/renderer/raster_bucket.hpp b/src/mbgl/renderer/raster_bucket.hpp index 168685b163..22a151cf7d 100644 --- a/src/mbgl/renderer/raster_bucket.hpp +++ b/src/mbgl/renderer/raster_bucket.hpp @@ -18,7 +18,7 @@ class RasterBucket : public Bucket { public: RasterBucket(TexturePool&, const StyleLayoutRaster&); - void render(Painter &painter, const StyleLayer &layer_desc, const Tile::ID &id, + void render(Painter &painter, const StyleLayer &layer_desc, const TileID &id, const mat4 &matrix) override; bool hasData() const override; diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index d5940eccf1..c0c732084e 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -30,7 +30,7 @@ SymbolBucket::~SymbolBucket() { // Do not remove. header file only contains forward definitions to unique pointers. } -void SymbolBucket::render(Painter &painter, const StyleLayer &layer_desc, const Tile::ID &id, +void SymbolBucket::render(Painter &painter, const StyleLayer &layer_desc, const TileID &id, const mat4 &matrix) { painter.renderSymbol(*this, layer_desc, id, matrix); } diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp index 94d8ce45c7..9ddd653c5d 100644 --- a/src/mbgl/renderer/symbol_bucket.hpp +++ b/src/mbgl/renderer/symbol_bucket.hpp @@ -55,7 +55,7 @@ public: SymbolBucket(Collision &collision); ~SymbolBucket() override; - void render(Painter &painter, const StyleLayer &layer_desc, const Tile::ID &id, + void render(Painter &painter, const StyleLayer &layer_desc, const TileID &id, const mat4 &matrix) override; bool hasData() const override; bool hasTextData() const; diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 4923e59da4..2fb3ccabcb 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -1,5 +1,6 @@ #include <mbgl/style/style.hpp> #include <mbgl/map/sprite.hpp> +#include <mbgl/map/source.hpp> #include <mbgl/style/style_layer.hpp> #include <mbgl/style/style_parser.hpp> #include <mbgl/style/style_bucket.hpp> @@ -36,10 +37,17 @@ void Style::cascade(const std::vector<std::string>& classes) { void Style::recalculate(float z, TimePoint now) { uv::writelock lock(mtx); + for (const auto& source : sources) { + source->enabled = false; + } + zoomHistory.update(z, now); for (const auto& layer : layers) { layer->updateProperties(z, now, zoomHistory); + if (layer->bucket && layer->bucket->source) { + layer->bucket->source->enabled = true; + } } } @@ -73,6 +81,7 @@ void Style::loadJSON(const uint8_t *const data) { StyleParser parser; parser.parse(doc); + sources = parser.getSources(); layers = parser.getLayers(); sprite_url = parser.getSprite(); glyph_url = parser.getGlyphURL(); diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index 5a4febaab3..dde21173f3 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -15,6 +15,7 @@ namespace mbgl { +class Source; class StyleLayer; class Style : public util::noncopyable { @@ -32,6 +33,7 @@ public: const std::string &getSpriteURL() const; + std::vector<util::ptr<Source>> sources; std::vector<util::ptr<StyleLayer>> layers; std::string glyph_url; std::string base; diff --git a/src/mbgl/style/style_bucket.hpp b/src/mbgl/style/style_bucket.hpp index b79b324b0c..e29000e5ad 100644 --- a/src/mbgl/style/style_bucket.hpp +++ b/src/mbgl/style/style_bucket.hpp @@ -10,7 +10,7 @@ namespace mbgl { -class StyleSource; +class Source; class StyleBucket : public util::noncopyable { public: @@ -20,7 +20,7 @@ public: const StyleLayerType type; std::string name; - util::ptr<StyleSource> style_source; + util::ptr<Source> source; std::string source_layer; FilterExpression filter; ClassProperties layout; diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp index ca547b5d35..afed2eeee6 100644 --- a/src/mbgl/style/style_parser.cpp +++ b/src/mbgl/style/style_parser.cpp @@ -1,5 +1,5 @@ -#include <mbgl/style/style_source.hpp> #include <mbgl/style/style_parser.hpp> +#include <mbgl/map/source.hpp> #include <mbgl/style/style_layer.hpp> #include <mbgl/map/annotation.hpp> #include <mbgl/util/constants.hpp> @@ -59,11 +59,11 @@ void StyleParser::parse(JSVal document) { iconOverlap.AddMember("icon-allow-overlap", true, d.GetAllocator()); parseLayout(iconOverlap, pointBucket); - SourceInfo& info = sources.emplace(id, std::make_shared<StyleSource>()).first->second->info; - info.type = SourceType::Annotations; - - auto source_it = sources.find(id); - pointBucket->style_source = source_it->second; + util::ptr<Source> source = std::make_shared<Source>(); + sourcesMap.emplace(id, source); + sources.emplace_back(source); + source->info.type = SourceType::Annotations; + pointBucket->source = source; annotations->bucket = pointBucket; // // end point annotations @@ -218,12 +218,13 @@ void StyleParser::parseSources(JSVal value) { rapidjson::Value::ConstMemberIterator itr = value.MemberBegin(); for (; itr != value.MemberEnd(); ++itr) { std::string name { itr->name.GetString(), itr->name.GetStringLength() }; - SourceInfo& info = sources.emplace(name, std::make_shared<StyleSource>()).first->second->info; - - parseRenderProperty<SourceTypeClass>(itr->value, info.type, "type"); - parseRenderProperty(itr->value, info.url, "url"); - parseRenderProperty(itr->value, info.tile_size, "tileSize"); - info.parseTileJSONProperties(itr->value); + util::ptr<Source> source = std::make_shared<Source>(); + parseRenderProperty<SourceTypeClass>(itr->value, source->info.type, "type"); + parseRenderProperty(itr->value, source->info.url, "url"); + parseRenderProperty(itr->value, source->info.tile_size, "tileSize"); + source->info.parseTileJSONProperties(itr->value); + sources.emplace_back(source); + sourcesMap.emplace(name, source); } } else { Log::Warning(Event::ParseStyle, "sources must be an object"); @@ -939,9 +940,9 @@ void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) { JSVal value_source = replaceConstant(value["source"]); if (value_source.IsString()) { const std::string source_name = { value_source.GetString(), value_source.GetStringLength() }; - auto source_it = sources.find(source_name); - if (source_it != sources.end()) { - bucket->style_source = source_it->second; + auto source_it = sourcesMap.find(source_name); + if (source_it != sourcesMap.end()) { + bucket->source = source_it->second; } else { Log::Warning(Event::ParseStyle, "can't find source '%s' required for layer '%s'", source_name.c_str(), layer->id.c_str()); } diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/style_parser.hpp index 66c536e7c5..6f970d21eb 100644 --- a/src/mbgl/style/style_parser.hpp +++ b/src/mbgl/style/style_parser.hpp @@ -3,7 +3,7 @@ #include <rapidjson/document.h> #include <mbgl/style/style.hpp> -#include <mbgl/style/style_source.hpp> +#include <mbgl/map/source.hpp> #include <mbgl/style/filter_expression.hpp> #include <mbgl/style/class_properties.hpp> #include <mbgl/style/style_bucket.hpp> @@ -17,6 +17,7 @@ namespace mbgl { enum class ClassID : uint32_t; class StyleLayer; +class Source; class StyleParser { public: @@ -26,6 +27,10 @@ public: void parse(JSVal document); + std::vector<util::ptr<Source>> getSources() { + return sources; + } + std::vector<util::ptr<StyleLayer>> getLayers() { return layers; } @@ -90,12 +95,10 @@ private: private: std::unordered_map<std::string, const rapidjson::Value *> constants; - std::unordered_map<std::string, const util::ptr<StyleSource>> sources; - - // This stores the root layer. + std::vector<util::ptr<Source>> sources; std::vector<util::ptr<StyleLayer>> layers; - // This maps ids to Layer objects, with all items being at the root level. + std::unordered_map<std::string, const util::ptr<Source>> sourcesMap; std::unordered_map<std::string, std::pair<JSVal, util::ptr<StyleLayer>>> layersMap; // Store a stack of layers we're parsing right now. This is to prevent reference cycles. diff --git a/src/mbgl/style/style_source.cpp b/src/mbgl/style/style_source.cpp deleted file mode 100644 index f46a6fb09b..0000000000 --- a/src/mbgl/style/style_source.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include <mbgl/style/style_source.hpp> -#include <mbgl/platform/platform.hpp> -#include <mbgl/platform/log.hpp> - -#include <limits> - -namespace mbgl { - -void parse(const rapidjson::Value& value, std::vector<std::string>& target, const char *name) { - if (!value.HasMember(name)) - return; - - const rapidjson::Value& property = value[name]; - if (!property.IsArray()) - return; - - for (rapidjson::SizeType i = 0; i < property.Size(); i++) - if (!property[i].IsString()) - return; - - for (rapidjson::SizeType i = 0; i < property.Size(); i++) - target.emplace_back(std::string(property[i].GetString(), property[i].GetStringLength())); -} - -void parse(const rapidjson::Value& value, std::string& target, const char* name) { - if (!value.HasMember(name)) - return; - - const rapidjson::Value& property = value[name]; - if (!property.IsString()) - return; - - target = { property.GetString(), property.GetStringLength() }; -} - -void parse(const rapidjson::Value& value, uint16_t& target, const char* name) { - if (!value.HasMember(name)) - return; - - const rapidjson::Value& property = value[name]; - if (!property.IsUint()) - return; - - unsigned int uint = property.GetUint(); - if (uint > std::numeric_limits<uint16_t>::max()) - return; - - target = uint; -} - -template <size_t N> -void parse(const rapidjson::Value& value, std::array<float, N>& target, const char* name) { - if (!value.HasMember(name)) - return; - - const rapidjson::Value& property = value[name]; - if (!property.IsArray() || property.Size() != N) - return; - - for (rapidjson::SizeType i = 0; i < property.Size(); i++) - if (!property[i].IsNumber()) - return; - - for (rapidjson::SizeType i = 0; i < property.Size(); i++) - target[i] = property[i].GetDouble(); -} - -void SourceInfo::parseTileJSONProperties(const rapidjson::Value& value) { - parse(value, tiles, "tiles"); - parse(value, min_zoom, "minzoom"); - parse(value, max_zoom, "maxzoom"); - parse(value, attribution, "attribution"); - parse(value, center, "center"); - parse(value, bounds, "bounds"); -} - -} diff --git a/src/mbgl/style/style_source.hpp b/src/mbgl/style/style_source.hpp deleted file mode 100644 index 8c7d028880..0000000000 --- a/src/mbgl/style/style_source.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef MBGL_STYLE_STYLE_SOURCE -#define MBGL_STYLE_STYLE_SOURCE - -#include <mbgl/style/types.hpp> -#include <mbgl/util/ptr.hpp> -#include <mbgl/util/noncopyable.hpp> -#include <rapidjson/document.h> - -#include <vector> -#include <string> - -namespace mbgl { - -class Source; - -class SourceInfo : private util::noncopyable { -public: - SourceType type = SourceType::Vector; - std::string url; - std::vector<std::string> tiles; - uint16_t tile_size = 512; - uint16_t min_zoom = 0; - uint16_t max_zoom = 22; - std::string attribution; - std::array<float, 3> center = {{0, 0, 0}}; - std::array<float, 4> bounds = {{-180, -90, 180, 90}}; - - void parseTileJSONProperties(const rapidjson::Value&); -}; - - -class StyleSource : private util::noncopyable { -public: - SourceInfo info; - bool enabled = false; - util::ptr<Source> source; -}; - -} - -#endif diff --git a/src/mbgl/util/clip_ids.cpp b/src/mbgl/util/clip_ids.cpp index e7833b679f..42a1627b6e 100644 --- a/src/mbgl/util/clip_ids.cpp +++ b/src/mbgl/util/clip_ids.cpp @@ -1,8 +1,8 @@ #include <mbgl/util/clip_ids.hpp> -#include <mbgl/map/tile.hpp> #include <mbgl/platform/log.hpp> #include <mbgl/util/math.hpp> +#include <mbgl/map/tile.hpp> #include <list> #include <vector> @@ -15,7 +15,7 @@ namespace mbgl { ClipIDGenerator::Leaf::Leaf(Tile &tile_) : tile(tile_) {} -void ClipIDGenerator::Leaf::add(const Tile::ID &p) { +void ClipIDGenerator::Leaf::add(const TileID &p) { if (p.isChildOf(tile.id)) { // Ensure that no already present child is a parent of the new p. for (const auto& child : children) { diff --git a/src/mbgl/util/clip_ids.hpp b/src/mbgl/util/clip_ids.hpp index 5855b16af7..154003f280 100644 --- a/src/mbgl/util/clip_ids.hpp +++ b/src/mbgl/util/clip_ids.hpp @@ -1,7 +1,8 @@ #ifndef MBGL_UTIL_CLIP_IDS #define MBGL_UTIL_CLIP_IDS -#include <mbgl/map/tile.hpp> +#include <mbgl/map/tile_id.hpp> + #include <list> #include <set> #include <vector> @@ -10,15 +11,17 @@ namespace mbgl { +class Tile; + class ClipIDGenerator { private: struct Leaf { Leaf(Tile &tile); - void add(const Tile::ID &p); + void add(const TileID &p); bool operator==(const Leaf &other) const; Tile &tile; - std::forward_list<Tile::ID> children; + std::forward_list<TileID> children; }; typedef std::vector<Leaf> Pool; diff --git a/src/mbgl/util/tile_cover.cpp b/src/mbgl/util/tile_cover.cpp new file mode 100644 index 0000000000..5185e78d92 --- /dev/null +++ b/src/mbgl/util/tile_cover.cpp @@ -0,0 +1,93 @@ +#include <mbgl/util/tile_cover.hpp> +#include <mbgl/util/vec.hpp> +#include <mbgl/util/box.hpp> + +namespace mbgl { + +// Taken from polymaps src/Layer.js +// https://github.com/simplegeo/polymaps/blob/master/src/Layer.js#L333-L383 + +struct edge { + double x0 = 0, y0 = 0; + double x1 = 0, y1 = 0; + double dx = 0, dy = 0; + + edge(vec2<double> a, vec2<double> b) { + if (a.y > b.y) { std::swap(a, b); } + x0 = a.x; + y0 = a.y; + x1 = b.x; + y1 = b.y; + dx = b.x - a.x; + dy = b.y - a.y; + } +}; + +typedef const std::function<void(int32_t x0, int32_t x1, int32_t y)> ScanLine; + +// scan-line conversion +static void scanSpans(edge e0, edge e1, int32_t ymin, int32_t ymax, ScanLine scanLine) { + double y0 = std::fmax(ymin, std::floor(e1.y0)); + double y1 = std::fmin(ymax, std::ceil(e1.y1)); + + // sort edges by x-coordinate + if ((e0.x0 == e1.x0 && e0.y0 == e1.y0) ? + (e0.x0 + e1.dy / e0.dy * e0.dx < e1.x1) : + (e0.x1 - e1.dy / e0.dy * e0.dx < e1.x0)) { + std::swap(e0, e1); + } + + // scan lines! + double m0 = e0.dx / e0.dy; + double m1 = e1.dx / e1.dy; + double d0 = e0.dx > 0; // use y + 1 to compute x0 + double d1 = e1.dx < 0; // use y + 1 to compute x1 + for (int32_t y = y0; y < y1; y++) { + double x0 = m0 * std::fmax(0, std::fmin(e0.dy, y + d0 - e0.y0)) + e0.x0; + double x1 = m1 * std::fmax(0, std::fmin(e1.dy, y + d1 - e1.y0)) + e1.x0; + scanLine(std::floor(x1), std::ceil(x0), y); + } +} + +// scan-line conversion +static void scanTriangle(const mbgl::vec2<double> a, const mbgl::vec2<double> b, const mbgl::vec2<double> c, int32_t ymin, int32_t ymax, ScanLine& scanLine) { + edge ab = edge(a, b); + edge bc = edge(b, c); + edge ca = edge(c, a); + + // sort edges by y-length + if (ab.dy > bc.dy) { std::swap(ab, bc); } + if (ab.dy > ca.dy) { std::swap(ab, ca); } + if (bc.dy > ca.dy) { std::swap(bc, ca); } + + // scan span! scan span! + if (ab.dy) scanSpans(ca, ab, ymin, ymax, scanLine); + if (bc.dy) scanSpans(ca, bc, ymin, ymax, scanLine); +} + +std::forward_list<TileID> tileCover(int8_t z, const mbgl::box &bounds) { + int32_t tiles = 1 << z; + std::forward_list<mbgl::TileID> t; + + auto scanLine = [&](int32_t x0, int32_t x1, int32_t y) { + int32_t x; + if (y >= 0 && y <= tiles) { + for (x = x0; x < x1; x++) { + t.emplace_front(z, x, y); + } + } + }; + + // Divide the screen up in two triangles and scan each of them: + // \---+ + // | \ | + // +---\. + scanTriangle(bounds.tl, bounds.tr, bounds.br, 0, tiles, scanLine); + scanTriangle(bounds.br, bounds.bl, bounds.tl, 0, tiles, scanLine); + + t.unique(); + + return t; +} + +} diff --git a/src/mbgl/util/tile_cover.hpp b/src/mbgl/util/tile_cover.hpp new file mode 100644 index 0000000000..78121a30ba --- /dev/null +++ b/src/mbgl/util/tile_cover.hpp @@ -0,0 +1,15 @@ +#ifndef MBGL_UTIL_TILE_COVER +#define MBGL_UTIL_TILE_COVER + +#include <mbgl/map/tile_id.hpp> +#include <mbgl/util/box.hpp> + +#include <forward_list> + +namespace mbgl { + +std::forward_list<TileID> tileCover(int8_t z, const box& bounds); + +} + +#endif diff --git a/test/miscellaneous/clip_ids.cpp b/test/miscellaneous/clip_ids.cpp index 845b094520..cf7ebb398b 100644 --- a/test/miscellaneous/clip_ids.cpp +++ b/test/miscellaneous/clip_ids.cpp @@ -4,6 +4,7 @@ #include <algorithm> #include <mbgl/util/clip_ids.hpp> +#include <mbgl/map/tile.hpp> #include <mbgl/util/std.hpp> using namespace mbgl; @@ -29,11 +30,11 @@ template <typename T> void print(const T &sources) { TEST(ClipIDs, ParentAndFourChildren) { const std::vector<std::vector<std::shared_ptr<Tile>>> sources = { { - std::make_shared<Tile>(Tile::ID { 1, 0, 0 }), - std::make_shared<Tile>(Tile::ID { 1, 0, 1 }), - std::make_shared<Tile>(Tile::ID { 1, 1, 0 }), - std::make_shared<Tile>(Tile::ID { 1, 1, 1 }), - std::make_shared<Tile>(Tile::ID { 0, 0, 0 }), + std::make_shared<Tile>(TileID { 1, 0, 0 }), + std::make_shared<Tile>(TileID { 1, 0, 1 }), + std::make_shared<Tile>(TileID { 1, 1, 0 }), + std::make_shared<Tile>(TileID { 1, 1, 1 }), + std::make_shared<Tile>(TileID { 0, 0, 0 }), }, }; @@ -50,11 +51,11 @@ TEST(ClipIDs, ParentAndFourChildren) { TEST(ClipIDs, ParentAndFourChildrenNegative) { const std::vector<std::vector<std::shared_ptr<Tile>>> sources = { { - std::make_shared<Tile>(Tile::ID { 1, -2, 0 }), - std::make_shared<Tile>(Tile::ID { 1, -2, 1 }), - std::make_shared<Tile>(Tile::ID { 1, -1, 0 }), - std::make_shared<Tile>(Tile::ID { 1, -1, 1 }), - std::make_shared<Tile>(Tile::ID { 0, -1, 0 }), + std::make_shared<Tile>(TileID { 1, -2, 0 }), + std::make_shared<Tile>(TileID { 1, -2, 1 }), + std::make_shared<Tile>(TileID { 1, -1, 0 }), + std::make_shared<Tile>(TileID { 1, -1, 1 }), + std::make_shared<Tile>(TileID { 0, -1, 0 }), }, }; @@ -71,11 +72,11 @@ TEST(ClipIDs, ParentAndFourChildrenNegative) { TEST(ClipIDs, NegativeParentAndMissingLevel) { const std::vector<std::vector<std::shared_ptr<Tile>>> sources = { { - std::make_shared<Tile>(Tile::ID { 1, -1, 0 }), - std::make_shared<Tile>(Tile::ID { 2, -1, 0 }), - std::make_shared<Tile>(Tile::ID { 2, -2, 1 }), - std::make_shared<Tile>(Tile::ID { 2, -1, 1 }), - std::make_shared<Tile>(Tile::ID { 2, -2, 0 }), + std::make_shared<Tile>(TileID { 1, -1, 0 }), + std::make_shared<Tile>(TileID { 2, -1, 0 }), + std::make_shared<Tile>(TileID { 2, -2, 1 }), + std::make_shared<Tile>(TileID { 2, -1, 1 }), + std::make_shared<Tile>(TileID { 2, -2, 0 }), }, }; @@ -93,13 +94,13 @@ TEST(ClipIDs, NegativeParentAndMissingLevel) { TEST(ClipIDs, SevenOnSameLevel) { const std::vector<std::vector<std::shared_ptr<Tile>>> sources = { { - std::make_shared<Tile>(Tile::ID { 2, 0, 0 }), - std::make_shared<Tile>(Tile::ID { 2, 0, 1 }), - std::make_shared<Tile>(Tile::ID { 2, 0, 2 }), - std::make_shared<Tile>(Tile::ID { 2, 1, 0 }), - std::make_shared<Tile>(Tile::ID { 2, 1, 1 }), - std::make_shared<Tile>(Tile::ID { 2, 1, 2 }), - std::make_shared<Tile>(Tile::ID { 2, 2, 0 }), + std::make_shared<Tile>(TileID { 2, 0, 0 }), + std::make_shared<Tile>(TileID { 2, 0, 1 }), + std::make_shared<Tile>(TileID { 2, 0, 2 }), + std::make_shared<Tile>(TileID { 2, 1, 0 }), + std::make_shared<Tile>(TileID { 2, 1, 1 }), + std::make_shared<Tile>(TileID { 2, 1, 2 }), + std::make_shared<Tile>(TileID { 2, 2, 0 }), }, }; @@ -118,18 +119,18 @@ TEST(ClipIDs, SevenOnSameLevel) { TEST(ClipIDs, MultipleLevels) { const std::vector<std::vector<std::shared_ptr<Tile>>> sources = { { - std::make_shared<Tile>(Tile::ID { 2, 0, 0 }), - std::make_shared<Tile>(Tile::ID { 3, 0, 0 }), - std::make_shared<Tile>(Tile::ID { 3, 0, 1 }), - std::make_shared<Tile>(Tile::ID { 4, 0, 2 }), - std::make_shared<Tile>(Tile::ID { 4, 1, 2 }), - std::make_shared<Tile>(Tile::ID { 4, 0, 3 }), - std::make_shared<Tile>(Tile::ID { 4, 1, 3 }), - std::make_shared<Tile>(Tile::ID { 3, 1, 0 }), - std::make_shared<Tile>(Tile::ID { 3, 1, 1 }), - std::make_shared<Tile>(Tile::ID { 2, 1, 0 }), - std::make_shared<Tile>(Tile::ID { 3, 2, 0 }), - std::make_shared<Tile>(Tile::ID { 3, 2, 1 }), + std::make_shared<Tile>(TileID { 2, 0, 0 }), + std::make_shared<Tile>(TileID { 3, 0, 0 }), + std::make_shared<Tile>(TileID { 3, 0, 1 }), + std::make_shared<Tile>(TileID { 4, 0, 2 }), + std::make_shared<Tile>(TileID { 4, 1, 2 }), + std::make_shared<Tile>(TileID { 4, 0, 3 }), + std::make_shared<Tile>(TileID { 4, 1, 3 }), + std::make_shared<Tile>(TileID { 3, 1, 0 }), + std::make_shared<Tile>(TileID { 3, 1, 1 }), + std::make_shared<Tile>(TileID { 2, 1, 0 }), + std::make_shared<Tile>(TileID { 3, 2, 0 }), + std::make_shared<Tile>(TileID { 3, 2, 1 }), }, }; @@ -154,17 +155,17 @@ TEST(ClipIDs, MultipleLevels) { TEST(ClipIDs, Bug206) { const std::vector<std::vector<std::shared_ptr<Tile>>> sources = { { - std::make_shared<Tile>(Tile::ID { 10, 162, 395 }), - std::make_shared<Tile>(Tile::ID { 10, 162, 396 }), - std::make_shared<Tile>(Tile::ID { 10, 163, 395 }), - std::make_shared<Tile>(Tile::ID { 11, 326, 791 }), - std::make_shared<Tile>(Tile::ID { 12, 654, 1582 }), - std::make_shared<Tile>(Tile::ID { 12, 654, 1583 }), - std::make_shared<Tile>(Tile::ID { 12, 655, 1582 }), - std::make_shared<Tile>(Tile::ID { 12, 655, 1583 }), - std::make_shared<Tile>(Tile::ID { 10, 163, 396 }), - std::make_shared<Tile>(Tile::ID { 10, 164, 395 }), - std::make_shared<Tile>(Tile::ID { 10, 164, 396 }), + std::make_shared<Tile>(TileID { 10, 162, 395 }), + std::make_shared<Tile>(TileID { 10, 162, 396 }), + std::make_shared<Tile>(TileID { 10, 163, 395 }), + std::make_shared<Tile>(TileID { 11, 326, 791 }), + std::make_shared<Tile>(TileID { 12, 654, 1582 }), + std::make_shared<Tile>(TileID { 12, 654, 1583 }), + std::make_shared<Tile>(TileID { 12, 655, 1582 }), + std::make_shared<Tile>(TileID { 12, 655, 1583 }), + std::make_shared<Tile>(TileID { 10, 163, 396 }), + std::make_shared<Tile>(TileID { 10, 164, 395 }), + std::make_shared<Tile>(TileID { 10, 164, 396 }), }, }; @@ -188,23 +189,23 @@ TEST(ClipIDs, Bug206) { TEST(ClipIDs, MultipleSources) { const std::vector<std::vector<std::shared_ptr<Tile>>> sources = { { - std::make_shared<Tile>(Tile::ID { 0, 0, 0 }), - std::make_shared<Tile>(Tile::ID { 1, 1, 1 }), - std::make_shared<Tile>(Tile::ID { 2, 2, 1 }), - std::make_shared<Tile>(Tile::ID { 2, 2, 2 }), + std::make_shared<Tile>(TileID { 0, 0, 0 }), + std::make_shared<Tile>(TileID { 1, 1, 1 }), + std::make_shared<Tile>(TileID { 2, 2, 1 }), + std::make_shared<Tile>(TileID { 2, 2, 2 }), }, { - std::make_shared<Tile>(Tile::ID { 0, 0, 0 }), - std::make_shared<Tile>(Tile::ID { 1, 1, 1 }), - std::make_shared<Tile>(Tile::ID { 2, 1, 1 }), - std::make_shared<Tile>(Tile::ID { 2, 2, 2 }), + std::make_shared<Tile>(TileID { 0, 0, 0 }), + std::make_shared<Tile>(TileID { 1, 1, 1 }), + std::make_shared<Tile>(TileID { 2, 1, 1 }), + std::make_shared<Tile>(TileID { 2, 2, 2 }), }, { - std::make_shared<Tile>(Tile::ID { 1, 0, 0 }), - std::make_shared<Tile>(Tile::ID { 1, 0, 1 }), - std::make_shared<Tile>(Tile::ID { 1, 1, 0 }), - std::make_shared<Tile>(Tile::ID { 1, 1, 1 }), - std::make_shared<Tile>(Tile::ID { 2, 1, 1 }), + std::make_shared<Tile>(TileID { 1, 0, 0 }), + std::make_shared<Tile>(TileID { 1, 0, 1 }), + std::make_shared<Tile>(TileID { 1, 1, 0 }), + std::make_shared<Tile>(TileID { 1, 1, 1 }), + std::make_shared<Tile>(TileID { 2, 1, 1 }), }, }; @@ -230,13 +231,13 @@ TEST(ClipIDs, MultipleSources) { TEST(ClipIDs, DuplicateIDs) { const std::vector<std::vector<std::shared_ptr<Tile>>> sources = { { - std::make_shared<Tile>(Tile::ID { 2, 0, 0 }), - std::make_shared<Tile>(Tile::ID { 2, 0, 1 }), + std::make_shared<Tile>(TileID { 2, 0, 0 }), + std::make_shared<Tile>(TileID { 2, 0, 1 }), }, { - std::make_shared<Tile>(Tile::ID { 2, 0, 0 }), - std::make_shared<Tile>(Tile::ID { 2, 0, 1 }), - std::make_shared<Tile>(Tile::ID { 2, 0, 1 }), + std::make_shared<Tile>(TileID { 2, 0, 0 }), + std::make_shared<Tile>(TileID { 2, 0, 1 }), + std::make_shared<Tile>(TileID { 2, 0, 1 }), } }; diff --git a/test/miscellaneous/tile.cpp b/test/miscellaneous/tile.cpp index 01da68f10d..6c5c89ac43 100644 --- a/test/miscellaneous/tile.cpp +++ b/test/miscellaneous/tile.cpp @@ -1,50 +1,50 @@ #include <iostream> #include "../fixtures/util.hpp" -#include <mbgl/map/tile.hpp> +#include <mbgl/map/tile_id.hpp> using namespace mbgl; TEST(Variant, isChild) { - ASSERT_TRUE(Tile::ID(1, 0, 0).isChildOf(Tile::ID(0, 0, 0))); - ASSERT_TRUE(Tile::ID(1, 1, 0).isChildOf(Tile::ID(0, 0, 0))); - ASSERT_TRUE(Tile::ID(1, 2, 0).isChildOf(Tile::ID(0, 1, 0))); - ASSERT_TRUE(Tile::ID(1, 3, 0).isChildOf(Tile::ID(0, 1, 0))); - ASSERT_TRUE(Tile::ID(1, 4, 0).isChildOf(Tile::ID(0, 2, 0))); - ASSERT_TRUE(Tile::ID(1, 5, 0).isChildOf(Tile::ID(0, 2, 0))); - ASSERT_TRUE(Tile::ID(2, 0, 0).isChildOf(Tile::ID(0, 0, 0))); - - ASSERT_TRUE(Tile::ID(2, 8, 0).isChildOf(Tile::ID(0, 2, 0))); - ASSERT_TRUE(Tile::ID(2, 9, 0).isChildOf(Tile::ID(0, 2, 0))); - ASSERT_TRUE(Tile::ID(2, 10, 0).isChildOf(Tile::ID(0, 2, 0))); - ASSERT_TRUE(Tile::ID(2, 11, 0).isChildOf(Tile::ID(0, 2, 0))); - ASSERT_TRUE(Tile::ID(2, 12, 0).isChildOf(Tile::ID(0, 3, 0))); - ASSERT_TRUE(Tile::ID(2, 13, 0).isChildOf(Tile::ID(0, 3, 0))); - - ASSERT_TRUE(Tile::ID(1, -1, 0).isChildOf(Tile::ID(0, -1, 0))); - ASSERT_TRUE(Tile::ID(1, -2, 0).isChildOf(Tile::ID(0, -1, 0))); - ASSERT_TRUE(Tile::ID(1, -3, 0).isChildOf(Tile::ID(0, -2, 0))); - ASSERT_TRUE(Tile::ID(1, -4, 0).isChildOf(Tile::ID(0, -2, 0))); - ASSERT_TRUE(Tile::ID(2, -1, 0).isChildOf(Tile::ID(0, -1, 0))); - ASSERT_TRUE(Tile::ID(2, -2, 0).isChildOf(Tile::ID(0, -1, 0))); - ASSERT_TRUE(Tile::ID(2, -3, 0).isChildOf(Tile::ID(0, -1, 0))); - ASSERT_TRUE(Tile::ID(2, -4, 0).isChildOf(Tile::ID(0, -1, 0))); - ASSERT_TRUE(Tile::ID(2, -5, 0).isChildOf(Tile::ID(0, -2, 0))); - ASSERT_TRUE(Tile::ID(2, -6, 0).isChildOf(Tile::ID(0, -2, 0))); - ASSERT_TRUE(Tile::ID(2, -7, 0).isChildOf(Tile::ID(0, -2, 0))); - ASSERT_TRUE(Tile::ID(2, -8, 0).isChildOf(Tile::ID(0, -2, 0))); - - ASSERT_FALSE(Tile::ID(4, -16, 0).isChildOf(Tile::ID(0, -2, 0))); - ASSERT_TRUE(Tile::ID(4, -17, 0).isChildOf(Tile::ID(0, -2, 0))); - - ASSERT_TRUE(Tile::ID(2, -1, 0).isChildOf(Tile::ID(1, -1, 0))); - ASSERT_TRUE(Tile::ID(2, -2, 0).isChildOf(Tile::ID(1, -1, 0))); - ASSERT_TRUE(Tile::ID(2, -3, 0).isChildOf(Tile::ID(1, -2, 0))); - ASSERT_TRUE(Tile::ID(2, -4, 0).isChildOf(Tile::ID(1, -2, 0))); - ASSERT_TRUE(Tile::ID(3, -1, 0).isChildOf(Tile::ID(1, -1, 0))); - ASSERT_TRUE(Tile::ID(3, -2, 0).isChildOf(Tile::ID(1, -1, 0))); - ASSERT_TRUE(Tile::ID(3, -3, 0).isChildOf(Tile::ID(1, -1, 0))); - ASSERT_TRUE(Tile::ID(3, -4, 0).isChildOf(Tile::ID(1, -1, 0))); - ASSERT_TRUE(Tile::ID(3, -5, 0).isChildOf(Tile::ID(1, -2, 0))); + ASSERT_TRUE(TileID(1, 0, 0).isChildOf(TileID(0, 0, 0))); + ASSERT_TRUE(TileID(1, 1, 0).isChildOf(TileID(0, 0, 0))); + ASSERT_TRUE(TileID(1, 2, 0).isChildOf(TileID(0, 1, 0))); + ASSERT_TRUE(TileID(1, 3, 0).isChildOf(TileID(0, 1, 0))); + ASSERT_TRUE(TileID(1, 4, 0).isChildOf(TileID(0, 2, 0))); + ASSERT_TRUE(TileID(1, 5, 0).isChildOf(TileID(0, 2, 0))); + ASSERT_TRUE(TileID(2, 0, 0).isChildOf(TileID(0, 0, 0))); + + ASSERT_TRUE(TileID(2, 8, 0).isChildOf(TileID(0, 2, 0))); + ASSERT_TRUE(TileID(2, 9, 0).isChildOf(TileID(0, 2, 0))); + ASSERT_TRUE(TileID(2, 10, 0).isChildOf(TileID(0, 2, 0))); + ASSERT_TRUE(TileID(2, 11, 0).isChildOf(TileID(0, 2, 0))); + ASSERT_TRUE(TileID(2, 12, 0).isChildOf(TileID(0, 3, 0))); + ASSERT_TRUE(TileID(2, 13, 0).isChildOf(TileID(0, 3, 0))); + + ASSERT_TRUE(TileID(1, -1, 0).isChildOf(TileID(0, -1, 0))); + ASSERT_TRUE(TileID(1, -2, 0).isChildOf(TileID(0, -1, 0))); + ASSERT_TRUE(TileID(1, -3, 0).isChildOf(TileID(0, -2, 0))); + ASSERT_TRUE(TileID(1, -4, 0).isChildOf(TileID(0, -2, 0))); + ASSERT_TRUE(TileID(2, -1, 0).isChildOf(TileID(0, -1, 0))); + ASSERT_TRUE(TileID(2, -2, 0).isChildOf(TileID(0, -1, 0))); + ASSERT_TRUE(TileID(2, -3, 0).isChildOf(TileID(0, -1, 0))); + ASSERT_TRUE(TileID(2, -4, 0).isChildOf(TileID(0, -1, 0))); + ASSERT_TRUE(TileID(2, -5, 0).isChildOf(TileID(0, -2, 0))); + ASSERT_TRUE(TileID(2, -6, 0).isChildOf(TileID(0, -2, 0))); + ASSERT_TRUE(TileID(2, -7, 0).isChildOf(TileID(0, -2, 0))); + ASSERT_TRUE(TileID(2, -8, 0).isChildOf(TileID(0, -2, 0))); + + ASSERT_FALSE(TileID(4, -16, 0).isChildOf(TileID(0, -2, 0))); + ASSERT_TRUE(TileID(4, -17, 0).isChildOf(TileID(0, -2, 0))); + + ASSERT_TRUE(TileID(2, -1, 0).isChildOf(TileID(1, -1, 0))); + ASSERT_TRUE(TileID(2, -2, 0).isChildOf(TileID(1, -1, 0))); + ASSERT_TRUE(TileID(2, -3, 0).isChildOf(TileID(1, -2, 0))); + ASSERT_TRUE(TileID(2, -4, 0).isChildOf(TileID(1, -2, 0))); + ASSERT_TRUE(TileID(3, -1, 0).isChildOf(TileID(1, -1, 0))); + ASSERT_TRUE(TileID(3, -2, 0).isChildOf(TileID(1, -1, 0))); + ASSERT_TRUE(TileID(3, -3, 0).isChildOf(TileID(1, -1, 0))); + ASSERT_TRUE(TileID(3, -4, 0).isChildOf(TileID(1, -1, 0))); + ASSERT_TRUE(TileID(3, -5, 0).isChildOf(TileID(1, -2, 0))); } |