I am trying to calculate the distance between two Geo Locations. The problem I have is the following: I tried with libraries like :Geocalc and Haversine formulas, like this:
public static final double RKilometers = 6371;
public static double calculationByDistance(double lat1, double lon1, double lat2, double lon2) {
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
lat1 = Math.toRadians(lat1);
lat2 = Math.toRadians(lat2);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
double c = 2 * Math.asin(Math.sqrt(a));
return RKilometers * c;
}
But I get the same wrong values with all those options. For short distances it works perfectly, but for long distances it doesn´t.
This is the test I did:
//distance between Barrow Island(Australia) and Tavatave(Madagascar)
assertEquals(calculationByDistance(20.82, 115.4, 18.15, 49.4), 6885, 20);
//get 6875.965169284442
//here is the problem
//distance between Rio Grande and Glasgow
assertEquals(calculationByDistance(32.05, 52.11, 55.83, 4.25), 10744, 20);
//get 4522.502442756569
Does someone know where is my error? Thank you!
I had this code from a long ago, I don't even remember if I wrote it myself or got it off someone. as far as I remember it gives a pretty good estimate, you can try it out and see if it works for you. (edits are welcomed)
public static double distFrom(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 3958.75; //this is in miles I believe
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double sindLat = Math.sin(dLat / 2);
double sindLng = Math.sin(dLng / 2);
double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2)
* Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2));
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
return dist;
}
I found the error. The problem was the values for latitud and longitud were wrong. I took the data from Wolframalpha and they don´t show the signs for the values. The rights values for my test are:
assertEquals(calculationByDistance(-32.05, 52.11, 55.83, -4.25), 10744, 20);
Thank you for your time!!!And sorry for the stupid error :)
public static float distFrom(float lat1, float lng1, float lat2, float lng2)
{
// Earth Radius in meters
double earthRadius = 6371000;
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));
float dist = (float) (earthRadius * c);
System.out.println("Distance is : " + dist);
return dist; // distance in meters
}
It is hard to propose you any code snippet or existing tools and services. Just because calculating distance depends on the certain task. There are many kinds of map projections and corresponding formulas.
For example, if you are using Google maps you probably can do more precise calculation taking into account height differences. OpenStreetMap, for instance, doesn't provide (at least a couple years ago) any height info, so your precision can vary (compare precision achieved using OpenStreetMap for 'flat' city in Eastern Europe and San Francisco, for example).
I've got satisfied with https://code.google.com/p/simplelatlng/. It is really simple and saves you from writing boilerplate code.
For long distances specific web services can do good job (especially when service aggregates data from the several other services).
Related
I have used locationA.distanceTo(locationB);
and also have copy pasted a method written for haversine formula.
The actual distance between the two geopoints is 25m but i get a
result of 6894.52192658389 using the above methods.
Followed this:Creating a method using Haversine Formula, Android V2
and this Find distance between two points on map using Google Map API V2
Checked distance using this free tool http://www.onlineconversion.com/map_greatcircle_distance.htm
You can try the code below :
public static float distFrom(float lat1, float lng1, float lat2, float lng2) {
double earthRadius = 6371000; //meters
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));
float dist = (float) (earthRadius * c);
return dist;
}
It will gives you the result in meters, you can convert to any required unit.
I have one Location (lat and long) and I want to find the next location(lat and long), which is 1 km away in 180 degree (in south) from my location(lat and long). Can you give me and algorithm or function?
Start with the Rosetta code implementation in Java:
public static double haversine(double lat1, double lon1, double lat2, double lon2) {
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
lat1 = Math.toRadians(lat1);
lat2 = Math.toRadians(lat2);
double a = Math.pow(Math.sin(dLat / 2),2) + Math.pow(Math.sin(dLon / 2),2) * Math.cos(lat1) * Math.cos(lat2);
double c = 2 * Math.asin(Math.sqrt(a));
return R * c;
}
If you know that lon1 == lon2, then an awful lot of this code drops right out, because dLon == 0:
public static double haversine(double lat1, double lat2) {
double dLat = Math.toRadians(lat2 - lat1);
return R * dLat;
}
(which should be familiar as the length = Radius * angle in radians formula)
So, if you know that R = 6372.8, and your desired result is 1, then it is easy to come up with a value for dLat:
dLat = 1.0 / 6372.8;
In other words, simply subtract 1.0 / 6372.8 from your current latitude (and remember to handle points of latitude less than 180 - 1.0 / 6372.8 carefully).
For an easy solution have a look at the SimpleLatLng library and its travel() method:
/**
* <p>
* Calculate the end point of traveling along a great-circle path from a
* given starting point with a given intitial bearing for a known distance.
* </p>
*
* #param start
* the starting point.
* #param initialBearing
* the initial bearing.
* #param distance
* the distance to travel.
* #param unit
* the unit in which distance is measured.
* #return the end point.
*/
public static LatLng travel(LatLng start, double initialBearing, double distance,
LengthUnit unit) {
double bR = Math.toRadians(initialBearing);
double lat1R = Math.toRadians(start.getLatitude());
double lon1R = Math.toRadians(start.getLongitude());
double dR = distance / LatLngConfig.getEarthRadius(unit);
double a = Math.sin(dR) * Math.cos(lat1R);
double lat2 = Math.asin(Math.sin(lat1R) * Math.cos(dR) + a * Math.cos(bR));
double lon2 = lon1R
+ Math.atan2(Math.sin(bR) * a, Math.cos(dR) - Math.sin(lat1R) * Math.sin(lat2));
return new LatLng(Math.toDegrees(lat2), Math.toDegrees(lon2));
}
You just give it the starting point, direction, distance and unit and you get the calculated location. You'll need to get the complete library as this method uses some classes declared by the library. It has some other useful calculations too.
It's available under the Apache 2.0 License.
Moving due South, also due North, makes the calculation simple as it avoids using longitude.
See
1 kms is equal to 0.0088339 degrees.
So in the the Northern hemisphere subtract 0.0088339 from the latitude of location and leave longitude as is.
For Southern Hemisphere add 0.0088339.
i have used Haversine for calculating distance between two location.
public static class Haversine {
static int Radius = 6371;
public static double haversine(double lat1, double lon1, double lat2,
double lon2) {
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
lat1 = Math.toRadians(lat1);
lat2 = Math.toRadians(lat2);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(lat1))
* Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2)
* Math.sin(dLon / 2);
double c = 2 * Math.asin(Math.sqrt(a));
double valueResult = Radius * c;
double km = valueResult / 1;
DecimalFormat newFormat = new DecimalFormat("####");
int kmInDec = Integer.valueOf(newFormat.format(km));
double meter = valueResult % 1000;
int meterInDec = Integer.valueOf(newFormat.format(meter));
Log.i("Radius Value", "" + valueResult + " KM " + kmInDec
+ " Meter " + meterInDec);
return Radius * c;
/*double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1)* Math.cos(lat2);
double c = 2 * Math.asin(Math.sqrt(a));
return R * 2 * Math.asin(Math.sqrt(a));*/
}
}
From the above code i am not able to get exact distance between 2 location.
When i run the above mehtod then it shows 4.32 km from my two places but when i checked on the google map then it shows the 5.3 km .
i have also used Location.distanceBetween method still it shows the 4.32 km .
How can i get exact distance between location?
You can see this link.
Haversine and Location.distanceBetween method are both the origin to the point at which a line.
So, you can use http://maps.googleapis.com/maps/api/directions/json?origin=Toronto&destination=Montreal&sensor=false to get the real distance.
From Google official repository link
SphericalUtil
MathUtil
Usage
double distance = SphericalUtil.computeDistanceBetween(new LatLng(9.000,10.00), new LatLng(9.000,11.00));
The above method will returns the distance between two LatLngs, in meters. Or try this
private String getDistance(LatLng my_latlong,LatLng frnd_latlong){
Location l1=new Location("One");
l1.setLatitude(my_latlong.latitude);
l1.setLongitude(my_latlong.longitude);
Location l2=new Location("Two");
l2.setLatitude(frnd_latlong.latitude);
l2.setLongitude(frnd_latlong.longitude);
float distance=l1.distanceTo(l2);
String dist=distance+" M";
if(distance>1000.0f)
{
distance=distance/1000.0f;
dist=distance+" KM";
}
return dist;
}
or you can give a look at link
Can we use android location https://developer.android.com/reference/android/location/Location.html
inside the java standalone application. I have to find the distance between two lat/lng pairs. Now i am using
public double Haversine(double lat1,double lon1,double lat2,double lon2)
{
double R = 6372.8; // Earth Radius in Kilometers
double dLat = Deg2Rad(lat2 - lat1);
double dLon = Deg2Rad(lon2 - lon1);
double a = (Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(Deg2Rad(lat1)) * Math.cos(Deg2Rad(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2));
double c = (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)));
double d = R * c;
// Return Distance in Kilometers
return d;
}
public double Deg2Rad( double deg) {
public double Deg2Rad( double deg) {
return (deg * Math.PI / 180);
}
But the above code gives the air distance. But i need roadway distance. Please help me out.. thanks in advance
You can do this using Directions API of Google Maps
https://developers.google.com/maps/documentation/directions/
Good example is : http://javapapers.com/android/draw-path-on-google-maps-android-api/
This is example of Distance API of Google Map, but you can refer to it and use Directions API in same way
You can use Google direction API for this. http://code.google.com/apis/maps/documentation/directions/
I think you will find this helpful
How To Calculate Distance Between Two Points in Driving Direction Mode in Android
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Working with latitude/longitude values in Java
Duplicate:
Working with latitude/longitude values in Java
How do I calculate distance between two latitude longitude points?
I need to calculate the distance between two points given by two coordinates. The project I am working on is a Java-project, so Java-code will be great, but pseudo-code can also be given, then I can implement it myself :)
As you probably know, there are three ways to represent coordinates:
Degrees:Minutes:Seconds (49°30'00"N, 123°30'00"W)
Degrees:Decimal Minutes (49°30.0', -123°30.0'), (49d30.0m,-123d30.0')
Decimal Degrees (49.5000°,-123.5000°), generally with 4-6 decimal numbers.
It's the third way my coordinates are given in, so the code for this values will be preferred :)
Based on another question on stackoverflow, I got this code.. This calculates the result in meters, not in miles :)
public static float distFrom(float lat1, float lng1, float lat2, float lng2) {
double earthRadius = 6371000; //meters
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));
float dist = (float) (earthRadius * c);
return dist;
}
You can use the Java Geodesy Library for GPS, it uses the Vincenty's formulae which takes account of the earths surface curvature.
Implementation goes like this:
import org.gavaghan.geodesy.*;
...
GeodeticCalculator geoCalc = new GeodeticCalculator();
Ellipsoid reference = Ellipsoid.WGS84;
GlobalPosition pointA = new GlobalPosition(latitude, longitude, 0.0); // Point A
GlobalPosition userPos = new GlobalPosition(userLat, userLon, 0.0); // Point B
double distance = geoCalc.calculateGeodeticCurve(reference, userPos, pointA).getEllipsoidalDistance(); // Distance between Point A and Point B
The resulting distance is in meters.
In C++ it is done like this:
#define LOCAL_PI 3.1415926535897932385
double ToRadians(double degrees)
{
double radians = degrees * LOCAL_PI / 180;
return radians;
}
double DirectDistance(double lat1, double lng1, double lat2, double lng2)
{
double earthRadius = 3958.75;
double dLat = ToRadians(lat2-lat1);
double dLng = ToRadians(lng2-lng1);
double a = sin(dLat/2) * sin(dLat/2) +
cos(ToRadians(lat1)) * cos(ToRadians(lat2)) *
sin(dLng/2) * sin(dLng/2);
double c = 2 * atan2(sqrt(a), sqrt(1-a));
double dist = earthRadius * c;
double meterConversion = 1609.00;
return dist * meterConversion;
}