Use ProjNET instead of ProjNet4GeoAPI

This commit is contained in:
ClemensFischer 2026-01-15 11:04:11 +01:00
parent 5334bb4ea6
commit 4420b3dd03
15 changed files with 135 additions and 71 deletions

View file

@ -7,7 +7,7 @@
<GeneratePackageOnBuild>$(GeneratePackage)</GeneratePackageOnBuild>
<PackageId>XAML.MapControl.MapProjections.Avalonia</PackageId>
<Title>$(AssemblyTitle)</Title>
<Description>Map projections library for XAML Map Control, based on ProjNET4GeoAPI</Description>
<Description>Map projections library for XAML Map Control, based on ProjNET</Description>
</PropertyGroup>
<ItemGroup>
@ -20,6 +20,6 @@
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.3.10" />
<PackageReference Include="ProjNET4GeoAPI" Version="1.4.1" />
<PackageReference Include="ProjNET" Version="2.1.0" />
</ItemGroup>
</Project>

View file

@ -5,7 +5,7 @@ namespace MapControl.Projections
/// <summary>
/// ED50 Universal Transverse Mercator Projection.
/// </summary>
public class Ed50UtmProjection : GeoApiProjection
public class Ed50UtmProjection : ProjNetMapProjection
{
public const int FirstZone = 28;
public const int LastZone = 38;
@ -27,18 +27,18 @@ namespace MapControl.Projections
+ "GEOGCS[\"ED50\","
+ "DATUM[\"European_Datum_1950\","
+ "SPHEROID[\"International 1924\",6378388,297],TOWGS84[-87,-98,-121,0,0,0,0]],"
+ GeoApiProjectionFactory.PrimeMeridianGreenwich + ","
+ GeoApiProjectionFactory.UnitDegree + ","
+ ProjNetMapProjectionFactory.PrimeMeridianGreenwich + ","
+ ProjNetMapProjectionFactory.UnitDegree + ","
+ "AUTHORITY[\"EPSG\",\"4230\"]],"
+ GeoApiProjectionFactory.ProjectionTransverseMercator + ","
+ ProjNetMapProjectionFactory.ProjectionTransverseMercator + ","
+ "PARAMETER[\"latitude_of_origin\",0],"
+ $"PARAMETER[\"central_meridian\",{6 * zone - 183}],"
+ "PARAMETER[\"scale_factor\",0.9996],"
+ "PARAMETER[\"false_easting\",500000],"
+ "PARAMETER[\"false_northing\",0],"
+ GeoApiProjectionFactory.UnitMeter + ","
+ GeoApiProjectionFactory.AxisEasting + ","
+ GeoApiProjectionFactory.AxisNorthing + ","
+ ProjNetMapProjectionFactory.UnitMeter + ","
+ ProjNetMapProjectionFactory.AxisEasting + ","
+ ProjNetMapProjectionFactory.AxisNorthing + ","
+ $"AUTHORITY[\"EPSG\",\"230{zone:00}\"]]";
}
}

View file

@ -5,7 +5,7 @@ namespace MapControl.Projections
/// <summary>
/// ETRS89 Universal Transverse Mercator Projection.
/// </summary>
public class Etrs89UtmProjection : GeoApiProjection
public class Etrs89UtmProjection : ProjNetMapProjection
{
public const int FirstZone = 28;
public const int LastZone = 38;
@ -24,16 +24,16 @@ namespace MapControl.Projections
Zone = zone;
CoordinateSystemWkt
= $"PROJCS[\"ETRS89 / UTM zone {zone}N\","
+ GeoApiProjectionFactory.GeoGcsEtrs89 + ","
+ GeoApiProjectionFactory.ProjectionTransverseMercator + ","
+ ProjNetMapProjectionFactory.GeoGcsEtrs89 + ","
+ ProjNetMapProjectionFactory.ProjectionTransverseMercator + ","
+ "PARAMETER[\"latitude_of_origin\",0],"
+ $"PARAMETER[\"central_meridian\",{6 * zone - 183}],"
+ "PARAMETER[\"scale_factor\",0.9996],"
+ "PARAMETER[\"false_easting\",500000],"
+ "PARAMETER[\"false_northing\",0],"
+ GeoApiProjectionFactory.UnitMeter + ","
+ GeoApiProjectionFactory.AxisEasting + ","
+ GeoApiProjectionFactory.AxisNorthing + ","
+ ProjNetMapProjectionFactory.UnitMeter + ","
+ ProjNetMapProjectionFactory.AxisEasting + ","
+ ProjNetMapProjectionFactory.AxisNorthing + ","
+ $"AUTHORITY[\"EPSG\",\"258{zone:00}\"]]";
}
}

