How can I calculate distance between multiple latitude and longitude? - java

I want to calculate total distance between each points both contains lat and long, these points are stored in local database, so the scenario is I want to calculate distance from point a to b & b to c & c to d and these points(lat and long) are stored into database using google place api
All the points are fetched from database.

you can calculate distance between 2 location points without using places api
private double distance(double lat1, double lon1, double lat2, double lon2) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1))
* Math.sin(deg2rad(lat2))
+ Math.cos(deg2rad(lat1))
* Math.cos(deg2rad(lat2))
* Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
return (dist);
}
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}

I'm not sure if I understand the scope of this question. Do you need to take into account the curvature of earth? Or it is just 2 random points?
If it's the first : I can show you this link as i cannot help you out:
https://www.movable-type.co.uk/scripts/latlong.html
If it is the latter:
Suppose 1 is latitude and 2 is longitude, so that a1 is latitude of point A.
Calculating 2 points in a plane is something like somethign like this:
Distance = sqrt((a1−b1)+(a2−b2))
So, to calculate for example distance from D to E is: sqrt((e1-d1) + (e2-d2))

class DistanceCalculator
{
public static void main (String[] args) throws java.lang.Exception
{
System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, "M") + " Miles\n");
System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, "K") + " Kilometers\n");
System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, "N") + " Nautical Miles\n");
}
private static double distance(double lat1, double lon1, double lat2, double lon2, String unit) {
if ((lat1 == lat2) && (lon1 == lon2)) {
return 0;
}
else {
double theta = lon1 - lon2;
double dist = Math.sin(Math.toRadians(lat1)) * Math.sin(Math.toRadians(lat2)) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.cos(Math.toRadians(theta));
dist = Math.acos(dist);
dist = Math.toDegrees(dist);
dist = dist * 60 * 1.1515;
if (unit == "K") {
dist = dist * 1.609344;
} else if (unit == "N") {
dist = dist * 0.8684;
}
return (dist);
}
}
}

float[] distanceWidth = new float[2];
Location.distanceBetween(
startLatitude,
startLongitude,
endLatitude,
endLongitude,
distanceWidth);
//You will get float[] of results after Location.distanceBetween().
float distance = distanceHeight[0];
float distanceInKm = distance/1000;

Related

Problem with the calculating distance between locations using Haversine formula

I am calculating the distance between two points recorded in the history of Yandex.Maps in the Android 11 app. Everything works well in the getPoints method. We write all the coordinates they were in our database to a list of arrays. I even implemented overflow, exit, and array checks. Again, up to this point, everything worked well and as expected.
public ArrayList<Double> getPoints () {
ArrayList<Double> location = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("select latitude,longitude from "+Table_Name_Location,null);
if(cursor.getCount() > 0) {
while (cursor.moveToNext()) {
Double latitude = cursor.getDouble(cursor.getColumnIndex("Lat"));
Double longitude = cursor.getDouble(cursor.getColumnIndex("Longi"));
location.add(latitude);
location.add(longitude);
}
}
cursor.close();
return location;
}
However, when I try to calculate the length in the distance method, several latitudes and longitudes stored in the SQLite database incorrectly calculate the total distance, for example, 450 kilometres, and according to our data, we should get 230 km. A calculation error occurs.
private double distance(double lat1, double lon1, double lat2, double lon2) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1))
* Math.sin(deg2rad(lat2))
+ Math.cos(deg2rad(lat1))
* Math.cos(deg2rad(lat2))
* Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
return (dist);
}
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
I tried to calculate the distance using the haversine formula. I also wrote functions to convert radians to degrees and vice versa. In the distance method, I calculate the distance using the haversine formula. I suspect that the error is in calculating the distance, namely in the implementation of the haversine formula.
For distance you need the reverse Haversine formula:
dlon = lon2 - lon1
dlat = lat2 - lat1
a = (sin(dlat/2))^2 + cos(lat1) * cos(lat2) * (sin(dlon/2))^2
c = 2 * atan2(sqrt(a), sqrt(1-a))
d = R * c
R = 6371 # mean radius of the Earth in km
(source of formula: link)
The implementation of this in Java would look like the following:
private double distance(double lat1, double lon1, double lat2, double lon2) {
final int R = 6371;
double latDistance = Math.toRadians(lat2 - lat1);
double lonDistance = Math.toRadians(lon2 - lon1);
double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
}
/**
* Calculate the distance between two points in meters using the Haversine formula
*
* #param lat latitude of the first point
* #param lon longitude of the first point
* #param lat2 latitude of the second point
* #param lon2 longitude of the second point
* #return the distance between the two points in meters
**/
public static double distance(double lat, double lon, double lat2, double lon2) {
final double R = 6371e3;
final double la = lat * java.lang.Math.PI / 180;
final double laa = lat2 * java.lang.Math.PI / 180;
final double lo = (lat2 - lat) * java.lang.Math.PI / 180;
final double loo = (lon2 - lon) * java.lang.Math.PI / 180;
final double a = java.lang.Math.sin(lo / 2) * java.lang.Math.sin(lo / 2) + java.lang.Math.cos(la) * java.lang.Math.cos(laa) * java.lang.Math.sin(loo / 2) * java.lang.Math.sin(loo / 2);
final double c = 2 * java.lang.Math.atan2(java.lang.Math.sqrt(a), java.lang.Math.sqrt(1 - a));
return R * c;
}

