Code updates based on Codacy and updated test project from .net framework to .net core

This commit is contained in:
Ieuan Walker
2019-07-16 13:20:17 +01:00
parent 8f5c72a3dd
commit cdc3855537
20 changed files with 416 additions and 542 deletions

View File

@@ -3,9 +3,9 @@ using DemoProject.Examples;
namespace DemoProject
{
class Program
internal class Program
{
static void Main()
private static void Main()
{
EastingNorthingToLatitudeLongitude.Example();

View File

@@ -1,138 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\xunit.runner.visualstudio.2.4.1\build\net20\xunit.runner.visualstudio.props" Condition="Exists('..\packages\xunit.runner.visualstudio.2.4.1\build\net20\xunit.runner.visualstudio.props')" />
<Import Project="..\packages\Microsoft.NET.Test.Sdk.16.2.0\build\net40\Microsoft.NET.Test.Sdk.props" Condition="Exists('..\packages\Microsoft.NET.Test.Sdk.16.2.0\build\net40\Microsoft.NET.Test.Sdk.props')" />
<Import Project="..\packages\Microsoft.CodeCoverage.16.2.0\build\netstandard1.0\Microsoft.CodeCoverage.props" Condition="Exists('..\packages\Microsoft.CodeCoverage.16.2.0\build\netstandard1.0\Microsoft.CodeCoverage.props')" />
<Import Project="..\packages\xunit.core.2.4.1\build\xunit.core.props" Condition="Exists('..\packages\xunit.core.2.4.1\build\xunit.core.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{7DAF4F03-B372-43B2-A22C-64C2790BCF68}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GeoUK.OSTN.Tests</RootNamespace>
<AssemblyName>GeoUK.OSTN.Tests</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.CodeCoverage.Shim, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeCoverage.16.2.0\lib\net45\Microsoft.VisualStudio.CodeCoverage.Shim.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll</HintPath>
</Reference>
<Reference Include="xunit.assert, Version=2.4.1.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.assert.2.4.1\lib\netstandard1.1\xunit.assert.dll</HintPath>
</Reference>
<Reference Include="xunit.core, Version=2.4.1.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.core.2.4.1\lib\net452\xunit.core.dll</HintPath>
</Reference>
<Reference Include="xunit.execution.desktop, Version=2.4.1.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.execution.2.4.1\lib\net452\xunit.execution.desktop.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ExtensionMethods.cs" />
<Compile Include="Models\DataPoint.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TransformTests.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSGM15_NI_TestInput_ETRS89toIG.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSGM15_NI_TestInput_IGtoETRS89.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSGM15_NI_TestOutput_ETRS89toIG.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSGM15_NI_TestOutput_IGtoETRS89.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestFiles_README.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestInput_ETRStoOSGB.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestInput_OSGBtoETRS.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestOutput_ETRStoOSGB.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestOutput_OSGBtoETRS.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GeoUK.OSTN\GeoUK.OSTN.csproj">
<Project>{e7c614ac-e67d-4e04-ba4e-e1bbf4cac6fd}</Project>
<Name>GeoUK.OSTN</Name>
</ProjectReference>
<ProjectReference Include="..\GeoUK\GeoUK.csproj">
<Project>{5c458fbf-4e2a-4f9d-acc2-9ce5bed34236}</Project>
<Name>GeoUK</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\packages\xunit.analyzers.0.10.0\analyzers\dotnet\cs\xunit.analyzers.dll" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\xunit.core.2.4.1\build\xunit.core.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.core.2.4.1\build\xunit.core.props'))" />
<Error Condition="!Exists('..\packages\xunit.core.2.4.1\build\xunit.core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.core.2.4.1\build\xunit.core.targets'))" />
<Error Condition="!Exists('..\packages\Microsoft.CodeCoverage.16.2.0\build\netstandard1.0\Microsoft.CodeCoverage.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeCoverage.16.2.0\build\netstandard1.0\Microsoft.CodeCoverage.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.CodeCoverage.16.2.0\build\netstandard1.0\Microsoft.CodeCoverage.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeCoverage.16.2.0\build\netstandard1.0\Microsoft.CodeCoverage.targets'))" />
<Error Condition="!Exists('..\packages\Microsoft.NET.Test.Sdk.16.2.0\build\net40\Microsoft.NET.Test.Sdk.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.NET.Test.Sdk.16.2.0\build\net40\Microsoft.NET.Test.Sdk.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.NET.Test.Sdk.16.2.0\build\net40\Microsoft.NET.Test.Sdk.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.NET.Test.Sdk.16.2.0\build\net40\Microsoft.NET.Test.Sdk.targets'))" />
<Error Condition="!Exists('..\packages\xunit.runner.visualstudio.2.4.1\build\net20\xunit.runner.visualstudio.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.runner.visualstudio.2.4.1\build\net20\xunit.runner.visualstudio.props'))" />
</Target>
<Import Project="..\packages\xunit.core.2.4.1\build\xunit.core.targets" Condition="Exists('..\packages\xunit.core.2.4.1\build\xunit.core.targets')" />
<Import Project="..\packages\Microsoft.CodeCoverage.16.2.0\build\netstandard1.0\Microsoft.CodeCoverage.targets" Condition="Exists('..\packages\Microsoft.CodeCoverage.16.2.0\build\netstandard1.0\Microsoft.CodeCoverage.targets')" />
<Import Project="..\packages\Microsoft.NET.Test.Sdk.16.2.0\build\net40\Microsoft.NET.Test.Sdk.targets" Condition="Exists('..\packages\Microsoft.NET.Test.Sdk.16.2.0\build\net40\Microsoft.NET.Test.Sdk.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// 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")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("GeoUK.OSTN.Tests")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[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
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("7daf4f03-b372-43b2-a22c-64c2790bcf68")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// 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")]

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.CodeCoverage" version="16.2.0" targetFramework="net472" />
<package id="Microsoft.NET.Test.Sdk" version="16.2.0" targetFramework="net472" />
<package id="xunit" version="2.4.1" targetFramework="net472" />
<package id="xunit.abstractions" version="2.0.3" targetFramework="net472" />
<package id="xunit.analyzers" version="0.10.0" targetFramework="net472" />
<package id="xunit.assert" version="2.4.1" targetFramework="net472" />
<package id="xunit.core" version="2.4.1" targetFramework="net472" />
<package id="xunit.extensibility.core" version="2.4.1" targetFramework="net472" />
<package id="xunit.extensibility.execution" version="2.4.1" targetFramework="net472" />
<package id="xunit.runner.visualstudio" version="2.4.1" targetFramework="net472" developmentDependency="true" />
</packages>

View File

@@ -1,6 +1,6 @@
using System;
namespace GeoUK.OSTN.Tests
namespace GeoUK.OSTN.XUnit
{
// Source: https://scottlilly.com/c-tip-how-to-check-if-two-double-values-are-equal/
public static class ExtensionMethods

View File

@@ -0,0 +1,64 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<None Remove="TestDataFiles_OSGM15_OSTN15\OSGM15_NI_TestInput_ETRS89toIG.txt" />
<None Remove="TestDataFiles_OSGM15_OSTN15\OSGM15_NI_TestInput_IGtoETRS89.txt" />
<None Remove="TestDataFiles_OSGM15_OSTN15\OSGM15_NI_TestOutput_ETRS89toIG.txt" />
<None Remove="TestDataFiles_OSGM15_OSTN15\OSGM15_NI_TestOutput_IGtoETRS89.txt" />
<None Remove="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestFiles_README.txt" />
<None Remove="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestInput_ETRStoOSGB.txt" />
<None Remove="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestInput_OSGBtoETRS.txt" />
<None Remove="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestOutput_ETRStoOSGB.txt" />
<None Remove="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestOutput_OSGBtoETRS.txt" />
</ItemGroup>
<ItemGroup>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSGM15_NI_TestInput_ETRS89toIG.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSGM15_NI_TestInput_IGtoETRS89.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSGM15_NI_TestOutput_ETRS89toIG.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSGM15_NI_TestOutput_IGtoETRS89.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestFiles_README.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestInput_ETRStoOSGB.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestInput_OSGBtoETRS.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestOutput_ETRStoOSGB.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestDataFiles_OSGM15_OSTN15\OSTN15_OSGM15_TestOutput_OSGBtoETRS.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GeoUK.OSTN\GeoUK.OSTN.csproj" />
<ProjectReference Include="..\GeoUK\GeoUK.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,4 +1,4 @@
namespace GeoUK.OSTN.Tests.Models
namespace GeoUK.OSTN.XUnit.Models
{
public class DataPoint
{

View File

@@ -1,11 +1,11 @@
using GeoUK.Coordinates;
using GeoUK.OSTN.Tests.Models;
using System;
using System;
using System.Collections.Generic;
using System.IO;
using GeoUK.Coordinates;
using GeoUK.OSTN.XUnit.Models;
using Xunit;
namespace GeoUK.OSTN.Tests
namespace GeoUK.OSTN.XUnit
{
public class TransformTests
{

View File

@@ -7,11 +7,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeoUK.OSTN", "GeoUK.OSTN\Ge
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeoUK", "GeoUK\GeoUK.csproj", "{5C458FBF-4E2A-4F9D-ACC2-9CE5BED34236}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeoUK.OSTN.Tests", "GeoUK.OSTN.Tests\GeoUK.OSTN.Tests.csproj", "{7DAF4F03-B372-43B2-A22C-64C2790BCF68}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Demo", "Demo", "{848710E1-EBD1-44BA-9F97-C24D760806E9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DemoProject", "Demo\DemoProject\DemoProject.csproj", "{1BB0810A-37FF-4F68-8C7E-E687A5369E0C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DemoProject", "Demo\DemoProject\DemoProject.csproj", "{1BB0810A-37FF-4F68-8C7E-E687A5369E0C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeoUK.OSTN.XUnit", "GeoUK.OSTN.XUnit\GeoUK.OSTN.XUnit.csproj", "{FA7CD528-E649-49A7-8C3A-0BAB8B2C0E34}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -27,14 +27,14 @@ Global
{5C458FBF-4E2A-4F9D-ACC2-9CE5BED34236}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5C458FBF-4E2A-4F9D-ACC2-9CE5BED34236}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5C458FBF-4E2A-4F9D-ACC2-9CE5BED34236}.Release|Any CPU.Build.0 = Release|Any CPU
{7DAF4F03-B372-43B2-A22C-64C2790BCF68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7DAF4F03-B372-43B2-A22C-64C2790BCF68}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7DAF4F03-B372-43B2-A22C-64C2790BCF68}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7DAF4F03-B372-43B2-A22C-64C2790BCF68}.Release|Any CPU.Build.0 = Release|Any CPU
{1BB0810A-37FF-4F68-8C7E-E687A5369E0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1BB0810A-37FF-4F68-8C7E-E687A5369E0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1BB0810A-37FF-4F68-8C7E-E687A5369E0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1BB0810A-37FF-4F68-8C7E-E687A5369E0C}.Release|Any CPU.Build.0 = Release|Any CPU
{FA7CD528-E649-49A7-8C3A-0BAB8B2C0E34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FA7CD528-E649-49A7-8C3A-0BAB8B2C0E34}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA7CD528-E649-49A7-8C3A-0BAB8B2C0E34}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA7CD528-E649-49A7-8C3A-0BAB8B2C0E34}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -5,281 +5,278 @@ using System;
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, Projection projection, EastingNorthing coordinates)
{
double M;
double N = coordinates.Northing;
double 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, Projection projection, EastingNorthing coordinates)
{
double M;
double N = coordinates.Northing;
double 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;
double lat = ((N - N0) / (a * F0)) + lat0;
//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;
double lat = ((N - N0) / (a * F0)) + lat0;
//check for error and reiterate as required
int loopCount = 0;
do
{
M = CalculateM(lat, lat0, a, b, F0);
//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));
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;
double VII = Math.Tan(lat) / (2 * p * v);
double VII = Math.Tan(lat) / (2 * p * v);
double VIIIa = Math.Tan(lat) / (24 * p * Math.Pow(v, 3));
double VIIIb = 5 + (3 * Math.Pow(Math.Tan(lat), 2)) + n2 - 9 * (Math.Pow(Math.Tan(lat), 2)) * n2;
double VIII = VIIIa * VIIIb;
double VIIIa = Math.Tan(lat) / (24 * p * Math.Pow(v, 3));
double VIIIb = 5 + (3 * Math.Pow(Math.Tan(lat), 2)) + n2 - 9 * (Math.Pow(Math.Tan(lat), 2)) * n2;
double VIII = VIIIa * VIIIb;
double IXa = Math.Tan(lat) / (720 * p * Math.Pow(v, 5));
double IXb = 61 + (90 * Math.Pow(Math.Tan(lat), 2)) + (45 * Math.Pow(Math.Tan(lat), 4));
double IX = IXa * IXb;
double IXa = Math.Tan(lat) / (720 * p * Math.Pow(v, 5));
double IXb = 61 + (90 * Math.Pow(Math.Tan(lat), 2)) + (45 * Math.Pow(Math.Tan(lat), 4));
double IX = IXa * IXb;
double X = MathEx.Secant(lat) / v;
double X = MathEx.Secant(lat) / v;
double XIa = MathEx.Secant(lat) / (6 * Math.Pow(v, 3));
double XIb = v / p + (2 * Math.Pow(Math.Tan(lat), 2));
double XI = XIa * XIb;
double XIa = MathEx.Secant(lat) / (6 * Math.Pow(v, 3));
double XIb = v / p + (2 * Math.Pow(Math.Tan(lat), 2));
double XI = XIa * XIb;
double XIIa = MathEx.Secant(lat) / (120 * Math.Pow(v, 5));
double XIIb = 5 + (28 * Math.Pow(Math.Tan(lat), 2)) + (24 * Math.Pow(Math.Tan(lat), 4));
double XII = XIIa * XIIb;
double XIIa = MathEx.Secant(lat) / (120 * Math.Pow(v, 5));
double XIIb = 5 + (28 * Math.Pow(Math.Tan(lat), 2)) + (24 * Math.Pow(Math.Tan(lat), 4));
double XII = XIIa * XIIb;
double XIIAa = MathEx.Secant(lat) / (5040 * Math.Pow(v, 7));
double XIIAb = 61 + (662 * Math.Pow(Math.Tan(lat), 2)) + (1320 * Math.Pow(Math.Tan(lat), 4)) + (720 * Math.Pow(Math.Tan(lat), 6));
double XIIA = XIIAa * XIIAb;
double XIIAa = MathEx.Secant(lat) / (5040 * Math.Pow(v, 7));
double XIIAb = 61 + (662 * Math.Pow(Math.Tan(lat), 2)) + (1320 * Math.Pow(Math.Tan(lat), 4)) + (720 * Math.Pow(Math.Tan(lat), 6));
double XIIA = XIIAa * XIIAb;
lat = lat - VII * Math.Pow(E - E0, 2) + VIII * Math.Pow(E - E0, 4) - IX * Math.Pow(E - E0, 6);
double 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);
double lon = lon0 + X * (E - E0) - XI * Math.Pow(E - E0, 3) + XII * Math.Pow(E - E0, 5) - XIIA * Math.Pow(E - E0, 7);
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 *= -1;
}
private static bool IsNearlyZero(double x, double tolerance)
{
if (x < 0)
{
x *= -1;
}
return (x < 0 && x > tolerance * -1) || (x >= 0 && x < tolerance);
}
return (x < 0 && x > tolerance * -1) || (x >= 0 && x < tolerance);
}
private static double CalculateM(double latitude, double latitudeOrigin, double semiMajorAxis, double semiMinorAxis, double scaleFactor)
{
double n = (semiMajorAxis - semiMinorAxis) / (semiMajorAxis + semiMinorAxis);
private static double CalculateM(double latitude, double latitudeOrigin, double semiMajorAxis, double semiMinorAxis, double scaleFactor)
{
double n = (semiMajorAxis - semiMinorAxis) / (semiMajorAxis + semiMinorAxis);
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);
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;
}
return M;
}
/// <summary>
/// Converts decimal degrees to radians.
/// </summary>
/// <param name="degrees"></param>
/// <returns></returns>
public static double ToRadians(double degrees) => degrees * (Math.PI / 180);
/// <summary>
/// Converts decimal degrees to radians.
/// </summary>
/// <param name="degrees"></param>
/// <returns></returns>
public static double ToRadians(double degrees) => degrees * (Math.PI / 180);
/// <summary>
/// Converts radians to decimal degrees.
/// </summary>
/// <param name="radians"></param>
/// <returns></returns>
public static double ToDegrees(double radians) => radians * (180 / Math.PI);
/// <summary>
/// Converts radians to decimal degrees.
/// </summary>
/// <param name="radians"></param>
/// <returns></returns>
public static double ToDegrees(double radians) => radians * (180 / Math.PI);
/// <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, Projection projection, Cartesian coordinates)
{
LatitudeLongitude coords = ToLatitudeLongitude(ellipsoid, coordinates);
return ToEastingNorthing(ellipsoid, projection, coords);
}
/// <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, 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, Projection projection, LatitudeLongitude coordinates)
{
double lat = ToRadians(coordinates.Latitude);
double lon = ToRadians(coordinates.Longitude);
/// <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, Projection projection, LatitudeLongitude coordinates)
{
double lat = ToRadians(coordinates.Latitude);
double lon = ToRadians(coordinates.Longitude);
//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;
//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);
//B3
double v = a * F0 * Math.Pow((1 - e2 * Math.Pow(Math.Sin(lat), 2)), -0.5);
//B3
double v = a * F0 * Math.Pow((1 - e2 * Math.Pow(Math.Sin(lat), 2)), -0.5);
//B4
double p = a * F0 * (1 - e2) * Math.Pow((1 - e2 * Math.Pow(Math.Sin(lat), 2)), -1.5);
//B4
double p = a * F0 * (1 - e2) * Math.Pow((1 - e2 * Math.Pow(Math.Sin(lat), 2)), -1.5);
//B5
double n2 = v / p - 1;
//B5
double n2 = v / p - 1;
//B6
double M = CalculateM(lat, lat0, a, b, F0);
//B6
double M = CalculateM(lat, lat0, a, b, F0);
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);
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);
//B7
double N = I + (II * Math.Pow((lon - lon0), 2)) + (III * Math.Pow((lon - lon0), 4)) + (IIIA * Math.Pow((lon - lon0), 6));
//B7
double N = I + (II * Math.Pow((lon - lon0), 2)) + (III * Math.Pow((lon - lon0), 4)) + (IIIA * Math.Pow((lon - lon0), 6));
//B8
double E = E0 + (IV * (lon - lon0)) + (V * Math.Pow((lon - lon0), 3)) + (VI * Math.Pow((lon - lon0), 5));
//B8
double E = E0 + (IV * (lon - lon0)) + (V * Math.Pow((lon - lon0), 3)) + (VI * Math.Pow((lon - lon0), 5));
return new EastingNorthing(E, N, coordinates.EllipsoidalHeight); //height is still with respect to the ellipsoid
}
return new EastingNorthing(E, N, coordinates.EllipsoidalHeight); //height is still with respect to the ellipsoid
}
public static Cartesian ToCartesian(Ellipsoid ellipsoid, Projection projection, EastingNorthing coordinates)
{
LatitudeLongitude latLongCoordinates = ToLatitudeLongitude(
ellipsoid,
projection,
coordinates);
public static Cartesian ToCartesian(Ellipsoid ellipsoid, Projection projection, EastingNorthing coordinates)
{
LatitudeLongitude latLongCoordinates = ToLatitudeLongitude(
ellipsoid,
projection,
coordinates);
return ToCartesian(ellipsoid, latLongCoordinates);
}
return ToCartesian(ellipsoid, latLongCoordinates);
}
/// <summary>
/// Converts latitude, longitude and ellipsoidal 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.EllipsoidalHeight;
/// <summary>
/// Converts latitude, longitude and ellipsoidal 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.EllipsoidalHeight;
double e2 = ellipsoid.EccentricitySquared;
double a = ellipsoid.SemiMajorAxis;
double e2 = ellipsoid.EccentricitySquared;
double a = ellipsoid.SemiMajorAxis;
double v = a / Math.Sqrt(1 - (e2 * Math.Pow(Math.Sin(lat), 2)));
double v = a / Math.Sqrt(1 - (e2 * Math.Pow(Math.Sin(lat), 2)));
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 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);
return new Cartesian(x, y, z);
}
return new Cartesian(x, y, z);
}
/// <summary>
/// Converts cartesian coordinates to latitude, longitude and ellipsoidal 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);
/// <summary>
/// Converts cartesian coordinates to latitude, longitude and ellipsoidal 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);
//have a first stab
double v = 0.0;
double lat = Math.Atan(coordinates.Z / (p * (1 - e2)));
//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;
//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;
return new LatitudeLongitude(ToDegrees(lat), ToDegrees(lon), height);
}
return new LatitudeLongitude(ToDegrees(lat), ToDegrees(lon), height);
}
/// <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 ToDecimalDegrees(int degrees, int minutes, double seconds)
{
//determine seconds as minutes
double m = minutes + (seconds / 60.0);
return ToDecimalDegrees(degrees, m);
}
/// <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 ToDecimalDegrees(int degrees, int minutes, double seconds)
{
//determine seconds as minutes
double m = minutes + (seconds / 60.0);
return ToDecimalDegrees(degrees, m);
}
/// <summary>
/// Converts degrees and decimal minutes to decimal degrees.
/// </summary>
/// <param name="degrees"></param>
/// <param name="minutes"></param>
/// <returns></returns>
public static double ToDecimalDegrees(int degrees, double minutes) => degrees + (minutes / 60.0);
}
/// <summary>
/// Converts degrees and decimal minutes to decimal degrees.
/// </summary>
/// <param name="degrees"></param>
/// <param name="minutes"></param>
/// <returns></returns>
public static double ToDecimalDegrees(int degrees, double minutes) => degrees + (minutes / 60.0);
}
}

