00001
00002
00003
00004
00005
00006 namespace NewGamePhysics.Mathematics
00007 {
00008 using System;
00009
00016 class MercatorProjection
00017 {
00021 private static readonly double MajorRadius = 6378137.0;
00022
00026 private static readonly double MinorRadius = 6356752.3142;
00027
00031 private static readonly double Ratio = MinorRadius / MajorRadius;
00032
00036 private static readonly double Eccentricity = Math.Sqrt(1.0 - (Ratio * Ratio));
00037
00041 private static readonly double Deg2Rad = Math.PI / 180.0;
00042
00046 private static readonly double Rad2Deg = 180.0 / Math.PI;
00047
00051 private static readonly double PiHalf = Math.PI / 2.0;
00052
00059 public static double lonToX(double lon)
00060 {
00061 if ((lon < 0) || (lon > 360.0))
00062 {
00063 throw new ArgumentOutOfRangeException("lon");
00064 }
00065
00066 return lon / 360.0;
00067 }
00068
00076 public static double latToY(double lat)
00077 {
00078 if ((lat < -90.0) || (lat > 90.0))
00079 {
00080 throw new ArgumentOutOfRangeException("lat");
00081 }
00082
00083
00084 lat = Math.Min(89.0, Math.Max(lat, -89.0));
00085
00086
00087 double phi = DegToRad(lat);
00088 double sinphi = Math.Sin(phi);
00089 double con = Eccentricity * sinphi;
00090 con = Math.Pow(((1.0 - con) / (1.0 + con)), 0.5 * Eccentricity);
00091 double ts = Math.Tan(0.5 * ((Math.PI * 0.5) - phi)) / con;
00092 double y = -Math.Log(ts) * 0.5;
00093 y += 1.0;
00094 y *= 0.5;
00095 y = Math.Min(1.0, Math.Max(y, 0.0));
00096 return y;
00097 }
00098
00105 public static double xToLon(double x)
00106 {
00107 if ((x < 0.0) || (x > 1.0))
00108 {
00109 throw new ArgumentOutOfRangeException("lon");
00110 }
00111
00112 return x * 360.0;
00113 }
00114
00121 public static double yToLat(double y)
00122 {
00123 if ((y < 0.0) || (y > 1.0))
00124 {
00125 throw new ArgumentOutOfRangeException("lon");
00126 }
00127
00128 double ts = Math.Exp(-y);
00129 double phi = PiHalf - 2 * Math.Atan(ts);
00130 double dphi = 1.0;
00131 int i = 0;
00132 while ((Math.Abs(dphi) > 0.000000001) && (i < 15))
00133 {
00134 double c = Eccentricity * Math.Sin(phi);
00135 dphi = PiHalf - 2 * Math.Atan(ts * Math.Pow((1.0 - c) / (1.0 + c), 0.5 * Eccentricity)) - phi;
00136 phi += dphi;
00137 i++;
00138 }
00139 return RadToDeg(phi);
00140 }
00141
00147 private static double RadToDeg(double rad)
00148 {
00149 return rad * Rad2Deg;
00150 }
00151
00157 private static double DegToRad(double deg)
00158 {
00159 return deg * Deg2Rad;
00160 }
00161 }
00162 }