diff options
Diffstat (limited to 'src/mbgl/style/sources')
-rw-r--r-- | src/mbgl/style/sources/geojson_source.cpp | 15 | ||||
-rw-r--r-- | src/mbgl/style/sources/geojson_source_impl.cpp | 85 | ||||
-rw-r--r-- | src/mbgl/style/sources/geojson_source_impl.hpp | 16 |
3 files changed, 75 insertions, 41 deletions
diff --git a/src/mbgl/style/sources/geojson_source.cpp b/src/mbgl/style/sources/geojson_source.cpp index a3eec4f4ef..2bf27880b4 100644 --- a/src/mbgl/style/sources/geojson_source.cpp +++ b/src/mbgl/style/sources/geojson_source.cpp @@ -4,17 +4,22 @@ namespace mbgl { namespace style { -GeoJSONSource::GeoJSONSource(const std::string& id) - : Source(SourceType::GeoJSON, std::make_unique<GeoJSONSource::Impl>(std::move(id), *this)) - , impl(static_cast<Impl*>(baseImpl.get())) { +GeoJSONSource::GeoJSONSource(const std::string& id, const GeoJSONOptions options) + : Source(SourceType::GeoJSON, + std::make_unique<GeoJSONSource::Impl>(std::move(id), *this, options)), + impl(static_cast<Impl*>(baseImpl.get())) { } void GeoJSONSource::setURL(const std::string& url) { impl->setURL(url); } -void GeoJSONSource::setGeoJSON(GeoJSON&& geoJSON) { - impl->setGeoJSON(std::move(geoJSON)); +void GeoJSONSource::setGeoJSON(const mapbox::geojson::geojson& geoJSON) { + impl->setGeoJSON(geoJSON); +} + +std::string GeoJSONSource::getURL() { + return impl->getURL(); } } // namespace style diff --git a/src/mbgl/style/sources/geojson_source_impl.cpp b/src/mbgl/style/sources/geojson_source_impl.cpp index 9e6b3d34f6..0821ac0232 100644 --- a/src/mbgl/style/sources/geojson_source_impl.cpp +++ b/src/mbgl/style/sources/geojson_source_impl.cpp @@ -1,43 +1,37 @@ -#include <mbgl/style/sources/geojson_source_impl.hpp> -#include <mbgl/style/source_observer.hpp> +#include <mbgl/platform/log.hpp> +#include <mbgl/storage/file_source.hpp> #include <mbgl/style/conversion/geojson.hpp> +#include <mbgl/style/source_observer.hpp> +#include <mbgl/style/sources/geojson_source_impl.hpp> #include <mbgl/tile/geojson_tile.hpp> -#include <mbgl/storage/file_source.hpp> -#include <mbgl/platform/log.hpp> #include <mbgl/util/rapidjson.hpp> #include <mapbox/geojson.hpp> #include <mapbox/geojson/rapidjson.hpp> #include <mapbox/geojsonvt.hpp> #include <mapbox/geojsonvt/convert.hpp> +#include <supercluster.hpp> #include <rapidjson/error/en.h> #include <sstream> -using namespace mapbox::geojsonvt; - namespace mbgl { namespace style { namespace conversion { template <> Result<GeoJSON> convertGeoJSON(const JSValue& value) { - Options options; - options.buffer = util::EXTENT / util::tileSize * 128; - options.extent = util::EXTENT; - try { - const auto geojson = mapbox::geojson::convert(value); - return GeoJSON { std::make_unique<GeoJSONVT>(geojson, options) }; + return mapbox::geojson::convert(value); } catch (const std::exception& ex) { - return Error { ex.what() }; + return Error{ ex.what() }; } } } // namespace conversion -GeoJSONSource::Impl::Impl(std::string id_, Source& base_) - : Source::Impl(SourceType::GeoJSON, std::move(id_), base_) { +GeoJSONSource::Impl::Impl(std::string id_, Source& base_, const GeoJSONOptions options_) + : Source::Impl(SourceType::GeoJSON, std::move(id_), base_), options(options_) { } GeoJSONSource::Impl::~Impl() = default; @@ -46,12 +40,36 @@ void GeoJSONSource::Impl::setURL(std::string url) { urlOrGeoJSON = std::move(url); } -void GeoJSONSource::Impl::setGeoJSON(GeoJSON&& geoJSON) { - urlOrGeoJSON = std::move(geoJSON); +std::string GeoJSONSource::Impl::getURL() { + assert(urlOrGeoJSON.is<std::string>()); + return urlOrGeoJSON.get<std::string>(); +} + +void GeoJSONSource::Impl::setGeoJSON(const GeoJSON& geoJSON) { + double scale = util::EXTENT / util::tileSize; + + if (!options.cluster) { + mapbox::geojsonvt::Options vtOptions; + vtOptions.maxZoom = options.maxzoom; + vtOptions.extent = util::EXTENT; + vtOptions.buffer = std::round(scale * options.buffer); + vtOptions.tolerance = scale * options.tolerance; + urlOrGeoJSON = std::make_unique<mapbox::geojsonvt::GeoJSONVT>(geoJSON, vtOptions); + + } else { + mapbox::supercluster::Options clusterOptions; + clusterOptions.maxZoom = options.clusterMaxZoom; + clusterOptions.extent = util::EXTENT; + clusterOptions.radius = std::round(scale * options.clusterRadius); + + const auto& features = geoJSON.get<mapbox::geometry::feature_collection<double>>(); + urlOrGeoJSON = + std::make_unique<mapbox::supercluster::Supercluster>(features, clusterOptions); + } } void GeoJSONSource::Impl::load(FileSource& fileSource) { - if (urlOrGeoJSON.is<GeoJSON>()) { + if (!urlOrGeoJSON.is<std::string>()) { loaded = true; return; } @@ -63,19 +81,23 @@ void GeoJSONSource::Impl::load(FileSource& fileSource) { const std::string& url = urlOrGeoJSON.get<std::string>(); req = fileSource.request(Resource::source(url), [this](Response res) { if (res.error) { - observer->onSourceError(base, std::make_exception_ptr(std::runtime_error(res.error->message))); + observer->onSourceError( + base, std::make_exception_ptr(std::runtime_error(res.error->message))); } else if (res.notModified) { return; } else if (res.noContent) { - observer->onSourceError(base, std::make_exception_ptr(std::runtime_error("unexpectedly empty GeoJSON"))); + observer->onSourceError( + base, std::make_exception_ptr(std::runtime_error("unexpectedly empty GeoJSON"))); } else { rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> d; d.Parse<0>(res.data->c_str()); if (d.HasParseError()) { std::stringstream message; - message << d.GetErrorOffset() << " - " << rapidjson::GetParseError_En(d.GetParseError()); - observer->onSourceError(base, std::make_exception_ptr(std::runtime_error(message.str()))); + message << d.GetErrorOffset() << " - " + << rapidjson::GetParseError_En(d.GetParseError()); + observer->onSourceError(base, + std::make_exception_ptr(std::runtime_error(message.str()))); return; } @@ -83,13 +105,13 @@ void GeoJSONSource::Impl::load(FileSource& fileSource) { conversion::Result<GeoJSON> geoJSON = conversion::convertGeoJSON<JSValue>(d); if (!geoJSON) { - Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s", geoJSON.error().message.c_str()); + Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s", + geoJSON.error().message.c_str()); // Create an empty GeoJSON VT object to make sure we're not infinitely waiting for // tiles to load. - mapbox::geojson::feature_collection features; - urlOrGeoJSON = GeoJSON { std::make_unique<GeoJSONVT>(features) }; + setGeoJSON(GeoJSON{ FeatureCollection{} }); } else { - urlOrGeoJSON = std::move(*geoJSON); + setGeoJSON(*geoJSON); } loaded = true; @@ -100,13 +122,20 @@ void GeoJSONSource::Impl::load(FileSource& fileSource) { Range<uint8_t> GeoJSONSource::Impl::getZoomRange() { assert(loaded); - return { 0, urlOrGeoJSON.get<GeoJSON>().impl->options.maxZoom }; + return { 0, options.maxzoom }; } std::unique_ptr<Tile> GeoJSONSource::Impl::createTile(const OverscaledTileID& tileID, const UpdateParameters& parameters) { assert(loaded); - return std::make_unique<GeoJSONTile>(tileID, base.getID(), parameters, *urlOrGeoJSON.get<GeoJSON>().impl); + if (urlOrGeoJSON.is<GeoJSONVTPointer>()) { + return std::make_unique<GeoJSONTile>(tileID, base.getID(), parameters, + *urlOrGeoJSON.get<GeoJSONVTPointer>()); + } else { + assert(urlOrGeoJSON.is<SuperclusterPointer>()); + return std::make_unique<GeoJSONTile>(tileID, base.getID(), parameters, + *urlOrGeoJSON.get<SuperclusterPointer>()); + } } } // namespace style diff --git a/src/mbgl/style/sources/geojson_source_impl.hpp b/src/mbgl/style/sources/geojson_source_impl.hpp index e6e01c06e9..eb3563e85a 100644 --- a/src/mbgl/style/sources/geojson_source_impl.hpp +++ b/src/mbgl/style/sources/geojson_source_impl.hpp @@ -1,7 +1,7 @@ #pragma once -#include <mbgl/style/sources/geojson_source.hpp> #include <mbgl/style/source_impl.hpp> +#include <mbgl/style/sources/geojson_source.hpp> #include <mbgl/util/variant.hpp> namespace mbgl { @@ -12,11 +12,13 @@ namespace style { class GeoJSONSource::Impl : public Source::Impl { public: - Impl(std::string id, Source&); + Impl(std::string id, Source&, const GeoJSONOptions); ~Impl() final; void setURL(std::string); - void setGeoJSON(GeoJSON&&); + void setGeoJSON(const GeoJSON&); + + std::string getURL(); void load(FileSource&) final; @@ -24,16 +26,14 @@ public: return util::tileSize; } - const variant<std::string, GeoJSON>& getURLOrGeoJSON() const { - return urlOrGeoJSON; - } - private: Range<uint8_t> getZoomRange() final; std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) final; - variant<std::string, GeoJSON> urlOrGeoJSON; + variant<std::string, GeoJSONVTPointer, SuperclusterPointer> urlOrGeoJSON; std::unique_ptr<AsyncRequest> req; + + GeoJSONOptions options; }; } // namespace style |