use std::iter::{Fuse, FusedIterator};
use super::*;
pub mod bar;
pub mod crop;
pub mod output_zip;
pub mod unwrapper;
use marker::Area;
pub mod marker;
pub mod plotit;
use plotit::*;
use unwrapper::Unwrapper;
#[derive(Copy, Clone, Debug)]
pub enum PlotType {
Scatter,
Line,
Histo,
LineFill,
LineFillRaw,
Bars,
}
#[derive(Copy, Clone, Debug)]
pub enum PlotMetaType {
Plot(PlotType),
Text,
}
#[derive(Copy, Clone)]
pub enum ChainDisplay<A, B> {
A(A),
B(B),
}
impl<A: Display, B: Display> fmt::Display for ChainDisplay<A, B> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ChainDisplay::A(a) => write!(f, "{}", a),
ChainDisplay::B(b) => write!(f, "{}", b),
}
}
}
#[derive(Clone)]
pub struct Chain<A, B> {
a: Fuse<A>,
b: Fuse<B>,
}
impl<L: Point, D1: Display, D2: Display, A, B> FusedIterator for Chain<A, B>
where
A: Iterator<Item = PlotTag<L, D1>>,
B: Iterator<Item = PlotTag<L, D2>>,
{
}
impl<L: Point, D1: Display, D2: Display, A, B> Iterator for Chain<A, B>
where
A: Iterator<Item = PlotTag<L, D1>>,
B: Iterator<Item = PlotTag<L, D2>>,
{
type Item = PlotTag<L, ChainDisplay<D1, D2>>;
fn size_hint(&self) -> (usize, Option<usize>) {
let (a, b) = self.a.size_hint();
let (c, d) = self.b.size_hint();
let k = match (b, d) {
(Some(a), Some(b)) => Some(a + b),
(Some(a), _) => Some(a),
(_, Some(b)) => Some(b),
(_, _) => None,
};
(a + c, k)
}
fn next(&mut self) -> Option<Self::Item> {
if let Some(a) = self.a.next() {
Some(match a {
PlotTag::Start {
name,
typ,
size_hint,
} => PlotTag::Start {
name: ChainDisplay::A(name),
typ,
size_hint,
},
PlotTag::Plot(p) => PlotTag::Plot(p),
PlotTag::Finish() => PlotTag::Finish(),
})
} else {
self.b.next().map(|a| match a {
PlotTag::Start {
name,
typ,
size_hint,
} => PlotTag::Start {
name: ChainDisplay::B(name),
typ,
size_hint,
},
PlotTag::Plot(p) => PlotTag::Plot(p),
PlotTag::Finish() => PlotTag::Finish(),
})
}
}
}
pub trait PlotIterator {
type L: Point;
type P: Iterator<Item = PlotTag<Self::L, Self::D>>;
type D: Display;
fn unpack(self) -> PlotRes<Self::P, Self::L>;
fn chain<P: PlotIterator<L = Self::L>>(self, other: P) -> PlotRes<Chain<Self::P, P::P>, Self::L>
where
Self: Sized,
{
let PlotRes {
area: curr_area,
it: p1,
num_plots: n1,
} = self.unpack();
let PlotRes {
area: other_area,
it: p,
num_plots: n2,
} = other.unpack();
let mut area = curr_area;
area.grow_area(&other_area);
PlotRes {
area,
it: Chain {
a: p1.fuse(),
b: p.fuse(),
},
num_plots: n1 + n2,
}
}
fn dyn_box<'a>(self) -> PlotRes<DynIt<'a, Self::L, Self::D>, Self::L>
where
Self::P: 'a,
Self: Sized,
{
let PlotRes {
area,
it,
num_plots,
} = self.unpack();
PlotRes {
it: Box::new(it),
area,
num_plots,
}
}
}
type DynIt<'a, L, D> = Box<dyn Iterator<Item = PlotTag<L, D>> + 'a>;
#[derive(Copy, Clone)]
pub struct PlotRes<I: Iterator, L: Point> {
pub(crate) area: Area<L::X, L::Y>,
pub(crate) num_plots: usize,
pub(crate) it: I,
}
impl<P: Iterator<Item = PlotTag<L, D>>, L: Point, D: Display> PlotIterator for PlotRes<P, L> {
type L = L;
type P = P;
type D = D;
fn unpack(self) -> PlotRes<Self::P, Self::L> {
self
}
}
pub trait Point {
type X: PlotNum;
type Y: PlotNum;
fn get(&self) -> (&Self::X, &Self::Y);
}
impl<X: PlotNum, Y: PlotNum> Point for (X, Y) {
type X = X;
type Y = Y;
fn get(&self) -> (&Self::X, &Self::Y) {
(&self.0, &self.1)
}
}
#[derive(Clone)]
pub enum PlotTag<L: Point, D: Display> {
Start {
name: D,
typ: PlotMetaType,
size_hint: (usize, Option<usize>),
},
Plot(L),
Finish(),
}
pub fn origin<L: Point>() -> PlotRes<std::iter::Empty<PlotTag<L, &'static str>>, L>
where
L::X: HasZero,
L::Y: HasZero,
{
markers(Some(L::X::zero()), Some(L::Y::zero()))
}
pub fn markers<XI: IntoIterator<Item = L::X>, YI: IntoIterator<Item = L::Y>, L: Point>(
x: XI,
y: YI,
) -> PlotRes<std::iter::Empty<PlotTag<L, &'static str>>, L> {
let mut area = Area::new();
for a in x {
area.grow(Some(&a), None);
}
for a in y {
area.grow(None, Some(&a));
}
PlotRes {
area,
it: std::iter::empty(),
num_plots: 0,
}
}
pub fn cloned<L: Point, I: IntoIterator>(it: I) -> ClonedPlotIt<I::IntoIter>
where
I::IntoIter: Clone,
I::Item: build::unwrapper::Unwrapper<Item = L>,
{
ClonedPlotIt::new(it.into_iter())
}
pub struct SinglePlotBuilder<D> {
label: D,
}
#[derive(Clone)]
pub struct PlotIterCreator<I, D> {
start: Option<(PlotMetaType, D)>,
it: Fuse<I>,
posted_finish: bool,
}
impl<I: Iterator<Item = L>, L: Point, D: Display> PlotIterCreator<I, D> {
fn new(label: D, typ: PlotMetaType, it: I) -> Self {
Self {
start: Some((typ, label)),
it: it.fuse(),
posted_finish: false,
}
}
}
impl<I: ExactSizeIterator<Item = L>, L: Point, D: Display> ExactSizeIterator
for PlotIterCreator<I, D>
{
}
impl<I: Iterator<Item = L>, L: Point, D: Display> FusedIterator for PlotIterCreator<I, D> {}
impl<I: Iterator<Item = L>, L: Point, D: Display> Iterator for PlotIterCreator<I, D> {
type Item = PlotTag<L, D>;
fn next(&mut self) -> Option<PlotTag<L, D>> {
if let Some((typ, name)) = self.start.take() {
Some(PlotTag::Start {
typ,
name,
size_hint: self.size_hint(),
})
} else if let Some(l) = self.it.next() {
Some(PlotTag::Plot(l))
} else if !self.posted_finish {
self.posted_finish = true;
Some(PlotTag::Finish())
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (a, b) = self.it.size_hint();
(a + 2, b.map(|b| b + 2))
}
}
impl<D: Display> SinglePlotBuilder<D> {
fn gen<P: PlotIt>(self, it: P, typ: PlotMetaType) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
let mut area = Area::new();
let it = it.unpack(&mut area);
PlotRes {
area,
it: PlotIterCreator::new(self.label, typ, it),
num_plots: 1,
}
}
pub fn line<P: PlotIt>(self, it: P) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
self.gen(it, PlotMetaType::Plot(PlotType::Line))
}
pub(crate) fn bars<P: PlotIt>(self, it: P) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
self.gen(it, PlotMetaType::Plot(PlotType::Bars))
}
pub fn scatter<P: PlotIt>(self, it: P) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
self.gen(it, PlotMetaType::Plot(PlotType::Scatter))
}
pub fn histogram<P: PlotIt>(self, it: P) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
self.gen(it, PlotMetaType::Plot(PlotType::Histo))
}
pub fn line_fill<P: PlotIt>(self, it: P) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
self.gen(it, PlotMetaType::Plot(PlotType::LineFill))
}
pub fn line_fill_raw<P: PlotIt>(self, it: P) -> PlotRes<PlotIterCreator<P::It, D>, P::L> {
self.gen(it, PlotMetaType::Plot(PlotType::LineFillRaw))
}
pub fn text<L: Point>(self) -> PlotRes<PlotIterCreator<std::iter::Empty<L>, D>, L> {
let area = Area::new();
PlotRes {
area,
it: PlotIterCreator::new(self.label, PlotMetaType::Text, std::iter::empty()),
num_plots: 1,
}
}
}
pub fn plot<D: Display>(label: D) -> SinglePlotBuilder<D> {
SinglePlotBuilder { label }
}
impl<I: IntoIterator<Item = P>, P: PlotIterator<L = L>, L: Point> PlotIterator for I {
type L = L;
type P = std::iter::Flatten<std::vec::IntoIter<P::P>>;
type D = P::D;
fn unpack(self) -> PlotRes<Self::P, Self::L> {
let mut total = 0;
let (areas, its): (Vec<_>, Vec<_>) = self
.into_iter()
.map(|x| {
let PlotRes {
area,
it,
num_plots,
} = x.unpack();
total += num_plots;
(area, it)
})
.unzip();
let mut area = Area::new();
for a in areas {
area.grow_area(&a);
}
let it = its.into_iter().flatten();
PlotRes {
area,
it,
num_plots: total,
}
}
}