Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

[core] Add support for queryRenderedFeatures filter #8246

Merged
merged 3 commits into from
Mar 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions benchmark/api/query.benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ static void API_queryRenderedFeaturesLayerFromLowDensity(::benchmark::State& sta
QueryBenchmark bench;

while (state.KeepRunning()) {
bench.map.queryRenderedFeatures(bench.box, {{ "testlayer" }});
bench.map.queryRenderedFeatures(bench.box, {{{ "testlayer" }}, {}});
}
}

static void API_queryRenderedFeaturesLayerFromHighDensity(::benchmark::State& state) {
QueryBenchmark bench;

while (state.KeepRunning()) {
bench.map.queryRenderedFeatures(bench.box, {{ "road-street" }});
bench.map.queryRenderedFeatures(bench.box, {{{"road-street" }}, {}});
}
}

Expand Down
2 changes: 1 addition & 1 deletion cmake/core-files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions include/mbgl/map/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -24,8 +25,6 @@ class View;
class FileSource;
class Scheduler;
class SpriteImage;
struct CameraOptions;
struct AnimationOptions;

namespace style {
class Source;
Expand Down Expand Up @@ -183,8 +182,9 @@ class Map : private util::noncopyable {
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
Expand Down
19 changes: 19 additions & 0 deletions include/mbgl/map/query.hpp
Original file line number Diff line number Diff line change
@@ -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;
};

}
3 changes: 3 additions & 0 deletions include/mbgl/style/filter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,9 @@ class Filter : public FilterBase {

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;
};
Expand Down
5 changes: 5 additions & 0 deletions include/mbgl/style/filter_evaluator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
import com.mapbox.mapboxsdk.style.layers.Filter;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.services.commons.geojson.Feature;
Expand Down Expand Up @@ -1674,7 +1675,23 @@ public void snapshot(@NonNull SnapshotReadyCallback callback) {
@NonNull
public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates, @Nullable String...
layerIds) {
return nativeMapView.queryRenderedFeatures(coordinates, layerIds);
return nativeMapView.queryRenderedFeatures(coordinates, layerIds, null);
}

/**
* Queries the map for rendered features
*
* @param coordinates the point to query
* @param filter filters the returned features
* @param layerIds optionally - only query these layers
* @return the list of feature
*/
@UiThread
@NonNull
public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates,
@Nullable Filter.Statement filter,
@Nullable String... layerIds) {
return nativeMapView.queryRenderedFeatures(coordinates, layerIds, filter);
}

/**
Expand All @@ -1686,9 +1703,25 @@ public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates, @Nullabl
*/
@UiThread
@NonNull
public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates, @Nullable String...
layerIds) {
return nativeMapView.queryRenderedFeatures(coordinates, layerIds);
public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates,
@Nullable String... layerIds) {
return nativeMapView.queryRenderedFeatures(coordinates, layerIds, null);
}

/**
* Queries the map for rendered features
*
* @param coordinates the box to query
* @param filter filters the returned features
* @param layerIds optionally - only query these layers
* @return the list of feature
*/
@UiThread
@NonNull
public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates,
@Nullable Filter.Statement filter,
@Nullable String... layerIds) {
return nativeMapView.queryRenderedFeatures(coordinates, layerIds, filter);
}

//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.mapbox.mapboxsdk.geometry.ProjectedMeters;
import com.mapbox.mapboxsdk.storage.FileSource;
import com.mapbox.mapboxsdk.style.layers.CannotAddLayerException;
import com.mapbox.mapboxsdk.style.layers.Filter;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.sources.CannotAddSourceException;
import com.mapbox.mapboxsdk.style.sources.Source;
Expand Down Expand Up @@ -881,27 +882,31 @@ public void removeImage(String name) {
// Feature querying

@NonNull
public List<Feature> queryRenderedFeatures(PointF coordinates, String... layerIds) {
public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates,
@Nullable String[] layerIds,
@Nullable Filter.Statement filter) {
if (isDestroyedOn("queryRenderedFeatures")) {
return new ArrayList<>();
}
Feature[] features = nativeQueryRenderedFeaturesForPoint(coordinates.x / pixelRatio,
coordinates.y / pixelRatio, layerIds);
coordinates.y / pixelRatio, layerIds, filter != null ? filter.toArray() : null);
return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
}

@NonNull
public List<Feature> queryRenderedFeatures(RectF coordinates, String... layerIds) {
public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates,
@Nullable String[] layerIds,
@Nullable Filter.Statement filter) {
if (isDestroyedOn("queryRenderedFeatures")) {
return new ArrayList<>();
}
Feature[] features = nativeQueryRenderedFeaturesForBox(

coordinates.left / pixelRatio,
coordinates.top / pixelRatio,
coordinates.right / pixelRatio,
coordinates.bottom / pixelRatio,
layerIds);
layerIds,
filter != null ? filter.toArray() : null);
return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
}

Expand Down Expand Up @@ -1139,12 +1144,14 @@ private native void nativeAddImage(String name, int width, int height, float pix

private native void nativeTakeSnapshot();

private native Feature[] nativeQueryRenderedFeaturesForPoint(float x, float y, String[]
layerIds);
private native Feature[] nativeQueryRenderedFeaturesForPoint(float x, float y,
String[] layerIds,
Object[] filter);

private native Feature[] nativeQueryRenderedFeaturesForBox(float left, float top,
float right, float bottom,
String[] layerIds);
String[] layerIds,
Object[] filter);

