move existing points in a drawn polygon

This commit is contained in:
Dustin Carlino 2018-09-18 17:24:46 -07:00
parent 8b0fb9248c
commit 0cd27d7f50
4 changed files with 134 additions and 103 deletions

View File

@ -0,0 +1,124 @@
use ezgui::{Canvas, GfxCtx, TextBox, UserInput};
use geom::{Circle, Line, Polygon, Pt2D};
use piston::input::{Button, Key, ReleaseEvent};
use plugins::Colorizer;
const POINT_RADIUS: f64 = 2.0;
pub enum DrawPolygonState {
Empty,
// Option<usize> is the point currently being hovered over
DrawingPoints(Vec<Pt2D>, Option<usize>),
MovingPoint(Vec<Pt2D>, usize),
NamingPolygon(TextBox, Vec<Pt2D>),
}
impl DrawPolygonState {
pub fn new() -> DrawPolygonState {
DrawPolygonState::Empty
}
pub fn event(&mut self, input: &mut UserInput, canvas: &Canvas) -> bool {
let mut new_state: Option<DrawPolygonState> = None;
match self {
DrawPolygonState::Empty => {
if input.unimportant_key_pressed(Key::N, "start drawing a polygon") {
new_state = Some(DrawPolygonState::DrawingPoints(Vec::new(), None));
}
}
DrawPolygonState::DrawingPoints(ref mut pts, ref mut current_idx) => {
if input.key_pressed(Key::Escape, "throw away this neighborhood polygon") {
new_state = Some(DrawPolygonState::Empty);
} else if input.key_pressed(Key::P, "add a new point here") {
pts.push(canvas.get_cursor_in_map_space());
} else if pts.len() >= 3
&& input.key_pressed(Key::Return, "confirm the polygon's shape")
{
new_state = Some(DrawPolygonState::NamingPolygon(TextBox::new(), pts.clone()));
}
if new_state.is_none() {
let cursor = canvas.get_cursor_in_map_space();
*current_idx = pts
.iter()
.position(|pt| Circle::new(*pt, POINT_RADIUS).contains_pt(cursor));
if let Some(idx) = current_idx {
// TODO mouse dragging might be more intuitive, but it's unclear how to
// override part of canvas.handle_event
if input.key_pressed(Key::LCtrl, "hold to move this point") {
new_state = Some(DrawPolygonState::MovingPoint(pts.clone(), *idx));
}
}
}
}
DrawPolygonState::MovingPoint(ref mut pts, idx) => {
pts[*idx] = canvas.get_cursor_in_map_space();
if let Some(Button::Keyboard(Key::LCtrl)) =
input.use_event_directly().release_args()
{
new_state = Some(DrawPolygonState::DrawingPoints(pts.clone(), Some(*idx)));
}
}
DrawPolygonState::NamingPolygon(tb, pts) => {
if tb.event(input.use_event_directly()) {
println!("TODO: save neighborhood {} with points {:?}", tb.line, pts);
new_state = Some(DrawPolygonState::Empty);
}
input.consume_event();
}
}
if let Some(s) = new_state {
*self = s;
}
match self {
DrawPolygonState::Empty => false,
_ => true,
}
}
pub fn get_osd_lines(&self) -> Vec<String> {
// TODO draw the cursor
if let DrawPolygonState::NamingPolygon(tb, _) = self {
return vec![tb.line.clone()];
}
Vec::new()
}
pub fn draw(&self, g: &mut GfxCtx) {
// TODO add colorscheme entries
let red = [1.0, 0.0, 0.0, 1.0];
let green = [0.0, 1.0, 0.0, 1.0];
let blue = [0.0, 0.0, 1.0, 1.0];
let cyan = [0.0, 1.0, 1.0, 1.0];
let (pts, current_idx) = match self {
DrawPolygonState::Empty => {
return;
}
DrawPolygonState::DrawingPoints(pts, current_idx) => (pts, *current_idx),
DrawPolygonState::MovingPoint(pts, idx) => (pts, Some(*idx)),
DrawPolygonState::NamingPolygon(_, pts) => {
g.draw_polygon(blue, &Polygon::new(pts));
return;
}
};
if pts.len() == 2 {
g.draw_line(red, POINT_RADIUS / 2.0, &Line::new(pts[0], pts[1]));
}
if pts.len() >= 3 {
g.draw_polygon(blue, &Polygon::new(pts));
}
for pt in pts {
g.draw_circle(red, &Circle::new(*pt, POINT_RADIUS));
}
if let Some(last) = pts.last() {
g.draw_circle(green, &Circle::new(*last, POINT_RADIUS));
}
if let Some(idx) = current_idx {
g.draw_circle(cyan, &Circle::new(pts[idx], POINT_RADIUS));
}
}
}
impl Colorizer for DrawPolygonState {}

View File

@ -1,13 +1,13 @@
pub mod classification;
pub mod color_picker;
pub mod debug_objects;
pub mod draw_polygon;
pub mod floodfill;
pub mod follow;
pub mod geom_validation;
pub mod hider;
pub mod road_editor;
pub mod search;
pub mod select_polygon;
pub mod show_route;
pub mod sim_controls;
pub mod steep;

View File

