GPS- Deriving British Ordnance Survey Grid Reference from NMEA data

Part 2 - create NMEA2OSG class

The NMEA2OSG class will work in a similar way to the NMEAinterpreter class.
Latitude, longitude and ellipsoidal height will pe passed to the NMEA2OSG class which will then generate events producing the transformed data.

At this point I have to give thanks and credit to Roger Muggleton, the creator of the pages which detailed the necessary calculations. - (  and who kindly gave me permission to make use of his work.

Thanks are also due to Nick Daniels ( for his invaluable advice on C# coding.

This is quite involved maths, and I am not going to try to explain all of it. It is the same as that used in the Ordnance Survey document A Guide to Coordinate Systems in Great Britain and converts latitude and longitude to a Transverse Mercator projection.

The NMEAinterpreter class produces latitude and longitude in the following form:-

52°09.1461"N         002°33.3717"W

In order to work mathematically with the latitude and longitude, they need to be converted into decimal values. So the first function of our class is to parse latitude and longitude and then pass them, along with ellipsoid height, to the transformation function.

We want to convert the minutes to degrees (divide by 60) and take account of the fact that Southerly and Westerly values are considered to be negative.

    public double deciLat;
    public double deciLon;

    public bool ParseNMEA(string Nlat, string Nlon, double height)     {      //grab the bit up to the °
     deciLat = Convert.ToDouble(Nlat.Substring(0, Nlat.IndexOf("°")));      deciLon = Convert.ToDouble(Nlon.Substring(0, Nlon.IndexOf("°")));      //remove that bit from the string now we've used it and the ° symbol      Nlat = Nlat.Substring(Nlat.IndexOf("°") + 1);      Nlon = Nlon.Substring(Nlon.IndexOf("°") + 1);      //grab the bit up to the ", divide it by 60 to convert to degrees
     //and add it to our double value
     deciLat += (Convert.ToDouble(Nlat.Substring(0, Nlat.IndexOf("\""))))/60;      deciLon += (Convert.ToDouble(Nlon.Substring(0, Nlat.IndexOf("\""))))/60;      //remove that part of the string now and just leave the compass direction
     Nlat = Nlat.Substring(Nlat.IndexOf("\"") + 1);      Nlon = Nlon.Substring(Nlon.IndexOf("\"") + 1);     // check for negative directions      if (Nlat == "S") deciLat = 0 - deciLat;      if (Nlon == "W") deciLon = 0 - deciLon;      //now we can transform them
     return Transform(deciLat, deciLon, height);     }

Now that we have our decimal values, we can transform them - see the next page.

You might also like...



Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Programs must be written for people to read, and only incidentally for machines to execute.”