summaryrefslogtreecommitdiff
path: root/platform/default/mbgl/storage/offline.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/default/mbgl/storage/offline.cpp')
-rw-r--r--platform/default/mbgl/storage/offline.cpp142
1 files changed, 70 insertions, 72 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_,