I am trying to convert the code snippet given in this http://www.movable-type.co.uk/scripts/latlong.html into java. But I am not getting same result as that of site. Here is my code to find the midpoint between two points where their latitudes and longitudes are given
midPoint(12.870672,77.658964,12.974831,77.60935);
public static void midPoint(double lat1,dou开发者_开发问答ble lon1,double lat2,double lon2)
{
double dLon = Math.toRadians(lon2-lon1);
double Bx = Math.cos(lat2) * Math.cos(dLon);
double By = Math.cos(lat2) * Math.sin(dLon);
double lat3 = Math.atan2(Math.sin(lat1)+Math.sin(lat2),Math.sqrt( (Math.cos(lat1)+Bx)*(Math.cos(lat1)+Bx) + By*By) );
double lon3 = lon1 + Math.atan2(By, Math.cos(lat1) + Bx);
System.out.print(lat3 +" " + lon3 );
}
I am not sure whethe dLon is correct or not. So please help me guys to figure it out. P.S.I need to find the latitude and longitude of the midpoint
You need to convert to radians. Change it to the following:
public static void midPoint(double lat1,double lon1,double lat2,double lon2){
double dLon = Math.toRadians(lon2 - lon1);
//convert to radians
lat1 = Math.toRadians(lat1);
lat2 = Math.toRadians(lat2);
lon1 = Math.toRadians(lon1);
double Bx = Math.cos(lat2) * Math.cos(dLon);
double By = Math.cos(lat2) * Math.sin(dLon);
double lat3 = Math.atan2(Math.sin(lat1) + Math.sin(lat2), Math.sqrt((Math.cos(lat1) + Bx) * (Math.cos(lat1) + Bx) + By * By));
double lon3 = lon1 + Math.atan2(By, Math.cos(lat1) + Bx);
//print out in degrees
System.out.println(Math.toDegrees(lat3) + " " + Math.toDegrees(lon3));
}
Even easier with Android Google Maps Utilities:
LatLngBounds bounds = new LatLngBounds(start, dest);
bounds.getCenter();
Update: Better use the builder (for why see Bad Losers Answer):
LatLngBounds.builder().include(start).include(dest).build().getCenter();
Please use LatLngBounds with the builder rather than the constructor if you want to correctly handle transgression of the antimeridian (longitude +/-180).
Here is the test illustrating the problem:
LatLng mp = midPoint(new LatLng(-43.95139,-176.56111),new LatLng(-36.397816,174.663496));
public static LatLng midPoint (LatLng SW, LatLng NE) {
LatLngBounds bounds = new LatLngBounds(SW, NE);
Log.d("BAD!", bounds.toString() + " CENTRE: " + bounds.getCenter().toString());
bounds = LatLngBounds.builder().include(SW).include(NE).build();
Log.d("GOOD", bounds.toString() + " CENTRE: " + bounds.getCenter().toString());
return bounds.getCenter();
}
Actual results:
BAD!: LatLngBounds{southwest=lat/lng: (-43.95139,-176.56111), northeast=lat/lng: (-36.397816,174.663496)} CENTRE: lat/lng: (-40.174603,-0.948807)
GOOD: LatLngBounds{southwest=lat/lng: (-43.95139,174.663496), northeast=lat/lng: (-36.397816,-176.56111)} CENTRE: lat/lng: (-40.174603,179.051193)
The constructor technique produces a central longitude out by 180 degrees!
You need to convert you lat and lon values used in the other formulas to Radians also. You can see this in the code ~3/5ths of the way down the page. The clue was given at the end of the spherical law of cosines distance formula:
(Note that here and in all subsequent code fragments, for simplicity I do not show conversions from degrees to radians; see below for complete versions).
Here's @dogbane's Java
code converted to TypeScript
.
type LatLng = {
lat: number;
lng: number;
};
function calculateMidPoint(latLngA: LatLng, latLngB: LatLng) {
function toRadians(degress: number): number {
return degress * (Math.PI / 180);
}
function toDegrees(radians: number): string {
return (radians * (180 / Math.PI)).toFixed(4);
}
const lngDiff = toRadians(latLngB.lng - latLngA.lng);
const latA = toRadians(latLngA.lat);
const latB = toRadians(latLngB.lat);
const lngA = toRadians(latLngA.lng);
const bx = Math.cos(latB) * Math.cos(lngDiff);
const by = Math.cos(latB) * Math.sin(lngDiff);
const latMidway = toDegrees(
Math.atan2(
Math.sin(latA) + Math.sin(latB),
Math.sqrt((Math.cos(latA) + bx) * (Math.cos(latA) + bx) + by * by)
)
);
const lngMidway = toDegrees(lngA + Math.atan2(by, Math.cos(latA) + bx));
console.log(
`Midway point between ${latLngA} and ${latLngB} is: Lat: ${latMidway}, lng: ${lngMidway}`
);
}
Following is @dogbane 's java
code converted to Kotlin
:
private fun midPoint(lat1: Double, lon1: Double, lat2: Double, lon2: Double) : String {
var lat1 = lat1
var lon1 = lon1
var lat2 = lat2
val dLon: Double = Math.toRadians(lon2 - lon1)
//convert to radians
lat1 = Math.toRadians(lat1)
lat2 = Math.toRadians(lat2)
lon1 = Math.toRadians(lon1)
val Bx: Double = Math.cos(lat2) * Math.cos(dLon)
val By: Double = Math.cos(lat2) * Math.sin(dLon)
val lat3: Double = Math.atan2(Math.sin(lat1) + Math.sin(lat2), Math.sqrt((Math.cos(lat1) + Bx) * (Math.cos(lat1) + Bx) + By * By))
val lon3: Double = lon1 + Math.atan2(By, Math.cos(lat1) + Bx)
var result: String = ""
result = Math.toDegrees(lat3).toString() + "," + Math.toDegrees(lon3).toString()
return result;
}
My last job I made a tracking module and I was using this formula to calculate the distance between 2 coordinates.
//Location lat and lon
double locLat = -23.548333;
double locLon = -46.636111;
//Destination lat and lon
double dstLat = -22.902778;
double dstLon = -43.206667;
double arcoAB = 90 - (dstLat);
double arcoAC = 90 - (locLat);
double difLon = locLon - (dstLon);
double cosA = Math.cos(Math.toRadians(arcoAC)) * Math.cos(Math.toRadians(arcoAB)) + Math.sin(Math.toRadians(arcoAC)) * Math.sin(Math.toRadians(arcoAB)) * Math.cos(Math.toRadians(difLon));
double acosCosA = Math.toDegrees(Math.acos(cosA));
double raio = 2 * Math.PI * 6371;
double distance = (raio * acosCosA) / 360;
return distance; //Distance in KM, convert to anything else (miles, meters..) if you need..
You can get the mid point dividing the distance by 2.
Ah, this another formula works too:
double dLat = Math.toRadians(dstLat - locLat);
double dLon = Math.toRadians(dstLon - locLon);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(locLat)) * Math.cos(Math.toRadians(dstLat))
* Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = 6371 * c;
return d; //Distance in KM
精彩评论