use crate::geometry::point::Point;
use std::collections::VecDeque;
pub fn convex_hull(ps: Vec<(i64, i64)>) -> Vec<(i64, i64)> {
let n = ps.len();
let mut ps: Vec<Point<i64>> = ps.iter().map(|&(x, y)| Point::<i64>(x, y)).collect();
ps.sort();
let mut k = 0;
let mut deque: VecDeque<Point<i64>> = VecDeque::new();
for &pi in &ps {
while k > 1 && (deque[k - 1] - deque[k - 2]).det(pi - deque[k - 1]) <= 0 {
deque.pop_back();
k -= 1;
}
deque.push_back(pi);
k += 1;
}
let t = k;
for i in (0..n - 1).rev() {
let pi = ps[i];
while k > t && (deque[k - 1] - deque[k - 2]).det(pi - deque[k - 1]) <= 0 {
deque.pop_back();
k -= 1;
}
deque.push_back(pi);
k += 1;
}
let mut ret: Vec<(i64, i64)> = deque
.into_iter()
.take(k - 1)
.map(|pair| (pair.0, pair.1))
.collect();
ret.sort_unstable();
ret
}
#[cfg(test)]
mod test_convex_hull {
use crate::geometry::convex_hull;
#[test]
fn it_works() {
let ps = vec![(0, 0), (2, 2), (3, 1), (1, 4), (4, 4)];
let hull = convex_hull::convex_hull(ps);
assert_eq!(hull, vec![(0, 0), (1, 4), (3, 1), (4, 4)]);
let ps = vec![(0, 0), (2, 2), (4, 4)];
let hull = convex_hull::convex_hull(ps);
assert_eq!(hull, vec![(0, 0), (4, 4)]);
let ps = vec![(0, 0), (0, 1), (0, 2), (1, 1)];
let hull = convex_hull::convex_hull(ps);
assert_eq!(hull, vec![(0, 0), (0, 2), (1, 1)]);
}
}