Degrees minutes seconds to radians formula not working - java

Here is the code:
double r = Double.parseDouble(radius.getText().toString());
double del = Double.parseDouble(delta.getText().toString());
double dm = ((int)((del - ((int)del)) * 100));
double rads = (((int)del) + (dm / 60) + (((((del - ((int)del)) * 100) - ((int)((del - ((int)del)) * 100))) * 100) / 3600)) * (Math.PI / 180);
String t = String.valueOf(r * (Math.tan(rads / 2)));
String c = String.valueOf(2* r* (Math.sin((rads/2))));
String m = String.valueOf(r*(1- Math.cos((rads/2))));
String a = String.valueOf(2*Math.PI*r*((((int)del) + (dm / 60) + (((((del - ((int)del)) * 100) - ((int)((del - ((int)del)) * 100))) * 100) / 3600))/360));
tangent.setText(t);
arc.setText(a);
chord.setText(c);
mid.setText(m);
My objective is to reduce the number of variables I am using in my program to clean it up a bit. As it sits the way I have posted it, the formulas work. If I replace "dm" in the double "rads" with the current value of "((int)((del - ((int)del)) * 100))", the formulas no longer work. It has something to do with the "/60". I've tried different bracket situations and just doesn't seem to work. I have replaced the "dm" in other parts of the formula and it all still works, its just in that one location. Any ideas?

Your code is hard to read. That's part of the reason why you're struggling.
I'd write it this way:
package misc;
/**
* Created by Michael on 12/12/2015.
* #link https://stackoverflow.com/questions/34236175/degrees-minutes-seconds-to-radians-formula-not-working
*/
public class AngleConverter {
public static void main(String[] args) {
double degrees = (args.length > 0) ? Double.valueOf(args[0]) : 0.0;
double minutes = (args.length > 1) ? Double.valueOf(args[1]) : 0.0;
double seconds = (args.length > 2) ? Double.valueOf(args[2]) : 0.0;
double radians = convertDegreesToRadians(degrees, minutes, seconds);
System.out.println(String.format("degrees: %10.6f", degrees));
System.out.println(String.format("minutes: %10.6f", minutes));
System.out.println(String.format("seconds: %10.6f", seconds));
System.out.println(String.format("radians: %10.6f", radians));
System.out.println(String.format("degrees: %10.6f", Math.toDegrees(radians)));
}
public static double convertDegreesToRadians(double degrees, double minutes, double seconds) {
double angle = degrees + minutes/60.0 + seconds/3600.0;
return Math.toRadians(angle);
}
}

Let's say you have d m s degrees, minutes and seconds. Given that
60 minutes = 1 degree
60 seconds = 1 minute
we get that the total number of degrees represented by d m s is
deg = d + m/60 + s/60^2
Now it is a matter of converting deg degrees to radians. But
360 degrees = 2*Pi radians
So,
1 degrees = (2*Pi/360) radians
and
deg degrees = deg * (2*Pi/360) radians
Summarizing, the answer is
(d + m/60 + s/60^2) * 2 * Pi / 360
Which can be rewritten as
((s/60 + m)/60 + d)/60 * Pi/3

Related

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

Trying to calculate sunrise...ain't getting the right answer

