Skip to content

Commit 5dd7df5

Browse files
committed
Few more changes to astro-core
1 parent c5d9076 commit 5dd7df5

2 files changed

Lines changed: 56 additions & 26 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Celestial
22

33
[![CI](https://github.com/gaker/celestial/workflows/Rust%20CI/badge.svg)](https://github.com/gaker/celestial/actions)
4-
[![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/astro-core)](https://github.com/gaker/celestial)
4+
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5+
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
56

67
Astronomical computation library for Rust.
78

astro-core/src/location.rs

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::errors::{AstroError, AstroResult, MathErrorKind};
2222
/// - **Longitude**: Angular distance east or west of the prime meridian (-180° to +180°)
2323
/// - **Height**: Distance above the WGS84 reference ellipsoid (not sea level)
2424
///
25-
/// All angular coordinates are stored internally in radians for computational efficiency.
25+
/// All angular coordinates are stored internally in radians.
2626
///
2727
/// # Examples
2828
///
@@ -58,36 +58,65 @@ impl Location {
5858
/// Create a new Location with validation
5959
///
6060
/// Creates a location using angular coordinates in radians. Input values are
61-
/// validated to ensure they represent a physically meaningful location on Earth.
61+
/// validated to ensure they represent a physically meaningful location on Earth's
62+
/// WGS84 reference ellipsoid.
6263
///
6364
/// # Arguments
64-
/// * `latitude` - Latitude in radians (positive north, -π/2 ≤ lat ≤ π/2)
65-
/// * `longitude` - Longitude in radians (positive east, -π ≤ lon ≤ π)
66-
/// * `height` - Height above WGS84 ellipsoid in meters (-12000 ≤ h ≤ 100000)
6765
///
68-
/// # Range Limits
66+
/// * `latitude` - Latitude in radians, positive north of equator
67+
/// - Range: [-π/2, π/2] (exactly ±1.5707963267948966 rad)
68+
/// - π/2 = 90.0° (North Pole), -π/2 = -90.0° (South Pole)
69+
/// * `longitude` - Longitude in radians, positive east of Prime Meridian
70+
/// - Range: [-π, π] (exactly ±3.141592653589793 rad)
71+
/// - No wrapping performed - values outside range are rejected
72+
/// * `height` - Height above WGS84 reference ellipsoid in meters
73+
/// - Range: [-12000, 100000] m (Dead Sea to edge of space)
74+
/// - Note: This is height above ellipsoid, not mean sea level (MSL)
6975
///
70-
/// - Latitude: ±π/2 rad (±90°) - from south pole to north pole
71-
/// - Longitude: ±π rad (±180°) - full range around Earth
72-
/// - Height: -12000 to +100000 m - from deepest trenches to edge of space
76+
/// # Returns
7377
///
74-
/// # Panics
78+
/// - `Ok(Location)` - Valid location ready for astronomical calculations
79+
/// - `Err(AstroError)` - Invalid input with specific validation error
7580
///
76-
/// Panics if any coordinate is outside its valid range. Use this constructor
77-
/// when you need guaranteed valid coordinates for precision calculations.
81+
/// # Errors
7882
///
79-
/// # Example
83+
/// Returns `AstroError::MathError` with `MathErrorKind::InvalidInput` for:
84+
///
85+
/// - **Non-finite values**: NaN, positive infinity, or negative infinity
86+
/// - **Latitude out of range**: |latitude| > π/2 radians
87+
/// - **Longitude out of range**: |longitude| > π radians
88+
/// - **Height out of range**: height < -12000 or height > 100000 meters
89+
///
90+
/// # WGS84 Reference System
91+
///
92+
/// This constructor validates coordinates for the World Geodetic System 1984:
93+
/// - Semi-major axis (a): 6,378,137.0 m (equatorial radius)
94+
/// - Flattening (f): 1/298.257223563 (Earth's oblateness)
95+
/// - Eccentricity squared (e²): 0.00669437999014 (derived parameter)
96+
///
97+
/// # Coordinate Conventions
98+
///
99+
/// - **Latitude**: Geodetic latitude (angle between normal to ellipsoid and equatorial plane)
100+
/// - **Longitude**: No automatic wrapping - use exactly [-π, π] range
101+
/// - **Height**: Perpendicular distance from ellipsoid surface (not orthometric height)
102+
///
103+
/// # Examples
80104
///
81105
/// ```rust
82106
/// use astro_core::Location;
83-
/// use std::f64::consts::PI;
107+
/// use std::f64::consts::{PI, FRAC_PI_2};
108+
///
109+
/// // Valid locations
110+
/// let greenwich = Location::new(0.0, 0.0, 0.0)?; // Prime meridian, sea level
111+
/// let north_pole = Location::new(FRAC_PI_2, 0.0, 0.0)?; // Exactly 90° N
112+
/// let mauna_kea = Location::new(0.3462, -2.7124, 4207.0)?; // Observatory
84113
///
85-
/// let greenwich = Location::new(0.0, 0.0, 0.0); // Prime meridian, sea level
86-
/// let north_pole = Location::new(PI/2.0, 0.0, 0.0); // 90° N
114+
/// // This fails - longitude out of range
115+
/// let invalid = Location::new(0.0, 4.0, 0.0); // 4.0 > π
116+
/// assert!(invalid.is_err());
117+
/// # Ok::<(), astro_core::AstroError>(())
87118
/// ```
88-
pub fn new(latitude: f64, longitude: f64, height: f64) -> AstroResult<Self> {
89-
// Input validation for precision astronomical calculations
90-
119+
pub fn new(latitude: f64, longitude: f64, height: f64) -> AstroResult<Self> {
91120
// Check for NaN or infinite values
92121
if !latitude.is_finite() {
93122
return Err(AstroError::math_error(
@@ -116,21 +145,21 @@ impl Location {
116145
return Err(AstroError::math_error(
117146
"location_validation",
118147
MathErrorKind::InvalidInput,
119-
&format!("Latitude {:.6} rad outside valid range [-π/2, π/2]", latitude)
148+
"Latitude outside valid range [-π/2, π/2]"
120149
));
121150
}
122151
if longitude.abs() > std::f64::consts::PI {
123152
return Err(AstroError::math_error(
124153
"location_validation",
125154
MathErrorKind::InvalidInput,
126-
&format!("Longitude {:.6} rad outside valid range [-π, π]", longitude)
155+
"Longitude outside valid range [-π, π]"
127156
));
128157
}
129158
if !(-12000.0..=100000.0).contains(&height) {
130159
return Err(AstroError::math_error(
131160
"location_validation",
132161
MathErrorKind::InvalidInput,
133-
&format!("Height {:.1} m outside reasonable range [-12000, 100000]", height)
162+
"Height outside reasonable range [-12000, 100000] meters"
134163
));
135164
}
136165

@@ -186,14 +215,14 @@ impl Location {
186215
return Err(AstroError::math_error(
187216
"location_validation",
188217
MathErrorKind::InvalidInput,
189-
&format!("Latitude {:.6}° outside valid range [-90, 90]", lat_deg)
218+
"Latitude outside valid range [-90, 90] degrees"
190219
));
191220
}
192221
if lon_deg.abs() > 180.0 {
193222
return Err(AstroError::math_error(
194223
"location_validation",
195224
MathErrorKind::InvalidInput,
196-
&format!("Longitude {:.6}° outside valid range [-180, 180]", lon_deg)
225+
"Longitude outside valid range [-180, 180] degrees"
197226
));
198227
}
199228

@@ -258,7 +287,7 @@ impl Location {
258287
return Err(AstroError::math_error(
259288
"geocentric_conversion",
260289
MathErrorKind::DivisionByZero,
261-
&format!("Latitude {:.6} rad causes division by zero in WGS84 conversion", lat)
290+
"Latitude too close to critical value causing division by zero"
262291
));
263292
}
264293

0 commit comments

Comments
 (0)