use crate::axis::plot::coordinate::Coordinate2D;
use std::fmt;
#[allow(unused_imports)]
use crate::{Axis, Picture};
pub mod coordinate;
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum PlotKey {
Custom(String),
Type2D(Type2D),
XError(ErrorCharacter),
XErrorDirection(ErrorDirection),
YError(ErrorCharacter),
YErrorDirection(ErrorDirection),
}
impl fmt::Display for PlotKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PlotKey::Custom(key) => write!(f, "{key}"),
PlotKey::Type2D(value) => write!(f, "{value}"),
PlotKey::XError(value) => write!(f, "error bars/x {value}"),
PlotKey::XErrorDirection(value) => write!(f, "error bars/x dir={value}"),
PlotKey::YError(value) => write!(f, "error bars/y {value}"),
PlotKey::YErrorDirection(value) => write!(f, "error bars/y dir={value}"),
}
}
}
#[derive(Clone, Debug, Default)]
pub struct Plot2D {
keys: Vec<PlotKey>,
pub coordinates: Vec<Coordinate2D>,
}
impl fmt::Display for Plot2D {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "\t\\addplot[")?;
if !self.keys.is_empty() {
writeln!(f)?;
for key in self.keys.iter() {
writeln!(f, "\t\t{key},")?;
}
write!(f, "\t")?;
}
writeln!(f, "] coordinates {{")?;
for coordinate in self.coordinates.iter() {
writeln!(f, "\t\t{coordinate}")?;
}
write!(f, "\t}};")?;
Ok(())
}
}
impl Plot2D {
pub fn new() -> Self {
Default::default()
}
pub fn add_key(&mut self, key: PlotKey) {
match key {
PlotKey::Custom(_) => (),
_ => {
if let Some(index) = self
.keys
.iter()
.position(|k| std::mem::discriminant(k) == std::mem::discriminant(&key))
{
self.keys.remove(index);
}
}
}
self.keys.push(key);
}
}
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
pub enum Type2D {
SharpPlot,
Smooth { tension: f64 },
ConstLeft,
ConstRight,
ConstMid,
JumpLeft,
JumpRight,
JumpMid,
XBar { bar_width: f64, bar_shift: f64 },
YBar { bar_width: f64, bar_shift: f64 },
XComb,
YComb,
OnlyMarks,
}
impl fmt::Display for Type2D {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Type2D::SharpPlot => write!(f, "sharp plot"),
Type2D::Smooth { tension } => write!(f, "smooth, tension={tension}"),
Type2D::ConstLeft => write!(f, "const plot mark left"),
Type2D::ConstRight => write!(f, "const plot mark right"),
Type2D::ConstMid => write!(f, "const plot mark mid"),
Type2D::JumpLeft => write!(f, "jump mark left"),
Type2D::JumpRight => write!(f, "jump mark right"),
Type2D::JumpMid => write!(f, "jump mark mid"),
Type2D::XBar {
bar_width,
bar_shift,
} => write!(f, "xbar, bar width={bar_width}, bar shift={bar_shift}"),
Type2D::YBar {
bar_width,
bar_shift,
} => write!(f, "ybar, bar width={bar_width}, bar shift={bar_shift}"),
Type2D::XComb => write!(f, "xcomb"),
Type2D::YComb => write!(f, "ycomb"),
Type2D::OnlyMarks => write!(f, "only marks"),
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum ErrorCharacter {
Absolute,
Relative,
}
impl fmt::Display for ErrorCharacter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorCharacter::Absolute => write!(f, "explicit"),
ErrorCharacter::Relative => write!(f, "explicit relative"),
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum ErrorDirection {
None,
Plus,
Minus,
Both,
}
impl fmt::Display for ErrorDirection {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorDirection::None => write!(f, "none"),
ErrorDirection::Plus => write!(f, "plus"),
ErrorDirection::Minus => write!(f, "minus"),
ErrorDirection::Both => write!(f, "both"),
}
}
}
#[cfg(test)]
mod tests;