This is my current code:
public class Sunpos {
final private double Pi = Math.PI;
final private double eul = 2.71828182845904523552 ;
final private double sonauf = 90;
final private double RAD = 0.017453292519943295769236907684886;
public double sunrisefinal (double Breitengrad, double Laengengrad, int tagzahl, int sommerzeit, int nacht) {
double lngHour = Laengengrad/15;
double t = tagzahl + ((6 - lngHour)/24);
// double ab = tagzahl + ((18 - lngHour)/24);
double M = (0.9856 * t) - 3.289;
double L = M + (1.916 * Math.sin(M)) + (0.020 * Math.sin(2 * M)) + 282.634;
if (L >= 359) { L -= 360; }
else if (L < 0) { L += 360; }
double RA = (Math.atan(0.91764 * Math.tan(Pi/180)*L));
if (RA >= 359) { RA -= 360; }
else if (RA < 0) { RA += 360; }
double Lquadrant = (Math.floor(L/90)*90);
double RAquadrant = (Math.floor(RA/90))*90;
RA = RA + (Lquadrant - RAquadrant);
RA = RA/15;
double sinDec = 0.39782 * Math.sin((Pi/180)*L);
double cosDec = (180/Pi)*(Math.cos(Math.asin(sinDec)));
double cosH = (Math.cos((Pi/180)*sonauf)-(sinDec*Math.sin((Pi/180)*Breitengrad)))/(cosDec * Math.cos((Pi/180)*Breitengrad));
double H = 360 - Math.acos(cosH);
H /= 15;
double T = H + RA -(0.06571 * t) - 6.622;
double UTC = T - lngHour;
if (UTC >= 23) { UTC -= 24; }
else if (UTC < 0) { UTC += 24; }
double locTime = UTC; // Fuer die schweiz!
System.out.println(locTime);
return(0);
}
The inputs are the following: ( 50, 10, 294, 1, 0). The last 2 can be ignored.
Now I am basing this on the following page:
http://williams.best.vwh.net/sunrise_sunset_algorithm.htm
The code should be complete according to the site, but I don't get anywhere near the supposed results. I should get around 7.5 for today but I'm getting a 9.358.
Now, that might be because something with radiants/degrees? I can't quite get my Mind into that, as I've been trying to insert those converters (Pi/180) into the code, without any usable result.
Can anyone tell me where to put them or point me in the right direction? I've spent waaaay too much time on this already, and now I'm so close.
I'll just post my implementation here in case people need it (ported from the same source as yours)
https://gist.github.com/zhong-j-yu/2232343b14a5b5ef5b9d
public class SunRiseSetAlgo
{
static double calcSunrise(int dayOfYear, double localOffset, double latitude, double longitude)
{
return calc(dayOfYear, localOffset, latitude, longitude, true);
}
static double calcSunset(int dayOfYear, double localOffset, double latitude, double longitude)
{
return calc(dayOfYear, localOffset, latitude, longitude, false);
}
// http://williams.best.vwh.net/sunrise_sunset_algorithm.htm
static double calc(int dayOfYear, double localOffset, double latitude, double longitude, boolean rise)
{
//1. first calculate the day of the year
// int N1 = floor(275 * month / 9.0);
// int N2 = floor((month + 9) / 12.0);
// int N3 = (1 + floor((year - 4 * floor(year / 4.0) + 2) / 3.0));
// int N = N1 - (N2 * N3) + day - 30;
int N = dayOfYear;
//2. convert the longitude to hour value and calculate an approximate time
double lngHour = longitude / 15;
double t = rise?
N + (( 6 - lngHour) / 24) :
N + ((18 - lngHour) / 24);
//3. calculate the Sun's mean anomaly
double M = (0.9856 * t) - 3.289;
//4. calculate the Sun's true longitude
double L = M + (1.916 * sin(M)) + (0.020 * sin(2 * M)) + 282.634;
L = mod(L, 360);
//5a. calculate the Sun's right ascension
double RA = atan(0.91764 * tan(L));
RA = mod(RA, 360);
//5b. right ascension value needs to be in the same quadrant as L
double Lquadrant = (floor( L/90)) * 90;
double RAquadrant = (floor(RA/90)) * 90;
RA = RA + (Lquadrant - RAquadrant);
//5c. right ascension value needs to be converted into hours
RA = RA / 15;
//6. calculate the Sun's declination
double sinDec = 0.39782 * sin(L);
double cosDec = cos(asin(sinDec));
//7a. calculate the Sun's local hour angle
double zenith = 90 + 50.0/60;
double cosH = (cos(zenith) - (sinDec * sin(latitude))) / (cosDec * cos(latitude));
if (cosH > 1)
throw new Error("the sun never rises on this location (on the specified date");
if (cosH < -1)
throw new Error("the sun never sets on this location (on the specified date");
//7b. finish calculating H and convert into hours
double H = rise?
360 - acos(cosH) :
acos(cosH);
H = H / 15;
//8. calculate local mean time of rising/setting
double T = H + RA - (0.06571 * t) - 6.622;
//9. adjust back to UTC
double UT = T - lngHour;
//10. convert UT value to local time zone of latitude/longitude
double localT = UT + localOffset;
localT = mod(localT, 24);
return localT;
}
static int floor(double d){ return (int)Math.floor(d); }
static double sin(double degree)
{
return Math.sin(degree*Math.PI/180);
}
static double cos(double degree)
{
return Math.cos(degree*Math.PI/180);
}
static double tan(double degree)
{
return Math.tan(degree*Math.PI/180);
}
static double atan(double x)
{
return Math.atan(x) *180/Math.PI;
}
static double asin(double x)
{
return Math.asin(x) *180/Math.PI;
}
static double acos(double x)
{
return Math.acos(x) *180/Math.PI;
}
static double mod(double x, double lim)
{
return x - lim * floor(x/lim);
}
}
Everone seems to link to this http://williams.best.vwh.net/sunrise_sunset_algorithm.htm
which doesn't exist anymore. Why not try something that gets updated once in a while like https://en.wikipedia.org/wiki/Sunrise_equation
Then if you like you could help edit it to make it better.

Haversine formula in Java producing incorrect result

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.

Bounding Box Given 4 Lat/Long and Bearing

I need to find a bounding box given 4 lat/long points and a bearing (as seen in the example picture). I always know which two points are lined up by the bearing (1 and 2 in the example), so I will always know the length of the bounding box. The width however is arbitrary, with the points being anywhere along the lines (3 and 4 in the example).
My first thought is that I'll have to calculate the angles between the points (1 & 3, 1 & 4, 2 & 3, 2 & 4) and then use a series of "law of cosine" equations to calculate the corner points. Is there a simpler way? Would that even work?
So looking around and even asking on probably a more appropriate site (here), I found a solution based on something by Chris Veness (here) to find the intersection point given two points and their bearings. So to get the corners of the bounding box I just take each combination of top/bottom and left/right (1 & 3, 1 & 4, 2 & 3, 2 & 4) and find the intersections using the known bearing and adjusting accordingly. For example to find the bottom right of the image I'd calculate the intersection of points 1 & 3 using the bearing + 90 for the direction of point 1 and the bearing - 180 for the direction of point 3.
I can take no credit for the algorithm or even really explain it in terms of how it works geometrically, but its worked in my testing. Below is my java translation from the javascript version provided by Chris
public static CoordD getIntersection(CoordD point1, double bearing1, CoordD point2, double bearning2) {
double lat1 = rad(point1.latitude); double lon1 = rad(point1.longitude);
double lat2 = rad(point2.latitude); double lon2 = rad(point2.longitude);
double bearing13 = rad(bearing1); double bearing 23 = rad(bearing2);
double dLat = lat2 - lat1; double dLon = lon2 - lon1;
double dist12 = 2 * Math.asin( Math.sqrt( Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLon / 2) * Math.sin(dLon / 2) ) );
if (dist12 == 0) return null;
double bearingA = Math.acos( ( Math.sin(lat2) - Math.sin(lat1) * Math.cos(dist12) ) /
( Math.sin(dist12) * Math.cos(lat1) ) );
double bearingB = Math.acos( ( Math.sin(lat1) - Math.sin(lat2) * Math.cos(dist12) ) /
( Math.sin(dist12) * Math.cos(lat2) ) );
if (Double.isNaN(bearingA)) bearingA = 0;
if (Double.isNaN(bearingB)) bearingB = 0;
double bearing12, bearing21;
if (Math.sin(dLon) > 0) {
bearing12 = bearingA;
bearing21 = 2 * Math.PI - bearingB;
} else {
bearing12 = 2 * Math.PI - bearingA;
bearing21 = bearingB;
}
double alpha1 = (bearing13 - bearing12 + Math.PI) % (2 * Math.PI) - Math.PI; // Angle 2-1-3
double alpha2 = (bearing21 - bearing23 + Math.PI) % (2 * Math.PI) - Math.PI; // Angle 1-2-3
if (Math.sin(alpha1) == 0 && Math.sin(alpha2) == 0) return null; // Infinite intersections
if (Math.sin(alpha1) * Math.sin(alpha2) < 0) return null; // Ambiguous intersection
// needed?
// alpha1 = Math.abs(alpha1);
// alpha2 = Math.abs(alpha2);
double alpha3 = Math.acos( -Math.cos(alpha1) * Math.cos(alpha2) +
Math.sin(alpha1) * Math.sin(alpha2) * Math.cos(dist12) );
double dist13 = Math.atan2( Math.sin(dist12) * Math.sin(alpha1) * Math.sin(alpha2),
Math.cos(alpha2) + Math.cos(alpha1) * Math.cos(alpha3) );
double lat3 = Math.asin( Math.sin(lat1) * Math.cos(dist13) +
Math.cos(lat1) * Math.sin(dist13) * Math.cos(bearing13) );
double dLon13 = Math.atan2( Math.sin(bearing13) * Math.sin(dist13) * Math.cos(lat1),
Math.cos(dist13) - Math.sin(lat1) * Math.sin(lat3) );
double lon3 = lon1 + dLon3;
lon3 = (lon3 + 3 * Math.PI) % ( 2* Math.PI) - Math.PI // normalize to +/-180
return new CoordD(deg(lat3), deg(lon3));
}
rad() and deg() are just helper functions that translate between radians and degrees. CoordD is a helper class that just contains two double to store a lat/long point.

