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!