View file

@ -5,7 +5,7 @@ namespace MapControl.Projections
/// <summary>
/// NAD27 Universal Transverse Mercator Projection.
/// </summary>
public class Nad27UtmProjection : GeoApiProjection
public class Nad27UtmProjection : ProjNetMapProjection
{
public const int FirstZone = 1;
public const int LastZone = 22;
@ -27,18 +27,18 @@ namespace MapControl.Projections
+ "GEOGCS[\"NAD27\","
+ "DATUM[\"North_American_Datum_1927\","
+ "SPHEROID[\"Clarke 1866\",6378206.4,294.978698213898]],"
+ GeoApiProjectionFactory.PrimeMeridianGreenwich + ","
+ GeoApiProjectionFactory.UnitDegree + ","
+ ProjNetMapProjectionFactory.PrimeMeridianGreenwich + ","
+ ProjNetMapProjectionFactory.UnitDegree + ","
+ "AUTHORITY[\"EPSG\",\"4267\"]],"
+ GeoApiProjectionFactory.ProjectionTransverseMercator + ","
+ ProjNetMapProjectionFactory.ProjectionTransverseMercator + ","
+ "PARAMETER[\"latitude_of_origin\",0],"
+ $"PARAMETER[\"central_meridian\",{6 * zone - 183}],"
+ "PARAMETER[\"scale_factor\",0.9996],"
+ "PARAMETER[\"false_easting\",500000],"
+ "PARAMETER[\"false_northing\",0],"
+ GeoApiProjectionFactory.UnitMeter + ","
+ GeoApiProjectionFactory.AxisEasting + ","
+ GeoApiProjectionFactory.AxisNorthing + ","
+ ProjNetMapProjectionFactory.UnitMeter + ","
+ ProjNetMapProjectionFactory.AxisEasting + ","
+ ProjNetMapProjectionFactory.AxisNorthing + ","
+ $"AUTHORITY[\"EPSG\",\"267{zone:00}\"]]";
}
}

View file

@ -5,7 +5,7 @@ namespace MapControl.Projections
/// <summary>
/// NAD83 Universal Transverse Mercator Projection.
/// </summary>
public class Nad83UtmProjection : GeoApiProjection
public class Nad83UtmProjection : ProjNetMapProjection
{
public const int FirstZone = 1;
public const int LastZone = 23;
@ -27,18 +27,18 @@ namespace MapControl.Projections
+ "GEOGCS[\"NAD83\","
+ "DATUM[\"North_American_Datum_1983\","
+ "SPHEROID[\"GRS 1980\",6378137,298.257222101]],"
+ GeoApiProjectionFactory.PrimeMeridianGreenwich + ","
+ GeoApiProjectionFactory.UnitDegree + ","
+ ProjNetMapProjectionFactory.PrimeMeridianGreenwich + ","
+ ProjNetMapProjectionFactory.UnitDegree + ","
+ "AUTHORITY[\"EPSG\",\"4269\"]],"
+ GeoApiProjectionFactory.ProjectionTransverseMercator + ","
+ ProjNetMapProjectionFactory.ProjectionTransverseMercator + ","
+ "PARAMETER[\"latitude_of_origin\",0],"
+ $"PARAMETER[\"central_meridian\",{6 * zone - 183}],"
+ "PARAMETER[\"scale_factor\",0.9996],"
+ "PARAMETER[\"false_easting\",500000],"
+ "PARAMETER[\"false_northing\",0],"
+ GeoApiProjectionFactory.UnitMeter + ","
+ GeoApiProjectionFactory.AxisEasting + ","
+ GeoApiProjectionFactory.AxisNorthing + ","
+ ProjNetMapProjectionFactory.UnitMeter + ","
+ ProjNetMapProjectionFactory.AxisEasting + ","
+ ProjNetMapProjectionFactory.AxisNorthing + ","
+ $"AUTHORITY[\"EPSG\",\"269{zone:00}\"]]";
}
}

View file

