Home > Erlang > Distance between two points on Earth in Erlang: an implementation of Haversine function

Distance between two points on Earth in Erlang: an implementation of Haversine function


During my daily  routine at Univesity of Trento I deal with different tasks in different programming languages. Lately I had to find a good way to compute the distance between two points on Earth which were identified by their lat, long coordinates. After a while, I decided to solve this task by using the haversine function.

The haversine  (as known as the haversed sine), is a trigonometric function mostly employed in order to compute the great-circle distances between two points on a sphere, where the two points are identified by their longitude and latitude.

This method is strongly recommended in the literature  for calculating short distances on Earth and in that sense it works great, but when we use it we have to keep in mind that it has a major drawback: the formula approximates the shape of the Earth to a sphere (actually it is an ellipsoidal), therefore it introduces some overestimation errors for  trans-polar distances and underestimation errors for trans-equatorial distances.

If you don’t know how to implement the haversine function you will probably use your  google-fu. The first web page you should check out is the wikipedia page for haversine, and the second one is  this webpage. In the second link you may find a bunch of different implementations in several languages (e.g. Haskell, Python, C, Clojure etc) of the haversine problem…but wait! There isn’t an Erlang implementation!

Ok, let’s solve this problem right now! Here is my implementation of the haversine function for two points distance:

-module(haversine).
-export([distance/4]).

distance(Lng1, Lat1, Lng2, Lat2) ->
    Deg2rad = fun(Deg) -> math:pi()*Deg/180 end,
    [RLng1, RLat1, RLng2, RLat2] = [Deg2rad(Deg) || Deg <- [Lng1, Lat1, Lng2, Lat2]],

    DLon = RLng2 - RLng1,
    DLat = RLat2 - RLat1,

    A = math:pow(math:sin(DLat/2), 2) + math:cos(RLat1) * math:cos(RLat2) * math:pow(math:sin(DLon/2), 2),

    C = 2 * math:asin(math:sqrt(A)),

    %% suppose radius of Earth is 6372.8 km
    Km = 6372.8 * C,
    Km.

As you may notice the implementation is fairly easy: first of all we use a list comprehension to convert our latitudes and longitues to radians. Once we get the values expressed in radians, we just need to extract the desired distance by using the haversine function. 

Let’s try the code with the webpage example! Suppose you want to compute the distance between Nashville, TN, USA: (36.12, -86.67) and Los Angeles International Airport (LAX) in Los Angeles, CA, USA:  (33.94, -118.40):

1> haversine:distance(-86.67,36.12,-118.40,33.94).
2887.2599506071087

Good! Seems working! You may find my implementation here (pick the right git branch), just if you don’t want to cut and paste the code from this web page!

Hope this will be helpful to you as it was for me!

Categories: Erlang Tags: , ,
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: