mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-21 13:21:45 +03:00
chokepoints finder -> debug mode
This commit is contained in:
parent
a2fb26d5fb
commit
4df4a0931e
53
editor/src/debug/chokepoints.rs
Normal file
53
editor/src/debug/chokepoints.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use counter::Counter;
|
||||
use map_model::{IntersectionID, LaneID, PathStep};
|
||||
use sim::Sim;
|
||||
use std::collections::HashSet;
|
||||
|
||||
const TOP_N: usize = 10;
|
||||
|
||||
pub struct ChokepointsFinder {
|
||||
pub lanes: HashSet<LaneID>,
|
||||
pub intersections: HashSet<IntersectionID>,
|
||||
}
|
||||
|
||||
impl ChokepointsFinder {
|
||||
pub fn new(sim: &Sim) -> ChokepointsFinder {
|
||||
let mut count_per_lane: Counter<LaneID, usize> = Counter::new();
|
||||
let mut count_per_intersection: Counter<IntersectionID, usize> = Counter::new();
|
||||
|
||||
let active = sim.active_agents();
|
||||
println!("Finding chokepoints from {} active agents", active.len());
|
||||
for a in active.into_iter() {
|
||||
// Why would an active agent not have a path? Pedestrian riding a bus.
|
||||
if let Some(path) = sim.get_path(a) {
|
||||
for step in path.get_steps() {
|
||||
match step {
|
||||
PathStep::Lane(l) | PathStep::ContraflowLane(l) => {
|
||||
count_per_lane.update(vec![*l]);
|
||||
}
|
||||
PathStep::Turn(t) => {
|
||||
count_per_intersection.update(vec![t.parent]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let lanes: HashSet<LaneID> = count_per_lane
|
||||
.most_common_ordered()
|
||||
.into_iter()
|
||||
.take(TOP_N)
|
||||
.map(|(l, _)| l)
|
||||
.collect();
|
||||
let intersections: HashSet<IntersectionID> = count_per_intersection
|
||||
.most_common_ordered()
|
||||
.into_iter()
|
||||
.take(TOP_N)
|
||||
.map(|(i, _)| i)
|
||||
.collect();
|
||||
ChokepointsFinder {
|
||||
lanes,
|
||||
intersections,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
mod chokepoints;
|
||||
|
||||
use crate::game::{GameState, Mode};
|
||||
use ezgui::{EventCtx, EventLoopMode, GfxCtx, Wizard};
|
||||
use crate::objects::ID;
|
||||
use ezgui::{Color, EventCtx, EventLoopMode, GfxCtx, Text, Wizard};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct DebugMode {
|
||||
state: State,
|
||||
chokepoints: Option<chokepoints::ChokepointsFinder>,
|
||||
}
|
||||
|
||||
enum State {
|
||||
@ -14,6 +18,7 @@ impl DebugMode {
|
||||
pub fn new() -> DebugMode {
|
||||
DebugMode {
|
||||
state: State::Exploring,
|
||||
chokepoints: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,9 +31,27 @@ impl DebugMode {
|
||||
.ui
|
||||
.handle_mouseover(ctx, None, &state.ui.state.primary.sim);
|
||||
|
||||
ctx.input.set_mode("Debug Mode", ctx.canvas);
|
||||
let mut txt = Text::new();
|
||||
txt.add_styled_line("Debug Mode".to_string(), None, Some(Color::BLUE), None);
|
||||
if mode.chokepoints.is_some() {
|
||||
txt.add_line("Showing chokepoints".to_string());
|
||||
}
|
||||
ctx.input
|
||||
.set_mode_with_new_prompt("Debug Mode", txt, ctx.canvas);
|
||||
if ctx.input.modal_action("quit") {
|
||||
state.mode = Mode::SplashScreen(Wizard::new(), None);
|
||||
return EventLoopMode::InputOnly;
|
||||
}
|
||||
|
||||
if ctx.input.modal_action("show/hide chokepoints") {
|
||||
if mode.chokepoints.is_some() {
|
||||
mode.chokepoints = None;
|
||||
} else {
|
||||
// TODO Nothing will actually exist. ;)
|
||||
mode.chokepoints = Some(chokepoints::ChokepointsFinder::new(
|
||||
&state.ui.state.primary.sim,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
EventLoopMode::InputOnly
|
||||
@ -41,9 +64,20 @@ impl DebugMode {
|
||||
match state.mode {
|
||||
Mode::Debug(ref mode) => match mode.state {
|
||||
State::Exploring => {
|
||||
let mut color_overrides = HashMap::new();
|
||||
if let Some(ref chokepoints) = mode.chokepoints {
|
||||
let color = state.ui.state.cs.get_def("chokepoint", Color::RED);
|
||||
for l in &chokepoints.lanes {
|
||||
color_overrides.insert(ID::Lane(*l), color);
|
||||
}
|
||||
for i in &chokepoints.intersections {
|
||||
color_overrides.insert(ID::Intersection(*i), color);
|
||||
}
|
||||
}
|
||||
|
||||
state
|
||||
.ui
|
||||
.new_draw(g, None, HashMap::new(), &state.ui.state.primary.sim);
|
||||
.new_draw(g, None, color_overrides, &state.ui.state.primary.sim);
|
||||
}
|
||||
},
|
||||
_ => unreachable!(),
|
||||
|
@ -1,84 +0,0 @@
|
||||
use crate::objects::{DrawCtx, ID};
|
||||
use crate::plugins::{BlockingPlugin, PluginCtx};
|
||||
use counter::Counter;
|
||||
use ezgui::Color;
|
||||
use map_model::{IntersectionID, LaneID, PathStep};
|
||||
use sim::Sim;
|
||||
use std::collections::HashSet;
|
||||
|
||||
const TOP_N: usize = 10;
|
||||
|
||||
pub struct ChokepointsFinder {
|
||||
lanes: HashSet<LaneID>,
|
||||
intersections: HashSet<IntersectionID>,
|
||||
}
|
||||
|
||||
impl ChokepointsFinder {
|
||||
pub fn new(ctx: &mut PluginCtx) -> Option<ChokepointsFinder> {
|
||||
if ctx.input.action_chosen("find chokepoints") {
|
||||
return Some(find_chokepoints(&ctx.primary.sim));
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockingPlugin for ChokepointsFinder {
|
||||
fn blocking_event(&mut self, ctx: &mut PluginCtx) -> bool {
|
||||
ctx.input.set_mode("Chokepoints Debugger", &ctx.canvas);
|
||||
|
||||
if ctx.input.modal_action("quit") {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn color_for(&self, obj: ID, ctx: &DrawCtx) -> Option<Color> {
|
||||
let color = ctx.cs.get_def("chokepoint", Color::RED);
|
||||
match obj {
|
||||
ID::Lane(l) if self.lanes.contains(&l) => Some(color),
|
||||
ID::Intersection(i) if self.intersections.contains(&i) => Some(color),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn find_chokepoints(sim: &Sim) -> ChokepointsFinder {
|
||||
let mut count_per_lane: Counter<LaneID, usize> = Counter::new();
|
||||
let mut count_per_intersection: Counter<IntersectionID, usize> = Counter::new();
|
||||
|
||||
let active = sim.active_agents();
|
||||
println!("Finding chokepoints from {} active agents", active.len());
|
||||
for a in active.into_iter() {
|
||||
// Why would an active agent not have a path? Pedestrian riding a bus.
|
||||
if let Some(path) = sim.get_path(a) {
|
||||
for step in path.get_steps() {
|
||||
match step {
|
||||
PathStep::Lane(l) | PathStep::ContraflowLane(l) => {
|
||||
count_per_lane.update(vec![*l]);
|
||||
}
|
||||
PathStep::Turn(t) => {
|
||||
count_per_intersection.update(vec![t.parent]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let lanes: HashSet<LaneID> = count_per_lane
|
||||
.most_common_ordered()
|
||||
.into_iter()
|
||||
.take(TOP_N)
|
||||
.map(|(l, _)| l)
|
||||
.collect();
|
||||
let intersections: HashSet<IntersectionID> = count_per_intersection
|
||||
.most_common_ordered()
|
||||
.into_iter()
|
||||
.take(TOP_N)
|
||||
.map(|(i, _)| i)
|
||||
.collect();
|
||||
ChokepointsFinder {
|
||||
lanes,
|
||||
intersections,
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
pub mod chokepoints;
|
||||
pub mod connected_roads;
|
||||
pub mod debug_objects;
|
||||
pub mod debug_polygon;
|
||||
|
@ -210,10 +210,7 @@ impl UIState {
|
||||
}
|
||||
|
||||
if self.enable_debug_controls {
|
||||
if let Some(p) = debug::chokepoints::ChokepointsFinder::new(&mut ctx) {
|
||||
self.exclusive_blocking_plugin = Some(Box::new(p));
|
||||
return;
|
||||
} else if let Some(p) = debug::debug_polygon::DebugPolygon::new(&mut ctx) {
|
||||
if let Some(p) = debug::debug_polygon::DebugPolygon::new(&mut ctx) {
|
||||
self.exclusive_blocking_plugin = Some(Box::new(p));
|
||||
return;
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ impl GUI for UI {
|
||||
vec![
|
||||
(None, "screenshot everything"),
|
||||
(Some(Key::F1), "screenshot just this"),
|
||||
(None, "find chokepoints"),
|
||||
(Some(Key::Num1), "show/hide buildings"),
|
||||
(Some(Key::Num2), "show/hide intersections"),
|
||||
(Some(Key::Num3), "show/hide lanes"),
|
||||
@ -97,7 +96,6 @@ impl GUI for UI {
|
||||
],
|
||||
),
|
||||
ModalMenu::new("Original Roads", vec![(Key::Enter, "quit")]),
|
||||
ModalMenu::new("Chokepoints Debugger", vec![(Key::Enter, "quit")]),
|
||||
ModalMenu::new("A/B Trip Explorer", vec![(Key::Enter, "quit")]),
|
||||
ModalMenu::new("A/B All Trips Explorer", vec![(Key::Enter, "quit")]),
|
||||
ModalMenu::new("Search", vec![(Key::Enter, "quit")]),
|
||||
@ -174,7 +172,10 @@ impl GUI for UI {
|
||||
(Key::Dot, "forwards"),
|
||||
],
|
||||
),
|
||||
ModalMenu::new("Debug Mode", vec![(Key::Escape, "quit")]),
|
||||
ModalMenu::new(
|
||||
"Debug Mode",
|
||||
vec![(Key::Escape, "quit"), (Key::C, "show/hide chokepoints")],
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user