Calculate the distance between two Geographical Coordinates in Java

I have two GPS Coordinates, for example: (44.40239182909422, 8.930511474608954) and (30.297017883371236, 122.3822021484364)
I would like to know the distance in meters between these two points. I don't know if the first coordinate is greater than the second or not.
I am trying to understand and modify this code example:
private double _distance(double lat1, double lon1, double lat2, double lon2) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515; // 60 is the number of minutes in a degree; //1.1515 is the number of statute miles in a nautical mile.One nautical mile is the length of one minute of latitude at the equator.
dist = dist * 1.609344;
return (dist);
}
To calculate the 'theta' I added the following code:
double theta = lon1 - lon2;
if(lon2>lon1)
theta = lon2 - lon1;
The distance function will return the distance between two points in meteres
public double distance() {
double lat1 = 44.40239182909422;
double lon1 = 8.930511474608954;
double lat2 = 30.297017883371236;
double lon2 = 122.3822021484364;
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 1.609344 * 1000;
return (dist); // 134910.69784909734
}
/* The function to convert decimal into radians */
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
/* The function to convert radians into decimal */
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}

Find nearest city on current location - Android

Hey I was wondering if you could help me.
I've basically got the users current location and ran a .getLocality() function from the geocoder object to display the city they're in. However if the users current location is in Middlesex how would I get it it say London??
Thanks for your help.
You may calculate the distance between your current locations latitude,longitude and passing lat & long of all the cities you have Now after that calculate which city has the least distance and show that.
public static double distance(double lat1, double lon1, double lat2, double lon2) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
return (dist);
}
public static double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
public static double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}

Getting absurd values when trying to calculate distance between two coordinates in Android

