1use std::ops::{Add, Neg, Sub};
9
10pub const PREC_DISTANCE: DistanceType = 1e-5;
12
13pub type FloatType = f64;
15
16pub type DistanceType = FloatType;
18
19#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Default)]
21#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22pub enum Angle {
23 #[default]
25 R0,
26 R90,
28 R180,
30 R270,
32}
33
34impl Angle {
35 pub fn as_int(&self) -> u32 {
37 match self {
38 Angle::R0 => 0,
39 Angle::R90 => 1,
40 Angle::R180 => 2,
41 Angle::R270 => 3,
42 }
43 }
44
45 pub fn from_u32(a: u32) -> Self {
48 match a % 4 {
49 0 => Angle::R0,
50 1 => Angle::R90,
51 2 => Angle::R180,
52 3 => Angle::R270,
53 _ => unreachable!(),
54 }
55 }
56}
57
58impl Add for Angle {
59 type Output = Self;
60
61 fn add(self, rhs: Self) -> Self::Output {
62 Self::from_u32(self.as_int() + rhs.as_int())
63 }
64}
65
66impl Sub for Angle {
67 type Output = Self;
68
69 fn sub(self, rhs: Self) -> Self::Output {
70 Self::from_u32(self.as_int() + 4 - rhs.as_int())
71 }
72}
73
74impl Neg for Angle {
75 type Output = Self;
76
77 fn neg(self) -> Self::Output {
78 Self::from_u32(4 - self.as_int())
79 }
80}
81
82#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
85pub enum Side {
86 Left,
88 Center,
90 Right,
92}
93
94impl Side {
95 pub fn is_left(&self) -> bool {
97 *self == Side::Left
98 }
99 pub fn is_right(&self) -> bool {
101 *self == Side::Right
102 }
103 pub fn is_center(&self) -> bool {
105 *self == Side::Center
106 }
107
108 pub fn other(&self) -> Self {
110 match self {
111 Side::Left => Side::Right,
112 Side::Center => Side::Center,
113 Side::Right => Side::Left,
114 }
115 }
116}
117
118#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
120pub enum Orientation {
121 ClockWise,
123 CounterClockWise,
125 Straight,
127}
128
129impl Orientation {
130 pub fn is_clock_wise(self) -> bool {
132 self == Self::ClockWise
133 }
134 pub fn is_counter_clock_wise(self) -> bool {
136 self == Self::CounterClockWise
137 }
138 pub fn is_straight(self) -> bool {
140 self == Self::Straight
141 }
142}
143
144#[derive(Clone, Copy, PartialEq, Eq, Debug)]
149pub enum ContainsResult {
150 No,
152 OnBounds,
154 WithinBounds,
156}
157
158impl ContainsResult {
159 pub fn is_within_bounds(&self) -> bool {
161 matches!(self, ContainsResult::WithinBounds)
162 }
163
164 pub fn inclusive_bounds(&self) -> bool {
166 matches!(
167 self,
168 ContainsResult::WithinBounds | ContainsResult::OnBounds
169 )
170 }
171
172 pub fn on_bounds(&self) -> bool {
174 matches!(self, ContainsResult::OnBounds)
175 }
176
177 pub fn is_no(&self) -> bool {
179 matches!(self, ContainsResult::No)
180 }
181
182 pub fn max(self, other: Self) -> Self {
185 match (self, other) {
186 (ContainsResult::WithinBounds, _) => ContainsResult::WithinBounds,
187 (_, ContainsResult::WithinBounds) => ContainsResult::WithinBounds,
188 (ContainsResult::OnBounds, _) => ContainsResult::OnBounds,
189 (_, ContainsResult::OnBounds) => ContainsResult::OnBounds,
190 (ContainsResult::No, _) => ContainsResult::No,
191 }
192 }
193
194 pub fn min(self, other: Self) -> Self {
197 match (self, other) {
198 (ContainsResult::No, _) => ContainsResult::No,
199 (_, ContainsResult::No) => ContainsResult::No,
200 (ContainsResult::OnBounds, _) => ContainsResult::OnBounds,
201 (_, ContainsResult::OnBounds) => ContainsResult::OnBounds,
202 (ContainsResult::WithinBounds, _) => ContainsResult::WithinBounds,
203 }
204 }
205}