1 use crate::element::Polygon;
2 use crate::style::ShapeStyle;
3 /// The surface series.
4 ///
5 /// Currently the surface is representing any surface in form
6 /// y = f(x,z)
7 ///
8 /// TODO: make this more general
9 pub struct SurfaceSeries<X, Y, Z> {
10     x_data: Vec<X>,
11     y_data: Vec<Y>,
12     z_data: Vec<Z>,
13     style: ShapeStyle,
14     size: usize,
15     state: usize,
16 }
17 
18 impl<X, Y, Z> SurfaceSeries<X, Y, Z> {
new<XS, ZS, YF, S>(xs: XS, zs: ZS, y_func: YF, style: S) -> Self where YF: Fn(&X, &Z) -> Y, XS: Iterator<Item = X>, ZS: Iterator<Item = Z>, S: Into<ShapeStyle>,19     pub fn new<XS, ZS, YF, S>(xs: XS, zs: ZS, y_func: YF, style: S) -> Self
20     where
21         YF: Fn(&X, &Z) -> Y,
22         XS: Iterator<Item = X>,
23         ZS: Iterator<Item = Z>,
24         S: Into<ShapeStyle>,
25     {
26         let x_data: Vec<_> = xs.collect();
27         let z_data: Vec<_> = zs.collect();
28         let y_data: Vec<_> = x_data
29             .iter()
30             .map(|x| z_data.iter().map(move |z| (x, z)))
31             .flatten()
32             .map(|(x, z)| y_func(x, z))
33             .collect();
34         let size = (x_data.len().max(1) - 1) * (z_data.len().max(1) - 1);
35         Self {
36             x_data,
37             y_data,
38             z_data,
39             style: style.into(),
40             size,
41             state: 0,
42         }
43     }
44 
point_at(&self, x: usize, z: usize) -> (X, Y, Z) where X: Clone, Y: Clone, Z: Clone,45     fn point_at(&self, x: usize, z: usize) -> (X, Y, Z)
46     where
47         X: Clone,
48         Y: Clone,
49         Z: Clone,
50     {
51         (
52             self.x_data[x].clone(),
53             self.y_data[x * self.z_data.len() + z].clone(),
54             self.z_data[z].clone(),
55         )
56     }
57 }
58 
59 impl<X: Clone, Y: Clone, Z: Clone> Iterator for SurfaceSeries<X, Y, Z> {
60     type Item = Polygon<(X, Y, Z)>;
61 
next(&mut self) -> Option<Self::Item>62     fn next(&mut self) -> Option<Self::Item> {
63         if self.size <= self.state {
64             return None;
65         }
66 
67         let x = self.state / (self.z_data.len() - 1);
68         let z = self.state % (self.z_data.len() - 1);
69 
70         self.state += 1;
71 
72         Some(Polygon::new(
73             vec![
74                 self.point_at(x, z),
75                 self.point_at(x, z + 1),
76                 self.point_at(x + 1, z + 1),
77                 self.point_at(x + 1, z),
78             ],
79             self.style.clone(),
80         ))
81     }
82 }
83