From 1e773605f6f197e85aff1feef9cd9d7862ca25f7 Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Wed, 23 Feb 2022 19:43:19 -0500 Subject: [PATCH] progress --- Cargo.toml | 2 ++ TODO.md | 1 + src/chart_manager.rs | 13 ++++++++++ src/egui_app.rs | 60 +++++++++++++++++++++++++++++++++----------- 4 files changed, 61 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5ef0a66..47da783 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,8 @@ egui = "0.17.0" eframe = "0.17.0" emath = "0.17.0" epaint = "0.17.0" +instant = { version = "0.1.12", features = ["wasm-bindgen"] } + [target.'cfg(target_arch = "wasm32")'.dependencies] console_error_panic_hook = "0.1.7" tracing-wasm = "0.2.1" diff --git a/TODO.md b/TODO.md index cfabc77..2ed2a34 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,6 @@ ## TODO: 1. Port to [egui](https://github.com/emilk/egui) - Proper support for dynamic chart display size. + - Don't re-render plot on mouse movement 2. Multiple functions in one graph. 3. Non `y=` functions. \ No newline at end of file diff --git a/src/chart_manager.rs b/src/chart_manager.rs index 320e09e..3bb5fad 100644 --- a/src/chart_manager.rs +++ b/src/chart_manager.rs @@ -56,6 +56,19 @@ impl ChartManager { (filtered_data, rect_data, area) } + pub fn do_update_front(&self, resolution: usize, num_interval: usize) -> bool { + (self.resolution != resolution) | (num_interval != self.num_interval) + } + + pub fn do_update_back(&self, func_str_new: String, min_x: f64, max_x: f64) -> bool { + let func_str: String = add_asterisks(func_str_new); + let update_func: bool = !self.function.str_compare(func_str.clone()); + + let underlying_update = update_func | (min_x != self.min_x) | (max_x != self.max_x); + + underlying_update + } + #[allow(clippy::too_many_arguments)] pub fn update( &mut self, func_str_new: String, min_x: f64, max_x: f64, num_interval: usize, diff --git a/src/egui_app.rs b/src/egui_app.rs index 30e2616..e74735b 100644 --- a/src/egui_app.rs +++ b/src/egui_app.rs @@ -1,12 +1,11 @@ use crate::chart_manager::ChartManager; -use crate::misc::{digits_precision, test_func}; +use crate::misc::{digits_precision, test_func, Cache}; use eframe::{egui, epi}; use egui::widgets::plot::{Bar, BarChart}; use egui::{ plot::{Line, Plot, Value, Values}, }; -use egui::{Color32}; -use std::time::Instant; +use egui::{Color32, plot}; pub struct MathApp { func_str: String, @@ -15,6 +14,7 @@ pub struct MathApp { num_interval: usize, resolution: usize, chart_manager: ChartManager, + bar_cache: Cache>, } impl Default for MathApp { @@ -26,6 +26,7 @@ impl Default for MathApp { num_interval: 100, resolution: 10000, chart_manager: ChartManager::new("x^2".to_string(), -10.0, 10.0, 100, 10000), + bar_cache: Cache::new_empty(), } } } @@ -47,10 +48,13 @@ impl epi::App for MathApp { min_x, max_x, num_interval, - resolution: _, + resolution, chart_manager, + bar_cache, } = self; - let start = Instant::now(); + + // Note: This Instant implementation does not show microseconds when using wasm. + let start = instant::Instant::now(); let min_x_total: f32 = -1000.0; let max_x_total: f32 = 1000.0; @@ -91,6 +95,10 @@ impl epi::App for MathApp { ui.add(egui::Slider::new(num_interval, 1..=usize::MAX).text("Interval")); }); + + let update_back = chart_manager.do_update_back(func_str.clone(), *min_x, *max_x); + let update_front = chart_manager.do_update_front(*num_interval, *resolution); + egui::CentralPanel::default().show(ctx, |ui| { if !parse_error.is_empty() { ui.label(format!("Error: {}", parse_error)); @@ -99,10 +107,10 @@ impl epi::App for MathApp { let (filtered_data, rect_data, area) = chart_manager.update( self.func_str.clone(), - self.min_x, - self.max_x, - self.num_interval, - self.resolution, + *min_x, + *max_x, + *num_interval, + *resolution, ); let filtered_data_values = filtered_data @@ -112,17 +120,39 @@ impl epi::App for MathApp { let curve = Line::new(Values::from_values(filtered_data_values)).color(Color32::RED); - let bars = rect_data - .iter() - .map(|(x, y)| Bar::new(*x, *y)) - .collect(); - let barchart = BarChart::new(bars).color(Color32::BLUE); + let bars: Vec = match update_front { + true => { + let bars: Vec = rect_data + .iter() + .map(|(x, y)| Bar::new(*x, *y)) + .collect(); + + bar_cache.set(bars.clone()); + bars + }, + false => { + if bar_cache.is_valid() { + bar_cache.get().clone() + } else { + let bars: Vec = rect_data + .iter() + .map(|(x, y)| Bar::new(*x, *y)) + .collect(); + + bar_cache.set(bars.clone()); + bars + } + }, + }; + let bar_chart = BarChart::new(bars).color(Color32::BLUE); + + Plot::new("plot") .view_aspect(1.0) .include_y(0) .show(ui, |plot_ui| { plot_ui.line(curve); - plot_ui.bar_chart(barchart); + plot_ui.bar_chart(bar_chart); }); let duration = start.elapsed();