[core] Add support for queryRenderedFeatures filter
This commit is contained in:
committed by
Ivo van Dongen
parent
ac4e13416a
commit
60d10dd27d
@@ -55,7 +55,7 @@ static void API_queryRenderedFeaturesLayerFromLowDensity(::benchmark::State& sta
|
||||
QueryBenchmark bench;
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
bench.map.queryRenderedFeatures(bench.box, {{ "testlayer" }});
|
||||
bench.map.queryRenderedFeatures(bench.box, {{{ "testlayer" }}, {}});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ static void API_queryRenderedFeaturesLayerFromHighDensity(::benchmark::State& st
|
||||
QueryBenchmark bench;
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
bench.map.queryRenderedFeatures(bench.box, {{ "road-street" }});
|
||||
bench.map.queryRenderedFeatures(bench.box, {{{"road-street" }}, {}});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ set(MBGL_CORE_FILES
|
||||
include/mbgl/map/camera.hpp
|
||||
include/mbgl/map/map.hpp
|
||||
include/mbgl/map/mode.hpp
|
||||
include/mbgl/map/query.hpp
|
||||
include/mbgl/map/view.hpp
|
||||
src/mbgl/map/backend.cpp
|
||||
src/mbgl/map/backend_scope.cpp
|
||||
@@ -271,7 +272,6 @@ set(MBGL_CORE_FILES
|
||||
src/mbgl/style/property_evaluator.hpp
|
||||
src/mbgl/style/property_parsing.cpp
|
||||
src/mbgl/style/property_parsing.hpp
|
||||
src/mbgl/style/query_parameters.hpp
|
||||
src/mbgl/style/rapidjson_conversion.hpp
|
||||
src/mbgl/style/source.cpp
|
||||
src/mbgl/style/source_impl.cpp
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <mbgl/annotation/annotation.hpp>
|
||||
#include <mbgl/style/transition_options.hpp>
|
||||
#include <mbgl/map/camera.hpp>
|
||||
#include <mbgl/map/query.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
@@ -24,8 +25,6 @@ class View;
|
||||
class FileSource;
|
||||
class Scheduler;
|
||||
class SpriteImage;
|
||||
struct CameraOptions;
|
||||
struct AnimationOptions;
|
||||
|
||||
namespace style {
|
||||
class Source;
|
||||
@@ -183,8 +182,9 @@ public:
|
||||
double getDefaultPitch() const;
|
||||
|
||||
// Feature queries
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate&, const optional<std::vector<std::string>>& layerIDs = {});
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenBox&, const optional<std::vector<std::string>>& layerIDs = {});
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate&, const QueryOptions& options = {});
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenBox&, const QueryOptions& options = {});
|
||||
|
||||
AnnotationIDs queryPointAnnotations(const ScreenBox&);
|
||||
|
||||
// Memory
|
||||
|
||||
19
include/mbgl/map/query.hpp
Normal file
19
include/mbgl/map/query.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/optional.hpp>
|
||||
#include <mbgl/style/filter.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
/**
|
||||
* Options for Map queries.
|
||||
*/
|
||||
class QueryOptions {
|
||||
public:
|
||||
/** layerIDs to include in the query */
|
||||
optional<std::vector<std::string>> layerIDs;
|
||||
|
||||
optional<style::Filter> filter;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -266,6 +266,9 @@ public:
|
||||
|
||||
bool operator()(const Feature&) const;
|
||||
|
||||
template <class GeometryTileFeature>
|
||||
bool operator()(const GeometryTileFeature&) const;
|
||||
|
||||
template <class PropertyAccessor>
|
||||
bool operator()(FeatureType type, optional<FeatureIdentifier> id, PropertyAccessor accessor) const;
|
||||
};
|
||||
|
||||
@@ -246,6 +246,11 @@ inline bool Filter::operator()(const Feature& feature) const {
|
||||
});
|
||||
}
|
||||
|
||||
template <class GeometryTileFeature>
|
||||
bool Filter::operator()(const GeometryTileFeature& feature) const {
|
||||
return operator()(feature.getType(), feature.getID(), [&] (const auto& key) { return feature.getValue(key); });
|
||||
}
|
||||
|
||||
template <class PropertyAccessor>
|
||||
bool Filter::operator()(FeatureType type, optional<FeatureIdentifier> id, PropertyAccessor accessor) const {
|
||||
return FilterBase::visit(*this, FilterEvaluator<PropertyAccessor> { type, id, accessor });
|
||||
|
||||
Submodule mapbox-gl-js updated: 7804faf897...f9c5c17592
@@ -721,7 +721,7 @@ jni::Array<jni::Object<Feature>> NativeMapView::queryRenderedFeaturesForPoint(JN
|
||||
}
|
||||
point<double> point = {x, y};
|
||||
|
||||
return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, map->queryRenderedFeatures(point, layers));
|
||||
return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, map->queryRenderedFeatures(point, { layers, {} }));
|
||||
}
|
||||
|
||||
jni::Array<jni::Object<Feature>> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, jni::jfloat right, jni::jfloat bottom, jni::Array<jni::String> layerIds) {
|
||||
@@ -734,7 +734,7 @@ jni::Array<jni::Object<Feature>> NativeMapView::queryRenderedFeaturesForBox(JNIE
|
||||
}
|
||||
box<double> box = { point<double>{ left, top}, point<double>{ right, bottom } };
|
||||
|
||||
return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, map->queryRenderedFeatures(box, layers));
|
||||
return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, map->queryRenderedFeatures(box, { layers, {} }));
|
||||
}
|
||||
|
||||
jni::Array<jni::Object<Layer>> NativeMapView::getLayers(JNIEnv& env) {
|
||||
|
||||
@@ -4621,7 +4621,7 @@ public:
|
||||
optionalLayerIDs = layerIDs;
|
||||
}
|
||||
|
||||
std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenCoordinate, optionalLayerIDs);
|
||||
std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenCoordinate, { optionalLayerIDs, {} });
|
||||
return MGLFeaturesFromMBGLFeatures(features);
|
||||
}
|
||||
|
||||
@@ -4645,7 +4645,7 @@ public:
|
||||
optionalLayerIDs = layerIDs;
|
||||
}
|
||||
|
||||
std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenBox, optionalLayerIDs);
|
||||
std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenBox, { optionalLayerIDs, {} });
|
||||
return MGLFeaturesFromMBGLFeatures(features);
|
||||
}
|
||||
|
||||
|
||||
@@ -2533,7 +2533,7 @@ public:
|
||||
optionalLayerIDs = layerIDs;
|
||||
}
|
||||
|
||||
std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenCoordinate, optionalLayerIDs);
|
||||
std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenCoordinate, { optionalLayerIDs });
|
||||
return MGLFeaturesFromMBGLFeatures(features);
|
||||
}
|
||||
|
||||
@@ -2558,7 +2558,7 @@ public:
|
||||
optionalLayerIDs = layerIDs;
|
||||
}
|
||||
|
||||
std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenBox, optionalLayerIDs);
|
||||
std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenBox, { optionalLayerIDs });
|
||||
return MGLFeaturesFromMBGLFeatures(features);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <mbgl/style/conversion/layer.hpp>
|
||||
#include <mbgl/style/conversion/filter.hpp>
|
||||
#include <mbgl/sprite/sprite_image.cpp>
|
||||
#include <mbgl/map/query.hpp>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -866,6 +867,9 @@ void NodeMap::DumpDebugLogs(const Nan::FunctionCallbackInfo<v8::Value>& info) {
|
||||
}
|
||||
|
||||
void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>& info) {
|
||||
using namespace mbgl::style;
|
||||
using namespace mbgl::style::conversion;
|
||||
|
||||
auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
|
||||
if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
|
||||
|
||||
@@ -878,6 +882,39 @@ void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>&
|
||||
return Nan::ThrowTypeError("First argument must have two components");
|
||||
}
|
||||
|
||||
mbgl::QueryOptions queryOptions;
|
||||
if (!info[1]->IsNull() && !info[1]->IsUndefined()) {
|
||||
if (!info[1]->IsObject()) {
|
||||
return Nan::ThrowTypeError("options argument must be an object");
|
||||
}
|
||||
|
||||
auto options = Nan::To<v8::Object>(info[1]).ToLocalChecked();
|
||||
|
||||
//Check if layers is set. If provided, it must be an array of strings
|
||||
if (Nan::Has(options, Nan::New("layers").ToLocalChecked()).FromJust()) {
|
||||
auto layersOption = Nan::Get(options, Nan::New("layers").ToLocalChecked()).ToLocalChecked();
|
||||
if (!layersOption->IsArray()) {
|
||||
return Nan::ThrowTypeError("Requires options.layers property to be an array");
|
||||
}
|
||||
auto layers = layersOption.As<v8::Array>();
|
||||
std::vector<std::string> layersVec;
|
||||
for (uint32_t i=0; i < layers->Length(); i++) {
|
||||
layersVec.push_back(*Nan::Utf8String(Nan::Get(layers,i).ToLocalChecked()));
|
||||
}
|
||||
queryOptions.layerIDs = layersVec;
|
||||
}
|
||||
|
||||
//Check if filter is provided. If set it must be a valid Filter object
|
||||
if (Nan::Has(options, Nan::New("filter").ToLocalChecked()).FromJust()) {
|
||||
auto filterOption = Nan::Get(options, Nan::New("filter").ToLocalChecked()).ToLocalChecked();
|
||||
Result<Filter> converted = convert<Filter>(filterOption);
|
||||
if (!converted) {
|
||||
return Nan::ThrowTypeError(converted.error().message.c_str());
|
||||
}
|
||||
queryOptions.filter = std::move(*converted);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
std::vector<mbgl::Feature> result;
|
||||
|
||||
@@ -894,13 +931,13 @@ void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>&
|
||||
Nan::Get(pos1, 0).ToLocalChecked()->NumberValue(),
|
||||
Nan::Get(pos1, 1).ToLocalChecked()->NumberValue()
|
||||
}
|
||||
});
|
||||
}, queryOptions);
|
||||
|
||||
} else {
|
||||
result = nodeMap->map->queryRenderedFeatures(mbgl::ScreenCoordinate {
|
||||
Nan::Get(posOrBox, 0).ToLocalChecked()->NumberValue(),
|
||||
Nan::Get(posOrBox, 1).ToLocalChecked()->NumberValue()
|
||||
});
|
||||
}, queryOptions);
|
||||
}
|
||||
|
||||
auto array = Nan::New<v8::Array>();
|
||||
|
||||
@@ -49,7 +49,7 @@ module.exports = function (style, options, callback) {
|
||||
applyOperations(options.operations, function() {
|
||||
map.render(options, function (err, pixels) {
|
||||
var results = options.queryGeometry ?
|
||||
map.queryRenderedFeatures(options.queryGeometry) :
|
||||
map.queryRenderedFeatures(options.queryGeometry, options.queryOptions || {}) :
|
||||
[];
|
||||
map.release();
|
||||
if (timedOut) return;
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include <mbgl/util/constants.hpp>
|
||||
#include <mbgl/util/math.hpp>
|
||||
#include <mbgl/math/minmax.hpp>
|
||||
#include <mbgl/map/query.hpp>
|
||||
#include <mbgl/style/filter.hpp>
|
||||
#include <mbgl/style/filter_evaluator.hpp>
|
||||
|
||||
#include <mapbox/geometry/envelope.hpp>
|
||||
|
||||
@@ -56,7 +59,7 @@ void FeatureIndex::query(
|
||||
const float bearing,
|
||||
const double tileSize,
|
||||
const double scale,
|
||||
const optional<std::vector<std::string>>& filterLayerIDs,
|
||||
const QueryOptions& queryOptions,
|
||||
const GeometryTileData& geometryTileData,
|
||||
const CanonicalTileID& tileID,
|
||||
const style::Style& style,
|
||||
@@ -76,7 +79,7 @@ void FeatureIndex::query(
|
||||
if (indexedFeature.sortIndex == previousSortIndex) continue;
|
||||
previousSortIndex = indexedFeature.sortIndex;
|
||||
|
||||
addFeature(result, indexedFeature, queryGeometry, filterLayerIDs, geometryTileData, tileID, style, bearing, pixelsToTileUnits);
|
||||
addFeature(result, indexedFeature, queryGeometry, queryOptions, geometryTileData, tileID, style, bearing, pixelsToTileUnits);
|
||||
}
|
||||
|
||||
// Query symbol features, if they've been placed.
|
||||
@@ -87,7 +90,7 @@ void FeatureIndex::query(
|
||||
std::vector<IndexedSubfeature> symbolFeatures = collisionTile->queryRenderedSymbols(queryGeometry, scale);
|
||||
std::sort(symbolFeatures.begin(), symbolFeatures.end(), topDownSymbols);
|
||||
for (const auto& symbolFeature : symbolFeatures) {
|
||||
addFeature(result, symbolFeature, queryGeometry, filterLayerIDs, geometryTileData, tileID, style, bearing, pixelsToTileUnits);
|
||||
addFeature(result, symbolFeature, queryGeometry, queryOptions, geometryTileData, tileID, style, bearing, pixelsToTileUnits);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +98,7 @@ void FeatureIndex::addFeature(
|
||||
std::unordered_map<std::string, std::vector<Feature>>& result,
|
||||
const IndexedSubfeature& indexedFeature,
|
||||
const GeometryCoordinates& queryGeometry,
|
||||
const optional<std::vector<std::string>>& filterLayerIDs,
|
||||
const QueryOptions& options,
|
||||
const GeometryTileData& geometryTileData,
|
||||
const CanonicalTileID& tileID,
|
||||
const style::Style& style,
|
||||
@@ -103,7 +106,7 @@ void FeatureIndex::addFeature(
|
||||
const float pixelsToTileUnits) const {
|
||||
|
||||
auto& layerIDs = bucketLayerIDs.at(indexedFeature.bucketName);
|
||||
if (filterLayerIDs && !vectorsIntersect(layerIDs, *filterLayerIDs)) {
|
||||
if (options.layerIDs && !vectorsIntersect(layerIDs, *options.layerIDs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -114,7 +117,7 @@ void FeatureIndex::addFeature(
|
||||
assert(geometryTileFeature);
|
||||
|
||||
for (const auto& layerID : layerIDs) {
|
||||
if (filterLayerIDs && !vectorContains(*filterLayerIDs, layerID)) {
|
||||
if (options.layerIDs && !vectorContains(*options.layerIDs, layerID)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -125,6 +128,10 @@ void FeatureIndex::addFeature(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (options.filter && !(*options.filter)(*geometryTileFeature)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result[layerID].push_back(convertFeature(*geometryTileFeature, tileID));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class QueryOptions;
|
||||
|
||||
namespace style {
|
||||
class Style;
|
||||
} // namespace style
|
||||
@@ -39,7 +41,7 @@ public:
|
||||
const float bearing,
|
||||
const double tileSize,
|
||||
const double scale,
|
||||
const optional<std::vector<std::string>>& layerIDs,
|
||||
const QueryOptions& options,
|
||||
const GeometryTileData&,
|
||||
const CanonicalTileID&,
|
||||
const style::Style&,
|
||||
@@ -59,7 +61,7 @@ private:
|
||||
std::unordered_map<std::string, std::vector<Feature>>& result,
|
||||
const IndexedSubfeature&,
|
||||
const GeometryCoordinates& queryGeometry,
|
||||
const optional<std::vector<std::string>>& filterLayerIDs,
|
||||
const QueryOptions& options,
|
||||
const GeometryTileData&,
|
||||
const CanonicalTileID&,
|
||||
const style::Style&,
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <mbgl/style/observer.hpp>
|
||||
#include <mbgl/style/transition_options.hpp>
|
||||
#include <mbgl/style/update_parameters.hpp>
|
||||
#include <mbgl/style/query_parameters.hpp>
|
||||
#include <mbgl/renderer/painter.hpp>
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
@@ -810,20 +809,20 @@ void Map::removeAnnotation(AnnotationID annotation) {
|
||||
|
||||
#pragma mark - Feature query api
|
||||
|
||||
std::vector<Feature> Map::queryRenderedFeatures(const ScreenCoordinate& point, const optional<std::vector<std::string>>& layerIDs) {
|
||||
std::vector<Feature> Map::queryRenderedFeatures(const ScreenCoordinate& point, const QueryOptions& options) {
|
||||
if (!impl->style) return {};
|
||||
|
||||
return impl->style->queryRenderedFeatures({
|
||||
return impl->style->queryRenderedFeatures(
|
||||
{ point },
|
||||
impl->transform.getState(),
|
||||
layerIDs
|
||||
});
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
std::vector<Feature> Map::queryRenderedFeatures(const ScreenBox& box, const optional<std::vector<std::string>>& layerIDs) {
|
||||
std::vector<Feature> Map::queryRenderedFeatures(const ScreenBox& box, const QueryOptions& options) {
|
||||
if (!impl->style) return {};
|
||||
|
||||
return impl->style->queryRenderedFeatures({
|
||||
return impl->style->queryRenderedFeatures(
|
||||
{
|
||||
box.min,
|
||||
{ box.max.x, box.min.y },
|
||||
@@ -832,12 +831,14 @@ std::vector<Feature> Map::queryRenderedFeatures(const ScreenBox& box, const opti
|
||||
box.min
|
||||
},
|
||||
impl->transform.getState(),
|
||||
layerIDs
|
||||
});
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
AnnotationIDs Map::queryPointAnnotations(const ScreenBox& box) {
|
||||
auto features = queryRenderedFeatures(box, {{ AnnotationManager::PointLayerID }});
|
||||
QueryOptions options;
|
||||
options.layerIDs = {{ AnnotationManager::PointLayerID }};
|
||||
auto features = queryRenderedFeatures(box, options);
|
||||
std::set<AnnotationID> set;
|
||||
for (auto &feature : features) {
|
||||
assert(feature.id);
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geo.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class TransformState;
|
||||
|
||||
namespace style {
|
||||
|
||||
class QueryParameters {
|
||||
public:
|
||||
const ScreenLineString& geometry;
|
||||
const TransformState& transformState;
|
||||
const optional<std::vector<std::string>>& layerIDs;
|
||||
};
|
||||
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
@@ -4,12 +4,12 @@
|
||||
#include <mbgl/renderer/render_tile.hpp>
|
||||
#include <mbgl/renderer/painter.hpp>
|
||||
#include <mbgl/style/update_parameters.hpp>
|
||||
#include <mbgl/style/query_parameters.hpp>
|
||||
#include <mbgl/text/placement_config.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
#include <mbgl/math/clamp.hpp>
|
||||
#include <mbgl/util/tile_cover.hpp>
|
||||
#include <mbgl/util/enum.hpp>
|
||||
#include <mbgl/map/query.hpp>
|
||||
|
||||
#include <mbgl/algorithm/update_renderables.hpp>
|
||||
#include <mbgl/algorithm/generate_clip_ids.hpp>
|
||||
@@ -200,17 +200,19 @@ void Source::Impl::reloadTiles() {
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::vector<Feature>> Source::Impl::queryRenderedFeatures(const QueryParameters& parameters) const {
|
||||
std::unordered_map<std::string, std::vector<Feature>> Source::Impl::queryRenderedFeatures(const ScreenLineString& geometry,
|
||||
const TransformState& transformState,
|
||||
const QueryOptions& options) const {
|
||||
std::unordered_map<std::string, std::vector<Feature>> result;
|
||||
if (renderTiles.empty() || parameters.geometry.empty()) {
|
||||
if (renderTiles.empty() || geometry.empty()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
LineString<double> queryGeometry;
|
||||
|
||||
for (const auto& p : parameters.geometry) {
|
||||
for (const auto& p : geometry) {
|
||||
queryGeometry.push_back(TileCoordinate::fromScreenCoordinate(
|
||||
parameters.transformState, 0, { p.x, parameters.transformState.getSize().height - p.y }).p);
|
||||
transformState, 0, { p.x, transformState.getSize().height - p.y }).p);
|
||||
}
|
||||
|
||||
mapbox::geometry::box<double> box = mapbox::geometry::envelope(queryGeometry);
|
||||
@@ -245,8 +247,8 @@ std::unordered_map<std::string, std::vector<Feature>> Source::Impl::queryRendere
|
||||
|
||||
renderTile.tile.queryRenderedFeatures(result,
|
||||
tileSpaceQueryGeometry,
|
||||
parameters.transformState,
|
||||
parameters.layerIDs);
|
||||
transformState,
|
||||
options);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -66,7 +66,9 @@ public:
|
||||
std::map<UnwrappedTileID, RenderTile>& getRenderTiles();
|
||||
|
||||
std::unordered_map<std::string, std::vector<Feature>>
|
||||
queryRenderedFeatures(const QueryParameters&) const;
|
||||
queryRenderedFeatures(const ScreenLineString& geometry,
|
||||
const TransformState& transformState,
|
||||
const QueryOptions& options) const;
|
||||
|
||||
void setCacheSize(size_t);
|
||||
void onLowMemory();
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <mbgl/style/layers/raster_layer.hpp>
|
||||
#include <mbgl/style/layer_impl.hpp>
|
||||
#include <mbgl/style/parser.hpp>
|
||||
#include <mbgl/style/query_parameters.hpp>
|
||||
#include <mbgl/style/transition_options.hpp>
|
||||
#include <mbgl/style/class_dictionary.hpp>
|
||||
#include <mbgl/style/update_parameters.hpp>
|
||||
@@ -31,6 +30,7 @@
|
||||
#include <mbgl/util/logging.hpp>
|
||||
#include <mbgl/util/math.hpp>
|
||||
#include <mbgl/math/minmax.hpp>
|
||||
#include <mbgl/map/query.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -502,11 +502,13 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Feature> Style::queryRenderedFeatures(const QueryParameters& parameters) const {
|
||||
std::vector<Feature> Style::queryRenderedFeatures(const ScreenLineString& geometry,
|
||||
const TransformState& transformState,
|
||||
const QueryOptions& options) const {
|
||||
std::unordered_set<std::string> sourceFilter;
|
||||
|
||||
if (parameters.layerIDs) {
|
||||
for (const auto& layerID : *parameters.layerIDs) {
|
||||
if (options.layerIDs) {
|
||||
for (const auto& layerID : *options.layerIDs) {
|
||||
auto layer = getLayer(layerID);
|
||||
if (layer) sourceFilter.emplace(layer->baseImpl->source);
|
||||
}
|
||||
@@ -520,7 +522,7 @@ std::vector<Feature> Style::queryRenderedFeatures(const QueryParameters& paramet
|
||||
continue;
|
||||
}
|
||||
|
||||
auto sourceResults = source->baseImpl->queryRenderedFeatures(parameters);
|
||||
auto sourceResults = source->baseImpl->queryRenderedFeatures(geometry, transformState, options);
|
||||
std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin()));
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ class GlyphAtlas;
|
||||
class SpriteAtlas;
|
||||
class LineAtlas;
|
||||
class RenderData;
|
||||
class TransformState;
|
||||
class QueryOptions;
|
||||
|
||||
namespace style {
|
||||
|
||||
@@ -95,8 +97,10 @@ public:
|
||||
|
||||
RenderData getRenderData(MapDebugOptions, float angle) const;
|
||||
|
||||
std::vector<Feature> queryRenderedFeatures(const QueryParameters&) const;
|
||||
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenLineString& geometry,
|
||||
const TransformState& transformState,
|
||||
const QueryOptions& options) const;
|
||||
|
||||
float getQueryRadius() const;
|
||||
|
||||
void setSourceTileCacheSize(size_t);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <mbgl/text/collision_tile.hpp>
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/map/query.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -141,7 +142,7 @@ void GeometryTile::queryRenderedFeatures(
|
||||
std::unordered_map<std::string, std::vector<Feature>>& result,
|
||||
const GeometryCoordinates& queryGeometry,
|
||||
const TransformState& transformState,
|
||||
const optional<std::vector<std::string>>& layerIDs) {
|
||||
const QueryOptions& options) {
|
||||
|
||||
if (!featureIndex || !data) return;
|
||||
|
||||
@@ -150,7 +151,7 @@ void GeometryTile::queryRenderedFeatures(
|
||||
transformState.getAngle(),
|
||||
util::tileSize * id.overscaleFactor(),
|
||||
std::pow(2, transformState.getZoom() - id.overscaledZ),
|
||||
layerIDs,
|
||||
options,
|
||||
*data,
|
||||
id.canonical,
|
||||
style,
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
std::unordered_map<std::string, std::vector<Feature>>& result,
|
||||
const GeometryCoordinates& queryGeometry,
|
||||
const TransformState&,
|
||||
const optional<std::vector<std::string>>& layerIDs) override;
|
||||
const QueryOptions& options) override;
|
||||
|
||||
void cancel() override;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <mbgl/renderer/debug_bucket.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
#include <mbgl/map/query.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -32,6 +33,6 @@ void Tile::queryRenderedFeatures(
|
||||
std::unordered_map<std::string, std::vector<Feature>>&,
|
||||
const GeometryCoordinates&,
|
||||
const TransformState&,
|
||||
const optional<std::vector<std::string>>&) {}
|
||||
const QueryOptions&) {}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -21,6 +21,7 @@ class DebugBucket;
|
||||
class TransformState;
|
||||
class TileObserver;
|
||||
class PlacementConfig;
|
||||
class QueryOptions;
|
||||
|
||||
namespace style {
|
||||
class Layer;
|
||||
@@ -55,7 +56,7 @@ public:
|
||||
std::unordered_map<std::string, std::vector<Feature>>& result,
|
||||
const GeometryCoordinates& queryGeometry,
|
||||
const TransformState&,
|
||||
const optional<std::vector<std::string>>& layerIDs);
|
||||
const QueryOptions& options);
|
||||
|
||||
void setTriedOptional();
|
||||
|
||||
|
||||
@@ -401,7 +401,7 @@ TEST(Annotations, VisibleFeatures) {
|
||||
test.map.setBearing(45);
|
||||
test::render(test.map, test.view);
|
||||
|
||||
auto features = test.map.queryRenderedFeatures(box);
|
||||
auto features = test.map.queryRenderedFeatures(box, {});
|
||||
auto sortID = [](const Feature& lhs, const Feature& rhs) { return lhs.id < rhs.id; };
|
||||
auto sameID = [](const Feature& lhs, const Feature& rhs) { return lhs.id == rhs.id; };
|
||||
std::sort(features.begin(), features.end(), sortID);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
using namespace mbgl;
|
||||
using namespace mbgl::style;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -39,7 +40,7 @@ TEST(Query, QueryRenderedFeatures) {
|
||||
QueryTest test;
|
||||
|
||||
auto features1 = test.map.queryRenderedFeatures(test.map.pixelForLatLng({ 0, 0 }));
|
||||
EXPECT_EQ(features1.size(), 3u);
|
||||
EXPECT_EQ(features1.size(), 4u);
|
||||
|
||||
auto features2 = test.map.queryRenderedFeatures(test.map.pixelForLatLng({ 9, 9 }));
|
||||
EXPECT_EQ(features2.size(), 0u);
|
||||
@@ -50,15 +51,33 @@ TEST(Query, QueryRenderedFeaturesFilterLayer) {
|
||||
|
||||
auto zz = test.map.pixelForLatLng({ 0, 0 });
|
||||
|
||||
auto features1 = test.map.queryRenderedFeatures(zz, {{ "layer1"}});
|
||||
auto features1 = test.map.queryRenderedFeatures(zz, {{{ "layer1"}}, {}});
|
||||
EXPECT_EQ(features1.size(), 1u);
|
||||
|
||||
auto features2 = test.map.queryRenderedFeatures(zz, {{ "layer1", "layer2" }});
|
||||
auto features2 = test.map.queryRenderedFeatures(zz, {{{ "layer1", "layer2" }}, {}});
|
||||
EXPECT_EQ(features2.size(), 2u);
|
||||
|
||||
auto features3 = test.map.queryRenderedFeatures(zz, {{ "foobar" }});
|
||||
auto features3 = test.map.queryRenderedFeatures(zz, {{{ "foobar" }}, {}});
|
||||
EXPECT_EQ(features3.size(), 0u);
|
||||
|
||||
auto features4 = test.map.queryRenderedFeatures(zz, {{ "foobar", "layer3" }});
|
||||
auto features4 = test.map.queryRenderedFeatures(zz, {{{ "foobar", "layer3" }}, {}});
|
||||
EXPECT_EQ(features4.size(), 1u);
|
||||
}
|
||||
|
||||
TEST(Query, QueryRenderedFeaturesFilter) {
|
||||
QueryTest test;
|
||||
|
||||
auto zz = test.map.pixelForLatLng({ 0, 0 });
|
||||
|
||||
const EqualsFilter eqFilter = { "key1", std::string("value1") };
|
||||
auto features1 = test.map.queryRenderedFeatures(zz, {{}, { eqFilter }});
|
||||
EXPECT_EQ(features1.size(), 1u);
|
||||
|
||||
const IdentifierNotEqualsFilter idNotEqFilter = { std::string("feature1") };
|
||||
auto features2 = test.map.queryRenderedFeatures(zz, {{{ "layer4" }}, { idNotEqFilter }});
|
||||
EXPECT_EQ(features2.size(), 0u);
|
||||
|
||||
const GreaterThanFilter gtFilter = { "key2", 1.0 };
|
||||
auto features3 = test.map.queryRenderedFeatures(zz, {{ }, { gtFilter }});
|
||||
EXPECT_EQ(features3.size(), 1u);
|
||||
}
|
||||
|
||||
28
test/fixtures/api/query_style.json
vendored
28
test/fixtures/api/query_style.json
vendored
@@ -30,6 +30,26 @@
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"source4": {
|
||||
"type": "geojson",
|
||||
"data": {
|
||||
"type": "Feature",
|
||||
"id": "feature1",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
},
|
||||
"properties": {
|
||||
"key1": "value1",
|
||||
"key2": 1.5,
|
||||
"key3": false,
|
||||
"key4": 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"layers": [
|
||||
@@ -56,6 +76,14 @@
|
||||
"layout": {
|
||||
"icon-image": "test-icon"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "layer4",
|
||||
"type": "symbol",
|
||||
"source": "source4",
|
||||
"layout": {
|
||||
"icon-image": "test-icon"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user