Explicitly draw the OSM boundary in the map_editor, so we can effectively create borders

This commit is contained in:
Dustin Carlino 2021-02-19 17:33:37 -08:00
parent 94c8a34804
commit 15b154aa23
2 changed files with 80 additions and 25 deletions

View File

@ -8,7 +8,7 @@ extern crate log;
use model::{Model, ID};
use abstutil::{CmdArgs, Timer};
use geom::{Distance, Line, Polygon};
use geom::{Distance, Line, Polygon, Pt2D};
use map_gui::tools::CameraState;
use map_model::osm;
use map_model::raw::OriginalRoad;
@ -53,6 +53,8 @@ enum Mode {
MovingRoadPoint(OriginalRoad, usize),
CreatingRoad(osm::NodeID),
PreviewIntersection(Drawable),
SetBoundaryPt1,
SetBoundaryPt2(Pt2D),
}
impl MainState {
@ -109,6 +111,9 @@ impl MainState {
]),
Text::new().draw(ctx).named("instructions"),
Widget::col(vec![
ctx.style()
.btn_outline_light_text("adjust boundary")
.build_def(ctx),
ctx.style()
.btn_solid_dark_text("export to OSM")
.build_def(ctx),
@ -305,6 +310,9 @@ impl State<App> for MainState {
"close" => {
return Transition::Pop;
}
"adjust boundary" => {
self.mode = Mode::SetBoundaryPt1;
}
"export to OSM" => {
app.model.export_to_osm();
}
@ -392,6 +400,37 @@ impl State<App> for MainState {
app.model.world.handle_mouseover(ctx);
}
}
Mode::SetBoundaryPt1 => {
let mut txt = Text::new();
txt.add_appended(vec![
Line("Click").fg(ctx.style().hotkey_color),
Line(" the top-left corner of this map"),
]);
let instructions = txt.draw(ctx);
self.panel.replace(ctx, "instructions", instructions);
if let Some(pt) = cursor {
if ctx.normal_left_click() {
self.mode = Mode::SetBoundaryPt2(pt);
}
}
}
Mode::SetBoundaryPt2(pt1) => {
let mut txt = Text::new();
txt.add_appended(vec![
Line("Click").fg(ctx.style().hotkey_color),
Line(" the bottom-right corner of this map"),
]);
let instructions = txt.draw(ctx);
self.panel.replace(ctx, "instructions", instructions);
if let Some(pt2) = cursor {
if ctx.normal_left_click() {
app.model.set_boundary(ctx, pt1, pt2);
self.mode = Mode::Viewing;
}
}
}
}
self.last_id = app.model.world.get_selection();
@ -440,6 +479,14 @@ impl State<App> for MainState {
}
}
}
Mode::SetBoundaryPt1 => {}
Mode::SetBoundaryPt2(pt1) => {
if let Some(pt2) = g.canvas.get_cursor_in_map_space() {
if let Some(rect) = Polygon::rectangle_two_corners(pt1, pt2) {
g.draw_polygon(Color::YELLOW.alpha(0.5), rect);
}
}
}
};
self.panel.draw(g);

View File

@ -80,40 +80,48 @@ impl Model {
// General
impl Model {
// TODO Only for truly synthetic maps...
pub fn export_to_osm(&mut self) {
// Shift the map to start at (0, 0)
let bounds = self.compute_bounds();
if bounds.min_x != 0.0 || bounds.min_y != 0.0 {
for b in self.map.buildings.values_mut() {
b.polygon = b.polygon.translate(-bounds.min_x, -bounds.min_y);
}
for i in self.map.intersections.values_mut() {
i.point = i.point.offset(-bounds.min_x, -bounds.min_y);
}
for r in self.map.roads.values_mut() {
for pt in &mut r.center_points {
*pt = pt.offset(-bounds.min_x, -bounds.min_y);
}
dump_to_osm(&self.map).unwrap();
}
pub fn set_boundary(&mut self, ctx: &EventCtx, top_left: Pt2D, bottom_right: Pt2D) {
// Shift the map to treat top_left as (0, 0)
for b in self.map.buildings.values_mut() {
b.polygon = b.polygon.translate(-top_left.x(), -top_left.y());
}
for i in self.map.intersections.values_mut() {
i.point = i.point.offset(-top_left.x(), -top_left.y());
}
for r in self.map.roads.values_mut() {
for pt in &mut r.center_points {
*pt = pt.offset(-top_left.x(), -top_left.y());
}
}
let pt1 = Pt2D::new(0.0, 0.0);
let pt2 = bottom_right.offset(-top_left.x(), -top_left.y());
self.map.boundary_polygon = Polygon::rectangle_two_corners(pt1, pt2).unwrap();
let bounds = self.compute_bounds();
self.map.boundary_polygon = bounds.get_rectangle();
// Make gps_bounds sane
self.map.gps_bounds = GPSBounds::new();
let mut seattle_bounds = GPSBounds::new();
seattle_bounds.update(LonLat::new(-122.453224, 47.723277));
seattle_bounds.update(LonLat::new(-122.240505, 47.495342));
self.map
.gps_bounds
.update(Pt2D::new(bounds.min_x, bounds.min_y).to_gps(&seattle_bounds));
self.map
.gps_bounds
.update(Pt2D::new(bounds.max_x, bounds.max_y).to_gps(&seattle_bounds));
self.map.gps_bounds = GPSBounds::new();
self.map.gps_bounds.update(pt1.to_gps(&seattle_bounds));
self.map.gps_bounds.update(pt2.to_gps(&seattle_bounds));
dump_to_osm(&self.map).unwrap();
// Re-add everything to the world, since we just shifted coordinates around
self.world = World::new();
for id in self.map.buildings.keys().cloned().collect::<Vec<_>>() {
self.bldg_added(id, ctx);
}
for id in self.map.intersections.keys().cloned().collect::<Vec<_>>() {
self.intersection_added(id, ctx);
}
for id in self.map.roads.keys().cloned().collect::<Vec<_>>() {
self.road_added(id, ctx);
}
}
fn compute_bounds(&self) -> Bounds {