egui_charts/drawings/rendering/
traits.rs1use crate::tokens::DESIGN_TOKENS;
8use egui::{Color32, Painter, Pos2};
9
10pub use crate::drawings::registry::DrawingRenderer;
11
12pub fn render_handles(painter: &Painter, points: &[Pos2], size: f32, selected: bool) {
14 if !selected || points.is_empty() {
15 return;
16 }
17
18 let handle_color = DESIGN_TOKENS.semantic.extended.accent; let border_color = Color32::WHITE;
20 let radius = size / 2.0;
21
22 for &point in points {
23 painter.circle_filled(point, radius + 1.0, border_color);
25 painter.circle_filled(point, radius, handle_color);
27 }
28}
29
30pub fn point_near_line(point: Pos2, line_start: Pos2, line_end: Pos2, tolerance: f32) -> bool {
32 let line_vec = line_end - line_start;
33 let line_len_sq = line_vec.length_sq();
34
35 if line_len_sq < 1e-6 {
36 return (point - line_start).length() <= tolerance;
38 }
39
40 let t = ((point - line_start).dot(line_vec) / line_len_sq).clamp(0.0, 1.0);
42 let projection = line_start + t * line_vec;
43 let distance = (point - projection).length();
44
45 distance <= tolerance
46}
47
48pub fn point_near_points(point: Pos2, points: &[Pos2], tolerance: f32) -> Option<usize> {
50 for (i, &p) in points.iter().enumerate() {
51 if (point - p).length() <= tolerance {
52 return Some(i);
53 }
54 }
55 None
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn test_point_near_line() {
64 let start = Pos2::new(0.0, 0.0);
65 let end = Pos2::new(100.0, 0.0);
66
67 assert!(point_near_line(Pos2::new(50.0, 0.0), start, end, 5.0));
69
70 assert!(point_near_line(Pos2::new(50.0, 3.0), start, end, 5.0));
72
73 assert!(!point_near_line(Pos2::new(50.0, 10.0), start, end, 5.0));
75
76 assert!(point_near_line(Pos2::new(-3.0, 0.0), start, end, 5.0));
78
79 assert!(!point_near_line(Pos2::new(-10.0, 0.0), start, end, 5.0));
81 }
82
83 #[test]
84 fn test_point_near_points() {
85 let points = vec![
86 Pos2::new(0.0, 0.0),
87 Pos2::new(100.0, 100.0),
88 Pos2::new(50.0, 50.0),
89 ];
90
91 assert_eq!(
93 point_near_points(Pos2::new(3.0, 0.0), &points, 5.0),
94 Some(0)
95 );
96
97 assert_eq!(
99 point_near_points(Pos2::new(52.0, 50.0), &points, 5.0),
100 Some(2)
101 );
102
103 assert_eq!(
105 point_near_points(Pos2::new(200.0, 200.0), &points, 5.0),
106 None
107 );
108 }
109}