mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 23:43:25 +03:00
find all the short lanes, from map_editor
This commit is contained in:
parent
4d2f77e90c
commit
e881d13014
@ -55,6 +55,7 @@ fi
|
||||
for poly in `ls data/polygons/`; do
|
||||
name=`basename -s .poly $poly`;
|
||||
if [ ! -f data/input/$name.osm ]; then
|
||||
echo "Running osmconvert for $name"
|
||||
osmconvert data/input/Seattle.osm \
|
||||
-B=data/polygons/$name.poly \
|
||||
--complete-ways \
|
||||
|
@ -24,7 +24,7 @@ struct UI {
|
||||
}
|
||||
|
||||
enum State {
|
||||
Viewing,
|
||||
Viewing { short_roads: HashSet<StableRoadID> },
|
||||
MovingIntersection(StableIntersectionID),
|
||||
MovingBuilding(StableBuildingID),
|
||||
MovingRoadPoint(StableRoadID, usize),
|
||||
@ -45,6 +45,14 @@ enum State {
|
||||
StampingRoads(String, String, String, String),
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn viewing() -> State {
|
||||
State::Viewing {
|
||||
short_roads: HashSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UI {
|
||||
fn new(ctx: &EventCtx) -> UI {
|
||||
let mut args = CmdArgs::new();
|
||||
@ -69,7 +77,7 @@ impl UI {
|
||||
};
|
||||
let mut ui = UI {
|
||||
model,
|
||||
state: State::Viewing,
|
||||
state: State::viewing(),
|
||||
menu: ModalMenu::new(
|
||||
"Map Editor",
|
||||
vec![vec![
|
||||
@ -80,6 +88,8 @@ impl UI {
|
||||
(None, "produce OSM parking+sidewalk diff"),
|
||||
(hotkey(Key::G), "preview all intersections"),
|
||||
(None, "find overlapping intersections"),
|
||||
(None, "find short roads"),
|
||||
(None, "clear short roads"),
|
||||
]],
|
||||
ctx,
|
||||
),
|
||||
@ -124,7 +134,9 @@ impl GUI for UI {
|
||||
}
|
||||
|
||||
match self.state {
|
||||
State::Viewing => {
|
||||
State::Viewing {
|
||||
ref mut short_roads,
|
||||
} => {
|
||||
{
|
||||
let before = match self.last_id {
|
||||
Some(ID::Road(r)) | Some(ID::RoadPoint(r, _)) => Some(r),
|
||||
@ -289,6 +301,10 @@ impl GUI for UI {
|
||||
} else if self.menu.action("find overlapping intersections") {
|
||||
let (draw, labels) = find_overlapping_intersections(&self.model, ctx);
|
||||
self.state = State::PreviewIntersection(draw, labels, false);
|
||||
} else if self.menu.action("find short roads") {
|
||||
*short_roads = find_short_roads(&self.model);
|
||||
} else if self.menu.action("clear short roads") {
|
||||
short_roads.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -297,7 +313,7 @@ impl GUI for UI {
|
||||
if let Some(cursor) = ctx.canvas.get_cursor_in_map_space() {
|
||||
self.model.move_i(id, cursor, ctx.prerender);
|
||||
if ctx.input.key_released(Key::LeftControl) {
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -305,7 +321,7 @@ impl GUI for UI {
|
||||
if let Some(cursor) = ctx.canvas.get_cursor_in_map_space() {
|
||||
self.model.move_b(id, cursor, ctx.prerender);
|
||||
if ctx.input.key_released(Key::LeftControl) {
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -313,7 +329,7 @@ impl GUI for UI {
|
||||
if let Some(cursor) = ctx.canvas.get_cursor_in_map_space() {
|
||||
self.model.move_r_pt(r, idx, cursor, ctx.prerender);
|
||||
if ctx.input.key_released(Key::LeftControl) {
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -327,9 +343,9 @@ impl GUI for UI {
|
||||
.unwrap_or_else(String::new),
|
||||
) {
|
||||
self.model.set_b_label(id, label, ctx.prerender);
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
} else if wizard.aborted() {
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
}
|
||||
}
|
||||
State::LabelingRoad(r, ref mut wizard) => {
|
||||
@ -342,9 +358,9 @@ impl GUI for UI {
|
||||
.unwrap_or_else(String::new),
|
||||
) {
|
||||
self.model.set_r_label(r, label, ctx.prerender);
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
} else if wizard.aborted() {
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
}
|
||||
}
|
||||
State::LabelingIntersection(id, ref mut wizard) => {
|
||||
@ -356,19 +372,19 @@ impl GUI for UI {
|
||||
.unwrap_or_else(String::new),
|
||||
) {
|
||||
self.model.set_i_label(id, label, ctx.prerender);
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
} else if wizard.aborted() {
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
}
|
||||
}
|
||||
State::CreatingRoad(i1) => {
|
||||
if ctx.input.key_pressed(Key::Escape, "stop defining road") {
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
} else if let Some(ID::Intersection(i2)) = self.model.world.get_selection() {
|
||||
if i1 != i2 && ctx.input.key_pressed(Key::R, "finalize road") {
|
||||
self.model.create_r(i1, i2, ctx.prerender);
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
}
|
||||
}
|
||||
@ -379,10 +395,10 @@ impl GUI for UI {
|
||||
self.model.map.roads[&id].get_spec().to_string(),
|
||||
) {
|
||||
self.model.edit_lanes(id, s, ctx.prerender);
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
} else if wizard.aborted() {
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
}
|
||||
}
|
||||
@ -416,7 +432,7 @@ impl GUI for UI {
|
||||
}
|
||||
}
|
||||
if done || wizard.aborted() {
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
}
|
||||
}
|
||||
@ -424,9 +440,9 @@ impl GUI for UI {
|
||||
if let Some(name) = wizard.wrap(ctx).input_string("Name the synthetic map") {
|
||||
self.model.map.name = name;
|
||||
self.model.export();
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
} else if wizard.aborted() {
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
}
|
||||
}
|
||||
State::SelectingRectangle(pt1, ref mut pt2, ref mut keydown) => {
|
||||
@ -442,7 +458,7 @@ impl GUI for UI {
|
||||
}
|
||||
}
|
||||
if ctx.input.key_pressed(Key::Escape, "stop selecting area") {
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
} else if ctx
|
||||
.input
|
||||
.key_pressed(Key::Backspace, "delete everything in area")
|
||||
@ -451,7 +467,7 @@ impl GUI for UI {
|
||||
self.model.delete_everything_inside(rect, ctx.prerender);
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
}
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
}
|
||||
}
|
||||
State::CreatingTurnRestrictionPt1(from) => {
|
||||
@ -459,7 +475,7 @@ impl GUI for UI {
|
||||
.input
|
||||
.key_pressed(Key::Escape, "stop defining turn restriction")
|
||||
{
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
} else if let Some(ID::Road(to)) = self.model.world.get_selection() {
|
||||
if ctx
|
||||
@ -487,10 +503,10 @@ impl GUI for UI {
|
||||
})
|
||||
{
|
||||
self.model.add_tr(from, restriction, to, ctx.prerender);
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
} else if wizard.aborted() {
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
}
|
||||
}
|
||||
@ -505,7 +521,7 @@ impl GUI for UI {
|
||||
.input
|
||||
.key_pressed(Key::P, "stop previewing intersection")
|
||||
{
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
}
|
||||
}
|
||||
@ -527,10 +543,10 @@ impl GUI for UI {
|
||||
if !ok {
|
||||
println!("Sorry, don't understand {}", line);
|
||||
}
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
} else if wizard.aborted() {
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
}
|
||||
}
|
||||
@ -539,7 +555,7 @@ impl GUI for UI {
|
||||
.input
|
||||
.key_pressed(Key::Escape, "stop copying road metadata")
|
||||
{
|
||||
self.state = State::Viewing;
|
||||
self.state = State::viewing();
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
} else if let Some(ID::Road(id)) = self.model.world.get_selection() {
|
||||
if ctx.input.key_pressed(
|
||||
@ -614,7 +630,13 @@ impl GUI for UI {
|
||||
| State::EnteringWarp(ref wizard) => {
|
||||
wizard.draw(g);
|
||||
}
|
||||
State::Viewing => {}
|
||||
State::Viewing { ref short_roads } => {
|
||||
for r in short_roads {
|
||||
if let Some(p) = self.model.world.get_unioned_polygon(ID::Road(*r)) {
|
||||
g.draw_polygon(Color::CYAN, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
State::MovingIntersection(_)
|
||||
| State::MovingBuilding(_)
|
||||
| State::MovingRoadPoint(_, _)
|
||||
@ -736,6 +758,26 @@ fn find_overlapping_intersections(model: &Model, ctx: &EventCtx) -> (Drawable, V
|
||||
(ctx.prerender.upload(batch), Vec::new())
|
||||
}
|
||||
|
||||
// TODO StableRoadID is dangerous, as this map changes. :\
|
||||
fn find_short_roads(model: &Model) -> HashSet<StableRoadID> {
|
||||
// Assume the full map has been built. We really care about short lanes there.
|
||||
let map: map_model::Map = abstutil::read_binary(
|
||||
&abstutil::path_map(&model.map.name),
|
||||
&mut Timer::throwaway(),
|
||||
)
|
||||
.unwrap();
|
||||
// Buses are 12.5
|
||||
let threshold = Distance::meters(13.0);
|
||||
let mut roads: HashSet<StableRoadID> = HashSet::new();
|
||||
for l in map.all_lanes() {
|
||||
if l.length() < threshold {
|
||||
roads.insert(map.get_r(l.parent).stable_id);
|
||||
}
|
||||
}
|
||||
println!("{} short roads", roads.len());
|
||||
roads
|
||||
}
|
||||
|
||||
fn main() {
|
||||
ezgui::run(
|
||||
ezgui::Settings::new("Synthetic map editor", (1800.0, 800.0)),
|
||||
|
@ -153,4 +153,8 @@ impl<ID: ObjectID> World<ID> {
|
||||
let obj = self.objects.remove(&id).unwrap();
|
||||
self.quadtree.remove(obj.quadtree_id).unwrap();
|
||||
}
|
||||
|
||||
pub fn get_unioned_polygon(&self, id: ID) -> Option<&Polygon> {
|
||||
Some(&self.objects.get(&id)?.unioned_polygon)
|
||||
}
|
||||
}
|
||||
|
@ -419,13 +419,21 @@ impl RawMap {
|
||||
let road = self.roads.get_mut(&r).unwrap();
|
||||
if road.i1 == i2 {
|
||||
road.i1 = i1;
|
||||
|
||||
road.center_points[0] = i1_pt;
|
||||
// TODO More extreme: All of the points of the short road. Except there usually
|
||||
// aren't many, since they're short.
|
||||
//road.center_points.insert(0, i1_pt);
|
||||
|
||||
// TODO Should we even do this?
|
||||
road.orig_id.node1 = i1_orig_id.osm_node_id;
|
||||
} else {
|
||||
assert_eq!(road.i2, i2);
|
||||
road.i2 = i1;
|
||||
|
||||
*road.center_points.last_mut().unwrap() = i1_pt;
|
||||
//road.center_points.push(i1_pt);
|
||||
|
||||
// TODO Should we even do this?
|
||||
road.orig_id.node2 = i1_orig_id.osm_node_id;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user