mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 09:24:26 +03:00
Explicitly draw the OSM boundary in the map_editor, so we can effectively create borders
This commit is contained in:
parent
94c8a34804
commit
15b154aa23
@ -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);
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user