1use crate::{Float, Line, Num, Vec2, impl_approx, impl_bytemuck, impl_casts, impl_interp, line};
2use serde::{Deserialize, Serialize};
3
4pub type TriangleF = Triangle<f32>;
5pub type TriangleI = Triangle<i32>;
6
7#[repr(transparent)]
9#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
10pub struct Triangle<T>(pub [Vec2<T>; 3]);
11
12impl_bytemuck!(Triangle);
13
14impl_interp!(
15 NAME = Triangle
16 INDICES = [0, 1, 2]
17);
18
19impl_casts!(
20 NAME = Triangle
21 FIELDS = (0)
22);
23
24impl_approx!(
25 NAME = Triangle
26 FIELDS = (0)
27);
28
29#[inline]
31pub const fn triangle<T>(a: Vec2<T>, b: Vec2<T>, c: Vec2<T>) -> Triangle<T> {
32 Triangle([a, b, c])
33}
34
35impl<T> Triangle<T> {
36 #[inline]
38 pub const fn new(a: Vec2<T>, b: Vec2<T>, c: Vec2<T>) -> Self {
39 Self([a, b, c])
40 }
41
42 #[inline]
43 pub fn map<U>(self, f: impl Fn(Vec2<T>) -> Vec2<U>) -> Triangle<U> {
44 Triangle(self.0.map(f))
45 }
46}
47
48impl<T: Copy> Triangle<T> {
49 #[inline]
51 pub const fn a(&self) -> Vec2<T> {
52 self.0[0]
53 }
54
55 #[inline]
57 pub const fn b(&self) -> Vec2<T> {
58 self.0[1]
59 }
60
61 #[inline]
63 pub const fn c(&self) -> Vec2<T> {
64 self.0[2]
65 }
66
67 #[inline]
69 pub fn edges(&self) -> [Line<T>; 3] {
70 [self.edge_ab(), self.edge_bc(), self.edge_ca()]
71 }
72
73 #[inline]
75 pub const fn edge_ab(&self) -> Line<T> {
76 line(self.a(), self.b())
77 }
78
79 #[inline]
81 pub const fn edge_bc(&self) -> Line<T> {
82 line(self.b(), self.c())
83 }
84
85 #[inline]
87 pub const fn edge_ca(&self) -> Line<T> {
88 line(self.c(), self.a())
89 }
90}
91
92impl<T: Num> Triangle<T> {
93 pub const ZERO: Self = Self([Vec2::ZERO; 3]);
95
96 #[inline]
98 pub fn ab(&self) -> Vec2<T> {
99 self.b() - self.a()
100 }
101
102 #[inline]
104 pub fn bc(&self) -> Vec2<T> {
105 self.c() - self.b()
106 }
107
108 #[inline]
110 pub fn ca(&self) -> Vec2<T> {
111 self.a() - self.c()
112 }
113}
114
115impl<T: Float> Triangle<T> {
116 #[inline]
118 pub fn norm_ab(&self) -> Vec2<T> {
119 self.ab().turn_left().norm()
120 }
121
122 #[inline]
124 pub fn norm_bc(&self) -> Vec2<T> {
125 self.bc().turn_left().norm()
126 }
127
128 #[inline]
130 pub fn norm_ca(&self) -> Vec2<T> {
131 self.ca().turn_left().norm()
132 }
133
134 #[inline]
135 pub fn transform_by(&self, f: impl FnMut(Vec2<T>) -> Vec2<T>) -> Self {
136 Self(self.0.map(f))
137 }
138}
139
140impl<T> AsRef<[Vec2<T>]> for Triangle<T> {
141 #[inline]
142 fn as_ref(&self) -> &[Vec2<T>] {
143 self.0.as_slice()
144 }
145}
146
147impl<T> From<(Vec2<T>, Vec2<T>, Vec2<T>)> for Triangle<T> {
148 #[inline]
149 fn from((a, b, c): (Vec2<T>, Vec2<T>, Vec2<T>)) -> Self {
150 Self([a, b, c])
151 }
152}
153
154impl<T> From<Triangle<T>> for (Vec2<T>, Vec2<T>, Vec2<T>) {
155 #[inline]
156 fn from(Triangle([a, b, c]): Triangle<T>) -> Self {
157 (a, b, c)
158 }
159}
160
161impl<T> From<[Vec2<T>; 3]> for Triangle<T> {
162 #[inline]
163 fn from(value: [Vec2<T>; 3]) -> Self {
164 Self(value)
165 }
166}
167
168impl<T> From<Triangle<T>> for [Vec2<T>; 3] {
169 #[inline]
170 fn from(value: Triangle<T>) -> Self {
171 value.0
172 }
173}
174