From 18885def718fe3d779b4b01f0e7c4461361bd3ff Mon Sep 17 00:00:00 2001 From: Tobrun Date: Wed, 19 Jun 2019 19:51:44 +0200 Subject: [android] - optimise CameraUpdateFactory#newLatLngBounds to use camera position tilt and bearing values (#14953) --- .../mapboxsdk/camera/CameraUpdateFactory.java | 81 ++++++++++-- .../mapboxsdk/camera/CameraUpdateFactoryTest.kt | 144 +++++++++++++++++++++ 2 files changed, 213 insertions(+), 12 deletions(-) create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactoryTest.kt diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java index c4cc6d019..5ff4104ea 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java @@ -4,13 +4,13 @@ import android.graphics.Point; import android.graphics.PointF; import android.support.annotation.IntDef; import android.support.annotation.NonNull; - import android.support.annotation.Nullable; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngBounds; import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.Projection; import com.mapbox.mapboxsdk.maps.UiSettings; +import junit.framework.Assert; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -45,9 +45,11 @@ public final class CameraUpdateFactory { /** * Returns a CameraUpdate that transforms the camera such that the specified - * latitude/longitude bounds are centered on screen at the greatest possible zoom level. + * latitude/longitude bounds are centered on screen at the greatest possible zoom level while maintaining + * current camera position bearing and tilt values. + *

* You can specify padding, in order to inset the bounding box from the map view's edges. - * The returned CameraUpdate has a bearing of 0 and a tilt of 0. + *

