From e581f05aca3d59479f9c8a98d2543cc8eb4842c8 Mon Sep 17 00:00:00 2001 From: Michal Sustr Date: Wed, 3 Dec 2025 16:54:13 +0100 Subject: [PATCH 1/2] Simplify heatmap code --- egui_plot/src/items/heatmap.rs | 72 ++++++++++++++++------------------ egui_plot/src/items/mod.rs | 1 - egui_plot/src/lib.rs | 1 - examples/heatmap/src/app.rs | 1 - 4 files changed, 33 insertions(+), 42 deletions(-) diff --git a/egui_plot/src/items/heatmap.rs b/egui_plot/src/items/heatmap.rs index 8f492d05..bd1e731b 100644 --- a/egui_plot/src/items/heatmap.rs +++ b/egui_plot/src/items/heatmap.rs @@ -38,25 +38,6 @@ pub const BASE_COLORS: [Color32; 10] = [ Color32::from_rgb(122, 4, 2), ]; -#[derive(Debug)] -pub enum HeatmapErr { - ZeroColumns, - ZeroRows, - BadLength, -} - -impl std::fmt::Display for HeatmapErr { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::ZeroColumns => write!(f, "number of columns must not be zero"), - Self::ZeroRows => write!(f, "number of rows must not be zero"), - Self::BadLength => write!(f, "length of value vector is not divisible by number of columns"), - } - } -} - -impl std::error::Error for HeatmapErr {} - /// Default resolution for heatmap color palette pub const DEFAULT_RESOLUTION: usize = 128; @@ -134,9 +115,8 @@ impl Heatmap { /// Create a 2D heatmap. Will automatically infer number of rows. /// /// - `values` contains magnitude of each tile. The alignment is row by row. - /// - `cols` is the number of columns (i.e. the length of each row) and must - /// not be zero. - /// - `values.len()` must be a multiple of `cols`. + /// - `cols` is the number of columns (i.e. the length of each row). + /// - `values.len()` should be a multiple of `cols`. /// /// Example: To display this /// @@ -146,23 +126,15 @@ impl Heatmap { /// /// pass `values = vec![0.0, 0.1, 0.3, 0.4]` and `cols = 2`. /// - /// Returns error type if provided parameters are inconsistent - /// - /// # Errors - /// - `HeatmapErr::ZeroColumns` if `cols` is zero - /// - `HeatmapErr::ZeroRows` if `values` is empty - /// - `HeatmapErr::BadLength` if `values.len()` is not divisible by `cols` - pub fn new(values: Vec, cols: usize) -> Result { - if cols == 0 { - return Err(HeatmapErr::ZeroColumns); - } - if (values.len() % cols) != 0 { - return Err(HeatmapErr::BadLength); + /// If parameters are invalid (e.g., `cols` is zero, `values` is empty, or + /// `values.len()` is not divisible by `cols`), an empty heatmap is created. + pub fn new(values: Vec, cols: usize) -> Self { + // Handle invalid parameters by creating an empty heatmap + if cols == 0 || values.is_empty() || (values.len() % cols) != 0 { + return Self::empty(); } + let rows = values.len() / cols; - if rows == 0 { - return Err(HeatmapErr::ZeroRows); - } // determine range let mut min = f64::MAX; @@ -174,7 +146,7 @@ impl Heatmap { let resolution = DEFAULT_RESOLUTION; - Ok(Self { + Self { base: PlotItemBase::new(String::new()), pos: PlotPoint { x: 0.0, y: 0.0 }, values, @@ -190,7 +162,29 @@ impl Heatmap { highlight: false, name: String::new(), tile_size: Vec2 { x: 1.0, y: 1.0 }, - }) + } + } + + /// Create an empty heatmap (no tiles). + fn empty() -> Self { + let resolution = DEFAULT_RESOLUTION; + Self { + base: PlotItemBase::new(String::new()), + pos: PlotPoint { x: 0.0, y: 0.0 }, + values: Vec::new(), + cols: 0, + rows: 0, + min: 0.0, + max: 0.0, + formatter: Box::new(|v| format!("{v:.1}")), + custom_mapping: None, + show_labels: true, + resolution, + palette: Self::linear_gradient_from_base_colors(&BASE_COLORS, resolution), + highlight: false, + name: String::new(), + tile_size: Vec2 { x: 1.0, y: 1.0 }, + } } /// Set the resolution of the color palette. diff --git a/egui_plot/src/items/mod.rs b/egui_plot/src/items/mod.rs index d51972dc..a4e6b41b 100644 --- a/egui_plot/src/items/mod.rs +++ b/egui_plot/src/items/mod.rs @@ -22,7 +22,6 @@ use egui::pos2; use egui::vec2; use emath::Float as _; pub use heatmap::Heatmap; -pub use heatmap::HeatmapErr; pub use line::HLine; pub use line::VLine; pub use plot_image::PlotImage; diff --git a/egui_plot/src/lib.rs b/egui_plot/src/lib.rs index cfe39c48..a3e1078c 100644 --- a/egui_plot/src/lib.rs +++ b/egui_plot/src/lib.rs @@ -43,7 +43,6 @@ pub use crate::items::BoxSpread; pub use crate::items::ClosestElem; pub use crate::items::HLine; pub use crate::items::Heatmap; -pub use crate::items::HeatmapErr; pub use crate::items::Line; pub use crate::items::LineStyle; pub use crate::items::MarkerShape; diff --git a/examples/heatmap/src/app.rs b/examples/heatmap/src/app.rs index 329cb7ff..ac3f7bd6 100644 --- a/examples/heatmap/src/app.rs +++ b/examples/heatmap/src/app.rs @@ -94,7 +94,6 @@ impl HeatmapDemo { } let heatmap = egui_plot::Heatmap::new(values, self.cols) - .expect("Failed to create heatmap") .palette(&self.palette) .highlight(true) .show_labels(self.show_labels); From bb773952a429802db2a8319681fe7a570006dd3e Mon Sep 17 00:00:00 2001 From: Michal Sustr Date: Wed, 3 Dec 2025 16:55:56 +0100 Subject: [PATCH 2/2] allow empty --- egui_plot/src/items/span.rs | 6 +++--- examples/heatmap/src/app.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/egui_plot/src/items/span.rs b/egui_plot/src/items/span.rs index 727aa4e3..191c6890 100644 --- a/egui_plot/src/items/span.rs +++ b/egui_plot/src/items/span.rs @@ -29,9 +29,9 @@ use crate::utils::find_name_candidate; /// Padding between the label of the span and both the edge of the view and the /// span borders. /// -/// For example, for a horizontal span, this is the padding between the top of the span -/// label and the top edge of the plot view, but also the margin between the left/right -/// edges of the span and the span label. +/// For example, for a horizontal span, this is the padding between the top of +/// the span label and the top edge of the plot view, but also the margin +/// between the left/right edges of the span and the span label. const LABEL_PADDING: f32 = 4.0; /// A span covering a range on either axis. diff --git a/examples/heatmap/src/app.rs b/examples/heatmap/src/app.rs index ac3f7bd6..71c39ee6 100644 --- a/examples/heatmap/src/app.rs +++ b/examples/heatmap/src/app.rs @@ -55,8 +55,8 @@ impl HeatmapDemo { }); ui.group(|ui| { ui.vertical(|ui| { - ui.add(egui::Slider::new(&mut self.rows, 1..=50).text("Rows")); - ui.add(egui::Slider::new(&mut self.cols, 1..=50).text("Columns")); + ui.add(egui::Slider::new(&mut self.rows, 0..=50).text("Rows")); + ui.add(egui::Slider::new(&mut self.cols, 0..=50).text("Columns")); }); }); ui.group(|ui| {