mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-28 08:53:26 +03:00
count the buildings and parking spots in each tract
This commit is contained in:
parent
083b96f0e7
commit
6f2b907927
@ -1,15 +1,16 @@
|
||||
use crate::common::CommonState;
|
||||
use crate::helpers::rotating_color;
|
||||
use crate::helpers::{rotating_color, ID};
|
||||
use crate::ui::UI;
|
||||
use abstutil::Timer;
|
||||
use abstutil::{prettyprint_usize, Timer};
|
||||
use ezgui::{Color, EventCtx, GfxCtx, Key, ModalMenu, Text};
|
||||
use geom::{GPSBounds, Polygon};
|
||||
use geom::Polygon;
|
||||
use popdat::PopDat;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub struct DataVisualizer {
|
||||
menu: ModalMenu,
|
||||
popdat: PopDat,
|
||||
tracts: Vec<Tract>,
|
||||
tracts: BTreeMap<String, Tract>,
|
||||
|
||||
// TODO Urgh. 0, 1, or 2.
|
||||
current_dataset: usize,
|
||||
@ -17,9 +18,11 @@ pub struct DataVisualizer {
|
||||
}
|
||||
|
||||
struct Tract {
|
||||
name: String,
|
||||
polygon: Polygon,
|
||||
color: Color,
|
||||
|
||||
num_bldgs: usize,
|
||||
num_parking_spots: usize,
|
||||
}
|
||||
|
||||
impl DataVisualizer {
|
||||
@ -39,7 +42,7 @@ impl DataVisualizer {
|
||||
],
|
||||
ctx,
|
||||
),
|
||||
tracts: clip(&popdat, &ui.primary.map.get_gps_bounds()),
|
||||
tracts: clip(&popdat, ui, &mut timer),
|
||||
popdat,
|
||||
current_dataset: 0,
|
||||
current_tract: None,
|
||||
@ -52,6 +55,12 @@ impl DataVisualizer {
|
||||
if let Some(ref name) = self.current_tract {
|
||||
txt.add_line("Census ".to_string());
|
||||
txt.append(name.clone(), Some(ui.cs.get("OSD name color")));
|
||||
let tract = &self.tracts[name];
|
||||
txt.add_line(format!("{} buildings", prettyprint_usize(tract.num_bldgs)));
|
||||
txt.add_line(format!(
|
||||
"{} parking spots ",
|
||||
prettyprint_usize(tract.num_parking_spots)
|
||||
));
|
||||
}
|
||||
self.menu.handle_event(ctx, Some(txt));
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
@ -70,9 +79,9 @@ impl DataVisualizer {
|
||||
if !ctx.canvas.is_dragging() && ctx.input.get_moved_mouse().is_some() {
|
||||
if let Some(pt) = ctx.canvas.get_cursor_in_map_space() {
|
||||
self.current_tract = None;
|
||||
for tract in &self.tracts {
|
||||
for (name, tract) in &self.tracts {
|
||||
if tract.polygon.contains_pt(pt) {
|
||||
self.current_tract = Some(tract.name.clone());
|
||||
self.current_tract = Some(name.clone());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -83,8 +92,8 @@ impl DataVisualizer {
|
||||
}
|
||||
|
||||
pub fn draw(&self, g: &mut GfxCtx, ui: &UI) {
|
||||
for tract in &self.tracts {
|
||||
let color = if Some(tract.name.clone()) == self.current_tract {
|
||||
for (name, tract) in &self.tracts {
|
||||
let color = if Some(name.clone()) == self.current_tract {
|
||||
ui.cs.get("selected")
|
||||
} else {
|
||||
tract.color
|
||||
@ -104,18 +113,50 @@ impl DataVisualizer {
|
||||
}
|
||||
}
|
||||
|
||||
fn clip(popdat: &PopDat, bounds: &GPSBounds) -> Vec<Tract> {
|
||||
fn clip(popdat: &PopDat, ui: &UI, timer: &mut Timer) -> BTreeMap<String, Tract> {
|
||||
// TODO Partial clipping could be neat, except it'd be confusing to interpret totals.
|
||||
let mut results = Vec::new();
|
||||
let mut results = BTreeMap::new();
|
||||
timer.start_iter("clip tracts", popdat.tracts.len());
|
||||
for (name, tract) in &popdat.tracts {
|
||||
if let Some(pts) = bounds.try_convert(&tract.pts) {
|
||||
timer.next();
|
||||
if let Some(pts) = ui.primary.map.get_gps_bounds().try_convert(&tract.pts) {
|
||||
// TODO We should actually make sure the polygon is completely contained within the
|
||||
// map's boundary.
|
||||
results.push(Tract {
|
||||
name: name.clone(),
|
||||
polygon: Polygon::new(&pts),
|
||||
let polygon = Polygon::new(&pts);
|
||||
|
||||
// TODO Don't just use the center...
|
||||
let mut num_bldgs = 0;
|
||||
let mut num_parking_spots = 0;
|
||||
for id in ui
|
||||
.primary
|
||||
.draw_map
|
||||
.get_matching_objects(polygon.get_bounds())
|
||||
{
|
||||
match id {
|
||||
ID::Building(b) => {
|
||||
if polygon.contains_pt(ui.primary.map.get_b(b).polygon.center()) {
|
||||
num_bldgs += 1;
|
||||
}
|
||||
}
|
||||
ID::Lane(l) => {
|
||||
let lane = ui.primary.map.get_l(l);
|
||||
if lane.is_parking() && polygon.contains_pt(lane.lane_center_pts.middle()) {
|
||||
num_parking_spots += lane.number_parking_spots();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
results.insert(
|
||||
name.clone(),
|
||||
Tract {
|
||||
polygon,
|
||||
color: rotating_color(results.len()),
|
||||
});
|
||||
num_bldgs,
|
||||
num_parking_spots,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
println!(
|
||||
|
@ -298,17 +298,6 @@ impl DrawMap {
|
||||
&self.areas[id.0]
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_matching_lanes(&self, bounds: Bounds) -> Vec<LaneID> {
|
||||
let mut results: Vec<LaneID> = Vec::new();
|
||||
for &(id, _, _) in &self.quadtree.query(bounds.as_bbox()) {
|
||||
if let ID::Lane(id) = id {
|
||||
results.push(*id);
|
||||
}
|
||||
}
|
||||
results
|
||||
}
|
||||
|
||||
// Unsorted, unexpanded, raw result.
|
||||
pub fn get_matching_objects(&self, bounds: Bounds) -> Vec<ID> {
|
||||
let mut results: Vec<ID> = Vec::new();
|
||||
|
Loading…
Reference in New Issue
Block a user