From 4f4a875ebef8e6dda70211b0e3c0fa43a2a23990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Sch=C3=B6nberg?= Date: Sun, 28 May 2017 17:50:53 +0200 Subject: [PATCH] Add a marker and circle of accuracy for current location Currently the user's position is not visible on the map. This commit adds a marker to the user's position and a circular polygon which shows the accuracy of the location measurement. --- .../free/nrw/commons/MediaDataExtractor.java | 2 +- .../fr/free/nrw/commons/location/LatLng.java | 4 +- .../location/LocationServiceManager.java | 16 +++++- .../nrw/commons/nearby/NearbyInfoDialog.java | 2 +- .../nrw/commons/nearby/NearbyMapFragment.java | 52 +++++++++++++++++++ .../free/nrw/commons/nearby/NearbyPlaces.java | 4 +- 6 files changed, 73 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java b/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java index 280309d3d..8bbc03f4d 100644 --- a/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java +++ b/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java @@ -262,7 +262,7 @@ public class MediaDataExtractor { NodeList childNodes = parentNode.getChildNodes(); double latitudeText = Double.parseDouble(childNodes.item(1).getTextContent()); double longitudeText = Double.parseDouble(childNodes.item(2).getTextContent()); - LatLng coordinates = new LatLng(latitudeText, longitudeText); + LatLng coordinates = new LatLng(latitudeText, longitudeText, 0); return coordinates.getPrettyCoordinateString(); } diff --git a/app/src/main/java/fr/free/nrw/commons/location/LatLng.java b/app/src/main/java/fr/free/nrw/commons/location/LatLng.java index acd67ebf7..0cc5ba00f 100644 --- a/app/src/main/java/fr/free/nrw/commons/location/LatLng.java +++ b/app/src/main/java/fr/free/nrw/commons/location/LatLng.java @@ -4,6 +4,7 @@ public class LatLng { public final double latitude; public final double longitude; + public final float accuracy; /** Accepts latitude and longitude. * North and South values are cut off at 90° @@ -11,13 +12,14 @@ public class LatLng { * @param latitude double value * @param longitude double value */ - public LatLng(double latitude, double longitude) { + public LatLng(double latitude, double longitude, float accuracy) { if(-180.0D <= longitude && longitude < 180.0D) { this.longitude = longitude; } else { this.longitude = ((longitude - 180.0D) % 360.0D + 360.0D) % 360.0D - 180.0D; } this.latitude = Math.max(-90.0D, Math.min(90.0D, latitude)); + this.accuracy = accuracy; } public int hashCode() { diff --git a/app/src/main/java/fr/free/nrw/commons/location/LocationServiceManager.java b/app/src/main/java/fr/free/nrw/commons/location/LocationServiceManager.java index 3c0d2b23b..041281464 100644 --- a/app/src/main/java/fr/free/nrw/commons/location/LocationServiceManager.java +++ b/app/src/main/java/fr/free/nrw/commons/location/LocationServiceManager.java @@ -14,6 +14,7 @@ public class LocationServiceManager implements LocationListener { private String provider; private LocationManager locationManager; private LatLng latestLocation; + private Float latestLocationAccuracy; public LocationServiceManager(Context context) { this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); @@ -24,6 +25,16 @@ public class LocationServiceManager implements LocationListener { return latestLocation; } + /** + * Returns the accuracy of the location. The measurement is + * given as a radius in meter of 68 % confidence. + * + * @return Float + */ + public Float getLatestLocationAccuracy() { + return latestLocationAccuracy; + } + /** Registers a LocationManager to listen for current location. */ public void registerLocationManager() { @@ -57,9 +68,10 @@ public class LocationServiceManager implements LocationListener { public void onLocationChanged(Location location) { double currentLatitude = location.getLatitude(); double currentLongitude = location.getLongitude(); - Timber.d("Latitude: %f Longitude: %f", currentLatitude, currentLongitude); + latestLocationAccuracy = location.getAccuracy(); + Timber.d("Latitude: %f Longitude: %f Accuracy %f", currentLatitude, currentLongitude, latestLocationAccuracy); - latestLocation = new LatLng(currentLatitude, currentLongitude); + latestLocation = new LatLng(currentLatitude, currentLongitude, latestLocationAccuracy); } @Override diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java index 9308413da..e9e4ba771 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java @@ -57,7 +57,7 @@ public class NearbyInfoDialog extends OverlayDialog { Bundle bundle = getArguments(); placeTitle.setText(bundle.getString(ARG_TITLE)); placeDescription.setText(bundle.getString(ARG_DESC)); - location = new LatLng(bundle.getDouble(ARG_LATITUDE), bundle.getDouble(ARG_LONGITUDE)); + location = new LatLng(bundle.getDouble(ARG_LATITUDE), bundle.getDouble(ARG_LONGITUDE), 0); getArticleLink(bundle); } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java index b80d16313..093eee33f 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java @@ -1,5 +1,6 @@ package fr.free.nrw.commons.nearby; +import android.graphics.Color; import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; @@ -14,6 +15,8 @@ import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.annotations.Marker; +import com.mapbox.mapboxsdk.annotations.MarkerOptions; +import com.mapbox.mapboxsdk.annotations.PolygonOptions; import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.geometry.LatLng; @@ -24,6 +27,7 @@ import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; import com.mapbox.services.android.telemetry.MapboxTelemetry; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.List; import fr.free.nrw.commons.R; @@ -102,6 +106,8 @@ public class NearbyMapFragment extends android.support.v4.app.Fragment { return false; } }); + + addCurrentLocationMarker(mapboxMap); } }); if (PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean("theme",true)) { @@ -111,6 +117,52 @@ public class NearbyMapFragment extends android.support.v4.app.Fragment { } } + /** + * Adds a marker for the user's current position. Adds a + * circle which uses the accuracy * 2, to draw a circle + * which represents the user's position with an accuracy + * of 95%. + */ + public void addCurrentLocationMarker(MapboxMap mapboxMap) { + MarkerOptions currentLocationMarker = new MarkerOptions() + .position(new LatLng(curLatLng.latitude, curLatLng.longitude)); + mapboxMap.addMarker(currentLocationMarker); + + List circle = createCircleArray(curLatLng.latitude, curLatLng.longitude, + curLatLng.accuracy * 2, 100); + + mapboxMap.addPolygon( + new PolygonOptions() + .addAll(circle) + .strokeColor(Color.parseColor("#55000000")) + .fillColor(Color.parseColor("#11000000")) + ); + } + + /** + * Creates a series of points that create a circle on the map. + * Takes the center latitude, center longitude of the circle, + * the radius in meter and the number of nodes of the circle. + * + * @return List List of LatLng points of the circle. + */ + public List createCircleArray(double centerLat, double centerLong, float radius, int nodes) { + List circle = new ArrayList<>(); + float radiusKilometer = radius / 1000; + double radiusLong = radiusKilometer / + (111.320 * Math.cos(centerLat * Math.PI / 180)); + double radiusLat = radiusKilometer / 110.574; + + for (int i = 0; i < nodes; i++) { + double theta = ((double) i / (double) nodes) * (2 * Math.PI); + double nodeLongitude = centerLong + radiusLong * Math.cos(theta); + double nodeLatitude = centerLat + radiusLat * Math.sin(theta); + circle.add(new LatLng(nodeLatitude, nodeLongitude)); + } + + return circle; + } + @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java index 365d3e06f..4683246fc 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java @@ -125,7 +125,7 @@ public class NearbyPlaces { type, // list type, // details Uri.parse(icon), - new LatLng(latitude, longitude), + new LatLng(latitude, longitude, 0), new Sitelinks.Builder() .setWikipediaLink(wikipediaSitelink) .setCommonsLink(commonsSitelink) @@ -187,7 +187,7 @@ public class NearbyPlaces { type, // list type, // details null, - new LatLng(latitude, longitude), + new LatLng(latitude, longitude, 0), new Sitelinks.Builder().build() )); }