@ -1,7 +1,4 @@
using GeoAPI.CoordinateSystems;
using GeoAPI.CoordinateSystems.Transformations;
using GeoAPI.Geometries;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
using System;
#if WPF
@ -13,15 +10,15 @@ using Avalonia;
namespace MapControl.Projections
{
/// <summary>
/// MapProjection based on ProjNET4GeoApi.
/// MapProjection based on ProjNet.
/// </summary>
public class GeoApiProjection : MapProjection
public class ProjNetMapProjection : MapProjection
{
protected GeoApiProjection()
protected ProjNetMapProjection()
{
}
public GeoApiProjection(string coordinateSystemWkt)
public ProjNetMapProjection(string coordinateSystemWkt)
{
CoordinateSystemWkt = coordinateSystemWkt;
}
@ -34,13 +31,13 @@ namespace MapControl.Projections
public string CoordinateSystemWkt
{
get => CoordinateSystem?.WKT;
protected set => CoordinateSystem = new CoordinateSystemFactory().CreateFromWkt(value) as IProjectedCoordinateSystem;
protected set => CoordinateSystem = new CoordinateSystemFactory().CreateFromWkt(value) as ProjectedCoordinateSystem;
}
/// <summary>
/// Gets or sets the ICoordinateSystem of the MapProjection.
/// </summary>
public IProjectedCoordinateSystem CoordinateSystem
public ProjectedCoordinateSystem CoordinateSystem
{
get;
protected set
@ -90,9 +87,9 @@ namespace MapControl.Projections
}
}
public IMathTransform LocationToMapTransform { get; private set; }
public MathTransform LocationToMapTransform { get; private set; }
public IMathTransform MapToLocationTransform { get; private set; }
public MathTransform MapToLocationTransform { get; private set; }
public override Point RelativeScale(double latitude, double longitude)
{
@ -110,8 +107,8 @@ namespace MapControl.Projections
try
{
var coordinate = LocationToMapTransform.Transform(new Coordinate(longitude, latitude));
return new Point(coordinate.X, coordinate.Y);
var coordinate = LocationToMapTransform.Transform([longitude, latitude]);
return new Point(coordinate[0], coordinate[1]);
}
catch
{
@ -128,8 +125,8 @@ namespace MapControl.Projections
try
{
var coordinate = MapToLocationTransform.Transform(new Coordinate(x, y));
return new Location(coordinate.Y, coordinate.X);
var coordinate = MapToLocationTransform.Transform([x, y]);
return new Location(coordinate[1], coordinate[0]);
}
catch
{

View file

@ -2,8 +2,9 @@
namespace MapControl.Projections
{
public class GeoApiProjectionFactory : MapProjectionFactory
public class ProjNetMapProjectionFactory : MapProjectionFactory
{
internal const string SpheroidWgs84 = "SPHEROID[\"WGS 84\",6378137,298.257223563]";
internal const string SpheroidGrs1980 = "SPHEROID[\"GRS 1980\",6378137,298.257222101]";
internal const string SpheroidGrs1967Modified = "SPHEROID[\"GRS 1967 Modified\",6378160,298.25]";
internal const string PrimeMeridianGreenwich = "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]]";
@ -14,6 +15,14 @@ namespace MapControl.Projections
internal const string AxisEasting = "AXIS[\"Easting\",EAST]";
internal const string AxisNorthing = "AXIS[\"Northing\",NORTH]";
internal const string GeoGcsWgs84
= "GEOGCS[\"WGS 84\","
+ "DATUM[\"WGS_1984\","
+ SpheroidWgs84 + "],"
+ PrimeMeridianGreenwich + ","
+ UnitDegree + ","
+ "AUTHORITY[\"EPSG\",\"4326\"]]";
internal const string GeoGcsEtrs89
= "GEOGCS[\"ETRS89\","
+ "DATUM[\"European_Terrestrial_Reference_System_1989\","
@ -241,7 +250,9 @@ namespace MapControl.Projections
{
MapControl.WebMercatorProjection.DefaultCrsId => new WebMercatorProjection(),
MapControl.WorldMercatorProjection.DefaultCrsId => new WorldMercatorProjection(),
Wgs84AutoUtmProjection.DefaultCrsId => new Wgs84AutoUtmProjection(),
MapControl.Wgs84UpsNorthProjection.DefaultCrsId => new Wgs84UpsNorthProjection(),
MapControl.Wgs84UpsSouthProjection.DefaultCrsId => new Wgs84UpsSouthProjection(),
MapControl.Wgs84AutoUtmProjection.DefaultCrsId => new Wgs84AutoUtmProjection(),
_ => base.GetProjection(crsId)
};
@ -253,7 +264,7 @@ namespace MapControl.Projections
var code when code >= Nad83UtmProjection.FirstZoneEpsgCode && code <= Nad83UtmProjection.LastZoneEpsgCode => new Nad83UtmProjection(epsgCode % 100),
var code when code >= Wgs84UtmProjection.FirstZoneNorthEpsgCode && code <= Wgs84UtmProjection.LastZoneNorthEpsgCode => new Wgs84UtmProjection(epsgCode % 100, Hemisphere.North),
var code when code >= Wgs84UtmProjection.FirstZoneSouthEpsgCode && code <= Wgs84UtmProjection.LastZoneSouthEpsgCode => new Wgs84UtmProjection(epsgCode % 100, Hemisphere.South),
_ => CoordinateSystemWkts.TryGetValue(epsgCode, out string wkt) ? new GeoApiProjection(wkt) : base.GetProjection(epsgCode)
_ => CoordinateSystemWkts.TryGetValue(epsgCode, out string wkt) ? new ProjNetMapProjection(wkt) : base.GetProjection(epsgCode)
};
}
}

View file

@ -9,10 +9,10 @@ using Avalonia;
namespace MapControl.Projections
{
/// <summary>
/// Spherical Mercator Projection implemented by setting the CoordinateSystem property of a GeoApiProjection.
/// Spherical Mercator Projection implemented by setting the CoordinateSystem property of a ProjNetMapProjection.
/// See "Map Projections - A Working Manual" (https://pubs.usgs.gov/pp/1395/report.pdf), p.41-44.
/// </summary>
public class WebMercatorProjection : GeoApiProjection
public class WebMercatorProjection : ProjNetMapProjection
{
public WebMercatorProjection()
{

View file

@ -9,12 +9,10 @@ namespace MapControl.Projections
/// </summary>
public class Wgs84AutoUtmProjection : Wgs84UtmProjection
{
public const string DefaultCrsId = "AUTO2:42001";
private readonly string autoCrsId;
public Wgs84AutoUtmProjection() // parameterless constructor for XAML
: this(DefaultCrsId)
: this(MapControl.Wgs84AutoUtmProjection.DefaultCrsId)
{
}

View file

@ -0,0 +1,62 @@
#if WPF
using System.Windows;
#elif AVALONIA
using Avalonia;
#endif
namespace MapControl.Projections
{
public class Wgs84UpsNorthProjection : ProjNetMapProjection
{
public Wgs84UpsNorthProjection()
{
CoordinateSystemWkt
= "PROJCS[\"WGS 84 / UPS North (N,E)\","
+ ProjNetMapProjectionFactory.GeoGcsWgs84 + ","
+ "PROJECTION[\"Polar_Stereographic\"],"
+ "PARAMETER[\"latitude_of_origin\",90],"
+ "PARAMETER[\"central_meridian\",0],"
+ "PARAMETER[\"scale_factor\",0.994],"
+ "PARAMETER[\"false_easting\",2000000],"
+ "PARAMETER[\"false_northing\",2000000],"
+ ProjNetMapProjectionFactory.UnitMeter + ","
+ "AUTHORITY[\"EPSG\",\"32661\"]]";
Type = MapProjectionType.Azimuthal;
}
public override Point RelativeScale(double latitude, double longitude)
{
var k = PolarStereographicProjection.RelativeScale(Hemisphere.North, Wgs84EquatorialRadius, Wgs84Flattening, 0.994, latitude);
return new Point(k, k);
}
}
public class Wgs84UpsSouthProjection : ProjNetMapProjection
{
public Wgs84UpsSouthProjection()
{
CoordinateSystemWkt
= "PROJCS[\"WGS 84 / UPS South (N,E)\","
+ ProjNetMapProjectionFactory.GeoGcsWgs84 + ","
+ "PROJECTION[\"Polar_Stereographic\"],"
+ "PARAMETER[\"latitude_of_origin\",-90],"
+ "PARAMETER[\"central_meridian\",0],"
+ "PARAMETER[\"scale_factor\",0.994],"
+ "PARAMETER[\"false_easting\",2000000],"
+ "PARAMETER[\"false_northing\",2000000],"
+ ProjNetMapProjectionFactory.UnitMeter + ","
+ "AUTHORITY[\"EPSG\",\"32761\"]]";
Type = MapProjectionType.Azimuthal;
}
public override Point RelativeScale(double latitude, double longitude)
{
var k = PolarStereographicProjection.RelativeScale(Hemisphere.South, Wgs84EquatorialRadius, Wgs84Flattening, 0.994, latitude);
return new Point(k, k);
}
}
}

View file

@ -6,7 +6,7 @@ namespace MapControl.Projections
/// <summary>
/// WGS84 Universal Transverse Mercator Projection.
/// </summary>
public class Wgs84UtmProjection : GeoApiProjection
public class Wgs84UtmProjection : ProjNetMapProjection
{
public const int FirstZone = 1;
public const int LastZone = 60;

View file

@ -7,35 +7,31 @@ using Avalonia;
namespace MapControl.Projections
{
/// <summary>
/// Elliptical Mercator Projection implemented by setting the WKT property of a GeoApiProjection.
/// Elliptical Mercator Projection implemented by setting the WKT property of a ProjNetMapProjection.
/// See "Map Projections - A Working Manual" (https://pubs.usgs.gov/pp/1395/report.pdf), p.44-45.
/// </summary>
public class WorldMercatorProjection : GeoApiProjection
public class WorldMercatorProjection : ProjNetMapProjection
{
public WorldMercatorProjection()
{
CoordinateSystemWkt
= "PROJCS[\"WGS 84 / World Mercator\","
+ "GEOGCS[\"WGS 84\","
+ "DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],"
+ GeoApiProjectionFactory.PrimeMeridianGreenwich + ","
+ GeoApiProjectionFactory.UnitDegree + ","
+ "AUTHORITY[\"EPSG\",\"4326\"]],"
+ ProjNetMapProjectionFactory.GeoGcsWgs84 + ","
+ "PROJECTION[\"Mercator_1SP\"],"
+ "PARAMETER[\"latitude_of_origin\",0],"
+ "PARAMETER[\"central_meridian\",0],"
+ "PARAMETER[\"scale_factor\",1],"
+ "PARAMETER[\"false_easting\",0],"
+ "PARAMETER[\"false_northing\",0],"
+ GeoApiProjectionFactory.UnitMeter + ","
+ GeoApiProjectionFactory.AxisEasting + ","
+ GeoApiProjectionFactory.AxisNorthing + ","
+ ProjNetMapProjectionFactory.UnitMeter + ","
+ ProjNetMapProjectionFactory.AxisEasting + ","
+ ProjNetMapProjectionFactory.AxisNorthing + ","
+ "AUTHORITY[\"EPSG\",\"3395\"]]";
}
public override Point RelativeScale(double latitude, double longitude)
{
var k = MapControl.WorldMercatorProjection.ScaleFactor(latitude);
var k = MapControl.WorldMercatorProjection.RelativeScale(latitude);
return new Point(k, k);
}

View file

@ -9,7 +9,7 @@
<GeneratePackageOnBuild>$(GeneratePackage)</GeneratePackageOnBuild>
<PackageId>XAML.MapControl.MapProjections.UWP</PackageId>
<Title>$(AssemblyTitle)</Title>
<Description>Map projections library for XAML Map Control, based on ProjNET4GeoAPI</Description>
<Description>Map projections library for XAML Map Control, based on ProjNET</Description>
<DisableRuntimeMarshalling>true</DisableRuntimeMarshalling>
<DefaultLanguage>en-US</DefaultLanguage>
</PropertyGroup>
@ -23,6 +23,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="ProjNET4GeoAPI" Version="1.4.1" />
<PackageReference Include="ProjNET" Version="2.1.0" />
</ItemGroup>
</Project>

View file

@ -9,7 +9,7 @@
<GeneratePackageOnBuild>$(GeneratePackage)</GeneratePackageOnBuild>
<PackageId>XAML.MapControl.MapProjections.WPF</PackageId>
<Title>$(AssemblyTitle)</Title>
<Description>Map projections library for XAML Map Control, based on ProjNET4GeoAPI</Description>
<Description>Map projections library for XAML Map Control, based on ProjNET</Description>
</PropertyGroup>
<ItemGroup>
@ -25,6 +25,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="ProjNET4GeoAPI" Version="1.4.1" />
<PackageReference Include="ProjNET" Version="2.1.0" />
</ItemGroup>
</Project>

View file

@ -8,7 +8,7 @@
<GeneratePackageOnBuild>$(GeneratePackage)</GeneratePackageOnBuild>
<PackageId>XAML.MapControl.MapProjections.WinUI</PackageId>
<Title>$(AssemblyTitle)</Title>
<Description>Map projections library for XAML Map Control, based on ProjNET4GeoAPI</Description>
<Description>Map projections library for XAML Map Control, based on ProjNET</Description>
</PropertyGroup>
<ItemGroup>
@ -21,6 +21,6 @@
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.8.251106002" />
<PackageReference Include="ProjNET4GeoAPI" Version="1.4.1" />
<PackageReference Include="ProjNET" Version="2.1.0" />
</ItemGroup>
</Project>