From 60d10dd27df38ac4e97214d1cd514198c381695c Mon Sep 17 00:00:00 2001 From: Asheem Mamoowala Date: Tue, 21 Feb 2017 18:34:45 -0800 Subject: [core] Add support for queryRenderedFeatures filter --- benchmark/api/query.benchmark.cpp | 4 +-- cmake/core-files.cmake | 2 +- include/mbgl/map/map.hpp | 8 +++--- include/mbgl/map/query.hpp | 19 ++++++++++++++ include/mbgl/style/filter.hpp | 3 +++ include/mbgl/style/filter_evaluator.hpp | 5 ++++ mapbox-gl-js | 2 +- platform/android/src/native_map_view.cpp | 4 +-- platform/ios/src/MGLMapView.mm | 4 +-- platform/macos/src/MGLMapView.mm | 4 +-- platform/node/src/node_map.cpp | 41 ++++++++++++++++++++++++++++-- platform/node/test/suite_implementation.js | 2 +- src/mbgl/geometry/feature_index.cpp | 19 +++++++++----- src/mbgl/geometry/feature_index.hpp | 6 +++-- src/mbgl/map/map.cpp | 21 +++++++-------- src/mbgl/style/query_parameters.hpp | 21 --------------- src/mbgl/style/source_impl.cpp | 16 +++++++----- src/mbgl/style/source_impl.hpp | 4 ++- src/mbgl/style/style.cpp | 12 +++++---- src/mbgl/style/style.hpp | 8 ++++-- src/mbgl/tile/geometry_tile.cpp | 5 ++-- src/mbgl/tile/geometry_tile.hpp | 2 +- src/mbgl/tile/tile.cpp | 3 ++- src/mbgl/tile/tile.hpp | 3 ++- test/api/annotations.test.cpp | 2 +- test/api/query.test.cpp | 29 +++++++++++++++++---- test/fixtures/api/query_style.json | 28 ++++++++++++++++++++ 27 files changed, 195 insertions(+), 82 deletions(-) create mode 100644 include/mbgl/map/query.hpp delete mode 100644 src/mbgl/style/query_parameters.hpp diff --git a/benchmark/api/query.benchmark.cpp b/benchmark/api/query.benchmark.cpp index f7474dd2ee..53a524b450 100644 --- a/benchmark/api/query.benchmark.cpp +++ b/benchmark/api/query.benchmark.cpp @@ -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" }}, {}}); } } diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index 5173b92c05..a9fe077db9 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -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 diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 95a82ebd74..7e4eeb8d5b 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -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 queryRenderedFeatures(const ScreenCoordinate&, const optional>& layerIDs = {}); - std::vector queryRenderedFeatures(const ScreenBox&, const optional>& layerIDs = {}); + std::vector queryRenderedFeatures(const ScreenCoordinate&, const QueryOptions& options = {}); + std::vector queryRenderedFeatures(const ScreenBox&, const QueryOptions& options = {}); + AnnotationIDs queryPointAnnotations(const ScreenBox&); // Memory diff --git a/include/mbgl/map/query.hpp b/include/mbgl/map/query.hpp new file mode 100644 index 0000000000..e864dbaa67 --- /dev/null +++ b/include/mbgl/map/query.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +namespace mbgl { + +/** + * Options for Map queries. + */ +class QueryOptions { +public: + /** layerIDs to include in the query */ + optional> layerIDs; + + optional filter; +}; + +} diff --git a/include/mbgl/style/filter.hpp b/include/mbgl/style/filter.hpp index 5e61adf064..a204a2b17a 100644 --- a/include/mbgl/style/filter.hpp +++ b/include/mbgl/style/filter.hpp @@ -266,6 +266,9 @@ public: bool operator()(const Feature&) const; + template + bool operator()(const GeometryTileFeature&) const; + template bool operator()(FeatureType type, optional id, PropertyAccessor accessor) const; }; diff --git a/include/mbgl/style/filter_evaluator.hpp b/include/mbgl/style/filter_evaluator.hpp index 370064445a..66223d7282 100644 --- a/include/mbgl/style/filter_evaluator.hpp +++ b/include/mbgl/style/filter_evaluator.hpp @@ -246,6 +246,11 @@ inline bool Filter::operator()(const Feature& feature) const { }); } +template +bool Filter::operator()(const GeometryTileFeature& feature) const { + return operator()(feature.getType(), feature.getID(), [&] (const auto& key) { return feature.getValue(key); }); +} + template bool Filter::operator()(FeatureType type, optional id, PropertyAccessor accessor) const { return FilterBase::visit(*this, FilterEvaluator { type, id, accessor }); diff --git a/mapbox-gl-js b/mapbox-gl-js index 7804faf897..f9c5c17592 160000 --- a/mapbox-gl-js +++ b/mapbox-gl-js @@ -1 +1 @@ -Subproject commit 7804faf89741cf7db90582d9e0881253cb9d4cd8 +Subproject commit f9c5c175926278a24f1b0d958867632023773ede diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 1930d1854d..73edc8e298 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -721,7 +721,7 @@ jni::Array> NativeMapView::queryRenderedFeaturesForPoint(JN } point point = {x, y}; - return *convert>, std::vector>(env, map->queryRenderedFeatures(point, layers)); + return *convert>, std::vector>(env, map->queryRenderedFeatures(point, { layers, {} })); } jni::Array> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, jni::jfloat right, jni::jfloat bottom, jni::Array layerIds) { @@ -734,7 +734,7 @@ jni::Array> NativeMapView::queryRenderedFeaturesForBox(JNIE } box box = { point{ left, top}, point{ right, bottom } }; - return *convert>, std::vector>(env, map->queryRenderedFeatures(box, layers)); + return *convert>, std::vector>(env, map->queryRenderedFeatures(box, { layers, {} })); } jni::Array> NativeMapView::getLayers(JNIEnv& env) { diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 58f8f407e4..2990a4e163 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -4621,7 +4621,7 @@ public: optionalLayerIDs = layerIDs; } - std::vector features = _mbglMap->queryRenderedFeatures(screenCoordinate, optionalLayerIDs); + std::vector features = _mbglMap->queryRenderedFeatures(screenCoordinate, { optionalLayerIDs, {} }); return MGLFeaturesFromMBGLFeatures(features); } @@ -4645,7 +4645,7 @@ public: optionalLayerIDs = layerIDs; } - std::vector features = _mbglMap->queryRenderedFeatures(screenBox, optionalLayerIDs); + std::vector features = _mbglMap->queryRenderedFeatures(screenBox, { optionalLayerIDs, {} }); return MGLFeaturesFromMBGLFeatures(features); } diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index 827da35076..ff98095e15 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -2533,7 +2533,7 @@ public: optionalLayerIDs = layerIDs; } - std::vector features = _mbglMap->queryRenderedFeatures(screenCoordinate, optionalLayerIDs); + std::vector features = _mbglMap->queryRenderedFeatures(screenCoordinate, { optionalLayerIDs }); return MGLFeaturesFromMBGLFeatures(features); } @@ -2558,7 +2558,7 @@ public: optionalLayerIDs = layerIDs; } - std::vector features = _mbglMap->queryRenderedFeatures(screenBox, optionalLayerIDs); + std::vector features = _mbglMap->queryRenderedFeatures(screenBox, { optionalLayerIDs }); return MGLFeaturesFromMBGLFeatures(features); } diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp index 66cdb3eda7..174db7d737 100644 --- a/platform/node/src/node_map.cpp +++ b/platform/node/src/node_map.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -866,6 +867,9 @@ void NodeMap::DumpDebugLogs(const Nan::FunctionCallbackInfo& info) { } void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo& info) { + using namespace mbgl::style; + using namespace mbgl::style::conversion; + auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -878,6 +882,39 @@ void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo& 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(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(); + std::vector 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 converted = convert(filterOption); + if (!converted) { + return Nan::ThrowTypeError(converted.error().message.c_str()); + } + queryOptions.filter = std::move(*converted); + } + } + try { std::vector result; @@ -894,13 +931,13 @@ void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo& 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(); diff --git a/platform/node/test/suite_implementation.js b/platform/node/test/suite_implementation.js index 6648757a98..ef97652893 100644 --- a/platform/node/test/suite_implementation.js +++ b/platform/node/test/suite_implementation.js @@ -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; diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index 5019d888ca..64fb7bd247 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include #include @@ -56,7 +59,7 @@ void FeatureIndex::query( const float bearing, const double tileSize, const double scale, - const optional>& 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 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>& result, const IndexedSubfeature& indexedFeature, const GeometryCoordinates& queryGeometry, - const optional>& 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)); } } diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp index ca813f4b6b..d2f68fd103 100644 --- a/src/mbgl/geometry/feature_index.hpp +++ b/src/mbgl/geometry/feature_index.hpp @@ -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>& layerIDs, + const QueryOptions& options, const GeometryTileData&, const CanonicalTileID&, const style::Style&, @@ -59,7 +61,7 @@ private: std::unordered_map>& result, const IndexedSubfeature&, const GeometryCoordinates& queryGeometry, - const optional>& filterLayerIDs, + const QueryOptions& options, const GeometryTileData&, const CanonicalTileID&, const style::Style&, diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 857f088b62..f4f4d67148 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -810,20 +809,20 @@ void Map::removeAnnotation(AnnotationID annotation) { #pragma mark - Feature query api -std::vector Map::queryRenderedFeatures(const ScreenCoordinate& point, const optional>& layerIDs) { +std::vector 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 Map::queryRenderedFeatures(const ScreenBox& box, const optional>& layerIDs) { +std::vector 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 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 set; for (auto &feature : features) { assert(feature.id); diff --git a/src/mbgl/style/query_parameters.hpp b/src/mbgl/style/query_parameters.hpp deleted file mode 100644 index 3c1abf3b70..0000000000 --- a/src/mbgl/style/query_parameters.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include - -#include - -namespace mbgl { - -class TransformState; - -namespace style { - -class QueryParameters { -public: - const ScreenLineString& geometry; - const TransformState& transformState; - const optional>& layerIDs; -}; - -} // namespace style -} // namespace mbgl diff --git a/src/mbgl/style/source_impl.cpp b/src/mbgl/style/source_impl.cpp index 003df4f6b1..22e51f8885 100644 --- a/src/mbgl/style/source_impl.cpp +++ b/src/mbgl/style/source_impl.cpp @@ -4,12 +4,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include @@ -200,17 +200,19 @@ void Source::Impl::reloadTiles() { } } -std::unordered_map> Source::Impl::queryRenderedFeatures(const QueryParameters& parameters) const { +std::unordered_map> Source::Impl::queryRenderedFeatures(const ScreenLineString& geometry, + const TransformState& transformState, + const QueryOptions& options) const { std::unordered_map> result; - if (renderTiles.empty() || parameters.geometry.empty()) { + if (renderTiles.empty() || geometry.empty()) { return result; } LineString 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 box = mapbox::geometry::envelope(queryGeometry); @@ -245,8 +247,8 @@ std::unordered_map> Source::Impl::queryRendere renderTile.tile.queryRenderedFeatures(result, tileSpaceQueryGeometry, - parameters.transformState, - parameters.layerIDs); + transformState, + options); } return result; diff --git a/src/mbgl/style/source_impl.hpp b/src/mbgl/style/source_impl.hpp index e6340ae1cb..ea2135c3c1 100644 --- a/src/mbgl/style/source_impl.hpp +++ b/src/mbgl/style/source_impl.hpp @@ -66,7 +66,9 @@ public: std::map& getRenderTiles(); std::unordered_map> - queryRenderedFeatures(const QueryParameters&) const; + queryRenderedFeatures(const ScreenLineString& geometry, + const TransformState& transformState, + const QueryOptions& options) const; void setCacheSize(size_t); void onLowMemory(); diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index b6f14ecf4b..aacf811f4d 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -31,6 +30,7 @@ #include #include #include +#include #include @@ -502,11 +502,13 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const return result; } -std::vector Style::queryRenderedFeatures(const QueryParameters& parameters) const { +std::vector Style::queryRenderedFeatures(const ScreenLineString& geometry, + const TransformState& transformState, + const QueryOptions& options) const { std::unordered_set 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 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())); } diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index 4c4bcec63a..5246f6877d 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -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 queryRenderedFeatures(const QueryParameters&) const; - + std::vector queryRenderedFeatures(const ScreenLineString& geometry, + const TransformState& transformState, + const QueryOptions& options) const; + float getQueryRadius() const; void setSourceTileCacheSize(size_t); diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 9aeb35c821..83d130841d 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace mbgl { @@ -141,7 +142,7 @@ void GeometryTile::queryRenderedFeatures( std::unordered_map>& result, const GeometryCoordinates& queryGeometry, const TransformState& transformState, - const optional>& 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, diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index c61a510311..85a068ee01 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -44,7 +44,7 @@ public: std::unordered_map>& result, const GeometryCoordinates& queryGeometry, const TransformState&, - const optional>& layerIDs) override; + const QueryOptions& options) override; void cancel() override; diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp index e84eaaf780..4829ac8355 100644 --- a/src/mbgl/tile/tile.cpp +++ b/src/mbgl/tile/tile.cpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace mbgl { @@ -32,6 +33,6 @@ void Tile::queryRenderedFeatures( std::unordered_map>&, const GeometryCoordinates&, const TransformState&, - const optional>&) {} + const QueryOptions&) {} } // namespace mbgl diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp index cebf913f56..0f0babf085 100644 --- a/src/mbgl/tile/tile.hpp +++ b/src/mbgl/tile/tile.hpp @@ -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>& result, const GeometryCoordinates& queryGeometry, const TransformState&, - const optional>& layerIDs); + const QueryOptions& options); void setTriedOptional(); diff --git a/test/api/annotations.test.cpp b/test/api/annotations.test.cpp index 6644e9c92c..30027d8610 100644 --- a/test/api/annotations.test.cpp +++ b/test/api/annotations.test.cpp @@ -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); diff --git a/test/api/query.test.cpp b/test/api/query.test.cpp index 4d2bf00f67..b42046fb48 100644 --- a/test/api/query.test.cpp +++ b/test/api/query.test.cpp @@ -10,6 +10,7 @@ #include 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); +} diff --git a/test/fixtures/api/query_style.json b/test/fixtures/api/query_style.json index 6978e1ba1b..4e11921775 100644 --- a/test/fixtures/api/query_style.json +++ b/test/fixtures/api/query_style.json @@ -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" + } } ] } -- cgit v1.2.1