// converts lat and lon (OSGB36) to OS 6 figure northing and easting private void Initialise(LatLonCoord coord) { // Debug.Assert(coord.Elipsoid == CoordSystem.OSGB36); double lat = coord.Latitude; double lon = coord.Longitude; double phi = Math.DegToRad(lat); // convert latitude to radians double lam = Math.DegToRad(lon); // convert longitude to radians double a = 6377563.396; // OSGB semi-major axis double b = 6356256.91; // OSGB semi-minor axis double e0 = 400000; // easting of false origin double n0 = -100000; // northing of false origin double f0 = 0.9996012717; // OSGB scale factor on central meridian double e2 = 0.0066705397616; // OSGB eccentricity squared double lam0 = -0.034906585039886591; // OSGB false east double phi0 = 0.85521133347722145; // OSGB false north double af0 = a * f0; double bf0 = b * f0; // easting double slat2 = Math.Sin(phi) * Math.Sin(phi); double nu = af0 / (Math.Sqrt(1 - (e2 * (slat2)))); double rho = (nu * (1 - e2)) / (1 - (e2 * slat2)); double eta2 = (nu / rho) - 1; double p = lam - lam0; double IV = nu * Math.Cos(phi); double clat3 = Math.Pow(Math.Cos(phi), 3); double tlat2 = Math.Tan(phi) * Math.Tan(phi); double V = (nu / 6) * clat3 * ((nu / rho) - tlat2); double clat5 = Math.Pow(Math.Cos(phi), 5); double tlat4 = Math.Pow(Math.Tan(phi), 4); double VI = (nu / 120) * clat5 * ((5 - (18 * tlat2)) + tlat4 + (14 * eta2) - (58 * tlat2 * eta2)); double east = e0 + (p * IV) + (Math.Pow(p, 3) * V) + (Math.Pow(p, 5) * VI); // northing double n = (af0 - bf0) / (af0 + bf0); double M = Marc(bf0, n, phi0, phi); double I = M + (n0); double II = (nu / 2) * Math.Sin(phi) * Math.Cos(phi); double III = ((nu / 24) * Math.Sin(phi) * Math.Pow(Math.Cos(phi), 3)) * (5 - Math.Pow(Math.Tan(phi), 2) + (9 * eta2)); double IIIA = ((nu / 720) * Math.Sin(phi) * clat5) * (61 - (58 * tlat2) + tlat4); double north = I + ((p * p) * II) + (Math.Pow(p, 4) * III) + (Math.Pow(p, 6) * IIIA); // make whole number values east = Math.Round(east); // round to whole number north = Math.Round(north); // round to whole number // convert to nat grid ref Eastings = east; Northings = north; }
internal NmeaFixMessage( DateTime time, LatLonCoord coords, double altitude, // Above sea level FixQuality quality, int sateliteCount) { this.Time = time; this.Coords = coords; this.Altitude = altitude; this.Quality = quality; this.SateliteCount = sateliteCount; }
public OSGBGridRef(LatLonCoord coord) { // Debug.Assert(coord.Elipsoid == CoordSystem.OSGB36); Initialise(coord); }
// Processes WGS84 lat and lon in decimal form with S and W as -ve private static LatLonCoord WGS84ToOSGB36(LatLonCoord coord) { // Debug.Assert(coord.Elipsoid == CoordSystem.WGS84); double WGlat = coord.Latitude; double WGlon = coord.Longitude; double height = coord.Altitude; //first off convert to radians double radWGlat = Math.DegToRad(WGlat); double radWGlon = Math.DegToRad(WGlon); /* these calculations were derived from the work of * Roger Muggleton (http://www.carabus.co.uk/) */ /* quoting Roger Muggleton :- * There are many ways to convert data from one system to another, the most accurate * being the most complex! For this example I shall use a 7 parameter Helmert * transformation. * The process is in three parts: * (1) Convert latitude and longitude to Cartesian coordinates (these also include height * data, and have three parameters, X, Y and Z). * (2) Transform to the new system by applying the 7 parameters and using a little maths. * (3) Convert back to latitude and longitude. * For the example we shall transform a GRS80 location to Airy, e.g. a GPS reading to * the Airy spheroid. * The following code converts latitude and longitude to Cartesian coordinates. The * input parameters are: WGS84 latitude and longitude, axis is the GRS80/WGS84 major * axis in metres, ecc is the eccentricity, and height is the height above the * ellipsoid. * v = axis / (Math.sqrt (1 - ecc * (Math.Pow (Math.sin(lat), 2)))); * x = (v + height) * Math.cos(lat) * Math.cos(lon); * y = (v + height) * Math.cos(lat) * Math.sin(lon); * z = ((1 - ecc) * v + height) * Math.sin(lat); * The transformation requires the 7 parameters: xp, yp and zp correct the coordinate * origin, xr, yr and zr correct the orientation of the axes, and sf deals with the * changing scale factors. */ //these are the values for WGS86(GRS80) to OSGB36(Airy) double h = height; // height above datum (from GPS GGA sentence) const double a = 6378137; // WGS84_AXIS const double e = 0.00669438037928458; // WGS84_ECCENTRIC const double a2 = 6377563.396; //OSGB_AXIS const double e2 = 0.0066705397616; // OSGB_ECCENTRIC const double xp = -446.448; const double yp = 125.157; const double zp = -542.06; const double xr = -0.1502; const double yr = -0.247; const double zr = -0.8421; const double s = 20.4894; // convert to cartesian; lat, lon are radians double sf = s * 0.000001; double v = a / (Math.Sqrt(1 - (e * (Math.Sin(radWGlat) * Math.Sin(radWGlat))))); double x = (v + h) * Math.Cos(radWGlat) * Math.Cos(radWGlon); double y = (v + h) * Math.Cos(radWGlat) * Math.Sin(radWGlon); double z = ((1 - e) * v + h) * Math.Sin(radWGlat); // transform cartesian double xrot = Math.DegToRad(xr / 3600); double yrot = Math.DegToRad(yr / 3600); double zrot = Math.DegToRad(zr / 3600); double hx = x + (x * sf) - (y * zrot) + (z * yrot) + xp; double hy = (x * zrot) + y + (y * sf) - (z * xrot) + yp; double hz = (-1 * x * yrot) + (y * xrot) + z + (z * sf) + zp; // Convert back to lat, lon double newLon = Math.Atan(hy / hx); double p = Math.Sqrt((hx * hx) + (hy * hy)); double newLat = Math.Atan(hz / (p * (1 - e2))); v = a2 / (Math.Sqrt(1 - e2 * (Math.Sin(newLat) * Math.Sin(newLat)))); double errvalue = 1.0; double lat0 = 0; while (errvalue > 0.001) { lat0 = Math.Atan((hz + e2 * v * Math.Sin(newLat)) / p); errvalue = Math.Abs(lat0 - newLat); newLat = lat0; } //convert back to degrees newLat = Math.RadToDeg(newLat); newLon = Math.RadToDeg(newLon); return new LatLonCoord(newLat, newLon, height, CoordSystem.OSGB36); }
public bool IsEqualTo(LatLonCoord coord) { return (coord != null) && (this.Latitude == coord.Latitude) && (this.Longitude == coord.Longitude) && (this.Altitude == coord.Altitude) && (this.Elipsoid == coord.Elipsoid); }
public static LatLonCoord Convert( LatLonCoord sourceCoord, CoordSystem targetElipsoid) { if ((sourceCoord.Elipsoid == CoordSystem.WGS84) && (targetElipsoid == CoordSystem.OSGB36)) { return WGS84ToOSGB36(sourceCoord); } throw new NotImplementedException("Conversion not supported");; }
// 5325.5117,N,00213.9296,W = +53° 25.5117', -02° 13.9296' private static LatLonCoord DecodePositionelement( string latitudeDeg, string latitudeMin, string longitudeDeg, string longitudeMin, string altitudeAboveMeanSeaLevel, string heightOfMeanSeaLevelAboveElipsoid) { int latDegrees = (int)(double)double.Parse(latitudeDeg.Substring(0, 2)); double latMinutes = (double)double.Parse(latitudeDeg.Substring(2)); if (latitudeMin == "S") // TODO: Better validation needed. latDegrees = -latDegrees; int lonDegrees = (int)(double)double.Parse(longitudeDeg.Substring(0, 3)); double lonMinutes = (double)double.Parse(longitudeDeg.Substring(3)); if (longitudeMin == "W") // TODO: Better validation needed. lonDegrees = -lonDegrees; double altitudeAboveElipsoid = (double)double.Parse(altitudeAboveMeanSeaLevel) + (double)double.Parse(heightOfMeanSeaLevelAboveElipsoid); LatLonCoord ll = new LatLonCoord(latDegrees, latMinutes, lonDegrees, lonMinutes, altitudeAboveElipsoid, CoordSystem.WGS84); return ll; }