Simple calculations for working with lat/lon and km distance?
Asked Answered
H

6

154

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:

How to calculate the bounding box for a given lat/lng location?

The accepted answer seems adequate for my requirements.

Hypoderma answered 10/8, 2009 at 7:14 Comment(1)
Possible duplicate of How to calculate the bounding box for a given lat/lng location?Brainstorm
P
284

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.

Plenum answered 10/8, 2009 at 7:32 Comment(13)
Do you mean cos(longitude) in the second formula?Arondell
How did you came up with this? I'm missing something, can you please elaborate on the Longitude calculations? TyArondell
@Odys: If you're comparing two points that lie on the same line of longitude (north/south), they lie on a great circle and the conversion factor is just the Earth's polar circumference divided by 360 degrees. But it's different for east-west measurements, because (except for the equator) you're not measuring along a "great circle", so the "circumference" at a given latitude is smaller. And the correction factor turns out to be the cosine of the latitude.Plenum
My explanation: cos(0°) = 1 => Therefore there is no correction factor applied doing the calculation at the equator. The longitudes are the widest there. cos(90°) = 0 => At the poles the longitudes meet in one point. There is no distance to be calculated.Jetsam
Longitude: 1 deg = 111.320*cos(latitude) km for Berlin (latitude~=52.504) this yields: -68.92914538114779 .... A negative value. (Calculated by running this statement in Java: 111.320 * (Math.cos(52.504)))Effluent
@Stijn: You need to convert from degrees to radians before calling Math.cos().Plenum
@JimLewis Ok.... how? Is Google using degrees? And this formula assuming radians?? I just codified to Java what this answer says in pseudocode.Effluent
This gives negative values when latitude is between 90 and 180 degrees. I just use absolute. Hopefully it's correct...Whitehead
@Khanh But there is nothing in world btwn 90 and 180 degrees of lat. The correction factor is only designed for earth/spheres where 0<=lat<=90.Truscott
@PriyaRanjanSingh you're right, I can't remember where I got a latitude greater than 90 degrees.Whitehead
Looking at a globe (for instance at the provided link) you can easily see the longitudes (circles through the north/south poles) is always the same size regardless of latitude (going from east to west). However, the circle created by the latitude will get smaller when approaching the poles (and have 0 diameters at the poles) so you should change latitude at different longitudes, not longitude at different latitudes. Or?! Doing cos(longitude) for 90 → -90 at least yields a 0 (at 90) → 1 (at 0) → 0 (at -90) result, in line with my observations... (and needs)...Rosemarierosemary
Just think about a wedge of an orange , or a slice of pie, or spokes on a wire wheel, or radial strands of a spider web, etc., etc. The distance between any pair of lines that are not parallel to each other changes as you move along them.Brigette
Is there a name and reference for this approximation?Plateau
W
5

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:

http://www.jstott.me.uk/jcoord/

Wavelength answered 10/8, 2009 at 7:41 Comment(4)
The site has the library now.Doralyn
The link is broken!Shishko
For PHP, you can use this fork: github.com/dvdoug/PHPCoordStorybook
There is github.com/xni06/JCoord (Java) and jstott.me.uk/jscoord (Javascript)Waves
O
5

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))
Outshoot answered 23/7, 2019 at 7:55 Comment(1)
I think it should be "lat * pi / 180"Guttate
A
1

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);
Acarology answered 20/2, 2017 at 6:26 Comment(0)
P
1

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.

Pleasurable answered 23/8, 2018 at 16:26 Comment(1)
Thanks for the link to utm. Shocking that it seems to have no documentation at all.Unworldly
W
-1

Why not use properly formulated geospatial queries???

Here is the SQL server reference page on the STContains geospatial function:

https://learn.microsoft.com/en-us/sql/t-sql/spatial-geography/stcontains-geography-data-type?view=sql-server-ver15

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

Whitecollar answered 23/1, 2020 at 19:41 Comment(1)
Please take a moment to read through the editing help in the help center. Formatting on Stack Overflow is different than other sites.Oakley

© 2022 - 2024 — McMap. All rights reserved.