Programmatically calculate distances between UK postcodes

Calculating distances in the UK is easy, thanks to the National Grid, a postcode lookup table, and a dash of Pythagoras.

By Mike Lewis

In this article, I'll explain how to write program code that calculates the straight-line distance between any pair of British addresses (or, more precisely, postcodes). Why would you want to do that? I can think of at least two reasons; no doubt you can come up with others:

You can do this in almost any programming language or development tool. The example code I'll show you is for SQL Server (T-SQL), PHP, JavaScript and Visual FoxPro, but the general technique is in no way specific to those tools.

In each case, the starting point is the same: the National Grid.

Figure 1

Figure 1: Use the National Grid to
locate any point in Great Britain.

National Grid? What's that?

In Britain, the National Grid is a system for identifying the location of any point in the country, to any desired precision. It's based on a notional grid, 1300 km high (south to north) by 700 km wide (west to east). Its origin (that is, its bottom left corner) lies in the English Channel, to the south west of Cornwall. The land area covered by the grid is divided into 56 squares, each measuring 100 km x 100 km, and each identified by a two-letter code (Figure 1).

Every point within the grid has an associated grid reference. These grid references (also known as map references or Ordnance Survey [OS] references) are widely used in the UK, especially when describing routes, giving directions or identifying landmarks.

As an example, the grid reference of the Moot Hall in Keswick is NY 266 234. In this case, the letters NY refer to the 100 km x 100 km square. 266 is the horizontal distance of the point in question from the south west corner of the square, expressed in units of 100 metres. This horizontal distance is called the easting (you can also think of it as the x co-ordinate). Similarly, 234 is the vertical distance from the south west corner of the square. This is the northing (or y co-ordinate).

This method of expressing a grid reference (two letters followed by a pair of three-digit numbers) is one that's familiar to many people in the UK. (In practice, when identifying places in a known town or district, it's common to omit the letters.) But it's not so useful in mathematical or programming applications, such as calculating distances.

For those purposes, you need to use an all-numeric version of the grid reference. This is based on the same co-ordinate system, but is relative to the origin of the grid as a whole rather than that of an individual square. Staying with the same example, the Moot Hall is 326.6 km. east of the origin, and 523.4 km north of it. So its all-numeric reference (again, to a precision of 100 metres) is 3266 5234.

(If you would like more information about the National Grid, there is a useful guide on the Ordnance Survey website.)

Grid references from postcodes

So how do you obtain the grid reference for a given location, given the corresponding address? The answer is to use a lookup table.

The Postcode Address File (PAF) is the official lookup table of postal codes in the UK. For each unit postcode, it gives the corresponding all-numeric grid reference. A unit postcode covers a very small area - typically a short section of a street or city block - so its grid reference will be very precise. (For more information about the structure and terminology of British postal codes, see Parsing and validating UK postcodes in SQL Server.)

Unfortunately, You can't simply download a free copy of the PAF, as it's subject to strict copyright and licensing controls. The most practical way to access it is by means of specialist addressing software. There are a number of these products available. Some are web-based, others are desktop applications. Many of them provide an API for looking up grid references. But they are inevitably expensive, and will probably not be economical if only used occasionally.

However, it is possible to download a free copy of a much smaller file: one that gives grid references at the level of the outward postcode only. The outward postcode is the first half of the code (before the space), and corresponds to a district - typically a large village, a small town or the section of a city. Calculating distances based on outward postcodes will be less accurate than using the PAF, but it will be good enough in most cases.

One place where you can download this free file is Dan Gibbs' site. It comes in several formats, including comma-delimited (which can be opened in Excel or imported into other applications) and XML. It also has a script which generates the lookup table for a MySQL database. It should be possible to adapt the script for other databases without too much effort.

Note added June 2016: The EasyPeasy site, from which the outward postcode file could previously be downloaded, is no longer available.

Figure 2

Figure 2: Using Pythagoras
to determine distances.

Calculating the distance

So, now you have the grid references for your addresses. The final step is to use them to calculate the straight-line distance between any two of those addresses. This is simply a matter of applying Pythagoras' theorem. As I'm sure you know, this says that, in any right-angle triangle, the square of the hypotenuse equals the sum of the squares of the other two sides.

