# Ruby: Calculating the Orthodromic Distance Using the Haversine Formula

# Ruby: Calculating the Orthodromic Distance Using the Haversine Formula

Join the DZone community and get the full member experience.

Join For FreeHortonworks Sandbox for HDP and HDF is your chance to get started on learning, developing, testing and trying out new features. Each download comes preconfigured with interactive tutorials, sample data and developments from the Apache community.

As part of the UI I’m building around my football stadiums data set I wanted to calculate the distance from a football stadium to a point on the map in Ruby since cypher doesn’t currently return this value.

I had the following cypher query to return the football stadiums near Westminster along with their lat/long values:

lat, long, distance = ["51.55786291569685", "0.144195556640625", 10] query = " START node = node:geom('withinDistance:[#{lat}, #{long}, #{distance}]')" query << " RETURN node.name, node.team, node.lat, node.lon" rows = result["data"].map do |row| { :team => row[1], :stadium => row[0], :lat => row[2], :lon => row[3] } p rows

which returns the following:

[{:team=>"Millwall", :stadium=>"The Den", :lat=>51.4859, :lon=>-0.050743}, {:team=>"Arsenal", :stadium=>"Emirates Stadium", :lat=>51.5549, :lon=>-0.108436}, {:team=>"Chelsea", :stadium=>"Stamford Bridge", :lat=>51.4816, :lon=>-0.191034}, {:team=>"Fulham", :stadium=>"Craven Cottage", :lat=>51.4749, :lon=>-0.221619}, {:team=>"Queens Park Rangers", :stadium=>"Loftus Road", :lat=>51.5093, :lon=>-0.232204}, {:team=>"Leyton Orient", :stadium=>"Brisbane Road", :lat=>51.5601, :lon=>-0.012551}]

In the neo4j spatial code the distance between two points is referred to as the ‘orthodromic distance’ but searching for that didn’t come up with anything. However, I did eventually come across the following postwhich referred to the Haversine formula which is exactly what we want.

There is a good explanation of the formula on the Ask Dr Math forum which defines the formula like so:

dlon = lon2 - lon1 dlat = lat2 - lat1 a = (sin(dlat/2))^2 + cos(lat1) * cos(lat2) * (sin(dlon/2))^2 c = 2 * atan2(sqrt(a), sqrt(1-a)) d = R * c

where:

- R – the radius of the Earth
- c – the great circle distance in radians
- c – the great circle distance in the same units as R
- lat1, lat2, lon1, lon2 – latitude and longitudes in radians

To convert decimal degrees to radians we need to multiply the number of degrees by pi/180 radians/degree.

The Ruby translation of that formula looks like this:

def haversine(lat1, long1, lat2, long2) radius_of_earth = 6378.14 rlat1, rlong1, rlat2, rlong2 = [lat1, long1, lat2, long2].map { |d| as_radians(d)} dlon = rlong1 - rlong2 dlat = rlat1 - rlat2 a = power(Math::sin(dlat/2), 2) + Math::cos(rlat1) * Math::cos(rlat2) * power(Math::sin(dlon/2), 2) great_circle_distance = 2 * Math::atan2(Math::sqrt(a), Math::sqrt(1-a)) radius_of_earth * great_circle_distance end def as_radians(degrees) degrees * Math::PI/180 end def power(num, pow) num ** pow end

And if we change our initial code to use it:

lat, long, distance = ["51.55786291569685", "0.144195556640625", 10] query = " START node = node:geom('withinDistance:[#{lat}, #{long}, #{distance}]')" query << " RETURN node.name, node.team, node.lat, node.lon" rows = result["data"].map do |row| { :team => row[1], :stadium => row[0], :distance => haversine(lat, long, row[2], row[3]).round(2), :lat => row[2], :lon => row[3] } p rows

which gives us the output we want:

[{:team=>"Millwall", :stadium=>"The Den", :distance=>4.87, :lat=>51.4859, :lon=>-0.050743}, {:team=>"Arsenal", :stadium=>"Emirates Stadium", :distance=>5.57, :lat=>51.5549, :lon=>-0.108436}, {:team=>"Chelsea", :stadium=>"Stamford Bridge", :distance=>5.94, :lat=>51.4816, :lon=>-0.191034}, {:team=>"Fulham", :stadium=>"Craven Cottage", :distance=>8.18, :lat=>51.4749, :lon=>-0.221619}, {:team=>"Queens Park Rangers", :stadium=>"Loftus Road", :distance=>8.21, :lat=>51.5093, :lon=>-0.232204}, {:team=>"Leyton Orient", :stadium=>"Brisbane Road", :distance=>9.33, :lat=>51.5601, :lon=>-0.012551}]

Hortonworks Community Connection (HCC) is an online collaboration destination for developers, DevOps, customers and partners to get answers to questions, collaborate on technical articles and share code examples from GitHub. Join the discussion.

Published at DZone with permission of Mark Needham , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

## {{ parent.title || parent.header.title}}

## {{ parent.tldr }}

## {{ parent.linkDescription }}

{{ parent.urlSource.name }}