summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrosecodym <rosecodym@gmail.com>2016-07-15 16:41:54 -0700
committerrosecodym <rosecodym@gmail.com>2016-07-15 16:44:34 -0700
commit26abfb555e592d3cdc75b0184f645a9563d81934 (patch)
tree487c1fc554f6993bf17b411bdf5bc8c2ee04319b
parent89b54d4ad47ae4fd8e76a184455252ec1114c565 (diff)
downloadqtlocation-mapboxgl-upstream/wip-rosecodym.tar.gz
[core] create offline polygon region definitionupstream/wip-rosecodym
There is now a way to create and persist offline storage regions other than the old tile pyramids. The region type is now a variant, and the two options are the old tile pyramids, and a new type for polygons. Each type is an instantiation of a class template for offline regions with fixed geometry.
-rw-r--r--include/mbgl/storage/offline.hpp130
-rw-r--r--platform/default/mbgl/storage/offline.cpp142
-rw-r--r--platform/default/mbgl/storage/offline_download.cpp12
-rw-r--r--platform/macos/platform.gyp1
-rw-r--r--test/storage/offline.cpp57
-rw-r--r--test/storage/offline_database.cpp49
-rw-r--r--test/storage/offline_download.cpp34
7 files changed, 273 insertions, 152 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&);
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;
diff --git a/platform/macos/platform.gyp b/platform/macos/platform.gyp
index 68ab4ce467..2462765cc5 100644
--- a/platform/macos/platform.gyp
+++ b/platform/macos/platform.gyp
@@ -84,6 +84,7 @@
'<@(sqlite_cflags)',
'<@(zlib_cflags)',
'<@(rapidjson_cflags)',
+ '<@(geojson_cflags)',
],
'CLANG_ENABLE_OBJC_ARC': 'YES',
'CLANG_ENABLE_MODULES': 'YES',
diff --git a/test/storage/offline.cpp b/test/storage/offline.cpp
index 0faaabc298..c65e6eef42 100644
--- a/test/storage/offline.cpp
+++ b/test/storage/offline.cpp
@@ -5,50 +5,71 @@
using namespace mbgl;
+using OfflineTilePyramidRegionDefinition = OfflineFixedGeometryRegionDefinition<LatLngBounds>;
+
static const LatLngBounds sanFrancisco =
LatLngBounds::hull({ 37.6609, -122.5744 }, { 37.8271, -122.3204 });
static const LatLngBounds sanFranciscoWrapped =
LatLngBounds::hull({ 37.6609, 238.5744 }, { 37.8271, 238.3204 });
-TEST(OfflineTilePyramidRegionDefinition, TileCoverEmpty) {
- OfflineTilePyramidRegionDefinition region("", LatLngBounds::empty(), 0, 20, 1.0);
+TEST(OfflineRegionDefinition, TileCoverEmpty) {
+ OfflineTilePyramidRegionDefinition region("", LatLngBounds::empty(), {0, 20}, 1.0);
- EXPECT_EQ((std::vector<CanonicalTileID>{}), region.tileCover(SourceType::Vector, 512, { 0, 22 }));
+ EXPECT_EQ((std::vector<CanonicalTileID>{}), tileCover(region, SourceType::Vector, 512, { 0, 22 }));
}
-TEST(OfflineTilePyramidRegionDefinition, TileCoverZoomIntersection) {
- OfflineTilePyramidRegionDefinition region("", sanFrancisco, 2, 2, 1.0);
+TEST(OfflineRegionDefinition, TileCoverZoomIntersection) {
+ OfflineTilePyramidRegionDefinition region("", sanFrancisco, {2, 2}, 1.0);
EXPECT_EQ((std::vector<CanonicalTileID>{ { 2, 0, 1 } }),
- region.tileCover(SourceType::Vector, 512, { 0, 22 }));
+ tileCover(region, SourceType::Vector, 512, { 0, 22 }));
- EXPECT_EQ((std::vector<CanonicalTileID>{}), region.tileCover(SourceType::Vector, 512, { 3, 22 }));
+ EXPECT_EQ((std::vector<CanonicalTileID>{}), tileCover(region, SourceType::Vector, 512, { 3, 22 }));
}
-TEST(OfflineTilePyramidRegionDefinition, TileCoverTileSize) {
- OfflineTilePyramidRegionDefinition region("", LatLngBounds::world(), 0, 0, 1.0);
+TEST(OfflineRegionDefinition, TileCoverTileSize) {
+ OfflineTilePyramidRegionDefinition region("", LatLngBounds::world(), {0, 0}, 1.0);
EXPECT_EQ((std::vector<CanonicalTileID>{ { 0, 0, 0 } }),
- region.tileCover(SourceType::Vector, 512, { 0, 22 }));
+ tileCover(region, SourceType::Vector, 512, { 0, 22 }));
EXPECT_EQ((std::vector<CanonicalTileID>{ { 1, 0, 0 }, { 1, 0, 1 }, { 1, 1, 0 }, { 1, 1, 1 } }),
- region.tileCover(SourceType::Vector, 256, { 0, 22 }));
+ tileCover(region, SourceType::Vector, 256, { 0, 22 }));
}
-TEST(OfflineTilePyramidRegionDefinition, TileCoverZoomRounding) {
- OfflineTilePyramidRegionDefinition region("", sanFrancisco, 0.6, 0.7, 1.0);
+TEST(OfflineRegionDefinition, TileCoverZoomRounding) {
+ OfflineTilePyramidRegionDefinition region("", sanFrancisco, {0.6, 0.7}, 1.0);
EXPECT_EQ((std::vector<CanonicalTileID>{ { 0, 0, 0 } }),
- region.tileCover(SourceType::Vector, 512, { 0, 22 }));
+ tileCover(region, SourceType::Vector, 512, { 0, 22 }));
EXPECT_EQ((std::vector<CanonicalTileID>{ { 1, 0, 0 } }),
- region.tileCover(SourceType::Raster, 512, { 0, 22 }));
+ tileCover(region, SourceType::Raster, 512, { 0, 22 }));
}
-TEST(OfflineTilePyramidRegionDefinition, TileCoverWrapped) {
- OfflineTilePyramidRegionDefinition region("", sanFranciscoWrapped, 0, 0, 1.0);
+TEST(OfflineRegionDefinition, TileCoverWrapped) {
+ OfflineTilePyramidRegionDefinition region("", sanFranciscoWrapped, {0, 0}, 1.0);
EXPECT_EQ((std::vector<CanonicalTileID>{ { 0, 0, 0 } }),
- region.tileCover(SourceType::Vector, 512, { 0, 22 }));
+ tileCover(region, SourceType::Vector, 512, { 0, 22 }));
+}
+
+TEST(OfflinePolygonRegionDefinition, EncodeDecode) {
+ Polygon<double> polygon { {
+ { 1, 1, },
+ { 2, 2, },
+ { 1.5, 2.5 }
+ } };
+ OfflineFixedGeometryRegionDefinition<Polygon<double>> region("", polygon, { 2, 2 }, 1.0);
+
+ auto encoded = encodeOfflineRegionDefinition(region);
+ auto decoded = decodeOfflineRegionDefinition(encoded).get<OfflineFixedGeometryRegionDefinition<Polygon<double>>>();
+
+ EXPECT_EQ(region.maxZoom, decoded.maxZoom);
+ EXPECT_EQ(region.minZoom, decoded.minZoom);
+ EXPECT_EQ(region.pixelRatio, decoded.pixelRatio);
+ EXPECT_EQ(region.styleURL, decoded.styleURL);
+ EXPECT_EQ(region.geometry, decoded.geometry);
}
+
diff --git a/test/storage/offline_database.cpp b/test/storage/offline_database.cpp
index 6a3262abf6..23f310769c 100644
--- a/test/storage/offline_database.cpp
+++ b/test/storage/offline_database.cpp
@@ -262,15 +262,16 @@ TEST(OfflineDatabase, CreateRegion) {
using namespace mbgl;
OfflineDatabase db(":memory:");
- OfflineRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 };
+ OfflineFixedGeometryRegionDefinition<LatLngBounds> definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), {5, 6}, 2.0 };
OfflineRegionMetadata metadata {{ 1, 2, 3 }};
OfflineRegion region = db.createRegion(definition, metadata);
-
- EXPECT_EQ(definition.styleURL, region.getDefinition().styleURL);
- EXPECT_EQ(definition.bounds, region.getDefinition().bounds);
- EXPECT_EQ(definition.minZoom, region.getDefinition().minZoom);
- EXPECT_EQ(definition.maxZoom, region.getDefinition().maxZoom);
- EXPECT_EQ(definition.pixelRatio, region.getDefinition().pixelRatio);
+
+ auto retrieved = region.getDefinition().get<OfflineFixedGeometryRegionDefinition<LatLngBounds>>();
+ EXPECT_EQ(definition.styleURL, retrieved.styleURL);
+ EXPECT_EQ(definition.geometry, retrieved.geometry);
+ EXPECT_EQ(definition.minZoom, retrieved.minZoom);
+ EXPECT_EQ(definition.maxZoom, retrieved.maxZoom);
+ EXPECT_EQ(definition.pixelRatio, retrieved.pixelRatio);
EXPECT_EQ(metadata, region.getMetadata());
}
@@ -278,7 +279,7 @@ TEST(OfflineDatabase, ListRegions) {
using namespace mbgl;
OfflineDatabase db(":memory:");
- OfflineRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 };
+ OfflineFixedGeometryRegionDefinition<LatLngBounds> definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), {5, 6}, 2.0 };
OfflineRegionMetadata metadata {{ 1, 2, 3 }};
OfflineRegion region = db.createRegion(definition, metadata);
@@ -286,11 +287,12 @@ TEST(OfflineDatabase, ListRegions) {
ASSERT_EQ(1u, regions.size());
EXPECT_EQ(region.getID(), regions.at(0).getID());
- EXPECT_EQ(definition.styleURL, regions.at(0).getDefinition().styleURL);
- EXPECT_EQ(definition.bounds, regions.at(0).getDefinition().bounds);
- EXPECT_EQ(definition.minZoom, regions.at(0).getDefinition().minZoom);
- EXPECT_EQ(definition.maxZoom, regions.at(0).getDefinition().maxZoom);
- EXPECT_EQ(definition.pixelRatio, regions.at(0).getDefinition().pixelRatio);
+ auto retrievedDefinition = regions.at(0).getDefinition().get<OfflineFixedGeometryRegionDefinition<LatLngBounds>>();
+ EXPECT_EQ(definition.styleURL, retrievedDefinition.styleURL);
+ EXPECT_EQ(definition.geometry, retrievedDefinition.geometry);
+ EXPECT_EQ(definition.minZoom, retrievedDefinition.minZoom);
+ EXPECT_EQ(definition.maxZoom, retrievedDefinition.maxZoom);
+ EXPECT_EQ(definition.pixelRatio, retrievedDefinition.pixelRatio);
EXPECT_EQ(metadata, regions.at(0).getMetadata());
}
@@ -298,24 +300,25 @@ TEST(OfflineDatabase, GetRegionDefinition) {
using namespace mbgl;
OfflineDatabase db(":memory:");
- OfflineRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 };
+ OfflineFixedGeometryRegionDefinition<LatLngBounds> definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), {5, 6}, 2.0 };
OfflineRegionMetadata metadata {{ 1, 2, 3 }};
OfflineRegion region = db.createRegion(definition, metadata);
- OfflineRegionDefinition result = db.getRegionDefinition(region.getID());
+ OfflineFixedGeometryRegionDefinition<LatLngBounds> result = db.getRegionDefinition(region.getID()).get<OfflineFixedGeometryRegionDefinition<LatLngBounds>>();
EXPECT_EQ(definition.styleURL, result.styleURL);
- EXPECT_EQ(definition.bounds, result.bounds);
+ EXPECT_EQ(definition.geometry, result.geometry);
EXPECT_EQ(definition.minZoom, result.minZoom);
EXPECT_EQ(definition.maxZoom, result.maxZoom);
EXPECT_EQ(definition.pixelRatio, result.pixelRatio);
+ EXPECT_EQ(metadata, region.getMetadata());
}
TEST(OfflineDatabase, DeleteRegion) {
using namespace mbgl;
OfflineDatabase db(":memory:");
- OfflineRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 };
+ OfflineFixedGeometryRegionDefinition<LatLngBounds> definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), {5, 6}, 2.0 };
OfflineRegionMetadata metadata {{ 1, 2, 3 }};
OfflineRegion region = db.createRegion(definition, metadata);
@@ -334,12 +337,12 @@ TEST(OfflineDatabase, CreateRegionInfiniteMaxZoom) {
using namespace mbgl;
OfflineDatabase db(":memory:");
- OfflineRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0 };
+ OfflineFixedGeometryRegionDefinition<LatLngBounds> definition { "", LatLngBounds::world(), {0, INFINITY}, 1.0 };
OfflineRegionMetadata metadata;
OfflineRegion region = db.createRegion(definition, metadata);
- EXPECT_EQ(0, region.getDefinition().minZoom);
- EXPECT_EQ(INFINITY, region.getDefinition().maxZoom);
+ EXPECT_EQ(0, region.getDefinition().get<OfflineFixedGeometryRegionDefinition<LatLngBounds>>().minZoom);
+ EXPECT_EQ(INFINITY, region.getDefinition().get<OfflineFixedGeometryRegionDefinition<LatLngBounds>>().maxZoom);
}
TEST(OfflineDatabase, TEST_REQUIRES_WRITE(ConcurrentUse)) {
@@ -423,7 +426,7 @@ TEST(OfflineDatabase, PutRegionResourceDoesNotEvict) {
using namespace mbgl;
OfflineDatabase db(":memory:", 1024 * 100);
- OfflineRegionDefinition definition { "", LatLngBounds::world(), 0, INFINITY, 1.0 };
+ OfflineFixedGeometryRegionDefinition<LatLngBounds> definition { "", LatLngBounds::world(), {0, INFINITY }, 1.0 };
OfflineRegion region = db.createRegion(definition, OfflineRegionMetadata());
Response response;
@@ -453,7 +456,7 @@ TEST(OfflineDatabase, GetRegionCompletedStatus) {
using namespace mbgl;
OfflineDatabase db(":memory:");
- OfflineRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 };
+ OfflineFixedGeometryRegionDefinition<LatLngBounds> definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), {5, 6}, 2.0 };
OfflineRegionMetadata metadata;
OfflineRegion region = db.createRegion(definition, metadata);
@@ -487,7 +490,7 @@ TEST(OfflineDatabase, OfflineMapboxTileCount) {
using namespace mbgl;
OfflineDatabase db(":memory:");
- OfflineRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 };
+ OfflineFixedGeometryRegionDefinition<LatLngBounds> definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), {5, 6}, 2.0 };
OfflineRegionMetadata metadata;
OfflineRegion region1 = db.createRegion(definition, metadata);
diff --git a/test/storage/offline_download.cpp b/test/storage/offline_download.cpp
index eb676e3b8d..43eb1db9b6 100644
--- a/test/storage/offline_download.cpp
+++ b/test/storage/offline_download.cpp
@@ -14,6 +14,8 @@
using namespace mbgl;
using namespace std::literals::string_literals;
+using OfflineTilePyramidRegionDefinition = OfflineFixedGeometryRegionDefinition<LatLngBounds>;
+
class MockObserver : public OfflineRegionObserver {
public:
void statusChanged(OfflineRegionStatus status) override {
@@ -41,7 +43,7 @@ public:
std::size_t size = 0;
OfflineRegion createRegion() {
- OfflineRegionDefinition definition { "", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 1.0 };
+ OfflineTilePyramidRegionDefinition definition { "", LatLngBounds::hull({1, 2}, {3, 4}), {5, 6}, 1.0 };
OfflineRegionMetadata metadata;
return db.createRegion(definition, metadata);
}
@@ -61,7 +63,7 @@ TEST(OfflineDownload, NoSubresources) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
test.fileSource.styleResponse = [&] (const Resource& resource) {
@@ -101,7 +103,7 @@ TEST(OfflineDownload, InlineSource) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
test.fileSource.styleResponse = [&] (const Resource& resource) {
@@ -141,7 +143,7 @@ TEST(OfflineDownload, GeoJSONSource) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
test.fileSource.styleResponse = [&] (const Resource& resource) {
@@ -176,7 +178,7 @@ TEST(OfflineDownload, Activate) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
test.fileSource.styleResponse = [&] (const Resource& resource) {
@@ -245,7 +247,7 @@ TEST(OfflineDownload, GetStatusNoResources) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
OfflineRegionStatus status = download.getStatus();
@@ -262,7 +264,7 @@ TEST(OfflineDownload, GetStatusStyleComplete) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
test.db.putRegionResource(1,
@@ -284,7 +286,7 @@ TEST(OfflineDownload, GetStatusStyleAndSourceComplete) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
test.db.putRegionResource(1,
@@ -310,7 +312,7 @@ TEST(OfflineDownload, RequestError) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
test.fileSource.styleResponse = [&] (const Resource&) {
@@ -338,7 +340,7 @@ TEST(OfflineDownload, RequestErrorsAreRetried) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
test.fileSource.styleResponse = [&] (const Resource&) {
@@ -371,7 +373,7 @@ TEST(OfflineDownload, TileCountLimitExceededNoTileResponse) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
uint64_t tileLimit = 0;
@@ -413,7 +415,7 @@ TEST(OfflineDownload, TileCountLimitExceededWithTileResponse) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
uint64_t tileLimit = 1;
@@ -467,7 +469,7 @@ TEST(OfflineDownload, WithPreviouslyExistingTile) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
test.fileSource.styleResponse = [&] (const Resource& resource) {
@@ -501,7 +503,7 @@ TEST(OfflineDownload, ReactivatePreviouslyCompletedDownload) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
test.fileSource.styleResponse = [&] (const Resource& resource) {
@@ -527,7 +529,7 @@ TEST(OfflineDownload, ReactivatePreviouslyCompletedDownload) {
OfflineDownload redownload(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
std::vector<OfflineRegionStatus> statusesAfterReactivate;
@@ -568,7 +570,7 @@ TEST(OfflineDownload, Deactivate) {
OfflineRegion region = test.createRegion();
OfflineDownload download(
region.getID(),
- OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0),
+ OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/style.json", LatLngBounds::world(), {0.0, 0.0}, 1.0),
test.db, test.fileSource);
test.fileSource.styleResponse = [&] (const Resource& resource) {