Figure 2 shows how we can apply the theorem to find the distance between two places: Keswick and London, in this example. The required distance is the hypotenuse of the red triangle. The other two sides of that triangle are, respectively, (e2 - e1) and (n2 - n1), where e1 and e2 are the eastings of the two points, and n1 and n2 are their northings. The distance can be calculated by means of the formula shown in Figure 3.

Figure 3

Figure 3: The Pythagorean formula.

Program code

Here are some examples of the formula expressed in various programming languages. In each case, the code shows a function that receives the (all-numeric) eastings (e1 and e2) and northings (n1 and n2) respectively of the two points. The function returns the distance in whatever units the parameters are expressed. So if the grid references are passed as pairs of four-digit numbers, these are in units of 100 metres, and the returned value will also be in units of 100 metres.

Let's start with a T-SQL function for use with SQL Server:

CREATE FUNCTION dbo.GetDistance
  (@e1 float, @e2 float, @n1 float, @n2 float)
  RETURNS float
AS
BEGIN
  RETURN sqrt(square(@e1 - @e2) + square(@n1 - @n2))
END

Next, here's the same function in PHP:

function GetDistance($e1, $e2, $n1, $n2)
{
return sqrt(pow($e1 - $e2, 2) + pow($n1 - $n2, 2));
}

This next one is for you JavaScript folk:

function GetDistance(e1, e2, n1, n2)
{
return Math.sqrt(Math.pow(e1-e2, 2) + Math.pow(n1-n2, 2))
}

And finally, here's the function in good old Visual FoxPro (VFP):

FUNCTION GetDistance
LPARAMETERS e1, e2, n1, n2
RETURN SQRT((e1 - e2) ^ 2 + (n1 - n2) ^ 2)

Finding addresses within a given radius

To end up, let's see how to answer the sort of query I mentioned at the start: how to find all addresses within a given radius of a certain point. I'll show the code in T-SQL, for use with SQL Server. I'll leave it to you adapt this for other databases.

In the following example, the lookup table is called Postcodes. This contains the outward postcodes in a column named Outcode. The columns named x and y are the corresponding x and y co-ordinates (eastings and northings) respectively. Remember to adjust the setting of the threshold distance (@Radius) to match the precision of x and y. So, if these are stored in units of 100 metres, @Radius must also be expressed in units of 100 metres.

DECLARE @Start char(5), @StartE int, @StartN int, @Radius int

SET @Start = 'CA12' -- outcode of start point
SET @Radius = 1000  -- radius (same precision as the parameters)

-- Get easting and northing of start point
SELECT @StartE = x, @StartN = y 
  FROM Postcodes 
  WHERE @Start = Outcode

-- Get addresses within @Radius units of start point
SELECT a.Address 
  FROM Addresses a 
  JOIN Postcodes p 
  ON p.Outcode = LEFT(a.Postcode, CHARINDEX(' ', a.Postcode))
  WHERE dbo.GetDistance(@StartE, p.x, @StartN, p.y) <= @Radius

By the way, don't expect this code to run particularly quickly. Calculating square roots is not the fastest of operations, and it will have to be done many times in a query like this.

Limitations

The technique I have shown here for calculating the distance between two addresses has a couple of obvious limitations.

First, there will be an error owing to the fact that the co-ordinates are those of the centres of the postcodes, not the actual addresses you are interested in. If you're working at the unit level (which requires the PAF), that error will usually be negligible. But if you are using outward codes only, it will be more significant. It could amount to a couple of kilometres in a town centre or a city suburb; it will be usually more in a rural area, less in a densely-populated district. (As an example, the Moot Hall in Keswick is about 400 metres from the centre of its outward code, which is CA12.)

The other limitation is that the calculation is based on a flat grid. It therefore doesn't take account of the curvature of the earth. But that's not likely to be significant, given that Britain occupies a relatively small area.

Keep in mind too that the National Grid system covers England, Scotland, Wales and the Isle of Man, but not Northern Ireland (which is part of a separate Irish grid), nor the Channel Islands.

Despite these limitations, the technique I have shown here is a very effective way of calculating distances programmatically, and one that will find many applications. I hope you'll find some good ways of putting it to work.

Noted added July 2014: HexCentral reader John Hyde has contributed a useful tip for speeding up the process described in this article. See this blog post.

First Published: January 2012. Revised: June 2016

Please note: The information given on this site has been carefully checked and is believed to be correct, but no legal liability can be accepted for its use. Do not use code, components or techniques unless you are satisfied that they will work correctly with your sites or applications.

If you found this article useful, please tell your friends: