/// <summary> /// Converts a geodetic coordinate to a grid coordinate. /// </summary> /// <param name="coordinate">The geodetic coordinate to convert.</param> /// <param name="projection">The projection to use in the conversion.</param> /// <returns>The grid representation of the initial coordinate.</returns> public static GridCoordinate GeodeticToGrid(GeodeticCoordinate coordinate, Projection projection) { var gridCoordinate = new GridCoordinate { Projection = projection }; double flattening = projection.Ellipsoid.Flattening; double axis = projection.Ellipsoid.SemiMajorAxis; double eSquare = flattening * (2d - flattening); double n = flattening / (2d - flattening); double a = axis / (1d + n) * (1 + n * n / 4 + n * n * n * n / 64d); // ReSharper disable InconsistentNaming double A = eSquare; double B = (5d * eSquare * eSquare - eSquare * eSquare * eSquare) / 6d; double C = (104d * eSquare * eSquare * eSquare - 45d * eSquare * eSquare * eSquare * eSquare) / 120d; double D = (1237d * eSquare * eSquare * eSquare * eSquare) / 1260d; // ReSharper restore InconsistentNaming double beta1 = n / 2d - (2d * n * n) / 3d + (5d * n * n * n) / 16d + (41d * n * n * n * n) / 180d; double beta2 = (13d * n * n) / 48d - (3d * n * n * n) / 5d + (557d * n * n * n * n) / 1440d; double beta3 = (61d * n * n * n) / 240d - (103d * n * n * n * n) / 140d; double beta4 = (49561d * n * n * n * n) / 161280d; double radLat = coordinate.Latitude.ToRadians(); double radLon = coordinate.Longitude.ToRadians(); double radMeridian = projection.CentralMeridianLon.ToRadians(); double radLonDelta = radLon - radMeridian; double conformalLatitude = radLat - Math.Sin(radLat) * Math.Cos(radLat) * (A + B * Math.Pow(Math.Sin(radLat), 2d) + C * Math.Pow(Math.Sin(radLat), 4d) + D * Math.Pow(Math.Sin(radLat), 6d)); double xiPrime = Math.Atan(Math.Tan(conformalLatitude) / Math.Cos(radLonDelta)); // Bad naming but there is no name defined for this in the specs double etaPrime = Atanh(Math.Cos(conformalLatitude) * Math.Sin(radLonDelta)); // Bad naming but there is no name defined for this in the specs gridCoordinate.X = projection.CentralMeridianScale * a * (xiPrime + beta1 * Math.Sin(2d * xiPrime) * Math.Cosh(2d * etaPrime) + beta2 * Math.Sin(4d * xiPrime) * Math.Cosh(4d * etaPrime) + beta3 * Math.Sin(6d * xiPrime) * Math.Cosh(6d * etaPrime) + beta4 * Math.Sin(8d * xiPrime) * Math.Cosh(8d * etaPrime)) + projection.FalseNorthing; gridCoordinate.Y = projection.CentralMeridianScale * a * (etaPrime + beta1 * Math.Cos(2d * xiPrime) * Math.Sinh(2d * etaPrime) + beta2 * Math.Cos(4d * xiPrime) * Math.Sinh(4d * etaPrime) + beta3 * Math.Cos(6d * xiPrime) * Math.Sinh(6d * etaPrime) + beta4 * Math.Cos(8d * xiPrime) * Math.Sinh(8d * etaPrime)) + projection.FalseEasting; return(gridCoordinate); }