use super::*;
use std::fmt::Write;
pub struct Surface {
pub row_stride: i32,
pub col_stride: i32,
pub surface: bool,
pub wireframe: bool,
pub colormap_index: i32,
pub colormap_name: String,
pub colorbar: bool,
pub colorbar_label: String,
pub colorbar_number_format: String,
pub line_color: String,
pub line_style: String,
pub line_width: f64,
pub(crate) buffer: String,
}
impl Surface {
pub fn new() -> Self {
Surface {
row_stride: 0,
col_stride: 0,
surface: true,
wireframe: false,
colormap_index: 0,
colormap_name: String::new(),
colorbar: false,
colorbar_label: String::new(),
colorbar_number_format: String::new(),
line_color: "black".to_string(),
line_style: String::new(),
line_width: 0.0,
buffer: String::new(),
}
}
pub fn draw<T>(&mut self, x: &Vec<Vec<T>>, y: &Vec<Vec<T>>, z: &Vec<Vec<T>>)
where
T: std::fmt::Display,
{
matrix_to_array(&mut self.buffer, "x", x);
matrix_to_array(&mut self.buffer, "y", y);
matrix_to_array(&mut self.buffer, "z", z);
write!(&mut self.buffer, "maybeCreateAX3D()\n").unwrap();
if self.surface {
let opt_surface = self.options_surface();
write!(&mut self.buffer, "sf=AX3D.plot_surface(x,y,z{})\n", &opt_surface).unwrap();
}
if self.wireframe {
let opt_wireframe = self.options_wireframe();
write!(&mut self.buffer, "AX3D.plot_wireframe(x,y,z{})\n", &opt_wireframe).unwrap();
}
if self.colorbar {
let opt_colorbar = self.options_colorbar();
write!(&mut self.buffer, "cb=plt.colorbar(sf{})\n", &opt_colorbar).unwrap();
if self.colorbar_label != "" {
write!(&mut self.buffer, "cb.ax.set_ylabel(r'{}')\n", self.colorbar_label).unwrap();
}
}
}
pub(crate) fn options_surface(&self) -> String {
let mut opt = String::new();
if self.row_stride > 0 {
write!(&mut opt, ",rstride={}", self.row_stride).unwrap();
}
if self.col_stride > 0 {
write!(&mut opt, ",cstride={}", self.col_stride).unwrap();
}
if self.colormap_name != "" {
write!(&mut opt, ",cmap=plt.get_cmap('{}')", self.colormap_name).unwrap();
} else {
write!(&mut opt, ",cmap=getColormap({})", self.colormap_index).unwrap();
}
opt
}
pub(crate) fn options_wireframe(&self) -> String {
let mut opt = String::new();
if self.row_stride > 0 {
write!(&mut opt, ",rstride={}", self.row_stride).unwrap();
}
if self.col_stride > 0 {
write!(&mut opt, ",cstride={}", self.col_stride).unwrap();
}
if self.line_color != "" {
write!(&mut opt, ",color='{}'", self.line_color).unwrap();
}
if self.line_style != "" {
write!(&mut opt, ",linestyle='{}'", self.line_style).unwrap();
}
if self.line_width > 0.0 {
write!(&mut opt, ",linewidth={}", self.line_width).unwrap();
}
opt
}
pub(crate) fn options_colorbar(&self) -> String {
let mut opt = String::new();
if self.colorbar_number_format != "" {
write!(&mut opt, ",format='{}'", self.colorbar_number_format).unwrap();
}
opt
}
}
impl GraphMaker for Surface {
fn get_buffer<'a>(&'a self) -> &'a String {
&self.buffer
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_works() {
let surface = Surface::new();
assert_eq!(surface.row_stride, 0);
assert_eq!(surface.col_stride, 0);
assert_eq!(surface.surface, true);
assert_eq!(surface.wireframe, false);
assert_eq!(surface.colormap_index, 0);
assert_eq!(surface.colormap_name.len(), 0);
assert_eq!(surface.colorbar, false);
assert_eq!(surface.colorbar_label.len(), 0);
assert_eq!(surface.colorbar_number_format.len(), 0);
assert_eq!(surface.line_color, "black".to_string());
assert_eq!(surface.line_style.len(), 0);
assert_eq!(surface.line_width, 0.0);
assert_eq!(surface.buffer.len(), 0);
}
#[test]
fn options_surface_works() {
let mut surface = Surface::new();
surface.row_stride = 3;
surface.col_stride = 4;
let opt = surface.options_surface();
assert_eq!(opt, ",rstride=3,cstride=4,cmap=getColormap(0)");
surface.colormap_name = "Pastel1".to_string();
let opt = surface.options_surface();
assert_eq!(opt, ",rstride=3,cstride=4,cmap=plt.get_cmap('Pastel1')");
}
#[test]
fn options_wireframe_works() {
let mut surface = Surface::new();
surface.row_stride = 3;
surface.col_stride = 4;
surface.line_color = "red".to_string();
surface.line_style = "--".to_string();
surface.line_width = 2.5;
let opt = surface.options_wireframe();
assert_eq!(opt, ",rstride=3,cstride=4,color='red',linestyle='--',linewidth=2.5");
}
#[test]
fn options_colorbar_works() {
let mut surface = Surface::new();
surface.colorbar_number_format = "%.3f".to_string();
let opt = surface.options_colorbar();
assert_eq!(opt, ",format='%.3f'");
}
#[test]
fn draw_works() {
let mut surface = Surface::new();
surface.wireframe = true;
surface.colorbar = true;
surface.colorbar_label = "temperature".to_string();
let x = vec![vec![-0.5, 0.0, 0.5], vec![-0.5, 0.0, 0.5], vec![-0.5, 0.0, 0.5]];
let y = vec![vec![-0.5, -0.5, -0.5], vec![0.0, 0.0, 0.0], vec![0.5, 0.5, 0.5]];
let z = vec![vec![0.50, 0.25, 0.50], vec![0.25, 0.00, 0.25], vec![0.50, 0.25, 0.50]];
surface.draw(&x, &y, &z);
let b: &str = "x=np.array([[-0.5,0,0.5,],[-0.5,0,0.5,],[-0.5,0,0.5,],],dtype=float)\n\
y=np.array([[-0.5,-0.5,-0.5,],[0,0,0,],[0.5,0.5,0.5,],],dtype=float)\n\
z=np.array([[0.5,0.25,0.5,],[0.25,0,0.25,],[0.5,0.25,0.5,],],dtype=float)\n\
maybeCreateAX3D()\n\
sf=AX3D.plot_surface(x,y,z,cmap=getColormap(0))\n\
AX3D.plot_wireframe(x,y,z,color='black')\n\
cb=plt.colorbar(sf)\n\
cb.ax.set_ylabel(r'temperature')\n";
assert_eq!(surface.buffer, b);
}
}