From 65ab0c6a1fd10f5602610ac906d008669e4ac89a Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Fri, 5 Dec 2025 22:37:05 -0500 Subject: [PATCH] FunctionEntry: make newtons_method threshold smaller (fixes symbolicrepr) + prioritize special points --- src/function_entry.rs | 48 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/src/function_entry.rs b/src/function_entry.rs index 643d2c4..170a3ee 100644 --- a/src/function_entry.rs +++ b/src/function_entry.rs @@ -344,7 +344,7 @@ impl FunctionEntry { self.clear_integral(); } - let threshold: f64 = resolution / 2.0; + let threshold: f64 = f64::EPSILON; let x_range = settings.min_x..settings.max_x; // Calculates extrema @@ -377,7 +377,28 @@ impl FunctionEntry { let step = (settings.max_x - settings.min_x) / (settings.plot_width as f64); debug_assert!(step > 0.0); - // Plot back data + // Collect special points (extrema and roots) for exclusion from line hover detection + let special_points: Vec<&PlotPoint> = { + let mut points = Vec::new(); + if settings.do_extrema { + points.extend(self.extrema_data.iter()); + } + if settings.do_roots { + points.extend(self.root_data.iter()); + } + points + }; + + // Helper to check if a point is near any special point + // Uses a radius in x-axis units based on the step size + let exclusion_radius = step * 3.0; // Exclude points within 3 steps of special points + let is_near_special_point = |p: &PlotPoint| -> bool { + special_points + .iter() + .any(|sp| (p.x - sp.x).abs() < exclusion_radius) + }; + + // Plot back data, filtering out points near special points for better hover detection if !self.back_data.is_empty() { if self.integral && (step >= integral_step) { plot_ui.line( @@ -395,17 +416,32 @@ impl FunctionEntry { .fill(0.0), ); } + + // Filter out points near special points so cursor snaps to them more easily + let filtered_back_data: Vec = self + .back_data + .iter() + .filter(|p| !is_near_special_point(p)) + .cloned() + .collect(); + plot_ui.line( - self.back_data - .clone() + filtered_back_data .to_line() .stroke(egui::Stroke::new(4.0, main_plot_color)), ); } - // Plot derivative data + // Plot derivative data, also filtering near special points if self.derivative && !self.derivative_data.is_empty() { - plot_ui.line(self.derivative_data.clone().to_line().color(Color32::GREEN)); + let filtered_derivative_data: Vec = self + .derivative_data + .iter() + .filter(|p| !is_near_special_point(p)) + .cloned() + .collect(); + + plot_ui.line(filtered_derivative_data.to_line().color(Color32::GREEN)); } // Plot extrema points