[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.
This commit is contained in:
Alexander Shalamov
2018-11-14 16:30:10 +02:00
parent 664ceb4398
commit a1ca06e304
8 changed files with 137 additions and 1 deletions

View File

@@ -4,7 +4,7 @@
#include <mbgl/renderer/mode.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/geojson.hpp>
#include <functional>
#include <memory>
@@ -44,6 +44,13 @@ public:
AnnotationIDs queryShapeAnnotations(const ScreenBox& box) const;
AnnotationIDs getAnnotationIDs(const std::vector<Feature>&) const;
// Feature extension query
FeatureExtensionValue queryFeatureExtensions(const std::string& sourceID,
const Feature& feature,
const std::string& extension,
const std::string& extensionField,
const optional<std::map<std::string, Value>>& args = {}) const;
// Debug
void dumpDebugLogs();

View File

@@ -1,10 +1,12 @@
#pragma once
#include <mapbox/geojson.hpp>
#include <mbgl/util/feature.hpp>
namespace mbgl {
using GeoJSON = mapbox::geojson::geojson;
using FeatureCollection = mapbox::geojson::feature_collection;
using FeatureExtensionValue = mapbox::util::variant<Value, FeatureCollection>;
} // namespace mbgl

View File

@@ -4,6 +4,7 @@
#include <mbgl/tile/tile_observer.hpp>
#include <mbgl/util/mat4.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/style/source_impl.hpp>
#include <mbgl/style/layer_impl.hpp>
@@ -70,6 +71,14 @@ public:
virtual std::vector<Feature>
querySourceFeatures(const SourceQueryOptions&) const = 0;
virtual FeatureExtensionValue
queryFeatureExtensions(const Feature&,
const std::string&,
const std::string&,
const optional<std::map<std::string, Value>>&) const {
return {};
}
virtual void reduceMemoryUse() = 0;
virtual void dumpDebugLogs() const = 0;

View File

@@ -100,6 +100,14 @@ std::vector<Feature> 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<std::map<std::string, Value>>& args) const {
return impl->queryFeatureExtensions(sourceID, feature, extension, extensionField, args);
}
void Renderer::dumpDebugLogs() {
impl->dumDebugLogs();
}

View File

@@ -722,6 +722,17 @@ std::vector<Feature> 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<std::map<std::string, Value>>& 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) {

View File

@@ -53,6 +53,12 @@ public:
std::vector<Feature> querySourceFeatures(const std::string& sourceID, const SourceQueryOptions&) const;
std::vector<Feature> queryShapeAnnotations(const ScreenLineString&) const;
FeatureExtensionValue queryFeatureExtensions(const std::string& sourceID,
const Feature& feature,
const std::string& extension,
const std::string& extensionField,
const optional<std::map<std::string, Value>>& args) const;
void reduceMemoryUse();
void dumDebugLogs();

View File

@@ -7,15 +7,74 @@
#include <mbgl/algorithm/generate_clip_ids.hpp>
#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
#include <mapbox/eternal.hpp>
namespace mbgl {
using namespace style;
namespace {
template<typename T, typename C>
optional<T> getProperty(const C& cont, const typename C::key_type& name) {
const auto it = cont.find(name);
if (it == cont.end() || !(it->second.template is<T>())) {
return nullopt;
}
return it->second.template get<T>();
}
using FeatureExtensionGetterPtr = FeatureExtensionValue (*)(std::shared_ptr<style::GeoJSONData>,
std::uint32_t,
const optional<std::map<std::string, Value>>&);
FeatureExtensionValue getChildren(std::shared_ptr<style::GeoJSONData> clusterData,
std::uint32_t clusterID,
const optional<std::map<std::string, Value>>&) {
return clusterData->getChildren(clusterID);
}
FeatureExtensionValue getLeaves(std::shared_ptr<style::GeoJSONData> clusterData,
std::uint32_t clusterID,
const optional<std::map<std::string, Value>>& args) {
if (args) {
const auto limit = getProperty<uint64_t>(*args, "limit");
const auto offset = getProperty<uint64_t>(*args, "offset");
// Offset cannot be set without limit.
if (limit) {
if (offset) {
return clusterData->getLeaves(clusterID,
static_cast<std::uint32_t>(*limit),
static_cast<std::uint32_t>(*offset));
}
return clusterData->getLeaves(clusterID, static_cast<std::uint32_t>(*limit));
}
}
return clusterData->getLeaves(clusterID);
}
FeatureExtensionValue getClusterExpansionZoom(std::shared_ptr<style::GeoJSONData> clusterData,
std::uint32_t clusterID,
const optional<std::map<std::string, Value>>&) {
return Value{static_cast<uint64_t>(clusterData->getClusterExpansionZoom(clusterID))};
}
MAPBOX_ETERNAL_CONSTEXPR const auto extensionGetters = mapbox::eternal::hash_map<mapbox::eternal::string, FeatureExtensionGetterPtr>({
{"children", &getChildren},
{"leaves", &getLeaves},
{"expansion-zoom", &getClusterExpansionZoom}
});
}
RenderGeoJSONSource::RenderGeoJSONSource(Immutable<style::GeoJSONSource::Impl> impl_)
: RenderSource(impl_) {
tilePyramid.setObserver(this);
}
RenderGeoJSONSource::~RenderGeoJSONSource() = default;
const style::GeoJSONSource::Impl& RenderGeoJSONSource::impl() const {
return static_cast<const style::GeoJSONSource::Impl&>(*baseImpl);
}
@@ -94,6 +153,33 @@ std::vector<Feature> RenderGeoJSONSource::querySourceFeatures(const SourceQueryO
return tilePyramid.querySourceFeatures(options);
}
mapbox::util::variant<Value, FeatureCollection>
RenderGeoJSONSource::queryFeatureExtensions(const Feature& feature,
const std::string& extension,
const std::string& extensionField,
const optional<std::map<std::string, Value>>& args) const {
if (extension != "supercluster") {
return {};
}
const auto extensionIt = extensionGetters.find(extensionField.c_str());
if (extensionIt == extensionGetters.end()) {
return {};
}
const auto clusterID = getProperty<uint64_t>(feature.properties, "cluster_id");
if (!clusterID) {
return {};
}
auto jsonData = data.lock();
if (!jsonData) {
return {};
}
return extensionIt->second(std::move(jsonData), static_cast<std::uint32_t>(*clusterID), args);
}
void RenderGeoJSONSource::reduceMemoryUse() {
tilePyramid.reduceMemoryUse();
}

View File

@@ -13,6 +13,7 @@ class GeoJSONData;
class RenderGeoJSONSource : public RenderSource {
public:
RenderGeoJSONSource(Immutable<style::GeoJSONSource::Impl>);
~RenderGeoJSONSource() final;
bool isLoaded() const final;
@@ -37,6 +38,12 @@ public:
std::vector<Feature>
querySourceFeatures(const SourceQueryOptions&) const final;
FeatureExtensionValue
queryFeatureExtensions(const Feature& feature,
const std::string& extension,
const std::string& extensionField,
const optional<std::map<std::string, Value>>& args) const final;
void reduceMemoryUse() final;
void dumpDebugLogs() const final;