00001
00002
00003
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
00300 this.simulatedBody = CelestialObject.Earth;
00301
00302
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
00338 this.simulatedBody = CelestialObject.Mars;
00339
00340
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
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
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
00500 this.wgsModel = new GravityEarthWgsModel();
00501 this.grsModel = new GravityEarthGrsModel();
00502 this.gfcGrid = new GravityEarthGfcGrid();
00503 this.gfcModel = new GravityEarthGfcModel();
00504
00505
00506 this.mroModel = new GravityMarsMroModel();
00507
00508
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
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
00684 bool facApplicable = false;
00685
00686
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
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
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
00755 value += (2.0 * Math.PI * G * StandardBouguerDensity * this.groundElevation);
00756 }
00757 else if (earthGravityAnomaly == EarthGravityAnomaly.BouguerSpherical)
00758 {
00759
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
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 }