Skip to content

Commit

Permalink
heatmap: Add example to plot demo
Browse files Browse the repository at this point in the history
  • Loading branch information
JohannesProgrammiert committed May 27, 2023
1 parent 7d27aef commit 203d972
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 5 deletions.
27 changes: 23 additions & 4 deletions crates/egui/src/widgets/plot/items/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,25 @@ pub struct Heatmap<const RESOLUTION: usize> {
tile_size: Vec2,
}

impl<const RESOLUTION: usize> PartialEq for Heatmap<RESOLUTION> {
/// manual implementation of PartialEq because formatter and color mapping do not impl PartialEq.
///
/// > NOTE: custom_mapping and formatter are ignored
fn eq(&self, other: &Self) -> bool {
self.pos == other.pos
&& self.values == other.values
&& self.cols == other.cols
&& self.rows == other.rows
&& self.min == other.min
&& self.max == other.max
&& self.show_labels == other.show_labels
&& self.palette == other.palette
&& self.highlight == other.highlight
&& self.name == other.name
&& self.tile_size == other.tile_size
}
}

impl<const RESOLUTION: usize> Heatmap<RESOLUTION> {
/// Create a 2D heatmap. Will automatically infer number of rows.
///
Expand Down Expand Up @@ -1802,7 +1821,7 @@ impl<const RESOLUTION: usize> Heatmap<RESOLUTION> {
self
}

fn push_shapes(&self, ui: &Ui, transform: &ScreenTransform, shapes: &mut Vec<Shape>) {
fn push_shapes(&self, ui: &Ui, transform: &PlotTransform, shapes: &mut Vec<Shape>) {
let mut mesh = Mesh::default();
let mut labels: Vec<Shape> = Vec::new();
for i in 0..self.values.len() {
Expand All @@ -1820,7 +1839,7 @@ impl<const RESOLUTION: usize> Heatmap<RESOLUTION> {
fn tile_view_info(
&self,
ui: &Ui,
transform: &ScreenTransform,
transform: &PlotTransform,
index: usize,
) -> (Rect, Color32, Shape) {
let v = self.values[index];
Expand Down Expand Up @@ -1883,7 +1902,7 @@ impl<const RESOLUTION: usize> Heatmap<RESOLUTION> {
}

impl<const RESOLUTION: usize> PlotItem for Heatmap<RESOLUTION> {
fn shapes(&self, ui: &mut Ui, transform: &ScreenTransform, shapes: &mut Vec<Shape>) {
fn shapes(&self, ui: &mut Ui, transform: &PlotTransform, shapes: &mut Vec<Shape>) {
self.push_shapes(ui, transform, shapes);
}

Expand Down Expand Up @@ -1922,7 +1941,7 @@ impl<const RESOLUTION: usize> PlotItem for Heatmap<RESOLUTION> {
}
}

fn find_closest(&self, point: Pos2, transform: &ScreenTransform) -> Option<ClosestElem> {
fn find_closest(&self, point: Pos2, transform: &PlotTransform) -> Option<ClosestElem> {
self.values
.clone() // FIXME: is there a better solution that cloning?
.into_iter()
Expand Down
83 changes: 82 additions & 1 deletion crates/egui_demo_lib/src/demo/plot_demo.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::f64::consts::TAU;
use std::ops::RangeInclusive;

use egui::plot::{AxisBools, GridInput, GridMark, PlotResponse};
use egui::plot::{AxisBools, GridInput, GridMark, Heatmap, PlotResponse};
use egui::*;
use plot::{
Arrows, Bar, BarChart, BoxElem, BoxPlot, BoxSpread, CoordinatesFormatter, Corner, HLine,
Expand All @@ -21,6 +21,7 @@ enum Panel {
Interaction,
CustomAxes,
LinkedAxes,
Heatmap,
}

impl Default for Panel {
Expand All @@ -41,6 +42,7 @@ pub struct PlotDemo {
interaction_demo: InteractionDemo,
custom_axes_demo: CustomAxisDemo,
linked_axes_demo: LinkedAxisDemo,
heatmap_demo: HeatmapDemo,
open_panel: Panel,
}

Expand Down Expand Up @@ -87,6 +89,7 @@ impl super::View for PlotDemo {
ui.selectable_value(&mut self.open_panel, Panel::Interaction, "Interaction");
ui.selectable_value(&mut self.open_panel, Panel::CustomAxes, "Custom Axes");
ui.selectable_value(&mut self.open_panel, Panel::LinkedAxes, "Linked Axes");
ui.selectable_value(&mut self.open_panel, Panel::Heatmap, "Heatmap");
});
ui.separator();

Expand Down Expand Up @@ -115,6 +118,9 @@ impl super::View for PlotDemo {
Panel::LinkedAxes => {
self.linked_axes_demo.ui(ui);
}
Panel::Heatmap => {
self.heatmap_demo.ui(ui);
}
}
}
}
Expand Down Expand Up @@ -1006,3 +1012,78 @@ impl ChartsDemo {
.response
}
}
#[derive(PartialEq)]
struct HeatmapDemo {
tick: f64,
animate: bool,
show_labels: bool,
palette: Vec<Color32>,
rows: usize,
cols: usize,
}

impl Default for HeatmapDemo {
fn default() -> Self {
Self {
tick: 0.0,
animate: true,
show_labels: false,
palette: vec![Color32::WHITE, Color32::RED, Color32::BLACK],
rows: 10,
cols: 15,
}
}
}

impl HeatmapDemo {
fn ui(&mut self, ui: &mut Ui) -> Response {
ui.checkbox(&mut self.animate, "Animate");
if self.animate {
ui.ctx().request_repaint();
self.tick += 1.0;
}
ui.checkbox(&mut self.show_labels, "Show labels");
ui.add(Slider::new(&mut self.rows, 1..=100).text("Rows"));
ui.add(Slider::new(&mut self.cols, 1..=100).text("Columns"));
let mut values = Vec::new();
for y in 0..self.rows {
for x in 0..self.cols {
let y = y as f64;
let x = x as f64;
let cols = self.cols as f64;
let rows = self.rows as f64;
values.push(((x + self.tick) / rows).sin() + ((y + self.tick) / cols).cos())
}
}
if self.palette.len() > 1 {}
ui.add_enabled_ui(self.palette.len() > 1, |ui| {
if ui.button("Pop color").clicked() {
self.palette.pop();
}
});
if ui.button("Push color").clicked() {
self.palette.push(*self.palette.last().unwrap());
}
ui.horizontal(|ui| {
for color in &mut self.palette {
ui.color_edit_button_srgba(color);
}
});

let heatmap = Heatmap::<128>::new(values, self.cols)
.unwrap()
.palette(self.palette.clone())
.show_labels(self.show_labels);
Plot::new("Heatmap Demo")
.legend(Legend::default())
.allow_zoom(false)
.allow_scroll(false)
.allow_drag(false)
.allow_boxed_zoom(false)
.set_margin_fraction(vec2(0.0, 0.0))
.show(ui, |plot_ui| {
plot_ui.heatmap(heatmap);
})
.response
}
}

0 comments on commit 203d972

Please sign in to comment.