View File

@@ -2,135 +2,134 @@ using System;
namespace GeoUK.Coordinates
{
/// <summary>
/// This immutable class, derived from EastingNorthingCoordinates, provides a convenient means
/// to represent OSGB36 eastings and northings.
/// </summary>
/// <remarks>
/// Eastings and northings are represented in British National Grid and Height is specified
/// in meters based on the geoid datum returned by the RegionGeoidDatum property.
/// </remarks>
public class Osgb36 : EastingNorthing
{
/// <summary>
/// This immutable class, derived from EastingNorthingCoordinates, provides a convenient means
/// to represent OSGB36 eastings and northings.
/// </summary>
/// <remarks>
/// Eastings and northings are represented in British National Grid and Height is specified
/// in meters based on the geoid datum returned by the RegionGeoidDatum property.
/// </remarks>
public class Osgb36 : EastingNorthing
{
/// <summary>
/// Initializes a new instance of the <see cref="Coordinates.Osgb36Cordinates"/> class.
/// </summary>
/// <param name="easting">Easting.</param>
/// <param name="northing">Northing.</param>
public Osgb36(double easting, double northing)
: base(easting, northing, 0)
{
RegionGeoidDatum = Osgb36GeoidDatum.NewlynUkMainland;
}
/// <summary>
/// Initializes a new instance of the <see cref="Coordinates.Osgb36Cordinates"/> class.
/// </summary>
/// <param name="easting">Easting.</param>
/// <param name="northing">Northing.</param>
public Osgb36(double easting, double northing)
: base(easting, northing, 0)
{
RegionGeoidDatum = Osgb36GeoidDatum.NewlynUkMainland;
}
/// <summary>
/// Initializes a new instance of the <see cref="Coordinates.Osgb36Cordinates"/> class.
/// </summary>
/// <param name="eastingNorthingCoordinates">Easting northing coordinates.</param>
public Osgb36(EastingNorthing eastingNorthingCoordinates)
: base(eastingNorthingCoordinates.Easting, eastingNorthingCoordinates.Northing, eastingNorthingCoordinates.Height)
{
RegionGeoidDatum = Osgb36GeoidDatum.NewlynUkMainland;
}
/// <summary>
/// Initializes a new instance of the <see cref="Coordinates.Osgb36Cordinates"/> class.
/// </summary>
/// <param name="eastingNorthingCoordinates">Easting northing coordinates.</param>
public Osgb36(EastingNorthing eastingNorthingCoordinates)
: base(eastingNorthingCoordinates.Easting, eastingNorthingCoordinates.Northing, eastingNorthingCoordinates.Height)
{
RegionGeoidDatum = Osgb36GeoidDatum.NewlynUkMainland;
}
/// <summary>
/// Initializes a new instance of the <see cref="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)
{
RegionGeoidDatum = datum;
}
/// <summary>
/// Initializes a new instance of the <see cref="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)
{
RegionGeoidDatum = datum;
}
/// <summary>
/// Initializes a new instance of the <see cref="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)
{
RegionGeoidDatum = datum;
}
/// <summary>
/// Initializes a new instance of the <see cref="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)
{
RegionGeoidDatum = datum;
}
/// <summary>
/// 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 { get; }
/// <summary>
/// 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 { get; }
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
*/
double easting = Easting;
double northing = Northing;
double easting = Easting;
double northing = Northing;
string bngSquare = GetBngSquare(easting, northing);
string bngSquare = GetBngSquare(easting, northing);
//get the number of complete 500k squares
int indexNorthing = (int)Math.Floor(northing / 500000);
int indexEasting = (int)Math.Floor(easting / 500000);
//get the number of complete 500k squares
int indexNorthing = (int)Math.Floor(northing / 500000);
int indexEasting = (int)Math.Floor(easting / 500000);
//reduce E and N by the number of 500k squares
northing -= indexNorthing * 500000;
easting -= indexEasting * 500000;
//reduce E and N by the number of 500k squares
northing -= indexNorthing * 500000;
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 -= indexNorthing * 100000;
easting -= indexEasting * 100000;
northing -= indexNorthing * 100000;
easting -= indexEasting * 100000;
northing = Math.Round(northing / 100);
easting = Math.Round(easting / 100);
return $"{bngSquare}{Math.Round(easting):000}{Math.Round(northing):000}";
}
}
northing = Math.Round(northing / 100);
easting = Math.Round(easting / 100);
return $"{bngSquare}{Math.Round(easting):000}{Math.Round(northing):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)
{
string 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)
{
string result = string.Empty;
//test for our upper and lower limits
if (!(easting >= 0) || !(easting < 700000) || !(northing >= 0) || !(northing < 1300000)) return result;
//test for our upper and lower limits
if (easting < 0 || easting > 700000 || northing < 0 || northing > 1300000) return result;
char[] firstChar = { 'S', 'N', 'H', 'T', 'O', 'J' };
char[] secondChar = { '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' };
char[] firstChar = { 'S', 'N', 'H', 'T', 'O', 'J' };
char[] secondChar = { '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
int indexNorthing = (int)Math.Floor(northing / 500000);
int indexEasting = (int)Math.Floor(easting / 500000);
//calculate the first letter
int indexNorthing = (int)Math.Floor(northing / 500000);
int indexEasting = (int)Math.Floor(easting / 500000);
//get the first char
char chr1 = firstChar[(indexEasting * 3) + indexNorthing];
//get the first char
char 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);
//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
char chr2 = secondChar[(indexEasting * 5) + indexNorthing];
//get the second char
char chr2 = secondChar[(indexEasting * 5) + indexNorthing];
result = $"{chr1}{chr2}";
return result;
}
}
result = $"{chr1}{chr2}";
return result;
}
}
}