competitive/geometry/
ccw.rs1use super::{Approx, ApproxOrd, Complex, Zero};
2use std::{
3 cmp::Ordering,
4 ops::{Add, Mul, Sub},
5};
6
7pub trait Ccwable:
8 ApproxOrd + Copy + Zero + Add<Output = Self> + Sub<Output = Self> + Mul<Output = Self>
9{
10}
11
12impl Ccwable for i8 {}
13impl Ccwable for i16 {}
14impl Ccwable for i32 {}
15impl Ccwable for i64 {}
16impl Ccwable for i128 {}
17impl Ccwable for isize {}
18impl Ccwable for f32 {}
19impl Ccwable for f64 {}
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub enum Ccw {
23 OnlineFront = -2,
25 Clockwise = -1,
27 OnSegment = 0,
29 CounterClockwise = 1,
31 OnlineBack = 2,
33}
34impl Ccw {
35 pub fn ccw<T>(a: Complex<T>, b: Complex<T>, c: Complex<T>) -> Self
36 where
37 T: Ccwable,
38 {
39 let x = b - a;
40 let y = c - a;
41 let zero = T::zero();
42 match x.cross(y).approx_cmp(&zero) {
43 Ordering::Less => Self::Clockwise,
44 Ordering::Greater => Self::CounterClockwise,
45 Ordering::Equal => {
46 if Approx(x.dot(y)) < Approx(zero) {
47 Self::OnlineBack
48 } else if Approx((a - b).dot(c - b)) < Approx(zero) {
49 Self::OnlineFront
50 } else {
51 Self::OnSegment
52 }
53 }
54 }
55 }
56 pub fn ccw_open<T>(a: Complex<T>, b: Complex<T>, c: Complex<T>) -> Self
57 where
58 T: Ccwable,
59 {
60 let x = b - a;
61 let y = c - a;
62 let zero = T::zero();
63 match x.cross(y).approx_cmp(&zero) {
64 Ordering::Less => Self::Clockwise,
65 Ordering::Greater => Self::CounterClockwise,
66 Ordering::Equal => {
67 if Approx(x.dot(y)) <= Approx(zero) {
68 Self::OnlineBack
69 } else if Approx((a - b).dot(c - b)) <= Approx(zero) {
70 Self::OnlineFront
71 } else {
72 Self::OnSegment
73 }
74 }
75 }
76 }
77}