Joel Galenson | f13194f | 2021-06-21 13:38:59 -0700 | [diff] [blame] | 1 | use super::{BackendCoordAndZ, Drawable, PointCollection}; |
| 2 | use crate::style::ShapeStyle; |
| 3 | use plotters_backend::{BackendCoord, DrawingBackend, DrawingErrorKind}; |
| 4 | |
| 5 | pub struct Cubiod<X, Y, Z> { |
| 6 | face_style: ShapeStyle, |
| 7 | edge_style: ShapeStyle, |
| 8 | vert: [(X, Y, Z); 8], |
| 9 | } |
| 10 | |
| 11 | impl<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 | |
| 34 | impl<'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 | |
| 44 | impl<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 | } |