From 8fa0d34985945f63e55fb8d3876323df26c0374c Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 2 Apr 2024 15:27:04 +0200 Subject: [PATCH] egui_plots: Fix the same plot tick label being painted multiple times 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 bae9038378a..a5adf1c11c1 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);