diff options
Diffstat (limited to 'platform/android')
5 files changed, 1264 insertions, 0 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/HeatmapLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/HeatmapLayer.java new file mode 100644 index 0000000000..bfc663449f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/HeatmapLayer.java @@ -0,0 +1,249 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. + +package com.mapbox.mapboxsdk.style.layers; + +import android.support.annotation.ColorInt; +import android.support.annotation.NonNull; +import android.support.annotation.UiThread; + +import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor; + +import com.mapbox.mapboxsdk.style.layers.TransitionOptions; + +/** + * A heatmap. + * + * @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#layers-heatmap">The online documentation</a> + */ +@UiThread +public class HeatmapLayer extends Layer { + + /** + * Creates a HeatmapLayer. + * + * @param nativePtr pointer used by core + */ + public HeatmapLayer(long nativePtr) { + super(nativePtr); + } + + /** + * Creates a HeatmapLayer. + * + * @param layerId the id of the layer + * @param sourceId the id of the source + */ + public HeatmapLayer(String layerId, String sourceId) { + initialize(layerId, sourceId); + } + + protected native void initialize(String layerId, String sourceId); + + /** + * Set the source layer. + * + * @param sourceLayer the source layer to set + */ + public void setSourceLayer(String sourceLayer) { + nativeSetSourceLayer(sourceLayer); + } + + /** + * Set the source Layer. + * + * @param sourceLayer the source layer to set + * @return This + */ + public HeatmapLayer withSourceLayer(String sourceLayer) { + setSourceLayer(sourceLayer); + return this; + } + + /** + * Get the source layer. + * + * @return sourceLayer the source layer to get + */ + public String getSourceLayer() { + return nativeGetSourceLayer(); + } + + /** + * Set a single filter. + * + * @param filter the filter to set + */ + public void setFilter(Filter.Statement filter) { + nativeSetFilter(filter.toArray()); + } + + /** + * Set a single filter. + * + * @param filter the filter to set + * @return This + */ + public HeatmapLayer withFilter(Filter.Statement filter) { + setFilter(filter); + return this; + } + + /** + * Set a property or properties. + * + * @param properties the var-args properties + * @return This + */ + public HeatmapLayer withProperties(@NonNull PropertyValue<?>... properties) { + setProperties(properties); + return this; + } + + // Property getters + + /** + * Get the HeatmapRadius property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getHeatmapRadius() { + return (PropertyValue<Float>) new PropertyValue("heatmap-radius", nativeGetHeatmapRadius()); + } + + /** + * Get the HeatmapRadius property transition options + * + * @return transition options for Float + */ + public TransitionOptions getHeatmapRadiusTransition() { + return nativeGetHeatmapRadiusTransition(); + } + + /** + * Set the HeatmapRadius property transition options + * + * @param options transition options for Float + */ + public void setHeatmapRadiusTransition(TransitionOptions options) { + nativeSetHeatmapRadiusTransition(options.getDuration(), options.getDelay()); + } + + /** + * Get the HeatmapWeight property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getHeatmapWeight() { + return (PropertyValue<Float>) new PropertyValue("heatmap-weight", nativeGetHeatmapWeight()); + } + + /** + * Get the HeatmapIntensity property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getHeatmapIntensity() { + return (PropertyValue<Float>) new PropertyValue("heatmap-intensity", nativeGetHeatmapIntensity()); + } + + /** + * Get the HeatmapIntensity property transition options + * + * @return transition options for Float + */ + public TransitionOptions getHeatmapIntensityTransition() { + return nativeGetHeatmapIntensityTransition(); + } + + /** + * Set the HeatmapIntensity property transition options + * + * @param options transition options for Float + */ + public void setHeatmapIntensityTransition(TransitionOptions options) { + nativeSetHeatmapIntensityTransition(options.getDuration(), options.getDelay()); + } + + /** + * Get the HeatmapColor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getHeatmapColor() { + return (PropertyValue<String>) new PropertyValue("heatmap-color", nativeGetHeatmapColor()); + } + + /** + * Defines the color of each pixel based on its density value in a heatmap. Should be an expression that uses `["heatmap-density"]` as input. + * + * @return int representation of a rgba string color + * @throws RuntimeException thrown if property isn't a value + */ + @ColorInt + public int getHeatmapColorAsInt() { + PropertyValue<String> value = getHeatmapColor(); + if (value.isValue()) { + return rgbaToColor(value.getValue()); + } else { + throw new RuntimeException("heatmap-color was set as a Function"); + } + } + + /** + * Get the HeatmapOpacity property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getHeatmapOpacity() { + return (PropertyValue<Float>) new PropertyValue("heatmap-opacity", nativeGetHeatmapOpacity()); + } + + /** + * Get the HeatmapOpacity property transition options + * + * @return transition options for Float + */ + public TransitionOptions getHeatmapOpacityTransition() { + return nativeGetHeatmapOpacityTransition(); + } + + /** + * Set the HeatmapOpacity property transition options + * + * @param options transition options for Float + */ + public void setHeatmapOpacityTransition(TransitionOptions options) { + nativeSetHeatmapOpacityTransition(options.getDuration(), options.getDelay()); + } + + private native Object nativeGetHeatmapRadius(); + + private native TransitionOptions nativeGetHeatmapRadiusTransition(); + + private native void nativeSetHeatmapRadiusTransition(long duration, long delay); + + private native Object nativeGetHeatmapWeight(); + + private native Object nativeGetHeatmapIntensity(); + + private native TransitionOptions nativeGetHeatmapIntensityTransition(); + + private native void nativeSetHeatmapIntensityTransition(long duration, long delay); + + private native Object nativeGetHeatmapColor(); + + private native Object nativeGetHeatmapOpacity(); + + private native TransitionOptions nativeGetHeatmapOpacityTransition(); + + private native void nativeSetHeatmapOpacityTransition(long duration, long delay); + + @Override + protected native void finalize() throws Throwable; + +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java index 6e644c5591..43f5be98cb 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java @@ -1516,6 +1516,168 @@ public class PropertyFactory { } /** + * Radius of influence of one heatmap point in density-independent pixels. Increasing the value makes the heatmap smoother, but less detailed. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static PropertyValue<Float> heatmapRadius(Float value) { + return new PaintPropertyValue<>("heatmap-radius", value); + } + + /** + * Radius of influence of one heatmap point in density-independent pixels. Increasing the value makes the heatmap smoother, but less detailed. + * + * @param expression an expression statement + * @return property wrapper around an expression statement + */ + public static PropertyValue<Expression> heatmapRadius(Expression expression) { + return new PaintPropertyValue<>("heatmap-radius", expression); + } + + + /** + * Radius of influence of one heatmap point in density-independent pixels. Increasing the value makes the heatmap smoother, but less detailed. + * + * @param <T> the function input type + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + @Deprecated + public static <T> PropertyValue<Function<T, Float>> heatmapRadius(Function<T, Float> function) { + return new PaintPropertyValue<>("heatmap-radius", function); + } + + /** + * A measure of how much an individual point contributes to the heatmap. A value of 10 would be equivalent to having 10 points of weight 1 in the same spot. Especially useful when combined with clustering. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static PropertyValue<Float> heatmapWeight(Float value) { + return new PaintPropertyValue<>("heatmap-weight", value); + } + + /** + * A measure of how much an individual point contributes to the heatmap. A value of 10 would be equivalent to having 10 points of weight 1 in the same spot. Especially useful when combined with clustering. + * + * @param expression an expression statement + * @return property wrapper around an expression statement + */ + public static PropertyValue<Expression> heatmapWeight(Expression expression) { + return new PaintPropertyValue<>("heatmap-weight", expression); + } + + + /** + * A measure of how much an individual point contributes to the heatmap. A value of 10 would be equivalent to having 10 points of weight 1 in the same spot. Especially useful when combined with clustering. + * + * @param <T> the function input type + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + @Deprecated + public static <T> PropertyValue<Function<T, Float>> heatmapWeight(Function<T, Float> function) { + return new PaintPropertyValue<>("heatmap-weight", function); + } + + /** + * Similar to {@link PropertyFactory#heatmapWeight} but controls the intensity of the heatmap globally. Primarily used for adjusting the heatmap based on zoom level. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static PropertyValue<Float> heatmapIntensity(Float value) { + return new PaintPropertyValue<>("heatmap-intensity", value); + } + + /** + * Similar to {@link PropertyFactory#heatmapWeight} but controls the intensity of the heatmap globally. Primarily used for adjusting the heatmap based on zoom level. + * + * @param expression an expression statement + * @return property wrapper around an expression statement + */ + public static PropertyValue<Expression> heatmapIntensity(Expression expression) { + return new PaintPropertyValue<>("heatmap-intensity", expression); + } + + + /** + * Similar to {@link PropertyFactory#heatmapWeight} but controls the intensity of the heatmap globally. Primarily used for adjusting the heatmap based on zoom level. + * + * @param <Z> the zoom parameter type + * @param function a wrapper {@link CameraFunction} for Float + * @return property wrapper around a Float function + */ + @Deprecated + public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> heatmapIntensity(CameraFunction<Z, Float> function) { + return new PaintPropertyValue<>("heatmap-intensity", function); + } + + /** + * Defines the color of each pixel based on its density value in a heatmap. Should be an expression that uses `["heatmap-density"]` as input. + * + * @param value a int color value + * @return property wrapper around String color + */ + public static PropertyValue<String> heatmapColor(@ColorInt int value) { + return new PaintPropertyValue<>("heatmap-color", colorToRgbaString(value)); + } + + /** + * Defines the color of each pixel based on its density value in a heatmap. Should be an expression that uses `["heatmap-density"]` as input. + * + * @param value a String value + * @return property wrapper around String + */ + public static PropertyValue<String> heatmapColor(String value) { + return new PaintPropertyValue<>("heatmap-color", value); + } + + /** + * Defines the color of each pixel based on its density value in a heatmap. Should be an expression that uses `["heatmap-density"]` as input. + * + * @param expression an expression statement + * @return property wrapper around an expression statement + */ + public static PropertyValue<Expression> heatmapColor(Expression expression) { + return new PaintPropertyValue<>("heatmap-color", expression); + } + + /** + * The global opacity at which the heatmap layer will be drawn. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static PropertyValue<Float> heatmapOpacity(Float value) { + return new PaintPropertyValue<>("heatmap-opacity", value); + } + + /** + * The global opacity at which the heatmap layer will be drawn. + * + * @param expression an expression statement + * @return property wrapper around an expression statement + */ + public static PropertyValue<Expression> heatmapOpacity(Expression expression) { + return new PaintPropertyValue<>("heatmap-opacity", expression); + } + + + /** + * The global opacity at which the heatmap layer will be drawn. + * + * @param <Z> the zoom parameter type + * @param function a wrapper {@link CameraFunction} for Float + * @return property wrapper around a Float function + */ + @Deprecated + public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> heatmapOpacity(CameraFunction<Z, Float> function) { + return new PaintPropertyValue<>("heatmap-opacity", function); + } + + /** * The opacity of the entire fill extrusion layer. This is rendered on a per-layer, not per-feature, basis, and data-driven styling is not available. * * @param value a Float value diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HeatmapLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HeatmapLayerTest.java new file mode 100644 index 0000000000..0a4c35f1fe --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HeatmapLayerTest.java @@ -0,0 +1,660 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. + +package com.mapbox.mapboxsdk.testapp.style; + +import android.graphics.Color; +import android.support.test.espresso.UiController; +import android.support.test.runner.AndroidJUnit4; + +import timber.log.Timber; + +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.style.functions.CompositeFunction; +import com.mapbox.mapboxsdk.style.functions.CameraFunction; +import com.mapbox.mapboxsdk.style.functions.SourceFunction; +import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops; +import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops; +import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops; +import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops; +import com.mapbox.mapboxsdk.style.functions.stops.Stop; +import com.mapbox.mapboxsdk.style.functions.stops.Stops; +import com.mapbox.mapboxsdk.style.layers.HeatmapLayer; +import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction; +import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static com.mapbox.mapboxsdk.style.functions.Function.*; +import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop; +import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*; +import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke; +import static org.junit.Assert.*; +import static com.mapbox.mapboxsdk.style.layers.Property.*; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*; + +import com.mapbox.mapboxsdk.style.layers.TransitionOptions; +import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity; + +/** + * Basic smoke tests for HeatmapLayer + */ +@RunWith(AndroidJUnit4.class) +public class HeatmapLayerTest extends BaseActivityTest { + + private HeatmapLayer layer; + + @Override + protected Class getActivityClass() { + return EspressoTestActivity.class; + } + + private void setupLayer() { + Timber.i("Retrieving layer"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + if ((layer = mapboxMap.getLayerAs("my-layer")) == null) { + Timber.i("Adding layer"); + layer = new HeatmapLayer("my-layer", "composite"); + layer.setSourceLayer("composite"); + mapboxMap.addLayer(layer); + // Layer reference is now stale, get new reference + layer = mapboxMap.getLayerAs("my-layer"); + } + } + }); + } + + @Test + public void testSetVisibility() { + validateTestSetup(); + setupLayer(); + Timber.i("Visibility"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Get initial + assertEquals(layer.getVisibility().getValue(), VISIBLE); + + // Set + layer.setProperties(visibility(NONE)); + assertEquals(layer.getVisibility().getValue(), NONE); + } + }); + } + + @Test + public void testSourceLayer() { + validateTestSetup(); + setupLayer(); + Timber.i("SourceLayer"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Get initial + assertEquals(layer.getSourceLayer(), "composite"); + + // Set + final String sourceLayer = "test"; + layer.setSourceLayer(sourceLayer); + assertEquals(layer.getSourceLayer(), sourceLayer); + } + }); + } + + @Test + public void testHeatmapRadiusTransition() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-radiusTransitionOptions"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set and Get + TransitionOptions options = new TransitionOptions(300, 100); + layer.setHeatmapRadiusTransition(options); + assertEquals(layer.getHeatmapRadiusTransition(), options); + } + }); + } + + @Test + public void testHeatmapRadiusAsConstant() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-radius"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set and Get + layer.setProperties(heatmapRadius(0.3f)); + assertEquals((Float) layer.getHeatmapRadius().getValue(), (Float) 0.3f); + } + }); + } + + @Test + public void testHeatmapRadiusAsCameraFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-radius"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set + layer.setProperties( + heatmapRadius( + zoom( + exponential( + stop(2, heatmapRadius(0.3f)) + ).withBase(0.5f) + ) + ) + ); + + // Verify + assertNotNull(layer.getHeatmapRadius()); + assertNotNull(layer.getHeatmapRadius().getFunction()); + assertEquals(CameraFunction.class, layer.getHeatmapRadius().getFunction().getClass()); + assertEquals(ExponentialStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass()); + assertEquals(0.5f, ((ExponentialStops) layer.getHeatmapRadius().getFunction().getStops()).getBase(), 0.001); + assertEquals(1, ((ExponentialStops) layer.getHeatmapRadius().getFunction().getStops()).size()); + } + }); + } + + @Test + public void testHeatmapRadiusAsIdentitySourceFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-radius"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set + layer.setProperties( + heatmapRadius(property("FeaturePropertyA", Stops.<Float>identity())) + ); + + // Verify + assertNotNull(layer.getHeatmapRadius()); + assertNotNull(layer.getHeatmapRadius().getFunction()); + assertEquals(SourceFunction.class, layer.getHeatmapRadius().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapRadius().getFunction()).getProperty()); + assertEquals(IdentityStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass()); + } + }); + } + + @Test + public void testHeatmapRadiusAsExponentialSourceFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-radius"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set + layer.setProperties( + heatmapRadius( + property( + "FeaturePropertyA", + exponential( + stop(0.3f, heatmapRadius(0.3f)) + ).withBase(0.5f) + ) + ) + ); + + // Verify + assertNotNull(layer.getHeatmapRadius()); + assertNotNull(layer.getHeatmapRadius().getFunction()); + assertEquals(SourceFunction.class, layer.getHeatmapRadius().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapRadius().getFunction()).getProperty()); + assertEquals(ExponentialStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass()); + } + }); + } + + @Test + public void testHeatmapRadiusAsCategoricalSourceFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-radius"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set + layer.setProperties( + heatmapRadius( + property( + "FeaturePropertyA", + categorical( + stop(1.0f, heatmapRadius(0.3f)) + ) + ).withDefaultValue(heatmapRadius(0.3f)) + ) + ); + + // Verify + assertNotNull(layer.getHeatmapRadius()); + assertNotNull(layer.getHeatmapRadius().getFunction()); + assertEquals(SourceFunction.class, layer.getHeatmapRadius().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapRadius().getFunction()).getProperty()); + assertEquals(CategoricalStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass()); + assertNotNull(((SourceFunction) layer.getHeatmapRadius().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getHeatmapRadius().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getHeatmapRadius().getFunction()).getDefaultValue().getValue()); + } + }); + + } + + @Test + public void testHeatmapRadiusAsCompositeFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-radius"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set + layer.setProperties( + heatmapRadius( + composite( + "FeaturePropertyA", + exponential( + stop(0, 0.3f, heatmapRadius(0.9f)) + ).withBase(0.5f) + ).withDefaultValue(heatmapRadius(0.3f)) + ) + ); + + // Verify + assertNotNull(layer.getHeatmapRadius()); + assertNotNull(layer.getHeatmapRadius().getFunction()); + assertEquals(CompositeFunction.class, layer.getHeatmapRadius().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getHeatmapRadius().getFunction()).getProperty()); + assertEquals(ExponentialStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass()); + assertEquals(1, ((ExponentialStops) layer.getHeatmapRadius().getFunction().getStops()).size()); + + ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops = + (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getHeatmapRadius().getFunction().getStops(); + Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next(); + assertEquals(0f, stop.in.zoom, 0.001); + assertEquals(0.3f, stop.in.value, 0.001f); + assertEquals(0.9f, stop.out, 0.001f); + } + }); + } + + @Test + public void testHeatmapWeightAsConstant() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-weight"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set and Get + layer.setProperties(heatmapWeight(0.3f)); + assertEquals((Float) layer.getHeatmapWeight().getValue(), (Float) 0.3f); + } + }); + } + + @Test + public void testHeatmapWeightAsCameraFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-weight"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set + layer.setProperties( + heatmapWeight( + zoom( + exponential( + stop(2, heatmapWeight(0.3f)) + ).withBase(0.5f) + ) + ) + ); + + // Verify + assertNotNull(layer.getHeatmapWeight()); + assertNotNull(layer.getHeatmapWeight().getFunction()); + assertEquals(CameraFunction.class, layer.getHeatmapWeight().getFunction().getClass()); + assertEquals(ExponentialStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass()); + assertEquals(0.5f, ((ExponentialStops) layer.getHeatmapWeight().getFunction().getStops()).getBase(), 0.001); + assertEquals(1, ((ExponentialStops) layer.getHeatmapWeight().getFunction().getStops()).size()); + } + }); + } + + @Test + public void testHeatmapWeightAsIdentitySourceFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-weight"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set + layer.setProperties( + heatmapWeight(property("FeaturePropertyA", Stops.<Float>identity())) + ); + + // Verify + assertNotNull(layer.getHeatmapWeight()); + assertNotNull(layer.getHeatmapWeight().getFunction()); + assertEquals(SourceFunction.class, layer.getHeatmapWeight().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapWeight().getFunction()).getProperty()); + assertEquals(IdentityStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass()); + } + }); + } + + @Test + public void testHeatmapWeightAsExponentialSourceFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-weight"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set + layer.setProperties( + heatmapWeight( + property( + "FeaturePropertyA", + exponential( + stop(0.3f, heatmapWeight(0.3f)) + ).withBase(0.5f) + ) + ) + ); + + // Verify + assertNotNull(layer.getHeatmapWeight()); + assertNotNull(layer.getHeatmapWeight().getFunction()); + assertEquals(SourceFunction.class, layer.getHeatmapWeight().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapWeight().getFunction()).getProperty()); + assertEquals(ExponentialStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass()); + } + }); + } + + @Test + public void testHeatmapWeightAsCategoricalSourceFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-weight"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set + layer.setProperties( + heatmapWeight( + property( + "FeaturePropertyA", + categorical( + stop(1.0f, heatmapWeight(0.3f)) + ) + ).withDefaultValue(heatmapWeight(0.3f)) + ) + ); + + // Verify + assertNotNull(layer.getHeatmapWeight()); + assertNotNull(layer.getHeatmapWeight().getFunction()); + assertEquals(SourceFunction.class, layer.getHeatmapWeight().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapWeight().getFunction()).getProperty()); + assertEquals(CategoricalStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass()); + assertNotNull(((SourceFunction) layer.getHeatmapWeight().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getHeatmapWeight().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getHeatmapWeight().getFunction()).getDefaultValue().getValue()); + } + }); + + } + + @Test + public void testHeatmapWeightAsCompositeFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-weight"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set + layer.setProperties( + heatmapWeight( + composite( + "FeaturePropertyA", + exponential( + stop(0, 0.3f, heatmapWeight(0.9f)) + ).withBase(0.5f) + ).withDefaultValue(heatmapWeight(0.3f)) + ) + ); + + // Verify + assertNotNull(layer.getHeatmapWeight()); + assertNotNull(layer.getHeatmapWeight().getFunction()); + assertEquals(CompositeFunction.class, layer.getHeatmapWeight().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getHeatmapWeight().getFunction()).getProperty()); + assertEquals(ExponentialStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass()); + assertEquals(1, ((ExponentialStops) layer.getHeatmapWeight().getFunction().getStops()).size()); + + ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops = + (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getHeatmapWeight().getFunction().getStops(); + Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next(); + assertEquals(0f, stop.in.zoom, 0.001); + assertEquals(0.3f, stop.in.value, 0.001f); + assertEquals(0.9f, stop.out, 0.001f); + } + }); + } + + @Test + public void testHeatmapIntensityTransition() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-intensityTransitionOptions"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set and Get + TransitionOptions options = new TransitionOptions(300, 100); + layer.setHeatmapIntensityTransition(options); + assertEquals(layer.getHeatmapIntensityTransition(), options); + } + }); + } + + @Test + public void testHeatmapIntensityAsConstant() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-intensity"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set and Get + layer.setProperties(heatmapIntensity(0.3f)); + assertEquals((Float) layer.getHeatmapIntensity().getValue(), (Float) 0.3f); + } + }); + } + + @Test + public void testHeatmapIntensityAsCameraFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-intensity"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set + layer.setProperties( + heatmapIntensity( + zoom( + exponential( + stop(2, heatmapIntensity(0.3f)) + ).withBase(0.5f) + ) + ) + ); + + // Verify + assertNotNull(layer.getHeatmapIntensity()); + assertNotNull(layer.getHeatmapIntensity().getFunction()); + assertEquals(CameraFunction.class, layer.getHeatmapIntensity().getFunction().getClass()); + assertEquals(ExponentialStops.class, layer.getHeatmapIntensity().getFunction().getStops().getClass()); + assertEquals(0.5f, ((ExponentialStops) layer.getHeatmapIntensity().getFunction().getStops()).getBase(), 0.001); + assertEquals(1, ((ExponentialStops) layer.getHeatmapIntensity().getFunction().getStops()).size()); + } + }); + } + + @Test + public void testHeatmapColorAsConstant() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-color"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set and Get + layer.setProperties(heatmapColor("rgba(0, 0, 0, 1)")); + assertEquals((String) layer.getHeatmapColor().getValue(), (String) "rgba(0, 0, 0, 1)"); + } + }); + } + + @Test + public void testHeatmapColorAsIntConstant() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-color"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set and Get + layer.setProperties(heatmapColor(Color.RED)); + assertEquals(layer.getHeatmapColorAsInt(), Color.RED); + } + }); + } + + @Test + public void testHeatmapOpacityTransition() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-opacityTransitionOptions"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set and Get + TransitionOptions options = new TransitionOptions(300, 100); + layer.setHeatmapOpacityTransition(options); + assertEquals(layer.getHeatmapOpacityTransition(), options); + } + }); + } + + @Test + public void testHeatmapOpacityAsConstant() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-opacity"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set and Get + layer.setProperties(heatmapOpacity(0.3f)); + assertEquals((Float) layer.getHeatmapOpacity().getValue(), (Float) 0.3f); + } + }); + } + + @Test + public void testHeatmapOpacityAsCameraFunction() { + validateTestSetup(); + setupLayer(); + Timber.i("heatmap-opacity"); + invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() { + @Override + public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) { + assertNotNull(layer); + + // Set + layer.setProperties( + heatmapOpacity( + zoom( + exponential( + stop(2, heatmapOpacity(0.3f)) + ).withBase(0.5f) + ) + ) + ); + + // Verify + assertNotNull(layer.getHeatmapOpacity()); + assertNotNull(layer.getHeatmapOpacity().getFunction()); + assertEquals(CameraFunction.class, layer.getHeatmapOpacity().getFunction().getClass()); + assertEquals(ExponentialStops.class, layer.getHeatmapOpacity().getFunction().getStops().getClass()); + assertEquals(0.5f, ((ExponentialStops) layer.getHeatmapOpacity().getFunction().getStops()).getBase(), 0.001); + assertEquals(1, ((ExponentialStops) layer.getHeatmapOpacity().getFunction().getStops()).size()); + } + }); + } + +} diff --git a/platform/android/src/style/layers/heatmap_layer.cpp b/platform/android/src/style/layers/heatmap_layer.cpp new file mode 100644 index 0000000000..3f1d35feb2 --- /dev/null +++ b/platform/android/src/style/layers/heatmap_layer.cpp @@ -0,0 +1,141 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. + +#include "heatmap_layer.hpp" + +#include <string> + +#include "../conversion/property_value.hpp" +#include "../conversion/transition_options.hpp" + +namespace mbgl { +namespace android { + + /** + * Creates an owning peer object (for layers not attached to the map) from the JVM side + */ + HeatmapLayer::HeatmapLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + : Layer(env, std::make_unique<mbgl::style::HeatmapLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { + } + + /** + * Creates a non-owning peer object (for layers currently attached to the map) + */ + HeatmapLayer::HeatmapLayer(mbgl::Map& map, mbgl::style::HeatmapLayer& coreLayer) + : Layer(map, coreLayer) { + } + + /** + * Creates an owning peer object (for layers not attached to the map) + */ + HeatmapLayer::HeatmapLayer(mbgl::Map& map, std::unique_ptr<mbgl::style::HeatmapLayer> coreLayer) + : Layer(map, std::move(coreLayer)) { + } + + HeatmapLayer::~HeatmapLayer() = default; + + // Property getters + + jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapRadius(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapRadius()); + return jni::Object<jni::ObjectTag>(*converted); + } + + jni::Object<TransitionOptions> HeatmapLayer::getHeatmapRadiusTransition(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + mbgl::style::TransitionOptions options = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapRadiusTransition(); + return *convert<jni::Object<TransitionOptions>>(env, options); + } + + void HeatmapLayer::setHeatmapRadiusTransition(jni::JNIEnv&, jlong duration, jlong delay) { + mbgl::style::TransitionOptions options; + options.duration.emplace(mbgl::Milliseconds(duration)); + options.delay.emplace(mbgl::Milliseconds(delay)); + layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::setHeatmapRadiusTransition(options); + } + + jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapWeight(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapWeight()); + return jni::Object<jni::ObjectTag>(*converted); + } + + jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapIntensity(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapIntensity()); + return jni::Object<jni::ObjectTag>(*converted); + } + + jni::Object<TransitionOptions> HeatmapLayer::getHeatmapIntensityTransition(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + mbgl::style::TransitionOptions options = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapIntensityTransition(); + return *convert<jni::Object<TransitionOptions>>(env, options); + } + + void HeatmapLayer::setHeatmapIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay) { + mbgl::style::TransitionOptions options; + options.duration.emplace(mbgl::Milliseconds(duration)); + options.delay.emplace(mbgl::Milliseconds(delay)); + layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::setHeatmapIntensityTransition(options); + } + + jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapColor(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapColor()); + return jni::Object<jni::ObjectTag>(*converted); + } + + jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapOpacity(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapOpacity()); + return jni::Object<jni::ObjectTag>(*converted); + } + + jni::Object<TransitionOptions> HeatmapLayer::getHeatmapOpacityTransition(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + mbgl::style::TransitionOptions options = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapOpacityTransition(); + return *convert<jni::Object<TransitionOptions>>(env, options); + } + + void HeatmapLayer::setHeatmapOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { + mbgl::style::TransitionOptions options; + options.duration.emplace(mbgl::Milliseconds(duration)); + options.delay.emplace(mbgl::Milliseconds(delay)); + layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::setHeatmapOpacityTransition(options); + } + + + jni::Class<HeatmapLayer> HeatmapLayer::javaClass; + + jni::jobject* HeatmapLayer::createJavaPeer(jni::JNIEnv& env) { + static auto constructor = HeatmapLayer::javaClass.template GetConstructor<jni::jlong>(env); + return HeatmapLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + } + + void HeatmapLayer::registerNative(jni::JNIEnv& env) { + // Lookup the class + HeatmapLayer::javaClass = *jni::Class<HeatmapLayer>::Find(env).NewGlobalRef(env).release(); + + #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + + // Register the peer + jni::RegisterNativePeer<HeatmapLayer>( + env, HeatmapLayer::javaClass, "nativePtr", + std::make_unique<HeatmapLayer, JNIEnv&, jni::String, jni::String>, + "initialize", + "finalize", + METHOD(&HeatmapLayer::getHeatmapRadiusTransition, "nativeGetHeatmapRadiusTransition"), + METHOD(&HeatmapLayer::setHeatmapRadiusTransition, "nativeSetHeatmapRadiusTransition"), + METHOD(&HeatmapLayer::getHeatmapRadius, "nativeGetHeatmapRadius"), + METHOD(&HeatmapLayer::getHeatmapWeight, "nativeGetHeatmapWeight"), + METHOD(&HeatmapLayer::getHeatmapIntensityTransition, "nativeGetHeatmapIntensityTransition"), + METHOD(&HeatmapLayer::setHeatmapIntensityTransition, "nativeSetHeatmapIntensityTransition"), + METHOD(&HeatmapLayer::getHeatmapIntensity, "nativeGetHeatmapIntensity"), + METHOD(&HeatmapLayer::getHeatmapColor, "nativeGetHeatmapColor"), + METHOD(&HeatmapLayer::getHeatmapOpacityTransition, "nativeGetHeatmapOpacityTransition"), + METHOD(&HeatmapLayer::setHeatmapOpacityTransition, "nativeSetHeatmapOpacityTransition"), + METHOD(&HeatmapLayer::getHeatmapOpacity, "nativeGetHeatmapOpacity")); + } + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/style/layers/heatmap_layer.hpp b/platform/android/src/style/layers/heatmap_layer.hpp new file mode 100644 index 0000000000..9e8908b062 --- /dev/null +++ b/platform/android/src/style/layers/heatmap_layer.hpp @@ -0,0 +1,52 @@ +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. + +#pragma once + +#include "layer.hpp" +#include "../transition_options.hpp" +#include <mbgl/style/layers/heatmap_layer.hpp> +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class HeatmapLayer : public Layer { +public: + + static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/HeatmapLayer"; }; + + static jni::Class<HeatmapLayer> javaClass; + + static void registerNative(jni::JNIEnv&); + + HeatmapLayer(jni::JNIEnv&, jni::String, jni::String); + + HeatmapLayer(mbgl::Map&, mbgl::style::HeatmapLayer&); + + HeatmapLayer(mbgl::Map&, std::unique_ptr<mbgl::style::HeatmapLayer>); + + ~HeatmapLayer(); + + // Properties + + jni::Object<jni::ObjectTag> getHeatmapRadius(jni::JNIEnv&); + void setHeatmapRadiusTransition(jni::JNIEnv&, jlong duration, jlong delay); + jni::Object<TransitionOptions> getHeatmapRadiusTransition(jni::JNIEnv&); + + jni::Object<jni::ObjectTag> getHeatmapWeight(jni::JNIEnv&); + + jni::Object<jni::ObjectTag> getHeatmapIntensity(jni::JNIEnv&); + void setHeatmapIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay); + jni::Object<TransitionOptions> getHeatmapIntensityTransition(jni::JNIEnv&); + + jni::Object<jni::ObjectTag> getHeatmapColor(jni::JNIEnv&); + + jni::Object<jni::ObjectTag> getHeatmapOpacity(jni::JNIEnv&); + void setHeatmapOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); + jni::Object<TransitionOptions> getHeatmapOpacityTransition(jni::JNIEnv&); + jni::jobject* createJavaPeer(jni::JNIEnv&); + +}; // class HeatmapLayer + +} // namespace android +} // namespace mbgl |