@ -1,93 +0,0 @@
use ezgui::{Canvas, GfxCtx, TextBox, UserInput};
use geom::{Circle, Line, Polygon, Pt2D};
use piston::input::Key;
use plugins::Colorizer;
pub enum SelectPolygonState {
Empty,
SelectingPoints(Vec<Pt2D>),
NamingPolygon(TextBox, Vec<Pt2D>),
}
impl SelectPolygonState {
pub fn new() -> SelectPolygonState {
SelectPolygonState::Empty
}
pub fn event(&mut self, input: &mut UserInput, canvas: &Canvas) -> bool {
let mut new_state: Option<SelectPolygonState> = None;
match self {
SelectPolygonState::Empty => {
if input.unimportant_key_pressed(Key::N, "start drawing a polygon") {
new_state = Some(SelectPolygonState::SelectingPoints(Vec::new()));
}
}
SelectPolygonState::SelectingPoints(ref mut pts) => {
if input.key_pressed(Key::Escape, "throw away this neighborhood polygon") {
new_state = Some(SelectPolygonState::Empty);
} else if input.key_pressed(Key::P, "add a new point here") {
pts.push(canvas.get_cursor_in_map_space());
} else if pts.len() >= 3
&& input.key_pressed(Key::Return, "confirm the polygon's shape")
{
new_state = Some(SelectPolygonState::NamingPolygon(
TextBox::new(),
pts.clone(),
));
}
// TODO move existing points
}
SelectPolygonState::NamingPolygon(tb, pts) => {
if tb.event(input.use_event_directly()) {
println!("TODO: save neighborhood {} with points {:?}", tb.line, pts);
new_state = Some(SelectPolygonState::Empty);
}
input.consume_event();
}
}
if let Some(s) = new_state {
*self = s;
}
match self {
SelectPolygonState::Empty => false,
_ => true,
}
}
pub fn get_osd_lines(&self) -> Vec<String> {
// TODO draw the cursor
if let SelectPolygonState::NamingPolygon(tb, _) = self {
return vec![tb.line.clone()];
}
Vec::new()
}
pub fn draw(&self, g: &mut GfxCtx) {
let pts = match self {
SelectPolygonState::Empty => {
return;
}
SelectPolygonState::SelectingPoints(pts) => pts,
SelectPolygonState::NamingPolygon(_, pts) => pts,
};
// TODO add colorscheme entries
let red = [1.0, 0.0, 0.0, 1.0];
let green = [0.0, 1.0, 0.0, 1.0];
let blue = [0.0, 0.0, 1.0, 1.0];
let radius = 2.0;
if pts.len() == 2 {
g.draw_line(red, radius / 2.0, &Line::new(pts[0], pts[1]));
}
if pts.len() >= 3 {
g.draw_polygon(blue, &Polygon::new(pts));
}
for pt in pts {
g.draw_circle(red, &Circle::new(*pt, radius));
}
g.draw_circle(green, &Circle::new(*pts.last().unwrap(), radius));
}
}
impl Colorizer for SelectPolygonState {}

View File

@ -18,13 +18,13 @@ use piston::window::Size;
use plugins::classification::OsmClassifier;
use plugins::color_picker::ColorPicker;
use plugins::debug_objects::DebugObjectsState;
use plugins::draw_polygon::DrawPolygonState;
use plugins::floodfill::Floodfiller;
use plugins::follow::FollowState;
use plugins::geom_validation::Validator;
use plugins::hider::Hider;
use plugins::road_editor::RoadEditor;
use plugins::search::SearchState;
use plugins::select_polygon::SelectPolygonState;
use plugins::show_route::ShowRouteState;
use plugins::sim_controls::SimController;
use plugins::steep::SteepnessVisualizer;
@ -122,7 +122,7 @@ impl UIWrapper {
color_picker: ColorPicker::new(),
geom_validator: Validator::new(),
turn_cycler: TurnCyclerState::new(),
select_polygon: SelectPolygonState::new(),
draw_polygon: DrawPolygonState::new(),
active_plugin: None,
@ -236,7 +236,7 @@ impl UIWrapper {
.event(input, &mut ui.canvas, &ui.map, &ui.draw_map)
}),
Box::new(|ui, input| ui.turn_cycler.event(input, ui.current_selection)),
Box::new(|ui, input| ui.select_polygon.event(input, &ui.canvas)),
Box::new(|ui, input| ui.draw_polygon.event(input, &ui.canvas)),
],
}
}
@ -268,7 +268,7 @@ struct UI {
color_picker: ColorPicker,
geom_validator: Validator,
turn_cycler: TurnCyclerState,
select_polygon: SelectPolygonState,
draw_polygon: DrawPolygonState,
// An index into UIWrapper.plugins.
active_plugin: Option<usize>,
@ -446,7 +446,7 @@ impl UI {
self.debug_objects
.draw(&self.map, &self.canvas, &self.draw_map, &self.sim, g);
self.color_picker.draw(&self.canvas, g);
self.select_polygon.draw(g);
self.draw_polygon.draw(g);
// TODO Only if active (except for the weird sim_ctrl)?
let mut osd_lines = self.sim_ctrl.get_osd_lines(&self.sim);
@ -465,10 +465,10 @@ impl UI {
osd_lines.push(String::from(""));
osd_lines.extend(warp_lines);
}
let select_lines = self.select_polygon.get_osd_lines();
if !select_lines.is_empty() {
let draw_poly_lines = self.draw_polygon.get_osd_lines();
if !draw_poly_lines.is_empty() {
osd_lines.push(String::from(""));
osd_lines.extend(select_lines);
osd_lines.extend(draw_poly_lines);
}
self.canvas.draw_osd_notification(g, &osd_lines);
}
@ -518,7 +518,7 @@ impl UI {
13 => Some(Box::new(&self.floodfiller)),
14 => Some(Box::new(&self.geom_validator)),
15 => Some(Box::new(&self.turn_cycler)),
16 => Some(Box::new(&self.select_polygon)),
16 => Some(Box::new(&self.draw_polygon)),
_ => panic!("Active plugin {} is too high", idx),
}
}