* * @param bounds Bounds to match Camera position with * @param padding Padding added to the bounds @@ -59,9 +61,29 @@ public final class CameraUpdateFactory { /** * Returns a CameraUpdate that transforms the camera such that the specified - * latitude/longitude bounds are centered on screen at the greatest possible zoom level. + * latitude/longitude bounds are centered on screen at the greatest possible zoom level while using + * provided bearing and tilt values. + *

+ * You can specify padding, in order to inset the bounding box from the map view's edges. + *

+ * + * @param bounds Bounds to match Camera position with + * @param bearing Bearing to take in account when generating the bounds + * @param tilt Tilt to take in account when generating the bounds + * @param padding Padding added to the bounds + * @return CameraUpdate Final Camera Position + */ + public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, double bearing, double tilt, int padding) { + return newLatLngBounds(bounds, bearing, tilt, padding, padding, padding, padding); + } + + /** + * Returns a CameraUpdate that transforms the camera such that the specified + * latitude/longitude bounds are centered on screen at the greatest possible zoom level while maintaining + * current camera position bearing and tilt values. + *

* You can specify padding, in order to inset the bounding box from the map view's edges. - * The returned CameraUpdate has a bearing of 0 and a tilt of 0. + *

* * @param bounds Bounds to base the Camera position out of * @param paddingLeft Padding left of the bounds @@ -72,7 +94,29 @@ public final class CameraUpdateFactory { */ public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) { - return new CameraBoundsUpdate(bounds, paddingLeft, paddingTop, paddingRight, paddingBottom); + return new CameraBoundsUpdate(bounds, null, null, paddingLeft, paddingTop, paddingRight, paddingBottom); + } + + /** + * Returns a CameraUpdate that transforms the camera such that the specified + * latitude/longitude bounds are centered on screen at the greatest possible zoom level while using + * provided bearing and tilt values. + *

+ * You can specify padding, in order to inset the bounding box from the map view's edges. + *

+ * + * @param bounds Bounds to base the Camera position out of + * @param bearing Bearing to take in account when generating the bounds + * @param tilt Tilt to take in account when generating the bounds + * @param paddingLeft Padding left of the bounds + * @param paddingTop Padding top of the bounds + * @param paddingRight Padding right of the bounds + * @param paddingBottom Padding bottom of the bounds + * @return CameraUpdate Final Camera Position + */ + public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, double bearing, double tilt, + int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) { + return new CameraBoundsUpdate(bounds, bearing, tilt, paddingLeft, paddingTop, paddingRight, paddingBottom); } /** @@ -253,16 +297,21 @@ public final class CameraUpdateFactory { static final class CameraBoundsUpdate implements CameraUpdate { - private LatLngBounds bounds; - private int[] padding; + private final LatLngBounds bounds; + private final int[] padding; + private final Double bearing; + private final Double tilt; - CameraBoundsUpdate(LatLngBounds bounds, int[] padding) { + CameraBoundsUpdate(LatLngBounds bounds, Double bearing, Double tilt, int[] padding) { this.bounds = bounds; this.padding = padding; + this.bearing = bearing; + this.tilt = tilt; } - CameraBoundsUpdate(LatLngBounds bounds, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) { - this(bounds, new int[] {paddingLeft, paddingTop, paddingRight, paddingBottom}); + CameraBoundsUpdate(LatLngBounds bounds, Double bearing, Double tilt, int paddingLeft, + int paddingTop, int paddingRight, int paddingBottom) { + this(bounds, bearing, tilt, new int[] {paddingLeft, paddingTop, paddingRight, paddingBottom}); } public LatLngBounds getBounds() { @@ -275,7 +324,15 @@ public final class CameraUpdateFactory { @Override public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) { - return mapboxMap.getCameraForLatLngBounds(bounds, padding); + if (bearing == null && tilt == null) { + // use current camera position tilt and bearing + return mapboxMap.getCameraForLatLngBounds(bounds, padding); + } else { + // use provided tilt and bearing + Assert.assertNotNull(bearing); + Assert.assertNotNull(tilt); + return mapboxMap.getCameraForLatLngBounds(bounds, padding, bearing, tilt); + } } @Override diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactoryTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactoryTest.kt new file mode 100644 index 000000000..446b731a6 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactoryTest.kt @@ -0,0 +1,144 @@ +package com.mapbox.mapboxsdk.camera + +import android.support.test.runner.AndroidJUnit4 +import com.mapbox.mapboxsdk.geometry.LatLng +import com.mapbox.mapboxsdk.geometry.LatLngBounds +import com.mapbox.mapboxsdk.testapp.activity.BaseTest +import com.mapbox.mapboxsdk.testapp.activity.espresso.DeviceIndependentTestActivity +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class CameraUpdateFactoryTest : BaseTest() { + + override fun getActivityClass(): Class<*> { + return DeviceIndependentTestActivity::class.java + } + + @Test + fun testLatLngBoundsUntiltedUnrotated() { + rule.runOnUiThread { + mapboxMap.cameraPosition = CameraPosition.Builder() + .target(LatLng(60.0, 24.0)) + .bearing(0.0) + .tilt(0.0) + .build() + + val bounds: LatLngBounds = LatLngBounds.Builder() + .include(LatLng(62.0, 26.0)) + .include(LatLng(58.0, 22.0)) + .build() + + mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0)) + + val cameraPosition = mapboxMap.cameraPosition + assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1) + assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1) + assertEquals("bearing should match:", 0.0, cameraPosition.bearing, 0.1) + assertEquals("zoom should match", 5.5, cameraPosition.zoom, 0.1) + assertEquals("tilt should match:", 0.0, cameraPosition.tilt, 0.1) + } + } + + @Test + fun testLatLngBoundsTilted() { + rule.runOnUiThread { + mapboxMap.cameraPosition = CameraPosition.Builder() + .target(LatLng(60.0, 24.0)) + .bearing(0.0) + .tilt(45.0) + .build() + + val bounds: LatLngBounds = LatLngBounds.Builder() + .include(LatLng(62.0, 26.0)) + .include(LatLng(58.0, 22.0)) + .build() + + mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0)) + + val cameraPosition = mapboxMap.cameraPosition + assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1) + assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1) + assertEquals("bearing should match:", 0.0, cameraPosition.bearing, 0.1) + assertEquals("zoom should match", 6.0, cameraPosition.zoom, 0.1) + assertEquals("tilt should match:", 45.0, cameraPosition.tilt, 0.1) + } + } + + @Test + fun testLatLngBoundsRotated() { + rule.runOnUiThread { + mapboxMap.cameraPosition = CameraPosition.Builder() + .target(LatLng(60.0, 24.0)) + .bearing(30.0) + .tilt(0.0) + .build() + + val bounds: LatLngBounds = LatLngBounds.Builder() + .include(LatLng(62.0, 26.0)) + .include(LatLng(58.0, 22.0)) + .build() + + mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0)) + + val cameraPosition = mapboxMap.cameraPosition + assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1) + assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1) + assertEquals("bearing should match:", 30.0, cameraPosition.bearing, 0.1) + assertEquals("zoom should match", 5.3, cameraPosition.zoom, 0.1) + assertEquals("tilt should match:", 0.0, cameraPosition.tilt, 0.1) + } + } + + @Test + fun testLatLngBoundsTiltedRotated() { + rule.runOnUiThread { + mapboxMap.cameraPosition = CameraPosition.Builder() + .target(LatLng(60.0, 24.0)) + .bearing(30.0) + .tilt(45.0) + .build() + + val bounds: LatLngBounds = LatLngBounds.Builder() + .include(LatLng(62.0, 26.0)) + .include(LatLng(58.0, 22.0)) + .build() + + mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0)) + + val cameraPosition = mapboxMap.cameraPosition + assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1) + assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1) + assertEquals("bearing should match:", 30.0, cameraPosition.bearing, 0.1) + assertEquals("zoom should match", 5.6, cameraPosition.zoom, 0.1) + assertEquals("tilt should match:", 45.0, cameraPosition.tilt, 0.1) + } + } + + @Test + fun testLatLngBoundsWithProvidedTiltAndRotation() { + rule.runOnUiThread { + mapboxMap.cameraPosition = CameraPosition.Builder() + .target(LatLng(60.0, 24.0)) + .bearing(0.0) + .tilt(0.0) + .build() + + val bounds: LatLngBounds = LatLngBounds.Builder() + .include(LatLng(62.0, 26.0)) + .include(LatLng(58.0, 22.0)) + .build() + + mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 30.0, 40.0, 0)) + + val cameraPosition = mapboxMap.cameraPosition + assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1) + assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1) + assertEquals("bearing should match:", 30.0, cameraPosition.bearing, 0.1) + assertEquals("zoom should match", 5.6, cameraPosition.zoom, 0.1) + assertEquals("tilt should match:", 40.0, cameraPosition.tilt, 0.1) + } + } + +} \ No newline at end of file -- cgit v1.2.3