internal static PolarGeoCoordinate Convert(PolarGeoCoordinate source, CoordinateSystems destination) { PolarGeoCoordinate retVal; if (source.CoordinateSystem == CoordinateSystems.OSGB36 && destination == CoordinateSystems.WGS84) { retVal = Convert( source, EllipseParameter.GetEllipseParameters(EllipseParameter.Ellipses.Airy1830), HelmertTransform.GetTransform(HelmertTransform.HelmertTransformType.OSGB36toWGS84), EllipseParameter.GetEllipseParameters(EllipseParameter.Ellipses.WGS84)); } else if (source.CoordinateSystem == CoordinateSystems.WGS84 && destination == CoordinateSystems.OSGB36) { retVal = Convert( source, EllipseParameter.GetEllipseParameters(EllipseParameter.Ellipses.WGS84), HelmertTransform.GetTransform(HelmertTransform.HelmertTransformType.WGS84toOSGB36), EllipseParameter.GetEllipseParameters(EllipseParameter.Ellipses.Airy1830)); } else { throw new NotImplementedException("Requested source and destination are not currently supported"); } retVal.AlignSigFigs(source); return retVal; }
public static PolarGeoCoordinate ChangeUnits(PolarGeoCoordinate original, AngleUnit changeTo) { if (original.Units == changeTo) { return new PolarGeoCoordinate( original.Lat, original.Lon, original.Height, original.Units, original.CoordinateSystem); } if (original.Units == AngleUnit.Degrees && changeTo == AngleUnit.Radians) { return new PolarGeoCoordinate( Converter.DegToRad(original.Lat), Converter.DegToRad(original.Lon), original.Height, AngleUnit.Radians, original.CoordinateSystem); } if (original.Units == AngleUnit.Radians && changeTo == AngleUnit.Degrees) { return new PolarGeoCoordinate( Converter.RadToDeg(original.Lat), Converter.RadToDeg(original.Lon), original.Height, AngleUnit.Degrees, original.CoordinateSystem); } throw new NotImplementedException("Invalid conversion requested"); }
public static GridReference ChangeToGridReference(PolarGeoCoordinate original) { PolarGeoCoordinate convertible = original.CoordinateSystem != CoordinateSystems.OSGB36 ? ChangeCoordinateSystem(original, CoordinateSystems.OSGB36) : original; return Converter.GeodesicToGridReference(convertible); }
private static PolarGeoCoordinate Convert( PolarGeoCoordinate originalCoord, EllipseParameter e1, HelmertTransform t, EllipseParameter e2) { // -- convert polar to cartesian coordinates (using ellipse 1) PolarGeoCoordinate p1 = PolarGeoCoordinate.ChangeUnits(originalCoord, AngleUnit.Radians); double sinPhi = Math.Sin(p1.Lat); double cosPhi = Math.Cos(p1.Lat); double sinLambda = Math.Sin(p1.Lon); double cosLambda = Math.Cos(p1.Lon); double H = p1.Height; double eSq = (Math.Pow(e1.SemimajorAxis, 2) - Math.Pow(e1.SemiMinorAxis, 2)) / Math.Pow(e1.SemimajorAxis, 2); double nu = e1.SemimajorAxis / Math.Sqrt(1 - eSq * sinPhi * sinPhi); double x1 = (nu + H) * cosPhi * cosLambda; double y1 = (nu + H) * cosPhi * sinLambda; double z1 = ((1 - eSq) * nu + H) * sinPhi; // -- apply helmert transform using appropriate params double tx = t.tx, ty = t.ty, tz = t.tz; double rx = t.rx / 3600 * Math.PI / 180; // normalise seconds to radians double ry = t.ry / 3600 * Math.PI / 180; double rz = t.rz / 3600 * Math.PI / 180; double s1 = t.s / 1e6 + 1; // normalise ppm to (s+1) // apply transform double x2 = tx + x1 * s1 - y1 * rz + z1 * ry; double y2 = ty + x1 * rz + y1 * s1 - z1 * rx; double z2 = tz - x1 * ry + y1 * rx + z1 * s1; // -- convert cartesian to polar coordinates (using ellipse 2) double a = e2.SemimajorAxis; double precision = 4 / e2.SemimajorAxis; // results accurate to around 4 metres eSq = (Math.Pow(e2.SemimajorAxis, 2) - Math.Pow(e2.SemiMinorAxis, 2)) / Math.Pow(e2.SemimajorAxis, 2); double p = Math.Sqrt(x2 * x2 + y2 * y2); double phi = Math.Atan2(z2, p * (1 - eSq)), phiP = 2 * Math.PI; while (Math.Abs(phi - phiP) > precision) { nu = a / Math.Sqrt(1 - eSq * Math.Sin(phi) * Math.Sin(phi)); phiP = phi; phi = Math.Atan2(z2 + eSq * nu * Math.Sin(phi), p); } double lambda = Math.Atan2(y2, x2); H = p / Math.Cos(phi) - nu; return(new PolarGeoCoordinate( RadToDeg(phi), RadToDeg(lambda), H, AngleUnit.Degrees, t.outputCoordinateSystem)); }
internal static PolarGeoCoordinate GridReferenceToGeodesic(GridReference g) { double lat = _NatGridTrueOrigin.Lat; double M = 0; do { lat = (g.Northing - _NatNETrueOrigin.Northing - M) / (_Airy1830.SemimajorAxis * _NatGridScaleFactor) + lat; double Ma = (1 + _n + (5d / 4d) * _n2 + (5d / 4d) * _n3) * (lat - _NatGridTrueOrigin.Lat); double Mb = (3 * _n + 3 * _n * _n + (21d / 8d) * _n3) * Math.Sin(lat - _NatGridTrueOrigin.Lat) * Math.Cos(lat + _NatGridTrueOrigin.Lat); double Mc = ((15d / 8d) * _n2 + (15d / 8d) * _n3) * Math.Sin(2 * (lat - _NatGridTrueOrigin.Lat)) * Math.Cos(2 * (lat + _NatGridTrueOrigin.Lat)); double Md = (35d / 24d) * _n3 * Math.Sin(3 * (lat - _NatGridTrueOrigin.Lat)) * Math.Cos(3 * (lat + _NatGridTrueOrigin.Lat)); M = _Airy1830.SemiMinorAxis * _NatGridScaleFactor * (Ma - Mb + Mc - Md); // meridional arc } while (g.Northing - _NatNETrueOrigin.Northing - M >= 0.00001); // ie until < 0.01mm double cosLat = Math.Cos(lat), sinLat = Math.Sin(lat); double nu = _Airy1830.SemimajorAxis * _NatGridScaleFactor / Math.Sqrt(1 - _e2 * sinLat * sinLat); // transverse radius of curvature double rho = _Airy1830.SemimajorAxis * _NatGridScaleFactor * (1 - _e2) / Math.Pow(1 - _e2 * sinLat * sinLat, 1.5); // meridional radius of curvature double eta2 = nu / rho - 1; double tanLat = Math.Tan(lat); double tan2lat = tanLat * tanLat, tan4lat = tan2lat * tan2lat, tan6lat = tan4lat * tan2lat; double secLat = 1 / cosLat; double nu3 = nu * nu * nu, nu5 = nu3 * nu * nu, nu7 = nu5 * nu * nu; double VII = tanLat / (2 * rho * nu); double VIII = tanLat / (24 * rho * nu3) * (5 + 3 * tan2lat + eta2 - 9 * tan2lat * eta2); double IX = tanLat / (720 * rho * nu5) * (61 + 90 * tan2lat + 45 * tan4lat); double X = secLat / nu; double XI = secLat / (6 * nu3) * (nu / rho + 2 * tan2lat); double XII = secLat / (120 * nu5) * (5 + 28 * tan2lat + 24 * tan4lat); double XIIA = secLat / (5040 * nu7) * (61 + 662 * tan2lat + 1320 * tan4lat + 720 * tan6lat); double dE = (g.Easting - _NatNETrueOrigin.Easting); double dE2 = dE * dE; double dE3 = dE2 * dE; double dE4 = dE2 * dE2; double dE5 = dE3 * dE2; double dE6 = dE4 * dE2; double dE7 = dE5 * dE2; lat = lat - VII * dE2 + VIII * dE4 - IX * dE6; double lon = _NatGridTrueOrigin.Lon + X * dE - XI * dE3 + XII * dE5 - XIIA * dE7; PolarGeoCoordinate retVal = new PolarGeoCoordinate(lat, lon, 0, AngleUnit.Radians, CoordinateSystems.OSGB36); retVal = PolarGeoCoordinate.ChangeUnits(retVal, AngleUnit.Degrees); retVal.SetSigFigs(7); return(retVal); }
public static GridReference ChangeToGridReference(PolarGeoCoordinate original) { PolarGeoCoordinate convertible; if (original.CoordinateSystem != CoordinateSystems.OSGB36) { convertible = ChangeCoordinateSystem(original, CoordinateSystems.OSGB36); } else { convertible = original; } return(Converter.GeodesicToGridReference(convertible)); }
internal static GridReference GeodesicToGridReference(PolarGeoCoordinate originalCoords) { PolarGeoCoordinate originalRads = PolarGeoCoordinate.ChangeUnits(originalCoords, AngleUnit.Radians); double cosLat = Math.Cos(originalRads.Lat); double sinLat = Math.Sin(originalRads.Lat); double nu = _Airy1830.SemimajorAxis * _NatGridScaleFactor / Math.Sqrt(1 - _e2 * sinLat * sinLat); // transverse radius of curvature double rho = _Airy1830.SemimajorAxis * _NatGridScaleFactor * (1 - _e2) / Math.Pow(1 - _e2 * sinLat * sinLat, 1.5); // meridional radius of curvature double eta2 = nu / rho - 1; double Ma = (1 + _n + (5d / 4d) * _n2 + (5d / 4d) * _n3) * (originalRads.Lat - _NatGridTrueOrigin.Lat); double Mb = (3 * _n + 3 * _n * _n + (21d / 8d) * _n3) * Math.Sin(originalRads.Lat - _NatGridTrueOrigin.Lat) * Math.Cos(originalRads.Lat + _NatGridTrueOrigin.Lat); double Mc = ((15d / 8d) * _n2 + (15d / 8d) * _n3) * Math.Sin(2 * (originalRads.Lat - _NatGridTrueOrigin.Lat)) * Math.Cos(2 * (originalRads.Lat + _NatGridTrueOrigin.Lat)); double Md = (35d / 24d) * _n3 * Math.Sin(3 * (originalRads.Lat - _NatGridTrueOrigin.Lat)) * Math.Cos(3 * (originalRads.Lat + _NatGridTrueOrigin.Lat)); double M = _Airy1830.SemiMinorAxis * _NatGridScaleFactor * (Ma - Mb + Mc - Md); // meridional arc double cos3lat = cosLat * cosLat * cosLat; double cos5lat = cos3lat * cosLat * cosLat; double tan2lat = Math.Tan(originalRads.Lat) * Math.Tan(originalRads.Lat); double tan4lat = tan2lat * tan2lat; double I = M + _NatNETrueOrigin.Northing; 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 = originalRads.Lon - _NatGridTrueOrigin.Lon; 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 = _NatNETrueOrigin.Easting + IV * dLon + V * dLon3 + VI * dLon5; return new GridReference((int)E, (int)N); }
internal static GridReference GeodesicToGridReference(PolarGeoCoordinate originalCoords) { PolarGeoCoordinate originalRads = PolarGeoCoordinate.ChangeUnits(originalCoords, AngleUnit.Radians); double cosLat = Math.Cos(originalRads.Lat); double sinLat = Math.Sin(originalRads.Lat); double nu = _Airy1830.SemimajorAxis * _NatGridScaleFactor / Math.Sqrt(1 - _e2 * sinLat * sinLat); // transverse radius of curvature double rho = _Airy1830.SemimajorAxis * _NatGridScaleFactor * (1 - _e2) / Math.Pow(1 - _e2 * sinLat * sinLat, 1.5); // meridional radius of curvature double eta2 = nu / rho - 1; double Ma = (1 + _n + (5d / 4d) * _n2 + (5d / 4d) * _n3) * (originalRads.Lat - _NatGridTrueOrigin.Lat); double Mb = (3 * _n + 3 * _n * _n + (21d / 8d) * _n3) * Math.Sin(originalRads.Lat - _NatGridTrueOrigin.Lat) * Math.Cos(originalRads.Lat + _NatGridTrueOrigin.Lat); double Mc = ((15d / 8d) * _n2 + (15d / 8d) * _n3) * Math.Sin(2 * (originalRads.Lat - _NatGridTrueOrigin.Lat)) * Math.Cos(2 * (originalRads.Lat + _NatGridTrueOrigin.Lat)); double Md = (35d / 24d) * _n3 * Math.Sin(3 * (originalRads.Lat - _NatGridTrueOrigin.Lat)) * Math.Cos(3 * (originalRads.Lat + _NatGridTrueOrigin.Lat)); double M = _Airy1830.SemiMinorAxis * _NatGridScaleFactor * (Ma - Mb + Mc - Md); // meridional arc double cos3lat = cosLat * cosLat * cosLat; double cos5lat = cos3lat * cosLat * cosLat; double tan2lat = Math.Tan(originalRads.Lat) * Math.Tan(originalRads.Lat); double tan4lat = tan2lat * tan2lat; double I = M + _NatNETrueOrigin.Northing; 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 = originalRads.Lon - _NatGridTrueOrigin.Lon; 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 = _NatNETrueOrigin.Easting + IV * dLon + V * dLon3 + VI * dLon5; return(new GridReference((int)E, (int)N)); }
internal static PolarGeoCoordinate ReduceSigFigsBy1(PolarGeoCoordinate source) { double Lat = Converter.SetSigFigs( source.Lat, Converter.GetSigFigs(source.Lat) - 1); double Lon = Converter.SetSigFigs( source.Lon, Converter.GetSigFigs(source.Lon) - 1); double Height = Converter.SetSigFigs( source.Height, Converter.GetSigFigs(source.Height) - 1); return(new PolarGeoCoordinate(Lat, Lon, Height, source.Units, source.CoordinateSystem)); }
internal void AlignSigFigs(PolarGeoCoordinate source) { int SigFigsSrc = Converter.GetSigFigs(source.Lat); int SigFigsDest = Converter.GetSigFigs(this.Lat); this.Lat = Converter.SetSigFigs(this.Lat, SigFigsDest < SigFigsSrc ? SigFigsDest : SigFigsSrc); SigFigsSrc = Converter.GetSigFigs(source.Lon); SigFigsDest = Converter.GetSigFigs(this.Lon); this.Lon = Converter.SetSigFigs(this.Lon, SigFigsDest < SigFigsSrc ? SigFigsDest : SigFigsSrc); SigFigsSrc = Converter.GetSigFigs(source.Height); SigFigsDest = Converter.GetSigFigs(this.Height); this.Height = Converter.SetSigFigs(this.Height, SigFigsDest < SigFigsSrc ? SigFigsDest : SigFigsSrc); }
public bool IsTheSameAs(PolarGeoCoordinate compareTo) { if ( compareTo.CoordinateSystem != this.CoordinateSystem || compareTo.Height != this.Height || compareTo.Lat != this.Lat || compareTo.Lon != this.Lon || compareTo.Units != this.Units ) { return(false); } else { return(true); } }
// overload of IsTheSameAs to ignore rounding errors on final digit and align the sigfigs on both coords public bool IsTheSameAs(PolarGeoCoordinate compareTo, bool ignoreFinalDigit, bool alignSigFigs) { if (alignSigFigs) { this.AlignSigFigs(compareTo); } if (ignoreFinalDigit) { compareTo = ReduceSigFigsBy1(compareTo); PolarGeoCoordinate comparer = ReduceSigFigsBy1(this); bool retVal = comparer.IsTheSameAs(compareTo); return(retVal); } return(this.IsTheSameAs(compareTo)); }
public void TestDegreesToRadians() { PolarGeoCoordinate deg = new PolarGeoCoordinate(180, 180, 0, AngleUnit.Degrees, CoordinateSystems.OSGB36); PolarGeoCoordinate rad = new PolarGeoCoordinate(Math.PI, Math.PI, 0, AngleUnit.Radians, CoordinateSystems.OSGB36); Assert.IsTrue(rad.IsTheSameAs(PolarGeoCoordinate.ChangeUnits(deg, AngleUnit.Radians))); }
// overload of IsTheSameAs to ignore rounding errors on final digit and align the sigfigs on both coords public bool IsTheSameAs(PolarGeoCoordinate compareTo, bool ignoreFinalDigit, bool alignSigFigs) { if (alignSigFigs) { this.AlignSigFigs(compareTo); } if (ignoreFinalDigit) { compareTo = ReduceSigFigsBy1(compareTo); PolarGeoCoordinate comparer = ReduceSigFigsBy1(this); bool retVal = comparer.IsTheSameAs(compareTo); return retVal; } return this.IsTheSameAs(compareTo); }
public static PolarGeoCoordinate ChangeCoordinateSystem( PolarGeoCoordinate original, CoordinateSystems destination) { PolarGeoCoordinate retVal = Converter.Convert(original, destination); return retVal; }
internal static PolarGeoCoordinate ReduceSigFigsBy1(PolarGeoCoordinate source) { double Lat = Converter.SetSigFigs(source.Lat, Converter.GetSigFigs(source.Lat) - 1); double Lon = Converter.SetSigFigs(source.Lon, Converter.GetSigFigs(source.Lon) - 1); double Height = Converter.SetSigFigs(source.Height, Converter.GetSigFigs(source.Height) - 1); return new PolarGeoCoordinate(Lat, Lon, Height, source.Units, source.CoordinateSystem); }
public bool IsTheSameAs(PolarGeoCoordinate compareTo) { if (compareTo.CoordinateSystem != this.CoordinateSystem || compareTo.Height != this.Height || compareTo.Lat != this.Lat || compareTo.Lon != this.Lon || compareTo.Units != this.Units) { return false; } return true; }
public static PolarGeoCoordinate ChangeCoordinateSystem(PolarGeoCoordinate original, CoordinateSystems destination) { PolarGeoCoordinate retVal = Converter.Convert(original, destination); return(retVal); }
private static PolarGeoCoordinate Convert( PolarGeoCoordinate originalCoord, EllipseParameter e1, HelmertTransform t, EllipseParameter e2) { // -- convert polar to cartesian coordinates (using ellipse 1) PolarGeoCoordinate p1 = PolarGeoCoordinate.ChangeUnits(originalCoord, AngleUnit.Radians); double sinPhi = Math.Sin(p1.Lat); double cosPhi = Math.Cos(p1.Lat); double sinLambda = Math.Sin(p1.Lon); double cosLambda = Math.Cos(p1.Lon); double H = p1.Height; double eSq = (Math.Pow(e1.SemimajorAxis, 2) - Math.Pow(e1.SemiMinorAxis, 2)) / Math.Pow(e1.SemimajorAxis, 2); double nu = e1.SemimajorAxis / Math.Sqrt(1 - eSq * sinPhi * sinPhi); double x1 = (nu + H) * cosPhi * cosLambda; double y1 = (nu + H) * cosPhi * sinLambda; double z1 = ((1 - eSq) * nu + H) * sinPhi; // -- apply helmert transform using appropriate params double tx = t.tx, ty = t.ty, tz = t.tz; double rx = t.rx / 3600 * Math.PI / 180; // normalise seconds to radians double ry = t.ry / 3600 * Math.PI / 180; double rz = t.rz / 3600 * Math.PI / 180; double s1 = t.s / 1e6 + 1; // normalise ppm to (s+1) // apply transform double x2 = tx + x1 * s1 - y1 * rz + z1 * ry; double y2 = ty + x1 * rz + y1 * s1 - z1 * rx; double z2 = tz - x1 * ry + y1 * rx + z1 * s1; // -- convert cartesian to polar coordinates (using ellipse 2) double a = e2.SemimajorAxis; double precision = 4 / e2.SemimajorAxis; // results accurate to around 4 metres eSq = (Math.Pow(e2.SemimajorAxis, 2) - Math.Pow(e2.SemiMinorAxis, 2)) / Math.Pow(e2.SemimajorAxis, 2); double p = Math.Sqrt(x2 * x2 + y2 * y2); double phi = Math.Atan2(z2, p * (1 - eSq)), phiP = 2 * Math.PI; while (Math.Abs(phi - phiP) > precision) { nu = a / Math.Sqrt(1 - eSq * Math.Sin(phi) * Math.Sin(phi)); phiP = phi; phi = Math.Atan2(z2 + eSq * nu * Math.Sin(phi), p); } double lambda = Math.Atan2(y2, x2); H = p / Math.Cos(phi) - nu; return new PolarGeoCoordinate( RadToDeg(phi), RadToDeg(lambda), H, AngleUnit.Degrees, t.outputCoordinateSystem); }
internal static PolarGeoCoordinate GridReferenceToGeodesic(GridReference g) { double lat = _NatGridTrueOrigin.Lat; double M = 0; do { lat = (g.Northing - _NatNETrueOrigin.Northing - M) / (_Airy1830.SemimajorAxis * _NatGridScaleFactor) + lat; double Ma = (1 + _n + (5d / 4d) * _n2 + (5d / 4d) * _n3) * (lat - _NatGridTrueOrigin.Lat); double Mb = (3 * _n + 3 * _n * _n + (21d / 8d) * _n3) * Math.Sin(lat - _NatGridTrueOrigin.Lat) * Math.Cos(lat + _NatGridTrueOrigin.Lat); double Mc = ((15d / 8d) * _n2 + (15d / 8d) * _n3) * Math.Sin(2 * (lat - _NatGridTrueOrigin.Lat)) * Math.Cos(2 * (lat + _NatGridTrueOrigin.Lat)); double Md = (35d / 24d) * _n3 * Math.Sin(3 * (lat - _NatGridTrueOrigin.Lat)) * Math.Cos(3 * (lat + _NatGridTrueOrigin.Lat)); M = _Airy1830.SemiMinorAxis * _NatGridScaleFactor * (Ma - Mb + Mc - Md); // meridional arc } while (g.Northing - _NatNETrueOrigin.Northing - M >= 0.00001); // ie until < 0.01mm double cosLat = Math.Cos(lat), sinLat = Math.Sin(lat); double nu = _Airy1830.SemimajorAxis * _NatGridScaleFactor / Math.Sqrt(1 - _e2 * sinLat * sinLat); // transverse radius of curvature double rho = _Airy1830.SemimajorAxis * _NatGridScaleFactor * (1 - _e2) / Math.Pow(1 - _e2 * sinLat * sinLat, 1.5); // meridional radius of curvature double eta2 = nu / rho - 1; double tanLat = Math.Tan(lat); double tan2lat = tanLat * tanLat, tan4lat = tan2lat * tan2lat, tan6lat = tan4lat * tan2lat; double secLat = 1 / cosLat; double nu3 = nu * nu * nu, nu5 = nu3 * nu * nu, nu7 = nu5 * nu * nu; double VII = tanLat / (2 * rho * nu); double VIII = tanLat / (24 * rho * nu3) * (5 + 3 * tan2lat + eta2 - 9 * tan2lat * eta2); double IX = tanLat / (720 * rho * nu5) * (61 + 90 * tan2lat + 45 * tan4lat); double X = secLat / nu; double XI = secLat / (6 * nu3) * (nu / rho + 2 * tan2lat); double XII = secLat / (120 * nu5) * (5 + 28 * tan2lat + 24 * tan4lat); double XIIA = secLat / (5040 * nu7) * (61 + 662 * tan2lat + 1320 * tan4lat + 720 * tan6lat); double dE = g.Easting - _NatNETrueOrigin.Easting; double dE2 = dE * dE; double dE3 = dE2 * dE; double dE4 = dE2 * dE2; double dE5 = dE3 * dE2; double dE6 = dE4 * dE2; double dE7 = dE5 * dE2; lat = lat - VII * dE2 + VIII * dE4 - IX * dE6; double lon = _NatGridTrueOrigin.Lon + X * dE - XI * dE3 + XII * dE5 - XIIA * dE7; var retVal = new PolarGeoCoordinate(lat, lon, 0, AngleUnit.Radians, CoordinateSystems.OSGB36); retVal = PolarGeoCoordinate.ChangeUnits(retVal, AngleUnit.Degrees); retVal.SetSigFigs(7); return retVal; }