Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 33 additions & 39 deletions egui_plot/src/items/heatmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
///
Expand All @@ -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<f64>, cols: usize) -> Result<Self, HeatmapErr> {
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<f64>, 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;
Expand All @@ -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,
Expand All @@ -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.
Expand Down
1 change: 0 additions & 1 deletion egui_plot/src/items/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions egui_plot/src/items/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 0 additions & 1 deletion egui_plot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 2 additions & 3 deletions examples/heatmap/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down Expand Up @@ -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);
Expand Down
Loading