ezel 0.0.1

A good plotting library
Documentation
use piet::{kurbo::Circle, Color, RenderContext};
use polars::prelude::DataFrame;

use crate::{
    cartesian::camera2::Camera2,
    data::{ConstOrColumn, ConstOrColumnTrait},
    primitive::{Marker, MarkerShape},
};

use super::BoundingBox;

pub struct Scatter {
    pub df: DataFrame,
    pub x: ConstOrColumn<f64>,
    pub y: ConstOrColumn<f64>,
    pub marker: MarkerOpts,
}

impl Scatter {
    pub fn render<C: RenderContext>(&self, ctx: &mut C, camera: &Camera2) {
        let n = self.df.height();
        for i in 0..n {
            let marker = self.marker.get(&self.df, i);
            let pos = (self.x.get(&self.df, i), self.y.get(&self.df, i));
            let pos = camera.map(pos);

            match marker.shape {
                MarkerShape::Circle => {
                    if marker.filled {
                        ctx.fill(Circle::new(pos, marker.size), &marker.color);
                    } else {
                        ctx.stroke(
                            Circle::new(pos, marker.size),
                            &marker.color,
                            marker.stroke_thickness,
                        );
                    }
                }
                MarkerShape::Char(_ch) => todo!(),
            }
        }
    }

    pub fn bounding_box(&self) -> Option<BoundingBox> {
        let x_range = self.x.min_max(&self.df)?;
        let y_range = self.y.min_max(&self.df)?;

        Some(BoundingBox {
            min_x: x_range.0,
            max_x: x_range.1,
            min_y: y_range.0,
            max_y: y_range.1,
        })
    }
}

pub struct MarkerOpts {
    pub size: ConstOrColumn<f64>,
    pub color: ConstOrColumn<Color>,
    pub shape: ConstOrColumn<MarkerShape>,
}

impl Default for MarkerOpts {
    fn default() -> Self {
        Self {
            size: ConstOrColumn::Const(5.0),
            color: ConstOrColumn::Const(Color::GREEN),
            shape: ConstOrColumn::Const(MarkerShape::Circle),
        }
    }
}

impl MarkerOpts {
    pub fn get(&self, df: &DataFrame, idx: usize) -> Marker {
        Marker {
            size: self.size.get(df, idx),
            color: self.color.get(df, idx),
            shape: self.shape.get(df, idx),
            filled: true,
            stroke_thickness: 2.0,
            // filled: self.size.get(df, idx),
            // stroke_thickness: todo!(),
        }
    }
}