use super::gaussint::GaussInt;
use super::zzbase::ZZNum;
use num_traits::One;
use std::collections::HashMap;
pub fn revcomp(angles: &[i8]) -> Vec<i8> {
angles.iter().rev().map(|a| -a).collect()
}
pub fn normalize_angle<T: ZZNum>(angle: i8) -> i8 {
let a = angle % T::turn();
if a.abs() <= T::hturn() {
a
} else {
-(a.signum() * T::turn() - a)
}
}
pub fn cell_of<T: ZZNum>(zz: T) -> GaussInt<i64> {
let c = zz.complex();
GaussInt {
real: c.re.round() as i64,
imag: c.im.round() as i64,
}
}
pub fn cell_neighborhood_of<T: ZZNum>(zz: T) -> Vec<GaussInt<i64>> {
let c = cell_of(zz);
let r = GaussInt::new(c.real + 1, c.imag);
let l = GaussInt::new(c.real - 1, c.imag);
let u = GaussInt::new(c.real, c.imag + 1);
let d = GaussInt::new(c.real, c.imag - 1);
vec![l, d, c, u, r] }
pub fn seg_neighborhood_of<T: ZZNum>(p1: T, p2: T) -> Vec<GaussInt<i64>> {
let mut result = cell_neighborhood_of(p1);
result.extend(cell_neighborhood_of(p2));
result.sort();
result.dedup();
result
}
pub fn indices_from_cells(
lattice: &HashMap<GaussInt<i64>, Vec<usize>>,
cells: &[GaussInt<i64>],
) -> Vec<usize> {
let mut pt_indices: Vec<usize> = Vec::new();
for cell in cells {
lattice.get(&cell).and_then(|pts| {
pt_indices.extend(pts);
None::<()>
});
}
pt_indices
}
fn is_ccw<T: ZZNum>(a: T, b: T, c: T) -> bool {
(b - a).wedge(&(c - a)).re_signum().is_one()
}
pub fn intersect<T: ZZNum>(&(a, b): &(T, T), &(c, d): &(T, T)) -> bool {
let l_ab = a.line_through(&b);
if c.is_colinear(&l_ab) && d.is_colinear(&l_ab) {
c.is_between(&a, &b) || d.is_between(&a, &b)
} else {
if a == c || a == d || b == c || b == d {
false } else {
is_ccw(a, c, d) != is_ccw(b, c, d) && is_ccw(a, b, c) != is_ccw(a, b, d)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::zz::ZZ12;
use crate::zzbase::ZZBase;
use num_traits::{One, Zero};
#[test]
fn test_revcomp() {
assert_eq!(revcomp(vec![].as_slice()), vec![]);
assert_eq!(revcomp(vec![6].as_slice()), vec![-6]);
let v = vec![1, 3, -2, 4];
assert_eq!(revcomp(v.as_slice()), vec![-4, 2, -3, -1]);
assert_eq!(revcomp(revcomp(v.as_slice()).as_slice()).as_slice(), v);
}
#[test]
fn test_normalize_angles() {
assert_eq!(normalize_angle::<ZZ12>(0), 0);
assert_eq!(normalize_angle::<ZZ12>(1), 1);
assert_eq!(normalize_angle::<ZZ12>(-1), -1);
assert_eq!(normalize_angle::<ZZ12>(5), 5);
assert_eq!(normalize_angle::<ZZ12>(-5), -5);
assert_eq!(normalize_angle::<ZZ12>(6), 6);
assert_eq!(normalize_angle::<ZZ12>(-6), -6);
assert_eq!(normalize_angle::<ZZ12>(7), -5);
assert_eq!(normalize_angle::<ZZ12>(-7), 5);
assert_eq!(normalize_angle::<ZZ12>(11), -1);
assert_eq!(normalize_angle::<ZZ12>(-11), 1);
assert_eq!(normalize_angle::<ZZ12>(12), 0);
assert_eq!(normalize_angle::<ZZ12>(-12), 0);
assert_eq!(normalize_angle::<ZZ12>(13), 1);
assert_eq!(normalize_angle::<ZZ12>(-13), -1);
}
#[test]
fn test_indices_from_cells() {
let grid: HashMap<GaussInt<i64>, Vec<usize>> = HashMap::from([
(GaussInt::new(0, 0), vec![0, 1]),
(GaussInt::new(1, 0), vec![2, 0]),
]);
assert_eq!(indices_from_cells(&grid, &[GaussInt::new(0, 0)]), &[0, 1]);
assert_eq!(indices_from_cells(&grid, &[GaussInt::new(1, 0)]), &[2, 0]);
assert_eq!(indices_from_cells(&grid, &[GaussInt::new(2, 0)]), &[]);
assert_eq!(
indices_from_cells(
&grid,
&[
GaussInt::new(2, 0),
GaussInt::new(1, 0),
GaussInt::new(0, 0)
]
),
&[2, 0, 0, 1]
);
}
#[test]
fn test_intersect() {
let a: ZZ12 = ZZ12::zero();
let b: ZZ12 = ZZ12::one();
let c: ZZ12 = ZZ12::from(2);
let d: ZZ12 = ZZ12::from(3);
let e: ZZ12 = ZZ12::one_i();
let f: ZZ12 = b + e;
assert!(!intersect(&(a, b), &(c, d))); assert!(!intersect(&(d, c), &(a, b))); assert!(!intersect(&(a, b), &(b, c))); assert!(intersect(&(a, c), &(b, d))); assert!(intersect(&(a, d), &(b, c)));
assert!(!intersect(&(a, b), &(e, f)));
assert!(!intersect(&(a, e), &(b, f)));
assert!(!intersect(&(a, e), &(b, c))); assert!(!intersect(&(a, f), &(b, c)));
assert!(!intersect(&(a, e), &(a, b))); assert!(!intersect(&(a, f), &(a, b))); assert!(!intersect(&(a, e), &(e, e - b)));
assert!(intersect(&(b, f), &(a, c))); assert!(intersect(&(b, e), &(a, c)));
assert!(intersect(&(a, f), &(b, e))); assert!(intersect(&(a, f), &(c, e))); assert!(intersect(&(a, f), &(d, e))); }
}