# Converting WGS84 coordinates to British National Grid Easting/Northings using C#?

I'm looking for some code, ideally C#, to convert a WGS84 coordinate to British National Grid Easting and Northings.

Does anyone have this to hand?

I tried converting the Javascript code here:

http://www.movable-type.co.uk/scripts/latlong-gridref.html

to C# - but the code doesn't seem to give the correct coordinates for easting and northings - see below:

``````public void LatLongToEastNorth(double latitude, double longitude)
{

double a = 6377563.396, b = 6356256.910; // Airy 1830 major & minor semi-axes
double F0 = 0.9996012717; // NatGrid scale factor on central meridian
double lon0 = toRad(-2); // NatGrid true origin
double N0 = -100000, E0 = 400000; // northing & easting of true origin, metres
double e2 = 1 - (b * b) / (a * a); // eccentricity squared
double n = (a - b) / (a + b), n2 = n * n, n3 = n * n * n;

double cosLat = Math.Cos(latitude), sinLat = Math.Sin(latitude);
double nu = a * F0 / Math.Sqrt(1 - e2 * sinLat * sinLat) ; // transverse radius of curvature
double rho = a * F0 * (1 - e2) / Math.Pow(1 - e2 * sinLat * sinLat, 1.5); // meridional radius of curvature

double eta2 = nu / rho - 1;

double Ma = (1 + n + (5 / 4) * n2 + (5 / 4) * n3) * (latitude - lat0);
double Mb = (3 * n + 3 * n * n + (21 / 8) * n3) * Math.Sin(latitude - lat0) * Math.Cos(latitude + lat0);
double Mc = ((15 / 8) * n2 + (15 / 8) * n3) * Math.Sin(2 * (latitude - lat0)) * Math.Cos(2 * (latitude + lat0));
double Md = (35 / 24) * n3 * Math.Sin(3 * (latitude - lat0)) * Math.Cos(3 * (latitude + lat0));
double M = b * F0 * (Ma - Mb + Mc - Md); // meridional arc

double cos3lat = cosLat * cosLat * cosLat;
double cos5lat = cos3lat * cosLat * cosLat;
double tan2lat = Math.Tan(latitude) * Math.Tan(latitude);
double tan4lat = tan2lat * tan2lat;

double I = M + N0;
double II = (nu / 2) * sinLat * cosLat;
double III = (nu / 24) * sinLat * cos3lat * (5 - tan2lat + 9 * eta2);
double IIIA = (nu / 720) * sinLat * cos5lat * (61 - 58 * tan2lat + tan4lat);
double IV = nu * cosLat;
double V = (nu / 6) * cos3lat * (nu / rho - tan2lat);
double VI = (nu / 120) * cos5lat * (5 - 18 * tan2lat + tan4lat + 14 * eta2 - 58 * tan2lat * eta2);

double dLon = longitude - lon0;
double dLon2 = dLon * dLon, dLon3 = dLon2 * dLon, dLon4 = dLon3 * dLon, dLon5 = dLon4 * dLon, dLon6 = dLon5 * dLon;

double N = I + II * dLon2 + III * dLon4 + IIIA * dLon6;
double E = E0 + IV * dLon + V * dLon3 + VI * dLon5;

//return gridrefNumToLet(E, N, 8);
}
``````
• It would be very useful if you (and everyone else) posted a sample test point when you say you're not getting the correct coordinates after a projection or datum transformation. That makes it easy for someone to try to reproduce the problem and lead to a better solution more quickly. Jun 29, 2011 at 15:55
• @mkennedy - fair enough actually. Jun 29, 2011 at 17:59
• The function assumes that latitude, longitude are already on OSGB36 (Airy 1830), not WGS84. Has a datum transformation been done already? That would definitely affect the results. Jun 30, 2011 at 0:49

You could try the .NET library Proj.Net. See the Loading a projection by Spatial Reference ID page for how to add in the GB National Grid.

Example code from this forum post:

``````CoordinateSystemFactory c = new CoordinateSystemFactory();
ICoordinateSystem target = c.CreateFromWkt("PROJCS[\"OSGB 1936 / British National Grid\",GEOGCS[\"OSGB 1936\",DATUM[\"OSGB_1936\",SPHEROID[\"Airy 1830\",6377563.396,299.3249646,AUTHORITY[\"EPSG\",\"7001\"]],AUTHORITY[\"EPSG\",\"6277\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4277\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",49],PARAMETER[\"central_meridian\",-2],PARAMETER[\"scale_factor\",0.9996012717],PARAMETER[\"false_easting\",400000],PARAMETER[\"false_northing\",-100000],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AUTHORITY[\"EPSG\",\"27700\"]]");
ICoordinateSystem source = c.CreateFromWkt("GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.0174532925199433]]");

CoordinateTransformationFactory trf = new CoordinateTransformationFactory();
ICoordinateTransformation tr = trf.CreateFromCoordinateSystems(source, target);

double[] point = new double[] {-4.0, 55.6};
double[] result = tr.MathTransform.Transform(point);

Console.WriteLine(result);
``````

Alternatively the Ordnance Survey have a downloadable tool if you register at http://gps.ordnancesurvey.co.uk/convert.asp

• seems good, but I also wanted to understand what was going on in code and then hopefully transplant it to Objective C. I suspect I won't be able to do this with these thrid party dlls. Jun 29, 2011 at 12:44
• @Vidar Proj.Net is OpenSource so you can download/view/compile. If you are using C then why not look at the source for the original Proj4 trac.osgeo.org/proj/browser Jun 29, 2011 at 12:51

The proj.4 library might be of assistance, but it is written in C, rather than C#. There is a C# wrapper for it here.

I was being a bit dumb actually - I must have put through the wrong long and lat values - the code does actually work. But you may want to consider what mkennedy put about datums WGS84 and the Airy 1830 - this will have some effect on the accuracy of your final easting and northing readings - myabe 60-100m out, so it all depends on how accurate you want it to be.