mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 07:25:47 +03:00
Add a tool in the main UI to try to merge junctions. #654
It maintains a JSON file of ways to merge that the importer also uses. For maps fast to import, this is the nicest workflow. Unlike map_editor, turns and trimmed roads can also be checked.
This commit is contained in:
parent
b925f0c015
commit
2224dccda9
@ -1,4 +1,4 @@
|
||||
use std::collections::{BTreeSet, HashMap};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use osm::{NodeID, OsmID, RelationID, WayID};
|
||||
|
||||
@ -29,18 +29,6 @@ pub struct OsmExtract {
|
||||
pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmExtract {
|
||||
let mut doc = crate::reader::read(&opts.osm_input, &map.gps_bounds, timer).unwrap();
|
||||
|
||||
// Use this to quickly test overrides to some ways before upstreaming in OSM.
|
||||
if false {
|
||||
let ways: BTreeSet<WayID> = abstio::read_json("osm_ways.json".to_string(), timer);
|
||||
for id in ways {
|
||||
doc.ways
|
||||
.get_mut(&id)
|
||||
.unwrap()
|
||||
.tags
|
||||
.insert("junction", "intersection");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Hacks to override OSM data. There's no problem upstream, but we want to accomplish
|
||||
// various things for A/B Street.
|
||||
if let Some(way) = doc.ways.get_mut(&WayID(881403608)) {
|
||||
|
@ -7,8 +7,9 @@ use map_gui::colors::ColorSchemeChoice;
|
||||
use map_gui::load::MapLoader;
|
||||
use map_gui::options::OptionsPanel;
|
||||
use map_gui::render::{calculate_corners, DrawMap, DrawOptions};
|
||||
use map_gui::tools::{ChooseSomething, PopupMsg, PromptInput};
|
||||
use map_gui::tools::{find_exe, ChooseSomething, PopupMsg, PromptInput, RunCommand};
|
||||
use map_gui::{AppLike, ID};
|
||||
use map_model::raw::OriginalRoad;
|
||||
use map_model::{
|
||||
osm, ControlTrafficSignal, IntersectionID, PathConstraints, Position, RoadID,
|
||||
NORMAL_LANE_THICKNESS,
|
||||
@ -156,6 +157,11 @@ impl DebugMode {
|
||||
.btn_outline
|
||||
.text("import color-scheme")
|
||||
.build_def(ctx),
|
||||
ctx.style()
|
||||
.btn_outline
|
||||
.text("undo all merged roads")
|
||||
.hotkey(lctrl(Key::M))
|
||||
.build_def(ctx),
|
||||
]),
|
||||
Text::from_all(vec![
|
||||
Line("Hold "),
|
||||
@ -386,6 +392,14 @@ impl State<App> for DebugMode {
|
||||
DrawMap::new(ctx, &app.primary.map, &app.opts, &app.cs, timer);
|
||||
});
|
||||
}
|
||||
"undo all merged roads" => {
|
||||
if let Err(err) =
|
||||
std::fs::rename("merge_osm_ways.json", "UNDO_merge_osm_ways.json")
|
||||
{
|
||||
warn!("No merged road file? {}", err);
|
||||
}
|
||||
return Transition::Push(reimport_map(ctx, app));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Outcome::Changed(_) => {
|
||||
@ -589,6 +603,7 @@ impl ContextualActions for Actions {
|
||||
));
|
||||
actions.push((Key::C, "export roads".to_string()));
|
||||
actions.push((Key::E, "show equiv_pos".to_string()));
|
||||
actions.push((Key::M, "merge short segment".to_string()));
|
||||
}
|
||||
ID::Intersection(i) => {
|
||||
actions.push((Key::H, "hide this".to_string()));
|
||||
@ -781,6 +796,15 @@ impl ContextualActions for Actions {
|
||||
}
|
||||
}))
|
||||
}
|
||||
(ID::Lane(l), "merge short segment") => {
|
||||
let mut timer = Timer::throwaway();
|
||||
let mut ways: Vec<OriginalRoad> =
|
||||
abstio::maybe_read_json("merge_osm_ways.json".to_string(), &mut timer)
|
||||
.unwrap_or_else(|_| Vec::new());
|
||||
ways.push(app.primary.map.get_parent(l).orig_id);
|
||||
abstio::write_json("merge_osm_ways.json".to_string(), &ways);
|
||||
Transition::Push(reimport_map(ctx, app))
|
||||
}
|
||||
(ID::Area(a), "debug area geometry") => {
|
||||
let pts = &app.primary.map.get_a(a).polygon.points();
|
||||
let center = if pts[0] == *pts.last().unwrap() {
|
||||
@ -1035,3 +1059,24 @@ fn draw_arterial_crosswalks(ctx: &mut EventCtx, app: &App) -> Drawable {
|
||||
}
|
||||
ctx.upload(batch)
|
||||
}
|
||||
|
||||
fn reimport_map(ctx: &mut EventCtx, app: &App) -> Box<dyn State<App>> {
|
||||
RunCommand::new_state(
|
||||
ctx,
|
||||
app,
|
||||
vec![
|
||||
find_exe("importer"),
|
||||
"--map".to_string(),
|
||||
app.primary.map.get_name().map.clone(),
|
||||
format!("--city={}", app.primary.map.get_name().city.to_path()),
|
||||
"--skip_ch".to_string(),
|
||||
],
|
||||
Box::new(|ctx, app, _, _| {
|
||||
Transition::Push(MapLoader::force_reload(
|
||||
ctx,
|
||||
app.primary.map.get_name().clone(),
|
||||
Box::new(|_, _| Transition::Pop),
|
||||
))
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use maplit::btreeset;
|
||||
|
||||
use map_gui::tools::PopupMsg;
|
||||
@ -40,10 +38,6 @@ fn make_select_panel(ctx: &mut EventCtx, selector: &RoadSelector) -> Panel {
|
||||
.btn_outline
|
||||
.text("export one road to Streetmix")
|
||||
.build_def(ctx),
|
||||
ctx.style()
|
||||
.btn_outline
|
||||
.text("export list of roads")
|
||||
.build_def(ctx),
|
||||
ctx.style().btn_close_widget(ctx),
|
||||
])
|
||||
.evenly_spaced(),
|
||||
@ -86,18 +80,6 @@ impl State<App> for BulkSelect {
|
||||
)],
|
||||
));
|
||||
}
|
||||
"export list of roads" => {
|
||||
let mut osm_ids: BTreeSet<map_model::osm::WayID> = BTreeSet::new();
|
||||
for r in &self.selector.roads {
|
||||
osm_ids.insert(app.primary.map.get_r(*r).orig_id.osm_way_id);
|
||||
}
|
||||
abstio::write_json("osm_ways.json".to_string(), &osm_ids);
|
||||
return Transition::Push(PopupMsg::new_state(
|
||||
ctx,
|
||||
"List of roads exported",
|
||||
vec!["Wrote osm_ways.json"],
|
||||
));
|
||||
}
|
||||
x => {
|
||||
if self.selector.event(ctx, app, Some(x)) {
|
||||
self.panel = make_select_panel(ctx, &self.selector);
|
||||
|
@ -40,6 +40,15 @@ impl MapLoader {
|
||||
});
|
||||
}
|
||||
|
||||
MapLoader::force_reload(ctx, name, on_load)
|
||||
}
|
||||
|
||||
/// Even if the current map name matches, still reload.
|
||||
pub fn force_reload<A: AppLike + 'static>(
|
||||
ctx: &mut EventCtx,
|
||||
name: MapName,
|
||||
on_load: Box<dyn FnOnce(&mut EventCtx, &mut A) -> Transition<A>>,
|
||||
) -> Box<dyn State<A>> {
|
||||
// TODO Generalize this more, maybe with some kind of country code -> font config
|
||||
if let Some(extra_font) = match name.city.country.as_ref() {
|
||||
"ir" | "ly" => Some("NotoSansArabic-Regular.ttf"),
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::collections::{BTreeSet, VecDeque};
|
||||
|
||||
use abstutil::Timer;
|
||||
use geom::{Angle, Distance};
|
||||
|
||||
use crate::osm;
|
||||
@ -43,6 +44,24 @@ pub fn merge_short_roads(map: &mut RawMap, consolidate_all: bool) -> BTreeSet<No
|
||||
}
|
||||
}
|
||||
|
||||
// Use this to quickly test overrides to some ways before upstreaming in OSM.
|
||||
// Since these IDs might be based on already merged roads, do these last.
|
||||
if let Ok(ways) = abstio::maybe_read_json::<Vec<OriginalRoad>>(
|
||||
"merge_osm_ways.json".to_string(),
|
||||
&mut Timer::throwaway(),
|
||||
) {
|
||||
for id in ways {
|
||||
match map.merge_short_road(id) {
|
||||
Ok((i, _, _, _)) => {
|
||||
merged.insert(i);
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("Not merging short road / junction=intersection: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
merged
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user