I'm trying to sum up the total distance between an array of LatLng but failing hard. Here's what I've got so far:
private double sumDistance() {
Location loc = new Location("distance provider");
double previousLatitude;
double previousLongitude;
float[] results = new float[1];
for (LatLng latLng : mMapList) {
previousLatitude = latLng.latitude;
previousLongitude = latLng.longitude;
loc.distanceBetween(previousLatitude, previousLongitude, latLng.latitude, latLng.longitude, results);
}
return 0;
}
The problem with this is that the latlng for both are the same. Is there some way I can get the previous latlng or a cleaner way to do this that I'm not thinking of?
Why don't you assign the "previous variable" after you've calculated the distance? Something like this should work
private double sumDistance() {
Location loc = new Location("distance provider");
double previousLatitude = mMapList.get(0).latitude;
double previousLongitude = mMapList.get(0).longitude;
float[] results;
for (int i=1;i<mMapList.size();i++) {
loc.distanceBetween(previousLatitude, previousLongitude, mMapList.get(i).latitude, mMapList.get(i).longitude, results);
previousLatitude = mMapList[i].latitude;
previousLongitude = mMapList[i].longitude;
}
return 0;
}
double previousLatitude;
double previousLongitude;
float[] results;
for (int i=0; i<mMapList.size(); ++i) {
LatLng latLng = mMapList.get(i);
if (i == 0) {
// Previous weren't set yet, nothing to measure
// Set them and skip loop
previousLatitude = latLng.latitude;
previousLongitude = latLng.longitude;
continue;
}
// Measure previous with current
loc.distanceBetween(previousLatitude, previousLongitude, latLng.latitude, latLng.longitude, results);
// ~ Use the distance
// Modify the previous ones
previousLatitude = latLng.latitude;
previousLongitude = latLng.longitude;
}
Related
I've been stuck on the problem. i'm searching for Tesco stores in this geocoder. Is there anyway way of getting only the closest result of the geo.getFromLocationName?
private void setUpMap() throws IOException {
Geocoder geo = new Geocoder(getApplicationContext(), Locale.getDefault());
List<Address> addressList= geo.getFromLocationName("Tesco",1);
Address add = addressList.get(0);
String locality = add.getLocality();
double lat = addressList.get(0).getLatitude();
double lng = addressList.get(0).getLongitude();
mMap.addMarker(new MarkerOptions().position(new LatLng(lat,lng)).title("Waitrose"));
}
Modify your method like this:
private void setUpMap() throws IOException {
Geocoder geo = new Geocoder(getApplicationContext(), Locale.getDefault());
List<Address> addressList= geo.getFromLocationName("Tesco",1);
Address yourAddress = // get your location or the address to compare
Address closest = findClosest(addressList, yourAddress);
// do what you need
}
To create the findClosest you have to create a function that iterates over results and use haversine formula to calculate the distance to your location (or the desired one).
public double rad(double x)
{
return x*Math.PI/180.;
}
public Address findClosest( List<Address> addressList, Address yourAddress )
{
double lat = yourAddress.getLatitude(); // your (or desired) latitude
double lng = yourAddress.getLongitude(); // your (or desired) longitude
double R = 6371.; // radius of earth in km
double[] distances = new double[addressList.lenght];
var closest = -1;
for( i=0;i<addressList.lenght; i++ ) {
double mlat = addressList.get(i).getLatitude();
double mlng = addressList.get(i).getLongitude();
double dLat = rad(mlat - lat);
double dLong = rad(mlng - lng);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(rad(lat)) * Math.cos(rad(lat)) * Math.sin(dLong/2) * Math.sin(dLong/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double d = R * c;
distances[i] = d;
if ( closest == -1 || d < distances[closest] ) {
closest = i;
}
}
return addressList.get(closest);
}
I've searched for similar questions here but none of them helped me.
I have an application running on the map that shows the path taken by the user and an icon in the form of "police". What I want now is that this icon to move the map behind me. So I created a method (stalk) that calculates a new point given the current position of the user, the position of the icon and the map. The method works, but the problem is that when I run my application icon only moves once, because his position is not updated.
Here's part of my code:
public void onMyLocationChange(Location location) {
double latitude = location.getLatitude();
double longitude = location.getLongitude();
lat = String.valueOf(latitude);
longi = String.valueOf(longitude);
posCurrent = new LatLng(latitude, longitude);
posAtuais.add(posCurrent);
posInicial = posAtuais.get(0);
Marker marker = map.addMarker(new MarkerOptions().position(posInicial));
map.moveCamera(CameraUpdateFactory.newLatLngZoom(posCurrent, 19));
PolylineOptions options = new PolylineOptions().width(5).color(mudaLinhaCor(heart_rate)).geodesic(true);
for (int z = 0; z < posAtuais.size(); z++) {
LatLng point = posAtuais.get(z);
options.add(point);
}
line = map.addPolyline(options);
LatLng posPolice = stalk(posCurrent, POLICE, map);
Marker init = map.addMarker(new MarkerOptions().position(posPolice)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.police)));
}
//A method that computes a new position
public LatLng stalk(LatLng player,LatLng police,GoogleMap mapView){
Projection projection = mapView.getProjection();
Point pointInicial = new Point(); //police
pointInicial = projection.toScreenLocation(police);
Point pointFinal = new Point(); //player
pointFinal = projection.toScreenLocation(player);
double y=0.2;
int x=0;
if((pointInicial.x==pointFinal.x)){
y=pointInicial.y+1;
}else{
double m=(pointFinal.y-pointInicial.y)/(pointFinal.x-pointInicial.x);
double b=pointInicial.y-(m*pointInicial.x);
int i=1;
while(y != (int)y){
if(pointInicial.x<pointFinal.x){
x=pointInicial.x+i;
//System.out.println("entrou no x<xfnal: "+x);
}
else if(pointInicial.x>pointFinal.x){
//System.out.println("entrou no x>xfnal");
x=pointInicial.x-i;
}
y=m*x+b;
//System.out.println("y: : "+y);
i++;
}
}
return projection.fromScreenLocation(new Point(x, (int) y));
}
Someone could help me.
Implement OnMarkerDragListener in your activity then
#Override
public void onMarkerDragStart(Marker arg0) {
markerOptions.position(latLng);
}
#Override
public void onMarkerDragEnd(Marker arg0) {
myMap.clear();
latLng = arg0.getPosition();
markerOptions.position(latLng);
Marker marker = myMap.addMarker(markerOptions);
}
I get the data from my database which contains, TITLE, SNIPPET and LOCATION and tried to test to check the distances between my currentlocation. I'm confused how to display the title of the closest marker to my position.
List<MyMarkerObj> m = data.getMyMarkers();
for (int i = 0; i < m.size(); i++) {
String[] slatlng = m.get(i).getPosition().split(" ");
LatLng lat = new LatLng(Double.valueOf(slatlng[0]), Double.valueOf(slatlng[1]));
map.addMarker(new MarkerOptions()
.title(m.get(i).getTitle())
.snippet(m.get(i).getSnippet())
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
.position(lat)
);
float[] distance = new float[1];
Location.distanceBetween(currentlat, currentlong,Double.valueOf(slatlng[0]), Double.valueOf(slatlng[1]), distance);
Toast.makeText(getActivity(), "Marker Distance: "+ m.get(i).getTitle() +" "+distance[0], Toast.LENGTH_LONG).show();
}
I made few changes here. Try it..
List<MyMarkerObj> m = data.getMyMarkers();
float mindist;
int pos=0;
for (int i = 0; i < m.size(); i++) {
String[] slatlng = m.get(i).getPosition().split(" ");
LatLng lat = new LatLng(Double.valueOf(slatlng[0]), Double.valueOf(slatlng[1]));
map.addMarker(new MarkerOptions()
.title(m.get(i).getTitle())
.snippet(m.get(i).getSnippet())
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
.position(lat)
);
float[] distance = new float[1];
Location.distanceBetween(currentlat, currentlong,Double.valueOf(slatlng[0]), Double.valueOf(slatlng[1]), distance);
if(i==0) mindist=distance[0];
else if(mindist>distance[0]) {
mindist=distance[0];
pos=i;
}
}
Toast.makeText(getActivity(), "Closest Marker Distance: "+ m.get(pos).getTitle() +" "+mindist, Toast.LENGTH_LONG).show();
You can use this simple function to calculate distance between two points in latitude and longitude format it works like a charm, and you can then check for which distance is closest from your location. just pass the latitude and longitude of both location in it
public double distanceFrom(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 3958.75;
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(dLng/2) * Math.sin(dLng/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
int meterConversion = 1609;
return new Double(dist * meterConversion).floatValue(); // this will return distance
}
I have a Problem to get the right way to get the distanceTo from my 2 Geo Points. How to get it work?
from the gps class:
double latitude; // latitude
String mlat;
latitude = location.getLatitude();
mlat = String.valueOf(latitude);
from the ListView:
// Get distance
String mReportA;
double mLocB;
int distance;
mReportA = e.getString("lat");
mReportA = e.getString("lon");
mLocB = gps.latitude;
mLocB = gps.longitude;
distance = mReportA.distanceTo(mLocB);
Error in Eclipse: The method distanceTo(double) is undefined for the type String
I get e.getString("lat"); from json
To calculate distance between two geopoint you can follow the below example.
double currentLatitude = location.getLatitude();
double currentLongitude = location.getLongitude();
double endLatitude = lat;
double endLongitude = lng;
float[] results = new float[3];
Location.distanceBetween(currentLatitude, currentLongitude,endLatitude, endLongitude, results);
BigDecimal bd = new BigDecimal(results[0]);// results in meters
BigDecimal rounded = bd.setScale(2, RoundingMode.HALF_UP);
double values = rounded.doubleValue();
EDIT
if (values > 1000) {
values = (Double) (values * 0.001f);// convert meters to Kilometers
bd = new BigDecimal(values);
rounded = bd.setScale(2, RoundingMode.HALF_UP);
values = rounded.doubleValue();
}
// Here is the code to find out the distance between two locations
float distance;
Location locationA = new Location("A");
locationA.setLatitude(latA);
locationA.setLongitude(lngA);
Location locationB = new Location("B");
locationB.setLatitude(latB);
LocationB.setLongitude(lngB);
distance = locationA.distanceTo(locationB);
I am having trouble in converting the latitude and longitude values into android esri arcGIS map Point. Here's my code to get latitude and longitude values from GPS coordinates:
LocationManager lm;
String towers;
double lat;
double longi;
TextView txt;
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria crit = new Criteria();
towers = lm.getBestProvider(crit, false);
Location location = lm.getLastKnownLocation(towers);
if(location != null)
{
lat = location.getLatitude();
longi = location.getLongitude();
}
now I have the latitude and longitude values. Now all I need is to convert these values into valid esri arcGIS MapPoint. Can anyone help me?
Thanks in advance.
Assuming you're using the ESRI Android API? If so, create a graphics layer on your map. Then create a point object
com.esri.core.geometry.Point
Point myPoint = new Point();
then set the x/y values:
myPoint.setX(longi);
myPoint.setY(lat);
then add myPoint to the graphics object.
http://help.arcgis.com/en/arcgismobile/10.0/apis/android/api/index.html
Yes, it is possible. But you don't use the locationmanager in ArcGis.
ArcGIS has the predefined method like LocationListener, that is: OnStatusChangedListener.
See the below code for converting location latitude and longitude into esri arcGIS MapPoint.
mMapView.setOnStatusChangedListener(new OnStatusChangedListener() {
/**
*
*/
private static final long serialVersionUID = 1L;
public void onStatusChanged(Object source, STATUS status) {
if (source == mMapView && status == STATUS.INITIALIZED) {
LocationService ls = mMapView.getLocationService();
ls.setAutoPan(false);
ls.setLocationListener(new LocationListener() {
boolean locationChanged = false;
// Zooms to the current location when first GPS fix
// arrives.
public void onLocationChanged(Location loc) {
if (!locationChanged) {
locationChanged = true;
double locy = loc.getLatitude();
double locx = loc.getLongitude();
Point wgspoint = new Point(locx, locy);
Point mapPoint = (Point) GeometryEngine.project(wgspoint,
SpatialReference.create(4326),
mMapView.getSpatialReference());
Unit mapUnit = mMapView.getSpatialReference().getUnit();
double zoomWidth = Unit.convertUnits(
SEARCH_RADIUS, Unit.create(LinearUnit.Code.MILE_US), mapUnit);
Envelope zoomExtent = new Envelope(mapPoint, zoomWidth, zoomWidth);
mMapView.setExtent(zoomExtent);
GraphicsLayer gLayer = new GraphicsLayer();
PictureMarkerSymbol symbol = new
PictureMarkerSymbol(getResources().getDrawable(R.drawable.twiz_car_red));
Graphic graphic = new Graphic(mapPoint, symbol);
//Graphic point=new Graphic(new Point(x, y),new
SimpleMarkerSymbol(Color.CYAN,20,STYLE.CIRCLE));
gLayer.addGraphic(graphic);
mMapView .addLayer(gLayer);
}
}
public void onProviderDisabled(String arg0) {
}
public void onProviderEnabled(String arg0) {
}
public void onStatusChanged(String arg0, int arg1,
Bundle arg2) {
}
});
ls.start();
}
}
});
I've borrowed some code from here
private Point ToGeographic(Point pnt)
{
double mercatorX_lon = pnt.getX();
double mercatorY_lat = pnt.getY();
if (Math.abs(mercatorX_lon) < 180 && Math.abs(mercatorY_lat) < 90)
return pnt;
if ((Math.abs(mercatorX_lon) > 20037508.3427892) || (Math.abs(mercatorY_lat) > 20037508.3427892))
return pnt;
double x = mercatorX_lon;
double y = mercatorY_lat;
double num3 = x / 6378137.0;
double num4 = num3 * 57.295779513082323;
double num5 = Math.floor((double)((num4 + 180.0) / 360.0));
double num6 = num4 - (num5 * 360.0);
double num7 = 1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * y) / 6378137.0)));
mercatorX_lon = num6;
mercatorY_lat = num7 * 57.295779513082323;
return new Point(mercatorX_lon, mercatorY_lat);
}
private Point ToWebMercator(Point pnt)
{
double mercatorX_lon = pnt.getX();
double mercatorY_lat = pnt.getY();
if ((Math.abs(mercatorX_lon) > 180 || Math.abs(mercatorY_lat) > 90))
return pnt;
double num = mercatorX_lon * 0.017453292519943295;
double x = 6378137.0 * num;
double a = mercatorY_lat * 0.017453292519943295;
mercatorX_lon = x;
mercatorY_lat = 3189068.5 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)));
return new Point(mercatorX_lon, mercatorY_lat);
}
I make no claims of efficiency, but it's a starting point at least.
Disclaimer: I'm not an expert in this, but want to try to help. :)
There is now an ArcGIS Stack Exchange site. There's more information being added all the time and is a nice consolidated resource compared to what is out there disbursed on the interwebs.
For frameworks, I recommend GeoTools for Android.
As an aside, QGIS for Android is an interesting project from Marco Bernasocchi which you may find helpful as a reference.
Hope you can find what you're looking for!
i made a function that converts the two parameters of a location point to arcgis point :
private Point ConvertMyLocationPoint(final double x, final double y) {
Point wgspoint = new Point(x, y);
Point mapPoint = (Point) GeometryEngine.project(wgspoint, SpatialReference.create(4326),
mMapView.getSpatialReference());
return mapPoint;
}
//convert longitude and latitude to map point X Y
- (AGSPoint *)agsPointFromLatitude:(double)latitude longitude:(double)longitude
{
double mercatorX = longitude * 0.017453292519943295 * 6378137.0;
double a = latitude * 0.017453292519943295;
double mercatorY = 3189068.5 * log((1.0 + sin(a))/(1.0 - sin(a)));
AGSPoint *obj = [AGSPoint pointWithX:mercatorX y:mercatorY spatialReference: [AGSSpatialReference wgs84SpatialReference]];
return obj;
}