- Main Page
- Classes
- Files

- File List

# C:/Users/Andreas Schiffler/Desktop/SVN/NewGamePhysics/NewGamePhysics/Physics/GravityCalculator.cs

    00001 ﻿// --------------------------------------------------------
    00002 // GravityCalculator.cs
    00003 // (A. Schiffler, 2009)
    00004 // --------------------------------------------------------
    00005
    00006 namespace NewGamePhysics.Physics
    00007 {
    00008     using System;
    00009     using System.Text;
    00010
    00018     public enum EarthGravityModel
    00019     {
    00023         None,
    00024
    00028         FolkPhysics,
    00029
    00036         Igf67,
    00037
    00044         Grs80,
    00045
    00055         Grs80Hd,
    00056
    00063         Wgs84,
    00064
    00074         Wgs84Hd,
    00075
    00083         GfcGrid,
    00084
    00094         Ggm03sModel,
    00095
    00110         Eigen5cModel,
    00111     }
    00112
    00119     public enum EarthGravityAnomaly
    00120     {
    00124         None,
    00125
    00131         Fac,
    00132
    00139         BouguerPlane,
    00140
    00147         BouguerSpherical,
    00148     }
    00149
    00150
    00155     public enum MarsGravityModel
    00156     {
    00160         None,
    00161
    00165         Normal,
    00166
    00176         GgMro,
    00177     }
    00178
    00182     public class GravityCalculator
    00183     {
    00187         public const double G = 6.67428e-11;
    00188
    00192         private CelestialObject simulatedBody;
    00193
    00201         public const double StandardBouguerDensity = 2670.0;
    00202
    00207         private EarthGravityModel earthGravityModel;
    00208
    00213         private MarsGravityModel marsGravityModel;
    00214
    00219         private EarthGravityAnomaly earthGravityAnomaly;
    00220
    00224         private GravityEarthGrsModel grsModel;
    00225
    00229         private GravityEarthWgsModel wgsModel;
    00230
    00235         private GravityEarthGfcGrid gfcGrid;
    00236
    00241         private GravityEarthGfcModel gfcModel;
    00242
    00247         private GravityMarsMroModel mroModel;
    00248
    00253         private double value;
    00254
    00258         private double latitude;
    00259
    00263         private double longitude;
    00264
    00269         private double elevation;
    00270
    00276         private double groundElevation;
    00277
    00281         private DateTime lastCalculation = DateTime.Now;
    00282
    00288         public EarthGravityModel EarthGravityModel
    00289         {
    00290             get
    00291             {
    00292                 return this.earthGravityModel;
    00293             }
    00294
    00295             set
    00296             {
    00297                 this.earthGravityModel = value;
    00298
    00299                 // Set body to mars
    00300                 this.simulatedBody = CelestialObject.Earth;
    00301
    00302                 // Update models
    00303                 this.UnloadModelData();
    00304                 switch (value)
    00305                 {
    00306                     case EarthGravityModel.GfcGrid:
    00307                         this.gfcGrid.LoadGravityMap(@"Physics\Grids\eigen5c.gdf");
    00308                         break;
    00309                     case EarthGravityModel.Ggm03sModel:
    00310                         this.gfcModel.LoadGfcModel(@"Physics\Models\ggm03s.gfc");
    00311                         break;
    00312                     case EarthGravityModel.Eigen5cModel:
    00313                         this.gfcModel.LoadGfcModel(@"Physics\Models\eigen5c.gfc");
    00314                         break;
    00315                 }
    00316
    00317                 UpdateValue();
    00318             }
    00319         }
    00320
    00326         public MarsGravityModel MarsGravityModel
    00327         {
    00328             get
    00329             {
    00330                 return this.marsGravityModel;
    00331             }
    00332
    00333             set
    00334             {
    00335                 this.marsGravityModel = value;
    00336
    00337                 // Set body to mars
    00338                 this.simulatedBody = CelestialObject.Mars;
    00339
    00340                 // Update models
    00341                 this.UnloadModelData();
    00342                 switch (value)
    00343                 {
    00344                     case MarsGravityModel.GgMro:
    00345                         this.mroModel.LoadAnomalyMap(@"Physics\Models\ggmro_095a_anom_085.img");
    00346                         break;
    00347                 }
    00348
    00349                 UpdateValue();
    00350             }
    00351         }
    00352
    00359         public EarthGravityAnomaly EarthGravityAnomaly
    00360         {
    00361             get
    00362             {
    00363                 return this.earthGravityAnomaly;
    00364             }
    00365
    00366             set
    00367             {
    00368                 this.earthGravityAnomaly = value;
    00369                 if (this.simulatedBody == CelestialObject.Earth)
    00370                 {
    00371                     UpdateValue();
    00372                 }
    00373             }
    00374         }
    00375
    00379         public double Value
    00380         {
    00381             get
    00382             {
    00383                 return this.value;
    00384             }
    00385         }
    00386
    00391         public double Latitude
    00392         {
    00393             get { return this.latitude; }
    00394             set
    00395             {
    00396                 if ((value < -90.0) || (value > 90.0))
    00397                 {
    00398                     throw new ArgumentOutOfRangeException();
    00399                 }
    00400
    00401                 this.latitude = value;
    00402                 UpdateValue();
    00403             }
    00404         }
    00405
    00410         public double Longitude
    00411         {
    00412             get { return this.longitude; }
    00413             set
    00414             {
    00415                 if ((value < 0.0) || (value > 360.0))
    00416                 {
    00417                     throw new ArgumentOutOfRangeException();
    00418                 }
    00419
    00420                 this.longitude = value;
    00421                 UpdateValue();
    00422             }
    00423         }
    00424
    00430         public double Elevation
    00431         {
    00432             get { return this.elevation; }
    00433             set
    00434             {
    00435                 if ((value >= 0.0) &&
    00436                     (value <= 1000000.0))
    00437                 {
    00438                     this.elevation = value;
    00439
    00440                     // Maybe adjust ground elevation as well
    00441                     if (this.groundElevation > value)
    00442                     {
    00443                         this.groundElevation = value;
    00444                     }
    00445
    00446                     UpdateValue();
    00447                 }
    00448                 else
    00449                 {
    00450                     throw new ArgumentOutOfRangeException();
    00451                 }
    00452             }
    00453         }
    00454
    00460         public double GroundElevation
    00461         {
    00462             get { return this.groundElevation; }
    00463             set
    00464             {
    00465                 if ((value >= 0.0) &&
    00466                     (value <= 10000.0))
    00467                 {
    00468                     this.groundElevation = value;
    00469
    00470                     // Maybe adjust elevation to be consistent
    00471                     if (this.elevation < value)
    00472                     {
    00473                         this.elevation = value;
    00474                     }
    00475
    00476                     UpdateValue();
    00477                 }
    00478                 else
    00479                 {
    00480                     throw new ArgumentOutOfRangeException();
    00481                 }
    00482             }
    00483         }
    00484
    00488         public GravityCalculator()
    00489             : this(CelestialObject.Earth)
    00490         {
    00491         }
    00492
    00497         public GravityCalculator(CelestialObject body)
    00498         {
    00499             // Initialize earth models
    00500             this.wgsModel = new GravityEarthWgsModel();
    00501             this.grsModel = new GravityEarthGrsModel();
    00502             this.gfcGrid = new GravityEarthGfcGrid();
    00503             this.gfcModel = new GravityEarthGfcModel();
    00504
    00505             // Initialize mars models
    00506             this.mroModel = new GravityMarsMroModel();
    00507
    00508             // Initialize instance state
    00509             this.simulatedBody = body;
    00510             this.earthGravityModel = EarthGravityModel.None;
    00511             this.earthGravityAnomaly = EarthGravityAnomaly.None;
    00512             this.marsGravityModel = MarsGravityModel.None;
    00513             this.latitude = 0.0;
    00514             this.elevation = 0.0;
    00515             this.groundElevation = 0.0;
    00516
    00517             // Initialize current value
    00518             this.UpdateValue();
    00519         }
    00520
    00526         public string GetModelInfo()
    00527         {
    00528             StringBuilder sb = new StringBuilder();
    00529
    00530             switch (this.simulatedBody)
    00531             {
    00532                 case CelestialObject.Sun:
    00533                     sb.AppendLine("Model: Fixed value.");
    00534                     sb.AppendLine("Source: http://www.wikipedia.org [Earth's Gravity]");
    00535                     break;
    00536                 case CelestialObject.Mercury:
    00537                     sb.AppendLine("Model: Fixed value.");
    00538                     sb.AppendLine("Source: http://www.wikipedia.org [Earth's Gravity]");
    00539                     break;
    00540                 case CelestialObject.Venus:
    00541                     sb.AppendLine("Model: Fixed value.");
    00542                     sb.AppendLine("Source: http://www.wikipedia.org [Earth's Gravity]");
    00543                     break;
    00544                 case CelestialObject.Earth:
    00545                     switch (this.earthGravityModel)
    00546                     {
    00547                         case EarthGravityModel.None:
    00548                             sb.AppendLine("Model: Fixed value.");
    00549                             sb.AppendLine("Source: http://www.wikipedia.org [Earth's Gravity]");
    00550                             break;
    00551                         case EarthGravityModel.FolkPhysics:
    00552                             sb.AppendLine("Model: Commonly used fixed value.");
    00553                             break;
    00554                         case EarthGravityModel.Igf67:
    00555                             sb.AppendLine("Model: Geodetic Reference System from 1967 (Version provided by IGF).");
    00556                             sb.AppendLine("Source: http://geophysics.ou.edu/solid_earth/notes/potential/igf.htm");
    00557                             break;
    00558                         case EarthGravityModel.Grs80:
    00559                             sb.AppendLine("Model: The GRS 80 geodetic system.");
    00560                             sb.AppendLine("Source: http://bgi.cnes.fr:8110");
    00561                             break;
    00562                         case EarthGravityModel.Grs80Hd:
    00563                             sb.AppendLine("Model: High-res calculation of the geodetic reference system (GRS 80)");
    00564                             sb.AppendLine("Applies height correction.");
    00565                             sb.AppendLine("Source: Hofmann-Wellenhof/Moritz, Physical Godesy, 2006.");
    00566                             break;
    00567                         case EarthGravityModel.Wgs84:
    00568                             sb.AppendLine("Model: World Geodetic System 84 Ellipsoidal Gravity Formula");
    00569                             sb.AppendLine("Source: http://www.wikipedia.org [Earth's Gravity]");
    00570                             break;
    00571                         case EarthGravityModel.Wgs84Hd:
    00572                             sb.AppendLine("Model: High-res calculation of the World Geodetic System (WGS 84)");
    00573                             sb.AppendLine("Applies height correction.");
    00574                             sb.AppendLine("Source: Hofmann-Wellenhof/Moritz, Physical Godesy, 2006.");
    00575                             break;
    00576                         case EarthGravityModel.GfcGrid:
    00577                             sb.AppendLine("Model: Grid interpolator of earths gravity based on data from");
    00578                             sb.AppendLine("the International Center for Global Earth Models (ICGEM).");
    00579                             sb.AppendLine("Grid based on eigen5c model with a 1 degree resolution.");
    00580                             sb.AppendLine("Source: http://icgem.gfz-potsdam.de/ICGEM/ICGEM.html");
    00581                             break;
    00582                         case EarthGravityModel.Ggm03sModel:
    00583                             sb.AppendLine("Model: Satellite only mean Earth Gravity Model from GRACE satellite");
    00584                             sb.AppendLine("GGM03S is an unconstrained global gravity model complete to degree and order 180");
    00585                             sb.AppendLine("accelerometer data. 47 months of GRACE data for the period from January 2003");
    00586                             sb.AppendLine("through December 2006 were used (January 2004 excluded). The GRACE atmosphere-ocean");
    00587                             sb.AppendLine("de-aliasing product (AOD1B) was used, but the mean of the AOD1B for the 47 months");
    00588                             sb.AppendLine("has been restored so that GGM03S represents the true mean field.");
    00589                             sb.AppendLine("Source: http://icgem.gfz-potsdam.de/ICGEM/ICGEM.html");
    00590                             break;
    00591                         case EarthGravityModel.Eigen5cModel:
    00592                             sb.AppendLine("Model: A new global combined high-resolution GRACE-based gravity");
    00593                             sb.AppendLine("field model of the GFZ-GRGS cooperation.");
    00594                             sb.AppendLine("The reference epoch of this gravity field model is 01 Oct 2004");
    00595                             sb.AppendLine("Source: http://icgem.gfz-potsdam.de/ICGEM/ICGEM.html");
    00596                             break;
    00597                     }
    00598                     break;
    00599                 case CelestialObject.Moon:
    00600                     sb.AppendLine("Model: Fixed value.");
    00601                     sb.AppendLine("Source: http://www.wikipedia.org [Earth's Gravity]");
    00602                     break;
    00603                 case CelestialObject.Mars:
    00604                     switch (this.marsGravityModel)
    00605                     {
    00606                         case MarsGravityModel.None:
    00607                             sb.AppendLine("Model: Fixed value.");
    00608                             sb.AppendLine("Source: http://www.wikipedia.org [Earth's Gravity]");
    00609                             break;
    00610                         case MarsGravityModel.Normal:
    00611                             sb.AppendLine("Model: Ellipsoid.");
    00612                             sb.AppendLine("Algorithm: Hofmann-Wellenhof/Moritz, Physical Godesy, 2006");
    00613                             sb.AppendLine("Source: http://pds-geosciences.wustl.edu/mro/mro-m-rss-5-sdp-v1/mrors_1xxx/data/rsdmap/");
    00614                             break;
    00615                         case MarsGravityModel.GgMro:
    00616                             sb.AppendLine("Model: GgMro 095A NASA GSFC Mars Reconnaissance Orbiter.");
    00617                             sb.AppendLine("A digital map of the Mars gravity anomalies derived from");
    00618                             sb.AppendLine("spherical harmonic coefficients of the NASA GSFC MROMGM0032 Mars gravity field");
    00619                             sb.AppendLine("Source: http://pds-geosciences.wustl.edu/mro/mro-m-rss-5-sdp-v1/mrors_1xxx/data/rsdmap/");
    00620                             break;
    00621                     }
    00622                     break;
    00623                 case CelestialObject.Jupiter:
    00624                     sb.AppendLine("Model: Fixed value.");
    00625                     sb.AppendLine("Source: http://www.wikipedia.org [Earth's Gravity]");
    00626                     break;
    00627                 case CelestialObject.Io:
    00628                     sb.AppendLine("Model: Fixed value.");
    00629                     sb.AppendLine("Source: http://www.wikipedia.org [Io_(moon)]");
    00630                     break;
    00631                 case CelestialObject.Europa:
    00632                     sb.AppendLine("Model: Fixed value.");
    00633                     sb.AppendLine("Source: http://www.wikipedia.org [Europa_(moon)]");
    00634                     break;
    00635                 case CelestialObject.Ganymede:
    00636                     sb.AppendLine("Model: Fixed value.");
    00637                     sb.AppendLine("Source: http://www.wikipedia.org [Ganymede_(moon)]");
    00638                     break;
    00639                 case CelestialObject.Callisto:
    00640                     sb.AppendLine("Model: Fixed value.");
    00641                     sb.AppendLine("Source: http://www.wikipedia.org [Callisto_(moon)]");
    00642                     break;
    00643                 case CelestialObject.Saturn:
    00644                     sb.AppendLine("Model: Fixed value.");
    00645                     sb.AppendLine("Source: http://www.wikipedia.org [Earth's Gravity]");
    00646                     break;
    00647                 case CelestialObject.Uranus:
    00648                     sb.AppendLine("Model: Fixed value.");
    00649                     sb.AppendLine("Source: http://www.wikipedia.org [Earth's Gravity]");
    00650                     break;
    00651                 case CelestialObject.Neptune:
    00652                     sb.AppendLine("Model: Fixed value.");
    00653                     sb.AppendLine("Source: http://www.wikipedia.org [Earth's Gravity]");
    00654                     break;
    00655             }
    00656
    00657             return sb.ToString();
    00658         }
    00659
    00666         private void UpdateValue()
    00667         {
    00668             switch (this.simulatedBody)
    00669             {
    00670                 case CelestialObject.Sun:
    00671                     value = 274.1;
    00672                     break;
    00673
    00674                 case CelestialObject.Mercury:
    00675                     value = 3.703;
    00676                     break;
    00677
    00678                 case CelestialObject.Venus:
    00679                     value = 8.872;
    00680                     break;
    00681
    00682                 case CelestialObject.Earth:
    00683                     // Flag controlling usage of fac correction
    00684                     bool facApplicable = false;
    00685
    00686                     // Model gravity and calculate a dynamic value
    00687                     double sinLat = Math.Sin(this.latitude * Math.PI / 180.0);
    00688                     double sin2Lat = Math.Sin(2.0 * this.latitude * Math.PI / 180.0);
    00689                     double sinLat2 = sinLat * sinLat;
    00690                     double sin2Lat2 = sin2Lat * sin2Lat;
    00691                     switch (earthGravityModel)
    00692                     {
    00693                         case EarthGravityModel.None:
    00694                             value = 9.80665;
    00695                             break;
    00696
    00697                         case EarthGravityModel.FolkPhysics:
    00698                             value = 9.81;
    00699                             break;
    00700
    00701                         case EarthGravityModel.Igf67:
    00702                             value = 9.78031846 * (1.0 + 0.0053024 * sinLat2 - 0.0000058 * sin2Lat2);
    00703                             facApplicable = true;
    00704                             break;
    00705
    00706                         case EarthGravityModel.Grs80:
    00707                             value = 9.7803267715 * (1.0 + 0.001931851353 * sinLat2) / Math.Sqrt(1.0 - 0.00669438002290 * sinLat2);
    00708                             facApplicable = true;
    00709                             break;
    00710
    00711                         case EarthGravityModel.Grs80Hd:
    00712                             value = grsModel.Calculate(this.latitude, this.elevation);
    00713                             break;
    00714
    00715                         case EarthGravityModel.Wgs84:
    00716                             value = 9.780326774 * (1.0 + 0.00193185138639 * sinLat2) / Math.Sqrt(1.0 - 0.00669437999013 * sinLat2);
    00717                             facApplicable = true;
    00718                             break;
    00719
    00720                         case EarthGravityModel.Wgs84Hd:
    00721                             value = wgsModel.Calculate(this.latitude, this.elevation);
    00722                             break;
    00723
    00724                         case EarthGravityModel.GfcGrid:
    00725                             value = gfcGrid.Calculate(this.latitude, this.longitude, this.elevation);
    00726                             break;
    00727
    00728                         case EarthGravityModel.Ggm03sModel:
    00729                             value = gfcModel.Calculate(this.latitude, this.longitude, this.elevation);
    00730                             break;
    00731
    00732                         case EarthGravityModel.Eigen5cModel:
    00733                             // Use rate limiter (5Hz max.) since calculation is slow
    00734                             if (DateTime.Now > lastCalculation.AddMilliseconds(200))
    00735                             {
    00736                                 value = gfcModel.Calculate(this.latitude, this.longitude, this.elevation);
    00737                                 lastCalculation = DateTime.Now;
    00738                             }
    00739
    00740                             break;
    00741                     }
    00742
    00743                     // Anomaly correction for elevation
    00744                     if ((facApplicable) &&
    00745                         ((earthGravityAnomaly == EarthGravityAnomaly.Fac) ||
    00746                          (earthGravityAnomaly == EarthGravityAnomaly.BouguerPlane)))
    00747                     {
    00748                         value -= (3.086e-6 * this.elevation);
    00749
    00750                     }
    00751
    00752                     if (earthGravityAnomaly == EarthGravityAnomaly.BouguerPlane)
    00753                     {
    00754                         // Anomaly correction for ground level (plane Bouguer plate
    00755                         value += (2.0 * Math.PI * G * StandardBouguerDensity * this.groundElevation);
    00756                     }
    00757                     else if (earthGravityAnomaly == EarthGravityAnomaly.BouguerSpherical)
    00758                     {
    00759                         // Anomaly correction for ground level (spherical Bouguer plate)
    00760                         value += (4.0 * Math.PI * G * StandardBouguerDensity * this.groundElevation);
    00761                     }
    00762
    00763                     break;
    00764
    00765                 case CelestialObject.Moon:
    00766                     value = 1.625;
    00767                     break;
    00768
    00769                 case CelestialObject.Mars:
    00770                     // Model gravity and calculate a dynamic value
    00771                     switch (marsGravityModel)
    00772                     {
    00773                         case MarsGravityModel.None:
    00774                             value = 3.728;
    00775                             break;
    00776
    00777                         case MarsGravityModel.Normal:
    00778                             value = GravityMarsNormalModel.Calculate(this.latitude);
    00779                             break;
    00780
    00781                         case MarsGravityModel.GgMro:
    00782                             value = mroModel.Calculate(this.latitude, this.longitude, this.elevation);
    00783                             break;
    00784                     }
    00785
    00786                     break;
    00787
    00788                 case CelestialObject.Jupiter:
    00789                     value = 25.93;
    00790                     break;
    00791
    00792                 case CelestialObject.Io:
    00793                     value = 1.796;
    00794                     break;
    00795
    00796                 case CelestialObject.Europa:
    00797                     value = 1.314;
    00798                     break;
    00799
    00800                 case CelestialObject.Ganymede:
    00801                     value = 1.428;
    00802                     break;
    00803
    00804                 case CelestialObject.Callisto:
    00805                     value = 1.235;
    00806                     break;
    00807
    00808                 case CelestialObject.Saturn:
    00809                     value = 11.19;
    00810                     break;
    00811
    00812                 case CelestialObject.Uranus:
    00813                     value = 9.01;
    00814                     break;
    00815
    00816                 case CelestialObject.Neptune:
    00817                     value = 11.28;
    00818                     break;
    00819
    00820                 case CelestialObject.Pluto:
    00821                     value = 0.61;
    00822                     break;
    00823             }
    00824         }
    00825
    00829         private void UnloadModelData()
    00830         {
    00831             this.gfcGrid.UnloadGravityMap();
    00832             this.gfcModel.UnloadGfcModel();
    00833             this.mroModel.UnloadAnomalyMap();
    00834         }
    00835     }
    00836 }