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.
This commit is contained in:
Tobias Schönberg 2017-05-28 17:50:53 +02:00
parent 4b400cd8aa
commit 4f4a875ebe
6 changed files with 73 additions and 7 deletions

View file

@ -262,7 +262,7 @@ public class MediaDataExtractor {
NodeList childNodes = parentNode.getChildNodes(); NodeList childNodes = parentNode.getChildNodes();
double latitudeText = Double.parseDouble(childNodes.item(1).getTextContent()); double latitudeText = Double.parseDouble(childNodes.item(1).getTextContent());
double longitudeText = Double.parseDouble(childNodes.item(2).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(); return coordinates.getPrettyCoordinateString();
} }

View file

@ -4,6 +4,7 @@ public class LatLng {
public final double latitude; public final double latitude;
public final double longitude; public final double longitude;
public final float accuracy;
/** Accepts latitude and longitude. /** Accepts latitude and longitude.
* North and South values are cut off at 90° * North and South values are cut off at 90°
@ -11,13 +12,14 @@ public class LatLng {
* @param latitude double value * @param latitude double value
* @param longitude 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) { if(-180.0D <= longitude && longitude < 180.0D) {
this.longitude = longitude; this.longitude = longitude;
} else { } else {
this.longitude = ((longitude - 180.0D) % 360.0D + 360.0D) % 360.0D - 180.0D; 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.latitude = Math.max(-90.0D, Math.min(90.0D, latitude));
this.accuracy = accuracy;
} }
public int hashCode() { public int hashCode() {

View file

@ -14,6 +14,7 @@ public class LocationServiceManager implements LocationListener {
private String provider; private String provider;
private LocationManager locationManager; private LocationManager locationManager;
private LatLng latestLocation; private LatLng latestLocation;
private Float latestLocationAccuracy;
public LocationServiceManager(Context context) { public LocationServiceManager(Context context) {
this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
@ -24,6 +25,16 @@ public class LocationServiceManager implements LocationListener {
return latestLocation; 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. /** Registers a LocationManager to listen for current location.
*/ */
public void registerLocationManager() { public void registerLocationManager() {
@ -57,9 +68,10 @@ public class LocationServiceManager implements LocationListener {
public void onLocationChanged(Location location) { public void onLocationChanged(Location location) {
double currentLatitude = location.getLatitude(); double currentLatitude = location.getLatitude();
double currentLongitude = location.getLongitude(); 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 @Override

View file

@ -57,7 +57,7 @@ public class NearbyInfoDialog extends OverlayDialog {
Bundle bundle = getArguments(); Bundle bundle = getArguments();
placeTitle.setText(bundle.getString(ARG_TITLE)); placeTitle.setText(bundle.getString(ARG_TITLE));
placeDescription.setText(bundle.getString(ARG_DESC)); 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); getArticleLink(bundle);
} }

View file

@ -1,5 +1,6 @@
package fr.free.nrw.commons.nearby; package fr.free.nrw.commons.nearby;
import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
@ -14,6 +15,8 @@ import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.annotations.Marker; 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.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLng;
@ -24,6 +27,7 @@ import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.services.android.telemetry.MapboxTelemetry; import com.mapbox.services.android.telemetry.MapboxTelemetry;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
@ -102,6 +106,8 @@ public class NearbyMapFragment extends android.support.v4.app.Fragment {
return false; return false;
} }
}); });
addCurrentLocationMarker(mapboxMap);
} }
}); });
if (PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean("theme",true)) { 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<LatLng> 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<LatLng> createCircleArray(double centerLat, double centerLong, float radius, int nodes) {
List<LatLng> 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 @Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);

View file

@ -125,7 +125,7 @@ public class NearbyPlaces {
type, // list type, // list
type, // details type, // details
Uri.parse(icon), Uri.parse(icon),
new LatLng(latitude, longitude), new LatLng(latitude, longitude, 0),
new Sitelinks.Builder() new Sitelinks.Builder()
.setWikipediaLink(wikipediaSitelink) .setWikipediaLink(wikipediaSitelink)
.setCommonsLink(commonsSitelink) .setCommonsLink(commonsSitelink)
@ -187,7 +187,7 @@ public class NearbyPlaces {
type, // list type, // list
type, // details type, // details
null, null,
new LatLng(latitude, longitude), new LatLng(latitude, longitude, 0),
new Sitelinks.Builder().build() new Sitelinks.Builder().build()
)); ));
} }