Haversine formula in Java producing incorrect result - java

I am trying to use this implementation of Haversine formula given on wikipedia for trial but this formula is not giving expected result.
public class Haversine {
public static final double R = 6372.8; // In kilometers
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.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
double c = 2 * Math.asin(Math.sqrt(a));
return R * c;
}
public static void main(String[] args) {
System.out.println(haversine(36.12, -86.67, 33.94, -118.40));
}
}
Input GPS latitude format : ddmm.mmmm
Input GPS longitude format : dddmm.mmmm
Above formats for lat-lon are specified in requirement document.
Sample input coordinates are as below :
lat1 = 3359.64868, lon1 = 8356.178
lat2 = 3359.649, lon2 = 8356.178
Before passing these values to Haversine method, I am converting these values into degrees format. Please correct me if this step is not necessary.
I am using formula below to convert from degree minute format to Decimal degree format :
Decimal Degree = degree + (minute / 60)
So new coordinates become
lat1 = 33 + (59.64868 / 60) = 33.994144666666664
lon1 = 83 + (56.178 / 60) = 83.9363
lat2 = 33 + (59.649 / 60) = 33.99415
lon2 = 83 + (56.178 / 60) = 83.9363
Call to haversine method becomes like
haversine(33.994144666666664, 83.9363, 33.99415, 83.9363)
which is returning value 5.932071604620887E-4
To validate the values, I provided same input (33.994144666666664, 83.9363, 33.99415, 83.9363) to converter present on this website but it gives result as 0.001 km.
I tried to provide input values without converting to decimal degrees but then also output from two methods is not matching.
Can anyone please tell me what mistake I am doing here?

The result 5.932071604620887E-4 you are getting is the representation of 5.932071604620887 * 10^(-4), which is 5.932071604620887 / 10000 = 0.0005932071604620887.
If the website returns 0.001, my suggestions is they just round to the 3rd decimal place. Hence, your calculation is correct.

Related

Find location 1 Km away in 180 degree (South) from my location

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.

Not able to get perfect distance between two places

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

Calculate distance between two GeoLocation

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).

calculate distance with 2 geo points

I want to calculate the distance between 2 geo points, for now between my school and my house. The distance should be close 1200 meter.
I get these values back which don't make sense.
104.247784180256
35.017200205306295 (if I reverse lat and lon)
Google maps says:
51.987957 is N
5.911305 is O
is 51.987957 lat or lon? According to my documentation of where I get the GPS signal from it should be latitude but I have my doubt about that.
float R = 6371; // km
// 104.247784180256
float lat1 = 5.894213; // school
float lon1 = 51.98381; // school
float lat2 = 5.909912; // keuken
float lon2 = 51.988781; // keuken
// switched > distance = 35.017200205306295
/*
float lon1 = 5.894213; // school
float lat1 = 51.98381; // school
float lon2 = 5.909912; // keuken
float lat2 = 51.988781; // keuken
*/
void setup() {
double d = calculateDistance( lon1, lat1, lon2, lat2);
println(d);
}
double calculateDistance(float lon1, float lat1, float lon2, float lat2) {
double d = Math.acos(Math.sin(lat1)*Math.sin(lat2) +
Math.cos(lat1)*Math.cos(lat2) *
Math.cos(lon2-lon1)) * R;
return d;
}
You are using the latitude and longitude the wrong way around.
You can simply check on google maps if you search for "#51.98381,5.894213", this points to your school. And keep in mind it is latitude,longitude.
I use the following code to calculate (note i do it in sql, but its about the idea):
((ACOS(SIN(lat1 * PI() / 180) * SIN(lat2 * PI() / 180) + COS(lat1 * PI() / 180) * COS(lat2 * PI() / 180) * COS((long1 - long2) * PI() / 180)) * 180 / PI()) * 60 * 1.1515 * 1.609344)
This gives back the distance in kilometers.
Also note that the functions use radians and not degrees.
The result is 1.20877685491371 km, which is the 1200 meters you expect.

Calculate distance in meters when you know longitude and latitude in java [duplicate]

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;
}

Categories

Resources