it builds! (still need to implement colors and multiple inputs)
This commit is contained in:
179
src/egui_app.rs
179
src/egui_app.rs
@@ -1,7 +1,7 @@
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use crate::chart_manager::{ChartManager, UpdateType};
|
||||
use crate::misc::{digits_precision, test_func, Cache};
|
||||
use crate::function::Function;
|
||||
use crate::misc::{digits_precision, test_func};
|
||||
use eframe::{egui, epi};
|
||||
use egui::plot::{Line, Plot, Value, Values};
|
||||
use egui::widgets::plot::{Bar, BarChart};
|
||||
@@ -12,98 +12,60 @@ use git_version::git_version;
|
||||
const GIT_VERSION: &str = git_version!();
|
||||
|
||||
// Sets some hard-coded limits to the application
|
||||
const NUM_INTERVAL_RANGE: RangeInclusive<usize> = 10..=1000000;
|
||||
const INTEGRAL_NUM_RANGE: RangeInclusive<usize> = 10..=1000000;
|
||||
const MIN_X_TOTAL: f64 = -1000.0;
|
||||
const MAX_X_TOTAL: f64 = 1000.0;
|
||||
const X_RANGE: RangeInclusive<f64> = MIN_X_TOTAL..=MAX_X_TOTAL;
|
||||
|
||||
pub struct MathApp {
|
||||
func_str: String,
|
||||
functions: Vec<Function>,
|
||||
min_x: f64,
|
||||
max_x: f64,
|
||||
|
||||
// Currently really unused. But once fully implemented it will represent the full graph's min_x and max_x, being seperate from min_x and max_x for the intergral.
|
||||
min_x_graph: f64,
|
||||
max_x_graph: f64,
|
||||
integral_min_x: f64,
|
||||
integral_max_x: f64,
|
||||
|
||||
num_interval: usize,
|
||||
resolution: usize,
|
||||
chart_manager: ChartManager,
|
||||
back_cache: Cache<Vec<Value>>,
|
||||
front_cache: Cache<(Vec<Bar>, f64)>,
|
||||
integral_num: usize,
|
||||
}
|
||||
|
||||
impl Default for MathApp {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
let def_func = "x^2".to_string();
|
||||
let def_func_str = "x^2".to_string();
|
||||
let def_min_x = -10.0;
|
||||
let def_max_x = 10.0;
|
||||
let def_interval: usize = 1000;
|
||||
let def_resolution: usize = 10000;
|
||||
|
||||
let def_funcs: Vec<Function> = vec![Function::new(
|
||||
def_func_str,
|
||||
def_min_x,
|
||||
def_max_x,
|
||||
true,
|
||||
Some(def_min_x),
|
||||
Some(def_max_x),
|
||||
Some(def_interval),
|
||||
)];
|
||||
|
||||
Self {
|
||||
func_str: def_func.clone(),
|
||||
functions: def_funcs,
|
||||
min_x: def_min_x,
|
||||
max_x: def_max_x,
|
||||
min_x_graph: def_min_x,
|
||||
max_x_graph: def_max_x,
|
||||
num_interval: def_interval,
|
||||
resolution: def_resolution,
|
||||
chart_manager: ChartManager::new(
|
||||
def_func,
|
||||
def_min_x,
|
||||
def_max_x,
|
||||
def_min_x,
|
||||
def_max_x,
|
||||
def_interval,
|
||||
def_resolution,
|
||||
),
|
||||
back_cache: Cache::new_empty(),
|
||||
front_cache: Cache::new_empty(),
|
||||
integral_min_x: def_min_x,
|
||||
integral_max_x: def_max_x,
|
||||
integral_num: def_interval,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MathApp {
|
||||
#[inline]
|
||||
fn get_back(&mut self) -> Line {
|
||||
let data = if self.back_cache.is_valid() {
|
||||
self.back_cache.get().clone()
|
||||
} else {
|
||||
let data = self.chart_manager.draw_back();
|
||||
let data_values: Vec<Value> = data.iter().map(|(x, y)| Value::new(*x, *y)).collect();
|
||||
self.back_cache.set(data_values.clone());
|
||||
data_values
|
||||
};
|
||||
Line::new(Values::from_values(data)).color(Color32::RED)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_front(&mut self) -> (Vec<Bar>, f64) {
|
||||
if self.front_cache.is_valid() {
|
||||
let cache = self.front_cache.get();
|
||||
let vec_bars: Vec<Bar> = cache.0.to_vec();
|
||||
(vec_bars, cache.1)
|
||||
} else {
|
||||
let (data, area) = self.chart_manager.draw_front();
|
||||
let bars: Vec<Bar> = data.iter().map(|(x, y)| Bar::new(*x, *y)).collect();
|
||||
|
||||
let output = (bars, area);
|
||||
self.front_cache.set(output.clone());
|
||||
output
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_data(&mut self) -> (Line, Vec<Bar>, f64) {
|
||||
let (bars, area) = self.get_front();
|
||||
(self.get_back(), bars, area)
|
||||
pub fn get_step(&self) -> f64 {
|
||||
(self.integral_min_x - self.integral_max_x).abs() / (self.integral_num as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl epi::App for MathApp {
|
||||
|
||||
// The name of the program (displayed when running natively as the window title)
|
||||
fn name(&self) -> &str { "Integral Demonstration" }
|
||||
|
||||
@@ -118,16 +80,12 @@ impl epi::App for MathApp {
|
||||
#[inline]
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &epi::Frame) {
|
||||
let Self {
|
||||
func_str,
|
||||
functions,
|
||||
min_x,
|
||||
max_x,
|
||||
min_x_graph,
|
||||
max_x_graph,
|
||||
num_interval,
|
||||
resolution,
|
||||
chart_manager,
|
||||
back_cache,
|
||||
front_cache,
|
||||
integral_min_x,
|
||||
integral_max_x,
|
||||
integral_num,
|
||||
} = self;
|
||||
|
||||
// Note: This Instant implementation does not show microseconds when using wasm.
|
||||
@@ -146,21 +104,28 @@ impl epi::App for MathApp {
|
||||
ui.label("- signum, min, max");
|
||||
});
|
||||
|
||||
let mut func_new_strings: Vec<String> = Vec::new();
|
||||
let mut parse_error: String = "".to_string();
|
||||
egui::SidePanel::left("side_panel")
|
||||
.resizable(false)
|
||||
.show(ctx, |ui| {
|
||||
ui.heading("Side Panel");
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Function: ");
|
||||
ui.text_edit_singleline(func_str);
|
||||
});
|
||||
for function in functions.iter() {
|
||||
let mut func_str = function.get_string();
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Function: ");
|
||||
ui.text_edit_singleline(&mut func_str);
|
||||
});
|
||||
|
||||
let func_test_output = test_func(func_str.clone());
|
||||
if !func_test_output.is_empty() {
|
||||
parse_error = func_test_output;
|
||||
let func_test_output = test_func(func_str.clone());
|
||||
if !func_test_output.is_empty() {
|
||||
parse_error += &func_test_output;
|
||||
}
|
||||
|
||||
func_new_strings.push(func_str);
|
||||
}
|
||||
|
||||
let min_x_old = *min_x;
|
||||
let min_x_response =
|
||||
ui.add(egui::Slider::new(min_x, X_RANGE.clone()).text("Min X"));
|
||||
@@ -178,11 +143,11 @@ impl epi::App for MathApp {
|
||||
*min_x = -10.0;
|
||||
*max_x = 10.0;
|
||||
}
|
||||
*min_x_graph = *min_x;
|
||||
*max_x_graph = *max_x;
|
||||
*integral_min_x = *min_x;
|
||||
*integral_max_x = *max_x;
|
||||
}
|
||||
|
||||
ui.add(egui::Slider::new(num_interval, NUM_INTERVAL_RANGE).text("Interval"));
|
||||
ui.add(egui::Slider::new(integral_num, INTEGRAL_NUM_RANGE).text("Interval"));
|
||||
|
||||
// Opensource and Licensing information
|
||||
ui.horizontal(|ui| {
|
||||
@@ -210,30 +175,13 @@ impl epi::App for MathApp {
|
||||
ui.label(GIT_VERSION);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if parse_error.is_empty() {
|
||||
let do_update = chart_manager.update(
|
||||
func_str.clone(),
|
||||
*min_x,
|
||||
*max_x,
|
||||
*min_x_graph,
|
||||
*max_x_graph,
|
||||
*num_interval,
|
||||
*resolution,
|
||||
);
|
||||
|
||||
// Invalidates caches according to what settings were changed
|
||||
match do_update {
|
||||
UpdateType::Full => {
|
||||
back_cache.invalidate();
|
||||
front_cache.invalidate();
|
||||
let mut i: usize = 0;
|
||||
for function in functions.iter_mut() {
|
||||
function.update(func_new_strings[i].clone(), *min_x, *max_x, true, Some(*integral_min_x), Some(*integral_max_x), Some(*integral_num));
|
||||
i += 1;
|
||||
}
|
||||
UpdateType::Back => back_cache.invalidate(),
|
||||
UpdateType::Front => front_cache.invalidate(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
if !parse_error.is_empty() {
|
||||
@@ -241,26 +189,33 @@ impl epi::App for MathApp {
|
||||
return;
|
||||
}
|
||||
|
||||
let (curve, bars, area) = self.get_data();
|
||||
|
||||
let bar_chart = BarChart::new(bars)
|
||||
.color(Color32::BLUE)
|
||||
.width(self.chart_manager.get_step());
|
||||
|
||||
let step = self.get_step();
|
||||
let mut area_list: Vec<f64> = Vec::new();
|
||||
Plot::new("plot")
|
||||
.view_aspect(1.0)
|
||||
.data_aspect(1.0)
|
||||
.include_y(0)
|
||||
.show(ui, |plot_ui| {
|
||||
plot_ui.line(curve);
|
||||
plot_ui.bar_chart(bar_chart);
|
||||
for function in self.functions.iter_mut() {
|
||||
let output = function.run();
|
||||
let back = output.get_back();
|
||||
plot_ui.line(Line::new(Values::from_values(back)).color(Color32::RED));
|
||||
|
||||
if output.has_integral() {
|
||||
let (bars, area) = output.get_front();
|
||||
let bar_chart =
|
||||
BarChart::new(bars.clone()).color(Color32::BLUE).width(step);
|
||||
plot_ui.bar_chart(bar_chart);
|
||||
area_list.push(digits_precision(area, 8))
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let duration = start.elapsed();
|
||||
|
||||
ui.label(format!(
|
||||
"Area: {} Took: {:?}",
|
||||
digits_precision(area, 8),
|
||||
"Area: {:?} Took: {:?}",
|
||||
area_list.clone(),
|
||||
duration
|
||||
));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user