Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[android] - move calculation of LatLngBounds to core (#8765)
Browse files Browse the repository at this point in the history
  • Loading branch information
tobrun authored Apr 20, 2017
1 parent 86433df commit 0757393
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 158 deletions.
1 change: 1 addition & 0 deletions platform/android/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to
* Expose source layer identifier [#8709](https://github.com/mapbox/mapbox-gl-native/pull/8709).
* Ensure surface is created after display and context [#8759](https://github.com/mapbox/mapbox-gl-native/pull/8759)
* Harden telemetry event dispatch [#8767](https://github.com/mapbox/mapbox-gl-native/pull/8767)
* Move LatLngBounds calculation for CameraUpdateFactory to core [#8765](https://github.com/mapbox/mapbox-gl-native/pull/8765)

## 5.0.2 - April 3, 2017

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,24 +231,6 @@ public Builder(CameraUpdateFactory.ZoomUpdate update) {
}
}

/**
* Create Builder from an existing array of doubles.
* <p>
* These values conform to map.ccp representation of a camera position.
* </p>
*
* @param nativeCameraValues Values containing target, bearing, tilt and zoom
*/
public Builder(double[] nativeCameraValues) {
super();
if (nativeCameraValues != null && nativeCameraValues.length == 5) {
target(new LatLng(nativeCameraValues[0], nativeCameraValues[1]).wrap());
bearing(MathUtils.convertNativeBearing(nativeCameraValues[2]));
tilt(nativeCameraValues[3]);
zoom(nativeCameraValues[4]);
}
}

/**
* Sets the direction that the camera is pointing in, in degrees clockwise from north.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.RectF;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;

Expand All @@ -11,7 +10,6 @@
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;
Expand Down Expand Up @@ -199,17 +197,13 @@ public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) {
static final class CameraBoundsUpdate implements CameraUpdate {

private LatLngBounds bounds;
private RectF padding;
private int[] padding;

CameraBoundsUpdate(LatLngBounds bounds, RectF padding) {
CameraBoundsUpdate(LatLngBounds bounds, int[] padding) {
this.bounds = bounds;
this.padding = padding;
}

CameraBoundsUpdate(LatLngBounds bounds, int[] padding) {
this(bounds, new RectF(padding[0], padding[1], padding[2], padding[3]));
}

CameraBoundsUpdate(LatLngBounds bounds, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
this(bounds, new int[] {paddingLeft, paddingTop, paddingRight, paddingBottom});
}
Expand All @@ -218,64 +212,13 @@ public LatLngBounds getBounds() {
return bounds;
}

public RectF getPadding() {
public int[] getPadding() {
return padding;
}

@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 = projection.calculateZoom(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();
return mapboxMap.getCameraForLatLngBounds(bounds, padding);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1521,6 +1521,27 @@ public void setLatLngBoundsForCameraTarget(@Nullable LatLngBounds latLngBounds)
nativeMapView.setLatLngBounds(latLngBounds);
}

/**
* Gets a camera position that would fit a bounds.
*
* @param latLngBounds the bounds to constrain the map with
*/
public CameraPosition getCameraForLatLngBounds(@Nullable LatLngBounds latLngBounds, int[] padding) {
// calculate and set additional bounds padding
int[] mapPadding = getPadding();
for (int i = 0; i < padding.length; i++) {
padding[i] = mapPadding[i] + padding[i];
}
projection.setContentPadding(padding, myLocationViewSettings.getPadding());

// get padded camera position from LatLngBounds
CameraPosition cameraPosition = nativeMapView.getCameraForLatLngBounds(latLngBounds);

// reset map padding
setPadding(mapPadding);
return cameraPosition;
}

//
// Padding
//
Expand All @@ -1544,7 +1565,11 @@ public void setLatLngBoundsForCameraTarget(@Nullable LatLngBounds latLngBounds)
* @param bottom The bottom margin in pixels.
*/
public void setPadding(int left, int top, int right, int bottom) {
projection.setContentPadding(new int[] {left, top, right, bottom}, myLocationViewSettings.getPadding());
setPadding(new int[] {left, top, right, bottom});
}

private void setPadding(int[] padding) {
projection.setContentPadding(padding, myLocationViewSettings.getPadding());
uiSettings.invalidate();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.Polygon;
import com.mapbox.mapboxsdk.annotations.Polyline;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
Expand Down Expand Up @@ -317,6 +318,13 @@ public LatLng getLatLng() {
return nativeGetLatLng().wrap();
}

public CameraPosition getCameraForLatLngBounds(LatLngBounds latLngBounds) {
if (isDestroyedOn("getCameraForLatLngBounds")) {
return null;
}
return nativeGetCameraForLatLngBounds(latLngBounds);
}

public void resetPosition() {
if (isDestroyedOn("resetPosition")) {
return;
Expand Down Expand Up @@ -676,11 +684,11 @@ public void flyTo(double angle, LatLng center, long duration, double pitch, doub
nativeFlyTo(angle, center.getLatitude(), center.getLongitude(), duration, pitch, zoom);
}

public double[] getCameraValues() {
public CameraPosition getCameraPosition() {
if (isDestroyedOn("getCameraValues")) {
return new double[] {};
return new CameraPosition.Builder().build();
}
return nativeGetCameraValues();
return nativeGetCameraPosition();
}

// Runtime style Api
Expand Down Expand Up @@ -970,6 +978,8 @@ private native void nativeInitialize(NativeMapView nativeMapView,

private native LatLng nativeGetLatLng();

private native CameraPosition nativeGetCameraForLatLngBounds(LatLngBounds latLngBounds);

private native void nativeResetPosition();

private native double nativeGetPitch();
Expand Down Expand Up @@ -1054,7 +1064,7 @@ private native void nativeEaseTo(double angle, double latitude, double longitude
private native void nativeFlyTo(double angle, double latitude, double longitude,
long duration, double pitch, double zoom);

private native double[] nativeGetCameraValues();
private native CameraPosition nativeGetCameraPosition();

private native long nativeGetTransitionDuration();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ final void animateCamera(MapboxMap mapboxMap, CameraUpdate update, int durationM
@Nullable
CameraPosition invalidateCameraPosition() {
if (mapView != null) {
cameraPosition = new CameraPosition.Builder(mapView.getCameraValues()).build();
cameraPosition = mapView.getCameraPosition();
if (onCameraChangeListener != null) {
onCameraChangeListener.onCameraChange(this.cameraPosition);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
package com.mapbox.mapboxsdk.testapp.activity.camera;

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;

import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.camera.CameraUpdate;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.UiSettings;
import com.mapbox.mapboxsdk.testapp.R;

import java.util.ArrayList;
import java.util.List;

import timber.log.Timber;

/**
* Test activity showcasing using the LatLngBounds camera API.
* <p>
Expand All @@ -31,6 +27,9 @@ public class LatLngBoundsActivity extends AppCompatActivity implements OnMapRead
private static final LatLng LOS_ANGELES = new LatLng(34.053940, -118.242622);
private static final LatLng NEW_YORK = new LatLng(40.712730, -74.005953);

private final LatLng CHINA_BOTTOM_LEFT = new LatLng(15.68169, 73.499857);
private final LatLng CHINA_TOP_RIGHT = new LatLng(53.560711, 134.77281);

private MapView mapView;
private MapboxMap mapboxMap;

Expand All @@ -46,41 +45,31 @@ protected void onCreate(Bundle savedInstanceState) {
}

@Override
public void onMapReady(MapboxMap map) {
public void onMapReady(final MapboxMap map) {
mapboxMap = map;
UiSettings uiSettings = mapboxMap.getUiSettings();
uiSettings.setAllGesturesEnabled(false);

mapboxMap.addMarker(new MarkerOptions()
.title("Los Angeles")
.snippet("City Hall")
.position(LOS_ANGELES));

mapboxMap.addMarker(new MarkerOptions()
.title("New York")
.snippet("City Hall")
.position(NEW_YORK));

List<LatLng> points = new ArrayList<>();
points.add(NEW_YORK);
points.add(LOS_ANGELES);

// Create Bounds
final LatLngBounds bounds = new LatLngBounds.Builder()
.includes(points)
.build();

// Add map padding
int mapPadding = (int) getResources().getDimension(R.dimen.fab_margin);
mapboxMap.setPadding(mapPadding, mapPadding, mapPadding, mapPadding);

// Move camera to the bounds with added padding
int padding = (int) getResources().getDimension(R.dimen.coordinatebounds_margin);
mapboxMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, padding), 1500);

// Log data
Timber.e("Move to bounds: " + bounds.toString());
Timber.e("Resulting bounds:" + mapboxMap.getProjection().getVisibleRegion().latLngBounds.toString());
moveToBounds(new LatLngBounds.Builder().include(NEW_YORK).include(LOS_ANGELES).build(), new int[] {0, 0, 0, 0});
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
moveToBounds(new LatLngBounds.Builder().include(CHINA_BOTTOM_LEFT).include(CHINA_TOP_RIGHT).build(),
new int[] {100, 100, 100, 100 });
}
}, 5000);
}

private void moveToBounds(LatLngBounds latLngBounds, int[] padding) {
mapboxMap.clear();
mapboxMap.addMarker(new MarkerOptions().position(latLngBounds.getNorthEast()));
mapboxMap.addMarker(new MarkerOptions().position(latLngBounds.getSouthEast()));
mapboxMap.addMarker(new MarkerOptions().position(latLngBounds.getSouthWest()));
mapboxMap.addMarker(new MarkerOptions().position(latLngBounds.getNorthWest()));
CameraUpdate update =
CameraUpdateFactory.newLatLngBounds(latLngBounds,
padding[0],
padding[1],
padding[2],
padding[3]);
mapboxMap.moveCamera(update);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,6 @@ public void testTypedArrayBuilder() {
assertEquals("zoom should match", zoom, cameraPosition.zoom, DELTA);
}

@Test
public void testJniBuilder() {
double bearing = 180;
double zoom = 12;
double latitude = 10;
double longitude = 11;
double tilt = 44;

double[] cameraVars = new double[]{latitude, longitude, bearing, tilt, zoom};
CameraPosition cameraPosition = new CameraPosition.Builder(cameraVars).build();
assertEquals("bearing should match", bearing, cameraPosition.bearing, DELTA);
assertEquals("latlng should match", new LatLng(latitude, longitude), cameraPosition.target);
assertEquals("tilt should match", tilt, cameraPosition.tilt, DELTA);
assertEquals("zoom should match", zoom, cameraPosition.zoom, DELTA);
}

@Test
public void testToString() {
LatLng latLng = new LatLng(1, 2);
Expand Down
2 changes: 2 additions & 0 deletions platform/android/config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ add_library(mbgl-android STATIC
platform/android/src/style/conversion/property_value.hpp
platform/android/src/style/conversion/types.hpp
platform/android/src/style/conversion/types_string_values.hpp
platform/android/src/map/camera_position.cpp
platform/android/src/map/camera_position.hpp

# Style conversion Java -> C++
platform/android/src/style/android_conversion.hpp
Expand Down
3 changes: 3 additions & 0 deletions platform/android/src/jni.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ void registerNatives(JavaVM *vm) {
IdentityStops::registerNative(env);
IntervalStops::registerNative(env);

// Map
CameraPosition::registerNative(env);

// Connectivity
ConnectivityListener::registerNative(env);

Expand Down
Loading

0 comments on commit 0757393

Please sign in to comment.