Change all line endings to Unix-style.

Windows users with core.autocrlf set to true will actually see an improvement.
This commit is contained in:
Joe Amenta 2019-07-03 06:04:29 -04:00
Родитель 75f0cb843c
Коммит 351d134506
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: AD51C2580E479CD4
57 изменённых файлов: 16883 добавлений и 16883 удалений

380
.gitignore поставляемый
Просмотреть файл

@ -1,190 +1,190 @@
# Created by http://www.gitignore.io
### VisualStudio ###
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Roslyn cache directories
*.ide/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
#NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# If using the old MSBuild-Integrated Package Restore, uncomment this:
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
*.vs/
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
/packages
**/BenchmarkDotNet*/
/ProjNet/CoordinateSystems/Transformations/MathTransformFactory.cs
# Created by http://www.gitignore.io
### VisualStudio ###
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Roslyn cache directories
*.ide/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
#NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# If using the old MSBuild-Integrated Package Restore, uncomment this:
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
*.vs/
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
/packages
**/BenchmarkDotNet*/
/ProjNet/CoordinateSystems/Transformations/MathTransformFactory.cs

Просмотреть файл

@ -1,101 +1,101 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Xml.Linq;
using NUnit.Framework;
using ProjNet;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNET.Tests
{
public class CoordinateSystemServicesTest
{
[Test]
public void TestConstructor()
{
var css = new CoordinateSystemServices(new CoordinateSystemFactory(),
new CoordinateTransformationFactory());
Assert.IsNotNull(css.GetCoordinateSystem(4326));
Assert.IsNotNull(css.GetCoordinateSystem(3857));
}
[TestCase(@"D:\temp\ConsoleApplication9\SpatialRefSys.xml")]
public void TestConstructorLoadXml(string xmlPath)
{
if (!File.Exists(xmlPath))
throw new IgnoreException("Specified file not found");
var css = new CoordinateSystemServices(new CoordinateSystemFactory(),
new CoordinateTransformationFactory(), LoadXml(xmlPath));
Assert.IsNotNull(css.GetCoordinateSystem(4326));
Assert.IsNotNull(css.GetCoordinateSystem("EPSG", 4326));
Assert.IsTrue(ReferenceEquals(css.GetCoordinateSystem("EPSG", 4326), css.GetCoordinateSystem(4326)));
}
[TestCase(@"")]
public void TestConstructorLoadCsv(string csvPath)
{
if (!string.IsNullOrWhiteSpace(csvPath))
if (!File.Exists(csvPath))
throw new IgnoreException("Specified file not found");
var css = new CoordinateSystemServices(new CoordinateSystemFactory(),
new CoordinateTransformationFactory(), LoadCsv(csvPath));
Assert.IsNotNull(css.GetCoordinateSystem(4326));
Assert.IsNotNull(css.GetCoordinateSystem("EPSG", 4326));
Assert.IsTrue(ReferenceEquals(css.GetCoordinateSystem("EPSG", 4326), css.GetCoordinateSystem(4326)));
Thread.Sleep(1000);
}
internal static IEnumerable<KeyValuePair<int, string>> LoadCsv(string csvPath = null)
{
Console.WriteLine("Reading '{0}'.", csvPath ?? "SRID.csv from resources stream");
var sw = new Stopwatch();
sw.Start();
foreach (var sridWkt in SRIDReader.GetSrids(csvPath))
yield return new KeyValuePair<int, string>(sridWkt.WktId, sridWkt.Wkt);
sw.Stop();
Console.WriteLine("Read '{1}' in {0:N0}ms", sw.ElapsedMilliseconds, csvPath ?? "SRID.csv from resources stream");
}
private static IEnumerable<KeyValuePair<int, string>> LoadXml(string xmlPath)
{
var stream = System.IO.File.OpenRead(xmlPath);
Console.WriteLine("Reading '{0}'.", xmlPath);
var sw = new Stopwatch();
sw.Start();
var document = XDocument.Load(stream);
var rs = from tmp in document.Elements("SpatialReference").Elements("ReferenceSystem") select tmp;
foreach (var node in rs)
{
var sridElement = node.Element("SRID");
if (sridElement != null)
{
var srid = int.Parse(sridElement.Value);
yield return new KeyValuePair<int, string>(srid, node.LastNode.ToString());
}
}
sw.Stop();
Console.WriteLine("Read '{1}' in {0:N0}ms", sw.ElapsedMilliseconds, xmlPath);
}
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Xml.Linq;
using NUnit.Framework;
using ProjNet;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNET.Tests
{
public class CoordinateSystemServicesTest
{
[Test]
public void TestConstructor()
{
var css = new CoordinateSystemServices(new CoordinateSystemFactory(),
new CoordinateTransformationFactory());
Assert.IsNotNull(css.GetCoordinateSystem(4326));
Assert.IsNotNull(css.GetCoordinateSystem(3857));
}
[TestCase(@"D:\temp\ConsoleApplication9\SpatialRefSys.xml")]
public void TestConstructorLoadXml(string xmlPath)
{
if (!File.Exists(xmlPath))
throw new IgnoreException("Specified file not found");
var css = new CoordinateSystemServices(new CoordinateSystemFactory(),
new CoordinateTransformationFactory(), LoadXml(xmlPath));
Assert.IsNotNull(css.GetCoordinateSystem(4326));
Assert.IsNotNull(css.GetCoordinateSystem("EPSG", 4326));
Assert.IsTrue(ReferenceEquals(css.GetCoordinateSystem("EPSG", 4326), css.GetCoordinateSystem(4326)));
}
[TestCase(@"")]
public void TestConstructorLoadCsv(string csvPath)
{
if (!string.IsNullOrWhiteSpace(csvPath))
if (!File.Exists(csvPath))
throw new IgnoreException("Specified file not found");
var css = new CoordinateSystemServices(new CoordinateSystemFactory(),
new CoordinateTransformationFactory(), LoadCsv(csvPath));
Assert.IsNotNull(css.GetCoordinateSystem(4326));
Assert.IsNotNull(css.GetCoordinateSystem("EPSG", 4326));
Assert.IsTrue(ReferenceEquals(css.GetCoordinateSystem("EPSG", 4326), css.GetCoordinateSystem(4326)));
Thread.Sleep(1000);
}
internal static IEnumerable<KeyValuePair<int, string>> LoadCsv(string csvPath = null)
{
Console.WriteLine("Reading '{0}'.", csvPath ?? "SRID.csv from resources stream");
var sw = new Stopwatch();
sw.Start();
foreach (var sridWkt in SRIDReader.GetSrids(csvPath))
yield return new KeyValuePair<int, string>(sridWkt.WktId, sridWkt.Wkt);
sw.Stop();
Console.WriteLine("Read '{1}' in {0:N0}ms", sw.ElapsedMilliseconds, csvPath ?? "SRID.csv from resources stream");
}
private static IEnumerable<KeyValuePair<int, string>> LoadXml(string xmlPath)
{
var stream = System.IO.File.OpenRead(xmlPath);
Console.WriteLine("Reading '{0}'.", xmlPath);
var sw = new Stopwatch();
sw.Start();
var document = XDocument.Load(stream);
var rs = from tmp in document.Elements("SpatialReference").Elements("ReferenceSystem") select tmp;
foreach (var node in rs)
{
var sridElement = node.Element("SRID");
if (sridElement != null)
{
var srid = int.Parse(sridElement.Value);
yield return new KeyValuePair<int, string>(srid, node.LastNode.ToString());
}
}
sw.Stop();
Console.WriteLine("Read '{1}' in {0:N0}ms", sw.ElapsedMilliseconds, xmlPath);
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,90 +1,90 @@
using System;
using System.Globalization;
using NetTopologySuite.Geometries;
using NetTopologySuite.Geometries.Implementation;
using NUnit.Framework;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
using ProjNET.Tests.Geometries.Implementation;
namespace ProjNET.Tests
{
public class CoordinateTransformTestsBase
{
protected readonly CoordinateSystemFactory CoordinateSystemFactory = new CoordinateSystemFactory();
protected readonly CoordinateTransformationFactory CoordinateTransformationFactory = new CoordinateTransformationFactory();
public CoordinateSequence CreateSequence(string sequenceTypeName, Coordinate[] coordinates)
{
switch (sequenceTypeName)
{
case "CoordinateArraySequence":
return CoordinateArraySequenceFactory.Instance.Create(coordinates);
case "PackedDoubleCoordinateSequence":
return PackedCoordinateSequenceFactory.DoubleFactory.Create(coordinates);
case "PackedFloatCoordinateSequence":
return PackedCoordinateSequenceFactory.FloatFactory.Create(coordinates);
case "DotSpatialAffineCoordinateSequence":
return DotSpatialAffineCoordinateSequenceFactory.Instance.Create(coordinates);
case "SpanCoordinateSequence":
return SpanCoordinateSequenceFactory.Instance.Create(coordinates);
}
throw new NotSupportedException($"Creation of {sequenceTypeName} not supported");
}
protected bool Verbose { get; set; }
protected bool ToleranceLessThan(double[] p1, double[] p2, double tolerance)
{
double d0 = Math.Abs(p1[0] - p2[0]);
double d1 = Math.Abs(p1[1] - p2[1]);
if (p1.Length > 2 && p2.Length > 2)
{
double d2 = Math.Abs(p1[2] - p2[2]);
if (Verbose)
Console.WriteLine("Allowed Tolerance {3}; got dx: {0}, dy: {1}, dz {2}", d0, d1, d2, tolerance);
return d0 < tolerance && d1 < tolerance && d2 < tolerance;
}
Console.WriteLine();
if (Verbose)
Console.WriteLine("Allowed tolerance {2}; got dx: {0}, dy: {1}", d0, d1, tolerance);
return d0 < tolerance && d1 < tolerance;
}
protected string TransformationError(string projection, double[] pExpected, double[] pResult, bool reverse = false)
{
return string.Format(CultureInfo.InvariantCulture,
"{6} {7} transformation outside tolerance!\n\tExpected [{0}, {1}],\n\tgot [{2}, {3}],\n\tdelta [{4}, {5}]",
pExpected[0], pExpected[1],
pResult[0], pResult[1],
pExpected[0]-pResult[0], pExpected[1]-pResult[1],
projection, reverse ? "reverse" : "forward");
}
public void Test(string title, CoordinateSystem source, CoordinateSystem target,
double[] testPoint, double[] expectedPoint,
double tolerance, double reverseTolerance = double.NaN)
{
var ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(source, target);
double[] forwardResult = ct.MathTransform.Transform(testPoint);
double[] reverseResult = double.IsNaN(reverseTolerance)
? testPoint
: ct.MathTransform.Inverse().Transform(forwardResult);
bool forward = ToleranceLessThan(forwardResult, expectedPoint, tolerance);
bool reverse = double.IsNaN(reverseTolerance) ||
ToleranceLessThan(reverseResult, testPoint, reverseTolerance);
if (!forward)
TransformationError(title, expectedPoint, forwardResult);
if (!reverse)
TransformationError(title, testPoint, reverseResult, true);
Assert.IsTrue(forward && reverse);
}
}
}
using System;
using System.Globalization;
using NetTopologySuite.Geometries;
using NetTopologySuite.Geometries.Implementation;
using NUnit.Framework;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
using ProjNET.Tests.Geometries.Implementation;
namespace ProjNET.Tests
{
public class CoordinateTransformTestsBase
{
protected readonly CoordinateSystemFactory CoordinateSystemFactory = new CoordinateSystemFactory();
protected readonly CoordinateTransformationFactory CoordinateTransformationFactory = new CoordinateTransformationFactory();
public CoordinateSequence CreateSequence(string sequenceTypeName, Coordinate[] coordinates)
{
switch (sequenceTypeName)
{
case "CoordinateArraySequence":
return CoordinateArraySequenceFactory.Instance.Create(coordinates);
case "PackedDoubleCoordinateSequence":
return PackedCoordinateSequenceFactory.DoubleFactory.Create(coordinates);
case "PackedFloatCoordinateSequence":
return PackedCoordinateSequenceFactory.FloatFactory.Create(coordinates);
case "DotSpatialAffineCoordinateSequence":
return DotSpatialAffineCoordinateSequenceFactory.Instance.Create(coordinates);
case "SpanCoordinateSequence":
return SpanCoordinateSequenceFactory.Instance.Create(coordinates);
}
throw new NotSupportedException($"Creation of {sequenceTypeName} not supported");
}
protected bool Verbose { get; set; }
protected bool ToleranceLessThan(double[] p1, double[] p2, double tolerance)
{
double d0 = Math.Abs(p1[0] - p2[0]);
double d1 = Math.Abs(p1[1] - p2[1]);
if (p1.Length > 2 && p2.Length > 2)
{
double d2 = Math.Abs(p1[2] - p2[2]);
if (Verbose)
Console.WriteLine("Allowed Tolerance {3}; got dx: {0}, dy: {1}, dz {2}", d0, d1, d2, tolerance);
return d0 < tolerance && d1 < tolerance && d2 < tolerance;
}
Console.WriteLine();
if (Verbose)
Console.WriteLine("Allowed tolerance {2}; got dx: {0}, dy: {1}", d0, d1, tolerance);
return d0 < tolerance && d1 < tolerance;
}
protected string TransformationError(string projection, double[] pExpected, double[] pResult, bool reverse = false)
{
return string.Format(CultureInfo.InvariantCulture,
"{6} {7} transformation outside tolerance!\n\tExpected [{0}, {1}],\n\tgot [{2}, {3}],\n\tdelta [{4}, {5}]",
pExpected[0], pExpected[1],
pResult[0], pResult[1],
pExpected[0]-pResult[0], pExpected[1]-pResult[1],
projection, reverse ? "reverse" : "forward");
}
public void Test(string title, CoordinateSystem source, CoordinateSystem target,
double[] testPoint, double[] expectedPoint,
double tolerance, double reverseTolerance = double.NaN)
{
var ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(source, target);
double[] forwardResult = ct.MathTransform.Transform(testPoint);
double[] reverseResult = double.IsNaN(reverseTolerance)
? testPoint
: ct.MathTransform.Inverse().Transform(forwardResult);
bool forward = ToleranceLessThan(forwardResult, expectedPoint, tolerance);
bool reverse = double.IsNaN(reverseTolerance) ||
ToleranceLessThan(reverseResult, testPoint, reverseTolerance);
if (!forward)
TransformationError(title, expectedPoint, forwardResult);
if (!reverse)
TransformationError(title, testPoint, reverseResult, true);
Assert.IsTrue(forward && reverse);
}
}
}

Просмотреть файл

@ -1,42 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<SolutionDir Condition=" '$(SolutionDir)' == '' ">$(ProjectDir)..\</SolutionDir>
<TargetFramework>netcoreapp2.2</TargetFramework>
<SignAssembly>true</SignAssembly>
<NoWarn>1701;1702;1591</NoWarn>
<IsPackable>false</IsPackable>
</PropertyGroup>
<Import Project="$(SolutionDir)ProjNet.Common.props" />
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
<PackageReference Include="NetTopologySuite" Version="2.0.0-pre001" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="Npgsql" Version="4.0.5" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)ProjNet\ProjNET.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="TestData\*.wkt" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="SRID.csv" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
</Project>
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<SolutionDir Condition=" '$(SolutionDir)' == '' ">$(ProjectDir)..\</SolutionDir>
<TargetFramework>netcoreapp2.2</TargetFramework>
<SignAssembly>true</SignAssembly>
<NoWarn>1701;1702;1591</NoWarn>
<IsPackable>false</IsPackable>
</PropertyGroup>
<Import Project="$(SolutionDir)ProjNet.Common.props" />
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
<PackageReference Include="NetTopologySuite" Version="2.0.0-pre001" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="Npgsql" Version="4.0.5" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)ProjNet\ProjNET.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="TestData\*.wkt" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="SRID.csv" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,237 +1,237 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using ProjNet.CoordinateSystems;
namespace ProjNET.Tests
{
[TestFixture]
public class ProjNetIssues : CoordinateTransformTestsBase
{
public ProjNetIssues()
{
Verbose = true;
}
[Test, Description("WGS_84UTM to WGS_84 is inaccurate")]
public void TestIssue23773()
{
var csUtm18N = ProjectedCoordinateSystem.WGS84_UTM(18, true);
var csUtm18NWkt = CoordinateSystemFactory.CreateFromWkt(
"PROJCS[\"WGS 84 / UTM zone 18N\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-75],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"32618\"],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]");
var csWgs84 = GeographicCoordinateSystem.WGS84;
var ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(csUtm18N, csWgs84);
var ct2 = CoordinateTransformationFactory.CreateFromCoordinateSystems(csUtm18NWkt, csWgs84);
double[] putm = new[] {307821.867d, 4219306.387d};
double[] pgeo = ct.MathTransform.Transform(putm);
double[] pgeoWkt = ct2.MathTransform.Transform(putm);
double[] pExpected = new[] {-77.191769, 38.101147d};
Assert.IsTrue(ToleranceLessThan(pgeoWkt, pExpected, 0.00001d),
TransformationError("UTM18N -> WGS84", pExpected, pgeo));
Assert.IsTrue(ToleranceLessThan(pgeo, pExpected, 0.00001d),
TransformationError("UTM18N -> WGS84", pExpected, pgeo));
}
[Test, Description("Proj.net reprojection problem, Discussion http://projnet.codeplex.com/discussions/351733")]
public void TestDiscussion351733()
{
var csSource = CoordinateSystemFactory.CreateFromWkt(
"PROJCS[\"Pulkovo 1942 / Gauss-Kruger zone 14\",GEOGCS[\"Pulkovo 1942\",DATUM[\"Pulkovo_1942\",SPHEROID[\"Krassowsky 1940\",6378245,298.3,AUTHORITY[\"EPSG\",\"7024\"]],TOWGS84[23.92,-141.27,-80.9,-0,0.35,0.82,-0.12],AUTHORITY[\"EPSG\",\"6284\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4284\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",81],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",14500000],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"28414\"],AXIS[\"X\",NORTH],AXIS[\"Y\",EAST]]\"");
var csTarget = CoordinateSystemFactory.CreateFromWkt(
"GEOGCS[\"Pulkovo 1942\",DATUM[\"Pulkovo_1942\",SPHEROID[\"Krassowsky 1940\",6378245,298.3,AUTHORITY[\"EPSG\",\"7024\"]],TOWGS84[23.92,-141.27,-80.9,-0,0.35,0.82,-0.12],AUTHORITY[\"EPSG\",\"6284\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4284\"]]\"");
var ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(csSource, csTarget);
double[] pp = new[] {14181052.913, 6435927.692};
double[] pg = ct.MathTransform.Transform(pp);
double[] pExpected = new[] { 75.613911283608331, 57.926509119323505 };
double[] pp2 = ct.MathTransform.Inverse().Transform(pg);
Verbose = true;
Assert.IsTrue(ToleranceLessThan(pg, pExpected, 1e-6),
TransformationError("EPSG 28414 -> EPSG 4284", pExpected, pg));
Assert.IsTrue(ToleranceLessThan(pp, pp2, 1e-3),
TransformationError("EPSG 28414 -> Pulkovo 1942", pp, pp2, true));
}
[Test, Description("Problem converting coordinates, Discussion http://projnet.codeplex.com/discussions/352813")]
public void TestDiscussion352813()
{
var csSource = GeographicCoordinateSystem.WGS84;
var csTarget = ProjectedCoordinateSystem.WebMercator;
// CoordinateSystemFactory.CreateFromWkt(
//"PROJCS[\"Popular Visualisation CRS / Mercator\"," +
// "GEOGCS[\"Popular Visualisation CRS\"," +
// "DATUM[\"Popular Visualisation Datum\"," +
// "SPHEROID[\"Popular Visualisation Sphere\", 6378137, 298.257223563, " +
// "AUTHORITY[\"EPSG\", \"7030\"]]," +
// /*"TOWGS84[0, 0, 0, 0, 0, 0, 0], */"AUTHORITY[\"EPSG\", \"6055\"]], " +
// "PRIMEM[\"Greenwich\", 0, AUTHORITY[\"EPSG\", \"8901\"]]," +
// "UNIT[\"degree\", 0.0174532925199433, AUTHORITY[\"EPSG\", \"9102\"]]," +
// "AXIS[\"E\", EAST]," +
// "AXIS[\"N\", NORTH]," +
// "AUTHORITY[\"EPSG\", \"4055\"]]," +
// "PROJECTION[\"Mercator\"]," +
// "PARAMETER[\"semi_major\", 6378137]," +
// "PARAMETER[\"semi_minor\", 6378137]," +
// "PARAMETER[\"scale_factor\", 1]," +
// "PARAMETER[\"False_Easting\", 0]," +
// "PARAMETER[\"False_Northing\", 0]," +
// "PARAMETER[\"Central_Meridian\", 0]," +
// "PARAMETER[\"Latitude_of_origin\", 0]," +
// "UNIT[\"metre\", 1, AUTHORITY[\"EPSG\", \"9001\"]]," +
// "AXIS[\"East\", EAST]," +
//"AXIS[\"North\", NORTH]," +
//"AUTHORITY[\"EPSG\", \"3857\"]]");
//"PROJCS["WGS 84 / Pseudo-Mercator",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],PROJECTION["Mercator_1SP"],PARAMETER["central_meridian",0],PARAMETER["scale_factor",1],PARAMETER["false_easting",0],PARAMETER["false_northing",0],EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"],AUTHORITY["EPSG","3857"],AXIS["X",EAST],AXIS["Y",NORTH]]"
var ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(csSource, csTarget);
//var ct2 = CoordinateTransformationFactory.CreateFromCoordinateSystems(csSource, csTarget2);
Verbose = true;
double[] pg1 = new[] { 23.57892d, 37.94712d };
//src DotSpatial.Projections
double[] pExpected = new[] { 2624793.3678553337, 4571958.333297424 };
double[] pp = ct.MathTransform.Transform(pg1);
Console.WriteLine(TransformationError("EPSG 4326 -> EPSG 3857", pExpected, pp));
Assert.IsTrue(ToleranceLessThan(pp, pExpected, 1e-9),
TransformationError("EPSG 4326 -> EPSG 3857", pExpected, pp));
double[] pg2 = ct.MathTransform.Inverse().Transform(pp);
Assert.IsTrue(ToleranceLessThan(pg1, pg2, 1e-13),
TransformationError("EPSG 4326 -> EPSG 3857", pg1, pg2, true));
}
[Test, Description("Concerned about the accuracy, Discussion http://projnet.codeplex.com/discussions/361248")]
public void TestDiscussion361248_1()
{
var csSource = CoordinateSystemFactory.CreateFromWkt(
@"GEOGCS[""WGS 84"",
DATUM[""WGS_1984"",
SPHEROID[""WGS 84"",6378137,298.257223563,
AUTHORITY[""EPSG"",""7030""]],
AUTHORITY[""EPSG"",""6326""]],
PRIMEM[""Greenwich"",0,
AUTHORITY[""EPSG"",""8901""]],
UNIT[""degree"",0.01745329251994328,
AUTHORITY[""EPSG"",""9122""]],
AUTHORITY[""EPSG"",""4326""]]");
var csTarget = CoordinateSystemFactory.CreateFromWkt(
"PROJCS[\"GDA94 / MGA zone 50\",GEOGCS[\"GDA94\",DATUM[\"Geocentric_Datum_of_Australia_1994\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6283\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4283\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",117],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",10000000],AUTHORITY[\"EPSG\",\"28350\"],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]");
//Chose PostGis values
Test("WGS 84 -> GDA94 / MGA zone 50", csSource, csTarget, new[] { 136d, -30d }, new[] { 2349315.05731837, 6524249.91789138}, 0.05, 1.0e-4);
}
[Test, Description("Concerned about the accuracy, Discussion http://projnet.codeplex.com/discussions/361248")]
public void TestDiscussion361248_2()
{
var csSource = ProjectedCoordinateSystem.WGS84_UTM(18, true);
var csTarget = CoordinateSystemFactory.CreateFromWkt(
@"GEOGCS[""WGS 84"",
DATUM[""WGS_1984"",
SPHEROID[""WGS 84"",6378137,298.257223563,
AUTHORITY[""EPSG"",""7030""]],
AUTHORITY[""EPSG"",""6326""]],
PRIMEM[""Greenwich"",0,
AUTHORITY[""EPSG"",""8901""]],
UNIT[""degree"",0.01745329251994328,
AUTHORITY[""EPSG"",""9122""]],
AUTHORITY[""EPSG"",""4326""]]");
Test("WGS84_UTM(18,N) -> WGS84", csSource, csTarget, new[] { 307821.867, 4219306.387 }, new[] { -77.191769, 38.101147 }, 1e-6);
}
/// <summary>
/// Wrong <c>null</c> check in ObliqueMercatorProjection.Inverse() method
/// </summary>
/// <seealso href="https://code.google.com/p/nettopologysuite/issues/detail?id=191"/>
[Test, Description("ObliqueMercatorProjection.Inverse() wrong null check")]
public void TestNtsIssue191()
{
var parameters = new List<ProjectionParameter>();
parameters.Add(new ProjectionParameter("latitude_of_center", 45.30916666666666));
parameters.Add(new ProjectionParameter("longitude_of_center", -86));
parameters.Add(new ProjectionParameter("azimuth", 337.25556));
parameters.Add(new ProjectionParameter("rectified_grid_angle", 337.25556));
parameters.Add(new ProjectionParameter("scale_factor", 0.9996));
parameters.Add(new ProjectionParameter("false_easting", 2546731.496));
parameters.Add(new ProjectionParameter("false_northing", -4354009.816));
var factory = new CoordinateSystemFactory();
var projection = factory.CreateProjection("Test Oblique", "oblique_mercator", parameters);
Assert.That(projection, Is.Not.Null);
var wgs84 = GeographicCoordinateSystem.WGS84;
var dummy = factory.CreateProjectedCoordinateSystem("dummy pcs",
wgs84, projection, LinearUnit.Metre,
new AxisInfo("X", AxisOrientationEnum.East),
new AxisInfo("Y", AxisOrientationEnum.North));
Assert.That(dummy, Is.Not.Null);
var transform = CoordinateTransformationFactory.CreateFromCoordinateSystems(wgs84, dummy);
Assert.That(transform, Is.Not.Null);
var mathTransform = transform.MathTransform;
var inverse = mathTransform.Inverse();
Assert.That(inverse, Is.Not.Null);
}
/// <summary>
/// Wrong AngularUnits.EqualParams implementation
/// </summary>
[Test]
public void TestAngularUnitsEqualParamsIssue()
{
//string sourceWkt = " UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]";
string wkt = "PROJCS[\"DHDN / Gauss-Kruger zone 3\",GEOGCS[\"DHDN\",DATUM[\"Deutsches_Hauptdreiecksnetz\",SPHEROID[\"Bessel 1841\",6377397.155,299.1528128,AUTHORITY[\"EPSG\",\"7004\"]],AUTHORITY[\"EPSG\",\"6314\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4314\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",9],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",3500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AUTHORITY[\"EPSG\",\"31467\"]]";
var pcs1 = CoordinateSystemFactory.CreateFromWkt (wkt) as ProjectedCoordinateSystem;
Assert.NotNull (pcs1);
Assert.NotNull (pcs1.GeographicCoordinateSystem);
Assert.NotNull (pcs1.GeographicCoordinateSystem.AngularUnit);
string savedWkt = pcs1.WKT;
var pcs2 = CoordinateSystemFactory.CreateFromWkt (savedWkt) as ProjectedCoordinateSystem;
//test AngularUnit parsing via ProjectedCoordinateSystem
Assert.NotNull (pcs2);
Assert.NotNull (pcs2.GeographicCoordinateSystem);
Assert.NotNull (pcs2.GeographicCoordinateSystem.AngularUnit);
//check equality of angular units via RadiansPerUnit
Assert.AreEqual (pcs1.GeographicCoordinateSystem.AngularUnit.RadiansPerUnit, pcs2.GeographicCoordinateSystem.AngularUnit.RadiansPerUnit, 0.0000000000001);
//check equality of angular units
Assert.AreEqual (true, pcs1.GeographicCoordinateSystem.AngularUnit.EqualParams (pcs2.GeographicCoordinateSystem.AngularUnit));
}
[Test, Description("transformation somehow is wrong"), Category("Question")]
public void TestGitHubIssue53()
{
// arrange
var csWgs84 = GeographicCoordinateSystem.WGS84;
var csUtm35N = ProjectedCoordinateSystem.WGS84_UTM(35, true);
var csTrans = CoordinateTransformationFactory.CreateFromCoordinateSystems(csWgs84, csUtm35N);
var csTransBack = CoordinateTransformationFactory.CreateFromCoordinateSystems(csUtm35N, csWgs84);
// act
double[] point = { 42.5, 24.5 };
double[] r = csTrans.MathTransform.Transform(point);
double[] rBack = csTransBack.MathTransform.Transform(r);
// assert
Assert.AreEqual(point[0], rBack[0], 1e-5);
Assert.AreEqual(point[1], rBack[1], 1e-5);
}
}
}
using System;
using System.Collections.Generic;
using NUnit.Framework;
using ProjNet.CoordinateSystems;
namespace ProjNET.Tests
{
[TestFixture]
public class ProjNetIssues : CoordinateTransformTestsBase
{
public ProjNetIssues()
{
Verbose = true;
}
[Test, Description("WGS_84UTM to WGS_84 is inaccurate")]
public void TestIssue23773()
{
var csUtm18N = ProjectedCoordinateSystem.WGS84_UTM(18, true);
var csUtm18NWkt = CoordinateSystemFactory.CreateFromWkt(
"PROJCS[\"WGS 84 / UTM zone 18N\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-75],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"32618\"],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]");
var csWgs84 = GeographicCoordinateSystem.WGS84;
var ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(csUtm18N, csWgs84);
var ct2 = CoordinateTransformationFactory.CreateFromCoordinateSystems(csUtm18NWkt, csWgs84);
double[] putm = new[] {307821.867d, 4219306.387d};
double[] pgeo = ct.MathTransform.Transform(putm);
double[] pgeoWkt = ct2.MathTransform.Transform(putm);
double[] pExpected = new[] {-77.191769, 38.101147d};
Assert.IsTrue(ToleranceLessThan(pgeoWkt, pExpected, 0.00001d),
TransformationError("UTM18N -> WGS84", pExpected, pgeo));
Assert.IsTrue(ToleranceLessThan(pgeo, pExpected, 0.00001d),
TransformationError("UTM18N -> WGS84", pExpected, pgeo));
}
[Test, Description("Proj.net reprojection problem, Discussion http://projnet.codeplex.com/discussions/351733")]
public void TestDiscussion351733()
{
var csSource = CoordinateSystemFactory.CreateFromWkt(
"PROJCS[\"Pulkovo 1942 / Gauss-Kruger zone 14\",GEOGCS[\"Pulkovo 1942\",DATUM[\"Pulkovo_1942\",SPHEROID[\"Krassowsky 1940\",6378245,298.3,AUTHORITY[\"EPSG\",\"7024\"]],TOWGS84[23.92,-141.27,-80.9,-0,0.35,0.82,-0.12],AUTHORITY[\"EPSG\",\"6284\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4284\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",81],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",14500000],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"28414\"],AXIS[\"X\",NORTH],AXIS[\"Y\",EAST]]\"");
var csTarget = CoordinateSystemFactory.CreateFromWkt(
"GEOGCS[\"Pulkovo 1942\",DATUM[\"Pulkovo_1942\",SPHEROID[\"Krassowsky 1940\",6378245,298.3,AUTHORITY[\"EPSG\",\"7024\"]],TOWGS84[23.92,-141.27,-80.9,-0,0.35,0.82,-0.12],AUTHORITY[\"EPSG\",\"6284\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4284\"]]\"");
var ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(csSource, csTarget);
double[] pp = new[] {14181052.913, 6435927.692};
double[] pg = ct.MathTransform.Transform(pp);
double[] pExpected = new[] { 75.613911283608331, 57.926509119323505 };
double[] pp2 = ct.MathTransform.Inverse().Transform(pg);
Verbose = true;
Assert.IsTrue(ToleranceLessThan(pg, pExpected, 1e-6),
TransformationError("EPSG 28414 -> EPSG 4284", pExpected, pg));
Assert.IsTrue(ToleranceLessThan(pp, pp2, 1e-3),
TransformationError("EPSG 28414 -> Pulkovo 1942", pp, pp2, true));
}
[Test, Description("Problem converting coordinates, Discussion http://projnet.codeplex.com/discussions/352813")]
public void TestDiscussion352813()
{
var csSource = GeographicCoordinateSystem.WGS84;
var csTarget = ProjectedCoordinateSystem.WebMercator;
// CoordinateSystemFactory.CreateFromWkt(
//"PROJCS[\"Popular Visualisation CRS / Mercator\"," +
// "GEOGCS[\"Popular Visualisation CRS\"," +
// "DATUM[\"Popular Visualisation Datum\"," +
// "SPHEROID[\"Popular Visualisation Sphere\", 6378137, 298.257223563, " +
// "AUTHORITY[\"EPSG\", \"7030\"]]," +
// /*"TOWGS84[0, 0, 0, 0, 0, 0, 0], */"AUTHORITY[\"EPSG\", \"6055\"]], " +
// "PRIMEM[\"Greenwich\", 0, AUTHORITY[\"EPSG\", \"8901\"]]," +
// "UNIT[\"degree\", 0.0174532925199433, AUTHORITY[\"EPSG\", \"9102\"]]," +
// "AXIS[\"E\", EAST]," +
// "AXIS[\"N\", NORTH]," +
// "AUTHORITY[\"EPSG\", \"4055\"]]," +
// "PROJECTION[\"Mercator\"]," +
// "PARAMETER[\"semi_major\", 6378137]," +
// "PARAMETER[\"semi_minor\", 6378137]," +
// "PARAMETER[\"scale_factor\", 1]," +
// "PARAMETER[\"False_Easting\", 0]," +
// "PARAMETER[\"False_Northing\", 0]," +
// "PARAMETER[\"Central_Meridian\", 0]," +
// "PARAMETER[\"Latitude_of_origin\", 0]," +
// "UNIT[\"metre\", 1, AUTHORITY[\"EPSG\", \"9001\"]]," +
// "AXIS[\"East\", EAST]," +
//"AXIS[\"North\", NORTH]," +
//"AUTHORITY[\"EPSG\", \"3857\"]]");
//"PROJCS["WGS 84 / Pseudo-Mercator",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],PROJECTION["Mercator_1SP"],PARAMETER["central_meridian",0],PARAMETER["scale_factor",1],PARAMETER["false_easting",0],PARAMETER["false_northing",0],EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"],AUTHORITY["EPSG","3857"],AXIS["X",EAST],AXIS["Y",NORTH]]"
var ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(csSource, csTarget);
//var ct2 = CoordinateTransformationFactory.CreateFromCoordinateSystems(csSource, csTarget2);
Verbose = true;
double[] pg1 = new[] { 23.57892d, 37.94712d };
//src DotSpatial.Projections
double[] pExpected = new[] { 2624793.3678553337, 4571958.333297424 };
double[] pp = ct.MathTransform.Transform(pg1);
Console.WriteLine(TransformationError("EPSG 4326 -> EPSG 3857", pExpected, pp));
Assert.IsTrue(ToleranceLessThan(pp, pExpected, 1e-9),
TransformationError("EPSG 4326 -> EPSG 3857", pExpected, pp));
double[] pg2 = ct.MathTransform.Inverse().Transform(pp);
Assert.IsTrue(ToleranceLessThan(pg1, pg2, 1e-13),
TransformationError("EPSG 4326 -> EPSG 3857", pg1, pg2, true));
}
[Test, Description("Concerned about the accuracy, Discussion http://projnet.codeplex.com/discussions/361248")]
public void TestDiscussion361248_1()
{
var csSource = CoordinateSystemFactory.CreateFromWkt(
@"GEOGCS[""WGS 84"",
DATUM[""WGS_1984"",
SPHEROID[""WGS 84"",6378137,298.257223563,
AUTHORITY[""EPSG"",""7030""]],
AUTHORITY[""EPSG"",""6326""]],
PRIMEM[""Greenwich"",0,
AUTHORITY[""EPSG"",""8901""]],
UNIT[""degree"",0.01745329251994328,
AUTHORITY[""EPSG"",""9122""]],
AUTHORITY[""EPSG"",""4326""]]");
var csTarget = CoordinateSystemFactory.CreateFromWkt(
"PROJCS[\"GDA94 / MGA zone 50\",GEOGCS[\"GDA94\",DATUM[\"Geocentric_Datum_of_Australia_1994\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6283\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4283\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",117],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",10000000],AUTHORITY[\"EPSG\",\"28350\"],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]");
//Chose PostGis values
Test("WGS 84 -> GDA94 / MGA zone 50", csSource, csTarget, new[] { 136d, -30d }, new[] { 2349315.05731837, 6524249.91789138}, 0.05, 1.0e-4);
}
[Test, Description("Concerned about the accuracy, Discussion http://projnet.codeplex.com/discussions/361248")]
public void TestDiscussion361248_2()
{
var csSource = ProjectedCoordinateSystem.WGS84_UTM(18, true);
var csTarget = CoordinateSystemFactory.CreateFromWkt(
@"GEOGCS[""WGS 84"",
DATUM[""WGS_1984"",
SPHEROID[""WGS 84"",6378137,298.257223563,
AUTHORITY[""EPSG"",""7030""]],
AUTHORITY[""EPSG"",""6326""]],
PRIMEM[""Greenwich"",0,
AUTHORITY[""EPSG"",""8901""]],
UNIT[""degree"",0.01745329251994328,
AUTHORITY[""EPSG"",""9122""]],
AUTHORITY[""EPSG"",""4326""]]");
Test("WGS84_UTM(18,N) -> WGS84", csSource, csTarget, new[] { 307821.867, 4219306.387 }, new[] { -77.191769, 38.101147 }, 1e-6);
}
/// <summary>
/// Wrong <c>null</c> check in ObliqueMercatorProjection.Inverse() method
/// </summary>
/// <seealso href="https://code.google.com/p/nettopologysuite/issues/detail?id=191"/>
[Test, Description("ObliqueMercatorProjection.Inverse() wrong null check")]
public void TestNtsIssue191()
{
var parameters = new List<ProjectionParameter>();
parameters.Add(new ProjectionParameter("latitude_of_center", 45.30916666666666));
parameters.Add(new ProjectionParameter("longitude_of_center", -86));
parameters.Add(new ProjectionParameter("azimuth", 337.25556));
parameters.Add(new ProjectionParameter("rectified_grid_angle", 337.25556));
parameters.Add(new ProjectionParameter("scale_factor", 0.9996));
parameters.Add(new ProjectionParameter("false_easting", 2546731.496));
parameters.Add(new ProjectionParameter("false_northing", -4354009.816));
var factory = new CoordinateSystemFactory();
var projection = factory.CreateProjection("Test Oblique", "oblique_mercator", parameters);
Assert.That(projection, Is.Not.Null);
var wgs84 = GeographicCoordinateSystem.WGS84;
var dummy = factory.CreateProjectedCoordinateSystem("dummy pcs",
wgs84, projection, LinearUnit.Metre,
new AxisInfo("X", AxisOrientationEnum.East),
new AxisInfo("Y", AxisOrientationEnum.North));
Assert.That(dummy, Is.Not.Null);
var transform = CoordinateTransformationFactory.CreateFromCoordinateSystems(wgs84, dummy);
Assert.That(transform, Is.Not.Null);
var mathTransform = transform.MathTransform;
var inverse = mathTransform.Inverse();
Assert.That(inverse, Is.Not.Null);
}
/// <summary>
/// Wrong AngularUnits.EqualParams implementation
/// </summary>
[Test]
public void TestAngularUnitsEqualParamsIssue()
{
//string sourceWkt = " UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]";
string wkt = "PROJCS[\"DHDN / Gauss-Kruger zone 3\",GEOGCS[\"DHDN\",DATUM[\"Deutsches_Hauptdreiecksnetz\",SPHEROID[\"Bessel 1841\",6377397.155,299.1528128,AUTHORITY[\"EPSG\",\"7004\"]],AUTHORITY[\"EPSG\",\"6314\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4314\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",9],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",3500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AUTHORITY[\"EPSG\",\"31467\"]]";
var pcs1 = CoordinateSystemFactory.CreateFromWkt (wkt) as ProjectedCoordinateSystem;
Assert.NotNull (pcs1);
Assert.NotNull (pcs1.GeographicCoordinateSystem);
Assert.NotNull (pcs1.GeographicCoordinateSystem.AngularUnit);
string savedWkt = pcs1.WKT;
var pcs2 = CoordinateSystemFactory.CreateFromWkt (savedWkt) as ProjectedCoordinateSystem;
//test AngularUnit parsing via ProjectedCoordinateSystem
Assert.NotNull (pcs2);
Assert.NotNull (pcs2.GeographicCoordinateSystem);
Assert.NotNull (pcs2.GeographicCoordinateSystem.AngularUnit);
//check equality of angular units via RadiansPerUnit
Assert.AreEqual (pcs1.GeographicCoordinateSystem.AngularUnit.RadiansPerUnit, pcs2.GeographicCoordinateSystem.AngularUnit.RadiansPerUnit, 0.0000000000001);
//check equality of angular units
Assert.AreEqual (true, pcs1.GeographicCoordinateSystem.AngularUnit.EqualParams (pcs2.GeographicCoordinateSystem.AngularUnit));
}
[Test, Description("transformation somehow is wrong"), Category("Question")]
public void TestGitHubIssue53()
{
// arrange
var csWgs84 = GeographicCoordinateSystem.WGS84;
var csUtm35N = ProjectedCoordinateSystem.WGS84_UTM(35, true);
var csTrans = CoordinateTransformationFactory.CreateFromCoordinateSystems(csWgs84, csUtm35N);
var csTransBack = CoordinateTransformationFactory.CreateFromCoordinateSystems(csUtm35N, csWgs84);
// act
double[] point = { 42.5, 24.5 };
double[] r = csTrans.MathTransform.Transform(point);
double[] rBack = csTransBack.MathTransform.Transform(r);
// assert
Assert.AreEqual(point[0], rBack[0], 1e-5);
Assert.AreEqual(point[1], rBack[1], 1e-5);
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,71 +1,71 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using ProjNet.CoordinateSystems;
namespace ProjNET.Tests
{
internal class SRIDReader
{
private static readonly Lazy<CoordinateSystemFactory> CoordinateSystemFactory =
new Lazy<CoordinateSystemFactory>(() => new CoordinateSystemFactory());
public struct WktString {
/// <summary>
/// Well-known ID
/// </summary>
public int WktId;
/// <summary>
/// Well-known Text
/// </summary>
public string Wkt;
}
/// <summary>
/// Enumerates all SRID's in the SRID.csv file.
/// </summary>
/// <returns>Enumerator</returns>
public static IEnumerable<WktString> GetSrids(string filename = null)
{
var stream = string.IsNullOrWhiteSpace(filename)
? Assembly.GetExecutingAssembly().GetManifestResourceStream("ProjNET.Tests.SRID.csv")
: File.OpenRead(filename);
using (var sr = new StreamReader(stream, Encoding.UTF8))
{
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
if (string.IsNullOrWhiteSpace(line)) continue;
int split = line.IndexOf(';');
if (split <= -1) continue;
var wkt = new WktString
{
WktId = int.Parse(line.Substring(0, split)),
Wkt = line.Substring(split + 1)
};
yield return wkt;
}
}
}
/// <summary>
/// Gets a coordinate system from the SRID.csv file
/// </summary>
/// <param name="id">EPSG ID</param>
/// <param name="file">(optional) path to CSV File with WKT definitions.</param>
/// <returns>Coordinate system, or <value>null</value> if no entry with <paramref name="id"/> was not found.</returns>
public static CoordinateSystem GetCSbyID(int id, string file = null)
{
//ICoordinateSystemFactory factory = new CoordinateSystemFactory();
foreach (var wkt in GetSrids(file))
if (wkt.WktId == id)
return CoordinateSystemFactory.Value.CreateFromWkt(wkt.Wkt);
return null;
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using ProjNet.CoordinateSystems;
namespace ProjNET.Tests
{
internal class SRIDReader
{
private static readonly Lazy<CoordinateSystemFactory> CoordinateSystemFactory =
new Lazy<CoordinateSystemFactory>(() => new CoordinateSystemFactory());
public struct WktString {
/// <summary>
/// Well-known ID
/// </summary>
public int WktId;
/// <summary>
/// Well-known Text
/// </summary>
public string Wkt;
}
/// <summary>
/// Enumerates all SRID's in the SRID.csv file.
/// </summary>
/// <returns>Enumerator</returns>
public static IEnumerable<WktString> GetSrids(string filename = null)
{
var stream = string.IsNullOrWhiteSpace(filename)
? Assembly.GetExecutingAssembly().GetManifestResourceStream("ProjNET.Tests.SRID.csv")
: File.OpenRead(filename);
using (var sr = new StreamReader(stream, Encoding.UTF8))
{
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
if (string.IsNullOrWhiteSpace(line)) continue;
int split = line.IndexOf(';');
if (split <= -1) continue;
var wkt = new WktString
{
WktId = int.Parse(line.Substring(0, split)),
Wkt = line.Substring(split + 1)
};
yield return wkt;
}
}
}
/// <summary>
/// Gets a coordinate system from the SRID.csv file
/// </summary>
/// <param name="id">EPSG ID</param>
/// <param name="file">(optional) path to CSV File with WKT definitions.</param>
/// <returns>Coordinate system, or <value>null</value> if no entry with <paramref name="id"/> was not found.</returns>
public static CoordinateSystem GetCSbyID(int id, string file = null)
{
//ICoordinateSystemFactory factory = new CoordinateSystemFactory();
foreach (var wkt in GetSrids(file))
if (wkt.WktId == id)
return CoordinateSystemFactory.Value.CreateFromWkt(wkt.Wkt);
return null;
}
}
}

Просмотреть файл

@ -1,24 +1,24 @@
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace ProjNET.Tests.Serialization
{
public class BaseSerializationTest
{
public IFormatter GetFormatter()
{
return new BinaryFormatter();
}
public static T SanD<T>(T instance, IFormatter formatter)
{
using (var ms = new MemoryStream())
{
formatter.Serialize(ms, instance);
ms.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(ms);
}
}
}
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace ProjNET.Tests.Serialization
{
public class BaseSerializationTest
{
public IFormatter GetFormatter()
{
return new BinaryFormatter();
}
public static T SanD<T>(T instance, IFormatter formatter)
{
using (var ms = new MemoryStream())
{
formatter.Serialize(ms, instance);
ms.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(ms);
}
}
}
}

Просмотреть файл

@ -1,24 +1,24 @@
using NUnit.Framework;
using ProjNet.CoordinateSystems;
namespace ProjNET.Tests.Serialization
{
public class CoordinateSystemsProjectionsTest : BaseSerializationTest
{
[Test]
public void TestProjectionParameterSet()
{
var ps = new ProjNet.CoordinateSystems.Projections.ProjectionParameterSet(
new[]
{
new ProjectionParameter("latitude_of_origin", 0),
new ProjectionParameter("false_easting", 500)
}
);
var psD = SanD(ps, GetFormatter());
Assert.AreEqual(ps, psD);
}
}
}
using NUnit.Framework;
using ProjNet.CoordinateSystems;
namespace ProjNET.Tests.Serialization
{
public class CoordinateSystemsProjectionsTest : BaseSerializationTest
{
[Test]
public void TestProjectionParameterSet()
{
var ps = new ProjNet.CoordinateSystems.Projections.ProjectionParameterSet(
new[]
{
new ProjectionParameter("latitude_of_origin", 0),
new ProjectionParameter("false_easting", 500)
}
);
var psD = SanD(ps, GetFormatter());
Assert.AreEqual(ps, psD);
}
}
}

Просмотреть файл

@ -1,117 +1,117 @@
using System.Reflection;
using NUnit.Framework;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNET.Tests
{
public class SharpMapIssues: CoordinateTransformTestsBase
{
public SharpMapIssues()
{
Verbose = true;
}
string wkt2236 = "PROJCS[\"NAD83 / Florida East (ftUS)\", GEOGCS [ \"NAD83\", DATUM [\"North American Datum 1983 (EPSG ID 6269)\", SPHEROID [\"GRS 1980 (EPSG ID 7019)\", 6378137, 298.257222101]], PRIMEM [ \"Greenwich\", 0.000000 ], UNIT [\"Decimal Degree\", 0.01745329251994328]], PROJECTION [\"SPCS83 Florida East zone (US Survey feet) (EPSG OP 15318)\"], PARAMETER [\"Latitude_Of_Origin\", 24.33333333333333333333333333333333333333], PARAMETER [\"Central_Meridian\", -80.9999999999999999999999999999999999999], PARAMETER [\"Scale_Factor\", 0.999941177], PARAMETER [\"False_Easting\", 656166.6669999999999999999999999999999999], PARAMETER [\"False_Northing\", 0], UNIT [\"U.S. Foot\", 0.3048006096012192024384048768097536195072]]";
string wkt8307 = "GEOGCS [ \"WGS 84\", DATUM [\"World Geodetic System 1984 (EPSG ID 6326)\", SPHEROID [\"WGS 84 (EPSG ID 7030)\", 6378137, 298.257223563]], PRIMEM [ \"Greenwich\", 0.000000 ], UNIT [\"Decimal Degree\", 0.01745329251994328]]";
[Test, Description("NAD83 (State Plane) projection to the WGS84 (Lat/Long), http://sharpmap.codeplex.com/discussions/435794")]
public void TestNad83ToWGS84()
{
var src = CoordinateSystemFactory.CreateFromWkt(wkt2236);
var tgt = CoordinateSystemFactory.CreateFromWkt(wkt8307);//CoordinateSystems.GeographicCoordinateSystem.WGS84;;
ProjNet.CoordinateSystems.Projections.ProjectionsRegistry.Register("SPCS83 Florida East zone (US Survey feet) (EPSG OP 15318)",
ReflectType("ProjNet.CoordinateSystems.Projections.TransverseMercator"));
ICoordinateTransformation transform = null;
Assert.DoesNotThrow(() => transform = CoordinateTransformationFactory.CreateFromCoordinateSystems(src, tgt));
Assert.IsNotNull(transform);
}
private System.Type ReflectType(string typeName)
{
var asm = Assembly.GetAssembly(typeof (ProjNet.CoordinateSystems.Projections.MapProjection));
var res = asm.GetType(typeName);
return res;
}
private string wkt7151 = "PROJCS[\"NAD_1983_Hotine_Oblique_Mercator_Azimuth_Natural_Origin\",GEOGCS[\"GCS_North_American_1983\",DATUM[\"D_North_American_1983\",SPHEROID[\"GRS_1980\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.017453292519943295]],PROJECTION[\"Hotine_Oblique_Mercator\"],PARAMETER[\"longitude_of_center\",-86.0],PARAMETER[\"latitude_of_center\",45.30916666666666],PARAMETER[\"azimuth\",337.25555999999995],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",2546731.496],PARAMETER[\"false_northing\",-4354009.816],PARAMETER[\"rectified_grid_angle\",337.25555999999995],UNIT[\"m\",1.0]]";
//projection problem with Michigan GeoRef
[Test, Description("projection problem with Michigan GeoRef")]
public void TestMichiganGeoRefToWebMercator()
{
var src = CoordinateSystemFactory.CreateFromWkt(wkt7151);
var tgt = ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator;
ICoordinateTransformation transform = null;
Assert.DoesNotThrow(() => transform = CoordinateTransformationFactory.CreateFromCoordinateSystems(src, tgt));
Assert.IsNotNull(transform);
double[] ptSrc = new[] {535247.9375, 324548.09375};
double[] ptTgt = null;
Assert.DoesNotThrow(() => ptTgt = transform.MathTransform.Transform(ptSrc));
Assert.IsNotNull(ptTgt);
}
[Test, Description("Parse AUTHORITY with unqouted AuthorityCode")]
public void TestAuthorityCodeParsing()
{
const string wkt1 = "PROJCS[\"NAD_1983_BC_Environment_Albers\",GEOGCS[\"GCS_North_American_1983\",DATUM[\"D_North_American_1983\",SPHEROID[\"GRS_1980\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Albers\"],PARAMETER[\"False_Easting\",1000000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",-126.0],PARAMETER[\"Standard_Parallel_1\",50.0],PARAMETER[\"Standard_Parallel_2\",58.5],PARAMETER[\"Latitude_Of_Origin\",45.0],UNIT[\"Meter\",1.0],AUTHORITY[\"EPSG\",\"3005\"]]";
CoordinateSystem cs1 = null, cs2 = null;
Assert.DoesNotThrow( () => cs1 = CoordinateSystemFactory.CreateFromWkt(wkt1));
Assert.IsNotNull(cs1);
const string wkt2 = "PROJCS[\"NAD_1983_BC_Environment_Albers\",GEOGCS[\"GCS_North_American_1983\",DATUM[\"D_North_American_1983\",SPHEROID[\"GRS_1980\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Albers\"],PARAMETER[\"False_Easting\",1000000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",-126.0],PARAMETER[\"Standard_Parallel_1\",50.0],PARAMETER[\"Standard_Parallel_2\",58.5],PARAMETER[\"Latitude_Of_Origin\",45.0],UNIT[\"Meter\",1.0],AUTHORITY[\"EPSG\",3005]]";
Assert.DoesNotThrow(() => cs2 = CoordinateSystemFactory.CreateFromWkt(wkt2));
Assert.IsNotNull(cs2);
//Assert.AreEqual(cs1, cs2);
Assert.IsTrue(cs1.EqualParams(cs2));
}
[Test]
public void Test25832To3857()
{
const string wkt1 = //"PROJCS[\"ETRS89 / UTM zone 32N\",GEOGCS[\"ETRS89\",DATUM[\"European_Terrestrial_Reference_System_1989\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6258\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4258\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",9],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AUTHORITY[\"EPSG\",\"25832\"]]";
"PROJCS[\"ETRS89 / UTM zone 32N\",GEOGCS[\"ETRS89\",DATUM[\"European_Terrestrial_Reference_System_1989\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6258\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4258\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",9],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"25832\"],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]";
CoordinateSystem cs1 = null, cs2 = null;
Assert.DoesNotThrow(() => cs1 = CoordinateSystemFactory.CreateFromWkt(wkt1));
Assert.IsNotNull(cs1);
const string wkt2 = "PROJCS[\"WGS 84 / Pseudo-Mercator\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\", SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"latitude_of_origin\", 0],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],EXTENSION[\"PROJ4\",\"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs\"],AUTHORITY[\"EPSG\",\"3857\"],AXIS[\"X\",EAST],AXIS[\"Y\",NORTH]]";
Assert.DoesNotThrow(() => cs2 = CoordinateSystemFactory.CreateFromWkt(wkt2));
Assert.IsNotNull(cs2);
ICoordinateTransformation ct = null;
Assert.DoesNotThrow(() => ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(cs1, cs2));
Assert.IsNotNull(ct);
Assert.DoesNotThrow(() => ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(cs2, cs1));
Assert.IsNotNull(ct);
Assert.DoesNotThrow(() => ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(cs1, ProjectedCoordinateSystem.WebMercator));
Assert.IsNotNull(ct);
Assert.DoesNotThrow(() => ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(ProjectedCoordinateSystem.WebMercator, cs1));
Assert.IsNotNull(ct);
}
using System.Reflection;
using NUnit.Framework;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
[Test]
public void TestLaea()
{
const string Epsg3035 =
@"PROJCS[""ETRS89 / ETRS-LAEA"",GEOGCS[""ETRS89"",DATUM[""European_Terrestrial_Reference_System_1989"",SPHEROID[""GRS 1980"",6378137,298.257222101,AUTHORITY[""EPSG"",""7019""]],AUTHORITY[""EPSG"",""6258""]],PRIMEM[""Greenwich"",0,AUTHORITY[""EPSG"",""8901""]],UNIT[""degree"",0.01745329251994328,AUTHORITY[""EPSG"",""9122""]],AUTHORITY[""EPSG"",""4258""]],UNIT[""metre"",1,AUTHORITY[""EPSG"",""9001""]],PROJECTION[""Lambert_Azimuthal_Equal_Area""],PARAMETER[""latitude_of_center"",52],PARAMETER[""longitude_of_center"",10],PARAMETER[""false_easting"",4321000],PARAMETER[""false_northing"",3210000],AUTHORITY[""EPSG"",""3035""],AXIS[""X"",EAST],AXIS[""Y"",NORTH]]";
var csSrc = GeographicCoordinateSystem.WGS84;
var csTgt = CoordinateSystemFactory.CreateFromWkt(Epsg3035);
var ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(csSrc, csTgt);
namespace ProjNET.Tests
{
public class SharpMapIssues: CoordinateTransformTestsBase
{
public SharpMapIssues()
{
Verbose = true;
}
string wkt2236 = "PROJCS[\"NAD83 / Florida East (ftUS)\", GEOGCS [ \"NAD83\", DATUM [\"North American Datum 1983 (EPSG ID 6269)\", SPHEROID [\"GRS 1980 (EPSG ID 7019)\", 6378137, 298.257222101]], PRIMEM [ \"Greenwich\", 0.000000 ], UNIT [\"Decimal Degree\", 0.01745329251994328]], PROJECTION [\"SPCS83 Florida East zone (US Survey feet) (EPSG OP 15318)\"], PARAMETER [\"Latitude_Of_Origin\", 24.33333333333333333333333333333333333333], PARAMETER [\"Central_Meridian\", -80.9999999999999999999999999999999999999], PARAMETER [\"Scale_Factor\", 0.999941177], PARAMETER [\"False_Easting\", 656166.6669999999999999999999999999999999], PARAMETER [\"False_Northing\", 0], UNIT [\"U.S. Foot\", 0.3048006096012192024384048768097536195072]]";
string wkt8307 = "GEOGCS [ \"WGS 84\", DATUM [\"World Geodetic System 1984 (EPSG ID 6326)\", SPHEROID [\"WGS 84 (EPSG ID 7030)\", 6378137, 298.257223563]], PRIMEM [ \"Greenwich\", 0.000000 ], UNIT [\"Decimal Degree\", 0.01745329251994328]]";
[Test, Description("NAD83 (State Plane) projection to the WGS84 (Lat/Long), http://sharpmap.codeplex.com/discussions/435794")]
public void TestNad83ToWGS84()
{
var src = CoordinateSystemFactory.CreateFromWkt(wkt2236);
var tgt = CoordinateSystemFactory.CreateFromWkt(wkt8307);//CoordinateSystems.GeographicCoordinateSystem.WGS84;;
ProjNet.CoordinateSystems.Projections.ProjectionsRegistry.Register("SPCS83 Florida East zone (US Survey feet) (EPSG OP 15318)",
ReflectType("ProjNet.CoordinateSystems.Projections.TransverseMercator"));
ICoordinateTransformation transform = null;
Assert.DoesNotThrow(() => transform = CoordinateTransformationFactory.CreateFromCoordinateSystems(src, tgt));
Assert.IsNotNull(transform);
}
private System.Type ReflectType(string typeName)
{
var asm = Assembly.GetAssembly(typeof (ProjNet.CoordinateSystems.Projections.MapProjection));
var res = asm.GetType(typeName);
return res;
}
private string wkt7151 = "PROJCS[\"NAD_1983_Hotine_Oblique_Mercator_Azimuth_Natural_Origin\",GEOGCS[\"GCS_North_American_1983\",DATUM[\"D_North_American_1983\",SPHEROID[\"GRS_1980\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.017453292519943295]],PROJECTION[\"Hotine_Oblique_Mercator\"],PARAMETER[\"longitude_of_center\",-86.0],PARAMETER[\"latitude_of_center\",45.30916666666666],PARAMETER[\"azimuth\",337.25555999999995],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",2546731.496],PARAMETER[\"false_northing\",-4354009.816],PARAMETER[\"rectified_grid_angle\",337.25555999999995],UNIT[\"m\",1.0]]";
//projection problem with Michigan GeoRef
[Test, Description("projection problem with Michigan GeoRef")]
public void TestMichiganGeoRefToWebMercator()
{
var src = CoordinateSystemFactory.CreateFromWkt(wkt7151);
var tgt = ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator;
ICoordinateTransformation transform = null;
Assert.DoesNotThrow(() => transform = CoordinateTransformationFactory.CreateFromCoordinateSystems(src, tgt));
Assert.IsNotNull(transform);
double[] ptSrc = new[] {535247.9375, 324548.09375};
double[] ptTgt = null;
Assert.DoesNotThrow(() => ptTgt = transform.MathTransform.Transform(ptSrc));
Assert.IsNotNull(ptTgt);
}
[Test, Description("Parse AUTHORITY with unqouted AuthorityCode")]
public void TestAuthorityCodeParsing()
{
const string wkt1 = "PROJCS[\"NAD_1983_BC_Environment_Albers\",GEOGCS[\"GCS_North_American_1983\",DATUM[\"D_North_American_1983\",SPHEROID[\"GRS_1980\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Albers\"],PARAMETER[\"False_Easting\",1000000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",-126.0],PARAMETER[\"Standard_Parallel_1\",50.0],PARAMETER[\"Standard_Parallel_2\",58.5],PARAMETER[\"Latitude_Of_Origin\",45.0],UNIT[\"Meter\",1.0],AUTHORITY[\"EPSG\",\"3005\"]]";
CoordinateSystem cs1 = null, cs2 = null;
Assert.DoesNotThrow( () => cs1 = CoordinateSystemFactory.CreateFromWkt(wkt1));
Assert.IsNotNull(cs1);
const string wkt2 = "PROJCS[\"NAD_1983_BC_Environment_Albers\",GEOGCS[\"GCS_North_American_1983\",DATUM[\"D_North_American_1983\",SPHEROID[\"GRS_1980\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Albers\"],PARAMETER[\"False_Easting\",1000000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",-126.0],PARAMETER[\"Standard_Parallel_1\",50.0],PARAMETER[\"Standard_Parallel_2\",58.5],PARAMETER[\"Latitude_Of_Origin\",45.0],UNIT[\"Meter\",1.0],AUTHORITY[\"EPSG\",3005]]";
Assert.DoesNotThrow(() => cs2 = CoordinateSystemFactory.CreateFromWkt(wkt2));
Assert.IsNotNull(cs2);
//Assert.AreEqual(cs1, cs2);
Assert.IsTrue(cs1.EqualParams(cs2));
}
[Test]
public void Test25832To3857()
{
const string wkt1 = //"PROJCS[\"ETRS89 / UTM zone 32N\",GEOGCS[\"ETRS89\",DATUM[\"European_Terrestrial_Reference_System_1989\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6258\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4258\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",9],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AUTHORITY[\"EPSG\",\"25832\"]]";
"PROJCS[\"ETRS89 / UTM zone 32N\",GEOGCS[\"ETRS89\",DATUM[\"European_Terrestrial_Reference_System_1989\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6258\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4258\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",9],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"25832\"],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]";
CoordinateSystem cs1 = null, cs2 = null;
Assert.DoesNotThrow(() => cs1 = CoordinateSystemFactory.CreateFromWkt(wkt1));
Assert.IsNotNull(cs1);
const string wkt2 = "PROJCS[\"WGS 84 / Pseudo-Mercator\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\", SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"latitude_of_origin\", 0],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],EXTENSION[\"PROJ4\",\"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs\"],AUTHORITY[\"EPSG\",\"3857\"],AXIS[\"X\",EAST],AXIS[\"Y\",NORTH]]";
Assert.DoesNotThrow(() => cs2 = CoordinateSystemFactory.CreateFromWkt(wkt2));
Assert.IsNotNull(cs2);
ICoordinateTransformation ct = null;
Assert.DoesNotThrow(() => ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(cs1, cs2));
Assert.IsNotNull(ct);
Assert.DoesNotThrow(() => ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(cs2, cs1));
Assert.IsNotNull(ct);
Assert.DoesNotThrow(() => ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(cs1, ProjectedCoordinateSystem.WebMercator));
Assert.IsNotNull(ct);
Assert.DoesNotThrow(() => ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(ProjectedCoordinateSystem.WebMercator, cs1));
Assert.IsNotNull(ct);
}
[Test]
public void TestLaea()
{
const string Epsg3035 =
@"PROJCS[""ETRS89 / ETRS-LAEA"",GEOGCS[""ETRS89"",DATUM[""European_Terrestrial_Reference_System_1989"",SPHEROID[""GRS 1980"",6378137,298.257222101,AUTHORITY[""EPSG"",""7019""]],AUTHORITY[""EPSG"",""6258""]],PRIMEM[""Greenwich"",0,AUTHORITY[""EPSG"",""8901""]],UNIT[""degree"",0.01745329251994328,AUTHORITY[""EPSG"",""9122""]],AUTHORITY[""EPSG"",""4258""]],UNIT[""metre"",1,AUTHORITY[""EPSG"",""9001""]],PROJECTION[""Lambert_Azimuthal_Equal_Area""],PARAMETER[""latitude_of_center"",52],PARAMETER[""longitude_of_center"",10],PARAMETER[""false_easting"",4321000],PARAMETER[""false_northing"",3210000],AUTHORITY[""EPSG"",""3035""],AXIS[""X"",EAST],AXIS[""Y"",NORTH]]";
var csSrc = GeographicCoordinateSystem.WGS84;
var csTgt = CoordinateSystemFactory.CreateFromWkt(Epsg3035);
var ct = CoordinateTransformationFactory.CreateFromCoordinateSystems(csSrc, csTgt);
(double resX, double resY) = ((MathTransform) ct.MathTransform).Transform(16.4, 48.2);
Assert.That(resX, Is.EqualTo(4796297.431434812).Within(1e-2));
Assert.That(resY, Is.EqualTo(2807999.1539475969).Within(1e-2));
(double origX, double origY) = ((MathTransform) ct.MathTransform.Inverse()).Transform(resX, resY);
Assert.That(origX, Is.EqualTo(16.4).Within(1e-2));
Assert.That(origY, Is.EqualTo(48.2).Within(1e-2));
Assert.That(resX, Is.EqualTo(4796297.431434812).Within(1e-2));
Assert.That(resY, Is.EqualTo(2807999.1539475969).Within(1e-2));
(double origX, double origY) = ((MathTransform) ct.MathTransform.Inverse()).Transform(resX, resY);
Assert.That(origX, Is.EqualTo(16.4).Within(1e-2));
Assert.That(origY, Is.EqualTo(48.2).Within(1e-2));
}
}
}
}

Просмотреть файл

@ -1,140 +1,140 @@
using System;
using System.Data;
using System.IO;
using Newtonsoft.Json.Linq;
using Npgsql;
using NUnit.Framework;
using ProjNet.CoordinateSystems;
namespace ProjNET.Tests.WKT
{
[TestFixture]
public class SpatialRefSysTableParser
{
private static string _connectionString;
private static readonly Lazy<CoordinateSystemFactory> CoordinateSystemFactory =
new Lazy<CoordinateSystemFactory>(() => new CoordinateSystemFactory());
[Test]
public void TestParsePostgisDefinitions()
{
if (string.IsNullOrWhiteSpace(ConnectionString))
throw new IgnoreException("No Connection string provided or provided connection string invalid.");
using (var cn = new NpgsqlConnection(ConnectionString))
{
cn.Open();
var cmd = cn.CreateCommand();
cmd.CommandText = "SELECT \"srid\", \"srtext\" FROM \"public\".\"spatial_ref_sys\" ORDER BY \"srid\";";
int counted = 0;
int failed = 0;
int tested = 0;
using (var r = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
if (r != null)
{
while (r.Read())
{
counted++;
int srid = r.GetInt32(0);
string srtext = r.GetString(1);
if (string.IsNullOrWhiteSpace(srtext)) continue;
if (srtext.StartsWith("COMPD_CS")) continue;
tested++;
if (!TestParse(srid, srtext)) failed++;
}
}
}
Console.WriteLine("\n\nTotal number of Tests {0}, failed {1}", tested, failed);
Assert.IsTrue(failed == 0);
}
}
[Test]//, Ignore("Only run this if you want a new SRID.csv file")]
public void TestCreateSridCsv()
{
if (string.IsNullOrWhiteSpace(ConnectionString))
throw new IgnoreException("No Connection string provided or provided connection string invalid.");
if (File.Exists("SRID.csv")) File.Delete("SRID.csv");
using (var sw = new StreamWriter(File.OpenWrite("SRID.csv")))
using (var cn = new NpgsqlConnection(ConnectionString))
{
cn.Open();
var cm = cn.CreateCommand();
cm.CommandText = "SELECT \"srid\", \"srtext\" FROM \"public\".\"spatial_ref_sys\" ORDER BY srid;";
using (var dr = cm.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (dr.Read())
{
int srid = dr.GetInt32(0);
string srtext = dr.GetString(1);
switch (srtext.Substring(0, srtext.IndexOf("[")))
{
case "PROJCS":
case "GEOGCS":
case "GEOCCS":
sw.WriteLine($"{srid};{srtext}");
break;
}
}
}
cm.Dispose();
}
}
private static string ConnectionString
{
get
{
if (!string.IsNullOrWhiteSpace(_connectionString))
return _connectionString;
if (!File.Exists("appsettings.json"))
return null;
JToken token = null;
using (var jtr = new Newtonsoft.Json.JsonTextReader(new StreamReader("appsettings.json")))
token = JToken.ReadFrom(jtr);
string connectionString = (string)token["ConnectionString"];
try
{
using (var cn = new NpgsqlConnection(connectionString))
cn.Open();
}
catch (Exception)
{
return null;
}
_connectionString = connectionString;
return _connectionString;
}
}
private static bool TestParse(int srid, string srtext)
{
try
{
CoordinateSystemFactory.Value.CreateFromWkt(srtext);
//CoordinateSystemWktReader.Parse(srtext);
return true;
}
catch (Exception ex)
{
Console.WriteLine("Test {0} failed:\n {1}\n {2}", srid, srtext, ex.Message);
return false;
}
}
}
}
using System;
using System.Data;
using System.IO;
using Newtonsoft.Json.Linq;
using Npgsql;
using NUnit.Framework;
using ProjNet.CoordinateSystems;
namespace ProjNET.Tests.WKT
{
[TestFixture]
public class SpatialRefSysTableParser
{
private static string _connectionString;
private static readonly Lazy<CoordinateSystemFactory> CoordinateSystemFactory =
new Lazy<CoordinateSystemFactory>(() => new CoordinateSystemFactory());
[Test]
public void TestParsePostgisDefinitions()
{
if (string.IsNullOrWhiteSpace(ConnectionString))
throw new IgnoreException("No Connection string provided or provided connection string invalid.");
using (var cn = new NpgsqlConnection(ConnectionString))
{
cn.Open();
var cmd = cn.CreateCommand();
cmd.CommandText = "SELECT \"srid\", \"srtext\" FROM \"public\".\"spatial_ref_sys\" ORDER BY \"srid\";";
int counted = 0;
int failed = 0;
int tested = 0;
using (var r = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
if (r != null)
{
while (r.Read())
{
counted++;
int srid = r.GetInt32(0);
string srtext = r.GetString(1);
if (string.IsNullOrWhiteSpace(srtext)) continue;
if (srtext.StartsWith("COMPD_CS")) continue;
tested++;
if (!TestParse(srid, srtext)) failed++;
}
}
}
Console.WriteLine("\n\nTotal number of Tests {0}, failed {1}", tested, failed);
Assert.IsTrue(failed == 0);
}
}
[Test]//, Ignore("Only run this if you want a new SRID.csv file")]
public void TestCreateSridCsv()
{
if (string.IsNullOrWhiteSpace(ConnectionString))
throw new IgnoreException("No Connection string provided or provided connection string invalid.");
if (File.Exists("SRID.csv")) File.Delete("SRID.csv");
using (var sw = new StreamWriter(File.OpenWrite("SRID.csv")))
using (var cn = new NpgsqlConnection(ConnectionString))
{
cn.Open();
var cm = cn.CreateCommand();
cm.CommandText = "SELECT \"srid\", \"srtext\" FROM \"public\".\"spatial_ref_sys\" ORDER BY srid;";
using (var dr = cm.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (dr.Read())
{
int srid = dr.GetInt32(0);
string srtext = dr.GetString(1);
switch (srtext.Substring(0, srtext.IndexOf("[")))
{
case "PROJCS":
case "GEOGCS":
case "GEOCCS":
sw.WriteLine($"{srid};{srtext}");
break;
}
}
}
cm.Dispose();
}
}
private static string ConnectionString
{
get
{
if (!string.IsNullOrWhiteSpace(_connectionString))
return _connectionString;
if (!File.Exists("appsettings.json"))
return null;
JToken token = null;
using (var jtr = new Newtonsoft.Json.JsonTextReader(new StreamReader("appsettings.json")))
token = JToken.ReadFrom(jtr);
string connectionString = (string)token["ConnectionString"];
try
{
using (var cn = new NpgsqlConnection(connectionString))
cn.Open();
}
catch (Exception)
{
return null;
}
_connectionString = connectionString;
return _connectionString;
}
}
private static bool TestParse(int srid, string srtext)
{
try
{
CoordinateSystemFactory.Value.CreateFromWkt(srtext);
//CoordinateSystemWktReader.Parse(srtext);
return true;
}
catch (Exception ex)
{
Console.WriteLine("Test {0} failed:\n {1}\n {2}", srid, srtext, ex.Message);
return false;
}
}
}
}

Просмотреть файл

@ -1,498 +1,498 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using NUnit.Framework;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNET.Tests.WKT
{
[TestFixture]
public class WKTCoordSysParserTests
{
private readonly CoordinateSystemFactory _coordinateSystemFactory = new CoordinateSystemFactory();
/// <summary>
/// Parses a coordinate system WKT
/// </summary>
/// <remarks><code>
/// PROJCS["NAD83(HARN) / Texas Central (ftUS)",
/// GEOGCS[
/// "NAD83(HARN)",
/// DATUM[
/// "NAD83_High_Accuracy_Regional_Network",
/// SPHEROID[
/// "GRS 1980",
/// 6378137,
/// 298.257222101,
/// AUTHORITY["EPSG","7019"]
/// ],
/// TOWGS84[725,685,536,0,0,0,0],
/// AUTHORITY["EPSG","6152"]
/// ],
/// PRIMEM[
/// "Greenwich",
/// 0,
/// AUTHORITY["EPSG","8901"]
/// ],
/// UNIT[
/// "degree",
/// 0.01745329251994328,
/// AUTHORITY["EPSG","9122"]
/// ],
/// AUTHORITY["EPSG","4152"]
/// ],
/// PROJECTION["Lambert_Conformal_Conic_2SP"],
/// PARAMETER["standard_parallel_1",31.88333333333333],
/// PARAMETER["standard_parallel_2",30.11666666666667],
/// PARAMETER["latitude_of_origin",29.66666666666667],
/// PARAMETER["central_meridian",-100.3333333333333],
/// PARAMETER["false_easting",2296583.333],
/// PARAMETER["false_northing",9842500.000000002],
/// UNIT[
/// "US survey foot",
/// 0.3048006096012192,
/// AUTHORITY["EPSG","9003"]
/// ],
/// AUTHORITY["EPSG","2918"]
/// ]
/// </code></remarks>
[Test]
public void TestProjectedCoordinateSystem_EPSG_2918()
{
const string wkt = "PROJCS[\"NAD83(HARN) / Texas Central (ftUS)\", "+
"GEOGCS[\"NAD83(HARN)\", " +
"DATUM[\"NAD83_High_Accuracy_Regional_Network\", "+
"SPHEROID[\"GRS 1980\", 6378137, 298.257222101, AUTHORITY[\"EPSG\", \"7019\"]], "+
"TOWGS84[725, 685, 536, 0, 0, 0, 0], " +
"AUTHORITY[\"EPSG\", \"6152\"]], "+
"PRIMEM[\"Greenwich\", 0, AUTHORITY[\"EPSG\", \"8901\"]], "+
"UNIT[\"degree\", 0.0174532925199433, AUTHORITY[\"EPSG\", \"9122\"]], "+
"AUTHORITY[\"EPSG\", \"4152\"]], "+
"UNIT[\"US survey foot\", 0.304800609601219, AUTHORITY[\"EPSG\", \"9003\"]], "+
"PROJECTION[\"Lambert_Conformal_Conic_2SP\"], " +
"PARAMETER[\"standard_parallel_1\", 31.883333333333], " +
"PARAMETER[\"standard_parallel_2\", 30.1166666667], " +
"PARAMETER[\"latitude_of_origin\", 29.6666666667], " +
"PARAMETER[\"central_meridian\", -100.333333333333], " +
"PARAMETER[\"false_easting\", 2296583.333], " +
"PARAMETER[\"false_northing\", 9842500], " +
"AUTHORITY[\"EPSG\", \"2918\"]]";
ProjectedCoordinateSystem pcs = null;
Assert.That(() => pcs = _coordinateSystemFactory.CreateFromWkt(wkt) as ProjectedCoordinateSystem, Throws.Nothing);
Assert.That(pcs, Is.Not.Null, "Could not parse WKT: " + wkt);
CheckInfo(pcs, "NAD83(HARN) / Texas Central (ftUS)", "EPSG", 2918);
var gcs = pcs.GeographicCoordinateSystem;
CheckInfo(gcs, "NAD83(HARN)", "EPSG", 4152);
CheckDatum(gcs.HorizontalDatum, "NAD83_High_Accuracy_Regional_Network", "EPSG", 6152);
CheckEllipsoid(gcs.HorizontalDatum.Ellipsoid, "GRS 1980", 6378137, 298.257222101, "EPSG", 7019);
Assert.AreEqual(new Wgs84ConversionInfo(725, 685, 536, 0, 0, 0, 0), pcs.GeographicCoordinateSystem.HorizontalDatum.Wgs84Parameters);
CheckPrimem(gcs.PrimeMeridian, "Greenwich", 0, "EPSG", 8901);
CheckUnit(gcs.AngularUnit, "degree", 0.0174532925199433, "EPSG", 9122);
CheckProjection(pcs.Projection, "Lambert_Conformal_Conic_2SP", new[]
{
Tuple.Create("standard_parallel_1", 31.883333333333),
Tuple.Create("standard_parallel_2", 30.1166666667),
Tuple.Create("latitude_of_origin", 29.6666666667),
Tuple.Create("central_meridian", -100.333333333333),
Tuple.Create("false_easting", 2296583.333),
Tuple.Create("false_northing", 9842500d)
});
CheckUnit(pcs.LinearUnit, "US survey foot", 0.304800609601219, "EPSG", 9003);
}
/// <summary>
/// This test reads in a file with 2671 pre-defined coordinate systems and projections,
/// and tries to parse them.
/// </summary>
[Test]
public void ParseAllWKTs()
{
int parseCount = 0;
foreach (var wkt in SRIDReader.GetSrids())
{
var cs = _coordinateSystemFactory.CreateFromWkt(wkt.Wkt);
Assert.IsNotNull(cs, "Could not parse WKT: " + wkt);
parseCount++;
}
Assert.That(parseCount, Is.GreaterThan(2671), "Not all WKT was parsed");
}
/// <summary>
/// This test reads in a file with 2671 pre-defined coordinate systems and projections,
/// and tries to create a transformation with them.
/// </summary>
[Test]
public void TestCreateCoordinateTransformationForWktInCsv()
{
//GeographicCoordinateSystem.WGS84
var fac = new CoordinateSystemFactory();
int parseCount = 0;
int failedCss = 0;
var failedProjections = new HashSet<string>();
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ProjNET.Tests.SRID.csv"))
{
using (var sr = new StreamReader(stream, Encoding.UTF8))
{
var ctFactory = new CoordinateTransformationFactory();
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
if (string.IsNullOrWhiteSpace(line)) continue;
int split = line.IndexOf(';');
if (split > -1)
{
string wkt = line.Substring(split + 1);
var cs = fac.CreateFromWkt(wkt);
if (cs == null) continue; //We check this in another test.
if (cs is ProjectedCoordinateSystem pcs)
{
switch (pcs.Projection.ClassName)
{
//Skip not supported projections
case "Oblique_Stereographic":
case "Transverse_Mercator_South_Orientated":
case "Lambert_Conformal_Conic_1SP":
case "Lambert_Azimuthal_Equal_Area":
case "Tunisia_Mining_Grid":
case "New_Zealand_Map_Grid":
case "Polyconic":
case "Lambert_Conformal_Conic_2SP_Belgium":
case "Polar_Stereographic":
case "Hotine_Oblique_Mercator_Azimuth_Center":
case "Mercator_1SP":
case "Mercator_2SP":
case "Cylindrical_Equal_Area":
case "Equirectangular":
case "Laborde_Oblique_Mercator":
continue;
}
}
try
{
ctFactory.CreateFromCoordinateSystems(GeographicCoordinateSystem.WGS84, cs);
}
catch (Exception)
{
if (cs is ProjectedCoordinateSystem ics)
{
if (!failedProjections.Contains(ics.Projection.ClassName))
failedProjections.Add(ics.Projection.ClassName);
}
else
{
Assert.That(false);
}
failedCss += 1;
// Assert.Fail(
// $"Could not create transformation from:\r\n{wkt}\r\n{ex.Message}\r\nClass name:{ics.Projection.ClassName}");
//else
// Assert.Fail($"Could not create transformation from:\r\n{wkt}\r\n{ex.Message}");
}
parseCount++;
}
}
}
}
Assert.GreaterOrEqual(parseCount, 2556, "Not all WKT was processed");
if (failedCss > 0)
{
Console.WriteLine($"Failed to create transfroms for {failedCss} coordinate systems");
foreach (string fp in failedProjections)
{
Console.WriteLine($"case \"{fp}\":");
}
}
}
/// <summary>
/// Test parsing of a <see cref="ProjectedCoordinateSystem"/> from WKT
/// </summary>
[Test]
public void TestProjectedCoordinateSystem_EPSG27700_UnitBeforeProjection()
{
const string wkt = "PROJCS[\"OSGB 1936 / British National Grid\"," +
"GEOGCS[\"OSGB 1936\"," +
"DATUM[\"OSGB_1936\"," +
"SPHEROID[\"Airy 1830\",6377563.396,299.3249646,AUTHORITY[\"EPSG\",\"7001\"]]," +
"AUTHORITY[\"EPSG\",\"6277\"]]," +
"PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]]," +
"UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]," +
"AUTHORITY[\"EPSG\",\"4277\"]]," +
"UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]]," +
"PROJECTION[\"Transverse_Mercator\"]," +
"PARAMETER[\"latitude_of_origin\",49]," +
"PARAMETER[\"central_meridian\",-2]," +
"PARAMETER[\"scale_factor\",0.9996012717]," +
"PARAMETER[\"false_easting\",400000]," +
"PARAMETER[\"false_northing\",-100000]," +
"AUTHORITY[\"EPSG\",\"27700\"]," +
"AXIS[\"Easting\",EAST]," +
"AXIS[\"Northing\",NORTH]]";
ProjectedCoordinateSystem pcs = null;
Assert.That(() => pcs = _coordinateSystemFactory.CreateFromWkt(wkt) as ProjectedCoordinateSystem, Throws.Nothing);
CheckInfo(pcs, "OSGB 1936 / British National Grid", "EPSG", 27700);
var gcs = pcs.GeographicCoordinateSystem;
CheckInfo(gcs, "OSGB 1936", "EPSG", 4277);
CheckDatum(gcs.HorizontalDatum, "OSGB_1936", "EPSG", 6277);
CheckEllipsoid(gcs.HorizontalDatum.Ellipsoid, "Airy 1830", 6377563.396, 299.3249646, "EPSG", 7001);
CheckPrimem(gcs.PrimeMeridian, "Greenwich", 0, "EPSG", 8901);
CheckUnit(gcs.AngularUnit, "degree", 0.0174532925199433, "EPSG", 9122);
Assert.AreEqual("Transverse_Mercator", pcs.Projection.ClassName, "Projection Classname");
CheckProjection(pcs.Projection, "Transverse_Mercator", new []
{
Tuple.Create("latitude_of_origin", 49d),
Tuple.Create("central_meridian",-2d),
Tuple.Create("scale_factor",0.9996012717),
Tuple.Create("false_easting",400000d),
Tuple.Create("false_northing",-100000d)
});
CheckUnit(pcs.LinearUnit, "metre", 1d, "EPSG", 9001);
string newWkt = pcs.WKT.Replace(", ", ",");
Assert.AreEqual(wkt, newWkt);
}
[Test]
public void TestParseSrOrg()
{
Assert.That(() => _coordinateSystemFactory.CreateFromWkt(
"PROJCS[\"WGS 84 / Pseudo-Mercator\",GEOGCS[\"Popular Visualisation CRS\"," +
"DATUM[\"Popular_Visualisation_Datum\",SPHEROID[\"Popular Visualisation Sphere\"," +
"6378137,0,AUTHORITY[\"EPSG\",\"7059\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\"," +
"\"6055\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\"," +
"0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4055\"]]," +
"UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Mercator_1SP\"]," +
"PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[" +
"\"false_easting\",0],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"3785\"]" +
",AXIS[\"X\",EAST],AXIS[\"Y\",NORTH]]"), Throws.Nothing);
}
[Test]
public void TestProjNetIssues()
{
Assert.That(() => _coordinateSystemFactory.CreateFromWkt(
"PROJCS[\"International_Terrestrial_Reference_Frame_1992Lambert_Conformal_Conic_2SP\"," +
"GEOGCS[\"GCS_International_Terrestrial_Reference_Frame_1992\"," +
"DATUM[\"International_Terrestrial_Reference_Frame_1992\"," +
"SPHEROID[\"GRS_1980\",6378137,298.257222101]," +
"TOWGS84[0,0,0,0,0,0,0]]," +
"PRIMEM[\"Greenwich\",0]," +
"UNIT[\"Degree\",0.0174532925199433]]," +
"PROJECTION[\"Lambert_Conformal_Conic_2SP\",AUTHORITY[\"EPSG\",\"9802\"]]," +
"PARAMETER[\"Central_Meridian\",-102]," +
"PARAMETER[\"Latitude_Of_Origin\",12]," +
"PARAMETER[\"False_Easting\",2500000]," +
"PARAMETER[\"False_Northing\",0]," +
"PARAMETER[\"Standard_Parallel_1\",17.5]," +
"PARAMETER[\"Standard_Parallel_2\",29.5]," +
"PARAMETER[\"Scale_Factor\",1]," +
"UNIT[\"Meter\",1,AUTHORITY[\"EPSG\",\"9001\"]]]"), Throws.Nothing);
Assert.That(() => _coordinateSystemFactory.CreateFromWkt(
"PROJCS[\"Google Maps Global Mercator\"," +
"GEOGCS[\"WGS 84\"," +
"DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]]," +
"AUTHORITY[\"EPSG\",\"6326\"]]," +
"PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]]," +
"UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]]," +
"AUTHORITY[\"EPSG\",\"4326\"]]," +
"PROJECTION[\"Mercator_2SP\"]," +
"PARAMETER[\"standard_parallel_1\",0]," +
"PARAMETER[\"latitude_of_origin\",0]," +
"PARAMETER[\"central_meridian\",0]," +
"PARAMETER[\"false_easting\",0]," +
"PARAMETER[\"false_northing\",0]," +
"UNIT[\"Meter\",1]," +
"EXTENSION[\"PROJ4\",\"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs\"]," +
"AUTHORITY[\"EPSG\",\"900913\"]]"), Throws.Nothing);
}
/// <summary>
/// Test parsing of a <see cref="FittedCoordinateSystem"/> from WKT
/// </summary>
[Test]
public void TestFittedCoordinateSystemWkt ()
{
var fac = new CoordinateSystemFactory ();
FittedCoordinateSystem fcs = null;
string wkt = "FITTED_CS[\"Local coordinate system MNAU (based on Gauss-Krueger)\"," +
"PARAM_MT[\"Affine\"," +
"PARAMETER[\"num_row\",3],PARAMETER[\"num_col\",3],PARAMETER[\"elt_0_0\", 0.883485346527455],PARAMETER[\"elt_0_1\", -0.468458794848877],PARAMETER[\"elt_0_2\", 3455869.17937689],PARAMETER[\"elt_1_0\", 0.468458794848877],PARAMETER[\"elt_1_1\", 0.883485346527455],PARAMETER[\"elt_1_2\", 5478710.88035753],PARAMETER[\"elt_2_2\", 1]]," +
"PROJCS[\"DHDN / Gauss-Kruger zone 3\"," +
"GEOGCS[\"DHDN\"," +
"DATUM[\"Deutsches_Hauptdreiecksnetz\"," +
"SPHEROID[\"Bessel 1841\", 6377397.155, 299.1528128, AUTHORITY[\"EPSG\", \"7004\"]]," +
"TOWGS84[612.4, 77, 440.2, -0.054, 0.057, -2.797, 0.525975255930096]," +
"AUTHORITY[\"EPSG\", \"6314\"]]," +
"PRIMEM[\"Greenwich\", 0, AUTHORITY[\"EPSG\", \"8901\"]]," +
"UNIT[\"degree\", 0.0174532925199433, AUTHORITY[\"EPSG\", \"9122\"]]," +
"AUTHORITY[\"EPSG\", \"4314\"]]," +
"UNIT[\"metre\", 1, AUTHORITY[\"EPSG\", \"9001\"]]," +
"PROJECTION[\"Transverse_Mercator\"]," +
"PARAMETER[\"latitude_of_origin\", 0]," +
"PARAMETER[\"central_meridian\", 9]," +
"PARAMETER[\"scale_factor\", 1]," +
"PARAMETER[\"false_easting\", 3500000]," +
"PARAMETER[\"false_northing\", 0]," +
"AUTHORITY[\"EPSG\", \"31467\"]]" +
"]";
try
{
fcs = fac.CreateFromWkt (wkt) as FittedCoordinateSystem;
}
catch (Exception ex)
{
Assert.Fail ("Could not create fitted coordinate system from:\r\n" + wkt + "\r\n" + ex.Message);
}
Assert.That(fcs, Is.Not.Null);
Assert.That(fcs.ToBase(), Is.Not.Null.Or.Empty);
Assert.That(fcs.BaseCoordinateSystem, Is.Not.Null);
Assert.AreEqual ("Local coordinate system MNAU (based on Gauss-Krueger)", fcs.Name);
//Assert.AreEqual ("CUSTOM", fcs.Authority);
//Assert.AreEqual (123456, fcs.AuthorityCode);
Assert.AreEqual ("EPSG", fcs.BaseCoordinateSystem.Authority);
Assert.AreEqual (31467, fcs.BaseCoordinateSystem.AuthorityCode);
}
/// <summary>
/// Test parsing of a <see cref="GeocentricCoordinateSystem"/> from WKT
/// </summary>
[Test]
public void TestGeocentricCoordinateSystem()
{
var fac = new CoordinateSystemFactory();
GeocentricCoordinateSystem fcs = null;
const string wkt = "GEOCCS[\"TUREF\", " +
"DATUM[\"Turkish_National_Reference_Frame\", " +
"SPHEROID[\"GRS 1980\", 6378137, 298.257222101, AUTHORITY[\"EPSG\", \"7019\"]], " +
"AUTHORITY[\"EPSG\", \"1057\"]], " +
"PRIMEM[\"Greenwich\", 0, AUTHORITY[\"EPSG\", \"8901\"]], " +
"UNIT[\"metre\", 1, AUTHORITY[\"EPSG\", \"9001\"]], " +
"AXIS[\"Geocentric X\", OTHER], AXIS[\"Geocentric Y\", OTHER], AXIS[\"Geocentric Z\", NORTH], " +
"AUTHORITY[\"EPSG\", \"5250\"]]";
try
{
fcs = fac.CreateFromWkt(wkt) as GeocentricCoordinateSystem;
}
catch (Exception ex)
{
Assert.Fail("Could not create geocentric coordinate system from:\r\n" + wkt + "\r\n" + ex.Message);
}
Assert.That(fcs, Is.Not.Null);
Assert.That(CheckInfo(fcs, "TUREF", "EPSG", 5250L));
Assert.That(CheckDatum(fcs.HorizontalDatum, "Turkish_National_Reference_Frame", "EPSG", 1057L), Is.True);
Assert.That(CheckEllipsoid(fcs.HorizontalDatum.Ellipsoid, "GRS 1980", 6378137, 298.257222101, "EPSG", 7019), Is.True);
Assert.That(CheckPrimem(fcs.PrimeMeridian, "Greenwich", 0, "EPSG", 8901L), Is.True);
Assert.That(CheckUnit(fcs.PrimeMeridian.AngularUnit, "degree", null, null, null), Is.True);
Assert.That(CheckUnit(fcs.LinearUnit, "metre", 1, "EPSG", 9001L), Is.True);
Assert.That(fcs.Authority, Is.EqualTo("EPSG"));
Assert.That(fcs.AuthorityCode, Is.EqualTo(5250L));
}
#region Utility
private bool CheckPrimem(PrimeMeridian primeMeridian, string name, double? longitude, string authority, long? code)
{
Assert.That(primeMeridian, Is.Not.Null);
Assert.That(CheckInfo(primeMeridian, name, authority, code));
Assert.That(primeMeridian.Longitude, Is.EqualTo(longitude));
return true;
}
private static bool CheckUnit(IUnit unit, string name, double? value, string authority, long? code)
{
Assert.That(unit, Is.Not.Null);
Assert.That(CheckInfo(unit, name, authority, code));
Assert.That(unit, Is.InstanceOf<LinearUnit>().Or.InstanceOf<AngularUnit>());
if (!value.HasValue) return true;
if (unit is LinearUnit lunit)
Assert.That(lunit.MetersPerUnit, Is.EqualTo(value));
else if (unit is AngularUnit aunit)
Assert.That(aunit.RadiansPerUnit, Is.EqualTo(value));
return true;
}
private static bool CheckEllipsoid(Ellipsoid ellipsoid, string name, double? semiMajor, double? inverseFlattening, string authority, long? code)
{
Assert.That(ellipsoid, Is.Not.Null);
Assert.That(CheckInfo(ellipsoid, name, authority, code));
if (semiMajor.HasValue) Assert.That(ellipsoid.SemiMajorAxis, Is.EqualTo(semiMajor));
if (inverseFlattening.HasValue) Assert.That(ellipsoid.InverseFlattening, Is.EqualTo(inverseFlattening));
return true;
}
private static bool CheckDatum(Datum datum, string name, string authority, long? code)
{
Assert.That(datum, Is.Not.Null);
Assert.That(datum, Is.InstanceOf<HorizontalDatum>()/*.Or.InstanceOf<IVerticalDatum>()*/);
Assert.That(CheckInfo(datum, name,authority, code), Is.True);
return true;
}
private static bool CheckInfo(IInfo info, string name, string authority = null, long? code = null)
{
Assert.That(info, Is.Not.Null);
if (!string.IsNullOrWhiteSpace(name)) Assert.That(info.Name, Is.EqualTo(name));
if (!string.IsNullOrWhiteSpace(authority)) Assert.That(info.Authority, Is.EqualTo(authority));
if (code.HasValue) Assert.That(info.AuthorityCode, Is.EqualTo(code));
return true;
}
private static void CheckProjection(IProjection projection, string name, IList<Tuple<string, double>> pp = null, string authority = null, long? code = null)
{
Assert.That(projection, Is.Not.Null, "Projection not null");
Assert.That(projection.ClassName, Is.EqualTo(name), "Projection class name");
CheckInfo(projection, name, authority, code);
if (pp == null) return;
Assert.That(projection.NumParameters, Is.EqualTo(pp.Count), "Number of projection parameters");
for (int i = 0; i < pp.Count; i++)
{
ProjectionParameter par = null;
Assert.That(() => par = projection.GetParameter(pp[i].Item1), Throws.Nothing, $"Getting projection parameter '{pp[i].Item1}' throws.");
Assert.That(par, Is.Not.Null, $"Projection parameter '{pp[i].Item1}' is null");
Assert.That(par.Name, Is.EqualTo(pp[i].Item1), $"Projection parameter '{par.Name}' name is not '{pp[i].Item1}'.");
Assert.That(par.Value, Is.EqualTo(pp[i].Item2), $"Projection parameter value for '{par.Name}' name ({par.Value:R}) is not '{pp[i].Item2:R}'.");
}
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using NUnit.Framework;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNET.Tests.WKT
{
[TestFixture]
public class WKTCoordSysParserTests
{
private readonly CoordinateSystemFactory _coordinateSystemFactory = new CoordinateSystemFactory();
/// <summary>
/// Parses a coordinate system WKT
/// </summary>
/// <remarks><code>
/// PROJCS["NAD83(HARN) / Texas Central (ftUS)",
/// GEOGCS[
/// "NAD83(HARN)",
/// DATUM[
/// "NAD83_High_Accuracy_Regional_Network",
/// SPHEROID[
/// "GRS 1980",
/// 6378137,
/// 298.257222101,
/// AUTHORITY["EPSG","7019"]
/// ],
/// TOWGS84[725,685,536,0,0,0,0],
/// AUTHORITY["EPSG","6152"]
/// ],
/// PRIMEM[
/// "Greenwich",
/// 0,
/// AUTHORITY["EPSG","8901"]
/// ],
/// UNIT[
/// "degree",
/// 0.01745329251994328,
/// AUTHORITY["EPSG","9122"]
/// ],
/// AUTHORITY["EPSG","4152"]
/// ],
/// PROJECTION["Lambert_Conformal_Conic_2SP"],
/// PARAMETER["standard_parallel_1",31.88333333333333],
/// PARAMETER["standard_parallel_2",30.11666666666667],
/// PARAMETER["latitude_of_origin",29.66666666666667],
/// PARAMETER["central_meridian",-100.3333333333333],
/// PARAMETER["false_easting",2296583.333],
/// PARAMETER["false_northing",9842500.000000002],
/// UNIT[
/// "US survey foot",
/// 0.3048006096012192,
/// AUTHORITY["EPSG","9003"]
/// ],
/// AUTHORITY["EPSG","2918"]
/// ]
/// </code></remarks>
[Test]
public void TestProjectedCoordinateSystem_EPSG_2918()
{
const string wkt = "PROJCS[\"NAD83(HARN) / Texas Central (ftUS)\", "+
"GEOGCS[\"NAD83(HARN)\", " +
"DATUM[\"NAD83_High_Accuracy_Regional_Network\", "+
"SPHEROID[\"GRS 1980\", 6378137, 298.257222101, AUTHORITY[\"EPSG\", \"7019\"]], "+
"TOWGS84[725, 685, 536, 0, 0, 0, 0], " +
"AUTHORITY[\"EPSG\", \"6152\"]], "+
"PRIMEM[\"Greenwich\", 0, AUTHORITY[\"EPSG\", \"8901\"]], "+
"UNIT[\"degree\", 0.0174532925199433, AUTHORITY[\"EPSG\", \"9122\"]], "+
"AUTHORITY[\"EPSG\", \"4152\"]], "+
"UNIT[\"US survey foot\", 0.304800609601219, AUTHORITY[\"EPSG\", \"9003\"]], "+
"PROJECTION[\"Lambert_Conformal_Conic_2SP\"], " +
"PARAMETER[\"standard_parallel_1\", 31.883333333333], " +
"PARAMETER[\"standard_parallel_2\", 30.1166666667], " +
"PARAMETER[\"latitude_of_origin\", 29.6666666667], " +
"PARAMETER[\"central_meridian\", -100.333333333333], " +
"PARAMETER[\"false_easting\", 2296583.333], " +
"PARAMETER[\"false_northing\", 9842500], " +
"AUTHORITY[\"EPSG\", \"2918\"]]";
ProjectedCoordinateSystem pcs = null;
Assert.That(() => pcs = _coordinateSystemFactory.CreateFromWkt(wkt) as ProjectedCoordinateSystem, Throws.Nothing);
Assert.That(pcs, Is.Not.Null, "Could not parse WKT: " + wkt);
CheckInfo(pcs, "NAD83(HARN) / Texas Central (ftUS)", "EPSG", 2918);
var gcs = pcs.GeographicCoordinateSystem;
CheckInfo(gcs, "NAD83(HARN)", "EPSG", 4152);
CheckDatum(gcs.HorizontalDatum, "NAD83_High_Accuracy_Regional_Network", "EPSG", 6152);
CheckEllipsoid(gcs.HorizontalDatum.Ellipsoid, "GRS 1980", 6378137, 298.257222101, "EPSG", 7019);
Assert.AreEqual(new Wgs84ConversionInfo(725, 685, 536, 0, 0, 0, 0), pcs.GeographicCoordinateSystem.HorizontalDatum.Wgs84Parameters);
CheckPrimem(gcs.PrimeMeridian, "Greenwich", 0, "EPSG", 8901);
CheckUnit(gcs.AngularUnit, "degree", 0.0174532925199433, "EPSG", 9122);
CheckProjection(pcs.Projection, "Lambert_Conformal_Conic_2SP", new[]
{
Tuple.Create("standard_parallel_1", 31.883333333333),
Tuple.Create("standard_parallel_2", 30.1166666667),
Tuple.Create("latitude_of_origin", 29.6666666667),
Tuple.Create("central_meridian", -100.333333333333),
Tuple.Create("false_easting", 2296583.333),
Tuple.Create("false_northing", 9842500d)
});
CheckUnit(pcs.LinearUnit, "US survey foot", 0.304800609601219, "EPSG", 9003);
}
/// <summary>
/// This test reads in a file with 2671 pre-defined coordinate systems and projections,
/// and tries to parse them.
/// </summary>
[Test]
public void ParseAllWKTs()
{
int parseCount = 0;
foreach (var wkt in SRIDReader.GetSrids())
{
var cs = _coordinateSystemFactory.CreateFromWkt(wkt.Wkt);
Assert.IsNotNull(cs, "Could not parse WKT: " + wkt);
parseCount++;
}
Assert.That(parseCount, Is.GreaterThan(2671), "Not all WKT was parsed");
}
/// <summary>
/// This test reads in a file with 2671 pre-defined coordinate systems and projections,
/// and tries to create a transformation with them.
/// </summary>
[Test]
public void TestCreateCoordinateTransformationForWktInCsv()
{
//GeographicCoordinateSystem.WGS84
var fac = new CoordinateSystemFactory();
int parseCount = 0;
int failedCss = 0;
var failedProjections = new HashSet<string>();
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ProjNET.Tests.SRID.csv"))
{
using (var sr = new StreamReader(stream, Encoding.UTF8))
{
var ctFactory = new CoordinateTransformationFactory();
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
if (string.IsNullOrWhiteSpace(line)) continue;
int split = line.IndexOf(';');
if (split > -1)
{
string wkt = line.Substring(split + 1);
var cs = fac.CreateFromWkt(wkt);
if (cs == null) continue; //We check this in another test.
if (cs is ProjectedCoordinateSystem pcs)
{
switch (pcs.Projection.ClassName)
{
//Skip not supported projections
case "Oblique_Stereographic":
case "Transverse_Mercator_South_Orientated":
case "Lambert_Conformal_Conic_1SP":
case "Lambert_Azimuthal_Equal_Area":
case "Tunisia_Mining_Grid":
case "New_Zealand_Map_Grid":
case "Polyconic":
case "Lambert_Conformal_Conic_2SP_Belgium":
case "Polar_Stereographic":
case "Hotine_Oblique_Mercator_Azimuth_Center":
case "Mercator_1SP":
case "Mercator_2SP":
case "Cylindrical_Equal_Area":
case "Equirectangular":
case "Laborde_Oblique_Mercator":
continue;
}
}
try
{
ctFactory.CreateFromCoordinateSystems(GeographicCoordinateSystem.WGS84, cs);
}
catch (Exception)
{
if (cs is ProjectedCoordinateSystem ics)
{
if (!failedProjections.Contains(ics.Projection.ClassName))
failedProjections.Add(ics.Projection.ClassName);
}
else
{
Assert.That(false);
}
failedCss += 1;
// Assert.Fail(
// $"Could not create transformation from:\r\n{wkt}\r\n{ex.Message}\r\nClass name:{ics.Projection.ClassName}");
//else
// Assert.Fail($"Could not create transformation from:\r\n{wkt}\r\n{ex.Message}");
}
parseCount++;
}
}
}
}
Assert.GreaterOrEqual(parseCount, 2556, "Not all WKT was processed");
if (failedCss > 0)
{
Console.WriteLine($"Failed to create transfroms for {failedCss} coordinate systems");
foreach (string fp in failedProjections)
{
Console.WriteLine($"case \"{fp}\":");
}
}
}
/// <summary>
/// Test parsing of a <see cref="ProjectedCoordinateSystem"/> from WKT
/// </summary>
[Test]
public void TestProjectedCoordinateSystem_EPSG27700_UnitBeforeProjection()
{
const string wkt = "PROJCS[\"OSGB 1936 / British National Grid\"," +
"GEOGCS[\"OSGB 1936\"," +
"DATUM[\"OSGB_1936\"," +
"SPHEROID[\"Airy 1830\",6377563.396,299.3249646,AUTHORITY[\"EPSG\",\"7001\"]]," +
"AUTHORITY[\"EPSG\",\"6277\"]]," +
"PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]]," +
"UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]," +
"AUTHORITY[\"EPSG\",\"4277\"]]," +
"UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]]," +
"PROJECTION[\"Transverse_Mercator\"]," +
"PARAMETER[\"latitude_of_origin\",49]," +
"PARAMETER[\"central_meridian\",-2]," +
"PARAMETER[\"scale_factor\",0.9996012717]," +
"PARAMETER[\"false_easting\",400000]," +
"PARAMETER[\"false_northing\",-100000]," +
"AUTHORITY[\"EPSG\",\"27700\"]," +
"AXIS[\"Easting\",EAST]," +
"AXIS[\"Northing\",NORTH]]";
ProjectedCoordinateSystem pcs = null;
Assert.That(() => pcs = _coordinateSystemFactory.CreateFromWkt(wkt) as ProjectedCoordinateSystem, Throws.Nothing);
CheckInfo(pcs, "OSGB 1936 / British National Grid", "EPSG", 27700);
var gcs = pcs.GeographicCoordinateSystem;
CheckInfo(gcs, "OSGB 1936", "EPSG", 4277);
CheckDatum(gcs.HorizontalDatum, "OSGB_1936", "EPSG", 6277);
CheckEllipsoid(gcs.HorizontalDatum.Ellipsoid, "Airy 1830", 6377563.396, 299.3249646, "EPSG", 7001);
CheckPrimem(gcs.PrimeMeridian, "Greenwich", 0, "EPSG", 8901);
CheckUnit(gcs.AngularUnit, "degree", 0.0174532925199433, "EPSG", 9122);
Assert.AreEqual("Transverse_Mercator", pcs.Projection.ClassName, "Projection Classname");
CheckProjection(pcs.Projection, "Transverse_Mercator", new []
{
Tuple.Create("latitude_of_origin", 49d),
Tuple.Create("central_meridian",-2d),
Tuple.Create("scale_factor",0.9996012717),
Tuple.Create("false_easting",400000d),
Tuple.Create("false_northing",-100000d)
});
CheckUnit(pcs.LinearUnit, "metre", 1d, "EPSG", 9001);
string newWkt = pcs.WKT.Replace(", ", ",");
Assert.AreEqual(wkt, newWkt);
}
[Test]
public void TestParseSrOrg()
{
Assert.That(() => _coordinateSystemFactory.CreateFromWkt(
"PROJCS[\"WGS 84 / Pseudo-Mercator\",GEOGCS[\"Popular Visualisation CRS\"," +
"DATUM[\"Popular_Visualisation_Datum\",SPHEROID[\"Popular Visualisation Sphere\"," +
"6378137,0,AUTHORITY[\"EPSG\",\"7059\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\"," +
"\"6055\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\"," +
"0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4055\"]]," +
"UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Mercator_1SP\"]," +
"PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[" +
"\"false_easting\",0],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"3785\"]" +
",AXIS[\"X\",EAST],AXIS[\"Y\",NORTH]]"), Throws.Nothing);
}
[Test]
public void TestProjNetIssues()
{
Assert.That(() => _coordinateSystemFactory.CreateFromWkt(
"PROJCS[\"International_Terrestrial_Reference_Frame_1992Lambert_Conformal_Conic_2SP\"," +
"GEOGCS[\"GCS_International_Terrestrial_Reference_Frame_1992\"," +
"DATUM[\"International_Terrestrial_Reference_Frame_1992\"," +
"SPHEROID[\"GRS_1980\",6378137,298.257222101]," +
"TOWGS84[0,0,0,0,0,0,0]]," +
"PRIMEM[\"Greenwich\",0]," +
"UNIT[\"Degree\",0.0174532925199433]]," +
"PROJECTION[\"Lambert_Conformal_Conic_2SP\",AUTHORITY[\"EPSG\",\"9802\"]]," +
"PARAMETER[\"Central_Meridian\",-102]," +
"PARAMETER[\"Latitude_Of_Origin\",12]," +
"PARAMETER[\"False_Easting\",2500000]," +
"PARAMETER[\"False_Northing\",0]," +
"PARAMETER[\"Standard_Parallel_1\",17.5]," +
"PARAMETER[\"Standard_Parallel_2\",29.5]," +
"PARAMETER[\"Scale_Factor\",1]," +
"UNIT[\"Meter\",1,AUTHORITY[\"EPSG\",\"9001\"]]]"), Throws.Nothing);
Assert.That(() => _coordinateSystemFactory.CreateFromWkt(
"PROJCS[\"Google Maps Global Mercator\"," +
"GEOGCS[\"WGS 84\"," +
"DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]]," +
"AUTHORITY[\"EPSG\",\"6326\"]]," +
"PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]]," +
"UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]]," +
"AUTHORITY[\"EPSG\",\"4326\"]]," +
"PROJECTION[\"Mercator_2SP\"]," +
"PARAMETER[\"standard_parallel_1\",0]," +
"PARAMETER[\"latitude_of_origin\",0]," +
"PARAMETER[\"central_meridian\",0]," +
"PARAMETER[\"false_easting\",0]," +
"PARAMETER[\"false_northing\",0]," +
"UNIT[\"Meter\",1]," +
"EXTENSION[\"PROJ4\",\"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs\"]," +
"AUTHORITY[\"EPSG\",\"900913\"]]"), Throws.Nothing);
}
/// <summary>
/// Test parsing of a <see cref="FittedCoordinateSystem"/> from WKT
/// </summary>
[Test]
public void TestFittedCoordinateSystemWkt ()
{
var fac = new CoordinateSystemFactory ();
FittedCoordinateSystem fcs = null;
string wkt = "FITTED_CS[\"Local coordinate system MNAU (based on Gauss-Krueger)\"," +
"PARAM_MT[\"Affine\"," +
"PARAMETER[\"num_row\",3],PARAMETER[\"num_col\",3],PARAMETER[\"elt_0_0\", 0.883485346527455],PARAMETER[\"elt_0_1\", -0.468458794848877],PARAMETER[\"elt_0_2\", 3455869.17937689],PARAMETER[\"elt_1_0\", 0.468458794848877],PARAMETER[\"elt_1_1\", 0.883485346527455],PARAMETER[\"elt_1_2\", 5478710.88035753],PARAMETER[\"elt_2_2\", 1]]," +
"PROJCS[\"DHDN / Gauss-Kruger zone 3\"," +
"GEOGCS[\"DHDN\"," +
"DATUM[\"Deutsches_Hauptdreiecksnetz\"," +
"SPHEROID[\"Bessel 1841\", 6377397.155, 299.1528128, AUTHORITY[\"EPSG\", \"7004\"]]," +
"TOWGS84[612.4, 77, 440.2, -0.054, 0.057, -2.797, 0.525975255930096]," +
"AUTHORITY[\"EPSG\", \"6314\"]]," +
"PRIMEM[\"Greenwich\", 0, AUTHORITY[\"EPSG\", \"8901\"]]," +
"UNIT[\"degree\", 0.0174532925199433, AUTHORITY[\"EPSG\", \"9122\"]]," +
"AUTHORITY[\"EPSG\", \"4314\"]]," +
"UNIT[\"metre\", 1, AUTHORITY[\"EPSG\", \"9001\"]]," +
"PROJECTION[\"Transverse_Mercator\"]," +
"PARAMETER[\"latitude_of_origin\", 0]," +
"PARAMETER[\"central_meridian\", 9]," +
"PARAMETER[\"scale_factor\", 1]," +
"PARAMETER[\"false_easting\", 3500000]," +
"PARAMETER[\"false_northing\", 0]," +
"AUTHORITY[\"EPSG\", \"31467\"]]" +
"]";
try
{
fcs = fac.CreateFromWkt (wkt) as FittedCoordinateSystem;
}
catch (Exception ex)
{
Assert.Fail ("Could not create fitted coordinate system from:\r\n" + wkt + "\r\n" + ex.Message);
}
Assert.That(fcs, Is.Not.Null);
Assert.That(fcs.ToBase(), Is.Not.Null.Or.Empty);
Assert.That(fcs.BaseCoordinateSystem, Is.Not.Null);
Assert.AreEqual ("Local coordinate system MNAU (based on Gauss-Krueger)", fcs.Name);
//Assert.AreEqual ("CUSTOM", fcs.Authority);
//Assert.AreEqual (123456, fcs.AuthorityCode);
Assert.AreEqual ("EPSG", fcs.BaseCoordinateSystem.Authority);
Assert.AreEqual (31467, fcs.BaseCoordinateSystem.AuthorityCode);
}
/// <summary>
/// Test parsing of a <see cref="GeocentricCoordinateSystem"/> from WKT
/// </summary>
[Test]
public void TestGeocentricCoordinateSystem()
{
var fac = new CoordinateSystemFactory();
GeocentricCoordinateSystem fcs = null;
const string wkt = "GEOCCS[\"TUREF\", " +
"DATUM[\"Turkish_National_Reference_Frame\", " +
"SPHEROID[\"GRS 1980\", 6378137, 298.257222101, AUTHORITY[\"EPSG\", \"7019\"]], " +
"AUTHORITY[\"EPSG\", \"1057\"]], " +
"PRIMEM[\"Greenwich\", 0, AUTHORITY[\"EPSG\", \"8901\"]], " +
"UNIT[\"metre\", 1, AUTHORITY[\"EPSG\", \"9001\"]], " +
"AXIS[\"Geocentric X\", OTHER], AXIS[\"Geocentric Y\", OTHER], AXIS[\"Geocentric Z\", NORTH], " +
"AUTHORITY[\"EPSG\", \"5250\"]]";
try
{
fcs = fac.CreateFromWkt(wkt) as GeocentricCoordinateSystem;
}
catch (Exception ex)
{
Assert.Fail("Could not create geocentric coordinate system from:\r\n" + wkt + "\r\n" + ex.Message);
}
Assert.That(fcs, Is.Not.Null);
Assert.That(CheckInfo(fcs, "TUREF", "EPSG", 5250L));
Assert.That(CheckDatum(fcs.HorizontalDatum, "Turkish_National_Reference_Frame", "EPSG", 1057L), Is.True);
Assert.That(CheckEllipsoid(fcs.HorizontalDatum.Ellipsoid, "GRS 1980", 6378137, 298.257222101, "EPSG", 7019), Is.True);
Assert.That(CheckPrimem(fcs.PrimeMeridian, "Greenwich", 0, "EPSG", 8901L), Is.True);
Assert.That(CheckUnit(fcs.PrimeMeridian.AngularUnit, "degree", null, null, null), Is.True);
Assert.That(CheckUnit(fcs.LinearUnit, "metre", 1, "EPSG", 9001L), Is.True);
Assert.That(fcs.Authority, Is.EqualTo("EPSG"));
Assert.That(fcs.AuthorityCode, Is.EqualTo(5250L));
}
#region Utility
private bool CheckPrimem(PrimeMeridian primeMeridian, string name, double? longitude, string authority, long? code)
{
Assert.That(primeMeridian, Is.Not.Null);
Assert.That(CheckInfo(primeMeridian, name, authority, code));
Assert.That(primeMeridian.Longitude, Is.EqualTo(longitude));
return true;
}
private static bool CheckUnit(IUnit unit, string name, double? value, string authority, long? code)
{
Assert.That(unit, Is.Not.Null);
Assert.That(CheckInfo(unit, name, authority, code));
Assert.That(unit, Is.InstanceOf<LinearUnit>().Or.InstanceOf<AngularUnit>());
if (!value.HasValue) return true;
if (unit is LinearUnit lunit)
Assert.That(lunit.MetersPerUnit, Is.EqualTo(value));
else if (unit is AngularUnit aunit)
Assert.That(aunit.RadiansPerUnit, Is.EqualTo(value));
return true;
}
private static bool CheckEllipsoid(Ellipsoid ellipsoid, string name, double? semiMajor, double? inverseFlattening, string authority, long? code)
{
Assert.That(ellipsoid, Is.Not.Null);
Assert.That(CheckInfo(ellipsoid, name, authority, code));
if (semiMajor.HasValue) Assert.That(ellipsoid.SemiMajorAxis, Is.EqualTo(semiMajor));
if (inverseFlattening.HasValue) Assert.That(ellipsoid.InverseFlattening, Is.EqualTo(inverseFlattening));
return true;
}
private static bool CheckDatum(Datum datum, string name, string authority, long? code)
{
Assert.That(datum, Is.Not.Null);
Assert.That(datum, Is.InstanceOf<HorizontalDatum>()/*.Or.InstanceOf<IVerticalDatum>()*/);
Assert.That(CheckInfo(datum, name,authority, code), Is.True);
return true;
}
private static bool CheckInfo(IInfo info, string name, string authority = null, long? code = null)
{
Assert.That(info, Is.Not.Null);
if (!string.IsNullOrWhiteSpace(name)) Assert.That(info.Name, Is.EqualTo(name));
if (!string.IsNullOrWhiteSpace(authority)) Assert.That(info.Authority, Is.EqualTo(authority));
if (code.HasValue) Assert.That(info.AuthorityCode, Is.EqualTo(code));
return true;
}
private static void CheckProjection(IProjection projection, string name, IList<Tuple<string, double>> pp = null, string authority = null, long? code = null)
{
Assert.That(projection, Is.Not.Null, "Projection not null");
Assert.That(projection.ClassName, Is.EqualTo(name), "Projection class name");
CheckInfo(projection, name, authority, code);
if (pp == null) return;
Assert.That(projection.NumParameters, Is.EqualTo(pp.Count), "Number of projection parameters");
for (int i = 0; i < pp.Count; i++)
{
ProjectionParameter par = null;
Assert.That(() => par = projection.GetParameter(pp[i].Item1), Throws.Nothing, $"Getting projection parameter '{pp[i].Item1}' throws.");
Assert.That(par, Is.Not.Null, $"Projection parameter '{pp[i].Item1}' is null");
Assert.That(par.Name, Is.EqualTo(pp[i].Item1), $"Projection parameter '{par.Name}' name is not '{pp[i].Item1}'.");
Assert.That(par.Value, Is.EqualTo(pp[i].Item2), $"Projection parameter value for '{par.Name}' name ({par.Value:R}) is not '{pp[i].Item2:R}'.");
}
}
#endregion
}
}

Просмотреть файл

@ -1,83 +1,83 @@
using System;
using NUnit.Framework;
using ProjNet.CoordinateSystems.Transformations;
using ProjNet.IO.CoordinateSystems;
namespace ProjNET.Tests.WKT
{
[TestFixture]
public class WKTMathTransformParserTests
{
/// <summary>
/// Test parsing of affine math transform from WKT
/// </summary>
[Test]
public void ParseAffineTransformWkt ()
{
//TODO MathTransformFactory fac = new MathTransformFactory ();
MathTransform mt = null;
string wkt = "PARAM_MT[\"Affine\"," +
"PARAMETER[\"num_row\",3]," +
"PARAMETER[\"num_col\",3]," +
"PARAMETER[\"elt_0_0\", 0.883485346527455]," +
"PARAMETER[\"elt_0_1\", -0.468458794848877]," +
"PARAMETER[\"elt_0_2\", 3455869.17937689]," +
"PARAMETER[\"elt_1_0\", 0.468458794848877]," +
"PARAMETER[\"elt_1_1\", 0.883485346527455]," +
"PARAMETER[\"elt_1_2\", 5478710.88035753]," +
"PARAMETER[\"elt_2_2\", 1]]";
try
{
//TODO replace with MathTransformFactory implementation
mt = MathTransformWktReader.Parse (wkt);
}
catch (Exception ex)
{
Assert.Fail ("Could not create affine math transformation from:\r\n" + wkt + "\r\n" + ex.Message);
}
Assert.IsNotNull (mt);
Assert.IsNotNull (mt as AffineTransform);
Assert.AreEqual (2, mt.DimSource);
Assert.AreEqual (2, mt.DimTarget);
//test simple transform
double[] outPt = mt.Transform (new double[] { 0.0, 0.0 });
Assert.AreEqual (2, outPt.Length);
Assert.AreEqual (3455869.17937689, outPt[0], 0.00000001);
Assert.AreEqual (5478710.88035753, outPt[1], 0.00000001);
}
/// <summary>
/// MathTransformWktReader parses real number with exponent incorrectly
/// </summary>
[TestCase("PARAM_MT[\"Affine\",PARAMETER[\"num_row\", 3],PARAMETER[\"num_col\", 3],PARAMETER[\"elt_0_0\", 6.12303176911189E-17]]")]
[TestCase("PARAM_MT[\"Affine\",PARAMETER[\"num_row\", 3],PARAMETER[\"num_col\", 3],PARAMETER[\"elt_0_0\", 5.235E4]]")]
[TestCase ("PARAM_MT[\"Affine\",PARAMETER[\"num_row\", 3],PARAMETER[\"num_col\", 3],PARAMETER[\"elt_0_0\", 5.235E+4]]")]
public void TestMathTransformWktReaderExponencialNumberParsingIssue(string wkt)
{
//string wkt = "PARAM_MT[\"Affine\",PARAMETER[\"num_row\", 3],PARAMETER[\"num_col\", 3],PARAMETER[\"elt_0_0\", 6.12303176911189E-17]]";
MathTransform mt = null;
try
{
//TODO replace with MathTransformFactory implementation
mt = MathTransformWktReader.Parse (wkt);
}
catch (ArgumentException ex)
{
Assert.Fail ("Failed to parse WKT of affine math transformation from:\r\n" + wkt + "\r\n" + ex.Message);
}
catch (Exception e)
{
Assert.Fail ("Could not create affine math transformation from:\r\n" + wkt + "\r\n" + e.Message);
}
Assert.IsNotNull (mt);
Assert.IsNotNull (mt as AffineTransform);
}
}
}
using System;
using NUnit.Framework;
using ProjNet.CoordinateSystems.Transformations;
using ProjNet.IO.CoordinateSystems;
namespace ProjNET.Tests.WKT
{
[TestFixture]
public class WKTMathTransformParserTests
{
/// <summary>
/// Test parsing of affine math transform from WKT
/// </summary>
[Test]
public void ParseAffineTransformWkt ()
{
//TODO MathTransformFactory fac = new MathTransformFactory ();
MathTransform mt = null;
string wkt = "PARAM_MT[\"Affine\"," +
"PARAMETER[\"num_row\",3]," +
"PARAMETER[\"num_col\",3]," +
"PARAMETER[\"elt_0_0\", 0.883485346527455]," +
"PARAMETER[\"elt_0_1\", -0.468458794848877]," +
"PARAMETER[\"elt_0_2\", 3455869.17937689]," +
"PARAMETER[\"elt_1_0\", 0.468458794848877]," +
"PARAMETER[\"elt_1_1\", 0.883485346527455]," +
"PARAMETER[\"elt_1_2\", 5478710.88035753]," +
"PARAMETER[\"elt_2_2\", 1]]";
try
{
//TODO replace with MathTransformFactory implementation
mt = MathTransformWktReader.Parse (wkt);
}
catch (Exception ex)
{
Assert.Fail ("Could not create affine math transformation from:\r\n" + wkt + "\r\n" + ex.Message);
}
Assert.IsNotNull (mt);
Assert.IsNotNull (mt as AffineTransform);
Assert.AreEqual (2, mt.DimSource);
Assert.AreEqual (2, mt.DimTarget);
//test simple transform
double[] outPt = mt.Transform (new double[] { 0.0, 0.0 });
Assert.AreEqual (2, outPt.Length);
Assert.AreEqual (3455869.17937689, outPt[0], 0.00000001);
Assert.AreEqual (5478710.88035753, outPt[1], 0.00000001);
}
/// <summary>
/// MathTransformWktReader parses real number with exponent incorrectly
/// </summary>
[TestCase("PARAM_MT[\"Affine\",PARAMETER[\"num_row\", 3],PARAMETER[\"num_col\", 3],PARAMETER[\"elt_0_0\", 6.12303176911189E-17]]")]
[TestCase("PARAM_MT[\"Affine\",PARAMETER[\"num_row\", 3],PARAMETER[\"num_col\", 3],PARAMETER[\"elt_0_0\", 5.235E4]]")]
[TestCase ("PARAM_MT[\"Affine\",PARAMETER[\"num_row\", 3],PARAMETER[\"num_col\", 3],PARAMETER[\"elt_0_0\", 5.235E+4]]")]
public void TestMathTransformWktReaderExponencialNumberParsingIssue(string wkt)
{
//string wkt = "PARAM_MT[\"Affine\",PARAMETER[\"num_row\", 3],PARAMETER[\"num_col\", 3],PARAMETER[\"elt_0_0\", 6.12303176911189E-17]]";
MathTransform mt = null;
try
{
//TODO replace with MathTransformFactory implementation
mt = MathTransformWktReader.Parse (wkt);
}
catch (ArgumentException ex)
{
Assert.Fail ("Failed to parse WKT of affine math transformation from:\r\n" + wkt + "\r\n" + ex.Message);
}
catch (Exception e)
{
Assert.Fail ("Could not create affine math transformation from:\r\n" + wkt + "\r\n" + e.Message);
}
Assert.IsNotNull (mt);
Assert.IsNotNull (mt as AffineTransform);
}
}
}

Просмотреть файл

@ -1,154 +1,154 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Definition of angular units.
/// </summary>
[Serializable]
public class AngularUnit : Info, IUnit
{
/// <summary>
/// Equality tolerance value. Values with a difference less than this are considered equal.
/// </summary>
private const double EqualityTolerance = 2.0e-17;
/// <summary>
/// Initializes a new instance of a angular unit
/// </summary>
/// <param name="radiansPerUnit">Radians per unit</param>
public AngularUnit(double radiansPerUnit)
: this(
radiansPerUnit,string.Empty,string.Empty,-1,string.Empty,string.Empty,string.Empty)
{
}
/// <summary>
/// Initializes a new instance of a angular unit
/// </summary>
/// <param name="radiansPerUnit">Radians per unit</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="authorityCode">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal AngularUnit(double radiansPerUnit, string name, string authority, long authorityCode, string alias, string abbreviation, string remarks)
:
base(name, authority, authorityCode, alias, abbreviation, remarks)
{
_RadiansPerUnit = radiansPerUnit;
}
#region Predifined units
/// <summary>
/// The angular degrees are PI/180 = 0.017453292519943295769236907684886 radians
/// </summary>
public static AngularUnit Degrees
{
get { return new AngularUnit(0.017453292519943295769236907684886, "degree", "EPSG", 9102, "deg", string.Empty, "=pi/180 radians"); }
}
/// <summary>
/// SI standard unit
/// </summary>
public static AngularUnit Radian
{
get { return new AngularUnit(1, "radian", "EPSG", 9101, "rad", string.Empty, "SI standard unit."); }
}
/// <summary>
/// Pi / 200 = 0.015707963267948966192313216916398 radians
/// </summary>
public static AngularUnit Grad
{
get { return new AngularUnit(0.015707963267948966192313216916398, "grad", "EPSG", 9105, "gr", string.Empty, "=pi/200 radians."); }
}
/// <summary>
/// Pi / 200 = 0.015707963267948966192313216916398 radians
/// </summary>
public static AngularUnit Gon
{
get { return new AngularUnit(0.015707963267948966192313216916398, "gon", "EPSG", 9106, "g", string.Empty, "=pi/200 radians."); }
}
#endregion
#region IAngularUnit Members
private double _RadiansPerUnit;
/// <summary>
/// Gets or sets the number of radians per <see cref="AngularUnit"/>.
/// </summary>
public double RadiansPerUnit
{
get { return _RadiansPerUnit; }
set { _RadiansPerUnit = value; }
}
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat,"UNIT[\"{0}\", {1}", Name, RadiansPerUnit);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
public override string XML
{
get
{
return string.Format(CultureInfo.InvariantCulture.NumberFormat, "<CS_AngularUnit RadiansPerUnit=\"{0}\">{1}</CS_AngularUnit>", RadiansPerUnit, InfoXml);
}
}
#endregion
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is AngularUnit))
return false;
return Math.Abs(((AngularUnit)obj).RadiansPerUnit - this.RadiansPerUnit) < EqualityTolerance;
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Definition of angular units.
/// </summary>
[Serializable]
public class AngularUnit : Info, IUnit
{
/// <summary>
/// Equality tolerance value. Values with a difference less than this are considered equal.
/// </summary>
private const double EqualityTolerance = 2.0e-17;
/// <summary>
/// Initializes a new instance of a angular unit
/// </summary>
/// <param name="radiansPerUnit">Radians per unit</param>
public AngularUnit(double radiansPerUnit)
: this(
radiansPerUnit,string.Empty,string.Empty,-1,string.Empty,string.Empty,string.Empty)
{
}
/// <summary>
/// Initializes a new instance of a angular unit
/// </summary>
/// <param name="radiansPerUnit">Radians per unit</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="authorityCode">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal AngularUnit(double radiansPerUnit, string name, string authority, long authorityCode, string alias, string abbreviation, string remarks)
:
base(name, authority, authorityCode, alias, abbreviation, remarks)
{
_RadiansPerUnit = radiansPerUnit;
}
#region Predifined units
/// <summary>
/// The angular degrees are PI/180 = 0.017453292519943295769236907684886 radians
/// </summary>
public static AngularUnit Degrees
{
get { return new AngularUnit(0.017453292519943295769236907684886, "degree", "EPSG", 9102, "deg", string.Empty, "=pi/180 radians"); }
}
/// <summary>
/// SI standard unit
/// </summary>
public static AngularUnit Radian
{
get { return new AngularUnit(1, "radian", "EPSG", 9101, "rad", string.Empty, "SI standard unit."); }
}
/// <summary>
/// Pi / 200 = 0.015707963267948966192313216916398 radians
/// </summary>
public static AngularUnit Grad
{
get { return new AngularUnit(0.015707963267948966192313216916398, "grad", "EPSG", 9105, "gr", string.Empty, "=pi/200 radians."); }
}
/// <summary>
/// Pi / 200 = 0.015707963267948966192313216916398 radians
/// </summary>
public static AngularUnit Gon
{
get { return new AngularUnit(0.015707963267948966192313216916398, "gon", "EPSG", 9106, "g", string.Empty, "=pi/200 radians."); }
}
#endregion
#region IAngularUnit Members
private double _RadiansPerUnit;
/// <summary>
/// Gets or sets the number of radians per <see cref="AngularUnit"/>.
/// </summary>
public double RadiansPerUnit
{
get { return _RadiansPerUnit; }
set { _RadiansPerUnit = value; }
}
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat,"UNIT[\"{0}\", {1}", Name, RadiansPerUnit);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
public override string XML
{
get
{
return string.Format(CultureInfo.InvariantCulture.NumberFormat, "<CS_AngularUnit RadiansPerUnit=\"{0}\">{1}</CS_AngularUnit>", RadiansPerUnit, InfoXml);
}
}
#endregion
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is AngularUnit))
return false;
return Math.Abs(((AngularUnit)obj).RadiansPerUnit - this.RadiansPerUnit) < EqualityTolerance;
}
}
}

Просмотреть файл

@ -1,113 +1,113 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Base interface for all coordinate systems.
/// </summary>
/// <remarks>
/// <para>A coordinate system is a mathematical space, where the elements of the space
/// are called positions. Each position is described by a list of numbers. The length
/// of the list corresponds to the dimension of the coordinate system. So in a 2D
/// coordinate system each position is described by a list containing 2 numbers.</para>
/// <para>However, in a coordinate system, not all lists of numbers correspond to a
/// position - some lists may be outside the domain of the coordinate system. For
/// example, in a 2D Lat/Lon coordinate system, the list (91,91) does not correspond
/// to a position.</para>
/// <para>Some coordinate systems also have a mapping from the mathematical space into
/// locations in the real world. So in a Lat/Lon coordinate system, the mathematical
/// position (lat, long) corresponds to a location on the surface of the Earth. This
/// mapping from the mathematical space into real-world locations is called a Datum.</para>
/// </remarks>
[Serializable]
public abstract class CoordinateSystem : Info
{
/// <summary>
/// Initializes a new instance of a coordinate system.
/// </summary>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="authorityCode">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal CoordinateSystem(string name, string authority, long authorityCode, string alias, string abbreviation, string remarks)
: base (name, authority, authorityCode, alias,abbreviation, remarks) { }
#region ICoordinateSystem Members
/// <summary>
/// Dimension of the coordinate system.
/// </summary>
public int Dimension
{
get { return _AxisInfo.Count; }
}
/// <summary>
/// Gets the units for the dimension within coordinate system.
/// Each dimension in the coordinate system has corresponding units.
/// </summary>
public abstract IUnit GetUnits(int dimension);
private List<AxisInfo> _AxisInfo;
internal List<AxisInfo> AxisInfo
{
get { return _AxisInfo; }
set { _AxisInfo = value; }
}
/// <summary>
/// Gets axis details for dimension within coordinate system.
/// </summary>
/// <param name="dimension">Dimension</param>
/// <returns>Axis info</returns>
public AxisInfo GetAxis(int dimension)
{
if (dimension >= _AxisInfo.Count || dimension < 0)
throw new ArgumentException("AxisInfo not available for dimension " + dimension.ToString(CultureInfo.InvariantCulture));
return _AxisInfo[dimension];
}
private double[] _DefaultEnvelope;
/// <summary>
/// Gets default envelope of coordinate system.
/// </summary>
/// <remarks>
/// Coordinate systems which are bounded should return the minimum bounding box of their domain.
/// Unbounded coordinate systems should return a box which is as large as is likely to be used.
/// For example, a (lon,lat) geographic coordinate system in degrees should return a box from
/// (-180,-90) to (180,90), and a geocentric coordinate system could return a box from (-r,-r,-r)
/// to (+r,+r,+r) where r is the approximate radius of the Earth.
/// </remarks>
public double[] DefaultEnvelope
{
get { return _DefaultEnvelope; }
set { _DefaultEnvelope = value; }
}
#endregion
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Base interface for all coordinate systems.
/// </summary>
/// <remarks>
/// <para>A coordinate system is a mathematical space, where the elements of the space
/// are called positions. Each position is described by a list of numbers. The length
/// of the list corresponds to the dimension of the coordinate system. So in a 2D
/// coordinate system each position is described by a list containing 2 numbers.</para>
/// <para>However, in a coordinate system, not all lists of numbers correspond to a
/// position - some lists may be outside the domain of the coordinate system. For
/// example, in a 2D Lat/Lon coordinate system, the list (91,91) does not correspond
/// to a position.</para>
/// <para>Some coordinate systems also have a mapping from the mathematical space into
/// locations in the real world. So in a Lat/Lon coordinate system, the mathematical
/// position (lat, long) corresponds to a location on the surface of the Earth. This
/// mapping from the mathematical space into real-world locations is called a Datum.</para>
/// </remarks>
[Serializable]
public abstract class CoordinateSystem : Info
{
/// <summary>
/// Initializes a new instance of a coordinate system.
/// </summary>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="authorityCode">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal CoordinateSystem(string name, string authority, long authorityCode, string alias, string abbreviation, string remarks)
: base (name, authority, authorityCode, alias,abbreviation, remarks) { }
#region ICoordinateSystem Members
/// <summary>
/// Dimension of the coordinate system.
/// </summary>
public int Dimension
{
get { return _AxisInfo.Count; }
}
/// <summary>
/// Gets the units for the dimension within coordinate system.
/// Each dimension in the coordinate system has corresponding units.
/// </summary>
public abstract IUnit GetUnits(int dimension);
private List<AxisInfo> _AxisInfo;
internal List<AxisInfo> AxisInfo
{
get { return _AxisInfo; }
set { _AxisInfo = value; }
}
/// <summary>
/// Gets axis details for dimension within coordinate system.
/// </summary>
/// <param name="dimension">Dimension</param>
/// <returns>Axis info</returns>
public AxisInfo GetAxis(int dimension)
{
if (dimension >= _AxisInfo.Count || dimension < 0)
throw new ArgumentException("AxisInfo not available for dimension " + dimension.ToString(CultureInfo.InvariantCulture));
return _AxisInfo[dimension];
}
private double[] _DefaultEnvelope;
/// <summary>
/// Gets default envelope of coordinate system.
/// </summary>
/// <remarks>
/// Coordinate systems which are bounded should return the minimum bounding box of their domain.
/// Unbounded coordinate systems should return a box which is as large as is likely to be used.
/// For example, a (lon,lat) geographic coordinate system in degrees should return a box from
/// (-180,-90) to (180,90), and a geocentric coordinate system could return a box from (-r,-r,-r)
/// to (+r,+r,+r) where r is the approximate radius of the Earth.
/// </remarks>
public double[] DefaultEnvelope
{
get { return _DefaultEnvelope; }
set { _DefaultEnvelope = value; }
}
#endregion
}
}

Просмотреть файл

@ -1,321 +1,321 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Text;
using ProjNet.IO.CoordinateSystems;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Builds up complex objects from simpler objects or values.
/// </summary>
/// <remarks>
/// <para>ICoordinateSystemFactory allows applications to make coordinate systems that
/// cannot be created by a <see cref="ICoordinateSystemAuthorityFactory"/>. This factory is very
/// flexible, whereas the authority factory is easier to use.</para>
/// <para>So <see cref="ICoordinateSystemAuthorityFactory"/>can be used to make 'standard' coordinate
/// systems, and <see cref="CoordinateSystemFactory"/> can be used to make 'special'
/// coordinate systems.</para>
/// <para>For example, the EPSG authority has codes for USA state plane coordinate systems
/// using the NAD83 datum, but these coordinate systems always use meters. EPSG does not
/// have codes for NAD83 state plane coordinate systems that use feet units. This factory
/// lets an application create such a hybrid coordinate system.</para>
/// </remarks>
public class CoordinateSystemFactory
{
/// <summary>
/// Creates an instance of this class
/// </summary>
public CoordinateSystemFactory() { }
/// <summary>
/// Creates a coordinate system object from an XML string.
/// </summary>
/// <param name="xml">XML representation for the spatial reference</param>
/// <returns>The resulting spatial reference object</returns>
public CoordinateSystem CreateFromXml(string xml)
{
throw new NotImplementedException();
}
/// <summary>
/// Creates a spatial reference object given its Well-known text representation.
/// The output object may be either a <see cref="GeographicCoordinateSystem"/> or
/// a <see cref="ProjectedCoordinateSystem"/>.
/// </summary>
/// <param name="WKT">The Well-known text representation for the spatial reference</param>
/// <returns>The resulting spatial reference object</returns>
public CoordinateSystem CreateFromWkt(string WKT)
{
var info = CoordinateSystemWktReader.Parse(WKT);
return info as CoordinateSystem;
}
/*
/// <summary>
/// Creates a <see cref="CompoundCoordinateSystem"/> [NOT IMPLEMENTED].
/// </summary>
/// <param name="name">Name of compound coordinate system.</param>
/// <param name="head">Head coordinate system</param>
/// <param name="tail">Tail coordinate system</param>
/// <returns>Compound coordinate system</returns>
public ICompoundCoordinateSystem CreateCompoundCoordinateSystem(string name, ICoordinateSystem head, ICoordinateSystem tail)
{
throw new NotImplementedException();
}
*/
/// <summary>
/// Creates a <see cref="FittedCoordinateSystem"/>.
/// </summary>
/// <remarks>The units of the axes in the fitted coordinate system will be
/// inferred from the units of the base coordinate system. If the affine map
/// performs a rotation, then any mixed axes must have identical units. For
/// example, a (lat_deg,lon_deg,height_feet) system can be rotated in the
/// (lat,lon) plane, since both affected axes are in degrees. But you
/// should not rotate this coordinate system in any other plane.</remarks>
/// <param name="name">Name of coordinate system</param>
/// <param name="baseCoordinateSystem">Base coordinate system</param>
/// <param name="toBaseWkt"></param>
/// <param name="arAxes"></param>
/// <returns>Fitted coordinate system</returns>
public FittedCoordinateSystem CreateFittedCoordinateSystem(string name, CoordinateSystem baseCoordinateSystem, string toBaseWkt, List<AxisInfo> arAxes)
{
throw new NotImplementedException();
}
/*
/// <summary>
/// Creates a <see cref="ILocalCoordinateSystem">local coordinate system</see>.
/// </summary>
/// <remarks>
/// The dimension of the local coordinate system is determined by the size of
/// the axis array. All the axes will have the same units. If you want to make
/// a coordinate system with mixed units, then you can make a compound
/// coordinate system from different local coordinate systems.
/// </remarks>
/// <param name="name">Name of local coordinate system</param>
/// <param name="datum">Local datum</param>
/// <param name="unit">Units</param>
/// <param name="axes">Axis info</param>
/// <returns>Local coordinate system</returns>
public ILocalCoordinateSystem CreateLocalCoordinateSystem(string name, ILocalDatum datum, IUnit unit, List<AxisInfo> axes)
{
throw new NotImplementedException();
}
*/
/// <summary>
/// Creates an <see cref="Ellipsoid"/> from radius values.
/// </summary>
/// <seealso cref="CreateFlattenedSphere"/>
/// <param name="name">Name of ellipsoid</param>
/// <param name="semiMajorAxis"></param>
/// <param name="semiMinorAxis"></param>
/// <param name="linearUnit"></param>
/// <returns>Ellipsoid</returns>
public Ellipsoid CreateEllipsoid(string name, double semiMajorAxis, double semiMinorAxis, LinearUnit linearUnit)
{
double ivf = 0;
if (semiMajorAxis != semiMinorAxis)
ivf = semiMajorAxis / (semiMajorAxis - semiMinorAxis);
return new Ellipsoid(semiMajorAxis, semiMinorAxis, ivf, false, linearUnit, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/// <summary>
/// Creates an <see cref="Ellipsoid"/> from an major radius, and inverse flattening.
/// </summary>
/// <seealso cref="CreateEllipsoid"/>
/// <param name="name">Name of ellipsoid</param>
/// <param name="semiMajorAxis">Semi major-axis</param>
/// <param name="inverseFlattening">Inverse flattening</param>
/// <param name="linearUnit">Linear unit</param>
/// <returns>Ellipsoid</returns>
public Ellipsoid CreateFlattenedSphere(string name, double semiMajorAxis, double inverseFlattening, LinearUnit linearUnit)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name");
return new Ellipsoid(semiMajorAxis, -1, inverseFlattening, true, linearUnit, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/// <summary>
/// Creates a <see cref="ProjectedCoordinateSystem"/> using a projection object.
/// </summary>
/// <param name="name">Name of projected coordinate system</param>
/// <param name="gcs">Geographic coordinate system</param>
/// <param name="projection">Projection</param>
/// <param name="linearUnit">Linear unit</param>
/// <param name="axis0">Primary axis</param>
/// <param name="axis1">Secondary axis</param>
/// <returns>Projected coordinate system</returns>
public ProjectedCoordinateSystem CreateProjectedCoordinateSystem(string name, GeographicCoordinateSystem gcs, IProjection projection, LinearUnit linearUnit, AxisInfo axis0, AxisInfo axis1)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name", nameof(name));
if (gcs == null)
throw new ArgumentException("Geographic coordinate system was null", nameof(gcs));
if (projection == null)
throw new ArgumentException("Projection was null", nameof(projection));
if (linearUnit == null)
throw new ArgumentException("Linear unit was null");
var info = new List<AxisInfo>(2);
info.Add(axis0);
info.Add(axis1);
return new ProjectedCoordinateSystem(null, gcs, linearUnit, projection, info, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/// <summary>
/// Creates a <see cref="Projection"/>.
/// </summary>
/// <param name="name">Name of projection</param>
/// <param name="wktProjectionClass">Projection class</param>
/// <param name="parameters">Projection parameters</param>
/// <returns>Projection</returns>
public IProjection CreateProjection(string name, string wktProjectionClass, List<ProjectionParameter> parameters)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name");
if (parameters == null || parameters.Count == 0)
throw new ArgumentException("Invalid projection parameters");
return new Projection(wktProjectionClass, parameters, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/// <summary>
/// Creates <see cref="HorizontalDatum"/> from ellipsoid and Bursa-World parameters.
/// </summary>
/// <remarks>
/// Since this method contains a set of Bursa-Wolf parameters, the created
/// datum will always have a relationship to WGS84. If you wish to create a
/// horizontal datum that has no relationship with WGS84, then you can
/// either specify a <see cref="DatumType">horizontalDatumType</see> of <see cref="DatumType.HD_Other"/>, or create it via WKT.
/// </remarks>
/// <param name="name">Name of ellipsoid</param>
/// <param name="datumType">Type of datum</param>
/// <param name="ellipsoid">Ellipsoid</param>
/// <param name="toWgs84">Wgs84 conversion parameters</param>
/// <returns>Horizontal datum</returns>
public HorizontalDatum CreateHorizontalDatum(string name, DatumType datumType, Ellipsoid ellipsoid, Wgs84ConversionInfo toWgs84)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name");
if (ellipsoid == null)
throw new ArgumentException("Ellipsoid was null");
return new HorizontalDatum(ellipsoid, toWgs84, datumType, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/// <summary>
/// Creates a <see cref="PrimeMeridian"/>, relative to Greenwich.
/// </summary>
/// <param name="name">Name of prime meridian</param>
/// <param name="angularUnit">Angular unit</param>
/// <param name="longitude">Longitude</param>
/// <returns>Prime meridian</returns>
public PrimeMeridian CreatePrimeMeridian(string name, AngularUnit angularUnit, double longitude)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name");
return new PrimeMeridian(longitude, angularUnit, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/// <summary>
/// Creates a <see cref="GeographicCoordinateSystem"/>, which could be Lat/Lon or Lon/Lat.
/// </summary>
/// <param name="name">Name of geographical coordinate system</param>
/// <param name="angularUnit">Angular units</param>
/// <param name="datum">Horizontal datum</param>
/// <param name="primeMeridian">Prime meridian</param>
/// <param name="axis0">First axis</param>
/// <param name="axis1">Second axis</param>
/// <returns>Geographic coordinate system</returns>
public GeographicCoordinateSystem CreateGeographicCoordinateSystem(string name, AngularUnit angularUnit, HorizontalDatum datum, PrimeMeridian primeMeridian, AxisInfo axis0, AxisInfo axis1)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name");
var info = new List<AxisInfo>(2);
info.Add(axis0);
info.Add(axis1);
return new GeographicCoordinateSystem(angularUnit, datum, primeMeridian, info, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/*
/// <summary>
/// Creates a <see cref="ILocalDatum"/>.
/// </summary>
/// <param name="name">Name of datum</param>
/// <param name="datumType">Datum type</param>
/// <returns></returns>
public ILocalDatum CreateLocalDatum(string name, DatumType datumType)
{
throw new NotImplementedException();
}
*/
/*
/// <summary>
/// Creates a <see cref="IVerticalDatum"/> from an enumerated type value.
/// </summary>
/// <param name="name">Name of datum</param>
/// <param name="datumType">Type of datum</param>
/// <returns>Vertical datum</returns>
public IVerticalDatum CreateVerticalDatum(string name, DatumType datumType)
{
throw new NotImplementedException();
}
*/
/*
/// <summary>
/// Creates a <see cref="IVerticalCoordinateSystem"/> from a <see cref="IVerticalDatum">datum</see> and <see cref="LinearUnit">linear units</see>.
/// </summary>
/// <param name="name">Name of vertical coordinate system</param>
/// <param name="datum">Vertical datum</param>
/// <param name="verticalUnit">Unit</param>
/// <param name="axis">Axis info</param>
/// <returns>Vertical coordinate system</returns>
public IVerticalCoordinateSystem CreateVerticalCoordinateSystem(string name, IVerticalDatum datum, ILinearUnit verticalUnit, AxisInfo axis)
{
throw new NotImplementedException();
}
*/
/// <summary>
/// Creates a <see cref="CreateGeocentricCoordinateSystem"/> from a <see cref="HorizontalDatum">datum</see>,
/// <see cref="LinearUnit">linear unit</see> and <see cref="PrimeMeridian"/>.
/// </summary>
/// <param name="name">Name of geocentric coordinate system</param>
/// <param name="datum">Horizontal datum</param>
/// <param name="linearUnit">Linear unit</param>
/// <param name="primeMeridian">Prime meridian</param>
/// <returns>Geocentric Coordinate System</returns>
public GeocentricCoordinateSystem CreateGeocentricCoordinateSystem(string name, HorizontalDatum datum, LinearUnit linearUnit, PrimeMeridian primeMeridian)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name");
var info = new List<AxisInfo>(3);
info.Add(new AxisInfo("X", AxisOrientationEnum.Other));
info.Add(new AxisInfo("Y", AxisOrientationEnum.Other));
info.Add(new AxisInfo("Z", AxisOrientationEnum.Other));
return new GeocentricCoordinateSystem(datum, linearUnit, primeMeridian, info, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Text;
using ProjNet.IO.CoordinateSystems;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Builds up complex objects from simpler objects or values.
/// </summary>
/// <remarks>
/// <para>ICoordinateSystemFactory allows applications to make coordinate systems that
/// cannot be created by a <see cref="ICoordinateSystemAuthorityFactory"/>. This factory is very
/// flexible, whereas the authority factory is easier to use.</para>
/// <para>So <see cref="ICoordinateSystemAuthorityFactory"/>can be used to make 'standard' coordinate
/// systems, and <see cref="CoordinateSystemFactory"/> can be used to make 'special'
/// coordinate systems.</para>
/// <para>For example, the EPSG authority has codes for USA state plane coordinate systems
/// using the NAD83 datum, but these coordinate systems always use meters. EPSG does not
/// have codes for NAD83 state plane coordinate systems that use feet units. This factory
/// lets an application create such a hybrid coordinate system.</para>
/// </remarks>
public class CoordinateSystemFactory
{
/// <summary>
/// Creates an instance of this class
/// </summary>
public CoordinateSystemFactory() { }
/// <summary>
/// Creates a coordinate system object from an XML string.
/// </summary>
/// <param name="xml">XML representation for the spatial reference</param>
/// <returns>The resulting spatial reference object</returns>
public CoordinateSystem CreateFromXml(string xml)
{
throw new NotImplementedException();
}
/// <summary>
/// Creates a spatial reference object given its Well-known text representation.
/// The output object may be either a <see cref="GeographicCoordinateSystem"/> or
/// a <see cref="ProjectedCoordinateSystem"/>.
/// </summary>
/// <param name="WKT">The Well-known text representation for the spatial reference</param>
/// <returns>The resulting spatial reference object</returns>
public CoordinateSystem CreateFromWkt(string WKT)
{
var info = CoordinateSystemWktReader.Parse(WKT);
return info as CoordinateSystem;
}
/*
/// <summary>
/// Creates a <see cref="CompoundCoordinateSystem"/> [NOT IMPLEMENTED].
/// </summary>
/// <param name="name">Name of compound coordinate system.</param>
/// <param name="head">Head coordinate system</param>
/// <param name="tail">Tail coordinate system</param>
/// <returns>Compound coordinate system</returns>
public ICompoundCoordinateSystem CreateCompoundCoordinateSystem(string name, ICoordinateSystem head, ICoordinateSystem tail)
{
throw new NotImplementedException();
}
*/
/// <summary>
/// Creates a <see cref="FittedCoordinateSystem"/>.
/// </summary>
/// <remarks>The units of the axes in the fitted coordinate system will be
/// inferred from the units of the base coordinate system. If the affine map
/// performs a rotation, then any mixed axes must have identical units. For
/// example, a (lat_deg,lon_deg,height_feet) system can be rotated in the
/// (lat,lon) plane, since both affected axes are in degrees. But you
/// should not rotate this coordinate system in any other plane.</remarks>
/// <param name="name">Name of coordinate system</param>
/// <param name="baseCoordinateSystem">Base coordinate system</param>
/// <param name="toBaseWkt"></param>
/// <param name="arAxes"></param>
/// <returns>Fitted coordinate system</returns>
public FittedCoordinateSystem CreateFittedCoordinateSystem(string name, CoordinateSystem baseCoordinateSystem, string toBaseWkt, List<AxisInfo> arAxes)
{
throw new NotImplementedException();
}
/*
/// <summary>
/// Creates a <see cref="ILocalCoordinateSystem">local coordinate system</see>.
/// </summary>
/// <remarks>
/// The dimension of the local coordinate system is determined by the size of
/// the axis array. All the axes will have the same units. If you want to make
/// a coordinate system with mixed units, then you can make a compound
/// coordinate system from different local coordinate systems.
/// </remarks>
/// <param name="name">Name of local coordinate system</param>
/// <param name="datum">Local datum</param>
/// <param name="unit">Units</param>
/// <param name="axes">Axis info</param>
/// <returns>Local coordinate system</returns>
public ILocalCoordinateSystem CreateLocalCoordinateSystem(string name, ILocalDatum datum, IUnit unit, List<AxisInfo> axes)
{
throw new NotImplementedException();
}
*/
/// <summary>
/// Creates an <see cref="Ellipsoid"/> from radius values.
/// </summary>
/// <seealso cref="CreateFlattenedSphere"/>
/// <param name="name">Name of ellipsoid</param>
/// <param name="semiMajorAxis"></param>
/// <param name="semiMinorAxis"></param>
/// <param name="linearUnit"></param>
/// <returns>Ellipsoid</returns>
public Ellipsoid CreateEllipsoid(string name, double semiMajorAxis, double semiMinorAxis, LinearUnit linearUnit)
{
double ivf = 0;
if (semiMajorAxis != semiMinorAxis)
ivf = semiMajorAxis / (semiMajorAxis - semiMinorAxis);
return new Ellipsoid(semiMajorAxis, semiMinorAxis, ivf, false, linearUnit, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/// <summary>
/// Creates an <see cref="Ellipsoid"/> from an major radius, and inverse flattening.
/// </summary>
/// <seealso cref="CreateEllipsoid"/>
/// <param name="name">Name of ellipsoid</param>
/// <param name="semiMajorAxis">Semi major-axis</param>
/// <param name="inverseFlattening">Inverse flattening</param>
/// <param name="linearUnit">Linear unit</param>
/// <returns>Ellipsoid</returns>
public Ellipsoid CreateFlattenedSphere(string name, double semiMajorAxis, double inverseFlattening, LinearUnit linearUnit)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name");
return new Ellipsoid(semiMajorAxis, -1, inverseFlattening, true, linearUnit, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/// <summary>
/// Creates a <see cref="ProjectedCoordinateSystem"/> using a projection object.
/// </summary>
/// <param name="name">Name of projected coordinate system</param>
/// <param name="gcs">Geographic coordinate system</param>
/// <param name="projection">Projection</param>
/// <param name="linearUnit">Linear unit</param>
/// <param name="axis0">Primary axis</param>
/// <param name="axis1">Secondary axis</param>
/// <returns>Projected coordinate system</returns>
public ProjectedCoordinateSystem CreateProjectedCoordinateSystem(string name, GeographicCoordinateSystem gcs, IProjection projection, LinearUnit linearUnit, AxisInfo axis0, AxisInfo axis1)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name", nameof(name));
if (gcs == null)
throw new ArgumentException("Geographic coordinate system was null", nameof(gcs));
if (projection == null)
throw new ArgumentException("Projection was null", nameof(projection));
if (linearUnit == null)
throw new ArgumentException("Linear unit was null");
var info = new List<AxisInfo>(2);
info.Add(axis0);
info.Add(axis1);
return new ProjectedCoordinateSystem(null, gcs, linearUnit, projection, info, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/// <summary>
/// Creates a <see cref="Projection"/>.
/// </summary>
/// <param name="name">Name of projection</param>
/// <param name="wktProjectionClass">Projection class</param>
/// <param name="parameters">Projection parameters</param>
/// <returns>Projection</returns>
public IProjection CreateProjection(string name, string wktProjectionClass, List<ProjectionParameter> parameters)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name");
if (parameters == null || parameters.Count == 0)
throw new ArgumentException("Invalid projection parameters");
return new Projection(wktProjectionClass, parameters, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/// <summary>
/// Creates <see cref="HorizontalDatum"/> from ellipsoid and Bursa-World parameters.
/// </summary>
/// <remarks>
/// Since this method contains a set of Bursa-Wolf parameters, the created
/// datum will always have a relationship to WGS84. If you wish to create a
/// horizontal datum that has no relationship with WGS84, then you can
/// either specify a <see cref="DatumType">horizontalDatumType</see> of <see cref="DatumType.HD_Other"/>, or create it via WKT.
/// </remarks>
/// <param name="name">Name of ellipsoid</param>
/// <param name="datumType">Type of datum</param>
/// <param name="ellipsoid">Ellipsoid</param>
/// <param name="toWgs84">Wgs84 conversion parameters</param>
/// <returns>Horizontal datum</returns>
public HorizontalDatum CreateHorizontalDatum(string name, DatumType datumType, Ellipsoid ellipsoid, Wgs84ConversionInfo toWgs84)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name");
if (ellipsoid == null)
throw new ArgumentException("Ellipsoid was null");
return new HorizontalDatum(ellipsoid, toWgs84, datumType, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/// <summary>
/// Creates a <see cref="PrimeMeridian"/>, relative to Greenwich.
/// </summary>
/// <param name="name">Name of prime meridian</param>
/// <param name="angularUnit">Angular unit</param>
/// <param name="longitude">Longitude</param>
/// <returns>Prime meridian</returns>
public PrimeMeridian CreatePrimeMeridian(string name, AngularUnit angularUnit, double longitude)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name");
return new PrimeMeridian(longitude, angularUnit, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/// <summary>
/// Creates a <see cref="GeographicCoordinateSystem"/>, which could be Lat/Lon or Lon/Lat.
/// </summary>
/// <param name="name">Name of geographical coordinate system</param>
/// <param name="angularUnit">Angular units</param>
/// <param name="datum">Horizontal datum</param>
/// <param name="primeMeridian">Prime meridian</param>
/// <param name="axis0">First axis</param>
/// <param name="axis1">Second axis</param>
/// <returns>Geographic coordinate system</returns>
public GeographicCoordinateSystem CreateGeographicCoordinateSystem(string name, AngularUnit angularUnit, HorizontalDatum datum, PrimeMeridian primeMeridian, AxisInfo axis0, AxisInfo axis1)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name");
var info = new List<AxisInfo>(2);
info.Add(axis0);
info.Add(axis1);
return new GeographicCoordinateSystem(angularUnit, datum, primeMeridian, info, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
/*
/// <summary>
/// Creates a <see cref="ILocalDatum"/>.
/// </summary>
/// <param name="name">Name of datum</param>
/// <param name="datumType">Datum type</param>
/// <returns></returns>
public ILocalDatum CreateLocalDatum(string name, DatumType datumType)
{
throw new NotImplementedException();
}
*/
/*
/// <summary>
/// Creates a <see cref="IVerticalDatum"/> from an enumerated type value.
/// </summary>
/// <param name="name">Name of datum</param>
/// <param name="datumType">Type of datum</param>
/// <returns>Vertical datum</returns>
public IVerticalDatum CreateVerticalDatum(string name, DatumType datumType)
{
throw new NotImplementedException();
}
*/
/*
/// <summary>
/// Creates a <see cref="IVerticalCoordinateSystem"/> from a <see cref="IVerticalDatum">datum</see> and <see cref="LinearUnit">linear units</see>.
/// </summary>
/// <param name="name">Name of vertical coordinate system</param>
/// <param name="datum">Vertical datum</param>
/// <param name="verticalUnit">Unit</param>
/// <param name="axis">Axis info</param>
/// <returns>Vertical coordinate system</returns>
public IVerticalCoordinateSystem CreateVerticalCoordinateSystem(string name, IVerticalDatum datum, ILinearUnit verticalUnit, AxisInfo axis)
{
throw new NotImplementedException();
}
*/
/// <summary>
/// Creates a <see cref="CreateGeocentricCoordinateSystem"/> from a <see cref="HorizontalDatum">datum</see>,
/// <see cref="LinearUnit">linear unit</see> and <see cref="PrimeMeridian"/>.
/// </summary>
/// <param name="name">Name of geocentric coordinate system</param>
/// <param name="datum">Horizontal datum</param>
/// <param name="linearUnit">Linear unit</param>
/// <param name="primeMeridian">Prime meridian</param>
/// <returns>Geocentric Coordinate System</returns>
public GeocentricCoordinateSystem CreateGeocentricCoordinateSystem(string name, HorizontalDatum datum, LinearUnit linearUnit, PrimeMeridian primeMeridian)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Invalid name");
var info = new List<AxisInfo>(3);
info.Add(new AxisInfo("X", AxisOrientationEnum.Other));
info.Add(new AxisInfo("Y", AxisOrientationEnum.Other));
info.Add(new AxisInfo("Z", AxisOrientationEnum.Other));
return new GeocentricCoordinateSystem(datum, linearUnit, primeMeridian, info, name, string.Empty, -1, string.Empty, string.Empty, string.Empty);
}
}
}

Просмотреть файл

@ -1,79 +1,79 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A set of quantities from which other quantities are calculated.
/// </summary>
/// <remarks>
/// For the OGC abstract model, it can be defined as a set of real points on the earth
/// that have coordinates. EG. A datum can be thought of as a set of parameters
/// defining completely the origin and orientation of a coordinate system with respect
/// to the earth. A textual description and/or a set of parameters describing the
/// relationship of a coordinate system to some predefined physical locations (such
/// as center of mass) and physical directions (such as axis of spin). The definition
/// of the datum may also include the temporal behavior (such as the rate of change of
/// the orientation of the coordinate axes).
/// </remarks>
[Serializable]
public abstract class Datum : Info
{
/// <summary>
/// Initializes a new instance of a Datum object
/// </summary>
/// <param name="type">Datum type</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal Datum(DatumType type,
string name, string authority, long code, string alias,
string remarks, string abbreviation)
: base(name, authority, code, alias, abbreviation, remarks)
{
DatumType = type;
}
#region IDatum Members
/// <summary>
/// Gets or sets the type of the datum as an enumerated code.
/// </summary>
public DatumType DatumType { get; set; }
#endregion
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is Ellipsoid))
return false;
return (obj as Datum).DatumType == this.DatumType;
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A set of quantities from which other quantities are calculated.
/// </summary>
/// <remarks>
/// For the OGC abstract model, it can be defined as a set of real points on the earth
/// that have coordinates. EG. A datum can be thought of as a set of parameters
/// defining completely the origin and orientation of a coordinate system with respect
/// to the earth. A textual description and/or a set of parameters describing the
/// relationship of a coordinate system to some predefined physical locations (such
/// as center of mass) and physical directions (such as axis of spin). The definition
/// of the datum may also include the temporal behavior (such as the rate of change of
/// the orientation of the coordinate axes).
/// </remarks>
[Serializable]
public abstract class Datum : Info
{
/// <summary>
/// Initializes a new instance of a Datum object
/// </summary>
/// <param name="type">Datum type</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal Datum(DatumType type,
string name, string authority, long code, string alias,
string remarks, string abbreviation)
: base(name, authority, code, alias, abbreviation, remarks)
{
DatumType = type;
}
#region IDatum Members
/// <summary>
/// Gets or sets the type of the datum as an enumerated code.
/// </summary>
public DatumType DatumType { get; set; }
#endregion
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is Ellipsoid))
return false;
return (obj as Datum).DatumType == this.DatumType;
}
}
}

Просмотреть файл

@ -1,259 +1,259 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// The IEllipsoid interface defines the standard information stored with ellipsoid objects.
/// </summary>
[Serializable]
public class Ellipsoid : Info
{
/// <summary>
/// Initializes a new instance of an Ellipsoid
/// </summary>
/// <param name="semiMajorAxis">Semi major axis</param>
/// <param name="semiMinorAxis">Semi minor axis</param>
/// <param name="inverseFlattening">Inverse flattening</param>
/// <param name="isIvfDefinitive">Inverse Flattening is definitive for this ellipsoid (Semi-minor axis will be overridden)</param>
/// <param name="axisUnit">Axis unit</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal Ellipsoid(
double semiMajorAxis,
double semiMinorAxis,
double inverseFlattening,
bool isIvfDefinitive,
LinearUnit axisUnit, string name, string authority, long code, string alias,
string abbreviation, string remarks)
: base(name, authority, code, alias, abbreviation, remarks)
{
SemiMajorAxis = semiMajorAxis;
InverseFlattening = inverseFlattening;
AxisUnit = axisUnit;
IsIvfDefinitive = isIvfDefinitive;
if (isIvfDefinitive && (inverseFlattening == 0 || double.IsInfinity(inverseFlattening)))
SemiMinorAxis = semiMajorAxis;
else if (isIvfDefinitive)
SemiMinorAxis = (1.0 - (1.0 / InverseFlattening)) * semiMajorAxis;
else
SemiMinorAxis = semiMinorAxis;
}
#region Predefined ellipsoids
/// <summary>
/// WGS 84 ellipsoid
/// </summary>
/// <remarks>
/// Inverse flattening derived from four defining parameters
/// (semi-major axis;
/// C20 = -484.16685*10e-6;
/// earth's angular velocity w = 7292115e11 rad/sec;
/// gravitational constant GM = 3986005e8 m*m*m/s/s).
/// </remarks>
public static Ellipsoid WGS84
{
get
{
return new Ellipsoid(6378137, 0, 298.257223563, true, LinearUnit.Metre, "WGS 84", "EPSG", 7030, "WGS84", "",
"Inverse flattening derived from four defining parameters (semi-major axis; C20 = -484.16685*10e-6; earth's angular velocity w = 7292115e11 rad/sec; gravitational constant GM = 3986005e8 m*m*m/s/s).");
}
}
/// <summary>
/// WGS 72 Ellipsoid
/// </summary>
public static Ellipsoid WGS72
{
get
{
return new Ellipsoid(6378135.0, 0, 298.26, true, LinearUnit.Metre, "WGS 72", "EPSG", 7043, "WGS 72", string.Empty, string.Empty);
}
}
/// <summary>
/// GRS 1980 / International 1979 ellipsoid
/// </summary>
/// <remarks>
/// Adopted by IUGG 1979 Canberra.
/// Inverse flattening is derived from
/// geocentric gravitational constant GM = 3986005e8 m*m*m/s/s;
/// dynamic form factor J2 = 108263e8 and Earth's angular velocity = 7292115e-11 rad/s.")
/// </remarks>
public static Ellipsoid GRS80
{
get
{
return new Ellipsoid(6378137, 0, 298.257222101, true, LinearUnit.Metre, "GRS 1980", "EPSG", 7019, "International 1979", "",
"Adopted by IUGG 1979 Canberra. Inverse flattening is derived from geocentric gravitational constant GM = 3986005e8 m*m*m/s/s; dynamic form factor J2 = 108263e8 and Earth's angular velocity = 7292115e-11 rad/s.");
}
}
/// <summary>
/// International 1924 / Hayford 1909 ellipsoid
/// </summary>
/// <remarks>
/// Described as a=6378388 m. and b=6356909m. from which 1/f derived to be 296.95926.
/// The figure was adopted as the International ellipsoid in 1924 but with 1/f taken as
/// 297 exactly from which b is derived as 6356911.946m.
/// </remarks>
public static Ellipsoid International1924
{
get
{
return new Ellipsoid(6378388, 0, 297, true, LinearUnit.Metre, "International 1924", "EPSG", 7022, "Hayford 1909", string.Empty,
"Described as a=6378388 m. and b=6356909 m. from which 1/f derived to be 296.95926. The figure was adopted as the International ellipsoid in 1924 but with 1/f taken as 297 exactly from which b is derived as 6356911.946m.");
}
}
/// <summary>
/// Clarke 1880
/// </summary>
/// <remarks>
/// Clarke gave a and b and also 1/f=293.465 (to 3 decimal places). 1/f derived from a and b = 293.4663077
/// </remarks>
public static Ellipsoid Clarke1880
{
get
{
return new Ellipsoid(20926202, 0, 297, true, LinearUnit.ClarkesFoot, "Clarke 1880", "EPSG", 7034, "Clarke 1880", string.Empty,
"Clarke gave a and b and also 1/f=293.465 (to 3 decimal places). 1/f derived from a and b = 293.4663077…");
}
}
/// <summary>
/// Clarke 1866
/// </summary>
/// <remarks>
/// Original definition a=20926062 and b=20855121 (British) feet. Uses Clarke's 1865 inch-metre ratio of 39.370432 to obtain metres. (Metric value then converted to US survey feet for use in the United States using 39.37 exactly giving a=20925832.16 ft US).
/// </remarks>
public static Ellipsoid Clarke1866
{
get
{
return new Ellipsoid(6378206.4, 6356583.8, double.PositiveInfinity, false, LinearUnit.Metre, "Clarke 1866", "EPSG", 7008, "Clarke 1866", string.Empty,
"Original definition a=20926062 and b=20855121 (British) feet. Uses Clarke's 1865 inch-metre ratio of 39.370432 to obtain metres. (Metric value then converted to US survey feet for use in the United States using 39.37 exactly giving a=20925832.16 ft US).");
}
}
/// <summary>
/// Sphere
/// </summary>
/// <remarks>
/// Authalic sphere derived from GRS 1980 ellipsoid (code 7019). (An authalic sphere is
/// one with a surface area equal to the surface area of the ellipsoid). 1/f is infinite.
/// </remarks>
public static Ellipsoid Sphere
{
get
{
return new Ellipsoid(6370997.0, 6370997.0, double.PositiveInfinity, false, LinearUnit.Metre, "GRS 1980 Authalic Sphere", "EPSG", 7048, "Sphere", "",
"Authalic sphere derived from GRS 1980 ellipsoid (code 7019). (An authalic sphere is one with a surface area equal to the surface area of the ellipsoid). 1/f is infinite.");
}
}
#endregion
#region IEllipsoid Members
/// <summary>
/// Gets or sets the value of the semi-major axis.
/// </summary>
public double SemiMajorAxis { get; set; }
/// <summary>
/// Gets or sets the value of the semi-minor axis.
/// </summary>
public double SemiMinorAxis { get; set; }
/// <summary>
/// Gets or sets the value of the inverse of the flattening constant of the ellipsoid.
/// </summary>
public double InverseFlattening { get; set; }
/// <summary>
/// Gets or sets the value of the axis unit.
/// </summary>
public LinearUnit AxisUnit { get; set; }
/// <summary>
/// Tells if the Inverse Flattening is definitive for this ellipsoid. Some ellipsoids use
/// the IVF as the defining value, and calculate the polar radius whenever asked. Other
/// ellipsoids use the polar radius to calculate the IVF whenever asked. This
/// distinction can be important to avoid floating-point rounding errors.
/// </summary>
public bool IsIvfDefinitive { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat, "SPHEROID[\"{0}\", {1}, {2}", Name, SemiMajorAxis, InverseFlattening);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
return string.Format(CultureInfo.InvariantCulture.NumberFormat,
"<CS_Ellipsoid SemiMajorAxis=\"{0}\" SemiMinorAxis=\"{1}\" InverseFlattening=\"{2}\" IvfDefinitive=\"{3}\">{4}{5}</CS_Ellipsoid>",
SemiMajorAxis, SemiMinorAxis, InverseFlattening, (IsIvfDefinitive ? 1 : 0), InfoXml, AxisUnit.XML); ;
}
}
#endregion
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is Ellipsoid))
return false;
var e = obj as Ellipsoid;
return (e.InverseFlattening == this.InverseFlattening &&
e.IsIvfDefinitive == this.IsIvfDefinitive &&
e.SemiMajorAxis == this.SemiMajorAxis &&
e.SemiMinorAxis == this.SemiMinorAxis &&
e.AxisUnit.EqualParams(this.AxisUnit));
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// The IEllipsoid interface defines the standard information stored with ellipsoid objects.
/// </summary>
[Serializable]
public class Ellipsoid : Info
{
/// <summary>
/// Initializes a new instance of an Ellipsoid
/// </summary>
/// <param name="semiMajorAxis">Semi major axis</param>
/// <param name="semiMinorAxis">Semi minor axis</param>
/// <param name="inverseFlattening">Inverse flattening</param>
/// <param name="isIvfDefinitive">Inverse Flattening is definitive for this ellipsoid (Semi-minor axis will be overridden)</param>
/// <param name="axisUnit">Axis unit</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal Ellipsoid(
double semiMajorAxis,
double semiMinorAxis,
double inverseFlattening,
bool isIvfDefinitive,
LinearUnit axisUnit, string name, string authority, long code, string alias,
string abbreviation, string remarks)
: base(name, authority, code, alias, abbreviation, remarks)
{
SemiMajorAxis = semiMajorAxis;
InverseFlattening = inverseFlattening;
AxisUnit = axisUnit;
IsIvfDefinitive = isIvfDefinitive;
if (isIvfDefinitive && (inverseFlattening == 0 || double.IsInfinity(inverseFlattening)))
SemiMinorAxis = semiMajorAxis;
else if (isIvfDefinitive)
SemiMinorAxis = (1.0 - (1.0 / InverseFlattening)) * semiMajorAxis;
else
SemiMinorAxis = semiMinorAxis;
}
#region Predefined ellipsoids
/// <summary>
/// WGS 84 ellipsoid
/// </summary>
/// <remarks>
/// Inverse flattening derived from four defining parameters
/// (semi-major axis;
/// C20 = -484.16685*10e-6;
/// earth's angular velocity w = 7292115e11 rad/sec;
/// gravitational constant GM = 3986005e8 m*m*m/s/s).
/// </remarks>
public static Ellipsoid WGS84
{
get
{
return new Ellipsoid(6378137, 0, 298.257223563, true, LinearUnit.Metre, "WGS 84", "EPSG", 7030, "WGS84", "",
"Inverse flattening derived from four defining parameters (semi-major axis; C20 = -484.16685*10e-6; earth's angular velocity w = 7292115e11 rad/sec; gravitational constant GM = 3986005e8 m*m*m/s/s).");
}
}
/// <summary>
/// WGS 72 Ellipsoid
/// </summary>
public static Ellipsoid WGS72
{
get
{
return new Ellipsoid(6378135.0, 0, 298.26, true, LinearUnit.Metre, "WGS 72", "EPSG", 7043, "WGS 72", string.Empty, string.Empty);
}
}
/// <summary>
/// GRS 1980 / International 1979 ellipsoid
/// </summary>
/// <remarks>
/// Adopted by IUGG 1979 Canberra.
/// Inverse flattening is derived from
/// geocentric gravitational constant GM = 3986005e8 m*m*m/s/s;
/// dynamic form factor J2 = 108263e8 and Earth's angular velocity = 7292115e-11 rad/s.")
/// </remarks>
public static Ellipsoid GRS80
{
get
{
return new Ellipsoid(6378137, 0, 298.257222101, true, LinearUnit.Metre, "GRS 1980", "EPSG", 7019, "International 1979", "",
"Adopted by IUGG 1979 Canberra. Inverse flattening is derived from geocentric gravitational constant GM = 3986005e8 m*m*m/s/s; dynamic form factor J2 = 108263e8 and Earth's angular velocity = 7292115e-11 rad/s.");
}
}
/// <summary>
/// International 1924 / Hayford 1909 ellipsoid
/// </summary>
/// <remarks>
/// Described as a=6378388 m. and b=6356909m. from which 1/f derived to be 296.95926.
/// The figure was adopted as the International ellipsoid in 1924 but with 1/f taken as
/// 297 exactly from which b is derived as 6356911.946m.
/// </remarks>
public static Ellipsoid International1924
{
get
{
return new Ellipsoid(6378388, 0, 297, true, LinearUnit.Metre, "International 1924", "EPSG", 7022, "Hayford 1909", string.Empty,
"Described as a=6378388 m. and b=6356909 m. from which 1/f derived to be 296.95926. The figure was adopted as the International ellipsoid in 1924 but with 1/f taken as 297 exactly from which b is derived as 6356911.946m.");
}
}
/// <summary>
/// Clarke 1880
/// </summary>
/// <remarks>
/// Clarke gave a and b and also 1/f=293.465 (to 3 decimal places). 1/f derived from a and b = 293.4663077
/// </remarks>
public static Ellipsoid Clarke1880
{
get
{
return new Ellipsoid(20926202, 0, 297, true, LinearUnit.ClarkesFoot, "Clarke 1880", "EPSG", 7034, "Clarke 1880", string.Empty,
"Clarke gave a and b and also 1/f=293.465 (to 3 decimal places). 1/f derived from a and b = 293.4663077…");
}
}
/// <summary>
/// Clarke 1866
/// </summary>
/// <remarks>
/// Original definition a=20926062 and b=20855121 (British) feet. Uses Clarke's 1865 inch-metre ratio of 39.370432 to obtain metres. (Metric value then converted to US survey feet for use in the United States using 39.37 exactly giving a=20925832.16 ft US).
/// </remarks>
public static Ellipsoid Clarke1866
{
get
{
return new Ellipsoid(6378206.4, 6356583.8, double.PositiveInfinity, false, LinearUnit.Metre, "Clarke 1866", "EPSG", 7008, "Clarke 1866", string.Empty,
"Original definition a=20926062 and b=20855121 (British) feet. Uses Clarke's 1865 inch-metre ratio of 39.370432 to obtain metres. (Metric value then converted to US survey feet for use in the United States using 39.37 exactly giving a=20925832.16 ft US).");
}
}
/// <summary>
/// Sphere
/// </summary>
/// <remarks>
/// Authalic sphere derived from GRS 1980 ellipsoid (code 7019). (An authalic sphere is
/// one with a surface area equal to the surface area of the ellipsoid). 1/f is infinite.
/// </remarks>
public static Ellipsoid Sphere
{
get
{
return new Ellipsoid(6370997.0, 6370997.0, double.PositiveInfinity, false, LinearUnit.Metre, "GRS 1980 Authalic Sphere", "EPSG", 7048, "Sphere", "",
"Authalic sphere derived from GRS 1980 ellipsoid (code 7019). (An authalic sphere is one with a surface area equal to the surface area of the ellipsoid). 1/f is infinite.");
}
}
#endregion
#region IEllipsoid Members
/// <summary>
/// Gets or sets the value of the semi-major axis.
/// </summary>
public double SemiMajorAxis { get; set; }
/// <summary>
/// Gets or sets the value of the semi-minor axis.
/// </summary>
public double SemiMinorAxis { get; set; }
/// <summary>
/// Gets or sets the value of the inverse of the flattening constant of the ellipsoid.
/// </summary>
public double InverseFlattening { get; set; }
/// <summary>
/// Gets or sets the value of the axis unit.
/// </summary>
public LinearUnit AxisUnit { get; set; }
/// <summary>
/// Tells if the Inverse Flattening is definitive for this ellipsoid. Some ellipsoids use
/// the IVF as the defining value, and calculate the polar radius whenever asked. Other
/// ellipsoids use the polar radius to calculate the IVF whenever asked. This
/// distinction can be important to avoid floating-point rounding errors.
/// </summary>
public bool IsIvfDefinitive { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat, "SPHEROID[\"{0}\", {1}, {2}", Name, SemiMajorAxis, InverseFlattening);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
return string.Format(CultureInfo.InvariantCulture.NumberFormat,
"<CS_Ellipsoid SemiMajorAxis=\"{0}\" SemiMinorAxis=\"{1}\" InverseFlattening=\"{2}\" IvfDefinitive=\"{3}\">{4}{5}</CS_Ellipsoid>",
SemiMajorAxis, SemiMinorAxis, InverseFlattening, (IsIvfDefinitive ? 1 : 0), InfoXml, AxisUnit.XML); ;
}
}
#endregion
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is Ellipsoid))
return false;
var e = obj as Ellipsoid;
return (e.InverseFlattening == this.InverseFlattening &&
e.IsIvfDefinitive == this.IsIvfDefinitive &&
e.SemiMajorAxis == this.SemiMajorAxis &&
e.SemiMinorAxis == this.SemiMinorAxis &&
e.AxisUnit.EqualParams(this.AxisUnit));
}
}
}

Просмотреть файл

@ -1,154 +1,154 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A coordinate system which sits inside another coordinate system. The fitted
/// coordinate system can be rotated and shifted, or use any other math transform
/// to inject itself into the base coordinate system.
/// </summary>
[Serializable]
public class FittedCoordinateSystem : CoordinateSystem //, IFittedCoordinateSystem
{
/// <summary>
/// Creates an instance of FittedCoordinateSystem using the specified parameters
/// </summary>
/// <param name="baseSystem">Underlying coordinate system.</param>
/// <param name="transform">Transformation from fitted coordinate system to the base one</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
protected internal FittedCoordinateSystem (CoordinateSystem baseSystem, MathTransform transform,
string name, string authority, long code, string alias, string remarks, string abbreviation)
: base(name, authority, code, alias, abbreviation, remarks)
{
BaseCoordinateSystem = baseSystem;
ToBaseTransform = transform;
//get axis infos from the source
base.AxisInfo = new List<AxisInfo> (baseSystem.Dimension);
for (int dim = 0; dim < baseSystem.Dimension; dim++)
{
base.AxisInfo.Add (baseSystem.GetAxis (dim));
}
}
#region public properties
/// <summary>
/// Represents math transform that injects itself into the base coordinate system.
/// </summary>
public MathTransform ToBaseTransform { get; }
#endregion public properties
#region FittedCoordinateSystem Members
/// <summary>
/// Gets underlying coordinate system.
/// </summary>
public CoordinateSystem BaseCoordinateSystem { get; }
/// <summary>
/// Gets Well-Known Text of a math transform to the base coordinate system.
/// The dimension of this fitted coordinate system is determined by the source
/// dimension of the math transform. The transform should be one-to-one within
/// this coordinate system's domain, and the base coordinate system dimension
/// must be at least as big as the dimension of this coordinate system.
/// </summary>
/// <returns></returns>
public string ToBase ()
{
return ToBaseTransform.WKT;
}
#endregion
#region ICoordinateSystem Members
/// <summary>
/// Returns the Well-known text for this object as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
//<fitted cs> = FITTED_CS["<name>", <to base>, <base cs>]
var sb = new StringBuilder();
sb.AppendFormat ("FITTED_CS[\"{0}\", {1}, {2}]", Name, this.ToBaseTransform.WKT, this.BaseCoordinateSystem.WKT);
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
public override string XML
{
get
{
throw new NotImplementedException ();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams (object obj)
{
var fcs = obj as FittedCoordinateSystem;
if (fcs != null)
{
if (fcs.BaseCoordinateSystem.EqualParams (this.BaseCoordinateSystem))
{
string fcsToBase = fcs.ToBase ();
string thisToBase = this.ToBase ();
if (string.Equals (fcsToBase, thisToBase))
{
return true;
}
}
}
return false;
}
/// <summary>
/// Gets the units for the dimension within coordinate system.
/// Each dimension in the coordinate system has corresponding units.
/// </summary>
public override IUnit GetUnits(int dimension)
{
return BaseCoordinateSystem.GetUnits (dimension);
}
#endregion
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A coordinate system which sits inside another coordinate system. The fitted
/// coordinate system can be rotated and shifted, or use any other math transform
/// to inject itself into the base coordinate system.
/// </summary>
[Serializable]
public class FittedCoordinateSystem : CoordinateSystem //, IFittedCoordinateSystem
{
/// <summary>
/// Creates an instance of FittedCoordinateSystem using the specified parameters
/// </summary>
/// <param name="baseSystem">Underlying coordinate system.</param>
/// <param name="transform">Transformation from fitted coordinate system to the base one</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
protected internal FittedCoordinateSystem (CoordinateSystem baseSystem, MathTransform transform,
string name, string authority, long code, string alias, string remarks, string abbreviation)
: base(name, authority, code, alias, abbreviation, remarks)
{
BaseCoordinateSystem = baseSystem;
ToBaseTransform = transform;
//get axis infos from the source
base.AxisInfo = new List<AxisInfo> (baseSystem.Dimension);
for (int dim = 0; dim < baseSystem.Dimension; dim++)
{
base.AxisInfo.Add (baseSystem.GetAxis (dim));
}
}
#region public properties
/// <summary>
/// Represents math transform that injects itself into the base coordinate system.
/// </summary>
public MathTransform ToBaseTransform { get; }
#endregion public properties
#region FittedCoordinateSystem Members
/// <summary>
/// Gets underlying coordinate system.
/// </summary>
public CoordinateSystem BaseCoordinateSystem { get; }
/// <summary>
/// Gets Well-Known Text of a math transform to the base coordinate system.
/// The dimension of this fitted coordinate system is determined by the source
/// dimension of the math transform. The transform should be one-to-one within
/// this coordinate system's domain, and the base coordinate system dimension
/// must be at least as big as the dimension of this coordinate system.
/// </summary>
/// <returns></returns>
public string ToBase ()
{
return ToBaseTransform.WKT;
}
#endregion
#region ICoordinateSystem Members
/// <summary>
/// Returns the Well-known text for this object as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
//<fitted cs> = FITTED_CS["<name>", <to base>, <base cs>]
var sb = new StringBuilder();
sb.AppendFormat ("FITTED_CS[\"{0}\", {1}, {2}]", Name, this.ToBaseTransform.WKT, this.BaseCoordinateSystem.WKT);
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
public override string XML
{
get
{
throw new NotImplementedException ();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams (object obj)
{
var fcs = obj as FittedCoordinateSystem;
if (fcs != null)
{
if (fcs.BaseCoordinateSystem.EqualParams (this.BaseCoordinateSystem))
{
string fcsToBase = fcs.ToBase ();
string thisToBase = this.ToBase ();
if (string.Equals (fcsToBase, thisToBase))
{
return true;
}
}
}
return false;
}
/// <summary>
/// Gets the units for the dimension within coordinate system.
/// Each dimension in the coordinate system has corresponding units.
/// </summary>
public override IUnit GetUnits(int dimension)
{
return BaseCoordinateSystem.GetUnits (dimension);
}
#endregion
}
}

Просмотреть файл

@ -1,153 +1,153 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A 3D coordinate system, with its origin at the center of the Earth.
/// </summary>
[Serializable]
public class GeocentricCoordinateSystem : CoordinateSystem
{
internal GeocentricCoordinateSystem(HorizontalDatum datum, LinearUnit linearUnit, PrimeMeridian primeMeridian, List<AxisInfo> axisInfo,
string name, string authority, long code, string alias,
string remarks, string abbreviation)
: base(name, authority, code, alias, abbreviation, remarks)
{
HorizontalDatum = datum;
LinearUnit = linearUnit;
PrimeMeridian = primeMeridian;
if (axisInfo.Count != 3)
throw new ArgumentException("Axis info should contain three axes for geocentric coordinate systems");
base.AxisInfo = axisInfo;
}
#region Predefined geographic coordinate systems
/// <summary>
/// Creates a geocentric coordinate system based on the WGS84 ellipsoid, suitable for GPS measurements
/// </summary>
public static GeocentricCoordinateSystem WGS84
{
get
{
return new CoordinateSystemFactory().CreateGeocentricCoordinateSystem("WGS84 Geocentric",
HorizontalDatum.WGS84, LinearUnit.Metre, PrimeMeridian.Greenwich);
}
}
#endregion
#region GeocentricCoordinateSystem Members
/// <summary>
/// Returns the HorizontalDatum. The horizontal datum is used to determine where
/// the centre of the Earth is considered to be. All coordinate points will be
/// measured from the centre of the Earth, and not the surface.
/// </summary>
public HorizontalDatum HorizontalDatum { get; set; }
/// <summary>
/// Gets the units used along all the axes.
/// </summary>
public LinearUnit LinearUnit { get; set; }
/// <summary>
/// Gets units for dimension within coordinate system. Each dimension in
/// the coordinate system has corresponding units.
/// </summary>
/// <param name="dimension">Dimension</param>
/// <returns>Unit</returns>
public override IUnit GetUnits(int dimension)
{
return LinearUnit;
}
/// <summary>
/// Returns the PrimeMeridian.
/// </summary>
public PrimeMeridian PrimeMeridian { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat("GEOCCS[\"{0}\", {1}, {2}, {3}", Name, HorizontalDatum.WKT, PrimeMeridian.WKT, LinearUnit.WKT);
//Skip axis info if they contain default values
if (AxisInfo.Count != 3 ||
AxisInfo[0].Name != "X" || AxisInfo[0].Orientation != AxisOrientationEnum.Other ||
AxisInfo[1].Name != "Y" || AxisInfo[1].Orientation != AxisOrientationEnum.East ||
AxisInfo[2].Name != "Z" || AxisInfo[2].Orientation != AxisOrientationEnum.North)
for (int i = 0; i < AxisInfo.Count; i++)
sb.AppendFormat(", {0}", GetAxis(i).WKT);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode>0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat,
"<CS_CoordinateSystem Dimension=\"{0}\"><CS_GeocentricCoordinateSystem>{1}",
Dimension, InfoXml);
foreach (var ai in AxisInfo)
sb.Append(ai.XML);
sb.AppendFormat("{0}{1}{2}</CS_GeocentricCoordinateSystem></CS_CoordinateSystem>",
HorizontalDatum.XML, LinearUnit.XML, PrimeMeridian.XML);
return sb.ToString();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is GeocentricCoordinateSystem gcc))
return false;
return gcc.HorizontalDatum.EqualParams(HorizontalDatum) &&
gcc.LinearUnit.EqualParams(LinearUnit) &&
gcc.PrimeMeridian.EqualParams(PrimeMeridian);
}
#endregion
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A 3D coordinate system, with its origin at the center of the Earth.
/// </summary>
[Serializable]
public class GeocentricCoordinateSystem : CoordinateSystem
{
internal GeocentricCoordinateSystem(HorizontalDatum datum, LinearUnit linearUnit, PrimeMeridian primeMeridian, List<AxisInfo> axisInfo,
string name, string authority, long code, string alias,
string remarks, string abbreviation)
: base(name, authority, code, alias, abbreviation, remarks)
{
HorizontalDatum = datum;
LinearUnit = linearUnit;
PrimeMeridian = primeMeridian;
if (axisInfo.Count != 3)
throw new ArgumentException("Axis info should contain three axes for geocentric coordinate systems");
base.AxisInfo = axisInfo;
}
#region Predefined geographic coordinate systems
/// <summary>
/// Creates a geocentric coordinate system based on the WGS84 ellipsoid, suitable for GPS measurements
/// </summary>
public static GeocentricCoordinateSystem WGS84
{
get
{
return new CoordinateSystemFactory().CreateGeocentricCoordinateSystem("WGS84 Geocentric",
HorizontalDatum.WGS84, LinearUnit.Metre, PrimeMeridian.Greenwich);
}
}
#endregion
#region GeocentricCoordinateSystem Members
/// <summary>
/// Returns the HorizontalDatum. The horizontal datum is used to determine where
/// the centre of the Earth is considered to be. All coordinate points will be
/// measured from the centre of the Earth, and not the surface.
/// </summary>
public HorizontalDatum HorizontalDatum { get; set; }
/// <summary>
/// Gets the units used along all the axes.
/// </summary>
public LinearUnit LinearUnit { get; set; }
/// <summary>
/// Gets units for dimension within coordinate system. Each dimension in
/// the coordinate system has corresponding units.
/// </summary>
/// <param name="dimension">Dimension</param>
/// <returns>Unit</returns>
public override IUnit GetUnits(int dimension)
{
return LinearUnit;
}
/// <summary>
/// Returns the PrimeMeridian.
/// </summary>
public PrimeMeridian PrimeMeridian { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat("GEOCCS[\"{0}\", {1}, {2}, {3}", Name, HorizontalDatum.WKT, PrimeMeridian.WKT, LinearUnit.WKT);
//Skip axis info if they contain default values
if (AxisInfo.Count != 3 ||
AxisInfo[0].Name != "X" || AxisInfo[0].Orientation != AxisOrientationEnum.Other ||
AxisInfo[1].Name != "Y" || AxisInfo[1].Orientation != AxisOrientationEnum.East ||
AxisInfo[2].Name != "Z" || AxisInfo[2].Orientation != AxisOrientationEnum.North)
for (int i = 0; i < AxisInfo.Count; i++)
sb.AppendFormat(", {0}", GetAxis(i).WKT);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode>0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat,
"<CS_CoordinateSystem Dimension=\"{0}\"><CS_GeocentricCoordinateSystem>{1}",
Dimension, InfoXml);
foreach (var ai in AxisInfo)
sb.Append(ai.XML);
sb.AppendFormat("{0}{1}{2}</CS_GeocentricCoordinateSystem></CS_CoordinateSystem>",
HorizontalDatum.XML, LinearUnit.XML, PrimeMeridian.XML);
return sb.ToString();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is GeocentricCoordinateSystem gcc))
return false;
return gcc.HorizontalDatum.EqualParams(HorizontalDatum) &&
gcc.LinearUnit.EqualParams(LinearUnit) &&
gcc.PrimeMeridian.EqualParams(PrimeMeridian);
}
#endregion
}
}

Просмотреть файл

@ -1,194 +1,194 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A coordinate system based on latitude and longitude.
/// </summary>
/// <remarks>
/// Some geographic coordinate systems are Lat/Lon, and some are Lon/Lat.
/// You can find out which this is by examining the axes. You should also
/// check the angular units, since not all geographic coordinate systems
/// use degrees.
/// </remarks>
[Serializable]
public class GeographicCoordinateSystem : HorizontalCoordinateSystem
{
/// <summary>
/// Creates an instance of a Geographic Coordinate System
/// </summary>
/// <param name="angularUnit">Angular units</param>
/// <param name="horizontalDatum">Horizontal datum</param>
/// <param name="primeMeridian">Prime meridian</param>
/// <param name="axisInfo">Axis info</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="authorityCode">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal GeographicCoordinateSystem(AngularUnit angularUnit, HorizontalDatum horizontalDatum, PrimeMeridian primeMeridian, List<AxisInfo> axisInfo, string name, string authority, long authorityCode, string alias, string abbreviation, string remarks)
:
base(horizontalDatum, axisInfo, name, authority, authorityCode, alias, abbreviation, remarks)
{
AngularUnit = angularUnit;
PrimeMeridian = primeMeridian;
}
#region Predefined geographic coordinate systems
/// <summary>
/// Creates a decimal degrees geographic coordinate system based on the WGS84 ellipsoid, suitable for GPS measurements
/// </summary>
public static GeographicCoordinateSystem WGS84
{
get {
var axes = new List<AxisInfo>(2);
axes.Add(new AxisInfo("Lon", AxisOrientationEnum.East));
axes.Add(new AxisInfo("Lat", AxisOrientationEnum.North));
return new GeographicCoordinateSystem(CoordinateSystems.AngularUnit.Degrees,
CoordinateSystems.HorizontalDatum.WGS84, CoordinateSystems.PrimeMeridian.Greenwich, axes,
"WGS 84", "EPSG", 4326, string.Empty, string.Empty, string.Empty);
}
}
#endregion
#region IGeographicCoordinateSystem Members
/// <summary>
/// Gets or sets the angular units of the geographic coordinate system.
/// </summary>
public AngularUnit AngularUnit { get; set; }
/// <summary>
/// Gets units for dimension within coordinate system. Each dimension in
/// the coordinate system has corresponding units.
/// </summary>
/// <param name="dimension">Dimension</param>
/// <returns>Unit</returns>
public override IUnit GetUnits(int dimension)
{
return AngularUnit;
}
/// <summary>
/// Gets or sets the prime meridian of the geographic coordinate system.
/// </summary>
public PrimeMeridian PrimeMeridian { get; set; }
/// <summary>
/// Gets the number of available conversions to WGS84 coordinates.
/// </summary>
public int NumConversionToWGS84
{
get { return WGS84ConversionInfo.Count; }
}
internal List<Wgs84ConversionInfo> WGS84ConversionInfo { get; set; }
/// <summary>
/// Gets details on a conversion to WGS84.
/// </summary>
public Wgs84ConversionInfo GetWgs84ConversionInfo(int index)
{
return WGS84ConversionInfo[index];
}
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat("GEOGCS[\"{0}\", {1}, {2}, {3}",Name, HorizontalDatum.WKT, PrimeMeridian.WKT, AngularUnit.WKT);
//Skip axis info if they contain default values
if (AxisInfo.Count != 2 ||
AxisInfo[0].Name != "Lon" || AxisInfo[0].Orientation != AxisOrientationEnum.East ||
AxisInfo[1].Name != "Lat" || AxisInfo[1].Orientation != AxisOrientationEnum.North)
for (int i = 0; i < AxisInfo.Count; i++)
sb.AppendFormat(", {0}", GetAxis(i).WKT);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat,
"<CS_CoordinateSystem Dimension=\"{0}\"><CS_GeographicCoordinateSystem>{1}",
this.Dimension, InfoXml);
foreach(var ai in AxisInfo)
sb.Append(ai.XML);
sb.AppendFormat("{0}{1}{2}</CS_GeographicCoordinateSystem></CS_CoordinateSystem>",
HorizontalDatum.XML, AngularUnit.XML, PrimeMeridian.XML);
return sb.ToString();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is GeographicCoordinateSystem gcs))
return false;
if (gcs.Dimension != Dimension) return false;
if (WGS84ConversionInfo != null && gcs.WGS84ConversionInfo == null) return false;
if (WGS84ConversionInfo == null && gcs.WGS84ConversionInfo != null) return false;
if (WGS84ConversionInfo != null && gcs.WGS84ConversionInfo != null)
{
if (WGS84ConversionInfo.Count != gcs.WGS84ConversionInfo.Count) return false;
for (int i = 0; i < WGS84ConversionInfo.Count; i++)
if (!gcs.WGS84ConversionInfo[i].Equals(WGS84ConversionInfo[i]))
return false;
}
if (AxisInfo.Count != gcs.AxisInfo.Count) return false;
for (int i = 0; i < gcs.AxisInfo.Count; i++)
if (gcs.AxisInfo[i].Orientation != AxisInfo[i].Orientation)
return false;
return gcs.AngularUnit.EqualParams(AngularUnit) &&
gcs.HorizontalDatum.EqualParams(HorizontalDatum) &&
gcs.PrimeMeridian.EqualParams(PrimeMeridian);
}
#endregion
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A coordinate system based on latitude and longitude.
/// </summary>
/// <remarks>
/// Some geographic coordinate systems are Lat/Lon, and some are Lon/Lat.
/// You can find out which this is by examining the axes. You should also
/// check the angular units, since not all geographic coordinate systems
/// use degrees.
/// </remarks>
[Serializable]
public class GeographicCoordinateSystem : HorizontalCoordinateSystem
{
/// <summary>
/// Creates an instance of a Geographic Coordinate System
/// </summary>
/// <param name="angularUnit">Angular units</param>
/// <param name="horizontalDatum">Horizontal datum</param>
/// <param name="primeMeridian">Prime meridian</param>
/// <param name="axisInfo">Axis info</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="authorityCode">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal GeographicCoordinateSystem(AngularUnit angularUnit, HorizontalDatum horizontalDatum, PrimeMeridian primeMeridian, List<AxisInfo> axisInfo, string name, string authority, long authorityCode, string alias, string abbreviation, string remarks)
:
base(horizontalDatum, axisInfo, name, authority, authorityCode, alias, abbreviation, remarks)
{
AngularUnit = angularUnit;
PrimeMeridian = primeMeridian;
}
#region Predefined geographic coordinate systems
/// <summary>
/// Creates a decimal degrees geographic coordinate system based on the WGS84 ellipsoid, suitable for GPS measurements
/// </summary>
public static GeographicCoordinateSystem WGS84
{
get {
var axes = new List<AxisInfo>(2);
axes.Add(new AxisInfo("Lon", AxisOrientationEnum.East));
axes.Add(new AxisInfo("Lat", AxisOrientationEnum.North));
return new GeographicCoordinateSystem(CoordinateSystems.AngularUnit.Degrees,
CoordinateSystems.HorizontalDatum.WGS84, CoordinateSystems.PrimeMeridian.Greenwich, axes,
"WGS 84", "EPSG", 4326, string.Empty, string.Empty, string.Empty);
}
}
#endregion
#region IGeographicCoordinateSystem Members
/// <summary>
/// Gets or sets the angular units of the geographic coordinate system.
/// </summary>
public AngularUnit AngularUnit { get; set; }
/// <summary>
/// Gets units for dimension within coordinate system. Each dimension in
/// the coordinate system has corresponding units.
/// </summary>
/// <param name="dimension">Dimension</param>
/// <returns>Unit</returns>
public override IUnit GetUnits(int dimension)
{
return AngularUnit;
}
/// <summary>
/// Gets or sets the prime meridian of the geographic coordinate system.
/// </summary>
public PrimeMeridian PrimeMeridian { get; set; }
/// <summary>
/// Gets the number of available conversions to WGS84 coordinates.
/// </summary>
public int NumConversionToWGS84
{
get { return WGS84ConversionInfo.Count; }
}
internal List<Wgs84ConversionInfo> WGS84ConversionInfo { get; set; }
/// <summary>
/// Gets details on a conversion to WGS84.
/// </summary>
public Wgs84ConversionInfo GetWgs84ConversionInfo(int index)
{
return WGS84ConversionInfo[index];
}
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat("GEOGCS[\"{0}\", {1}, {2}, {3}",Name, HorizontalDatum.WKT, PrimeMeridian.WKT, AngularUnit.WKT);
//Skip axis info if they contain default values
if (AxisInfo.Count != 2 ||
AxisInfo[0].Name != "Lon" || AxisInfo[0].Orientation != AxisOrientationEnum.East ||
AxisInfo[1].Name != "Lat" || AxisInfo[1].Orientation != AxisOrientationEnum.North)
for (int i = 0; i < AxisInfo.Count; i++)
sb.AppendFormat(", {0}", GetAxis(i).WKT);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat,
"<CS_CoordinateSystem Dimension=\"{0}\"><CS_GeographicCoordinateSystem>{1}",
this.Dimension, InfoXml);
foreach(var ai in AxisInfo)
sb.Append(ai.XML);
sb.AppendFormat("{0}{1}{2}</CS_GeographicCoordinateSystem></CS_CoordinateSystem>",
HorizontalDatum.XML, AngularUnit.XML, PrimeMeridian.XML);
return sb.ToString();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is GeographicCoordinateSystem gcs))
return false;
if (gcs.Dimension != Dimension) return false;
if (WGS84ConversionInfo != null && gcs.WGS84ConversionInfo == null) return false;
if (WGS84ConversionInfo == null && gcs.WGS84ConversionInfo != null) return false;
if (WGS84ConversionInfo != null && gcs.WGS84ConversionInfo != null)
{
if (WGS84ConversionInfo.Count != gcs.WGS84ConversionInfo.Count) return false;
for (int i = 0; i < WGS84ConversionInfo.Count; i++)
if (!gcs.WGS84ConversionInfo[i].Equals(WGS84ConversionInfo[i]))
return false;
}
if (AxisInfo.Count != gcs.AxisInfo.Count) return false;
for (int i = 0; i < gcs.AxisInfo.Count; i++)
if (gcs.AxisInfo[i].Orientation != AxisInfo[i].Orientation)
return false;
return gcs.AngularUnit.EqualParams(AngularUnit) &&
gcs.HorizontalDatum.EqualParams(HorizontalDatum) &&
gcs.PrimeMeridian.EqualParams(PrimeMeridian);
}
#endregion
}
}

Просмотреть файл

@ -1,61 +1,61 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A 2D coordinate system suitable for positions on the Earth's surface.
/// </summary>
[Serializable]
public abstract class HorizontalCoordinateSystem : CoordinateSystem
{
/// <summary>
/// Creates an instance of HorizontalCoordinateSystem
/// </summary>
/// <param name="datum">Horizontal datum</param>
/// <param name="axisInfo">Axis information</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal HorizontalCoordinateSystem(HorizontalDatum datum, List<AxisInfo> axisInfo,
string name, string authority, long code, string alias,
string remarks, string abbreviation)
: base(name, authority, code, alias, abbreviation, remarks)
{
HorizontalDatum = datum;
if (axisInfo.Count != 2)
throw new ArgumentException("Axis info should contain two axes for horizontal coordinate systems");
base.AxisInfo = axisInfo;
}
#region IHorizontalCoordinateSystem Members
/// <summary>
/// Gets or sets the HorizontalDatum.
/// </summary>
public HorizontalDatum HorizontalDatum { get; set; }
#endregion
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A 2D coordinate system suitable for positions on the Earth's surface.
/// </summary>
[Serializable]
public abstract class HorizontalCoordinateSystem : CoordinateSystem
{
/// <summary>
/// Creates an instance of HorizontalCoordinateSystem
/// </summary>
/// <param name="datum">Horizontal datum</param>
/// <param name="axisInfo">Axis information</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal HorizontalCoordinateSystem(HorizontalDatum datum, List<AxisInfo> axisInfo,
string name, string authority, long code, string alias,
string remarks, string abbreviation)
: base(name, authority, code, alias, abbreviation, remarks)
{
HorizontalDatum = datum;
if (axisInfo.Count != 2)
throw new ArgumentException("Axis info should contain two axes for horizontal coordinate systems");
base.AxisInfo = axisInfo;
}
#region IHorizontalCoordinateSystem Members
/// <summary>
/// Gets or sets the HorizontalDatum.
/// </summary>
public HorizontalDatum HorizontalDatum { get; set; }
#endregion
}
}

Просмотреть файл

@ -1,210 +1,210 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Horizontal datum defining the standard datum information.
/// </summary>
[Serializable]
public class HorizontalDatum : Datum
{
/// <summary>
/// Initializes a new instance of a horizontal datum
/// </summary>
/// <param name="ellipsoid">Ellipsoid</param>
/// <param name="toWgs84">Parameters for a Bursa Wolf transformation into WGS84</param>
/// <param name="type">Datum type</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal HorizontalDatum(
Ellipsoid ellipsoid, Wgs84ConversionInfo toWgs84, DatumType type,
string name, string authority, long code, string alias, string remarks, string abbreviation)
: base(type, name, authority, code, alias, remarks, abbreviation)
{
Ellipsoid = ellipsoid;
Wgs84Parameters = toWgs84;
}
#region Predefined datums
/// <summary>
/// EPSG's WGS 84 datum has been the then current realisation. No distinction is made between the original WGS 84
/// frame, WGS 84 (G730), WGS 84 (G873) and WGS 84 (G1150). Since 1997, WGS 84 has been maintained within 10cm of
/// the then current ITRF.
/// </summary>
/// <remarks>
/// <para>Area of use: World</para>
/// <para>Origin description: Defined through a consistent set of station coordinates. These have changed with time: by 0.7m
/// on 29/6/1994 [WGS 84 (G730)], a further 0.2m on 29/1/1997 [WGS 84 (G873)] and a further 0.06m on
/// 20/1/2002 [WGS 84 (G1150)].</para>
/// </remarks>
public static HorizontalDatum WGS84
{
get
{
return new HorizontalDatum(CoordinateSystems.Ellipsoid.WGS84,
null, DatumType.HD_Geocentric, "World Geodetic System 1984", "EPSG", 6326, string.Empty,
"EPSG's WGS 84 datum has been the then current realisation. No distinction is made between the original WGS 84 frame, WGS 84 (G730), WGS 84 (G873) and WGS 84 (G1150). Since 1997, WGS 84 has been maintained within 10cm of the then current ITRF.", string.Empty);
}
}
/// <summary>
/// World Geodetic System 1972
/// </summary>
/// <remarks>
/// <para>Used by GPS before 1987. For Transit satellite positioning see also WGS 72BE. Datum code 6323 reserved for southern hemisphere ProjCS's.</para>
/// <para>Area of use: World</para>
/// <para>Origin description: Developed from a worldwide distribution of terrestrial and
/// geodetic satellite observations and defined through a set of station coordinates.</para>
/// </remarks>
public static HorizontalDatum WGS72
{
get
{
var datum =
new HorizontalDatum(CoordinateSystems.Ellipsoid.WGS72,
null, DatumType.HD_Geocentric, "World Geodetic System 1972", "EPSG", 6322, string.Empty,
"Used by GPS before 1987. For Transit satellite positioning see also WGS 72BE. Datum code 6323 reserved for southern hemisphere ProjCS's.", string.Empty);
datum.Wgs84Parameters = new Wgs84ConversionInfo(0, 0, 4.5, 0, 0, 0.554, 0.219);
return datum;
}
}
/// <summary>
/// European Terrestrial Reference System 1989
/// </summary>
/// <remarks>
/// <para>Area of use:
/// Europe: Albania; Andorra; Austria; Belgium; Bosnia and Herzegovina; Bulgaria; Croatia;
/// Cyprus; Czech Republic; Denmark; Estonia; Finland; Faroe Islands; France; Germany; Greece;
/// Hungary; Ireland; Italy; Latvia; Liechtenstein; Lithuania; Luxembourg; Malta; Netherlands;
/// Norway; Poland; Portugal; Romania; San Marino; Serbia and Montenegro; Slovakia; Slovenia;
/// Spain; Svalbard; Sweden; Switzerland; United Kingdom (UK) including Channel Islands and
/// Isle of Man; Vatican City State.</para>
/// <para>Origin description: Fixed to the stable part of the Eurasian continental
/// plate and consistent with ITRS at the epoch 1989.0.</para>
/// </remarks>
public static HorizontalDatum ETRF89
{
get
{
var datum = new HorizontalDatum(CoordinateSystems.Ellipsoid.GRS80, null, DatumType.HD_Geocentric,
"European Terrestrial Reference System 1989", "EPSG", 6258, "ETRF89", "The distinction in usage between ETRF89 and ETRS89 is confused: although in principle conceptually different in practice both are used for the realisation.", string.Empty);
datum.Wgs84Parameters = new Wgs84ConversionInfo();
return datum;
}
}
/// <summary>
/// European Datum 1950
/// </summary>
/// <remarks>
/// <para>Area of use:
/// Europe - west - Denmark; Faroe Islands; France offshore; Israel offshore; Italy including San
/// Marino and Vatican City State; Ireland offshore; Netherlands offshore; Germany; Greece (offshore);
/// North Sea; Norway; Spain; Svalbard; Turkey; United Kingdom UKCS offshore. Egypt - Western Desert.
/// </para>
/// <para>Origin description: Fundamental point: Potsdam (Helmert Tower).
/// Latitude: 52 deg 22 min 51.4456 sec N; Longitude: 13 deg 3 min 58.9283 sec E (of Greenwich).</para>
/// </remarks>
public static HorizontalDatum ED50
{
get
{
return new HorizontalDatum(CoordinateSystems.Ellipsoid.International1924, new Wgs84ConversionInfo(-87, -98, -121, 0, 0, 0, 0), DatumType.HD_Geocentric,
"European Datum 1950", "EPSG", 6230, "ED50", string.Empty, string.Empty);
}
}
#endregion
#region IHorizontalDatum Members
/// <summary>
/// Gets or sets the ellipsoid of the datum
/// </summary>
public Ellipsoid Ellipsoid { get; set; }
/// <summary>
/// Gets preferred parameters for a Bursa Wolf transformation into WGS84
/// </summary>
public Wgs84ConversionInfo Wgs84Parameters { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat("DATUM[\"{0}\", {1}", Name, Ellipsoid.WKT);
if (Wgs84Parameters != null)
sb.AppendFormat(", {0}", Wgs84Parameters.WKT);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
return string.Format(CultureInfo.InvariantCulture.NumberFormat,
"<CS_HorizontalDatum DatumType=\"{0}\">{1}{2}{3}</CS_HorizontalDatum>",
(int)DatumType, InfoXml, Ellipsoid.XML, (Wgs84Parameters == null ? string.Empty : Wgs84Parameters.XML));
}
}
#endregion
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is HorizontalDatum))
return false;
var datum = obj as HorizontalDatum;
if (datum.Wgs84Parameters == null && this.Wgs84Parameters != null) return false;
if (datum.Wgs84Parameters != null && !datum.Wgs84Parameters.Equals(this.Wgs84Parameters))
return false;
return (datum != null && this.Ellipsoid != null &&
datum.Ellipsoid.EqualParams(this.Ellipsoid) || datum == null && this.Ellipsoid == null) && this.DatumType == datum.DatumType;
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Horizontal datum defining the standard datum information.
/// </summary>
[Serializable]
public class HorizontalDatum : Datum
{
/// <summary>
/// Initializes a new instance of a horizontal datum
/// </summary>
/// <param name="ellipsoid">Ellipsoid</param>
/// <param name="toWgs84">Parameters for a Bursa Wolf transformation into WGS84</param>
/// <param name="type">Datum type</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal HorizontalDatum(
Ellipsoid ellipsoid, Wgs84ConversionInfo toWgs84, DatumType type,
string name, string authority, long code, string alias, string remarks, string abbreviation)
: base(type, name, authority, code, alias, remarks, abbreviation)
{
Ellipsoid = ellipsoid;
Wgs84Parameters = toWgs84;
}
#region Predefined datums
/// <summary>
/// EPSG's WGS 84 datum has been the then current realisation. No distinction is made between the original WGS 84
/// frame, WGS 84 (G730), WGS 84 (G873) and WGS 84 (G1150). Since 1997, WGS 84 has been maintained within 10cm of
/// the then current ITRF.
/// </summary>
/// <remarks>
/// <para>Area of use: World</para>
/// <para>Origin description: Defined through a consistent set of station coordinates. These have changed with time: by 0.7m
/// on 29/6/1994 [WGS 84 (G730)], a further 0.2m on 29/1/1997 [WGS 84 (G873)] and a further 0.06m on
/// 20/1/2002 [WGS 84 (G1150)].</para>
/// </remarks>
public static HorizontalDatum WGS84
{
get
{
return new HorizontalDatum(CoordinateSystems.Ellipsoid.WGS84,
null, DatumType.HD_Geocentric, "World Geodetic System 1984", "EPSG", 6326, string.Empty,
"EPSG's WGS 84 datum has been the then current realisation. No distinction is made between the original WGS 84 frame, WGS 84 (G730), WGS 84 (G873) and WGS 84 (G1150). Since 1997, WGS 84 has been maintained within 10cm of the then current ITRF.", string.Empty);
}
}
/// <summary>
/// World Geodetic System 1972
/// </summary>
/// <remarks>
/// <para>Used by GPS before 1987. For Transit satellite positioning see also WGS 72BE. Datum code 6323 reserved for southern hemisphere ProjCS's.</para>
/// <para>Area of use: World</para>
/// <para>Origin description: Developed from a worldwide distribution of terrestrial and
/// geodetic satellite observations and defined through a set of station coordinates.</para>
/// </remarks>
public static HorizontalDatum WGS72
{
get
{
var datum =
new HorizontalDatum(CoordinateSystems.Ellipsoid.WGS72,
null, DatumType.HD_Geocentric, "World Geodetic System 1972", "EPSG", 6322, string.Empty,
"Used by GPS before 1987. For Transit satellite positioning see also WGS 72BE. Datum code 6323 reserved for southern hemisphere ProjCS's.", string.Empty);
datum.Wgs84Parameters = new Wgs84ConversionInfo(0, 0, 4.5, 0, 0, 0.554, 0.219);
return datum;
}
}
/// <summary>
/// European Terrestrial Reference System 1989
/// </summary>
/// <remarks>
/// <para>Area of use:
/// Europe: Albania; Andorra; Austria; Belgium; Bosnia and Herzegovina; Bulgaria; Croatia;
/// Cyprus; Czech Republic; Denmark; Estonia; Finland; Faroe Islands; France; Germany; Greece;
/// Hungary; Ireland; Italy; Latvia; Liechtenstein; Lithuania; Luxembourg; Malta; Netherlands;
/// Norway; Poland; Portugal; Romania; San Marino; Serbia and Montenegro; Slovakia; Slovenia;
/// Spain; Svalbard; Sweden; Switzerland; United Kingdom (UK) including Channel Islands and
/// Isle of Man; Vatican City State.</para>
/// <para>Origin description: Fixed to the stable part of the Eurasian continental
/// plate and consistent with ITRS at the epoch 1989.0.</para>
/// </remarks>
public static HorizontalDatum ETRF89
{
get
{
var datum = new HorizontalDatum(CoordinateSystems.Ellipsoid.GRS80, null, DatumType.HD_Geocentric,
"European Terrestrial Reference System 1989", "EPSG", 6258, "ETRF89", "The distinction in usage between ETRF89 and ETRS89 is confused: although in principle conceptually different in practice both are used for the realisation.", string.Empty);
datum.Wgs84Parameters = new Wgs84ConversionInfo();
return datum;
}
}
/// <summary>
/// European Datum 1950
/// </summary>
/// <remarks>
/// <para>Area of use:
/// Europe - west - Denmark; Faroe Islands; France offshore; Israel offshore; Italy including San
/// Marino and Vatican City State; Ireland offshore; Netherlands offshore; Germany; Greece (offshore);
/// North Sea; Norway; Spain; Svalbard; Turkey; United Kingdom UKCS offshore. Egypt - Western Desert.
/// </para>
/// <para>Origin description: Fundamental point: Potsdam (Helmert Tower).
/// Latitude: 52 deg 22 min 51.4456 sec N; Longitude: 13 deg 3 min 58.9283 sec E (of Greenwich).</para>
/// </remarks>
public static HorizontalDatum ED50
{
get
{
return new HorizontalDatum(CoordinateSystems.Ellipsoid.International1924, new Wgs84ConversionInfo(-87, -98, -121, 0, 0, 0, 0), DatumType.HD_Geocentric,
"European Datum 1950", "EPSG", 6230, "ED50", string.Empty, string.Empty);
}
}
#endregion
#region IHorizontalDatum Members
/// <summary>
/// Gets or sets the ellipsoid of the datum
/// </summary>
public Ellipsoid Ellipsoid { get; set; }
/// <summary>
/// Gets preferred parameters for a Bursa Wolf transformation into WGS84
/// </summary>
public Wgs84ConversionInfo Wgs84Parameters { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat("DATUM[\"{0}\", {1}", Name, Ellipsoid.WKT);
if (Wgs84Parameters != null)
sb.AppendFormat(", {0}", Wgs84Parameters.WKT);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
return string.Format(CultureInfo.InvariantCulture.NumberFormat,
"<CS_HorizontalDatum DatumType=\"{0}\">{1}{2}{3}</CS_HorizontalDatum>",
(int)DatumType, InfoXml, Ellipsoid.XML, (Wgs84Parameters == null ? string.Empty : Wgs84Parameters.XML));
}
}
#endregion
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is HorizontalDatum))
return false;
var datum = obj as HorizontalDatum;
if (datum.Wgs84Parameters == null && this.Wgs84Parameters != null) return false;
if (datum.Wgs84Parameters != null && !datum.Wgs84Parameters.Equals(this.Wgs84Parameters))
return false;
return (datum != null && this.Ellipsoid != null &&
datum.Ellipsoid.EqualParams(this.Ellipsoid) || datum == null && this.Ellipsoid == null) && this.DatumType == datum.DatumType;
}
}
}

Просмотреть файл

@ -1,186 +1,186 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// The Info object defines the standard information
/// stored with spatial reference objects
/// </summary>
[Serializable]
public abstract class Info : IInfo
{
/// <summary>
/// A base interface for metadata applicable to coordinate system objects.
/// </summary>
/// <remarks>
/// <para>The metadata items Abbreviation, Alias, Authority, AuthorityCode, Name and Remarks
/// were specified in the Simple Features interfaces, so they have been kept here.</para>
/// <para>This specification does not dictate what the contents of these items
/// should be. However, the following guidelines are suggested:</para>
/// <para>When <see cref="ICoordinateSystemAuthorityFactory"/> is used to create an object, the Authority
/// and 'AuthorityCode' values should be set to the authority name of the factory object, and the authority
/// code supplied by the client, respectively. The other values may or may not be set. (If the authority is
/// EPSG, the implementer may consider using the corresponding metadata values in the EPSG tables.)</para>
/// <para>When <see cref="CoordinateSystemFactory"/> creates an object, the 'Name' should be set to the value
/// supplied by the client. All of the other metadata items should be left empty</para>
/// </remarks>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal Info(
string name,
string authority,
long code,
string alias,
string abbreviation,
string remarks)
{
_Name = name;
_Authority = authority;
_Code = code;
_Alias = alias;
_Abbreviation = abbreviation;
_Remarks = remarks;
}
#region ISpatialReferenceInfo Members
private string _Name;
/// <summary>
/// Gets or sets the name of the object.
/// </summary>
public string Name
{
get { return _Name; }
set { _Name = value; }
}
private string _Authority;
/// <summary>
/// Gets or sets the authority name for this object, e.g., "EPSG",
/// is this is a standard object with an authority specific
/// identity code. Returns "CUSTOM" if this is a custom object.
/// </summary>
public string Authority
{
get { return _Authority; }
set { _Authority = value; }
}
private long _Code;
/// <summary>
/// Gets or sets the authority specific identification code of the object
/// </summary>
public long AuthorityCode
{
get { return _Code; }
set { _Code = value; }
}
private string _Alias;
/// <summary>
/// Gets or sets the alias of the object.
/// </summary>
public string Alias
{
get { return _Alias; }
set { _Alias = value; }
}
private string _Abbreviation;
/// <summary>
/// Gets or sets the abbreviation of the object.
/// </summary>
public string Abbreviation
{
get { return _Abbreviation; }
set { _Abbreviation = value; }
}
private string _Remarks;
/// <summary>
/// Gets or sets the provider-supplied remarks for the object.
/// </summary>
public string Remarks
{
get { return _Remarks; }
set { _Remarks = value; }
}
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string ToString()
{
return WKT;
}
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public abstract string WKT {get ;}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
public abstract string XML { get; }
/// <summary>
/// Returns an XML string of the info object
/// </summary>
internal string InfoXml
{
get
{
var sb = new StringBuilder();
sb.AppendFormat("<CS_Info");
if(AuthorityCode>0) sb.AppendFormat(" AuthorityCode=\"{0}\"",AuthorityCode);
if (!string.IsNullOrWhiteSpace(Abbreviation)) sb.AppendFormat(" Abbreviation=\"{0}\"", Abbreviation);
if (!string.IsNullOrWhiteSpace(Authority)) sb.AppendFormat(" Authority=\"{0}\"", Authority);
if (!string.IsNullOrWhiteSpace(Name)) sb.AppendFormat(" Name=\"{0}\"", Name);
sb.Append("/>");
return sb.ToString();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public abstract bool EqualParams(object obj);
#endregion
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// The Info object defines the standard information
/// stored with spatial reference objects
/// </summary>
[Serializable]
public abstract class Info : IInfo
{
/// <summary>
/// A base interface for metadata applicable to coordinate system objects.
/// </summary>
/// <remarks>
/// <para>The metadata items Abbreviation, Alias, Authority, AuthorityCode, Name and Remarks
/// were specified in the Simple Features interfaces, so they have been kept here.</para>
/// <para>This specification does not dictate what the contents of these items
/// should be. However, the following guidelines are suggested:</para>
/// <para>When <see cref="ICoordinateSystemAuthorityFactory"/> is used to create an object, the Authority
/// and 'AuthorityCode' values should be set to the authority name of the factory object, and the authority
/// code supplied by the client, respectively. The other values may or may not be set. (If the authority is
/// EPSG, the implementer may consider using the corresponding metadata values in the EPSG tables.)</para>
/// <para>When <see cref="CoordinateSystemFactory"/> creates an object, the 'Name' should be set to the value
/// supplied by the client. All of the other metadata items should be left empty</para>
/// </remarks>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal Info(
string name,
string authority,
long code,
string alias,
string abbreviation,
string remarks)
{
_Name = name;
_Authority = authority;
_Code = code;
_Alias = alias;
_Abbreviation = abbreviation;
_Remarks = remarks;
}
#region ISpatialReferenceInfo Members
private string _Name;
/// <summary>
/// Gets or sets the name of the object.
/// </summary>
public string Name
{
get { return _Name; }
set { _Name = value; }
}
private string _Authority;
/// <summary>
/// Gets or sets the authority name for this object, e.g., "EPSG",
/// is this is a standard object with an authority specific
/// identity code. Returns "CUSTOM" if this is a custom object.
/// </summary>
public string Authority
{
get { return _Authority; }
set { _Authority = value; }
}
private long _Code;
/// <summary>
/// Gets or sets the authority specific identification code of the object
/// </summary>
public long AuthorityCode
{
get { return _Code; }
set { _Code = value; }
}
private string _Alias;
/// <summary>
/// Gets or sets the alias of the object.
/// </summary>
public string Alias
{
get { return _Alias; }
set { _Alias = value; }
}
private string _Abbreviation;
/// <summary>
/// Gets or sets the abbreviation of the object.
/// </summary>
public string Abbreviation
{
get { return _Abbreviation; }
set { _Abbreviation = value; }
}
private string _Remarks;
/// <summary>
/// Gets or sets the provider-supplied remarks for the object.
/// </summary>
public string Remarks
{
get { return _Remarks; }
set { _Remarks = value; }
}
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string ToString()
{
return WKT;
}
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public abstract string WKT {get ;}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
public abstract string XML { get; }
/// <summary>
/// Returns an XML string of the info object
/// </summary>
internal string InfoXml
{
get
{
var sb = new StringBuilder();
sb.AppendFormat("<CS_Info");
if(AuthorityCode>0) sb.AppendFormat(" AuthorityCode=\"{0}\"",AuthorityCode);
if (!string.IsNullOrWhiteSpace(Abbreviation)) sb.AppendFormat(" Abbreviation=\"{0}\"", Abbreviation);
if (!string.IsNullOrWhiteSpace(Authority)) sb.AppendFormat(" Authority=\"{0}\"", Authority);
if (!string.IsNullOrWhiteSpace(Name)) sb.AppendFormat(" Name=\"{0}\"", Name);
sb.Append("/>");
return sb.ToString();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public abstract bool EqualParams(object obj);
#endregion
}
}

Просмотреть файл

@ -1,143 +1,143 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Definition of linear units.
/// </summary>
[Serializable]
public class LinearUnit : Info, IUnit
{
/// <summary>
/// Creates an instance of a linear unit
/// </summary>
/// <param name="metersPerUnit">Number of meters per <see cref="LinearUnit" /></param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="authorityCode">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
public LinearUnit(double metersPerUnit, string name, string authority, long authorityCode, string alias, string abbreviation, string remarks)
:
base(name, authority, authorityCode, alias, abbreviation, remarks)
{
MetersPerUnit = metersPerUnit;
}
#region Predefined units
/// <summary>
/// Returns the meters linear unit.
/// Also known as International metre. SI standard unit.
/// </summary>
public static LinearUnit Metre
{
get { return new LinearUnit(1.0,"metre", "EPSG", 9001, "m", string.Empty, "Also known as International metre. SI standard unit."); }
}
/// <summary>
/// Returns the foot linear unit (1ft = 0.3048m).
/// </summary>
public static LinearUnit Foot
{
get { return new LinearUnit(0.3048, "foot", "EPSG", 9002, "ft", string.Empty, string.Empty); }
}
/// <summary>
/// Returns the US Survey foot linear unit (1ftUS = 0.304800609601219m).
/// </summary>
public static LinearUnit USSurveyFoot
{
get { return new LinearUnit(0.304800609601219, "US survey foot", "EPSG", 9003, "American foot", "ftUS", "Used in USA."); }
}
/// <summary>
/// Returns the Nautical Mile linear unit (1NM = 1852m).
/// </summary>
public static LinearUnit NauticalMile
{
get { return new LinearUnit(1852, "nautical mile", "EPSG", 9030, "NM", string.Empty, string.Empty); }
}
/// <summary>
/// Returns Clarke's foot.
/// </summary>
/// <remarks>
/// Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre.
/// Used in older Australian, southern African &amp; British West Indian mapping.
/// </remarks>
public static LinearUnit ClarkesFoot
{
get { return new LinearUnit(0.3047972654, "Clarke's foot", "EPSG", 9005, "Clarke's foot", string.Empty, "Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre. Used in older Australian, southern African & British West Indian mapping."); }
}
#endregion
#region ILinearUnit Members
/// <summary>
/// Gets or sets the number of meters per <see cref="LinearUnit"/>.
/// </summary>
public double MetersPerUnit { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat, "UNIT[\"{0}\", {1}", Name, MetersPerUnit);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
return string.Format(CultureInfo.InvariantCulture.NumberFormat, "<CS_LinearUnit MetersPerUnit=\"{0}\">{1}</CS_LinearUnit>", MetersPerUnit, InfoXml);
}
}
#endregion
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is LinearUnit))
return false;
return (obj as LinearUnit).MetersPerUnit == this.MetersPerUnit;
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Definition of linear units.
/// </summary>
[Serializable]
public class LinearUnit : Info, IUnit
{
/// <summary>
/// Creates an instance of a linear unit
/// </summary>
/// <param name="metersPerUnit">Number of meters per <see cref="LinearUnit" /></param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="authorityCode">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
public LinearUnit(double metersPerUnit, string name, string authority, long authorityCode, string alias, string abbreviation, string remarks)
:
base(name, authority, authorityCode, alias, abbreviation, remarks)
{
MetersPerUnit = metersPerUnit;
}
#region Predefined units
/// <summary>
/// Returns the meters linear unit.
/// Also known as International metre. SI standard unit.
/// </summary>
public static LinearUnit Metre
{
get { return new LinearUnit(1.0,"metre", "EPSG", 9001, "m", string.Empty, "Also known as International metre. SI standard unit."); }
}
/// <summary>
/// Returns the foot linear unit (1ft = 0.3048m).
/// </summary>
public static LinearUnit Foot
{
get { return new LinearUnit(0.3048, "foot", "EPSG", 9002, "ft", string.Empty, string.Empty); }
}
/// <summary>
/// Returns the US Survey foot linear unit (1ftUS = 0.304800609601219m).
/// </summary>
public static LinearUnit USSurveyFoot
{
get { return new LinearUnit(0.304800609601219, "US survey foot", "EPSG", 9003, "American foot", "ftUS", "Used in USA."); }
}
/// <summary>
/// Returns the Nautical Mile linear unit (1NM = 1852m).
/// </summary>
public static LinearUnit NauticalMile
{
get { return new LinearUnit(1852, "nautical mile", "EPSG", 9030, "NM", string.Empty, string.Empty); }
}
/// <summary>
/// Returns Clarke's foot.
/// </summary>
/// <remarks>
/// Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre.
/// Used in older Australian, southern African &amp; British West Indian mapping.
/// </remarks>
public static LinearUnit ClarkesFoot
{
get { return new LinearUnit(0.3047972654, "Clarke's foot", "EPSG", 9005, "Clarke's foot", string.Empty, "Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre. Used in older Australian, southern African & British West Indian mapping."); }
}
#endregion
#region ILinearUnit Members
/// <summary>
/// Gets or sets the number of meters per <see cref="LinearUnit"/>.
/// </summary>
public double MetersPerUnit { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat, "UNIT[\"{0}\", {1}", Name, MetersPerUnit);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
return string.Format(CultureInfo.InvariantCulture.NumberFormat, "<CS_LinearUnit MetersPerUnit=\"{0}\">{1}</CS_LinearUnit>", MetersPerUnit, InfoXml);
}
}
#endregion
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is LinearUnit))
return false;
return (obj as LinearUnit).MetersPerUnit == this.MetersPerUnit;
}
}
}

Просмотреть файл

@ -1,85 +1,85 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Simple class that implements the IParameterInfo interface for providing general set of the parameters.
/// It allows discovering the names, and for setting and getting parameter values.
/// </summary>
[Serializable]
internal class ParameterInfo
{
/// <summary>
/// Gets the number of parameters expected.
/// </summary>
public int NumParameters
{
get
{
if (Parameters != null)
{
return Parameters.Count;
}
return 0;
}
}
/// <summary>
/// Gets or sets the parameters set for this projection.
/// </summary>
public List<Parameter> Parameters
{
get;
set;
}
/// <summary>
/// Returns the default parameters for this projection.
/// </summary>
/// <returns></returns>
public Parameter[] DefaultParameters ()
{
return new Parameter[0];
}
/// <summary>
/// Gets the parameter by its name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public Parameter GetParameterByName (string name)
{
if (Parameters != null)
{
//search parameter collection by name
foreach (var param in Parameters)
{
if (param != null && param.Name == name)
{
return param;
}
}
}
return null;
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Simple class that implements the IParameterInfo interface for providing general set of the parameters.
/// It allows discovering the names, and for setting and getting parameter values.
/// </summary>
[Serializable]
internal class ParameterInfo
{
/// <summary>
/// Gets the number of parameters expected.
/// </summary>
public int NumParameters
{
get
{
if (Parameters != null)
{
return Parameters.Count;
}
return 0;
}
}
/// <summary>
/// Gets or sets the parameters set for this projection.
/// </summary>
public List<Parameter> Parameters
{
get;
set;
}
/// <summary>
/// Returns the default parameters for this projection.
/// </summary>
/// <returns></returns>
public Parameter[] DefaultParameters ()
{
return new Parameter[0];
}
/// <summary>
/// Gets the parameter by its name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public Parameter GetParameterByName (string name)
{
if (Parameters != null)
{
//search parameter collection by name
foreach (var param in Parameters)
{
if (param != null && param.Name == name)
{
return param;
}
}
}
return null;
}
}
}

Просмотреть файл

@ -1,207 +1,207 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A meridian used to take longitude measurements from.
/// </summary>
[Serializable]
public class PrimeMeridian : Info
{
/// <summary>
/// Initializes a new instance of a prime meridian
/// </summary>
/// <param name="longitude">Longitude of prime meridian</param>
/// <param name="angularUnit">Angular unit</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="authorityCode">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal PrimeMeridian(double longitude, AngularUnit angularUnit, string name, string authority, long authorityCode, string alias, string abbreviation, string remarks)
:
base(name, authority, authorityCode, alias, abbreviation, remarks)
{
Longitude = longitude;
AngularUnit = angularUnit;
}
#region Predefined prime meridans
/// <summary>
/// Greenwich prime meridian
/// </summary>
public static PrimeMeridian Greenwich
{
get { return new PrimeMeridian(0.0, CoordinateSystems.AngularUnit.Degrees, "Greenwich", "EPSG", 8901, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Lisbon prime meridian
/// </summary>
public static PrimeMeridian Lisbon
{
get { return new PrimeMeridian(-9.0754862, CoordinateSystems.AngularUnit.Degrees, "Lisbon", "EPSG", 8902, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Paris prime meridian.
/// Value adopted by IGN (Paris) in 1936. Equivalent to 2 deg 20min 14.025sec. Preferred by EPSG to earlier value of 2deg 20min 13.95sec (2.596898 grads) used by RGS London.
/// </summary>
public static PrimeMeridian Paris
{
get { return new PrimeMeridian(2.5969213, CoordinateSystems.AngularUnit.Degrees, "Paris", "EPSG", 8903, string.Empty, string.Empty, "Value adopted by IGN (Paris) in 1936. Equivalent to 2 deg 20min 14.025sec. Preferred by EPSG to earlier value of 2deg 20min 13.95sec (2.596898 grads) used by RGS London."); }
}
/// <summary>
/// Bogota prime meridian
/// </summary>
public static PrimeMeridian Bogota
{
get { return new PrimeMeridian(-74.04513, CoordinateSystems.AngularUnit.Degrees, "Bogota", "EPSG", 8904, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Madrid prime meridian
/// </summary>
public static PrimeMeridian Madrid
{
get { return new PrimeMeridian(-3.411658, CoordinateSystems.AngularUnit.Degrees, "Madrid", "EPSG", 8905, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Rome prime meridian
/// </summary>
public static PrimeMeridian Rome
{
get { return new PrimeMeridian(12.27084, CoordinateSystems.AngularUnit.Degrees, "Rome", "EPSG", 8906, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Bern prime meridian.
/// 1895 value. Newer value of 7 deg 26 min 22.335 sec E determined in 1938.
/// </summary>
public static PrimeMeridian Bern
{
get { return new PrimeMeridian(7.26225, CoordinateSystems.AngularUnit.Degrees, "Bern", "EPSG", 8907, string.Empty, string.Empty, "1895 value. Newer value of 7 deg 26 min 22.335 sec E determined in 1938."); }
}
/// <summary>
/// Jakarta prime meridian
/// </summary>
public static PrimeMeridian Jakarta
{
get { return new PrimeMeridian(106.482779, CoordinateSystems.AngularUnit.Degrees, "Jakarta", "EPSG", 8908, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Ferro prime meridian.
/// Used in Austria and former Czechoslovakia.
/// </summary>
public static PrimeMeridian Ferro
{
get { return new PrimeMeridian(-17.66666666666667, CoordinateSystems.AngularUnit.Degrees, "Ferro", "EPSG", 8909, string.Empty, string.Empty, "Used in Austria and former Czechoslovakia."); }
}
/// <summary>
/// Brussels prime meridian
/// </summary>
public static PrimeMeridian Brussels
{
get { return new PrimeMeridian(4.220471, CoordinateSystems.AngularUnit.Degrees, "Brussels", "EPSG", 8910, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Stockholm prime meridian
/// </summary>
public static PrimeMeridian Stockholm
{
get { return new PrimeMeridian(18.03298, CoordinateSystems.AngularUnit.Degrees, "Stockholm", "EPSG", 8911, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Athens prime meridian.
/// Used in Greece for older mapping based on Hatt projection.
/// </summary>
public static PrimeMeridian Athens
{
get { return new PrimeMeridian(23.4258815, CoordinateSystems.AngularUnit.Degrees, "Athens", "EPSG", 8912, string.Empty, string.Empty, "Used in Greece for older mapping based on Hatt projection."); }
}
/// <summary>
/// Oslo prime meridian.
/// Formerly known as Kristiania or Christiania.
/// </summary>
public static PrimeMeridian Oslo
{
get { return new PrimeMeridian(10.43225, CoordinateSystems.AngularUnit.Degrees, "Oslo", "EPSG", 8913, string.Empty, string.Empty, "Formerly known as Kristiania or Christiania."); }
}
#endregion
#region IPrimeMeridian Members
/// <summary>
/// Gets or sets the longitude of the prime meridian (relative to the Greenwich prime meridian).
/// </summary>
public double Longitude { get; set; }
/// <summary>
/// Gets or sets the AngularUnits.
/// </summary>
public AngularUnit AngularUnit { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat, "PRIMEM[\"{0}\", {1}", Name, Longitude);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
return string.Format(CultureInfo.InvariantCulture.NumberFormat,
"<CS_PrimeMeridian Longitude=\"{0}\" >{1}{2}</CS_PrimeMeridian>", Longitude, InfoXml, AngularUnit.XML);
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is PrimeMeridian))
return false;
var prime = obj as PrimeMeridian;
return prime.AngularUnit.EqualParams(this.AngularUnit) && prime.Longitude == this.Longitude;
}
#endregion
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A meridian used to take longitude measurements from.
/// </summary>
[Serializable]
public class PrimeMeridian : Info
{
/// <summary>
/// Initializes a new instance of a prime meridian
/// </summary>
/// <param name="longitude">Longitude of prime meridian</param>
/// <param name="angularUnit">Angular unit</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="authorityCode">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal PrimeMeridian(double longitude, AngularUnit angularUnit, string name, string authority, long authorityCode, string alias, string abbreviation, string remarks)
:
base(name, authority, authorityCode, alias, abbreviation, remarks)
{
Longitude = longitude;
AngularUnit = angularUnit;
}
#region Predefined prime meridans
/// <summary>
/// Greenwich prime meridian
/// </summary>
public static PrimeMeridian Greenwich
{
get { return new PrimeMeridian(0.0, CoordinateSystems.AngularUnit.Degrees, "Greenwich", "EPSG", 8901, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Lisbon prime meridian
/// </summary>
public static PrimeMeridian Lisbon
{
get { return new PrimeMeridian(-9.0754862, CoordinateSystems.AngularUnit.Degrees, "Lisbon", "EPSG", 8902, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Paris prime meridian.
/// Value adopted by IGN (Paris) in 1936. Equivalent to 2 deg 20min 14.025sec. Preferred by EPSG to earlier value of 2deg 20min 13.95sec (2.596898 grads) used by RGS London.
/// </summary>
public static PrimeMeridian Paris
{
get { return new PrimeMeridian(2.5969213, CoordinateSystems.AngularUnit.Degrees, "Paris", "EPSG", 8903, string.Empty, string.Empty, "Value adopted by IGN (Paris) in 1936. Equivalent to 2 deg 20min 14.025sec. Preferred by EPSG to earlier value of 2deg 20min 13.95sec (2.596898 grads) used by RGS London."); }
}
/// <summary>
/// Bogota prime meridian
/// </summary>
public static PrimeMeridian Bogota
{
get { return new PrimeMeridian(-74.04513, CoordinateSystems.AngularUnit.Degrees, "Bogota", "EPSG", 8904, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Madrid prime meridian
/// </summary>
public static PrimeMeridian Madrid
{
get { return new PrimeMeridian(-3.411658, CoordinateSystems.AngularUnit.Degrees, "Madrid", "EPSG", 8905, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Rome prime meridian
/// </summary>
public static PrimeMeridian Rome
{
get { return new PrimeMeridian(12.27084, CoordinateSystems.AngularUnit.Degrees, "Rome", "EPSG", 8906, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Bern prime meridian.
/// 1895 value. Newer value of 7 deg 26 min 22.335 sec E determined in 1938.
/// </summary>
public static PrimeMeridian Bern
{
get { return new PrimeMeridian(7.26225, CoordinateSystems.AngularUnit.Degrees, "Bern", "EPSG", 8907, string.Empty, string.Empty, "1895 value. Newer value of 7 deg 26 min 22.335 sec E determined in 1938."); }
}
/// <summary>
/// Jakarta prime meridian
/// </summary>
public static PrimeMeridian Jakarta
{
get { return new PrimeMeridian(106.482779, CoordinateSystems.AngularUnit.Degrees, "Jakarta", "EPSG", 8908, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Ferro prime meridian.
/// Used in Austria and former Czechoslovakia.
/// </summary>
public static PrimeMeridian Ferro
{
get { return new PrimeMeridian(-17.66666666666667, CoordinateSystems.AngularUnit.Degrees, "Ferro", "EPSG", 8909, string.Empty, string.Empty, "Used in Austria and former Czechoslovakia."); }
}
/// <summary>
/// Brussels prime meridian
/// </summary>
public static PrimeMeridian Brussels
{
get { return new PrimeMeridian(4.220471, CoordinateSystems.AngularUnit.Degrees, "Brussels", "EPSG", 8910, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Stockholm prime meridian
/// </summary>
public static PrimeMeridian Stockholm
{
get { return new PrimeMeridian(18.03298, CoordinateSystems.AngularUnit.Degrees, "Stockholm", "EPSG", 8911, string.Empty, string.Empty, string.Empty); }
}
/// <summary>
/// Athens prime meridian.
/// Used in Greece for older mapping based on Hatt projection.
/// </summary>
public static PrimeMeridian Athens
{
get { return new PrimeMeridian(23.4258815, CoordinateSystems.AngularUnit.Degrees, "Athens", "EPSG", 8912, string.Empty, string.Empty, "Used in Greece for older mapping based on Hatt projection."); }
}
/// <summary>
/// Oslo prime meridian.
/// Formerly known as Kristiania or Christiania.
/// </summary>
public static PrimeMeridian Oslo
{
get { return new PrimeMeridian(10.43225, CoordinateSystems.AngularUnit.Degrees, "Oslo", "EPSG", 8913, string.Empty, string.Empty, "Formerly known as Kristiania or Christiania."); }
}
#endregion
#region IPrimeMeridian Members
/// <summary>
/// Gets or sets the longitude of the prime meridian (relative to the Greenwich prime meridian).
/// </summary>
public double Longitude { get; set; }
/// <summary>
/// Gets or sets the AngularUnits.
/// </summary>
public AngularUnit AngularUnit { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat, "PRIMEM[\"{0}\", {1}", Name, Longitude);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
return string.Format(CultureInfo.InvariantCulture.NumberFormat,
"<CS_PrimeMeridian Longitude=\"{0}\" >{1}{2}</CS_PrimeMeridian>", Longitude, InfoXml, AngularUnit.XML);
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is PrimeMeridian))
return false;
var prime = obj as PrimeMeridian;
return prime.AngularUnit.EqualParams(this.AngularUnit) && prime.Longitude == this.Longitude;
}
#endregion
}
}

Просмотреть файл

@ -1,229 +1,229 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A 2D cartographic coordinate system.
/// </summary>
[Serializable]
public class ProjectedCoordinateSystem : HorizontalCoordinateSystem
{
/// <summary>
/// Initializes a new instance of a projected coordinate system
/// </summary>
/// <param name="datum">Horizontal datum</param>
/// <param name="geographicCoordinateSystem">Geographic coordinate system</param>
/// <param name="linearUnit">Linear unit</param>
/// <param name="projection">Projection</param>
/// <param name="axisInfo">Axis info</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal ProjectedCoordinateSystem(HorizontalDatum datum, GeographicCoordinateSystem geographicCoordinateSystem,
LinearUnit linearUnit, IProjection projection, List<AxisInfo> axisInfo,
string name, string authority, long code, string alias,
string remarks, string abbreviation)
: base(datum, axisInfo, name, authority, code, alias, abbreviation, remarks)
{
GeographicCoordinateSystem = geographicCoordinateSystem;
LinearUnit = linearUnit;
Projection = projection;
}
#region Predefined projected coordinate systems
/// <summary>
/// Universal Transverse Mercator - WGS84
/// </summary>
/// <param name="zone">UTM zone</param>
/// <param name="zoneIsNorth">true of Northern hemisphere, false if southern</param>
/// <returns>UTM/WGS84 coordsys</returns>
public static ProjectedCoordinateSystem WGS84_UTM(int zone, bool zoneIsNorth)
{
var pInfo = new List<ProjectionParameter>();
pInfo.Add(new ProjectionParameter("latitude_of_origin", 0));
pInfo.Add(new ProjectionParameter("central_meridian", zone * 6 - 183));
pInfo.Add(new ProjectionParameter("scale_factor", 0.9996));
pInfo.Add(new ProjectionParameter("false_easting", 500000));
pInfo.Add(new ProjectionParameter("false_northing", zoneIsNorth ? 0 : 10000000));
//IProjection projection = cFac.CreateProjection("UTM" + Zone.ToString() + (ZoneIsNorth ? "N" : "S"), "Transverse_Mercator", parameters);
var proj = new Projection("Transverse_Mercator", pInfo, "UTM" + zone.ToString(CultureInfo.InvariantCulture) + (zoneIsNorth ? "N" : "S"),
"EPSG", 32600 + zone + (zoneIsNorth ? 0 : 100), string.Empty, string.Empty, string.Empty);
var axes = new List<AxisInfo>
{
new AxisInfo("East", AxisOrientationEnum.East),
new AxisInfo("North", AxisOrientationEnum.North)
};
return new ProjectedCoordinateSystem(CoordinateSystems.HorizontalDatum.WGS84,
CoordinateSystems.GeographicCoordinateSystem.WGS84, CoordinateSystems.LinearUnit.Metre, proj, axes,
"WGS 84 / UTM zone " + zone.ToString(CultureInfo.InvariantCulture) + (zoneIsNorth ? "N" : "S"), "EPSG", 32600 + zone + (zoneIsNorth ? 0 : 100),
string.Empty, "Large and medium scale topographic mapping and engineering survey.", string.Empty);
}
/// <summary>
/// Gets a WebMercator coordinate reference system
/// </summary>
public static ProjectedCoordinateSystem WebMercator
{
get
{
var pInfo = new List<ProjectionParameter>
{
/*
new ProjectionParameter("semi_major", 6378137.0),
new ProjectionParameter("semi_minor", 6378137.0),
new ProjectionParameter("scale_factor", 1.0),
*/
new ProjectionParameter("latitude_of_origin", 0.0),
new ProjectionParameter("central_meridian", 0.0),
new ProjectionParameter("false_easting", 0.0),
new ProjectionParameter("false_northing", 0.0)
};
var proj = new Projection("Popular Visualisation Pseudo-Mercator", pInfo, "Popular Visualisation Pseudo-Mercator", "EPSG", 3856,
"Pseudo-Mercator", string.Empty, string.Empty);
var axes = new List<AxisInfo>
{
new AxisInfo("East", AxisOrientationEnum.East),
new AxisInfo("North", AxisOrientationEnum.North)
};
return new ProjectedCoordinateSystem(CoordinateSystems.HorizontalDatum.WGS84,
CoordinateSystems.GeographicCoordinateSystem.WGS84, CoordinateSystems.LinearUnit.Metre, proj, axes,
"WGS 84 / Pseudo-Mercator", "EPSG", 3857, "WGS 84 / Popular Visualisation Pseudo-Mercator",
"Certain Web mapping and visualisation applications." +
"Uses spherical development of ellipsoidal coordinates. Relative to an ellipsoidal development errors of up to 800 metres in position and 0.7 percent in scale may arise. It is not a recognised geodetic system: see WGS 84 / World Mercator (CRS code 3395).",
"WebMercator");
}
}
/// <summary>
/// Gets or sets the GeographicCoordinateSystem.
/// </summary>
public GeographicCoordinateSystem GeographicCoordinateSystem { get; set; }
/// <summary>
/// Gets or sets the <see cref="LinearUnit">LinearUnits</see>. The linear unit must be the same as the <see cref="CoordinateSystem"/> units.
/// </summary>
public LinearUnit LinearUnit { get; set; }
/// <summary>
/// Gets units for dimension within coordinate system. Each dimension in
/// the coordinate system has corresponding units.
/// </summary>
/// <param name="dimension">Dimension</param>
/// <returns>Unit</returns>
public override IUnit GetUnits(int dimension)
{
return LinearUnit;
}
/// <summary>
/// Gets or sets the projection
/// </summary>
public IProjection Projection { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat("PROJCS[\"{0}\", {1}, {2}, {3}", Name, GeographicCoordinateSystem.WKT, LinearUnit.WKT, Projection.WKT);
for(int i=0;i<Projection.NumParameters;i++)
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat, ", {0}", Projection.GetParameter(i).WKT);
//sb.AppendFormat(", {0}", LinearUnit.WKT);
//Skip authority and code if not defined
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
//Skip axis info if they contain default values
if (AxisInfo.Count != 2 ||
AxisInfo[0].Name != "X" || AxisInfo[0].Orientation != AxisOrientationEnum.East ||
AxisInfo[1].Name != "Y" || AxisInfo[1].Orientation != AxisOrientationEnum.North)
for (int i = 0; i < AxisInfo.Count; i++)
sb.AppendFormat(", {0}", GetAxis(i).WKT);
//if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
// sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
public override string XML
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat,
"<CS_CoordinateSystem Dimension=\"{0}\"><CS_ProjectedCoordinateSystem>{1}",
Dimension, InfoXml);
foreach (var ai in AxisInfo)
sb.Append(ai.XML);
sb.AppendFormat("{0}{1}{2}</CS_ProjectedCoordinateSystem></CS_CoordinateSystem>",
GeographicCoordinateSystem.XML, LinearUnit.XML, Projection.XML);
return sb.ToString();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is ProjectedCoordinateSystem pcs))
return false;
if (pcs.Dimension != Dimension)
return false;
for (int i = 0; i < pcs.Dimension; i++)
{
if(pcs.GetAxis(i).Orientation != GetAxis(i).Orientation)
return false;
if (!pcs.GetUnits(i).EqualParams(GetUnits(i)))
return false;
}
return pcs.GeographicCoordinateSystem.EqualParams(GeographicCoordinateSystem) &&
pcs.HorizontalDatum.EqualParams(HorizontalDatum) &&
pcs.LinearUnit.EqualParams(LinearUnit) &&
pcs.Projection.EqualParams(Projection);
}
#endregion
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// A 2D cartographic coordinate system.
/// </summary>
[Serializable]
public class ProjectedCoordinateSystem : HorizontalCoordinateSystem
{
/// <summary>
/// Initializes a new instance of a projected coordinate system
/// </summary>
/// <param name="datum">Horizontal datum</param>
/// <param name="geographicCoordinateSystem">Geographic coordinate system</param>
/// <param name="linearUnit">Linear unit</param>
/// <param name="projection">Projection</param>
/// <param name="axisInfo">Axis info</param>
/// <param name="name">Name</param>
/// <param name="authority">Authority name</param>
/// <param name="code">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal ProjectedCoordinateSystem(HorizontalDatum datum, GeographicCoordinateSystem geographicCoordinateSystem,
LinearUnit linearUnit, IProjection projection, List<AxisInfo> axisInfo,
string name, string authority, long code, string alias,
string remarks, string abbreviation)
: base(datum, axisInfo, name, authority, code, alias, abbreviation, remarks)
{
GeographicCoordinateSystem = geographicCoordinateSystem;
LinearUnit = linearUnit;
Projection = projection;
}
#region Predefined projected coordinate systems
/// <summary>
/// Universal Transverse Mercator - WGS84
/// </summary>
/// <param name="zone">UTM zone</param>
/// <param name="zoneIsNorth">true of Northern hemisphere, false if southern</param>
/// <returns>UTM/WGS84 coordsys</returns>
public static ProjectedCoordinateSystem WGS84_UTM(int zone, bool zoneIsNorth)
{
var pInfo = new List<ProjectionParameter>();
pInfo.Add(new ProjectionParameter("latitude_of_origin", 0));
pInfo.Add(new ProjectionParameter("central_meridian", zone * 6 - 183));
pInfo.Add(new ProjectionParameter("scale_factor", 0.9996));
pInfo.Add(new ProjectionParameter("false_easting", 500000));
pInfo.Add(new ProjectionParameter("false_northing", zoneIsNorth ? 0 : 10000000));
//IProjection projection = cFac.CreateProjection("UTM" + Zone.ToString() + (ZoneIsNorth ? "N" : "S"), "Transverse_Mercator", parameters);
var proj = new Projection("Transverse_Mercator", pInfo, "UTM" + zone.ToString(CultureInfo.InvariantCulture) + (zoneIsNorth ? "N" : "S"),
"EPSG", 32600 + zone + (zoneIsNorth ? 0 : 100), string.Empty, string.Empty, string.Empty);
var axes = new List<AxisInfo>
{
new AxisInfo("East", AxisOrientationEnum.East),
new AxisInfo("North", AxisOrientationEnum.North)
};
return new ProjectedCoordinateSystem(CoordinateSystems.HorizontalDatum.WGS84,
CoordinateSystems.GeographicCoordinateSystem.WGS84, CoordinateSystems.LinearUnit.Metre, proj, axes,
"WGS 84 / UTM zone " + zone.ToString(CultureInfo.InvariantCulture) + (zoneIsNorth ? "N" : "S"), "EPSG", 32600 + zone + (zoneIsNorth ? 0 : 100),
string.Empty, "Large and medium scale topographic mapping and engineering survey.", string.Empty);
}
/// <summary>
/// Gets a WebMercator coordinate reference system
/// </summary>
public static ProjectedCoordinateSystem WebMercator
{
get
{
var pInfo = new List<ProjectionParameter>
{
/*
new ProjectionParameter("semi_major", 6378137.0),
new ProjectionParameter("semi_minor", 6378137.0),
new ProjectionParameter("scale_factor", 1.0),
*/
new ProjectionParameter("latitude_of_origin", 0.0),
new ProjectionParameter("central_meridian", 0.0),
new ProjectionParameter("false_easting", 0.0),
new ProjectionParameter("false_northing", 0.0)
};
var proj = new Projection("Popular Visualisation Pseudo-Mercator", pInfo, "Popular Visualisation Pseudo-Mercator", "EPSG", 3856,
"Pseudo-Mercator", string.Empty, string.Empty);
var axes = new List<AxisInfo>
{
new AxisInfo("East", AxisOrientationEnum.East),
new AxisInfo("North", AxisOrientationEnum.North)
};
return new ProjectedCoordinateSystem(CoordinateSystems.HorizontalDatum.WGS84,
CoordinateSystems.GeographicCoordinateSystem.WGS84, CoordinateSystems.LinearUnit.Metre, proj, axes,
"WGS 84 / Pseudo-Mercator", "EPSG", 3857, "WGS 84 / Popular Visualisation Pseudo-Mercator",
"Certain Web mapping and visualisation applications." +
"Uses spherical development of ellipsoidal coordinates. Relative to an ellipsoidal development errors of up to 800 metres in position and 0.7 percent in scale may arise. It is not a recognised geodetic system: see WGS 84 / World Mercator (CRS code 3395).",
"WebMercator");
}
}
/// <summary>
/// Gets or sets the GeographicCoordinateSystem.
/// </summary>
public GeographicCoordinateSystem GeographicCoordinateSystem { get; set; }
/// <summary>
/// Gets or sets the <see cref="LinearUnit">LinearUnits</see>. The linear unit must be the same as the <see cref="CoordinateSystem"/> units.
/// </summary>
public LinearUnit LinearUnit { get; set; }
/// <summary>
/// Gets units for dimension within coordinate system. Each dimension in
/// the coordinate system has corresponding units.
/// </summary>
/// <param name="dimension">Dimension</param>
/// <returns>Unit</returns>
public override IUnit GetUnits(int dimension)
{
return LinearUnit;
}
/// <summary>
/// Gets or sets the projection
/// </summary>
public IProjection Projection { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat("PROJCS[\"{0}\", {1}, {2}, {3}", Name, GeographicCoordinateSystem.WKT, LinearUnit.WKT, Projection.WKT);
for(int i=0;i<Projection.NumParameters;i++)
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat, ", {0}", Projection.GetParameter(i).WKT);
//sb.AppendFormat(", {0}", LinearUnit.WKT);
//Skip authority and code if not defined
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
//Skip axis info if they contain default values
if (AxisInfo.Count != 2 ||
AxisInfo[0].Name != "X" || AxisInfo[0].Orientation != AxisOrientationEnum.East ||
AxisInfo[1].Name != "Y" || AxisInfo[1].Orientation != AxisOrientationEnum.North)
for (int i = 0; i < AxisInfo.Count; i++)
sb.AppendFormat(", {0}", GetAxis(i).WKT);
//if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
// sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
public override string XML
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat,
"<CS_CoordinateSystem Dimension=\"{0}\"><CS_ProjectedCoordinateSystem>{1}",
Dimension, InfoXml);
foreach (var ai in AxisInfo)
sb.Append(ai.XML);
sb.AppendFormat("{0}{1}{2}</CS_ProjectedCoordinateSystem></CS_CoordinateSystem>",
GeographicCoordinateSystem.XML, LinearUnit.XML, Projection.XML);
return sb.ToString();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is ProjectedCoordinateSystem pcs))
return false;
if (pcs.Dimension != Dimension)
return false;
for (int i = 0; i < pcs.Dimension; i++)
{
if(pcs.GetAxis(i).Orientation != GetAxis(i).Orientation)
return false;
if (!pcs.GetUnits(i).EqualParams(GetUnits(i)))
return false;
}
return pcs.GeographicCoordinateSystem.EqualParams(GeographicCoordinateSystem) &&
pcs.HorizontalDatum.EqualParams(HorizontalDatum) &&
pcs.LinearUnit.EqualParams(LinearUnit) &&
pcs.Projection.EqualParams(Projection);
}
#endregion
}
}

Просмотреть файл

@ -1,163 +1,163 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// The Projection class defines the standard information stored with a projection
/// objects. A projection object implements a coordinate transformation from a geographic
/// coordinate system to a projected coordinate system, given the ellipsoid for the
/// geographic coordinate system. It is expected that each coordinate transformation of
/// interest, e.g., Transverse Mercator, Lambert, will be implemented as a class of
/// type Projection, supporting the IProjection interface.
/// </summary>
[Serializable]
public class Projection : Info, IProjection
{
internal Projection(string className, List<ProjectionParameter> parameters,
string name, string authority, long code, string alias,
string remarks, string abbreviation)
: base(name, authority, code, alias, abbreviation, remarks)
{
_parameters = parameters;
_ClassName = className;
}
#region Predefined projections
#endregion
#region IProjection Members
/// <summary>
/// Gets the number of parameters of the projection.
/// </summary>
public int NumParameters
{
get { return _parameters.Count; }
}
private List<ProjectionParameter> _parameters;
/// <summary>
/// Gets or sets the parameters of the projection
/// </summary>
internal List<ProjectionParameter> Parameters
{
get { return _parameters; }
set { _parameters = value; }
}
/// <summary>
/// Gets an indexed parameter of the projection.
/// </summary>
/// <param name="index">Index of parameter</param>
/// <returns>n'th parameter</returns>
public ProjectionParameter GetParameter(int index)
{
return _parameters[index];
}
/// <summary>
/// Gets an named parameter of the projection.
/// </summary>
/// <remarks>The parameter name is case insensitive</remarks>
/// <param name="name">Name of parameter</param>
/// <returns>parameter or null if not found</returns>
public ProjectionParameter GetParameter(string name)
{
foreach (ProjectionParameter par in _parameters)
if (par.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
return par;
return null;
}
private string _ClassName;
/// <summary>
/// Gets the projection classification name (e.g. "Transverse_Mercator").
/// </summary>
public string ClassName
{
get { return _ClassName; }
}
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("PROJECTION[\"{0}\"", Name);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat, "<CS_Projection Classname=\"{0}\">{1}", ClassName, InfoXml);
foreach (ProjectionParameter param in Parameters)
sb.Append(param.XML);
sb.Append("</CS_Projection>");
return sb.ToString();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is Projection))
return false;
Projection proj = obj as Projection;
if (proj.NumParameters != this.NumParameters)
return false;
for (int i = 0; i < _parameters.Count; i++)
{
ProjectionParameter param = GetParameter(proj.GetParameter(i).Name);
if (param == null)
return false;
if (param.Value != proj.GetParameter(i).Value)
return false;
}
return true;
}
#endregion
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// The Projection class defines the standard information stored with a projection
/// objects. A projection object implements a coordinate transformation from a geographic
/// coordinate system to a projected coordinate system, given the ellipsoid for the
/// geographic coordinate system. It is expected that each coordinate transformation of
/// interest, e.g., Transverse Mercator, Lambert, will be implemented as a class of
/// type Projection, supporting the IProjection interface.
/// </summary>
[Serializable]
public class Projection : Info, IProjection
{
internal Projection(string className, List<ProjectionParameter> parameters,
string name, string authority, long code, string alias,
string remarks, string abbreviation)
: base(name, authority, code, alias, abbreviation, remarks)
{
_parameters = parameters;
_ClassName = className;
}
#region Predefined projections
#endregion
#region IProjection Members
/// <summary>
/// Gets the number of parameters of the projection.
/// </summary>
public int NumParameters
{
get { return _parameters.Count; }
}
private List<ProjectionParameter> _parameters;
/// <summary>
/// Gets or sets the parameters of the projection
/// </summary>
internal List<ProjectionParameter> Parameters
{
get { return _parameters; }
set { _parameters = value; }
}
/// <summary>
/// Gets an indexed parameter of the projection.
/// </summary>
/// <param name="index">Index of parameter</param>
/// <returns>n'th parameter</returns>
public ProjectionParameter GetParameter(int index)
{
return _parameters[index];
}
/// <summary>
/// Gets an named parameter of the projection.
/// </summary>
/// <remarks>The parameter name is case insensitive</remarks>
/// <param name="name">Name of parameter</param>
/// <returns>parameter or null if not found</returns>
public ProjectionParameter GetParameter(string name)
{
foreach (ProjectionParameter par in _parameters)
if (par.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
return par;
return null;
}
private string _ClassName;
/// <summary>
/// Gets the projection classification name (e.g. "Transverse_Mercator").
/// </summary>
public string ClassName
{
get { return _ClassName; }
}
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("PROJECTION[\"{0}\"", Name);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object
/// </summary>
public override string XML
{
get
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat, "<CS_Projection Classname=\"{0}\">{1}", ClassName, InfoXml);
foreach (ProjectionParameter param in Parameters)
sb.Append(param.XML);
sb.Append("</CS_Projection>");
return sb.ToString();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is Projection))
return false;
Projection proj = obj as Projection;
if (proj.NumParameters != this.NumParameters)
return false;
for (int i = 0; i < _parameters.Count; i++)
{
ProjectionParameter param = GetParameter(proj.GetParameter(i).Name);
if (param == null)
return false;
if (param.Value != proj.GetParameter(i).Value)
return false;
}
return true;
}
#endregion
}
}

Просмотреть файл

@ -1,243 +1,243 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// Implements the Albers projection.
/// </summary>
/// <remarks>
/// <para>Implements the Albers projection. The Albers projection is most commonly
/// used to project the United States of America. It gives the northern
/// border with Canada a curved appearance.</para>
///
/// <para>The <a href="http://www.geog.mcgill.ca/courses/geo201/mapproj/naaeana.gif">Albers Equal Area</a>
/// projection has the property that the area bounded
/// by any pair of parallels and meridians is exactly reproduced between the
/// image of those parallels and meridians in the projected domain, that is,
/// the projection preserves the correct area of the earth though distorts
/// direction, distance and shape somewhat.</para>
/// </remarks>
[Serializable]
internal class AlbersProjection : MapProjection
{
private readonly double _c; //constant c
private readonly double _ro0;
private readonly double _n;
#region Constructors
/// <summary>
/// Creates an instance of an Albers projection object.
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>latitude_of_false_origin</term><description>The latitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>longitude_of_false_origin</term><description>The longitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>latitude_of_1st_standard_parallel</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is nearest the pole. Scale is true along this parallel.</description></item>
/// <item><term>latitude_of_2nd_standard_parallel</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is furthest from the pole. Scale is true along this parallel.</description></item>
/// <item><term>easting_at_false_origin</term><description>The easting value assigned to the false origin.</description></item>
/// <item><term>northing_at_false_origin</term><description>The northing value assigned to the false origin.</description></item>
/// </list>
/// </remarks>
public AlbersProjection(IEnumerable<ProjectionParameter> parameters)
: this(parameters, null)
{
}
/// <summary>
/// Creates an instance of an Albers projection object.
/// </summary>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>latitude_of_center</term><description>The latitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>longitude_of_center</term><description>The longitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>standard_parallel_1</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is nearest the pole. Scale is true along this parallel.</description></item>
/// <item><term>standard_parallel_2</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is furthest from the pole. Scale is true along this parallel.</description></item>
/// <item><term>false_easting</term><description>The easting value assigned to the false origin.</description></item>
/// <item><term>false_northing</term><description>The northing value assigned to the false origin.</description></item>
/// </list>
/// </remarks>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <param name="inverse">Indicates whether the projection forward (meters to degrees or degrees to meters).</param>
protected AlbersProjection(IEnumerable<ProjectionParameter> parameters, AlbersProjection inverse)
: base(parameters, inverse)
{
Name = "Albers_Conic_Equal_Area";
double lat0 = lat_origin;
double lat1 = Degrees2Radians(_Parameters.GetParameterValue("standard_parallel_1"));
double lat2 = Degrees2Radians(_Parameters.GetParameterValue("standard_parallel_2"));
if (Math.Abs(lat1 + lat2) < double.Epsilon)
throw new ArgumentException("Equal latitudes for standard parallels on opposite sides of Equator.");
double alpha1 = alpha(lat1);
double alpha2 = alpha(lat2);
double m1 = Math.Cos(lat1) / Math.Sqrt(1 - _es * Math.Pow(Math.Sin(lat1), 2));
double m2 = Math.Cos(lat2) / Math.Sqrt(1 - _es * Math.Pow(Math.Sin(lat2), 2));
_n = (Math.Pow(m1, 2) - Math.Pow(m2, 2)) / (alpha2 - alpha1);
_c = Math.Pow(m1, 2) + (_n * alpha1);
_ro0 = Ro(alpha(lat0));
/*
double sin_p0 = Math.Sin(lat0);
double cos_p0 = Math.Cos(lat0);
double q0 = qsfnz(e, sin_p0, cos_p0);
double sin_p1 = Math.Sin(lat1);
double cos_p1 = Math.Cos(lat1);
double m1 = msfnz(e,sin_p1,cos_p1);
double q1 = qsfnz(e,sin_p1,cos_p1);
double sin_p2 = Math.Sin(lat2);
double cos_p2 = Math.Cos(lat2);
double m2 = msfnz(e,sin_p2,cos_p2);
double q2 = qsfnz(e,sin_p2,cos_p2);
if (Math.Abs(lat1 - lat2) > EPSLN)
ns0 = (m1 * m1 - m2 * m2)/ (q2 - q1);
else
ns0 = sin_p1;
C = m1 * m1 + ns0 * q1;
rh = this._semiMajor * Math.Sqrt(C - ns0 * q0)/ns0;
*/
}
#endregion
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
#region Public methods
/// <summary>
/// Converts coordinates in decimal degrees to projected meters.
/// </summary>
/// <param name="lon">The longitude of the point in radians when entering, its x-ordinate in meters after exit.</param>
/// <param name="lat">The latitude of the point in radians when entering, its y-in ordinate meters after exit.</param>
protected sealed override void RadiansToMeters(ref double lon, ref double lat)
{
double a = alpha(lat);
double ro = Ro(a);
double theta = _n * (lon - central_meridian);
lon = ro * Math.Sin(theta);
lat = _ro0 - ro * Math.Cos(theta);
}
/// <summary>
/// Converts coordinates in projected meters to decimal degrees.
/// </summary>
/// <param name="x">The x-ordinate of the point in meters when entering, its longitude in radians after exit.</param>
/// <param name="y">The y-ordinate of the point in meters when entering, its latitude in radians after exit.</param>
protected sealed override void MetersToRadians(ref double x, ref double y)
{
double theta = Math.Atan(x / (_ro0 - y));
double ro = Math.Sqrt(Math.Pow(x, 2) + Math.Pow(_ro0 - y, 2));
double q = (_c - Math.Pow(ro, 2) * Math.Pow(_n, 2) / Math.Pow(_semiMajor, 2)) / _n;
//double b = Math.Sin(q / (1 - ((1 - _es) / (2 * _e)) * Math.Log((1 - _e) / (1 + _e))));
double lat = Math.Asin(q * 0.5);
double preLat = double.MaxValue;
int iterationCounter = 0;
while (Math.Abs(lat - preLat) > 0.000001)
{
preLat = lat;
double sin = Math.Sin(lat);
double e2sin2 = _es * Math.Pow(sin, 2);
lat += Math.Pow(1 - e2sin2, 2) / (2 * Math.Cos(lat)) *
(q / (1 - _es) - sin / (1 - e2sin2) +
1 / (2 * _e) * Math.Log((1 - _e * sin) / (1 + _e * sin)));
iterationCounter++;
if (iterationCounter > 25)
throw new ArgumentException(
"Transformation failed to converge in Albers backwards transformation");
}
x = central_meridian + (theta / _n);
y = lat;
}
/// <summary>
/// Returns the inverse of this projection.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current projection.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
_inverse = new AlbersProjection(_Parameters.ToProjectionParameter(), this);
return _inverse;
}
#endregion
#region Math helper functions
//private double ToAuthalic(double lat)
//{
// return Math.Atan(Q(lat) / Q(Math.PI * 0.5));
//}
//private double Q(double angle)
//{
// double sin = Math.Sin(angle);
// double esin = e * sin;
// return Math.Abs(sin / (1 - Math.Pow(esin, 2)) - 0.5 * e) * Math.Log((1 - esin) / (1 + esin)));
//}
private double alpha(double lat)
{
double sin = Math.Sin(lat);
double sinsq = Math.Pow(sin, 2);
return (1 - _es) * (((sin / (1 - _es * sinsq)) - 1 / (2 * _e) * Math.Log((1 - _e * sin) / (1 + _e * sin))));
}
private double Ro(double a)
{
return _semiMajor * Math.Sqrt((_c - _n * a)) / _n;
}
#endregion
}
}
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// Implements the Albers projection.
/// </summary>
/// <remarks>
/// <para>Implements the Albers projection. The Albers projection is most commonly
/// used to project the United States of America. It gives the northern
/// border with Canada a curved appearance.</para>
///
/// <para>The <a href="http://www.geog.mcgill.ca/courses/geo201/mapproj/naaeana.gif">Albers Equal Area</a>
/// projection has the property that the area bounded
/// by any pair of parallels and meridians is exactly reproduced between the
/// image of those parallels and meridians in the projected domain, that is,
/// the projection preserves the correct area of the earth though distorts
/// direction, distance and shape somewhat.</para>
/// </remarks>
[Serializable]
internal class AlbersProjection : MapProjection
{
private readonly double _c; //constant c
private readonly double _ro0;
private readonly double _n;
#region Constructors
/// <summary>
/// Creates an instance of an Albers projection object.
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>latitude_of_false_origin</term><description>The latitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>longitude_of_false_origin</term><description>The longitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>latitude_of_1st_standard_parallel</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is nearest the pole. Scale is true along this parallel.</description></item>
/// <item><term>latitude_of_2nd_standard_parallel</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is furthest from the pole. Scale is true along this parallel.</description></item>
/// <item><term>easting_at_false_origin</term><description>The easting value assigned to the false origin.</description></item>
/// <item><term>northing_at_false_origin</term><description>The northing value assigned to the false origin.</description></item>
/// </list>
/// </remarks>
public AlbersProjection(IEnumerable<ProjectionParameter> parameters)
: this(parameters, null)
{
}
/// <summary>
/// Creates an instance of an Albers projection object.
/// </summary>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>latitude_of_center</term><description>The latitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>longitude_of_center</term><description>The longitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>standard_parallel_1</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is nearest the pole. Scale is true along this parallel.</description></item>
/// <item><term>standard_parallel_2</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is furthest from the pole. Scale is true along this parallel.</description></item>
/// <item><term>false_easting</term><description>The easting value assigned to the false origin.</description></item>
/// <item><term>false_northing</term><description>The northing value assigned to the false origin.</description></item>
/// </list>
/// </remarks>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <param name="inverse">Indicates whether the projection forward (meters to degrees or degrees to meters).</param>
protected AlbersProjection(IEnumerable<ProjectionParameter> parameters, AlbersProjection inverse)
: base(parameters, inverse)
{
Name = "Albers_Conic_Equal_Area";
double lat0 = lat_origin;
double lat1 = Degrees2Radians(_Parameters.GetParameterValue("standard_parallel_1"));
double lat2 = Degrees2Radians(_Parameters.GetParameterValue("standard_parallel_2"));
if (Math.Abs(lat1 + lat2) < double.Epsilon)
throw new ArgumentException("Equal latitudes for standard parallels on opposite sides of Equator.");
double alpha1 = alpha(lat1);
double alpha2 = alpha(lat2);
double m1 = Math.Cos(lat1) / Math.Sqrt(1 - _es * Math.Pow(Math.Sin(lat1), 2));
double m2 = Math.Cos(lat2) / Math.Sqrt(1 - _es * Math.Pow(Math.Sin(lat2), 2));
_n = (Math.Pow(m1, 2) - Math.Pow(m2, 2)) / (alpha2 - alpha1);
_c = Math.Pow(m1, 2) + (_n * alpha1);
_ro0 = Ro(alpha(lat0));
/*
double sin_p0 = Math.Sin(lat0);
double cos_p0 = Math.Cos(lat0);
double q0 = qsfnz(e, sin_p0, cos_p0);
double sin_p1 = Math.Sin(lat1);
double cos_p1 = Math.Cos(lat1);
double m1 = msfnz(e,sin_p1,cos_p1);
double q1 = qsfnz(e,sin_p1,cos_p1);
double sin_p2 = Math.Sin(lat2);
double cos_p2 = Math.Cos(lat2);
double m2 = msfnz(e,sin_p2,cos_p2);
double q2 = qsfnz(e,sin_p2,cos_p2);
if (Math.Abs(lat1 - lat2) > EPSLN)
ns0 = (m1 * m1 - m2 * m2)/ (q2 - q1);
else
ns0 = sin_p1;
C = m1 * m1 + ns0 * q1;
rh = this._semiMajor * Math.Sqrt(C - ns0 * q0)/ns0;
*/
}
#endregion
#region Public methods
/// <summary>
/// Converts coordinates in decimal degrees to projected meters.
/// </summary>
/// <param name="lon">The longitude of the point in radians when entering, its x-ordinate in meters after exit.</param>
/// <param name="lat">The latitude of the point in radians when entering, its y-in ordinate meters after exit.</param>
protected sealed override void RadiansToMeters(ref double lon, ref double lat)
{
double a = alpha(lat);
double ro = Ro(a);
double theta = _n * (lon - central_meridian);
lon = ro * Math.Sin(theta);
lat = _ro0 - ro * Math.Cos(theta);
}
/// <summary>
/// Converts coordinates in projected meters to decimal degrees.
/// </summary>
/// <param name="x">The x-ordinate of the point in meters when entering, its longitude in radians after exit.</param>
/// <param name="y">The y-ordinate of the point in meters when entering, its latitude in radians after exit.</param>
protected sealed override void MetersToRadians(ref double x, ref double y)
{
double theta = Math.Atan(x / (_ro0 - y));
double ro = Math.Sqrt(Math.Pow(x, 2) + Math.Pow(_ro0 - y, 2));
double q = (_c - Math.Pow(ro, 2) * Math.Pow(_n, 2) / Math.Pow(_semiMajor, 2)) / _n;
//double b = Math.Sin(q / (1 - ((1 - _es) / (2 * _e)) * Math.Log((1 - _e) / (1 + _e))));
double lat = Math.Asin(q * 0.5);
double preLat = double.MaxValue;
int iterationCounter = 0;
while (Math.Abs(lat - preLat) > 0.000001)
{
preLat = lat;
double sin = Math.Sin(lat);
double e2sin2 = _es * Math.Pow(sin, 2);
lat += Math.Pow(1 - e2sin2, 2) / (2 * Math.Cos(lat)) *
(q / (1 - _es) - sin / (1 - e2sin2) +
1 / (2 * _e) * Math.Log((1 - _e * sin) / (1 + _e * sin)));
iterationCounter++;
if (iterationCounter > 25)
throw new ArgumentException(
"Transformation failed to converge in Albers backwards transformation");
}
x = central_meridian + (theta / _n);
y = lat;
}
/// <summary>
/// Returns the inverse of this projection.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current projection.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
_inverse = new AlbersProjection(_Parameters.ToProjectionParameter(), this);
return _inverse;
}
#endregion
#region Math helper functions
//private double ToAuthalic(double lat)
//{
// return Math.Atan(Q(lat) / Q(Math.PI * 0.5));
//}
//private double Q(double angle)
//{
// double sin = Math.Sin(angle);
// double esin = e * sin;
// return Math.Abs(sin / (1 - Math.Pow(esin, 2)) - 0.5 * e) * Math.Log((1 - esin) / (1 + esin)));
//}
private double alpha(double lat)
{
double sin = Math.Sin(lat);
double sinsq = Math.Pow(sin, 2);
return (1 - _es) * (((sin / (1 - _es * sinsq)) - 1 / (2 * _e) * Math.Log((1 - _e * sin) / (1 + _e * sin))));
}
private double Ro(double a)
{
return _semiMajor * Math.Sqrt((_c - _n * a)) / _n;
}
#endregion
}
}

Просмотреть файл

@ -1,154 +1,154 @@
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
internal class CassiniSoldnerProjection : MapProjection
{
// ReSharper disable InconsistentNaming
private const double One6th = 0.16666666666666666666d; //C1
private const double One120th = 0.00833333333333333333d; //C2
private const double One24th = 0.04166666666666666666d; //C3
private const double One3rd = 0.33333333333333333333d; //C4
private const double One15th = 0.06666666666666666666d; //C5
// ReSharper restore InconsistentNaming
private readonly double _cFactor;
private readonly double _m0;
private readonly double _reciprocalSemiMajor;
public CassiniSoldnerProjection(IEnumerable<ProjectionParameter> parameters) : this(parameters, null)
{
}
public CassiniSoldnerProjection(IEnumerable<ProjectionParameter> parameters, CassiniSoldnerProjection inverse)
: base(parameters, inverse)
{
Authority = "EPSG";
AuthorityCode = 9806;
Name = "Cassini_Soldner";
_cFactor = _es / (1 - _es);
_m0 = mlfn(lat_origin, Math.Sin(lat_origin), Math.Cos(lat_origin));
_reciprocalSemiMajor = 1d / _semiMajor;
}
public override MathTransform Inverse()
{
if (_inverse == null)
_inverse = new CassiniSoldnerProjection(_Parameters.ToProjectionParameter(), this);
return _inverse;
}
//protected override double[] RadiansToMeters(double[] lonlat)
//{
// var lambda = lonlat[0] - central_meridian;
// var phi = lonlat[1];
// double sinPhi, cosPhi; // sin and cos value
// sincos(phi, out sinPhi, out cosPhi);
// var y = mlfn(phi, sinPhi, cosPhi);
// var n = 1.0d / Math.Sqrt(1 - _es * sinPhi * sinPhi);
// var tn = Math.Tan(phi);
// var t = tn * tn;
// var a1 = lambda * cosPhi;
// var a2 = a1 * a1;
// var c = _cFactor * Math.Pow(cosPhi, 2.0d);
// var x = n * a1 * (1.0d - a2 * t * (One6th - (8.0d - t + 8.0d * c) * a2 * One120th));
// y -= _m0 - n * tn * a2 * (0.5d + (5.0d - t + 6.0d * c) * a2 * One24th);
// return lonlat.Length == 2
// ? new[] {_semiMajor*x, _semiMajor*y}
// : new[] {_semiMajor*x, _semiMajor*y, lonlat[2]};
//}
protected override void RadiansToMeters(ref double lon, ref double lat)
{
double lambda = lon - central_meridian;
double phi = lat;
double sinPhi, cosPhi; // sin and cos value
sincos(phi, out sinPhi, out cosPhi);
double y = mlfn(phi, sinPhi, cosPhi);
double n = 1.0d / Math.Sqrt(1 - _es * sinPhi * sinPhi);
double tn = Math.Tan(phi);
double t = tn * tn;
double a1 = lambda * cosPhi;
double a2 = a1 * a1;
double c = _cFactor * Math.Pow(cosPhi, 2.0d);
double x = n * a1 * (1.0d - a2 * t * (One6th - (8.0d - t + 8.0d * c) * a2 * One120th));
y -= _m0 - n * tn * a2 * (0.5d + (5.0d - t + 6.0d * c) * a2 * One24th);
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
lon = x * _semiMajor;
lat = y * _semiMajor;
}
//protected override double[] MetersToRadians(double[] p)
//{
// var x = p[0] * _reciprocalSemiMajor;
// var y = p[1] * _reciprocalSemiMajor;
// var phi1 = Phi1(_m0 + y);
// var tn = Math.Tan(phi1);
// var t = tn * tn;
// var n = Math.Sin(phi1);
// var r = 1.0d / (1.0d - _es * n * n);
// n = Math.Sqrt(r);
// r *= (1.0d - _es) * n;
// var dd = x / n;
// var d2 = dd * dd;
// var phi = phi1 - (n * tn / r) * d2 * (.5 - (1.0 + 3.0 * t) * d2 * One24th);
// var lambda = dd * (1.0 + t * d2 * (-One3rd + (1.0 + 3.0 * t) * d2 * One15th)) / Math.Cos(phi1);
// lambda = adjust_lon(lambda + central_meridian);
// return p.Length == 2
// ? new[] {lambda, phi}
// : new[] {lambda, phi, p[2]};
//}
protected override void MetersToRadians(ref double x, ref double y)
{
x *= _reciprocalSemiMajor;
y *= _reciprocalSemiMajor;
double phi1 = Phi1(_m0 + y);
double tn = Math.Tan(phi1);
double t = tn * tn;
double n = Math.Sin(phi1);
double r = 1.0d / (1.0d - _es * n * n);
n = Math.Sqrt(r);
r *= (1.0d - _es) * n;
double dd = x / n;
double d2 = dd * dd;
y = phi1 - (n * tn / r) * d2 * (.5 - (1.0 + 3.0 * t) * d2 * One24th);
double lambda = dd * (1.0 + t * d2 * (-One3rd + (1.0 + 3.0 * t) * d2 * One15th)) / Math.Cos(phi1);
x = adjust_lon(lambda + central_meridian);
}
private double Phi1(double arg)
{
const int maxIter = 10;
const double eps = 1e-11;
double k = 1.0d / (1.0d - _es);
double phi = arg;
for (int i = maxIter; i > 0; --i)
{ // rarely goes over 2 iterations
double sinPhi = Math.Sin(phi);
double t = 1.0d - _es * sinPhi * sinPhi;
t = (mlfn(phi, sinPhi, Math.Cos(phi)) - arg) * (t * Math.Sqrt(t)) * k;
phi -= t;
if (Math.Abs(t) < eps) return phi;
}
throw new ArgumentException("Convergence error.");
}
}
namespace ProjNet.CoordinateSystems.Projections
{
internal class CassiniSoldnerProjection : MapProjection
{
// ReSharper disable InconsistentNaming
private const double One6th = 0.16666666666666666666d; //C1
private const double One120th = 0.00833333333333333333d; //C2
private const double One24th = 0.04166666666666666666d; //C3
private const double One3rd = 0.33333333333333333333d; //C4
private const double One15th = 0.06666666666666666666d; //C5
// ReSharper restore InconsistentNaming
private readonly double _cFactor;
private readonly double _m0;
private readonly double _reciprocalSemiMajor;
public CassiniSoldnerProjection(IEnumerable<ProjectionParameter> parameters) : this(parameters, null)
{
}
public CassiniSoldnerProjection(IEnumerable<ProjectionParameter> parameters, CassiniSoldnerProjection inverse)
: base(parameters, inverse)
{
Authority = "EPSG";
AuthorityCode = 9806;
Name = "Cassini_Soldner";
_cFactor = _es / (1 - _es);
_m0 = mlfn(lat_origin, Math.Sin(lat_origin), Math.Cos(lat_origin));
_reciprocalSemiMajor = 1d / _semiMajor;
}
public override MathTransform Inverse()
{
if (_inverse == null)
_inverse = new CassiniSoldnerProjection(_Parameters.ToProjectionParameter(), this);
return _inverse;
}
//protected override double[] RadiansToMeters(double[] lonlat)
//{
// var lambda = lonlat[0] - central_meridian;
// var phi = lonlat[1];
// double sinPhi, cosPhi; // sin and cos value
// sincos(phi, out sinPhi, out cosPhi);
// var y = mlfn(phi, sinPhi, cosPhi);
// var n = 1.0d / Math.Sqrt(1 - _es * sinPhi * sinPhi);
// var tn = Math.Tan(phi);
// var t = tn * tn;
// var a1 = lambda * cosPhi;
// var a2 = a1 * a1;
// var c = _cFactor * Math.Pow(cosPhi, 2.0d);
// var x = n * a1 * (1.0d - a2 * t * (One6th - (8.0d - t + 8.0d * c) * a2 * One120th));
// y -= _m0 - n * tn * a2 * (0.5d + (5.0d - t + 6.0d * c) * a2 * One24th);
// return lonlat.Length == 2
// ? new[] {_semiMajor*x, _semiMajor*y}
// : new[] {_semiMajor*x, _semiMajor*y, lonlat[2]};
//}
protected override void RadiansToMeters(ref double lon, ref double lat)
{
double lambda = lon - central_meridian;
double phi = lat;
double sinPhi, cosPhi; // sin and cos value
sincos(phi, out sinPhi, out cosPhi);
double y = mlfn(phi, sinPhi, cosPhi);
double n = 1.0d / Math.Sqrt(1 - _es * sinPhi * sinPhi);
double tn = Math.Tan(phi);
double t = tn * tn;
double a1 = lambda * cosPhi;
double a2 = a1 * a1;
double c = _cFactor * Math.Pow(cosPhi, 2.0d);
double x = n * a1 * (1.0d - a2 * t * (One6th - (8.0d - t + 8.0d * c) * a2 * One120th));
y -= _m0 - n * tn * a2 * (0.5d + (5.0d - t + 6.0d * c) * a2 * One24th);
lon = x * _semiMajor;
lat = y * _semiMajor;
}
//protected override double[] MetersToRadians(double[] p)
//{
// var x = p[0] * _reciprocalSemiMajor;
// var y = p[1] * _reciprocalSemiMajor;
// var phi1 = Phi1(_m0 + y);
// var tn = Math.Tan(phi1);
// var t = tn * tn;
// var n = Math.Sin(phi1);
// var r = 1.0d / (1.0d - _es * n * n);
// n = Math.Sqrt(r);
// r *= (1.0d - _es) * n;
// var dd = x / n;
// var d2 = dd * dd;
// var phi = phi1 - (n * tn / r) * d2 * (.5 - (1.0 + 3.0 * t) * d2 * One24th);
// var lambda = dd * (1.0 + t * d2 * (-One3rd + (1.0 + 3.0 * t) * d2 * One15th)) / Math.Cos(phi1);
// lambda = adjust_lon(lambda + central_meridian);
// return p.Length == 2
// ? new[] {lambda, phi}
// : new[] {lambda, phi, p[2]};
//}
protected override void MetersToRadians(ref double x, ref double y)
{
x *= _reciprocalSemiMajor;
y *= _reciprocalSemiMajor;
double phi1 = Phi1(_m0 + y);
double tn = Math.Tan(phi1);
double t = tn * tn;
double n = Math.Sin(phi1);
double r = 1.0d / (1.0d - _es * n * n);
n = Math.Sqrt(r);
r *= (1.0d - _es) * n;
double dd = x / n;
double d2 = dd * dd;
y = phi1 - (n * tn / r) * d2 * (.5 - (1.0 + 3.0 * t) * d2 * One24th);
double lambda = dd * (1.0 + t * d2 * (-One3rd + (1.0 + 3.0 * t) * d2 * One15th)) / Math.Cos(phi1);
x = adjust_lon(lambda + central_meridian);
}
private double Phi1(double arg)
{
const int maxIter = 10;
const double eps = 1e-11;
double k = 1.0d / (1.0d - _es);
double phi = arg;
for (int i = maxIter; i > 0; --i)
{ // rarely goes over 2 iterations
double sinPhi = Math.Sin(phi);
double t = 1.0d - _es * sinPhi * sinPhi;
t = (mlfn(phi, sinPhi, Math.Cos(phi)) - arg) * (t * Math.Sqrt(t)) * k;
phi -= t;
if (Math.Abs(t) < eps) return phi;
}
throw new ArgumentException("Convergence error.");
}
}
}

Просмотреть файл

@ -1,238 +1,238 @@
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
[Serializable]
internal class HotineObliqueMercatorProjection : MapProjection
{
private readonly double _azimuth;
private readonly double _sinP20, _cosP20;
private readonly double _bl, _al;
private readonly double _d, _el;
private readonly double _singrid, _cosgrid;
private readonly double _singam, _cosgam;
private readonly double _sinaz, _cosaz;
private readonly double _u;
private bool NaturalOriginOffsets {
get
{
if (AuthorityCode == 9812) return false;
if (AuthorityCode == 9815) return true;
throw new ArgumentException("AuthorityCode");
}
}
public HotineObliqueMercatorProjection(IEnumerable<ProjectionParameter> parameters)
: this(parameters, null)
{
}
public HotineObliqueMercatorProjection(IEnumerable<ProjectionParameter> parameters, HotineObliqueMercatorProjection inverse)
: base(parameters, inverse)
{
Authority = "EPSG";
AuthorityCode = 9812;
Name = "Hotine_Oblique_Mercator";
_azimuth = Degrees2Radians(_Parameters.GetParameterValue("azimuth"));
double rectifiedGridAngle = Degrees2Radians(_Parameters.GetParameterValue("rectified_grid_angle"));
sincos(lat_origin, out _sinP20, out _cosP20);
double con = 1.0 - _es * Math.Pow(_sinP20, 2);
double com = Math.Sqrt(1.0 - _es);
_bl = Math.Sqrt(1.0 + _es * Math.Pow(_cosP20, 4.0) / ( 1.0 - _es ));
_al = _semiMajor * _bl * scale_factor * com / con;
double f;
if (Math.Abs(lat_origin) < EPSLN)
{
//ts = 1.0;
_d = 1.0;
_el = 1.0;
f = 1.0;
}
else
{
double ts = tsfnz(_e, lat_origin, _sinP20);
con = Math.Sqrt(con);
_d = _bl * com / ( _cosP20 * con );
if ( ( _d * _d - 1.0 ) > 0.0 )
{
if ( lat_origin >= 0.0 )
f = _d + Math.Sqrt(_d * _d - 1.0);
else
f = _d - Math.Sqrt(_d * _d - 1.0);
}
else
f = _d;
_el = f * Math.Pow(ts, _bl);
}
double g = .5 * ( f - 1.0 / f );
double gama = asinz(Math.Sin(_azimuth) / _d);
lon_origin = lon_origin - asinz(g * Math.Tan(gama)) / _bl;
con = Math.Abs(lat_origin);
if ( ( con > EPSLN ) && ( Math.Abs(con - HALF_PI) > EPSLN ) )
{
sincos(gama, out _singam, out _cosgam);
sincos(_azimuth, out _sinaz, out _cosaz);
if ( lat_origin >= 0 )
_u = ( _al / _bl ) * Math.Atan(Math.Sqrt(_d * _d - 1.0) / _cosaz);
else
_u = -( _al / _bl ) * Math.Atan(Math.Sqrt(_d * _d - 1.0) / _cosaz);
}
else
{
throw new ArgumentException("Input data error");
}
sincos(rectifiedGridAngle, out _singrid, out _cosgrid);
}
public override MathTransform Inverse()
{
if (_inverse == null)
{
_inverse = new HotineObliqueMercatorProjection(_Parameters.ToProjectionParameter(), this);
}
return _inverse;
}
//protected override double[] RadiansToMeters(double[] lonlat)
//{
// var lon = lonlat[0];
// var lat = lonlat[1];
// Double us, ul;
// // Forward equations
// // -----------------
// var sin_phi = Math.Sin(lat);
// var dlon = adjust_lon(lon - lon_origin);
// var vl = Math.Sin(_bl * dlon);
// if (Math.Abs(Math.Abs(lat) - HALF_PI) > EPSLN)
// {
// var ts1 = tsfnz(_e, lat, sin_phi);
// var q = _el / (Math.Pow(ts1, _bl));
// var s = .5 * (q - 1.0 / q);
// var t = .5 * (q + 1.0 / q);
// ul = (s * _singam - vl * _cosgam) / t;
// var con = Math.Cos(_bl * dlon);
// if (Math.Abs(con) < .0000001)
// {
// us = _al * _bl * dlon;
// }
// else
// {
// us = _al * Math.Atan((s * _cosgam + vl * _singam) / con) / _bl;
// if (con < 0)
// us = us + PI * _al / _bl;
// }
// }
// else
// {
// if (lat >= 0)
// ul = _singam;
// else
// ul = -_singam;
// us = _al * lat / _bl;
// }
// if (Math.Abs(Math.Abs(ul) - 1.0) <= EPSLN)
// {
// throw new Exception("Point projects into infinity");
// }
// var vs = .5 * _al * Math.Log((1.0 - ul) / (1.0 + ul)) / _bl;
// if (!NaturalOriginOffsets) us = us - _u;
// var x = vs * _cosgrid + us * _singrid;
// var y = us * _cosgrid - vs * _singrid;
// return lonlat.Length == 2
// ? new [] {x, y} :
// new [] {x, y, lonlat[2]};
//}
protected override void RadiansToMeters(ref double lon, ref double lat)
{
double us, ul;
// Forward equations
// -----------------
double sin_phi = Math.Sin(lat);
double dlon = adjust_lon(lon - lon_origin);
double vl = Math.Sin(_bl * dlon);
if (Math.Abs(Math.Abs(lat) - HALF_PI) > EPSLN)
{
double ts1 = tsfnz(_e, lat, sin_phi);
double q = _el / (Math.Pow(ts1, _bl));
double s = .5 * (q - 1.0 / q);
double t = .5 * (q + 1.0 / q);
ul = (s * _singam - vl * _cosgam) / t;
double con = Math.Cos(_bl * dlon);
if (Math.Abs(con) < .0000001)
{
us = _al * _bl * dlon;
}
else
{
us = _al * Math.Atan((s * _cosgam + vl * _singam) / con) / _bl;
if (con < 0)
us = us + PI * _al / _bl;
}
}
else
{
if (lat >= 0)
ul = _singam;
else
ul = -_singam;
us = _al * lat / _bl;
}
if (Math.Abs(Math.Abs(ul) - 1.0) <= EPSLN)
throw new Exception("Point projects into infinity");
double vs = .5 * _al * Math.Log((1.0 - ul) / (1.0 + ul)) / _bl;
if (!NaturalOriginOffsets) us = us - _u;
lon = vs * _cosgrid + us * _singrid;
lat = us * _cosgrid - vs * _singrid;
}
protected override void MetersToRadians(ref double x, ref double y)
{
// Inverse equations
// -----------------
double vs = x * _cosgrid - y * _singrid;
double us = y * _cosgrid + x * _singrid;
if (!NaturalOriginOffsets) us = us + _u;
double q = Math.Exp(-_bl * vs / _al);
double s = .5 * (q - 1.0 / q);
double t = .5 * (q + 1.0 / q);
double vl = Math.Sin(_bl * us / _al);
double ul = (vl * _cosgam + s * _singam) / t;
if (Math.Abs(Math.Abs(ul) - 1.0) <= EPSLN)
{
x = lon_origin;
y = sign(ul) * HALF_PI;
}
else
{
double con = 1.0 / _bl;
double ts1 = Math.Pow((_el / Math.Sqrt((1.0 + ul) / (1.0 - ul))), con);
long flag;
y = phi2z(_e, ts1, out flag);
con = Math.Cos(_bl * us / _al);
double theta = lon_origin - Math.Atan2((s * _cosgam - vl * _singam), con) / _bl;
x = adjust_lon(theta);
}
}
}
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
[Serializable]
internal class HotineObliqueMercatorProjection : MapProjection
{
private readonly double _azimuth;
private readonly double _sinP20, _cosP20;
private readonly double _bl, _al;
private readonly double _d, _el;
private readonly double _singrid, _cosgrid;
private readonly double _singam, _cosgam;
private readonly double _sinaz, _cosaz;
private readonly double _u;
private bool NaturalOriginOffsets {
get
{
if (AuthorityCode == 9812) return false;
if (AuthorityCode == 9815) return true;
throw new ArgumentException("AuthorityCode");
}
}
public HotineObliqueMercatorProjection(IEnumerable<ProjectionParameter> parameters)
: this(parameters, null)
{
}
public HotineObliqueMercatorProjection(IEnumerable<ProjectionParameter> parameters, HotineObliqueMercatorProjection inverse)
: base(parameters, inverse)
{
Authority = "EPSG";
AuthorityCode = 9812;
Name = "Hotine_Oblique_Mercator";
_azimuth = Degrees2Radians(_Parameters.GetParameterValue("azimuth"));
double rectifiedGridAngle = Degrees2Radians(_Parameters.GetParameterValue("rectified_grid_angle"));
sincos(lat_origin, out _sinP20, out _cosP20);
double con = 1.0 - _es * Math.Pow(_sinP20, 2);
double com = Math.Sqrt(1.0 - _es);
_bl = Math.Sqrt(1.0 + _es * Math.Pow(_cosP20, 4.0) / ( 1.0 - _es ));
_al = _semiMajor * _bl * scale_factor * com / con;
double f;
if (Math.Abs(lat_origin) < EPSLN)
{
//ts = 1.0;
_d = 1.0;
_el = 1.0;
f = 1.0;
}
else
{
double ts = tsfnz(_e, lat_origin, _sinP20);
con = Math.Sqrt(con);
_d = _bl * com / ( _cosP20 * con );
if ( ( _d * _d - 1.0 ) > 0.0 )
{
if ( lat_origin >= 0.0 )
f = _d + Math.Sqrt(_d * _d - 1.0);
else
f = _d - Math.Sqrt(_d * _d - 1.0);
}
else
f = _d;
_el = f * Math.Pow(ts, _bl);
}
double g = .5 * ( f - 1.0 / f );
double gama = asinz(Math.Sin(_azimuth) / _d);
lon_origin = lon_origin - asinz(g * Math.Tan(gama)) / _bl;
con = Math.Abs(lat_origin);
if ( ( con > EPSLN ) && ( Math.Abs(con - HALF_PI) > EPSLN ) )
{
sincos(gama, out _singam, out _cosgam);
sincos(_azimuth, out _sinaz, out _cosaz);
if ( lat_origin >= 0 )
_u = ( _al / _bl ) * Math.Atan(Math.Sqrt(_d * _d - 1.0) / _cosaz);
else
_u = -( _al / _bl ) * Math.Atan(Math.Sqrt(_d * _d - 1.0) / _cosaz);
}
else
{
throw new ArgumentException("Input data error");
}
sincos(rectifiedGridAngle, out _singrid, out _cosgrid);
}
public override MathTransform Inverse()
{
if (_inverse == null)
{
_inverse = new HotineObliqueMercatorProjection(_Parameters.ToProjectionParameter(), this);
}
return _inverse;
}
//protected override double[] RadiansToMeters(double[] lonlat)
//{
// var lon = lonlat[0];
// var lat = lonlat[1];
// Double us, ul;
// // Forward equations
// // -----------------
// var sin_phi = Math.Sin(lat);
// var dlon = adjust_lon(lon - lon_origin);
// var vl = Math.Sin(_bl * dlon);
// if (Math.Abs(Math.Abs(lat) - HALF_PI) > EPSLN)
// {
// var ts1 = tsfnz(_e, lat, sin_phi);
// var q = _el / (Math.Pow(ts1, _bl));
// var s = .5 * (q - 1.0 / q);
// var t = .5 * (q + 1.0 / q);
// ul = (s * _singam - vl * _cosgam) / t;
// var con = Math.Cos(_bl * dlon);
// if (Math.Abs(con) < .0000001)
// {
// us = _al * _bl * dlon;
// }
// else
// {
// us = _al * Math.Atan((s * _cosgam + vl * _singam) / con) / _bl;
// if (con < 0)
// us = us + PI * _al / _bl;
// }
// }
// else
// {
// if (lat >= 0)
// ul = _singam;
// else
// ul = -_singam;
// us = _al * lat / _bl;
// }
// if (Math.Abs(Math.Abs(ul) - 1.0) <= EPSLN)
// {
// throw new Exception("Point projects into infinity");
// }
// var vs = .5 * _al * Math.Log((1.0 - ul) / (1.0 + ul)) / _bl;
// if (!NaturalOriginOffsets) us = us - _u;
// var x = vs * _cosgrid + us * _singrid;
// var y = us * _cosgrid - vs * _singrid;
// return lonlat.Length == 2
// ? new [] {x, y} :
// new [] {x, y, lonlat[2]};
//}
protected override void RadiansToMeters(ref double lon, ref double lat)
{
double us, ul;
// Forward equations
// -----------------
double sin_phi = Math.Sin(lat);
double dlon = adjust_lon(lon - lon_origin);
double vl = Math.Sin(_bl * dlon);
if (Math.Abs(Math.Abs(lat) - HALF_PI) > EPSLN)
{
double ts1 = tsfnz(_e, lat, sin_phi);
double q = _el / (Math.Pow(ts1, _bl));
double s = .5 * (q - 1.0 / q);
double t = .5 * (q + 1.0 / q);
ul = (s * _singam - vl * _cosgam) / t;
double con = Math.Cos(_bl * dlon);
if (Math.Abs(con) < .0000001)
{
us = _al * _bl * dlon;
}
else
{
us = _al * Math.Atan((s * _cosgam + vl * _singam) / con) / _bl;
if (con < 0)
us = us + PI * _al / _bl;
}
}
else
{
if (lat >= 0)
ul = _singam;
else
ul = -_singam;
us = _al * lat / _bl;
}
if (Math.Abs(Math.Abs(ul) - 1.0) <= EPSLN)
throw new Exception("Point projects into infinity");
double vs = .5 * _al * Math.Log((1.0 - ul) / (1.0 + ul)) / _bl;
if (!NaturalOriginOffsets) us = us - _u;
lon = vs * _cosgrid + us * _singrid;
lat = us * _cosgrid - vs * _singrid;
}
protected override void MetersToRadians(ref double x, ref double y)
{
// Inverse equations
// -----------------
double vs = x * _cosgrid - y * _singrid;
double us = y * _cosgrid + x * _singrid;
if (!NaturalOriginOffsets) us = us + _u;
double q = Math.Exp(-_bl * vs / _al);
double s = .5 * (q - 1.0 / q);
double t = .5 * (q + 1.0 / q);
double vl = Math.Sin(_bl * us / _al);
double ul = (vl * _cosgam + s * _singam) / t;
if (Math.Abs(Math.Abs(ul) - 1.0) <= EPSLN)
{
x = lon_origin;
y = sign(ul) * HALF_PI;
}
else
{
double con = 1.0 / _bl;
double ts1 = Math.Pow((_el / Math.Sqrt((1.0 + ul) / (1.0 - ul))), con);
long flag;
y = phi2z(_e, ts1, out flag);
con = Math.Cos(_bl * us / _al);
double theta = lon_origin - Math.Atan2((s * _cosgam - vl * _singam), con) / _bl;
x = adjust_lon(theta);
}
}
}
}

Просмотреть файл

@ -1,270 +1,270 @@
// Copyright 2008
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// Implemetns the Krovak Projection.
/// </summary>
/// <remarks>
/// <para>The normal case of the Lambert Conformal conic is for the axis of the cone
/// to be coincident with the minor axis of the ellipsoid, that is the axis of the cone
/// is normal to the ellipsoid at a pole. For the Oblique Conformal Conic the axis
/// of the cone is normal to the ellipsoid at a defined location and its extension
/// cuts the minor axis at a defined angle. This projection is used in the Czech Republic
/// and Slovakia under the name "Krovak" projection.</para>
/// </remarks>
[Serializable]
internal class KrovakProjection : MapProjection
{
/**
* Maximum number of iterations for iterative computations.
*/
private const int MaximumIterations = 15;
/**
* When to stop the iteration.
*/
private const double IterationTolerance = 1E-11;
/**
* Azimuth of the centre line passing through the centre of the projection.
* This is equals to the co-latitude of the cone axis at point of intersection
* with the ellipsoid.
*/
private readonly double _azimuth;
/**
* Latitude of pseudo standard parallel.
*/
private readonly double _pseudoStandardParallel;
/**
* Useful variables calculated from parameters defined by user.
*/
private readonly double _sinAzim, _cosAzim, _n, _tanS2, _alfa, _hae, _k1, _ka, _ro0, _rop;
private readonly double _reciprocSemiMajor;
/**
* Useful constant - 45° in radians.
*/
private const double S45 = 0.785398163397448;
#region Constructors
/// <summary>
/// Creates an instance of an LambertConformalConic2SPProjection projection object.
/// </summary>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>latitude_of_false_origin</term><description>The latitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>longitude_of_false_origin</term><description>The longitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>latitude_of_1st_standard_parallel</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is nearest the pole. Scale is true along this parallel.</description></item>
/// <item><term>latitude_of_2nd_standard_parallel</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is furthest from the pole. Scale is true along this parallel.</description></item>
/// <item><term>easting_at_false_origin</term><description>The easting value assigned to the false origin.</description></item>
/// <item><term>northing_at_false_origin</term><description>The northing value assigned to the false origin.</description></item>
/// </list>
/// </remarks>
/// <param name="parameters">List of parameters to initialize the projection.</param>
public KrovakProjection(IEnumerable<ProjectionParameter> parameters)
: this(parameters,null)
{
}
/// <summary>
/// Creates an instance of an Krovak projection object.
/// </summary>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Parameter</term><description>Description</description></listheader>
/// <item><term>latitude_of_origin</term><description>The latitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>central_meridian</term><description>The longitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>standard_parallel_1</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is nearest the pole. Scale is true along this parallel.</description></item>
/// <item><term>standard_parallel_2</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is furthest from the pole. Scale is true along this parallel.</description></item>
/// <item><term>false_easting</term><description>The easting value assigned to the false origin.</description></item>
/// <item><term>false_northing</term><description>The northing value assigned to the false origin.</description></item>
/// </list>
/// </remarks>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <param name="inverse">Indicates whether the projection forward (meters to degrees or degrees to meters).</param>
protected KrovakProjection(IEnumerable<ProjectionParameter> parameters, KrovakProjection inverse)
: base(parameters, inverse)
{
Name = "Krovak";
Authority = "EPSG";
AuthorityCode = 9819;
//PROJCS["S-JTSK (Ferro) / Krovak",
//GEOGCS["S-JTSK (Ferro)",
// DATUM["D_S_JTSK_Ferro",
// SPHEROID["Bessel 1841",6377397.155,299.1528128]],
// PRIMEM["Ferro",-17.66666666666667],
// UNIT["degree",0.0174532925199433]],
//PROJECTION["Krovak"],
//PARAMETER["latitude_of_center",49.5],
//PARAMETER["longitude_of_center",42.5],
//PARAMETER["azimuth",30.28813972222222],
//PARAMETER["pseudo_standard_parallel_1",78.5],
//PARAMETER["scale_factor",0.9999],
//PARAMETER["false_easting",0],
//PARAMETER["false_northing",0],
//UNIT["metre",1]]
//Check for missing parameters
_azimuth = Degrees2Radians(_Parameters.GetParameterValue("azimuth"));
_pseudoStandardParallel = Degrees2Radians(_Parameters.GetParameterValue("pseudo_standard_parallel_1"));
// Calculates useful constants.
_sinAzim = Math.Sin(_azimuth);
_cosAzim = Math.Cos(_azimuth);
_n = Math.Sin(_pseudoStandardParallel);
_tanS2 = Math.Tan(_pseudoStandardParallel / 2 + S45);
double sinLat = Math.Sin(lat_origin);
double cosLat = Math.Cos(lat_origin);
double cosL2 = cosLat * cosLat;
_alfa = Math.Sqrt(1 + ((_es * (cosL2 * cosL2)) / (1 - _es))); // parameter B
_hae = _alfa * _e / 2;
double u0 = Math.Asin(sinLat / _alfa);
double esl = _e * sinLat;
double g = Math.Pow((1 - esl) / (1 + esl), (_alfa * _e) / 2);
_k1 = Math.Pow(Math.Tan(lat_origin / 2 + S45), _alfa) * g / Math.Tan(u0 / 2 + S45);
_ka = Math.Pow(1 / _k1, -1 / _alfa);
double radius = Math.Sqrt(1 - _es) / (1 - (_es * (sinLat * sinLat)));
_ro0 = scale_factor * radius / Math.Tan(_pseudoStandardParallel);
_rop = _ro0 * Math.Pow(_tanS2, _n);
_reciprocSemiMajor = 1 / _semiMajor;
}
#endregion
/// <summary>
/// Converts coordinates in radians to projected meters.
/// </summary>
/// <param name="lon"></param>
/// <param name="lat"></param>
protected override void RadiansToMeters(ref double lon, ref double lat)
{
double lambda = lon - central_meridian;
double phi = lat;
double esp = _e * Math.Sin(phi);
double gfi = Math.Pow(((1.0 - esp) / (1.0 + esp)), _hae);
double u = 2 * (Math.Atan(Math.Pow(Math.Tan(phi / 2 + S45), _alfa) / _k1 * gfi) - S45);
double deltav = -lambda * _alfa;
double cosU = Math.Cos(u);
double s = Math.Asin((_cosAzim * Math.Sin(u)) + (_sinAzim * cosU * Math.Cos(deltav)));
double d = Math.Asin(cosU * Math.Sin(deltav) / Math.Cos(s));
double eps = _n * d;
double ro = _rop / Math.Pow(Math.Tan(s / 2 + S45), _n);
/* x and y are reverted */
lat = -(ro * Math.Cos(eps)) * _semiMajor;
lon = -(ro * Math.Sin(eps)) * _semiMajor;
}
/// <summary>
/// Converts coordinates in projected meters to radians.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
protected override void MetersToRadians(ref double x, ref double y)
{
x *= _reciprocSemiMajor;
y *= _reciprocSemiMajor;
// x -> southing, y -> westing
double ro = Math.Sqrt(x * x + y * y);
double eps = Math.Atan2(-x, -y);
double d = eps / _n;
double s = 2 * (Math.Atan(Math.Pow(_ro0 / ro, 1 / _n) * _tanS2) - S45);
double cs = Math.Cos(s);
double u = Math.Asin((_cosAzim * Math.Sin(s)) - (_sinAzim * cs * Math.Cos(d)));
double kau = _ka * Math.Pow(Math.Tan((u / 2.0) + S45), 1 / _alfa);
double deltav = Math.Asin((cs * Math.Sin(d)) / Math.Cos(u));
double lambda = -deltav / _alfa;
double phi = 0d;
// iteration calculation
for (int iter = MaximumIterations;;)
{
double fi1 = phi;
double esf = _e * Math.Sin(fi1);
phi = 2.0 * (Math.Atan(kau * Math.Pow((1.0 + esf) / (1.0 - esf), _e / 2.0)) - S45);
if (Math.Abs(fi1 - phi) <= IterationTolerance)
{
break;
}
if (--iter < 0)
{
break;
//throw new ProjectionException(Errors.format(ErrorKeys.NO_CONVERGENCE));
}
}
x = lambda + central_meridian;
y = phi;
}
/// <summary>
/// Returns the inverse of this projection.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current projection.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
{
_inverse = new KrovakProjection(_Parameters.ToProjectionParameter(), this);
}
return _inverse;
}
}
}
// Copyright 2008
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// Implemetns the Krovak Projection.
/// </summary>
/// <remarks>
/// <para>The normal case of the Lambert Conformal conic is for the axis of the cone
/// to be coincident with the minor axis of the ellipsoid, that is the axis of the cone
/// is normal to the ellipsoid at a pole. For the Oblique Conformal Conic the axis
/// of the cone is normal to the ellipsoid at a defined location and its extension
/// cuts the minor axis at a defined angle. This projection is used in the Czech Republic
/// and Slovakia under the name "Krovak" projection.</para>
/// </remarks>
[Serializable]
internal class KrovakProjection : MapProjection
{
/**
* Maximum number of iterations for iterative computations.
*/
private const int MaximumIterations = 15;
/**
* When to stop the iteration.
*/
private const double IterationTolerance = 1E-11;
/**
* Azimuth of the centre line passing through the centre of the projection.
* This is equals to the co-latitude of the cone axis at point of intersection
* with the ellipsoid.
*/
private readonly double _azimuth;
/**
* Latitude of pseudo standard parallel.
*/
private readonly double _pseudoStandardParallel;
/**
* Useful variables calculated from parameters defined by user.
*/
private readonly double _sinAzim, _cosAzim, _n, _tanS2, _alfa, _hae, _k1, _ka, _ro0, _rop;
private readonly double _reciprocSemiMajor;
/**
* Useful constant - 45° in radians.
*/
private const double S45 = 0.785398163397448;
#region Constructors
/// <summary>
/// Creates an instance of an LambertConformalConic2SPProjection projection object.
/// </summary>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>latitude_of_false_origin</term><description>The latitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>longitude_of_false_origin</term><description>The longitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>latitude_of_1st_standard_parallel</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is nearest the pole. Scale is true along this parallel.</description></item>
/// <item><term>latitude_of_2nd_standard_parallel</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is furthest from the pole. Scale is true along this parallel.</description></item>
/// <item><term>easting_at_false_origin</term><description>The easting value assigned to the false origin.</description></item>
/// <item><term>northing_at_false_origin</term><description>The northing value assigned to the false origin.</description></item>
/// </list>
/// </remarks>
/// <param name="parameters">List of parameters to initialize the projection.</param>
public KrovakProjection(IEnumerable<ProjectionParameter> parameters)
: this(parameters,null)
{
}
/// <summary>
/// Creates an instance of an Krovak projection object.
/// </summary>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Parameter</term><description>Description</description></listheader>
/// <item><term>latitude_of_origin</term><description>The latitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>central_meridian</term><description>The longitude of the point which is not the natural origin and at which grid coordinate values false easting and false northing are defined.</description></item>
/// <item><term>standard_parallel_1</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is nearest the pole. Scale is true along this parallel.</description></item>
/// <item><term>standard_parallel_2</term><description>For a conic projection with two standard parallels, this is the latitude of intersection of the cone with the ellipsoid that is furthest from the pole. Scale is true along this parallel.</description></item>
/// <item><term>false_easting</term><description>The easting value assigned to the false origin.</description></item>
/// <item><term>false_northing</term><description>The northing value assigned to the false origin.</description></item>
/// </list>
/// </remarks>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <param name="inverse">Indicates whether the projection forward (meters to degrees or degrees to meters).</param>
protected KrovakProjection(IEnumerable<ProjectionParameter> parameters, KrovakProjection inverse)
: base(parameters, inverse)
{
Name = "Krovak";
Authority = "EPSG";
AuthorityCode = 9819;
//PROJCS["S-JTSK (Ferro) / Krovak",
//GEOGCS["S-JTSK (Ferro)",
// DATUM["D_S_JTSK_Ferro",
// SPHEROID["Bessel 1841",6377397.155,299.1528128]],
// PRIMEM["Ferro",-17.66666666666667],
// UNIT["degree",0.0174532925199433]],
//PROJECTION["Krovak"],
//PARAMETER["latitude_of_center",49.5],
//PARAMETER["longitude_of_center",42.5],
//PARAMETER["azimuth",30.28813972222222],
//PARAMETER["pseudo_standard_parallel_1",78.5],
//PARAMETER["scale_factor",0.9999],
//PARAMETER["false_easting",0],
//PARAMETER["false_northing",0],
//UNIT["metre",1]]
//Check for missing parameters
_azimuth = Degrees2Radians(_Parameters.GetParameterValue("azimuth"));
_pseudoStandardParallel = Degrees2Radians(_Parameters.GetParameterValue("pseudo_standard_parallel_1"));
// Calculates useful constants.
_sinAzim = Math.Sin(_azimuth);
_cosAzim = Math.Cos(_azimuth);
_n = Math.Sin(_pseudoStandardParallel);
_tanS2 = Math.Tan(_pseudoStandardParallel / 2 + S45);
double sinLat = Math.Sin(lat_origin);
double cosLat = Math.Cos(lat_origin);
double cosL2 = cosLat * cosLat;
_alfa = Math.Sqrt(1 + ((_es * (cosL2 * cosL2)) / (1 - _es))); // parameter B
_hae = _alfa * _e / 2;
double u0 = Math.Asin(sinLat / _alfa);
double esl = _e * sinLat;
double g = Math.Pow((1 - esl) / (1 + esl), (_alfa * _e) / 2);
_k1 = Math.Pow(Math.Tan(lat_origin / 2 + S45), _alfa) * g / Math.Tan(u0 / 2 + S45);
_ka = Math.Pow(1 / _k1, -1 / _alfa);
double radius = Math.Sqrt(1 - _es) / (1 - (_es * (sinLat * sinLat)));
_ro0 = scale_factor * radius / Math.Tan(_pseudoStandardParallel);
_rop = _ro0 * Math.Pow(_tanS2, _n);
_reciprocSemiMajor = 1 / _semiMajor;
}
#endregion
/// <summary>
/// Converts coordinates in radians to projected meters.
/// </summary>
/// <param name="lon"></param>
/// <param name="lat"></param>
protected override void RadiansToMeters(ref double lon, ref double lat)
{
double lambda = lon - central_meridian;
double phi = lat;
double esp = _e * Math.Sin(phi);
double gfi = Math.Pow(((1.0 - esp) / (1.0 + esp)), _hae);
double u = 2 * (Math.Atan(Math.Pow(Math.Tan(phi / 2 + S45), _alfa) / _k1 * gfi) - S45);
double deltav = -lambda * _alfa;
double cosU = Math.Cos(u);
double s = Math.Asin((_cosAzim * Math.Sin(u)) + (_sinAzim * cosU * Math.Cos(deltav)));
double d = Math.Asin(cosU * Math.Sin(deltav) / Math.Cos(s));
double eps = _n * d;
double ro = _rop / Math.Pow(Math.Tan(s / 2 + S45), _n);
/* x and y are reverted */
lat = -(ro * Math.Cos(eps)) * _semiMajor;
lon = -(ro * Math.Sin(eps)) * _semiMajor;
}
/// <summary>
/// Converts coordinates in projected meters to radians.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
protected override void MetersToRadians(ref double x, ref double y)
{
x *= _reciprocSemiMajor;
y *= _reciprocSemiMajor;
// x -> southing, y -> westing
double ro = Math.Sqrt(x * x + y * y);
double eps = Math.Atan2(-x, -y);
double d = eps / _n;
double s = 2 * (Math.Atan(Math.Pow(_ro0 / ro, 1 / _n) * _tanS2) - S45);
double cs = Math.Cos(s);
double u = Math.Asin((_cosAzim * Math.Sin(s)) - (_sinAzim * cs * Math.Cos(d)));
double kau = _ka * Math.Pow(Math.Tan((u / 2.0) + S45), 1 / _alfa);
double deltav = Math.Asin((cs * Math.Sin(d)) / Math.Cos(u));
double lambda = -deltav / _alfa;
double phi = 0d;
// iteration calculation
for (int iter = MaximumIterations;;)
{
double fi1 = phi;
double esf = _e * Math.Sin(fi1);
phi = 2.0 * (Math.Atan(kau * Math.Pow((1.0 + esf) / (1.0 - esf), _e / 2.0)) - S45);
if (Math.Abs(fi1 - phi) <= IterationTolerance)
{
break;
}
if (--iter < 0)
{
break;
//throw new ProjectionException(Errors.format(ErrorKeys.NO_CONVERGENCE));
}
}
x = lambda + central_meridian;
y = phi;
}
/// <summary>
/// Returns the inverse of this projection.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current projection.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
{
_inverse = new KrovakProjection(_Parameters.ToProjectionParameter(), this);
}
return _inverse;
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,180 +1,180 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// Implements the Mercator projection.
/// </summary>
/// <remarks>
/// <para>This map projection introduced in 1569 by Gerardus Mercator. It is often described as a cylindrical projection,
/// but it must be derived mathematically. The meridians are equally spaced, parallel vertical lines, and the
/// parallels of latitude are parallel, horizontal straight lines, spaced farther and farther apart as their distance
/// from the Equator increases. This projection is widely used for navigation charts, because any straight line
/// on a Mercator-projection map is a line of constant true bearing that enables a navigator to plot a straight-line
/// course. It is less practical for world maps because the scale is distorted; areas farther away from the equator
/// appear disproportionately large. On a Mercator projection, for example, the landmass of Greenland appears to be
/// greater than that of the continent of South America; in actual area, Greenland is smaller than the Arabian Peninsula.
/// </para>
/// </remarks>
[Serializable]
internal class Mercator : MapProjection
{
//double lon_center; //Center longitude (projection center)
//double lat_origin; //center latitude
//double e,e2; //eccentricity constants
private readonly double _k0; //small value m
/// <summary>
/// Initializes the MercatorProjection object with the specified parameters to project points.
/// </summary>
/// <param name="parameters">ParameterList with the required parameters.</param>
/// <remarks>
/// </remarks>
public Mercator(IEnumerable<ProjectionParameter> parameters)
: this(parameters, null)
{
}
/// <summary>
/// Initializes the MercatorProjection object with the specified parameters.
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <param name="isInverse">Indicates whether the projection forward (meters to degrees or degrees to meters).</param>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>central_meridian</term><description>The longitude of the point from which the values of both the geographical coordinates on the ellipsoid and the grid coordinates on the projection are deemed to increment or decrement for computational purposes. Alternatively it may be considered as the longitude of the point which in the absence of application of false coordinates has grid coordinates of (0,0).</description></item>
/// <item><term>latitude_of_origin</term><description>The latitude of the point from which the values of both the geographical coordinates on the ellipsoid and the grid coordinates on the projection are deemed to increment or decrement for computational purposes. Alternatively it may be considered as the latitude of the point which in the absence of application of false coordinates has grid coordinates of (0,0).</description></item>
/// <item><term>scale_factor</term><description>The factor by which the map grid is reduced or enlarged during the projection process, defined by its value at the natural origin.</description></item>
/// <item><term>false_easting</term><description>Since the natural origin may be at or near the centre of the projection and under normal coordinate circumstances would thus give rise to negative coordinates over parts of the mapped area, this origin is usually given false coordinates which are large enough to avoid this inconvenience. The False Easting, FE, is the easting value assigned to the abscissa (east).</description></item>
/// <item><term>false_northing</term><description>Since the natural origin may be at or near the centre of the projection and under normal coordinate circumstances would thus give rise to negative coordinates over parts of the mapped area, this origin is usually given false coordinates which are large enough to avoid this inconvenience. The False Northing, FN, is the northing value assigned to the ordinate.</description></item>
/// </list>
/// </remarks>
protected Mercator(IEnumerable<ProjectionParameter> parameters, Mercator isInverse)
: base(parameters, isInverse)
{
Authority = "EPSG";
var scaleFactor = GetParameter("scale_factor");
if (scaleFactor == null) //This is a two standard parallel Mercator projection (2SP)
{
_k0 = Math.Cos(lat_origin) / Math.Sqrt(1.0 - _es * Math.Sin(lat_origin) * Math.Sin(lat_origin));
AuthorityCode = 9805;
Name = "Mercator_2SP";
}
else //This is a one standard parallel Mercator projection (1SP)
{
_k0 = scaleFactor.Value;
Name = "Mercator_1SP";
}
}
/// <summary>
/// Converts coordinates in decimal degrees to projected meters.
/// </summary>
/// <param name="lon">The longitude of the point in decimal degrees.</param>
/// <param name="lat">The latitude of the point in decimal degrees.</param>
/// <returns>Point in projected meters</returns>
protected override void RadiansToMeters(ref double lon, ref double lat)
{
if (double.IsNaN(lon) || double.IsNaN(lat))
{
lon = double.NaN;
lat = double.NaN;
return;
}
double dLongitude = lon;
double dLatitude = lat;
/* Forward equations */
if (Math.Abs(Math.Abs(dLatitude) - HALF_PI) <= EPSLN)
throw new ArgumentException("Transformation cannot be computed at the poles.");
double esinphi = _e * Math.Sin(dLatitude);
lon = _semiMajor * _k0 * (dLongitude - central_meridian);
lat = _semiMajor * _k0 * Math.Log(Math.Tan(PI * 0.25 + dLatitude * 0.5) *
Math.Pow((1 - esinphi) / (1 + esinphi), _e * 0.5));
}
/// <summary>
/// Converts coordinates in projected meters to decimal degrees.
/// </summary>
/// <param name="x">The x-ordinate in projected meters</param>
/// <param name="y">The y-ordinate in projected meters</param>
/// <returns>Transformed point in decimal degrees</returns>
protected override void MetersToRadians(ref double x, ref double y)
{
/* Inverse equations
-----------------*/
double dX = x; // * _metersPerUnit - this._falseEasting;
double dY = y; // * _metersPerUnit - this._falseNorthing;
double ts = Math.Exp(-dY / (_semiMajor * _k0)); //t
double chi = HALF_PI - 2 * Math.Atan(ts);
double e4 = Math.Pow(_e, 4);
double e6 = Math.Pow(_e, 6);
double e8 = Math.Pow(_e, 8);
y = chi + (_es * 0.5 + 5 * e4 / 24 + e6 / 12 + 13 * e8 / 360) * Math.Sin(2 * chi)
+ (7 * e4 / 48 + 29 * e6 / 240 + 811 * e8 / 11520) * Math.Sin(4 * chi) +
+(7 * e6 / 120 + 81 * e8 / 1120) * Math.Sin(6 * chi) +
+(4279 * e8 / 161280) * Math.Sin(8 * chi);
x = dX / (_semiMajor * _k0) + central_meridian;
//return (x, y, z);
}
/// <summary>
/// Returns the inverse of this projection.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current projection.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
_inverse = new Mercator(_Parameters.ToProjectionParameter(), this);
return _inverse;
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// Implements the Mercator projection.
/// </summary>
/// <remarks>
/// <para>This map projection introduced in 1569 by Gerardus Mercator. It is often described as a cylindrical projection,
/// but it must be derived mathematically. The meridians are equally spaced, parallel vertical lines, and the
/// parallels of latitude are parallel, horizontal straight lines, spaced farther and farther apart as their distance
/// from the Equator increases. This projection is widely used for navigation charts, because any straight line
/// on a Mercator-projection map is a line of constant true bearing that enables a navigator to plot a straight-line
/// course. It is less practical for world maps because the scale is distorted; areas farther away from the equator
/// appear disproportionately large. On a Mercator projection, for example, the landmass of Greenland appears to be
/// greater than that of the continent of South America; in actual area, Greenland is smaller than the Arabian Peninsula.
/// </para>
/// </remarks>
[Serializable]
internal class Mercator : MapProjection
{
//double lon_center; //Center longitude (projection center)
//double lat_origin; //center latitude
//double e,e2; //eccentricity constants
private readonly double _k0; //small value m
/// <summary>
/// Initializes the MercatorProjection object with the specified parameters to project points.
/// </summary>
/// <param name="parameters">ParameterList with the required parameters.</param>
/// <remarks>
/// </remarks>
public Mercator(IEnumerable<ProjectionParameter> parameters)
: this(parameters, null)
{
}
/// <summary>
/// Initializes the MercatorProjection object with the specified parameters.
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <param name="isInverse">Indicates whether the projection forward (meters to degrees or degrees to meters).</param>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>central_meridian</term><description>The longitude of the point from which the values of both the geographical coordinates on the ellipsoid and the grid coordinates on the projection are deemed to increment or decrement for computational purposes. Alternatively it may be considered as the longitude of the point which in the absence of application of false coordinates has grid coordinates of (0,0).</description></item>
/// <item><term>latitude_of_origin</term><description>The latitude of the point from which the values of both the geographical coordinates on the ellipsoid and the grid coordinates on the projection are deemed to increment or decrement for computational purposes. Alternatively it may be considered as the latitude of the point which in the absence of application of false coordinates has grid coordinates of (0,0).</description></item>
/// <item><term>scale_factor</term><description>The factor by which the map grid is reduced or enlarged during the projection process, defined by its value at the natural origin.</description></item>
/// <item><term>false_easting</term><description>Since the natural origin may be at or near the centre of the projection and under normal coordinate circumstances would thus give rise to negative coordinates over parts of the mapped area, this origin is usually given false coordinates which are large enough to avoid this inconvenience. The False Easting, FE, is the easting value assigned to the abscissa (east).</description></item>
/// <item><term>false_northing</term><description>Since the natural origin may be at or near the centre of the projection and under normal coordinate circumstances would thus give rise to negative coordinates over parts of the mapped area, this origin is usually given false coordinates which are large enough to avoid this inconvenience. The False Northing, FN, is the northing value assigned to the ordinate.</description></item>
/// </list>
/// </remarks>
protected Mercator(IEnumerable<ProjectionParameter> parameters, Mercator isInverse)
: base(parameters, isInverse)
{
Authority = "EPSG";
var scaleFactor = GetParameter("scale_factor");
if (scaleFactor == null) //This is a two standard parallel Mercator projection (2SP)
{
_k0 = Math.Cos(lat_origin) / Math.Sqrt(1.0 - _es * Math.Sin(lat_origin) * Math.Sin(lat_origin));
AuthorityCode = 9805;
Name = "Mercator_2SP";
}
else //This is a one standard parallel Mercator projection (1SP)
{
_k0 = scaleFactor.Value;
Name = "Mercator_1SP";
}
}
/// <summary>
/// Converts coordinates in decimal degrees to projected meters.
/// </summary>
/// <param name="lon">The longitude of the point in decimal degrees.</param>
/// <param name="lat">The latitude of the point in decimal degrees.</param>
/// <returns>Point in projected meters</returns>
protected override void RadiansToMeters(ref double lon, ref double lat)
{
if (double.IsNaN(lon) || double.IsNaN(lat))
{
lon = double.NaN;
lat = double.NaN;
return;
}
double dLongitude = lon;
double dLatitude = lat;
/* Forward equations */
if (Math.Abs(Math.Abs(dLatitude) - HALF_PI) <= EPSLN)
throw new ArgumentException("Transformation cannot be computed at the poles.");
double esinphi = _e * Math.Sin(dLatitude);
lon = _semiMajor * _k0 * (dLongitude - central_meridian);
lat = _semiMajor * _k0 * Math.Log(Math.Tan(PI * 0.25 + dLatitude * 0.5) *
Math.Pow((1 - esinphi) / (1 + esinphi), _e * 0.5));
}
/// <summary>
/// Converts coordinates in projected meters to decimal degrees.
/// </summary>
/// <param name="x">The x-ordinate in projected meters</param>
/// <param name="y">The y-ordinate in projected meters</param>
/// <returns>Transformed point in decimal degrees</returns>
protected override void MetersToRadians(ref double x, ref double y)
{
/* Inverse equations
-----------------*/
double dX = x; // * _metersPerUnit - this._falseEasting;
double dY = y; // * _metersPerUnit - this._falseNorthing;
double ts = Math.Exp(-dY / (_semiMajor * _k0)); //t
double chi = HALF_PI - 2 * Math.Atan(ts);
double e4 = Math.Pow(_e, 4);
double e6 = Math.Pow(_e, 6);
double e8 = Math.Pow(_e, 8);
y = chi + (_es * 0.5 + 5 * e4 / 24 + e6 / 12 + 13 * e8 / 360) * Math.Sin(2 * chi)
+ (7 * e4 / 48 + 29 * e6 / 240 + 811 * e8 / 11520) * Math.Sin(4 * chi) +
+(7 * e6 / 120 + 81 * e8 / 1120) * Math.Sin(6 * chi) +
+(4279 * e8 / 161280) * Math.Sin(8 * chi);
x = dX / (_semiMajor * _k0) + central_meridian;
//return (x, y, z);
}
/// <summary>
/// Returns the inverse of this projection.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current projection.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
_inverse = new Mercator(_Parameters.ToProjectionParameter(), this);
return _inverse;
}
}
}

Просмотреть файл

@ -1,212 +1,212 @@
// Copyright 2015
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// Implements the Oblique Stereographic Projection.
/// </summary>
[Serializable]
internal class ObliqueStereographicProjection : MapProjection
{
private readonly double _globalScale;
private readonly double _reciprocGlobalScale;
private static double ITERATION_TOLERANCE = 1E-14;
private static int MAXIMUM_ITERATIONS = 15;
private static double EPSILON = 1E-6;
private double C, K, ratexp;
private double phic0, cosc0, sinc0, R2;
/// <summary>
/// Initializes the ObliqueStereographicProjection object with the specified parameters.
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>central_meridian</term><description>The longitude of the point from which the values of both the geographical coordinates on the ellipsoid and the grid coordinates on the projection are deemed to increment or decrement for computational purposes. Alternatively it may be considered as the longitude of the point which in the absence of application of false coordinates has grid coordinates of (0,0).</description></item>
/// <item><term>latitude_of_origin</term><description>The latitude of the point from which the values of both the geographical coordinates on the ellipsoid and the grid coordinates on the projection are deemed to increment or decrement for computational purposes. Alternatively it may be considered as the latitude of the point which in the absence of application of false coordinates has grid coordinates of (0,0).</description></item>
/// <item><term>scale_factor</term><description>The factor by which the map grid is reduced or enlarged during the projection process, defined by its value at the natural origin.</description></item>
/// <item><term>false_easting</term><description>Since the natural origin may be at or near the centre of the projection and under normal coordinate circumstances would thus give rise to negative coordinates over parts of the mapped area, this origin is usually given false coordinates which are large enough to avoid this inconvenience. The False Easting, FE, is the easting value assigned to the abscissa (east).</description></item>
/// <item><term>false_northing</term><description>Since the natural origin may be at or near the centre of the projection and under normal coordinate circumstances would thus give rise to negative coordinates over parts of the mapped area, this origin is usually given false coordinates which are large enough to avoid this inconvenience. The False Northing, FN, is the northing value assigned to the ordinate.</description></item>
/// </list>
/// </remarks>
public ObliqueStereographicProjection(IEnumerable<ProjectionParameter> parameters)
: this(parameters, null)
{
}
/// <summary>
/// Initializes the ObliqueStereographicProjection object with the specified parameters.
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <param name="inverse">Inverse projection</param>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>central_meridian</term><description>The longitude of the point from which the values of both the geographical coordinates on the ellipsoid and the grid coordinates on the projection are deemed to increment or decrement for computational purposes. Alternatively it may be considered as the longitude of the point which in the absence of application of false coordinates has grid coordinates of (0,0).</description></item>
/// <item><term>latitude_of_origin</term><description>The latitude of the point from which the values of both the geographical coordinates on the ellipsoid and the grid coordinates on the projection are deemed to increment or decrement for computational purposes. Alternatively it may be considered as the latitude of the point which in the absence of application of false coordinates has grid coordinates of (0,0).</description></item>
/// <item><term>scale_factor</term><description>The factor by which the map grid is reduced or enlarged during the projection process, defined by its value at the natural origin.</description></item>
/// <item><term>false_easting</term><description>Since the natural origin may be at or near the centre of the projection and under normal coordinate circumstances would thus give rise to negative coordinates over parts of the mapped area, this origin is usually given false coordinates which are large enough to avoid this inconvenience. The False Easting, FE, is the easting value assigned to the abscissa (east).</description></item>
/// <item><term>false_northing</term><description>Since the natural origin may be at or near the centre of the projection and under normal coordinate circumstances would thus give rise to negative coordinates over parts of the mapped area, this origin is usually given false coordinates which are large enough to avoid this inconvenience. The False Northing, FN, is the northing value assigned to the ordinate.</description></item>
/// </list>
/// </remarks>
public ObliqueStereographicProjection(IEnumerable<ProjectionParameter> parameters, ObliqueStereographicProjection inverse)
: base(parameters, inverse)
{
_globalScale = scale_factor * _semiMajor;
_reciprocGlobalScale = 1 / _globalScale;
double sphi = Math.Sin(lat_origin);
double cphi = Math.Cos(lat_origin);
cphi *= cphi;
R2 = 2.0 * Math.Sqrt(1 - _es) / (1 - _es * sphi * sphi);
C = Math.Sqrt(1.0 + _es * cphi * cphi / (1.0 - _es));
phic0 = Math.Asin(sphi / C);
sinc0 = Math.Sin(phic0);
cosc0 = Math.Cos(phic0);
ratexp = 0.5 * C * _e;
K = Math.Tan(0.5 * phic0 + Math.PI / 4) / (Math.Pow(Math.Tan(0.5 * lat_origin + Math.PI / 4), C) * srat(_e * sphi, ratexp));
}
/// <summary>
/// Converts coordinates in projected meters to radians.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
protected override void MetersToRadians(ref double x, ref double y)
{
x *= _reciprocGlobalScale;
y *= _reciprocGlobalScale;
double rho = Math.Sqrt((x * x) + (y * y));
if (Math.Abs(rho) < EPSILON)
{
x = 0.0;
y = phic0;
}
else
{
double ce = 2.0 * Math.Atan2(rho, R2);
double sinc = Math.Sin(ce);
double cosc = Math.Cos(ce);
x = Math.Atan2(x * sinc, rho * cosc0 * cosc - y * sinc0
* sinc);
y = (cosc * sinc0) + (y * sinc * cosc0 / rho);
if (Math.Abs(y) >= 1.0)
{
y = (y < 0.0) ? -Math.PI / 2.0 : Math.PI / 2.0;
}
else
{
y = Math.Asin(y);
}
}
x /= C;
double num = Math.Pow(Math.Tan(0.5 * y + Math.PI / 4.0) / K, 1.0 / C);
for (int iter = MAXIMUM_ITERATIONS; ;)
{
double phi = 2.0 * Math.Atan(num * srat(_e * Math.Sin(y), -0.5 * _e)) - Math.PI / 2.0;
if (Math.Abs(phi - y) < ITERATION_TOLERANCE)
{
break;
}
y = phi;
if (--iter < 0)
{
throw new Exception("Oblique Stereographics doesn't converge");
}
}
x += central_meridian;
}
/// <summary>
/// Method to convert a point (lon, lat) in radians to (x, y) in meters
/// </summary>
/// <param name="lon">The longitude of the point in radians when entering, its x-ordinate in meters after exit.</param>
/// <param name="lat">The latitude of the point in radians when entering, its y-ordinate in meters after exit.</param>
protected override void RadiansToMeters(ref double lon, ref double lat)
{
double x = lon - central_meridian;
double y = lat;
y = 2.0 * Math.Atan(K * Math.Pow(Math.Tan(0.5 * y + Math.PI / 4), C)
* srat(_e * Math.Sin(y), ratexp))
- Math.PI / 2;
x *= C;
double sinc = Math.Sin(y);
double cosc = Math.Cos(y);
double cosl = Math.Cos(x);
double k_ = R2 / (1.0 + sinc0 * sinc + cosc0 * cosc * cosl);
lon = k_ * cosc * Math.Sin(x) * _globalScale;
lat = k_ * (cosc0 * sinc - sinc0 * cosc * cosl) * _globalScale;
}
/// <summary>
/// Returns the inverse of this projection.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current projection.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
{
_inverse = new ObliqueStereographicProjection(_Parameters.ToProjectionParameter(), this);
}
return _inverse;
}
private double srat(double esinp, double exp)
{
return Math.Pow((1.0 - esinp) / (1.0 + esinp), exp);
}
}
}
// Copyright 2015
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// Implements the Oblique Stereographic Projection.
/// </summary>
[Serializable]
internal class ObliqueStereographicProjection : MapProjection
{
private readonly double _globalScale;
private readonly double _reciprocGlobalScale;
private static double ITERATION_TOLERANCE = 1E-14;
private static int MAXIMUM_ITERATIONS = 15;
private static double EPSILON = 1E-6;
private double C, K, ratexp;
private double phic0, cosc0, sinc0, R2;
/// <summary>
/// Initializes the ObliqueStereographicProjection object with the specified parameters.
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>central_meridian</term><description>The longitude of the point from which the values of both the geographical coordinates on the ellipsoid and the grid coordinates on the projection are deemed to increment or decrement for computational purposes. Alternatively it may be considered as the longitude of the point which in the absence of application of false coordinates has grid coordinates of (0,0).</description></item>
/// <item><term>latitude_of_origin</term><description>The latitude of the point from which the values of both the geographical coordinates on the ellipsoid and the grid coordinates on the projection are deemed to increment or decrement for computational purposes. Alternatively it may be considered as the latitude of the point which in the absence of application of false coordinates has grid coordinates of (0,0).</description></item>
/// <item><term>scale_factor</term><description>The factor by which the map grid is reduced or enlarged during the projection process, defined by its value at the natural origin.</description></item>
/// <item><term>false_easting</term><description>Since the natural origin may be at or near the centre of the projection and under normal coordinate circumstances would thus give rise to negative coordinates over parts of the mapped area, this origin is usually given false coordinates which are large enough to avoid this inconvenience. The False Easting, FE, is the easting value assigned to the abscissa (east).</description></item>
/// <item><term>false_northing</term><description>Since the natural origin may be at or near the centre of the projection and under normal coordinate circumstances would thus give rise to negative coordinates over parts of the mapped area, this origin is usually given false coordinates which are large enough to avoid this inconvenience. The False Northing, FN, is the northing value assigned to the ordinate.</description></item>
/// </list>
/// </remarks>
public ObliqueStereographicProjection(IEnumerable<ProjectionParameter> parameters)
: this(parameters, null)
{
}
/// <summary>
/// Initializes the ObliqueStereographicProjection object with the specified parameters.
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <param name="inverse">Inverse projection</param>
/// <remarks>
/// <para>The parameters this projection expects are listed below.</para>
/// <list type="table">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>central_meridian</term><description>The longitude of the point from which the values of both the geographical coordinates on the ellipsoid and the grid coordinates on the projection are deemed to increment or decrement for computational purposes. Alternatively it may be considered as the longitude of the point which in the absence of application of false coordinates has grid coordinates of (0,0).</description></item>
/// <item><term>latitude_of_origin</term><description>The latitude of the point from which the values of both the geographical coordinates on the ellipsoid and the grid coordinates on the projection are deemed to increment or decrement for computational purposes. Alternatively it may be considered as the latitude of the point which in the absence of application of false coordinates has grid coordinates of (0,0).</description></item>
/// <item><term>scale_factor</term><description>The factor by which the map grid is reduced or enlarged during the projection process, defined by its value at the natural origin.</description></item>
/// <item><term>false_easting</term><description>Since the natural origin may be at or near the centre of the projection and under normal coordinate circumstances would thus give rise to negative coordinates over parts of the mapped area, this origin is usually given false coordinates which are large enough to avoid this inconvenience. The False Easting, FE, is the easting value assigned to the abscissa (east).</description></item>
/// <item><term>false_northing</term><description>Since the natural origin may be at or near the centre of the projection and under normal coordinate circumstances would thus give rise to negative coordinates over parts of the mapped area, this origin is usually given false coordinates which are large enough to avoid this inconvenience. The False Northing, FN, is the northing value assigned to the ordinate.</description></item>
/// </list>
/// </remarks>
public ObliqueStereographicProjection(IEnumerable<ProjectionParameter> parameters, ObliqueStereographicProjection inverse)
: base(parameters, inverse)
{
_globalScale = scale_factor * _semiMajor;
_reciprocGlobalScale = 1 / _globalScale;
double sphi = Math.Sin(lat_origin);
double cphi = Math.Cos(lat_origin);
cphi *= cphi;
R2 = 2.0 * Math.Sqrt(1 - _es) / (1 - _es * sphi * sphi);
C = Math.Sqrt(1.0 + _es * cphi * cphi / (1.0 - _es));
phic0 = Math.Asin(sphi / C);
sinc0 = Math.Sin(phic0);
cosc0 = Math.Cos(phic0);
ratexp = 0.5 * C * _e;
K = Math.Tan(0.5 * phic0 + Math.PI / 4) / (Math.Pow(Math.Tan(0.5 * lat_origin + Math.PI / 4), C) * srat(_e * sphi, ratexp));
}
/// <summary>
/// Converts coordinates in projected meters to radians.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
protected override void MetersToRadians(ref double x, ref double y)
{
x *= _reciprocGlobalScale;
y *= _reciprocGlobalScale;
double rho = Math.Sqrt((x * x) + (y * y));
if (Math.Abs(rho) < EPSILON)
{
x = 0.0;
y = phic0;
}
else
{
double ce = 2.0 * Math.Atan2(rho, R2);
double sinc = Math.Sin(ce);
double cosc = Math.Cos(ce);
x = Math.Atan2(x * sinc, rho * cosc0 * cosc - y * sinc0
* sinc);
y = (cosc * sinc0) + (y * sinc * cosc0 / rho);
if (Math.Abs(y) >= 1.0)
{
y = (y < 0.0) ? -Math.PI / 2.0 : Math.PI / 2.0;
}
else
{
y = Math.Asin(y);
}
}
x /= C;
double num = Math.Pow(Math.Tan(0.5 * y + Math.PI / 4.0) / K, 1.0 / C);
for (int iter = MAXIMUM_ITERATIONS; ;)
{
double phi = 2.0 * Math.Atan(num * srat(_e * Math.Sin(y), -0.5 * _e)) - Math.PI / 2.0;
if (Math.Abs(phi - y) < ITERATION_TOLERANCE)
{
break;
}
y = phi;
if (--iter < 0)
{
throw new Exception("Oblique Stereographics doesn't converge");
}
}
x += central_meridian;
}
/// <summary>
/// Method to convert a point (lon, lat) in radians to (x, y) in meters
/// </summary>
/// <param name="lon">The longitude of the point in radians when entering, its x-ordinate in meters after exit.</param>
/// <param name="lat">The latitude of the point in radians when entering, its y-ordinate in meters after exit.</param>
protected override void RadiansToMeters(ref double lon, ref double lat)
{
double x = lon - central_meridian;
double y = lat;
y = 2.0 * Math.Atan(K * Math.Pow(Math.Tan(0.5 * y + Math.PI / 4), C)
* srat(_e * Math.Sin(y), ratexp))
- Math.PI / 2;
x *= C;
double sinc = Math.Sin(y);
double cosc = Math.Cos(y);
double cosl = Math.Cos(x);
double k_ = R2 / (1.0 + sinc0 * sinc + cosc0 * cosc * cosl);
lon = k_ * cosc * Math.Sin(x) * _globalScale;
lat = k_ * (cosc0 * sinc - sinc0 * cosc * cosl) * _globalScale;
}
/// <summary>
/// Returns the inverse of this projection.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current projection.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
{
_inverse = new ObliqueStereographicProjection(_Parameters.ToProjectionParameter(), this);
}
return _inverse;
}
private double srat(double esinp, double exp)
{
return Math.Pow((1.0 - esinp) / (1.0 + esinp), exp);
}
}
}

Просмотреть файл

@ -1,164 +1,164 @@
/*
* http://svn.osgeo.org/geotools/tags/2.6.2/modules/library/referencing/src/main/java/org/geotools/referencing/operation/projection/Polyconic.java
* http://svn.osgeo.org/geotools/tags/2.6.2/modules/library/referencing/src/main/java/org/geotools/referencing/operation/projection/MapProjection.java
*/
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
///
/// </summary>
[Serializable]
internal class PolyconicProjection : MapProjection
{
/// <summary>
/// Maximum difference allowed when comparing real numbers.
/// </summary>
private const double Epsilon = 1E-10;
/// <summary>
/// Maximum number of iterations for iterative computations.
/// </summary>
private const int MaximumIterations = 20;
/// <summary>
/// Difference allowed in iterative computations.
/// </summary>
private const double IterationTolerance = 1E-12;
///<summary>
/// Meridian distance at the latitude of origin.
/// Used for calculations for the ellipsoid.
/// </summary>
private readonly double _ml0;
private readonly double _reciprocSemiMajorTimesScaleFactor;
///<summary>
/// Constructs a new map projection from the supplied parameters.
///</summary>
/// <param name="parameters">The parameter values in standard units</param>
public PolyconicProjection(IEnumerable<ProjectionParameter> parameters)
: this(parameters, null)
{ }
/// <summary>
/// Constructs a new map projection from the supplied parameters.
/// </summary>
/// <param name="parameters">The parameter values in standard units</param>
/// <param name="inverse">Defines if Projection is inverse</param>
protected PolyconicProjection(IEnumerable<ProjectionParameter> parameters, PolyconicProjection inverse)
: base(parameters, inverse)
{
_ml0 = mlfn(lat_origin, Math.Sin(lat_origin), Math.Cos(lat_origin));
_reciprocSemiMajorTimesScaleFactor = 1 / (_semiMajor * scale_factor);
}
protected override void RadiansToMeters(ref double lon, ref double lat)
{
double lam = lon;
double phi = lat;
double delta_lam = adjust_lon(lam - central_meridian);
double x, y;
if (Math.Abs(phi) <= Epsilon)
{
x = delta_lam; //lam;
y = -_ml0;
}
else
{
double sp = Math.Sin(phi);
double cp;
double ms = Math.Abs(cp = Math.Cos(phi)) > Epsilon ? msfn(sp, cp) / sp : 0.0;
/*lam =*/
delta_lam *= sp;
x = ms * Math.Sin( /*lam*/delta_lam);
y = (mlfn(phi, sp, cp) - _ml0) + ms * (1.0 - Math.Cos( /*lam*/delta_lam));
}
lon = scale_factor * _semiMajor * x;
lat = scale_factor * _semiMajor * y;
}
protected override void MetersToRadians(ref double x, ref double y)
{
x *= _reciprocSemiMajorTimesScaleFactor;
y *= _reciprocSemiMajorTimesScaleFactor;
double lam, phi;
y += _ml0;
if (Math.Abs(y) <= Epsilon)
{
lam = x;
phi = 0.0;
}
else
{
double r = y * y + x * x;
phi = y;
int iter = 0;
for (; iter <= MaximumIterations; iter++)
{
double sp = Math.Sin(phi);
double cp = Math.Cos(phi);
if (Math.Abs(cp) < IterationTolerance)
throw new Exception("No Convergence");
double s2ph = sp * cp;
double mlp = Math.Sqrt(1.0 - _es * sp * sp);
double c = sp * mlp / cp;
double ml = mlfn(phi, sp, cp);
double mlb = ml * ml + r;
mlp = (1.0 - _es) / (mlp * mlp * mlp);
double dPhi = (ml + ml + c * mlb - 2.0 * y * (c * ml + 1.0)) / (
_es * s2ph * (mlb - 2.0 * y * ml) / c +
2.0 * (y - ml) * (c * mlp - 1.0 / s2ph) - mlp - mlp);
if (Math.Abs(dPhi) <= IterationTolerance)
break;
phi += dPhi;
}
if (iter > MaximumIterations)
throw new Exception("No Convergence");
double c2 = Math.Sin(phi);
lam = Math.Asin(x * Math.Tan(phi) * Math.Sqrt(1.0 - _es * c2 * c2)) / Math.Sin(phi);
}
x = adjust_lon(lam + central_meridian);
/*
* http://svn.osgeo.org/geotools/tags/2.6.2/modules/library/referencing/src/main/java/org/geotools/referencing/operation/projection/Polyconic.java
* http://svn.osgeo.org/geotools/tags/2.6.2/modules/library/referencing/src/main/java/org/geotools/referencing/operation/projection/MapProjection.java
*/
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
///
/// </summary>
[Serializable]
internal class PolyconicProjection : MapProjection
{
/// <summary>
/// Maximum difference allowed when comparing real numbers.
/// </summary>
private const double Epsilon = 1E-10;
/// <summary>
/// Maximum number of iterations for iterative computations.
/// </summary>
private const int MaximumIterations = 20;
/// <summary>
/// Difference allowed in iterative computations.
/// </summary>
private const double IterationTolerance = 1E-12;
///<summary>
/// Meridian distance at the latitude of origin.
/// Used for calculations for the ellipsoid.
/// </summary>
private readonly double _ml0;
private readonly double _reciprocSemiMajorTimesScaleFactor;
///<summary>
/// Constructs a new map projection from the supplied parameters.
///</summary>
/// <param name="parameters">The parameter values in standard units</param>
public PolyconicProjection(IEnumerable<ProjectionParameter> parameters)
: this(parameters, null)
{ }
/// <summary>
/// Constructs a new map projection from the supplied parameters.
/// </summary>
/// <param name="parameters">The parameter values in standard units</param>
/// <param name="inverse">Defines if Projection is inverse</param>
protected PolyconicProjection(IEnumerable<ProjectionParameter> parameters, PolyconicProjection inverse)
: base(parameters, inverse)
{
_ml0 = mlfn(lat_origin, Math.Sin(lat_origin), Math.Cos(lat_origin));
_reciprocSemiMajorTimesScaleFactor = 1 / (_semiMajor * scale_factor);
}
protected override void RadiansToMeters(ref double lon, ref double lat)
{
double lam = lon;
double phi = lat;
double delta_lam = adjust_lon(lam - central_meridian);
double x, y;
if (Math.Abs(phi) <= Epsilon)
{
x = delta_lam; //lam;
y = -_ml0;
}
else
{
double sp = Math.Sin(phi);
double cp;
double ms = Math.Abs(cp = Math.Cos(phi)) > Epsilon ? msfn(sp, cp) / sp : 0.0;
/*lam =*/
delta_lam *= sp;
x = ms * Math.Sin( /*lam*/delta_lam);
y = (mlfn(phi, sp, cp) - _ml0) + ms * (1.0 - Math.Cos( /*lam*/delta_lam));
}
lon = scale_factor * _semiMajor * x;
lat = scale_factor * _semiMajor * y;
}
protected override void MetersToRadians(ref double x, ref double y)
{
x *= _reciprocSemiMajorTimesScaleFactor;
y *= _reciprocSemiMajorTimesScaleFactor;
double lam, phi;
y += _ml0;
if (Math.Abs(y) <= Epsilon)
{
lam = x;
phi = 0.0;
}
else
{
double r = y * y + x * x;
phi = y;
int iter = 0;
for (; iter <= MaximumIterations; iter++)
{
double sp = Math.Sin(phi);
double cp = Math.Cos(phi);
if (Math.Abs(cp) < IterationTolerance)
throw new Exception("No Convergence");
double s2ph = sp * cp;
double mlp = Math.Sqrt(1.0 - _es * sp * sp);
double c = sp * mlp / cp;
double ml = mlfn(phi, sp, cp);
double mlb = ml * ml + r;
mlp = (1.0 - _es) / (mlp * mlp * mlp);
double dPhi = (ml + ml + c * mlb - 2.0 * y * (c * ml + 1.0)) / (
_es * s2ph * (mlb - 2.0 * y * ml) / c +
2.0 * (y - ml) * (c * mlp - 1.0 / s2ph) - mlp - mlp);
if (Math.Abs(dPhi) <= IterationTolerance)
break;
phi += dPhi;
}
if (iter > MaximumIterations)
throw new Exception("No Convergence");
double c2 = Math.Sin(phi);
lam = Math.Asin(x * Math.Tan(phi) * Math.Sqrt(1.0 - _es * c2 * c2)) / Math.Sin(phi);
}
x = adjust_lon(lam + central_meridian);
y = phi;
}
/// <summary>
/// Returns the inverse of this projection.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current projection.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
_inverse = new PolyconicProjection(_Parameters.ToProjectionParameter(), this);
return _inverse;
}
#region Private helpers
///<summary>
/// Computes function <code>f(s,c,e²) = c/sqrt(1 - s²*e²)</code> needed for the true scale
/// latitude (Snyder 14-15), where <var>s</var> and <var>c</var> are the sine and cosine of
/// the true scale latitude, and <var>e²</var> is the eccentricity squared.
///</summary>
double msfn(double s, double c)
{
return c / Math.Sqrt(1.0 - (s * s) * _es);
}
#endregion
}
}
/// <summary>
/// Returns the inverse of this projection.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current projection.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
_inverse = new PolyconicProjection(_Parameters.ToProjectionParameter(), this);
return _inverse;
}
#region Private helpers
///<summary>
/// Computes function <code>f(s,c,e²) = c/sqrt(1 - s²*e²)</code> needed for the true scale
/// latitude (Snyder 14-15), where <var>s</var> and <var>c</var> are the sine and cosine of
/// the true scale latitude, and <var>e²</var> is the eccentricity squared.
///</summary>
double msfn(double s, double c)
{
return c / Math.Sqrt(1.0 - (s * s) * _es);
}
#endregion
}
}

Просмотреть файл

@ -1,169 +1,169 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// A set of projection parameters
/// </summary>
// TODO: KeyedCollection<string, double>
[Serializable]
public class ProjectionParameterSet : Dictionary<string, double>, IEquatable<ProjectionParameterSet>
{
private readonly Dictionary<string, string> _originalNames = new Dictionary<string, string>();
private readonly Dictionary<int, string> _originalIndex = new Dictionary<int, string>();
/// <summary>
/// Needed for serialzation
/// </summary>
public ProjectionParameterSet(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
:base(info, context)
{}
/// <summary>
/// Creates an instance of this class
/// </summary>
/// <param name="parameters">An enumeration of parameters</param>
public ProjectionParameterSet(IEnumerable<ProjectionParameter> parameters)
{
foreach (var pp in parameters)
{
string key = pp.Name.ToLowerInvariant();
_originalNames.Add(key, pp.Name);
_originalIndex.Add(_originalIndex.Count, key);
Add(key, pp.Value);
}
}
/// <summary>
/// Function to create an enumeration of <see cref="ProjectionParameter"/>s of the content of this projection parameter set.
/// </summary>
/// <returns>An enumeration of <see cref="ProjectionParameter"/>s</returns>
public IEnumerable<ProjectionParameter> ToProjectionParameter()
{
foreach (var oi in _originalIndex)
yield return new ProjectionParameter(_originalNames[oi.Value], this[oi.Value]);
}
/// <summary>
/// Function to get the value of a mandatory projection parameter
/// </summary>
/// <returns>The value of the parameter</returns>
/// <param name="parameterName">The name of the parameter</param>
/// <param name="alternateNames">Possible alternate names for <paramref name="parameterName"/></param>
/// <exception cref="ArgumentException">Thrown if <paramref name="parameterName"> or any of <paramref name="alternateNames"/> is not defined.</paramref></exception>
public double GetParameterValue(string parameterName, params string[] alternateNames)
{
string name = parameterName.ToLowerInvariant();
if (!ContainsKey(name))
{
foreach (string alternateName in alternateNames)
{
double res;
if (TryGetValue(alternateName.ToLowerInvariant(), out res))
return res;
}
var sb = new StringBuilder();
sb.AppendFormat("Missing projection parameter '{0}'", parameterName);
if (alternateNames.Length > 0)
{
sb.AppendFormat("\nIt is also not defined as '{0}'", alternateNames[0]);
for (int i = 1; i < alternateNames.Length; i++)
sb.AppendFormat(", '{0}'", alternateNames[i]);
sb.Append(".");
}
throw new ArgumentException(sb.ToString(), "parameterName");
}
return this[name];
}
/// <summary>
/// Method to check if all mandatory projection parameters are passed
/// </summary>
public double GetOptionalParameterValue(string name, double value, params string[] alternateNames)
{
name = name.ToLowerInvariant();
if (!ContainsKey(name))
{
foreach (string alternateName in alternateNames)
{
double res;
if (TryGetValue(alternateName.ToLowerInvariant(), out res))
return res;
}
//Add(name, value);
return value;
}
return this[name];
}
/// <summary>
/// Function to find a parameter based on its name
/// </summary>
/// <param name="name">The name of the parameter</param>
/// <returns>The parameter if present, otherwise null</returns>
public ProjectionParameter Find(string name)
{
name = name.ToLowerInvariant();
return ContainsKey(name) ? new ProjectionParameter(_originalNames[name], this[name]) : null;
}
/// <summary>
/// Function to get the parameter at the given index
/// </summary>
/// <param name="index">The index</param>
/// <returns>The parameter</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public ProjectionParameter GetAtIndex(int index)
{
if (index < 0 || index >= Count)
using System;
using System.Collections.Generic;
using System.Text;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// A set of projection parameters
/// </summary>
// TODO: KeyedCollection<string, double>
[Serializable]
public class ProjectionParameterSet : Dictionary<string, double>, IEquatable<ProjectionParameterSet>
{
private readonly Dictionary<string, string> _originalNames = new Dictionary<string, string>();
private readonly Dictionary<int, string> _originalIndex = new Dictionary<int, string>();
/// <summary>
/// Needed for serialzation
/// </summary>
public ProjectionParameterSet(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
:base(info, context)
{}
/// <summary>
/// Creates an instance of this class
/// </summary>
/// <param name="parameters">An enumeration of parameters</param>
public ProjectionParameterSet(IEnumerable<ProjectionParameter> parameters)
{
foreach (var pp in parameters)
{
string key = pp.Name.ToLowerInvariant();
_originalNames.Add(key, pp.Name);
_originalIndex.Add(_originalIndex.Count, key);
Add(key, pp.Value);
}
}
/// <summary>
/// Function to create an enumeration of <see cref="ProjectionParameter"/>s of the content of this projection parameter set.
/// </summary>
/// <returns>An enumeration of <see cref="ProjectionParameter"/>s</returns>
public IEnumerable<ProjectionParameter> ToProjectionParameter()
{
foreach (var oi in _originalIndex)
yield return new ProjectionParameter(_originalNames[oi.Value], this[oi.Value]);
}
/// <summary>
/// Function to get the value of a mandatory projection parameter
/// </summary>
/// <returns>The value of the parameter</returns>
/// <param name="parameterName">The name of the parameter</param>
/// <param name="alternateNames">Possible alternate names for <paramref name="parameterName"/></param>
/// <exception cref="ArgumentException">Thrown if <paramref name="parameterName"> or any of <paramref name="alternateNames"/> is not defined.</paramref></exception>
public double GetParameterValue(string parameterName, params string[] alternateNames)
{
string name = parameterName.ToLowerInvariant();
if (!ContainsKey(name))
{
foreach (string alternateName in alternateNames)
{
double res;
if (TryGetValue(alternateName.ToLowerInvariant(), out res))
return res;
}
var sb = new StringBuilder();
sb.AppendFormat("Missing projection parameter '{0}'", parameterName);
if (alternateNames.Length > 0)
{
sb.AppendFormat("\nIt is also not defined as '{0}'", alternateNames[0]);
for (int i = 1; i < alternateNames.Length; i++)
sb.AppendFormat(", '{0}'", alternateNames[i]);
sb.Append(".");
}
throw new ArgumentException(sb.ToString(), "parameterName");
}
return this[name];
}
/// <summary>
/// Method to check if all mandatory projection parameters are passed
/// </summary>
public double GetOptionalParameterValue(string name, double value, params string[] alternateNames)
{
name = name.ToLowerInvariant();
if (!ContainsKey(name))
{
foreach (string alternateName in alternateNames)
{
double res;
if (TryGetValue(alternateName.ToLowerInvariant(), out res))
return res;
}
//Add(name, value);
return value;
}
return this[name];
}
/// <summary>
/// Function to find a parameter based on its name
/// </summary>
/// <param name="name">The name of the parameter</param>
/// <returns>The parameter if present, otherwise null</returns>
public ProjectionParameter Find(string name)
{
name = name.ToLowerInvariant();
return ContainsKey(name) ? new ProjectionParameter(_originalNames[name], this[name]) : null;
}
/// <summary>
/// Function to get the parameter at the given index
/// </summary>
/// <param name="index">The index</param>
/// <returns>The parameter</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public ProjectionParameter GetAtIndex(int index)
{
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException(nameof(index));
string name = _originalIndex[index];
return new ProjectionParameter(_originalNames[name], this[name]);
}
string name = _originalIndex[index];
return new ProjectionParameter(_originalNames[name], this[name]);
}
/// <summary>
/// Checks this projection parameter set with <paramref name="other"/>-
/// </summary>
/// <param name="other">The other projection parameter set.</param>
/// <returns><value>true</value> if both sets are equal.</returns>
public bool Equals(ProjectionParameterSet other)
{
if (other == null)
return false;
if (other.Count != Count)
return false;
foreach (var kvp in this)
{
if (!other.ContainsKey(kvp.Key))
return false;
double otherValue = other.GetParameterValue(kvp.Key);
if (otherValue != kvp.Value)
return false;
}
return true;
}
internal void SetParameterValue(string name, double value)
{
string key = name.ToLowerInvariant();
if (!ContainsKey(key))
{
_originalIndex.Add(_originalIndex.Count, key);
_originalNames.Add(key, name);
Add(key, value);
}
else
{
Remove(key);
Add(key, value);
}
}
}
/// <returns><value>true</value> if both sets are equal.</returns>
public bool Equals(ProjectionParameterSet other)
{
if (other == null)
return false;
if (other.Count != Count)
return false;
foreach (var kvp in this)
{
if (!other.ContainsKey(kvp.Key))
return false;
double otherValue = other.GetParameterValue(kvp.Key);
if (otherValue != kvp.Value)
return false;
}
return true;
}
internal void SetParameterValue(string name, double value)
{
string key = name.ToLowerInvariant();
if (!ContainsKey(key))
{
_originalIndex.Add(_originalIndex.Count, key);
_originalNames.Add(key, name);
Add(key, value);
}
else
{
Remove(key);
Add(key, value);
}
}
}
}

Просмотреть файл

@ -1,127 +1,127 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// Registry class for all known <see cref="MapProjection"/>s.
/// </summary>
public class ProjectionsRegistry
{
private static readonly Dictionary<string, Type> TypeRegistry = new Dictionary<string, Type>();
private static readonly Dictionary<string, Type> ConstructorRegistry = new Dictionary<string, Type>();
private static readonly object RegistryLock = new object();
/// <summary>
/// Static constructor
/// </summary>
static ProjectionsRegistry()
{
Register("mercator", typeof(Mercator));
Register("mercator_1sp", typeof (Mercator));
Register("mercator_2sp", typeof (Mercator));
Register("pseudo-mercator", typeof(PseudoMercator));
Register("popular_visualisation pseudo-mercator", typeof(PseudoMercator));
Register("google_mercator", typeof(PseudoMercator));
Register("transverse_mercator", typeof(TransverseMercator));
Register("albers", typeof(AlbersProjection));
Register("albers_conic_equal_area", typeof(AlbersProjection));
Register("krovak", typeof(KrovakProjection));
Register("polyconic", typeof(PolyconicProjection));
Register("lambert_conformal_conic", typeof(LambertConformalConic2SP));
Register("lambert_conformal_conic_2sp", typeof(LambertConformalConic2SP));
using System;
using System.Collections.Generic;
using System.Reflection;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// Registry class for all known <see cref="MapProjection"/>s.
/// </summary>
public class ProjectionsRegistry
{
private static readonly Dictionary<string, Type> TypeRegistry = new Dictionary<string, Type>();
private static readonly Dictionary<string, Type> ConstructorRegistry = new Dictionary<string, Type>();
private static readonly object RegistryLock = new object();
/// <summary>
/// Static constructor
/// </summary>
static ProjectionsRegistry()
{
Register("mercator", typeof(Mercator));
Register("mercator_1sp", typeof (Mercator));
Register("mercator_2sp", typeof (Mercator));
Register("pseudo-mercator", typeof(PseudoMercator));
Register("popular_visualisation pseudo-mercator", typeof(PseudoMercator));
Register("google_mercator", typeof(PseudoMercator));
Register("transverse_mercator", typeof(TransverseMercator));
Register("albers", typeof(AlbersProjection));
Register("albers_conic_equal_area", typeof(AlbersProjection));
Register("krovak", typeof(KrovakProjection));
Register("polyconic", typeof(PolyconicProjection));
Register("lambert_conformal_conic", typeof(LambertConformalConic2SP));
Register("lambert_conformal_conic_2sp", typeof(LambertConformalConic2SP));
Register("lambert_conic_conformal_(2sp)", typeof(LambertConformalConic2SP));
Register("lambert_azimuthal_equal_area", typeof(LambertAzimuthalEqualAreaProjection));
Register("cassini_soldner", typeof(CassiniSoldnerProjection));
Register("hotine_oblique_mercator", typeof(HotineObliqueMercatorProjection));
Register("oblique_mercator", typeof(ObliqueMercatorProjection));
Register("oblique_stereographic", typeof(ObliqueStereographicProjection));
}
/// <summary>
/// Method to register a new Map
/// </summary>
/// <param name="name"></param>
/// <param name="type"></param>
public static void Register(string name, Type type)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentNullException(nameof(name));
if (type == null)
throw new ArgumentNullException(nameof(type));
if (!typeof(MathTransform).IsAssignableFrom(type))
throw new ArgumentException("The provided type does not implement 'GeoAPI.CoordinateSystems.Transformations.IMathTransform'!", nameof(type));
var ci = CheckConstructor(type);
if (ci == null)
throw new ArgumentException("The provided type is lacking a suitable constructor", nameof(type));
string key = name.ToLowerInvariant().Replace(' ', '_');
lock (RegistryLock)
{
if (TypeRegistry.ContainsKey(key))
{
var rt = TypeRegistry[key];
if (ReferenceEquals(type, rt))
return;
throw new ArgumentException("A different projection type has been registered with this name", "name");
}
TypeRegistry.Add(key, type);
ConstructorRegistry.Add(key, ci);
}
}
private static Type CheckConstructor(Type type)
{
// find a constructor that accepts exactly one parameter that's an
// instance of List<ProjectionParameter>, and then return the exact
// parameter type so that we can create instances of this type with
// minimal copying in the future, when possible.
foreach (var c in type.GetConstructors())
{
var parameters = c.GetParameters();
if (parameters.Length == 1 && parameters[0].ParameterType.IsAssignableFrom(typeof(List<ProjectionParameter>)))
{
return parameters[0].ParameterType;
}
}
return null;
}
internal static MathTransform CreateProjection(string className, IEnumerable<ProjectionParameter> parameters)
{
string key = className.ToLowerInvariant().Replace(' ', '_');
Type projectionType;
Type ci;
lock (RegistryLock)
{
if (!TypeRegistry.TryGetValue(key, out projectionType))
throw new NotSupportedException($"Projection {className} is not supported.");
ci = ConstructorRegistry[key];
}
if (!ci.IsInstanceOfType(parameters))
{
parameters = new List<ProjectionParameter>(parameters);
}
return (MathTransform) Activator.CreateInstance(projectionType, parameters);
}
}
Register("cassini_soldner", typeof(CassiniSoldnerProjection));
Register("hotine_oblique_mercator", typeof(HotineObliqueMercatorProjection));
Register("oblique_mercator", typeof(ObliqueMercatorProjection));
Register("oblique_stereographic", typeof(ObliqueStereographicProjection));
}
/// <summary>
/// Method to register a new Map
/// </summary>
/// <param name="name"></param>
/// <param name="type"></param>
public static void Register(string name, Type type)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentNullException(nameof(name));
if (type == null)
throw new ArgumentNullException(nameof(type));
if (!typeof(MathTransform).IsAssignableFrom(type))
throw new ArgumentException("The provided type does not implement 'GeoAPI.CoordinateSystems.Transformations.IMathTransform'!", nameof(type));
var ci = CheckConstructor(type);
if (ci == null)
throw new ArgumentException("The provided type is lacking a suitable constructor", nameof(type));
string key = name.ToLowerInvariant().Replace(' ', '_');
lock (RegistryLock)
{
if (TypeRegistry.ContainsKey(key))
{
var rt = TypeRegistry[key];
if (ReferenceEquals(type, rt))
return;
throw new ArgumentException("A different projection type has been registered with this name", "name");
}
TypeRegistry.Add(key, type);
ConstructorRegistry.Add(key, ci);
}
}
private static Type CheckConstructor(Type type)
{
// find a constructor that accepts exactly one parameter that's an
// instance of List<ProjectionParameter>, and then return the exact
// parameter type so that we can create instances of this type with
// minimal copying in the future, when possible.
foreach (var c in type.GetConstructors())
{
var parameters = c.GetParameters();
if (parameters.Length == 1 && parameters[0].ParameterType.IsAssignableFrom(typeof(List<ProjectionParameter>)))
{
return parameters[0].ParameterType;
}
}
return null;
}
internal static MathTransform CreateProjection(string className, IEnumerable<ProjectionParameter> parameters)
{
string key = className.ToLowerInvariant().Replace(' ', '_');
Type projectionType;
Type ci;
lock (RegistryLock)
{
if (!TypeRegistry.TryGetValue(key, out projectionType))
throw new NotSupportedException($"Projection {className} is not supported.");
ci = ConstructorRegistry[key];
}
if (!ci.IsInstanceOfType(parameters))
{
parameters = new List<ProjectionParameter>(parameters);
}
return (MathTransform) Activator.CreateInstance(projectionType, parameters);
}
}
}

Просмотреть файл

@ -1,254 +1,254 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// Summary description for MathTransform.
/// </summary>
/// <remarks>
/// <para>Universal (UTM) and Modified (MTM) Transverses Mercator projections. This
/// is a cylindrical projection, in which the cylinder has been rotated 90°.
/// Instead of being tangent to the equator (or to an other standard latitude),
/// it is tangent to a central meridian. Deformation are more important as we
/// are going further from the central meridian. The Transverse Mercator
/// projection is appropriate for region witch have a greater extent north-south
/// than east-west.</para>
///
/// <para>Reference: John P. Snyder (Map Projections - A Working Manual,
/// U.S. Geological Survey Professional Paper 1395, 1987)</para>
/// </remarks>
[Serializable]
internal class TransverseMercator : MapProjection
{
// /*
// * Maximum number of iterations for iterative computations.
// */
// private const int MAXIMUM_ITERATIONS = 15;
// /*
// * Relative iteration precision used in the {@code mlfn} method.
// * This overrides the value in the {@link MapProjection} class.
// */
// private const double ITERATION_TOLERANCE = 1E-11;
/*
* Maximum difference allowed when comparing real numbers.
*/
private const double EPSILON = 1E-6;
// /*
// * Maximum difference allowed when comparing latitudes.
// */
// private const double EPSILON_LATITUDE = 1E-10;
/*
* A derived quantity of eccentricity, computed by <code>e'² = (²-²)/² = es/(1-es)</code>
* where <c>a</c> is the semi-major axis length and <c>b</c> is the semi-minor axis
* length.
*/
private readonly double _esp;
/*
* Meridian distance at the {@code latitudeOfOrigin}.
* Used for calculations for the ellipsoid.
*/
private readonly double _ml0;
private readonly double _reciprocSemiMajor;
/*
* Constants used for the forward and inverse transform for the elliptical
* case of the Transverse Mercator.
*/
private const double FC1= 1.00000000000000000000000, // 1/1
FC2= 0.50000000000000000000000, // 1/2
FC3= 0.16666666666666666666666, // 1/6
FC4= 0.08333333333333333333333, // 1/12
FC5= 0.05000000000000000000000, // 1/20
FC6= 0.03333333333333333333333, // 1/30
FC7= 0.02380952380952380952380, // 1/42
FC8= 0.01785714285714285714285; // 1/56
// // Variables common to all subroutines in this code file
// // -----------------------------------------------------
// private double esp; /* eccentricity constants */
// private double ml0; /* small value m */
/// <summary>
/// Creates an instance of an TransverseMercatorProjection projection object.
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
public TransverseMercator(IEnumerable<ProjectionParameter> parameters)
: this(parameters, null)
{
}
/// <summary>
/// Creates an instance of an TransverseMercatorProjection projection object.
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <param name="inverse">Flag indicating wether is a forward/projection (false) or an inverse projection (true).</param>
/// <remarks>
/// <list type="bullet">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>semi_major</term><description>Semi major radius</description></item>
/// <item><term>semi_minor</term><description>Semi minor radius</description></item>
/// <item><term>scale_factor</term><description></description></item>
/// <item><term>central meridian</term><description></description></item>
/// <item><term>latitude_origin</term><description></description></item>
/// <item><term>false_easting</term><description></description></item>
/// <item><term>false_northing</term><description></description></item>
/// </list>
/// </remarks>
protected TransverseMercator(IEnumerable<ProjectionParameter> parameters, TransverseMercator inverse)
: base(parameters, inverse)
{
Name = "Transverse_Mercator";
Authority = "EPSG";
AuthorityCode = 9807;
_esp = _es / (1.0 - _es);
_ml0 = mlfn(lat_origin, Math.Sin(lat_origin), Math.Cos(lat_origin));
/*
e = Math.Sqrt(_es);
ml0 = _semiMajor*mlfn(lat_origin, Math.Sin(lat_origin), Math.Cos(lat_origin));
esp = _es / (1.0 - _es);
*/
_reciprocSemiMajor = 1 / _semiMajor;
}
/// <summary>
/// Converts coordinates in radians to projected meters.
/// </summary>
/// <param name="lon">The longitude of the point in radians.</param>
/// <param name="lat">The latitude of the point in radians.</param>
/// <returns>Point in projected meters</returns>
protected override void RadiansToMeters(ref double lon, ref double lat)
{
double x = lon;
x = adjust_lon(x - central_meridian);
double y = lat;
double sinphi = Math.Sin(y);
double cosphi = Math.Cos(y);
double t = (Math.Abs(cosphi) > EPSILON) ? sinphi / cosphi : 0;
t *= t;
double al = cosphi * x;
double als = al * al;
al /= Math.Sqrt(1.0 - _es * sinphi * sinphi);
double n = _esp * cosphi * cosphi;
/* NOTE: meridinal distance at latitudeOfOrigin is always 0 */
y = (mlfn(y, sinphi, cosphi) - _ml0 +
sinphi * al * x *
FC2 * (1.0 +
FC4 * als * (5.0 - t + n * (9.0 + 4.0 * n) +
FC6 * als * (61.0 + t * (t - 58.0) + n * (270.0 - 330.0 * t) +
FC8 * als * (1385.0 + t * (t * (543.0 - t) - 3111.0))))));
x = al * (FC1 + FC3 * als * (1.0 - t + n +
FC5 * als * (5.0 + t * (t - 18.0) + n * (14.0 - 58.0 * t) +
FC7 * als * (61.0 + t * (t * (179.0 - t) - 479.0)))));
lon = scale_factor*_semiMajor*x;
lat = scale_factor*_semiMajor*y;
}
/// <summary>
/// Converts coordinates in projected meters to radians.
/// </summary>
/// <param name="x">The x-ordinate of the point</param>
/// <param name="y">The y-ordinate of the point</param>
/// <returns>Transformed point in decimal degrees</returns>
protected override void MetersToRadians(ref double x, ref double y)
{
x *= _reciprocSemiMajor;
y *= _reciprocSemiMajor;
double phi = inv_mlfn(_ml0 + y / scale_factor);
if (Math.Abs(phi) >= PI / 2)
{
y = y < 0.0 ? -(PI / 2) : (PI / 2);
x = 0.0;
}
else
{
double sinphi = Math.Sin(phi);
double cosphi = Math.Cos(phi);
double t = (Math.Abs(cosphi) > EPSILON) ? sinphi / cosphi : 0.0;
double n = _esp * cosphi * cosphi;
double con = 1.0 - _es * sinphi * sinphi;
double d = x * Math.Sqrt(con) / scale_factor;
con *= t;
t *= t;
double ds = d * d;
y = phi - (con * ds / (1.0 - _es)) *
FC2 * (1.0 - ds *
FC4 * (5.0 + t * (3.0 - 9.0 * n) + n * (1.0 - 4 * n) - ds *
FC6 * (61.0 + t * (90.0 - 252.0 * n + 45.0 * t) + 46.0 * n - ds *
FC8 * (1385.0 + t * (3633.0 + t * (4095.0 + 1574.0 * t))))));
x = adjust_lon(central_meridian + d * (FC1 - ds * FC3 * (1.0 + 2.0 * t + n -
ds * FC5 * (5.0 + t * (28.0 + 24 * t + 8.0 * n) + 6.0 * n -
ds * FC7 * (61.0 + t * (662.0 + t * (1320.0 + 720.0 * t)))))) / cosphi);
}
}
/// <summary>
/// Returns the inverse of this projection.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current projection.</returns>
public override MathTransform Inverse()
{
if (_inverse==null)
_inverse = new TransverseMercator(_Parameters.ToProjectionParameter(), this);
return _inverse;
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Collections.Generic;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.CoordinateSystems.Projections
{
/// <summary>
/// Summary description for MathTransform.
/// </summary>
/// <remarks>
/// <para>Universal (UTM) and Modified (MTM) Transverses Mercator projections. This
/// is a cylindrical projection, in which the cylinder has been rotated 90°.
/// Instead of being tangent to the equator (or to an other standard latitude),
/// it is tangent to a central meridian. Deformation are more important as we
/// are going further from the central meridian. The Transverse Mercator
/// projection is appropriate for region witch have a greater extent north-south
/// than east-west.</para>
///
/// <para>Reference: John P. Snyder (Map Projections - A Working Manual,
/// U.S. Geological Survey Professional Paper 1395, 1987)</para>
/// </remarks>
[Serializable]
internal class TransverseMercator : MapProjection
{
// /*
// * Maximum number of iterations for iterative computations.
// */
// private const int MAXIMUM_ITERATIONS = 15;
// /*
// * Relative iteration precision used in the {@code mlfn} method.
// * This overrides the value in the {@link MapProjection} class.
// */
// private const double ITERATION_TOLERANCE = 1E-11;
/*
* Maximum difference allowed when comparing real numbers.
*/
private const double EPSILON = 1E-6;
// /*
// * Maximum difference allowed when comparing latitudes.
// */
// private const double EPSILON_LATITUDE = 1E-10;
/*
* A derived quantity of eccentricity, computed by <code>e'² = (²-²)/² = es/(1-es)</code>
* where <c>a</c> is the semi-major axis length and <c>b</c> is the semi-minor axis
* length.
*/
private readonly double _esp;
/*
* Meridian distance at the {@code latitudeOfOrigin}.
* Used for calculations for the ellipsoid.
*/
private readonly double _ml0;
private readonly double _reciprocSemiMajor;
/*
* Constants used for the forward and inverse transform for the elliptical
* case of the Transverse Mercator.
*/
private const double FC1= 1.00000000000000000000000, // 1/1
FC2= 0.50000000000000000000000, // 1/2
FC3= 0.16666666666666666666666, // 1/6
FC4= 0.08333333333333333333333, // 1/12
FC5= 0.05000000000000000000000, // 1/20
FC6= 0.03333333333333333333333, // 1/30
FC7= 0.02380952380952380952380, // 1/42
FC8= 0.01785714285714285714285; // 1/56
// // Variables common to all subroutines in this code file
// // -----------------------------------------------------
// private double esp; /* eccentricity constants */
// private double ml0; /* small value m */
/// <summary>
/// Creates an instance of an TransverseMercatorProjection projection object.
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
public TransverseMercator(IEnumerable<ProjectionParameter> parameters)
: this(parameters, null)
{
}
/// <summary>
/// Creates an instance of an TransverseMercatorProjection projection object.
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <param name="inverse">Flag indicating wether is a forward/projection (false) or an inverse projection (true).</param>
/// <remarks>
/// <list type="bullet">
/// <listheader><term>Items</term><description>Descriptions</description></listheader>
/// <item><term>semi_major</term><description>Semi major radius</description></item>
/// <item><term>semi_minor</term><description>Semi minor radius</description></item>
/// <item><term>scale_factor</term><description></description></item>
/// <item><term>central meridian</term><description></description></item>
/// <item><term>latitude_origin</term><description></description></item>
/// <item><term>false_easting</term><description></description></item>
/// <item><term>false_northing</term><description></description></item>
/// </list>
/// </remarks>
protected TransverseMercator(IEnumerable<ProjectionParameter> parameters, TransverseMercator inverse)
: base(parameters, inverse)
{
Name = "Transverse_Mercator";
Authority = "EPSG";
AuthorityCode = 9807;
_esp = _es / (1.0 - _es);
_ml0 = mlfn(lat_origin, Math.Sin(lat_origin), Math.Cos(lat_origin));
/*
e = Math.Sqrt(_es);
ml0 = _semiMajor*mlfn(lat_origin, Math.Sin(lat_origin), Math.Cos(lat_origin));
esp = _es / (1.0 - _es);
*/
_reciprocSemiMajor = 1 / _semiMajor;
}
/// <summary>
/// Converts coordinates in radians to projected meters.
/// </summary>
/// <param name="lon">The longitude of the point in radians.</param>
/// <param name="lat">The latitude of the point in radians.</param>
/// <returns>Point in projected meters</returns>
protected override void RadiansToMeters(ref double lon, ref double lat)
{
double x = lon;
x = adjust_lon(x - central_meridian);
double y = lat;
double sinphi = Math.Sin(y);
double cosphi = Math.Cos(y);
double t = (Math.Abs(cosphi) > EPSILON) ? sinphi / cosphi : 0;
t *= t;
double al = cosphi * x;
double als = al * al;
al /= Math.Sqrt(1.0 - _es * sinphi * sinphi);
double n = _esp * cosphi * cosphi;
/* NOTE: meridinal distance at latitudeOfOrigin is always 0 */
y = (mlfn(y, sinphi, cosphi) - _ml0 +
sinphi * al * x *
FC2 * (1.0 +
FC4 * als * (5.0 - t + n * (9.0 + 4.0 * n) +
FC6 * als * (61.0 + t * (t - 58.0) + n * (270.0 - 330.0 * t) +
FC8 * als * (1385.0 + t * (t * (543.0 - t) - 3111.0))))));
x = al * (FC1 + FC3 * als * (1.0 - t + n +
FC5 * als * (5.0 + t * (t - 18.0) + n * (14.0 - 58.0 * t) +
FC7 * als * (61.0 + t * (t * (179.0 - t) - 479.0)))));
lon = scale_factor*_semiMajor*x;
lat = scale_factor*_semiMajor*y;
}
/// <summary>
/// Converts coordinates in projected meters to radians.
/// </summary>
/// <param name="x">The x-ordinate of the point</param>
/// <param name="y">The y-ordinate of the point</param>
/// <returns>Transformed point in decimal degrees</returns>
protected override void MetersToRadians(ref double x, ref double y)
{
x *= _reciprocSemiMajor;
y *= _reciprocSemiMajor;
double phi = inv_mlfn(_ml0 + y / scale_factor);
if (Math.Abs(phi) >= PI / 2)
{
y = y < 0.0 ? -(PI / 2) : (PI / 2);
x = 0.0;
}
else
{
double sinphi = Math.Sin(phi);
double cosphi = Math.Cos(phi);
double t = (Math.Abs(cosphi) > EPSILON) ? sinphi / cosphi : 0.0;
double n = _esp * cosphi * cosphi;
double con = 1.0 - _es * sinphi * sinphi;
double d = x * Math.Sqrt(con) / scale_factor;
con *= t;
t *= t;
double ds = d * d;
y = phi - (con * ds / (1.0 - _es)) *
FC2 * (1.0 - ds *
FC4 * (5.0 + t * (3.0 - 9.0 * n) + n * (1.0 - 4 * n) - ds *
FC6 * (61.0 + t * (90.0 - 252.0 * n + 45.0 * t) + 46.0 * n - ds *
FC8 * (1385.0 + t * (3633.0 + t * (4095.0 + 1574.0 * t))))));
x = adjust_lon(central_meridian + d * (FC1 - ds * FC3 * (1.0 + 2.0 * t + n -
ds * FC5 * (5.0 + t * (28.0 + 24 * t + 8.0 * n) + 6.0 * n -
ds * FC7 * (61.0 + t * (662.0 + t * (1320.0 + 720.0 * t)))))) / cosphi);
}
}
/// <summary>
/// Returns the inverse of this projection.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current projection.</returns>
public override MathTransform Inverse()
{
if (_inverse==null)
_inverse = new TransverseMercator(_Parameters.ToProjectionParameter(), this);
return _inverse;
}
}
}

Просмотреть файл

@ -1,488 +1,488 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
/// Represents affine math transform which transforms input coordinates to target using affine transformation matrix. Dimensionality might change.
/// </summary>
///<remarks>If the transform's input dimension is M, and output dimension is N, then the matrix will have size [N+1][M+1].
///The +1 in the matrix dimensions allows the matrix to do a shift, as well as a rotation.
///The [M][j] element of the matrix will be the j'th ordinate of the moved origin.
///The [i][N] element of the matrix will be 0 for i less than M, and 1 for i equals M.</remarks>
/// <seealso href="http://en.wikipedia.org/wiki/Affine_transformation"/>
[Serializable]
public class AffineTransform : MathTransform
{
#region class variables
/// <summary>
/// Saved inverse transform
/// </summary>
private MathTransform _inverse;
/// <summary>
/// Dimension of source points - it's related to number of transformation matrix rows
/// </summary>
private readonly int _dimSource;
/// <summary>
/// Dimension of output points - it's related to number of columns
/// </summary>
private readonly int _dimTarget;
/// <summary>
/// Represents transform matrix of this affine transformation from input points to output ones using dimensionality defined within the affine transform
/// Number of rows = dimTarget + 1
/// Number of columns = dimSource + 1
/// </summary>
private readonly double[,] _transformMatrix;
#endregion class variables
#region constructors & finalizers
/// <summary>
/// Creates instance of 2D affine transform (source dimensionality 2, target dimensionality 2) using the specified values
/// </summary>
/// <param name="m00">Value for row 0, column 0 - AKA ScaleX</param>
/// <param name="m01">Value for row 0, column 1 - AKA ShearX</param>
/// <param name="m02">Value for row 0, column 2 - AKA Translate X</param>
/// <param name="m10">Value for row 1, column 0 - AKA Shear Y</param>
/// <param name="m11">Value for row 1, column 1 - AKA Scale Y</param>
/// <param name="m12">Value for row 1, column 2 - AKA Translate Y</param>
public AffineTransform(double m00, double m01, double m02, double m10, double m11, double m12)
{
//fill dimensionlity
_dimSource = 2;
_dimTarget = 2;
//create matrix - 2D affine transform uses 3x3 matrix (3rd row is the special one)
_transformMatrix = new [,] { { m00, m01, m02 }, { m10, m11, m12 }, { 0, 0, 1 } };
}
/// <summary>
/// Creates instance of affine transform using the specified matrix.
/// </summary>
/// <remarks>If the transform's input dimension is M, and output dimension is N, then the matrix will have size [N+1][M+1].
/// The +1 in the matrix dimensions allows the matrix to do a shift, as well as a rotation. The [M][j] element of the matrix will be the j'th ordinate of the moved origin. The [i][N] element of the matrix will be 0 for i less than M, and 1 for i equals M.</remarks>
///
/// <param name="matrix">Matrix used to create afiine transform</param>
public AffineTransform(double[,] matrix)
{
//check validity
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.GetLength(0) <= 1)
{
throw new ArgumentException("Transformation matrix must have at least 2 rows.");
}
if (matrix.GetLength(1) <= 1)
{
throw new ArgumentException("Transformation matrix must have at least 2 columns.");
}
//fill dimensionlity - dimension is M, and output dimension is N, then the matrix will have size [N+1][M+1].
_dimSource = matrix.GetLength(1) - 1;
_dimTarget = matrix.GetLength(0) - 1;
//use specified matrix
_transformMatrix = matrix;
}
#endregion constructors & finalizers
#region public properties
/// <summary>
/// Gets a Well-Known text representation of this affine math transformation.
/// </summary>
/// <value></value>
public override string WKT
{
get
{
//PARAM_MT["Affine",
// PARAMETER["num_row",3],
// PARAMETER["num_col",3],
// PARAMETER["elt_0_1",1],
// PARAMETER["elt_0_2",2],
// PARAMETER["elt 1 2",3]]
var sb = new StringBuilder();
sb.Append("PARAM_MT[\"Affine\"");
//append parameters
foreach (var param in GetParameterValues())
{
sb.Append(",");
sb.Append(param.WKT);
}
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this affine transformation.
/// </summary>
/// <value></value>
public override string XML
{
get { throw new NotImplementedException("The method or operation is not implemented."); }
}
/// <summary>
/// Gets the dimension of input points.
/// </summary>
public override int DimSource { get { return _dimSource; } }
/// <summary>
/// Gets the dimension of output points.
/// </summary>
public override int DimTarget { get { return _dimTarget; } }
#endregion public properties
#region private methods
/// <summary>
/// Return affine transformation matrix as group of parameter values that maiy be used for retrieving WKT of this affine transform
/// </summary>
/// <returns>List of string pairs NAME VALUE</returns>
private IList<ProjectionParameter> GetParameterValues()
{
int rowCnt = _transformMatrix.GetLength(0);
int colCnt = _transformMatrix.GetLength(1);
var pInfo = new List<ProjectionParameter>();
pInfo.Add(new ProjectionParameter("num_row", rowCnt));
pInfo.Add(new ProjectionParameter("num_col", colCnt));
//fill matrix values
for (int row = 0; row < rowCnt; row++)
{
for (int col = 0; col < colCnt; col++)
{
string name = string.Format(CultureInfo.InvariantCulture.NumberFormat, "elt_{0}_{1}", row, col);
pInfo.Add(new ProjectionParameter(name, _transformMatrix[row, col]));
}
}
return pInfo;
}
/// <summary>
/// Given L,U,P and b solve for x.
/// Input the L and U matrices as a single matrix LU.
/// Return the solution as a double[].
/// LU will be a n+1xm+1 matrix where the first row and columns are zero.
/// This is for ease of computation and consistency with Cormen et al.
/// pseudocode.
/// The pi array represents the permutation matrix.
/// </summary>
/// <seealso href="http://www.rkinteractive.com/blogs/SoftwareDevelopment/post/2013/05/14/Algorithms-In-C-Solving-A-System-Of-Linear-Equations.aspx"/>
/// <param name="LU"></param>
/// <param name="pi"></param>
/// <param name="b"></param>
/// <returns></returns>
private static double[] LUPSolve(double[,] LU, int[] pi, double[] b)
{
int n = LU.GetLength(0) - 1;
double[] x = new double[n + 1];
double[] y = new double[n + 1];
/*
* Solve for y using formward substitution
* */
for (int i = 0; i <= n; i++)
{
double suml = 0;
for (int j = 0; j <= i - 1; j++)
{
/*
* Since we've taken L and U as a singular matrix as an input
* the value for L at index i and j will be 1 when i equals j, not LU[i][j], since
* the diagonal values are all 1 for L.
* */
double lij;
if (i == j)
{
lij = 1;
}
else
{
lij = LU[i, j];
}
suml += lij * y[j];
}
y[i] = b[pi[i]] - suml;
}
//Solve for x by using back substitution
for (int i = n; i >= 0; i--)
{
double sumu = 0;
for (int j = i + 1; j <= n; j++)
{
sumu += LU[i, j] * x[j];
}
x[i] = (y[i] - sumu) / LU[i, i];
}
return x;
}
/// <summary>
/// Perform LUP decomposition on a matrix A.
/// Return P as an array of ints and L and U are just in A, "in place".
/// In order to make some of the calculations more straight forward and to
/// match Cormen's et al. pseudocode the matrix A should have its first row and first columns
/// to be all 0.
/// </summary>
/// <seealso href="http://www.rkinteractive.com/blogs/SoftwareDevelopment/post/2013/05/07/Algorithms-In-C-LUP-Decomposition.aspx"/>
/// <param name="A"></param>
/// <returns></returns>
private static int[] LUPDecomposition(double[,] A)
{
int n = A.GetLength(0) - 1;
/*
* pi represents the permutation matrix. We implement it as an array
* whose value indicates which column the 1 would appear. We use it to avoid
* dividing by zero or small numbers.
* */
int[] pi = new int[n + 1];
int kp = 0;
//Initialize the permutation matrix, will be the identity matrix
for (int j = 0; j <= n; j++)
{
pi[j] = j;
}
for (int k = 0; k <= n; k++)
{
/*
* In finding the permutation matrix p that avoids dividing by zero
* we take a slightly different approach. For numerical stability
* We find the element with the largest
* absolute value of those in the current first column (column k). If all elements in
* the current first column are zero then the matrix is singluar and throw an
* error.
* */
double p = 0;
for (int i = k; i <= n; i++)
{
if (Math.Abs(A[i, k]) > p)
{
p = Math.Abs(A[i, k]);
kp = i;
}
}
if (p == 0)
{
throw new Exception("singular matrix");
}
/*
* These lines update the pivot array (which represents the pivot matrix)
* by exchanging pi[k] and pi[kp].
* */
int pik = pi[k];
int pikp = pi[kp];
pi[k] = pikp;
pi[kp] = pik;
/*
* Exchange rows k and kpi as determined by the pivot
* */
for (int i = 0; i <= n; i++)
{
double aki = A[k, i];
double akpi = A[kp, i];
A[k, i] = akpi;
A[kp, i] = aki;
}
/*
* Compute the Schur complement
* */
for (int i = k + 1; i <= n; i++)
{
A[i, k] = A[i, k] / A[k, k];
for (int j = k + 1; j <= n; j++)
{
A[i, j] = A[i, j] - (A[i, k] * A[k, j]);
}
}
}
return pi;
}
/// <summary>
/// Given an nXn matrix A, solve n linear equations to find the inverse of A.
/// </summary>
/// <seealso href="http://www.rkinteractive.com/blogs/SoftwareDevelopment/post/2013/05/21/Algorithms-In-C-Finding-The-Inverse-Of-A-Matrix.aspx"/>
/// <param name="A"></param>
/// <returns></returns>
private static double[,] InvertMatrix(double[,] A)
{
int n = A.GetLength(0);
int m = A.GetLength(1);
//x will hold the inverse matrix to be returned
double[,] x = new double[n, m];
/*
* solve will contain the vector solution for the LUP decomposition as we solve
* for each vector of x. We will combine the solutions into the double[][] array x.
* */
double[] solve;
//Get the LU matrix and P matrix (as an array)
int[] P = LUPDecomposition(A);
double[,] LU = A;
/*
* Solve AX = e for each column ei of the identity matrix using LUP decomposition
* */
for (int i = 0; i < n; i++)
{
//e will represent each column in the identity matrix
double[] e = new double[m];
e[i] = 1;
solve = LUPSolve(LU, P, e);
for (int j = 0; j < solve.Length; j++)
{
x[j, i] = solve[j];
}
}
return x;
}
#endregion private methods
#region public methods
/// <summary>
/// Returns the inverse of this affine transformation.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current affine transformation.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
{
//find the inverse transformation matrix - use cloned matrix array
//remarks about dimensionality: if input dimension is M, and output dimension is N, then the matrix will have size [N+1][M+1].
double[,] invMatrix = InvertMatrix((double[,])_transformMatrix.Clone());
_inverse = new AffineTransform(invMatrix);
}
return _inverse;
}
/// <summary>
/// Transforms a coordinate point. The passed parameter point should not be modified.
/// </summary>
/// <param name="x">The x-ordinate value</param>
/// <param name="y">The y-ordinate value</param>
/// <param name="z">The z-ordinate value</param>
/// <returns>The converted x-, y- and z-ordinate tuple</returns>
private (double x, double y, double z) TransformAffine(double x, double y, double z)
{
//check source dimensionality - allow coordinate clipping, if source dimensionality is greater then expected source dimensionality of affine transformation
Span<double> point = stackalloc double[0];
switch (_dimSource)
{
case 0:
point = default;
break;
case 1:
point = stackalloc double[] { x };
break;
case 2:
point = stackalloc double[] { x, y };
break;
case 3:
point = stackalloc double[] { x, y, z };
break;
default:
throw new NotSupportedException();
}
if (_dimTarget > 3)
{
throw new NotSupportedException();
}
//use transformation matrix to create output points that has dimTarget dimensionality
Span<double> transformed = stackalloc double[_dimTarget];
//count each target dimension using the apropriate row
for (int row = 0; row < _dimTarget; row++)
{
//start with the last value which is in fact multiplied by 1
double dimVal = _transformMatrix[row, _dimSource];
for (int col = 0; col < _dimSource; col++)
{
dimVal += _transformMatrix[row, col] * point[col];
}
transformed[row] = dimVal;
}
(double x, double y, double z) ret = default;
if (transformed.Length > 2)
{
ret.z = transformed[2];
}
if (transformed.Length > 1)
{
ret.y = transformed[1];
}
if (transformed.Length > 0)
{
ret.x = transformed[0];
}
return ret;
}
/// <inheritdoc />
public override void Transform(ref double x, ref double y, ref double z)
{
(x, y, z) = TransformAffine(x, y, z);
}
/// <summary>
/// Reverses the transformation
/// </summary>
public override void Invert()
{
throw new NotSupportedException("The method or operation is not supported.");
}
/// <summary>
/// Returns this affine transform as an affine transform matrix.
/// </summary>
/// <returns></returns>
public double[,] GetMatrix()
{
return (double[,])this._transformMatrix.Clone();
}
#endregion public methods
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
/// Represents affine math transform which transforms input coordinates to target using affine transformation matrix. Dimensionality might change.
/// </summary>
///<remarks>If the transform's input dimension is M, and output dimension is N, then the matrix will have size [N+1][M+1].
///The +1 in the matrix dimensions allows the matrix to do a shift, as well as a rotation.
///The [M][j] element of the matrix will be the j'th ordinate of the moved origin.
///The [i][N] element of the matrix will be 0 for i less than M, and 1 for i equals M.</remarks>
/// <seealso href="http://en.wikipedia.org/wiki/Affine_transformation"/>
[Serializable]
public class AffineTransform : MathTransform
{
#region class variables
/// <summary>
/// Saved inverse transform
/// </summary>
private MathTransform _inverse;
/// <summary>
/// Dimension of source points - it's related to number of transformation matrix rows
/// </summary>
private readonly int _dimSource;
/// <summary>
/// Dimension of output points - it's related to number of columns
/// </summary>
private readonly int _dimTarget;
/// <summary>
/// Represents transform matrix of this affine transformation from input points to output ones using dimensionality defined within the affine transform
/// Number of rows = dimTarget + 1
/// Number of columns = dimSource + 1
/// </summary>
private readonly double[,] _transformMatrix;
#endregion class variables
#region constructors & finalizers
/// <summary>
/// Creates instance of 2D affine transform (source dimensionality 2, target dimensionality 2) using the specified values
/// </summary>
/// <param name="m00">Value for row 0, column 0 - AKA ScaleX</param>
/// <param name="m01">Value for row 0, column 1 - AKA ShearX</param>
/// <param name="m02">Value for row 0, column 2 - AKA Translate X</param>
/// <param name="m10">Value for row 1, column 0 - AKA Shear Y</param>
/// <param name="m11">Value for row 1, column 1 - AKA Scale Y</param>
/// <param name="m12">Value for row 1, column 2 - AKA Translate Y</param>
public AffineTransform(double m00, double m01, double m02, double m10, double m11, double m12)
{
//fill dimensionlity
_dimSource = 2;
_dimTarget = 2;
//create matrix - 2D affine transform uses 3x3 matrix (3rd row is the special one)
_transformMatrix = new [,] { { m00, m01, m02 }, { m10, m11, m12 }, { 0, 0, 1 } };
}
/// <summary>
/// Creates instance of affine transform using the specified matrix.
/// </summary>
/// <remarks>If the transform's input dimension is M, and output dimension is N, then the matrix will have size [N+1][M+1].
/// The +1 in the matrix dimensions allows the matrix to do a shift, as well as a rotation. The [M][j] element of the matrix will be the j'th ordinate of the moved origin. The [i][N] element of the matrix will be 0 for i less than M, and 1 for i equals M.</remarks>
///
/// <param name="matrix">Matrix used to create afiine transform</param>
public AffineTransform(double[,] matrix)
{
//check validity
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.GetLength(0) <= 1)
{
throw new ArgumentException("Transformation matrix must have at least 2 rows.");
}
if (matrix.GetLength(1) <= 1)
{
throw new ArgumentException("Transformation matrix must have at least 2 columns.");
}
//fill dimensionlity - dimension is M, and output dimension is N, then the matrix will have size [N+1][M+1].
_dimSource = matrix.GetLength(1) - 1;
_dimTarget = matrix.GetLength(0) - 1;
//use specified matrix
_transformMatrix = matrix;
}
#endregion constructors & finalizers
#region public properties
/// <summary>
/// Gets a Well-Known text representation of this affine math transformation.
/// </summary>
/// <value></value>
public override string WKT
{
get
{
//PARAM_MT["Affine",
// PARAMETER["num_row",3],
// PARAMETER["num_col",3],
// PARAMETER["elt_0_1",1],
// PARAMETER["elt_0_2",2],
// PARAMETER["elt 1 2",3]]
var sb = new StringBuilder();
sb.Append("PARAM_MT[\"Affine\"");
//append parameters
foreach (var param in GetParameterValues())
{
sb.Append(",");
sb.Append(param.WKT);
}
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this affine transformation.
/// </summary>
/// <value></value>
public override string XML
{
get { throw new NotImplementedException("The method or operation is not implemented."); }
}
/// <summary>
/// Gets the dimension of input points.
/// </summary>
public override int DimSource { get { return _dimSource; } }
/// <summary>
/// Gets the dimension of output points.
/// </summary>
public override int DimTarget { get { return _dimTarget; } }
#endregion public properties
#region private methods
/// <summary>
/// Return affine transformation matrix as group of parameter values that maiy be used for retrieving WKT of this affine transform
/// </summary>
/// <returns>List of string pairs NAME VALUE</returns>
private IList<ProjectionParameter> GetParameterValues()
{
int rowCnt = _transformMatrix.GetLength(0);
int colCnt = _transformMatrix.GetLength(1);
var pInfo = new List<ProjectionParameter>();
pInfo.Add(new ProjectionParameter("num_row", rowCnt));
pInfo.Add(new ProjectionParameter("num_col", colCnt));
//fill matrix values
for (int row = 0; row < rowCnt; row++)
{
for (int col = 0; col < colCnt; col++)
{
string name = string.Format(CultureInfo.InvariantCulture.NumberFormat, "elt_{0}_{1}", row, col);
pInfo.Add(new ProjectionParameter(name, _transformMatrix[row, col]));
}
}
return pInfo;
}
/// <summary>
/// Given L,U,P and b solve for x.
/// Input the L and U matrices as a single matrix LU.
/// Return the solution as a double[].
/// LU will be a n+1xm+1 matrix where the first row and columns are zero.
/// This is for ease of computation and consistency with Cormen et al.
/// pseudocode.
/// The pi array represents the permutation matrix.
/// </summary>
/// <seealso href="http://www.rkinteractive.com/blogs/SoftwareDevelopment/post/2013/05/14/Algorithms-In-C-Solving-A-System-Of-Linear-Equations.aspx"/>
/// <param name="LU"></param>
/// <param name="pi"></param>
/// <param name="b"></param>
/// <returns></returns>
private static double[] LUPSolve(double[,] LU, int[] pi, double[] b)
{
int n = LU.GetLength(0) - 1;
double[] x = new double[n + 1];
double[] y = new double[n + 1];
/*
* Solve for y using formward substitution
* */
for (int i = 0; i <= n; i++)
{
double suml = 0;
for (int j = 0; j <= i - 1; j++)
{
/*
* Since we've taken L and U as a singular matrix as an input
* the value for L at index i and j will be 1 when i equals j, not LU[i][j], since
* the diagonal values are all 1 for L.
* */
double lij;
if (i == j)
{
lij = 1;
}
else
{
lij = LU[i, j];
}
suml += lij * y[j];
}
y[i] = b[pi[i]] - suml;
}
//Solve for x by using back substitution
for (int i = n; i >= 0; i--)
{
double sumu = 0;
for (int j = i + 1; j <= n; j++)
{
sumu += LU[i, j] * x[j];
}
x[i] = (y[i] - sumu) / LU[i, i];
}
return x;
}
/// <summary>
/// Perform LUP decomposition on a matrix A.
/// Return P as an array of ints and L and U are just in A, "in place".
/// In order to make some of the calculations more straight forward and to
/// match Cormen's et al. pseudocode the matrix A should have its first row and first columns
/// to be all 0.
/// </summary>
/// <seealso href="http://www.rkinteractive.com/blogs/SoftwareDevelopment/post/2013/05/07/Algorithms-In-C-LUP-Decomposition.aspx"/>
/// <param name="A"></param>
/// <returns></returns>
private static int[] LUPDecomposition(double[,] A)
{
int n = A.GetLength(0) - 1;
/*
* pi represents the permutation matrix. We implement it as an array
* whose value indicates which column the 1 would appear. We use it to avoid
* dividing by zero or small numbers.
* */
int[] pi = new int[n + 1];
int kp = 0;
//Initialize the permutation matrix, will be the identity matrix
for (int j = 0; j <= n; j++)
{
pi[j] = j;
}
for (int k = 0; k <= n; k++)
{
/*
* In finding the permutation matrix p that avoids dividing by zero
* we take a slightly different approach. For numerical stability
* We find the element with the largest
* absolute value of those in the current first column (column k). If all elements in
* the current first column are zero then the matrix is singluar and throw an
* error.
* */
double p = 0;
for (int i = k; i <= n; i++)
{
if (Math.Abs(A[i, k]) > p)
{
p = Math.Abs(A[i, k]);
kp = i;
}
}
if (p == 0)
{
throw new Exception("singular matrix");
}
/*
* These lines update the pivot array (which represents the pivot matrix)
* by exchanging pi[k] and pi[kp].
* */
int pik = pi[k];
int pikp = pi[kp];
pi[k] = pikp;
pi[kp] = pik;
/*
* Exchange rows k and kpi as determined by the pivot
* */
for (int i = 0; i <= n; i++)
{
double aki = A[k, i];
double akpi = A[kp, i];
A[k, i] = akpi;
A[kp, i] = aki;
}
/*
* Compute the Schur complement
* */
for (int i = k + 1; i <= n; i++)
{
A[i, k] = A[i, k] / A[k, k];
for (int j = k + 1; j <= n; j++)
{
A[i, j] = A[i, j] - (A[i, k] * A[k, j]);
}
}
}
return pi;
}
/// <summary>
/// Given an nXn matrix A, solve n linear equations to find the inverse of A.
/// </summary>
/// <seealso href="http://www.rkinteractive.com/blogs/SoftwareDevelopment/post/2013/05/21/Algorithms-In-C-Finding-The-Inverse-Of-A-Matrix.aspx"/>
/// <param name="A"></param>
/// <returns></returns>
private static double[,] InvertMatrix(double[,] A)
{
int n = A.GetLength(0);
int m = A.GetLength(1);
//x will hold the inverse matrix to be returned
double[,] x = new double[n, m];
/*
* solve will contain the vector solution for the LUP decomposition as we solve
* for each vector of x. We will combine the solutions into the double[][] array x.
* */
double[] solve;
//Get the LU matrix and P matrix (as an array)
int[] P = LUPDecomposition(A);
double[,] LU = A;
/*
* Solve AX = e for each column ei of the identity matrix using LUP decomposition
* */
for (int i = 0; i < n; i++)
{
//e will represent each column in the identity matrix
double[] e = new double[m];
e[i] = 1;
solve = LUPSolve(LU, P, e);
for (int j = 0; j < solve.Length; j++)
{
x[j, i] = solve[j];
}
}
return x;
}
#endregion private methods
#region public methods
/// <summary>
/// Returns the inverse of this affine transformation.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current affine transformation.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
{
//find the inverse transformation matrix - use cloned matrix array
//remarks about dimensionality: if input dimension is M, and output dimension is N, then the matrix will have size [N+1][M+1].
double[,] invMatrix = InvertMatrix((double[,])_transformMatrix.Clone());
_inverse = new AffineTransform(invMatrix);
}
return _inverse;
}
/// <summary>
/// Transforms a coordinate point. The passed parameter point should not be modified.
/// </summary>
/// <param name="x">The x-ordinate value</param>
/// <param name="y">The y-ordinate value</param>
/// <param name="z">The z-ordinate value</param>
/// <returns>The converted x-, y- and z-ordinate tuple</returns>
private (double x, double y, double z) TransformAffine(double x, double y, double z)
{
//check source dimensionality - allow coordinate clipping, if source dimensionality is greater then expected source dimensionality of affine transformation
Span<double> point = stackalloc double[0];
switch (_dimSource)
{
case 0:
point = default;
break;
case 1:
point = stackalloc double[] { x };
break;
case 2:
point = stackalloc double[] { x, y };
break;
case 3:
point = stackalloc double[] { x, y, z };
break;
default:
throw new NotSupportedException();
}
if (_dimTarget > 3)
{
throw new NotSupportedException();
}
//use transformation matrix to create output points that has dimTarget dimensionality
Span<double> transformed = stackalloc double[_dimTarget];
//count each target dimension using the apropriate row
for (int row = 0; row < _dimTarget; row++)
{
//start with the last value which is in fact multiplied by 1
double dimVal = _transformMatrix[row, _dimSource];
for (int col = 0; col < _dimSource; col++)
{
dimVal += _transformMatrix[row, col] * point[col];
}
transformed[row] = dimVal;
}
(double x, double y, double z) ret = default;
if (transformed.Length > 2)
{
ret.z = transformed[2];
}
if (transformed.Length > 1)
{
ret.y = transformed[1];
}
if (transformed.Length > 0)
{
ret.x = transformed[0];
}
return ret;
}
/// <inheritdoc />
public override void Transform(ref double x, ref double y, ref double z)
{
(x, y, z) = TransformAffine(x, y, z);
}
/// <summary>
/// Reverses the transformation
/// </summary>
public override void Invert()
{
throw new NotSupportedException("The method or operation is not supported.");
}
/// <summary>
/// Returns this affine transform as an affine transform matrix.
/// </summary>
/// <returns></returns>
public double[,] GetMatrix()
{
return (double[,])this._transformMatrix.Clone();
}
#endregion public methods
}
}

Просмотреть файл

@ -1,160 +1,160 @@
// Copyright 2006 - Morten Nielsen (www.iter.dk)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Linq;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
///
/// </summary>
[Serializable]
internal class ConcatenatedTransform : MathTransform, ICoordinateTransformationCore
{
/// <summary>
///
/// </summary>
private MathTransform _inverse;
private readonly List<ICoordinateTransformationCore> _coordinateTransformationList;
/// <summary>
///
/// </summary>
public ConcatenatedTransform()
{ _coordinateTransformationList = new List<ICoordinateTransformationCore>();}
/// <summary>
///
/// </summary>
/// <param name="transformList"></param>
public ConcatenatedTransform(IEnumerable<ICoordinateTransformationCore> transformList)
: this()
{
_coordinateTransformationList.AddRange(transformList);
}
/// <summary>
///
/// </summary>
public IList<ICoordinateTransformationCore> CoordinateTransformationList
{
get { return _coordinateTransformationList; }
/*
set
{
_coordinateTransformationList = value;
_inverse = null;
}
*/
}
public override int DimSource
{
get { return (_coordinateTransformationList[0]).SourceCS.Dimension; }
}
public override int DimTarget
{
get { return _coordinateTransformationList[_coordinateTransformationList.Count-1].TargetCS.Dimension; }
}
/// <inheritdoc />
public override void Transform(ref double x, ref double y, ref double z)
{
foreach (var ctc in _coordinateTransformationList)
{
if (ctc is CoordinateTransformation ct)
ct.MathTransform.Transform(ref x, ref y, ref z);
else if (ctc is ConcatenatedTransform cct)
cct.Transform(ref x, ref y, ref z);
}
}
/// <summary>
/// Returns the inverse of this conversion.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current conversion.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
{
_inverse = Clone();
_inverse.Invert();
}
return _inverse;
}
/// <summary>
/// Reverses the transformation
/// </summary>
public override void Invert()
{
_coordinateTransformationList.Reverse();
foreach (var ic in _coordinateTransformationList)
{
if (ic is CoordinateTransformation ct)
ct.MathTransform.Invert();
else if (ic is ConcatenatedTransform cct)
cct.Invert();
}
}
public ConcatenatedTransform Clone()
{
var clonedList = new List<ICoordinateTransformationCore>(_coordinateTransformationList.Count);
foreach (var ct in _coordinateTransformationList)
clonedList.Add(CloneCoordinateTransformation(ct));
return new ConcatenatedTransform(clonedList);
}
private static readonly CoordinateTransformationFactory CoordinateTransformationFactory =
new CoordinateTransformationFactory();
private static ICoordinateTransformationCore CloneCoordinateTransformation(ICoordinateTransformationCore ict)
{
return CoordinateTransformationFactory.CreateFromCoordinateSystems(ict.SourceCS, ict.TargetCS);
}
/// <summary>
/// Gets a Well-Known text representation of this object.
/// </summary>
/// <value></value>
public override string WKT
{
get { throw new NotImplementedException(); }
}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
/// <value></value>
public override string XML
{
get { throw new NotImplementedException(); }
}
public CoordinateSystem SourceCS { get => CoordinateTransformationList[0].SourceCS; }
public CoordinateSystem TargetCS { get => CoordinateTransformationList[CoordinateTransformationList.Count-1].TargetCS; }
}
}
// Copyright 2006 - Morten Nielsen (www.iter.dk)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Linq;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
///
/// </summary>
[Serializable]
internal class ConcatenatedTransform : MathTransform, ICoordinateTransformationCore
{
/// <summary>
///
/// </summary>
private MathTransform _inverse;
private readonly List<ICoordinateTransformationCore> _coordinateTransformationList;
/// <summary>
///
/// </summary>
public ConcatenatedTransform()
{ _coordinateTransformationList = new List<ICoordinateTransformationCore>();}
/// <summary>
///
/// </summary>
/// <param name="transformList"></param>
public ConcatenatedTransform(IEnumerable<ICoordinateTransformationCore> transformList)
: this()
{
_coordinateTransformationList.AddRange(transformList);
}
/// <summary>
///
/// </summary>
public IList<ICoordinateTransformationCore> CoordinateTransformationList
{
get { return _coordinateTransformationList; }
/*
set
{
_coordinateTransformationList = value;
_inverse = null;
}
*/
}
public override int DimSource
{
get { return (_coordinateTransformationList[0]).SourceCS.Dimension; }
}
public override int DimTarget
{
get { return _coordinateTransformationList[_coordinateTransformationList.Count-1].TargetCS.Dimension; }
}
/// <inheritdoc />
public override void Transform(ref double x, ref double y, ref double z)
{
foreach (var ctc in _coordinateTransformationList)
{
if (ctc is CoordinateTransformation ct)
ct.MathTransform.Transform(ref x, ref y, ref z);
else if (ctc is ConcatenatedTransform cct)
cct.Transform(ref x, ref y, ref z);
}
}
/// <summary>
/// Returns the inverse of this conversion.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current conversion.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
{
_inverse = Clone();
_inverse.Invert();
}
return _inverse;
}
/// <summary>
/// Reverses the transformation
/// </summary>
public override void Invert()
{
_coordinateTransformationList.Reverse();
foreach (var ic in _coordinateTransformationList)
{
if (ic is CoordinateTransformation ct)
ct.MathTransform.Invert();
else if (ic is ConcatenatedTransform cct)
cct.Invert();
}
}
public ConcatenatedTransform Clone()
{
var clonedList = new List<ICoordinateTransformationCore>(_coordinateTransformationList.Count);
foreach (var ct in _coordinateTransformationList)
clonedList.Add(CloneCoordinateTransformation(ct));
return new ConcatenatedTransform(clonedList);
}
private static readonly CoordinateTransformationFactory CoordinateTransformationFactory =
new CoordinateTransformationFactory();
private static ICoordinateTransformationCore CloneCoordinateTransformation(ICoordinateTransformationCore ict)
{
return CoordinateTransformationFactory.CreateFromCoordinateSystems(ict.SourceCS, ict.TargetCS);
}
/// <summary>
/// Gets a Well-Known text representation of this object.
/// </summary>
/// <value></value>
public override string WKT
{
get { throw new NotImplementedException(); }
}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
/// <value></value>
public override string XML
{
get { throw new NotImplementedException(); }
}
public CoordinateSystem SourceCS { get => CoordinateTransformationList[0].SourceCS; }
public CoordinateSystem TargetCS { get => CoordinateTransformationList[CoordinateTransformationList.Count-1].TargetCS; }
}
}

Просмотреть файл

@ -1,111 +1,111 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
/// Describes a coordinate transformation. This class only describes a
/// coordinate transformation, it does not actually perform the transform
/// operation on points. To transform points you must use a <see cref="MathTransform"/>.
/// </summary>
[Serializable]
public class CoordinateTransformation : ICoordinateTransformation
{
/// <summary>
/// Initializes an instance of a CoordinateTransformation
/// </summary>
/// <param name="sourceCS">Source coordinate system</param>
/// <param name="targetCS">Target coordinate system</param>
/// <param name="transformType">Transformation type</param>
/// <param name="mathTransform">Math transform</param>
/// <param name="name">Name of transform</param>
/// <param name="authority">Authority</param>
/// <param name="authorityCode">Authority code</param>
/// <param name="areaOfUse">Area of use</param>
/// <param name="remarks">Remarks</param>
internal CoordinateTransformation(CoordinateSystem sourceCS, CoordinateSystem targetCS, TransformType transformType, MathTransform mathTransform,
string name, string authority, long authorityCode, string areaOfUse, string remarks)
{
TargetCS = targetCS;
SourceCS = sourceCS;
TransformType = transformType;
MathTransform = mathTransform;
Name = name;
Authority = authority;
AuthorityCode = authorityCode;
AreaOfUse = areaOfUse;
Remarks = remarks;
}
#region ICoordinateTransformation Members
/// <summary>
/// Human readable description of domain in source coordinate system.
/// </summary>
public string AreaOfUse { get; }
/// <summary>
/// Authority which defined transformation and parameter values.
/// </summary>
/// <remarks>
/// An Authority is an organization that maintains definitions of Authority Codes. For example the European Petroleum Survey Group (EPSG) maintains a database of coordinate systems, and other spatial referencing objects, where each object has a code number ID. For example, the EPSG code for a WGS84 Lat/Lon coordinate system is 4326
/// </remarks>
public string Authority { get; }
/// <summary>
/// Code used by authority to identify transformation. An empty string is used for no code.
/// </summary>
/// <remarks>The AuthorityCode is a compact string defined by an Authority to reference a particular spatial reference object. For example, the European Survey Group (EPSG) authority uses 32 bit integers to reference coordinate systems, so all their code strings will consist of a few digits. The EPSG code for WGS84 Lat/Lon is 4326.</remarks>
public long AuthorityCode { get; }
/// <summary>
/// Gets math transform.
/// </summary>
public MathTransform MathTransform { get; }
/// <summary>
/// Name of transformation.
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the provider-supplied remarks.
/// </summary>
public string Remarks { get; }
/// <summary>
/// Source coordinate system.
/// </summary>
public CoordinateSystem SourceCS { get; }
/// <summary>
/// Target coordinate system.
/// </summary>
public CoordinateSystem TargetCS { get; }
/// <summary>
/// Semantic type of transform. For example, a datum transformation or a coordinate conversion.
/// </summary>
public TransformType TransformType { get; }
#endregion
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
/// Describes a coordinate transformation. This class only describes a
/// coordinate transformation, it does not actually perform the transform
/// operation on points. To transform points you must use a <see cref="MathTransform"/>.
/// </summary>
[Serializable]
public class CoordinateTransformation : ICoordinateTransformation
{
/// <summary>
/// Initializes an instance of a CoordinateTransformation
/// </summary>
/// <param name="sourceCS">Source coordinate system</param>
/// <param name="targetCS">Target coordinate system</param>
/// <param name="transformType">Transformation type</param>
/// <param name="mathTransform">Math transform</param>
/// <param name="name">Name of transform</param>
/// <param name="authority">Authority</param>
/// <param name="authorityCode">Authority code</param>
/// <param name="areaOfUse">Area of use</param>
/// <param name="remarks">Remarks</param>
internal CoordinateTransformation(CoordinateSystem sourceCS, CoordinateSystem targetCS, TransformType transformType, MathTransform mathTransform,
string name, string authority, long authorityCode, string areaOfUse, string remarks)
{
TargetCS = targetCS;
SourceCS = sourceCS;
TransformType = transformType;
MathTransform = mathTransform;
Name = name;
Authority = authority;
AuthorityCode = authorityCode;
AreaOfUse = areaOfUse;
Remarks = remarks;
}
#region ICoordinateTransformation Members
/// <summary>
/// Human readable description of domain in source coordinate system.
/// </summary>
public string AreaOfUse { get; }
/// <summary>
/// Authority which defined transformation and parameter values.
/// </summary>
/// <remarks>
/// An Authority is an organization that maintains definitions of Authority Codes. For example the European Petroleum Survey Group (EPSG) maintains a database of coordinate systems, and other spatial referencing objects, where each object has a code number ID. For example, the EPSG code for a WGS84 Lat/Lon coordinate system is 4326
/// </remarks>
public string Authority { get; }
/// <summary>
/// Code used by authority to identify transformation. An empty string is used for no code.
/// </summary>
/// <remarks>The AuthorityCode is a compact string defined by an Authority to reference a particular spatial reference object. For example, the European Survey Group (EPSG) authority uses 32 bit integers to reference coordinate systems, so all their code strings will consist of a few digits. The EPSG code for WGS84 Lat/Lon is 4326.</remarks>
public long AuthorityCode { get; }
/// <summary>
/// Gets math transform.
/// </summary>
public MathTransform MathTransform { get; }
/// <summary>
/// Name of transformation.
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the provider-supplied remarks.
/// </summary>
public string Remarks { get; }
/// <summary>
/// Source coordinate system.
/// </summary>
public CoordinateSystem SourceCS { get; }
/// <summary>
/// Target coordinate system.
/// </summary>
public CoordinateSystem TargetCS { get; }
/// <summary>
/// Semantic type of transform. For example, a datum transformation or a coordinate conversion.
/// </summary>
public TransformType TransformType { get; }
#endregion
}
}

Просмотреть файл

@ -1,419 +1,419 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using ProjNet.CoordinateSystems.Projections;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
/// Creates coordinate transformations.
/// </summary>
public class CoordinateTransformationFactory
{
#region ICoordinateTransformationFactory Members
/// <summary>
/// Creates a transformation between two coordinate systems.
/// </summary>
/// <remarks>
/// This method will examine the coordinate systems in order to construct
/// a transformation between them. This method may fail if no path between
/// the coordinate systems is found, using the normal failing behavior of
/// the DCP (e.g. throwing an exception).</remarks>
/// <param name="sourceCS">Source coordinate system</param>
/// <param name="targetCS">Target coordinate system</param>
/// <returns></returns>
public ICoordinateTransformation CreateFromCoordinateSystems(CoordinateSystem sourceCS, CoordinateSystem targetCS)
{
ICoordinateTransformation trans;
if (sourceCS is ProjectedCoordinateSystem && targetCS is GeographicCoordinateSystem) //Projected -> Geographic
trans = Proj2Geog((ProjectedCoordinateSystem)sourceCS, (GeographicCoordinateSystem)targetCS);
else if (sourceCS is GeographicCoordinateSystem && targetCS is ProjectedCoordinateSystem) //Geographic -> Projected
trans = Geog2Proj((GeographicCoordinateSystem)sourceCS, (ProjectedCoordinateSystem)targetCS);
else if (sourceCS is GeographicCoordinateSystem && targetCS is GeocentricCoordinateSystem) //Geocentric -> Geographic
trans = Geog2Geoc((GeographicCoordinateSystem)sourceCS, (GeocentricCoordinateSystem)targetCS);
else if (sourceCS is GeocentricCoordinateSystem && targetCS is GeographicCoordinateSystem) //Geocentric -> Geographic
trans = Geoc2Geog((GeocentricCoordinateSystem)sourceCS, (GeographicCoordinateSystem)targetCS);
else if (sourceCS is ProjectedCoordinateSystem && targetCS is ProjectedCoordinateSystem) //Projected -> Projected
trans = Proj2Proj((sourceCS as ProjectedCoordinateSystem), (targetCS as ProjectedCoordinateSystem));
else if (sourceCS is GeocentricCoordinateSystem && targetCS is GeocentricCoordinateSystem) //Geocentric -> Geocentric
trans = CreateGeoc2Geoc((GeocentricCoordinateSystem)sourceCS, (GeocentricCoordinateSystem)targetCS);
else if (sourceCS is GeographicCoordinateSystem && targetCS is GeographicCoordinateSystem) //Geographic -> Geographic
trans = CreateGeog2Geog(sourceCS as GeographicCoordinateSystem, targetCS as GeographicCoordinateSystem);
else if (sourceCS is FittedCoordinateSystem) //Fitted -> Any
trans = Fitt2Any ((FittedCoordinateSystem)sourceCS, targetCS);
else if (targetCS is FittedCoordinateSystem) //Any -> Fitted
trans = Any2Fitt (sourceCS, (FittedCoordinateSystem)targetCS);
else
throw new NotSupportedException("No support for transforming between the two specified coordinate systems");
//if (trans.MathTransform is ConcatenatedTransform) {
// List<ICoordinateTransformation> MTs = new List<ICoordinateTransformation>();
// SimplifyTrans(trans.MathTransform as ConcatenatedTransform, ref MTs);
// return new CoordinateTransformation(sourceCS,
// targetCS, TransformType.Transformation, new ConcatenatedTransform(MTs),
// string.Empty, string.Empty, -1, string.Empty, string.Empty);
//}
return trans;
}
#endregion
private static void SimplifyTrans(ConcatenatedTransform mtrans, ref List<ICoordinateTransformationCore> MTs)
{
foreach(var t in mtrans.CoordinateTransformationList)
{
if(t is ConcatenatedTransform ct)
SimplifyTrans(ct, ref MTs);
else
MTs.Add(t);
}
}
#region Methods for converting between specific systems
private static CoordinateTransformation Geog2Geoc(GeographicCoordinateSystem source, GeocentricCoordinateSystem target)
{
var geocMathTransform = CreateCoordinateOperation(target);
if (source.PrimeMeridian.EqualParams(target.PrimeMeridian))
{
return new CoordinateTransformation(source, target, TransformType.Conversion, geocMathTransform, string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
var ct = new ConcatenatedTransform();
ct.CoordinateTransformationList.Add(new CoordinateTransformation(source, target, TransformType.Transformation, new PrimeMeridianTransform(source.PrimeMeridian, target.PrimeMeridian), string.Empty, string.Empty, -1, string.Empty, string.Empty));
ct.CoordinateTransformationList.Add(new CoordinateTransformation(source, target, TransformType.Conversion, geocMathTransform, string.Empty, string.Empty, -1, string.Empty, string.Empty));
return new CoordinateTransformation(source, target, TransformType.Conversion, ct, string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
private static CoordinateTransformation Geoc2Geog(GeocentricCoordinateSystem source, GeographicCoordinateSystem target)
{
var geocMathTransform = CreateCoordinateOperation(source).Inverse();
if (source.PrimeMeridian.EqualParams(target.PrimeMeridian))
{
return new CoordinateTransformation(source, target, TransformType.Conversion, geocMathTransform, string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
var ct = new ConcatenatedTransform();
ct.CoordinateTransformationList.Add(new CoordinateTransformation(source, target, TransformType.Conversion, geocMathTransform, string.Empty, string.Empty, -1, string.Empty, string.Empty));
ct.CoordinateTransformationList.Add(new CoordinateTransformation(source, target, TransformType.Transformation, new PrimeMeridianTransform(source.PrimeMeridian, target.PrimeMeridian), string.Empty, string.Empty, -1, string.Empty, string.Empty));
return new CoordinateTransformation(source, target, TransformType.Conversion, ct, string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
private static CoordinateTransformation Proj2Proj(ProjectedCoordinateSystem source, ProjectedCoordinateSystem target)
{
var ct = new ConcatenatedTransform();
var ctFac = new CoordinateTransformationFactory();
//First transform from projection to geographic
ct.CoordinateTransformationList.Add(ctFac.CreateFromCoordinateSystems(source, source.GeographicCoordinateSystem));
//Transform geographic to geographic:
var geogToGeog = ctFac.CreateFromCoordinateSystems(source.GeographicCoordinateSystem,
target.GeographicCoordinateSystem);
if (geogToGeog != null)
ct.CoordinateTransformationList.Add(geogToGeog);
//Transform to new projection
ct.CoordinateTransformationList.Add(ctFac.CreateFromCoordinateSystems(target.GeographicCoordinateSystem, target));
return new CoordinateTransformation(source,
target, TransformType.Transformation, ct,
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
private static CoordinateTransformation Geog2Proj(GeographicCoordinateSystem source, ProjectedCoordinateSystem target)
{
if (source.EqualParams(target.GeographicCoordinateSystem))
{
var mathTransform = CreateCoordinateOperation(target.Projection,
target.GeographicCoordinateSystem.HorizontalDatum.Ellipsoid, target.LinearUnit);
return new CoordinateTransformation(source, target, TransformType.Transformation, mathTransform,
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
// Geographic coordinatesystems differ - Create concatenated transform
var ct = new ConcatenatedTransform();
var ctFac = new CoordinateTransformationFactory();
ct.CoordinateTransformationList.Add(ctFac.CreateFromCoordinateSystems(source,target.GeographicCoordinateSystem));
ct.CoordinateTransformationList.Add(ctFac.CreateFromCoordinateSystems(target.GeographicCoordinateSystem, target));
return new CoordinateTransformation(source,
target, TransformType.Transformation, ct,
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
private static CoordinateTransformation Proj2Geog(ProjectedCoordinateSystem source, GeographicCoordinateSystem target)
{
if (source.GeographicCoordinateSystem.EqualParams(target))
{
var mathTransform = CreateCoordinateOperation(source.Projection, source.GeographicCoordinateSystem.HorizontalDatum.Ellipsoid, source.LinearUnit).Inverse();
return new CoordinateTransformation(source, target, TransformType.Transformation, mathTransform,
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
else
{ // Geographic coordinatesystems differ - Create concatenated transform
var ct = new ConcatenatedTransform();
var ctFac = new CoordinateTransformationFactory();
ct.CoordinateTransformationList.Add(ctFac.CreateFromCoordinateSystems(source, source.GeographicCoordinateSystem));
ct.CoordinateTransformationList.Add(ctFac.CreateFromCoordinateSystems(source.GeographicCoordinateSystem, target));
return new CoordinateTransformation(source,
target, TransformType.Transformation, ct,
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
}
/// <summary>
/// Geographic to geographic transformation
/// </summary>
/// <remarks>Adds a datum shift if necessary</remarks>
/// <param name="source"></param>
/// <param name="target"></param>
/// <returns></returns>
private static ICoordinateTransformation CreateGeog2Geog(GeographicCoordinateSystem source, GeographicCoordinateSystem target)
{
if (source.HorizontalDatum.EqualParams(target.HorizontalDatum))
{
//No datum shift needed
return new CoordinateTransformation(source,
target, TransformType.Conversion, new GeographicTransform(source, target),
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
//Create datum shift
//Convert to geocentric, perform shift and return to geographic
var ctFac = new CoordinateTransformationFactory();
var cFac = new CoordinateSystemFactory();
var sourceCentric = cFac.CreateGeocentricCoordinateSystem(source.HorizontalDatum.Name + " Geocentric",
source.HorizontalDatum, LinearUnit.Metre, source.PrimeMeridian);
var targetCentric = cFac.CreateGeocentricCoordinateSystem(target.HorizontalDatum.Name + " Geocentric",
target.HorizontalDatum, LinearUnit.Metre, source.PrimeMeridian);
var ct = new ConcatenatedTransform();
AddIfNotNull(ct, ctFac.CreateFromCoordinateSystems(source, sourceCentric));
AddIfNotNull(ct, ctFac.CreateFromCoordinateSystems(sourceCentric, targetCentric));
AddIfNotNull(ct, ctFac.CreateFromCoordinateSystems(targetCentric, target));
return new CoordinateTransformation(source,
target, TransformType.Transformation, ct,
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
private static void AddIfNotNull(ConcatenatedTransform concatTrans, ICoordinateTransformation trans)
{
if (trans != null)
concatTrans.CoordinateTransformationList.Add(trans);
}
/// <summary>
/// Geocentric to Geocentric transformation
/// </summary>
/// <param name="source"></param>
/// <param name="target"></param>
/// <returns></returns>
private static CoordinateTransformation CreateGeoc2Geoc(GeocentricCoordinateSystem source, GeocentricCoordinateSystem target)
{
var ct = new ConcatenatedTransform();
//Does source has a datum different from WGS84 and is there a shift specified?
if (source.HorizontalDatum.Wgs84Parameters != null && !source.HorizontalDatum.Wgs84Parameters.HasZeroValuesOnly)
ct.CoordinateTransformationList.Add(
new CoordinateTransformation(
((target.HorizontalDatum.Wgs84Parameters == null || target.HorizontalDatum.Wgs84Parameters.HasZeroValuesOnly) ? target : GeocentricCoordinateSystem.WGS84),
source, TransformType.Transformation,
new DatumTransform(source.HorizontalDatum.Wgs84Parameters)
, "", "", -1, "", ""));
//Does target has a datum different from WGS84 and is there a shift specified?
if (target.HorizontalDatum.Wgs84Parameters != null && !target.HorizontalDatum.Wgs84Parameters.HasZeroValuesOnly)
ct.CoordinateTransformationList.Add(
new CoordinateTransformation(
((source.HorizontalDatum.Wgs84Parameters == null || source.HorizontalDatum.Wgs84Parameters.HasZeroValuesOnly) ? source : GeocentricCoordinateSystem.WGS84),
target,
TransformType.Transformation,
new DatumTransform(target.HorizontalDatum.Wgs84Parameters).Inverse()
, "", "", -1, "", ""));
//If we don't have a transformation in this list, return null
if (ct.CoordinateTransformationList.Count == 0)
return null;
//If we only have one shift, lets just return the datumshift from/to wgs84
if (ct.CoordinateTransformationList.Count == 1)
return new CoordinateTransformation(source, target, TransformType.ConversionAndTransformation, ((ICoordinateTransformation)ct.CoordinateTransformationList[0]).MathTransform, "", "", -1, "", "");
return new CoordinateTransformation(source, target, TransformType.ConversionAndTransformation, ct, "", "", -1, "", "");
}
/// <summary>
/// Creates transformation from fitted coordinate system to the target one
/// </summary>
/// <param name="source"></param>
/// <param name="target"></param>
/// <returns></returns>
private static CoordinateTransformation Fitt2Any (FittedCoordinateSystem source, CoordinateSystem target)
{
//transform from fitted to base system of fitted (which is equal to target)
var mt = CreateFittedTransform (source);
//case when target system is equal to base system of the fitted
if (source.BaseCoordinateSystem.EqualParams (target))
{
//Transform form base system of fitted to target coordinate system
return CreateTransform (source, target, TransformType.Transformation, mt);
}
//Transform form base system of fitted to target coordinate system
var ct = new ConcatenatedTransform ();
ct.CoordinateTransformationList.Add (CreateTransform (source, source.BaseCoordinateSystem, TransformType.Transformation, mt));
//Transform form base system of fitted to target coordinate system
var ctFac = new CoordinateTransformationFactory ();
ct.CoordinateTransformationList.Add (ctFac.CreateFromCoordinateSystems (source.BaseCoordinateSystem, target));
return CreateTransform (source, target, TransformType.Transformation, ct);
}
/// <summary>
/// Creates transformation from source coordinate system to specified target system which is the fitted one
/// </summary>
/// <param name="source"></param>
/// <param name="target"></param>
/// <returns></returns>
private static CoordinateTransformation Any2Fitt (CoordinateSystem source, FittedCoordinateSystem target)
{
//Transform form base system of fitted to target coordinate system - use invered math transform
var invMt = CreateFittedTransform (target).Inverse ();
//case when source system is equal to base system of the fitted
if (target.BaseCoordinateSystem.EqualParams (source))
{
//Transform form base system of fitted to target coordinate system
return CreateTransform (source, target, TransformType.Transformation, invMt);
}
var ct = new ConcatenatedTransform ();
//First transform from source to base system of fitted
var ctFac = new CoordinateTransformationFactory ();
ct.CoordinateTransformationList.Add (ctFac.CreateFromCoordinateSystems (source, target.BaseCoordinateSystem));
//Transform form base system of fitted to target coordinate system - use invered math transform
ct.CoordinateTransformationList.Add (CreateTransform (target.BaseCoordinateSystem, target, TransformType.Transformation, invMt));
return CreateTransform (source, target, TransformType.Transformation, ct);
}
private static MathTransform CreateFittedTransform (FittedCoordinateSystem fittedSystem)
{
//create transform From fitted to base and inverts it
return fittedSystem.ToBaseTransform;
//MathTransformFactory mtFac = new MathTransformFactory ();
////create transform From fitted to base and inverts it
//return mtFac.CreateFromWKT (fittedSystem.ToBase ());
throw new NotImplementedException ();
}
/// <summary>
/// Creates an instance of CoordinateTransformation as an anonymous transformation without neither autohority nor code defined.
/// </summary>
/// <param name="sourceCS">Source coordinate system</param>
/// <param name="targetCS">Target coordinate system</param>
/// <param name="transformType">Transformation type</param>
/// <param name="mathTransform">Math transform</param>
private static CoordinateTransformation CreateTransform (CoordinateSystem sourceCS, CoordinateSystem targetCS, TransformType transformType, MathTransform mathTransform)
{
return new CoordinateTransformation (sourceCS, targetCS, transformType, mathTransform, string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
#endregion
private static MathTransform CreateCoordinateOperation(GeocentricCoordinateSystem geo)
{
var parameterList = new List<ProjectionParameter>(2);
var ellipsoid = geo.HorizontalDatum.Ellipsoid;
//var toMeter = ellipsoid.AxisUnit.MetersPerUnit;
if (parameterList.Find((p) => p.Name.ToLowerInvariant().Replace(' ', '_').Equals("semi_major")) == null)
parameterList.Add(new ProjectionParameter("semi_major", /*toMeter * */ellipsoid.SemiMajorAxis));
if (parameterList.Find((p) => p.Name.ToLowerInvariant().Replace(' ', '_').Equals("semi_minor")) == null)
parameterList.Add(new ProjectionParameter("semi_minor", /*toMeter * */ellipsoid.SemiMinorAxis));
return new GeocentricTransform(parameterList);
}
private static MathTransform CreateCoordinateOperation(IProjection projection, Ellipsoid ellipsoid, LinearUnit unit)
{
var parameterList = new List<ProjectionParameter>(projection.NumParameters);
for (int i = 0; i < projection.NumParameters; i++)
parameterList.Add(projection.GetParameter(i));
//var toMeter = 1d/ellipsoid.AxisUnit.MetersPerUnit;
if (parameterList.Find((p) => p.Name.ToLowerInvariant().Replace(' ', '_').Equals("semi_major")) == null)
parameterList.Add(new ProjectionParameter("semi_major", /*toMeter * */ellipsoid.SemiMajorAxis));
if (parameterList.Find((p) => p.Name.ToLowerInvariant().Replace(' ', '_').Equals("semi_minor")) == null)
parameterList.Add(new ProjectionParameter("semi_minor", /*toMeter * */ellipsoid.SemiMinorAxis));
if (parameterList.Find((p) => p.Name.ToLowerInvariant().Replace(' ', '_').Equals("unit")) == null)
parameterList.Add(new ProjectionParameter("unit", unit.MetersPerUnit));
var operation = ProjectionsRegistry.CreateProjection(projection.ClassName, parameterList);
/*
var mpOperation = operation as MapProjection;
if (mpOperation != null && projection.AuthorityCode !=-1)
{
mpOperation.Authority = projection.Authority;
mpOperation.AuthorityCode = projection.AuthorityCode;
}
*/
return operation;
/*
switch (projection.ClassName.ToLower(CultureInfo.InvariantCulture).Replace(' ', '_'))
{
case "mercator":
case "mercator_1sp":
case "mercator_2sp":
//1SP
transform = new Mercator(parameterList);
break;
case "transverse_mercator":
transform = new TransverseMercator(parameterList);
break;
case "albers":
case "albers_conic_equal_area":
transform = new AlbersProjection(parameterList);
break;
case "krovak":
transform = new KrovakProjection(parameterList);
break;
case "polyconic":
transform = new PolyconicProjection(parameterList);
break;
case "lambert_conformal_conic":
case "lambert_conformal_conic_2sp":
case "lambert_conic_conformal_(2sp)":
transform = new LambertConformalConic2SP(parameterList);
break;
default:
throw new NotSupportedException(String.Format("Projection {0} is not supported.", projection.ClassName));
}
return transform;
*/
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using ProjNet.CoordinateSystems.Projections;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
/// Creates coordinate transformations.
/// </summary>
public class CoordinateTransformationFactory
{
#region ICoordinateTransformationFactory Members
/// <summary>
/// Creates a transformation between two coordinate systems.
/// </summary>
/// <remarks>
/// This method will examine the coordinate systems in order to construct
/// a transformation between them. This method may fail if no path between
/// the coordinate systems is found, using the normal failing behavior of
/// the DCP (e.g. throwing an exception).</remarks>
/// <param name="sourceCS">Source coordinate system</param>
/// <param name="targetCS">Target coordinate system</param>
/// <returns></returns>
public ICoordinateTransformation CreateFromCoordinateSystems(CoordinateSystem sourceCS, CoordinateSystem targetCS)
{
ICoordinateTransformation trans;
if (sourceCS is ProjectedCoordinateSystem && targetCS is GeographicCoordinateSystem) //Projected -> Geographic
trans = Proj2Geog((ProjectedCoordinateSystem)sourceCS, (GeographicCoordinateSystem)targetCS);
else if (sourceCS is GeographicCoordinateSystem && targetCS is ProjectedCoordinateSystem) //Geographic -> Projected
trans = Geog2Proj((GeographicCoordinateSystem)sourceCS, (ProjectedCoordinateSystem)targetCS);
else if (sourceCS is GeographicCoordinateSystem && targetCS is GeocentricCoordinateSystem) //Geocentric -> Geographic
trans = Geog2Geoc((GeographicCoordinateSystem)sourceCS, (GeocentricCoordinateSystem)targetCS);
else if (sourceCS is GeocentricCoordinateSystem && targetCS is GeographicCoordinateSystem) //Geocentric -> Geographic
trans = Geoc2Geog((GeocentricCoordinateSystem)sourceCS, (GeographicCoordinateSystem)targetCS);
else if (sourceCS is ProjectedCoordinateSystem && targetCS is ProjectedCoordinateSystem) //Projected -> Projected
trans = Proj2Proj((sourceCS as ProjectedCoordinateSystem), (targetCS as ProjectedCoordinateSystem));
else if (sourceCS is GeocentricCoordinateSystem && targetCS is GeocentricCoordinateSystem) //Geocentric -> Geocentric
trans = CreateGeoc2Geoc((GeocentricCoordinateSystem)sourceCS, (GeocentricCoordinateSystem)targetCS);
else if (sourceCS is GeographicCoordinateSystem && targetCS is GeographicCoordinateSystem) //Geographic -> Geographic
trans = CreateGeog2Geog(sourceCS as GeographicCoordinateSystem, targetCS as GeographicCoordinateSystem);
else if (sourceCS is FittedCoordinateSystem) //Fitted -> Any
trans = Fitt2Any ((FittedCoordinateSystem)sourceCS, targetCS);
else if (targetCS is FittedCoordinateSystem) //Any -> Fitted
trans = Any2Fitt (sourceCS, (FittedCoordinateSystem)targetCS);
else
throw new NotSupportedException("No support for transforming between the two specified coordinate systems");
//if (trans.MathTransform is ConcatenatedTransform) {
// List<ICoordinateTransformation> MTs = new List<ICoordinateTransformation>();
// SimplifyTrans(trans.MathTransform as ConcatenatedTransform, ref MTs);
// return new CoordinateTransformation(sourceCS,
// targetCS, TransformType.Transformation, new ConcatenatedTransform(MTs),
// string.Empty, string.Empty, -1, string.Empty, string.Empty);
//}
return trans;
}
#endregion
private static void SimplifyTrans(ConcatenatedTransform mtrans, ref List<ICoordinateTransformationCore> MTs)
{
foreach(var t in mtrans.CoordinateTransformationList)
{
if(t is ConcatenatedTransform ct)
SimplifyTrans(ct, ref MTs);
else
MTs.Add(t);
}
}
#region Methods for converting between specific systems
private static CoordinateTransformation Geog2Geoc(GeographicCoordinateSystem source, GeocentricCoordinateSystem target)
{
var geocMathTransform = CreateCoordinateOperation(target);
if (source.PrimeMeridian.EqualParams(target.PrimeMeridian))
{
return new CoordinateTransformation(source, target, TransformType.Conversion, geocMathTransform, string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
var ct = new ConcatenatedTransform();
ct.CoordinateTransformationList.Add(new CoordinateTransformation(source, target, TransformType.Transformation, new PrimeMeridianTransform(source.PrimeMeridian, target.PrimeMeridian), string.Empty, string.Empty, -1, string.Empty, string.Empty));
ct.CoordinateTransformationList.Add(new CoordinateTransformation(source, target, TransformType.Conversion, geocMathTransform, string.Empty, string.Empty, -1, string.Empty, string.Empty));
return new CoordinateTransformation(source, target, TransformType.Conversion, ct, string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
private static CoordinateTransformation Geoc2Geog(GeocentricCoordinateSystem source, GeographicCoordinateSystem target)
{
var geocMathTransform = CreateCoordinateOperation(source).Inverse();
if (source.PrimeMeridian.EqualParams(target.PrimeMeridian))
{
return new CoordinateTransformation(source, target, TransformType.Conversion, geocMathTransform, string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
var ct = new ConcatenatedTransform();
ct.CoordinateTransformationList.Add(new CoordinateTransformation(source, target, TransformType.Conversion, geocMathTransform, string.Empty, string.Empty, -1, string.Empty, string.Empty));
ct.CoordinateTransformationList.Add(new CoordinateTransformation(source, target, TransformType.Transformation, new PrimeMeridianTransform(source.PrimeMeridian, target.PrimeMeridian), string.Empty, string.Empty, -1, string.Empty, string.Empty));
return new CoordinateTransformation(source, target, TransformType.Conversion, ct, string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
private static CoordinateTransformation Proj2Proj(ProjectedCoordinateSystem source, ProjectedCoordinateSystem target)
{
var ct = new ConcatenatedTransform();
var ctFac = new CoordinateTransformationFactory();
//First transform from projection to geographic
ct.CoordinateTransformationList.Add(ctFac.CreateFromCoordinateSystems(source, source.GeographicCoordinateSystem));
//Transform geographic to geographic:
var geogToGeog = ctFac.CreateFromCoordinateSystems(source.GeographicCoordinateSystem,
target.GeographicCoordinateSystem);
if (geogToGeog != null)
ct.CoordinateTransformationList.Add(geogToGeog);
//Transform to new projection
ct.CoordinateTransformationList.Add(ctFac.CreateFromCoordinateSystems(target.GeographicCoordinateSystem, target));
return new CoordinateTransformation(source,
target, TransformType.Transformation, ct,
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
private static CoordinateTransformation Geog2Proj(GeographicCoordinateSystem source, ProjectedCoordinateSystem target)
{
if (source.EqualParams(target.GeographicCoordinateSystem))
{
var mathTransform = CreateCoordinateOperation(target.Projection,
target.GeographicCoordinateSystem.HorizontalDatum.Ellipsoid, target.LinearUnit);
return new CoordinateTransformation(source, target, TransformType.Transformation, mathTransform,
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
// Geographic coordinatesystems differ - Create concatenated transform
var ct = new ConcatenatedTransform();
var ctFac = new CoordinateTransformationFactory();
ct.CoordinateTransformationList.Add(ctFac.CreateFromCoordinateSystems(source,target.GeographicCoordinateSystem));
ct.CoordinateTransformationList.Add(ctFac.CreateFromCoordinateSystems(target.GeographicCoordinateSystem, target));
return new CoordinateTransformation(source,
target, TransformType.Transformation, ct,
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
private static CoordinateTransformation Proj2Geog(ProjectedCoordinateSystem source, GeographicCoordinateSystem target)
{
if (source.GeographicCoordinateSystem.EqualParams(target))
{
var mathTransform = CreateCoordinateOperation(source.Projection, source.GeographicCoordinateSystem.HorizontalDatum.Ellipsoid, source.LinearUnit).Inverse();
return new CoordinateTransformation(source, target, TransformType.Transformation, mathTransform,
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
else
{ // Geographic coordinatesystems differ - Create concatenated transform
var ct = new ConcatenatedTransform();
var ctFac = new CoordinateTransformationFactory();
ct.CoordinateTransformationList.Add(ctFac.CreateFromCoordinateSystems(source, source.GeographicCoordinateSystem));
ct.CoordinateTransformationList.Add(ctFac.CreateFromCoordinateSystems(source.GeographicCoordinateSystem, target));
return new CoordinateTransformation(source,
target, TransformType.Transformation, ct,
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
}
/// <summary>
/// Geographic to geographic transformation
/// </summary>
/// <remarks>Adds a datum shift if necessary</remarks>
/// <param name="source"></param>
/// <param name="target"></param>
/// <returns></returns>
private static ICoordinateTransformation CreateGeog2Geog(GeographicCoordinateSystem source, GeographicCoordinateSystem target)
{
if (source.HorizontalDatum.EqualParams(target.HorizontalDatum))
{
//No datum shift needed
return new CoordinateTransformation(source,
target, TransformType.Conversion, new GeographicTransform(source, target),
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
//Create datum shift
//Convert to geocentric, perform shift and return to geographic
var ctFac = new CoordinateTransformationFactory();
var cFac = new CoordinateSystemFactory();
var sourceCentric = cFac.CreateGeocentricCoordinateSystem(source.HorizontalDatum.Name + " Geocentric",
source.HorizontalDatum, LinearUnit.Metre, source.PrimeMeridian);
var targetCentric = cFac.CreateGeocentricCoordinateSystem(target.HorizontalDatum.Name + " Geocentric",
target.HorizontalDatum, LinearUnit.Metre, source.PrimeMeridian);
var ct = new ConcatenatedTransform();
AddIfNotNull(ct, ctFac.CreateFromCoordinateSystems(source, sourceCentric));
AddIfNotNull(ct, ctFac.CreateFromCoordinateSystems(sourceCentric, targetCentric));
AddIfNotNull(ct, ctFac.CreateFromCoordinateSystems(targetCentric, target));
return new CoordinateTransformation(source,
target, TransformType.Transformation, ct,
string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
private static void AddIfNotNull(ConcatenatedTransform concatTrans, ICoordinateTransformation trans)
{
if (trans != null)
concatTrans.CoordinateTransformationList.Add(trans);
}
/// <summary>
/// Geocentric to Geocentric transformation
/// </summary>
/// <param name="source"></param>
/// <param name="target"></param>
/// <returns></returns>
private static CoordinateTransformation CreateGeoc2Geoc(GeocentricCoordinateSystem source, GeocentricCoordinateSystem target)
{
var ct = new ConcatenatedTransform();
//Does source has a datum different from WGS84 and is there a shift specified?
if (source.HorizontalDatum.Wgs84Parameters != null && !source.HorizontalDatum.Wgs84Parameters.HasZeroValuesOnly)
ct.CoordinateTransformationList.Add(
new CoordinateTransformation(
((target.HorizontalDatum.Wgs84Parameters == null || target.HorizontalDatum.Wgs84Parameters.HasZeroValuesOnly) ? target : GeocentricCoordinateSystem.WGS84),
source, TransformType.Transformation,
new DatumTransform(source.HorizontalDatum.Wgs84Parameters)
, "", "", -1, "", ""));
//Does target has a datum different from WGS84 and is there a shift specified?
if (target.HorizontalDatum.Wgs84Parameters != null && !target.HorizontalDatum.Wgs84Parameters.HasZeroValuesOnly)
ct.CoordinateTransformationList.Add(
new CoordinateTransformation(
((source.HorizontalDatum.Wgs84Parameters == null || source.HorizontalDatum.Wgs84Parameters.HasZeroValuesOnly) ? source : GeocentricCoordinateSystem.WGS84),
target,
TransformType.Transformation,
new DatumTransform(target.HorizontalDatum.Wgs84Parameters).Inverse()
, "", "", -1, "", ""));
//If we don't have a transformation in this list, return null
if (ct.CoordinateTransformationList.Count == 0)
return null;
//If we only have one shift, lets just return the datumshift from/to wgs84
if (ct.CoordinateTransformationList.Count == 1)
return new CoordinateTransformation(source, target, TransformType.ConversionAndTransformation, ((ICoordinateTransformation)ct.CoordinateTransformationList[0]).MathTransform, "", "", -1, "", "");
return new CoordinateTransformation(source, target, TransformType.ConversionAndTransformation, ct, "", "", -1, "", "");
}
/// <summary>
/// Creates transformation from fitted coordinate system to the target one
/// </summary>
/// <param name="source"></param>
/// <param name="target"></param>
/// <returns></returns>
private static CoordinateTransformation Fitt2Any (FittedCoordinateSystem source, CoordinateSystem target)
{
//transform from fitted to base system of fitted (which is equal to target)
var mt = CreateFittedTransform (source);
//case when target system is equal to base system of the fitted
if (source.BaseCoordinateSystem.EqualParams (target))
{
//Transform form base system of fitted to target coordinate system
return CreateTransform (source, target, TransformType.Transformation, mt);
}
//Transform form base system of fitted to target coordinate system
var ct = new ConcatenatedTransform ();
ct.CoordinateTransformationList.Add (CreateTransform (source, source.BaseCoordinateSystem, TransformType.Transformation, mt));
//Transform form base system of fitted to target coordinate system
var ctFac = new CoordinateTransformationFactory ();
ct.CoordinateTransformationList.Add (ctFac.CreateFromCoordinateSystems (source.BaseCoordinateSystem, target));
return CreateTransform (source, target, TransformType.Transformation, ct);
}
/// <summary>
/// Creates transformation from source coordinate system to specified target system which is the fitted one
/// </summary>
/// <param name="source"></param>
/// <param name="target"></param>
/// <returns></returns>
private static CoordinateTransformation Any2Fitt (CoordinateSystem source, FittedCoordinateSystem target)
{
//Transform form base system of fitted to target coordinate system - use invered math transform
var invMt = CreateFittedTransform (target).Inverse ();
//case when source system is equal to base system of the fitted
if (target.BaseCoordinateSystem.EqualParams (source))
{
//Transform form base system of fitted to target coordinate system
return CreateTransform (source, target, TransformType.Transformation, invMt);
}
var ct = new ConcatenatedTransform ();
//First transform from source to base system of fitted
var ctFac = new CoordinateTransformationFactory ();
ct.CoordinateTransformationList.Add (ctFac.CreateFromCoordinateSystems (source, target.BaseCoordinateSystem));
//Transform form base system of fitted to target coordinate system - use invered math transform
ct.CoordinateTransformationList.Add (CreateTransform (target.BaseCoordinateSystem, target, TransformType.Transformation, invMt));
return CreateTransform (source, target, TransformType.Transformation, ct);
}
private static MathTransform CreateFittedTransform (FittedCoordinateSystem fittedSystem)
{
//create transform From fitted to base and inverts it
return fittedSystem.ToBaseTransform;
//MathTransformFactory mtFac = new MathTransformFactory ();
////create transform From fitted to base and inverts it
//return mtFac.CreateFromWKT (fittedSystem.ToBase ());
throw new NotImplementedException ();
}
/// <summary>
/// Creates an instance of CoordinateTransformation as an anonymous transformation without neither autohority nor code defined.
/// </summary>
/// <param name="sourceCS">Source coordinate system</param>
/// <param name="targetCS">Target coordinate system</param>
/// <param name="transformType">Transformation type</param>
/// <param name="mathTransform">Math transform</param>
private static CoordinateTransformation CreateTransform (CoordinateSystem sourceCS, CoordinateSystem targetCS, TransformType transformType, MathTransform mathTransform)
{
return new CoordinateTransformation (sourceCS, targetCS, transformType, mathTransform, string.Empty, string.Empty, -1, string.Empty, string.Empty);
}
#endregion
private static MathTransform CreateCoordinateOperation(GeocentricCoordinateSystem geo)
{
var parameterList = new List<ProjectionParameter>(2);
var ellipsoid = geo.HorizontalDatum.Ellipsoid;
//var toMeter = ellipsoid.AxisUnit.MetersPerUnit;
if (parameterList.Find((p) => p.Name.ToLowerInvariant().Replace(' ', '_').Equals("semi_major")) == null)
parameterList.Add(new ProjectionParameter("semi_major", /*toMeter * */ellipsoid.SemiMajorAxis));
if (parameterList.Find((p) => p.Name.ToLowerInvariant().Replace(' ', '_').Equals("semi_minor")) == null)
parameterList.Add(new ProjectionParameter("semi_minor", /*toMeter * */ellipsoid.SemiMinorAxis));
return new GeocentricTransform(parameterList);
}
private static MathTransform CreateCoordinateOperation(IProjection projection, Ellipsoid ellipsoid, LinearUnit unit)
{
var parameterList = new List<ProjectionParameter>(projection.NumParameters);
for (int i = 0; i < projection.NumParameters; i++)
parameterList.Add(projection.GetParameter(i));
//var toMeter = 1d/ellipsoid.AxisUnit.MetersPerUnit;
if (parameterList.Find((p) => p.Name.ToLowerInvariant().Replace(' ', '_').Equals("semi_major")) == null)
parameterList.Add(new ProjectionParameter("semi_major", /*toMeter * */ellipsoid.SemiMajorAxis));
if (parameterList.Find((p) => p.Name.ToLowerInvariant().Replace(' ', '_').Equals("semi_minor")) == null)
parameterList.Add(new ProjectionParameter("semi_minor", /*toMeter * */ellipsoid.SemiMinorAxis));
if (parameterList.Find((p) => p.Name.ToLowerInvariant().Replace(' ', '_').Equals("unit")) == null)
parameterList.Add(new ProjectionParameter("unit", unit.MetersPerUnit));
var operation = ProjectionsRegistry.CreateProjection(projection.ClassName, parameterList);
/*
var mpOperation = operation as MapProjection;
if (mpOperation != null && projection.AuthorityCode !=-1)
{
mpOperation.Authority = projection.Authority;
mpOperation.AuthorityCode = projection.AuthorityCode;
}
*/
return operation;
/*
switch (projection.ClassName.ToLower(CultureInfo.InvariantCulture).Replace(' ', '_'))
{
case "mercator":
case "mercator_1sp":
case "mercator_2sp":
//1SP
transform = new Mercator(parameterList);
break;
case "transverse_mercator":
transform = new TransverseMercator(parameterList);
break;
case "albers":
case "albers_conic_equal_area":
transform = new AlbersProjection(parameterList);
break;
case "krovak":
transform = new KrovakProjection(parameterList);
break;
case "polyconic":
transform = new PolyconicProjection(parameterList);
break;
case "lambert_conformal_conic":
case "lambert_conformal_conic_2sp":
case "lambert_conic_conformal_(2sp)":
transform = new LambertConformalConic2SP(parameterList);
break;
default:
throw new NotSupportedException(String.Format("Projection {0} is not supported.", projection.ClassName));
}
return transform;
*/
}
}
}

Просмотреть файл

@ -1,126 +1,126 @@
// Copyright 2006 - Morten Nielsen (www.iter.dk)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
/// Transformation for applying
/// </summary>
[Serializable]
internal class DatumTransform : MathTransform
{
private MathTransform _inverse;
private readonly Wgs84ConversionInfo _toWgs94;
readonly double[] _v;
private bool _isInverse;
/// <summary>
/// Initializes a new instance of the <see cref="DatumTransform"/> class.
/// </summary>
/// <param name="towgs84"></param>
public DatumTransform(Wgs84ConversionInfo towgs84) : this(towgs84,false)
{
}
private DatumTransform(Wgs84ConversionInfo towgs84, bool isInverse)
{
_toWgs94 = towgs84;
_v = _toWgs94.GetAffineTransform();
_isInverse = isInverse;
}
/// <summary>
/// Gets a Well-Known text representation of this object.
/// </summary>
/// <value></value>
public override string WKT
{
get { throw new NotImplementedException(); }
}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
/// <value></value>
public override string XML
{
get { throw new NotImplementedException(); }
}
public override int DimSource
{
get { return 3; }
}
public override int DimTarget
{
get { return 3; }
}
/// <summary>
/// Creates the inverse transform of this object.
/// </summary>
/// <returns></returns>
/// <remarks>This method may fail if the transform is not one to one. However, all cartographic projections should succeed.</remarks>
public override MathTransform Inverse()
{
if (_inverse == null)
_inverse = new DatumTransform(_toWgs94,!_isInverse);
return _inverse;
}
/// <inheritdoc />
public sealed override void Transform(ref double x, ref double y, ref double z)
{
if (_isInverse)
{
(x, y, z) = ApplyInverted(x, y, z);
}
else
{
(x, y, z) = Apply(x, y, z);
}
}
private (double x, double y, double z) Apply(double x, double y, double z)
{
return (
x: _v[0] * (x - _v[3] * y + _v[2] * z) + _v[4],
y: _v[0] * (_v[3] * x + y - _v[1] * z) + _v[5],
z: _v[0] * (-_v[2] * x + _v[1] * y + z) + _v[6]);
}
private (double x, double y, double z) ApplyInverted(double x, double y, double z)
{
return (
x: (1 - (_v[0] - 1)) * (x + _v[3] * y - _v[2] * z) - _v[4],
y: (1 - (_v[0] - 1)) * (-_v[3] * x + y + _v[1] * z) - _v[5],
z: (1 - (_v[0] - 1)) * (_v[2] * x - _v[1] * y + z) - _v[6]);
}
/// <summary>
/// Reverses the transformation
/// </summary>
public override void Invert()
{
_isInverse = !_isInverse;
}
}
}
// Copyright 2006 - Morten Nielsen (www.iter.dk)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
/// Transformation for applying
/// </summary>
[Serializable]
internal class DatumTransform : MathTransform
{
private MathTransform _inverse;
private readonly Wgs84ConversionInfo _toWgs94;
readonly double[] _v;
private bool _isInverse;
/// <summary>
/// Initializes a new instance of the <see cref="DatumTransform"/> class.
/// </summary>
/// <param name="towgs84"></param>
public DatumTransform(Wgs84ConversionInfo towgs84) : this(towgs84,false)
{
}
private DatumTransform(Wgs84ConversionInfo towgs84, bool isInverse)
{
_toWgs94 = towgs84;
_v = _toWgs94.GetAffineTransform();
_isInverse = isInverse;
}
/// <summary>
/// Gets a Well-Known text representation of this object.
/// </summary>
/// <value></value>
public override string WKT
{
get { throw new NotImplementedException(); }
}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
/// <value></value>
public override string XML
{
get { throw new NotImplementedException(); }
}
public override int DimSource
{
get { return 3; }
}
public override int DimTarget
{
get { return 3; }
}
/// <summary>
/// Creates the inverse transform of this object.
/// </summary>
/// <returns></returns>
/// <remarks>This method may fail if the transform is not one to one. However, all cartographic projections should succeed.</remarks>
public override MathTransform Inverse()
{
if (_inverse == null)
_inverse = new DatumTransform(_toWgs94,!_isInverse);
return _inverse;
}
/// <inheritdoc />
public sealed override void Transform(ref double x, ref double y, ref double z)
{
if (_isInverse)
{
(x, y, z) = ApplyInverted(x, y, z);
}
else
{
(x, y, z) = Apply(x, y, z);
}
}
private (double x, double y, double z) Apply(double x, double y, double z)
{
return (
x: _v[0] * (x - _v[3] * y + _v[2] * z) + _v[4],
y: _v[0] * (_v[3] * x + y - _v[1] * z) + _v[5],
z: _v[0] * (-_v[2] * x + _v[1] * y + z) + _v[6]);
}
private (double x, double y, double z) ApplyInverted(double x, double y, double z)
{
return (
x: (1 - (_v[0] - 1)) * (x + _v[3] * y - _v[2] * z) - _v[4],
y: (1 - (_v[0] - 1)) * (-_v[3] * x + y + _v[1] * z) - _v[5],
z: (1 - (_v[0] - 1)) * (_v[2] * x - _v[1] * y + z) - _v[6]);
}
/// <summary>
/// Reverses the transformation
/// </summary>
public override void Invert()
{
_isInverse = !_isInverse;
}
}
}

Просмотреть файл

@ -1,280 +1,280 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
///
/// </summary>
/// <remarks>
/// <para>Latitude, Longitude and ellipsoidal height in terms of a 3-dimensional geographic system
/// may by expressed in terms of a geocentric (earth centered) Cartesian coordinate reference system
/// X, Y, Z with the Z axis corresponding to the earth's rotation axis positive northwards, the X
/// axis through the intersection of the prime meridian and equator, and the Y axis through
/// the intersection of the equator with longitude 90 degrees east. The geographic and geocentric
/// systems are based on the same geodetic datum.</para>
/// <para>Geocentric coordinate reference systems are conventionally taken to be defined with the X
/// axis through the intersection of the Greenwich meridian and equator. This requires that the equivalent
/// geographic coordinate reference systems based on a non-Greenwich prime meridian should first be
/// transformed to their Greenwich equivalent. Geocentric coordinates X, Y and Z take their units from
/// the units of the ellipsoid axes (a and b). As it is conventional for X, Y and Z to be in metres,
/// if the ellipsoid axis dimensions are given in another linear unit they should first be converted
/// to metres.</para>
/// </remarks>
[Serializable]
internal class GeocentricTransform : MathTransform
{
private const double COS_67P5 = 0.38268343236508977; /* cosine of 67.5 degrees */
private const double AD_C = 1.0026000; /* Toms region 1 constant */
/// <summary>
///
/// </summary>
private bool _isInverse;
/// <summary>
///
/// </summary>
private MathTransform _inverse;
/// <summary>
/// Eccentricity squared : (a^2 - b^2)/a^2
/// </summary>
private readonly double _es;
/// <summary>
/// major axis
/// </summary>
private readonly double _semiMajor;
/// <summary>
/// Minor axis
/// </summary>
private readonly double _semiMinor;
/*
private double ab; // Semi_major / semi_minor
private double ba; // Semi_minor / semi_major
*/
private readonly double _ses; // Second eccentricity squared : (a^2 - b^2)/b^2
/// <summary>
///
/// </summary>
private List<ProjectionParameter> _parameters;
/// <summary>
/// Initializes a geocentric projection object
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <param name="isInverse">Indicates whether the projection forward (meters to degrees or degrees to meters).</param>
public GeocentricTransform(List<ProjectionParameter> parameters, bool isInverse) : this(parameters)
{
_isInverse = isInverse;
}
/// <summary>
/// Initializes a geocentric projection object
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
internal GeocentricTransform(List<ProjectionParameter> parameters)
{
_parameters = parameters;
_semiMajor = _parameters.Find(delegate(ProjectionParameter par)
{
// Do not remove the following lines containing "_Parameters = _Parameters;"
// There is an issue deploying code with anonymous delegates to
// SQLCLR because they're compiled using a writable static field
// (which is not allowed in SQLCLR SAFE mode).
// To workaround this, we will use a harmless reference to the
// _Parameters field inside the anonymous delegate code making
// the compiler generates a private nested class with a function
// that is used as the delegate.
// For details, see http://www.hedgate.net/articles/2006/01/27/troubles-with-shared-state-and-anonymous-delegates-in-sqlclr
#pragma warning disable 1717
_parameters = _parameters;
#pragma warning restore 1717
return par.Name.Equals("semi_major", StringComparison.OrdinalIgnoreCase);
}).Value;
_semiMinor = _parameters.Find(delegate(ProjectionParameter par)
{
#pragma warning disable 1717
_parameters = _parameters; // See explanation above.
#pragma warning restore 1717
return par.Name.Equals("semi_minor", StringComparison.OrdinalIgnoreCase);
}).Value;
_es = 1.0 - (_semiMinor * _semiMinor) / (_semiMajor * _semiMajor); //e^2
_ses = (Math.Pow(_semiMajor, 2) - Math.Pow(_semiMinor, 2)) / Math.Pow(_semiMinor, 2);
//ba = _semiMinor / _semiMajor;
//ab = _semiMajor / _semiMinor;
}
public override int DimSource
{
get { return 3; }
}
public override int DimTarget
{
get { return 3; }
}
/// <summary>
/// Returns the inverse of this conversion.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current conversion.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
_inverse = new GeocentricTransform(this._parameters, !_isInverse);
return _inverse;
}
/// <summary>
/// Converts a point (lon, lat, z) in degrees to (x, y, z) in meters
/// </summary>
/// <param name="lon">The longitude in degree</param>
/// <param name="lat">The latitude in degree</param>
/// <param name="z">The z-ordinate value</param>
private void DegreesToMeters(ref double lon, ref double lat, ref double z)
{
lon = Degrees2Radians(lon);
lat = Degrees2Radians(lat);
z = double.IsNaN(z) ? 0 : z;
double v = _semiMajor / Math.Sqrt(1 - _es * Math.Pow(Math.Sin(lat), 2));
double x = (v + z) * Math.Cos(lat) * Math.Cos(lon);
double y = (v + z) * Math.Cos(lat) * Math.Sin(lon);
z = ((1 - _es) * v + z) * Math.Sin(lat);
lon = x;
lat = y;
}
/// <summary>
/// Converts coordinates in projected meters to decimal degrees.
/// </summary>
/// <param name="x">The x-ordinate when entering, the longitude value upon exit.</param>
/// <param name="y">The y-ordinate when entering, the latitude value upon exit.</param>
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
///
/// </summary>
/// <remarks>
/// <para>Latitude, Longitude and ellipsoidal height in terms of a 3-dimensional geographic system
/// may by expressed in terms of a geocentric (earth centered) Cartesian coordinate reference system
/// X, Y, Z with the Z axis corresponding to the earth's rotation axis positive northwards, the X
/// axis through the intersection of the prime meridian and equator, and the Y axis through
/// the intersection of the equator with longitude 90 degrees east. The geographic and geocentric
/// systems are based on the same geodetic datum.</para>
/// <para>Geocentric coordinate reference systems are conventionally taken to be defined with the X
/// axis through the intersection of the Greenwich meridian and equator. This requires that the equivalent
/// geographic coordinate reference systems based on a non-Greenwich prime meridian should first be
/// transformed to their Greenwich equivalent. Geocentric coordinates X, Y and Z take their units from
/// the units of the ellipsoid axes (a and b). As it is conventional for X, Y and Z to be in metres,
/// if the ellipsoid axis dimensions are given in another linear unit they should first be converted
/// to metres.</para>
/// </remarks>
[Serializable]
internal class GeocentricTransform : MathTransform
{
private const double COS_67P5 = 0.38268343236508977; /* cosine of 67.5 degrees */
private const double AD_C = 1.0026000; /* Toms region 1 constant */
/// <summary>
///
/// </summary>
private bool _isInverse;
/// <summary>
///
/// </summary>
private MathTransform _inverse;
/// <summary>
/// Eccentricity squared : (a^2 - b^2)/a^2
/// </summary>
private readonly double _es;
/// <summary>
/// major axis
/// </summary>
private readonly double _semiMajor;
/// <summary>
/// Minor axis
/// </summary>
private readonly double _semiMinor;
/*
private double ab; // Semi_major / semi_minor
private double ba; // Semi_minor / semi_major
*/
private readonly double _ses; // Second eccentricity squared : (a^2 - b^2)/b^2
/// <summary>
///
/// </summary>
private List<ProjectionParameter> _parameters;
/// <summary>
/// Initializes a geocentric projection object
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
/// <param name="isInverse">Indicates whether the projection forward (meters to degrees or degrees to meters).</param>
public GeocentricTransform(List<ProjectionParameter> parameters, bool isInverse) : this(parameters)
{
_isInverse = isInverse;
}
/// <summary>
/// Initializes a geocentric projection object
/// </summary>
/// <param name="parameters">List of parameters to initialize the projection.</param>
internal GeocentricTransform(List<ProjectionParameter> parameters)
{
_parameters = parameters;
_semiMajor = _parameters.Find(delegate(ProjectionParameter par)
{
// Do not remove the following lines containing "_Parameters = _Parameters;"
// There is an issue deploying code with anonymous delegates to
// SQLCLR because they're compiled using a writable static field
// (which is not allowed in SQLCLR SAFE mode).
// To workaround this, we will use a harmless reference to the
// _Parameters field inside the anonymous delegate code making
// the compiler generates a private nested class with a function
// that is used as the delegate.
// For details, see http://www.hedgate.net/articles/2006/01/27/troubles-with-shared-state-and-anonymous-delegates-in-sqlclr
#pragma warning disable 1717
_parameters = _parameters;
#pragma warning restore 1717
return par.Name.Equals("semi_major", StringComparison.OrdinalIgnoreCase);
}).Value;
_semiMinor = _parameters.Find(delegate(ProjectionParameter par)
{
#pragma warning disable 1717
_parameters = _parameters; // See explanation above.
#pragma warning restore 1717
return par.Name.Equals("semi_minor", StringComparison.OrdinalIgnoreCase);
}).Value;
_es = 1.0 - (_semiMinor * _semiMinor) / (_semiMajor * _semiMajor); //e^2
_ses = (Math.Pow(_semiMajor, 2) - Math.Pow(_semiMinor, 2)) / Math.Pow(_semiMinor, 2);
//ba = _semiMinor / _semiMajor;
//ab = _semiMajor / _semiMinor;
}
public override int DimSource
{
get { return 3; }
}
public override int DimTarget
{
get { return 3; }
}
/// <summary>
/// Returns the inverse of this conversion.
/// </summary>
/// <returns>IMathTransform that is the reverse of the current conversion.</returns>
public override MathTransform Inverse()
{
if (_inverse == null)
_inverse = new GeocentricTransform(this._parameters, !_isInverse);
return _inverse;
}
/// <summary>
/// Converts a point (lon, lat, z) in degrees to (x, y, z) in meters
/// </summary>
/// <param name="lon">The longitude in degree</param>
/// <param name="lat">The latitude in degree</param>
/// <param name="z">The z-ordinate value</param>
private void MetersToDegrees(ref double x, ref double y, ref double z)
{
bool At_Pole = false; // indicates whether location is in polar region */
double lon;
double lat = 0;
double Height;
if (x != 0.0)
lon = Math.Atan2(y, x);
else
{
if (y > 0)
lon = Math.PI / 2;
else if (y < 0)
lon = -Math.PI * 0.5;
else
{
At_Pole = true;
lon = 0.0;
if (z > 0.0)
{
/* north pole */
lat = Math.PI * 0.5;
}
else if (z < 0.0)
{
/* south pole */
lat = -Math.PI * 0.5;
}
else
{
/* center of earth */
lon = Radians2Degrees(lon);
lat = Radians2Degrees(Math.PI * 0.5);
x = lon;
y = lat;
z = -_semiMinor;
return;
}
}
}
double W2 = x * x + y * y; // Square of distance from Z axis
double W = Math.Sqrt(W2); // distance from Z axis
double T0 = z * AD_C; // initial estimate of vertical component
double S0 = Math.Sqrt(T0 * T0 + W2); //initial estimate of horizontal component
double Sin_B0 = T0 / S0; //sin(B0), B0 is estimate of Bowring aux variable
double Cos_B0 = W / S0; //cos(B0)
double Sin3_B0 = Math.Pow(Sin_B0, 3);
double T1 = z + _semiMinor * _ses * Sin3_B0; //corrected estimate of vertical component
double Sum = W - _semiMajor * _es * Cos_B0 * Cos_B0 * Cos_B0; //numerator of cos(phi1)
double S1 = Math.Sqrt(T1 * T1 + Sum * Sum); //corrected estimate of horizontal component
double Sin_p1 = T1 / S1; //sin(phi1), phi1 is estimated latitude
double Cos_p1 = Sum / S1; //cos(phi1)
double Rn = _semiMajor / Math.Sqrt(1.0 - _es * Sin_p1 * Sin_p1); //Earth radius at location
if (Cos_p1 >= COS_67P5)
Height = W / Cos_p1 - Rn;
else if (Cos_p1 <= -COS_67P5)
Height = W / -Cos_p1 - Rn;
else Height = z / Sin_p1 + Rn * (_es - 1.0);
if (!At_Pole)
lat = Math.Atan(Sin_p1 / Cos_p1);
x = Radians2Degrees(lon);
y = Radians2Degrees(lat);
z = Height;
}
public sealed override void Transform(ref double x, ref double y, ref double z)
{
if (_isInverse)
MetersToDegrees(ref x, ref y, ref z);
else
private void DegreesToMeters(ref double lon, ref double lat, ref double z)
{
lon = Degrees2Radians(lon);
lat = Degrees2Radians(lat);
z = double.IsNaN(z) ? 0 : z;
double v = _semiMajor / Math.Sqrt(1 - _es * Math.Pow(Math.Sin(lat), 2));
double x = (v + z) * Math.Cos(lat) * Math.Cos(lon);
double y = (v + z) * Math.Cos(lat) * Math.Sin(lon);
z = ((1 - _es) * v + z) * Math.Sin(lat);
lon = x;
lat = y;
}
/// <summary>
/// Converts coordinates in projected meters to decimal degrees.
/// </summary>
/// <param name="x">The x-ordinate when entering, the longitude value upon exit.</param>
/// <param name="y">The y-ordinate when entering, the latitude value upon exit.</param>
/// <param name="z">The z-ordinate value</param>
private void MetersToDegrees(ref double x, ref double y, ref double z)
{
bool At_Pole = false; // indicates whether location is in polar region */
double lon;
double lat = 0;
double Height;
if (x != 0.0)
lon = Math.Atan2(y, x);
else
{
if (y > 0)
lon = Math.PI / 2;
else if (y < 0)
lon = -Math.PI * 0.5;
else
{
At_Pole = true;
lon = 0.0;
if (z > 0.0)
{
/* north pole */
lat = Math.PI * 0.5;
}
else if (z < 0.0)
{
/* south pole */
lat = -Math.PI * 0.5;
}
else
{
/* center of earth */
lon = Radians2Degrees(lon);
lat = Radians2Degrees(Math.PI * 0.5);
x = lon;
y = lat;
z = -_semiMinor;
return;
}
}
}
double W2 = x * x + y * y; // Square of distance from Z axis
double W = Math.Sqrt(W2); // distance from Z axis
double T0 = z * AD_C; // initial estimate of vertical component
double S0 = Math.Sqrt(T0 * T0 + W2); //initial estimate of horizontal component
double Sin_B0 = T0 / S0; //sin(B0), B0 is estimate of Bowring aux variable
double Cos_B0 = W / S0; //cos(B0)
double Sin3_B0 = Math.Pow(Sin_B0, 3);
double T1 = z + _semiMinor * _ses * Sin3_B0; //corrected estimate of vertical component
double Sum = W - _semiMajor * _es * Cos_B0 * Cos_B0 * Cos_B0; //numerator of cos(phi1)
double S1 = Math.Sqrt(T1 * T1 + Sum * Sum); //corrected estimate of horizontal component
double Sin_p1 = T1 / S1; //sin(phi1), phi1 is estimated latitude
double Cos_p1 = Sum / S1; //cos(phi1)
double Rn = _semiMajor / Math.Sqrt(1.0 - _es * Sin_p1 * Sin_p1); //Earth radius at location
if (Cos_p1 >= COS_67P5)
Height = W / Cos_p1 - Rn;
else if (Cos_p1 <= -COS_67P5)
Height = W / -Cos_p1 - Rn;
else Height = z / Sin_p1 + Rn * (_es - 1.0);
if (!At_Pole)
lat = Math.Atan(Sin_p1 / Cos_p1);
x = Radians2Degrees(lon);
y = Radians2Degrees(lat);
z = Height;
}
public sealed override void Transform(ref double x, ref double y, ref double z)
{
if (_isInverse)
MetersToDegrees(ref x, ref y, ref z);
else
DegreesToMeters(ref x, ref y, ref z);
}
/// <summary>
/// Reverses the transformation
/// </summary>
public override void Invert()
{
_isInverse = !_isInverse;
}
/// <summary>
/// Gets a Well-Known text representation of this object.
/// </summary>
/// <value></value>
public override string WKT
{
get { throw new NotImplementedException("The method or operation is not implemented."); }
}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
/// <value></value>
public override string XML
{
get { throw new NotImplementedException("The method or operation is not implemented."); }
}
}
}
}
/// <summary>
/// Reverses the transformation
/// </summary>
public override void Invert()
{
_isInverse = !_isInverse;
}
/// <summary>
/// Gets a Well-Known text representation of this object.
/// </summary>
/// <value></value>
public override string WKT
{
get { throw new NotImplementedException("The method or operation is not implemented."); }
}
/// <summary>
/// Gets an XML representation of this object.
/// </summary>
/// <value></value>
public override string XML
{
get { throw new NotImplementedException("The method or operation is not implemented."); }
}
}
}

Просмотреть файл

@ -1,105 +1,105 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
/// The GeographicTransform class is implemented on geographic transformation objects and
/// implements datum transformations between geographic coordinate systems.
/// </summary>
[Serializable]
public class GeographicTransform : MathTransform
{
internal GeographicTransform(GeographicCoordinateSystem sourceGCS, GeographicCoordinateSystem targetGCS)
{
SourceGCS = sourceGCS;
TargetGCS = targetGCS;
}
/// <summary>
/// Gets or sets the source geographic coordinate system for the transformation.
/// </summary>
public GeographicCoordinateSystem SourceGCS { get; set; }
/// <summary>
/// Gets or sets the target geographic coordinate system for the transformation.
/// </summary>
public GeographicCoordinateSystem TargetGCS { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification. [NOT IMPLEMENTED].
/// </summary>
public override string WKT
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
/// Gets an XML representation of this object [NOT IMPLEMENTED].
/// </summary>
public override string XML
{
get
{
throw new NotImplementedException();
}
}
public override int DimSource
{
get { return SourceGCS.Dimension; }
}
public override int DimTarget
{
get { return TargetGCS.Dimension; }
}
/// <summary>
/// Creates the inverse transform of this object.
/// </summary>
/// <remarks>This method may fail if the transform is not one to one. However, all cartographic projections should succeed.</remarks>
/// <returns></returns>
public override MathTransform Inverse()
{
throw new NotImplementedException();
}
/// <inheritdoc />
public sealed override void Transform(ref double x, ref double y, ref double z)
{
x /= SourceGCS.AngularUnit.RadiansPerUnit;
x -= SourceGCS.PrimeMeridian.Longitude / SourceGCS.PrimeMeridian.AngularUnit.RadiansPerUnit;
x += TargetGCS.PrimeMeridian.Longitude / TargetGCS.PrimeMeridian.AngularUnit.RadiansPerUnit;
x *= SourceGCS.AngularUnit.RadiansPerUnit;
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
/// The GeographicTransform class is implemented on geographic transformation objects and
/// implements datum transformations between geographic coordinate systems.
/// </summary>
[Serializable]
public class GeographicTransform : MathTransform
{
internal GeographicTransform(GeographicCoordinateSystem sourceGCS, GeographicCoordinateSystem targetGCS)
{
SourceGCS = sourceGCS;
TargetGCS = targetGCS;
}
/// <summary>
/// Gets or sets the source geographic coordinate system for the transformation.
/// </summary>
public GeographicCoordinateSystem SourceGCS { get; set; }
/// <summary>
/// Gets or sets the target geographic coordinate system for the transformation.
/// </summary>
public GeographicCoordinateSystem TargetGCS { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification. [NOT IMPLEMENTED].
/// </summary>
public override string WKT
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
/// Gets an XML representation of this object [NOT IMPLEMENTED].
/// </summary>
public override string XML
{
get
{
throw new NotImplementedException();
}
}
public override int DimSource
{
get { return SourceGCS.Dimension; }
}
/// <summary>
/// Reverses the transformation
/// </summary>
public override void Invert()
{
throw new NotImplementedException();
}
}
}
public override int DimTarget
{
get { return TargetGCS.Dimension; }
}
/// <summary>
/// Creates the inverse transform of this object.
/// </summary>
/// <remarks>This method may fail if the transform is not one to one. However, all cartographic projections should succeed.</remarks>
/// <returns></returns>
public override MathTransform Inverse()
{
throw new NotImplementedException();
}
/// <inheritdoc />
public sealed override void Transform(ref double x, ref double y, ref double z)
{
x /= SourceGCS.AngularUnit.RadiansPerUnit;
x -= SourceGCS.PrimeMeridian.Longitude / SourceGCS.PrimeMeridian.AngularUnit.RadiansPerUnit;
x += TargetGCS.PrimeMeridian.Longitude / TargetGCS.PrimeMeridian.AngularUnit.RadiansPerUnit;
x *= SourceGCS.AngularUnit.RadiansPerUnit;
}
/// <summary>
/// Reverses the transformation
/// </summary>
public override void Invert()
{
throw new NotImplementedException();
}
}
}

Просмотреть файл

@ -1,117 +1,117 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
/// Adjusts target Prime Meridian
/// </summary>
[Serializable]
internal class PrimeMeridianTransform : MathTransform
{
#region class variables
private bool _isInverted;
private readonly PrimeMeridian _source;
private readonly PrimeMeridian _target;
#endregion class variables
#region constructors & finalizers
/// <summary>
/// Creates instance prime meridian transform
/// </summary>
/// <param name="source"></param>
/// <param name="target"></param>
public PrimeMeridianTransform(PrimeMeridian source, PrimeMeridian target)
{
if (!source.AngularUnit.EqualParams(target.AngularUnit))
{
throw new NotImplementedException("The method or operation is not implemented.");
}
_source = source;
_target = target;
}
#endregion constructors & finalizers
#region public properties
/// <summary>
/// Gets a Well-Known text representation of this affine math transformation.
/// </summary>
/// <value></value>
public override string WKT
{
get { throw new NotImplementedException("The method or operation is not implemented."); }
}
/// <summary>
/// Gets an XML representation of this affine transformation.
/// </summary>
/// <value></value>
public override string XML
{
get { throw new NotImplementedException("The method or operation is not implemented."); }
}
/// <summary>
/// Gets the dimension of input points.
/// </summary>
public override int DimSource { get { return 3; } }
/// <summary>
/// Gets the dimension of output points.
/// </summary>
public override int DimTarget { get { return 3; } }
#endregion public properties
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
#region public methods
/// <inheritdoc />
public override MathTransform Inverse()
{
return new PrimeMeridianTransform(_target, _source);
}
/// <inheritdoc />
public sealed override void Transform(ref double x, ref double y, ref double z)
{
if (_isInverted)
x += _target.Longitude - _source.Longitude;
else
x += _source.Longitude - _target.Longitude;
}
protected override void TransformCore(Span<double> xs, Span<double> ys, Span<double> zs,
int strideX, int strideY, int strideZ)
{
for (int i = 0, j = 0, k = 0; i < xs.Length; i += strideX, j += strideY, k += strideZ)
{
Transform(ref xs[i], ref ys[j], ref zs[k]);
}
}
/// <inheritdoc />
public override void Invert()
{
_isInverted = !_isInverted;
}
#endregion public methods
}
}
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
namespace ProjNet.CoordinateSystems.Transformations
{
/// <summary>
/// Adjusts target Prime Meridian
/// </summary>
[Serializable]
internal class PrimeMeridianTransform : MathTransform
{
#region class variables
private bool _isInverted;
private readonly PrimeMeridian _source;
private readonly PrimeMeridian _target;
#endregion class variables
#region constructors & finalizers
/// <summary>
/// Creates instance prime meridian transform
/// </summary>
/// <param name="source"></param>
/// <param name="target"></param>
public PrimeMeridianTransform(PrimeMeridian source, PrimeMeridian target)
{
if (!source.AngularUnit.EqualParams(target.AngularUnit))
{
throw new NotImplementedException("The method or operation is not implemented.");
}
_source = source;
_target = target;
}
#endregion constructors & finalizers
#region public properties
/// <summary>
/// Gets a Well-Known text representation of this affine math transformation.
/// </summary>
/// <value></value>
public override string WKT
{
get { throw new NotImplementedException("The method or operation is not implemented."); }
}
/// <summary>
/// Gets an XML representation of this affine transformation.
/// </summary>
/// <value></value>
public override string XML
{
get { throw new NotImplementedException("The method or operation is not implemented."); }
}
/// <summary>
/// Gets the dimension of input points.
/// </summary>
public override int DimSource { get { return 3; } }
/// <summary>
/// Gets the dimension of output points.
/// </summary>
public override int DimTarget { get { return 3; } }
#endregion public properties
#region public methods
/// <inheritdoc />
public override MathTransform Inverse()
{
return new PrimeMeridianTransform(_target, _source);
}
/// <inheritdoc />
public sealed override void Transform(ref double x, ref double y, ref double z)
{
if (_isInverted)
x += _target.Longitude - _source.Longitude;
else
x += _source.Longitude - _target.Longitude;
}
protected override void TransformCore(Span<double> xs, Span<double> ys, Span<double> zs,
int strideX, int strideY, int strideZ)
{
for (int i = 0, j = 0, k = 0; i < xs.Length; i += strideX, j += strideY, k += strideZ)
{
Transform(ref xs[i], ref ys[j], ref zs[k]);
}
}
/// <inheritdoc />
public override void Invert()
{
_isInverted = !_isInverted;
}
#endregion public methods
}
}

Просмотреть файл

@ -1,104 +1,104 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Class for defining units
/// </summary>
[Serializable]
public class Unit : Info, IUnit
{
/// <summary>
/// Initializes a new unit
/// </summary>
/// <param name="conversionFactor">Conversion factor to base unit</param>
/// <param name="name">Name of unit</param>
/// <param name="authority">Authority name</param>
/// <param name="authorityCode">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal Unit(double conversionFactor, string name, string authority, long authorityCode, string alias, string abbreviation, string remarks)
:
base(name, authority, authorityCode, alias, abbreviation, remarks)
{
ConversionFactor = conversionFactor;
}
/// <summary>
/// Initializes a new unit
/// </summary>
/// <param name="name">Name of unit</param>
/// <param name="conversionFactor">Conversion factor to base unit</param>
internal Unit(string name, double conversionFactor)
: this(conversionFactor, name, string.Empty, -1, string.Empty, string.Empty, string.Empty)
{
}
/// <summary>
/// Gets or sets the number of units per base-unit.
/// </summary>
public double ConversionFactor { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat, "UNIT[\"{0}\", {1}", Name, ConversionFactor);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object [NOT IMPLEMENTED].
/// </summary>
public override string XML
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is Unit))
return false;
return (obj as Unit).ConversionFactor == ConversionFactor;
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Globalization;
using System.Text;
namespace ProjNet.CoordinateSystems
{
/// <summary>
/// Class for defining units
/// </summary>
[Serializable]
public class Unit : Info, IUnit
{
/// <summary>
/// Initializes a new unit
/// </summary>
/// <param name="conversionFactor">Conversion factor to base unit</param>
/// <param name="name">Name of unit</param>
/// <param name="authority">Authority name</param>
/// <param name="authorityCode">Authority-specific identification code.</param>
/// <param name="alias">Alias</param>
/// <param name="abbreviation">Abbreviation</param>
/// <param name="remarks">Provider-supplied remarks</param>
internal Unit(double conversionFactor, string name, string authority, long authorityCode, string alias, string abbreviation, string remarks)
:
base(name, authority, authorityCode, alias, abbreviation, remarks)
{
ConversionFactor = conversionFactor;
}
/// <summary>
/// Initializes a new unit
/// </summary>
/// <param name="name">Name of unit</param>
/// <param name="conversionFactor">Conversion factor to base unit</param>
internal Unit(string name, double conversionFactor)
: this(conversionFactor, name, string.Empty, -1, string.Empty, string.Empty, string.Empty)
{
}
/// <summary>
/// Gets or sets the number of units per base-unit.
/// </summary>
public double ConversionFactor { get; set; }
/// <summary>
/// Returns the Well-known text for this object
/// as defined in the simple features specification.
/// </summary>
public override string WKT
{
get
{
var sb = new StringBuilder();
sb.AppendFormat(CultureInfo.InvariantCulture.NumberFormat, "UNIT[\"{0}\", {1}", Name, ConversionFactor);
if (!string.IsNullOrWhiteSpace(Authority) && AuthorityCode > 0)
sb.AppendFormat(", AUTHORITY[\"{0}\", \"{1}\"]", Authority, AuthorityCode);
sb.Append("]");
return sb.ToString();
}
}
/// <summary>
/// Gets an XML representation of this object [NOT IMPLEMENTED].
/// </summary>
public override string XML
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
/// Checks whether the values of this instance is equal to the values of another instance.
/// Only parameters used for coordinate system are used for comparison.
/// Name, abbreviation, authority, alias and remarks are ignored in the comparison.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if equal</returns>
public override bool EqualParams(object obj)
{
if (!(obj is Unit))
return false;
return (obj as Unit).ConversionFactor == ConversionFactor;
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,241 +1,241 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Collections.Generic;
using System.IO;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.IO.CoordinateSystems
{
/// <summary>
/// Creates an math transform based on the supplied Well Known Text (WKT).
/// </summary>
public static class MathTransformWktReader
{
/// <summary>
/// Reads and parses a WKT-formatted projection string.
/// </summary>
/// <param name="wkt">String containing WKT.</param>
/// <returns>Object representation of the WKT.</returns>
/// <exception cref="System.ArgumentException">If a token is not recognised.</exception>
public static MathTransform Parse (string wkt)
{
if (string.IsNullOrWhiteSpace (wkt))
throw new ArgumentNullException ("wkt");
using (TextReader reader = new StringReader (wkt))
{
var tokenizer = new WktStreamTokenizer (reader);
tokenizer.NextToken ();
string objectName = tokenizer.GetStringValue ();
switch (objectName)
{
case "PARAM_MT":
return ReadMathTransform (tokenizer);
default:
throw new ArgumentException ($"'{objectName}' is not recognized.");
}
}
}
/// <summary>
/// Reads math transform from using current token from the specified tokenizer
/// </summary>
/// <param name="tokenizer"></param>
/// <returns></returns>
internal static MathTransform ReadMathTransform (WktStreamTokenizer tokenizer)
{
if (tokenizer.GetStringValue () != "PARAM_MT")
tokenizer.ReadToken ("PARAM_MT");
tokenizer.ReadToken ("[");
string transformName = tokenizer.ReadDoubleQuotedWord ();
tokenizer.ReadToken (",");
switch (transformName.ToUpperInvariant ())
{
case "AFFINE":
return ReadAffineTransform (tokenizer);
default:
throw new NotSupportedException ("Transform not supported '" + transformName + "'");
}
}
private static ParameterInfo ReadParameters (WktStreamTokenizer tokenizer)
{
var paramList = new List<Parameter> ();
while (tokenizer.GetStringValue () == "PARAMETER")
{
tokenizer.ReadToken ("[");
string paramName = tokenizer.ReadDoubleQuotedWord ();
tokenizer.ReadToken (",");
tokenizer.NextToken ();
double paramValue = tokenizer.GetNumericValue ();
tokenizer.ReadToken ("]");
//test, whether next parameter is delimited by comma
tokenizer.NextToken ();
if (tokenizer.GetStringValue () != "]")
tokenizer.NextToken ();
paramList.Add (new Parameter (paramName, paramValue));
}
var info = new ParameterInfo () { Parameters = paramList };
return info;
}
private static MathTransform ReadAffineTransform (WktStreamTokenizer tokenizer)
{
/*
PARAM_MT[
"Affine",
PARAMETER["num_row",3],
PARAMETER["num_col",3],
PARAMETER["elt_0_0", 0.883485346527455],
PARAMETER["elt_0_1", -0.468458794848877],
PARAMETER["elt_0_2", 3455869.17937689],
PARAMETER["elt_1_0", 0.468458794848877],
PARAMETER["elt_1_1", 0.883485346527455],
PARAMETER["elt_1_2", 5478710.88035753],
PARAMETER["elt_2_2", 1]
]
*/
//tokenizer stands on the first PARAMETER
if (tokenizer.GetStringValue () != "PARAMETER")
tokenizer.ReadToken ("PARAMETER");
var paramInfo = ReadParameters (tokenizer);
//manage required parameters - row, col
var rowParam = paramInfo.GetParameterByName ("num_row");
var colParam = paramInfo.GetParameterByName ("num_col");
if (rowParam == null)
{
throw new ArgumentNullException (nameof(rowParam), "Affine transform does not contain 'num_row' parameter");
}
if (colParam == null)
{
throw new ArgumentNullException (nameof(colParam), "Affine transform does not contain 'num_col' parameter");
}
int rowVal = (int)rowParam.Value;
int colVal = (int)colParam.Value;
if (rowVal <= 0)
{
throw new ArgumentException ("Affine transform contains invalid value of 'num_row' parameter");
}
if (colVal <= 0)
{
throw new ArgumentException ("Affine transform contains invalid value of 'num_col' parameter");
}
//creates working matrix;
double[,] matrix = new double[rowVal, colVal];
//simply process matrix values - no elt_ROW_COL parsing
foreach (var param in paramInfo.Parameters)
{
if (param == null || param.Name == null)
{
continue;
}
switch (param.Name)
{
case "num_row":
case "num_col":
break;
case "elt_0_0":
matrix[0, 0] = param.Value;
break;
case "elt_0_1":
matrix[0, 1] = param.Value;
break;
case "elt_0_2":
matrix[0, 2] = param.Value;
break;
case "elt_0_3":
matrix[0, 3] = param.Value;
break;
case "elt_1_0":
matrix[1, 0] = param.Value;
break;
case "elt_1_1":
matrix[1, 1] = param.Value;
break;
case "elt_1_2":
matrix[1, 2] = param.Value;
break;
case "elt_1_3":
matrix[1, 3] = param.Value;
break;
case "elt_2_0":
matrix[2, 0] = param.Value;
break;
case "elt_2_1":
matrix[2, 1] = param.Value;
break;
case "elt_2_2":
matrix[2, 2] = param.Value;
break;
case "elt_2_3":
matrix[2, 3] = param.Value;
break;
case "elt_3_0":
matrix[3, 0] = param.Value;
break;
case "elt_3_1":
matrix[3, 1] = param.Value;
break;
case "elt_3_2":
matrix[3, 2] = param.Value;
break;
case "elt_3_3":
matrix[3, 3] = param.Value;
break;
}
}
//read rest of WKT
if (tokenizer.GetStringValue () != "]")
tokenizer.ReadToken ("]");
//use "matrix" constructor to create transformation matrix
var affineTransform = new AffineTransform (matrix);
return affineTransform;
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Collections.Generic;
using System.IO;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
namespace ProjNet.IO.CoordinateSystems
{
/// <summary>
/// Creates an math transform based on the supplied Well Known Text (WKT).
/// </summary>
public static class MathTransformWktReader
{
/// <summary>
/// Reads and parses a WKT-formatted projection string.
/// </summary>
/// <param name="wkt">String containing WKT.</param>
/// <returns>Object representation of the WKT.</returns>
/// <exception cref="System.ArgumentException">If a token is not recognised.</exception>
public static MathTransform Parse (string wkt)
{
if (string.IsNullOrWhiteSpace (wkt))
throw new ArgumentNullException ("wkt");
using (TextReader reader = new StringReader (wkt))
{
var tokenizer = new WktStreamTokenizer (reader);
tokenizer.NextToken ();
string objectName = tokenizer.GetStringValue ();
switch (objectName)
{
case "PARAM_MT":
return ReadMathTransform (tokenizer);
default:
throw new ArgumentException ($"'{objectName}' is not recognized.");
}
}
}
/// <summary>
/// Reads math transform from using current token from the specified tokenizer
/// </summary>
/// <param name="tokenizer"></param>
/// <returns></returns>
internal static MathTransform ReadMathTransform (WktStreamTokenizer tokenizer)
{
if (tokenizer.GetStringValue () != "PARAM_MT")
tokenizer.ReadToken ("PARAM_MT");
tokenizer.ReadToken ("[");
string transformName = tokenizer.ReadDoubleQuotedWord ();
tokenizer.ReadToken (",");
switch (transformName.ToUpperInvariant ())
{
case "AFFINE":
return ReadAffineTransform (tokenizer);
default:
throw new NotSupportedException ("Transform not supported '" + transformName + "'");
}
}
private static ParameterInfo ReadParameters (WktStreamTokenizer tokenizer)
{
var paramList = new List<Parameter> ();
while (tokenizer.GetStringValue () == "PARAMETER")
{
tokenizer.ReadToken ("[");
string paramName = tokenizer.ReadDoubleQuotedWord ();
tokenizer.ReadToken (",");
tokenizer.NextToken ();
double paramValue = tokenizer.GetNumericValue ();
tokenizer.ReadToken ("]");
//test, whether next parameter is delimited by comma
tokenizer.NextToken ();
if (tokenizer.GetStringValue () != "]")
tokenizer.NextToken ();
paramList.Add (new Parameter (paramName, paramValue));
}
var info = new ParameterInfo () { Parameters = paramList };
return info;
}
private static MathTransform ReadAffineTransform (WktStreamTokenizer tokenizer)
{
/*
PARAM_MT[
"Affine",
PARAMETER["num_row",3],
PARAMETER["num_col",3],
PARAMETER["elt_0_0", 0.883485346527455],
PARAMETER["elt_0_1", -0.468458794848877],
PARAMETER["elt_0_2", 3455869.17937689],
PARAMETER["elt_1_0", 0.468458794848877],
PARAMETER["elt_1_1", 0.883485346527455],
PARAMETER["elt_1_2", 5478710.88035753],
PARAMETER["elt_2_2", 1]
]
*/
//tokenizer stands on the first PARAMETER
if (tokenizer.GetStringValue () != "PARAMETER")
tokenizer.ReadToken ("PARAMETER");
var paramInfo = ReadParameters (tokenizer);
//manage required parameters - row, col
var rowParam = paramInfo.GetParameterByName ("num_row");
var colParam = paramInfo.GetParameterByName ("num_col");
if (rowParam == null)
{
throw new ArgumentNullException (nameof(rowParam), "Affine transform does not contain 'num_row' parameter");
}
if (colParam == null)
{
throw new ArgumentNullException (nameof(colParam), "Affine transform does not contain 'num_col' parameter");
}
int rowVal = (int)rowParam.Value;
int colVal = (int)colParam.Value;
if (rowVal <= 0)
{
throw new ArgumentException ("Affine transform contains invalid value of 'num_row' parameter");
}
if (colVal <= 0)
{
throw new ArgumentException ("Affine transform contains invalid value of 'num_col' parameter");
}
//creates working matrix;
double[,] matrix = new double[rowVal, colVal];
//simply process matrix values - no elt_ROW_COL parsing
foreach (var param in paramInfo.Parameters)
{
if (param == null || param.Name == null)
{
continue;
}
switch (param.Name)
{
case "num_row":
case "num_col":
break;
case "elt_0_0":
matrix[0, 0] = param.Value;
break;
case "elt_0_1":
matrix[0, 1] = param.Value;
break;
case "elt_0_2":
matrix[0, 2] = param.Value;
break;
case "elt_0_3":
matrix[0, 3] = param.Value;
break;
case "elt_1_0":
matrix[1, 0] = param.Value;
break;
case "elt_1_1":
matrix[1, 1] = param.Value;
break;
case "elt_1_2":
matrix[1, 2] = param.Value;
break;
case "elt_1_3":
matrix[1, 3] = param.Value;
break;
case "elt_2_0":
matrix[2, 0] = param.Value;
break;
case "elt_2_1":
matrix[2, 1] = param.Value;
break;
case "elt_2_2":
matrix[2, 2] = param.Value;
break;
case "elt_2_3":
matrix[2, 3] = param.Value;
break;
case "elt_3_0":
matrix[3, 0] = param.Value;
break;
case "elt_3_1":
matrix[3, 1] = param.Value;
break;
case "elt_3_2":
matrix[3, 2] = param.Value;
break;
case "elt_3_3":
matrix[3, 3] = param.Value;
break;
}
}
//read rest of WKT
if (tokenizer.GetStringValue () != "]")
tokenizer.ReadToken ("]");
//use "matrix" constructor to create transformation matrix
var affineTransform = new AffineTransform (matrix);
return affineTransform;
}
}
}

Просмотреть файл

@ -1,272 +1,272 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Globalization;
using System.IO;
namespace ProjNet.IO.CoordinateSystems
{
///<summary>
///The StreamTokenizer class takes an input stream and parses it into "tokens", allowing the tokens to be read one at a time. The parsing process is controlled by a table and a number of flags that can be set to various states. The stream tokenizer can recognize identifiers, numbers, quoted strings, and various comment style
///</summary>
///<remarks>
///This is a crude c# implementation of Java's <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/io/StreamTokenizer.html">StreamTokenizer</a> class.
///</remarks>
internal class StreamTokenizer
{
private readonly NumberFormatInfo _nfi = CultureInfo.InvariantCulture.NumberFormat;
private TokenType _currentTokenType;
private readonly TextReader _reader;
private string _currentToken;
private int _lineNumber = 1;
private int _colNumber = 1;
private readonly bool _ignoreWhitespace;
/// <summary>
/// Initializes a new instance of the StreamTokenizer class.
/// </summary>
/// <param name="reader">A TextReader with some text to read.</param>
/// <param name="ignoreWhitespace">Flag indicating whether whitespace should be ignored.</param>
public StreamTokenizer(TextReader reader, bool ignoreWhitespace)
{
if (reader == null)
throw new ArgumentNullException("reader");
_reader = reader;
_ignoreWhitespace = ignoreWhitespace;
}
/// <summary>
/// The current line number of the stream being read.
/// </summary>
public int LineNumber
{
get { return _lineNumber; }
}
/// <summary>
/// The current column number of the stream being read.
/// </summary>
public int Column
{
get { return _colNumber; }
}
public bool IgnoreWhitespace
{
get { return _ignoreWhitespace; }
}
/// <summary>
/// If the current token is a number, this field contains the value of that number.
/// </summary>
/// <remarks>
/// If the current token is a number, this field contains the value of that number. The current token is a number when the value of the ttype field is TT_NUMBER.
/// </remarks>
/// <exception cref="FormatException">Current token is not a number in a valid format.</exception>
public double GetNumericValue()
{
string number = GetStringValue();
if (GetTokenType() == TokenType.Number)
return double.Parse(number, _nfi);
string s = string.Format(_nfi, "The token '{0}' is not a number at line {1} column {2}.",
number, LineNumber, Column);
throw new ArgumentException(s);
}
/// <summary>
/// If the current token is a word token, this field contains a string giving the characters of the word token.
/// </summary>
public string GetStringValue()
{
return _currentToken;
}
/// <summary>
/// Gets the token type of the current token.
/// </summary>
/// <returns></returns>
public TokenType GetTokenType()
{
return _currentTokenType;
}
/// <summary>
/// Returns the next token.
/// </summary>
/// <param name="ignoreWhitespace">Determines is whitespace is ignored. True if whitespace is to be ignored.</param>
/// <returns>The TokenType of the next token.</returns>
public TokenType NextToken(bool ignoreWhitespace)
{
return ignoreWhitespace ? NextNonWhitespaceToken() : NextTokenAny();
}
/// <summary>
/// Returns the next token.
/// </summary>
/// <returns>The TokenType of the next token.</returns>
public TokenType NextToken()
{
return NextToken(IgnoreWhitespace);
}
private TokenType NextTokenAny()
{
_currentToken = "";
_currentTokenType = TokenType.Eof;
int finished = _reader.Read();
bool isNumber = false;
bool isWord = false;
while (finished != -1)
{
char currentCharacter = (char) finished;
char nextCharacter = (char) _reader.Peek();
_currentTokenType = GetType(currentCharacter);
var nextTokenType = GetType(nextCharacter);
// handling of words with _
if (isWord && currentCharacter == '_')
_currentTokenType = TokenType.Word;
// handing of words ending in numbers
if (isWord && _currentTokenType == TokenType.Number)
_currentTokenType = TokenType.Word;
if (!isNumber)
{
if (_currentTokenType == TokenType.Word && nextCharacter == '_')
{
//enable words with _ inbetween
nextTokenType = TokenType.Word;
isWord = true;
}
if (_currentTokenType == TokenType.Word && nextTokenType == TokenType.Number)
{
//enable words ending with numbers
nextTokenType = TokenType.Word;
isWord = true;
}
}
// handle negative numbers
if (currentCharacter == '-' && nextTokenType == TokenType.Number && isNumber == false)
{
_currentTokenType = TokenType.Number;
nextTokenType = TokenType.Number;
}
// this handles numbers with a decimal point
if (isNumber && nextTokenType == TokenType.Number && currentCharacter == '.')
_currentTokenType = TokenType.Number;
if (_currentTokenType == TokenType.Number && nextCharacter == '.' && isNumber == false)
{
nextTokenType = TokenType.Number;
isNumber = true;
}
// this handles numbers with a scientific notation
if (isNumber)
{
if (_currentTokenType == TokenType.Number && nextCharacter == 'E')
{
nextTokenType = TokenType.Number;
}
if (currentCharacter == 'E' && (nextCharacter == '-' || nextCharacter == '+'))
{
_currentTokenType = TokenType.Number;
nextTokenType = TokenType.Number;
}
if ((currentCharacter == 'E' || currentCharacter == '-' || currentCharacter == '+') && nextTokenType == TokenType.Number)
{
_currentTokenType = TokenType.Number;
}
}
_colNumber++;
if (_currentTokenType == TokenType.Eol)
{
_lineNumber++;
_colNumber = 1;
}
_currentToken = _currentToken + currentCharacter;
if (_currentTokenType != nextTokenType)
finished = -1;
else if (_currentTokenType == TokenType.Symbol && currentCharacter != '-')
finished = -1;
else finished = _reader.Read();
}
return _currentTokenType;
}
/// <summary>
/// Determines a characters type (e.g. number, symbols, character).
/// </summary>
/// <param name="character">The character to determine.</param>
/// <returns>The TokenType the character is.</returns>
private static TokenType GetType(char character)
{
if (char.IsDigit(character))
return TokenType.Number;
if (char.IsLetter(character))
return TokenType.Word;
if (character == '\n')
return TokenType.Eol;
if (char.IsWhiteSpace(character) || char.IsControl(character))
return TokenType.Whitespace;
return TokenType.Symbol;
}
/// <summary>
/// Returns next token that is not whitespace.
/// </summary>
/// <returns></returns>
private TokenType NextNonWhitespaceToken()
{
var tokenType = NextTokenAny();
while (tokenType == TokenType.Whitespace || tokenType == TokenType.Eol)
tokenType = NextTokenAny();
return tokenType;
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Globalization;
using System.IO;
namespace ProjNet.IO.CoordinateSystems
{
///<summary>
///The StreamTokenizer class takes an input stream and parses it into "tokens", allowing the tokens to be read one at a time. The parsing process is controlled by a table and a number of flags that can be set to various states. The stream tokenizer can recognize identifiers, numbers, quoted strings, and various comment style
///</summary>
///<remarks>
///This is a crude c# implementation of Java's <a href="http://java.sun.com/products/jdk/1.2/docs/api/java/io/StreamTokenizer.html">StreamTokenizer</a> class.
///</remarks>
internal class StreamTokenizer
{
private readonly NumberFormatInfo _nfi = CultureInfo.InvariantCulture.NumberFormat;
private TokenType _currentTokenType;
private readonly TextReader _reader;
private string _currentToken;
private int _lineNumber = 1;
private int _colNumber = 1;
private readonly bool _ignoreWhitespace;
/// <summary>
/// Initializes a new instance of the StreamTokenizer class.
/// </summary>
/// <param name="reader">A TextReader with some text to read.</param>
/// <param name="ignoreWhitespace">Flag indicating whether whitespace should be ignored.</param>
public StreamTokenizer(TextReader reader, bool ignoreWhitespace)
{
if (reader == null)
throw new ArgumentNullException("reader");
_reader = reader;
_ignoreWhitespace = ignoreWhitespace;
}
/// <summary>
/// The current line number of the stream being read.
/// </summary>
public int LineNumber
{
get { return _lineNumber; }
}
/// <summary>
/// The current column number of the stream being read.
/// </summary>
public int Column
{
get { return _colNumber; }
}
public bool IgnoreWhitespace
{
get { return _ignoreWhitespace; }
}
/// <summary>
/// If the current token is a number, this field contains the value of that number.
/// </summary>
/// <remarks>
/// If the current token is a number, this field contains the value of that number. The current token is a number when the value of the ttype field is TT_NUMBER.
/// </remarks>
/// <exception cref="FormatException">Current token is not a number in a valid format.</exception>
public double GetNumericValue()
{
string number = GetStringValue();
if (GetTokenType() == TokenType.Number)
return double.Parse(number, _nfi);
string s = string.Format(_nfi, "The token '{0}' is not a number at line {1} column {2}.",
number, LineNumber, Column);
throw new ArgumentException(s);
}
/// <summary>
/// If the current token is a word token, this field contains a string giving the characters of the word token.
/// </summary>
public string GetStringValue()
{
return _currentToken;
}
/// <summary>
/// Gets the token type of the current token.
/// </summary>
/// <returns></returns>
public TokenType GetTokenType()
{
return _currentTokenType;
}
/// <summary>
/// Returns the next token.
/// </summary>
/// <param name="ignoreWhitespace">Determines is whitespace is ignored. True if whitespace is to be ignored.</param>
/// <returns>The TokenType of the next token.</returns>
public TokenType NextToken(bool ignoreWhitespace)
{
return ignoreWhitespace ? NextNonWhitespaceToken() : NextTokenAny();
}
/// <summary>
/// Returns the next token.
/// </summary>
/// <returns>The TokenType of the next token.</returns>
public TokenType NextToken()
{
return NextToken(IgnoreWhitespace);
}
private TokenType NextTokenAny()
{
_currentToken = "";
_currentTokenType = TokenType.Eof;
int finished = _reader.Read();
bool isNumber = false;
bool isWord = false;
while (finished != -1)
{
char currentCharacter = (char) finished;
char nextCharacter = (char) _reader.Peek();
_currentTokenType = GetType(currentCharacter);
var nextTokenType = GetType(nextCharacter);
// handling of words with _
if (isWord && currentCharacter == '_')
_currentTokenType = TokenType.Word;
// handing of words ending in numbers
if (isWord && _currentTokenType == TokenType.Number)
_currentTokenType = TokenType.Word;
if (!isNumber)
{
if (_currentTokenType == TokenType.Word && nextCharacter == '_')
{
//enable words with _ inbetween
nextTokenType = TokenType.Word;
isWord = true;
}
if (_currentTokenType == TokenType.Word && nextTokenType == TokenType.Number)
{
//enable words ending with numbers
nextTokenType = TokenType.Word;
isWord = true;
}
}
// handle negative numbers
if (currentCharacter == '-' && nextTokenType == TokenType.Number && isNumber == false)
{
_currentTokenType = TokenType.Number;
nextTokenType = TokenType.Number;
}
// this handles numbers with a decimal point
if (isNumber && nextTokenType == TokenType.Number && currentCharacter == '.')
_currentTokenType = TokenType.Number;
if (_currentTokenType == TokenType.Number && nextCharacter == '.' && isNumber == false)
{
nextTokenType = TokenType.Number;
isNumber = true;
}
// this handles numbers with a scientific notation
if (isNumber)
{
if (_currentTokenType == TokenType.Number && nextCharacter == 'E')
{
nextTokenType = TokenType.Number;
}
if (currentCharacter == 'E' && (nextCharacter == '-' || nextCharacter == '+'))
{
_currentTokenType = TokenType.Number;
nextTokenType = TokenType.Number;
}
if ((currentCharacter == 'E' || currentCharacter == '-' || currentCharacter == '+') && nextTokenType == TokenType.Number)
{
_currentTokenType = TokenType.Number;
}
}
_colNumber++;
if (_currentTokenType == TokenType.Eol)
{
_lineNumber++;
_colNumber = 1;
}
_currentToken = _currentToken + currentCharacter;
if (_currentTokenType != nextTokenType)
finished = -1;
else if (_currentTokenType == TokenType.Symbol && currentCharacter != '-')
finished = -1;
else finished = _reader.Read();
}
return _currentTokenType;
}
/// <summary>
/// Determines a characters type (e.g. number, symbols, character).
/// </summary>
/// <param name="character">The character to determine.</param>
/// <returns>The TokenType the character is.</returns>
private static TokenType GetType(char character)
{
if (char.IsDigit(character))
return TokenType.Number;
if (char.IsLetter(character))
return TokenType.Word;
if (character == '\n')
return TokenType.Eol;
if (char.IsWhiteSpace(character) || char.IsControl(character))
return TokenType.Whitespace;
return TokenType.Symbol;
}
/// <summary>
/// Returns next token that is not whitespace.
/// </summary>
/// <returns></returns>
private TokenType NextNonWhitespaceToken()
{
var tokenType = NextTokenAny();
while (tokenType == TokenType.Whitespace || tokenType == TokenType.Eol)
tokenType = NextTokenAny();
return tokenType;
}
}
}

Просмотреть файл

@ -1,76 +1,76 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#region Using
#endregion
namespace ProjNet.IO.CoordinateSystems
{
/// <summary>
/// Represents the type of token created by the StreamTokenizer class.
/// </summary>
internal enum TokenType
{
/// <summary>
/// Indicates that the token is a word.
/// </summary>
Word,
/// <summary>
/// Indicates that the token is a number.
/// </summary>
Number,
/// <summary>
/// Indicates that the end of line has been read. The field can only have this value if the eolIsSignificant method has been called with the argument true.
/// </summary>
Eol,
/// <summary>
/// Indicates that the end of the input stream has been reached.
/// </summary>
Eof,
/// <summary>
/// Indictaes that the token is white space (space, tab, newline).
/// </summary>
Whitespace,
/// <summary>
/// Characters that are not whitespace, numbers, etc...
/// </summary>
Symbol
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#region Using
#endregion
namespace ProjNet.IO.CoordinateSystems
{
/// <summary>
/// Represents the type of token created by the StreamTokenizer class.
/// </summary>
internal enum TokenType
{
/// <summary>
/// Indicates that the token is a word.
/// </summary>
Word,
/// <summary>
/// Indicates that the token is a number.
/// </summary>
Number,
/// <summary>
/// Indicates that the end of line has been read. The field can only have this value if the eolIsSignificant method has been called with the argument true.
/// </summary>
Eol,
/// <summary>
/// Indicates that the end of the input stream has been reached.
/// </summary>
Eof,
/// <summary>
/// Indictaes that the token is white space (space, tab, newline).
/// </summary>
Whitespace,
/// <summary>
/// Characters that are not whitespace, numbers, etc...
/// </summary>
Symbol
}
}

Просмотреть файл

@ -1,115 +1,115 @@
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Globalization;
using System.IO;
namespace ProjNet.IO.CoordinateSystems
{
/// <summary>
/// Reads a stream of Well Known Text (wkt) string and returns a stream of tokens.
/// </summary>
internal class WktStreamTokenizer : StreamTokenizer
{
private readonly NumberFormatInfo _nfi = CultureInfo.InvariantCulture.NumberFormat;
/// <summary>
/// Initializes a new instance of the WktStreamTokenizer class.
/// </summary>
/// <remarks>The WktStreamTokenizer class ais in reading WKT streams.</remarks>
/// <param name="reader">A TextReader that contains </param>
public WktStreamTokenizer(TextReader reader) : base(reader, true) { }
/// <summary>
/// Reads a token and checks it is what is expected.
/// </summary>
/// <param name="expectedToken">The expected token.</param>
internal void ReadToken(string expectedToken)
{
NextToken();
if (GetStringValue() != expectedToken)
{
string s = string.Format(_nfi, "Expecting ('{3}') but got a '{0}' at line {1} column {2}.", GetStringValue(), LineNumber, Column, expectedToken);
throw new ArgumentException(s);
}
}
/// <summary>
/// Reads a string inside double quotes.
/// </summary>
/// <remarks>
/// White space inside quotes is preserved.
/// </remarks>
/// <returns>The string inside the double quotes.</returns>
public string ReadDoubleQuotedWord()
{
string word = "";
if (GetStringValue()!="\"")
ReadToken("\"");
NextToken(false);
while (GetStringValue() != "\"")
{
word = word + GetStringValue();
NextToken(false);
}
return word;
}
/// <summary>
/// Reads the authority and authority code.
/// </summary>
/// <param name="authority">String to place the authority in.</param>
/// <param name="authorityCode">String to place the authority code in.</param>
public void ReadAuthority(out string authority, out long authorityCode)
{
//AUTHORITY["EPGS","9102"]]
if (GetStringValue() != "AUTHORITY")
ReadToken("AUTHORITY");
ReadToken("[");
authority = ReadDoubleQuotedWord();
ReadToken(",");
NextToken();
if (GetTokenType() == TokenType.Number)
authorityCode = (long) GetNumericValue();
else
long.TryParse(ReadDoubleQuotedWord(), NumberStyles.Any, _nfi, out authorityCode);
ReadToken("]");
}
}
}
// Copyright 2005 - 2009 - Morten Nielsen (www.sharpgis.net)
//
// This file is part of ProjNet.
// ProjNet is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// ProjNet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with ProjNet; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
/*
* Copyright (C) 2002 Urban Science Applications, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
using System;
using System.Globalization;
using System.IO;
namespace ProjNet.IO.CoordinateSystems
{
/// <summary>
/// Reads a stream of Well Known Text (wkt) string and returns a stream of tokens.
/// </summary>
internal class WktStreamTokenizer : StreamTokenizer
{
private readonly NumberFormatInfo _nfi = CultureInfo.InvariantCulture.NumberFormat;
/// <summary>
/// Initializes a new instance of the WktStreamTokenizer class.
/// </summary>
/// <remarks>The WktStreamTokenizer class ais in reading WKT streams.</remarks>
/// <param name="reader">A TextReader that contains </param>
public WktStreamTokenizer(TextReader reader) : base(reader, true) { }
/// <summary>
/// Reads a token and checks it is what is expected.
/// </summary>
/// <param name="expectedToken">The expected token.</param>
internal void ReadToken(string expectedToken)
{
NextToken();
if (GetStringValue() != expectedToken)
{
string s = string.Format(_nfi, "Expecting ('{3}') but got a '{0}' at line {1} column {2}.", GetStringValue(), LineNumber, Column, expectedToken);
throw new ArgumentException(s);
}
}
/// <summary>
/// Reads a string inside double quotes.
/// </summary>
/// <remarks>
/// White space inside quotes is preserved.
/// </remarks>
/// <returns>The string inside the double quotes.</returns>
public string ReadDoubleQuotedWord()
{
string word = "";
if (GetStringValue()!="\"")
ReadToken("\"");
NextToken(false);
while (GetStringValue() != "\"")
{
word = word + GetStringValue();
NextToken(false);
}
return word;
}
/// <summary>
/// Reads the authority and authority code.
/// </summary>
/// <param name="authority">String to place the authority in.</param>
/// <param name="authorityCode">String to place the authority code in.</param>
public void ReadAuthority(out string authority, out long authorityCode)
{
//AUTHORITY["EPGS","9102"]]
if (GetStringValue() != "AUTHORITY")
ReadToken("AUTHORITY");
ReadToken("[");
authority = ReadDoubleQuotedWord();
ReadToken(",");
NextToken();
if (GetTokenType() == TokenType.Number)
authorityCode = (long) GetNumericValue();
else
long.TryParse(ReadDoubleQuotedWord(), NumberStyles.Any, _nfi, out authorityCode);
ReadToken("]");
}
}
}

Просмотреть файл

@ -1,38 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<SolutionDir Condition=" '$(SolutionDir)' == '' ">$(ProjectDir)..\</SolutionDir>
<RootNamespace>ProjNet</RootNamespace>
<TargetFramework>netstandard2.0</TargetFramework>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<Import Project="$(SolutionDir)ProjNet.Common.props" />
<PropertyGroup Label="Assembly Info">
<AssemblyTitle>Proj.NET</AssemblyTitle>
<Description>Proj.NET performs point-to-point coordinate conversions between geodetic coordinate systems for use in .Net, Geographic Information Systems (GIS) or GPS applications. The spatial reference model used adheres to the Simple Features specification.</Description>
</PropertyGroup>
<PropertyGroup Label="NuGet Package Info">
<PackageId>ProjNET</PackageId>
<Authors>Morton Nielsen, NetTopologySuite-Team</Authors>
<PackageIconUrl>https://raw.githubusercontent.com/NetTopologySuite/ProjNet4GeoAPI/master/icon.png</PackageIconUrl>
<PackageLicenseExpression>LGPL-2.1-or-later</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageDescription>.NET Spatial Reference and Projection Engine.
Proj.NET performs point-to-point coordinate conversions between geodetic coordinate systems for use in fx. Geographic Information Systems (GIS) or GPS applications. The spatial reference model used adheres to the Simple Features specification.
</PackageDescription>
<PackageTags>OGC;SFS;Projection</PackageTags>
</PropertyGroup>
<ItemGroup>
<None Include="$(SolutionDir)scskey.snk" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Memory" Version="4.5.2" />
</ItemGroup>
</Project>
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<SolutionDir Condition=" '$(SolutionDir)' == '' ">$(ProjectDir)..\</SolutionDir>
<RootNamespace>ProjNet</RootNamespace>
<TargetFramework>netstandard2.0</TargetFramework>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<Import Project="$(SolutionDir)ProjNet.Common.props" />
<PropertyGroup Label="Assembly Info">
<AssemblyTitle>Proj.NET</AssemblyTitle>
<Description>Proj.NET performs point-to-point coordinate conversions between geodetic coordinate systems for use in .Net, Geographic Information Systems (GIS) or GPS applications. The spatial reference model used adheres to the Simple Features specification.</Description>
</PropertyGroup>
<PropertyGroup Label="NuGet Package Info">
<PackageId>ProjNET</PackageId>
<Authors>Morton Nielsen, NetTopologySuite-Team</Authors>
<PackageIconUrl>https://raw.githubusercontent.com/NetTopologySuite/ProjNet4GeoAPI/master/icon.png</PackageIconUrl>
<PackageLicenseExpression>LGPL-2.1-or-later</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageDescription>.NET Spatial Reference and Projection Engine.
Proj.NET performs point-to-point coordinate conversions between geodetic coordinate systems for use in fx. Geographic Information Systems (GIS) or GPS applications. The spatial reference model used adheres to the Simple Features specification.
</PackageDescription>
<PackageTags>OGC;SFS;Projection</PackageTags>
</PropertyGroup>
<ItemGroup>
<None Include="$(SolutionDir)scskey.snk" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Memory" Version="4.5.2" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,44 +1,44 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29020.237
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjNET", "ProjNet\ProjNET.csproj", "{E028BDD2-55E1-4E5F-BE31-35FAEC8D6428}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AC62B826-FD1B-43B9-9E20-696588E560E7}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
icon.png = icon.png
ProjNet.Common.props = ProjNet.Common.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjNET.Tests", "ProjNet.Tests\ProjNET.Tests.csproj", "{67E8C952-1F48-4DFB-9507-BD44DB6784FD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjNet.Benchmark", "ProjNet.Benchmark\ProjNet.Benchmark.csproj", "{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E028BDD2-55E1-4E5F-BE31-35FAEC8D6428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E028BDD2-55E1-4E5F-BE31-35FAEC8D6428}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E028BDD2-55E1-4E5F-BE31-35FAEC8D6428}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E028BDD2-55E1-4E5F-BE31-35FAEC8D6428}.Release|Any CPU.Build.0 = Release|Any CPU
{67E8C952-1F48-4DFB-9507-BD44DB6784FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{67E8C952-1F48-4DFB-9507-BD44DB6784FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{67E8C952-1F48-4DFB-9507-BD44DB6784FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{67E8C952-1F48-4DFB-9507-BD44DB6784FD}.Release|Any CPU.Build.0 = Release|Any CPU
{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8E72A6F0-7BCE-400D-A437-BE88560B578E}
EndGlobalSection
EndGlobal

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29020.237
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjNET", "ProjNet\ProjNET.csproj", "{E028BDD2-55E1-4E5F-BE31-35FAEC8D6428}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AC62B826-FD1B-43B9-9E20-696588E560E7}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
icon.png = icon.png
ProjNet.Common.props = ProjNet.Common.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjNET.Tests", "ProjNet.Tests\ProjNET.Tests.csproj", "{67E8C952-1F48-4DFB-9507-BD44DB6784FD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjNet.Benchmark", "ProjNet.Benchmark\ProjNet.Benchmark.csproj", "{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E028BDD2-55E1-4E5F-BE31-35FAEC8D6428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E028BDD2-55E1-4E5F-BE31-35FAEC8D6428}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E028BDD2-55E1-4E5F-BE31-35FAEC8D6428}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E028BDD2-55E1-4E5F-BE31-35FAEC8D6428}.Release|Any CPU.Build.0 = Release|Any CPU
{67E8C952-1F48-4DFB-9507-BD44DB6784FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{67E8C952-1F48-4DFB-9507-BD44DB6784FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{67E8C952-1F48-4DFB-9507-BD44DB6784FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{67E8C952-1F48-4DFB-9507-BD44DB6784FD}.Release|Any CPU.Build.0 = Release|Any CPU
{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E5D1CC5-8CFE-4C9D-9553-900469C57D6C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8E72A6F0-7BCE-400D-A437-BE88560B578E}
EndGlobalSection
EndGlobal