// ******************************************************************************************************** // Product Name: DotSpatial.Projection // Description: The basic module for MapWindow version 6.0 // ******************************************************************************************************** // The contents of this file are subject to the MIT License (MIT) // you may not use this file except in compliance with the License. You may obtain a copy of the License at // http://dotspatial.codeplex.com/license // // Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF // ANY KIND, either expressed or implied. See the License for the specific language governing rights and // limitations under the License. // // The original content was ported from the C language from the 4.6 version of Proj4 libraries. // Frank Warmerdam has released the full content of that version under the MIT license which is // recognized as being approximately equivalent to public domain. The original work was done // mostly by Gerald Evenden. The latest versions of the C libraries can be obtained here: // http://trac.osgeo.org/proj/ // // The Initial Developer of this Original Code is Ted Dunsford. Created 8/13/2009 2:34:47 PM // // Contributor(s): (Open source contributors should list themselves and their modifications here). // // ******************************************************************************************************** using System; namespace DotSpatial.Projections.Transforms { /// /// NewZealandMapGrid /// public class NewZealandMapGrid : Transform { #region Private Variables private const double SEC5_TO_RAD = 0.4848136811095359935899141023; private const double RAD_TO_SEC5 = 2.062648062470963551564733573; private const int NBF = 5; private const int NTPSI = 9; private const int NTPHI = 8; private readonly double[][] _bf; private readonly double[] _tphi; private readonly double[] _tpsi; #endregion #region Constructors /// /// Creates a new instance of NewZealandMapGrid /// public NewZealandMapGrid() { Proj4Name = "nzmg"; Name = "New_Zealand_Map_Grid"; _bf = new double[6][]; _bf[0] = new[] { .7557853228, 0.0 }; _bf[1] = new[] { .249204646, .003371507 }; _bf[2] = new[] { -.001541739, .041058560 }; _bf[3] = new[] { -.10162907, .01727609 }; _bf[4] = new[] { -.26623489, -.36249218 }; _bf[5] = new[] { -.6870983, -1.1651967 }; _tphi = new[] { 1.5627014243, .5185406398, -.03333098, -.1052906, -.0368594, .007317, .01220, .00394, -.0013 }; _tpsi = new[] { .6399175073, -.1358797613, .063294409, -.02526853, .0117879, -.0055161, .0026906, -.001333, .00067, -.00034 }; } #endregion #region Methods /// /// Initializes the transform using the parameters from the specified coordinate system information /// /// A ProjectionInfo class contains all the standard and custom parameters needed to initialize this transform protected override void OnInit(ProjectionInfo projInfo) { Ra = 1 / (A = 6378388.0); Lam0 = DEG_TO_RAD * 173; Phi0 = DEG_TO_RAD * -41; X0 = 2510000; Y0 = 6023150; } /// protected override void OnForward(double[] lp, double[] xy, int startIndex, int numPoints) { for (int i = startIndex; i < startIndex + numPoints; i++) { int phi = i * 2 + PHI; int lam = i * 2 + LAMBDA; int x = i * 2 + X; int y = i * 2 + Y; double[] p = new double[2]; lp[phi] = (lp[phi] - Phi0) * RAD_TO_SEC5; p[R] = _tpsi[NTPSI]; for (int j = NTPSI - 1; j >= 0; j--) { p[R] = _tpsi[j] + lp[phi] * p[R]; } p[R] *= lp[phi]; p[I] = lp[lam]; //HACK: Create a shallow, value-based version of the array. //Because arrays are passed by refernce, the _bf array is getting permanently modified //inside the Proj.Zpoly1() method. Consequently, the results returned by this method differ each time around. double[][] bf = new double[_bf.Length][]; for (int k = 0; k < _bf.Length; k++) { bf[k] = new double[2]; bf[k][0] = _bf[k][0]; bf[k][1] = _bf[k][1]; } p = Proj.Zpoly1(p, bf, NBF); xy[x] = p[I]; xy[y] = p[R]; } } /// protected override void OnInverse(double[] xy, double[] lp, int startIndex, int numPoints) { for (int i = startIndex; i < startIndex + numPoints; i++) { int phi = i * 2 + PHI; int lam = i * 2 + LAMBDA; int x = i * 2 + X; int y = i * 2 + Y; int nn; double[] p = new double[2]; double[] dp = new double[2]; p[R] = xy[y]; p[I] = xy[x]; for (nn = 20; nn > 0; --nn) { double[] fp; double[] f = Proj.Zpolyd1(p, _bf, NBF, out fp); f[R] -= xy[y]; f[I] -= xy[x]; double den = fp[R] * fp[R] + fp[I] * fp[I]; p[R] += dp[R] = -(f[R] * fp[R] + f[I] * fp[I]) / den; p[I] += dp[I] = -(f[I] * fp[R] - f[R] * fp[I]) / den; if ((Math.Abs(dp[R]) + Math.Abs(dp[I])) <= EPS10) break; } if (nn > 0) { lp[lam] = p[I]; lp[phi] = _tphi[NTPHI]; for (int j = NTPHI - 1; j > 0; j++) { lp[phi] = _tphi[j] + p[R] * lp[phi]; } lp[phi] = Phi0 + p[R] * lp[phi] * SEC5_TO_RAD; } else { lp[lam] = lp[phi] = double.MaxValue; } } } #endregion #region Properties #endregion } }