diff --git a/MapControl/Shared/MapProjectionFactory.cs b/MapControl/Shared/MapProjectionFactory.cs index 260fbeb4..051dae79 100644 --- a/MapControl/Shared/MapProjectionFactory.cs +++ b/MapControl/Shared/MapProjectionFactory.cs @@ -32,6 +32,10 @@ namespace MapControl projection = new UpsSouthProjection(); break; + case "AUTO-UTM": + projection = new Wgs84AutoUtmProjection(null); // client-side auto zone + break; + case Wgs84AutoUtmProjection.DefaultCrsId: projection = new Wgs84AutoUtmProjection(); break; @@ -76,8 +80,8 @@ namespace MapControl var code when code >= Etrs89UtmProjection.FirstZoneEpsgCode && code <= Etrs89UtmProjection.LastZoneEpsgCode => new Etrs89UtmProjection(epsgCode % 100), var code when code >= Nad27UtmProjection.FirstZoneEpsgCode && code <= Nad27UtmProjection.LastZoneEpsgCode => new Nad27UtmProjection(epsgCode % 100), 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, true), - var code when code >= Wgs84UtmProjection.FirstZoneSouthEpsgCode && code <= Wgs84UtmProjection.LastZoneSouthEpsgCode => new Wgs84UtmProjection(epsgCode % 100, false), + 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), _ => null }; } diff --git a/MapControl/Shared/PolarStereographicProjection.cs b/MapControl/Shared/PolarStereographicProjection.cs index ae8a2c58..9770c4c8 100644 --- a/MapControl/Shared/PolarStereographicProjection.cs +++ b/MapControl/Shared/PolarStereographicProjection.cs @@ -24,13 +24,13 @@ namespace MapControl public double ScaleFactor { get; set; } = 0.994; public double FalseEasting { get; set; } = 2e6; public double FalseNorthing { get; set; } = 2e6; - public bool IsNorth { get; set; } + public Hemisphere Hemisphere { get; set; } public override Point RelativeScale(double latitude, double longitude) { latitude *= Math.PI / 180d; - if (!IsNorth) + if (Hemisphere == Hemisphere.South) { latitude = -latitude; } @@ -54,7 +54,7 @@ namespace MapControl latitude *= Math.PI / 180d; longitude *= Math.PI / 180d; - if (!IsNorth) + if (Hemisphere == Hemisphere.South) { latitude = -latitude; longitude = -longitude; @@ -71,7 +71,7 @@ namespace MapControl var x = r * Math.Sin(longitude); // p.161 (21-30) var y = -r * Math.Cos(longitude); // p.161 (21-31) - if (!IsNorth) + if (Hemisphere == Hemisphere.South) { x = -x; y = -y; @@ -85,7 +85,7 @@ namespace MapControl x -= FalseEasting; y -= FalseNorthing; - if (!IsNorth) + if (Hemisphere == Hemisphere.South) { x = -x; y = -y; @@ -99,7 +99,7 @@ namespace MapControl var lat = WorldMercatorProjection.ApproximateLatitude(e, t); // p.162 (3-5) var lon = Math.Atan2(x, -y); // p.162 (20-16) - if (!IsNorth) + if (Hemisphere == Hemisphere.South) { lat = -lat; lon = -lon; @@ -125,7 +125,7 @@ namespace MapControl public UpsNorthProjection(string crsId) { CrsId = crsId; - IsNorth = true; + Hemisphere = Hemisphere.North; } } @@ -145,7 +145,7 @@ namespace MapControl public UpsSouthProjection(string crsId) { CrsId = crsId; - IsNorth = false; + Hemisphere = Hemisphere.South; } } } diff --git a/MapControl/Shared/Wgs84AutoUtmProjection.cs b/MapControl/Shared/Wgs84AutoUtmProjection.cs index 1fadc803..5402caf7 100644 --- a/MapControl/Shared/Wgs84AutoUtmProjection.cs +++ b/MapControl/Shared/Wgs84AutoUtmProjection.cs @@ -3,8 +3,9 @@ namespace MapControl { /// - /// WGS84 Universal Transverse Mercator Projection with - /// automatic zone selection from projection center. + /// WGS84 Universal Transverse Mercator Projection with automatic zone selection from + /// the projection center. If the CRS Id passed to the constructor is null or empty, + /// appropriate CRS Ids EPSG:32601 to EPSG:32660 and EPSG:32701 to EPSG:32760 are used. /// public class Wgs84AutoUtmProjection : Wgs84UtmProjection { @@ -18,11 +19,8 @@ namespace MapControl // XAML needs parameterless constructor } - /// - /// When the crsId parameter is null or empty, the projection will use EPSG:32***. - /// public Wgs84AutoUtmProjection(string crsId) - : base(31, true) + : base(31, Hemisphere.North) { autoCrsId = crsId; @@ -43,11 +41,11 @@ namespace MapControl var lon = Location.NormalizeLongitude(value.Longitude); var zone = (int)Math.Floor(lon / 6d) + 31; - var north = value.Latitude >= 0d; + var hemisphere = value.Latitude >= 0d ? Hemisphere.North : Hemisphere.South; - if (Zone != zone || IsNorth != north) + if (Zone != zone || Hemisphere != hemisphere) { - SetZone(zone, north); + SetZone(zone, hemisphere); if (!string.IsNullOrEmpty(autoCrsId)) { diff --git a/MapControl/Shared/Wgs84UtmProjection.cs b/MapControl/Shared/Wgs84UtmProjection.cs index 5d909c28..e6156f65 100644 --- a/MapControl/Shared/Wgs84UtmProjection.cs +++ b/MapControl/Shared/Wgs84UtmProjection.cs @@ -2,6 +2,12 @@ namespace MapControl { + public enum Hemisphere + { + North, + South + } + /// /// WGS84 Universal Transverse Mercator Projection. /// @@ -15,11 +21,11 @@ namespace MapControl public const int LastZoneSouthEpsgCode = 32700 + LastZone; public int Zone { get; private set; } - public bool IsNorth { get; private set; } + public Hemisphere Hemisphere { get; private set; } - public Wgs84UtmProjection(int zone, bool north) + public Wgs84UtmProjection(int zone, Hemisphere hemisphere) { - SetZone(zone, north); + SetZone(zone, hemisphere); EquatorialRadius = Wgs84EquatorialRadius; Flattening = Wgs84Flattening; @@ -27,7 +33,7 @@ namespace MapControl FalseEasting = 5e5; } - protected void SetZone(int zone, bool north) + protected void SetZone(int zone, Hemisphere hemisphere) { if (zone < FirstZone || zone > LastZone) { @@ -35,10 +41,10 @@ namespace MapControl } Zone = zone; - IsNorth = north; - CrsId = $"EPSG:{(north ? 32600 : 32700) + zone}"; + Hemisphere = hemisphere; + CrsId = $"EPSG:{(hemisphere == Hemisphere.North ? 32600 : 32700) + zone}"; CentralMeridian = zone * 6d - 183d; - FalseNorthing = north ? 0d : 1e7; + FalseNorthing = hemisphere == Hemisphere.North ? 0d : 1e7; } } } diff --git a/MapProjections/Shared/Wgs84AutoUtmProjection.cs b/MapProjections/Shared/Wgs84AutoUtmProjection.cs index 20c0d72d..26b1ede0 100644 --- a/MapProjections/Shared/Wgs84AutoUtmProjection.cs +++ b/MapProjections/Shared/Wgs84AutoUtmProjection.cs @@ -3,8 +3,9 @@ namespace MapControl.Projections { /// - /// WGS84 Universal Transverse Mercator Projection with - /// automatic zone selection from projection center. + /// WGS84 Universal Transverse Mercator Projection with automatic zone selection from + /// the projection center. If the CRS Id passed to the constructor is null or empty, + /// appropriate CRS Ids EPSG:32601 to EPSG:32660 and EPSG:32701 to EPSG:32760 are used. /// public class Wgs84AutoUtmProjection : Wgs84UtmProjection { @@ -16,11 +17,8 @@ namespace MapControl.Projections // XAML needs parameterless constructor } - /// - /// When the crsId parameter is null or empty, the projection will use EPSG:32***. - /// public Wgs84AutoUtmProjection(string crsId) - : base(31, true) + : base(31, Hemisphere.North) { autoCrsId = crsId; @@ -41,11 +39,11 @@ namespace MapControl.Projections var lon = Location.NormalizeLongitude(value.Longitude); var zone = (int)Math.Floor(lon / 6d) + 31; - var north = value.Latitude >= 0d; + var hemisphere = value.Latitude >= 0d ? Hemisphere.North : Hemisphere.South; - if (Zone != zone || IsNorth != north) + if (Zone != zone || Hemisphere != hemisphere) { - SetZone(zone, north); + SetZone(zone, hemisphere); if (!string.IsNullOrEmpty(autoCrsId)) { diff --git a/MapProjections/Shared/Wgs84UtmProjection.cs b/MapProjections/Shared/Wgs84UtmProjection.cs index c2add366..28c23fcc 100644 --- a/MapProjections/Shared/Wgs84UtmProjection.cs +++ b/MapProjections/Shared/Wgs84UtmProjection.cs @@ -16,14 +16,14 @@ namespace MapControl.Projections public const int LastZoneSouthEpsgCode = 32700 + LastZone; public int Zone { get; private set; } - public bool IsNorth { get; private set; } + public Hemisphere Hemisphere { get; private set; } - public Wgs84UtmProjection(int zone, bool north) + public Wgs84UtmProjection(int zone, Hemisphere hemisphere) { - SetZone(zone, north); + SetZone(zone, hemisphere); } - protected void SetZone(int zone, bool north) + protected void SetZone(int zone, Hemisphere hemisphere) { if (zone < FirstZone || zone > LastZone) { @@ -31,8 +31,8 @@ namespace MapControl.Projections } Zone = zone; - IsNorth = north; - CoordinateSystem = ProjectedCoordinateSystem.WGS84_UTM(Zone, IsNorth); + Hemisphere = hemisphere; + CoordinateSystem = ProjectedCoordinateSystem.WGS84_UTM(Zone, hemisphere == Hemisphere.North); } } }