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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//! Precomputed body-fixed observer positions and velocities.
//!
//! This module computes and caches the **Earth-fixed (body-fixed) position and
//! velocity** of each observer present in an observation dataset. These quantities
//! are time-independent — they depend only on the observer's geographic coordinates
//! (longitude, latitude, height) — so they are computed once at cache-build time
//! and reused for every observation associated with the same observer.
//!
//! # Coordinate system
//!
//! All vectors are expressed in the **geocentric Earth-fixed frame** (ECEF-like),
//! with components given in **astronomical units (AU)** for positions and
//! **AU/day** for velocities.
//!
//! The body-fixed velocity is derived from Earth's sidereal rotation:
//!
//! ```text
//! v_fixed = ω_earth × r_fixed
//! ```
//!
//! where `ω_earth` is the Earth rotation vector (see [`crate::constants::EARTH_ROTATION`]).
//!
//! # Organisation
//!
//! - [`ObserverFixedPosition`] / [`ObserverFixedVelocity`] — type aliases for 3-vectors.
//! - [`ObserverFixedCache`] — holds the fixed position and velocity for one observer.
//! - [`BodyFixedObserverCache`] — map from [`ObserverId`] to [`ObserverFixedCache`].
//! - [`build_fixed_observer_cache`] — constructs the map from an iterator of observers.
use AHashMap;
use Vector3;
use NotNan;
use ;
use crate::;
/// Precomputed **body-fixed** position of the observer in **AU**.
///
/// The vector is expressed in the geocentric Earth-fixed frame. Its components
/// are stored as [`NotNan<f64>`] to guarantee the absence of NaN values at
/// construction time.
pub type ObserverFixedPosition = ;
/// Precomputed **body-fixed** velocity of the observer in **AU/day**.
///
/// Derived from the cross product of Earth's rotation vector with the observer's
/// body-fixed position: `v = ω × r`. Stored as [`NotNan<f64>`] for the same
/// NaN-safety guarantee as [`ObserverFixedPosition`].
pub type ObserverFixedVelocity = ;
/// Body-fixed position and velocity for a single ground-based observer.
///
/// This cache entry is time-independent: it is built once from the observer's
/// geographic coordinates and reused across all observations made by that observer.
///
/// # Fields
///
/// Both fields are in the geocentric Earth-fixed frame:
///
/// - position in **AU**
/// - velocity in **AU/day** (from Earth rotation)
/// Cache mapping observer IDs to their precomputed body-fixed positions and velocities.
///
/// This hash map is built once before any trajectory fitting (see
/// [`build_fixed_observer_cache`]) and looked up by [`ObserverId`] for every
/// observation in the dataset. Using [`AHashMap`] provides fast, non-cryptographic
/// hashing suited for integer-keyed lookups.
pub type BodyFixedObserverCache = ;
/// Builds the [`BodyFixedObserverCache`] from an iterator of `(ObserverId, &Observer)` pairs.
///
/// For each observer, computes the body-fixed position and velocity and stores
/// them in the map. This function is typically called once before the main
/// cache-building step in [`crate::cache::OutfitCache::build`].
///
/// # Arguments
///
/// - `observers` — an iterator yielding `(ObserverId, &Observer)` pairs, typically
/// obtained from [`photom::observation_dataset::ObsDataset::iter_observer`].
///
/// # Errors
///
/// Returns [`OutfitError`] if [`ObserverFixedCache::new`] fails for any observer
/// in the iterator (e.g., invalid geodetic coordinates or NaN conversion).
///
/// # Examples
///
/// ```rust,ignore
/// let cache = build_fixed_observer_cache(obs_dataset.iter_observer()?)?;
/// ```