mirror of
https://github.com/IeuanWalker/GeoUK.git
synced 2025-10-25 15:19:15 +00:00
code cleaned using CodeMaid
This commit is contained in:
@@ -16,4 +16,4 @@ namespace GeoUK.OSTN.Tests
|
||||
return (Math.Abs(initialValue - value) < maximumDifferenceAllowed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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")]
|
||||
@@ -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<DataPoint>();
|
||||
var outputData = new Dictionary<string, DataPoint>();
|
||||
|
||||
|
||||
using (var inputFile = new StreamReader(inputFileName))
|
||||
{
|
||||
string line;
|
||||
@@ -153,4 +150,4 @@ namespace GeoUK.OSTN.Tests
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,4 @@
|
||||
OSTN02 = 1,
|
||||
OSTN15 = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<int, OstnDataRecord> _ostn02Data;
|
||||
|
||||
public static Dictionary<int, OstnDataRecord> Ostn02Data
|
||||
{
|
||||
get
|
||||
@@ -21,6 +21,7 @@ namespace GeoUK.OSTN
|
||||
}
|
||||
|
||||
private static Dictionary<int, OstnDataRecord> _ostn15Data;
|
||||
|
||||
public static Dictionary<int, OstnDataRecord> Ostn15Data
|
||||
{
|
||||
get
|
||||
@@ -37,7 +38,7 @@ namespace GeoUK.OSTN
|
||||
/// <param name="ostnVersion">If not provided, it will load both OSTN02 and OSTN15 data.</param>
|
||||
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
|
||||
/// <returns>The embedded resource stream.</returns>
|
||||
/// <param name="assembly">Assembly.</param>
|
||||
/// <param name="resourceFileName">Resource file name.</param>
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads the OSTN data into memory.
|
||||
/// </summary>
|
||||
/// <param name="ostnVersion">If not provided, it will load both OSTN02 and OSTN15 data.</param>
|
||||
public static void PreloadResources(OstnVersionEnum? ostnVersion = null)
|
||||
{
|
||||
public static class Transform
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads the OSTN data into memory.
|
||||
/// </summary>
|
||||
/// <param name="ostnVersion">If not provided, it will load both OSTN02 and OSTN15 data.</param>
|
||||
public static void PreloadResources(OstnVersionEnum? ostnVersion = null)
|
||||
{
|
||||
ResourceManager.LoadResources(ostnVersion);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an ETRS89 to OSGB36/ODN datum transformation. Accuracy is approximately 10 centimeters.
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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<int> recordNumbers = new List<int>();
|
||||
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<int> recordNumbers = new List<int> ();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a data file record number.
|
||||
/// </summary>
|
||||
/// <param name="eastIndex"></param>
|
||||
/// <param name="northIndex"></param>
|
||||
/// <returns></returns>
|
||||
private static int CalculateRecordNumber(int eastIndex, int northIndex)
|
||||
{
|
||||
return eastIndex + (northIndex * 701) + 1;
|
||||
}
|
||||
/// <summary>
|
||||
/// Calculates a data file record number.
|
||||
/// </summary>
|
||||
/// <param name="eastIndex"></param>
|
||||
/// <param name="northIndex"></param>
|
||||
/// <returns></returns>
|
||||
private static int CalculateRecordNumber(int eastIndex, int northIndex)
|
||||
{
|
||||
return eastIndex + (northIndex * 701) + 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the parsed OSTN data from the embedded resource file.
|
||||
@@ -151,17 +145,18 @@ namespace GeoUK.OSTN
|
||||
/// <param name="ostnVersion"></param>
|
||||
/// <returns></returns>
|
||||
private static Dictionary<int, OstnDataRecord> GetOstnData(OstnVersionEnum ostnVersion)
|
||||
{
|
||||
{
|
||||
switch (ostnVersion)
|
||||
{
|
||||
case OstnVersionEnum.OSTN02:
|
||||
return ResourceManager.Ostn02Data;
|
||||
|
||||
case OstnVersionEnum.OSTN15:
|
||||
return ResourceManager.Ostn15Data;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
578
GeoUK/Convert.cs
578
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
|
||||
{
|
||||
/// <summary>
|
||||
/// This class performs various generic conversions between coordinate systems and units of measure.
|
||||
/// This class does not perform transformations.
|
||||
/// </summary>
|
||||
public static class Convert
|
||||
{
|
||||
/// <summary>
|
||||
/// Method to convert from Easting Northing coordinates to Latitude Longitude coordinates.
|
||||
/// </summary>
|
||||
/// <returns>The latitude longitude.</returns>
|
||||
/// <param name = "ellipsoid"></param>
|
||||
/// <param name="projection">Projection.</param>
|
||||
/// <param name="coordinates">Coordinates.</param>
|
||||
public static LatitudeLongitude ToLatitudeLongitude (Ellipsoid ellipsoid, Projections.Projection projection, EastingNorthing coordinates)
|
||||
{
|
||||
double M;
|
||||
var N = coordinates.Northing;
|
||||
var E = coordinates.Easting;
|
||||
/// <summary>
|
||||
/// This class performs various generic conversions between coordinate systems and units of measure.
|
||||
/// This class does not perform transformations.
|
||||
/// </summary>
|
||||
public static class Convert
|
||||
{
|
||||
/// <summary>
|
||||
/// Method to convert from Easting Northing coordinates to Latitude Longitude coordinates.
|
||||
/// </summary>
|
||||
/// <returns>The latitude longitude.</returns>
|
||||
/// <param name = "ellipsoid"></param>
|
||||
/// <param name="projection">Projection.</param>
|
||||
/// <param name="coordinates">Coordinates.</param>
|
||||
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);
|
||||
/// <summary>
|
||||
/// Converts decimal degrees to radians.
|
||||
/// </summary>
|
||||
/// <param name="degrees"></param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
/// <summary>
|
||||
/// Converts radians to decimal degrees.
|
||||
/// </summary>
|
||||
/// <param name="radians"></param>
|
||||
/// <returns></returns>
|
||||
public static double ToDegrees(double radians)
|
||||
{
|
||||
return radians * (180 / Math.PI);
|
||||
}
|
||||
|
||||
return M;
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts cartesian coordinates to grid eastings and northings for any Transverse Mercator map projection, including the Ordnance Survey National Grid.
|
||||
/// Ellipsoid height is ignored.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
public static EastingNorthing ToEastingNorthing(Ellipsoid ellipsoid, Projections.Projection projection, Cartesian coordinates)
|
||||
{
|
||||
LatitudeLongitude coords = ToLatitudeLongitude(ellipsoid, coordinates);
|
||||
return ToEastingNorthing(ellipsoid, projection, coords);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
/// <param name="ellipsoid"></param>
|
||||
/// <param name="projection"></param>
|
||||
/// <param name="coordinates"></param>
|
||||
/// <returns></returns>
|
||||
public static EastingNorthing ToEastingNorthing(Ellipsoid ellipsoid, Projections.Projection projection, LatitudeLongitude coordinates)
|
||||
{
|
||||
double lat = ToRadians(coordinates.Latitude);
|
||||
double lon = ToRadians(coordinates.Longitude);
|
||||
|
||||
/// <summary>
|
||||
/// Converts decimal degrees to radians.
|
||||
/// </summary>
|
||||
/// <param name="degrees"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Converts radians to decimal degrees.
|
||||
/// </summary>
|
||||
/// <param name="radians"></param>
|
||||
/// <returns></returns>
|
||||
public static double ToDegrees (double radians)
|
||||
{
|
||||
return radians * (180 / Math.PI);
|
||||
}
|
||||
//B2
|
||||
//double n = (a - b) / (a + b);
|
||||
|
||||
/// <summary>
|
||||
/// Converts cartesian coordinates to grid eastings and northings for any Transverse Mercator map projection, including the Ordnance Survey National Grid.
|
||||
/// Ellipsoid height is ignored.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
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);
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
/// <param name="ellipsoid"></param>
|
||||
/// <param name="projection"></param>
|
||||
/// <param name="coordinates"></param>
|
||||
/// <returns></returns>
|
||||
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
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts latitude, longitude and elipsoidal height coordinates to cartesian coordinates using the same ellipsoid.
|
||||
/// Please note this is not a transformation between ellipsoids.
|
||||
/// </summary>
|
||||
/// <param name="ellipsoid"></param>
|
||||
/// <param name="coordinates"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Converts latitude, longitude and elipsoidal height coordinates to cartesian coordinates using the same ellipsoid.
|
||||
/// Please note this is not a transformation between ellipsoids.
|
||||
/// </summary>
|
||||
/// <param name="ellipsoid"></param>
|
||||
/// <param name="coordinates"></param>
|
||||
/// <returns></returns>
|
||||
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)));
|
||||
/// <summary>
|
||||
/// Converts cartesian coordinates to latitude, longitude and elipsoidal height using the same ellipsoid.
|
||||
/// Please note this is not a transformation between ellipsoids.
|
||||
/// </summary>
|
||||
/// <param name="ellipsoid"></param>
|
||||
/// <param name="coordinates"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Converts cartesian coordinates to latitude, longitude and elipsoidal height using the same ellipsoid.
|
||||
/// Please note this is not a transformation between ellipsoids.
|
||||
/// </summary>
|
||||
/// <param name="ellipsoid"></param>
|
||||
/// <param name="coordinates"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
/// <summary>
|
||||
/// Converts degrees minutes and seconds to decimal degrees.
|
||||
/// </summary>
|
||||
/// <param name="degrees"></param>
|
||||
/// <param name="minutes"></param>
|
||||
/// <param name="seconds"></param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts degrees and decimel minutes to decimal degrees.
|
||||
/// </summary>
|
||||
/// <param name="degrees"></param>
|
||||
/// <param name="minutes"></param>
|
||||
/// <returns></returns>
|
||||
public static double ToDecimelDegrees(int degrees, double minutes)
|
||||
{
|
||||
//determine minutes as derees
|
||||
return degrees + (minutes / 60.0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts degrees minutes and seconds to decimal degrees.
|
||||
/// </summary>
|
||||
/// <param name="degrees"></param>
|
||||
/// <param name="minutes"></param>
|
||||
/// <param name="seconds"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Converts degrees and decimel minutes to decimal degrees.
|
||||
/// </summary>
|
||||
/// <param name="degrees"></param>
|
||||
/// <param name="minutes"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper funtion to reverse the sign of a value. Helps code to be more readable.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
private static double Negate (double value)
|
||||
{
|
||||
return value * -1.0;
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Helper funtion to reverse the sign of a value. Helps code to be more readable.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
private static double Negate(double value)
|
||||
{
|
||||
return value * -1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace GeoUK.Coordinates
|
||||
{
|
||||
/// <summary>
|
||||
@@ -25,6 +21,7 @@ namespace GeoUK.Coordinates
|
||||
_y = y;
|
||||
_z = z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the X axis parameter.
|
||||
/// </summary>
|
||||
@@ -32,6 +29,7 @@ namespace GeoUK.Coordinates
|
||||
{
|
||||
get { return _x; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Y axis parameter.
|
||||
/// </summary>
|
||||
@@ -39,6 +37,7 @@ namespace GeoUK.Coordinates
|
||||
{
|
||||
get { return _y; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Z axis parameter.
|
||||
/// </summary>
|
||||
@@ -46,6 +45,5 @@ namespace GeoUK.Coordinates
|
||||
{
|
||||
get { return _z; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace GeoUK.Coordinates
|
||||
{
|
||||
/// <summary>
|
||||
@@ -10,9 +6,10 @@ namespace GeoUK.Coordinates
|
||||
/// </summary>
|
||||
public class EastingNorthing
|
||||
{
|
||||
double _easting;
|
||||
double _northing;
|
||||
double _height;
|
||||
private double _easting;
|
||||
private double _northing;
|
||||
private double _height;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
@@ -24,6 +21,7 @@ namespace GeoUK.Coordinates
|
||||
_northing = northing;
|
||||
_height = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
@@ -36,6 +34,7 @@ namespace GeoUK.Coordinates
|
||||
_northing = northing;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retruns the easting parameter.
|
||||
/// </summary>
|
||||
@@ -43,6 +42,7 @@ namespace GeoUK.Coordinates
|
||||
{
|
||||
get { return _easting; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns the northing parameter.
|
||||
/// </summary>
|
||||
@@ -50,6 +50,7 @@ namespace GeoUK.Coordinates
|
||||
{
|
||||
get { return _northing; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the height parameter.
|
||||
/// </summary>
|
||||
@@ -58,4 +59,4 @@ namespace GeoUK.Coordinates
|
||||
get { return _height; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace GeoUK.Coordinates
|
||||
{
|
||||
/// <summary>
|
||||
@@ -13,61 +9,75 @@ namespace GeoUK.Coordinates
|
||||
/// Outside Model Boundary
|
||||
/// </summary>
|
||||
OutsideModelBoundary = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Newlyn, Uk Mainland
|
||||
/// </summary>
|
||||
NewlynUkMainland = 1,
|
||||
|
||||
/// <summary>
|
||||
/// StMarys, Scilly Isles
|
||||
/// </summary>
|
||||
StMarysScillyIsles = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Douglas02, Isle of Man
|
||||
/// </summary>
|
||||
Douglas02IsleofMan = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Stornoway, Outer Hebrides
|
||||
/// </summary>
|
||||
StornowayOuterHebrides = 4,
|
||||
|
||||
/// <summary>
|
||||
/// St. Kilda, St. Kilda
|
||||
/// </summary>
|
||||
StKildaStKilda = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Lerwick, Shetland Isles
|
||||
/// </summary>
|
||||
LerwickShetlandIsles = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Newlyn, Orkney Isles
|
||||
/// </summary>
|
||||
NewlynOrkneyIsles = 7,
|
||||
|
||||
/// <summary>
|
||||
/// Fair Isle, Fair Isle
|
||||
/// </summary>
|
||||
FairIsleFairIsle = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Flannan Isles, Flannan Isles
|
||||
/// </summary>
|
||||
FlannanIslesFlannanIsles = 9,
|
||||
|
||||
/// <summary>
|
||||
/// North Rona, North Rona
|
||||
/// </summary>
|
||||
NorthRonaNorthRona = 10,
|
||||
|
||||
/// <summary>
|
||||
/// Sule Skerry, Sule Skerry
|
||||
/// </summary>
|
||||
SuleSkerrySuleSkerry = 11,
|
||||
|
||||
/// <summary>
|
||||
/// Foula, Foula.
|
||||
/// </summary>
|
||||
FoulaFoula = 12,
|
||||
|
||||
/// <summary>
|
||||
/// Malin Head, Republic of Ireland
|
||||
/// </summary>
|
||||
MalinHeadRepublicofIreland = 13,
|
||||
|
||||
/// <summary>
|
||||
/// Belfast, Northern Ireland
|
||||
/// </summary>
|
||||
BelfastNorthernIreland = 14
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace GeoUK.Coordinates
|
||||
{
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// This immutable class represents a set of latitude/longitude/ellipsoidal height coordinates.
|
||||
/// </summary>
|
||||
public class LatitudeLongitude
|
||||
public class LatitudeLongitude
|
||||
|
||||
{
|
||||
{
|
||||
private double _degreesLatitude = 0.0;
|
||||
private double _degreesLongitude = 0.0;
|
||||
private double _elipsoidalHeight = 0.0;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
@@ -22,38 +21,42 @@ namespace GeoUK.Coordinates
|
||||
_degreesLongitude = degreesLongitude;
|
||||
_elipsoidalHeight = 0.0;
|
||||
}
|
||||
/// <summary>
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="degreesLatitude"></param>
|
||||
/// <param name="degreesLongitude"></param>
|
||||
/// <param name="elipsoidalHeight"></param>
|
||||
public LatitudeLongitude(double degreesLatitude, double degreesLongitude, double elipsoidalHeight)
|
||||
{
|
||||
{
|
||||
_degreesLatitude = degreesLatitude;
|
||||
_degreesLongitude = degreesLongitude;
|
||||
_elipsoidalHeight = elipsoidalHeight;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns latitude in degrees.
|
||||
/// </summary>
|
||||
public double Latitude
|
||||
{
|
||||
get
|
||||
{
|
||||
{
|
||||
get
|
||||
{
|
||||
return _degreesLatitude;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns longitude in degrees.
|
||||
/// </summary>
|
||||
public double Longitude
|
||||
{
|
||||
get
|
||||
{
|
||||
{
|
||||
get
|
||||
{
|
||||
return _degreesLongitude;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns elipsoidal height in meters.
|
||||
/// </summary>
|
||||
@@ -65,4 +68,4 @@ namespace GeoUK.Coordinates
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace GeoUK.Coordinates
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
@@ -14,47 +12,47 @@ namespace GeoUK.Coordinates
|
||||
/// </remarks>
|
||||
public class Osgb36 : EastingNorthing
|
||||
{
|
||||
Osgb36GeoidDatum _datum = Osgb36GeoidDatum.OutsideModelBoundary;
|
||||
private Osgb36GeoidDatum _datum = Osgb36GeoidDatum.OutsideModelBoundary;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GeoUK.Coordinates.Osgb36Cordinates"/> class.
|
||||
/// </summary>
|
||||
/// <param name="easting">Easting.</param>
|
||||
/// <param name="northing">Northing.</param>
|
||||
public Osgb36(double easting, double northing)
|
||||
: base(easting, northing, 0)
|
||||
{
|
||||
_datum = Osgb36GeoidDatum.NewlynUkMainland;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GeoUK.Coordinates.Osgb36Cordinates"/> class.
|
||||
/// </summary>
|
||||
/// <param name="easting">Easting.</param>
|
||||
/// <param name="northing">Northing.</param>
|
||||
public Osgb36(double easting, double northing)
|
||||
: base(easting, northing, 0)
|
||||
{
|
||||
_datum = Osgb36GeoidDatum.NewlynUkMainland;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GeoUK.Coordinates.Osgb36Cordinates"/> class.
|
||||
/// </summary>
|
||||
/// <param name="eastingNorthingCoordinates">Easting northing coordinates.</param>
|
||||
public Osgb36(EastingNorthing eastingNorthingCoordinates)
|
||||
: base(eastingNorthingCoordinates.Easting, eastingNorthingCoordinates.Northing, eastingNorthingCoordinates.Height)
|
||||
{
|
||||
_datum = Osgb36GeoidDatum.NewlynUkMainland;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GeoUK.Coordinates.Osgb36Cordinates"/> class.
|
||||
/// </summary>
|
||||
/// <param name="eastingNorthingCoordinates">Easting northing coordinates.</param>
|
||||
public Osgb36(EastingNorthing eastingNorthingCoordinates)
|
||||
: base(eastingNorthingCoordinates.Easting, eastingNorthingCoordinates.Northing, eastingNorthingCoordinates.Height)
|
||||
{
|
||||
_datum = Osgb36GeoidDatum.NewlynUkMainland;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GeoUK.Coordinates.Osgb36Cordinates"/> class.
|
||||
/// </summary>
|
||||
/// <param name="eastingNorthingCoordinates">Easting northing coordinates.</param>
|
||||
/// <param name="datum">Datum.</param>
|
||||
public Osgb36(EastingNorthing eastingNorthingCoordinates, Osgb36GeoidDatum datum)
|
||||
: base(eastingNorthingCoordinates.Easting, eastingNorthingCoordinates.Northing, eastingNorthingCoordinates.Height)
|
||||
{
|
||||
_datum = datum;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GeoUK.Coordinates.Osgb36Cordinates"/> class.
|
||||
/// </summary>
|
||||
/// <param name="eastingNorthingCoordinates">Easting northing coordinates.</param>
|
||||
/// <param name="datum">Datum.</param>
|
||||
public Osgb36(EastingNorthing eastingNorthingCoordinates, Osgb36GeoidDatum datum)
|
||||
: base(eastingNorthingCoordinates.Easting, eastingNorthingCoordinates.Northing, eastingNorthingCoordinates.Height)
|
||||
{
|
||||
_datum = datum;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GeoUK.Coordinates.Osgb36Cordinates"/> class.
|
||||
/// </summary>
|
||||
/// <param name="easting">Easting.</param>
|
||||
/// <param name="northing">Northing.</param>
|
||||
/// <param name="height">Height.</param>
|
||||
/// <param name="datum">Datum.</param>
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GeoUK.Coordinates.Osgb36Cordinates"/> class.
|
||||
/// </summary>
|
||||
/// <param name="easting">Easting.</param>
|
||||
/// <param name="northing">Northing.</param>
|
||||
/// <param name="height">Height.</param>
|
||||
/// <param name="datum">Datum.</param>
|
||||
public Osgb36(double easting, double northing, double height, Osgb36GeoidDatum datum)
|
||||
: base(easting, northing, height)
|
||||
{
|
||||
@@ -62,7 +60,7 @@ namespace GeoUK.Coordinates
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the two letter OS code based on easting and northing in metres.
|
||||
/// </summary>
|
||||
/// <returns>The square with northing.</returns>
|
||||
/// <param name="northing">Northing.</param>
|
||||
/// <param name="easting">Easting.</param>
|
||||
public static string GetBngSquare(double easting, double northing)
|
||||
{
|
||||
var result = string.Empty;
|
||||
/// <summary>
|
||||
/// Returns the two letter OS code based on easting and northing in metres.
|
||||
/// </summary>
|
||||
/// <returns>The square with northing.</returns>
|
||||
/// <param name="northing">Northing.</param>
|
||||
/// <param name="easting">Easting.</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace GeoUK.Ellipsoids
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This immutable class, derived from Ellipsoid, represents an Airy1930 ellipsoid and is provided for convienience.
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
@@ -19,7 +15,5 @@ namespace GeoUK.Ellipsoids
|
||||
: base(C_SEMI_MAJOR_AXIS, C_SEMI_MINOR_AXIS)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace GeoUK.Ellipsoids
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This immutable class, derived from Ellipsoid, represents an Airy1930 ellipsoid and is provided for convienience.
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
@@ -19,7 +15,5 @@ namespace GeoUK.Ellipsoids
|
||||
: base(C_SEMI_MAJOR_AXIS, C_SEMI_MINOR_AXIS)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace GeoUK.Ellipsoids
|
||||
{
|
||||
@@ -9,12 +7,11 @@ namespace GeoUK.Ellipsoids
|
||||
/// </summary>
|
||||
public class Ellipsoid
|
||||
{
|
||||
|
||||
private double _semiMajorAxis = 0.0;
|
||||
private double _semiMinorAxis = 0.0;
|
||||
private double _eccentricity = 0.0;
|
||||
private double _eccentricitySquared = 0.0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
@@ -27,6 +24,7 @@ namespace GeoUK.Ellipsoids
|
||||
_eccentricitySquared = (Math.Pow(semiMajorAxis, 2) - Math.Pow(semiMinorAxis, 2)) / Math.Pow(semiMajorAxis, 2);
|
||||
_eccentricity = Math.Sqrt(_eccentricitySquared);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Radius of curvature for a given latitude.
|
||||
/// </summary>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the semi-major axis of the ellipsoid.
|
||||
/// </summary>
|
||||
@@ -53,6 +52,7 @@ namespace GeoUK.Ellipsoids
|
||||
return _semiMajorAxis;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the semi-major axis of the ellipsoid.
|
||||
/// </summary>
|
||||
@@ -63,6 +63,7 @@ namespace GeoUK.Ellipsoids
|
||||
return _semiMinorAxis;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns the eccentricity of the ellipsoid.
|
||||
/// </summary>
|
||||
@@ -73,6 +74,7 @@ namespace GeoUK.Ellipsoids
|
||||
return _eccentricity;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns the eccentricity squared of the ellipsoid.
|
||||
/// </summary>
|
||||
@@ -83,6 +85,7 @@ namespace GeoUK.Ellipsoids
|
||||
return _eccentricitySquared;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns the second eccentricity squared of the ellipsoid.
|
||||
/// </summary>
|
||||
@@ -93,6 +96,7 @@ namespace GeoUK.Ellipsoids
|
||||
return (Math.Pow(_semiMajorAxis, 2) - Math.Pow(_semiMinorAxis, 2)) / Math.Pow(_semiMinorAxis, 2);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns radians for a given value of degrees.
|
||||
/// </summary>
|
||||
@@ -102,6 +106,7 @@ namespace GeoUK.Ellipsoids
|
||||
{
|
||||
return degrees * (Math.PI / 180);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns degrees for a given value of radians.
|
||||
/// </summary>
|
||||
@@ -112,4 +117,4 @@ namespace GeoUK.Ellipsoids
|
||||
return radians * (180 / Math.PI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
using System;
|
||||
|
||||
namespace GeoUK.Ellipsoids
|
||||
{
|
||||
/// <summary>
|
||||
@@ -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
|
||||
|
||||
/// <summary>
|
||||
@@ -18,7 +17,5 @@ namespace GeoUK.Ellipsoids
|
||||
: base(C_SEMI_MAJOR_AXIS, C_SEMI_MINOR_AXIS)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
public Hayford1909()
|
||||
: base(C_SEMI_MAJOR_AXIS, C_SEMI_MINOR_AXIS)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
private const double C_SEMI_MINOR_AXIS = 6356911.946; //b
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
public Hayford1909()
|
||||
: base(C_SEMI_MAJOR_AXIS, C_SEMI_MINOR_AXIS)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
using System;
|
||||
|
||||
namespace GeoUK.Ellipsoids
|
||||
{
|
||||
/// <summary>
|
||||
@@ -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
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
@@ -18,5 +18,4 @@ namespace GeoUK.Ellipsoids
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public static Osgb36 Etrs89ToOsgb(LatitudeLongitude coordinates)
|
||||
{
|
||||
var enCoordinates = Convert.ToEastingNorthing (new Grs80 (), new BritishNationalGrid (), coordinates);
|
||||
return Etrs89ToOsgb (enCoordinates, coordinates.ElipsoidalHeight);
|
||||
}
|
||||
public static class OSTN02Transform
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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<int> recordNumbers = new List<int>();
|
||||
string[] records = new string[4];
|
||||
TextReader tr = new StreamReader(dataStream);
|
||||
List<int> recordNumbers = new List<int>();
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a data file record number.
|
||||
/// </summary>
|
||||
/// <param name="eastIndex"></param>
|
||||
/// <param name="northIndex"></param>
|
||||
/// <returns></returns>
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Calculates a data file record number.
|
||||
/// </summary>
|
||||
/// <param name="eastIndex"></param>
|
||||
/// <param name="northIndex"></param>
|
||||
/// <returns></returns>
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace GeoUK.Projections
|
||||
{
|
||||
/// <summary>
|
||||
@@ -23,4 +19,4 @@ namespace GeoUK.Projections
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace GeoUK.Projections
|
||||
{
|
||||
/// <summary>
|
||||
@@ -9,11 +5,11 @@ namespace GeoUK.Projections
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
@@ -23,4 +19,4 @@ namespace GeoUK.Projections
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
@@ -36,6 +33,7 @@ namespace GeoUK.Projections
|
||||
{
|
||||
get { return _scaleFactor; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Easting coordinate of the true origin.
|
||||
/// </summary>
|
||||
@@ -43,6 +41,7 @@ namespace GeoUK.Projections
|
||||
{
|
||||
get { return _trueOriginEasting; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Northing coordinate of the true origin.
|
||||
/// </summary>
|
||||
@@ -50,13 +49,15 @@ namespace GeoUK.Projections
|
||||
{
|
||||
get { return _trueOriginNorthing; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Latitude coordinate of the true origin for the southern hemisphere.
|
||||
/// </summary>
|
||||
public double TrueOriginLatitude
|
||||
{
|
||||
get{ return _trueOriginLatitude; }
|
||||
get { return _trueOriginLatitude; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Longitude coordinate of the true origin for the southern hemisphere.
|
||||
/// </summary>
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
|
||||
namespace GeoUK.Projections
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Attempts to find and return the given resource from within the specified assembly.
|
||||
/// </summary>
|
||||
/// <returns>The embedded resource stream.</returns>
|
||||
/// <param name="assembly">Assembly.</param>
|
||||
/// <param name="resourceFileName">Resource file name.</param>
|
||||
public static Stream GetEmbeddedResourceStream(Assembly assembly, string resourceFileName)
|
||||
{
|
||||
var resourceNames = assembly.GetManifestResourceNames();
|
||||
|
||||
var resourcePaths = resourceNames
|
||||
.Where(x => x.EndsWith(resourceFileName, StringComparison.CurrentCultureIgnoreCase))
|
||||
.ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to find and return the given resource from within the specified assembly.
|
||||
/// </summary>
|
||||
/// <returns>The embedded resource stream.</returns>
|
||||
/// <param name="assembly">Assembly.</param>
|
||||
/// <param name="resourceFileName">Resource file name.</param>
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
/// </summary>
|
||||
public static class Transform
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="coordinates">Cartesian Coordinates to be transformed.</param>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Performs an ETRS89 to ITRS2000 datum transformation.
|
||||
/// </summary>
|
||||
/// <param name="coordinates">Cartesian Coordinates to be transformed.</param>
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an ITRS2000 to ETRS89 datum transformation.
|
||||
/// </summary>
|
||||
/// <param name="coordinates">Cartesian Coordinates to be transformed.</param>
|
||||
/// <param name="epochYear">Refers to the year the data specified in coordinates was gathered.</param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an ITRS94/96/97 to ETRS89 datum transformation.
|
||||
/// </summary>
|
||||
@@ -149,6 +144,7 @@ namespace GeoUK
|
||||
|
||||
return HelmertTransformation(coordinates, tx, ty, tz, rx, ry, rz, s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an ETRS89 to ITRS94/96/97 datum transformation.
|
||||
/// </summary>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This seven parameter method can be used to transform coordinates between datums.
|
||||
/// </summary>
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper funtion to reverse the sign of a value. Helps code to be more readable.
|
||||
/// </summary>
|
||||
@@ -272,4 +274,4 @@ namespace GeoUK
|
||||
return value * -1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user