From a0d0db5cca73047fb92d2032c787483813b0a135 Mon Sep 17 00:00:00 2001 From: Tobrun Date: Tue, 14 Feb 2017 13:53:04 +0100 Subject: wip --- .../mapboxsdk/camera/CameraUpdateFactory.java | 169 ++++++++++----------- .../java/com/mapbox/mapboxsdk/maps/MapboxMap.java | 6 - .../com/mapbox/mapboxsdk/maps/NativeMapView.java | 2 +- .../java/com/mapbox/mapboxsdk/maps/Projection.java | 27 +++- 4 files changed, 111 insertions(+), 93 deletions(-) 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 59fcb8e3e8..94d1066382 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 @@ -1,6 +1,7 @@ package com.mapbox.mapboxsdk.camera; import android.graphics.Point; +import android.graphics.PointF; import android.graphics.RectF; import android.support.annotation.IntDef; import android.support.annotation.NonNull; @@ -8,6 +9,9 @@ import android.support.annotation.NonNull; 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 com.mapbox.services.android.telemetry.utils.MathUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -220,60 +224,59 @@ public final class CameraUpdateFactory { @Override public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) { - //// Get required objects - //Projection projection = mapboxMap.getProjection(); - //UiSettings uiSettings = mapboxMap.getUiSettings(); - // - //// calculate correct padding - //int[] mapPadding = mapboxMap.getPadding(); - //RectF latLngPadding = getPadding(); - //RectF padding = new RectF(latLngPadding.left + mapPadding[0], - //latLngPadding.top + mapPadding[1], - //latLngPadding.right + mapPadding[2], - //latLngPadding.bottom + mapPadding[3]); - // - //// Calculate the bounds of the possibly rotated shape with respect to the viewport - //PointF nePixel = new PointF(-Float.MAX_VALUE, -Float.MAX_VALUE); - //PointF swPixel = new PointF(Float.MAX_VALUE, Float.MAX_VALUE); - //float viewportHeight = uiSettings.getHeight(); - //for (LatLng latLng : getBounds().toLatLngs()) { - // PointF pixel = projection.toScreenLocation(latLng); - // swPixel.x = Math.min(swPixel.x, pixel.x); - // nePixel.x = Math.max(nePixel.x, pixel.x); - // swPixel.y = Math.min(swPixel.y, viewportHeight - pixel.y); - // nePixel.y = Math.max(nePixel.y, viewportHeight - pixel.y); - //} - // - //// Calculate width/height - //float width = nePixel.x - swPixel.x; - //float height = nePixel.y - swPixel.y; - // - //double zoom = 0; - //float minScale = 1; - //// Calculate the zoom level - //if (padding != null) { - // float scaleX = (uiSettings.getWidth() - padding.left - padding.right) / width; - // float scaleY = (uiSettings.getHeight() - padding.top - padding.bottom) / height; - // minScale = scaleX < scaleY ? scaleX : scaleY; - // zoom = calculateZoom(mapboxMap, minScale); - // zoom = MathUtils.clamp(zoom, mapboxMap.getMinZoomLevel(), mapboxMap.getMaxZoomLevel()); - //} - // - //// Calculate the center point - //PointF paddedNEPixel = new PointF(nePixel.x + padding.right / minScale, nePixel.y + padding.top / minScale); - //PointF paddedSWPixel = new PointF(swPixel.x - padding.left / minScale, swPixel.y - padding.bottom / minScale); - //PointF centerPixel = new PointF((paddedNEPixel.x + paddedSWPixel.x) / 2, (paddedNEPixel.y + paddedSWPixel.y) - // / 2); - //centerPixel.y = viewportHeight - centerPixel.y; - //LatLng center = projection.fromScreenLocation(centerPixel); - // - //return new CameraPosition.Builder() - // .target(center) - // .zoom(zoom) - // .tilt(0) - // .bearing(0) - // .build(); - throw new RuntimeException(); + // Get required objects + Projection projection = mapboxMap.getProjection(); + UiSettings uiSettings = mapboxMap.getUiSettings(); + + // calculate correct padding + int[] mapPadding = mapboxMap.getPadding(); + RectF latLngPadding = getPadding(); + RectF padding = new RectF(latLngPadding.left + mapPadding[0], + latLngPadding.top + mapPadding[1], + latLngPadding.right + mapPadding[2], + latLngPadding.bottom + mapPadding[3]); + + // Calculate the bounds of the possibly rotated shape with respect to the viewport + PointF nePixel = new PointF(-Float.MAX_VALUE, -Float.MAX_VALUE); + PointF swPixel = new PointF(Float.MAX_VALUE, Float.MAX_VALUE); + float viewportHeight = uiSettings.getHeight(); + for (LatLng latLng : getBounds().toLatLngs()) { + PointF pixel = projection.toScreenLocation(latLng); + swPixel.x = Math.min(swPixel.x, pixel.x); + nePixel.x = Math.max(nePixel.x, pixel.x); + swPixel.y = Math.min(swPixel.y, viewportHeight - pixel.y); + nePixel.y = Math.max(nePixel.y, viewportHeight - pixel.y); + } + + // Calculate width/height + float width = nePixel.x - swPixel.x; + float height = nePixel.y - swPixel.y; + + double zoom = 0; + float minScale = 1; + // Calculate the zoom level + if (padding != null) { + float scaleX = (uiSettings.getWidth() - padding.left - padding.right) / width; + float scaleY = (uiSettings.getHeight() - padding.top - padding.bottom) / height; + minScale = scaleX < scaleY ? scaleX : scaleY; + zoom = calculateZoom(mapboxMap, minScale); + zoom = MathUtils.clamp(zoom, mapboxMap.getMinZoomLevel(), mapboxMap.getMaxZoomLevel()); + } + + // Calculate the center point + PointF paddedNEPixel = new PointF(nePixel.x + padding.right / minScale, nePixel.y + padding.top / minScale); + PointF paddedSWPixel = new PointF(swPixel.x - padding.left / minScale, swPixel.y - padding.bottom / minScale); + PointF centerPixel = new PointF((paddedNEPixel.x + paddedSWPixel.x) / 2, (paddedNEPixel.y + paddedSWPixel.y) + / 2); + centerPixel.y = viewportHeight - centerPixel.y; + LatLng center = projection.fromScreenLocation(centerPixel.x, centerPixel.y); + + return new CameraPosition.Builder() + .target(center) + .zoom(zoom) + .tilt(0) + .bearing(0) + .build(); } /** @@ -299,25 +302,22 @@ public final class CameraUpdateFactory { @Override public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) { - // UiSettings uiSettings = mapboxMap.getUiSettings(); - // Projection projection = mapboxMap.getProjection(); - // - // // Calculate the new center point - // float viewPortWidth = uiSettings.getWidth(); - // float viewPortHeight = uiSettings.getHeight(); - // PointF targetPoint = new PointF(viewPortWidth / 2 + x, viewPortHeight / 2 + y); - // - // // Convert point to LatLng - // LatLng latLng = projection.fromScreenLocation(targetPoint); - // - // CameraPosition previousPosition = mapboxMap.getCameraPosition(); - // return new CameraPosition.Builder() - // .target(latLng != null ? latLng : previousPosition.target) - // .zoom(previousPosition.zoom) - // .tilt(previousPosition.tilt) - // .bearing(previousPosition.bearing) - // .build(); - throw new RuntimeException(); + UiSettings uiSettings = mapboxMap.getUiSettings(); + Projection projection = mapboxMap.getProjection(); + + // Calculate the new center point + float viewPortWidth = uiSettings.getWidth(); + float viewPortHeight = uiSettings.getHeight(); + // Convert point to LatLng + LatLng latLng = projection.fromScreenLocation(viewPortWidth / 2 + x, viewPortHeight / 2 + y); + + CameraPosition previousPosition = mapboxMap.getCameraPosition(); + return new CameraPosition.Builder() + .target(latLng != null ? latLng : previousPosition.target) + .zoom(previousPosition.zoom) + .tilt(previousPosition.tilt) + .bearing(previousPosition.bearing) + .build(); } } @@ -400,18 +400,17 @@ public final class CameraUpdateFactory { @Override public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) { - throw new RuntimeException(); - // CameraPosition cameraPosition = mapboxMap.getCameraPosition(); - // if (getType() != CameraUpdateFactory.ZoomUpdate.ZOOM_TO_POINT) { - // return new CameraPosition.Builder(cameraPosition) - // .zoom(transformZoom(cameraPosition.zoom)) - // .build(); - // } else { - // return new CameraPosition.Builder(cameraPosition) - // .zoom(transformZoom(cameraPosition.zoom)) - // .target(mapboxMap.getProjection().fromScreenLocation(new PointF(getX(), getY()))) - // .build(); - // } + CameraPosition cameraPosition = mapboxMap.getCameraPosition(); + if (getType() != CameraUpdateFactory.ZoomUpdate.ZOOM_TO_POINT) { + return new CameraPosition.Builder(cameraPosition) + .zoom(transformZoom(cameraPosition.zoom)) + .build(); + } else { + return new CameraPosition.Builder(cameraPosition) + .zoom(transformZoom(cameraPosition.zoom)) + .target(mapboxMap.getProjection().fromScreenLocation(getX(), getY())) + .build(); + } } } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java index c1046e868a..8e85269678 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java @@ -469,7 +469,6 @@ public final class MapboxMap { * * @param minZoom The new minimum zoom level. */ - @UiThread public void setMinZoomPreference( @FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) { transform.setMinZoom(minZoom); @@ -482,7 +481,6 @@ public final class MapboxMap { * * @return The minimum zoom level. */ - @UiThread public double getMinZoomLevel() { return transform.getMinZoom(); } @@ -498,7 +496,6 @@ public final class MapboxMap { * * @param maxZoom The new maximum zoom level. */ - @UiThread public void setMaxZoomPreference(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) { transform.setMaxZoom(maxZoom); @@ -511,7 +508,6 @@ public final class MapboxMap { * * @return The maximum zoom level. */ - @UiThread public double getMaxZoomLevel() { return transform.getMaxZoom(); } @@ -565,7 +561,6 @@ public final class MapboxMap { * * @return the Projection associated with this map */ - @UiThread public Projection getProjection() { return projection; } @@ -592,7 +587,6 @@ public final class MapboxMap { * * @return The current position of the Camera. */ - @UiThread public final CameraPosition getCameraPosition() { return transform.getCameraPosition(); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java index 29b1b79582..087b52dee1 100755 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java @@ -403,7 +403,7 @@ final class NativeMapView { private native LatLng latLngForPixel(float x, float y); - PointF pixelForLatLng(LatLng latLng) { + PointF toScreenLocation(LatLng latLng) { PointF pointF = pixelForLatLng(latLng.getLatitude(), latLng.getLongitude()); pointF.set(pointF.x * pixelRatio, pointF.y * pixelRatio); return pointF; diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java index 3e073c9bd6..18040f9e96 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java @@ -1,8 +1,11 @@ package com.mapbox.mapboxsdk.maps; import android.graphics.PointF; +import android.os.Looper; import android.support.annotation.FloatRange; import android.support.annotation.NonNull; +import android.support.annotation.UiThread; +import android.support.annotation.WorkerThread; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngBounds; @@ -63,6 +66,7 @@ public class Projection { * @param latitude The latitude for which to return the value. * @return The distance measured in meters. */ + @UiThread public void getMetersPerPixelAtLatitude(@FloatRange(from = -90, to = 90) final double latitude, final Callback listener) { mapState.queueRenderEvent(new MapRunnable() { @@ -88,6 +92,7 @@ public class Projection { * @return The LatLng corresponding to the point on the screen, or null if the ray through * the given screen point does not intersect the ground plane. */ + @UiThread public void fromScreenLocation(final PointF point, final Callback listener) { mapState.queueRenderEvent(new MapRunnable() { @Override @@ -103,12 +108,22 @@ public class Projection { }); } + @WorkerThread + public LatLng fromScreenLocation(float x, float y) { + if (Looper.myLooper() == Looper.getMainLooper()) { + throw new IllegalThreadStateException("Projection#toScreenLocation needs to be called from a worker thread." + + "Please use Projection#toScreenLocation(LatLng latLng, Callback listener) instead."); + } + return mapState.getNativeMapView().fromScreenLocation(x, y); + } + /** * Gets a projection of the viewing frustum for converting between screen coordinates and * geo-latitude/longitude coordinates. * * @return The projection of the viewing frustum in its current state. */ + @UiThread public void getVisibleRegion(final Callback listener) { mapState.queueRenderEvent(new MapRunnable() { @Override @@ -142,6 +157,15 @@ public class Projection { }); } + @WorkerThread + public PointF toScreenLocation(final LatLng location) { + if (Looper.myLooper() == Looper.getMainLooper()) { + throw new IllegalThreadStateException("Projection#toScreenLocation needs to be called from a worker thread." + + "Please use Projection#toScreenLocation(LatLng latLng, Callback listener) instead."); + } + return mapState.getNativeMapView().toScreenLocation(location); + } + /** * Returns a screen location that corresponds to a geographical coordinate (LatLng). * The screen location is in screen pixels (not display pixels) relative to the top left @@ -150,11 +174,12 @@ public class Projection { * @param location A LatLng on the map to convert to a screen location. * @return A Point representing the screen location in screen pixels. */ + @UiThread public void toScreenLocation(final LatLng location, final Callback listener) { mapState.queueRenderEvent(new MapRunnable() { @Override public void execute(@NonNull NativeMapView nativeMapView) { - final PointF pointF = nativeMapView.pixelForLatLng(location); + final PointF pointF = nativeMapView.toScreenLocation(location); mapState.queueUiEvent(new Runnable() { @Override public void run() { -- cgit v1.2.1