use std::ops::{Add, Sub};
use std::result::Result;
use h3ron_h3_sys::H3Index;
use crate::error::Error;
use crate::H3Cell;
use crate::Index;
#[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 {
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))
}
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();
let coordij_origin = origin_cell.to_localij(origin_cell).unwrap();
let coordij_other = other_cell.to_localij(origin_cell).unwrap();
let coordij_diff = coordij_origin - coordij_other;
assert!(coordij_diff.i.abs() <= 1);
assert!(coordij_diff.j.abs() <= 1);
let other_cell_2 = H3Cell::from_localij(origin_cell, coordij_other).unwrap();
assert_eq!(other_cell, other_cell_2);
}
}