I am trying to find distance between two coordinates using latitudes and longitudes.I am using the following method:
private double distance(double lat1, double lon1, double lat2, double lon2, char unit) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
if (unit == 'K') {
dist = dist * 1.609344;
} else if (unit == 'N') {
dist = dist * 0.8684;
}
return (dist);
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*:: This function converts decimal degrees to radians :*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*:: This function converts radians to decimal degrees :*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
I am getting the current latitude and longitude from bundle from a previous activity and i am calling the method as follows:
String parameter=""+distance(current_latitude,current_longitude,Double.parseDouble(store_list.get(position).store_latitude),Double.parseDouble(store_list.get(position).store_longitude),'K');
But i am getting absurd results values like 8500 etc.Please help
Consider using the method provided by the Location class: http://developer.android.com/reference/android/location/Location.html#distanceBetween(double, double, double, double, float[])
public static void distanceBetween (double startLatitude, double startLongitude, double endLatitude, double endLongitude, float[] results)
Parameters
startLatitude the starting latitude
startLongitude the starting longitude
endLatitude the ending latitude
endLongitude the ending longitude
results an array of floats to hold the results
usage:
float[] results = new float[3];
Location.distanceBetween(current_latitude, current_longitude, Double.parseDouble(store_list.get(position).store_latitude), Double.parseDouble(store_list.get(position).store_longitude, results);
float distanceMeters = results[0];

Calculating distance between two points, using latitude longitude?

Here's my try, it's just a snippet of my code:
final double RADIUS = 6371.01;
double temp = Math.cos(Math.toRadians(latA))
* Math.cos(Math.toRadians(latB))
* Math.cos(Math.toRadians((latB) - (latA)))
+ Math.sin(Math.toRadians(latA))
* Math.sin(Math.toRadians(latB));
return temp * RADIUS * Math.PI / 180;
I am using this formulae to get the latitude and longitude:
x = Deg + (Min + Sec / 60) / 60)
The Java code given by Dommer above gives slightly incorrect results but the small errors add up if you are processing say a GPS track. Here is an implementation of the Haversine method in Java which also takes into account height differences between two points.
/**
* Calculate distance between two points in latitude and longitude taking
* into account height difference. If you are not interested in height
* difference pass 0.0. Uses Haversine method as its base.
*
* lat1, lon1 Start point lat2, lon2 End point el1 Start altitude in meters
* el2 End altitude in meters
* #returns Distance in Meters
*/
public static double distance(double lat1, double lat2, double lon1,
double lon2, double el1, double el2) {
final int R = 6371; // Radius of the earth
double latDistance = Math.toRadians(lat2 - lat1);
double lonDistance = Math.toRadians(lon2 - lon1);
double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
+ Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
* Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double distance = R * c * 1000; // convert to meters
double height = el1 - el2;
distance = Math.pow(distance, 2) + Math.pow(height, 2);
return Math.sqrt(distance);
}
Here's a Java function that calculates the distance between two lat/long points, posted below, just in case it disappears again.
private double distance(double lat1, double lon1, double lat2, double lon2, char unit) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
if (unit == 'K') {
dist = dist * 1.609344;
} else if (unit == 'N') {
dist = dist * 0.8684;
}
return (dist);
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*:: This function converts decimal degrees to radians :*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*:: This function converts radians to decimal degrees :*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'M') + " Miles\n");
System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'K') + " Kilometers\n");
System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'N') + " Nautical Miles\n");
Future readers who stumble upon this SOF article.
Obviously, the question was asked in 2010 and its now 2019.
But it comes up early in an internet search. The original question does not discount use of third-party-library (when I wrote this answer).
public double calculateDistanceInMeters(double lat1, double long1, double lat2,
double long2) {
double dist = org.apache.lucene.util.SloppyMath.haversinMeters(lat1, long1, lat2, long2);
return dist;
}
and
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-spatial</artifactId>
<version>8.2.0</version>
</dependency>
https://mvnrepository.com/artifact/org.apache.lucene/lucene-spatial/8.2.0
Please read documentation about "SloppyMath" before diving in!
https://lucene.apache.org/core/8_2_0/core/org/apache/lucene/util/SloppyMath.html
Note: this solution only works for short distances.
I tried to use dommer's posted formula for an application and found it did well for long distances but in my data I was using all very short distances, and dommer's post did very poorly. I needed speed, and the more complex geo calcs worked well but were too slow. So, in the case that you need speed and all the calculations you're making are short (maybe < 100m or so). I found this little approximation to work great. it assumes the world is flat mind you, so don't use it for long distances, it works by approximating the distance of a single Latitude and Longitude at the given Latitude and returning the Pythagorean distance in meters.
public class FlatEarthDist {
//returns distance in meters
public static double distance(double lat1, double lng1,
double lat2, double lng2){
double a = (lat1-lat2)*FlatEarthDist.distPerLat(lat1);
double b = (lng1-lng2)*FlatEarthDist.distPerLng(lat1);
return Math.sqrt(a*a+b*b);
}
private static double distPerLng(double lat){
return 0.0003121092*Math.pow(lat, 4)
+0.0101182384*Math.pow(lat, 3)
-17.2385140059*lat*lat
+5.5485277537*lat+111301.967182595;
}
private static double distPerLat(double lat){
return -0.000000487305676*Math.pow(lat, 4)
-0.0033668574*Math.pow(lat, 3)
+0.4601181791*lat*lat
-1.4558127346*lat+110579.25662316;
}
}
was a lot of great answers provided however I found some performance shortcomings, so let me offer a version with performance in mind. Every constant is precalculated and x,y variables are introduced to avoid calculating the same value twice. Hope it helps
private static final double r2d = 180.0D / 3.141592653589793D;
private static final double d2r = 3.141592653589793D / 180.0D;
private static final double d2km = 111189.57696D * r2d;
public static double meters(double lt1, double ln1, double lt2, double ln2) {
double x = lt1 * d2r;
double y = lt2 * d2r;
return Math.acos( Math.sin(x) * Math.sin(y) + Math.cos(x) * Math.cos(y) * Math.cos(d2r * (ln1 - ln2))) * d2km;
}
Here is a page with javascript examples for various spherical calculations. The very first one on the page should give you what you need.
http://www.movable-type.co.uk/scripts/latlong.html
Here is the Javascript code
var R = 6371; // km
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
Where 'd' will hold the distance.
package distanceAlgorithm;
public class CalDistance {
public static void main(String[] args) {
// TODO Auto-generated method stub
CalDistance obj=new CalDistance();
/*obj.distance(38.898556, -77.037852, 38.897147, -77.043934);*/
System.out.println(obj.distance(38.898556, -77.037852, 38.897147, -77.043934, "M") + " Miles\n");
System.out.println(obj.distance(38.898556, -77.037852, 38.897147, -77.043934, "K") + " Kilometers\n");
System.out.println(obj.distance(32.9697, -96.80322, 29.46786, -98.53506, "N") + " Nautical Miles\n");
}
public double distance(double lat1, double lon1, double lat2, double lon2, String sr) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
if (sr.equals("K")) {
dist = dist * 1.609344;
} else if (sr.equals("N")) {
dist = dist * 0.8684;
}
return (dist);
}
public double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
public double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
}
Slightly upgraded answer from #David George:
public static double distance(double lat1, double lat2, double lon1,
double lon2, double el1, double el2) {
final int R = 6371; // Radius of the earth
double latDistance = Math.toRadians(lat2 - lat1);
double lonDistance = Math.toRadians(lon2 - lon1);
double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
+ Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
* Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double distance = R * c * 1000; // convert to meters
double height = el1 - el2;
distance = Math.pow(distance, 2) + Math.pow(height, 2);
return Math.sqrt(distance);
}
public static double distanceBetweenLocations(Location l1, Location l2) {
if(l1.hasAltitude() && l2.hasAltitude()) {
return distance(l1.getLatitude(), l2.getLatitude(), l1.getLongitude(), l2.getLongitude(), l1.getAltitude(), l2.getAltitude());
}
return l1.distanceTo(l2);
}
distance function is the same, but I've created I small wrapper function, which takes 2 Location objects. Thanks to this, I only use distance function if both of locations actually have altitude, because sometimes they don't. And it can lead to strange results (if location doesn't know its altitude 0 will be returned). In this case, I fall back to classic distanceTo function.

Categories