Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

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)
    {
        latitude = toRad(latitude);
        longitude = toRad(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 lat0 = toRad(49);
        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);
    }

If you could help that would be great.

share|improve this question
    
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. –  mkennedy Jun 29 '11 at 15:55
    
@mkennedy - fair enough actually. –  Vidar Jun 29 '11 at 17:59
1  
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. –  mkennedy Jun 30 '11 at 0:49

3 Answers 3

up vote 0 down vote accepted

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.

share|improve this answer

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.

share|improve this answer

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

share|improve this answer
    
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. –  Vidar Jun 29 '11 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 –  geographika Jun 29 '11 at 12:51

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.