krz/moonrise

Night-sky companion for iPhone, Apple Watch and Vision Pro: what's up tonight, the Moon, planets, launches and missions, and a Library of the solar system. SwiftUI app with a Cloudflare Workers backend. astronomy cloudflare-workers ios night-sky space swiftui visionos watchos

Packages/MoonriseKit/Sources/CAstronomy/include/astronomy.h

1431 lines · 63933 bytes

   1/*
   2    Astronomy Engine for C/C++.
   3    https://github.com/cosinekitty/astronomy
   4
   5    MIT License
   6
   7    Copyright (c) 2019-2023 Don Cross <cosinekitty@gmail.com>
   8
   9    Permission is hereby granted, free of charge, to any person obtaining a copy
  10    of this software and associated documentation files (the "Software"), to deal
  11    in the Software without restriction, including without limitation the rights
  12    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13    copies of the Software, and to permit persons to whom the Software is
  14    furnished to do so, subject to the following conditions:
  15
  16    The above copyright notice and this permission notice shall be included in all
  17    copies or substantial portions of the Software.
  18
  19    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  25    SOFTWARE.
  26*/
  27
  28#ifndef __ASTRONOMY_H
  29#define __ASTRONOMY_H
  30
  31#include <stddef.h>     /* for size_t */
  32
  33#ifdef __cplusplus
  34extern "C" {
  35#endif
  36
  37/*---------- numeric constants ----------*/
  38
  39/**
  40 * \def C_AUDAY
  41 * @brief The speed of light in AU/day.
  42 */
  43#define C_AUDAY     173.1446326846693
  44
  45/**
  46 * \def KM_PER_AU
  47 * @brief The number of kilometers in one astronomical unit (AU).
  48 */
  49#define KM_PER_AU   1.4959787069098932e+8
  50
  51/**
  52 * \def AU_PER_LY
  53 * @brief The number of astronomical units per light-year.
  54 */
  55#define AU_PER_LY   63241.07708807546
  56
  57/**
  58 * \def DEG2RAD
  59 * @brief The factor to convert degrees to radians = pi/180.
  60 */
  61#define DEG2RAD     0.017453292519943296
  62
  63/**
  64 * \def HOUR2RAD
  65 * @brief The factor to convert sidereal hours to radians = pi/12.
  66 */
  67#define HOUR2RAD    0.2617993877991494365
  68
  69/**
  70 * \def RAD2DEG
  71 * @brief The factor to convert radians to degrees = 180/pi.
  72 */
  73#define RAD2DEG     57.295779513082321
  74
  75/**
  76 * \def RAD2HOUR
  77 * @brief The factor to convert radians to sidereal hours = 12/pi.
  78 */
  79#define RAD2HOUR    3.819718634205488
  80
  81/**
  82 * \def SUN_RADIUS_KM
  83 * @brief The mean radius of the Sun's photosphere, expressed in kilometers. The Sun is nearly spherical.
  84 */
  85#define SUN_RADIUS_KM               695700.0
  86
  87/**
  88 * \def MERCURY_EQUATORIAL_RADIUS_KM
  89 * @brief The equatorial radius of Mercury, expressed in kilometers.
  90 */
  91#define MERCURY_EQUATORIAL_RADIUS_KM    2440.5
  92
  93/**
  94 * \def MERCURY_POLAR_RADIUS_KM
  95 * @brief The polar radius of Mercury, expressed in kilometers.
  96 */
  97#define MERCURY_POLAR_RADIUS_KM         2438.3
  98
  99/**
 100 * \def VENUS_RADIUS_KM
 101 * @brief The mean radius of Venus, expressed in kilometers. Venus is nearly spherical.
 102 */
 103#define VENUS_RADIUS_KM     6051.8
 104
 105/**
 106 * \def EARTH_EQUATORIAL_RADIUS_KM
 107 * @brief The equatorial radius of the Earth, expressed in kilometers.
 108 */
 109#define EARTH_EQUATORIAL_RADIUS_KM  6378.1366
 110
 111/**
 112 * \def EARTH_FLATTENING
 113 * @brief The Earth's polar radius divided by its equatorial radius.
 114 */
 115#define EARTH_FLATTENING            0.996647180302104
 116
 117/**
 118 * \def EARTH_POLAR_RADIUS_KM
 119 * @brief The polar radius of the Earth, expressed in kilometers.
 120 */
 121#define EARTH_POLAR_RADIUS_KM       (EARTH_EQUATORIAL_RADIUS_KM * EARTH_FLATTENING)
 122
 123/**
 124 * \def MOON_EQUATORIAL_RADIUS_KM
 125 * @brief The equatorial radius of the Moon, expressed in kilometers.
 126 */
 127#define MOON_EQUATORIAL_RADIUS_KM   1738.1
 128
 129/**
 130 * \def MOON_POLAR_RADIUS_KM
 131 * @brief The polar radius of the Moon, expressed in kilometers.
 132 */
 133#define MOON_POLAR_RADIUS_KM        1736.0
 134
 135/**
 136 * \def MARS_EQUATORIAL_RADIUS_KM
 137 * @brief The equatorial radius of Mars, expressed in kilometers.
 138 */
 139#define MARS_EQUATORIAL_RADIUS_KM   3396.2
 140
 141/**
 142 * \def MARS_POLAR_RADIUS_KM
 143 * @brief The polar radius of Mars, expressed in kilometers.
 144 */
 145#define MARS_POLAR_RADIUS_KM        3376.2
 146
 147/*
 148    Jupiter radius data are nominal values obtained from:
 149    https://www.iau.org/static/resolutions/IAU2015_English.pdf
 150    https://nssdc.gsfc.nasa.gov/planetary/factsheet/jupiterfact.html
 151*/
 152
 153/**
 154 * \def JUPITER_EQUATORIAL_RADIUS_KM
 155 * @brief The equatorial radius of Jupiter, expressed in kilometers.
 156 */
 157#define JUPITER_EQUATORIAL_RADIUS_KM    71492.0
 158
 159/**
 160 * \def JUPITER_POLAR_RADIUS_KM
 161 * @brief The polar radius of Jupiter, expressed in kilometers.
 162 */
 163#define JUPITER_POLAR_RADIUS_KM         66854.0
 164
 165/**
 166 * \def JUPITER_MEAN_RADIUS_KM
 167 * @brief The volumetric mean radius of Jupiter, expressed in kilometers.
 168 */
 169#define JUPITER_MEAN_RADIUS_KM          69911.0
 170
 171/*
 172    The radii of Jupiter's four major moons are obtained from:
 173    https://ssd.jpl.nasa.gov/?sat_phys_par
 174*/
 175
 176/**
 177 * \def IO_RADIUS_KM
 178 * @brief The mean radius of Jupiter's moon Io, expressed in kilometers.
 179 */
 180#define IO_RADIUS_KM            1821.6
 181
 182/**
 183 * \def EUROPA_RADIUS_KM
 184 * @brief The mean radius of Jupiter's moon Europa, expressed in kilometers.
 185 */
 186#define EUROPA_RADIUS_KM        1560.8
 187
 188/**
 189 * \def GANYMEDE_RADIUS_KM
 190 * @brief The mean radius of Jupiter's moon Ganymede, expressed in kilometers.
 191 */
 192#define GANYMEDE_RADIUS_KM      2631.2
 193
 194/**
 195 * \def CALLISTO_RADIUS_KM
 196 * @brief The mean radius of Jupiter's moon Callisto, expressed in kilometers.
 197 */
 198#define CALLISTO_RADIUS_KM      2410.3
 199
 200/**
 201 * \def SATURN_EQUATORIAL_RADIUS_KM
 202 * @brief The equatorial radius of Saturn, expressed in kilometers.
 203 */
 204#define SATURN_EQUATORIAL_RADIUS_KM     60268.0
 205
 206/**
 207 * \def SATURN_POLAR_RADIUS_KM
 208 * @brief The polar radius of Saturn, expressed in kilometers.
 209 */
 210#define SATURN_POLAR_RADIUS_KM          54364.0
 211
 212/**
 213 * \def URANUS_EQUATORIAL_RADIUS_KM
 214 * @brief The equatorial radius of Uranus, expressed in kilometers.
 215 */
 216#define URANUS_EQUATORIAL_RADIUS_KM     25559.0
 217
 218/**
 219 * \def URANUS_POLAR_RADIUS_KM
 220 * @brief The polar radius of Uranus, expressed in kilometers.
 221 */
 222#define URANUS_POLAR_RADIUS_KM          24973.0
 223
 224/**
 225 * \def NEPTUNE_EQUATORIAL_RADIUS_KM
 226 * @brief The equatorial radius of Neptune, expressed in kilometers.
 227 */
 228#define NEPTUNE_EQUATORIAL_RADIUS_KM    24764.0
 229
 230/**
 231 * \def NEPTUNE_POLAR_RADIUS_KM
 232 * @brief The polar radius of Neptune, expressed in kilometers.
 233 */
 234#define NEPTUNE_POLAR_RADIUS_KM         24341.0
 235
 236/**
 237 * \def PLUTO_RADIUS_KM
 238 * @brief The mean radius of Pluto, expressed in kilometers. Pluto is nearly spherical.
 239 */
 240#define PLUTO_RADIUS_KM             1188.3
 241
 242
 243/*---------- types ----------*/
 244
 245/**
 246 * @brief Indicates success/failure of an Astronomy Engine function call.
 247 */
 248typedef enum
 249{
 250    ASTRO_SUCCESS,                  /**< The operation was successful. */
 251    ASTRO_NOT_INITIALIZED,          /**< A placeholder that can be used for data that is not yet initialized. */
 252    ASTRO_INVALID_BODY,             /**< The celestial body was not valid. Different sets of bodies are supported depending on the function. */
 253    ASTRO_NO_CONVERGE,              /**< A numeric solver failed to converge. This should not happen unless there is a bug in Astronomy Engine. */
 254    ASTRO_BAD_TIME,                 /**< The provided date/time is outside the range allowed by this function. */
 255    ASTRO_BAD_VECTOR,               /**< Vector magnitude is too small to be normalized into a unit vector. */
 256    ASTRO_SEARCH_FAILURE,           /**< Search was not able to find an ascending root crossing of the function in the specified time interval. */
 257    ASTRO_EARTH_NOT_ALLOWED,        /**< The Earth cannot be treated as a celestial body seen from an observer on the Earth itself. */
 258    ASTRO_NO_MOON_QUARTER,          /**< No lunar quarter occurs inside the specified time range. */
 259    ASTRO_WRONG_MOON_QUARTER,       /**< Internal error: Astronomy_NextMoonQuarter found the wrong moon quarter. */
 260    ASTRO_INTERNAL_ERROR,           /**< A self-check failed inside the code somewhere, indicating a bug needs to be fixed. */
 261    ASTRO_INVALID_PARAMETER,        /**< A parameter value passed to a function was not valid. */
 262    ASTRO_FAIL_APSIS,               /**< Special-case logic for finding Neptune/Pluto apsis failed. */
 263    ASTRO_BUFFER_TOO_SMALL,         /**< A provided buffer's size is too small to receive the requested data. */
 264    ASTRO_OUT_OF_MEMORY,            /**< An attempt to allocate memory failed. */
 265    ASTRO_INCONSISTENT_TIMES        /**< The provided initial state vectors did not have matching times. */
 266}
 267astro_status_t;
 268
 269/**
 270 * @brief A date and time used for astronomical calculations.
 271 *
 272 * This type is of fundamental importance to Astronomy Engine.
 273 * It is used to represent dates and times for all astronomical calculations.
 274 * It is also included in the values returned by many Astronomy Engine functions.
 275 *
 276 * To create a valid astro_time_t value from scratch, call #Astronomy_MakeTime
 277 * (for a given calendar date and time) or #Astronomy_CurrentTime (for the system's
 278 * current date and time).
 279 *
 280 * To adjust an existing astro_time_t by a certain real number of days,
 281 * call #Astronomy_AddDays.
 282 *
 283 * The astro_time_t type contains `ut` to represent Universal Time (UT1/UTC) and
 284 * `tt` to represent Terrestrial Time (TT, also known as *ephemeris time*).
 285 * The difference `tt-ut` is known as *&Delta;T*, using a best-fit piecewise model devised by
 286 * [Espenak and Meeus](https://eclipse.gsfc.nasa.gov/SEhelp/deltatpoly2004.html).
 287 *
 288 * Both `tt` and `ut` are necessary for performing different astronomical calculations.
 289 * Indeed, certain calculations (such as rise/set times) require both time scales.
 290 * See the documentation for the `ut` and `tt` fields for more detailed information.
 291 *
 292 * In cases where `astro_time_t` is included in a structure returned by
 293 * a function that can fail, the `astro_status_t` field `status` will contain a value
 294 * other than `ASTRO_SUCCESS`; in that case the `ut` and `tt` will hold `NAN` (not a number).
 295 * In general, when there is an error code stored in a struct field `status`, the
 296 * caller should ignore all other values in that structure, including the `ut` and `tt`
 297 * inside `astro_time_t`.
 298 */
 299typedef struct
 300{
 301    /**
 302     * @brief   UT1/UTC number of days since noon on January 1, 2000.
 303     *
 304     * The floating point number of days of Universal Time since noon UTC January 1, 2000.
 305     * Astronomy Engine approximates UTC and UT1 as being the same thing, although they are
 306     * not exactly equivalent; UTC and UT1 can disagree by up to &plusmn;0.9 seconds.
 307     * This approximation is sufficient for the accuracy requirements of Astronomy Engine.
 308     *
 309     * Universal Time Coordinate (UTC) is the international standard for legal and civil
 310     * timekeeping and replaces the older Greenwich Mean Time (GMT) standard.
 311     * UTC is kept in sync with unpredictable observed changes in the Earth's rotation
 312     * by occasionally adding leap seconds as needed.
 313     *
 314     * UT1 is an idealized time scale based on observed rotation of the Earth, which
 315     * gradually slows down in an unpredictable way over time, due to tidal drag by the Moon and Sun,
 316     * large scale weather events like hurricanes, and internal seismic and convection effects.
 317     * Conceptually, UT1 drifts from atomic time continuously and erratically, whereas UTC
 318     * is adjusted by a scheduled whole number of leap seconds as needed.
 319     *
 320     * The value in `ut` is appropriate for any calculation involving the Earth's rotation,
 321     * such as calculating rise/set times, culumination, and anything involving apparent
 322     * sidereal time.
 323     *
 324     * Before the era of atomic timekeeping, days based on the Earth's rotation
 325     * were often known as *mean solar days*.
 326     */
 327    double ut;
 328
 329    /**
 330     * @brief   Terrestrial Time days since noon on January 1, 2000.
 331     *
 332     * Terrestrial Time is an atomic time scale defined as a number of days since noon on January 1, 2000.
 333     * In this system, days are not based on Earth rotations, but instead by
 334     * the number of elapsed [SI seconds](https://physics.nist.gov/cuu/Units/second.html)
 335     * divided by 86400. Unlike `ut`, `tt` increases uniformly without adjustments
 336     * for changes in the Earth's rotation.
 337     *
 338     * The value in `tt` is used for calculations of movements not involving the Earth's rotation,
 339     * such as the orbits of planets around the Sun, or the Moon around the Earth.
 340     *
 341     * Historically, Terrestrial Time has also been known by the term *Ephemeris Time* (ET).
 342     */
 343    double tt;
 344
 345    /**
 346     * @brief   For internal use only. Used to optimize Earth tilt calculations.
 347     */
 348    double psi;
 349
 350    /**
 351     * @brief   For internal use only.  Used to optimize Earth tilt calculations.
 352     */
 353    double eps;
 354
 355    /**
 356     * @brief   For internal use only.  Lazy-caches sidereal time (Earth rotation).
 357     */
 358    double st;
 359}
 360astro_time_t;
 361
 362/**
 363 * @brief A calendar date and time expressed in UTC.
 364 */
 365typedef struct
 366{
 367    int     year;       /**< The year value, e.g. 2019. */
 368    int     month;      /**< The month value: 1=January, 2=February, ..., 12=December. */
 369    int     day;        /**< The day of the month in the range 1..31. */
 370    int     hour;       /**< The hour of the day in the range 0..23. */
 371    int     minute;     /**< The minute of the hour in the range 0..59. */
 372    double  second;     /**< The floating point number of seconds in the range [0,60). */
 373}
 374astro_utc_t;
 375
 376/**
 377 * @brief A 3D Cartesian vector whose components are expressed in Astronomical Units (AU).
 378 */
 379typedef struct
 380{
 381    astro_status_t status;  /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 382    double x;               /**< The Cartesian x-coordinate of the vector in AU. */
 383    double y;               /**< The Cartesian y-coordinate of the vector in AU. */
 384    double z;               /**< The Cartesian z-coordinate of the vector in AU. */
 385    astro_time_t t;         /**< The date and time at which this vector is valid. */
 386}
 387astro_vector_t;
 388
 389/**
 390 * @brief A state vector that contains a position (AU) and velocity (AU/day).
 391 */
 392typedef struct
 393{
 394    astro_status_t status;  /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 395    double x;               /**< The Cartesian position x-coordinate of the vector in AU. */
 396    double y;               /**< The Cartesian position y-coordinate of the vector in AU. */
 397    double z;               /**< The Cartesian position z-coordinate of the vector in AU. */
 398    double vx;              /**< The Cartesian velocity x-coordinate of the vector in AU/day. */
 399    double vy;              /**< The Cartesian velocity y-coordinate of the vector in AU/day. */
 400    double vz;              /**< The Cartesian velocity z-coordinate of the vector in AU/day. */
 401    astro_time_t t;         /**< The date and time at which this state vector is valid. */
 402}
 403astro_state_vector_t;
 404
 405/**
 406 * @brief Spherical coordinates: latitude, longitude, distance.
 407 */
 408typedef struct
 409{
 410    astro_status_t status;  /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 411    double lat;             /**< The latitude angle: -90..+90 degrees. */
 412    double lon;             /**< The longitude angle: 0..360 degrees. */
 413    double dist;            /**< Distance in AU. */
 414}
 415astro_spherical_t;
 416
 417/**
 418 * @brief An angular value expressed in degrees.
 419 */
 420typedef struct
 421{
 422    astro_status_t status;  /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 423    double angle;           /**< An angle expressed in degrees. */
 424}
 425astro_angle_result_t;
 426
 427/**
 428 * @brief A celestial body.
 429 */
 430typedef enum
 431{
 432    BODY_INVALID = -1,      /**< An invalid or undefined celestial body. */
 433    BODY_MERCURY,           /**< Mercury */
 434    BODY_VENUS,             /**< Venus */
 435    BODY_EARTH,             /**< Earth */
 436    BODY_MARS,              /**< Mars */
 437    BODY_JUPITER,           /**< Jupiter */
 438    BODY_SATURN,            /**< Saturn */
 439    BODY_URANUS,            /**< Uranus */
 440    BODY_NEPTUNE,           /**< Neptune */
 441    BODY_PLUTO,             /**< Pluto */
 442    BODY_SUN,               /**< Sun */
 443    BODY_MOON,              /**< Moon */
 444    BODY_EMB,               /**< Earth/Moon Barycenter */
 445    BODY_SSB,               /**< Solar System Barycenter */
 446    BODY_STAR1 = 101,       /**< user-defined star #1 */
 447    BODY_STAR2,             /**< user-defined star #2 */
 448    BODY_STAR3,             /**< user-defined star #3 */
 449    BODY_STAR4,             /**< user-defined star #4 */
 450    BODY_STAR5,             /**< user-defined star #5 */
 451    BODY_STAR6,             /**< user-defined star #6 */
 452    BODY_STAR7,             /**< user-defined star #7 */
 453    BODY_STAR8,             /**< user-defined star #8 */
 454}
 455astro_body_t;
 456
 457/**
 458 * @brief The location of an observer on (or near) the surface of the Earth.
 459 *
 460 * This structure is passed to functions that calculate phenomena as observed
 461 * from a particular place on the Earth.
 462 *
 463 * You can create this structure directly, or you can call the convenience function
 464 * #Astronomy_MakeObserver to create one for you.
 465 */
 466typedef struct
 467{
 468    double latitude;        /**< Geographic latitude in degrees north (positive) or south (negative) of the equator. */
 469    double longitude;       /**< Geographic longitude in degrees east (positive) or west (negative) of the prime meridian at Greenwich, England. */
 470    double height;          /**< The height above (positive) or below (negative) sea level, expressed in meters. */
 471}
 472astro_observer_t;
 473
 474/**
 475 * @brief Equatorial angular and cartesian coordinates.
 476 *
 477 * Coordinates of a celestial body as seen from the Earth (geocentric or topocentric, depending on context),
 478 * oriented with respect to the projection of the Earth's equator onto the sky.
 479 */
 480typedef struct
 481{
 482    astro_status_t status;  /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 483    double ra;              /**< right ascension in sidereal hours. */
 484    double dec;             /**< declination in degrees */
 485    double dist;            /**< distance to the celestial body in AU. */
 486    astro_vector_t vec;     /**< equatorial coordinates in cartesian vector form: x = March equinox, y = June solstice, z = north. */
 487}
 488astro_equatorial_t;
 489
 490/**
 491 * @brief Ecliptic angular and Cartesian coordinates.
 492 *
 493 * Coordinates of a celestial body as seen from the center of the Sun (heliocentric),
 494 * oriented with respect to the plane of the Earth's orbit around the Sun (the ecliptic).
 495 */
 496typedef struct
 497{
 498    astro_status_t status;  /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 499    astro_vector_t vec;     /**< Cartesian ecliptic vector: x=equinox, y=90 degrees prograde in ecliptic plane, z=northward perpendicular to ecliptic. */
 500    double elat;            /**< Latitude in degrees north (positive) or south (negative) of the ecliptic plane. */
 501    double elon;            /**< Longitude in degrees around the ecliptic plane prograde from the equinox. */
 502}
 503astro_ecliptic_t;
 504
 505/**
 506 * @brief Coordinates of a celestial body as seen by a topocentric observer.
 507 *
 508 * Contains horizontal and equatorial coordinates seen by an observer on or near
 509 * the surface of the Earth (a topocentric observer).
 510 * Optionally corrected for atmospheric refraction.
 511 */
 512typedef struct
 513{
 514    double azimuth;     /**< Compass direction around the horizon in degrees. 0=North, 90=East, 180=South, 270=West. */
 515    double altitude;    /**< Angle in degrees above (positive) or below (negative) the observer's horizon. */
 516    double ra;          /**< Right ascension in sidereal hours. */
 517    double dec;         /**< Declination in degrees. */
 518}
 519astro_horizon_t;
 520
 521/**
 522 * @brief Contains a rotation matrix that can be used to transform one coordinate system to another.
 523 */
 524typedef struct
 525{
 526    astro_status_t status;  /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 527    double rot[3][3];       /**< A normalized 3x3 rotation matrix. */
 528}
 529astro_rotation_t;
 530
 531/**
 532 * @brief Selects whether to correct for atmospheric refraction, and if so, how.
 533 */
 534typedef enum
 535{
 536    REFRACTION_NONE,    /**< No atmospheric refraction correction (airless). */
 537    REFRACTION_NORMAL,  /**< Recommended correction for standard atmospheric refraction. */
 538    REFRACTION_JPLHOR   /**< Used only for compatibility testing with JPL Horizons online tool. */
 539}
 540astro_refraction_t;
 541
 542/**
 543 * @brief Information about idealized atmospheric variables at a given elevation.
 544 */
 545typedef struct
 546{
 547    astro_status_t status;  /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 548    double pressure;        /**< Atmospheric pressure in pascals */
 549    double temperature;     /**< Atmospheric temperature in kelvins */
 550    double density;         /**< Atmospheric density relative to sea level */
 551}
 552astro_atmosphere_t;
 553
 554/**
 555 * @brief The result of a search for an astronomical event.
 556 */
 557typedef struct
 558{
 559    astro_status_t  status;     /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 560    astro_time_t    time;       /**< The time at which a searched-for event occurs. */
 561}
 562astro_search_result_t;
 563
 564/**
 565 * @brief
 566 *      The dates and times of changes of season for a given calendar year.
 567 *      Call #Astronomy_Seasons to calculate this data structure for a given year.
 568 */
 569typedef struct
 570{
 571    astro_status_t  status;         /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 572    astro_time_t    mar_equinox;    /**< The date and time of the March equinox for the specified year. */
 573    astro_time_t    jun_solstice;   /**< The date and time of the June soltice for the specified year. */
 574    astro_time_t    sep_equinox;    /**< The date and time of the September equinox for the specified year. */
 575    astro_time_t    dec_solstice;   /**< The date and time of the December solstice for the specified year. */
 576}
 577astro_seasons_t;
 578
 579/**
 580 * @brief A lunar quarter event (new moon, first quarter, full moon, or third quarter) along with its date and time.
 581 */
 582typedef struct
 583{
 584    astro_status_t  status;     /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 585    int             quarter;    /**< 0=new moon, 1=first quarter, 2=full moon, 3=third quarter. */
 586    astro_time_t    time;       /**< The date and time of the lunar quarter. */
 587}
 588astro_moon_quarter_t;
 589
 590/**
 591 * @brief A real value returned by a function whose ascending root is to be found.
 592 *
 593 * When calling #Astronomy_Search, the caller must pass in a callback function
 594 * compatible with the function-pointer type #astro_search_func_t
 595 * whose ascending root is to be found. That callback function must return astro_func_result_t.
 596 * If the function call is successful, it will set `status` to `ASTRO_SUCCESS` and `value`
 597 * to the numeric value appropriate for the given date and time.
 598 * If the call fails for some reason, it should set `status` to an appropriate error value
 599 * other than `ASTRO_SUCCESS`; in the error case, to guard against any possible misuse of `value`,
 600 * it is recommended to set `value` to `NAN`, though this is not strictly necessary.
 601 */
 602typedef struct
 603{
 604    astro_status_t status;      /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 605    double value;               /**< The value returned by a function whose ascending root is to be found. */
 606}
 607astro_func_result_t;
 608
 609/**
 610 * @brief A pointer to a function that is to be passed as a callback to #Astronomy_Search.
 611 *
 612 * The function #Astronomy_Search numerically solves for the time that a given event occurs.
 613 * An event is defined as the time when an arbitrary function transitions between having
 614 * a negative value and a non-negative value. This transition is called an *ascending root*.
 615 *
 616 * The type astro_search_func_t represents such a callback function that accepts a
 617 * custom `context` pointer and an astro_time_t representing the time to probe.
 618 * The function returns an astro_func_result_t that contains either a real
 619 * number in `value` or an error code in `status` that aborts the search.
 620 *
 621 * The `context` points to some data whose type varies depending on the callback function.
 622 * It can contain any auxiliary parameters (other than time) needed to evaluate the function.
 623 * For example, a function may pertain to a specific celestial body, in which case `context`
 624 * may point to a value of type astro_body_t. The `context` parameter is supplied by
 625 * the caller of #Astronomy_Search, which passes it along to every call to the callback function.
 626 * If the caller of `Astronomy_Search` knows that the callback function does not need a context,
 627 * it is safe to pass `NULL` as the context pointer.
 628 */
 629typedef astro_func_result_t (* astro_search_func_t) (void *context, astro_time_t time);
 630
 631/**
 632 * @brief A pointer to a function that calculates Delta T.
 633 *
 634 * Delta T is the discrepancy between times measured using an atomic clock
 635 * and times based on observations of the Earth's rotation, which is gradually
 636 * slowing down over time. Delta T = TT - UT, where
 637 * TT = Terrestrial Time, based on atomic time, and
 638 * UT = Universal Time, civil time based on the Earth's rotation.
 639 * Astronomy Engine defaults to using a Delta T function defined by
 640 * Espenak and Meeus in their "Five Millennium Canon of Solar Eclipses".
 641 * See: https://eclipse.gsfc.nasa.gov/SEhelp/deltatpoly2004.html
 642 */
 643typedef double (* astro_deltat_func) (double ut);
 644
 645double Astronomy_DeltaT_EspenakMeeus(double ut);
 646double Astronomy_DeltaT_JplHorizons(double ut);
 647
 648void Astronomy_SetDeltaTFunction(astro_deltat_func func);
 649
 650/**
 651 * @brief Indicates whether a body (especially Mercury or Venus) is best seen in the morning or evening.
 652 */
 653typedef enum
 654{
 655    VISIBLE_MORNING,    /**< The body is best visible in the morning, before sunrise. */
 656    VISIBLE_EVENING     /**< The body is best visible in the evening, after sunset. */
 657}
 658astro_visibility_t;
 659
 660/**
 661 * @brief
 662 *      Contains information about the visibility of a celestial body at a given date and time.
 663 *      See #Astronomy_Elongation for more detailed information about the members of this structure.
 664 *      See also #Astronomy_SearchMaxElongation for how to search for maximum elongation events.
 665 */
 666typedef struct
 667{
 668    astro_status_t      status;                 /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 669    astro_time_t        time;                   /**< The date and time of the observation. */
 670    astro_visibility_t  visibility;             /**< Whether the body is best seen in the morning or the evening. */
 671    double              elongation;             /**< The angle in degrees between the body and the Sun, as seen from the Earth. */
 672    double              ecliptic_separation;    /**< The difference between the ecliptic longitudes of the body and the Sun, as seen from the Earth. */
 673}
 674astro_elongation_t;
 675
 676/**
 677 * @brief Information about a celestial body crossing a specific hour angle.
 678 *
 679 * Returned by the function #Astronomy_SearchHourAngleEx to report information about
 680 * a celestial body crossing a certain hour angle as seen by a specified topocentric observer.
 681 */
 682typedef struct
 683{
 684    astro_status_t      status;     /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 685    astro_time_t        time;       /**< The date and time when the body crosses the specified hour angle. */
 686    astro_horizon_t     hor;        /**< Apparent coordinates of the body at the time it crosses the specified hour angle. */
 687}
 688astro_hour_angle_t;
 689
 690/**
 691 * @brief Information about the brightness and illuminated shape of a celestial body.
 692 *
 693 * Returned by the functions #Astronomy_Illumination and #Astronomy_SearchPeakMagnitude
 694 * to report the visual magnitude and illuminated fraction of a celestial body at a given date and time.
 695 */
 696typedef struct
 697{
 698    astro_status_t      status;         /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 699    astro_time_t        time;           /**< The date and time of the observation. */
 700    double              mag;            /**< The visual magnitude of the body. Smaller values are brighter. */
 701    double              phase_angle;    /**< The angle in degrees between the Sun and the Earth, as seen from the body. Indicates the body's phase as seen from the Earth. */
 702    double              phase_fraction; /**< A value in the range [0.0, 1.0] indicating what fraction of the body's apparent disc is illuminated, as seen from the Earth. */
 703    double              helio_dist;     /**< The distance between the Sun and the body at the observation time. */
 704    double              ring_tilt;      /**< For Saturn, the tilt angle in degrees of its rings as seen from Earth. For all other bodies, 0. */
 705}
 706astro_illum_t;
 707
 708/**
 709 * @brief The type of apsis: pericenter (closest approach) or apocenter (farthest distance).
 710 */
 711typedef enum
 712{
 713    APSIS_PERICENTER,   /**< The body is at its closest approach to the object it orbits. */
 714    APSIS_APOCENTER,    /**< The body is at its farthest distance from the object it orbits. */
 715    APSIS_INVALID       /**< Undefined or invalid apsis. */
 716}
 717astro_apsis_kind_t;
 718
 719/**
 720 * @brief An apsis event: pericenter (closest approach) or apocenter (farthest distance).
 721 *
 722 * For the Moon orbiting the Earth, or a planet orbiting the Sun, an *apsis* is an
 723 * event where the orbiting body reaches its closest or farthest point from the primary body.
 724 * The closest approach is called *pericenter* and the farthest point is *apocenter*.
 725 *
 726 * More specific terminology is common for particular orbiting bodies.
 727 * The Moon's closest approach to the Earth is called *perigee* and its farthest
 728 * point is called *apogee*. The closest approach of a planet to the Sun is called
 729 * *perihelion* and the furthest point is called *aphelion*.
 730 *
 731 * This data structure is returned by #Astronomy_SearchLunarApsis and #Astronomy_NextLunarApsis
 732 * to iterate through consecutive alternating perigees and apogees.
 733 */
 734typedef struct
 735{
 736    astro_status_t      status;     /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 737    astro_time_t        time;       /**< The date and time of the apsis. */
 738    astro_apsis_kind_t  kind;       /**< Whether this is a pericenter or apocenter event. */
 739    double              dist_au;    /**< The distance between the centers of the bodies in astronomical units. */
 740    double              dist_km;    /**< The distance between the centers of the bodies in kilometers. */
 741}
 742astro_apsis_t;
 743
 744/**
 745 * @brief The different kinds of lunar/solar eclipses.
 746 */
 747typedef enum
 748{
 749    ECLIPSE_NONE,       /**< No eclipse found. */
 750    ECLIPSE_PENUMBRAL,  /**< A penumbral lunar eclipse. (Never used for a solar eclipse.) */
 751    ECLIPSE_PARTIAL,    /**< A partial lunar/solar eclipse. */
 752    ECLIPSE_ANNULAR,    /**< An annular solar eclipse. (Never used for a lunar eclipse.) */
 753    ECLIPSE_TOTAL       /**< A total lunar/solar eclipse. */
 754}
 755astro_eclipse_kind_t;
 756
 757/**
 758 * @brief Information about a lunar eclipse.
 759 *
 760 * Returned by #Astronomy_SearchLunarEclipse or #Astronomy_NextLunarEclipse
 761 * to report information about a lunar eclipse event.
 762 * If a lunar eclipse is found, `status` holds `ASTRO_SUCCESS` and the other fields are set.
 763 * If `status` holds any other value, it is an error code and the other fields are undefined.
 764 *
 765 * When a lunar eclipse is found, it is classified as penumbral, partial, or total.
 766 * Penumbral eclipses are difficult to observe, because the Moon is only slightly dimmed
 767 * by the Earth's penumbra; no part of the Moon touches the Earth's umbra.
 768 * Partial eclipses occur when part, but not all, of the Moon touches the Earth's umbra.
 769 * Total eclipses occur when the entire Moon passes into the Earth's umbra.
 770 *
 771 * The `kind` field thus holds `ECLIPSE_PENUMBRAL`, `ECLIPSE_PARTIAL`, or `ECLIPSE_TOTAL`,
 772 * depending on the kind of lunar eclipse found.
 773 *
 774 * The `obscuration` field holds a value in the range [0, 1] that indicates what fraction
 775 * of the Moon's apparent disc area is covered by the Earth's umbra at the eclipse's peak.
 776 * This indicates how dark the peak eclipse appears. For penumbral eclipses, the obscuration
 777 * is 0, because the Moon does not pass through the Earth's umbra. For partial eclipses,
 778 * the obscuration is somewhere between 0 and 1. For total lunar eclipses, the obscuration is 1.
 779 *
 780 * Field `peak` holds the date and time of the center of the eclipse, when it is at its peak.
 781 *
 782 * Fields `sd_penum`, `sd_partial`, and `sd_total` hold the semi-duration of each phase
 783 * of the eclipse, which is half of the amount of time the eclipse spends in each
 784 * phase (expressed in minutes), or 0 if the eclipse never reaches that phase.
 785 * By converting from minutes to days, and subtracting/adding with `center`, the caller
 786 * may determine the date and time of the beginning/end of each eclipse phase.
 787 */
 788typedef struct
 789{
 790    astro_status_t          status;         /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 791    astro_eclipse_kind_t    kind;           /**< The type of lunar eclipse found. */
 792    double                  obscuration;    /**< The peak fraction of the Moon's apparent disc that is covered by the Earth's umbra. */
 793    astro_time_t            peak;           /**< The time of the eclipse at its peak. */
 794    double                  sd_penum;       /**< The semi-duration of the penumbral phase in minutes. */
 795    double                  sd_partial;     /**< The semi-duration of the partial phase in minutes, or 0.0 if none. */
 796    double                  sd_total;       /**< The semi-duration of the total phase in minutes, or 0.0 if none. */
 797}
 798astro_lunar_eclipse_t;
 799
 800
 801/**
 802 * @brief Reports the time and geographic location of the peak of a solar eclipse.
 803 *
 804 * Returned by #Astronomy_SearchGlobalSolarEclipse or #Astronomy_NextGlobalSolarEclipse
 805 * to report information about a solar eclipse event.
 806 * If a solar eclipse is found, `status` holds `ASTRO_SUCCESS` and `kind`, `peak`, and `distance`
 807 * have valid values. The `latitude` and `longitude` are set only for total and annular eclipses
 808 * (see more below).
 809 * If `status` holds any value other than `ASTRO_SUCCESS`, it is an error code;
 810 * in that case, `kind` holds `ECLIPSE_NONE` and all the other fields are undefined.
 811 *
 812 * The eclipse is classified as partial, annular, or total, depending on the
 813 * maximum amount of the Sun's disc obscured, as seen at the peak location
 814 * on the surface of the Earth.
 815 *
 816 * The `kind` field thus holds `ECLIPSE_PARTIAL`, `ECLIPSE_ANNULAR`, or `ECLIPSE_TOTAL`.
 817 * A total eclipse is when the peak observer sees the Sun completely blocked by the Moon.
 818 * An annular eclipse is like a total eclipse, but the Moon is too far from the Earth's surface
 819 * to completely block the Sun; instead, the Sun takes on a ring-shaped appearance.
 820 * A partial eclipse is when the Moon blocks part of the Sun's disc, but nobody on the Earth
 821 * observes either a total or annular eclipse.
 822 *
 823 * If `kind` is `ECLIPSE_TOTAL` or `ECLIPSE_ANNULAR`, the `latitude` and `longitude`
 824 * fields give the geographic coordinates of the center of the Moon's shadow projected
 825 * onto the daytime side of the Earth at the instant of the eclipse's peak.
 826 * If `kind` has any other value, `latitude` and `longitude` are undefined and should
 827 * not be used.
 828 *
 829 * For total or annular eclipses, the `obscuration` field holds the fraction (0, 1]
 830 * of the Sun's apparent disc area that is blocked from view by the Moon's silhouette,
 831 * as seen by an observer located at the geographic coordinates `latitude`, `longitude`
 832 * at the darkest time `peak`. The value will always be 1 for total eclipses, and less than
 833 * 1 for annular eclipses.
 834 * For partial eclipses, `obscuration` is undefined and should not be used.
 835 * This is because there is little practical use for an obscuration value of
 836 * a partial eclipse without supplying a particular observation location.
 837 * Developers who wish to find an obscuration value for partial solar eclipses should therefore use
 838 * #Astronomy_SearchLocalSolarEclipse and provide the geographic coordinates of an observer.
 839 */
 840typedef struct
 841{
 842    astro_status_t          status;         /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 843    astro_eclipse_kind_t    kind;           /**< The type of solar eclipse found. */
 844    double                  obscuration;    /**< The peak fraction of the Sun's apparent disc area obscured by the Moon (total and annular eclipses only). */
 845    astro_time_t            peak;           /**< The date and time when the solar eclipse is darkest. This is the instant when the axis of the Moon's shadow cone passes closest to the Earth's center. */
 846    double                  distance;       /**< The distance between the Sun/Moon shadow axis and the center of the Earth, in kilometers. */
 847    double                  latitude;       /**< The geographic latitude at the center of the peak eclipse shadow. */
 848    double                  longitude;      /**< The geographic longitude at the center of the peak eclipse shadow. */
 849}
 850astro_global_solar_eclipse_t;
 851
 852
 853/**
 854 * @brief Holds a time and the observed altitude of the Sun at that time.
 855 *
 856 * When reporting a solar eclipse observed at a specific location on the Earth
 857 * (a "local" solar eclipse), a series of events occur. In addition
 858 * to the time of each event, it is important to know the altitude of the Sun,
 859 * because each event may be invisible to the observer if the Sun is below
 860 * the horizon.
 861 *
 862 * If `altitude` is negative, the event is theoretical only; it would be
 863 * visible if the Earth were transparent, but the observer cannot actually see it.
 864 * If `altitude` is positive but less than a few degrees, visibility will be impaired by
 865 * atmospheric interference (sunrise or sunset conditions).
 866 */
 867typedef struct
 868{
 869    astro_time_t    time;       /**< The date and time of the event. */
 870    double          altitude;   /**< The angular altitude of the center of the Sun above/below the horizon, at `time`, corrected for atmospheric refraction and expressed in degrees. */
 871}
 872astro_eclipse_event_t;
 873
 874
 875/**
 876 * @brief Information about a solar eclipse as seen by an observer at a given time and geographic location.
 877 *
 878 * Returned by #Astronomy_SearchLocalSolarEclipse or #Astronomy_NextLocalSolarEclipse
 879 * to report information about a solar eclipse as seen at a given geographic location.
 880 * If a solar eclipse is found, `status` holds `ASTRO_SUCCESS` and the other fields are set.
 881 * If `status` holds any other value, it is an error code and the other fields are undefined.
 882 *
 883 * When a solar eclipse is found, it is classified as partial, annular, or total.
 884 * The `kind` field thus holds `ECLIPSE_PARTIAL`, `ECLIPSE_ANNULAR`, or `ECLIPSE_TOTAL`.
 885 * A partial solar eclipse is when the Moon does not line up directly enough with the Sun
 886 * to completely block the Sun's light from reaching the observer.
 887 * An annular eclipse occurs when the Moon's disc is completely visible against the Sun
 888 * but the Moon is too far away to completely block the Sun's light; this leaves the
 889 * Sun with a ring-like appearance.
 890 * A total eclipse occurs when the Moon is close enough to the Earth and aligned with the
 891 * Sun just right to completely block all sunlight from reaching the observer.
 892 *
 893 * The `obscuration` field reports what fraction of the Sun's disc appears blocked
 894 * by the Moon when viewed by the observer at the peak eclipse time.
 895 * This is a value that ranges from 0 (no blockage) to 1 (total eclipse).
 896 * The obscuration value will be between 0 and 1 for partial eclipses and annular eclipses.
 897 * The value will be exactly 1 for total eclipses. Obscuration gives an indication
 898 * of how dark the eclipse appears.
 899 *
 900 * There are 5 "event" fields, each of which contains a time and a solar altitude.
 901 * Field `peak` holds the date and time of the center of the eclipse, when it is at its peak.
 902 * The fields `partial_begin` and `partial_end` are always set, and indicate when
 903 * the eclipse begins/ends. If the eclipse reaches totality or becomes annular,
 904 * `total_begin` and `total_end` indicate when the total/annular phase begins/ends.
 905 * When an event field is valid, the caller must also check its `altitude` field to
 906 * see whether the Sun is above the horizon at that time. See #astro_eclipse_kind_t
 907 * for more information.
 908 */
 909typedef struct
 910{
 911    astro_status_t          status;         /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 912    astro_eclipse_kind_t    kind;           /**< The type of solar eclipse found: `ECLIPSE_PARTIAL`, `ECLIPSE_ANNULAR`, or `ECLIPSE_TOTAL`. */
 913    double                  obscuration;    /**< The fraction of the Sun's apparent disc area obscured by the Moon at the eclipse peak. */
 914    astro_eclipse_event_t   partial_begin;  /**< The time and Sun altitude at the beginning of the eclipse. */
 915    astro_eclipse_event_t   total_begin;    /**< If this is an annular or a total eclipse, the time and Sun altitude when annular/total phase begins; otherwise invalid. */
 916    astro_eclipse_event_t   peak;           /**< The time and Sun altitude when the eclipse reaches its peak. */
 917    astro_eclipse_event_t   total_end;      /**< If this is an annular or a total eclipse, the time and Sun altitude when annular/total phase ends; otherwise invalid. */
 918    astro_eclipse_event_t   partial_end;    /**< The time and Sun altitude at the end of the eclipse. */
 919}
 920astro_local_solar_eclipse_t;
 921
 922
 923/**
 924 * @brief Information about a transit of Mercury or Venus, as seen from the Earth.
 925 *
 926 * Returned by #Astronomy_SearchTransit or #Astronomy_NextTransit to report
 927 * information about a transit of Mercury or Venus.
 928 * A transit is when Mercury or Venus passes between the Sun and Earth so that
 929 * the other planet is seen in silhouette against the Sun.
 930 *
 931 * The `start` field reports the moment in time when the planet first becomes
 932 * visible against the Sun in its background.
 933 * The `peak` field reports when the planet is most aligned with the Sun,
 934 * as seen from the Earth.
 935 * The `finish` field reports the last moment when the planet is visible
 936 * against the Sun in its background.
 937 *
 938 * The calculations are performed from the point of view of a geocentric observer.
 939 */
 940typedef struct
 941{
 942    astro_status_t  status;         /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
 943    astro_time_t    start;          /**< Date and time at the beginning of the transit. */
 944    astro_time_t    peak;           /**< Date and time of the peak of the transit. */
 945    astro_time_t    finish;         /**< Date and time at the end of the transit. */
 946    double          separation;     /**< Angular separation in arcminutes between the centers of the Sun and the planet at time `peak`. */
 947}
 948astro_transit_t;
 949
 950
 951/**
 952 * @brief   Aberration calculation options.
 953 *
 954 * [Aberration](https://en.wikipedia.org/wiki/Aberration_of_light) is an effect
 955 * causing the apparent direction of an observed body to be shifted due to transverse
 956 * movement of the Earth with respect to the rays of light coming from that body.
 957 * This angular correction can be anywhere from 0 to about 20 arcseconds,
 958 * depending on the position of the observed body relative to the instantaneous
 959 * velocity vector of the Earth.
 960 *
 961 * Some Astronomy Engine functions allow optional correction for aberration by
 962 * passing in a value of this enumerated type.
 963 *
 964 * Aberration correction is useful to improve accuracy of coordinates of
 965 * apparent locations of bodies seen from the Earth.
 966 * However, because aberration affects not only the observed body (such as a planet)
 967 * but the surrounding stars, aberration may be unhelpful (for example)
 968 * for determining exactly when a planet crosses from one constellation to another.
 969 */
 970typedef enum
 971{
 972    ABERRATION,     /**< Request correction for aberration. */
 973    NO_ABERRATION   /**< Do not correct for aberration. */
 974}
 975astro_aberration_t;
 976
 977/**
 978 * @brief   Selects the date for which the Earth's equator is to be used for representing equatorial coordinates.
 979 *
 980 * The Earth's equator is not always in the same plane due to precession and nutation.
 981 *
 982 * Sometimes it is useful to have a fixed plane of reference for equatorial coordinates
 983 * across different calendar dates.  In these cases, a fixed *epoch*, or reference time,
 984 * is helpful. Astronomy Engine provides the J2000 epoch for such cases.  This refers
 985 * to the plane of the Earth's orbit as it was on noon UTC on 1 January 2000.
 986 *
 987 * For some other purposes, it is more helpful to represent coordinates using the Earth's
 988 * equator exactly as it is on that date. For example, when calculating rise/set times
 989 * or horizontal coordinates, it is most accurate to use the orientation of the Earth's
 990 * equator at that same date and time. For these uses, Astronomy Engine allows *of-date*
 991 * calculations.
 992 */
 993typedef enum
 994{
 995    EQUATOR_J2000,      /**< Represent equatorial coordinates in the J2000 epoch. */
 996    EQUATOR_OF_DATE     /**< Represent equatorial coordinates using the Earth's equator at the given date and time. */
 997}
 998astro_equator_date_t;
 999
1000/**
1001 * @brief Selects whether to search for a rise time or a set time.
1002 *
1003 * The #Astronomy_SearchRiseSetEx function finds the rise or set time of a body
1004 * depending on the value of its `direction` parameter.
1005 */
1006typedef enum
1007{
1008    DIRECTION_RISE = +1,    /**< Search for the time a body begins to rise above the horizon. */
1009    DIRECTION_SET  = -1,    /**< Search for the time a body finishes sinking below the horizon. */
1010}
1011astro_direction_t;
1012
1013
1014/**
1015 * @brief Reports the constellation that a given celestial point lies within.
1016 *
1017 * The #Astronomy_Constellation function returns this struct
1018 * to report which constellation corresponds with a given point in the sky.
1019 * Constellations are defined with respect to the B1875 equatorial system
1020 * per IAU standard. Although `Astronomy.Constellation` requires J2000 equatorial
1021 * coordinates, the struct contains converted B1875 coordinates for reference.
1022 */
1023typedef struct
1024{
1025    astro_status_t status;      /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
1026    const char    *symbol;      /**< 3-character mnemonic symbol for the constellation, e.g. "Ori". */
1027    const char    *name;        /**< Full name of constellation, e.g. "Orion". */
1028    double         ra_1875;     /**< Right ascension expressed in B1875 coordinates. */
1029    double         dec_1875;    /**< Declination expressed in B1875 coordinates. */
1030}
1031astro_constellation_t;
1032
1033
1034/**
1035 * @brief Selects the output format of the function #Astronomy_FormatTime.
1036 */
1037typedef enum
1038{
1039    TIME_FORMAT_DAY,    /**< Truncate to UTC calendar date only, e.g. `2020-12-31`. Buffer size must be at least 11 characters. */
1040    TIME_FORMAT_MINUTE, /**< Round to nearest UTC minute, e.g. `2020-12-31T15:47Z`. Buffer size must be at least 18 characters. */
1041    TIME_FORMAT_SECOND, /**< Round to nearest UTC second, e.g. `2020-12-31T15:47:32Z`. Buffer size must be at least 21 characters. */
1042    TIME_FORMAT_MILLI   /**< Round to nearest UTC millisecond, e.g. `2020-12-31T15:47:32.397Z`. Buffer size must be at least 25 characters. */
1043}
1044astro_time_format_t;
1045
1046/**
1047 * @brief Lunar libration angles, returned by #Astronomy_Libration.
1048 */
1049typedef struct
1050{
1051    double elat;                /**< Sub-Earth libration ecliptic latitude angle, in degrees. */
1052    double elon;                /**< Sub-Earth libration ecliptic longitude angle, in degrees. */
1053    double mlat;                /**< Moon's geocentric ecliptic latitude, in degrees. */
1054    double mlon;                /**< Moon's geocentric ecliptic longitude, in degrees. */
1055    double dist_km;             /**< Distance between the centers of the Earth and Moon in kilometers. */
1056    double diam_deg;            /**< The apparent angular diameter of the Moon, in degrees, as seen from the center of the Earth. */
1057}
1058astro_libration_t;
1059
1060/**
1061 * @brief Information about a body's rotation axis at a given time.
1062 *
1063 * This structure is returned by #Astronomy_RotationAxis to report
1064 * the orientation of a body's rotation axis at a given moment in time.
1065 * The axis is specified by the direction in space that the body's north pole
1066 * points, using angular equatorial coordinates in the J2000 system (EQJ).
1067 *
1068 * Thus `ra` is the right ascension, and `dec` is the declination, of the
1069 * body's north pole vector at the given moment in time. The north pole
1070 * of a body is defined as the pole that lies on the north side of the
1071 * [Solar System's invariable plane](https://en.wikipedia.org/wiki/Invariable_plane),
1072 * regardless of the body's direction of rotation.
1073 *
1074 * The `spin` field indicates the angular position of a prime meridian
1075 * arbitrarily recommended for the body by the International Astronomical
1076 * Union (IAU).
1077 *
1078 * The fields `ra`, `dec`, and `spin` correspond to the variables
1079 * α0, δ0, and W, respectively, from
1080 * [Report of the IAU Working Group on Cartographic Coordinates and Rotational Elements: 2015](https://astropedia.astrogeology.usgs.gov/download/Docs/WGCCRE/WGCCRE2015reprint.pdf).
1081 *
1082 * The field `north` is a unit vector pointing in the direction of the body's north pole.
1083 * It is expressed in the equatorial J2000 system (EQJ).
1084 */
1085typedef struct
1086{
1087    astro_status_t  status;     /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
1088    double          ra;         /**< The J2000 right ascension of the body's north pole direction, in sidereal hours. */
1089    double          dec;        /**< The J2000 declination of the body's north pole direction, in degrees. */
1090    double          spin;       /**< Rotation angle of the body's prime meridian, in degrees. */
1091    astro_vector_t  north;      /**< A J2000 dimensionless unit vector pointing in the direction of the body's north pole. */
1092}
1093astro_axis_t;
1094
1095
1096/**
1097 * \def TIME_TEXT_BYTES
1098 * @brief The smallest number of characters that is always large enough for #Astronomy_FormatTime.
1099 */
1100#define TIME_TEXT_BYTES  28
1101
1102/**
1103 * @brief Holds the positions and velocities of Jupiter's major 4 moons.
1104 *
1105 * The #Astronomy_JupiterMoons function returns this struct
1106 * to report position and velocity vectors for Jupiter's largest 4 moons
1107 * Io, Europa, Ganymede, and Callisto. Each position vector is relative
1108 * to the center of Jupiter. Both position and velocity are oriented in
1109 * the EQJ system (that is, using Earth's equator at the J2000 epoch.)
1110 * The positions are expressed in astronomical units (AU),
1111 * and the velocities in AU/day.
1112 */
1113typedef struct
1114{
1115    astro_state_vector_t io;        /**< Jovicentric position and velocity of Io. */
1116    astro_state_vector_t europa;    /**< Jovicentric position and velocity of Europa. */
1117    astro_state_vector_t ganymede;  /**< Jovicentric position and velocity of Ganymede. */
1118    astro_state_vector_t callisto;  /**< Jovicentric position and velocity of Callisto. */
1119}
1120astro_jupiter_moons_t;
1121
1122
1123/**
1124 * @brief  Indicates whether a crossing through the ecliptic plane is ascending or descending.
1125 */
1126typedef enum
1127{
1128    INVALID_NODE    =  0,   /**< Placeholder value for a missing or invalid node. */
1129    ASCENDING_NODE  = +1,   /**< The body passes through the ecliptic plane from south to north. */
1130    DESCENDING_NODE = -1    /**< The body passes through the ecliptic plane from north to south. */
1131}
1132astro_node_kind_t;
1133
1134/**
1135 * @brief Information about an ascending or descending node of a body.
1136 *
1137 * This structure is returned by #Astronomy_SearchMoonNode and #Astronomy_NextMoonNode
1138 * to report information about the center of the Moon passing through the ecliptic plane.
1139 */
1140typedef struct
1141{
1142    astro_status_t      status;     /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
1143    astro_time_t        time;       /**< The time when the body passes through the ecliptic plane. */
1144    astro_node_kind_t   kind;       /**< Either `ASCENDING_NODE` or `DESCENDING_NODE`, depending on the direction of the ecliptic plane crossing. */
1145}
1146astro_node_event_t;
1147
1148
1149/**
1150 * @brief A data type used for managing simulation of the gravitational forces on a small body.
1151 *
1152 * This is an opaque data type used to hold the internal state of
1153 * a numeric integrator used to calculate the trajectory of a small
1154 * body moving through the Solar System.
1155 */
1156typedef struct astro_grav_sim_s astro_grav_sim_t;
1157
1158
1159/*---------- functions ----------*/
1160
1161void Astronomy_Reset(void);
1162double Astronomy_VectorLength(astro_vector_t vector);
1163astro_angle_result_t Astronomy_AngleBetween(astro_vector_t a, astro_vector_t b);
1164const char *Astronomy_BodyName(astro_body_t body);
1165astro_body_t Astronomy_BodyCode(const char *name);
1166astro_observer_t Astronomy_MakeObserver(double latitude, double longitude, double height);
1167#if !defined(ASTRONOMY_ENGINE_NO_CURRENT_TIME)
1168astro_time_t Astronomy_CurrentTime(void);
1169#endif
1170astro_time_t Astronomy_MakeTime(int year, int month, int day, int hour, int minute, double second);
1171astro_time_t Astronomy_TimeFromUtc(astro_utc_t utc);
1172astro_utc_t  Astronomy_UtcFromTime(astro_time_t time);
1173astro_status_t Astronomy_FormatTime(astro_time_t time, astro_time_format_t format, char *text, size_t size);
1174astro_time_t Astronomy_TimeFromDays(double ut);
1175astro_time_t Astronomy_TerrestrialTime(double tt);
1176astro_time_t Astronomy_AddDays(astro_time_t time, double days);
1177double Astronomy_SiderealTime(astro_time_t *time);
1178astro_func_result_t Astronomy_HelioDistance(astro_body_t body, astro_time_t time);
1179astro_vector_t Astronomy_HelioVector(astro_body_t body, astro_time_t time);
1180astro_vector_t Astronomy_GeoVector(astro_body_t body, astro_time_t time, astro_aberration_t aberration);
1181astro_vector_t Astronomy_GeoMoon(astro_time_t time);
1182astro_spherical_t Astronomy_EclipticGeoMoon(astro_time_t time);
1183astro_state_vector_t Astronomy_GeoMoonState(astro_time_t time);
1184astro_state_vector_t Astronomy_GeoEmbState(astro_time_t time);
1185astro_libration_t Astronomy_Libration(astro_time_t time);
1186astro_state_vector_t Astronomy_BaryState(astro_body_t body, astro_time_t time);
1187astro_state_vector_t Astronomy_HelioState(astro_body_t body, astro_time_t time);
1188
1189double Astronomy_MassProduct(astro_body_t body);
1190double Astronomy_PlanetOrbitalPeriod(astro_body_t body);
1191
1192astro_state_vector_t Astronomy_LagrangePoint(
1193    int point,
1194    astro_time_t time,
1195    astro_body_t major_body,
1196    astro_body_t minor_body
1197);
1198
1199astro_state_vector_t Astronomy_LagrangePointFast(
1200    int point,
1201    astro_state_vector_t major_state,
1202    double major_mass,
1203    astro_state_vector_t minor_state,
1204    double minor_mass
1205);
1206
1207astro_jupiter_moons_t Astronomy_JupiterMoons(astro_time_t time);
1208
1209astro_equatorial_t Astronomy_Equator(
1210    astro_body_t body,
1211    astro_time_t *time,
1212    astro_observer_t observer,
1213    astro_equator_date_t equdate,
1214    astro_aberration_t aberration
1215);
1216
1217astro_vector_t Astronomy_ObserverVector(
1218    astro_time_t *time,
1219    astro_observer_t observer,
1220    astro_equator_date_t equdate
1221);
1222
1223astro_state_vector_t Astronomy_ObserverState(
1224    astro_time_t *time,
1225    astro_observer_t observer,
1226    astro_equator_date_t equdate
1227);
1228
1229astro_observer_t Astronomy_VectorObserver(astro_vector_t *vector, astro_equator_date_t equdate);
1230
1231double Astronomy_ObserverGravity(double latitude, double height);
1232
1233astro_ecliptic_t Astronomy_SunPosition(astro_time_t time);
1234astro_ecliptic_t Astronomy_Ecliptic(astro_vector_t eqj);
1235astro_angle_result_t Astronomy_EclipticLongitude(astro_body_t body, astro_time_t time);
1236
1237astro_horizon_t Astronomy_Horizon(
1238    astro_time_t *time,
1239    astro_observer_t observer,
1240    double ra,
1241    double dec,
1242    astro_refraction_t refraction);
1243
1244astro_angle_result_t Astronomy_AngleFromSun(astro_body_t body, astro_time_t time);
1245astro_elongation_t Astronomy_Elongation(astro_body_t body, astro_time_t time);
1246astro_elongation_t Astronomy_SearchMaxElongation(astro_body_t body, astro_time_t startTime);
1247astro_angle_result_t Astronomy_PairLongitude(astro_body_t body1, astro_body_t body2, astro_time_t time);
1248
1249/** @cond DOXYGEN_SKIP */
1250/* Provided for backward compatibility. Newer code can use Astronomy_PairLongitude. */
1251#define Astronomy_LongitudeFromSun(body,time)   (Astronomy_PairLongitude((body), BODY_SUN, (time)))
1252/** @endcond */
1253
1254astro_search_result_t Astronomy_SearchRelativeLongitude(astro_body_t body, double targetRelLon, astro_time_t startTime);
1255astro_angle_result_t Astronomy_MoonPhase(astro_time_t time);
1256astro_search_result_t Astronomy_SearchMoonPhase(double targetLon, astro_time_t startTime, double limitDays);
1257astro_moon_quarter_t Astronomy_SearchMoonQuarter(astro_time_t startTime);
1258astro_moon_quarter_t Astronomy_NextMoonQuarter(astro_moon_quarter_t mq);
1259astro_lunar_eclipse_t Astronomy_SearchLunarEclipse(astro_time_t startTime);
1260astro_lunar_eclipse_t Astronomy_NextLunarEclipse(astro_time_t prevEclipseTime);
1261astro_global_solar_eclipse_t Astronomy_SearchGlobalSolarEclipse(astro_time_t startTime);
1262astro_global_solar_eclipse_t Astronomy_NextGlobalSolarEclipse(astro_time_t prevEclipseTime);
1263astro_local_solar_eclipse_t Astronomy_SearchLocalSolarEclipse(astro_time_t startTime, astro_observer_t observer);
1264astro_local_solar_eclipse_t Astronomy_NextLocalSolarEclipse(astro_time_t prevEclipseTime, astro_observer_t observer);
1265astro_transit_t Astronomy_SearchTransit(astro_body_t body, astro_time_t startTime);
1266astro_transit_t Astronomy_NextTransit(astro_body_t body, astro_time_t prevTransitTime);
1267astro_node_event_t Astronomy_SearchMoonNode(astro_time_t startTime);
1268astro_node_event_t Astronomy_NextMoonNode(astro_node_event_t prevNode);
1269
1270astro_search_result_t Astronomy_Search(
1271    astro_search_func_t func,
1272    void *context,
1273    astro_time_t t1,
1274    astro_time_t t2,
1275    double dt_tolerance_seconds);
1276
1277astro_search_result_t Astronomy_SearchSunLongitude(
1278    double targetLon,
1279    astro_time_t startTime,
1280    double limitDays);
1281
1282astro_hour_angle_t Astronomy_SearchHourAngleEx(
1283    astro_body_t body,
1284    astro_observer_t observer,
1285    double hourAngle,
1286    astro_time_t startTime,
1287    int direction);
1288
1289astro_func_result_t Astronomy_HourAngle(
1290    astro_body_t body,
1291    astro_time_t *time,
1292    astro_observer_t observer);
1293
1294/** @cond DOXYGEN_SKIP */
1295
1296/* The following are provided for backward compatibility. */
1297#define Astronomy_SearchHourAngle(body,observer,hourAngle,startTime)    \
1298    Astronomy_SearchHourAngleEx((body), (observer), (hourAngle), (startTime), +1)
1299
1300#define Astronomy_SearchRiseSet(body,observer,direction,startTime,limitDays) \
1301    Astronomy_SearchRiseSetEx((body), (observer), (direction), (startTime), (limitDays), 0.0)
1302
1303/** @endcond */
1304
1305astro_search_result_t Astronomy_SearchRiseSetEx(
1306    astro_body_t body,
1307    astro_observer_t observer,
1308    astro_direction_t direction,
1309    astro_time_t startTime,
1310    double limitDays,
1311    double metersAboveGround);
1312
1313astro_search_result_t Astronomy_SearchAltitude(
1314    astro_body_t body,
1315    astro_observer_t observer,
1316    astro_direction_t direction,
1317    astro_time_t startTime,
1318    double limitDays,
1319    double altitude);
1320
1321astro_atmosphere_t Astronomy_Atmosphere(double elevationMeters);
1322
1323astro_axis_t Astronomy_RotationAxis(astro_body_t body, astro_time_t *time);
1324
1325astro_seasons_t Astronomy_Seasons(int year);
1326astro_illum_t Astronomy_Illumination(astro_body_t body, astro_time_t time);
1327astro_illum_t Astronomy_SearchPeakMagnitude(astro_body_t body, astro_time_t startTime);
1328astro_apsis_t Astronomy_SearchLunarApsis(astro_time_t startTime);
1329astro_apsis_t Astronomy_NextLunarApsis(astro_apsis_t apsis);
1330astro_apsis_t Astronomy_SearchPlanetApsis(astro_body_t body, astro_time_t startTime);
1331astro_apsis_t Astronomy_NextPlanetApsis(astro_body_t body, astro_apsis_t apsis);
1332
1333astro_rotation_t Astronomy_IdentityMatrix(void);
1334astro_rotation_t Astronomy_InverseRotation(astro_rotation_t rotation);
1335astro_rotation_t Astronomy_CombineRotation(astro_rotation_t a, astro_rotation_t b);
1336astro_rotation_t Astronomy_Pivot(astro_rotation_t rotation, int axis, double angle);
1337astro_vector_t Astronomy_VectorFromSphere(astro_spherical_t sphere, astro_time_t time);
1338astro_spherical_t Astronomy_SphereFromVector(astro_vector_t vector);
1339astro_equatorial_t Astronomy_EquatorFromVector(astro_vector_t vector);
1340astro_vector_t Astronomy_VectorFromHorizon(astro_spherical_t sphere, astro_time_t time, astro_refraction_t refraction);
1341astro_spherical_t Astronomy_HorizonFromVector(astro_vector_t vector, astro_refraction_t refraction);
1342astro_vector_t Astronomy_RotateVector(astro_rotation_t rotation, astro_vector_t vector);
1343astro_state_vector_t Astronomy_RotateState(astro_rotation_t rotation, astro_state_vector_t state);
1344
1345astro_rotation_t Astronomy_Rotation_EQD_EQJ(astro_time_t *time);
1346astro_rotation_t Astronomy_Rotation_EQD_ECL(astro_time_t *time);
1347astro_rotation_t Astronomy_Rotation_EQD_ECT(astro_time_t *time);
1348astro_rotation_t Astronomy_Rotation_EQD_HOR(astro_time_t *time, astro_observer_t observer);
1349astro_rotation_t Astronomy_Rotation_EQJ_EQD(astro_time_t *time);
1350astro_rotation_t Astronomy_Rotation_EQJ_ECT(astro_time_t *time);
1351astro_rotation_t Astronomy_Rotation_EQJ_ECL(void);
1352astro_rotation_t Astronomy_Rotation_EQJ_HOR(astro_time_t *time, astro_observer_t observer);
1353astro_rotation_t Astronomy_Rotation_ECL_EQD(astro_time_t *time);
1354astro_rotation_t Astronomy_Rotation_ECL_EQJ(void);
1355astro_rotation_t Astronomy_Rotation_ECL_HOR(astro_time_t *time, astro_observer_t observer);
1356astro_rotation_t Astronomy_Rotation_ECT_EQJ(astro_time_t *time);
1357astro_rotation_t Astronomy_Rotation_ECT_EQD(astro_time_t *time);
1358astro_rotation_t Astronomy_Rotation_HOR_EQD(astro_time_t *time, astro_observer_t observer);
1359astro_rotation_t Astronomy_Rotation_HOR_EQJ(astro_time_t *time, astro_observer_t observer);
1360astro_rotation_t Astronomy_Rotation_HOR_ECL(astro_time_t *time, astro_observer_t observer);
1361astro_rotation_t Astronomy_Rotation_EQJ_GAL(void);
1362astro_rotation_t Astronomy_Rotation_GAL_EQJ(void);
1363
1364double Astronomy_Refraction(astro_refraction_t refraction, double altitude);
1365double Astronomy_InverseRefraction(astro_refraction_t refraction, double bent_altitude);
1366
1367astro_constellation_t Astronomy_Constellation(double ra, double dec);
1368
1369astro_status_t Astronomy_GravSimInit(
1370    astro_grav_sim_t **simOut,
1371    astro_body_t originBody,
1372    astro_time_t time,
1373    int numBodies,
1374    const astro_state_vector_t *bodyStateArray
1375);
1376
1377astro_status_t Astronomy_GravSimUpdate(
1378    astro_grav_sim_t *sim,
1379    astro_time_t time,
1380    int numBodies,
1381    astro_state_vector_t *bodyStateArray
1382);
1383
1384astro_state_vector_t Astronomy_GravSimBodyState(
1385    astro_grav_sim_t *sim,
1386    astro_body_t body
1387);
1388
1389astro_time_t Astronomy_GravSimTime(const astro_grav_sim_t *sim);
1390int Astronomy_GravSimNumBodies(const astro_grav_sim_t *sim);
1391astro_body_t Astronomy_GravSimOrigin(const astro_grav_sim_t *sim);
1392void Astronomy_GravSimSwap(astro_grav_sim_t *sim);
1393void Astronomy_GravSimFree(astro_grav_sim_t *sim);
1394
1395/**
1396 * @brief A function for which to solve a light-travel time problem.
1397 *
1398 * The function #Astronomy_CorrectLightTravel solves a generalized
1399 * problem of deducing how far in the past light must have left
1400 * a target object to be seen by an observer at a specified time.
1401 * This function pointer type expresses an arbitrary position vector
1402 * as function of time. Such a function must be passed to
1403 * `Astronomy_CorrectLightTravel`.
1404 */
1405typedef astro_vector_t (* astro_position_func_t) (void *context, astro_time_t time);
1406
1407astro_vector_t Astronomy_CorrectLightTravel(
1408    void *context,
1409    astro_position_func_t func,
1410    astro_time_t time
1411);
1412
1413astro_vector_t Astronomy_BackdatePosition(
1414    astro_time_t time,
1415    astro_body_t observerBody,
1416    astro_body_t targetBody,
1417    astro_aberration_t aberration
1418);
1419
1420astro_status_t Astronomy_DefineStar(
1421    astro_body_t body,
1422    double ra,
1423    double dec,
1424    double distanceLightYears
1425);
1426
1427#ifdef __cplusplus
1428}
1429#endif
1430
1431#endif  /* ifndef __ASTRONOMY_H */