I've spend much time internet for finding a way to do this. By exist documention I wrote below code, But it does not show correct angle.
What's problem?
private double angleFromCoordinate(double lat1, double long1, double lat2,
double long2) {
double dLon = (long2 - long1);
double y = Math.sin(dLon) * Math.cos(lat2);
double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
* Math.cos(lat2) * Math.cos(dLon);
double brng = Math.atan2(y, x);
brng = Math.toDegrees(brng);
brng %= 360;
// brng = 360 - brng;
return brng;
}
UPDATED
result of below code:
int angle = (int) angleFromCoordinate(36.288024, 59.615656
, 39.033659, 48.662504);
angle is '58'
The methods Math.cos and Math.sin take a number of radians for their arguments. You are passing degrees into this method. You need to convert your degrees into radians at the start of the method.
private double angleFromCoordinate(double lat1, double long1, double lat2,
double long2) {
double lat1Rad = Math.toRadians(lat1);
double long1Rad = Math.toRadians(long1);
double lat2Rad = Math.toRadians(lat2);
double long2Rad = Math.toRadians(long2);
then use the new variables lat1Rad and so on for the remaining mathematics.
Related
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;
}
Im getting incorrect length of CD where D marks the projection of third point C on arc AB:
Input to above code::
startX,startY- start point's coordinates of the arc--> (48.1388, 11.54988)
endX,endY-end point's coordinates of arc--> (48.139, 11.54988)
thirdX,thirdY- coordinated of point C away from arc--> (48.1389, 11.5496)
dXt is coming to be -13.41654587971497 meters but the expected value is 31.16949
I've written the code based on the equations I found: here
I am unable to find the cause of incorrect value, please help.Thanks.
private static void pointToArcDistance(double thirdX, double thirdY, double startX, double startY,
double endX, double endY) {
double R = 6371000;
double φ1 = startX * Math.PI / 180;
double φ2 = endX * Math.PI / 180;
double Δφ = (endX - startX) * Math.PI / 180;
double Δλ = (endY - startY) * Math.PI / 180;
double a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d13 = R * c; // distance between start & endPoint in meters
double brng12 = bearing(startX, startY, endX, endY);
double brng13 = bearing(startX, startY, thirdX, thirdY);
double δ13 = d13 / R;
double dXt = Math.asin(Math.sin(δ13) * Math.sin(brng13 - brng12)) * R;
System.out.println("tangent distance(CD)::" + dXt);
}
private static double bearing(double lat1, double long1, double lat2, double long2) {
double y = Math.sin(long2 - long1) * Math.cos(lat2);
double x = Math.cos(lat1) * Math.sin(lat2) -
Math.sin(lat1) * Math.cos(lat2) * Math.cos(long2 - long1);
double polarDegrees = toDegrees(Math.atan2(y, x));
return polarDegrees
You transform radians to degrees here:
double polarDegrees = toDegrees(Math.atan2(y, x));
but the next calculations need radians.
So just remove toDegrees
To find the distance from a point to an arc:
First, find the center of the oval implied by the arc
Find the angle to the point using atan2
Find the x,y intercept with your oval using cos(angle) * r1, sin(angle) * r2
Use the distance formula from the x,y intercept to the point
I have this code segment from a forum, and it's used to calculate the distance from a line to a point. The problem is that I don't know the measure unit in which the result is returned. Here is the code:
private double distanceFromLineToPoint(Point A, Point B, Point C){ //A-B the line, C the point
double lat1=A.latitude;
double lon1=A.longitude;
double lat2=B.latitude;
double lon2=B.longitude;
double lat3=C.latitude;
double lon3=C.longitude;
double EARTH_RADIUS_KM=6371;
double y=Math.sin(lon3-lon1)*Math.cos(lat3);
double x = Math.cos(lat1) * Math.sin(lat3) - Math.sin(lat1) * Math.cos(lat3) * Math.cos(lat3 - lat1);
double bearing1=Math.toDegrees(Math.atan2(y,x));
bearing1=360-(bearing1+360%360);
double y2 = Math.sin(lon2 - lon1) * Math.cos(lat2);
double x2 = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lat2 - lat1);
double bearing2 = Math.toDegrees(Math.atan2(y2, x2));
bearing2 = 360 - (bearing2 + 360 % 360);
double lat1Rads = Math.toRadians(lat1);
double lat3Rads = Math.toRadians(lat3);
double dLon = Math.toRadians(lon3 - lon1);
double distanceAC = Math.acos(Math.sin(lat1Rads) * Math.sin(lat3Rads)+Math.cos(lat1Rads)*Math.cos(lat3Rads)*Math.cos(dLon)) * EARTH_RADIUS_KM;
return (Math.abs(Math.asin(Math.sin(distanceAC/EARTH_RADIUS_KM)*Math.sin(Math.toRadians(bearing1)-Math.toRadians(bearing2))) * EARTH_RADIUS_KM));
}
I'm trying to modify a formula to get the distances between 2 lat or 2 lon only which will translate into x, y coordinates.
The code/formula below (Haversine) gives the hypotenuse (direct distance between 2 points with an angle)
However I want to get x, y coordinates as well using only the latitudes & longitudes. Since these are straight lines, the angle should not matter.
One way would be to set both latitudes to zero - which will give me the longitude distance (and vice versa) - however it will require me to call the same function 3 times:
1 for direct distance, 1 for x distance, 1 for y distance
Is there any way that I can amend the code below to calculate all 3 at once efficiently and return it as an array [x_dis, y_dis, direct_dist]
private static double distance(double lat1, double lon1, double lat2, double lon2, String 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);
}
private static double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
private static double rad2deg(double rad) {
return (rad * 180 / Math.PI);
}
The best way I can see would be to create a function that calls it three times and returns each value.
private static double[] getAlldistances(double lat1, double lat2, double long1, double long2, string unit){
double latDistance = distance(lat1, 0, lat2, 0, unit);
double longDistance = distance(0, long1, 0, long2, unit);
double directDistance = distance(lat1, long1, lat2, long2, unit);
return double int[3] {latDistance, longDistance, directDistance};
}
This should use your existing function without an issue. By setting the long or lat to 0 for both points we are able to work out the distance between just the lats or the longs. The code is untested and should be treated as Pseudo code.
I'm not really good with mathematics but I need to calculate the distance of two different locations of the markers. Something like this:
public double CalculationByDistance(double initialLat, double initialLong, double finalLat, double finalLong){
return distance;
}
Or is there any alternative ways that I can calculate the distance of two markers, also I tried to google for answers.. but couldn't find any.
Reference:
http://en.wikipedia.org/wiki/Haversine_formula
Comments are appreciated :) Thanks!!
Try this, much simpler than Haversine!
Location me = new Location("");
Location dest = new Location("");
me.setLatitude(myLat);
me.setLongitude(myLong);
dest.setLatitude(destLat);
dest.setLongitude(destLong);
float dist = me.distanceTo(dest);
If you want to stick with Haversine, something like this:
public double CalculationByDistance(double initialLat, double initialLong,
double finalLat, double finalLong){
int R = 6371; // km (Earth radius)
double dLat = toRadians(finalLat-initialLat);
double dLon = toRadians(finalLong-initialLong);
initialLat = toRadians(initialLat);
finalLat = toRadians(finalLat);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(initialLat) * Math.cos(finalLat);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c;
}
public double toRadians(double deg) {
return deg * (Math.PI/180);
}
Also, you need to create a method toRadians() that convert values from degrees to radians, which is quite easy.
Hope it helps!
From your wikipedia link, applying the formula directly you can do the following:
public double CalculationByDistance(double initialLat, double initialLong, double finalLat, double finalLong){
/*PRE: All the input values are in radians!*/
double latDiff = finalLat - initialLat;
double longDiff = finalLong - initialLong;
double earthRadius = 6371; //In Km if you want the distance in km
double distance = 2*earthRadius*Math.asin(Math.sqrt(Math.pow(Math.sin(latDiff/2.0),2)+Math.cos(initialLat)*Math.cos(finalLat)*Math.pow(Math.sin(longDiff/2),2)));
return distance;
}
Use the below method for calculating the distance of two different locations.
public double getKilometers(double lat1, double long1, double lat2, double long2) {
double PI_RAD = Math.PI / 180.0;
double phi1 = lat1 * PI_RAD;
double phi2 = lat2 * PI_RAD;
double lam1 = long1 * PI_RAD;
double lam2 = long2 * PI_RAD;
return 6371.01 * acos(sin(phi1) * sin(phi2) + cos(phi1) * cos(phi2) * cos(lam2 - lam1));
}
try this
/**
* This is the implementation Haversine Distance Algorithm between two places
* #author ananth
* R = earth’s radius (mean radius = 6,371km)
Δlat = lat2− lat1
Δlong = long2− long1
a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
c = 2.atan2(√a, √(1−a))
d = R.c
*
*/
public class HaversineDistance {
/**
* #param args
* arg 1- latitude 1
* arg 2 — latitude 2
* arg 3 — longitude 1
* arg 4 — longitude 2
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
final int R = 6371; // Radious of the earth
Double lat1 = Double.parseDouble(args[0]);
Double lon1 = Double.parseDouble(args[1]);
Double lat2 = Double.parseDouble(args[2]);
Double lon2 = Double.parseDouble(args[3]);
Double latDistance = toRad(lat2-lat1);
Double lonDistance = toRad(lon2-lon1);
Double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2) +
Math.cos(toRad(lat1)) * Math.cos(toRad(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;
System.out.println(“The distance between two lat and long is::” + distance);
}
private static Double toRad(Double value) {
return value * Math.PI / 180;
}
}