💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

200 lines
5.5 KiB

  1. /*
  2. * Copyright (C) 2020 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "celestial-mechanics.hpp"
  20. #include "math/angles.hpp"
  21. #include <cmath>
  22. namespace ast
  23. {
  24. double approx_ecliptic_obliquity(double jd)
  25. {
  26. return math::radians<double>(23.4393 - 3.563e-7 * (jd - 2451545.0));
  27. }
  28. double3 approx_sun_ecliptic(double jd)
  29. {
  30. const double t = (jd - 2451545.0) / 36525.0;
  31. const double m = 6.24 + 628.302 * t;
  32. const double longitude = 4.895048 + 628.331951 * t + (0.033417 - 0.000084 * t) * std::sin(m) + 0.000351 * std::sin(m * 2.0);
  33. const double latitude = 0.0;
  34. const double distance = 1.000140 - (0.016708 - 0.000042 * t) * std::cos(m) - 0.000141 * std::cos(m * 2.0);
  35. double3 ecliptic;
  36. ecliptic.x = distance * std::cos(longitude) * std::cos(latitude);
  37. ecliptic.y = distance * std::sin(longitude) * std::cos(latitude);
  38. ecliptic.z = distance * std::sin(latitude);
  39. return ecliptic;
  40. }
  41. double3 approx_moon_ecliptic(double jd)
  42. {
  43. const double t = (jd - 2451545.0) / 36525.0;
  44. const double l1 = 3.8104 + 8399.7091 * t;
  45. const double m1 = 2.3554 + 8328.6911 * t;
  46. const double m = 6.2300 + 628.3019 * t;
  47. const double d = 5.1985 + 7771.3772 * t;
  48. const double d2 = d * 2.0;
  49. const double f = 1.6280 + 8433.4663 * t;
  50. const double longitude = l1
  51. + 0.1098 * std::sin(m1)
  52. + 0.0222 * std::sin(d2 - m1)
  53. + 0.0115 * std::sin(d2)
  54. + 0.0037 * std::sin(m1 * 2.0)
  55. - 0.0032 * std::sin(m)
  56. - 0.0020 * std::sin(d2)
  57. + 0.0010 * std::sin(d2 - m1 * 2.0)
  58. + 0.0010 * std::sin(d2 - m - m1)
  59. + 0.0009 * std::sin(d2 + m1)
  60. + 0.0008 * std::sin(d2 - m)
  61. + 0.0007 * std::sin(m1 - m)
  62. - 0.0006 * std::sin(d)
  63. - 0.0005 * std::sin(m + m1);
  64. const double latitude = 0.0895 * sin(f)
  65. + 0.0049 * std::sin(m1 + f)
  66. + 0.0048 * std::sin(m1 - f)
  67. + 0.0030 * std::sin(d2 - f)
  68. + 0.0010 * std::sin(d2 + f - m1)
  69. + 0.0008 * std::sin(d2 - f - m1)
  70. + 0.0006 * std::sin(d2 + f);
  71. const double r = 1.0 / (0.016593
  72. + 0.000904 * std::cos(m1)
  73. + 0.000166 * std::cos(d2 - m1)
  74. + 0.000137 * std::cos(d2)
  75. + 0.000049 * std::cos(m1 * 2.0)
  76. + 0.000015 * std::cos(d2 + m1)
  77. + 0.000009 * std::cos(d2 - m));
  78. double3 ecliptic;
  79. ecliptic.x = r * std::cos(longitude) * std::cos(latitude);
  80. ecliptic.y = r * std::sin(longitude) * std::cos(latitude);
  81. ecliptic.z = r * std::sin(latitude);
  82. return ecliptic;
  83. }
  84. double3x3 approx_moon_ecliptic_rotation(double jd)
  85. {
  86. const double t = (jd - 2451545.0) / 36525.0;
  87. const double l1 = 3.8104 + 8399.7091 * t;
  88. const double f = 1.6280 + 8433.4663 * t;
  89. const double az0 = f + math::pi<double>;
  90. const double ax = 0.026920;
  91. const double az1 = l1 - f;
  92. double3x3 rz0 =
  93. {
  94. cos(az0), -sin(az0), 0,
  95. sin(az0), cos(az0), 0,
  96. 0, 0, 1
  97. };
  98. double3x3 rx =
  99. {
  100. 1, 0, 0,
  101. 0, cos(ax), -sin(ax),
  102. 0, sin(ax), cos(ax)
  103. };
  104. double3x3 rz1 =
  105. {
  106. cos(az1), -sin(az1), 0,
  107. sin(az1), cos(az1), 0,
  108. 0, 0, 1
  109. };
  110. return rz0 * rx * rz1;
  111. }
  112. double3 solve_kepler(const kepler_orbit& orbit, double t)
  113. {
  114. // Orbital period (Kepler's third law)
  115. double pr = std::sqrt(orbit.a * orbit.a * orbit.a);
  116. // Mean anomaly
  117. double epoch = 0.0;
  118. double ma = (math::two_pi<double> * (t - epoch)) / pr;
  119. // Semi-minor axis
  120. const double b = std::sqrt(1.0 - orbit.ec * orbit.ec);
  121. // Trig of orbital elements (can be precalculated?)
  122. const double cos_ma = std::cos(ma);
  123. const double sin_ma = std::sin(ma);
  124. const double cos_om = std::cos(orbit.om);
  125. const double sin_om = std::sin(orbit.om);
  126. const double cos_i = std::cos(orbit.i);
  127. const double sin_i = std::sin(orbit.i);
  128. // Eccentric anomaly
  129. double ea = ma + orbit.ec * sin_ma * (1.0 + orbit.ec * cos_ma);
  130. // Find radial distance (r) and true anomaly (v)
  131. double x = orbit.a * (std::cos(ea) - orbit.ec);
  132. double y = b * std::sin(ea);
  133. double r = std::sqrt(x * x + y * y);
  134. double v = std::atan2(y, x);
  135. // Convert (r, v) to ecliptic rectangular coordinates
  136. double cos_wv = std::cos(orbit.w + v);
  137. double sin_wv = std::sin(orbit.w + v);
  138. return double3
  139. {
  140. r * (cos_om * cos_wv - sin_om * sin_wv * cos_i),
  141. r * (sin_om * cos_wv + cos_om * sin_wv * cos_i),
  142. r * sin_wv * sin_i
  143. };
  144. }
  145. double3 solve_kepler(double a, double ec, double w, double ma, double i, double om)
  146. {
  147. // Semi-minor axis
  148. double b = std::sqrt(1.0 - ec * ec);
  149. // Eccentric anomaly
  150. double ea = ma + ec * std::sin(ma) * (1.0 + ec * std::cos(ma));
  151. // Find radial distance (r) and true anomaly (v)
  152. double x = a * (std::cos(ea) - ec);
  153. double y = b * std::sin(ea);
  154. double r = std::sqrt(x * x + y * y);
  155. double v = std::atan2(y, x);
  156. // Convert (r, v) to ecliptic rectangular coordinates
  157. double cos_om = std::cos(om);
  158. double sin_om = std::sin(om);
  159. double cos_i = std::cos(i);
  160. double cos_wv = std::cos(w + v);
  161. double sin_wv = std::sin(w + v);
  162. return double3
  163. {
  164. r * (cos_om * cos_wv - sin_om * sin_wv * cos_i),
  165. r * (sin_om * cos_wv + cos_om * sin_wv * cos_i),
  166. r * sin_wv * std::sin(i)
  167. };
  168. }
  169. } // namespace ast