Converting UK National Grid to Lat Lon and vice versa

Just getting started on what I expect to be a long learning curve with maps (no prior experience).

I have a UK postcode picked more or less at random: BT3 9DT.
Google tells me this has the following properties:

Latitude: 54.6136 / 54°36'49"N
Longitude: -5.8986 / 5°53'54"W
OS Eastings: 335812
OS Northings: 375965

I thought I’d try to convert between grid and lat lon, but I can’t get the right answer.

using BritishNationalGrid

p1 = BNGPoint(335812, 375965)
println("p1 = ",p1)
println("lonlat(p1) = ", lonlat(p1))
println("BNGpoint = ", BNGPoint(lat=54.613625, lon=-5.898562))
println("BNGPoint = ", BritishNationalGrid.lonlat2bng(-5.898562, 54.613625))

I get the results

p1 = BNGPoint{Int64}(335812, 375965)
lonlat(p1) = (-2.9640652376747165, 53.27677828095288)
BNGpoint = BNGPoint{Float64}(148376.87358622215, 531260.3815596306)
BNGPoint = (148376.87358622215, 531260.3815596306)

What am I doing wrong?

you should probably open an issue with GitHub - anowacki/BritishNationalGrid.jl: Convert between British National Grid coordinates and WGS84 longitude and latitude, in Julia


From this place the EPSG for British National Grid is 27700 and with it I get the same numbers as you posted.

using GMT

ll = xy2lonlat([335812 375965], s_srs=27700)
1×2 Matrix{Float64}:
 -2.96407  53.2768

The lon, lat coordinates you posted from Google are on … Irland (green circle)

coast(region=(-11.5,2.5,50,55.5), shore=true)
plot!(ll, marker=:circ, mc=:blue, ms=0.4)
plot!([-5.8986 54.6136], marker=:circ, mc=:darkgreen, ms=0.4, show=true)

1 Like

huh, if you google it you indeed see what OP reports: [ 9DT.html]( 9DT.html)

And those coordinates are clearly wrong for Belfast if you check against Ordnance Survey National Grid - Wikipedia . It may be as simple as a typo in the first digit for easting.

1 Like

OP should QC the validity of the input data using the BGS Coordinate Converter.

Hardly because both decimal degrees and MM’SS agree

(36 + 49/60) / 60

(53 + 54/60) / 60

How to do it with PROJ

julia> using Proj

julia> trans = Proj.Transformation("EPSG:27700", "EPSG:4326")
Transformation unknown
    source: OSGB36 / British National Grid
    target: WGS 84
    direction: forward

julia> lat, lon = trans(335812, 375965)
(53.27676249144687, -2.9640654524079753)

julia> inv(trans)(lat, lon)
(335812.00078099035, 375964.9996478162)

Which is the same as most webapps or other instructions, like or the Excel from the OS here

So the data Google gave you for the easting/northing (how?) seems wrong. They should be more like:

julia> lat, lon = 54.6136, -5.8986
(54.6136, -5.8986)

julia> inv(trans)(lat, lon)
(148375.80935429584, 531258.8440080793)

I’m talking about the OS coordinates from the site linked by @jling.

Both you and and the OP show, easting is too far east for Belfast. From the grid squares on the wiki page, you can see that Belfast is not near as far east as 335812, and 135812 would appear closer to its location. But the poster above did the calculation to show that 148375 is the correct value, so the my simple typo hypothesis is incorrect.

1 Like

Thank you for all your answers.

It seems my original question is based on a mistaken assumption.

The coordinates I obtained from Google are correct, but they are not on the British National Grid.

It seems that the ONS publishes data for the whole of the UK (including Northern Ireland) using British National Grid coordinates. On the other hand, NIRSA, the devolved statistics agency for Northern Ireland, uses the Irish grid, which covers the whole of Ireland. The two grids are different.

If I make a map of NI administrative boundaries using data from NISRA (e.g. this one), I can plot a point representing these coordinates:

OS Eastings: 335812
OS Northings: 375965

However, if I use a map of UK administrative boundaries using data from ONS (e.g. this one), I must use the coordinates given by the BritishNationalGrid conversion from Google’s Lat, Lon:

