1use crate::{
2 Float, Line, Num, Rect, Vec2, impl_approx, impl_bytemuck, impl_casts, impl_interp, line,
3};
4use serde::{Deserialize, Serialize};
5
6pub type QuadF = Quad<f32>;
7pub type QuadI = Quad<i32>;
8
9#[repr(transparent)]
11#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
12pub struct Quad<T>(pub [Vec2<T>; 4]);
13
14impl_bytemuck!(Quad);
15
16impl_interp!(
17 NAME = Quad
18 INDICES = [0, 1, 2, 3]
19);
20
21impl_casts!(
22 NAME = Quad
23 FIELDS = (0)
24);
25
26impl_approx!(
27 NAME = Quad
28 FIELDS = (0)
29);
30
31#[inline]
33pub const fn quad<T>(a: Vec2<T>, b: Vec2<T>, c: Vec2<T>, d: Vec2<T>) -> Quad<T> {
34 Quad([a, b, c, d])
35}
36
37impl<T> Quad<T> {
38 #[inline]
40 pub const fn new(a: Vec2<T>, b: Vec2<T>, c: Vec2<T>, d: Vec2<T>) -> Self {
41 Self([a, b, c, d])
42 }
43}
44
45impl<T: Copy> Quad<T> {
46 #[inline]
48 pub const fn a(&self) -> Vec2<T> {
49 self.0[0]
50 }
51
52 #[inline]
54 pub const fn b(&self) -> Vec2<T> {
55 self.0[1]
56 }
57
58 #[inline]
60 pub const fn c(&self) -> Vec2<T> {
61 self.0[2]
62 }
63
64 #[inline]
66 pub const fn d(&self) -> Vec2<T> {
67 self.0[3]
68 }
69
70 #[inline]
72 pub fn edges(&self) -> [Line<T>; 4] {
73 [
74 self.edge_ab(),
75 self.edge_bc(),
76 self.edge_cd(),
77 self.edge_da(),
78 ]
79 }
80
81 #[inline]
83 pub const fn edge_ab(&self) -> Line<T> {
84 line(self.a(), self.b())
85 }
86
87 #[inline]
89 pub const fn edge_bc(&self) -> Line<T> {
90 line(self.b(), self.c())
91 }
92
93 #[inline]
95 pub const fn edge_cd(&self) -> Line<T> {
96 line(self.c(), self.d())
97 }
98
99 #[inline]
101 pub const fn edge_da(&self) -> Line<T> {
102 line(self.d(), self.a())
103 }
104}
105
106impl<T: Num> Quad<T> {
107 pub const ZERO: Self = Self([Vec2::ZERO; 4]);
109
110 pub fn from_rect(rect: Rect<T>) -> Self {
112 Self(rect.corners())
113 }
114
115 #[inline]
117 pub fn ab(&self) -> Vec2<T> {
118 self.a() - self.b()
119 }
120
121 #[inline]
123 pub fn bc(&self) -> Vec2<T> {
124 self.c() - self.b()
125 }
126
127 #[inline]
129 pub fn cd(&self) -> Vec2<T> {
130 self.d() - self.c()
131 }
132
133 #[inline]
135 pub fn da(&self) -> Vec2<T> {
136 self.a() - self.d()
137 }
138}
139
140impl<T: Float> Quad<T> {
141 #[inline]
143 pub fn norm_ab(&self) -> Vec2<T> {
144 self.ab().turn_left().norm()
145 }
146
147 #[inline]
149 pub fn norm_bc(&self) -> Vec2<T> {
150 self.bc().turn_left().norm()
151 }
152
153 #[inline]
155 pub fn norm_cd(&self) -> Vec2<T> {
156 self.cd().turn_left().norm()
157 }
158
159 #[inline]
161 pub fn norm_da(&self) -> Vec2<T> {
162 self.da().turn_left().norm()
163 }
164
165 #[inline]
168 pub fn line(line: impl Into<Line<T>>, width: T) -> Self {
169 let line = line.into();
170 let n2 = T::ONE + T::ONE;
171 let off = (line.end - line.start).turn_left().norm() * (width / n2);
172 Self([
173 line.start + off,
174 line.end + off,
175 line.end - off,
176 line.start - off,
177 ])
178 }
179
180 #[inline]
183 pub fn stroke(line: impl Into<Line<T>>, start_width: T, end_width: T) -> Self {
184 let line = line.into();
185 let off = (line.end - line.start).turn_left().norm();
186 let off_a = off * (start_width * T::HALF);
187 let off_b = off * (end_width * T::HALF);
188 Self([
189 line.start + off_a,
190 line.end + off_b,
191 line.end - off_b,
192 line.start - off_a,
193 ])
194 }
195
196 #[inline]
197 pub fn transform_by(&self, f: impl FnMut(Vec2<T>) -> Vec2<T>) -> Self {
198 Self(self.0.map(f))
199 }
200}
201
202impl<T> AsRef<[Vec2<T>]> for Quad<T> {
203 #[inline]
204 fn as_ref(&self) -> &[Vec2<T>] {
205 self.0.as_slice()
206 }
207}
208
209impl<T> From<(Vec2<T>, Vec2<T>, Vec2<T>, Vec2<T>)> for Quad<T> {
210 #[inline]
211 fn from((a, b, c, d): (Vec2<T>, Vec2<T>, Vec2<T>, Vec2<T>)) -> Self {
212 Self([a, b, c, d])
213 }
214}
215
216impl<T> From<Quad<T>> for (Vec2<T>, Vec2<T>, Vec2<T>, Vec2<T>) {
217 #[inline]
218 fn from(Quad([a, b, c, d]): Quad<T>) -> Self {
219 (a, b, c, d)
220 }
221}
222
223impl<T> From<[Vec2<T>; 4]> for Quad<T> {
224 #[inline]
225 fn from(value: [Vec2<T>; 4]) -> Self {
226 Self(value)
227 }
228}
229
230impl<T> From<Quad<T>> for [Vec2<T>; 4] {
231 #[inline]
232 fn from(value: Quad<T>) -> Self {
233 value.0
234 }
235}
236
237impl<T: Num> From<Rect<T>> for Quad<T> {
238 #[inline]
239 fn from(value: Rect<T>) -> Self {
240 Self::from_rect(value)
241 }
242}