From 36ebce163a74af40f6216cba2d68aa4c728443eb Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 2 Apr 2024 15:37:44 +0200 Subject: [PATCH] egui_plots: Fix the same plot tick label being painted multiple times (#4307) Usually this isn't visible (the same label being painted on top of itself), but it will be visible if the user has a custom formatter (e.g. `y_axis_formatter`) that choses a different format based on `GridMark:step_size` (e.g. using fewer decimals for thicker ticks). --- crates/egui_plot/src/lib.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/crates/egui_plot/src/lib.rs b/crates/egui_plot/src/lib.rs index bae903837..a5adf1c11 100644 --- a/crates/egui_plot/src/lib.rs +++ b/crates/egui_plot/src/lib.rs @@ -13,7 +13,7 @@ mod memory; mod plot_ui; mod transform; -use std::{ops::RangeInclusive, sync::Arc}; +use std::{cmp::Ordering, ops::RangeInclusive, sync::Arc}; use egui::ahash::HashMap; use egui::*; @@ -1717,9 +1717,31 @@ fn generate_marks(step_sizes: [f64; 3], bounds: (f64, f64)) -> Vec { fill_marks_between(&mut steps, step_sizes[0], bounds); fill_marks_between(&mut steps, step_sizes[1], bounds); fill_marks_between(&mut steps, step_sizes[2], bounds); + + // Remove duplicates: + // This can happen because we have overlapping steps, e.g.: + // step_size[0] = 10 => [-10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120] + // step_size[1] = 100 => [ 0, 100 ] + // step_size[2] = 1000 => [ 0 ] + + steps.sort_by(|a, b| match cmp_f64(a.value, b.value) { + // Keep the largest step size when we dedup later + Ordering::Equal => cmp_f64(b.step_size, a.step_size), + + ord => ord, + }); + steps.dedup_by(|a, b| a.value == b.value); + steps } +fn cmp_f64(a: f64, b: f64) -> Ordering { + match a.partial_cmp(&b) { + Some(ord) => ord, + None => a.is_nan().cmp(&b.is_nan()), + } +} + /// Fill in all values between [min, max] which are a multiple of `step_size` fn fill_marks_between(out: &mut Vec, step_size: f64, (min, max): (f64, f64)) { debug_assert!(max > min);