plugin to find and show chokepoints

This commit is contained in:
Dustin Carlino 2018-10-13 11:34:00 -07:00
parent 99559fa578
commit f7f9b5ab70
9 changed files with 127 additions and 5 deletions

View File

@ -13,9 +13,7 @@ pub fn split_up_roads(input: &raw_data::Map, elevation: &srtm::Elevation) -> raw
for r in &input.roads {
for (idx, raw_pt) in r.points.iter().enumerate() {
let pt = raw_pt.to_hashable();
counts_per_pt.entry(pt).or_insert(0);
let count = counts_per_pt[&pt] + 1;
counts_per_pt.insert(pt, count);
let count = (*counts_per_pt.entry(pt).or_insert(0) += 1);
if count == 2 {
intersections.insert(pt);

View File

@ -9,3 +9,4 @@
- lighting?
- fog effects
- in 3D, what if roads are sunken rivers and buildings giant skyscrapers?
- eyes on the houses, that blink

View File

@ -7,6 +7,7 @@ authors = ["Dustin Carlino <dabreegster@gmail.com>"]
aabb-quadtree = "0.1.0"
abstutil = { path = "../abstutil" }
control = { path = "../control" }
counter = "0.4.3"
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }
ezgui = { path = "../ezgui" }
flame = "0.2.2"

View File

@ -3,6 +3,7 @@
extern crate aabb_quadtree;
extern crate abstutil;
extern crate control;
extern crate counter;
extern crate dimensioned;
extern crate ezgui;
extern crate flame;

View File

@ -0,0 +1,101 @@
use colors::Colors;
use counter::Counter;
use dimensioned::si;
use ezgui::{Color, UserInput};
use map_model::{IntersectionID, LaneID, Map, Traversable};
use objects::{Ctx, DEBUG_EXTRA, ID};
use piston::input::Key;
use plugins::Colorizer;
use sim::Sim;
use std::collections::HashSet;
use std::f64;
const TOP_N: usize = 10;
pub enum ChokepointsFinder {
Inactive,
Active(HashSet<LaneID>, HashSet<IntersectionID>),
}
impl ChokepointsFinder {
pub fn new() -> ChokepointsFinder {
ChokepointsFinder::Inactive
}
pub fn event(&mut self, input: &mut UserInput, sim: &Sim, map: &Map) -> bool {
let mut new_state: Option<ChokepointsFinder> = None;
match self {
ChokepointsFinder::Inactive => {
if input.unimportant_key_pressed(
Key::C,
DEBUG_EXTRA,
"find chokepoints of current sim",
) {
new_state = Some(find_chokepoints(sim, map));
}
}
ChokepointsFinder::Active(_, _) => {
if input.key_pressed(Key::Return, "stop showing chokepoints") {
new_state = Some(ChokepointsFinder::Inactive);
}
}
};
if let Some(s) = new_state {
*self = s;
}
match self {
ChokepointsFinder::Inactive => false,
_ => true,
}
}
}
impl Colorizer for ChokepointsFinder {
fn color_for(&self, obj: ID, ctx: Ctx) -> Option<Color> {
match self {
ChokepointsFinder::Inactive => None,
ChokepointsFinder::Active(lanes, intersections) => match obj {
ID::Lane(l) if lanes.contains(&l) => Some(ctx.cs.get(Colors::MatchClassification)),
ID::Intersection(i) if intersections.contains(&i) => {
Some(ctx.cs.get(Colors::MatchClassification))
}
_ => None,
},
}
}
}
fn find_chokepoints(sim: &Sim, map: &Map) -> 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();
info!("Finding chokepoints from {} active agents", active.len());
for a in active.into_iter() {
for segment in sim.trace_route(a, map, f64::MAX * si::M).unwrap().segments {
match segment.on {
Traversable::Lane(l) => {
count_per_lane.update(vec![l]);
}
Traversable::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::Active(lanes, intersections)
}

View File

@ -1,4 +1,5 @@
pub mod a_b_tests;
pub mod chokepoints;
pub mod classification;
pub mod color_picker;
pub mod debug_objects;

View File

@ -12,6 +12,7 @@ use map_model::{IntersectionID, Map};
use objects::{Ctx, ID, ROOT_MENU};
use piston::input::Key;
use plugins::a_b_tests::ABTestManager;
use plugins::chokepoints::ChokepointsFinder;
use plugins::classification::OsmClassifier;
use plugins::color_picker::ColorPicker;
use plugins::debug_objects::DebugObjectsState;
@ -241,6 +242,13 @@ impl UIWrapper {
}
active
}),
Box::new(|ctx| {
ctx.ui.primary.chokepoints.event(
ctx.input,
&ctx.ui.primary.sim,
&ctx.ui.primary.map,
)
}),
Box::new(|ctx| {
let (active, new_ui) =
ctx.ui
@ -285,6 +293,7 @@ pub struct PerMapUI {
draw_neighborhoods: DrawNeighborhoodState,
scenarios: ScenarioManager,
edits_manager: EditsManager,
chokepoints: ChokepointsFinder,
}
impl PerMapUI {
@ -330,6 +339,7 @@ impl PerMapUI {
draw_neighborhoods: DrawNeighborhoodState::new(),
scenarios: ScenarioManager::new(),
edits_manager: EditsManager::new(),
chokepoints: ChokepointsFinder::new(),
}
}
}
@ -581,8 +591,9 @@ impl UI {
16 => Some(Box::new(&self.primary.draw_neighborhoods)),
17 => Some(Box::new(&self.primary.scenarios)),
18 => Some(Box::new(&self.primary.edits_manager)),
19 => Some(Box::new(&self.ab_test_manager)),
20 => Some(Box::new(&self.logs)),
19 => Some(Box::new(&self.primary.chokepoints)),
20 => Some(Box::new(&self.ab_test_manager)),
21 => Some(Box::new(&self.logs)),
_ => panic!("Active plugin {} is too high", idx),
}
}

View File

@ -344,6 +344,10 @@ impl Sim {
}
}
pub fn active_agents(&self) -> Vec<AgentID> {
self.trips_state.active_agents()
}
pub fn trace_route(&self, id: AgentID, map: &Map, dist_ahead: Distance) -> Option<Trace> {
match id {
AgentID::Car(car) => self.driving_state.trace_route(car, map, dist_ahead),

View File

@ -221,6 +221,10 @@ impl TripManager {
}
summary
}
pub fn active_agents(&self) -> Vec<AgentID> {
self.active_trip_mode.keys().cloned().collect()
}
}
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]