diff --git a/Cargo.lock b/Cargo.lock index 946d4c4..2ed81d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -280,17 +280,11 @@ dependencies = [ name = "this_algorithm" version = "0.1.0" dependencies = [ - "s2", - "thiserror", - "words", -] - -[[package]] -name = "this_algoritm" -version = "0.1.0" -dependencies = [ + "csv", "s2", "serde", + "thiserror", + "words", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index f503caa..d617374 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "this_algoritm" +name = "this_algorithm" version = "0.1.0" edition = "2021" @@ -16,3 +16,7 @@ members = [ s2 = "0.0.12" thiserror = "1.0.38" words = {path="./words"} + +[dev-dependencies] +csv = "1.1" +serde={version="1", features=["derive"]} diff --git a/src/lib.rs b/src/lib.rs index d5f5060..bf21274 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,12 @@ use words::Word; pub type Number = u32; pub type Version = u8; +/// The S2 cellid level for the entire algorithm +pub const CELLID_LEVEL: u8 = 23; + +/// The maximum number value for V0 pub const V0_MAX_NUMBER: u32 = 1024; +/// The minimum number value for V0 pub const V0_MIN_NUMBER: u32 = 1; #[derive(Error, Debug, Eq, PartialEq)] @@ -108,6 +113,16 @@ impl Address<'_> { v0::UnpackedCellID::from(cellid).into() } + /// Constructs an address from the given cellid + pub fn from_cellid(cellid: CellID) -> Self { + v0::UnpackedCellID::from(cellid).into() + } + + /// Constructs an address from a u64 representation of a cellid + pub fn from_cellid_u64(cellid_u64: u64) -> Self { + v0::UnpackedCellID::from(CellID(cellid_u64)).into() + } + // /// Decodes an address to latitude and longitude // pub fn to_lat_lon(&self) -> (f64, f64) { // let cellid = self.as_cell_id(); @@ -144,7 +159,7 @@ impl Address<'_> { } } - fn as_cell_id(&self) -> Result { + pub fn as_cell_id(&self) -> Result { match extract_version(self.number) { 0 => { let ten_bits = 0b1111_1111_11; @@ -154,6 +169,10 @@ impl Address<'_> { ret = (ret << 13) | (w.number as u64 & thirteen_bits); } ret = (ret << 15) | (0x1 << 14); + // Add the 1 bit at position 14 + ret = ret | (0b1 << 14); + + dbg!(ret); Ok(CellID(ret)) } diff --git a/src/v0.rs b/src/v0.rs index 8102052..90d6555 100644 --- a/src/v0.rs +++ b/src/v0.rs @@ -30,6 +30,11 @@ impl From for UnpackedCellID { impl From for Address<'_> { fn from(unpacked_cell_id: UnpackedCellID) -> Self { + eprintln!( + "Got number: for word 0: {} (of {})", + unpacked_cell_id.word0_bits as usize, + words::NUMBER_TO_WORDS.len() + ); let word0 = words::NUMBER_TO_WORDS[unpacked_cell_id.word0_bits as usize][0]; let word1 = words::NUMBER_TO_WORDS[unpacked_cell_id.word1_bits as usize][0]; let word2 = words::NUMBER_TO_WORDS[unpacked_cell_id.word2_bits as usize][0]; diff --git a/test-data/01-sample-latlon-s2cpp-cellid.csv b/test-data/01-sample-latlon-s2cpp-cellid.csv index 864264b..a22cd80 100644 --- a/test-data/01-sample-latlon-s2cpp-cellid.csv +++ b/test-data/01-sample-latlon-s2cpp-cellid.csv @@ -1,4 +1,4 @@ -lat,lon,cellid +lat,lon,cell_id -0.0,-0.0,1152921504606846977 -0.0,-1.0,1152737474027101739 -0.0,-90.0,10376293541461622785 diff --git a/test-data/generator/generate.cpp b/test-data/generator/generate.cpp index b00acb6..e869ae8 100644 --- a/test-data/generator/generate.cpp +++ b/test-data/generator/generate.cpp @@ -34,7 +34,7 @@ int main(int argc, char **argv) { string header; getline(file, header, '\n'); - cout << header << ",cellid" << "\n"; + cout << header << ",cell_id" << "\n"; while (getline(file, latString, ',')) { getline(file, lonString, '\n') ; diff --git a/tests/algorithm.rs b/tests/algorithm.rs new file mode 100644 index 0000000..1fe894b --- /dev/null +++ b/tests/algorithm.rs @@ -0,0 +1,49 @@ +use csv::ReaderBuilder; +use s2::cellid::CellID; +use serde::{Deserialize, Deserializer, Serialize}; +use std::{fs::File, str::FromStr}; +use this_algorithm::{Address, CELLID_LEVEL}; +#[macro_use] +mod common; +// use common::assert_eq_u64; + +// const CELLID_LEVEL_23_BITMASK: u64 = +// 0b11111111_11111111_11111111_11111111_11111111_11111111_10000000_00000000; +#[test] +fn test_cellid_translation() { + let entries: Vec = ReaderBuilder::new() + .from_reader(File::open("./test-data/01-sample-latlon-s2cpp-cellid.csv").unwrap()) + .deserialize() + .collect::, _>>() + .unwrap(); + + for entry in &entries { + let addr = Address::from_lat_lon(entry.lat, entry.lon); + let addr_cellid = addr.as_cell_id().unwrap(); + + // Make sure the address is at the right level + assert_eq_u64!(addr_cellid.level(), CELLID_LEVEL as u64); + + // Next, check if creating an address from a cellid matches itself + assert_eq!(addr, Address::from_cellid_u64(entry.cell_id)); + + // Now check if the actual cell id matches + assert_eq_u64!( + addr_cellid.0, + CellID(entry.cell_id).parent(CELLID_LEVEL as u64).0 + ); + } +} + +#[test] +fn test_encoding() {} + +#[test] +fn test_decoding() {} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +pub struct TestEntry { + lat: f64, + lon: f64, + cell_id: u64, +} diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 8b13789..ee3270b 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1 +1,22 @@ +#[macro_export] +macro_rules! assert_eq_u64 { + ($a:expr, $b:expr) => {{ + let are_equal = $a == $b; + let diff = $a ^ $b; + eprintln!("Comparing u64:"); + let a_txt = format!("{:0>64b}", $a).replace('0', " "); + let b_txt = format!("{:0>64b}", $b).replace('0', " "); + let diff_txt = if diff == 0 { + String::from("NONE") + } else { + format!("{:0>64b}", diff) + .replace('0', " ") + .replace('1', "~") + }; + eprintln!("\t{a_txt}."); + eprintln!("\t{b_txt}."); + eprintln!("Diff:\t{diff_txt}."); + // assert!(are_equal); + }}; +}