1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2026 Vallés Puig, Ramon
//! # Coordinates Module
//!
//! This module defines strongly typed spherical and cartesian coordinate systems used in astronomy.
//! The coordinate systems are implemented using Rust's type system with phantom types
//! to enforce compile-time safety. These phantom types represent the **frame** and **center** of
//! the coordinate system, ensuring that operations between incompatible coordinate systems are
//! disallowed unless explicitly converted. Moreover, thanks to the Unit module we can distinguish
//! the different vector types such as Directions (unitless), Position (length units) and Velocity
//! (Velocity Units), that enforce the compiler to validate any transformation of coordinates.
//! ## Key Concepts
//! - **Position, Direction and Velocity Types**: Both spherical and cartesian coordinates are parameterized
//! by a reference center (e.g., `Heliocentric`, `Geocentric`), a reference frame (e.g., `EclipticMeanJ2000`, `EquatorialMeanJ2000`, `ICRS`),
//! and a measure unit (`Unitless`, `LengthUnit`, `VelocityUnit`). This ensures that only compatible coordinates can be used together.
//! - **Phantom Types**: The `Center`, `Frame` and `Unit`types are zero-cost markers that encode coordinate semantics at compile time.
//! - **Type Safety**: Operations between coordinates are only allowed when their type parameters match, preventing accidental mixing of frames, centers or magnitude.
//! - **Conversions**: Seamless conversion between spherical and cartesian forms, and between different frames and centers, is provided via `From`/`Into` and the `Transform` trait.
//!
//! ## Compile-Time vs Runtime Safety
//!
//! **Most** reference centers (`Barycentric`, `Heliocentric`, `Geocentric`) use `Params = ()`,
//! so all coordinate invariants are enforced at **compile time** with no runtime overhead.
//!
//! **Parameterized** centers (`Topocentric`, `Bodycentric`) carry runtime data (e.g.,
//! [`Geodetic<ECEF>`](centers::Geodetic), [`BodycentricParams`](centers::BodycentricParams)).
//! For these, the *center type* is still checked at compile time (you can't mix `Topocentric`
//! and `Geocentric` positions), but the specific *site/body parameters* are checked at **runtime**.
//!
//! | Center kind | Params | Frame/Center type safety | Parameter equality |
//! |---------------------|-----------|--------------------------|---------------------|
//! | `Geocentric` etc. | `()` | compile-time | compile-time (trivial `()`) |
//! | `Topocentric` | `Geodetic<ECEF>` | compile-time | **runtime** (`assert!` or `Result`) |
//! | `Bodycentric` | `BodycentricParams` | compile-time | **runtime** (`assert!` or `Result`) |
//!
//! Operations that require matching parameters (e.g., `Position - Position`, `distance_to`)
//! **panic** by default on mismatch in all build profiles. Non-panicking alternatives are
//! available via `checked_sub()` and `try_distance_to()`.
//!
//! Use [`Geodetic::<ECEF>::try_new`](affn::ellipsoidal::Position::try_new)
//! to validate geographic coordinates before constructing topocentric positions.
//!
//! ## Module Organization
//!
//! The coordinate system is organized into several modules:
//!
//! ### Core Modules
//!
//! - **Reference frames and centers**: Trait definitions for orientation and origin in [`frames`] and [`centers`]
//! - **Cartesian types**: Vector, Direction, Position, Velocity in [`cartesian`]
//! - **Spherical types**: Direction, Position with astronomical extensions in [`spherical`]
//!
//! ### Additional Modules
//!
//! - **transform**: Generic transformations between coordinate systems and frames
//! - **observation**: Observer-dependent effects like aberration
//! - **horizontal**: Convention conversion helpers for horizontal (alt-az) coordinates
//!
//! The coordinate types are built on top of the `affn` crate (the pure geometry kernel).
//! Astronomy-specific frames, centers, and convenience methods are defined in this module.
//!
//! ## Coordinate Transform Architecture
//!
//! The coordinate system maintains a clean separation of concerns:
//!
//! - **Center transforms** (translations): Apply only to positions. Moving from geocentric to
//! heliocentric is a pure vector subtraction. No observation effects.
//!
//! - **Frame transforms** (rotations): Apply to positions, directions, and velocities.
//! Changing from ecliptic to equatorial is a pure rotation matrix.
//!
//! - **Observation transforms** (in [`observation`] module): Observer-dependent effects like
//! aberration. These require explicit `ObserverState` and produce directions with explicit
//! observational state (`Astrometric` or `Apparent`).
//!
//! ## Supported Reference Frames and Centers
//! - **Frames**: `EquatorialMeanJ2000`, `EquatorialMeanOfDate`, `EquatorialTrueOfDate`, `EclipticMeanJ2000`, `Horizontal`, `ICRS`, `ECEF`
//! - **Centers**: `Heliocentric`, `Geocentric`, `Barycentric`, `Topocentric`, `Bodycentric`
//!
//! ## Example
//! ```rust
//! use siderust::coordinates::spherical;
//! use siderust::coordinates::cartesian;
//! use siderust::coordinates::frames::EclipticMeanJ2000;
//! use qtty::*;
//!
//! // Create an ecliptic spherical direction (frame-only, no center)
//! let spherical = spherical::Direction::<EclipticMeanJ2000>::new(
//! 45.0 * DEG, 7.0 * DEG
//! );
//!
//! // Convert to cartesian coordinates
//! let cartesian: cartesian::Direction<EclipticMeanJ2000> = spherical.to_cartesian();
//!
//! // Convert back to spherical coordinates
//! let spherical_converted: spherical::Direction<EclipticMeanJ2000> =
//! spherical::Direction::from_cartesian(&cartesian);
//!
//! println!("Spherical -> Cartesian -> Spherical: {:?}", spherical_converted);
//! ```
//!
//! ## Submodules
//! - **frames**: Reference frame definitions (EclipticMeanJ2000, EquatorialMeanJ2000, ICRS, etc.)
//! - **centers**: Reference center definitions (Heliocentric, Geocentric, etc.)
//! - **cartesian**: Cartesian coordinate types and astronomical type aliases
//! - **spherical**: Spherical coordinate types and astronomical extensions
//! - **transform**: Generic transformations between coordinate systems and frames
//! - **observation**: Observational state types (`Astrometric`, `Apparent`) and aberration
//!
//! ## Prelude
//!
//! For ergonomic imports of extension traits:
//! ```rust,ignore
//! use siderust::coordinates::prelude::*;
//! ```
/// Prelude module for convenient imports.
///
/// Import this to get access to all coordinate extension traits and common
/// coordinate type aliases:
///
/// ```rust
/// use siderust::coordinates::prelude::*;
/// ```
///
/// This includes:
/// - [`DirectionAstroExt`](transform::DirectionAstroExt) - Frame transforms for directions
/// - [`VectorAstroExt`](transform::VectorAstroExt) - Frame transforms for vectors
/// - [`PositionAstroExt`](transform::PositionAstroExt) - Frame and center transforms for positions
/// - [`AstroContext`](transform::AstroContext) - Context for transformations
/// - All concise type aliases from [`types`] (e.g. `IcrsDir`, `GeographicPos`, etc.)