Skip to content

Commit

Permalink
add are_antipodal
Browse files Browse the repository at this point in the history
  • Loading branch information
VascoSch92 committed Jan 24, 2025
1 parent 1aa0dc3 commit f9c7e0f
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 56 deletions.
21 changes: 3 additions & 18 deletions src/earth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ fn convert_degrees_to_radians(lat1: f64, lon1: f64, lat2: f64, lon2: f64) -> (f6
(lat1, lon1, lat2, lon2)
}

fn are_antipodal(lat1: f64, lon1: f64, lat2: f64, lon2: f64) -> bool {
#[pyfunction]
#[pyo3(signature = (lat1, lon1, lat2, lon2))]
pub fn are_antipodal(lat1: f64, lon1: f64, lat2: f64, lon2: f64) -> bool {
let lat_condition = lat1 == -lat2;

let lon_difference = (lon1 - lon2).abs();
Expand Down Expand Up @@ -364,21 +366,4 @@ mod tests {
let (lat1, _, _, _) = convert_degrees_to_radians(0.0001, 0.0, 0.0, 0.0);
assert!((lat1 - 1.7453292519943295e-6).abs() < EPSILON);
}

#[test]
fn test_antipodal_points() {
assert!(are_antipodal(90.0, 0.0, -90.0, 0.0));
assert!(are_antipodal(0.0, 0.0, 0.0, 180.0));
assert!(are_antipodal(45.0, 90.0, -45.0, -90.0));
assert!(are_antipodal(-30.0, 60.0, 30.0, -120.0));
assert!(are_antipodal(20.0, -50.0, -20.0, 130.0));
assert!(are_antipodal(-15.0, 10.0, 15.0, -170.0));
}

#[test]
fn test_non_antipodal_points() {
assert!(!are_antipodal(0.0, 0.0, 0.0, 0.0));
assert!(!are_antipodal(10.0, 10.0, 10.0, 10.0));
assert!(!are_antipodal(-41.12, 30.0, 23.0, -17.0));
}
}
38 changes: 6 additions & 32 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,47 +1,20 @@
use std::fs;
use std::path::Path;

#[allow(unused_imports)]
use pyo3::prelude::*;
use toml::Value;

#[allow(unused_imports)]
use earth::{
bearing, destination, great_circle_distance, haversine_distance, tunnel_distance,
vincenty_distance, CIRCUMFERENCE as EARTH_CIRCUMFERENCE, FLATTENING as EARTH_FLATTENING,
RADIUS as EARTH_RADIUS, SEMI_MAJOR_AXIS as EARTH_SEMI_MAJOR_AXIS,
SEMI_MINOR_AXIS as EARTH_SEMI_MINOR_AXIS,
are_antipodal, bearing, destination, great_circle_distance, haversine_distance,
tunnel_distance, vincenty_distance, CIRCUMFERENCE as EARTH_CIRCUMFERENCE,
FLATTENING as EARTH_FLATTENING, RADIUS as EARTH_RADIUS,
SEMI_MAJOR_AXIS as EARTH_SEMI_MAJOR_AXIS, SEMI_MINOR_AXIS as EARTH_SEMI_MINOR_AXIS,
};

mod earth;

fn get_rustileo_version() -> Option<String> {
// Path to the Cargo.toml file
let cargo_toml_path = Path::new("Cargo.toml");

// Check if the file exists
if !cargo_toml_path.exists() {
return None;
}

// Read the contents of the file
let cargo_toml_content = fs::read_to_string(cargo_toml_path).ok()?;

// Parse the contents as TOML
let parsed_toml: Value = cargo_toml_content.parse::<Value>().ok()?;

// Extract the version from the [package] section
parsed_toml
.get("package")?
.get("version")?
.as_str()
.map(|s| s.to_string())
}

/// A Python module implemented in Rust.
#[pymodule]
fn rustileo(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add("__version__", get_rustileo_version())?;
m.add("__version__", "0.1.0")?;

let earth = PyModule::new(py, "earth")?;

Expand All @@ -53,6 +26,7 @@ fn rustileo(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
earth.add("FLATTENING", EARTH_FLATTENING)?;

// methods
earth.add_function(wrap_pyfunction!(are_antipodal, py)?)?;
earth.add_function(wrap_pyfunction!(great_circle_distance, py)?)?;
earth.add_function(wrap_pyfunction!(tunnel_distance, py)?)?;
earth.add_function(wrap_pyfunction!(haversine_distance, py)?)?;
Expand Down
29 changes: 23 additions & 6 deletions tests/test_earth.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,7 @@ def test_tunnel_distance_exceptions(lat1, lon1, lat2, lon2, error, error_msg):
(34.0522, -118.2437, 35.6895, 139.6917, 0.05, 8815),
],
)
def test_haversine_and_great_circle_distance(
lat1, lon1, lat2, lon2, rel_tol, expected_value
):
def test_haversine_and_great_circle_distance(lat1, lon1, lat2, lon2, rel_tol, expected_value):
computed_value_haversine = earth.haversine_distance(lat1, lon1, lat2, lon2)
computed_value_great_circle = earth.great_circle_distance(lat1, lon1, lat2, lon2)
msg = f"Expected: {expected_value}. Got {computed_value_haversine}"
Expand Down Expand Up @@ -220,9 +218,9 @@ def test_bearing_exceptions(lat1, lon1, lat2, lon2, error, error_msg):
def test_destination(lat, lon, distance, bearing, rel_tol, expected_lat, expected_lon):
computed_value = earth.destination(lat, lon, distance, bearing)
msg = f"Expected: ({expected_lat}, {expected_lon}). Got {computed_value}"
if not math.isclose(
computed_value[0], expected_lat, rel_tol=rel_tol
) or not math.isclose(computed_value[1], expected_lon, rel_tol=rel_tol):
if not math.isclose(computed_value[0], expected_lat, rel_tol=rel_tol) or not math.isclose(
computed_value[1], expected_lon, rel_tol=rel_tol
):
raise AssertionError(msg)


Expand All @@ -237,3 +235,22 @@ def test_destination(lat, lon, distance, bearing, rel_tol, expected_lat, expecte
def test_destination_exceptions(lat, lon, distance, bearing, error, error_msg):
with pytest.raises(error, match=error_msg):
_ = earth.destination(lat, lon, distance, bearing)


@pytest.mark.parametrize(
"lat1, lon1, lat2, lon2, expected",
[
(90.0, 0.0, -90.0, 0.0, True),
(0.0, 0.0, 0.0, 180.0, True),
(45.0, 90.0, -45.0, -90.0, True),
(-30.0, 60.0, 30.0, -120.0, True),
(20.0, -50.0, -20.0, 130.0, True),
(-15.0, 10.0, 15.0, -170.0, True),
(0.0, 0.0, 0.0, 0.0, False),
(10.0, 10.0, 10.0, 10.0, False),
(-41.12, 30.0, 23.0, -17.0, False),
],
)
def test_are_antipodal(lat1, lon1, lat2, lon2, expected):
result = earth.are_antipodal(lat1, lon1, lat2, lon2)
assert result == expected

0 comments on commit f9c7e0f

Please sign in to comment.