Added GeoApiProjectionFactory

This commit is contained in:
Clemens 2022-01-19 23:40:05 +01:00
parent d7c45effc6
commit 5b9e5529f6
6 changed files with 106 additions and 4 deletions

View file

@ -106,6 +106,15 @@ namespace MapControl.Projections
get { return isWebMercator; }
}
public GeoApiProjection(string wkt = null)
{
if (wkt != null)
{
WKT = wkt;
}
}
public override Point LocationToMap(Location location)
{
if (LocationToMapTransform == null)

View file

@ -0,0 +1,70 @@
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
// © 2022 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
namespace MapControl.Projections
{
public class GeoApiProjectionFactory : MapProjectionFactory
{
private readonly Dictionary<int, string> wkts = new Dictionary<int, string>();
private readonly HttpClient httpClient = new HttpClient();
public override MapProjection CreateProjection(string projectionDefinition)
{
var projection = base.CreateProjection(projectionDefinition);
if (projection == null &&
projectionDefinition.StartsWith("EPSG:") &&
int.TryParse(projectionDefinition.Substring(5), out int epsgCode))
{
if (epsgCode >= 32601 && epsgCode <= 32660)
{
projection = new UtmProjection(epsgCode - 32600, true);
}
else if (epsgCode == 32661)
{
projection = new UpsNorthProjection();
}
else if (epsgCode >= 32701 && epsgCode <= 32760)
{
projection = new UtmProjection(epsgCode - 32700, false);
}
else if (epsgCode == 32761)
{
projection = new UpsSouthProjection();
}
else
{
projection = new GeoApiProjection(GetWkt(epsgCode));
}
}
return projection;
}
private string GetWkt(int epsgCode)
{
if (!wkts.TryGetValue(epsgCode, out string wkt))
{
var url = string.Format("https://epsg.io/{0}.wkt", epsgCode);
try
{
wkt = httpClient.GetStringAsync(url).Result; // potential deadlock?
wkts[epsgCode] = wkt;
}
catch (Exception ex)
{
Debug.WriteLine($"GeoApiProjectionFactory.GetWkt({epsgCode}): {url}: {ex.Message}");
}
}
return wkt;
}
}
}

View file

@ -114,14 +114,16 @@ namespace MapControl.Projections
public class UpsNorthProjection : PolarStereographicProjection
{
public UpsNorthProjection() : base("EPSG:32661", true, 0.994, 2e6, 2e6)
public UpsNorthProjection()
: base("EPSG:32661", true, 0.994, 2e6, 2e6)
{
}
}
public class UpsSouthProjection : PolarStereographicProjection
{
public UpsSouthProjection() : base("EPSG:32761", false, 0.994, 2e6, 2e6)
public UpsSouthProjection()
: base("EPSG:32761", false, 0.994, 2e6, 2e6)
{
}
}

View file

@ -36,9 +36,23 @@ namespace MapControl.Projections
}
}
public UtmProjection()
{
}
public UtmProjection(int zoneNumber, bool north)
{
SetZone(zoneNumber, north);
}
public UtmProjection(Location location)
{
SetZone(location);
}
public void SetZone(int zoneNumber, bool north)
{
if (zoneNumber < 1 || zoneNumber > 61)
if (zoneNumber < 1 || zoneNumber > 60)
{
throw new ArgumentException("Invalid UTM zone number.", nameof(zoneNumber));
}
@ -56,7 +70,7 @@ namespace MapControl.Projections
{
var zoneNumber = Math.Min((int)(Location.NormalizeLongitude(location.Longitude) + 180d) / 6 + 1, 60);
SetZone(zoneNumber, location.Latitude >= 0);
SetZone(zoneNumber, location.Latitude >= 0d);
}
}
}

View file

@ -43,6 +43,9 @@
<Compile Include="..\Shared\GeoApiProjection.cs">
<Link>GeoApiProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\GeoApiProjectionFactory.cs">
<Link>GeoApiProjectionFactory.cs</Link>
</Compile>
<Compile Include="..\Shared\PolarStereographicProjection.cs">
<Link>PolarStereographicProjection.cs</Link>
</Compile>

View file

@ -24,6 +24,10 @@
<Compile Include="..\Shared\*.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net48' or '$(TargetFramework)'=='net462'">
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="ProjNET4GeoAPI" Version="1.4.1" />
</ItemGroup>