How can I measure distance and create a bounding box based on two latitude+longitude points in Java?

I am wanting to find the distance between two different points. This I know can be accomplished with the great circle distance.
http://www.meridianworlddata.com/Distance-calculation.asp
Once done, with a point and distance I would like to find the point that distance north, and that distance east in order to create a box around the point.
Here is a Java implementation of Haversine formula. I use this in a project to calculate distance in miles between lat/longs.
public static double distFrom(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 3958.75; // miles (or 6371.0 kilometers)
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;
}
Or you could use SimpleLatLng. Apache 2.0 licensed and used in one production system that I know of: mine.
Short story:
I was searching for a simple geo library and couldn't find one to fit my needs. And who wants to write and test and debug these little geo tools over and over again in every application? There's got to be a better way!
So SimpleLatLng was born as a way to store latitude-longitude data, do distance calculations, and create shaped boundaries.
I know I'm two years too late to help the original poster, but my aim is to help the people like me who find this question in a search. I would love to have some people use it and contribute to the testing and vision of this little lightweight utility.
We've had some success using OpenMap to plot a lot of positional data. There's a LatLonPoint class that has some basic functionality, including distance.
For a more accurate distance (0.5mm) you can also use the Vincenty approximation:
/**
* Calculates geodetic distance between two points specified by latitude/longitude using Vincenty inverse formula
* for ellipsoids
*
* #param lat1
* first point latitude in decimal degrees
* #param lon1
* first point longitude in decimal degrees
* #param lat2
* second point latitude in decimal degrees
* #param lon2
* second point longitude in decimal degrees
* #returns distance in meters between points with 5.10<sup>-4</sup> precision
* #see Originally posted here
*/
public static double distVincenty(double lat1, double lon1, double lat2, double lon2) {
double a = 6378137, b = 6356752.314245, f = 1 / 298.257223563; // WGS-84 ellipsoid params
double L = Math.toRadians(lon2 - lon1);
double U1 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat1)));
double U2 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat2)));
double sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
double sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
double sinLambda, cosLambda, sinSigma, cosSigma, sigma, sinAlpha, cosSqAlpha, cos2SigmaM;
double lambda = L, lambdaP, iterLimit = 100;
do {
sinLambda = Math.sin(lambda);
cosLambda = Math.cos(lambda);
sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda)
+ (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
if (sinSigma == 0)
return 0; // co-incident points
cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
sigma = Math.atan2(sinSigma, cosSigma);
sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
cosSqAlpha = 1 - sinAlpha * sinAlpha;
cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
if (Double.isNaN(cos2SigmaM))
cos2SigmaM = 0; // equatorial line: cosSqAlpha=0 (ยง6)
double C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
lambdaP = lambda;
lambda = L + (1 - C) * f * sinAlpha
* (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
} while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);
if (iterLimit == 0)
return Double.NaN; // formula failed to converge
double uSq = cosSqAlpha * (a * a - b * b) / (b * b);
double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
double deltaSigma = B
* sinSigma
* (cos2SigmaM + B
/ 4
* (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - B / 6 * cos2SigmaM
* (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
double dist = b * A * (sigma - deltaSigma);
return dist;
}
This code was freely adapted from http://www.movable-type.co.uk/scripts/latlong-vincenty.html
Corrected Haversine Distance formula....
public static double HaverSineDistance(double lat1, double lng1, double lat2, double lng2)
{
// mHager 08-12-2012
// http://en.wikipedia.org/wiki/Haversine_formula
// Implementation
// convert to radians
lat1 = Math.toRadians(lat1);
lng1 = Math.toRadians(lng1);
lat2 = Math.toRadians(lat2);
lng2 = Math.toRadians(lng2);
double dlon = lng2 - lng1;
double dlat = lat2 - lat1;
double a = Math.pow((Math.sin(dlat/2)),2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(dlon/2),2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return EARTH_RADIUS * c;
}
http://www.movable-type.co.uk/scripts/latlong.html
public static Double distanceBetweenTwoLocationsInKm(Double latitudeOne, Double longitudeOne, Double latitudeTwo, Double longitudeTwo) {
if (latitudeOne == null || latitudeTwo == null || longitudeOne == null || longitudeTwo == null) {
return null;
}
Double earthRadius = 6371.0;
Double diffBetweenLatitudeRadians = Math.toRadians(latitudeTwo - latitudeOne);
Double diffBetweenLongitudeRadians = Math.toRadians(longitudeTwo - longitudeOne);
Double latitudeOneInRadians = Math.toRadians(latitudeOne);
Double latitudeTwoInRadians = Math.toRadians(latitudeTwo);
Double a = Math.sin(diffBetweenLatitudeRadians / 2) * Math.sin(diffBetweenLatitudeRadians / 2) + Math.cos(latitudeOneInRadians) * Math.cos(latitudeTwoInRadians) * Math.sin(diffBetweenLongitudeRadians / 2)
* Math.sin(diffBetweenLongitudeRadians / 2);
Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return (earthRadius * c);
}
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);
GlobalPosition userPos = new GlobalPosition(userLat, userLon, 0.0);
double distance = geoCalc.calculateGeodeticCurve(reference, userPos, pointA).getEllipsoidalDistance();
The resulting distance is in meters.
This method would help you find the distance between to geographic location in km.
private double getDist(double lat1, double lon1, double lat2, double lon2)
{
int R = 6373; // radius of the earth in kilometres
double lat1rad = Math.toRadians(lat1);
double lat2rad = Math.toRadians(lat2);
double deltaLat = Math.toRadians(lat2-lat1);
double deltaLon = Math.toRadians(lon2-lon1);
double a = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) +
Math.cos(lat1rad) * Math.cos(lat2rad) *
Math.sin(deltaLon/2) * Math.sin(deltaLon/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double d = R * c;
return d;
}
Kotlin version of Haversine formula. Returned result in meters. Tested on https://www.vcalc.com/wiki/vCalc/Haversine+-+Distance
const val EARTH_RADIUS_IN_METERS = 6371007.177356707
fun distance(lat1: Double, lng1: Double, lat2: Double, lng2: Double): Double {
val latDiff = Math.toRadians(abs(lat2 - lat1))
val lngDiff = Math.toRadians(abs(lng2 - lng1))
val a = sin(latDiff / 2) * sin(latDiff / 2) +
cos(Math.toRadians(lat1)) * cos(Math.toRadians(lat2)) *
sin(lngDiff / 2) * sin(lngDiff / 2)
val c = 2 * atan2(sqrt(a), sqrt(1 - a))
return EARTH_RADIUS_IN_METERS * c
}
I know that there are many answers, but in doing some research on this topic, I found that most answers here use the Haversine formula, but the Vincenty formula is actually more accurate. There was one post that adapted the calculation from a Javascript version, but it's very unwieldy. I found a version that is superior because:
It also has an open license.
It uses OOP principles.
It has greater flexibility to choose the ellipsoid you want to use.
It has more methods to allow for different calculations in the future.
It is well documented.
VincentyDistanceCalculator
I typically use MATLAB with the Mapping Toolbox, and then use the code in my Java using MATLAB Builder JA. It makes my life a lot simpler. Given most schools have it for free student access, you can try it out (or get the trial version to get over your work).
For Android, there is a simple approach.
public static float getDistanceInMeter(LatLng start, LatLng end) {
float[] results = new float[1];
Location.distanceBetween(start.latitude, start.longitude, end.latitude, end.longitude, results);
return results[0];
}
;
https://developer.android.com/reference/android/location/Location#distanceBetween(lat1,lng1,lat2,lng2,output[])

Categories

Resources