Skip to content

Commit

Permalink
refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
VascoSch92 committed Jan 27, 2025
1 parent aae3144 commit 4555e4b
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 193 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ fastbuild:
@uv pip uninstall rustileo
@echo "[INFO] Clean uv cache"
@uv cache clean
@make init-dev
@echo "[INFO] Run test"
@uv run pytest .

Expand Down
5 changes: 5 additions & 0 deletions src/earth/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub const RADIUS: f64 = 6371.0; // km
pub const CIRCUMFERENCE: f64 = 40075.0; // km
pub const SEMI_MAJOR_AXIS: f64 = 6378.137; // km
pub const SEMI_MINOR_AXIS: f64 = 6_356.752_4; // km
pub const FLATTENING: f64 = 1.0 / 298.257_23;
110 changes: 110 additions & 0 deletions src/earth/coordinates.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
use crate::earth::constants::RADIUS;

pub struct Coordinate {
lat: f64,
lon: f64,
}

impl Coordinate {
pub fn new(lat: f64, lon: f64) -> Result<Self, String> {
if let Err(msg) = Self::validate_coordinate(lat, lon) {
Err(msg)
} else {
Ok(Self { lat, lon })
}
}

fn validate_coordinate(lat: f64, lon: f64) -> Result<(), String> {
if !(-90.0..=90.0).contains(&lat) {
return Err("Latitude must be between -90 and 90 degrees.".to_string());
}
if !(-180.0..=180.0).contains(&lon) {
return Err("Longitude must be between -180 and 180 degrees.".to_string());
}
Ok(())
}

pub fn in_radians(self) -> (f64, f64) {
(self.lat.to_radians(), self.lon.to_radians())
}

pub fn in_cartesian(self) -> (f64, f64, f64) {
let (lat, lon) = self.in_radians();
(
RADIUS * lat.cos() * lon.cos(),
RADIUS * lat.cos() * lon.sin(),
RADIUS * lat.sin(),
)
}
}

#[cfg(test)]
mod tests {
use super::*;
use std::f64::consts::PI;

#[test]
fn test_coordinate_construction() {
let coordinate_1 = Coordinate::new(0.0, 0.0).unwrap();
assert_eq!(coordinate_1.lat, 0.0);
assert_eq!(coordinate_1.lon, 0.0);

let coordinate_2 = Coordinate::new(-90.0, 180.0).unwrap();
assert_eq!(coordinate_2.lat, -90.0);
assert_eq!(coordinate_2.lon, 180.0);

let coordinate_3 = Coordinate::new(90.0, -180.0).unwrap();
assert_eq!(coordinate_3.lat, 90.0);
assert_eq!(coordinate_3.lon, -180.0);
}

#[test]
fn test_wrong_coordinates() {
let coordinate_1 = Coordinate::new(-91.0, 0.0);
assert!(
coordinate_1.is_err(),
"Latitude must be between -90 and 90 degrees."
);

let coordinate_2 = Coordinate::new(91.0, 0.0);
assert!(
coordinate_2.is_err(),
"Latitude must be between -90 and 90 degrees."
);

let coordinate_3 = Coordinate::new(0.0, 181.0);
assert!(
coordinate_3.is_err(),
"Longitude must be between -180 and 180 degrees."
);

let coordinate_4 = Coordinate::new(0.0, -181.0);
assert!(
coordinate_4.is_err(),
"Latitude must be between -180 and 180 degrees."
);
}

#[test]
fn test_to_radians() {
// Test zero coordinates
let coordinate_1 = Coordinate::new(0.0, 0.0).unwrap();
assert_eq!(coordinate_1.in_radians(), (0.0, 0.0));

// Test 90 degree coordinates
let coordinate_2 = Coordinate::new(90.0, 90.0).unwrap();
assert_eq!(coordinate_2.in_radians(), (PI / 2.0, PI / 2.0));

// Test negative coordinates with mixed angles
let coordinate_3 = Coordinate::new(-45.0, -180.0).unwrap();
assert_eq!(coordinate_3.in_radians(), (-PI / 4.0, -PI));

// Test extreme negative latitude with smaller longitude
let coordinate_4 = Coordinate::new(-90.0, -30.0).unwrap();
assert_eq!(coordinate_4.in_radians(), (-PI / 2.0, -PI / 6.0));

// Test coordinates at common angles
let coordinate_5 = Coordinate::new(30.0, 60.0).unwrap();
assert_eq!(coordinate_5.in_radians(), (PI / 6.0, PI / 3.0));
}
}
Loading

0 comments on commit 4555e4b

Please sign in to comment.