diff --git a/MapControl/Shared/Etrs89UtmProjection.cs b/MapControl/Shared/Etrs89UtmProjection.cs
deleted file mode 100644
index 17490e15..00000000
--- a/MapControl/Shared/Etrs89UtmProjection.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System;
-
-namespace MapControl
-{
- ///
- /// ETRS89 Universal Transverse Mercator Projection - EPSG:25828 to EPSG:25838.
- ///
- public class Etrs89UtmProjection : TransverseMercatorProjection
- {
- public const int FirstZone = 28;
- public const int LastZone = 38;
- public const int FirstZoneEpsgCode = 25800 + FirstZone;
- public const int LastZoneEpsgCode = 25800 + LastZone;
-
- public int Zone { get; }
-
- public Etrs89UtmProjection(int zone) : base(zone)
- {
- if (zone < FirstZone || zone > LastZone)
- {
- throw new ArgumentException($"Invalid ETRS89 UTM zone {zone}.", nameof(zone));
- }
-
- Zone = zone;
- CrsId = $"EPSG:{25800 + zone}";
-
- // GRS 1980
- EquatorialRadius = 6378137d;
- Flattening = 1d / 298.257222101;
- }
- }
-}
diff --git a/MapControl/Shared/Nad27UtmProjection.cs b/MapControl/Shared/Nad27UtmProjection.cs
deleted file mode 100644
index 2fd35922..00000000
--- a/MapControl/Shared/Nad27UtmProjection.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System;
-
-namespace MapControl
-{
- ///
- /// NAD27 Universal Transverse Mercator Projection - EPSG:26701 to EPSG:26722.
- ///
- public class Nad27UtmProjection : TransverseMercatorProjection
- {
- public const int FirstZone = 1;
- public const int LastZone = 22;
- public const int FirstZoneEpsgCode = 26700 + FirstZone;
- public const int LastZoneEpsgCode = 26700 + LastZone;
-
- public int Zone { get; }
-
- public Nad27UtmProjection(int zone) : base(zone)
- {
- if (zone < FirstZone || zone > LastZone)
- {
- throw new ArgumentException($"Invalid NAD27 UTM zone {zone}.", nameof(zone));
- }
-
- Zone = zone;
- CrsId = $"EPSG:{26700 + zone}";
-
- // Clarke 1866
- EquatorialRadius = 6378206.4;
- Flattening = 1d / 294.978698213898;
- }
- }
-}
diff --git a/MapControl/Shared/Nad83UtmProjection.cs b/MapControl/Shared/Nad83UtmProjection.cs
deleted file mode 100644
index e46566da..00000000
--- a/MapControl/Shared/Nad83UtmProjection.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System;
-
-namespace MapControl
-{
- ///
- /// NAD83 Universal Transverse Mercator Projection - EPSG:26901 to EPSG:26923.
- ///
- public class Nad83UtmProjection : TransverseMercatorProjection
- {
- public const int FirstZone = 1;
- public const int LastZone = 23;
- public const int FirstZoneEpsgCode = 26900 + FirstZone;
- public const int LastZoneEpsgCode = 26900 + LastZone;
-
- public int Zone { get; }
-
- public Nad83UtmProjection(int zone) : base(zone)
- {
- if (zone < FirstZone || zone > LastZone)
- {
- throw new ArgumentException($"Invalid NAD83 UTM zone {zone}.", nameof(zone));
- }
-
- Zone = zone;
- CrsId = $"EPSG:{26900 + zone}";
-
- // GRS 1980
- EquatorialRadius = 6378137d;
- Flattening = 1d / 298.257222101;
- }
- }
-}
diff --git a/MapControl/Shared/TransverseMercatorProjection.cs b/MapControl/Shared/TransverseMercatorProjection.cs
index e0c0430a..b48e681c 100644
--- a/MapControl/Shared/TransverseMercatorProjection.cs
+++ b/MapControl/Shared/TransverseMercatorProjection.cs
@@ -16,24 +16,32 @@ namespace MapControl
///
public class TransverseMercatorProjection : MapProjection
{
- private double f;
- private double n;
- private double a1; // α1
- private double a2; // α2
- private double a3; // α3
- private double b1; // β1
- private double b2; // β2
- private double b3; // β3
- private double d1; // δ1
- private double d2; // δ2
- private double d3; // δ3
- private double f1; // A/a
- private double f2; // 2*sqrt(n)/(1+n)
+ private readonly double n;
+ private readonly double a1; // α1
+ private readonly double a2; // α2
+ private readonly double a3; // α3
+ private readonly double b1; // β1
+ private readonly double b2; // β2
+ private readonly double b3; // β3
+ private readonly double d1; // δ1
+ private readonly double d2; // δ2
+ private readonly double d3; // δ3
+ private readonly double f1; // A/a
+ private readonly double f2; // 2*sqrt(n)/(1+n)
- private void InitializeParameters()
+ public TransverseMercatorProjection(
+ double equatorialRadius, double flattening,
+ double scaleFactor, double centralMeridian,
+ double falseEasting, double falseNorthing = 0d)
{
- f = Flattening;
- n = f / (2d - f);
+ EquatorialRadius = equatorialRadius;
+ Flattening = flattening;
+ ScaleFactor = scaleFactor;
+ CentralMeridian = centralMeridian;
+ FalseEasting = falseEasting;
+ FalseNorthing = falseNorthing;
+
+ n = flattening / (2d - flattening);
var n2 = n * n;
var n3 = n * n2;
a1 = n / 2d - n2 * 2d / 3d + n3 * 5d / 16d;
@@ -49,17 +57,14 @@ namespace MapControl
f2 = 2d * Math.Sqrt(n) / (1d + n);
}
- public TransverseMercatorProjection()
+ public TransverseMercatorProjection(
+ double equatorialRadius, double flattening,
+ double scaleFactor, int utmZone, bool north = true)
+ : this(equatorialRadius, flattening,
+ scaleFactor, utmZone * 6d - 183d, 5e5, north ? 0d : 1e7)
{
}
- public TransverseMercatorProjection(int utmZone) : this()
- {
- CentralMeridian = utmZone * 6d - 183d;
- ScaleFactor = 0.9996;
- FalseEasting = 5e5;
- }
-
public override double GridConvergence(double latitude, double longitude)
{
// φ
@@ -74,11 +79,6 @@ namespace MapControl
public override Matrix RelativeTransform(double latitude, double longitude)
{
- if (f != Flattening)
- {
- InitializeParameters();
- }
-
// φ
var phi = latitude * Math.PI / 180d;
var sinPhi = Math.Sin(phi);
@@ -118,11 +118,6 @@ namespace MapControl
public override Point LocationToMap(double latitude, double longitude)
{
- if (f != Flattening)
- {
- InitializeParameters();
- }
-
// φ
var phi = latitude * Math.PI / 180d;
var sinPhi = Math.Sin(phi);
@@ -152,11 +147,6 @@ namespace MapControl
public override Location MapToLocation(double x, double y)
{
- if (f != Flattening)
- {
- InitializeParameters();
- }
-
// k0 * A
var k0A = ScaleFactor * EquatorialRadius * f1;
// ξ
diff --git a/MapControl/Shared/TransverseMercatorProjectionSnyder.cs b/MapControl/Shared/TransverseMercatorProjectionSnyder.cs
index 12026aeb..cd47232b 100644
--- a/MapControl/Shared/TransverseMercatorProjectionSnyder.cs
+++ b/MapControl/Shared/TransverseMercatorProjectionSnyder.cs
@@ -15,15 +15,24 @@ namespace MapControl
///
public class TransverseMercatorProjectionSnyder : MapProjection
{
- public TransverseMercatorProjectionSnyder()
+ public TransverseMercatorProjectionSnyder(
+ double equatorialRadius, double flattening, double scaleFactor,
+ double centralMeridian, double latitudeOfOrigin,
+ double falseEasting, double falseNorthing = 0d)
{
+ EquatorialRadius = equatorialRadius;
+ Flattening = flattening;
+ ScaleFactor = scaleFactor;
+ CentralMeridian = centralMeridian;
+ LatitudeOfOrigin = latitudeOfOrigin;
+ FalseEasting = falseEasting;
+ FalseNorthing = falseNorthing;
}
- public TransverseMercatorProjectionSnyder(int utmZone) : this()
+ public TransverseMercatorProjectionSnyder(int utmZone, bool north = true)
+ : this(Wgs84EquatorialRadius, Wgs84Flattening,
+ 0.9996, utmZone * 6d - 183d, 0d, 5e5, north ? 0d : 1e7)
{
- CentralMeridian = utmZone * 6d - 183d;
- ScaleFactor = 0.9996;
- FalseEasting = 5e5;
}
public override double GridConvergence(double latitude, double longitude)
diff --git a/MapControl/Shared/UtmProjections.cs b/MapControl/Shared/UtmProjections.cs
new file mode 100644
index 00000000..1496b880
--- /dev/null
+++ b/MapControl/Shared/UtmProjections.cs
@@ -0,0 +1,107 @@
+using System;
+
+namespace MapControl
+{
+ ///
+ /// WGS84 Universal Transverse Mercator Projection -
+ /// EPSG:32601 to EPSG:32660 and EPSG:32701 to EPSG:32760.
+ ///
+ public class Wgs84UtmProjection : TransverseMercatorProjection
+ {
+ public const int FirstZone = 1;
+ public const int LastZone = 60;
+ public const int FirstZoneNorthEpsgCode = 32600 + FirstZone;
+ public const int LastZoneNorthEpsgCode = 32600 + LastZone;
+ public const int FirstZoneSouthEpsgCode = 32700 + FirstZone;
+ public const int LastZoneSouthEpsgCode = 32700 + LastZone;
+
+ public int Zone { get; }
+
+ public Wgs84UtmProjection(int zone, bool north)
+ : base(Wgs84EquatorialRadius, Wgs84Flattening, 0.9996, zone, north)
+ {
+ if (zone < FirstZone || zone > LastZone)
+ {
+ throw new ArgumentException($"Invalid WGS84 UTM zone {zone}.", nameof(zone));
+ }
+
+ Zone = zone;
+ CrsId = $"EPSG:{(north ? 32600 : 32700) + zone}";
+ }
+ }
+
+ ///
+ /// ETRS89 Universal Transverse Mercator Projection - EPSG:25828 to EPSG:25838.
+ ///
+ public class Etrs89UtmProjection : TransverseMercatorProjection
+ {
+ public const int FirstZone = 28;
+ public const int LastZone = 38;
+ public const int FirstZoneEpsgCode = 25800 + FirstZone;
+ public const int LastZoneEpsgCode = 25800 + LastZone;
+
+ public int Zone { get; }
+
+ public Etrs89UtmProjection(int zone)
+ : base(6378137d, 1d / 298.257222101, 0.9996, zone) // GRS 1980
+ {
+ if (zone < FirstZone || zone > LastZone)
+ {
+ throw new ArgumentException($"Invalid ETRS89 UTM zone {zone}.", nameof(zone));
+ }
+
+ Zone = zone;
+ CrsId = $"EPSG:{25800 + zone}";
+ }
+ }
+
+ ///
+ /// NAD83 Universal Transverse Mercator Projection - EPSG:26901 to EPSG:26923.
+ ///
+ public class Nad83UtmProjection : TransverseMercatorProjection
+ {
+ public const int FirstZone = 1;
+ public const int LastZone = 23;
+ public const int FirstZoneEpsgCode = 26900 + FirstZone;
+ public const int LastZoneEpsgCode = 26900 + LastZone;
+
+ public int Zone { get; }
+
+ public Nad83UtmProjection(int zone)
+ : base(6378137d, 1d / 298.257222101, 0.9996, zone) // GRS 1980
+ {
+ if (zone < FirstZone || zone > LastZone)
+ {
+ throw new ArgumentException($"Invalid NAD83 UTM zone {zone}.", nameof(zone));
+ }
+
+ Zone = zone;
+ CrsId = $"EPSG:{26900 + zone}";
+ }
+ }
+
+ ///
+ /// NAD27 Universal Transverse Mercator Projection - EPSG:26701 to EPSG:26722.
+ ///
+ public class Nad27UtmProjection : TransverseMercatorProjection
+ {
+ public const int FirstZone = 1;
+ public const int LastZone = 22;
+ public const int FirstZoneEpsgCode = 26700 + FirstZone;
+ public const int LastZoneEpsgCode = 26700 + LastZone;
+
+ public int Zone { get; }
+
+ public Nad27UtmProjection(int zone)
+ : base(6378206.4, 1d / 294.978698213898, 0.9996, zone) // Clarke 1866
+ {
+ if (zone < FirstZone || zone > LastZone)
+ {
+ throw new ArgumentException($"Invalid NAD27 UTM zone {zone}.", nameof(zone));
+ }
+
+ Zone = zone;
+ CrsId = $"EPSG:{26700 + zone}";
+ }
+ }
+}
diff --git a/MapControl/Shared/Wgs84UtmProjection.cs b/MapControl/Shared/Wgs84UtmProjection.cs
deleted file mode 100644
index 82aae18a..00000000
--- a/MapControl/Shared/Wgs84UtmProjection.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System;
-
-namespace MapControl
-{
- ///
- /// WGS84 Universal Transverse Mercator Projection -
- /// EPSG:32601 to EPSG:32660 and EPSG:32701 to EPSG:32760.
- ///
- public class Wgs84UtmProjection : TransverseMercatorProjection
- {
- public const int FirstZone = 1;
- public const int LastZone = 60;
- public const int FirstZoneNorthEpsgCode = 32600 + FirstZone;
- public const int LastZoneNorthEpsgCode = 32600 + LastZone;
- public const int FirstZoneSouthEpsgCode = 32700 + FirstZone;
- public const int LastZoneSouthEpsgCode = 32700 + LastZone;
-
- public int Zone { get; }
-
- public Wgs84UtmProjection(int zone, bool north) : base(zone)
- {
- if (zone < FirstZone || zone > LastZone)
- {
- throw new ArgumentException($"Invalid WGS84 UTM zone {zone}.", nameof(zone));
- }
-
- Zone = zone;
- CrsId = $"EPSG:{(north ? 32600 : 32700) + zone}";
- FalseNorthing = north ? 0d : 1e7;
- }
- }
-}