summaryrefslogtreecommitdiffstats
path: root/vendor/plotters/src/element/basic_shapes_3d.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/plotters/src/element/basic_shapes_3d.rs')
-rw-r--r--vendor/plotters/src/element/basic_shapes_3d.rs108
1 files changed, 108 insertions, 0 deletions
diff --git a/vendor/plotters/src/element/basic_shapes_3d.rs b/vendor/plotters/src/element/basic_shapes_3d.rs
new file mode 100644
index 000000000..97b15e62d
--- /dev/null
+++ b/vendor/plotters/src/element/basic_shapes_3d.rs
@@ -0,0 +1,108 @@
+use super::{BackendCoordAndZ, Drawable, PointCollection};
+use crate::style::ShapeStyle;
+use plotters_backend::{BackendCoord, DrawingBackend, DrawingErrorKind};
+
+/**
+Represents a cuboid, a six-faced solid.
+
+# Examples
+
+```
+use plotters::prelude::*;
+let drawing_area = SVGBackend::new("cuboid.svg", (300, 200)).into_drawing_area();
+drawing_area.fill(&WHITE).unwrap();
+let mut chart_builder = ChartBuilder::on(&drawing_area);
+let mut chart_context = chart_builder.margin(20).build_cartesian_3d(0.0..3.5, 0.0..2.5, 0.0..1.5).unwrap();
+chart_context.configure_axes().x_labels(4).y_labels(3).z_labels(2).draw().unwrap();
+let cubiod = Cubiod::new([(0.,0.,0.), (3.,2.,1.)], BLUE.mix(0.2), BLUE);
+chart_context.draw_series(std::iter::once(cubiod)).unwrap();
+```
+
+The result is a semi-transparent cuboid with blue edges:
+
+![](https://cdn.jsdelivr.net/gh/facorread/plotters-doc-data@b6703f7/apidoc/cuboid.svg)
+*/
+pub struct Cubiod<X, Y, Z> {
+ face_style: ShapeStyle,
+ edge_style: ShapeStyle,
+ vert: [(X, Y, Z); 8],
+}
+
+impl<X: Clone, Y: Clone, Z: Clone> Cubiod<X, Y, Z> {
+ /**
+ Creates a cuboid.
+
+ See [`Cubiod`] for more information and examples.
+ */
+ #[allow(clippy::redundant_clone)]
+ pub fn new<FS: Into<ShapeStyle>, ES: Into<ShapeStyle>>(
+ [(x0, y0, z0), (x1, y1, z1)]: [(X, Y, Z); 2],
+ face_style: FS,
+ edge_style: ES,
+ ) -> Self {
+ Self {
+ face_style: face_style.into(),
+ edge_style: edge_style.into(),
+ vert: [
+ (x0.clone(), y0.clone(), z0.clone()),
+ (x0.clone(), y0.clone(), z1.clone()),
+ (x0.clone(), y1.clone(), z0.clone()),
+ (x0.clone(), y1.clone(), z1.clone()),
+ (x1.clone(), y0.clone(), z0.clone()),
+ (x1.clone(), y0.clone(), z1.clone()),
+ (x1.clone(), y1.clone(), z0.clone()),
+ (x1.clone(), y1.clone(), z1.clone()),
+ ],
+ }
+ }
+}
+
+impl<'a, X: 'a, Y: 'a, Z: 'a> PointCollection<'a, (X, Y, Z), BackendCoordAndZ>
+ for &'a Cubiod<X, Y, Z>
+{
+ type Point = &'a (X, Y, Z);
+ type IntoIter = &'a [(X, Y, Z)];
+ fn point_iter(self) -> Self::IntoIter {
+ &self.vert
+ }
+}
+
+impl<X, Y, Z, DB: DrawingBackend> Drawable<DB, BackendCoordAndZ> for Cubiod<X, Y, Z> {
+ fn draw<I: Iterator<Item = (BackendCoord, i32)>>(
+ &self,
+ points: I,
+ backend: &mut DB,
+ _: (u32, u32),
+ ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
+ let vert: Vec<_> = points.collect();
+ let mut polygon = vec![];
+ for mask in [1, 2, 4].iter().cloned() {
+ let mask_a = if mask == 4 { 1 } else { mask * 2 };
+ let mask_b = if mask == 1 { 4 } else { mask / 2 };
+ let a = 0;
+ let b = a | mask_a;
+ let c = a | mask_a | mask_b;
+ let d = a | mask_b;
+ polygon.push([vert[a], vert[b], vert[c], vert[d]]);
+ polygon.push([
+ vert[a | mask],
+ vert[b | mask],
+ vert[c | mask],
+ vert[d | mask],
+ ]);
+ }
+ polygon.sort_by_cached_key(|t| std::cmp::Reverse(t[0].1 + t[1].1 + t[2].1 + t[3].1));
+
+ for p in polygon {
+ backend.fill_polygon(p.iter().map(|(coord, _)| *coord), &self.face_style)?;
+ backend.draw_path(
+ p.iter()
+ .map(|(coord, _)| *coord)
+ .chain(std::iter::once(p[0].0)),
+ &self.edge_style,
+ )?;
+ }
+
+ Ok(())
+ }
+}