Обратите внимание: эта реализация не преобразуется с точной точностью.
Вот реализация C#, которую я собрал для преобразования из NZMG в NZGD1949, а затем в нулевой сдвиг от NZGD1949 до NZGD2000. Координаты NZGD2000, по-видимому, совместимы с источником WGS84: http://www.linz.govt.nz/data/geodetic-system/coordinate-conversion/geodetic-datum-conversions/wgs84-nzgd2000.
Я добавил параметр useStaticCorrection к методу сдвига нулевой точки, потому что обнаружил, что мои результаты были последовательно отключены примерно на 40 метров по широте - это зависит от входных координат. Это может быть из-за ошибки в логике, но, насколько я могу судить, она кажется правильной (как упоминалось в источниках).
Источники:
Константы и коэффициенты
http://www.linz.govt.nz/data/geodetic-system/coordinate-conversion/projection-conversions/new-zealand-map-grid
Datum информация.
http://www.linz.govt.nz/regulatory/25000
NZMG -> NZGD1949 формула
http://www.linz.govt.nz/data/geodetic-system/coordinate-conversion/projection-conversions/new-zealand-map-grid
NZ1949 -> NZGD2000 различия
http://www.linz.govt.nz/data/geodetic-system/coordinate-conversion/geodetic-datum-conversions/nzgd1949-nzgd2000/three-seven
Equivilent сдвига в три параметра.
http://sas2.elte.hu/tg/eesti_datums_egs9.htm
// Lat/Long выдумки составляет
http://www.linz.govt.nz/data/geodetic-system/coordinate-conversion/geodetic-datum-conversions/datum-transformation-examples
public class Pair<T, U>
{
public Pair()
{
}
public Pair(T first, U second)
{
this.First = first;
this.Second = second;
}
public T First { get; set; }
public U Second { get; set; }
};
using System.Numerics;
public class NZMGConverter
{
//Constants and coefficients
//Source: http://www.linz.govt.nz/data/geodetic-system/coordinate-conversion/projection-conversions/new-zealand-map-grid
private static Double N0 = 6023150;
private static Double E0 = 2510000;
private static Double NZGD1949a = 6378388;
private static Double NZMGLatOrigin = -41;
private static Double NZMGLongOrigin = 173;
//some of these are unused but are included for completeness. (unused arrays are for converting from wgs84/nzgd2000 -> nzmg).
private static Double[] A = new Double[] { 0.6399175073, -0.1358797613, 0.0632944090, -0.0252685300, 0.0117879000, -0.0055161000, 0.0026906000, -0.0013330000, 0.0006700000, -0.0003400000 };
private static Complex[] B = new Complex[] { new Complex(0.7557853228, 0.0), new Complex(0.249204646, 0.003371507), new Complex(-0.001541739, 0.04105856), new Complex(-0.10162907, 0.01727609), new Complex(-0.26623489, -0.36249218), new Complex(-0.6870983, -1.1651967) };
private static Complex[] C = new Complex[] { new Complex(1.3231270439, 0.0), new Complex(-0.577245789, -0.007809598), new Complex(0.508307513, -0.112208952), new Complex(-0.15094762, 0.18200602), new Complex(1.01418179, 1.64497696), new Complex(1.9660549, 2.5127645) };
private static Double[] D = new Double[] { 1.5627014243, 0.5185406398, -0.0333309800, -0.1052906000, -0.0368594000, 0.0073170000, 0.0122000000, 0.0039400000, -0.0013000000 };
//Datum info.
//Source: http://www.linz.govt.nz/regulatory/25000
private static Double NZGD1949f = 0.003367003;
//Double NZGD1949InverseFlattening = 297;
private static Double NZGD1949e2 = (2 * 0.003367003) - Math.Pow(0.003367003, 2);
private static Double NZGD2000a = 6378137;
private static Double NZGD2000f = 0.003352811;
//Double NZGD2000InverseFlattening = 298.2572221;
private static Double NZGD2000e2 = (2 * 0.003352811) - Math.Pow(0.003352811, 2);
//NZ1949 -> NZGD2000 differences
//Source: http://www.linz.govt.nz/data/geodetic-system/coordinate-conversion/geodetic-datum-conversions/nzgd1949-nzgd2000/three-seven
private static Double differenceX = 54.4;
private static Double differenceY = -20.1;
private static Double differenceZ = 183.1;
//Source: http://www.linz.govt.nz/data/geodetic-system/coordinate-conversion/projection-conversions/new-zealand-map-grid
public static Pair<Double, Double> convertToNZGD1949(Double nzmgX, Double nzmgY)
{
Pair<Double, Double> result = null;
Complex z = new Complex((nzmgY - N0)/NZGD1949a, (nzmgX - E0)/NZGD1949a);
Complex theta0 = new Complex();
for (int i = 0; i < C.Length; ++i) { theta0 += Complex.Multiply(C[i], Complex.Pow(z, i + 1)); }
Double deltaLatWtheta0 = 0;
for (int i = 0; i < D.Length; ++i) { deltaLatWtheta0 += D[i] * Math.Pow(theta0.Real, (i + 1)); }
result = new Pair<double, double>();
result.First = NZMGLatOrigin + (Math.Pow(10, 5)/3600) * deltaLatWtheta0; //NZGD1949 lat
result.Second = NZMGLongOrigin + 180/Math.PI * theta0.Imaginary; //NZGD1949 long
return result;
}
//Equivilent of a Three parameter shift.
//Source: http://sas2.elte.hu/tg/eesti_datums_egs9.htm
public static Pair<Double, Double> datumShiftNZGD1949toNZGD2000(Double nzgd1949Lat, Double nzgd1949Long, Boolean useStaticCorrection)
{
Pair<Double, Double> result = null;
Double latInRaidans = nzgd1949Lat * (Math.PI/180);
Double lngInRaidans = nzgd1949Long * (Math.PI/180);
Double n = NZGD1949a/Math.Sqrt((1 - NZGD1949e2 * Math.Pow(Math.Sin(latInRaidans), 2)) * (3/2));
Double m = NZGD1949a * ((1 - NZGD1949e2)/(1 - NZGD1949e2 * Math.Pow(Math.Sin(latInRaidans), 2) * (3/2)));
Double difF = NZGD2000f - NZGD1949f;
Double difA = NZGD2000a - NZGD1949a;
Double changeInLat = (-1 * differenceX * Math.Sin(latInRaidans) * Math.Cos(lngInRaidans)
- differenceY * Math.Sin(latInRaidans) * Math.Sin(lngInRaidans)
+ differenceZ * Math.Cos(latInRaidans) + (NZGD1949a * difF + NZGD1949f * difA) * Math.Sin(2 * latInRaidans))
/(m * Math.Sin(1));
Double changeInLong = (-1 * differenceX * Math.Sin(lngInRaidans) + differenceY * Math.Cos(lngInRaidans))/(n * Math.Cos(latInRaidans) * Math.Sin(1));
result = new Pair<Double, Double>();
result.First = (latInRaidans + changeInLat) * (180/Math.PI);
result.Second = (lngInRaidans + changeInLong) * (180/Math.PI);
if (useStaticCorrection)
{
//Difference found by 3-parameter test values @ http://www.linz.govt.nz/data/geodetic-system/coordinate-conversion/geodetic-datum-conversions/datum-transformation-examples
Double staticLatCorrection = 0.00037432;
Double staticLongCorrection = -0.00003213;
result.First -= staticLatCorrection;
result.Second += staticLongCorrection;
}
return result;
}
}
Вы смотрели на http://www.linz.govt.nz/geodetic/conversion-coordinates/geodetic-datum-conversion/? Кажется, что [NZGD2000 эквивалентен WGS84] (http://www.linz.govt.nz/geodetic/conversion-coordinates/geodetic-datum-conversion/wgs84-nzgd2000), и есть формулы для преобразования NZGD1949 в NZGD2000. – xanatos
задать этот вопрос в GIS.Stachexchange – Ehsan
Можете ли вы упомянуть некоторые формулы? –