blob: 6dcab215734d73a710341a2713480b2cb4c6bf51 [file] [log] [blame]
Joel Galensonf13194f2021-06-21 13:38:59 -07001use super::{BackendCoordAndZ, Drawable, PointCollection};
2use crate::style::ShapeStyle;
3use plotters_backend::{BackendCoord, DrawingBackend, DrawingErrorKind};
4
5pub struct Cubiod<X, Y, Z> {
6 face_style: ShapeStyle,
7 edge_style: ShapeStyle,
8 vert: [(X, Y, Z); 8],
9}
10
11impl<X: Clone, Y: Clone, Z: Clone> Cubiod<X, Y, Z> {
12 pub fn new<FS: Into<ShapeStyle>, ES: Into<ShapeStyle>>(
13 [(x0, y0, z0), (x1, y1, z1)]: [(X, Y, Z); 2],
14 face_style: FS,
15 edge_style: ES,
16 ) -> Self {
17 Self {
18 face_style: face_style.into(),
19 edge_style: edge_style.into(),
20 vert: [
21 (x0.clone(), y0.clone(), z0.clone()),
22 (x0.clone(), y0.clone(), z1.clone()),
23 (x0.clone(), y1.clone(), z0.clone()),
24 (x0.clone(), y1.clone(), z1.clone()),
25 (x1.clone(), y0.clone(), z0.clone()),
26 (x1.clone(), y0.clone(), z1.clone()),
27 (x1.clone(), y1.clone(), z0.clone()),
28 (x1.clone(), y1.clone(), z1.clone()),
29 ],
30 }
31 }
32}
33
34impl<'a, X: 'a, Y: 'a, Z: 'a> PointCollection<'a, (X, Y, Z), BackendCoordAndZ>
35 for &'a Cubiod<X, Y, Z>
36{
37 type Point = &'a (X, Y, Z);
38 type IntoIter = &'a [(X, Y, Z)];
39 fn point_iter(self) -> Self::IntoIter {
40 &self.vert
41 }
42}
43
44impl<X, Y, Z, DB: DrawingBackend> Drawable<DB, BackendCoordAndZ> for Cubiod<X, Y, Z> {
45 fn draw<I: Iterator<Item = (BackendCoord, i32)>>(
46 &self,
47 points: I,
48 backend: &mut DB,
49 _: (u32, u32),
50 ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
51 let vert: Vec<_> = points.collect();
52 let mut polygon = vec![];
53 for mask in vec![1, 2, 4] {
54 let mask_a = if mask == 4 { 1 } else { mask * 2 };
55 let mask_b = if mask == 1 { 4 } else { mask / 2 };
56 let a = 0;
57 let b = a | mask_a;
58 let c = a | mask_a | mask_b;
59 let d = a | mask_b;
60 polygon.push([vert[a], vert[b], vert[c], vert[d]]);
61 polygon.push([
62 vert[a | mask],
63 vert[b | mask],
64 vert[c | mask],
65 vert[d | mask],
66 ]);
67 }
68 polygon.sort_by_cached_key(|t| std::cmp::Reverse(t[0].1 + t[1].1 + t[2].1 + t[3].1));
69
70 for p in polygon {
71 backend.fill_polygon(p.iter().map(|(coord, _)| *coord), &self.face_style)?;
72 backend.draw_path(
73 p.iter()
74 .map(|(coord, _)| *coord)
75 .chain(std::iter::once(p[0].0)),
76 &self.edge_style,
77 )?;
78 }
79
80 Ok(())
81 }
82}