int getWidth() {
if (isDestroyedOn("")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
import com.mapbox.mapboxsdk.style.layers.Filter;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.services.commons.geojson.Feature;
Expand Down Expand Up @@ -53,7 +54,7 @@ public void onClick(View view) {
int left = selectionBox.getLeft() - mapView.getLeft();
RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
Timber.i(String.format("Querying box %s for buildings", box));
List<Feature> features = mapboxMap.queryRenderedFeatures(box, "building");
List<Feature> features = mapboxMap.queryRenderedFeatures(box, Filter.lt("height", 10), "building");

// Show count
Toast.makeText(
Expand Down
40 changes: 35 additions & 5 deletions platform/android/src/native_map_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,14 @@
#include <mbgl/util/logging.hpp>
#include <mbgl/util/platform.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/style/filter.hpp>

// Java -> C++ conversion
#include "style/android_conversion.hpp"
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/filter.hpp>

// C++ -> Java conversion
#include "conversion/conversion.hpp"
#include "conversion/collection.hpp"
#include "geometry/conversion/feature.hpp"
Expand Down Expand Up @@ -694,6 +701,9 @@ void NativeMapView::setTransitionDelay(JNIEnv&, jlong delay) {
}

jni::Array<jlong> NativeMapView::queryPointAnnotations(JNIEnv& env, jni::Object<RectF> rect) {
using namespace mbgl::style;
using namespace mbgl::style::conversion;

// Convert input
mbgl::ScreenBox box = {
{ RectF::getLeft(env, rect), RectF::getTop(env, rect) },
Expand All @@ -711,20 +721,40 @@ jni::Array<jlong> NativeMapView::queryPointAnnotations(JNIEnv& env, jni::Object<
return result;
}

jni::Array<jni::Object<Feature>> NativeMapView::queryRenderedFeaturesForPoint(JNIEnv& env, jni::jfloat x, jni::jfloat y, jni::Array<jni::String> layerIds) {
static inline optional<mbgl::style::Filter> toFilter(jni::JNIEnv& env, jni::Array<jni::Object<>> jfilter) {
using namespace mbgl::style;
using namespace mbgl::style::conversion;

mbgl::optional<Filter> filter;
if (jfilter) {
Value filterValue(env, jfilter);
auto converted = convert<Filter>(filterValue);
if (!converted) {
mbgl::Log::Error(mbgl::Event::JNI, "Error setting filter: " + converted.error().message);
}
filter = std::move(*converted);
}
return filter;
}

jni::Array<jni::Object<Feature>> NativeMapView::queryRenderedFeaturesForPoint(JNIEnv& env, jni::jfloat x, jni::jfloat y,
jni::Array<jni::String> layerIds,
jni::Array<jni::Object<>> jfilter) {
using namespace mbgl::android::conversion;
using namespace mapbox::geometry;

mbgl::optional<std::vector<std::string>> layers;
if (layerIds != nullptr && layerIds.Length(env) > 0) {
layers = toVector(env, layerIds);
layers = android::conversion::toVector(env, layerIds);
}
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, toFilter(env, jfilter) }));
}

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) {
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,
jni::Array<jni::Object<>> jfilter) {
using namespace mbgl::android::conversion;
using namespace mapbox::geometry;

Expand All @@ -734,7 +764,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, toFilter(env, jfilter) }));
}

jni::Array<jni::Object<Layer>> NativeMapView::getLayers(JNIEnv& env) {
Expand Down
8 changes: 6 additions & 2 deletions platform/android/src/native_map_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,13 @@ class NativeMapView : public View, public Backend {

jni::Array<jlong> queryPointAnnotations(JNIEnv&, jni::Object<RectF>);

jni::Array<jni::Object<Feature>> queryRenderedFeaturesForPoint(JNIEnv&, jni::jfloat, jni::jfloat, jni::Array<jni::String>);
jni::Array<jni::Object<Feature>> queryRenderedFeaturesForPoint(JNIEnv&, jni::jfloat, jni::jfloat,
jni::Array<jni::String>,
jni::Array<jni::Object<>> jfilter);

jni::Array<jni::Object<Feature>> queryRenderedFeaturesForBox(JNIEnv&, jni::jfloat, jni::jfloat, jni::jfloat, jni::jfloat, jni::Array<jni::String>);
jni::Array<jni::Object<Feature>> queryRenderedFeaturesForBox(JNIEnv&, jni::jfloat, jni::jfloat, jni::jfloat,
jni::jfloat, jni::Array<jni::String>,
jni::Array<jni::Object<>> jfilter);

jni::Array<jni::Object<Layer>> getLayers(JNIEnv&);

Expand Down
1 change: 1 addition & 0 deletions platform/ios/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Fixed an issue that sometimes caused crashes when the SDK interacted with the file system in the background. ([#8125](https://github.com/mapbox/mapbox-gl-native/pull/8125))
* Added a `MGLDistanceFormatter` class for formatting geographic distances. ([#7888](https://github.com/mapbox/mapbox-gl-native/pull/7888))
* Fixed an issue that was causing the system location indicator to stay on in background after telemetry was disabled. ([#7833](https://github.com/mapbox/mapbox-gl-native/pull/7833))
* Added support for predicates in rendered feature querying [8256](https://github.com/mapbox/mapbox-gl-native/pull/8246)

## 3.4.2 - February 21, 2017

Expand Down
Loading