use crate::axes_common::*;
use crate::datatype::*;
use crate::options::*;
use crate::util::OneWayOwned;
use crate::writer::Writer;
use std::borrow::Borrow;
enum View
{
PitchYaw(f64, f64),
Map,
}
impl View
{
fn write_out(&self, writer: &mut dyn Writer)
{
match self
{
Self::PitchYaw(pitch, yaw) =>
{
writeln!(writer, "set view {:.12e},{:.12e}", pitch, yaw);
}
Self::Map =>
{
writer.write_str("set view map\n");
}
}
}
fn reset_state(&self, writer: &mut dyn Writer)
{
writer.write_str("unset view\n");
}
}
pub struct Axes3D
{
common: AxesCommonData,
z_axis: AxisData,
contour_base: bool,
contour_surface: bool,
contour_auto: AutoOption<u32>,
contour_levels: Option<Vec<f64>>,
contour_style: ContourStyle,
contour_label: AutoOption<String>,
view: Option<View>,
}
impl Axes3D
{
pub(crate) fn new() -> Axes3D
{
Axes3D {
common: AxesCommonData::new(),
z_axis: AxisData::new(ZTickAxis),
contour_base: false,
contour_surface: false,
contour_auto: Auto,
contour_levels: None,
contour_style: Linear,
contour_label: Auto,
view: None,
}
}
pub fn surface<'l, T: DataType, X: IntoIterator<Item = T>>(
&'l mut self, mat: X, num_rows: usize, num_cols: usize,
dimensions: Option<(f64, f64, f64, f64)>, options: &[PlotOption<&str>],
) -> &'l mut Self
{
self.common.elems.push(PlotElement::new_plot_matrix(
Pm3D,
true,
mat,
num_rows,
num_cols,
dimensions,
options.to_one_way_owned(),
));
self
}
pub fn points<
'l,
Tx: DataType,
X: IntoIterator<Item = Tx>,
Ty: DataType,
Y: IntoIterator<Item = Ty>,
Tz: DataType,
Z: IntoIterator<Item = Tz>,
>(
&'l mut self, x: X, y: Y, z: Z, options: &[PlotOption<&str>],
) -> &'l mut Self
{
self.common.elems.push(PlotElement::new_plot3(
Points,
x,
y,
z,
options.to_one_way_owned(),
));
self
}
pub fn lines<
'l,
Tx: DataType,
X: IntoIterator<Item = Tx>,
Ty: DataType,
Y: IntoIterator<Item = Ty>,
Tz: DataType,
Z: IntoIterator<Item = Tz>,
>(
&'l mut self, x: X, y: Y, z: Z, options: &[PlotOption<&str>],
) -> &'l mut Self
{
self.common.elems.push(PlotElement::new_plot3(
Lines,
x,
y,
z,
options.to_one_way_owned(),
));
self
}
pub fn lines_points<
'l,
Tx: DataType,
X: IntoIterator<Item = Tx>,
Ty: DataType,
Y: IntoIterator<Item = Ty>,
Tz: DataType,
Z: IntoIterator<Item = Tz>,
>(
&'l mut self, x: X, y: Y, z: Z, options: &[PlotOption<&str>],
) -> &'l mut Self
{
self.common.elems.push(PlotElement::new_plot3(
LinesPoints,
x,
y,
z,
options.to_one_way_owned(),
));
self
}
pub fn set_view<'l>(&'l mut self, pitch: f64, yaw: f64) -> &'l mut Self
{
self.view = Some(View::PitchYaw(pitch, yaw));
self
}
pub fn set_view_map<'l>(&'l mut self) -> &'l mut Self
{
self.view = Some(View::Map);
self
}
pub fn set_z_label<'l>(&'l mut self, text: &str, options: &[LabelOption<&str>])
-> &'l mut Self
{
self.z_axis
.label
.set(text.into(), options.to_one_way_owned());
self
}
pub fn set_x_axis<'l>(&'l mut self, show: bool, options: &[PlotOption<&str>]) -> &'l mut Self
{
self.common.x_axis.show = show;
self.common.x_axis.options = options.to_one_way_owned();
self
}
pub fn set_y_axis<'l>(&'l mut self, show: bool, options: &[PlotOption<&str>]) -> &'l mut Self
{
self.common.y_axis.show = show;
self.common.y_axis.options = options.to_one_way_owned();
self
}
pub fn set_z_axis<'l>(&'l mut self, show: bool, options: &[PlotOption<&str>]) -> &'l mut Self
{
self.z_axis.show = show;
self.z_axis.options = options.to_one_way_owned();
self
}
pub fn set_z_ticks<'l>(
&'l mut self, tick_placement: Option<(AutoOption<f64>, u32)>,
tick_options: &[TickOption<&str>], label_options: &[LabelOption<&str>],
) -> &'l mut Self
{
self.z_axis.set_ticks(
tick_placement,
tick_options.to_one_way_owned(),
label_options.to_one_way_owned(),
);
self
}
pub fn set_z_ticks_custom<
'l,
T: DataType,
S: ToString,
TickT: Borrow<Tick<T, S>>,
TL: IntoIterator<Item = TickT>,
>(
&'l mut self, ticks: TL, tick_options: &[TickOption<&str>],
label_options: &[LabelOption<&str>],
) -> &'l mut Self
{
self.z_axis.set_ticks_custom(
ticks.into_iter().map(|e| e.borrow().to_one_way_owned()),
tick_options.to_one_way_owned(),
label_options.to_one_way_owned(),
);
self
}
pub fn set_z_range<'l>(&'l mut self, min: AutoOption<f64>, max: AutoOption<f64>)
-> &'l mut Self
{
self.z_axis.set_range(min, max);
self
}
pub fn set_z_reverse<'l>(&'l mut self, reverse: bool) -> &'l mut Self
{
self.z_axis.set_reverse(reverse);
self
}
pub fn set_z_log<'l>(&'l mut self, base: Option<f64>) -> &'l mut Self
{
self.z_axis.set_log(base);
self
}
pub fn set_z_grid<'l>(&'l mut self, show: bool) -> &'l mut Self
{
self.z_axis.set_grid(show);
self
}
pub fn set_z_time<'l>(&'l mut self, is_time: bool) -> &'l mut Self
{
self.z_axis.set_time(is_time);
self
}
pub fn show_contours<'l>(
&'l mut self, base: bool, surface: bool, style: ContourStyle, label: AutoOption<&str>,
levels: AutoOption<u32>,
) -> &'l mut Self
{
self.contour_base = base;
self.contour_surface = surface;
self.contour_style = style;
self.contour_auto = levels;
self.contour_levels = None;
self.contour_label = label.map(|l| l.to_string());
self
}
pub fn show_contours_custom<'l, T: DataType, TC: IntoIterator<Item = T>>(
&'l mut self, base: bool, surface: bool, style: ContourStyle, label: AutoOption<&str>,
levels: TC,
) -> &'l mut Self
{
self.contour_base = base;
self.contour_surface = surface;
self.contour_style = style;
self.contour_auto = Auto;
self.contour_levels = Some(levels.into_iter().map(|l| l.get()).collect());
self.contour_label = label.map(|l| l.to_string());
self
}
pub(crate) fn reset_state(&self, writer: &mut dyn Writer)
{
self.common.reset_state(writer);
self.view.as_ref().map(|v| v.reset_state(writer));
}
pub(crate) fn write_out(&self, w: &mut dyn Writer, auto_layout: bool, version: GnuplotVersion)
{
fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T
{
if val < min
{
min
}
else if val > max
{
max
}
else
{
val
}
}
if self.contour_base || self.contour_surface
{
write!(w, "set contour ");
write!(
w,
"{}",
match (self.contour_base, self.contour_surface)
{
(true, false) => "base",
(false, true) => "surface",
(true, true) => "both",
_ => unreachable!(),
}
);
write!(w, "\n");
match self.contour_label
{
Auto => writeln!(w, "set clabel"),
Fix(ref s) =>
{
if s.len() == 0
{
writeln!(w, "unset clabel")
}
else
{
writeln!(w, r#"set clabel "{}""#, s)
}
}
};
fn set_cntrparam<F: FnOnce(&mut dyn Writer)>(w: &mut dyn Writer, wr: F)
{
write!(w, "set cntrparam ");
wr(w);
write!(w, "\n");
}
set_cntrparam(w, |w| {
write!(
w,
"{}",
match self.contour_style
{
Linear => "linear ",
Cubic(..) => "cubicspline",
Spline(..) => "bspline",
}
);
});
set_cntrparam(w, |w| {
let pt = match self.contour_style
{
Cubic(pt) => Some(pt),
Spline(pt, _) => Some(pt),
_ => None,
};
pt.map(|pt| {
write!(w, "points {}", clamp(pt, 2, 100));
});
});
set_cntrparam(w, |w| {
let ord = match self.contour_style
{
Spline(_, ord) => Some(ord),
_ => None,
};
ord.map(|ord| {
write!(w, "order {}", clamp(ord, 2, 10));
});
});
set_cntrparam(w, |w| {
write!(w, "levels ");
match self.contour_levels
{
Some(ref ls) =>
{
write!(w, "discrete ");
let mut left = ls.len();
for &l in ls.iter()
{
write!(w, "{:.12e}", l);
if left > 1
{
write!(w, ",");
}
left -= 1;
}
}
None =>
{
match self.contour_auto
{
Auto => write!(w, "auto "),
Fix(f) => write!(w, "{}", f),
};
}
};
});
}
self.common.write_out_commands(w, auto_layout, version);
self.z_axis.write_out_commands(w, version);
let mut grid_axes = vec![];
if self.common.x_axis.grid
{
grid_axes.push(self.common.x_axis.axis);
}
if self.common.y_axis.grid
{
grid_axes.push(self.common.y_axis.axis);
}
if self.common.cb_axis.grid
{
grid_axes.push(self.common.cb_axis.axis);
}
if self.z_axis.grid
{
grid_axes.push(self.z_axis.axis);
}
self.view.as_ref().map(|v| v.write_out(w));
self.common.write_grid_options(w, &grid_axes, version);
self.common.write_out_elements("splot", w, version);
}
}
impl AxesCommonPrivate for Axes3D
{
fn get_common_data_mut(&mut self) -> &mut AxesCommonData
{
&mut self.common
}
fn get_common_data(&self) -> &AxesCommonData
{
&self.common
}
}
impl AxesCommon for Axes3D {}