1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
use std::ops::{Add, Sub};
use std::result::Result;
use h3ron_h3_sys::H3Index;
use crate::error::Error;
use crate::H3Cell;
use crate::Index;
/// [`CoordIj`] coordinates for [`H3Cell`] anchored by an origin [`H3Cell`].
///
/// Thus coordinate space may have deleted regions or warping due
/// to pentagonal distortion.
///
/// This values are not guaranteed
/// to be compatible across different versions of H3.
#[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
pub struct CoordIj {
pub i: i32,
pub j: i32,
}
impl Sub for CoordIj {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self {
i: self.i - rhs.i,
j: self.j - rhs.j,
}
}
}
impl Add for CoordIj {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self {
i: self.i + rhs.i,
j: self.j + rhs.j,
}
}
}
impl From<h3ron_h3_sys::CoordIJ> for CoordIj {
fn from(sys_cij: h3ron_h3_sys::CoordIJ) -> Self {
Self {
i: sys_cij.i,
j: sys_cij.j,
}
}
}
impl From<CoordIj> for h3ron_h3_sys::CoordIJ {
fn from(coordij: CoordIj) -> Self {
Self {
i: coordij.i,
j: coordij.j,
}
}
}
impl H3Cell {
/// Produces an [`H3Cell`] for the given `coordij` coordinates anchored by `origin_cell`.
///
/// The coordinate space used by this function may have deleted
/// regions or warping due to pentagonal distortion.
///
/// Failure may occur if the index is too far away from the origin
/// or if the index is on the other side of a pentagon.
///
/// This function's output is not guaranteed
/// to be compatible across different versions of H3.
pub fn from_localij(origin_cell: Self, coordij: CoordIj) -> Result<Self, Error> {
let cij: h3ron_h3_sys::CoordIJ = coordij.into();
let mut h3_index_out: H3Index = 0;
Error::check_returncode(unsafe {
h3ron_h3_sys::localIjToCell(origin_cell.h3index(), &cij, 0, &mut h3_index_out)
})?;
Ok(Self::new(h3_index_out))
}
/// Produces [`CoordIj`] coordinates for this [`H3Cell`] instance anchored by an origin [`H3Cell`] `origin_cell`.
///
/// The coordinate space used by this function may have deleted
/// regions or warping due to pentagonal distortion.
///
/// Failure may occur if the index is too far away from the origin
/// or if the index is on the other side of a pentagon.
///
/// This function's output is not guaranteed
/// to be compatible across different versions of H3.
pub fn to_localij(&self, origin_cell: Self) -> Result<CoordIj, Error> {
let mut cij = h3ron_h3_sys::CoordIJ { i: 0, j: 0 };
Error::check_returncode(unsafe {
h3ron_h3_sys::cellToLocalIj(origin_cell.h3index(), self.h3index(), 0, &mut cij)
})?;
Ok(cij.into())
}
}
#[cfg(test)]
mod tests {
use crate::H3Cell;
#[test]
fn test_local_ij() {
let origin_cell = H3Cell::try_from(0x89283080ddbffff_u64).unwrap();
let ring = origin_cell.grid_disk(1).unwrap();
assert_ne!(ring.iter().count(), 0);
let other_cell = ring.iter().find(|i| *i != origin_cell).unwrap();
// the coordij of the origin index. This is not necessarily at (0, 0)
let coordij_origin = origin_cell.to_localij(origin_cell).unwrap();
// the coordij of the other index in the coordinate system of the origin index
let coordij_other = other_cell.to_localij(origin_cell).unwrap();
// As the other_index was taken from k_ring 1, the difference of the i and j coordinates
// must be -1, 0 or 1
let coordij_diff = coordij_origin - coordij_other;
assert!(coordij_diff.i.abs() <= 1);
assert!(coordij_diff.j.abs() <= 1);
// convert the coordij back to an index
let other_cell_2 = H3Cell::from_localij(origin_cell, coordij_other).unwrap();
assert_eq!(other_cell, other_cell_2);
}
}