diff --git a/TODO.md b/TODO.md index 562fe96..2f42911 100644 --- a/TODO.md +++ b/TODO.md @@ -6,4 +6,5 @@ - Different colors (kinda) 2. Rerwite of function parsing code - Non `y=` functions. -3. Display of intersections between functions \ No newline at end of file +3. Display of intersections between functions +4. Fix integral line \ No newline at end of file diff --git a/src/egui_app.rs b/src/egui_app.rs index 9a1b7a9..ae382c8 100644 --- a/src/egui_app.rs +++ b/src/egui_app.rs @@ -79,9 +79,8 @@ const HELP_PANEL: &str = - The 'Info' button provides information on the build currently running."; // Used in the "Functions" section of the Help window -const HELP_FUNCTION: &str = "- The 'X' button before the 'O' symbol allows you to delete the function in question. Deleting a function is prevented if only 1 function exists. -- The 'O' button after the 'X' button opens a window where you can configure some settings in relation to the function in question. -- The ∫ button (between the 'O' and 'd/dx' buttons) indicates whether estimating an integral for that function is enabled or not. +const HELP_FUNCTION: &str = "- The 'X' button before the '∫' button allows you to delete the function in question. Deleting a function is prevented if only 1 function exists. +- The ∫ button (between the 'X' and 'd/dx' buttons) indicates whether to integrate the function in question. - The 'd/dx' button next to the function input indicates whether or not calculating the derivative is enabled or not."; // Misc help info @@ -114,9 +113,6 @@ struct AppSettings { // Stores how integrals should be displayed pub integral_display_type: IntegralDisplay, - - // List of functions whose windows are open - pub opened_functions: Vec, } impl Default for AppSettings { @@ -130,7 +126,6 @@ impl Default for AppSettings { integral_max_x: DEFAULT_MAX_X, integral_num: DEFAULT_INTEGRAL_NUM, integral_display_type: IntegralDisplay::Rectangles, - opened_functions: Vec::new(), } } } @@ -182,6 +177,7 @@ impl MathApp { ui.selectable_value(&mut self.settings.sum, RiemannSum::Right, "Right"); }); + /* ComboBox::from_label("Integral Display") .selected_text(self.settings.integral_display_type.to_string()) .show_ui(ui, |ui| { @@ -196,6 +192,7 @@ impl MathApp { "Line", ); }); + */ let min_x_old = self.settings.integral_min_x; let min_x_changed = ui @@ -233,37 +230,14 @@ impl MathApp { let mut remove_i: Option = None; for (i, function) in self.functions.iter_mut().enumerate() { - let mut integral_toggle: bool = false; - let mut derivative_toggle: bool = false; let integral_enabled = function.integral; let derivative_enabled = function.derivative; + let mut derivative_toggle: bool = false; + let mut integral_toggle: bool = false; // Entry for a function ui.horizontal(|ui| { ui.label("Function:"); - if ui - .add(Button::new("O")) - .on_hover_text("Open Function Settings") - .clicked() - | self.settings.opened_functions.contains(&i) - { - self.settings.opened_functions.push(i); - Window::new(function.get_func_str()) - .default_pos([200.0, 200.0]) - .resizable(false) - .collapsible(false) - .show(ctx, |ui| { - if ui - .add( - Slider::new(&mut function.nth_derivative, 0..=2) // Derivatives go insane after the value 3, probably inaccuracies in the handling of floating point numbers. more investigation needed. - .text("Derivative"), - ) - .changed() - { - function.invalidate_derivative_cache(); - } - }); - } if ui .add(Button::new("X")) @@ -273,27 +247,21 @@ impl MathApp { remove_i = Some(i); } - if ui + integral_toggle = ui .add(Button::new("∫")) .on_hover_text(match integral_enabled { true => "Don't integrate", false => "Integrate", }) - .clicked() - { - integral_toggle = true; - } + .clicked(); - if ui + derivative_toggle = ui .add(Button::new("d/dx")) .on_hover_text(match derivative_enabled { true => "Don't Differentiate", false => "Differentiate", }) - .clicked() - { - derivative_toggle = true; - } + .clicked(); ui.text_edit_singleline(&mut self.func_strs[i]); }); diff --git a/src/function.rs b/src/function.rs index 72711bf..1adf4b4 100644 --- a/src/function.rs +++ b/src/function.rs @@ -239,6 +239,7 @@ impl FunctionEntry { let step = (self.integral_min_x - self.integral_max_x).abs() / (self.integral_num as f64); + let mut last_positive: Option = None; let mut area: f64 = 0.0; let data2: Vec<(f64, f64, f64)> = (0..self.integral_num) .map(|e| { @@ -257,6 +258,10 @@ impl FunctionEntry { RiemannSum::Middle => (self.run_func(left_x) + self.run_func(right_x)) / 2.0, }; + if last_positive.is_none() { + last_positive = Some(x.is_sign_positive()); + } + if !y.is_nan() { area += y * step; } @@ -311,6 +316,8 @@ impl FunctionEntry { self } + // Invalidates the derivative cache. This would be used in the case of a change in the nth_derivative + #[allow(dead_code)] pub fn invalidate_derivative_cache(&mut self) { self.derivative_cache = None; } } diff --git a/src/parsing.rs b/src/parsing.rs index 504deaa..e31708c 100644 --- a/src/parsing.rs +++ b/src/parsing.rs @@ -26,9 +26,15 @@ impl BackingFunction { return self.get(x); } - let (x1, x2) = (x - EPSILON, x + EPSILON); - let (y1, y2) = (self.derivative(x1, n - 1), (self.derivative(x2, n - 1))); - (y2 - y1) / DOUBLE_EPSILON + let (y1, y2) = ( + self.derivative(x - EPSILON, n - 1), + (self.derivative(x + EPSILON, n - 1)), + ); + + match y1 == y2 { + true => 0.0, + false => (y2 - y1) / DOUBLE_EPSILON, + } } }