diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..8b81670 --- /dev/null +++ b/.clang-format @@ -0,0 +1,10 @@ +--- +BasedOnStyle: LLVM +IndentWidth: 4 +ContinuationIndentWidth: 4 +ColumnLimit: 0 +PointerAlignment: Left +ReferenceAlignment: Left +AlignConsecutiveAssignments: Consecutive +AlignConsecutiveDeclarations: Consecutive +... diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 88cad5c..7e567cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,8 +10,69 @@ concurrency: permissions: contents: read + checks: write + pull-requests: write jobs: + lint-cpp: + name: C++ Lint (clang-format + clang-tidy) + runs-on: ubuntu-22.04 + env: + CARGO_TERM_COLOR: always + steps: + - name: Checkout (with submodules) + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + + - name: Install system dependencies + shell: bash + run: | + set -euo pipefail + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + cmake \ + ninja-build \ + clang-format \ + clang-tidy + + - name: Set up Rust (stable) + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: stable + + - name: Configure (CMake, compile commands) + shell: bash + run: | + set -euo pipefail + cmake -S . -B build -G Ninja -DSIDERUST_BUILD_DOCS=OFF -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + + - name: clang-format check + shell: bash + run: | + set -euo pipefail + mapfile -t files < <(git ls-files '*.hpp' '*.cpp') + if [ ${#files[@]} -eq 0 ]; then + echo "No C++ files found." + exit 0 + fi + clang-format --dry-run --Werror "${files[@]}" + + - name: clang-tidy check + shell: bash + run: | + set -euo pipefail + mapfile -t cpp_files < <(git ls-files '*.cpp') + if [ ${#cpp_files[@]} -eq 0 ]; then + echo "No C++ source files found." + exit 0 + fi + for file in "${cpp_files[@]}"; do + echo "Running clang-tidy on ${file}" + clang-tidy -p build --warnings-as-errors='*' "${file}" + done + build-test-docs: name: Build + Test + Docs runs-on: ubuntu-22.04 @@ -90,3 +151,114 @@ jobs: run: | set -euo pipefail cmake --build build --target docs + + coverage: + name: Test & Coverage + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.draft == false }} + runs-on: ubuntu-22.04 + env: + CARGO_TERM_COLOR: always + steps: + - name: Checkout (with submodules) + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + + - name: Install system dependencies + shell: bash + run: | + set -euo pipefail + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + build-essential \ + cmake \ + ninja-build \ + pkg-config \ + libssl-dev \ + gcovr + + - name: Set up Rust (stable) + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: stable + + - name: Configure (CMake, coverage) + shell: bash + run: | + set -euo pipefail + cmake -S . -B build-coverage -G Ninja \ + -DSIDERUST_BUILD_DOCS=OFF \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_CXX_FLAGS="--coverage" \ + -DCMAKE_EXE_LINKER_FLAGS="--coverage" + + - name: Build tests + shell: bash + run: | + set -euo pipefail + cmake --build build-coverage --target test_siderust + + - name: Run tests + shell: bash + run: | + set -euo pipefail + ctest --test-dir build-coverage --output-on-failure -L siderust_cpp + + - name: Coverage (Cobertura XML) + shell: bash + run: | + set -euo pipefail + gcovr \ + --root . \ + --exclude 'build-coverage/.*' \ + --exclude 'siderust/.*' \ + --exclude 'qtty-cpp/.*' \ + --exclude 'tempoch-cpp/.*' \ + --exclude 'tests/.*' \ + --exclude 'examples/.*' \ + --xml \ + --output coverage.xml + + - name: Coverage (HTML) + shell: bash + run: | + set -euo pipefail + mkdir -p coverage_html + gcovr \ + --root . \ + --exclude 'build-coverage/.*' \ + --exclude 'siderust/.*' \ + --exclude 'qtty-cpp/.*' \ + --exclude 'tempoch-cpp/.*' \ + --exclude 'tests/.*' \ + --exclude 'examples/.*' \ + --html-details \ + --output coverage_html/index.html + + - name: Build coverage summary (Markdown) + uses: irongut/CodeCoverageSummary@v1.3.0 + with: + filename: coverage.xml + badge: true + format: markdown + output: file + + - name: Publish to Job Summary + shell: bash + run: cat code-coverage-results.md >> "$GITHUB_STEP_SUMMARY" + + - name: Post coverage as PR comment + if: github.event_name == 'pull_request' + uses: mshick/add-pr-comment@v2 + with: + message-path: code-coverage-results.md + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload coverage HTML + if: always() + uses: actions/upload-artifact@v4 + with: + name: coverage-html + path: coverage_html + retention-days: 7 diff --git a/examples/altitude_events_example.cpp b/examples/altitude_events_example.cpp index 10ae4ee..f167b9a 100644 --- a/examples/altitude_events_example.cpp +++ b/examples/altitude_events_example.cpp @@ -1,6 +1,7 @@ /** * @file altitude_events_example.cpp - * @brief Altitude windows, crossings, and culminations for Sun, Moon, and stars. + * @brief Altitude windows, crossings, and culminations for Sun, Moon, and + * stars. * * Usage: * cmake --build build-make --target altitude_events_example @@ -24,14 +25,15 @@ static const char* culmination_kind_name(CulminationKind k) { } static void print_utc(const UTC& utc) { - std::printf("%04d-%02u-%02u %02u:%02u:%02u", - utc.year, utc.month, utc.day, + std::printf("%04d-%02u-%02u %02u:%02u:%02u", utc.year, utc.month, utc.day, utc.hour, utc.minute, utc.second); } -static void print_periods(const char* title, const std::vector& periods, std::size_t max_items = 4) { +static void print_periods(const char* title, const std::vector& periods, + std::size_t max_items = 4) { std::printf("%s: %zu period(s)\n", title, periods.size()); - const std::size_t n = (periods.size() < max_items) ? periods.size() : max_items; + const std::size_t n = + (periods.size() < max_items) ? periods.size() : max_items; for (std::size_t i = 0; i < n; ++i) { const auto s = periods[i].start().to_utc(); const auto e = periods[i].end().to_utc(); @@ -46,7 +48,9 @@ static void print_periods(const char* title, const std::vector& periods, } } -static void print_crossings(const char* title, const std::vector& events, std::size_t max_items = 6) { +static void print_crossings(const char* title, + const std::vector& events, + std::size_t max_items = 6) { std::printf("%s: %zu event(s)\n", title, events.size()); const std::size_t n = (events.size() < max_items) ? events.size() : max_items; for (std::size_t i = 0; i < n; ++i) { @@ -60,15 +64,16 @@ static void print_crossings(const char* title, const std::vector& } } -static void print_culminations(const char* title, const std::vector& events, std::size_t max_items = 6) { +static void print_culminations(const char* title, + const std::vector& events, + std::size_t max_items = 6) { std::printf("%s: %zu event(s)\n", title, events.size()); const std::size_t n = (events.size() < max_items) ? events.size() : max_items; for (std::size_t i = 0; i < n; ++i) { const auto t = events[i].time.to_utc(); std::printf(" %zu) ", i + 1); print_utc(t); - std::printf(" alt=%.3f deg kind=%s\n", - events[i].altitude.value(), + std::printf(" alt=%.3f deg kind=%s\n", events[i].altitude.value(), culmination_kind_name(events[i].kind)); } if (events.size() > n) { @@ -79,9 +84,9 @@ static void print_culminations(const char* title, const std::vector(); + auto ecef_m = obs.to_cartesian(); auto ecef_km = obs.to_cartesian(); std::printf("Observer (ECEF): x=%.2f m y=%.2f m z=%.2f m\n", ecef_m.x().value(), ecef_m.y().value(), ecef_m.z().value()); @@ -34,11 +34,11 @@ int main() { // Vega J2000 ICRS direction. spherical::direction::ICRS vega_icrs(279.23473, 38.78369); - auto vega_ecl = vega_icrs.to(jd); + auto vega_ecl = vega_icrs.to(jd); auto vega_eq_mod = vega_icrs.to(jd); auto vega_eq_tod = vega_icrs.to(jd); - auto vega_hor = vega_icrs.to_horizontal(jd, obs); - auto vega_back = vega_ecl.to(jd); + auto vega_hor = vega_icrs.to_horizontal(jd, obs); + auto vega_back = vega_ecl.to(jd); std::printf("Vega ICRS: RA=%.6f Dec=%.6f\n", vega_icrs.ra().value(), vega_icrs.dec().value()); @@ -54,8 +54,7 @@ int main() { vega_back.ra().value(), vega_back.dec().value()); spherical::position::ICRS target_sph_au( - 120.0_deg, -25.0_deg, 2.0_au - ); + 120.0_deg, -25.0_deg, 2.0_au); auto target_dir = target_sph_au.direction(); std::printf("Spherical ICRS position: RA=%.2f Dec=%.2f dist=%.3f AU\n", target_sph_au.ra().value(), @@ -64,12 +63,11 @@ int main() { std::printf("Direction extracted from spherical position: RA=%.2f Dec=%.2f\n\n", target_dir.ra().value(), target_dir.dec().value()); - cartesian::position::ICRS target_cart_m(1.5e11, -3.0e10, 2.0e10); + cartesian::position::ICRS target_cart_m(1.5e11, -3.0e10, 2.0e10); cartesian::position::ICRS target_cart_au( target_cart_m.x().to(), target_cart_m.y().to(), - target_cart_m.z().to() - ); + target_cart_m.z().to()); std::printf("Cartesian ICRS position: x=%.3e m y=%.3e m z=%.3e m\n", target_cart_m.x().value(), diff --git a/examples/coordinates_examples.cpp b/examples/coordinates_examples.cpp index c2de469..809d4f4 100644 --- a/examples/coordinates_examples.cpp +++ b/examples/coordinates_examples.cpp @@ -18,8 +18,8 @@ static void geodetic_and_ecef_example() { std::printf("1) Geodetic -> ECEF cartesian\n"); Geodetic obs(-17.8890, 28.7610, 2396.0); - auto ecef = obs.to_cartesian(); - auto ecef_km = obs.to_cartesian(); + auto ecef = obs.to_cartesian(); + auto ecef_km = obs.to_cartesian(); std::printf(" Geodetic lon=%.4f deg lat=%.4f deg h=%.1f m\n", obs.lon.value(), obs.lat.value(), obs.height.value()); @@ -33,11 +33,11 @@ static void spherical_direction_example() { std::printf("2) Spherical direction frame conversions\n"); spherical::direction::ICRS vega_icrs(279.23473, 38.78369); - auto jd = JulianDate::from_utc({2026, 7, 15, 22, 0, 0}); + auto jd = JulianDate::from_utc({2026, 7, 15, 22, 0, 0}); - auto ecl = vega_icrs.to(jd); + auto ecl = vega_icrs.to(jd); auto eq_mod = vega_icrs.to(jd); - auto hor = vega_icrs.to_horizontal(jd, ROQUE_DE_LOS_MUCHACHOS); + auto hor = vega_icrs.to_horizontal(jd, ROQUE_DE_LOS_MUCHACHOS); std::printf(" ICRS RA=%.5f Dec=%.5f\n", vega_icrs.ra().value(), vega_icrs.dec().value()); std::printf(" Ecliptic lon=%.5f lat=%.5f\n", ecl.lon().value(), ecl.lat().value()); @@ -49,8 +49,7 @@ static void spherical_position_example() { std::printf("3) Spherical position + extracting direction\n"); spherical::position::ICRS target( - 120.0_deg, -25.0_deg, 2.0e17_m - ); + 120.0_deg, -25.0_deg, 2.0e17_m); auto dir = target.direction(); std::printf(" Position RA=%.2f Dec=%.2f dist=%.3e m\n", @@ -62,7 +61,7 @@ static void spherical_position_example() { static void cartesian_and_units_example() { std::printf("4) Cartesian coordinate creation + unit conversion\n"); - cartesian::Direction axis_x(1.0, 0.0, 0.0); + cartesian::Direction axis_x(1.0, 0.0, 0.0); cartesian::position::EclipticMeanJ2000 sample_helio_au(1.0, 0.25, -0.1); auto x_km = sample_helio_au.x().to(); @@ -77,9 +76,9 @@ static void cartesian_and_units_example() { static void ephemeris_typed_example() { std::printf("5) Typed ephemeris coordinates\n"); - auto jd = JulianDate::J2000(); - auto earth = ephemeris::earth_heliocentric(jd); // cartesian::position::EclipticMeanJ2000 - auto moon = ephemeris::moon_geocentric(jd); // cartesian::position::MoonGeocentric + auto jd = JulianDate::J2000(); + auto earth = ephemeris::earth_heliocentric(jd); // cartesian::position::EclipticMeanJ2000 + auto moon = ephemeris::moon_geocentric(jd); // cartesian::position::MoonGeocentric std::printf(" Earth heliocentric (AU) x=%.8f y=%.8f z=%.8f\n", earth.x().value(), earth.y().value(), earth.z().value()); diff --git a/examples/demo.cpp b/examples/demo.cpp index 320b16c..8785b11 100644 --- a/examples/demo.cpp +++ b/examples/demo.cpp @@ -6,9 +6,9 @@ * cd build && cmake .. && cmake --build . && ./demo */ -#include #include #include +#include int main() { using namespace siderust; @@ -97,7 +97,7 @@ int main() { auto moon = ephemeris::moon_geocentric(jd); std::printf("Moon geocentric (typed km): (%.2f, %.2f, %.2f)\n", moon.x().value(), moon.y().value(), moon.z().value()); - auto moon_r = std::sqrt(moon.x().value()*moon.x().value() + moon.y().value()*moon.y().value() + moon.z().value()*moon.z().value()); + auto moon_r = std::sqrt(moon.x().value() * moon.x().value() + moon.y().value() * moon.y().value() + moon.z().value() * moon.z().value()); std::printf("Moon distance: %.2f km\n\n", moon_r); // --- Planets --- @@ -111,7 +111,7 @@ int main() { // --- Night periods (sun below -18°) --- auto night_start = mjd; auto night_end = mjd + 1.0; - auto nights = sun::below_threshold(obs, night_start, night_end, -18.0_deg); + auto nights = sun::below_threshold(obs, night_start, night_end, -18.0_deg); std::printf("Astronomical night periods (sun < -18 deg):\n"); for (auto& p : nights) { std::printf(" MJD %.6f – %.6f (%.2f hours)\n", diff --git a/examples/solar_system_bodies_example.cpp b/examples/solar_system_bodies_example.cpp index 426e257..20420d4 100644 --- a/examples/solar_system_bodies_example.cpp +++ b/examples/solar_system_bodies_example.cpp @@ -14,7 +14,7 @@ using namespace siderust; -template +template static double norm3(const PosT& p) { const double x = p.x().value(); const double y = p.y().value(); @@ -38,10 +38,10 @@ int main() { auto jd = JulianDate::from_utc({2026, 7, 15, 0, 0, 0}); std::printf("Epoch JD: %.6f\n\n", jd.value()); - auto sun_bary = ephemeris::sun_barycentric(jd); - auto earth_bary = ephemeris::earth_barycentric(jd); + auto sun_bary = ephemeris::sun_barycentric(jd); + auto earth_bary = ephemeris::earth_barycentric(jd); auto earth_helio = ephemeris::earth_heliocentric(jd); - auto moon_geo = ephemeris::moon_geocentric(jd); + auto moon_geo = ephemeris::moon_geocentric(jd); std::printf("Sun barycentric (EclipticMeanJ2000, AU):\n"); std::printf(" x=%.9f y=%.9f z=%.9f\n", diff --git a/include/siderust/altitude.hpp b/include/siderust/altitude.hpp index 680a992..aefee3c 100644 --- a/include/siderust/altitude.hpp +++ b/include/siderust/altitude.hpp @@ -8,9 +8,9 @@ * RAII-managed output arrays. */ -#include "ffi_core.hpp" -#include "coordinates.hpp" #include "bodies.hpp" +#include "coordinates.hpp" +#include "ffi_core.hpp" #include "time.hpp" #include @@ -25,7 +25,7 @@ namespace siderust { */ struct CrossingEvent { MJD time; - CrossingDirection direction; + CrossingDirection direction; static CrossingEvent from_c(const siderust_crossing_event_t& c) { return {MJD(c.mjd), static_cast(c.direction)}; @@ -36,9 +36,9 @@ struct CrossingEvent { * @brief A culmination (local altitude extremum) event. */ struct CulminationEvent { - MJD time; - qtty::Degree altitude; - CulminationKind kind; + MJD time; + qtty::Degree altitude; + CulminationKind kind; static CulminationEvent from_c(const siderust_culmination_event_t& c) { return {MJD(c.mjd), qtty::Degree(c.altitude_deg), static_cast(c.kind)}; @@ -135,13 +135,13 @@ inline qtty::Radian altitude_at(const Geodetic& obs, const MJD& mjd) { */ inline std::vector above_threshold( const Geodetic& obs, const Period& window, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ - tempoch_period_mjd_t* ptr = nullptr; uintptr_t count = 0; - check_status(siderust_sun_above_threshold_window( - obs.to_c(), window.c_inner(), threshold.value(), - opts.to_c(), &ptr, &count), - "sun::above_threshold"); + qtty::Degree threshold, const SearchOptions& opts = {}) { + tempoch_period_mjd_t* ptr = nullptr; + uintptr_t count = 0; + check_status(siderust_sun_above_threshold( + obs.to_c(), window.c_inner(), threshold.value(), + opts.to_c(), &ptr, &count), + "sun::above_threshold"); return detail::periods_from_c(ptr, count); } @@ -150,8 +150,7 @@ inline std::vector above_threshold( */ inline std::vector above_threshold( const Geodetic& obs, const MJD& start, const MJD& end, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ + qtty::Degree threshold, const SearchOptions& opts = {}) { return above_threshold(obs, Period(start, end), threshold, opts); } @@ -160,13 +159,13 @@ inline std::vector above_threshold( */ inline std::vector below_threshold( const Geodetic& obs, const Period& window, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ - tempoch_period_mjd_t* ptr = nullptr; uintptr_t count = 0; - check_status(siderust_sun_below_threshold_window( - obs.to_c(), window.c_inner(), threshold.value(), - opts.to_c(), &ptr, &count), - "sun::below_threshold"); + qtty::Degree threshold, const SearchOptions& opts = {}) { + tempoch_period_mjd_t* ptr = nullptr; + uintptr_t count = 0; + check_status(siderust_sun_below_threshold( + obs.to_c(), window.c_inner(), threshold.value(), + opts.to_c(), &ptr, &count), + "sun::below_threshold"); return detail::periods_from_c(ptr, count); } @@ -175,8 +174,7 @@ inline std::vector below_threshold( */ inline std::vector below_threshold( const Geodetic& obs, const MJD& start, const MJD& end, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ + qtty::Degree threshold, const SearchOptions& opts = {}) { return below_threshold(obs, Period(start, end), threshold, opts); } @@ -185,13 +183,13 @@ inline std::vector below_threshold( */ inline std::vector crossings( const Geodetic& obs, const Period& window, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ - siderust_crossing_event_t* ptr = nullptr; uintptr_t count = 0; - check_status(siderust_sun_crossings_window( - obs.to_c(), window.c_inner(), threshold.value(), - opts.to_c(), &ptr, &count), - "sun::crossings"); + qtty::Degree threshold, const SearchOptions& opts = {}) { + siderust_crossing_event_t* ptr = nullptr; + uintptr_t count = 0; + check_status(siderust_sun_crossings( + obs.to_c(), window.c_inner(), threshold.value(), + opts.to_c(), &ptr, &count), + "sun::crossings"); return detail::crossings_from_c(ptr, count); } @@ -200,8 +198,7 @@ inline std::vector crossings( */ inline std::vector crossings( const Geodetic& obs, const MJD& start, const MJD& end, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ + qtty::Degree threshold, const SearchOptions& opts = {}) { return crossings(obs, Period(start, end), threshold, opts); } @@ -210,13 +207,13 @@ inline std::vector crossings( */ inline std::vector culminations( const Geodetic& obs, const Period& window, - const SearchOptions& opts = {}) -{ - siderust_culmination_event_t* ptr = nullptr; uintptr_t count = 0; - check_status(siderust_sun_culminations_window( - obs.to_c(), window.c_inner(), - opts.to_c(), &ptr, &count), - "sun::culminations"); + const SearchOptions& opts = {}) { + siderust_culmination_event_t* ptr = nullptr; + uintptr_t count = 0; + check_status(siderust_sun_culminations( + obs.to_c(), window.c_inner(), + opts.to_c(), &ptr, &count), + "sun::culminations"); return detail::culminations_from_c(ptr, count); } @@ -225,8 +222,7 @@ inline std::vector culminations( */ inline std::vector culminations( const Geodetic& obs, const MJD& start, const MJD& end, - const SearchOptions& opts = {}) -{ + const SearchOptions& opts = {}) { return culminations(obs, Period(start, end), opts); } @@ -235,11 +231,11 @@ inline std::vector culminations( */ inline std::vector altitude_periods( const Geodetic& obs, const Period& window, - qtty::Degree min_alt, qtty::Degree max_alt) -{ - siderust_altitude_query_t q = {obs.to_c(), window.start().value(), window.end().value(), - min_alt.value(), max_alt.value()}; - tempoch_period_mjd_t* ptr = nullptr; uintptr_t count = 0; + qtty::Degree min_alt, qtty::Degree max_alt) { + siderust_altitude_query_t q = {obs.to_c(), window.start().value(), window.end().value(), + min_alt.value(), max_alt.value()}; + tempoch_period_mjd_t* ptr = nullptr; + uintptr_t count = 0; check_status(siderust_sun_altitude_periods(q, &ptr, &count), "sun::altitude_periods"); return detail::periods_from_c(ptr, count); @@ -250,11 +246,11 @@ inline std::vector altitude_periods( */ inline std::vector altitude_periods( const Geodetic& obs, const MJD& start, const MJD& end, - qtty::Degree min_alt, qtty::Degree max_alt) -{ - siderust_altitude_query_t q = {obs.to_c(), start.value(), end.value(), - min_alt.value(), max_alt.value()}; - tempoch_period_mjd_t* ptr = nullptr; uintptr_t count = 0; + qtty::Degree min_alt, qtty::Degree max_alt) { + siderust_altitude_query_t q = {obs.to_c(), start.value(), end.value(), + min_alt.value(), max_alt.value()}; + tempoch_period_mjd_t* ptr = nullptr; + uintptr_t count = 0; check_status(siderust_sun_altitude_periods(q, &ptr, &count), "sun::altitude_periods"); return detail::periods_from_c(ptr, count); @@ -283,13 +279,13 @@ inline qtty::Radian altitude_at(const Geodetic& obs, const MJD& mjd) { */ inline std::vector above_threshold( const Geodetic& obs, const Period& window, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ - tempoch_period_mjd_t* ptr = nullptr; uintptr_t count = 0; - check_status(siderust_moon_above_threshold_window( - obs.to_c(), window.c_inner(), threshold.value(), - opts.to_c(), &ptr, &count), - "moon::above_threshold"); + qtty::Degree threshold, const SearchOptions& opts = {}) { + tempoch_period_mjd_t* ptr = nullptr; + uintptr_t count = 0; + check_status(siderust_moon_above_threshold( + obs.to_c(), window.c_inner(), threshold.value(), + opts.to_c(), &ptr, &count), + "moon::above_threshold"); return detail::periods_from_c(ptr, count); } @@ -298,8 +294,7 @@ inline std::vector above_threshold( */ inline std::vector above_threshold( const Geodetic& obs, const MJD& start, const MJD& end, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ + qtty::Degree threshold, const SearchOptions& opts = {}) { return above_threshold(obs, Period(start, end), threshold, opts); } @@ -308,13 +303,13 @@ inline std::vector above_threshold( */ inline std::vector below_threshold( const Geodetic& obs, const Period& window, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ - tempoch_period_mjd_t* ptr = nullptr; uintptr_t count = 0; - check_status(siderust_moon_below_threshold_window( - obs.to_c(), window.c_inner(), threshold.value(), - opts.to_c(), &ptr, &count), - "moon::below_threshold"); + qtty::Degree threshold, const SearchOptions& opts = {}) { + tempoch_period_mjd_t* ptr = nullptr; + uintptr_t count = 0; + check_status(siderust_moon_below_threshold( + obs.to_c(), window.c_inner(), threshold.value(), + opts.to_c(), &ptr, &count), + "moon::below_threshold"); return detail::periods_from_c(ptr, count); } @@ -323,8 +318,7 @@ inline std::vector below_threshold( */ inline std::vector below_threshold( const Geodetic& obs, const MJD& start, const MJD& end, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ + qtty::Degree threshold, const SearchOptions& opts = {}) { return below_threshold(obs, Period(start, end), threshold, opts); } @@ -333,13 +327,13 @@ inline std::vector below_threshold( */ inline std::vector crossings( const Geodetic& obs, const Period& window, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ - siderust_crossing_event_t* ptr = nullptr; uintptr_t count = 0; - check_status(siderust_moon_crossings_window( - obs.to_c(), window.c_inner(), threshold.value(), - opts.to_c(), &ptr, &count), - "moon::crossings"); + qtty::Degree threshold, const SearchOptions& opts = {}) { + siderust_crossing_event_t* ptr = nullptr; + uintptr_t count = 0; + check_status(siderust_moon_crossings( + obs.to_c(), window.c_inner(), threshold.value(), + opts.to_c(), &ptr, &count), + "moon::crossings"); return detail::crossings_from_c(ptr, count); } @@ -348,8 +342,7 @@ inline std::vector crossings( */ inline std::vector crossings( const Geodetic& obs, const MJD& start, const MJD& end, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ + qtty::Degree threshold, const SearchOptions& opts = {}) { return crossings(obs, Period(start, end), threshold, opts); } @@ -358,13 +351,13 @@ inline std::vector crossings( */ inline std::vector culminations( const Geodetic& obs, const Period& window, - const SearchOptions& opts = {}) -{ - siderust_culmination_event_t* ptr = nullptr; uintptr_t count = 0; - check_status(siderust_moon_culminations_window( - obs.to_c(), window.c_inner(), - opts.to_c(), &ptr, &count), - "moon::culminations"); + const SearchOptions& opts = {}) { + siderust_culmination_event_t* ptr = nullptr; + uintptr_t count = 0; + check_status(siderust_moon_culminations( + obs.to_c(), window.c_inner(), + opts.to_c(), &ptr, &count), + "moon::culminations"); return detail::culminations_from_c(ptr, count); } @@ -373,8 +366,7 @@ inline std::vector culminations( */ inline std::vector culminations( const Geodetic& obs, const MJD& start, const MJD& end, - const SearchOptions& opts = {}) -{ + const SearchOptions& opts = {}) { return culminations(obs, Period(start, end), opts); } @@ -383,11 +375,11 @@ inline std::vector culminations( */ inline std::vector altitude_periods( const Geodetic& obs, const Period& window, - qtty::Degree min_alt, qtty::Degree max_alt) -{ - siderust_altitude_query_t q = {obs.to_c(), window.start().value(), window.end().value(), - min_alt.value(), max_alt.value()}; - tempoch_period_mjd_t* ptr = nullptr; uintptr_t count = 0; + qtty::Degree min_alt, qtty::Degree max_alt) { + siderust_altitude_query_t q = {obs.to_c(), window.start().value(), window.end().value(), + min_alt.value(), max_alt.value()}; + tempoch_period_mjd_t* ptr = nullptr; + uintptr_t count = 0; check_status(siderust_moon_altitude_periods(q, &ptr, &count), "moon::altitude_periods"); return detail::periods_from_c(ptr, count); @@ -398,11 +390,11 @@ inline std::vector altitude_periods( */ inline std::vector altitude_periods( const Geodetic& obs, const MJD& start, const MJD& end, - qtty::Degree min_alt, qtty::Degree max_alt) -{ - siderust_altitude_query_t q = {obs.to_c(), start.value(), end.value(), - min_alt.value(), max_alt.value()}; - tempoch_period_mjd_t* ptr = nullptr; uintptr_t count = 0; + qtty::Degree min_alt, qtty::Degree max_alt) { + siderust_altitude_query_t q = {obs.to_c(), start.value(), end.value(), + min_alt.value(), max_alt.value()}; + tempoch_period_mjd_t* ptr = nullptr; + uintptr_t count = 0; check_status(siderust_moon_altitude_periods(q, &ptr, &count), "moon::altitude_periods"); return detail::periods_from_c(ptr, count); @@ -422,8 +414,8 @@ namespace star_altitude { inline qtty::Radian altitude_at(const Star& s, const Geodetic& obs, const MJD& mjd) { double out; check_status(siderust_star_altitude_at( - s.c_handle(), obs.to_c(), mjd.value(), &out), - "star_altitude::altitude_at"); + s.c_handle(), obs.to_c(), mjd.value(), &out), + "star_altitude::altitude_at"); return qtty::Radian(out); } @@ -432,13 +424,13 @@ inline qtty::Radian altitude_at(const Star& s, const Geodetic& obs, const MJD& m */ inline std::vector above_threshold( const Star& s, const Geodetic& obs, const Period& window, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ - tempoch_period_mjd_t* ptr = nullptr; uintptr_t count = 0; - check_status(siderust_star_above_threshold_window( - s.c_handle(), obs.to_c(), window.c_inner(), threshold.value(), - opts.to_c(), &ptr, &count), - "star_altitude::above_threshold"); + qtty::Degree threshold, const SearchOptions& opts = {}) { + tempoch_period_mjd_t* ptr = nullptr; + uintptr_t count = 0; + check_status(siderust_star_above_threshold( + s.c_handle(), obs.to_c(), window.c_inner(), threshold.value(), + opts.to_c(), &ptr, &count), + "star_altitude::above_threshold"); return detail::periods_from_c(ptr, count); } @@ -447,8 +439,7 @@ inline std::vector above_threshold( */ inline std::vector above_threshold( const Star& s, const Geodetic& obs, const MJD& start, const MJD& end, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ + qtty::Degree threshold, const SearchOptions& opts = {}) { return above_threshold(s, obs, Period(start, end), threshold, opts); } @@ -457,13 +448,13 @@ inline std::vector above_threshold( */ inline std::vector below_threshold( const Star& s, const Geodetic& obs, const Period& window, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ - tempoch_period_mjd_t* ptr = nullptr; uintptr_t count = 0; - check_status(siderust_star_below_threshold_window( - s.c_handle(), obs.to_c(), window.c_inner(), threshold.value(), - opts.to_c(), &ptr, &count), - "star_altitude::below_threshold"); + qtty::Degree threshold, const SearchOptions& opts = {}) { + tempoch_period_mjd_t* ptr = nullptr; + uintptr_t count = 0; + check_status(siderust_star_below_threshold( + s.c_handle(), obs.to_c(), window.c_inner(), threshold.value(), + opts.to_c(), &ptr, &count), + "star_altitude::below_threshold"); return detail::periods_from_c(ptr, count); } @@ -472,8 +463,7 @@ inline std::vector below_threshold( */ inline std::vector below_threshold( const Star& s, const Geodetic& obs, const MJD& start, const MJD& end, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ + qtty::Degree threshold, const SearchOptions& opts = {}) { return below_threshold(s, obs, Period(start, end), threshold, opts); } @@ -482,13 +472,13 @@ inline std::vector below_threshold( */ inline std::vector crossings( const Star& s, const Geodetic& obs, const Period& window, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ - siderust_crossing_event_t* ptr = nullptr; uintptr_t count = 0; - check_status(siderust_star_crossings_window( - s.c_handle(), obs.to_c(), window.c_inner(), threshold.value(), - opts.to_c(), &ptr, &count), - "star_altitude::crossings"); + qtty::Degree threshold, const SearchOptions& opts = {}) { + siderust_crossing_event_t* ptr = nullptr; + uintptr_t count = 0; + check_status(siderust_star_crossings( + s.c_handle(), obs.to_c(), window.c_inner(), threshold.value(), + opts.to_c(), &ptr, &count), + "star_altitude::crossings"); return detail::crossings_from_c(ptr, count); } @@ -497,8 +487,7 @@ inline std::vector crossings( */ inline std::vector crossings( const Star& s, const Geodetic& obs, const MJD& start, const MJD& end, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ + qtty::Degree threshold, const SearchOptions& opts = {}) { return crossings(s, obs, Period(start, end), threshold, opts); } @@ -507,13 +496,13 @@ inline std::vector crossings( */ inline std::vector culminations( const Star& s, const Geodetic& obs, const Period& window, - const SearchOptions& opts = {}) -{ - siderust_culmination_event_t* ptr = nullptr; uintptr_t count = 0; - check_status(siderust_star_culminations_window( - s.c_handle(), obs.to_c(), window.c_inner(), - opts.to_c(), &ptr, &count), - "star_altitude::culminations"); + const SearchOptions& opts = {}) { + siderust_culmination_event_t* ptr = nullptr; + uintptr_t count = 0; + check_status(siderust_star_culminations( + s.c_handle(), obs.to_c(), window.c_inner(), + opts.to_c(), &ptr, &count), + "star_altitude::culminations"); return detail::culminations_from_c(ptr, count); } @@ -522,8 +511,7 @@ inline std::vector culminations( */ inline std::vector culminations( const Star& s, const Geodetic& obs, const MJD& start, const MJD& end, - const SearchOptions& opts = {}) -{ + const SearchOptions& opts = {}) { return culminations(s, obs, Period(start, end), opts); } @@ -542,8 +530,8 @@ inline qtty::Radian altitude_at(const spherical::direction::ICRS& dir, const Geodetic& obs, const MJD& mjd) { double out; check_status(siderust_icrs_altitude_at( - dir.to_c(), obs.to_c(), mjd.value(), &out), - "icrs_altitude::altitude_at"); + dir.to_c(), obs.to_c(), mjd.value(), &out), + "icrs_altitude::altitude_at"); return qtty::Radian(out); } @@ -561,13 +549,13 @@ inline qtty::Radian altitude_at(qtty::Degree ra, qtty::Degree dec, inline std::vector above_threshold( const spherical::direction::ICRS& dir, const Geodetic& obs, const Period& window, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ - tempoch_period_mjd_t* ptr = nullptr; uintptr_t count = 0; + qtty::Degree threshold, const SearchOptions& opts = {}) { + tempoch_period_mjd_t* ptr = nullptr; + uintptr_t count = 0; check_status(siderust_icrs_above_threshold( - dir.to_c(), obs.to_c(), window.c_inner(), - threshold.value(), opts.to_c(), &ptr, &count), - "icrs_altitude::above_threshold"); + dir.to_c(), obs.to_c(), window.c_inner(), + threshold.value(), opts.to_c(), &ptr, &count), + "icrs_altitude::above_threshold"); return detail::periods_from_c(ptr, count); } @@ -577,15 +565,13 @@ inline std::vector above_threshold( inline std::vector above_threshold( qtty::Degree ra, qtty::Degree dec, const Geodetic& obs, const MJD& start, const MJD& end, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ + qtty::Degree threshold, const SearchOptions& opts = {}) { return above_threshold( spherical::direction::ICRS(ra, dec), obs, Period(start, end), threshold, - opts - ); + opts); } /** @@ -594,13 +580,13 @@ inline std::vector above_threshold( inline std::vector below_threshold( const spherical::direction::ICRS& dir, const Geodetic& obs, const Period& window, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ - tempoch_period_mjd_t* ptr = nullptr; uintptr_t count = 0; + qtty::Degree threshold, const SearchOptions& opts = {}) { + tempoch_period_mjd_t* ptr = nullptr; + uintptr_t count = 0; check_status(siderust_icrs_below_threshold( - dir.to_c(), obs.to_c(), window.c_inner(), - threshold.value(), opts.to_c(), &ptr, &count), - "icrs_altitude::below_threshold"); + dir.to_c(), obs.to_c(), window.c_inner(), + threshold.value(), opts.to_c(), &ptr, &count), + "icrs_altitude::below_threshold"); return detail::periods_from_c(ptr, count); } @@ -610,15 +596,13 @@ inline std::vector below_threshold( inline std::vector below_threshold( qtty::Degree ra, qtty::Degree dec, const Geodetic& obs, const MJD& start, const MJD& end, - qtty::Degree threshold, const SearchOptions& opts = {}) -{ + qtty::Degree threshold, const SearchOptions& opts = {}) { return below_threshold( spherical::direction::ICRS(ra, dec), obs, Period(start, end), threshold, - opts - ); + opts); } } // namespace icrs_altitude diff --git a/include/siderust/bodies.hpp b/include/siderust/bodies.hpp index 7389de1..cbc3247 100644 --- a/include/siderust/bodies.hpp +++ b/include/siderust/bodies.hpp @@ -5,10 +5,10 @@ * @brief RAII Star handle, Planet value type, and catalog helpers. */ -#include "ffi_core.hpp" #include "coordinates.hpp" -#include +#include "ffi_core.hpp" #include +#include #include namespace siderust { @@ -21,9 +21,9 @@ namespace siderust { * @brief Proper motion for a star (equatorial). */ struct ProperMotion { - double pm_ra_deg_yr; ///< RA proper motion (deg/yr). - double pm_dec_deg_yr; ///< Dec proper motion (deg/yr). - RaConvention convention; ///< RA rate convention. + double pm_ra_deg_yr; ///< RA proper motion (deg/yr). + double pm_dec_deg_yr; ///< Dec proper motion (deg/yr). + RaConvention convention; ///< RA rate convention. ProperMotion(double ra, double dec, RaConvention conv = RaConvention::MuAlphaStar) @@ -128,12 +128,12 @@ inline Planet make_planet_neptune() { } // namespace detail inline const Planet MERCURY = detail::make_planet_mercury(); -inline const Planet VENUS = detail::make_planet_venus(); -inline const Planet EARTH = detail::make_planet_earth(); -inline const Planet MARS = detail::make_planet_mars(); +inline const Planet VENUS = detail::make_planet_venus(); +inline const Planet EARTH = detail::make_planet_earth(); +inline const Planet MARS = detail::make_planet_mars(); inline const Planet JUPITER = detail::make_planet_jupiter(); -inline const Planet SATURN = detail::make_planet_saturn(); -inline const Planet URANUS = detail::make_planet_uranus(); +inline const Planet SATURN = detail::make_planet_saturn(); +inline const Planet URANUS = detail::make_planet_uranus(); inline const Planet NEPTUNE = detail::make_planet_neptune(); // Backward-compatible function aliases. @@ -160,21 +160,25 @@ class Star { explicit Star(SiderustStar* h) : m_handle(h) {} -public: + public: Star() = default; - ~Star() { if (m_handle) siderust_star_free(m_handle); } + ~Star() { + if (m_handle) + siderust_star_free(m_handle); + } // Move-only Star(Star&& o) noexcept : m_handle(o.m_handle) { o.m_handle = nullptr; } Star& operator=(Star&& o) noexcept { if (this != &o) { - if (m_handle) siderust_star_free(m_handle); - m_handle = o.m_handle; + if (m_handle) + siderust_star_free(m_handle); + m_handle = o.m_handle; o.m_handle = nullptr; } return *this; } - Star(const Star&) = delete; + Star(const Star&) = delete; Star& operator=(const Star&) = delete; /// Whether the handle is valid. @@ -211,56 +215,54 @@ class Star { * @param epoch_jd Epoch of coordinates (Julian Date). * @param pm Optional proper motion. */ - static Star create(const std::string& name, - double distance_ly, - double mass_solar, - double radius_solar, - double luminosity_solar, - double ra_deg, - double dec_deg, - double epoch_jd, - const std::optional& pm = std::nullopt) - { - SiderustStar* h = nullptr; + static Star create(const std::string& name, + double distance_ly, + double mass_solar, + double radius_solar, + double luminosity_solar, + double ra_deg, + double dec_deg, + double epoch_jd, + const std::optional& pm = std::nullopt) { + SiderustStar* h = nullptr; const siderust_proper_motion_t* pm_ptr = nullptr; - siderust_proper_motion_t pm_c{}; + siderust_proper_motion_t pm_c{}; if (pm.has_value()) { - pm_c = pm->to_c(); + pm_c = pm->to_c(); pm_ptr = &pm_c; } check_status(siderust_star_create( - name.c_str(), distance_ly, mass_solar, radius_solar, - luminosity_solar, ra_deg, dec_deg, epoch_jd, pm_ptr, &h), - "Star::create" - ); + name.c_str(), distance_ly, mass_solar, radius_solar, + luminosity_solar, ra_deg, dec_deg, epoch_jd, pm_ptr, &h), + "Star::create"); return Star(h); } // -- Accessors -- std::string name() const { - char buf[256]; + char buf[256]; uintptr_t written = 0; check_status(siderust_star_name(m_handle, buf, sizeof(buf), &written), "Star::name"); return std::string(buf, written); } - double distance_ly() const { return siderust_star_distance_ly(m_handle); } - double mass_solar() const { return siderust_star_mass_solar(m_handle); } - double radius_solar() const { return siderust_star_radius_solar(m_handle); } - double luminosity_solar() const { return siderust_star_luminosity_solar(m_handle); } + double distance_ly() const { return siderust_star_distance_ly(m_handle); } + double mass_solar() const { return siderust_star_mass_solar(m_handle); } + double radius_solar() const { return siderust_star_radius_solar(m_handle); } + double luminosity_solar() const { return siderust_star_luminosity_solar(m_handle); } }; -inline const Star VEGA = Star::catalog("VEGA"); -inline const Star SIRIUS = Star::catalog("SIRIUS"); -inline const Star POLARIS = Star::catalog("POLARIS"); -inline const Star CANOPUS = Star::catalog("CANOPUS"); -inline const Star ARCTURUS = Star::catalog("ARCTURUS"); -inline const Star RIGEL = Star::catalog("RIGEL"); +inline const Star VEGA = Star::catalog("VEGA"); +inline const Star SIRIUS = Star::catalog("SIRIUS"); +inline const Star POLARIS = Star::catalog("POLARIS"); +inline const Star CANOPUS = Star::catalog("CANOPUS"); +inline const Star ARCTURUS = Star::catalog("ARCTURUS"); +inline const Star RIGEL = Star::catalog("RIGEL"); inline const Star BETELGEUSE = Star::catalog("BETELGEUSE"); -inline const Star PROCYON = Star::catalog("PROCYON"); -inline const Star ALDEBARAN = Star::catalog("ALDEBARAN"); -inline const Star ALTAIR = Star::catalog("ALTAIR"); +inline const Star PROCYON = Star::catalog("PROCYON"); +inline const Star ALDEBARAN = Star::catalog("ALDEBARAN"); +inline const Star ALTAIR = Star::catalog("ALTAIR"); } // namespace siderust diff --git a/include/siderust/centers.hpp b/include/siderust/centers.hpp index 947c470..0a67de4 100644 --- a/include/siderust/centers.hpp +++ b/include/siderust/centers.hpp @@ -23,16 +23,16 @@ namespace centers { // Center Trait // ============================================================================ -template -struct CenterTraits; // primary — intentionally undefined +template +struct CenterTraits; // primary — intentionally undefined -template +template struct is_center : std::false_type {}; -template +template struct is_center::ffi_id)>> : std::true_type {}; -template +template inline constexpr bool is_center_v = is_center::value; // ============================================================================ @@ -57,38 +57,38 @@ struct Bodycentric {}; /// Marker for simple (no-parameter) centers. struct NoParams {}; -template<> +template <> struct CenterTraits { static constexpr siderust_center_t ffi_id = SIDERUST_CENTER_T_BARYCENTRIC; - using Params = NoParams; + using Params = NoParams; static constexpr const char* name() { return "Barycentric"; } }; -template<> +template <> struct CenterTraits { static constexpr siderust_center_t ffi_id = SIDERUST_CENTER_T_HELIOCENTRIC; - using Params = NoParams; + using Params = NoParams; static constexpr const char* name() { return "Heliocentric"; } }; -template<> +template <> struct CenterTraits { static constexpr siderust_center_t ffi_id = SIDERUST_CENTER_T_GEOCENTRIC; - using Params = NoParams; + using Params = NoParams; static constexpr const char* name() { return "Geocentric"; } }; -template<> +template <> struct CenterTraits { static constexpr siderust_center_t ffi_id = SIDERUST_CENTER_T_TOPOCENTRIC; - using Params = Geodetic; // forward-declared + using Params = Geodetic; // forward-declared static constexpr const char* name() { return "Topocentric"; } }; -template<> +template <> struct CenterTraits { static constexpr siderust_center_t ffi_id = SIDERUST_CENTER_T_BODYCENTRIC; - using Params = NoParams; // placeholder for BodycentricParams + using Params = NoParams; // placeholder for BodycentricParams static constexpr const char* name() { return "Bodycentric"; } }; @@ -102,15 +102,17 @@ struct CenterTraits { * Hub = Barycentric. Supported shifts: Barycentric ↔ Heliocentric, * Barycentric ↔ Geocentric, and the composed Heliocentric ↔ Geocentric. */ -template +template struct has_center_transform : std::false_type {}; -template +template struct has_center_transform : std::true_type {}; -#define SIDERUST_CENTER_TRANSFORM_PAIR(A, B) \ - template<> struct has_center_transform : std::true_type {}; \ - template<> struct has_center_transform : std::true_type {} +#define SIDERUST_CENTER_TRANSFORM_PAIR(A, B) \ + template <> \ + struct has_center_transform : std::true_type {}; \ + template <> \ + struct has_center_transform : std::true_type {} SIDERUST_CENTER_TRANSFORM_PAIR(Barycentric, Heliocentric); SIDERUST_CENTER_TRANSFORM_PAIR(Barycentric, Geocentric); @@ -118,7 +120,7 @@ SIDERUST_CENTER_TRANSFORM_PAIR(Heliocentric, Geocentric); #undef SIDERUST_CENTER_TRANSFORM_PAIR -template +template inline constexpr bool has_center_transform_v = has_center_transform::value; } // namespace centers diff --git a/include/siderust/coordinates.hpp b/include/siderust/coordinates.hpp index 9e96656..a500e77 100644 --- a/include/siderust/coordinates.hpp +++ b/include/siderust/coordinates.hpp @@ -49,10 +49,10 @@ * @ingroup coordinates */ +#include "coordinates/cartesian.hpp" +#include "coordinates/conversions.hpp" #include "coordinates/geodetic.hpp" #include "coordinates/spherical.hpp" -#include "coordinates/cartesian.hpp" #include "coordinates/types.hpp" -#include "coordinates/conversions.hpp" -/** @} */ // end of group coordinates +/** @} */ // end of group coordinates diff --git a/include/siderust/coordinates/cartesian.hpp b/include/siderust/coordinates/cartesian.hpp index 8ea6dc2..79a069b 100644 --- a/include/siderust/coordinates/cartesian.hpp +++ b/include/siderust/coordinates/cartesian.hpp @@ -23,7 +23,7 @@ namespace cartesian { * @ingroup coordinates_cartesian * @tparam F Reference frame tag (e.g. `frames::ICRS`). */ -template +template struct Direction { static_assert(frames::is_frame_v, "F must be a valid frame tag"); @@ -49,7 +49,7 @@ struct Direction { * @tparam F Reference frame tag (e.g. `frames::ECEF`). * @tparam U Length unit (default: `qtty::Meter`). */ -template +template struct Position { static_assert(frames::is_frame_v, "F must be a valid frame tag"); static_assert(centers::is_center_v, "C must be a valid center tag"); @@ -71,7 +71,7 @@ struct Position { U y() const { return comp_y; } U z() const { return comp_z; } - static constexpr siderust_frame_t frame_id() { return frames::FrameTraits::ffi_id; } + static constexpr siderust_frame_t frame_id() { return frames::FrameTraits::ffi_id; } static constexpr siderust_center_t center_id() { return centers::CenterTraits::ffi_id; } /// Convert to C FFI struct. diff --git a/include/siderust/coordinates/conversions.hpp b/include/siderust/coordinates/conversions.hpp index d656636..fe9b727 100644 --- a/include/siderust/coordinates/conversions.hpp +++ b/include/siderust/coordinates/conversions.hpp @@ -10,20 +10,18 @@ namespace siderust { -template +template inline cartesian::Position Geodetic::to_cartesian() const { siderust_cartesian_pos_t out; check_status( siderust_geodetic_to_cartesian_ecef(to_c(), &out), - "Geodetic::to_cartesian" - ); + "Geodetic::to_cartesian"); const auto ecef_m = cartesian::position::ECEF::from_c(out); return cartesian::Position( ecef_m.x().template to(), ecef_m.y().template to(), - ecef_m.z().template to() - ); + ecef_m.z().template to()); } /** diff --git a/include/siderust/coordinates/geodetic.hpp b/include/siderust/coordinates/geodetic.hpp index a0bf8f2..86dc552 100644 --- a/include/siderust/coordinates/geodetic.hpp +++ b/include/siderust/coordinates/geodetic.hpp @@ -6,15 +6,15 @@ * @brief WGS84 geodetic coordinate type. */ -#include "../ffi_core.hpp" #include "../centers.hpp" +#include "../ffi_core.hpp" #include "../frames.hpp" #include namespace siderust { namespace cartesian { -template +template struct Position; } @@ -56,7 +56,7 @@ struct Geodetic { * * @tparam U Output length unit (default: meter). */ - template + template cartesian::Position to_cartesian() const; }; diff --git a/include/siderust/coordinates/spherical.hpp b/include/siderust/coordinates/spherical.hpp index 7d5c315..cd94da9 100644 --- a/include/siderust/coordinates/spherical.hpp +++ b/include/siderust/coordinates/spherical.hpp @@ -32,15 +32,15 @@ namespace spherical { * - Horizontal frame: `az()`, `al()` / `alt()` * - Lon/lat frames: `lon()`, `lat()` */ -template +template struct Direction { static_assert(frames::is_frame_v, "F must be a valid frame tag"); -private: - qtty::Degree azimuth_; ///< Azimuthal component (RA/longitude/azimuth). - qtty::Degree polar_; ///< Polar component (Dec/latitude/altitude). + private: + qtty::Degree azimuth_; ///< Azimuthal component (RA/longitude/azimuth). + qtty::Degree polar_; ///< Polar component (Dec/latitude/altitude). -public: + public: Direction() : azimuth_(qtty::Degree(0)), polar_(qtty::Degree(0)) {} Direction(qtty::Degree azimuth, qtty::Degree polar) @@ -62,40 +62,40 @@ struct Direction { /// @name RA / Dec (equatorial frames only) /// @{ - template, int> = 0> + template , int> = 0> qtty::Degree ra() const { return azimuth_; } - template, int> = 0> + template , int> = 0> qtty::Degree dec() const { return polar_; } /// @} /// @name Azimuth / Altitude (Horizontal frame only) /// @{ - template, int> = 0> + template , int> = 0> qtty::Degree az() const { return azimuth_; } - template, int> = 0> + template , int> = 0> qtty::Degree al() const { return polar_; } - template, int> = 0> + template , int> = 0> qtty::Degree alt() const { return polar_; } - template, int> = 0> + template , int> = 0> qtty::Degree altitude() const { return polar_; } /// @} /// @name Longitude / Latitude (lon/lat frames) /// @{ - template, int> = 0> + template , int> = 0> qtty::Degree lon() const { return azimuth_; } - template, int> = 0> + template , int> = 0> qtty::Degree lat() const { return polar_; } - template, int> = 0> + template , int> = 0> qtty::Degree longitude() const { return azimuth_; } - template, int> = 0> + template , int> = 0> qtty::Degree latitude() const { return polar_; } /// @} @@ -118,11 +118,10 @@ struct Direction { * * @tparam Target Destination frame tag. */ - template + template std::enable_if_t< frames::has_frame_transform_v, - Direction - > + Direction> to_frame(const JulianDate& jd) const { if constexpr (std::is_same_v) { return Direction(azimuth_.value(), polar_.value()); @@ -134,8 +133,7 @@ struct Direction { frames::FrameTraits::ffi_id, frames::FrameTraits::ffi_id, jd.value(), &out), - "Direction::to_frame" - ); + "Direction::to_frame"); return Direction::from_c(out); } } @@ -143,21 +141,19 @@ struct Direction { /** * @brief Shorthand: `.to(jd)` (calls `to_frame`). */ - template + template auto to(const JulianDate& jd) const - -> decltype(this->template to_frame(jd)) - { + -> decltype(this->template to_frame(jd)) { return to_frame(jd); } /** * @brief Transform to the horizontal (alt-az) frame. */ - template + template std::enable_if_t< frames::has_horizontal_transform_v, - Direction - > + Direction> to_horizontal(const JulianDate& jd, const Geodetic& observer) const { siderust_spherical_dir_t out; check_status( @@ -165,8 +161,7 @@ struct Direction { azimuth_.value(), polar_.value(), frames::FrameTraits::ffi_id, jd.value(), observer.to_c(), &out), - "Direction::to_horizontal" - ); + "Direction::to_horizontal"); return Direction::from_c(out); } }; @@ -181,17 +176,17 @@ struct Direction { * @tparam F Reference frame tag (e.g. `frames::ICRS`). * @tparam U Distance unit (default: `qtty::Meter`). */ -template +template struct Position { static_assert(frames::is_frame_v, "F must be a valid frame tag"); static_assert(centers::is_center_v, "C must be a valid center tag"); -private: + private: qtty::Degree azimuth_; qtty::Degree polar_; U dist_; -public: + public: Position() : azimuth_(qtty::Degree(0)), polar_(qtty::Degree(0)), dist_(U(0)) {} @@ -210,29 +205,29 @@ struct Position { /// @name Component accessors by frame convention /// @{ - template, int> = 0> + template , int> = 0> qtty::Degree ra() const { return azimuth_; } - template, int> = 0> + template , int> = 0> qtty::Degree dec() const { return polar_; } - template, int> = 0> + template , int> = 0> qtty::Degree az() const { return azimuth_; } - template, int> = 0> + template , int> = 0> qtty::Degree al() const { return polar_; } - template, int> = 0> + template , int> = 0> qtty::Degree alt() const { return polar_; } - template, int> = 0> + template , int> = 0> qtty::Degree lon() const { return azimuth_; } - template, int> = 0> + template , int> = 0> qtty::Degree lat() const { return polar_; } /// @} - static constexpr siderust_frame_t frame_id() { return frames::FrameTraits::ffi_id; } + static constexpr siderust_frame_t frame_id() { return frames::FrameTraits::ffi_id; } static constexpr siderust_center_t center_id() { return centers::CenterTraits::ffi_id; } U distance() const { return dist_; } diff --git a/include/siderust/coordinates/types/cartesian/position/ecliptic.hpp b/include/siderust/coordinates/types/cartesian/position/ecliptic.hpp index 8a86e84..d06e3f6 100644 --- a/include/siderust/coordinates/types/cartesian/position/ecliptic.hpp +++ b/include/siderust/coordinates/types/cartesian/position/ecliptic.hpp @@ -5,16 +5,16 @@ namespace siderust { namespace cartesian { namespace position { -template +template using EclipticMeanJ2000 = Position; -template +template using HelioBarycentric = Position; -template +template using GeoBarycentric = Position; -template +template using MoonGeocentric = Position; } // namespace position } // namespace cartesian diff --git a/include/siderust/coordinates/types/cartesian/position/equatorial.hpp b/include/siderust/coordinates/types/cartesian/position/equatorial.hpp index 4b4a1af..c5f8a5a 100644 --- a/include/siderust/coordinates/types/cartesian/position/equatorial.hpp +++ b/include/siderust/coordinates/types/cartesian/position/equatorial.hpp @@ -5,10 +5,10 @@ namespace siderust { namespace cartesian { namespace position { -template +template using ICRS = Position; -template +template using GCRS = Position; } // namespace position } // namespace cartesian diff --git a/include/siderust/coordinates/types/cartesian/position/geodetic.hpp b/include/siderust/coordinates/types/cartesian/position/geodetic.hpp index 5910987..e9d7684 100644 --- a/include/siderust/coordinates/types/cartesian/position/geodetic.hpp +++ b/include/siderust/coordinates/types/cartesian/position/geodetic.hpp @@ -5,7 +5,7 @@ namespace siderust { namespace cartesian { namespace position { -template +template using ECEF = Position; } // namespace position } // namespace cartesian diff --git a/include/siderust/coordinates/types/spherical/direction/equatorial.hpp b/include/siderust/coordinates/types/spherical/direction/equatorial.hpp index 844a12e..c920904 100644 --- a/include/siderust/coordinates/types/spherical/direction/equatorial.hpp +++ b/include/siderust/coordinates/types/spherical/direction/equatorial.hpp @@ -5,9 +5,9 @@ namespace siderust { namespace spherical { namespace direction { -using ICRS = Direction; -using ICRF = Direction; -using EquatorialMeanJ2000 = Direction; +using ICRS = Direction; +using ICRF = Direction; +using EquatorialMeanJ2000 = Direction; using EquatorialMeanOfDate = Direction; using EquatorialTrueOfDate = Direction; } // namespace direction diff --git a/include/siderust/coordinates/types/spherical/position/ecliptic.hpp b/include/siderust/coordinates/types/spherical/position/ecliptic.hpp index 14577df..ecf112b 100644 --- a/include/siderust/coordinates/types/spherical/position/ecliptic.hpp +++ b/include/siderust/coordinates/types/spherical/position/ecliptic.hpp @@ -5,7 +5,7 @@ namespace siderust { namespace spherical { namespace position { -template +template using EclipticMeanJ2000 = Position; } // namespace position } // namespace spherical diff --git a/include/siderust/coordinates/types/spherical/position/equatorial.hpp b/include/siderust/coordinates/types/spherical/position/equatorial.hpp index 86f6420..1a69bda 100644 --- a/include/siderust/coordinates/types/spherical/position/equatorial.hpp +++ b/include/siderust/coordinates/types/spherical/position/equatorial.hpp @@ -5,13 +5,13 @@ namespace siderust { namespace spherical { namespace position { -template +template using ICRS = Position; -template +template using GCRS = Position; -template +template using HCRS = Position; } // namespace position } // namespace spherical diff --git a/include/siderust/coordinates/types/spherical/position/horizontal.hpp b/include/siderust/coordinates/types/spherical/position/horizontal.hpp index a3eb33d..9234527 100644 --- a/include/siderust/coordinates/types/spherical/position/horizontal.hpp +++ b/include/siderust/coordinates/types/spherical/position/horizontal.hpp @@ -5,7 +5,7 @@ namespace siderust { namespace spherical { namespace position { -template +template using Horizontal = Position; } // namespace position } // namespace spherical diff --git a/include/siderust/ephemeris.hpp b/include/siderust/ephemeris.hpp index b9d3b15..d5377cb 100644 --- a/include/siderust/ephemeris.hpp +++ b/include/siderust/ephemeris.hpp @@ -8,8 +8,8 @@ * correct center, frame, and unit for each ephemeris query. */ -#include "ffi_core.hpp" #include "coordinates.hpp" +#include "ffi_core.hpp" #include "time.hpp" namespace siderust { diff --git a/include/siderust/ffi_core.hpp b/include/siderust/ffi_core.hpp index 994c72a..94d8a9f 100644 --- a/include/siderust/ffi_core.hpp +++ b/include/siderust/ffi_core.hpp @@ -25,52 +25,52 @@ namespace siderust { // ============================================================================ class SiderustException : public std::runtime_error { -public: + public: explicit SiderustException(const std::string& msg) : std::runtime_error(msg) {} }; class NullPointerError : public SiderustException { -public: + public: explicit NullPointerError(const std::string& msg) : SiderustException(msg) {} }; class InvalidFrameError : public SiderustException { -public: + public: explicit InvalidFrameError(const std::string& msg) : SiderustException(msg) {} }; class InvalidCenterError : public SiderustException { -public: + public: explicit InvalidCenterError(const std::string& msg) : SiderustException(msg) {} }; class TransformFailedError : public SiderustException { -public: + public: explicit TransformFailedError(const std::string& msg) : SiderustException(msg) {} }; class InvalidBodyError : public SiderustException { -public: + public: explicit InvalidBodyError(const std::string& msg) : SiderustException(msg) {} }; class UnknownStarError : public SiderustException { -public: + public: explicit UnknownStarError(const std::string& msg) : SiderustException(msg) {} }; class InvalidPeriodError : public SiderustException { -public: + public: explicit InvalidPeriodError(const std::string& msg) : SiderustException(msg) {} }; class AllocationFailedError : public SiderustException { -public: + public: explicit AllocationFailedError(const std::string& msg) : SiderustException(msg) {} }; class InvalidArgumentError : public SiderustException { -public: + public: explicit InvalidArgumentError(const std::string& msg) : SiderustException(msg) {} }; @@ -79,30 +79,31 @@ class InvalidArgumentError : public SiderustException { // ============================================================================ inline void check_status(siderust_status_t status, const char* operation) { - if (status == SIDERUST_STATUS_T_OK) return; + if (status == SIDERUST_STATUS_T_OK) + return; std::string msg = std::string(operation) + " failed: "; switch (status) { - case SIDERUST_STATUS_T_NULL_POINTER: - throw NullPointerError(msg + "null output pointer"); - case SIDERUST_STATUS_T_INVALID_FRAME: - throw InvalidFrameError(msg + "invalid or unsupported frame"); - case SIDERUST_STATUS_T_INVALID_CENTER: - throw InvalidCenterError(msg + "invalid or unsupported center"); - case SIDERUST_STATUS_T_TRANSFORM_FAILED: - throw TransformFailedError(msg + "coordinate transform failed"); - case SIDERUST_STATUS_T_INVALID_BODY: - throw InvalidBodyError(msg + "invalid body"); - case SIDERUST_STATUS_T_UNKNOWN_STAR: - throw UnknownStarError(msg + "unknown star name"); - case SIDERUST_STATUS_T_INVALID_PERIOD: - throw InvalidPeriodError(msg + "invalid period (start > end)"); - case SIDERUST_STATUS_T_ALLOCATION_FAILED: - throw AllocationFailedError(msg + "memory allocation failed"); - case SIDERUST_STATUS_T_INVALID_ARGUMENT: - throw InvalidArgumentError(msg + "invalid argument"); - default: - throw SiderustException(msg + "unknown error (" + std::to_string(status) + ")"); + case SIDERUST_STATUS_T_NULL_POINTER: + throw NullPointerError(msg + "null output pointer"); + case SIDERUST_STATUS_T_INVALID_FRAME: + throw InvalidFrameError(msg + "invalid or unsupported frame"); + case SIDERUST_STATUS_T_INVALID_CENTER: + throw InvalidCenterError(msg + "invalid or unsupported center"); + case SIDERUST_STATUS_T_TRANSFORM_FAILED: + throw TransformFailedError(msg + "coordinate transform failed"); + case SIDERUST_STATUS_T_INVALID_BODY: + throw InvalidBodyError(msg + "invalid body"); + case SIDERUST_STATUS_T_UNKNOWN_STAR: + throw UnknownStarError(msg + "unknown star name"); + case SIDERUST_STATUS_T_INVALID_PERIOD: + throw InvalidPeriodError(msg + "invalid period (start > end)"); + case SIDERUST_STATUS_T_ALLOCATION_FAILED: + throw AllocationFailedError(msg + "memory allocation failed"); + case SIDERUST_STATUS_T_INVALID_ARGUMENT: + throw InvalidArgumentError(msg + "invalid argument"); + default: + throw SiderustException(msg + "unknown error (" + std::to_string(status) + ")"); } } @@ -116,21 +117,21 @@ inline void check_tempoch_status(tempoch_status_t status, const char* operation) // ============================================================================ enum class Frame : int32_t { - ICRS = SIDERUST_FRAME_T_ICRS, - EclipticMeanJ2000 = SIDERUST_FRAME_T_ECLIPTIC_MEAN_J2000, - EquatorialMeanJ2000 = SIDERUST_FRAME_T_EQUATORIAL_MEAN_J2000, - EquatorialMeanOfDate = SIDERUST_FRAME_T_EQUATORIAL_MEAN_OF_DATE, - EquatorialTrueOfDate = SIDERUST_FRAME_T_EQUATORIAL_TRUE_OF_DATE, - Horizontal = SIDERUST_FRAME_T_HORIZONTAL, - ECEF = SIDERUST_FRAME_T_ECEF, - Galactic = SIDERUST_FRAME_T_GALACTIC, - GCRS = SIDERUST_FRAME_T_GCRS, - EclipticOfDate = SIDERUST_FRAME_T_ECLIPTIC_OF_DATE, - EclipticTrueOfDate = SIDERUST_FRAME_T_ECLIPTIC_TRUE_OF_DATE, - CIRS = SIDERUST_FRAME_T_CIRS, - TIRS = SIDERUST_FRAME_T_TIRS, - ITRF = SIDERUST_FRAME_T_ITRF, - ICRF = SIDERUST_FRAME_T_ICRF, + ICRS = SIDERUST_FRAME_T_ICRS, + EclipticMeanJ2000 = SIDERUST_FRAME_T_ECLIPTIC_MEAN_J2000, + EquatorialMeanJ2000 = SIDERUST_FRAME_T_EQUATORIAL_MEAN_J2000, + EquatorialMeanOfDate = SIDERUST_FRAME_T_EQUATORIAL_MEAN_OF_DATE, + EquatorialTrueOfDate = SIDERUST_FRAME_T_EQUATORIAL_TRUE_OF_DATE, + Horizontal = SIDERUST_FRAME_T_HORIZONTAL, + ECEF = SIDERUST_FRAME_T_ECEF, + Galactic = SIDERUST_FRAME_T_GALACTIC, + GCRS = SIDERUST_FRAME_T_GCRS, + EclipticOfDate = SIDERUST_FRAME_T_ECLIPTIC_OF_DATE, + EclipticTrueOfDate = SIDERUST_FRAME_T_ECLIPTIC_TRUE_OF_DATE, + CIRS = SIDERUST_FRAME_T_CIRS, + TIRS = SIDERUST_FRAME_T_TIRS, + ITRF = SIDERUST_FRAME_T_ITRF, + ICRF = SIDERUST_FRAME_T_ICRF, }; enum class Center : int32_t { diff --git a/include/siderust/frames.hpp b/include/siderust/frames.hpp index 7886780..2e2b0f3 100644 --- a/include/siderust/frames.hpp +++ b/include/siderust/frames.hpp @@ -24,19 +24,19 @@ namespace frames { * - `ffi_id` — the C FFI enum value * - `name()` — human-readable frame name */ -template -struct FrameTraits; // primary template — intentionally undefined +template +struct FrameTraits; // primary template — intentionally undefined /** * @brief Concept-like compile-time check (C++17: constexpr bool). */ -template +template struct is_frame : std::false_type {}; -template +template struct is_frame::ffi_id)>> : std::true_type {}; -template +template inline constexpr bool is_frame_v = is_frame::value; // ============================================================================ @@ -80,27 +80,28 @@ struct EclipticMeanOfDate {}; // FrameTraits Specializations // ============================================================================ -#define SIDERUST_DEFINE_FRAME(Tag, EnumVal, Label) \ - template<> struct FrameTraits { \ - static constexpr siderust_frame_t ffi_id = EnumVal;\ - static constexpr const char* name() { return Label; } \ +#define SIDERUST_DEFINE_FRAME(Tag, EnumVal, Label) \ + template <> \ + struct FrameTraits { \ + static constexpr siderust_frame_t ffi_id = EnumVal; \ + static constexpr const char* name() { return Label; } \ } -SIDERUST_DEFINE_FRAME(ICRS, SIDERUST_FRAME_T_ICRS, "ICRS"); -SIDERUST_DEFINE_FRAME(ICRF, SIDERUST_FRAME_T_ICRF, "ICRF"); -SIDERUST_DEFINE_FRAME(EclipticMeanJ2000, SIDERUST_FRAME_T_ECLIPTIC_MEAN_J2000, "EclipticMeanJ2000"); -SIDERUST_DEFINE_FRAME(EclipticOfDate, SIDERUST_FRAME_T_ECLIPTIC_OF_DATE, "EclipticOfDate"); -SIDERUST_DEFINE_FRAME(EclipticTrueOfDate, SIDERUST_FRAME_T_ECLIPTIC_TRUE_OF_DATE, "EclipticTrueOfDate"); -SIDERUST_DEFINE_FRAME(EquatorialMeanJ2000, SIDERUST_FRAME_T_EQUATORIAL_MEAN_J2000, "EquatorialMeanJ2000"); -SIDERUST_DEFINE_FRAME(EquatorialMeanOfDate, SIDERUST_FRAME_T_EQUATORIAL_MEAN_OF_DATE, "EquatorialMeanOfDate"); -SIDERUST_DEFINE_FRAME(EquatorialTrueOfDate, SIDERUST_FRAME_T_EQUATORIAL_TRUE_OF_DATE, "EquatorialTrueOfDate"); -SIDERUST_DEFINE_FRAME(Horizontal, SIDERUST_FRAME_T_HORIZONTAL, "Horizontal"); -SIDERUST_DEFINE_FRAME(Galactic, SIDERUST_FRAME_T_GALACTIC, "Galactic"); -SIDERUST_DEFINE_FRAME(ECEF, SIDERUST_FRAME_T_ECEF, "ECEF"); -SIDERUST_DEFINE_FRAME(ITRF, SIDERUST_FRAME_T_ITRF, "ITRF"); -SIDERUST_DEFINE_FRAME(CIRS, SIDERUST_FRAME_T_CIRS, "CIRS"); -SIDERUST_DEFINE_FRAME(GCRS, SIDERUST_FRAME_T_GCRS, "GCRS"); -SIDERUST_DEFINE_FRAME(TIRS, SIDERUST_FRAME_T_TIRS, "TIRS"); +SIDERUST_DEFINE_FRAME(ICRS, SIDERUST_FRAME_T_ICRS, "ICRS"); +SIDERUST_DEFINE_FRAME(ICRF, SIDERUST_FRAME_T_ICRF, "ICRF"); +SIDERUST_DEFINE_FRAME(EclipticMeanJ2000, SIDERUST_FRAME_T_ECLIPTIC_MEAN_J2000, "EclipticMeanJ2000"); +SIDERUST_DEFINE_FRAME(EclipticOfDate, SIDERUST_FRAME_T_ECLIPTIC_OF_DATE, "EclipticOfDate"); +SIDERUST_DEFINE_FRAME(EclipticTrueOfDate, SIDERUST_FRAME_T_ECLIPTIC_TRUE_OF_DATE, "EclipticTrueOfDate"); +SIDERUST_DEFINE_FRAME(EquatorialMeanJ2000, SIDERUST_FRAME_T_EQUATORIAL_MEAN_J2000, "EquatorialMeanJ2000"); +SIDERUST_DEFINE_FRAME(EquatorialMeanOfDate, SIDERUST_FRAME_T_EQUATORIAL_MEAN_OF_DATE, "EquatorialMeanOfDate"); +SIDERUST_DEFINE_FRAME(EquatorialTrueOfDate, SIDERUST_FRAME_T_EQUATORIAL_TRUE_OF_DATE, "EquatorialTrueOfDate"); +SIDERUST_DEFINE_FRAME(Horizontal, SIDERUST_FRAME_T_HORIZONTAL, "Horizontal"); +SIDERUST_DEFINE_FRAME(Galactic, SIDERUST_FRAME_T_GALACTIC, "Galactic"); +SIDERUST_DEFINE_FRAME(ECEF, SIDERUST_FRAME_T_ECEF, "ECEF"); +SIDERUST_DEFINE_FRAME(ITRF, SIDERUST_FRAME_T_ITRF, "ITRF"); +SIDERUST_DEFINE_FRAME(CIRS, SIDERUST_FRAME_T_CIRS, "CIRS"); +SIDERUST_DEFINE_FRAME(GCRS, SIDERUST_FRAME_T_GCRS, "GCRS"); +SIDERUST_DEFINE_FRAME(TIRS, SIDERUST_FRAME_T_TIRS, "TIRS"); #undef SIDERUST_DEFINE_FRAME @@ -113,55 +114,55 @@ SIDERUST_DEFINE_FRAME(TIRS, SIDERUST_FRAME_T_TIRS, * * Default: (longitude, latitude). Specialise per-frame for RA/Dec, Az/Alt, etc. */ -template +template struct SphericalNaming { static constexpr const char* lon_name() { return "longitude"; } static constexpr const char* lat_name() { return "latitude"; } }; -template<> +template <> struct SphericalNaming { static constexpr const char* lon_name() { return "right_ascension"; } static constexpr const char* lat_name() { return "declination"; } }; -template<> +template <> struct SphericalNaming { static constexpr const char* lon_name() { return "right_ascension"; } static constexpr const char* lat_name() { return "declination"; } }; -template<> +template <> struct SphericalNaming { static constexpr const char* lon_name() { return "right_ascension"; } static constexpr const char* lat_name() { return "declination"; } }; -template<> +template <> struct SphericalNaming { static constexpr const char* lon_name() { return "right_ascension"; } static constexpr const char* lat_name() { return "declination"; } }; -template<> +template <> struct SphericalNaming { static constexpr const char* lon_name() { return "right_ascension"; } static constexpr const char* lat_name() { return "declination"; } }; -template<> +template <> struct SphericalNaming { static constexpr const char* lon_name() { return "azimuth"; } static constexpr const char* lat_name() { return "altitude"; } }; -template<> +template <> struct SphericalNaming { static constexpr const char* lon_name() { return "l"; } static constexpr const char* lat_name() { return "b"; } }; -template<> +template <> struct SphericalNaming { static constexpr const char* lon_name() { return "ecliptic_longitude"; } static constexpr const char* lat_name() { return "ecliptic_latitude"; } @@ -176,13 +177,19 @@ struct SphericalNaming { * * Use `has_ra_dec_v` in `std::enable_if_t` to gate RA/Dec accessors. */ -template struct has_ra_dec : std::false_type {}; -template<> struct has_ra_dec : std::true_type {}; -template<> struct has_ra_dec : std::true_type {}; -template<> struct has_ra_dec : std::true_type {}; -template<> struct has_ra_dec : std::true_type {}; -template<> struct has_ra_dec : std::true_type {}; -template +template +struct has_ra_dec : std::false_type {}; +template <> +struct has_ra_dec : std::true_type {}; +template <> +struct has_ra_dec : std::true_type {}; +template <> +struct has_ra_dec : std::true_type {}; +template <> +struct has_ra_dec : std::true_type {}; +template <> +struct has_ra_dec : std::true_type {}; +template inline constexpr bool has_ra_dec_v = has_ra_dec::value; /** @@ -190,9 +197,11 @@ inline constexpr bool has_ra_dec_v = has_ra_dec::value; * * Use `has_az_alt_v` to gate Az/Alt accessors. */ -template struct has_az_alt : std::false_type {}; -template<> struct has_az_alt : std::true_type {}; -template +template +struct has_az_alt : std::false_type {}; +template <> +struct has_az_alt : std::true_type {}; +template inline constexpr bool has_az_alt_v = has_az_alt::value; /** @@ -200,17 +209,27 @@ inline constexpr bool has_az_alt_v = has_az_alt::value; * * Use `has_lon_lat_v` to gate lon/lat accessors. */ -template struct has_lon_lat : std::false_type {}; -template<> struct has_lon_lat : std::true_type {}; -template<> struct has_lon_lat : std::true_type {}; -template<> struct has_lon_lat : std::true_type {}; -template<> struct has_lon_lat : std::true_type {}; -template<> struct has_lon_lat : std::true_type {}; -template<> struct has_lon_lat : std::true_type {}; -template<> struct has_lon_lat : std::true_type {}; -template<> struct has_lon_lat : std::true_type {}; -template<> struct has_lon_lat : std::true_type {}; -template +template +struct has_lon_lat : std::false_type {}; +template <> +struct has_lon_lat : std::true_type {}; +template <> +struct has_lon_lat : std::true_type {}; +template <> +struct has_lon_lat : std::true_type {}; +template <> +struct has_lon_lat : std::true_type {}; +template <> +struct has_lon_lat : std::true_type {}; +template <> +struct has_lon_lat : std::true_type {}; +template <> +struct has_lon_lat : std::true_type {}; +template <> +struct has_lon_lat : std::true_type {}; +template <> +struct has_lon_lat : std::true_type {}; +template inline constexpr bool has_lon_lat_v = has_lon_lat::value; // ============================================================================ @@ -227,17 +246,19 @@ inline constexpr bool has_lon_lat_v = has_lon_lat::value; * * Same-frame identity transforms are always valid. */ -template +template struct has_frame_transform : std::false_type {}; // Identity -template +template struct has_frame_transform : std::true_type {}; // Hub spokes (bidirectional) -#define SIDERUST_FRAME_TRANSFORM_PAIR(A, B) \ - template<> struct has_frame_transform : std::true_type {}; \ - template<> struct has_frame_transform : std::true_type {} +#define SIDERUST_FRAME_TRANSFORM_PAIR(A, B) \ + template <> \ + struct has_frame_transform : std::true_type {}; \ + template <> \ + struct has_frame_transform : std::true_type {} // All pairs reachable through the ICRS hub SIDERUST_FRAME_TRANSFORM_PAIR(ICRS, EclipticMeanJ2000); @@ -259,23 +280,29 @@ SIDERUST_FRAME_TRANSFORM_PAIR(ICRF, ICRS); #undef SIDERUST_FRAME_TRANSFORM_PAIR -template +template inline constexpr bool has_frame_transform_v = has_frame_transform::value; /** * @brief Marks frames from which to_horizontal is reachable. */ -template +template struct has_horizontal_transform : std::false_type {}; -template<> struct has_horizontal_transform : std::true_type {}; -template<> struct has_horizontal_transform : std::true_type {}; -template<> struct has_horizontal_transform : std::true_type {}; -template<> struct has_horizontal_transform : std::true_type {}; -template<> struct has_horizontal_transform : std::true_type {}; -template<> struct has_horizontal_transform : std::true_type {}; - -template +template <> +struct has_horizontal_transform : std::true_type {}; +template <> +struct has_horizontal_transform : std::true_type {}; +template <> +struct has_horizontal_transform : std::true_type {}; +template <> +struct has_horizontal_transform : std::true_type {}; +template <> +struct has_horizontal_transform : std::true_type {}; +template <> +struct has_horizontal_transform : std::true_type {}; + +template inline constexpr bool has_horizontal_transform_v = has_horizontal_transform::value; } // namespace frames diff --git a/include/siderust/observatories.hpp b/include/siderust/observatories.hpp index f72741b..5e9c345 100644 --- a/include/siderust/observatories.hpp +++ b/include/siderust/observatories.hpp @@ -5,8 +5,8 @@ * @brief Named observatory locations. */ -#include "ffi_core.hpp" #include "coordinates.hpp" +#include "ffi_core.hpp" namespace siderust { diff --git a/include/siderust/siderust.hpp b/include/siderust/siderust.hpp index 1e863ff..5cf0df1 100644 --- a/include/siderust/siderust.hpp +++ b/include/siderust/siderust.hpp @@ -26,12 +26,12 @@ * @endcode */ -#include "ffi_core.hpp" -#include "frames.hpp" +#include "altitude.hpp" +#include "bodies.hpp" #include "centers.hpp" #include "coordinates.hpp" -#include "time.hpp" -#include "bodies.hpp" -#include "observatories.hpp" -#include "altitude.hpp" #include "ephemeris.hpp" +#include "ffi_core.hpp" +#include "frames.hpp" +#include "observatories.hpp" +#include "time.hpp" diff --git a/tests/test_altitude.cpp b/tests/test_altitude.cpp index b5fd83d..8ad505a 100644 --- a/tests/test_altitude.cpp +++ b/tests/test_altitude.cpp @@ -1,13 +1,13 @@ +#include #include #include -#include using namespace siderust; static const double PI = 3.14159265358979323846; class AltitudeTest : public ::testing::Test { -protected: + protected: Geodetic obs; MJD start; MJD end_; @@ -16,7 +16,7 @@ class AltitudeTest : public ::testing::Test { void SetUp() override { obs = ROQUE_DE_LOS_MUCHACHOS; start = MJD::from_jd(JulianDate::from_utc({2026, 7, 15, 18, 0, 0})); - end_ = start + 1.0; // 24 hours + end_ = start + 1.0; // 24 hours window = Period(start, end_); } }; @@ -94,15 +94,15 @@ TEST_F(AltitudeTest, MoonAboveThreshold) { // ============================================================================ TEST_F(AltitudeTest, StarAltitudeAt) { - const auto& vega = VEGA; - qtty::Radian alt = star_altitude::altitude_at(vega, obs, start); + const auto& vega = VEGA; + qtty::Radian alt = star_altitude::altitude_at(vega, obs, start); EXPECT_GT(alt.value(), -PI / 2.0); EXPECT_LT(alt.value(), PI / 2.0); } TEST_F(AltitudeTest, StarAboveThreshold) { - const auto& vega = VEGA; - auto periods = star_altitude::above_threshold(vega, obs, window, qtty::Degree(30.0)); + const auto& vega = VEGA; + auto periods = star_altitude::above_threshold(vega, obs, window, qtty::Degree(30.0)); // Vega should be well above 30° from La Palma in July EXPECT_GT(periods.size(), 0u); } @@ -113,14 +113,14 @@ TEST_F(AltitudeTest, StarAboveThreshold) { TEST_F(AltitudeTest, IcrsAltitudeAt) { const spherical::direction::ICRS vega_icrs(qtty::Degree(279.23), qtty::Degree(38.78)); - qtty::Radian alt = icrs_altitude::altitude_at(vega_icrs, obs, start); + qtty::Radian alt = icrs_altitude::altitude_at(vega_icrs, obs, start); EXPECT_GT(alt.value(), -PI / 2.0); EXPECT_LT(alt.value(), PI / 2.0); } TEST_F(AltitudeTest, IcrsAboveThreshold) { const spherical::direction::ICRS vega_icrs(qtty::Degree(279.23), qtty::Degree(38.78)); - auto periods = icrs_altitude::above_threshold( - vega_icrs, obs, window, qtty::Degree(30.0)); + auto periods = icrs_altitude::above_threshold( + vega_icrs, obs, window, qtty::Degree(30.0)); EXPECT_GT(periods.size(), 0u); } diff --git a/tests/test_bodies.cpp b/tests/test_bodies.cpp index 51f7e70..755e69b 100644 --- a/tests/test_bodies.cpp +++ b/tests/test_bodies.cpp @@ -36,13 +36,13 @@ TEST(Bodies, StarMoveSemantics) { TEST(Bodies, StarCreate) { auto s = Star::create( "TestStar", - 100.0, // distance_ly - 1.0, // mass_solar - 1.0, // radius_solar - 1.0, // luminosity_solar - 180.0, // ra_deg - 45.0, // dec_deg - 2451545.0 // epoch_jd (J2000) + 100.0, // distance_ly + 1.0, // mass_solar + 1.0, // radius_solar + 1.0, // luminosity_solar + 180.0, // ra_deg + 45.0, // dec_deg + 2451545.0 // epoch_jd (J2000) ); EXPECT_EQ(s.name(), "TestStar"); EXPECT_NEAR(s.distance_ly(), 100.0, 1e-6); @@ -50,8 +50,8 @@ TEST(Bodies, StarCreate) { TEST(Bodies, StarCreateWithProperMotion) { ProperMotion pm(0.001, -0.002, RaConvention::MuAlphaStar); - auto s = Star::create("PMStar", 50.0, 1.0, 1.0, 1.0, - 100.0, 30.0, 2451545.0, pm); + auto s = Star::create("PMStar", 50.0, 1.0, 1.0, 1.0, + 100.0, 30.0, 2451545.0, pm); EXPECT_EQ(s.name(), "PMStar"); } diff --git a/tests/test_coordinates.cpp b/tests/test_coordinates.cpp index a0f64b7..8cc6cc7 100644 --- a/tests/test_coordinates.cpp +++ b/tests/test_coordinates.cpp @@ -1,6 +1,6 @@ +#include #include #include -#include #include using namespace siderust; @@ -13,20 +13,18 @@ TEST(TypedCoordinates, AliasNamespaces) { static_assert(std::is_same_v>); static_assert(std::is_same_v>); static_assert(std::is_same_v< - spherical::position::ICRS, - spherical::Position - >); + spherical::position::ICRS, + spherical::Position>); static_assert(std::is_same_v< - cartesian::position::ECEF, - cartesian::Position - >); + cartesian::position::ECEF, + cartesian::Position>); } TEST(TypedCoordinates, IcrsDirToEcliptic) { using namespace siderust::frames; spherical::direction::ICRS vega(279.23473, 38.78369); - auto jd = JulianDate::J2000(); + auto jd = JulianDate::J2000(); // Compile-time typed transform: ICRS -> EclipticMeanJ2000 auto ecl = vega.to_frame(jd); @@ -42,7 +40,7 @@ TEST(TypedCoordinates, IcrsDirRoundtrip) { using namespace siderust::frames; spherical::direction::ICRS icrs(100.0, 30.0); - auto jd = JulianDate::J2000(); + auto jd = JulianDate::J2000(); auto ecl = icrs.to_frame(jd); auto back = ecl.to_frame(jd); @@ -56,7 +54,7 @@ TEST(TypedCoordinates, ToShorthand) { using namespace siderust::frames; spherical::direction::ICRS icrs(100.0, 30.0); - auto jd = JulianDate::J2000(); + auto jd = JulianDate::J2000(); // .to(jd) is a shorthand for .to_frame(jd) auto ecl = icrs.to(jd); @@ -68,8 +66,8 @@ TEST(TypedCoordinates, IcrsDirToHorizontal) { using namespace siderust::frames; spherical::direction::ICRS vega(279.23473, 38.78369); - auto jd = JulianDate::from_utc({2026, 7, 15, 22, 0, 0}); - auto obs = ROQUE_DE_LOS_MUCHACHOS; + auto jd = JulianDate::from_utc({2026, 7, 15, 22, 0, 0}); + auto obs = ROQUE_DE_LOS_MUCHACHOS; auto hor = vega.to_horizontal(jd, obs); @@ -82,7 +80,7 @@ TEST(TypedCoordinates, EquatorialToIcrs) { using namespace siderust::frames; spherical::direction::EquatorialMeanJ2000 eq(100.0, 30.0); - auto jd = JulianDate::J2000(); + auto jd = JulianDate::J2000(); auto icrs = eq.to_frame(jd); static_assert(std::is_same_v); @@ -97,7 +95,7 @@ TEST(TypedCoordinates, MultiHopTransform) { // EquatorialMeanOfDate -> EquatorialTrueOfDate (through hub) spherical::Direction mean_od(100.0, 30.0); - auto jd = JulianDate::J2000(); + auto jd = JulianDate::J2000(); auto true_od = mean_od.to_frame(jd); static_assert(std::is_same_v>); @@ -111,7 +109,7 @@ TEST(TypedCoordinates, SameFrameIdentity) { using namespace siderust::frames; spherical::direction::ICRS icrs(123.456, -45.678); - auto jd = JulianDate::J2000(); + auto jd = JulianDate::J2000(); auto same = icrs.to_frame(jd); EXPECT_DOUBLE_EQ(same.ra().value(), 123.456); @@ -122,7 +120,7 @@ TEST(TypedCoordinates, QttyDegreeAccessors) { spherical::direction::ICRS d(123.456, -45.678); // Frame-specific getters for ICRS. - qtty::Degree ra = d.ra(); + qtty::Degree ra = d.ra(); qtty::Degree dec = d.dec(); EXPECT_DOUBLE_EQ(ra.value(), 123.456); EXPECT_DOUBLE_EQ(dec.value(), -45.678); @@ -159,7 +157,7 @@ TEST(TypedCoordinates, GeodeticQttyFields) { // ============================================================================ TEST(TypedCoordinates, GeodeticToCartesianEcef) { - auto geo = geodetic(0.0, 0.0, 0.0); + auto geo = geodetic(0.0, 0.0, 0.0); auto cart = geodetic_to_cartesian_ecef(geo); // Typed return: cartesian::Position @@ -173,14 +171,13 @@ TEST(TypedCoordinates, GeodeticToCartesianEcef) { TEST(TypedCoordinates, GeodeticToCartesianMember) { auto geo = geodetic(0.0, 0.0, 0.0); - auto ecef_m = geo.to_cartesian(); + auto ecef_m = geo.to_cartesian(); auto ecef_km = geo.to_cartesian(); static_assert(std::is_same_v>); static_assert(std::is_same_v< - decltype(ecef_km), - cartesian::Position - >); + decltype(ecef_km), + cartesian::Position>); EXPECT_NEAR(ecef_m.x().value(), 6378137.0, 1.0); EXPECT_NEAR(ecef_km.x().value(), 6378.137, 1e-3); diff --git a/tests/test_ephemeris.cpp b/tests/test_ephemeris.cpp index 39759a2..fd1489d 100644 --- a/tests/test_ephemeris.cpp +++ b/tests/test_ephemeris.cpp @@ -1,6 +1,6 @@ +#include #include #include -#include using namespace siderust; @@ -14,9 +14,8 @@ TEST(Ephemeris, EarthHeliocentric) { // Compile-time type checks static_assert(std::is_same_v< - decltype(pos), - cartesian::position::EclipticMeanJ2000 - >); + decltype(pos), + cartesian::position::EclipticMeanJ2000>); static_assert(std::is_same_v); // Value check — distance should be ~1 AU @@ -38,9 +37,8 @@ TEST(Ephemeris, MoonGeocentric) { auto pos = ephemeris::moon_geocentric(jd); static_assert(std::is_same_v< - decltype(pos), - cartesian::position::MoonGeocentric - >); + decltype(pos), + cartesian::position::MoonGeocentric>); static_assert(std::is_same_v); double r = std::sqrt(pos.x().value() * pos.x().value() + pos.y().value() * pos.y().value() + pos.z().value() * pos.z().value()); diff --git a/tests/test_observatories.cpp b/tests/test_observatories.cpp index 2e9765e..bd673b4 100644 --- a/tests/test_observatories.cpp +++ b/tests/test_observatories.cpp @@ -14,7 +14,7 @@ TEST(Observatories, RoqueDeLos) { TEST(Observatories, ElParanal) { auto obs = EL_PARANAL; EXPECT_LT(obs.lon.value(), 0.0); - EXPECT_LT(obs.lat.value(), 0.0); // Southern hemisphere + EXPECT_LT(obs.lat.value(), 0.0); // Southern hemisphere EXPECT_GT(obs.height.value(), 2000.0); } diff --git a/tests/test_time.cpp b/tests/test_time.cpp index 7142369..395814c 100644 --- a/tests/test_time.cpp +++ b/tests/test_time.cpp @@ -19,7 +19,7 @@ TEST(Time, JulianDateFromUtc) { } TEST(Time, JulianDateRoundtripUtc) { - UTC original(2026, 7, 15, 22, 0, 0); + UTC original(2026, 7, 15, 22, 0, 0); auto jd = JulianDate::from_utc(original); auto utc = jd.to_utc(); EXPECT_EQ(utc.year, 2026); @@ -69,7 +69,7 @@ TEST(Time, PeriodDuration) { TEST(Time, PeriodIntersection) { Period a(60200.0, 60202.0); Period b(60201.0, 60203.0); - auto c = a.intersection(b); + auto c = a.intersection(b); EXPECT_NEAR(c.start_mjd(), 60201.0, 1e-10); EXPECT_NEAR(c.end_mjd(), 60202.0, 1e-10); }