1use std::collections::VecDeque;
2use std::ops::{Add, Div, Mul, Sub};
3
4#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
6pub struct Point<T>(pub T, pub T);
7
8impl<T: Add<T, Output = T>> std::ops::Add<Point<T>> for Point<T> {
9 type Output = Point<T>;
10 fn add(self, _rhs: Point<T>) -> Self::Output {
11 Point(self.0 + _rhs.0, self.1 + _rhs.1)
12 }
13}
14
15impl<T: Sub<T, Output = T>> std::ops::Sub<Point<T>> for Point<T> {
16 type Output = Point<T>;
17 fn sub(self, _rhs: Point<T>) -> Self {
18 Point(self.0 - _rhs.0, self.1 - _rhs.1)
19 }
20}
21
22impl<T: Copy + Mul<T, Output = T>> std::ops::Mul<T> for Point<T> {
23 type Output = Point<T>;
24 fn mul(self, k: T) -> Self {
25 Self(k * self.0, k * self.1)
26 }
27}
28
29impl<T: Copy + Div<T, Output = T>> std::ops::Div<T> for Point<T> {
30 type Output = Self;
31 fn div(self, k: T) -> Self {
32 Self(self.0 / k, self.1 / k)
33 }
34}
35
36impl<T: Mul<T, Output = T> + Sub<T, Output = T>> Point<T> {
37 pub fn det(self, _rhs: Point<T>) -> T {
38 self.0 * _rhs.1 - self.1 * _rhs.0
39 }
40}
41
42#[cfg(test)]
43mod test_point {
44 use crate::geometry::Point;
45
46 #[test]
47 fn it_works_i64() {
48 let p1: Point<i64> = Point(4, 6);
49 let p2 = Point(6, 4);
50
51 assert_eq!(p1 + p2, Point(10, 10));
52 assert_eq!(p1 - p2, Point(-2, 2));
53 assert_eq!(p1 * 4, Point(16, 24));
54 assert_eq!(p1 / 2, Point(2, 3));
55 }
56
57 #[test]
58 fn it_works_f64() {
59 let p1: Point<f64> = Point(4.0, 6.0);
60 let p2 = Point(6.0, 4.0);
61
62 assert_eq!(p1 + p2, Point(10.0, 10.0));
63 assert_eq!(p1 - p2, Point(-2.0, 2.0));
64 assert_eq!(p1 * 4.0, Point(16.0, 24.0));
65 assert_eq!(p1 / 2.0, Point(2.0, 3.0));
66 }
67}
68
69pub struct Line<T>(pub Point<T>, pub Point<T>);
70
71pub trait LineAPI<T> {
72 fn distance(&self, p: Point<T>) -> f64;
73 fn contains_point(&self, p: Point<T>) -> bool;
74}
75
76impl LineAPI<i64> for Line<i64> {
78 fn distance(&self, p: Point<i64>) -> f64 {
79 let v1 = self.1 - self.0;
80 let v2 = p - self.0;
81 let l1 = ((v1.0 * v1.0 + v1.1 * v1.1) as f64).sqrt();
82 let det = v1.det(v2) as f64;
83 det / l1
84 }
85
86 fn contains_point(&self, p: Point<i64>) -> bool {
87 let d = self.1 - self.0;
88 let e = p - self.0;
89 d.1 * e.0 == d.0 * e.1
90 }
91}
92
93impl LineAPI<f64> for Line<f64> {
95 fn distance(&self, p: Point<f64>) -> f64 {
96 let v1 = self.1 - self.0;
97 let v2 = p - self.0;
98 let l1 = (v1.0 * v1.0 + v1.1 * v1.1).sqrt();
99 let det = v1.det(v2);
100 det / l1
101 }
102
103 fn contains_point(&self, p: Point<f64>) -> bool {
104 let d = self.1 - self.0;
105 let e = p - self.0;
106 d.1 * e.0 == d.0 * e.1
107 }
108}
109
110#[cfg(test)]
111mod test_line {
112 use crate::geometry::Line;
113 use crate::geometry::LineAPI;
114 use crate::geometry::Point;
115
116 #[test]
117 fn it_works_line_f64() {
118 let x = Point(0.0, 0.0);
119 let y = Point(2.0, 3.0);
120 let line = Line(x, y);
121
122 let z = Point(0.0, 3.0);
123 let d = line.distance(z);
124 let d_truth = 1.664_100_588_675_687_4;
125
126 let result = (d * 1_000_000_000.0) as i64;
127 let expected = (d_truth * 1_000_000_000.0) as i64;
128 assert_eq!(result, expected);
129 }
130
131 #[test]
132 fn it_works_line_i64() {
133 let x = Point(0, 0);
134 let y = Point(2, 3);
135 let line = Line(x, y);
136
137 let z = Point(0, 3);
138 let d = line.distance(z);
139 let d_truth = 1.664_100_588_675_687_4;
140
141 let result = (d * 1_000_000_000.0) as i64;
142 let expected = (d_truth * 1_000_000_000.0) as i64;
143 assert_eq!(result, expected);
144
145 assert!(line.contains_point(Point(4, 6)));
147 assert!(line.contains_point(Point(-2, -3)));
148 assert!(!line.contains_point(Point(1, 1)));
149 }
150}
151
152pub fn convex_hull(ps: Vec<(i64, i64)>) -> Vec<(i64, i64)> {
153 let n = ps.len();
154
155 let mut ps: Vec<Point<i64>> = ps.iter().map(|&(x, y)| Point::<i64>(x, y)).collect();
156
157 ps.sort();
158
159 let mut k = 0;
160 let mut deque: VecDeque<Point<i64>> = VecDeque::new();
161
162 for &pi in &ps {
163 while k > 1 && (deque[k - 1] - deque[k - 2]).det(pi - deque[k - 1]) <= 0 {
164 deque.pop_back();
165 k -= 1;
166 }
167 deque.push_back(pi);
168 k += 1;
169 }
170
171 let t = k;
172 for i in (0..n - 1).rev() {
173 let pi = ps[i];
174 while k > t && (deque[k - 1] - deque[k - 2]).det(pi - deque[k - 1]) <= 0 {
175 deque.pop_back();
176 k -= 1;
177 }
178 deque.push_back(pi);
179 k += 1;
180 }
181
182 let mut ret: Vec<(i64, i64)> = deque.into_iter().take(k - 1).map(|pair| (pair.0, pair.1)).collect();
183
184 ret.sort_unstable();
185 ret
186}
187
188#[cfg(test)]
189mod test_convex_hull {
190 use crate::geometry::convex_hull;
191
192 #[test]
193 fn it_works() {
194 let ps = vec![(0, 0), (2, 2), (3, 1), (1, 4), (4, 4)];
195 let hull = convex_hull(ps);
196 assert_eq!(hull, vec![(0, 0), (1, 4), (3, 1), (4, 4)]);
197
198 let ps = vec![(0, 0), (2, 2), (4, 4)];
199 let hull = convex_hull(ps);
200 assert_eq!(hull, vec![(0, 0), (4, 4)]);
201
202 let ps = vec![(0, 0), (0, 1), (0, 2), (1, 1)];
203 let hull = convex_hull(ps);
204 assert_eq!(hull, vec![(0, 0), (0, 2), (1, 1)]);
205 }
206}