flow_plots/plots/
density.rs

1use crate::PlotBytes;
2use crate::density_calc::{RawPixelData, calculate_density_per_pixel};
3use crate::options::{DensityPlotOptions, PlotOptions};
4use crate::plots::traits::Plot;
5use crate::render::RenderConfig;
6use crate::render::plotters_backend::render_pixels;
7use anyhow::Result;
8
9/// Density plot implementation
10///
11/// Creates a 2D density plot from (x, y) coordinate pairs by binning
12/// data points into pixels and coloring by density.
13///
14/// # Example
15///
16/// ```rust,no_run
17/// use flow_plots::plots::density::DensityPlot;
18/// use flow_plots::options::DensityPlotOptions;
19/// use flow_plots::render::RenderConfig;
20///
21/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
22/// let plot = DensityPlot::new();
23/// let options = DensityPlotOptions::new()
24///     .width(800)
25///     .height(600)
26///     .build()?;
27/// let data: Vec<(f32, f32)> = vec![(100.0, 200.0), (150.0, 250.0)];
28/// let mut render_config = RenderConfig::default();
29/// let bytes = plot.render(data, &options, &mut render_config)?;
30/// # Ok(())
31/// # }
32/// ```
33pub struct DensityPlot;
34
35impl DensityPlot {
36    /// Create a new DensityPlot instance
37    pub fn new() -> Self {
38        Self
39    }
40}
41
42impl Plot for DensityPlot {
43    type Options = DensityPlotOptions;
44    type Data = Vec<(f32, f32)>;
45
46    fn render(
47        &self,
48        data: Self::Data,
49        options: &Self::Options,
50        render_config: &mut RenderConfig,
51    ) -> Result<PlotBytes> {
52        let density_start = std::time::Instant::now();
53
54        // Calculate density per pixel
55        let base = options.base();
56        let raw_pixels = calculate_density_per_pixel(
57            &data[..],
58            base.width as usize,
59            base.height as usize,
60            options,
61        );
62
63        eprintln!(
64            "  ├─ Density calculation: {:?} ({} pixels at {}x{})",
65            density_start.elapsed(),
66            raw_pixels.len(),
67            base.width,
68            base.height
69        );
70
71        let draw_start = std::time::Instant::now();
72        let result = render_pixels(raw_pixels, options, render_config);
73        eprintln!("  └─ Draw + encode: {:?}", draw_start.elapsed());
74
75        result
76    }
77}