Search code examples
debuggingmathlualatitude-longitudehaversine

How come this Lua Haversine code for lat/long won't work?


I'm trying to create a haversine "distance calculator," where I can input two lat/long coordinates and it'll give the distance between them, through use of the haversine formula. It's in Lua, and here's the code:

local R = 6371000 -- metres
local lat1 =  la1 * math.pi/180
local lat2 = la2 * math.pi/180
local dlat = (lat2 - lat1) * math.pi/180
local dlong = (long2 - long1) * math.pi/180

local a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(lat1) * math.cos(lat2) * math.sin(dlong/2) * math.sin(dlong/2)
local c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))

local d = R * c -- in metres
d = d / 1000 -- in kilometers

print(d)

I've tested it against multiple online distance checkers which use this formula, and this is always off by a large margin. And also, I took the code from here, and then changed it for Lua: https://www.movable-type.co.uk/scripts/latlong.html

Any idea why this isn't working? Thank you.


Solution

  • Your problem, assuming you just omitted the lines, in which you set the coordinates, is that you multiply dlat by math.pi/180, although lat1 and lat2 are already in radians, not degrees. local dlat should be lat2 - lat1.

    Below is an improved variant of the code:

    local function haversine (lat1, lat2, long1, long2) -- in radians.
        local cos, sin = math.cos, math.sin
        local dlat, dlong = lat2 - lat1, long2 - long1
        return sin (dlat / 2) ^ 2 + cos (lat1) * cos (lat2) * sin (dlong / 2) ^ 2
    end
    
    local function distance (p1, p2) -- in degrees.
        local pi, arcsin, sqrt = math.pi, math.asin, math.sqrt
        local d2r = pi / 180
    
        local R = 6371000 -- in metres
    
        local lat1, lat2 =  p1[1] * d2r, p2[1] * d2r
        local long1, long2 = p1[2] * d2r, p2[2] * d2r
        
        local a = haversine (lat1, lat2, long1, long2)
    
        return 2 * R * arcsin (sqrt (a)) / 1000 -- in km
    end
    
    
    local Moscow, Novokuznetsk = {55.7558, 37.6173}, {53.7596, 87.1216}
    print (distance (Moscow, Novokuznetsk)) -- 3126 km as reported by https://www.distancefromto.net/distance-from-moscow-to-novokuznetsk-ru.
    
    • distance and haversine are moved to functions,
    • functions from math are localised for tidier look and performance,
    • degrees to radians conversion rate is pre-calculated for performance,
    • ^ is used for power,
    • arctangent is replaced with arcsine, to simplify the formula.