diff options
Diffstat (limited to 'platform/default')
-rw-r--r-- | platform/default/mbgl/storage/offline.cpp | 142 | ||||
-rw-r--r-- | platform/default/mbgl/storage/offline_download.cpp | 12 |
2 files changed, 76 insertions, 78 deletions
diff --git a/platform/default/mbgl/storage/offline.cpp b/platform/default/mbgl/storage/offline.cpp index fd2d47819b..6a2777a520 100644 --- a/platform/default/mbgl/storage/offline.cpp +++ b/platform/default/mbgl/storage/offline.cpp @@ -1,6 +1,9 @@ +#include <mapbox/geojson/rapidjson.hpp> + #include <mbgl/storage/offline.hpp> #include <mbgl/util/tile_cover.hpp> #include <mbgl/util/tileset.hpp> +#include <mbgl/util/variant.hpp> #include <rapidjson/document.h> #include <rapidjson/stringbuffer.h> @@ -9,91 +12,86 @@ #include <cmath> namespace mbgl { + +const char OfflineFixedGeometryTraits<LatLngBounds>::typeName[] = "PYRAMID"; +const char OfflineFixedGeometryTraits<Polygon<double>>::typeName[] = "POLYGON"; + +void OfflineFixedGeometryTraits<LatLngBounds>::encode(rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator>& doc, LatLngBounds bounds) { + rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson::CrtAllocator> encodedBounds(rapidjson::kArrayType); + encodedBounds.PushBack(bounds.south(), doc.GetAllocator()); + encodedBounds.PushBack(bounds.west(), doc.GetAllocator()); + encodedBounds.PushBack(bounds.north(), doc.GetAllocator()); + encodedBounds.PushBack(bounds.east(), doc.GetAllocator()); + doc.AddMember("bounds", encodedBounds, doc.GetAllocator()); +} -OfflineTilePyramidRegionDefinition::OfflineTilePyramidRegionDefinition( - std::string styleURL_, LatLngBounds bounds_, double minZoom_, double maxZoom_, float pixelRatio_) - : styleURL(std::move(styleURL_)), - bounds(std::move(bounds_)), - minZoom(minZoom_), - maxZoom(maxZoom_), - pixelRatio(pixelRatio_) { - if (minZoom < 0 || maxZoom < 0 || maxZoom < minZoom || pixelRatio < 0 || - !std::isfinite(minZoom) || std::isnan(maxZoom) || !std::isfinite(pixelRatio)) { - throw std::invalid_argument("Invalid offline region definition"); +LatLngBounds OfflineFixedGeometryTraits<LatLngBounds>::decode(const rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator>& doc) { + if (!doc.HasMember("bounds") || !doc["bounds"].IsArray() || doc["bounds"].Size() != 4) { + throw std::runtime_error("Malformed pyramid offline region definition"); } + return LatLngBounds::hull(LatLng(doc["bounds"][0].GetDouble(), doc["bounds"][1].GetDouble()), + LatLng(doc["bounds"][2].GetDouble(), doc["bounds"][3].GetDouble())); } - -std::vector<CanonicalTileID> OfflineTilePyramidRegionDefinition::tileCover(SourceType type, uint16_t tileSize, const Range<uint8_t>& zoomRange) const { - double minZ = std::max<double>(util::coveringZoomLevel(minZoom, type, tileSize), zoomRange.min); - double maxZ = std::min<double>(util::coveringZoomLevel(maxZoom, type, tileSize), zoomRange.max); - - assert(minZ >= 0); - assert(maxZ >= 0); - assert(minZ < std::numeric_limits<uint8_t>::max()); - assert(maxZ < std::numeric_limits<uint8_t>::max()); - - std::vector<CanonicalTileID> result; - - for (uint8_t z = minZ; z <= maxZ; z++) { - for (const auto& tile : util::tileCover(bounds, z)) { - result.emplace_back(tile.canonical); - } + +void OfflineFixedGeometryTraits<Polygon<double>>::encode(rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator>& doc, const Polygon<double>& polygon) { + auto encodedGeom = mapbox::geojson::convert<Geometry<double>>({ polygon }, doc.GetAllocator()); + doc.AddMember("polygon", encodedGeom, doc.GetAllocator()); +} + +Polygon<double> OfflineFixedGeometryTraits<Polygon<double>>::decode(const rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator>& doc) { + if (!doc.HasMember("polygon")) { + throw std::runtime_error("Malformed polygon offline region definition"); } + return mapbox::geojson::convert<Geometry<double>>(doc["polygon"]).get<Polygon<double>>(); +} + +float pixelRatio(const OfflineRegionDefinition& region) { + return OfflineRegionDefinition::visit(region, [](const auto& r) { return r.pixelRatio; }); +} + +const std::string& styleURL(const OfflineRegionDefinition& region) { + return OfflineRegionDefinition::visit(region, [](const auto& r) -> const std::string& { return r.styleURL; }); +} - return result; +std::vector<CanonicalTileID> tileCover(const OfflineRegionDefinition& region, SourceType type, uint16_t tileSize, Range<uint8_t> zoomRange) { + return OfflineRegionDefinition::visit(region, [type, tileSize, zoomRange](const auto& r) { return r.tileCover(type, tileSize, zoomRange); }); +} + +std::string encodeOfflineRegionDefinition(const OfflineRegionDefinition& region) { + return OfflineRegionDefinition::visit(region, [](const auto& r) { return r.encode(); }); } OfflineRegionDefinition decodeOfflineRegionDefinition(const std::string& region) { + rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> doc; doc.Parse<0>(region.c_str()); - - if (doc.HasParseError() || - !doc.HasMember("style_url") || !doc["style_url"].IsString() || - !doc.HasMember("bounds") || !doc["bounds"].IsArray() || doc["bounds"].Size() != 4 || - !doc["bounds"][0].IsDouble() || !doc["bounds"][1].IsDouble() || - !doc["bounds"][2].IsDouble() || !doc["bounds"][3].IsDouble() || - !doc.HasMember("min_zoom") || !doc["min_zoom"].IsDouble() || - (doc.HasMember("max_zoom") && !doc["max_zoom"].IsDouble()) || - !doc.HasMember("pixel_ratio") || !doc["pixel_ratio"].IsDouble()) { + + if (doc.HasParseError()) { throw std::runtime_error("Malformed offline region definition"); } - - std::string styleURL { doc["style_url"].GetString(), doc["style_url"].GetStringLength() }; - LatLngBounds bounds = LatLngBounds::hull( - LatLng(doc["bounds"][0].GetDouble(), doc["bounds"][1].GetDouble()), - LatLng(doc["bounds"][2].GetDouble(), doc["bounds"][3].GetDouble())); - double minZoom = doc["min_zoom"].GetDouble(); - double maxZoom = doc.HasMember("max_zoom") ? doc["max_zoom"].GetDouble() : INFINITY; - float pixelRatio = doc["pixel_ratio"].GetDouble(); - - return { styleURL, bounds, minZoom, maxZoom, pixelRatio }; -} - -std::string encodeOfflineRegionDefinition(const OfflineRegionDefinition& region) { - rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> doc; - doc.SetObject(); - - doc.AddMember("style_url", rapidjson::StringRef(region.styleURL.data(), region.styleURL.length()), doc.GetAllocator()); - - rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson::CrtAllocator> bounds(rapidjson::kArrayType); - bounds.PushBack(region.bounds.south(), doc.GetAllocator()); - bounds.PushBack(region.bounds.west(), doc.GetAllocator()); - bounds.PushBack(region.bounds.north(), doc.GetAllocator()); - bounds.PushBack(region.bounds.east(), doc.GetAllocator()); - doc.AddMember("bounds", bounds, doc.GetAllocator()); - - doc.AddMember("min_zoom", region.minZoom, doc.GetAllocator()); - if (std::isfinite(region.maxZoom)) { - doc.AddMember("max_zoom", region.maxZoom, doc.GetAllocator()); + + std::string type; + if (!doc.HasMember("type")) { + // Might be an old database format; assume it's a tile pyramid + type = OfflineFixedGeometryTraits<LatLngBounds>::typeName; + } + else if (!doc["type"].IsString()) { + throw std::runtime_error("Malformed offline region definition"); + } + else { + type = doc["type"].GetString(); + } + + if (type == OfflineFixedGeometryTraits<LatLngBounds>::typeName) { + return OfflineFixedGeometryRegionDefinition<LatLngBounds>::decode(doc); + } + else if (type == OfflineFixedGeometryTraits<Polygon<double>>::typeName) { + return OfflineFixedGeometryRegionDefinition<Polygon<double>>::decode(doc); + } + else { + std::string msg("Unknown offline region type: "); + throw std::runtime_error(msg + type); } - - doc.AddMember("pixel_ratio", region.pixelRatio, doc.GetAllocator()); - - rapidjson::StringBuffer buffer; - rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); - doc.Accept(writer); - - return buffer.GetString(); } OfflineRegion::OfflineRegion(int64_t id_, diff --git a/platform/default/mbgl/storage/offline_download.cpp b/platform/default/mbgl/storage/offline_download.cpp index 6ff605167a..58551bca11 100644 --- a/platform/default/mbgl/storage/offline_download.cpp +++ b/platform/default/mbgl/storage/offline_download.cpp @@ -53,8 +53,8 @@ std::vector<Resource> OfflineDownload::spriteResources(const style::Parser& pars std::vector<Resource> result; if (!parser.spriteURL.empty()) { - result.push_back(Resource::spriteImage(parser.spriteURL, definition.pixelRatio)); - result.push_back(Resource::spriteJSON(parser.spriteURL, definition.pixelRatio)); + result.push_back(Resource::spriteImage(parser.spriteURL, pixelRatio(definition))); + result.push_back(Resource::spriteJSON(parser.spriteURL, pixelRatio(definition))); } return result; @@ -77,8 +77,8 @@ std::vector<Resource> OfflineDownload::glyphResources(const style::Parser& parse std::vector<Resource> OfflineDownload::tileResources(SourceType type, uint16_t tileSize, const Tileset& tileset) const { std::vector<Resource> result; - for (const auto& tile : definition.tileCover(type, tileSize, tileset.zoomRange)) { - result.push_back(Resource::tile(tileset.tiles[0], definition.pixelRatio, tile.x, tile.y, tile.z)); + for (const auto& tile : tileCover(definition, type, tileSize, tileset.zoomRange)) { + result.push_back(Resource::tile(tileset.tiles[0], pixelRatio(definition), tile.x, tile.y, tile.z)); } return result; @@ -92,7 +92,7 @@ OfflineRegionStatus OfflineDownload::getStatus() const { OfflineRegionStatus result = offlineDatabase.getRegionCompletedStatus(id); result.requiredResourceCount++; - optional<Response> styleResponse = offlineDatabase.get(Resource::style(definition.styleURL)); + optional<Response> styleResponse = offlineDatabase.get(Resource::style(styleURL(definition))); if (!styleResponse) { return result; } @@ -153,7 +153,7 @@ void OfflineDownload::activateDownload() { requiredSourceURLs.clear(); - ensureResource(Resource::style(definition.styleURL), [&] (Response styleResponse) { + ensureResource(Resource::style(styleURL(definition)), [&] (Response styleResponse) { status.requiredResourceCountIsPrecise = true; style::Parser parser; |