diff options
author | zmiao <miao.zhao@mapbox.com> | 2019-08-22 18:54:31 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-22 18:54:31 +0300 |
commit | 2a8359b0280e861450f9bdf390a01e0363202b3a (patch) | |
tree | 45787259e7f16199688f212f69a10c89dd2089cb /platform | |
parent | 4a5475b1c63843f35ac26ba3a17d58022c9b2777 (diff) | |
download | qtlocation-mapboxgl-2a8359b0280e861450f9bdf390a01e0363202b3a.tar.gz |
[android] bindings for aggregated cluster properties (#15425)
* [android] bindings for aggregated cluster properties
* [android] change the parameter type for adding clusterProperty
* [android] add changelog
* remove extra emplty line
Diffstat (limited to 'platform')
9 files changed, 92 insertions, 5 deletions
diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 54729fbcc5..ca57e48378 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -3,6 +3,8 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. ## master +### Features + - Introduce `clusterProperties` option for aggregated cluster properties. [#15425](https://github.com/mapbox/mapbox-gl-native/pull/15425) ## 8.3.0 This release changes how offline tile requests are billed — they are now billed on a pay-as-you-go basis and all developers are able raise the offline tile limit for their users. Offline requests were previously exempt from monthly active user (MAU) billing and increasing the offline per-user tile limit to more than 6,000 tiles required the purchase of an enterprise license. By upgrading to this release, you are opting into the changes outlined in [this blog post](https://blog.mapbox.com/offline-maps-for-all-bb0fc51827be) and [#15380](https://github.com/mapbox/mapbox-gl-native/pull/15380). diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java index 0f5ce76725..d6cddea066 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java @@ -1436,6 +1436,27 @@ public class Expression { } /** + * Gets the value of a cluster property accumulated so far. Can only be used in the clusterProperties + * option of a clustered GeoJSON source. + * <p> + * Example usage: + * </p> + * <pre> + * {@code + * GeoJsonOptions options = new GeoJsonOptions() + * .withCluster(true) + * .withClusterProperty("max", max(accumulated(), get("max")).toArray(), get("mag").toArray()); + * } + * </pre> + * + * @return expression + * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-accumulated">Style specification</a> + */ + public static Expression accumulated() { + return new Expression("accumulated"); + } + + /** * Gets the kernel density estimation of a pixel in a heatmap layer, * which is a relative measure of how many data points are crowded around a particular pixel. * Can only be used in the `heatmap-color` property. diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java index 1e1b9bafa6..091079ab92 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java @@ -1,9 +1,12 @@ package com.mapbox.mapboxsdk.style.sources; import android.support.annotation.NonNull; +import com.mapbox.mapboxsdk.style.expressions.Expression; import java.util.HashMap; +import static com.mapbox.mapboxsdk.style.expressions.Expression.ExpressionLiteral; + /** * Builder class for composing GeoJsonSource objects. * @@ -109,4 +112,28 @@ public class GeoJsonOptions extends HashMap<String, Object> { this.put("clusterRadius", clusterRadius); return this; } + + /** + * An object defining custom properties on the generated clusters if clustering is enabled, + * aggregating values from clustered points. Has the form {"property_name": [operator, [map_expression]]} or + * {"property_name": [[operator, accumulated, expression], [map_expression]]} + * + * @param propertyName name of the property + * @param operatorExpr operatorExpr is any expression function that accepts at least 2 operands (e.g. "+" or "max"). + * It accumulates the property value from clusters/points the cluster contains. It can either be + * a literal with single operator, or be a valid expression + * @param mapExpr map expression produces the value of a single point, it shall be a valid expression + * @return the current instance for chaining + */ + @NonNull + public GeoJsonOptions withClusterProperty(String propertyName, Expression operatorExpr, Expression mapExpr) { + HashMap<String, Object[]> properties = containsKey("clusterProperties") + ? (HashMap<String, Object[]>) get("clusterProperties") : new HashMap<String, Object[]>(); + Object operator = (operatorExpr instanceof ExpressionLiteral) + ? ((ExpressionLiteral)operatorExpr).toValue() : operatorExpr.toArray(); + Object map = mapExpr.toArray(); + properties.put(propertyName, new Object[]{operator, map}); + this.put("clusterProperties", properties); + return this; + } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java index 732a7929b8..cb2701d436 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java @@ -30,6 +30,8 @@ import java.util.List; import java.util.Objects; import static com.mapbox.mapboxsdk.style.expressions.Expression.all; +import static com.mapbox.mapboxsdk.style.expressions.Expression.accumulated; +import static com.mapbox.mapboxsdk.style.expressions.Expression.concat; import static com.mapbox.mapboxsdk.style.expressions.Expression.division; import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential; import static com.mapbox.mapboxsdk.style.expressions.Expression.get; @@ -39,6 +41,8 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.has; import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate; import static com.mapbox.mapboxsdk.style.expressions.Expression.literal; import static com.mapbox.mapboxsdk.style.expressions.Expression.lt; +import static com.mapbox.mapboxsdk.style.expressions.Expression.max; +import static com.mapbox.mapboxsdk.style.expressions.Expression.neq; import static com.mapbox.mapboxsdk.style.expressions.Expression.rgb; import static com.mapbox.mapboxsdk.style.expressions.Expression.stop; import static com.mapbox.mapboxsdk.style.expressions.Expression.toNumber; @@ -138,6 +142,9 @@ public class GeoJsonClusteringActivity extends AppCompatActivity { .withCluster(true) .withClusterMaxZoom(14) .withClusterRadius(50) + .withClusterProperty("max", max(accumulated(), get("max")), get("mag")) + .withClusterProperty("sum", literal("+"), get("mag")) + .withClusterProperty("felt", literal("any"), neq(get("felt"), literal("null"))) ); } @@ -182,9 +189,9 @@ public class GeoJsonClusteringActivity extends AppCompatActivity { } private SymbolLayer createClusterTextLayer() { - return new SymbolLayer("count", "earthquakes") + return new SymbolLayer("property", "earthquakes") .withProperties( - textField(Expression.toString(get("point_count"))), + textField(concat(get("point_count"), literal(", "), get("max"))), textSize(12f), textColor(Color.WHITE), textIgnorePlacement(true), diff --git a/platform/android/src/java_types.cpp b/platform/android/src/java_types.cpp index dd165470cf..7a1ba93a58 100644 --- a/platform/android/src/java_types.cpp +++ b/platform/android/src/java_types.cpp @@ -18,6 +18,10 @@ namespace java { jni::jclass* Map::jclass; jni::jmethodID* Map::getMethodId; + jni::jmethodID* Map::keySetMethodId; + + jni::jclass* Set::jclass; + jni::jmethodID* Set::toArrayMethodId; void registerNatives(JNIEnv& env) { ObjectArray::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "[Ljava/lang/Object;")).release(); @@ -34,6 +38,10 @@ namespace java { Map::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Map")).release(); Map::getMethodId = &jni::GetMethodID(env, *Map::jclass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); + Map::keySetMethodId = &jni::GetMethodID(env, *Map::jclass, "keySet", "()Ljava/util/Set;"); + + Set::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Set")).release(); + Set::toArrayMethodId = &jni::GetMethodID(env, *Set::jclass, "toArray", "()[Ljava/lang/Object;"); } } diff --git a/platform/android/src/java_types.hpp b/platform/android/src/java_types.hpp index edec5cb550..c7c93ce71b 100644 --- a/platform/android/src/java_types.hpp +++ b/platform/android/src/java_types.hpp @@ -29,6 +29,12 @@ namespace java { struct Map { static jni::jclass* jclass; static jni::jmethodID* getMethodId; + static jni::jmethodID* keySetMethodId; + }; + + struct Set { + static jni::jclass* jclass; + static jni::jmethodID* toArrayMethodId; }; void registerNatives(JNIEnv&); diff --git a/platform/android/src/style/android_conversion.hpp b/platform/android/src/style/android_conversion.hpp index 8559720b2f..d38dbfa684 100644 --- a/platform/android/src/style/android_conversion.hpp +++ b/platform/android/src/style/android_conversion.hpp @@ -47,9 +47,18 @@ public: } template <class Fn> - static optional<Error> eachMember(const mbgl::android::Value&, Fn&&) { - // TODO - mbgl::Log::Warning(mbgl::Event::Android, "eachMember not implemented"); + static optional<Error> eachMember(const mbgl::android::Value& value, Fn&& fn) { + assert(value.isObject()); + mbgl::android::Value keys = value.keyArray(); + std::size_t length = arrayLength(keys); + for(std::size_t i = 0; i < length; ++i){ + const auto k = keys.get(i).toString(); + auto v = value.get(k.c_str()); + optional<Error> result = fn(k, std::move(v)); + if (result) { + return result; + } + } return {}; } diff --git a/platform/android/src/style/value.cpp b/platform/android/src/style/value.cpp index f916909687..2f04840729 100644 --- a/platform/android/src/style/value.cpp +++ b/platform/android/src/style/value.cpp @@ -63,6 +63,12 @@ namespace android { return Value(env, jni::Local<jni::Object<>>(env, member)); } + Value Value::keyArray() const{ + jni::jobject* set = jni::CallMethod<jni::jobject*>(env, value.get(), *java::Map::keySetMethodId); + jni::jobject* array = jni::CallMethod<jni::jobject*>(env, set, *java::Set::toArrayMethodId); + return Value(env, jni::Local<jni::Object<>>(env, array)); + } + int Value::getLength() const { auto array = (jni::jarray<jni::jobject>*) value.get(); return jni::GetArrayLength(env, *array); diff --git a/platform/android/src/style/value.hpp b/platform/android/src/style/value.hpp index 0c702bb465..b507c5ed11 100644 --- a/platform/android/src/style/value.hpp +++ b/platform/android/src/style/value.hpp @@ -31,6 +31,7 @@ public: long toLong() const; bool toBool() const; Value get(const char* key) const; + Value keyArray() const; int getLength() const; Value get(const int index ) const; |