diff --git a/Cargo.lock b/Cargo.lock index 7b057f6..b257d33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -444,6 +444,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "geoutils" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36d244a08113319b5ebcabad2b8b7925732d15eec46d7e7ac3c11734f3b7a6ad" + [[package]] name = "getrandom" version = "0.2.8" @@ -1813,6 +1819,7 @@ name = "xpin" version = "0.1.0" dependencies = [ "csv", + "geoutils", "s2", "serde", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 42143c9..30f45c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,4 +22,5 @@ words = {path="./words"} [dev-dependencies] csv = "1.1" +geoutils = "0.5.1" serde={version="1", features=["derive"]} diff --git a/tests/algorithm.rs b/tests/algorithm.rs index 926089d..e664f09 100644 --- a/tests/algorithm.rs +++ b/tests/algorithm.rs @@ -23,51 +23,36 @@ fn test_invalid_lat_lon() { #[test] fn test_decoding_lat_lon() { - let mut max = f64::MIN; - let mut min = f64::MAX; + let mut max_error_m = f64::MIN; + let mut min_error_m = f64::MAX; for (idx, entry) in test_events().iter().enumerate() { eprintln!("Testing row {idx}"); let addr = Address::from_lat_lon(entry.lat, entry.lon).unwrap(); let addr_latlon = addr.as_lat_lon(); - let (lat_diff, lon_diff) = ( - (entry.lat - addr_latlon.0).abs(), - (entry.lon - addr_latlon.1).abs(), - ); + // The difference between the input lat/lon and the encoded-then-decoded lat/lon + // This distance is essentially the error + // If you pick a point on the map, this is how far off the encoded point actually represents + let difference_m = approx_geodetic_difference_m(addr_latlon, (entry.lat, entry.lon)); - min = if lat_diff < min { - lat_diff - } else if lon_diff < min { - lon_diff - } else { - min - }; - - max = if lat_diff > max && lat_diff < 1_f64 { - lat_diff - } else if lon_diff > max && lon_diff < 1_f64 { - lon_diff - } else { - max - }; - - if lat_diff > 0.01_f64 || lon_diff > 0.01_f64 { - eprintln!( - "Uh oh: {lat_diff}, {lon_diff}, ({}, {}) => ({:?}) => ({:?})", - entry.lat, entry.lon, addr, addr_latlon - ); + // Compute the max and min differences for fun + if difference_m > max_error_m { + eprintln!("Setting max to {difference_m}"); + max_error_m = difference_m; + } + if difference_m < min_error_m { + min_error_m = difference_m; } + eprintln!("Distance in meters: {:?}", difference_m); + // Ensure the distance is not more than the allowed distance - // assert!( - // approx_geodetic_difference_m(addr_latlon, (entry.lat, entry.lon)) - // < ALLOWED_DISTANCE_ERROR_M - // ); + assert!(difference_m <= ALLOWED_DISTANCE_ERROR_M); // assert_eq!((entry.lat, entry.lon), (latlon.0, latlon.1)); } - eprintln!("Got max: {max} and min: {min}"); + eprintln!("Got max: {max_error_m} and min: {min_error_m}"); } #[test] diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 1a3436a..03b2b0a 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1,4 +1,5 @@ #![allow(dead_code)] +use geoutils::Location; use std::fs::File; use csv::ReaderBuilder; @@ -7,7 +8,9 @@ use serde::{Deserialize, Serialize}; /// The allowed error for encoding and decoding points, in meters /// /// Due to the selected S2 level being 23, our error is expected to be under 2 meters -pub const ALLOWED_DISTANCE_ERROR_M: f64 = 0.0_f64; +/// +/// With the encoding I selected, the max difference of my sample data actually fits in under 1 meter! +pub const ALLOWED_DISTANCE_ERROR_M: f64 = 1.0_f64; // The earth's approximate latitude circumfrence pub const EARTH_CIRCUMFERENCE_LAT: f64 = 0.0_f64; // The earth's approximate longitude circumfrence @@ -62,7 +65,10 @@ pub struct TestEntry { pub cellid: u64, } -/// Gets the approximate geodetic difference in meters between two latlons +/// Gets the approximate geodetic difference in meters between two latlons in meters pub fn approx_geodetic_difference_m((lat1, lon1): (f64, f64), (lat2, lon2): (f64, f64)) -> f64 { - 1000.0_f64 + Location::new(lat1, lon1) + .distance_to(&Location::new(lat2, lon2)) + .unwrap() + .meters() }