00001
00002
00003
00004
00005
00006 namespace NewGamePhysics.Physics
00007 {
00008 using System;
00009 using System.IO;
00010
00011 using NewGamePhysics.Mathematics;
00012 using NewGamePhysics.Utilities;
00013
00019 public class GravityEarthGfcGrid
00020 {
00024 private const int LatMin = -90;
00025
00029 private const int LatMax = 90;
00030
00034 private const int LonMin = 0;
00035
00039 private const int LonMax = 360;
00040
00045 private double[,] grid;
00046
00050 private int size = 0;
00051
00055 public GravityEarthGfcGrid()
00056 {
00057 }
00058
00064 public GravityEarthGfcGrid(string gridFilename)
00065 {
00066 this.LoadGravityMap(gridFilename);
00067 }
00068
00072 public int Size
00073 {
00074 get { return this.size; }
00075 }
00076
00086 public double Calculate(double lat, double lon, double h)
00087 {
00088 if (null == this.grid)
00089 {
00090 throw new ApplicationException(
00091 "Gravity map not initialized. Load one first.");
00092 }
00093
00094 if ((lat < -90.0) || (lat > 90.0))
00095 {
00096 throw new ArgumentOutOfRangeException("lat");
00097 }
00098
00099 if ((lon < 0.0) || (lon > 360.0))
00100 {
00101 throw new ArgumentOutOfRangeException("lon");
00102 }
00103
00104 if ((h < 0.0) || (h > 100000.0))
00105 {
00106 throw new ArgumentOutOfRangeException("h");
00107 }
00108
00109
00110 int intLat = (int)Math.Truncate(lat);
00111 int intLon = (int)Math.Truncate(lon);
00112
00113
00114 double[,] G = new double[4, 4];
00115 for (int i = -1; i <= 2; i++)
00116 {
00117 for (int j = -1; j <= 2; j++)
00118 {
00119 int indexLat = LatWrap(intLat + i) - LatMin;
00120 int indexLon = LonWrap(intLon + j) - LonMin;
00121 G[i+1,j+1] = grid[indexLat, indexLon];
00122 }
00123 }
00124
00125
00126 Bicubic bicubic = new Bicubic(G);
00127 double x = Math.Abs(lat - (double)intLat);
00128 double y = lon - (double)intLon;
00129 double g = bicubic.Calc(x,y);
00130
00131
00132 g *= 1e-5;
00133
00134
00135 g -= (3.086e-6 * h);
00136
00137 return g;
00138 }
00139
00146 public void LoadGravityMap(string gridFilename)
00147 {
00148
00149 size = 0;
00150 grid = new double[(LatMax - LatMin + 1), (LonMax - LonMin + 1)];
00151
00152
00153 Scanf scanf = new Scanf();
00154 FileStream fileStream = null;
00155 StreamReader streamReader = null;
00156 try
00157 {
00158 fileStream = new FileStream(gridFilename, FileMode.Open);
00159 streamReader = new StreamReader(fileStream);
00160 string line;
00161 while ((line = streamReader.ReadLine()) != null)
00162 {
00163 object[] o = scanf.Scan(line, " %lf %lf %lf");
00164 if ((null != o) && (o.Length == 3))
00165 {
00166 int lon = (int)Math.Truncate((double)o[0]);
00167 int lat = (int)Math.Truncate((double)o[1]);
00168 double g = (double)o[2];
00169
00170
00171 if ((lat < LatMin) || (lat > LatMax) || (lon < LonMin) || (lon > LonMax))
00172 {
00173 throw new Exception("Invalid data: " + line);
00174 }
00175
00176 int latIndex = lat - LatMin;
00177 int lonIndex = lon - LonMin;
00178
00179
00180 if (grid[latIndex, lonIndex] != 0.0)
00181 {
00182 throw new Exception("Double grid value: " + line);
00183 }
00184
00185
00186 grid[latIndex, lonIndex] = g;
00187 size++;
00188 }
00189 }
00190 }
00191 finally
00192 {
00193 if (null != streamReader)
00194 {
00195 streamReader.Close();
00196 }
00197 if (null != fileStream)
00198 {
00199 fileStream.Close();
00200 }
00201 }
00202 }
00203
00207 public void UnloadGravityMap()
00208 {
00209 this.grid = null;
00210 }
00211
00217 private int LatWrap(int lat)
00218 {
00219 while (lat < LatMin)
00220 {
00221 lat =+ (LatMax - LatMin);
00222 }
00223
00224 while (lat > LatMax)
00225 {
00226 lat -= (LatMax - LatMin);
00227 }
00228
00229 return lat;
00230 }
00231
00237 private int LonWrap(int lon)
00238 {
00239 while (lon < LonMin)
00240 {
00241 lon += (LonMax - LonMin);
00242 }
00243
00244 while (lon > LonMax)
00245 {
00246 lon -= (LonMax - LonMin);
00247 }
00248
00249 return lon;
00250 }
00251 }
00252 }