Latitude: 54.6136 / 54°36'49"N
Longitude: -5.8986 / 5°53'54"W
BNGPoint = (148376.87358622215, 531260.3815596306)

The easting and northing I found in my search are Irish coordinates and not, as I had mistakenly assumed, British coordinates.

My next challenge is to find a way to convert between the two coordinate systems, ideally within GMT.jl…

1 Like

As you discovered, @TimG, Google was giving you the Irish Grid coordinates. BritishNationalGrid.jl only does OSGB NG coordinates (and does them correctly), which explains the apparent discrepancy.

The Irish Grid is described by code EPSG:29901, so if you wanted to convert from BNG to ING with Proj.jl (which BritishNationalGrid.jl uses anyway), you could do this:

julia> import Proj

julia> ing_from_bng = Proj.Transformation("EPSG:27700", "EPSG:29901", always_xy=true)
Transformation unknown
    source: OSGB36 / British National Grid
    target: OSNI 1952 / Irish National Grid
    direction: forward

julia> ing_from_bng(148376.87358622215, 531260.3815596306)
(335811.9954414863, 375965.6198268878)

To do the transformation the other way, just reverse the EPSG codes.

Note, however, that this will not be accurate to more than a few m because the high-accuracy grid of corrections used in transforming to/from BNG is only valid over part of the island of Ireland.

As an adjunct, I recently upgraded BritishNationalGrid.jl as it is something of a septuagenarian of a package that used to rely on Proj4.jl. I took the opportunity to use a recent Proj.jl (and therefore proj), and now transforming to/from BNG coordinates is much easier.

However, BritishNationalGrid.jl does do one thing for you—it bundles an artifact containing the grid file used in the BNG ↔︎ ETRS (European) ↔︎ WGS84 conversion which is not included in a normal Proj install. This makes transformations quicker and does not require an internet connection, which otherwise is necessary. (I found this out from this issue.)


To note, the BGS converter does a simpler conversion which will differ from the latest conversion (as done by Proj with the correct EPSG codes) by up to a few m. BritishNationalGrid.jl used also to use this method, but no longer does and now BritishNationalGrid.jl will agree with the OSGB’s webapps as mentioned above.

1 Like

This is super helpful, @anowacki. Thank you.

Just to be sure, my understanding is that EPSG:29901 only covers Northern Ireland but EPSG:29903 covers the whole island of Ireland. Is this right?

Also, when you say

the high-accuracy grid of corrections used in transforming to/from BNG is only valid over part of the island of Ireland

does this mean it is accurate for Northern Ireland (and accuracy diminishes elsewhere in Ireland), or is the region of high accuracy elsewhere?

I’m curious with this. Does it mean that it (downloads?) uses a grid shift for this operation?
The GMT.jl functions also use proj (the wrap GDAL funs that wrap PROJ) and I get a slight different result, whose difference could be explained by that (I’m not using grid shifts for this).

julia> xx = xy2lonlat([148376.87358622215 531260.3815596306], s_srs=27700, t_srs=29901)
1×2 Matrix{Float64}:
 3.35811e5  3.75964e5

julia> xx[1],xx[2]
(335810.5530613085, 375964.3863011688)

I should say that I’m not a geodesy expert, and so at this point my knowledge stops. As far as I know, yes, EPSG:29903 is for all Ireland using the Irish Grid.

Some information about how the calculations are done now versus pre-2016 is in this is in this article and the OSGB’s developer notes which accompanied the release of the new grids in 2016.

The article I linked to above shows the region where the OSTN15 grid which does the transformation is valid; it basically stops at the western tip of Northern Ireland. Away from that, (i.e., in Ireland), a polynomial mapping is done instead. This really is at the limit of my understanding, but I believe that if that is done, then you are back to the ~3 m accuracy of the old approach. So I think the answer is ‘yes and no’.

I will finish off by saying that there are other members of the community who are far more knowledgable about this topic, so I invite them to chime in if need be.

Yes—as a non-expert I only realised that newer versions of Proj (and indeed the OSGB) were using a grid-based approach when my conversions stopped working with the error hgridshift: could not find required grid(s), and I found this Proj.jl issue. It could well be the cause of the difference you see.

1 Like