From a1ca06e304a14582a90b258e817ec6f17d72fb11 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Wed, 14 Nov 2018 16:30:10 +0200 Subject: [core] Introduce Renderer::queryFeatureExtension API New interface allows it's users to query additional information about feature that was provided by qRF interface. This is particularly useful for clustered features. --- src/mbgl/renderer/render_source.hpp | 9 +++ src/mbgl/renderer/renderer.cpp | 8 ++ src/mbgl/renderer/renderer_impl.cpp | 11 +++ src/mbgl/renderer/renderer_impl.hpp | 6 ++ .../renderer/sources/render_geojson_source.cpp | 86 ++++++++++++++++++++++ .../renderer/sources/render_geojson_source.hpp | 7 ++ 6 files changed, 127 insertions(+) (limited to 'src') diff --git a/src/mbgl/renderer/render_source.hpp b/src/mbgl/renderer/render_source.hpp index dc80cb1dc6..31c26fd09a 100644 --- a/src/mbgl/renderer/render_source.hpp +++ b/src/mbgl/renderer/render_source.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +71,14 @@ public: virtual std::vector querySourceFeatures(const SourceQueryOptions&) const = 0; + virtual FeatureExtensionValue + queryFeatureExtensions(const Feature&, + const std::string&, + const std::string&, + const optional>&) const { + return {}; + } + virtual void reduceMemoryUse() = 0; virtual void dumpDebugLogs() const = 0; diff --git a/src/mbgl/renderer/renderer.cpp b/src/mbgl/renderer/renderer.cpp index 6b73e568fc..5a92a675c5 100644 --- a/src/mbgl/renderer/renderer.cpp +++ b/src/mbgl/renderer/renderer.cpp @@ -100,6 +100,14 @@ std::vector Renderer::querySourceFeatures(const std::string& sourceID, return impl->querySourceFeatures(sourceID, options); } +FeatureExtensionValue Renderer::queryFeatureExtensions(const std::string& sourceID, + const Feature& feature, + const std::string& extension, + const std::string& extensionField, + const optional>& args) const { + return impl->queryFeatureExtensions(sourceID, feature, extension, extensionField, args); +} + void Renderer::dumpDebugLogs() { impl->dumDebugLogs(); } diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index c844d1f87c..9058b0d62b 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -722,6 +722,17 @@ std::vector Renderer::Impl::querySourceFeatures(const std::string& sour return source->querySourceFeatures(options); } +FeatureExtensionValue Renderer::Impl::queryFeatureExtensions(const std::string& sourceID, + const Feature& feature, + const std::string& extension, + const std::string& extensionField, + const optional>& args) const { + if (RenderSource* renderSource = getRenderSource(sourceID)) { + return renderSource->queryFeatureExtensions(feature, extension, extensionField, args); + } + return {}; +} + void Renderer::Impl::reduceMemoryUse() { assert(BackendScope::exists()); for (const auto& entry : renderSources) { diff --git a/src/mbgl/renderer/renderer_impl.hpp b/src/mbgl/renderer/renderer_impl.hpp index 4124f6f416..4555ba27d5 100644 --- a/src/mbgl/renderer/renderer_impl.hpp +++ b/src/mbgl/renderer/renderer_impl.hpp @@ -53,6 +53,12 @@ public: std::vector querySourceFeatures(const std::string& sourceID, const SourceQueryOptions&) const; std::vector queryShapeAnnotations(const ScreenLineString&) const; + FeatureExtensionValue queryFeatureExtensions(const std::string& sourceID, + const Feature& feature, + const std::string& extension, + const std::string& extensionField, + const optional>& args) const; + void reduceMemoryUse(); void dumDebugLogs(); diff --git a/src/mbgl/renderer/sources/render_geojson_source.cpp b/src/mbgl/renderer/sources/render_geojson_source.cpp index 0099ebcf5e..a688026788 100644 --- a/src/mbgl/renderer/sources/render_geojson_source.cpp +++ b/src/mbgl/renderer/sources/render_geojson_source.cpp @@ -7,15 +7,74 @@ #include #include +#include + namespace mbgl { using namespace style; +namespace { + +template +optional getProperty(const C& cont, const typename C::key_type& name) { + const auto it = cont.find(name); + if (it == cont.end() || !(it->second.template is())) { + return nullopt; + } + return it->second.template get(); +} + +using FeatureExtensionGetterPtr = FeatureExtensionValue (*)(std::shared_ptr, + std::uint32_t, + const optional>&); + +FeatureExtensionValue getChildren(std::shared_ptr clusterData, + std::uint32_t clusterID, + const optional>&) { + return clusterData->getChildren(clusterID); +} + +FeatureExtensionValue getLeaves(std::shared_ptr clusterData, + std::uint32_t clusterID, + const optional>& args) { + if (args) { + const auto limit = getProperty(*args, "limit"); + const auto offset = getProperty(*args, "offset"); + // Offset cannot be set without limit. + if (limit) { + if (offset) { + return clusterData->getLeaves(clusterID, + static_cast(*limit), + static_cast(*offset)); + } + return clusterData->getLeaves(clusterID, static_cast(*limit)); + } + } + + return clusterData->getLeaves(clusterID); +} + +FeatureExtensionValue getClusterExpansionZoom(std::shared_ptr clusterData, + std::uint32_t clusterID, + const optional>&) { + return Value{static_cast(clusterData->getClusterExpansionZoom(clusterID))}; +} + +MAPBOX_ETERNAL_CONSTEXPR const auto extensionGetters = mapbox::eternal::hash_map({ + {"children", &getChildren}, + {"leaves", &getLeaves}, + {"expansion-zoom", &getClusterExpansionZoom} +}); + +} + RenderGeoJSONSource::RenderGeoJSONSource(Immutable impl_) : RenderSource(impl_) { tilePyramid.setObserver(this); } +RenderGeoJSONSource::~RenderGeoJSONSource() = default; + const style::GeoJSONSource::Impl& RenderGeoJSONSource::impl() const { return static_cast(*baseImpl); } @@ -94,6 +153,33 @@ std::vector RenderGeoJSONSource::querySourceFeatures(const SourceQueryO return tilePyramid.querySourceFeatures(options); } +mapbox::util::variant +RenderGeoJSONSource::queryFeatureExtensions(const Feature& feature, + const std::string& extension, + const std::string& extensionField, + const optional>& args) const { + if (extension != "supercluster") { + return {}; + } + + const auto extensionIt = extensionGetters.find(extensionField.c_str()); + if (extensionIt == extensionGetters.end()) { + return {}; + } + + const auto clusterID = getProperty(feature.properties, "cluster_id"); + if (!clusterID) { + return {}; + } + + auto jsonData = data.lock(); + if (!jsonData) { + return {}; + } + + return extensionIt->second(std::move(jsonData), static_cast(*clusterID), args); +} + void RenderGeoJSONSource::reduceMemoryUse() { tilePyramid.reduceMemoryUse(); } diff --git a/src/mbgl/renderer/sources/render_geojson_source.hpp b/src/mbgl/renderer/sources/render_geojson_source.hpp index 6351c5f6f8..c23559c09a 100644 --- a/src/mbgl/renderer/sources/render_geojson_source.hpp +++ b/src/mbgl/renderer/sources/render_geojson_source.hpp @@ -13,6 +13,7 @@ class GeoJSONData; class RenderGeoJSONSource : public RenderSource { public: RenderGeoJSONSource(Immutable); + ~RenderGeoJSONSource() final; bool isLoaded() const final; @@ -37,6 +38,12 @@ public: std::vector querySourceFeatures(const SourceQueryOptions&) const final; + FeatureExtensionValue + queryFeatureExtensions(const Feature& feature, + const std::string& extension, + const std::string& extensionField, + const optional>& args) const final; + void reduceMemoryUse() final; void dumpDebugLogs() const final; -- cgit v1.2.1