Load TileJSON; support inline TileJSON sources

Fixes #412
Refs https://github.com/mapbox/mapbox-gl-style-spec/pull/143
This commit is contained in:
Lauren Budorick
2014-08-18 17:49:50 -07:00
committed by John Firebaugh
parent b9c7e1bdd9
commit 0168612ed3
8 changed files with 176 additions and 61 deletions

View File

@@ -469,7 +469,8 @@ void Map::updateSources() {
for (const std::shared_ptr<StyleSource> &style_source : activeSources) {
if (style_source->enabled) {
if (!style_source->source) {
style_source->source = std::make_shared<Source>(style_source->info, getAccessToken());
style_source->source = std::make_shared<Source>(style_source->info);
style_source->source->load(*this);
}
} else {
style_source->source.reset();

View File

@@ -6,40 +6,73 @@
#include <mbgl/util/raster.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/texturepool.hpp>
#include <mbgl/util/filesource.hpp>
#include <mbgl/util/vec.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/geometry/glyph_atlas.hpp>
#include <mbgl/style/style_layer.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/map/vector_tile_data.hpp>
#include <mbgl/map/raster_tile_data.hpp>
namespace mbgl {
Source::Source(SourceInfo info, const std::string &access_token)
: info(
info.type,
normalizeSourceURL(info.url, access_token),
info.tile_size,
info.min_zoom,
info.max_zoom
) {}
Source::Source(SourceInfo& info)
: info(info)
{
}
std::string Source::normalizeSourceURL(const std::string &url, const std::string &access_token) {
std::string normalizeURL(const std::string& url, const std::string& access_token) {
const std::string t = "mapbox://";
if (url.compare(0, t.length(), t) == 0) {
if (access_token.empty()) {
throw std::runtime_error("You must provide a Mapbox API access token for Mapbox tile sources");
}
return std::string("https://api.tiles.mapbox.com/v4/") + url.substr(t.length()) + "/{z}/{x}/{y}.vector.pbf?access_token=" + access_token;
} else {
if (url.compare(0, t.length(), t) != 0)
return url;
if (access_token.empty())
throw std::runtime_error("You must provide a Mapbox API access token for Mapbox tile sources");
return std::string("https://api.tiles.mapbox.com/v4/")
+ url.substr(t.length())
+ ".json?access_token="
+ access_token;
}
// 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) {
if (info.url.empty()) {
loaded = true;
return;
}
std::string url = normalizeURL(info.url, map.getAccessToken());
std::shared_ptr<Source> source = shared_from_this();
map.getFileSource()->load(ResourceType::JSON, url, [source, &map](platform::Response *res) {
if (res->code != 200) {
Log::Warning(Event::General, "failed to load source TileJSON");
return;
}
rapidjson::Document d;
d.Parse<0>(res->body.c_str());
if (d.HasParseError()) {
Log::Warning(Event::General, "invalid source TileJSON");
return;
}
source->info.parseTileJSONProperties(d);
source->loaded = true;
map.update();
});
}
bool Source::update(Map &map) {
if (map.getTime() > updated) {
if (loaded && map.getTime() > updated) {
return updateTiles(map);
} else {
return false;

View File

@@ -14,13 +14,6 @@ TileData::TileData(Tile::ID id, Map &map, const SourceInfo &source)
state(State::initial),
map(map),
source(source),
url(util::replaceTokens(source.url, [&](const std::string &token) -> std::string {
if (token == "z") return std::to_string(id.z);
if (token == "x") return std::to_string(id.x);
if (token == "y") return std::to_string(id.y);
if (token == "ratio") return (map.getState().getPixelRatio() > 1.0 ? "@2x" : "");
return "";
})),
debugBucket(debugFontBuffer) {
// Initialize tile debug coordinates
const std::string str = util::sprintf<32>("%d/%d/%d", id.z, id.x, id.y);
@@ -36,11 +29,23 @@ const std::string TileData::toString() const {
}
void TileData::request() {
if (source.tiles.empty())
return;
std::string url = source.tiles[(id.x + id.y) % source.tiles.size()];
url = util::replaceTokens(url, [&](const std::string &token) -> std::string {
if (token == "z") return std::to_string(id.z);
if (token == "x") return std::to_string(id.x);
if (token == "y") return std::to_string(id.y);
if (token == "ratio") return (map.getState().getPixelRatio() > 1.0 ? "@2x" : "");
return "";
});
state = State::loading;
// Note: Somehow this feels slower than the change to request_http()
std::weak_ptr<TileData> weak_tile = shared_from_this();
map.getFileSource()->load(ResourceType::Tile, url, [weak_tile](platform::Response *res) {
map.getFileSource()->load(ResourceType::Tile, url, [weak_tile, url](platform::Response *res) {
std::shared_ptr<TileData> tile = weak_tile.lock();
if (!tile || tile->state == State::obsolete) {
// noop. Tile is obsolete and we're now just waiting for the refcount
@@ -54,7 +59,7 @@ void TileData::request() {
tile->reparse();
} else {
#if defined(DEBUG)
fprintf(stderr, "[%s] tile loading failed: %d, %s\n", tile->url.c_str(), res->code, res->error_message.c_str());
fprintf(stderr, "[%s] tile loading failed: %d, %s\n", url.c_str(), res->code, res->error_message.c_str());
#endif
}
});