Start implementing version 0

This commit is contained in:
Austen Adler 2023-02-16 00:11:36 -05:00
parent 9a6a68d2a7
commit d990e98de9
5 changed files with 109 additions and 6 deletions

View File

@ -10,6 +10,10 @@
= Algorithm = Algorithm
The goal of this document is to define the algorithm.
If you want to see the steps to get to this definition, go to link:DESIGN.html[DESIGN].
== Data format == Data format
[source,title='this_algorithm and S2 CellID Format'] [source,title='this_algorithm and S2 CellID Format']
@ -21,9 +25,9 @@ WORD0 (13 bits) : | | |vvvvvv vvvvvvv
0000 (10 bits) : | | | |vvvvvvvvv v 0000 (10 bits) : | | | |vvvvvvvvv v
Not represented : | | | | | Not represented : | | | | |
: | | | | | : | | | | |
Bit : 64 52 48 39 32 26 16 1 Bit : 63 51 48 38 32 25 16| 0
: | | | | | | | | : | | | | | | | | |
: 0100101110101000 1011100010010011 1001001100100l00 1100000000000000 : 0100101110101000 1011100010010011 1001001100100100 1100000000000000
=== S2 CellID Format === | | || | === S2 CellID Format === | | || |
Face number : ^^^ || | Face number : ^^^ || |
Data bits : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^| | Data bits : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^| |

View File

@ -12,6 +12,8 @@
The goal of this document is to walk through how the design was chosen. The goal of this document is to walk through how the design was chosen.
If you want to see the algorithm definition, go to link:ALGORITHM.html[ALGORITHM].
== 10,000 meter view == 10,000 meter view
This project allows anyone to address ~1 square meter of land by bringing together: This project allows anyone to address ~1 square meter of land by bringing together:
@ -423,7 +425,7 @@ data_bits = level * 2 = 23 * 2 = 46
Bit : 64 48 32 16 1 Bit : 64 48 32 16 1
: | | | | | : | | | | |
: 01001011101010001011100010010011 1001001100100l001100000000000000 : 01001011101010001011100010010011 10010011001001001100000000000000
Face number : ^^^ Face number : ^^^
Data bits : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ Data bits : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
Bit after data bits (1) : ^ Bit after data bits (1) : ^
@ -486,7 +488,7 @@ Data bits : vvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvv
Face number : vvv Face number : vvv
Bit : 64 48 32 16 1 Bit : 64 48 32 16 1
: | | | | | : | | | | |
: 01001011101010001011100010010011 1001001100100l001100000000000000 : 01001011101010001011100010010011 10010011001001001100000000000000
Not represented : ^^^^^^^^^^^^^^^ Not represented : ^^^^^^^^^^^^^^^
0000 (10 bits) : ^^^^^^^^^^ 0000 (10 bits) : ^^^^^^^^^^
WORD0 (13 bits) : ^^^^^^ ^^^^^^^ WORD0 (13 bits) : ^^^^^^ ^^^^^^^

View File

@ -0,0 +1,34 @@
use std::ops::RangeInclusive;
use s2::{cellid::CellID, latlng::LatLng};
pub fn lat_lon_to_cellid(lat: f64, lon: f64) -> CellID {
Into::<CellID>::into(LatLng::from_degrees(lat, lon))
}
pub(crate) fn extract_binary(number: u64, range: RangeInclusive<usize>) -> u64 {
(number >> range.start()) & (u64::MAX >> (63 - (range.end() - range.start())))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_extract_binary() {
assert_eq!(extract_binary(0b0, 0..=0), 0b0);
assert_eq!(extract_binary(0b11_1111_11, 2..=5), 0b1111);
assert_eq!(extract_binary(0b11_0101_11, 2..=5), 0b0101);
assert_eq!(extract_binary(0b11_1100_11, 2..=5), 0b1100);
assert_eq!(extract_binary(0b111_10011_, 0..=4), 0b10011);
assert_eq!(extract_binary(0b111100_1_1, 1..=1), 0b1);
assert_eq!(extract_binary(0b111100_0_1, 1..=1), 0b0);
// A full test from the docs
let cell_id = 0b0100101110101000_1011100010010011_1001001100100100_1100000000000000_u64;
assert_eq!(extract_binary(cell_id, 15..=24), 0b10_01001001);
assert_eq!(extract_binary(cell_id, 25..=37), 0b01001_11001001);
assert_eq!(extract_binary(cell_id, 38..=50), 0b00010_11100010);
assert_eq!(extract_binary(cell_id, 51..=63), 0b01001_01110101);
}
}

View File

@ -2,14 +2,18 @@
#![allow(clippy::cast_possible_truncation, clippy::multiple_crate_versions)] #![allow(clippy::cast_possible_truncation, clippy::multiple_crate_versions)]
#![allow(unused_imports)] #![allow(unused_imports)]
pub mod v0;
use conversions::lat_lon_to_cellid;
pub use s2::s1::angle::Angle;
use std::{ use std::{
fmt::Display, fmt::Display,
ops::{Add, AddAssign}, ops::{Add, AddAssign},
str::FromStr, str::FromStr,
}; };
mod conversions;
use thiserror::Error; use thiserror::Error;
use s2::cellid::CellID; use s2::{cellid::CellID, latlng::LatLng, s1::Deg};
use words::Word; use words::Word;
pub type Number = u32; pub type Number = u32;
@ -92,6 +96,24 @@ impl FromStr for Address<'_> {
} }
impl Address<'_> { impl Address<'_> {
pub fn from_lat_lon(lat: f64, lon: f64) -> Self {
let cellid = conversions::lat_lon_to_cellid(lat, lon);
v0::UnpackedCellID::from(cellid).into()
// Self::cellid_to_v0(&cellid)
}
// fn cellid_to_v0(cell_id: &CellID) -> Self {
// // The raw binary representation of the cellid
// let raw_cellid = cell_id.0;
// // Self {
// // number,
// // words: words.into_inner().unwrap(),
// // }
// }
fn parse_v0(number: Number, word_components: Vec<&str>) -> Result<Self, Error> { fn parse_v0(number: Number, word_components: Vec<&str>) -> Result<Self, Error> {
if !(V0_MIN_NUMBER..=V0_MAX_NUMBER).contains(&number) { if !(V0_MIN_NUMBER..=V0_MAX_NUMBER).contains(&number) {
return Err(Error::NumberOutOfRange(number)); return Err(Error::NumberOutOfRange(number));

41
this_algorithm/src/v0.rs Normal file
View File

@ -0,0 +1,41 @@
use crate::{conversions, Address};
use std::ops::RangeInclusive;
use s2::{cell::Cell, cellid::CellID};
pub struct UnpackedCellID {
pub number_bits: u16,
pub word0_bits: u16,
pub word1_bits: u16,
pub word2_bits: u16,
}
impl From<CellID> for UnpackedCellID {
fn from(cell_id: CellID) -> Self {
Self::from(cell_id.0)
}
}
impl From<u64> for UnpackedCellID {
fn from(cell_id: u64) -> Self {
Self {
number_bits: conversions::extract_binary(cell_id, 15..=24) as u16,
word0_bits: conversions::extract_binary(cell_id, 25..=37) as u16,
word1_bits: conversions::extract_binary(cell_id, 38..=50) as u16,
word2_bits: conversions::extract_binary(cell_id, 51..=63) as u16,
}
}
}
impl From<UnpackedCellID> for Address<'_> {
fn from(unpacked_cell_id: UnpackedCellID) -> Self {
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];
Self {
number: unpacked_cell_id.number_bits as u32,
words: [word0, word1, word2],
}
}
}