summaryrefslogtreecommitdiff
path: root/include/mbgl/storage/offline.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/mbgl/storage/offline.hpp')
-rw-r--r--include/mbgl/storage/offline.hpp130
1 files changed, 113 insertions, 17 deletions
diff --git a/include/mbgl/storage/offline.hpp b/include/mbgl/storage/offline.hpp
index 818cfe2ba5..af12744f0d 100644
--- a/include/mbgl/storage/offline.hpp
+++ b/include/mbgl/storage/offline.hpp
@@ -3,9 +3,16 @@
#include <mbgl/util/geo.hpp>
#include <mbgl/util/range.hpp>
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/variant.hpp>
+#include <mbgl/util/geometry.hpp>
+#include <mbgl/util/tile_cover.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/storage/response.hpp>
+#include <rapidjson/document.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+
#include <string>
#include <vector>
#include <functional>
@@ -15,7 +22,7 @@ namespace mbgl {
class TileID;
/*
- * An offline region defined by a style URL, geographic bounding box, zoom range, and
+ * An offline region defined by a style URL, geometry, zoom range, and
* device pixel ratio.
*
* Both minZoom and maxZoom must be ≥ 0, and maxZoom must be ≥ minZoom.
@@ -25,29 +32,118 @@ class TileID;
*
* pixelRatio must be ≥ 0 and should typically be 1.0 or 2.0.
*/
-class OfflineTilePyramidRegionDefinition {
+
+template <typename TGeometry>
+struct OfflineFixedGeometryTraits { };
+
+template <>
+struct OfflineFixedGeometryTraits<LatLngBounds> {
+ static const char typeName[];
+ constexpr static const size_t typeNameLength = sizeof("PYRAMID") - 1;
+
+ void encode(rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator>& doc, LatLngBounds bounds);
+ LatLngBounds decode(const rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator>& doc);
+};
+
+template <>
+struct OfflineFixedGeometryTraits<Polygon<double>> {
+ static const char typeName[];
+ constexpr static const size_t typeNameLength = sizeof("POLYGON") - 1;
+
+ void encode(rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator>&, const Polygon<double>&);
+ Polygon<double> decode(const rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator>&);
+};
+
+template <typename TGeometry>
+class OfflineFixedGeometryRegionDefinition {
public:
- OfflineTilePyramidRegionDefinition(std::string, LatLngBounds, double, double, float);
-
+ OfflineFixedGeometryRegionDefinition(std::string styleURL_, TGeometry geometry_, Range<double> zoomRange_, float pixelRatio_)
+ : styleURL(std::move(styleURL_)),
+ geometry(std::move(geometry_)),
+ minZoom(zoomRange_.min),
+ maxZoom(zoomRange_.max),
+ pixelRatio(pixelRatio_) { }
+
/* Private */
- std::vector<CanonicalTileID> tileCover(SourceType, uint16_t tileSize, const Range<uint8_t>& zoomRange) const;
-
+ std::vector<CanonicalTileID> tileCover(SourceType type, uint16_t tileSize, Range<uint8_t> sourceZoomRange) const {
+ double minZ = std::max<double>(util::coveringZoomLevel(minZoom, type, tileSize), sourceZoomRange.min);
+ double maxZ = std::min<double>(util::coveringZoomLevel(maxZoom, type, tileSize), sourceZoomRange.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(geometry, z)) {
+ result.emplace_back(tile.canonical);
+ }
+ }
+
+ return result;
+ }
+
+ std::string encode() const {
+ OfflineFixedGeometryTraits<TGeometry> geometryTraits;
+
+ rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> doc;
+ doc.SetObject();
+
+ doc.AddMember("type", rapidjson::StringRef(geometryTraits.typeName, geometryTraits.typeNameLength), doc.GetAllocator());
+ doc.AddMember("style_url", rapidjson::StringRef(styleURL.data(), styleURL.length()), doc.GetAllocator());
+
+ geometryTraits.encode(doc, geometry);
+
+ doc.AddMember("min_zoom", minZoom, doc.GetAllocator());
+ if (std::isfinite(maxZoom)) {
+ doc.AddMember("max_zoom", maxZoom, doc.GetAllocator());
+ }
+
+ doc.AddMember("pixel_ratio", pixelRatio, doc.GetAllocator());
+
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ doc.Accept(writer);
+
+ return buffer.GetString();
+ }
+
+ static OfflineFixedGeometryRegionDefinition<TGeometry> decode(const rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator>& doc) {
+ OfflineFixedGeometryTraits<TGeometry> geometryTraits;
+
+ if (doc.HasParseError() ||
+ !doc.HasMember("style_url") || !doc["style_url"].IsString() ||
+ !doc.HasMember("min_zoom") || !doc["min_zoom"].IsDouble() ||
+ (doc.HasMember("max_zoom") && !doc["max_zoom"].IsDouble()) ||
+ !doc.HasMember("pixel_ratio") || !doc["pixel_ratio"].IsDouble()) {
+ throw std::runtime_error("Malformed offline fixed geometry region definition");
+ }
+
+ std::string styleURL { doc["style_url"].GetString(), doc["style_url"].GetStringLength() };
+ double minZoom = doc["min_zoom"].GetDouble();
+ double maxZoom = doc.HasMember("max_zoom") ? doc["max_zoom"].GetDouble() : INFINITY;
+ Range<double> zoomRange{ minZoom, maxZoom };
+ float pixelRatio = doc["pixel_ratio"].GetDouble();
+
+ auto geometry = geometryTraits.decode(doc);
+
+ return { styleURL, geometry, zoomRange, pixelRatio };
+ }
+
const std::string styleURL;
- const LatLngBounds bounds;
+ const TGeometry geometry;
const double minZoom;
const double maxZoom;
const float pixelRatio;
};
-
-/*
- * For the present, a tile pyramid is the only type of offline region. In the future,
- * other definition types will be available and this will be a variant type.
- */
-using OfflineRegionDefinition = OfflineTilePyramidRegionDefinition;
-
-/*
- * The encoded format is private.
- */
+
+using OfflineRegionDefinition = variant<OfflineFixedGeometryRegionDefinition<LatLngBounds>, OfflineFixedGeometryRegionDefinition<Polygon<double>>>;
+
+float pixelRatio(const OfflineRegionDefinition&);
+const std::string& styleURL(const OfflineRegionDefinition&);
+std::vector<CanonicalTileID> tileCover(const OfflineRegionDefinition&, SourceType, uint16_t, Range<uint8_t>);
+
std::string encodeOfflineRegionDefinition(const OfflineRegionDefinition&);
OfflineRegionDefinition decodeOfflineRegionDefinition(const std::string&);