1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
//! A shape type representing triangles used for drawing.
//!
//! # Examples
//!
//! You can create a [Triangle][Tri] using [Tri::new]:
//!
//! ```
//! use pix_engine::prelude::*;
//!
//! // 2D
//! let tri: TriI2 = Tri::new([10, 20], [30, 10], [20, 25]);
//!
//! let p1 = point!(10, 20);
//! let p2 = point!(30, 10);
//! let p3 = point!(20, 25);
//! let tri: TriI2 = Tri::new(p1, p2, p3);
//! ```
use crate::prelude::*;
use num_traits::AsPrimitive;
// #[cfg(feature = "serde")]
// use serde::{Deserialize, Serialize};
/// A `Triangle` with three [Point]s.
///
/// Please see the [module-level documentation] for examples.
///
/// [module-level documentation]: crate::core::shape::triangle
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
// TODO: serde is not ready for const generics yet
// #[cfg_ater(feature = "serde", derive(Serialize, Deserialize))]
pub struct Tri<T, const N: usize>(pub(crate) [Point<T, N>; 3]);
/// A 2D `Triangle` represented by integers.
pub type TriI2 = Tri<i32, 2>;
/// A 3D `Tri` represented by integers.
pub type TriI3 = Tri<i32, 3>;
/// A 2D `Tri` represented by floating point numbers.
pub type TriF2 = Tri<Scalar, 2>;
/// A 3D `Tri` represented by floating point numbers.
pub type TriF3 = Tri<Scalar, 3>;
/// Constructs a [Triangle][Tri] with three points.
///
/// ```
/// # use pix_engine::prelude::*;
///
/// let t = tri!([10, 20], [30, 10], [20, 25]);
/// assert_eq!(t.values(), [
/// point!(10, 20),
/// point!(30, 10),
/// point!(20, 25),
/// ]);
///
/// let t = tri!([10, 20, 10], [30, 10, 40], [20, 25, 20]);
/// assert_eq!(t.values(), [
/// point!(10, 20, 10),
/// point!(30, 10, 40),
/// point!(20, 25, 20),
/// ]);
/// ```
#[macro_export]
macro_rules! tri {
($p1:expr, $p2:expr, $p3:expr$(,)?) => {
$crate::prelude::Tri::new($p1, $p2, $p3)
};
($x1:expr, $y1:expr, $x2:expr, $y2:expr, $x3:expr, $y3:expr$(,)?) => {
$crate::prelude::Line::new([$x1, $y1], [$x2, $y2], [$x3, $y3])
};
($x1:expr, $y1:expr, $z1:expr, $x2:expr, $y2:expr, $z2:expr, $x3:expr, $y3:expr, $z3:expr$(,)?) => {
$crate::prelude::Line::new([$x1, $y1, $z2], [$x2, $y2, $z2], [$x3, $y3, $z3])
};
}
impl<T, const N: usize> Tri<T, N> {
/// Constructs a `Triangle` with the given [Point]s.
///
/// # Example
///
/// ```
/// # use pix_engine::prelude::*;
/// let tri: TriI2 = Tri::new([10, 20], [30, 10], [20, 25]);
/// assert_eq!(tri.p1().values(), [10, 20]);
/// assert_eq!(tri.p2().values(), [30, 10]);
/// assert_eq!(tri.p3().values(), [20, 25]);
/// ```
pub fn new<P>(p1: P, p2: P, p3: P) -> Self
where
P: Into<Point<T, N>>,
{
Self([p1.into(), p2.into(), p3.into()])
}
}
impl<T, const N: usize> Tri<T, N>
where
T: Copy + Default,
{
/// Returns the first point of the triangle.
#[inline]
pub fn p1(&self) -> Point<T, N> {
self.0[0]
}
/// Sets the first point of the triangle.
#[inline]
pub fn set_p1<P>(&mut self, p: P)
where
P: Into<Point<T, N>>,
{
self.0[0] = p.into();
}
/// Returns the second point of the triangle.
#[inline]
pub fn p2(&self) -> Point<T, N> {
self.0[1]
}
/// Sets the second point of the triangle.
#[inline]
pub fn set_p2<P>(&mut self, p: P)
where
P: Into<Point<T, N>>,
{
self.0[1] = p.into();
}
/// Returns the third point of the triangle.
#[inline]
pub fn p3(&self) -> Point<T, N> {
self.0[2]
}
/// Sets the third point of the triangle.
#[inline]
pub fn set_p3<P>(&mut self, p: P)
where
P: Into<Point<T, N>>,
{
self.0[2] = p.into();
}
/// Returns `Triangle` points as `[Point<T, N>; 3]`.
///
/// # Example
///
/// ```
/// # use pix_engine::prelude::*;
/// let tri: TriI2 = Tri::new([10, 20], [30, 10], [20, 25]);
/// assert_eq!(tri.values(), [
/// point!(10, 20),
/// point!(30, 10),
/// point!(20, 25),
/// ]);
/// ```
pub fn values(&self) -> [Point<T, N>; 3] {
self.0
}
/// Returns `Triangle` as a [Vec].
///
/// # Example
///
/// ```
/// # use pix_engine::prelude::*;
/// let tri: TriI2 = Tri::new([10, 20], [30, 10], [20, 25]);
/// assert_eq!(
/// tri.to_vec(),
/// vec![
/// point!(10, 20),
/// point!(30, 10),
/// point!(20, 25),
/// ]
/// );
/// ```
pub fn to_vec(self) -> Vec<Point<T, N>> {
self.0.to_vec()
}
}
impl<T, const N: usize> Draw for Tri<T, N>
where
Self: Into<TriI2>,
T: Default + AsPrimitive<i32>,
{
/// Draw `Triangle` to the current [PixState] canvas.
fn draw(&self, s: &mut PixState) -> PixResult<()> {
s.triangle(*self)
}
}