From aa0f376e55394f298e95a83e40976b2feb8013d9 Mon Sep 17 00:00:00 2001 From: Ieuan Walker Date: Fri, 12 Jul 2019 19:49:45 +0100 Subject: [PATCH] code cleaned using CodeMaid --- GeoUK.OSTN.Tests/ExtensionMethods.cs | 2 +- GeoUK.OSTN.Tests/Models/DataPoint.cs | 10 +- GeoUK.OSTN.Tests/Properties/AssemblyInfo.cs | 13 +- GeoUK.OSTN.Tests/TransformTests.cs | 13 +- GeoUK.OSTN/OstnDataRecord.cs | 10 +- GeoUK.OSTN/OstnVersionEnum.cs | 2 +- GeoUK.OSTN/ResourceManager.cs | 43 +- GeoUK.OSTN/Shifts.cs | 21 +- GeoUK.OSTN/Transform.cs | 221 ++++--- GeoUK/Convert.cs | 578 +++++++++--------- GeoUK/Coordinates/Cartesian.cs | 10 +- GeoUK/Coordinates/EastingNorthing.cs | 17 +- GeoUK/Coordinates/GeoidDatum.cs | 20 +- GeoUK/Coordinates/LatitudeLongitude.cs | 39 +- GeoUK/Coordinates/Osgb36.cs | 188 +++--- GeoUK/Ellipsoids/Airy1830.cs | 16 +- GeoUK/Ellipsoids/Airy1830Modified.cs | 16 +- GeoUK/Ellipsoids/Ellipsoid.cs | 15 +- GeoUK/Ellipsoids/Grs80.cs | 7 +- GeoUK/Ellipsoids/Hayford1909.cs | 33 +- GeoUK/Ellipsoids/Wgs84.cs | 7 +- GeoUK/MathEx.cs | 57 +- GeoUK/OSTN02Transform.cs | 186 +++--- GeoUK/Projections/BritishNationalGrid.cs | 6 +- GeoUK/Projections/IrishNationalGrid.cs | 14 +- GeoUK/Projections/Projection.cs | 14 +- .../UniversalTransverseMercator.cs | 15 +- GeoUK/ResourceManager.cs | 50 +- GeoUK/Transform.cs | 48 +- 29 files changed, 816 insertions(+), 855 deletions(-) diff --git a/GeoUK.OSTN.Tests/ExtensionMethods.cs b/GeoUK.OSTN.Tests/ExtensionMethods.cs index d859ee9..5b6c850 100644 --- a/GeoUK.OSTN.Tests/ExtensionMethods.cs +++ b/GeoUK.OSTN.Tests/ExtensionMethods.cs @@ -16,4 +16,4 @@ namespace GeoUK.OSTN.Tests return (Math.Abs(initialValue - value) < maximumDifferenceAllowed); } } -} +} \ No newline at end of file diff --git a/GeoUK.OSTN.Tests/Models/DataPoint.cs b/GeoUK.OSTN.Tests/Models/DataPoint.cs index 75dbc5a..f113d32 100644 --- a/GeoUK.OSTN.Tests/Models/DataPoint.cs +++ b/GeoUK.OSTN.Tests/Models/DataPoint.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace GeoUK.OSTN.Tests.Models +namespace GeoUK.OSTN.Tests.Models { public class DataPoint { @@ -13,4 +7,4 @@ namespace GeoUK.OSTN.Tests.Models public double Y { get; set; } public double Height { get; set; } } -} +} \ No newline at end of file diff --git a/GeoUK.OSTN.Tests/Properties/AssemblyInfo.cs b/GeoUK.OSTN.Tests/Properties/AssemblyInfo.cs index eb1740a..1cc6ec1 100644 --- a/GeoUK.OSTN.Tests/Properties/AssemblyInfo.cs +++ b/GeoUK.OSTN.Tests/Properties/AssemblyInfo.cs @@ -1,8 +1,7 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("GeoUK.OSTN.Tests")] @@ -14,8 +13,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] @@ -25,12 +24,12 @@ using System.Runtime.InteropServices; // Version information for an assembly consists of the following four values: // // Major Version -// Minor Version +// Minor Version // Build Number // Revision // -// You can specify all the values or you can default the Build and Revision Numbers +// You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/GeoUK.OSTN.Tests/TransformTests.cs b/GeoUK.OSTN.Tests/TransformTests.cs index 61b0ade..ed6de81 100644 --- a/GeoUK.OSTN.Tests/TransformTests.cs +++ b/GeoUK.OSTN.Tests/TransformTests.cs @@ -1,11 +1,8 @@ -using System; +using GeoUK.Coordinates; +using GeoUK.OSTN.Tests.Models; +using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using GeoUK.Coordinates; -using GeoUK.OSTN.Tests.Models; using Xunit; namespace GeoUK.OSTN.Tests @@ -87,7 +84,7 @@ namespace GeoUK.OSTN.Tests var inputData = new List(); var outputData = new Dictionary(); - + using (var inputFile = new StreamReader(inputFileName)) { string line; @@ -153,4 +150,4 @@ namespace GeoUK.OSTN.Tests } } } -} +} \ No newline at end of file diff --git a/GeoUK.OSTN/OstnDataRecord.cs b/GeoUK.OSTN/OstnDataRecord.cs index 04ea40a..0b434c3 100644 --- a/GeoUK.OSTN/OstnDataRecord.cs +++ b/GeoUK.OSTN/OstnDataRecord.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace GeoUK.OSTN +namespace GeoUK.OSTN { public class OstnDataRecord { @@ -16,4 +10,4 @@ namespace GeoUK.OSTN public double ETRS89_ODN_HeightShift { get; set; } public double Height_Datum_Flag { get; set; } } -} +} \ No newline at end of file diff --git a/GeoUK.OSTN/OstnVersionEnum.cs b/GeoUK.OSTN/OstnVersionEnum.cs index 0096534..4c4911f 100644 --- a/GeoUK.OSTN/OstnVersionEnum.cs +++ b/GeoUK.OSTN/OstnVersionEnum.cs @@ -5,4 +5,4 @@ OSTN02 = 1, OSTN15 = 2 } -} +} \ No newline at end of file diff --git a/GeoUK.OSTN/ResourceManager.cs b/GeoUK.OSTN/ResourceManager.cs index 76ecc32..c57d484 100644 --- a/GeoUK.OSTN/ResourceManager.cs +++ b/GeoUK.OSTN/ResourceManager.cs @@ -1,15 +1,15 @@ using System; -using System.IO; using System.Collections.Generic; -using System.Text; -using System.Reflection; +using System.IO; using System.Linq; +using System.Reflection; namespace GeoUK.OSTN { internal static class ResourceManager { private static Dictionary _ostn02Data; + public static Dictionary Ostn02Data { get @@ -21,6 +21,7 @@ namespace GeoUK.OSTN } private static Dictionary _ostn15Data; + public static Dictionary Ostn15Data { get @@ -37,7 +38,7 @@ namespace GeoUK.OSTN /// If not provided, it will load both OSTN02 and OSTN15 data. public static void LoadResources(OstnVersionEnum? ostnVersion = null) { - if(!ostnVersion.HasValue || ostnVersion.Value == OstnVersionEnum.OSTN02) + if (!ostnVersion.HasValue || ostnVersion.Value == OstnVersionEnum.OSTN02) _ostn02Data = RetrieveEmbeddedOSTN(OstnVersionEnum.OSTN02); if (!ostnVersion.HasValue || ostnVersion.Value == OstnVersionEnum.OSTN15) @@ -57,9 +58,11 @@ namespace GeoUK.OSTN case OstnVersionEnum.OSTN02: stream = ResourceManager.GetEmbeddedResourceStream(typeof(Transform).GetTypeInfo().Assembly, "OSTN02_OSGM02_GB.txt"); break; + case OstnVersionEnum.OSTN15: stream = ResourceManager.GetEmbeddedResourceStream(typeof(Transform).GetTypeInfo().Assembly, "OSTN15_OSGM15_DataFile.txt"); break; + default: throw new NotImplementedException(); } @@ -100,23 +103,25 @@ namespace GeoUK.OSTN /// The embedded resource stream. /// Assembly. /// Resource file name. - private static Stream GetEmbeddedResourceStream (Assembly assembly, string resourceFileName) - { - var resourceNames = assembly.GetManifestResourceNames (); + private static Stream GetEmbeddedResourceStream(Assembly assembly, string resourceFileName) + { + var resourceNames = assembly.GetManifestResourceNames(); - var resourcePaths = resourceNames - .Where (x => x.EndsWith (resourceFileName, StringComparison.CurrentCultureIgnoreCase)) - .ToArray (); + var resourcePaths = resourceNames + .Where(x => x.EndsWith(resourceFileName, StringComparison.CurrentCultureIgnoreCase)) + .ToArray(); - if (!resourcePaths.Any ()) { - throw new Exception (String.Format ("Resource ending with {0} not found.", resourceFileName)); - } + if (!resourcePaths.Any()) + { + throw new Exception(String.Format("Resource ending with {0} not found.", resourceFileName)); + } - if (resourcePaths.Count () > 1) { - throw new Exception (String.Format ("Multiple resources ending with {0} found: {1}{2}", resourceFileName, Environment.NewLine, String.Join (Environment.NewLine, resourcePaths))); - } + if (resourcePaths.Count() > 1) + { + throw new Exception(String.Format("Multiple resources ending with {0} found: {1}{2}", resourceFileName, Environment.NewLine, String.Join(Environment.NewLine, resourcePaths))); + } - return assembly.GetManifestResourceStream (resourcePaths.Single ()); - } + return assembly.GetManifestResourceStream(resourcePaths.Single()); + } } -} +} \ No newline at end of file diff --git a/GeoUK.OSTN/Shifts.cs b/GeoUK.OSTN/Shifts.cs index 65e989e..2a5f8d8 100644 --- a/GeoUK.OSTN/Shifts.cs +++ b/GeoUK.OSTN/Shifts.cs @@ -1,16 +1,13 @@ -using System; -using GeoUK.Coordinates; +using GeoUK.Coordinates; namespace GeoUK.OSTN { - public class Shifts - { - - public double Se { get; set; } - public double Sn { get; set; } - public double Sg { get; set; } - - public Osgb36GeoidDatum GeoidDatum { get; set; } - } -} + public class Shifts + { + public double Se { get; set; } + public double Sn { get; set; } + public double Sg { get; set; } + public Osgb36GeoidDatum GeoidDatum { get; set; } + } +} \ No newline at end of file diff --git a/GeoUK.OSTN/Transform.cs b/GeoUK.OSTN/Transform.cs index 9d5f500..a298c43 100644 --- a/GeoUK.OSTN/Transform.cs +++ b/GeoUK.OSTN/Transform.cs @@ -1,149 +1,143 @@ -using System; -using GeoUK.Coordinates; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; +using GeoUK.Coordinates; using GeoUK.Ellipsoids; using GeoUK.Projections; +using System; +using System.Collections.Generic; namespace GeoUK.OSTN { - public static class Transform - { - /// - /// Loads the OSTN data into memory. - /// - /// If not provided, it will load both OSTN02 and OSTN15 data. - public static void PreloadResources(OstnVersionEnum? ostnVersion = null) - { + public static class Transform + { + /// + /// Loads the OSTN data into memory. + /// + /// If not provided, it will load both OSTN02 and OSTN15 data. + public static void PreloadResources(OstnVersionEnum? ostnVersion = null) + { ResourceManager.LoadResources(ostnVersion); - } + } - /// - /// Performs an ETRS89 to OSGB36/ODN datum transformation. Accuracy is approximately 10 centimeters. + /// + /// Performs an ETRS89 to OSGB36/ODN datum transformation. Accuracy is approximately 10 centimeters. /// Whilst very accurate this method is much slower than the Helmert transformation. /// public static Osgb36 Etrs89ToOsgb(LatitudeLongitude coordinates, OstnVersionEnum ostnVersion = OstnVersionEnum.OSTN15) - { - var enCoordinates = Convert.ToEastingNorthing (new Grs80 (), new BritishNationalGrid (), coordinates); - return Etrs89ToOsgb (enCoordinates, coordinates.ElipsoidalHeight); - } + { + var enCoordinates = Convert.ToEastingNorthing(new Grs80(), new BritishNationalGrid(), coordinates); + return Etrs89ToOsgb(enCoordinates, coordinates.ElipsoidalHeight); + } - private static Osgb36 Etrs89ToOsgb(EastingNorthing coordinates, double ellipsoidHeight, OstnVersionEnum ostnVersion = OstnVersionEnum.OSTN15) - { - var shifts = GetShifts (coordinates, ellipsoidHeight, ostnVersion); + private static Osgb36 Etrs89ToOsgb(EastingNorthing coordinates, double ellipsoidHeight, OstnVersionEnum ostnVersion = OstnVersionEnum.OSTN15) + { + var shifts = GetShifts(coordinates, ellipsoidHeight, ostnVersion); - var easting = coordinates.Easting + shifts.Se; - var northing = coordinates.Northing + shifts.Sn; - var height = ellipsoidHeight - shifts.Sg; + var easting = coordinates.Easting + shifts.Se; + var northing = coordinates.Northing + shifts.Sn; + var height = ellipsoidHeight - shifts.Sg; - return new Osgb36(easting, northing, height, shifts.GeoidDatum); + return new Osgb36(easting, northing, height, shifts.GeoidDatum); + } - } + /// + /// Performs an OSGB36/ODN to ETRS89 datum transformation. Accuracy is approximately 10 centimeters. + /// Whilst very accurate this method is much slower than the Helmert transformation. + /// + public static LatitudeLongitude OsgbToEtrs89(Osgb36 coordinates, OstnVersionEnum ostnVersion = OstnVersionEnum.OSTN15) + { + //calculate shifts from OSGB36 point + double errorN = double.MaxValue; + double errorE = double.MaxValue; + EastingNorthing enCoordinates = null; - /// - /// Performs an OSGB36/ODN to ETRS89 datum transformation. Accuracy is approximately 10 centimeters. - /// Whilst very accurate this method is much slower than the Helmert transformation. - /// - public static LatitudeLongitude OsgbToEtrs89 (Osgb36 coordinates, OstnVersionEnum ostnVersion = OstnVersionEnum.OSTN15) - { - //calculate shifts from OSGB36 point - double errorN = double.MaxValue; - double errorE = double.MaxValue; - EastingNorthing enCoordinates = null; + var shiftsA = GetShifts(coordinates, coordinates.Height, ostnVersion); - var shiftsA = GetShifts (coordinates, coordinates.Height, ostnVersion); + //0.0001 error meters + int iter = 0; + while ((errorN > 0.0001 || errorE > 0.0001) && iter < 10) + { + enCoordinates = new EastingNorthing(coordinates.Easting - shiftsA.Se, coordinates.Northing - shiftsA.Sn); + var shiftsB = GetShifts(enCoordinates, coordinates.Height, ostnVersion); - //0.0001 error meters - int iter = 0; - while ((errorN > 0.0001 || errorE > 0.0001) && iter <10) { + errorE = Math.Abs(shiftsA.Se - shiftsB.Se); + errorN = Math.Abs(shiftsA.Sn - shiftsB.Sn); - enCoordinates = new EastingNorthing (coordinates.Easting - shiftsA.Se, coordinates.Northing - shiftsA.Sn); - var shiftsB = GetShifts (enCoordinates, coordinates.Height, ostnVersion); + shiftsA = shiftsB; + iter++; + } - errorE = Math.Abs (shiftsA.Se - shiftsB.Se); - errorN = Math.Abs (shiftsA.Sn - shiftsB.Sn); + return Convert.ToLatitudeLongitude(new Wgs84(), new BritishNationalGrid(), enCoordinates); + } - shiftsA = shiftsB; - iter++; + private static Shifts GetShifts(EastingNorthing coordinates, double ellipsoidHeight, OstnVersionEnum ostnVersion) + { + //See OS Document: Transformations and OSGM02/OSGM15 user guide chapter 3 + var ostnData = GetOstnData(ostnVersion); - } + List recordNumbers = new List(); + var records = new OstnDataRecord[4]; - return Convert.ToLatitudeLongitude(new Wgs84(), new BritishNationalGrid(), enCoordinates); + //determine record numbers + int eastIndex = (int)(coordinates.Easting / 1000.0); + int northIndex = (int)(coordinates.Northing / 1000.0); - } + double x0 = eastIndex * 1000; + double y0 = northIndex * 1000; - private static Shifts GetShifts (EastingNorthing coordinates, double ellipsoidHeight, OstnVersionEnum ostnVersion) - { - //See OS Document: Transformations and OSGM02/OSGM15 user guide chapter 3 - var ostnData = GetOstnData(ostnVersion); - - List recordNumbers = new List (); - var records = new OstnDataRecord[4]; - - //determine record numbers - int eastIndex = (int)(coordinates.Easting / 1000.0); - int northIndex = (int)(coordinates.Northing / 1000.0); - - double x0 = eastIndex * 1000; - double y0 = northIndex * 1000; - - //work out the four records - recordNumbers.Add (CalculateRecordNumber (eastIndex, northIndex)); - recordNumbers.Add (CalculateRecordNumber (eastIndex + 1, northIndex)); - recordNumbers.Add (CalculateRecordNumber (eastIndex + 1, northIndex + 1)); - recordNumbers.Add (CalculateRecordNumber (eastIndex, northIndex + 1)); + //work out the four records + recordNumbers.Add(CalculateRecordNumber(eastIndex, northIndex)); + recordNumbers.Add(CalculateRecordNumber(eastIndex + 1, northIndex)); + recordNumbers.Add(CalculateRecordNumber(eastIndex + 1, northIndex + 1)); + recordNumbers.Add(CalculateRecordNumber(eastIndex, northIndex + 1)); // Get the corresponding reccords from the data dictionary - for (int index = 0; index < 4; index++) - { - records[index] = ostnData[recordNumbers[index]]; - } + for (int index = 0; index < 4; index++) + { + records[index] = ostnData[recordNumbers[index]]; + } //populate the properties - var se0 = System.Convert.ToDouble (records[0].ETRS89_OSGB36_EShift); - var se1 = System.Convert.ToDouble (records[1].ETRS89_OSGB36_EShift); - var se2 = System.Convert.ToDouble (records[2].ETRS89_OSGB36_EShift); - var se3 = System.Convert.ToDouble (records[3].ETRS89_OSGB36_EShift); + var se0 = System.Convert.ToDouble(records[0].ETRS89_OSGB36_EShift); + var se1 = System.Convert.ToDouble(records[1].ETRS89_OSGB36_EShift); + var se2 = System.Convert.ToDouble(records[2].ETRS89_OSGB36_EShift); + var se3 = System.Convert.ToDouble(records[3].ETRS89_OSGB36_EShift); - var sn0 = System.Convert.ToDouble (records[0].ETRS89_OSGB36_NShift); - var sn1 = System.Convert.ToDouble (records[1].ETRS89_OSGB36_NShift); - var sn2 = System.Convert.ToDouble (records[2].ETRS89_OSGB36_NShift); - var sn3 = System.Convert.ToDouble (records[3].ETRS89_OSGB36_NShift); + var sn0 = System.Convert.ToDouble(records[0].ETRS89_OSGB36_NShift); + var sn1 = System.Convert.ToDouble(records[1].ETRS89_OSGB36_NShift); + var sn2 = System.Convert.ToDouble(records[2].ETRS89_OSGB36_NShift); + var sn3 = System.Convert.ToDouble(records[3].ETRS89_OSGB36_NShift); - var sg0 = System.Convert.ToDouble (records[0].ETRS89_ODN_HeightShift); - var sg1 = System.Convert.ToDouble (records[1].ETRS89_ODN_HeightShift); - var sg2 = System.Convert.ToDouble (records[2].ETRS89_ODN_HeightShift); - var sg3 = System.Convert.ToDouble (records[3].ETRS89_ODN_HeightShift); + var sg0 = System.Convert.ToDouble(records[0].ETRS89_ODN_HeightShift); + var sg1 = System.Convert.ToDouble(records[1].ETRS89_ODN_HeightShift); + var sg2 = System.Convert.ToDouble(records[2].ETRS89_ODN_HeightShift); + var sg3 = System.Convert.ToDouble(records[3].ETRS89_ODN_HeightShift); - var dx = coordinates.Easting - x0; - var dy = coordinates.Northing - y0; + var dx = coordinates.Easting - x0; + var dy = coordinates.Northing - y0; - var t = dx / 1000.0; - var u = dy / 1000.0; + var t = dx / 1000.0; + var u = dy / 1000.0; - var shifts = new Shifts (); + var shifts = new Shifts(); - shifts.Se = (1 - t) * (1 - u) * se0 + t * (1 - u) * se1 + t * u * se2 + (1 - t) * u * se3; - shifts.Sn = (1 - t) * (1 - u) * sn0 + t * (1 - u) * sn1 + t * u * sn2 + (1 - t) * u * sn3; - shifts.Sg = (1 - t) * (1 - u) * sg0 + t * (1 - u) * sg1 + t * u * sg2 + (1 - t) * u * sg3; + shifts.Se = (1 - t) * (1 - u) * se0 + t * (1 - u) * se1 + t * u * se2 + (1 - t) * u * se3; + shifts.Sn = (1 - t) * (1 - u) * sn0 + t * (1 - u) * sn1 + t * u * sn2 + (1 - t) * u * sn3; + shifts.Sg = (1 - t) * (1 - u) * sg0 + t * (1 - u) * sg1 + t * u * sg2 + (1 - t) * u * sg3; - shifts.GeoidDatum = (Osgb36GeoidDatum)System.Convert.ToInt32 (records[0].Height_Datum_Flag); + shifts.GeoidDatum = (Osgb36GeoidDatum)System.Convert.ToInt32(records[0].Height_Datum_Flag); - return shifts; - } + return shifts; + } - /// - /// Calculates a data file record number. - /// - /// - /// - /// - private static int CalculateRecordNumber(int eastIndex, int northIndex) - { - return eastIndex + (northIndex * 701) + 1; - } + /// + /// Calculates a data file record number. + /// + /// + /// + /// + private static int CalculateRecordNumber(int eastIndex, int northIndex) + { + return eastIndex + (northIndex * 701) + 1; + } /// /// Retrieves the parsed OSTN data from the embedded resource file. @@ -151,17 +145,18 @@ namespace GeoUK.OSTN /// /// private static Dictionary GetOstnData(OstnVersionEnum ostnVersion) - { + { switch (ostnVersion) { case OstnVersionEnum.OSTN02: return ResourceManager.Ostn02Data; + case OstnVersionEnum.OSTN15: return ResourceManager.Ostn15Data; + default: throw new NotImplementedException(); } } - } -} - + } +} \ No newline at end of file diff --git a/GeoUK/Convert.cs b/GeoUK/Convert.cs index 3e3048d..d559e3e 100644 --- a/GeoUK/Convert.cs +++ b/GeoUK/Convert.cs @@ -1,44 +1,42 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Globalization; using GeoUK.Coordinates; using GeoUK.Ellipsoids; using GeoUK.Projections; +using System; +using System.Globalization; namespace GeoUK { - /// - /// This class performs various generic conversions between coordinate systems and units of measure. - /// This class does not perform transformations. - /// - public static class Convert - { - /// - /// Method to convert from Easting Northing coordinates to Latitude Longitude coordinates. - /// - /// The latitude longitude. - /// - /// Projection. - /// Coordinates. - public static LatitudeLongitude ToLatitudeLongitude (Ellipsoid ellipsoid, Projections.Projection projection, EastingNorthing coordinates) - { - double M; - var N = coordinates.Northing; - var E = coordinates.Easting; + /// + /// This class performs various generic conversions between coordinate systems and units of measure. + /// This class does not perform transformations. + /// + public static class Convert + { + /// + /// Method to convert from Easting Northing coordinates to Latitude Longitude coordinates. + /// + /// The latitude longitude. + /// + /// Projection. + /// Coordinates. + public static LatitudeLongitude ToLatitudeLongitude(Ellipsoid ellipsoid, Projections.Projection projection, EastingNorthing coordinates) + { + double M; + var N = coordinates.Northing; + var E = coordinates.Easting; - //from OS Guide - //constants needed are a Semi-Major Axis , b , e2 , N0 , E0 , F0 ,φ0 , and λ0 - double a = ellipsoid.SemiMajorAxis; - double b = ellipsoid.SemiMinorAxis; - double e2 = ellipsoid.EccentricitySquared; - double F0 = projection.ScaleFactor; - double lat0 = ToRadians (projection.TrueOriginLatitude); - double lon0 = ToRadians (projection.TrueOriginLongitude); - double E0 = projection.TrueOriginEasting; - double N0 = projection.TrueOriginNorthing; + //from OS Guide + //constants needed are a Semi-Major Axis , b , e2 , N0 , E0 , F0 ,φ0 , and λ0 + double a = ellipsoid.SemiMajorAxis; + double b = ellipsoid.SemiMinorAxis; + double e2 = ellipsoid.EccentricitySquared; + double F0 = projection.ScaleFactor; + double lat0 = ToRadians(projection.TrueOriginLatitude); + double lon0 = ToRadians(projection.TrueOriginLongitude); + double E0 = projection.TrueOriginEasting; + double N0 = projection.TrueOriginNorthing; - /* + /* Console.WriteLine ("a: {0}", a); Console.WriteLine ("b: {0}", b); Console.WriteLine ("e2: {0}", e2); @@ -53,58 +51,58 @@ namespace GeoUK Console.WriteLine ("E: {0}", E); */ - var lat = ((N - N0) / (a * F0)) + lat0; + var lat = ((N - N0) / (a * F0)) + lat0; - //double n = (a - b) / (a + b); - //check for error and reiterate as required - int loopCount = 0; - do { - M = CalculateM (lat, lat0, a, b, F0); + //double n = (a - b) / (a + b); + //check for error and reiterate as required + int loopCount = 0; + do + { + M = CalculateM(lat, lat0, a, b, F0); - lat += ((N - N0 - M) / (a * F0)); + lat += ((N - N0 - M) / (a * F0)); - /* + /* Console.WriteLine ("\nlat #{0}: {1}", loopCount + 1, lat); Console.WriteLine ("M #{0}: {1}", loopCount + 1, M); Console.WriteLine ("N - N0 - M #{0}: {1}\n", loopCount + 1, N - N0 - M); */ - loopCount++; - - } while (!IsNearlyZero (N - N0 - M, 1e-16) & loopCount < 10); + loopCount++; + } while (!IsNearlyZero(N - N0 - M, 1e-16) & loopCount < 10); - double v = a * F0 * Math.Pow ((1 - e2 * Math.Pow (Math.Sin (lat), 2)), -0.5); - double p = a * F0 * (1 - e2) * Math.Pow ((1 - e2 * Math.Pow (Math.Sin (lat), 2)), -1.5); - double n2 = (v / p) - 1; + double v = a * F0 * Math.Pow((1 - e2 * Math.Pow(Math.Sin(lat), 2)), -0.5); + double p = a * F0 * (1 - e2) * Math.Pow((1 - e2 * Math.Pow(Math.Sin(lat), 2)), -1.5); + double n2 = (v / p) - 1; - var VII = Math.Tan (lat) / (2 * p * v); + var VII = Math.Tan(lat) / (2 * p * v); - var VIIIa = Math.Tan (lat) / (24 * p * Math.Pow (v, 3)); - var VIIIb = 5 + (3 * Math.Pow (Math.Tan (lat), 2)) + n2 - 9 * (Math.Pow (Math.Tan (lat), 2)) * n2; - var VIII = VIIIa * VIIIb; + var VIIIa = Math.Tan(lat) / (24 * p * Math.Pow(v, 3)); + var VIIIb = 5 + (3 * Math.Pow(Math.Tan(lat), 2)) + n2 - 9 * (Math.Pow(Math.Tan(lat), 2)) * n2; + var VIII = VIIIa * VIIIb; - var IXa = Math.Tan (lat) / (720 * p * Math.Pow (v, 5)); - var IXb = 61 + (90 * Math.Pow (Math.Tan (lat), 2)) + (45 * Math.Pow (Math.Tan (lat), 4)); - var IX = IXa * IXb; + var IXa = Math.Tan(lat) / (720 * p * Math.Pow(v, 5)); + var IXb = 61 + (90 * Math.Pow(Math.Tan(lat), 2)) + (45 * Math.Pow(Math.Tan(lat), 4)); + var IX = IXa * IXb; - var X = MathEx.Secant (lat) / v; + var X = MathEx.Secant(lat) / v; - var XIa = MathEx.Secant (lat) / (6 * Math.Pow (v, 3)); - var XIb = v / p + (2 * Math.Pow (Math.Tan (lat), 2)); - var XI = XIa * XIb; + var XIa = MathEx.Secant(lat) / (6 * Math.Pow(v, 3)); + var XIb = v / p + (2 * Math.Pow(Math.Tan(lat), 2)); + var XI = XIa * XIb; - var XIIa = MathEx.Secant (lat) / (120 * Math.Pow (v, 5)); - var XIIb = 5 + (28 * Math.Pow (Math.Tan (lat), 2)) + (24 * Math.Pow (Math.Tan (lat), 4)); - var XII = XIIa * XIIb; + var XIIa = MathEx.Secant(lat) / (120 * Math.Pow(v, 5)); + var XIIb = 5 + (28 * Math.Pow(Math.Tan(lat), 2)) + (24 * Math.Pow(Math.Tan(lat), 4)); + var XII = XIIa * XIIb; - var XIIAa = MathEx.Secant (lat) / (5040 * Math.Pow (v, 7)); - var XIIAb = 61 + (662 * Math.Pow (Math.Tan (lat), 2)) + (1320 * Math.Pow (Math.Tan (lat), 4)) + (720 * Math.Pow (Math.Tan (lat), 6)); - var XIIA = XIIAa * XIIAb; + var XIIAa = MathEx.Secant(lat) / (5040 * Math.Pow(v, 7)); + var XIIAb = 61 + (662 * Math.Pow(Math.Tan(lat), 2)) + (1320 * Math.Pow(Math.Tan(lat), 4)) + (720 * Math.Pow(Math.Tan(lat), 6)); + var XIIA = XIIAa * XIIAb; - lat = lat - VII * Math.Pow (E - E0, 2) + VIII * Math.Pow (E - E0, 4) - IX * Math.Pow (E - E0, 6); - var lon = lon0 + X * (E - E0) - XI * Math.Pow (E - E0, 3) + XII * Math.Pow (E - E0, 5) - XIIA * Math.Pow (E - E0, 7); + lat = lat - VII * Math.Pow(E - E0, 2) + VIII * Math.Pow(E - E0, 4) - IX * Math.Pow(E - E0, 6); + var lon = lon0 + X * (E - E0) - XI * Math.Pow(E - E0, 3) + XII * Math.Pow(E - E0, 5) - XIIA * Math.Pow(E - E0, 7); - /* + /* Console.WriteLine ("v: {0}", v); Console.WriteLine ("p: {0}", p); Console.WriteLine ("n2: {0}", n2); @@ -119,267 +117,267 @@ namespace GeoUK Console.WriteLine ("lon: {0}", lon); */ - return new LatitudeLongitude (ToDegrees (lat), ToDegrees (lon)); + return new LatitudeLongitude(ToDegrees(lat), ToDegrees(lon)); + } + private static bool IsNearlyZero(double x, double tolerance) + { + if (x < 0) + { + x = x * -1; + } - } + return (x < 0 && x > tolerance * -1) || (x >= 0 && x < tolerance); + } - private static bool IsNearlyZero (double x, double tolerance) - { - if (x < 0) { - x = x * -1; - } + private static double CalculateM(double latitude, double latitudeOrigin, double semiMajorAxis, double semiMinorAxis, double scaleFactor) + { + double n = (semiMajorAxis - semiMinorAxis) / (semiMajorAxis + semiMinorAxis); - return (x < 0 && x > tolerance * -1) || (x >= 0 && x < tolerance); + double Ma = (1 + n + ((5.0 / 4.0) * Math.Pow(n, 2)) + ((5.0 / 4.0) * Math.Pow(n, 3))) * (latitude - latitudeOrigin); + double Mb = ((3 * n) + (3 * Math.Pow(n, 2)) + ((21.0 / 8.0) * Math.Pow(n, 3))) * Math.Sin(latitude - latitudeOrigin) * Math.Cos(latitude + latitudeOrigin); + double Mc = (((15.0 / 8.0) * Math.Pow(n, 2)) + (15.0 / 8.0) * Math.Pow(n, 3)) * Math.Sin(2 * (latitude - latitudeOrigin)) * Math.Cos(2 * (latitude + latitudeOrigin)); + double Md = (35.0 / 24.0 * Math.Pow(n, 3)) * Math.Sin(3 * (latitude - latitudeOrigin)) * Math.Cos(3 * (latitude + latitudeOrigin)); + double M = semiMinorAxis * scaleFactor * (Ma - Mb + Mc - Md); - } + return M; + } - private static double CalculateM (double latitude, double latitudeOrigin, double semiMajorAxis, double semiMinorAxis, double scaleFactor) - { - double n = (semiMajorAxis - semiMinorAxis) / (semiMajorAxis + semiMinorAxis); + /// + /// Converts decimal degrees to radians. + /// + /// + /// + public static double ToRadians(double degrees) + { + return degrees * (Math.PI / 180); + } - double Ma = (1 + n + ((5.0 / 4.0) * Math.Pow (n, 2)) + ((5.0 / 4.0) * Math.Pow (n, 3))) * (latitude - latitudeOrigin); - double Mb = ((3 * n) + (3 * Math.Pow (n, 2)) + ((21.0 / 8.0) * Math.Pow (n, 3))) * Math.Sin (latitude - latitudeOrigin) * Math.Cos (latitude + latitudeOrigin); - double Mc = (((15.0 / 8.0) * Math.Pow (n, 2)) + (15.0 / 8.0) * Math.Pow (n, 3)) * Math.Sin (2 * (latitude - latitudeOrigin)) * Math.Cos (2 * (latitude + latitudeOrigin)); - double Md = (35.0 / 24.0 * Math.Pow (n, 3)) * Math.Sin (3 * (latitude - latitudeOrigin)) * Math.Cos (3 * (latitude + latitudeOrigin)); - double M = semiMinorAxis * scaleFactor * (Ma - Mb + Mc - Md); + /// + /// Converts radians to decimal degrees. + /// + /// + /// + public static double ToDegrees(double radians) + { + return radians * (180 / Math.PI); + } - return M; - } + /// + /// Converts cartesian coordinates to grid eastings and northings for any Transverse Mercator map projection, including the Ordnance Survey National Grid. + /// Ellipsoid height is ignored. + /// + /// + /// When converting OSGB36 coordinates between (easting, northing) and (latitude, longitude), + /// use the Airy 1830 ellipsoid. When converting ETRS89 coordinates between (easting, northing) and + /// (latitude, longitude), use the GRS80 ellipsoid. Use the same National Grid projection + /// constants for both ETRS89 and OSGB36 coordinates. + /// + public static EastingNorthing ToEastingNorthing(Ellipsoid ellipsoid, Projections.Projection projection, Cartesian coordinates) + { + LatitudeLongitude coords = ToLatitudeLongitude(ellipsoid, coordinates); + return ToEastingNorthing(ellipsoid, projection, coords); + } + /// + /// Converts latitude and longitude to grid eastings and northings for any Transverse Mercator map projection, including the Ordnance Survey National Grid. + /// Ellipsoid height is ignored. + /// + /// + /// When converting OSGB36 coordinates between (easting, northing) and (latitude, longitude), + /// use the Airy 1830 ellipsoid. When converting ETRS89 coordinates between (easting, northing) and + /// (latitude, longitude), use the GRS80 ellipsoid. Use the same National Grid projection + /// constants for both ETRS89 and OSGB36 coordinates. + /// + /// + /// + /// + /// + public static EastingNorthing ToEastingNorthing(Ellipsoid ellipsoid, Projections.Projection projection, LatitudeLongitude coordinates) + { + double lat = ToRadians(coordinates.Latitude); + double lon = ToRadians(coordinates.Longitude); - /// - /// Converts decimal degrees to radians. - /// - /// - /// - public static double ToRadians (double degrees) - { - return degrees * (Math.PI / 180); - } + //OS Document Transformation and OSGM02 User Guide, Appendix B. + //B1 + double a = ellipsoid.SemiMajorAxis; + double b = ellipsoid.SemiMinorAxis; + double e2 = ellipsoid.EccentricitySquared; + double F0 = projection.ScaleFactor; + double lat0 = ToRadians(projection.TrueOriginLatitude); + double lon0 = ToRadians(projection.TrueOriginLongitude); + double E0 = projection.TrueOriginEasting; + double N0 = projection.TrueOriginNorthing; - /// - /// Converts radians to decimal degrees. - /// - /// - /// - public static double ToDegrees (double radians) - { - return radians * (180 / Math.PI); - } + //B2 + //double n = (a - b) / (a + b); - /// - /// Converts cartesian coordinates to grid eastings and northings for any Transverse Mercator map projection, including the Ordnance Survey National Grid. - /// Ellipsoid height is ignored. - /// - /// - /// When converting OSGB36 coordinates between (easting, northing) and (latitude, longitude), - /// use the Airy 1830 ellipsoid. When converting ETRS89 coordinates between (easting, northing) and - /// (latitude, longitude), use the GRS80 ellipsoid. Use the same National Grid projection - /// constants for both ETRS89 and OSGB36 coordinates. - /// - public static EastingNorthing ToEastingNorthing (Ellipsoid ellipsoid, Projections.Projection projection, Cartesian coordinates) - { - LatitudeLongitude coords = ToLatitudeLongitude (ellipsoid, coordinates); - return ToEastingNorthing (ellipsoid, projection, coords); - } + //B3 + double v = a * F0 * Math.Pow((1 - e2 * Math.Pow(Math.Sin(lat), 2)), -0.5); - /// - /// Converts latitude and longitude to grid eastings and northings for any Transverse Mercator map projection, including the Ordnance Survey National Grid. - /// Ellipsoid height is ignored. - /// - /// - /// When converting OSGB36 coordinates between (easting, northing) and (latitude, longitude), - /// use the Airy 1830 ellipsoid. When converting ETRS89 coordinates between (easting, northing) and - /// (latitude, longitude), use the GRS80 ellipsoid. Use the same National Grid projection - /// constants for both ETRS89 and OSGB36 coordinates. - /// - /// - /// - /// - /// - public static EastingNorthing ToEastingNorthing (Ellipsoid ellipsoid, Projections.Projection projection, LatitudeLongitude coordinates) - { - double lat = ToRadians (coordinates.Latitude); - double lon = ToRadians (coordinates.Longitude); + //B4 + double p = a * F0 * (1 - e2) * Math.Pow((1 - e2 * Math.Pow(Math.Sin(lat), 2)), -1.5); - //OS Document Transformation and OSGM02 User Guide, Appendix B. - //B1 - double a = ellipsoid.SemiMajorAxis; - double b = ellipsoid.SemiMinorAxis; - double e2 = ellipsoid.EccentricitySquared; - double F0 = projection.ScaleFactor; - double lat0 = ToRadians (projection.TrueOriginLatitude); - double lon0 = ToRadians (projection.TrueOriginLongitude); - double E0 = projection.TrueOriginEasting; - double N0 = projection.TrueOriginNorthing; - - //B2 - //double n = (a - b) / (a + b); + //B5 + double n2 = v / p - 1; - //B3 - double v = a * F0 * Math.Pow ((1 - e2 * Math.Pow (Math.Sin (lat), 2)), -0.5); + //B6 + var M = CalculateM(lat, lat0, a, b, F0); - //B4 - double p = a * F0 * (1 - e2) * Math.Pow ((1 - e2 * Math.Pow (Math.Sin (lat), 2)), -1.5); + // double Ma = (1 + n + ((5.0 / 4.0) * Math.Pow (n, 2)) + ((5.0 / 4.0) * Math.Pow (n, 3))) * (lat - lat0); + // double Mb = ((3 * n) + (3 * Math.Pow (n, 2)) + ((21.0 / 8.0) * Math.Pow (n, 3))) * Math.Sin (lat - lat0) * Math.Cos (lat + lat0); + // double Mc = (((15.0 / 8.0) * Math.Pow (n, 2)) + (15.0 / 8.0) * Math.Pow (n, 3)) * Math.Sin (2 * (lat - lat0)) * Math.Cos (2 * (lat + lat0)); + // double Md = (35.0 / 24.0 * Math.Pow (n, 3)) * Math.Sin (3 * (lat - lat0)) * Math.Cos (3 * (lat + lat0)); + // double M = b * F0 * (Ma - Mb + Mc - Md); - //B5 - double n2 = v / p - 1; + double I = M + N0; + double II = (v / 2) * Math.Sin(lat) * Math.Cos(lat); + double III = (v / 24) * Math.Sin(lat) * Math.Pow(Math.Cos(lat), 3) * (5 - Math.Pow(Math.Tan(lat), 2) + 9 * n2); + double IIIA = (v / 720) * Math.Sin(lat) * Math.Pow(Math.Cos(lat), 5) * (61 - 58 * Math.Pow(Math.Tan(lat), 2) + Math.Pow(Math.Tan(lat), 4)); + double IV = v * Math.Cos(lat); + double V = (v / 6) * Math.Pow(Math.Cos(lat), 3) * ((v / p) - Math.Pow(Math.Tan(lat), 2)); + double VI = (v / 120) * Math.Pow(Math.Cos(lat), 5) * (5 - 18 * Math.Pow(Math.Tan(lat), 2) + Math.Pow(Math.Tan(lat), 4) + 14 * n2 - 58 * Math.Pow(Math.Tan(lat), 2) * n2); - //B6 - var M = CalculateM (lat, lat0, a, b, F0); + //B7 + double N = I + (II * Math.Pow((lon - lon0), 2)) + (III * Math.Pow((lon - lon0), 4)) + (IIIA * Math.Pow((lon - lon0), 6)); -// double Ma = (1 + n + ((5.0 / 4.0) * Math.Pow (n, 2)) + ((5.0 / 4.0) * Math.Pow (n, 3))) * (lat - lat0); -// double Mb = ((3 * n) + (3 * Math.Pow (n, 2)) + ((21.0 / 8.0) * Math.Pow (n, 3))) * Math.Sin (lat - lat0) * Math.Cos (lat + lat0); -// double Mc = (((15.0 / 8.0) * Math.Pow (n, 2)) + (15.0 / 8.0) * Math.Pow (n, 3)) * Math.Sin (2 * (lat - lat0)) * Math.Cos (2 * (lat + lat0)); -// double Md = (35.0 / 24.0 * Math.Pow (n, 3)) * Math.Sin (3 * (lat - lat0)) * Math.Cos (3 * (lat + lat0)); -// double M = b * F0 * (Ma - Mb + Mc - Md); + //B8 + double E = E0 + (IV * (lon - lon0)) + (V * Math.Pow((lon - lon0), 3)) + (VI * Math.Pow((lon - lon0), 5)); - double I = M + N0; - double II = (v / 2) * Math.Sin (lat) * Math.Cos (lat); - double III = (v / 24) * Math.Sin (lat) * Math.Pow (Math.Cos (lat), 3) * (5 - Math.Pow (Math.Tan (lat), 2) + 9 * n2); - double IIIA = (v / 720) * Math.Sin (lat) * Math.Pow (Math.Cos (lat), 5) * (61 - 58 * Math.Pow (Math.Tan (lat), 2) + Math.Pow (Math.Tan (lat), 4)); - double IV = v * Math.Cos (lat); - double V = (v / 6) * Math.Pow (Math.Cos (lat), 3) * ((v / p) - Math.Pow (Math.Tan (lat), 2)); - double VI = (v / 120) * Math.Pow (Math.Cos (lat), 5) * (5 - 18 * Math.Pow (Math.Tan (lat), 2) + Math.Pow (Math.Tan (lat), 4) + 14 * n2 - 58 * Math.Pow (Math.Tan (lat), 2) * n2); + return new EastingNorthing(E, N, coordinates.ElipsoidalHeight); //height is still with respect to the ellipsoid + } - //B7 - double N = I + (II * Math.Pow ((lon - lon0), 2)) + (III * Math.Pow ((lon - lon0), 4)) + (IIIA * Math.Pow ((lon - lon0), 6)); + public static Cartesian ToCartesian(Ellipsoid ellipsoid, Projection projection, EastingNorthing coordinates) + { + var latLongCoordinates = ToLatitudeLongitude( + ellipsoid, + projection, + coordinates); - //B8 - double E = E0 + (IV * (lon - lon0)) + (V * Math.Pow ((lon - lon0), 3)) + (VI * Math.Pow ((lon - lon0), 5)); + return ToCartesian(ellipsoid, latLongCoordinates); + } - return new EastingNorthing (E, N, coordinates.ElipsoidalHeight); //height is still with respect to the ellipsoid - } + /// + /// Converts latitude, longitude and elipsoidal height coordinates to cartesian coordinates using the same ellipsoid. + /// Please note this is not a transformation between ellipsoids. + /// + /// + /// + /// + public static Cartesian ToCartesian(Ellipsoid ellipsoid, LatitudeLongitude coordinates) + { + double lat = ToRadians(coordinates.Latitude); + double lon = ToRadians(coordinates.Longitude); + double height = coordinates.ElipsoidalHeight; - public static Cartesian ToCartesian (Ellipsoid ellipsoid, Projection projection, EastingNorthing coordinates) - { - var latLongCoordinates = ToLatitudeLongitude ( - ellipsoid, - projection, - coordinates); - - return ToCartesian (ellipsoid, latLongCoordinates); - } + double e2 = ellipsoid.EccentricitySquared; + double a = ellipsoid.SemiMajorAxis; - /// - /// Converts latitude, longitude and elipsoidal height coordinates to cartesian coordinates using the same ellipsoid. - /// Please note this is not a transformation between ellipsoids. - /// - /// - /// - /// - public static Cartesian ToCartesian (Ellipsoid ellipsoid, LatitudeLongitude coordinates) - { + double v = a / Math.Sqrt(1 - (e2 * Math.Pow(Math.Sin(lat), 2))); - double lat = ToRadians (coordinates.Latitude); - double lon = ToRadians (coordinates.Longitude); - double height = coordinates.ElipsoidalHeight; + double x = (v + height) * Math.Cos(lat) * Math.Cos(lon); + double y = (v + height) * Math.Cos(lat) * Math.Sin(lon); + double z = ((1 - e2) * v + height) * Math.Sin(lat); - double e2 = ellipsoid.EccentricitySquared; - double a = ellipsoid.SemiMajorAxis; + return new Cartesian(x, y, z); + } - double v = a / Math.Sqrt (1 - (e2 * Math.Pow (Math.Sin (lat), 2))); + /// + /// Converts cartesian coordinates to latitude, longitude and elipsoidal height using the same ellipsoid. + /// Please note this is not a transformation between ellipsoids. + /// + /// + /// + /// + public static LatitudeLongitude ToLatitudeLongitude(Ellipsoid ellipsoid, Cartesian coordinates) + { + double e2 = ellipsoid.EccentricitySquared; + double a = ellipsoid.SemiMajorAxis; + double p = Math.Sqrt(Math.Pow(coordinates.X, 2) + Math.Pow(coordinates.Y, 2)); + double lon = Math.Atan(coordinates.Y / coordinates.X); - double x = (v + height) * Math.Cos (lat) * Math.Cos (lon); - double y = (v + height) * Math.Cos (lat) * Math.Sin (lon); - double z = ((1 - e2) * v + height) * Math.Sin (lat); + //have a first stab + double v = 0.0; + double lat = Math.Atan(coordinates.Z / (p * (1 - e2))); - return new Cartesian (x, y, z); - } + //iterate a few times 3 is enough but 10 to be safe + for (int iterations = 0; iterations < 10; iterations++) + { + v = a / Math.Sqrt(1 - (e2 * Math.Pow(Math.Sin(lat), 2))); + lat = Math.Atan((coordinates.Z + e2 * v * Math.Sin(lat)) / p); + } + double height = (p / Math.Cos(lat)) - v; - /// - /// Converts cartesian coordinates to latitude, longitude and elipsoidal height using the same ellipsoid. - /// Please note this is not a transformation between ellipsoids. - /// - /// - /// - /// - public static LatitudeLongitude ToLatitudeLongitude (Ellipsoid ellipsoid, Cartesian coordinates) - { - double e2 = ellipsoid.EccentricitySquared; - double a = ellipsoid.SemiMajorAxis; - double p = Math.Sqrt (Math.Pow (coordinates.X, 2) + Math.Pow (coordinates.Y, 2)); - double lon = Math.Atan (coordinates.Y / coordinates.X); + return new LatitudeLongitude(ToDegrees(lat), ToDegrees(lon), height); + } - //have a first stab - double v = 0.0; - double lat = Math.Atan (coordinates.Z / (p * (1 - e2))); - - //iterate a few times 3 is enough but 10 to be safe - for (int iterations = 0; iterations < 10; iterations++) { - v = a / Math.Sqrt (1 - (e2 * Math.Pow (Math.Sin (lat), 2))); - lat = Math.Atan ((coordinates.Z + e2 * v * Math.Sin (lat)) / p); - } - double height = (p / Math.Cos (lat)) - v; + /// + /// Converts degrees minutes and seconds to decimal degrees. + /// + /// + /// + /// + /// + public static double ToDecimelDegrees(int degrees, int minutes, double seconds) + { + //determine seconds as minutes + double m = minutes + (seconds / 60.0); + return ToDecimelDegrees(degrees, m); + } - return new LatitudeLongitude (ToDegrees (lat), ToDegrees (lon), height); - } + /// + /// Converts degrees and decimel minutes to decimal degrees. + /// + /// + /// + /// + public static double ToDecimelDegrees(int degrees, double minutes) + { + //determine minutes as derees + return degrees + (minutes / 60.0); + } - /// - /// Converts degrees minutes and seconds to decimal degrees. - /// - /// - /// - /// - /// - public static double ToDecimelDegrees (int degrees, int minutes, double seconds) - { - //determine seconds as minutes - double m = minutes + (seconds / 60.0); - return ToDecimelDegrees (degrees, m); - } + private static double Div(double value, double divisor) + { + double dblResult = 0; + bool blnNegative = false; - /// - /// Converts degrees and decimel minutes to decimal degrees. - /// - /// - /// - /// - public static double ToDecimelDegrees (int degrees, double minutes) - { - //determine minutes as derees - return degrees + (minutes / 60.0); - } + //make the division + dblResult = value / divisor; - private static double Div (double value, double divisor) - { - double dblResult = 0; - bool blnNegative = false; + //do all calculations on positive numbers + if (dblResult < 0) + { + blnNegative = true; + dblResult = dblResult * -1; + } - //make the division - dblResult = value / divisor; + //see if there is any remainder + if (dblResult % 1 > 0) + { + dblResult = Math.Ceiling(dblResult) - 1; + } + else + { + dblResult = System.Convert.ToInt32(dblResult, CultureInfo.InvariantCulture); + } - //do all calculations on positive numbers - if (dblResult < 0) { - blnNegative = true; - dblResult = dblResult * -1; - } + if (blnNegative) + { + dblResult = Negate(dblResult); + } - //see if there is any remainder - if (dblResult % 1 > 0) { - dblResult = Math.Ceiling (dblResult) - 1; - } else { - dblResult = System.Convert.ToInt32 (dblResult, CultureInfo.InvariantCulture); - } + return dblResult; + } - if (blnNegative) { - dblResult = Negate (dblResult); - } - - return dblResult; - - } - - /// - /// Helper funtion to reverse the sign of a value. Helps code to be more readable. - /// - /// - /// - private static double Negate (double value) - { - return value * -1.0; - } - - } + /// + /// Helper funtion to reverse the sign of a value. Helps code to be more readable. + /// + /// + /// + private static double Negate(double value) + { + return value * -1.0; + } + } } \ No newline at end of file diff --git a/GeoUK/Coordinates/Cartesian.cs b/GeoUK/Coordinates/Cartesian.cs index d7f140f..3e642e9 100644 --- a/GeoUK/Coordinates/Cartesian.cs +++ b/GeoUK/Coordinates/Cartesian.cs @@ -1,7 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Text; - namespace GeoUK.Coordinates { /// @@ -25,6 +21,7 @@ namespace GeoUK.Coordinates _y = y; _z = z; } + /// /// Returns the X axis parameter. /// @@ -32,6 +29,7 @@ namespace GeoUK.Coordinates { get { return _x; } } + /// /// Returns the Y axis parameter. /// @@ -39,6 +37,7 @@ namespace GeoUK.Coordinates { get { return _y; } } + /// /// Returns the Z axis parameter. /// @@ -46,6 +45,5 @@ namespace GeoUK.Coordinates { get { return _z; } } - } -} +} \ No newline at end of file diff --git a/GeoUK/Coordinates/EastingNorthing.cs b/GeoUK/Coordinates/EastingNorthing.cs index f686da1..d263fcd 100644 --- a/GeoUK/Coordinates/EastingNorthing.cs +++ b/GeoUK/Coordinates/EastingNorthing.cs @@ -1,7 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Text; - namespace GeoUK.Coordinates { /// @@ -10,9 +6,10 @@ namespace GeoUK.Coordinates /// public class EastingNorthing { - double _easting; - double _northing; - double _height; + private double _easting; + private double _northing; + private double _height; + /// /// Constructor. /// @@ -24,6 +21,7 @@ namespace GeoUK.Coordinates _northing = northing; _height = 0; } + /// /// Constructor. /// @@ -36,6 +34,7 @@ namespace GeoUK.Coordinates _northing = northing; _height = height; } + /// /// Retruns the easting parameter. /// @@ -43,6 +42,7 @@ namespace GeoUK.Coordinates { get { return _easting; } } + /// /// returns the northing parameter. /// @@ -50,6 +50,7 @@ namespace GeoUK.Coordinates { get { return _northing; } } + /// /// Returns the height parameter. /// @@ -58,4 +59,4 @@ namespace GeoUK.Coordinates get { return _height; } } } -} +} \ No newline at end of file diff --git a/GeoUK/Coordinates/GeoidDatum.cs b/GeoUK/Coordinates/GeoidDatum.cs index 21af7bc..0ac1235 100644 --- a/GeoUK/Coordinates/GeoidDatum.cs +++ b/GeoUK/Coordinates/GeoidDatum.cs @@ -1,7 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Text; - namespace GeoUK.Coordinates { /// @@ -13,61 +9,75 @@ namespace GeoUK.Coordinates /// Outside Model Boundary /// OutsideModelBoundary = 0, + /// /// Newlyn, Uk Mainland /// NewlynUkMainland = 1, + /// /// StMarys, Scilly Isles /// StMarysScillyIsles = 2, + /// /// Douglas02, Isle of Man /// Douglas02IsleofMan = 3, + /// /// Stornoway, Outer Hebrides /// StornowayOuterHebrides = 4, + /// /// St. Kilda, St. Kilda /// StKildaStKilda = 5, + /// /// Lerwick, Shetland Isles /// LerwickShetlandIsles = 6, + /// /// Newlyn, Orkney Isles /// NewlynOrkneyIsles = 7, + /// /// Fair Isle, Fair Isle /// FairIsleFairIsle = 8, + /// /// Flannan Isles, Flannan Isles /// FlannanIslesFlannanIsles = 9, + /// /// North Rona, North Rona /// NorthRonaNorthRona = 10, + /// /// Sule Skerry, Sule Skerry /// SuleSkerrySuleSkerry = 11, + /// /// Foula, Foula. /// FoulaFoula = 12, + /// /// Malin Head, Republic of Ireland /// MalinHeadRepublicofIreland = 13, + /// /// Belfast, Northern Ireland /// BelfastNorthernIreland = 14 } -} +} \ No newline at end of file diff --git a/GeoUK/Coordinates/LatitudeLongitude.cs b/GeoUK/Coordinates/LatitudeLongitude.cs index 2dda5de..898cbe8 100644 --- a/GeoUK/Coordinates/LatitudeLongitude.cs +++ b/GeoUK/Coordinates/LatitudeLongitude.cs @@ -1,16 +1,15 @@ -using System; - namespace GeoUK.Coordinates { - /// + /// /// This immutable class represents a set of latitude/longitude/ellipsoidal height coordinates. /// - public class LatitudeLongitude + public class LatitudeLongitude - { + { private double _degreesLatitude = 0.0; private double _degreesLongitude = 0.0; private double _elipsoidalHeight = 0.0; + /// /// Constructor. /// @@ -22,38 +21,42 @@ namespace GeoUK.Coordinates _degreesLongitude = degreesLongitude; _elipsoidalHeight = 0.0; } - /// + + /// /// Constructor. /// /// /// /// public LatitudeLongitude(double degreesLatitude, double degreesLongitude, double elipsoidalHeight) - { + { _degreesLatitude = degreesLatitude; _degreesLongitude = degreesLongitude; _elipsoidalHeight = elipsoidalHeight; } + /// /// Returns latitude in degrees. /// public double Latitude - { - get - { + { + get + { return _degreesLatitude; - } - } + } + } + /// /// Returns longitude in degrees. /// public double Longitude - { - get - { + { + get + { return _degreesLongitude; - } - } + } + } + /// /// returns elipsoidal height in meters. /// @@ -65,4 +68,4 @@ namespace GeoUK.Coordinates } } } -} +} \ No newline at end of file diff --git a/GeoUK/Coordinates/Osgb36.cs b/GeoUK/Coordinates/Osgb36.cs index 63a7271..0e2b5f8 100644 --- a/GeoUK/Coordinates/Osgb36.cs +++ b/GeoUK/Coordinates/Osgb36.cs @@ -1,11 +1,9 @@ using System; -using System.Collections.Generic; -using System.Text; namespace GeoUK.Coordinates { /// - /// This immutable class, derived from EastingNorthingCoordinates, provides a convenient means + /// This immutable class, derived from EastingNorthingCoordinates, provides a convenient means /// to represent OSGB36 eastings and northings. /// /// @@ -14,47 +12,47 @@ namespace GeoUK.Coordinates /// public class Osgb36 : EastingNorthing { - Osgb36GeoidDatum _datum = Osgb36GeoidDatum.OutsideModelBoundary; + private Osgb36GeoidDatum _datum = Osgb36GeoidDatum.OutsideModelBoundary; - /// - /// Initializes a new instance of the class. - /// - /// Easting. - /// Northing. - public Osgb36(double easting, double northing) - : base(easting, northing, 0) - { - _datum = Osgb36GeoidDatum.NewlynUkMainland; - } + /// + /// Initializes a new instance of the class. + /// + /// Easting. + /// Northing. + public Osgb36(double easting, double northing) + : base(easting, northing, 0) + { + _datum = Osgb36GeoidDatum.NewlynUkMainland; + } - /// - /// Initializes a new instance of the class. - /// - /// Easting northing coordinates. - public Osgb36(EastingNorthing eastingNorthingCoordinates) - : base(eastingNorthingCoordinates.Easting, eastingNorthingCoordinates.Northing, eastingNorthingCoordinates.Height) - { - _datum = Osgb36GeoidDatum.NewlynUkMainland; - } + /// + /// Initializes a new instance of the class. + /// + /// Easting northing coordinates. + public Osgb36(EastingNorthing eastingNorthingCoordinates) + : base(eastingNorthingCoordinates.Easting, eastingNorthingCoordinates.Northing, eastingNorthingCoordinates.Height) + { + _datum = Osgb36GeoidDatum.NewlynUkMainland; + } - /// - /// Initializes a new instance of the class. - /// - /// Easting northing coordinates. - /// Datum. - public Osgb36(EastingNorthing eastingNorthingCoordinates, Osgb36GeoidDatum datum) - : base(eastingNorthingCoordinates.Easting, eastingNorthingCoordinates.Northing, eastingNorthingCoordinates.Height) - { - _datum = datum; - } + /// + /// Initializes a new instance of the class. + /// + /// Easting northing coordinates. + /// Datum. + public Osgb36(EastingNorthing eastingNorthingCoordinates, Osgb36GeoidDatum datum) + : base(eastingNorthingCoordinates.Easting, eastingNorthingCoordinates.Northing, eastingNorthingCoordinates.Height) + { + _datum = datum; + } - /// - /// Initializes a new instance of the class. - /// - /// Easting. - /// Northing. - /// Height. - /// Datum. + /// + /// Initializes a new instance of the class. + /// + /// Easting. + /// Northing. + /// Height. + /// Datum. public Osgb36(double easting, double northing, double height, Osgb36GeoidDatum datum) : base(easting, northing, height) { @@ -62,7 +60,7 @@ namespace GeoUK.Coordinates } /// - /// Returns the Local Geoid datum in use. other property values should be + /// Returns the Local Geoid datum in use. other property values should be /// considered invalid if this property is set to OutsideModelBoundary. /// public Osgb36GeoidDatum RegionGeoidDatum @@ -70,76 +68,74 @@ namespace GeoUK.Coordinates get { return _datum; } } - public string MapReference { - get { - /* + public string MapReference + { + get + { + /* 10km (2-figure) Grid Reference: SO84 = 380000 Easting 240000 Northing 1km (4-figure) Grid Reference: NS2468 = 224000 Easting 668000 Northing 100m (6-figure) Grid Reference: TL123456 = 512300 Easting 245600 Northing */ - var easting = this.Easting; - var northing = this.Northing; + var easting = this.Easting; + var northing = this.Northing; - var bngSquare = GetBngSquare (easting, northing); + var bngSquare = GetBngSquare(easting, northing); - //get the number of complete 500k squares - var indexNorthing = (int)Math.Floor (northing / 500000); - var indexEasting = (int)Math.Floor (easting / 500000); + //get the number of complete 500k squares + var indexNorthing = (int)Math.Floor(northing / 500000); + var indexEasting = (int)Math.Floor(easting / 500000); - //reduce E and N by the number of 500k squares - northing = northing - indexNorthing * 500000; - easting = easting - indexEasting * 500000; + //reduce E and N by the number of 500k squares + northing = northing - indexNorthing * 500000; + easting = easting - indexEasting * 500000; - //reduce by the number of 100k squares within the 500k square. - indexNorthing = (int)Math.Floor (northing) / 100000; - indexEasting = (int)Math.Floor (easting) / 100000; + //reduce by the number of 100k squares within the 500k square. + indexNorthing = (int)Math.Floor(northing) / 100000; + indexEasting = (int)Math.Floor(easting) / 100000; - northing = northing - indexNorthing * 100000; - easting = easting - indexEasting * 100000; + northing = northing - indexNorthing * 100000; + easting = easting - indexEasting * 100000; - northing = Math.Round (northing / 100); - easting = Math.Round (easting / 100); - return string.Format ("{0}{1}{2}", bngSquare, Math.Round (easting).ToString("000"), Math.Round (northing).ToString ("000")); - } - } + northing = Math.Round(northing / 100); + easting = Math.Round(easting / 100); + return string.Format("{0}{1}{2}", bngSquare, Math.Round(easting).ToString("000"), Math.Round(northing).ToString("000")); + } + } - /// - /// Returns the two letter OS code based on easting and northing in metres. - /// - /// The square with northing. - /// Northing. - /// Easting. - public static string GetBngSquare(double easting, double northing) - { - var result = string.Empty; + /// + /// Returns the two letter OS code based on easting and northing in metres. + /// + /// The square with northing. + /// Northing. + /// Easting. + public static string GetBngSquare(double easting, double northing) + { + var result = string.Empty; - //test for our upper and lower limits - if (easting >=0 && easting < 700000 && northing >=0 && northing < 1300000) - { + //test for our upper and lower limits + if (easting >= 0 && easting < 700000 && northing >= 0 && northing < 1300000) + { + var firstChar = new char[6] { 'S', 'N', 'H', 'T', 'O', 'J' }; + var secondChar = new char[25] { 'V', 'Q', 'L', 'F', 'A', 'W', 'R', 'M', 'G', 'B', 'X', 'S', 'N', 'H', 'C', 'Y', 'T', 'O', 'J', 'D', 'Z', 'U', 'P', 'K', 'E' }; - var firstChar = new char[6] { 'S', 'N', 'H', 'T', 'O', 'J' }; - var secondChar = new char[25] {'V', 'Q', 'L', 'F', 'A', 'W', 'R', 'M', 'G', 'B', 'X', 'S', 'N', 'H', 'C', 'Y', 'T', 'O', 'J', 'D', 'Z', 'U', 'P', 'K', 'E'}; + //calculate the first letter + var indexNorthing = (int)Math.Floor(northing / 500000); + var indexEasting = (int)Math.Floor(easting / 500000); - //calculate the first letter - var indexNorthing = (int)Math.Floor(northing / 500000); - var indexEasting = (int)Math.Floor(easting / 500000); + //get the first char + var chr1 = firstChar[(indexEasting * 3) + indexNorthing]; - //get the first char - var chr1 = firstChar[(indexEasting * 3) + indexNorthing]; - - //to get the second letter we subtract the number of 500km sectors calculated above - indexNorthing = (int)Math.Floor((northing - (indexNorthing * 500000)) / 100000); - indexEasting = (int)Math.Floor((easting - (indexEasting * 500000))/ 100000); - - //get the second char - var chr2 = secondChar[(indexEasting * 5) + indexNorthing]; - - result = string.Format("{0}{1}", chr1, chr2); - - } - return result; - } + //to get the second letter we subtract the number of 500km sectors calculated above + indexNorthing = (int)Math.Floor((northing - (indexNorthing * 500000)) / 100000); + indexEasting = (int)Math.Floor((easting - (indexEasting * 500000)) / 100000); + //get the second char + var chr2 = secondChar[(indexEasting * 5) + indexNorthing]; + result = string.Format("{0}{1}", chr1, chr2); + } + return result; + } } -} +} \ No newline at end of file diff --git a/GeoUK/Ellipsoids/Airy1830.cs b/GeoUK/Ellipsoids/Airy1830.cs index a0c959c..e1caa84 100644 --- a/GeoUK/Ellipsoids/Airy1830.cs +++ b/GeoUK/Ellipsoids/Airy1830.cs @@ -1,16 +1,12 @@ -using System; - namespace GeoUK.Ellipsoids { - /// /// This immutable class, derived from Ellipsoid, represents an Airy1930 ellipsoid and is provided for convienience. /// public class Airy1830 : Ellipsoid - { - private const double C_SEMI_MAJOR_AXIS = 6377563.396; //a - private const double C_SEMI_MINOR_AXIS = 6356256.909; //b - + { + private const double C_SEMI_MAJOR_AXIS = 6377563.396; //a + private const double C_SEMI_MINOR_AXIS = 6356256.909; //b /// /// Constructor. @@ -19,7 +15,5 @@ namespace GeoUK.Ellipsoids : base(C_SEMI_MAJOR_AXIS, C_SEMI_MINOR_AXIS) { } - - } -} - + } +} \ No newline at end of file diff --git a/GeoUK/Ellipsoids/Airy1830Modified.cs b/GeoUK/Ellipsoids/Airy1830Modified.cs index 7e022e8..2be515c 100644 --- a/GeoUK/Ellipsoids/Airy1830Modified.cs +++ b/GeoUK/Ellipsoids/Airy1830Modified.cs @@ -1,16 +1,12 @@ -using System; - namespace GeoUK.Ellipsoids { - /// /// This immutable class, derived from Ellipsoid, represents an Airy1930 ellipsoid and is provided for convienience. /// public class Airy1830Modified : Ellipsoid - { - private const double C_SEMI_MAJOR_AXIS = 6377340.189; //a - private const double C_SEMI_MINOR_AXIS = 6356034.447; //b - + { + private const double C_SEMI_MAJOR_AXIS = 6377340.189; //a + private const double C_SEMI_MINOR_AXIS = 6356034.447; //b /// /// Constructor. @@ -19,7 +15,5 @@ namespace GeoUK.Ellipsoids : base(C_SEMI_MAJOR_AXIS, C_SEMI_MINOR_AXIS) { } - - } -} - + } +} \ No newline at end of file diff --git a/GeoUK/Ellipsoids/Ellipsoid.cs b/GeoUK/Ellipsoids/Ellipsoid.cs index 3c3f5d0..b38e81c 100644 --- a/GeoUK/Ellipsoids/Ellipsoid.cs +++ b/GeoUK/Ellipsoids/Ellipsoid.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace GeoUK.Ellipsoids { @@ -9,12 +7,11 @@ namespace GeoUK.Ellipsoids /// public class Ellipsoid { - private double _semiMajorAxis = 0.0; private double _semiMinorAxis = 0.0; private double _eccentricity = 0.0; private double _eccentricitySquared = 0.0; - + /// /// Constructor. /// @@ -27,6 +24,7 @@ namespace GeoUK.Ellipsoids _eccentricitySquared = (Math.Pow(semiMajorAxis, 2) - Math.Pow(semiMinorAxis, 2)) / Math.Pow(semiMajorAxis, 2); _eccentricity = Math.Sqrt(_eccentricitySquared); } + /// /// Calculates the Radius of curvature for a given latitude. /// @@ -43,6 +41,7 @@ namespace GeoUK.Ellipsoids //return (C_SEMI_MAJOR_AXIS / Math.Pow((1 - m_EccentricitySquared * Math.Pow(Math.Sin(dblRadians),2)), 0.5)); return _semiMajorAxis / Math.Pow((1 - _eccentricitySquared * Math.Pow(Math.Sin(dblRadians), 2)), 0.5); } + /// /// Returns the semi-major axis of the ellipsoid. /// @@ -53,6 +52,7 @@ namespace GeoUK.Ellipsoids return _semiMajorAxis; } } + /// /// Returns the semi-major axis of the ellipsoid. /// @@ -63,6 +63,7 @@ namespace GeoUK.Ellipsoids return _semiMinorAxis; } } + /// /// returns the eccentricity of the ellipsoid. /// @@ -73,6 +74,7 @@ namespace GeoUK.Ellipsoids return _eccentricity; } } + /// /// returns the eccentricity squared of the ellipsoid. /// @@ -83,6 +85,7 @@ namespace GeoUK.Ellipsoids return _eccentricitySquared; } } + /// /// returns the second eccentricity squared of the ellipsoid. /// @@ -93,6 +96,7 @@ namespace GeoUK.Ellipsoids return (Math.Pow(_semiMajorAxis, 2) - Math.Pow(_semiMinorAxis, 2)) / Math.Pow(_semiMinorAxis, 2); } } + /// /// Returns radians for a given value of degrees. /// @@ -102,6 +106,7 @@ namespace GeoUK.Ellipsoids { return degrees * (Math.PI / 180); } + /// /// Returns degrees for a given value of radians. /// @@ -112,4 +117,4 @@ namespace GeoUK.Ellipsoids return radians * (180 / Math.PI); } } -} +} \ No newline at end of file diff --git a/GeoUK/Ellipsoids/Grs80.cs b/GeoUK/Ellipsoids/Grs80.cs index f62a009..34721a6 100644 --- a/GeoUK/Ellipsoids/Grs80.cs +++ b/GeoUK/Ellipsoids/Grs80.cs @@ -1,5 +1,3 @@ -using System; - namespace GeoUK.Ellipsoids { /// @@ -9,6 +7,7 @@ namespace GeoUK.Ellipsoids { //WGS constants private const double C_SEMI_MAJOR_AXIS = 6378137; //a + private const double C_SEMI_MINOR_AXIS = 6356752.314; //b /// @@ -18,7 +17,5 @@ namespace GeoUK.Ellipsoids : base(C_SEMI_MAJOR_AXIS, C_SEMI_MINOR_AXIS) { } - } -} - +} \ No newline at end of file diff --git a/GeoUK/Ellipsoids/Hayford1909.cs b/GeoUK/Ellipsoids/Hayford1909.cs index 077f5b2..4fcf958 100644 --- a/GeoUK/Ellipsoids/Hayford1909.cs +++ b/GeoUK/Ellipsoids/Hayford1909.cs @@ -1,21 +1,18 @@ -using System; - -namespace GeoUK.Ellipsoids +namespace GeoUK.Ellipsoids { - public class Hayford1909 : Ellipsoid - { - //WGS constants - private const double C_SEMI_MAJOR_AXIS = 6378388; //a - private const double C_SEMI_MINOR_AXIS = 6356911.946; //b + public class Hayford1909 : Ellipsoid + { + //WGS constants + private const double C_SEMI_MAJOR_AXIS = 6378388; //a - /// - /// Constructor. - /// - public Hayford1909() - : base(C_SEMI_MAJOR_AXIS, C_SEMI_MINOR_AXIS) - { - } - - } -} + private const double C_SEMI_MINOR_AXIS = 6356911.946; //b + /// + /// Constructor. + /// + public Hayford1909() + : base(C_SEMI_MAJOR_AXIS, C_SEMI_MINOR_AXIS) + { + } + } +} \ No newline at end of file diff --git a/GeoUK/Ellipsoids/Wgs84.cs b/GeoUK/Ellipsoids/Wgs84.cs index 3e9fccd..1cf1718 100644 --- a/GeoUK/Ellipsoids/Wgs84.cs +++ b/GeoUK/Ellipsoids/Wgs84.cs @@ -1,5 +1,3 @@ -using System; - namespace GeoUK.Ellipsoids { /// @@ -9,7 +7,9 @@ namespace GeoUK.Ellipsoids { //WGS constants private const double C_SEMI_MAJOR_AXIS = 6378137; //a + private const double C_SEMI_MINOR_AXIS = 6356752.3141; //b + /// /// Constructor. /// @@ -18,5 +18,4 @@ namespace GeoUK.Ellipsoids { } } -} - +} \ No newline at end of file diff --git a/GeoUK/MathEx.cs b/GeoUK/MathEx.cs index 1fd2c78..951a488 100644 --- a/GeoUK/MathEx.cs +++ b/GeoUK/MathEx.cs @@ -2,33 +2,32 @@ namespace GeoUK { - public static class MathEx - { - public static double Secant(double x){ - return 1 / Math.Cos(x); - } - -// Cosecant Cosec(X) = 1 / Sin(X) -// Cotangent Cotan(X) = 1 / Tan(X) -// Inverse Sine Arcsin(X) = Atn(X / Sqr(-X * X + 1)) -// Inverse Cosine Arccos(X) = Atn(-X / Sqr(-X * X + 1)) + 2 * Atn(1) -// Inverse Secant Arcsec(X) = 2 * Atn(1) - Atn(Sgn(X) / Sqr(X * X - 1)) -// Inverse Cosecant Arccosec(X) = Atn(Sgn(X) / Sqr(X * X - 1)) -// Inverse Cotangent Arccotan(X) = 2 * Atn(1) - Atn(X) -// Hyperbolic Sine HSin(X) = (Exp(X) - Exp(-X)) / 2 -// Hyperbolic Cosine HCos(X) = (Exp(X) + Exp(-X)) / 2 -// Hyperbolic Tangent HTan(X) = (Exp(X) - Exp(-X)) / (Exp(X) + Exp(-X)) -// Hyperbolic Secant HSec(X) = 2 / (Exp(X) + Exp(-X)) -// Hyperbolic Cosecant HCosec(X) = 2 / (Exp(X) - Exp(-X)) -// Hyperbolic Cotangent HCotan(X) = (Exp(X) + Exp(-X)) / (Exp(X) - Exp(-X)) -// Inverse Hyperbolic Sine HArcsin(X) = Log(X + Sqr(X * X + 1)) -// Inverse Hyperbolic Cosine HArccos(X) = Log(X + Sqr(X * X - 1)) -// Inverse Hyperbolic Tangent HArctan(X) = Log((1 + X) / (1 - X)) / 2 -// Inverse Hyperbolic Secant HArcsec(X) = Log((Sqr(-X * X + 1) + 1) / X) -// Inverse Hyperbolic Cosecant HArccosec(X) = Log((Sgn(X) * Sqr(X * X + 1) + 1) / X) -// Inverse Hyperbolic Cotangent HArccotan(X) = Log((X + 1) / (X - 1)) / 2 -// Logarithm to base N LogN(X) = Log(X) / Log(N) - - } -} + public static class MathEx + { + public static double Secant(double x) + { + return 1 / Math.Cos(x); + } + // Cosecant Cosec(X) = 1 / Sin(X) + // Cotangent Cotan(X) = 1 / Tan(X) + // Inverse Sine Arcsin(X) = Atn(X / Sqr(-X * X + 1)) + // Inverse Cosine Arccos(X) = Atn(-X / Sqr(-X * X + 1)) + 2 * Atn(1) + // Inverse Secant Arcsec(X) = 2 * Atn(1) - Atn(Sgn(X) / Sqr(X * X - 1)) + // Inverse Cosecant Arccosec(X) = Atn(Sgn(X) / Sqr(X * X - 1)) + // Inverse Cotangent Arccotan(X) = 2 * Atn(1) - Atn(X) + // Hyperbolic Sine HSin(X) = (Exp(X) - Exp(-X)) / 2 + // Hyperbolic Cosine HCos(X) = (Exp(X) + Exp(-X)) / 2 + // Hyperbolic Tangent HTan(X) = (Exp(X) - Exp(-X)) / (Exp(X) + Exp(-X)) + // Hyperbolic Secant HSec(X) = 2 / (Exp(X) + Exp(-X)) + // Hyperbolic Cosecant HCosec(X) = 2 / (Exp(X) - Exp(-X)) + // Hyperbolic Cotangent HCotan(X) = (Exp(X) + Exp(-X)) / (Exp(X) - Exp(-X)) + // Inverse Hyperbolic Sine HArcsin(X) = Log(X + Sqr(X * X + 1)) + // Inverse Hyperbolic Cosine HArccos(X) = Log(X + Sqr(X * X - 1)) + // Inverse Hyperbolic Tangent HArctan(X) = Log((1 + X) / (1 - X)) / 2 + // Inverse Hyperbolic Secant HArcsec(X) = Log((Sqr(-X * X + 1) + 1) / X) + // Inverse Hyperbolic Cosecant HArccosec(X) = Log((Sgn(X) * Sqr(X * X + 1) + 1) / X) + // Inverse Hyperbolic Cotangent HArccotan(X) = Log((X + 1) / (X - 1)) / 2 + // Logarithm to base N LogN(X) = Log(X) / Log(N) + } +} \ No newline at end of file diff --git a/GeoUK/OSTN02Transform.cs b/GeoUK/OSTN02Transform.cs index b7aaa14..a7edc6f 100644 --- a/GeoUK/OSTN02Transform.cs +++ b/GeoUK/OSTN02Transform.cs @@ -1,116 +1,116 @@ -using System; -using GeoUK.Coordinates; -using System.IO; -using System.Collections.Generic; -using System.Reflection; +using GeoUK.Coordinates; using GeoUK.Ellipsoids; using GeoUK.Projections; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; namespace GeoUK { - public static class OSTN02Transform - { - /// - /// Performs an ETRS89 to OSGB36/ODN datum transformation. Accuracy is approximately 10 centimeters. - /// Whilst very accurate this method is much slower than the Helmert transformation. - /// - public static Osgb36 Etrs89ToOsgb(LatitudeLongitude coordinates) - { - var enCoordinates = Convert.ToEastingNorthing (new Grs80 (), new BritishNationalGrid (), coordinates); - return Etrs89ToOsgb (enCoordinates, coordinates.ElipsoidalHeight); - } + public static class OSTN02Transform + { + /// + /// Performs an ETRS89 to OSGB36/ODN datum transformation. Accuracy is approximately 10 centimeters. + /// Whilst very accurate this method is much slower than the Helmert transformation. + /// + public static Osgb36 Etrs89ToOsgb(LatitudeLongitude coordinates) + { + var enCoordinates = Convert.ToEastingNorthing(new Grs80(), new BritishNationalGrid(), coordinates); + return Etrs89ToOsgb(enCoordinates, coordinates.ElipsoidalHeight); + } - private static Osgb36 Etrs89ToOsgb(EastingNorthing coordinates, double ellipsoidHeight) - { - var dataStream = GetEmbeddedOSTN02 (); + private static Osgb36 Etrs89ToOsgb(EastingNorthing coordinates, double ellipsoidHeight) + { + var dataStream = GetEmbeddedOSTN02(); - TextReader tr = new StreamReader(dataStream); - List recordNumbers = new List(); - string[] records = new string[4]; + TextReader tr = new StreamReader(dataStream); + List recordNumbers = new List(); + string[] records = new string[4]; - //determine record numbers - int eastIndex = (int)(coordinates.Easting / 1000.0); - int northIndex = (int)(coordinates.Northing / 1000.0); + //determine record numbers + int eastIndex = (int)(coordinates.Easting / 1000.0); + int northIndex = (int)(coordinates.Northing / 1000.0); - double x0 = eastIndex * 1000; - double y0 = northIndex * 1000; + double x0 = eastIndex * 1000; + double y0 = northIndex * 1000; - //work out the four records - recordNumbers.Add(CalculateRecordNumber(eastIndex, northIndex)); - recordNumbers.Add(CalculateRecordNumber(eastIndex + 1, northIndex)); - recordNumbers.Add(CalculateRecordNumber(eastIndex + 1, northIndex + 1)); - recordNumbers.Add(CalculateRecordNumber(eastIndex, northIndex + 1)); + //work out the four records + recordNumbers.Add(CalculateRecordNumber(eastIndex, northIndex)); + recordNumbers.Add(CalculateRecordNumber(eastIndex + 1, northIndex)); + recordNumbers.Add(CalculateRecordNumber(eastIndex + 1, northIndex + 1)); + recordNumbers.Add(CalculateRecordNumber(eastIndex, northIndex + 1)); - //get records from the data file - int recordsFound = 0; - while (recordsFound < 4) - { - string csvRecord = tr.ReadLine(); - for (int index = 0; index < 4; index++) - { - if (csvRecord.StartsWith (recordNumbers [index].ToString ().Trim () + ",", StringComparison.Ordinal)) { - //dont use add as we need to keep these in same order as record numbers - records [index] = csvRecord; - recordsFound++; - } - } - } + //get records from the data file + int recordsFound = 0; + while (recordsFound < 4) + { + string csvRecord = tr.ReadLine(); + for (int index = 0; index < 4; index++) + { + if (csvRecord.StartsWith(recordNumbers[index].ToString().Trim() + ",", StringComparison.Ordinal)) + { + //dont use add as we need to keep these in same order as record numbers + records[index] = csvRecord; + recordsFound++; + } + } + } - //populate the properties - string[] fields0 = records[0].Split(",".ToCharArray()); - string[] fields1 = records[1].Split(",".ToCharArray()); - string[] fields2 = records[2].Split(",".ToCharArray()); - string[] fields3 = records[3].Split(",".ToCharArray()); + //populate the properties + string[] fields0 = records[0].Split(",".ToCharArray()); + string[] fields1 = records[1].Split(",".ToCharArray()); + string[] fields2 = records[2].Split(",".ToCharArray()); + string[] fields3 = records[3].Split(",".ToCharArray()); - var se0 = System.Convert.ToDouble(fields0[3]); - var se1 = System.Convert.ToDouble(fields1[3]); - var se2 = System.Convert.ToDouble(fields2[3]); - var se3 = System.Convert.ToDouble(fields3[3]); + var se0 = System.Convert.ToDouble(fields0[3]); + var se1 = System.Convert.ToDouble(fields1[3]); + var se2 = System.Convert.ToDouble(fields2[3]); + var se3 = System.Convert.ToDouble(fields3[3]); - var sn0 = System.Convert.ToDouble(fields0[4]); - var sn1 = System.Convert.ToDouble(fields1[4]); - var sn2 = System.Convert.ToDouble(fields2[4]); - var sn3 = System.Convert.ToDouble(fields3[4]); + var sn0 = System.Convert.ToDouble(fields0[4]); + var sn1 = System.Convert.ToDouble(fields1[4]); + var sn2 = System.Convert.ToDouble(fields2[4]); + var sn3 = System.Convert.ToDouble(fields3[4]); - var sg0 = System.Convert.ToDouble(fields0[5]); - var sg1 = System.Convert.ToDouble(fields1[5]); - var sg2 = System.Convert.ToDouble(fields2[5]); - var sg3 = System.Convert.ToDouble(fields3[5]); + var sg0 = System.Convert.ToDouble(fields0[5]); + var sg1 = System.Convert.ToDouble(fields1[5]); + var sg2 = System.Convert.ToDouble(fields2[5]); + var sg3 = System.Convert.ToDouble(fields3[5]); - var dx = coordinates.Easting - x0; - var dy = coordinates.Northing - y0; + var dx = coordinates.Easting - x0; + var dy = coordinates.Northing - y0; - var t = dx / 1000.0; - var u = dy / 1000.0; + var t = dx / 1000.0; + var u = dy / 1000.0; - var se = (1 - t) * (1 - u) * se0 + t * (1 - u) * se1 + t * u * se2 + (1 - t) * u * se3; - var sn = (1 - t) * (1 - u) * sn0 + t * (1 - u) * sn1 + t * u * sn2 + (1 - t) * u * sn3; - var sg = (1 - t) * (1 - u) * sg0 + t * (1 - u) * sg1 + t * u * sg2 + (1 - t) * u * sg3; + var se = (1 - t) * (1 - u) * se0 + t * (1 - u) * se1 + t * u * se2 + (1 - t) * u * se3; + var sn = (1 - t) * (1 - u) * sn0 + t * (1 - u) * sn1 + t * u * sn2 + (1 - t) * u * sn3; + var sg = (1 - t) * (1 - u) * sg0 + t * (1 - u) * sg1 + t * u * sg2 + (1 - t) * u * sg3; - var geoidDatum = (Osgb36GeoidDatum)System.Convert.ToInt32(fields0[6]); + var geoidDatum = (Osgb36GeoidDatum)System.Convert.ToInt32(fields0[6]); - var easting = coordinates.Easting + se; - var northing = coordinates.Northing + sn; - var height = ellipsoidHeight - sg; + var easting = coordinates.Easting + se; + var northing = coordinates.Northing + sn; + var height = ellipsoidHeight - sg; - return new Osgb36(easting, northing, height, geoidDatum); + return new Osgb36(easting, northing, height, geoidDatum); + } - } - - /// - /// Calculates a data file record number. - /// - /// - /// - /// - private static int CalculateRecordNumber(int eastIndex, int northIndex) - { - return eastIndex + (northIndex * 701) + 1; - } - private static Stream GetEmbeddedOSTN02() - { - return ResourceManager.GetEmbeddedResourceStream (typeof(OSTN02Transform).GetTypeInfo ().Assembly, "OSTN02_OSGM02_GB.txt"); - } - } -} + /// + /// Calculates a data file record number. + /// + /// + /// + /// + private static int CalculateRecordNumber(int eastIndex, int northIndex) + { + return eastIndex + (northIndex * 701) + 1; + } + private static Stream GetEmbeddedOSTN02() + { + return ResourceManager.GetEmbeddedResourceStream(typeof(OSTN02Transform).GetTypeInfo().Assembly, "OSTN02_OSGM02_GB.txt"); + } + } +} \ No newline at end of file diff --git a/GeoUK/Projections/BritishNationalGrid.cs b/GeoUK/Projections/BritishNationalGrid.cs index 92f685b..c29a7da 100644 --- a/GeoUK/Projections/BritishNationalGrid.cs +++ b/GeoUK/Projections/BritishNationalGrid.cs @@ -1,7 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Text; - namespace GeoUK.Projections { /// @@ -23,4 +19,4 @@ namespace GeoUK.Projections { } } -} +} \ No newline at end of file diff --git a/GeoUK/Projections/IrishNationalGrid.cs b/GeoUK/Projections/IrishNationalGrid.cs index b67c655..ddc826f 100644 --- a/GeoUK/Projections/IrishNationalGrid.cs +++ b/GeoUK/Projections/IrishNationalGrid.cs @@ -1,7 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Text; - namespace GeoUK.Projections { /// @@ -9,11 +5,11 @@ namespace GeoUK.Projections /// public class IrishNationalGrid : Projection { - private const double SCALE_FACTOR = 1.000035; - private const double E = 200000; - private const double TO_LAT = 53.5; + private const double SCALE_FACTOR = 1.000035; + private const double E = 200000; + private const double TO_LAT = 53.5; private const double TO_LONG = -8; - private const double N_NH = 250000; + private const double N_NH = 250000; /// /// Constructor. @@ -23,4 +19,4 @@ namespace GeoUK.Projections { } } -} +} \ No newline at end of file diff --git a/GeoUK/Projections/Projection.cs b/GeoUK/Projections/Projection.cs index ebcdf52..f1da2f3 100644 --- a/GeoUK/Projections/Projection.cs +++ b/GeoUK/Projections/Projection.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Globalization; namespace GeoUK.Projections @@ -16,7 +14,6 @@ namespace GeoUK.Projections private double _trueOriginEasting = 0.0; private double _trueOriginNorthing = 0.0; - /// /// Constructor. /// @@ -36,6 +33,7 @@ namespace GeoUK.Projections { get { return _scaleFactor; } } + /// /// Returns the Easting coordinate of the true origin. /// @@ -43,6 +41,7 @@ namespace GeoUK.Projections { get { return _trueOriginEasting; } } + /// /// Returns the Northing coordinate of the true origin. /// @@ -50,13 +49,15 @@ namespace GeoUK.Projections { get { return _trueOriginNorthing; } } + /// /// Returns the Latitude coordinate of the true origin for the southern hemisphere. /// public double TrueOriginLatitude { - get{ return _trueOriginLatitude; } + get { return _trueOriginLatitude; } } + /// /// Returns the Longitude coordinate of the true origin for the southern hemisphere. /// @@ -64,6 +65,7 @@ namespace GeoUK.Projections { get { return _trueOriginLongitude; } } + //public static double DegreesToRadians(double degrees) //{ // return degrees * (Math.PI / 180); @@ -109,8 +111,6 @@ namespace GeoUK.Projections } return dblResult; - } - } -} +} \ No newline at end of file diff --git a/GeoUK/Projections/UniversalTransverseMercator.cs b/GeoUK/Projections/UniversalTransverseMercator.cs index 1867941..672ff08 100644 --- a/GeoUK/Projections/UniversalTransverseMercator.cs +++ b/GeoUK/Projections/UniversalTransverseMercator.cs @@ -1,12 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Text; using System.Globalization; namespace GeoUK.Projections { /// - /// This immutable class, derived from Projection, represents the Universal Transverse Mercator projection. + /// This immutable class, derived from Projection, represents the Universal Transverse Mercator projection. /// The class handles all medidian calculations internally. /// public class UniversalTransverseMercator : Projection @@ -16,6 +13,7 @@ namespace GeoUK.Projections private const double TO_LAT = 0; //is this for britain? These will need to be calculated based on the lat and long being transfformed. private const double N_NH = 0; private const double N_SH = 10000000; + /// /// Constructor /// @@ -24,8 +22,8 @@ namespace GeoUK.Projections public UniversalTransverseMercator(double degreesLatitude, double degreesLongitude) : base(SCALE_FACTOR, E, CalculateOriginNorthing(degreesLatitude, degreesLongitude), TO_LAT, CalculateLongitudeOrigin(degreesLatitude, degreesLongitude)) { - } + private static double CalculateOriginNorthing(double degreesLatitude, double degreesLongitude) { double falseNorthing = 0.0; @@ -40,9 +38,9 @@ namespace GeoUK.Projections } return falseNorthing; } + private static double CalculateLongitudeOrigin(double degreesLatitude, double degreesLongitude) { - double longOrigin = 0.0; if (degreesLongitude < 0) @@ -68,9 +66,8 @@ namespace GeoUK.Projections longOrigin = Div(degreesLongitude, 6); longOrigin = (System.Convert.ToInt32(longOrigin, CultureInfo.InvariantCulture)) * 6 + 3; } - } + } return longOrigin; } - } -} +} \ No newline at end of file diff --git a/GeoUK/ResourceManager.cs b/GeoUK/ResourceManager.cs index 8d0c857..00147eb 100644 --- a/GeoUK/ResourceManager.cs +++ b/GeoUK/ResourceManager.cs @@ -1,39 +1,37 @@ using System; using System.IO; -using System.Collections.Generic; -using System.Text; -using System.Reflection; using System.Linq; +using System.Reflection; namespace GeoUK { internal static class ResourceManager { + /// + /// Attempts to find and return the given resource from within the specified assembly. + /// + /// The embedded resource stream. + /// Assembly. + /// Resource file name. + public static Stream GetEmbeddedResourceStream(Assembly assembly, string resourceFileName) + { + var resourceNames = assembly.GetManifestResourceNames(); + var resourcePaths = resourceNames + .Where(x => x.EndsWith(resourceFileName, StringComparison.CurrentCultureIgnoreCase)) + .ToArray(); - /// - /// Attempts to find and return the given resource from within the specified assembly. - /// - /// The embedded resource stream. - /// Assembly. - /// Resource file name. - public static Stream GetEmbeddedResourceStream (Assembly assembly, string resourceFileName) - { - var resourceNames = assembly.GetManifestResourceNames (); + if (!resourcePaths.Any()) + { + throw new Exception(string.Format("Resource ending with {0} not found.", resourceFileName)); + } - var resourcePaths = resourceNames - .Where (x => x.EndsWith (resourceFileName, StringComparison.CurrentCultureIgnoreCase)) - .ToArray (); + if (resourcePaths.Count() > 1) + { + throw new Exception(string.Format("Multiple resources ending with {0} found: {1}{2}", resourceFileName, Environment.NewLine, string.Join(Environment.NewLine, resourcePaths))); + } - if (!resourcePaths.Any ()) { - throw new Exception (string.Format ("Resource ending with {0} not found.", resourceFileName)); - } - - if (resourcePaths.Count () > 1) { - throw new Exception (string.Format ("Multiple resources ending with {0} found: {1}{2}", resourceFileName, Environment.NewLine, string.Join (Environment.NewLine, resourcePaths))); - } - - return assembly.GetManifestResourceStream (resourcePaths.Single ()); - } + return assembly.GetManifestResourceStream(resourcePaths.Single()); + } } -} +} \ No newline at end of file diff --git a/GeoUK/Transform.cs b/GeoUK/Transform.cs index 9e2e1d8..425c763 100644 --- a/GeoUK/Transform.cs +++ b/GeoUK/Transform.cs @@ -1,8 +1,5 @@ -using System; -using System.Globalization; using GeoUK.Coordinates; -using GeoUK.Ellipsoids; -using GeoUK.Projections; +using System; namespace GeoUK { @@ -11,14 +8,13 @@ namespace GeoUK /// public static class Transform { - /// /// Performs an ETRS89 to OSGB36 datum transformation. Accuracy is approximately 5 meters in all directions. /// For this method, ERTS89, ITRS2000 and WGS84 datums can be considered the same. /// /// Cartesian Coordinates to be transformed. /// - /// This method uses a Helmert transformation to determine the OSGB36 coordinates. + /// This method uses a Helmert transformation to determine the OSGB36 coordinates. /// Whilst only accurate to 5 meters in all directions, it is extremely fast. /// public static Cartesian Etrs89ToOsgb36(Cartesian coordinates) @@ -37,9 +33,9 @@ namespace GeoUK Cartesian result = HelmertTransformation(coordinates, tx, ty, tz, rx, ry, rz, s); - return result; - + return result; } + /// /// Performs an OSGB36 to ETRS89 datum transformation. Accuracy is approximately 5 meters in all directions. /// For this method, ERTS89, ITRS2000 and WGS84 datums can be considered the same. @@ -56,22 +52,21 @@ namespace GeoUK double ty = -125.157; double tz = 542.060; double s = -20.4894; - double rx = ToRadians(ToDecimelDegrees(0, 0, 0.1502)); + double rx = ToRadians(ToDecimelDegrees(0, 0, 0.1502)); double ry = ToRadians(ToDecimelDegrees(0, 0, 0.247)); double rz = ToRadians(ToDecimelDegrees(0, 0, 0.8421)); return HelmertTransformation(coordinates, tx, ty, tz, rx, ry, rz, s); + } - } - /* + /* * //(BUT CHANGE SIGNS OF EACH PARAMETER FOR REVERSE) tX (m) tY (m) tZ (m) s (ppm) rX (sec) rY (sec) rZ (sec) -446.448 +125.157 -542.060 +20.4894 -0.1502 -0.2470 -0.8421 - */ - /// + /// /// Performs an ETRS89 to ITRS2000 datum transformation. /// /// Cartesian Coordinates to be transformed. @@ -95,21 +90,21 @@ namespace GeoUK double rz = Negate(ToRadians(ToDecimelDegrees(0, 0, -0.000792) * dt)); return HelmertTransformation(coordinates, tx, ty, tz, rx, ry, rz, s); - } + /// /// Performs an ITRS2000 to ETRS89 datum transformation. /// /// Cartesian Coordinates to be transformed. /// Refers to the year the data specified in coordinates was gathered. /// - public static Cartesian Itrs2000ToEtrs89(Cartesian coordinates, int epochYear ) + public static Cartesian Itrs2000ToEtrs89(Cartesian coordinates, int epochYear) { //tX (m) tY (m) tZ (m) s (ppm) rX (sec) rY (sec) rZ (sec) //0.054 0.051 - 0.048 0 0.000081 dt 0.00049 dt - 0.000792 dt - //dt represents shift in years since time of survey to when ETRS89 was determined - + //dt represents shift in years since time of survey to when ETRS89 was determined + int dt = epochYear - 1989; //set up the parameters double tx = 0.054; @@ -121,8 +116,8 @@ namespace GeoUK double rz = ToRadians(ToDecimelDegrees(0, 0, -0.000792) * dt); return HelmertTransformation(coordinates, tx, ty, tz, rx, ry, rz, s); - } + /// /// Performs an ITRS94/96/97 to ETRS89 datum transformation. /// @@ -149,6 +144,7 @@ namespace GeoUK return HelmertTransformation(coordinates, tx, ty, tz, rx, ry, rz, s); } + /// /// Performs an ETRS89 to ITRS94/96/97 datum transformation. /// @@ -175,25 +171,30 @@ namespace GeoUK return HelmertTransformation(coordinates, tx, ty, tz, rx, ry, rz, s); } - private static double ToDecimelDegrees(int degrees, int minutes, double seconds) + + private static double ToDecimelDegrees(int degrees, int minutes, double seconds) { //determine seconds as minutes double m = minutes + (seconds / 60.0); return ToDecimelDegrees(degrees, m); } - private static double ToDecimelDegrees(int degrees, double minutes) + + private static double ToDecimelDegrees(int degrees, double minutes) { //determine minutes as derees return degrees + (minutes / 60.0); } - private static double ToRadians(double degrees) + + private static double ToRadians(double degrees) { return degrees * (Math.PI / 180.0); } - private static double ToDegrees(double radians) + + private static double ToDegrees(double radians) { return radians * (180.0 / Math.PI); } + /// /// This seven parameter method can be used to transform coordinates between datums. /// @@ -262,6 +263,7 @@ namespace GeoUK //adding to T whilst creating the cartesian coordinates return new Cartesian(T[0] + temp[0], T[1] + temp[1], T[2] + temp[2]); } + /// /// Helper funtion to reverse the sign of a value. Helps code to be more readable. /// @@ -272,4 +274,4 @@ namespace GeoUK return value * -1.0; } } -} +} \ No newline at end of file