diff options
author | tobrun <tobrun.van.nuland@gmail.com> | 2018-08-23 15:41:58 +0200 |
---|---|---|
committer | tobrun <tobrun.van.nuland@gmail.com> | 2018-08-23 15:41:58 +0200 |
commit | 70971335a6e4273eb8e51e50f6b715de913988db (patch) | |
tree | f742fb75110554edf7429fc5d35b2b9ee1723ab6 | |
parent | 0e1fc6ff870b43c0423dbc1841abed66759df611 (diff) | |
download | qtlocation-mapboxgl-upstream/tvn-next-gen-cluster-android.tar.gz |
[android] - integrate supercluster api 0.3.0upstream/tvn-next-gen-cluster-android
4 files changed, 106 insertions, 12 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java index 2d9b1c985a..996e4007d7 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java @@ -270,7 +270,26 @@ public class GeoJsonSource extends Source { public List<Feature> querySourceFeatures(@Nullable Expression filter) { checkThread(); Feature[] features = querySourceFeatures(filter != null ? filter.toArray() : null); - return features != null ? Arrays.asList(features) : new ArrayList<Feature>(); + return features != null ? Arrays.asList(features) : new ArrayList<>(); + } + + @NonNull + public List<Feature> getChildren(long clusterId) { + checkThread(); + Feature[] features = nativeGetChildren(clusterId); + return features != null ? Arrays.asList(features) : new ArrayList<>(); + } + + @NonNull + public List<Feature> getLeaves(long clusterId, long limit, long offset) { + checkThread(); + Feature[] features = nativeGetLeaves(clusterId, limit, offset); + return features != null ? Arrays.asList(features) : new ArrayList<>(); + } + + public double getClusterExpansionZoom(long clusterId) { + checkThread(); + return nativeGetClusterExpansionZoom(clusterId); } @Keep @@ -297,6 +316,15 @@ public class GeoJsonSource extends Source { @Keep private native Feature[] querySourceFeatures(Object[] filter); + @Keep + private native Feature[] nativeGetChildren(long clusterId); + + @Keep + private native Feature[] nativeGetLeaves(long clusterId, long limit, long offset); + + @Keep + private native double nativeGetClusterExpansionZoom(long clusterId); + @Override @Keep protected native void finalize() throws Throwable; 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 a14a2b9589..54cd4ba91a 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 @@ -5,6 +5,7 @@ import android.os.Bundle; import android.support.v4.content.res.ResourcesCompat; import android.support.v7.app.AppCompatActivity; import android.view.MenuItem; +import com.mapbox.geojson.Feature; import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.maps.MapView; @@ -20,6 +21,7 @@ import timber.log.Timber; import java.net.MalformedURLException; import java.net.URL; +import java.util.List; import static com.mapbox.mapboxsdk.style.expressions.Expression.all; import static com.mapbox.mapboxsdk.style.expressions.Expression.division; @@ -36,7 +38,9 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.stop; import static com.mapbox.mapboxsdk.style.expressions.Expression.toNumber; import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor; import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleRadius; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap; import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconColor; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement; import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage; import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize; import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAllowOverlap; @@ -52,6 +56,7 @@ public class GeoJsonClusteringActivity extends AppCompatActivity { private MapView mapView; private MapboxMap mapboxMap; + private GeoJsonSource source; @Override protected void onCreate(Bundle savedInstanceState) { @@ -59,10 +64,8 @@ public class GeoJsonClusteringActivity extends AppCompatActivity { setContentView(R.layout.activity_geojson_clustering); // Initialize map as normal - mapView = (MapView) findViewById(R.id.mapView); - // noinspection ConstantConditions + mapView = findViewById(R.id.mapView); mapView.onCreate(savedInstanceState); - mapView.getMapAsync(map -> { mapboxMap = map; mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(37.7749, 122.4194), 0)); @@ -132,7 +135,7 @@ public class GeoJsonClusteringActivity extends AppCompatActivity { private void addClusteredGeoJsonSource() { // Add a clustered source try { - mapboxMap.addSource( + mapboxMap.addSource(source = new GeoJsonSource("earthquakes", new URL("https://www.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson"), new GeoJsonOptions() @@ -155,11 +158,8 @@ public class GeoJsonClusteringActivity extends AppCompatActivity { SymbolLayer unclustered = new SymbolLayer("unclustered-points", "earthquakes"); unclustered.setProperties( iconImage("icon-id"), - iconSize( - division( - get("mag"), literal(4.0f) - ) - ), + iconAllowOverlap(true), + iconIgnorePlacement(true), iconColor( interpolate(exponential(1), get("mag"), stop(2.0, rgb(0, 255, 0)), @@ -171,9 +171,13 @@ public class GeoJsonClusteringActivity extends AppCompatActivity { mapboxMap.addLayer(unclustered); + + String[] layerIds = new String[layers.length]; + for (int i = 0; i < layers.length; i++) { // Add some nice circles - CircleLayer circles = new CircleLayer("cluster-" + i, "earthquakes"); + layerIds[i] = "cluster-" + i; + CircleLayer circles = new CircleLayer(layerIds[i], "earthquakes"); circles.setProperties( circleColor(layers[i][1]), circleRadius(18f) @@ -204,7 +208,40 @@ public class GeoJsonClusteringActivity extends AppCompatActivity { mapboxMap.addLayer(count); + mapboxMap.addOnMapClickListener(point -> { + List<Feature> features = mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(point), layerIds); + if (!features.isEmpty()) { + moveCameraToClusterExpansion(features.get(0), point); + recursiveLoopClusterFeatures(features); + } + }); + // Zoom out to start mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(1)); } + + private void moveCameraToClusterExpansion(Feature feature, LatLng latLng){ + if (feature.hasProperty("cluster") && feature.getBooleanProperty("cluster")) { + double newZoom = source.getClusterExpansionZoom((long) feature.getNumberProperty("cluster_id")); + mapboxMap.animateCamera( + CameraUpdateFactory.newLatLngZoom(latLng, newZoom + 0.01), 750 + ); + } + } + + + private void recursiveLoopClusterFeatures(List<Feature> features) { + for (Feature feature : features) { + boolean cluster = feature.hasProperty("cluster") && feature.getBooleanProperty("cluster"); + if (cluster) { + long pointCount = (long) feature.getNumberProperty("point_count"); + long clusterId = (long) feature.getNumberProperty("cluster_id"); + double expansionZoom = source.getClusterExpansionZoom(clusterId); + Timber.e("Cluster=%s (id=%s) with %s points, cluster will expand at zoom %s", cluster, clusterId, pointCount, expansionZoom); + recursiveLoopClusterFeatures(source.getLeaves(clusterId, 10, 0)); + } else { + Timber.e("Point data: %s", feature.toJson()); + } + } + } } diff --git a/platform/android/src/style/sources/geojson_source.cpp b/platform/android/src/style/sources/geojson_source.cpp index e526231763..4f52c2812a 100644 --- a/platform/android/src/style/sources/geojson_source.cpp +++ b/platform/android/src/style/sources/geojson_source.cpp @@ -103,6 +103,26 @@ namespace android { return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, features); } + jni::Array<jni::Object<geojson::Feature>> GeoJSONSource::getChildren(jni::JNIEnv& env, jni::jlong clusterId) { + using namespace mbgl::android::conversion; + using namespace mbgl::android::geojson; + + std::vector<mbgl::Feature> features = source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::getChildren(clusterId); + return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, features); + } + + jni::Array<jni::Object<geojson::Feature>> GeoJSONSource::getLeaves(jni::JNIEnv& env, jni::jlong clusterId, jni::jlong limit, jni::jlong offset) { + using namespace mbgl::android::conversion; + using namespace mbgl::android::geojson; + + std::vector<mbgl::Feature> features = source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::getLeaves(clusterId, limit, offset); + return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, features); + } + + jni::jdouble GeoJSONSource::getClusterExpansionZoom(jni::JNIEnv&, jni::jlong clusterId) { + return source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::getClusterExpansionZoom(clusterId); + } + jni::Class<GeoJSONSource> GeoJSONSource::javaClass; jni::Object<Source> GeoJSONSource::createJavaPeer(jni::JNIEnv& env) { @@ -172,7 +192,10 @@ namespace android { METHOD(&GeoJSONSource::setGeometry, "nativeSetGeometry"), METHOD(&GeoJSONSource::setURL, "nativeSetUrl"), METHOD(&GeoJSONSource::getURL, "nativeGetUrl"), - METHOD(&GeoJSONSource::querySourceFeatures, "querySourceFeatures") + METHOD(&GeoJSONSource::querySourceFeatures, "querySourceFeatures"), + METHOD(&GeoJSONSource::getLeaves, "nativeGetLeaves"), + METHOD(&GeoJSONSource::getChildren, "nativeGetChildren"), + METHOD(&GeoJSONSource::getClusterExpansionZoom, "nativeGetClusterExpansionZoom") ); } diff --git a/platform/android/src/style/sources/geojson_source.hpp b/platform/android/src/style/sources/geojson_source.hpp index b9c360c67c..513d1fc09a 100644 --- a/platform/android/src/style/sources/geojson_source.hpp +++ b/platform/android/src/style/sources/geojson_source.hpp @@ -58,6 +58,12 @@ public: jni::Array<jni::Object<geojson::Feature>> querySourceFeatures(jni::JNIEnv&, jni::Array<jni::Object<>> jfilter); + jni::Array<jni::Object<geojson::Feature>> getChildren(jni::JNIEnv&, jni::jlong); + + jni::Array<jni::Object<geojson::Feature>> getLeaves(jni::JNIEnv&, jni::jlong, jni::jlong, jni::jlong); + + jni::jdouble getClusterExpansionZoom(jni::JNIEnv&, jni::jlong); + private: jni::Object<Source> createJavaPeer(jni::JNIEnv&); std::unique_ptr<Update> awaitingUpdate; |