widgetry/tools/
lasso.rs
1use geom::{Distance, PolyLine, Polygon, Pt2D, Ring};
2
3use crate::{Color, EventCtx, GfxCtx};
4
5pub struct Lasso {
9 points: Vec<Pt2D>,
10 polygon: Option<Polygon>,
11 threshold: Distance,
12}
13
14impl Lasso {
15 pub fn new(threshold: Distance) -> Self {
17 Self {
18 points: Vec::new(),
19 polygon: None,
20 threshold,
21 }
22 }
23
24 pub fn event(&mut self, ctx: &mut EventCtx) -> Option<Polygon> {
26 if self.points.is_empty() {
27 if let Some(pt) = ctx.canvas.get_cursor_in_map_space() {
28 if ctx.input.left_mouse_button_pressed() {
29 self.points.push(pt);
30 }
31 }
32 return None;
33 }
34
35 if ctx.input.left_mouse_button_released() {
36 return self.polygon.take();
37 }
38
39 if ctx.redo_mouseover() {
40 if let Some(pt) = ctx.canvas.get_cursor_in_map_space() {
41 if self.points.last().as_ref().unwrap().dist_to(pt) > self.threshold {
42 self.points.push(pt);
43
44 let mut copy = self.points.clone();
47 copy.push(copy[0]);
48 self.polygon = Ring::new(copy).ok().map(|ring| ring.into_polygon());
49 }
50 }
51 }
52 None
53 }
54
55 pub fn draw(&self, g: &mut GfxCtx) {
56 if let Ok(pl) = PolyLine::new(self.points.clone()) {
57 g.draw_polygon(
58 Color::RED.alpha(0.8),
59 pl.make_polygons(Distance::meters(5.0) / g.canvas.cam_zoom),
60 );
61 }
62 if let Some(ref polygon) = self.polygon {
63 g.draw_polygon(Color::RED.alpha(0.5), polygon.clone());
64 }
65 }
66}
67
68pub struct PolyLineLasso {
70 pl: Option<PolyLine>,
71}
72
73impl PolyLineLasso {
74 pub fn new() -> Self {
75 Self { pl: None }
76 }
77
78 pub fn event(&mut self, ctx: &mut EventCtx) -> Option<PolyLine> {
80 if self.pl.is_none() {
81 if let Some(pt) = ctx.canvas.get_cursor_in_map_space() {
82 if ctx.input.left_mouse_button_pressed() {
83 self.pl = Some(PolyLine::must_new(vec![pt, pt.offset(0.1, 0.1)]));
84 }
85 }
86 return None;
87 }
88
89 if ctx.input.left_mouse_button_released() {
90 return self.pl.take();
91 }
92
93 if ctx.redo_mouseover() {
94 if let Some(pt) = ctx.canvas.get_cursor_in_map_space() {
95 let pl = self.pl.take().unwrap();
96 self.pl = Some(pl.optionally_push(pt));
97 }
98 }
99 None
100 }
101
102 pub fn draw(&self, g: &mut GfxCtx) {
103 if let Some(ref pl) = self.pl {
104 g.draw_polygon(
105 Color::RED.alpha(0.8),
106 pl.make_polygons(Distance::meters(5.0) / g.canvas.cam_zoom),
107 );
108 }
109 }
110}