Simple calculations for working with lat/lon and km distance?
AlgorithmGeometryGeolocationAlgorithm Problem Overview
Is there a simple calculation I can do which will convert km into a value which I can add to a lat or lon float to calculate a bounding box for searches? It doesn't need to be completely accurate.
For instance: if I were given a lat/lon for London, England (51.5001524, -0.1262362) and I wanted calculate what the lat would be 25km east/west from that point, and what the lon would be 25km north/south of that point, what would I need to do to convert the 25km into a decimal to add to the values above?
I'm looking for a general rule-of-thumb, ie: 1km == +/- 0.XXX
Edit:
My original search for "lat lon" didn't return this result:
The accepted answer seems adequate for my requirements.
Algorithm Solutions
Solution 1 - Algorithm
The approximate conversions are:
- Latitude: 1 deg = 110.574 km
- Longitude: 1 deg = 111.320*cos(latitude) km
This doesn't fully correct for the Earth's polar flattening - for that you'd probably want a more complicated formula using the WGS84 reference ellipsoid (the model used for GPS). But the error is probably negligible for your purposes.
Source: http://en.wikipedia.org/wiki/Latitude
Caution: Be aware that latlong coordinates are expressed in degrees, while the cos
function in most (all?) languages typically accepts radians, therefore a degree to radians conversion is needed.
Solution 2 - Algorithm
If you're using Java, Javascript or PHP, then there's a library that will do these calculations exactly, using some amusingly complicated (but still fast) trigonometry:
Solution 3 - Algorithm
Thanks Jim Lewis for his great answer and I would like to illustrate this solution by my function in Swift:
func getRandomLocation(forLocation location: CLLocation, withOffsetKM offset: Double) -> CLLocation {
let latDistance = (Double(arc4random()) / Double(UInt32.max)) * offset * 2.0 - offset
let longDistanceMax = sqrt(offset * offset - latDistance * latDistance)
let longDistance = (Double(arc4random()) / Double(UInt32.max)) * longDistanceMax * 2.0 - longDistanceMax
let lat: CLLocationDegrees = location.coordinate.latitude + latDistance / 110.574
let lng: CLLocationDegrees = location.coordinate.longitude + longDistance / (111.320 * cos(lat / .pi / 180))
return CLLocation(latitude: lat, longitude: lng)
}
In this function to convert distance I use following formulas:
latDistance / 110.574
longDistance / (111.320 * cos(lat / .pi / 180))
Solution 4 - Algorithm
http://www.jstott.me.uk/jcoord/ - use this library
LatLng lld1 = new LatLng(40.718119, -73.995667);
LatLng lld2 = new LatLng(51.499981, -0.125313);
Double distance = lld1.distance(lld2);
Log.d(TAG, "Distance in kilometers " + distance);
Solution 5 - Algorithm
Interesting that I didn't see a mention of UTM coordinates.
https://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system.
At least if you want to add km to the same zone, it should be straightforward (in Python : https://pypi.org/project/utm/ )
utm.from_latlon and utm.to_latlon.
Solution 6 - Algorithm
Why not use properly formulated geospatial queries???
Here is the SQL server reference page on the STContains geospatial function:
or if you do not waant to use box and radian conversion , you cna always use the distance function to find the points that you need:
DECLARE @CurrentLocation geography;
SET @CurrentLocation = geography::Point(12.822222, 80.222222, 4326)
SELECT * , Round (GeoLocation.STDistance(@CurrentLocation ),0) AS Distance FROM [Landmark]
WHERE GeoLocation.STDistance(@CurrentLocation )<= 2000 -- 2 Km
There should be similar functionality for almost any database out there.
If you have implemented geospatial indexing correctly your searches would be way faster than the approach you are using