diff --git a/editor/src/sandbox/mod.rs b/editor/src/sandbox/mod.rs index 97c56eda20..c8e81928ac 100644 --- a/editor/src/sandbox/mod.rs +++ b/editor/src/sandbox/mod.rs @@ -1,5 +1,4 @@ mod score; -mod show_activity; mod spawner; mod time_travel; @@ -19,7 +18,6 @@ use sim::Sim; pub struct SandboxMode { speed: SpeedControls, agent_tools: AgentTools, - show_activity: show_activity::ShowActivity, pub time_travel: time_travel::InactiveTimeTravel, common: CommonState, menu: ModalMenu, @@ -30,7 +28,6 @@ impl SandboxMode { SandboxMode { speed: SpeedControls::new(ctx, None), agent_tools: AgentTools::new(), - show_activity: show_activity::ShowActivity::Inactive, time_travel: time_travel::InactiveTimeTravel::new(), common: CommonState::new(), menu: ModalMenu::new( @@ -83,12 +80,6 @@ impl State for SandboxMode { let mut txt = Text::prompt("Sandbox Mode"); txt.add_line(ui.primary.sim.summary()); self.agent_tools.update_menu_info(&mut txt); - match self.show_activity { - show_activity::ShowActivity::Inactive => {} - _ => { - txt.add_line("Showing active traffic".to_string()); - } - } self.menu.handle_event(ctx, Some(txt)); ctx.canvas.handle_event(ctx.input); @@ -110,7 +101,6 @@ impl State for SandboxMode { } self.agent_tools.event(ctx, ui, &mut self.menu); - self.show_activity.event(ctx, ui, &mut self.menu); if ui.primary.current_selection.is_none() && self.menu.action("start time traveling") { return self.time_travel.start(ctx, ui); } @@ -213,7 +203,6 @@ impl State for SandboxMode { ); self.common.draw(g, ui); self.agent_tools.draw(g, ui); - self.show_activity.draw(g, ui); self.menu.draw(g); self.speed.draw(g); } diff --git a/editor/src/sandbox/show_activity.rs b/editor/src/sandbox/show_activity.rs deleted file mode 100644 index 2c71666202..0000000000 --- a/editor/src/sandbox/show_activity.rs +++ /dev/null @@ -1,186 +0,0 @@ -use crate::render::MIN_ZOOM_FOR_DETAIL; -use crate::ui::UI; -use ezgui::{Color, EventCtx, GfxCtx, ModalMenu}; -use geom::{Bounds, Distance, Duration, Polygon, Pt2D}; -use map_model::{RoadID, Traversable}; -use std::collections::HashMap; - -pub enum ShowActivity { - Inactive, - Unzoomed(Duration, RoadHeatmap), - Zoomed(Duration, Heatmap), -} - -impl ShowActivity { - pub fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI, menu: &mut ModalMenu) { - let zoomed = ctx.canvas.cam_zoom >= MIN_ZOOM_FOR_DETAIL; - - // If we survive past this, recompute current state. - match self { - ShowActivity::Inactive => { - if !menu.action("show/hide active traffic") { - return; - } - } - ShowActivity::Zoomed(time, ref heatmap) => { - if menu.action("show/hide active traffic") { - *self = ShowActivity::Inactive; - return; - } - if *time == ui.primary.sim.time() - && ctx.canvas.get_screen_bounds() == heatmap.bounds - && zoomed - { - return; - } - } - ShowActivity::Unzoomed(time, _) => { - if menu.action("show/hide active traffic") { - *self = ShowActivity::Inactive; - return; - } - if *time == ui.primary.sim.time() && !zoomed { - return; - } - } - }; - - if zoomed { - *self = ShowActivity::Zoomed(ui.primary.sim.time(), active_agent_heatmap(ctx, ui)); - } else { - *self = ShowActivity::Unzoomed(ui.primary.sim.time(), RoadHeatmap::new(ui)); - } - } - - pub fn draw(&self, g: &mut GfxCtx, ui: &UI) { - match self { - ShowActivity::Zoomed(_, ref heatmap) => { - heatmap.draw(g); - } - ShowActivity::Unzoomed(_, ref road_heatmap) => { - road_heatmap.draw(g, ui); - } - ShowActivity::Inactive => {} - } - } -} - -// A nice 10x10 -const NUM_TILES: usize = 10; - -pub struct Heatmap { - bounds: Bounds, - - counts: [[usize; NUM_TILES]; NUM_TILES], - max: usize, -} - -impl Heatmap { - fn new(bounds: Bounds) -> Heatmap { - Heatmap { - bounds, - counts: [[0; NUM_TILES]; NUM_TILES], - max: 0, - } - } - - fn add(&mut self, pt: Pt2D) { - // TODO Could also query sim with this filter - if !self.bounds.contains(pt) { - return; - } - - let x = ((pt.x() - self.bounds.min_x) / (self.bounds.max_x - self.bounds.min_x) - * (NUM_TILES as f64)) - .floor() as usize; - let y = ((pt.y() - self.bounds.min_y) / (self.bounds.max_y - self.bounds.min_y) - * (NUM_TILES as f64)) - .floor() as usize; - self.counts[x][y] += 1; - self.max = self.max.max(self.counts[x][y]); - } - - fn draw(&self, g: &mut GfxCtx) { - let tile_width = (self.bounds.max_x - self.bounds.min_x) / (NUM_TILES as f64); - let tile_height = (self.bounds.max_y - self.bounds.min_y) / (NUM_TILES as f64); - - for x in 0..NUM_TILES { - for y in 0..NUM_TILES { - if self.counts[x][y] == 0 { - continue; - } - - let percent = (self.counts[x][y] as f32) / (self.max as f32); - // TODO Map percent to hot/cold colors. For now, don't ever become totally opaque. - let color = Color::RED.alpha(percent * 0.8); - g.draw_polygon( - color, - &Polygon::rectangle_topleft( - Pt2D::new( - self.bounds.min_x + (x as f64) * tile_width, - self.bounds.min_y + (y as f64) * tile_height, - ), - Distance::meters(tile_width), - Distance::meters(tile_height), - ), - ); - } - } - } -} - -fn active_agent_heatmap(ctx: &EventCtx, ui: &mut UI) -> Heatmap { - let mut h = Heatmap::new(ctx.canvas.get_screen_bounds()); - let trip_positions = ui.primary.sim.get_trip_positions(&ui.primary.map); - for pt in trip_positions.canonical_pt_per_trip.values() { - h.add(*pt); - } - h -} - -pub struct RoadHeatmap { - // TODO Use the Counter type? Roll my own simple one? - count_per_road: HashMap, - max_count: usize, -} - -impl RoadHeatmap { - fn new(ui: &UI) -> RoadHeatmap { - let mut h = RoadHeatmap { - count_per_road: HashMap::new(), - max_count: 0, - }; - let map = &ui.primary.map; - for a in ui.primary.sim.active_agents() { - let r = match ui.primary.sim.location_for_agent(a, map) { - Traversable::Lane(l) => map.get_l(l).parent, - // Count the destination - Traversable::Turn(t) => map.get_l(t.dst).parent, - }; - h.count_per_road.entry(r).or_insert(0); - let count = h.count_per_road[&r] + 1; - h.count_per_road.insert(r, count); - h.max_count = h.max_count.max(count); - } - h - } - - fn draw(&self, g: &mut GfxCtx, ui: &UI) { - for (r, count) in &self.count_per_road { - let percent = (*count as f32) / (self.max_count as f32); - // TODO Map percent to hot/cold colors. For now, just bucket into 3 categories. - let color = if percent <= 0.3 { - Color::rgb(255, 255, 0) - } else if percent <= 0.6 { - Color::rgb(255, 128, 0) - } else { - Color::RED - }; - // TODO Inefficient! - g.draw_polygon( - color, - &ui.primary.map.get_r(*r).get_thick_polygon().unwrap(), - ); - } - } -} diff --git a/sim/src/sim.rs b/sim/src/sim.rs index e283fc4a4d..2c1981b9cb 100644 --- a/sim/src/sim.rs +++ b/sim/src/sim.rs @@ -775,14 +775,6 @@ impl Sim { } } - // TODO argh this is so inefficient - pub fn location_for_agent(&self, id: AgentID, map: &Map) -> Traversable { - match id { - AgentID::Car(id) => self.get_draw_car(id, map).unwrap().on, - AgentID::Pedestrian(id) => self.get_draw_ped(id, map).unwrap().on, - } - } - pub fn get_accepted_agents(&self, id: IntersectionID) -> HashSet { self.intersections.get_accepted_agents(id) }