mirror of
https://github.com/a-b-street/abstreet.git
synced 2025-01-01 19:04:50 +03:00
debug association between soundcast parcels and buildings
This commit is contained in:
parent
2d69392e9c
commit
20f8548634
@ -178,7 +178,7 @@ data/input/seattle/osm/mt_baker.osm,2cd7ba808d94318975bd73e9ced01c51,https://www
|
||||
data/input/seattle/osm/udistrict.osm,e5b0d978d1c74ae5c555a4ebd3ad9d70,https://www.dropbox.com/s/h66cidmzcq15pbo/udistrict.osm.zip?dl=0
|
||||
data/input/seattle/osm/washington-latest.osm.pbf,363e061c2bf9aa49b48fa12ec56d0ed1,https://www.dropbox.com/s/xha9cx696czbzlf/washington-latest.osm.pbf.zip?dl=0
|
||||
data/input/seattle/osm/west_seattle.osm,8f893f5a3302b3cf5a614b1d52e49b5f,https://www.dropbox.com/s/8m0vmvwg5zz3uod/west_seattle.osm.zip?dl=0
|
||||
data/input/seattle/parcels.bin,dc3eee0a4ba74a4a6ee626f2c55d5e51,https://www.dropbox.com/s/39bymqayph3easc/parcels.bin.zip?dl=0
|
||||
data/input/seattle/parcels.bin,494390afe74712bc296b29e02ef2711c,https://www.dropbox.com/s/39bymqayph3easc/parcels.bin.zip?dl=0
|
||||
data/input/seattle/parcels_urbansim.txt,db63d7d606e8702d12f9399e87e6a00f,https://www.dropbox.com/s/6g8rbsf200dssj3/parcels_urbansim.txt.zip?dl=0
|
||||
data/input/seattle/popdat.bin,d1fe506c5f4a65447646f0100e3e3a5a,https://www.dropbox.com/s/wrpji7e14rdwszs/popdat.bin.zip?dl=0
|
||||
data/input/seattle/sidewalks.bin,034dd47ab77902dbc81c0107f13d8965,https://www.dropbox.com/s/ma9bmisijc7v7xa/sidewalks.bin.zip?dl=0
|
||||
|
@ -3,12 +3,13 @@ use crate::game::{State, Transition};
|
||||
use aabb_quadtree::QuadTree;
|
||||
use abstutil::prettyprint_usize;
|
||||
use ezgui::{
|
||||
hotkey, Btn, Color, Composite, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key,
|
||||
Line, Outcome, Text, TextExt, VerticalAlignment, Widget,
|
||||
hotkey, Btn, Choice, Color, Composite, Drawable, EventCtx, GeomBatch, GfxCtx,
|
||||
HorizontalAlignment, Key, Line, Outcome, Text, TextExt, VerticalAlignment, Widget,
|
||||
};
|
||||
use geom::{Circle, Distance, PolyLine, Polygon, Pt2D, Ring};
|
||||
use kml::ExtraShapes;
|
||||
use std::collections::BTreeMap;
|
||||
use map_model::BuildingID;
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
|
||||
pub struct ViewKML {
|
||||
composite: Composite,
|
||||
@ -17,11 +18,15 @@ pub struct ViewKML {
|
||||
|
||||
selected: Option<usize>,
|
||||
quadtree: QuadTree<usize>,
|
||||
analysis: String,
|
||||
draw_analysis: Drawable,
|
||||
}
|
||||
|
||||
struct Object {
|
||||
polygon: Polygon,
|
||||
attribs: BTreeMap<String, String>,
|
||||
|
||||
osm_bldg: Option<BuildingID>,
|
||||
}
|
||||
|
||||
const RADIUS: Distance = Distance::const_meters(5.0);
|
||||
@ -37,10 +42,14 @@ impl ViewKML {
|
||||
};
|
||||
let bounds = app.primary.map.get_gps_bounds();
|
||||
|
||||
let dataset_name = abstutil::basename(path);
|
||||
|
||||
let mut batch = GeomBatch::new();
|
||||
let mut objects = Vec::new();
|
||||
let mut quadtree = QuadTree::default(app.primary.map.get_bounds().as_bbox());
|
||||
timer.start_iter("convert shapes", raw_shapes.shapes.len());
|
||||
for shape in raw_shapes.shapes {
|
||||
timer.next();
|
||||
if !bounds.contains(shape.points[0]) {
|
||||
continue;
|
||||
}
|
||||
@ -49,23 +58,17 @@ impl ViewKML {
|
||||
.into_iter()
|
||||
.map(|gps| Pt2D::forcibly_from_gps(gps, bounds))
|
||||
.collect();
|
||||
let obj = make_object(app, shape.attributes, pts, &dataset_name);
|
||||
|
||||
let polygon = if pts.len() == 1 {
|
||||
Circle::new(pts[0], RADIUS).to_polygon()
|
||||
} else if pts[0] == *pts.last().unwrap() {
|
||||
// TODO Toggle between these better
|
||||
//Polygon::new(&pts)
|
||||
Ring::new(pts).make_polygons(THICKNESS)
|
||||
} else {
|
||||
PolyLine::new(pts).make_polygons(THICKNESS)
|
||||
};
|
||||
quadtree.insert_with_box(objects.len(), obj.polygon.get_bounds().as_bbox());
|
||||
batch.push(Color::RED.alpha(0.8), obj.polygon.clone());
|
||||
objects.push(obj);
|
||||
}
|
||||
|
||||
quadtree.insert_with_box(objects.len(), polygon.get_bounds().as_bbox());
|
||||
batch.push(Color::RED.alpha(0.8), polygon.clone());
|
||||
objects.push(Object {
|
||||
polygon,
|
||||
attribs: shape.attributes,
|
||||
});
|
||||
let mut choices = vec![Choice::string("None")];
|
||||
if dataset_name == "parcels" {
|
||||
choices.push(Choice::string("parcels without buildings"));
|
||||
choices.push(Choice::string("parcels with multiple buildings"));
|
||||
}
|
||||
|
||||
Box::new(ViewKML {
|
||||
@ -81,8 +84,16 @@ impl ViewKML {
|
||||
.build_def(ctx, hotkey(Key::Escape))
|
||||
.align_right(),
|
||||
]),
|
||||
format!("{}: {} objects", path, prettyprint_usize(objects.len()))
|
||||
.draw_text(ctx),
|
||||
format!(
|
||||
"{}: {} objects",
|
||||
dataset_name,
|
||||
prettyprint_usize(objects.len())
|
||||
)
|
||||
.draw_text(ctx),
|
||||
Widget::row(vec![
|
||||
"Analysis:".draw_text(ctx).margin_right(10),
|
||||
Widget::dropdown(ctx, "analysis", "None".to_string(), choices),
|
||||
]),
|
||||
])
|
||||
.padding(10)
|
||||
.bg(app.cs.panel_bg),
|
||||
@ -92,13 +103,15 @@ impl ViewKML {
|
||||
objects,
|
||||
quadtree,
|
||||
selected: None,
|
||||
analysis: "None".to_string(),
|
||||
draw_analysis: ctx.upload(GeomBatch::new()),
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl State for ViewKML {
|
||||
fn event(&mut self, ctx: &mut EventCtx, _: &mut App) -> Transition {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
|
||||
ctx.canvas_movement();
|
||||
if ctx.redo_mouseover() {
|
||||
self.selected = None;
|
||||
@ -126,20 +139,96 @@ impl State for ViewKML {
|
||||
None => {}
|
||||
}
|
||||
|
||||
let analysis: String = self.composite.dropdown_value("analysis");
|
||||
if analysis != self.analysis {
|
||||
self.draw_analysis = ctx.upload(make_analysis(app, &self.objects, &analysis));
|
||||
self.analysis = analysis;
|
||||
}
|
||||
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &App) {
|
||||
fn draw(&self, g: &mut GfxCtx, app: &App) {
|
||||
g.redraw(&self.draw);
|
||||
g.redraw(&self.draw_analysis);
|
||||
self.composite.draw(g);
|
||||
|
||||
if let Some(idx) = self.selected {
|
||||
g.draw_polygon(Color::BLUE, &self.objects[idx].polygon);
|
||||
let obj = &self.objects[idx];
|
||||
|
||||
g.draw_polygon(Color::BLUE, &obj.polygon);
|
||||
let mut txt = Text::new();
|
||||
for (k, v) in &self.objects[idx].attribs {
|
||||
for (k, v) in &obj.attribs {
|
||||
txt.add(Line(format!("{} = {}", k, v)));
|
||||
}
|
||||
g.draw_mouse_tooltip(txt);
|
||||
|
||||
if let Some(b) = obj.osm_bldg {
|
||||
g.draw_polygon(Color::GREEN, &app.primary.map.get_b(b).polygon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_object(
|
||||
app: &App,
|
||||
attribs: BTreeMap<String, String>,
|
||||
pts: Vec<Pt2D>,
|
||||
dataset_name: &str,
|
||||
) -> Object {
|
||||
let polygon = if pts.len() == 1 {
|
||||
Circle::new(pts[0], RADIUS).to_polygon()
|
||||
} else if pts[0] == *pts.last().unwrap() {
|
||||
// TODO Toggle between these better
|
||||
//Polygon::new(&pts)
|
||||
Ring::new(pts).make_polygons(THICKNESS)
|
||||
} else {
|
||||
PolyLine::new(pts).make_polygons(THICKNESS)
|
||||
};
|
||||
|
||||
let mut osm_bldg = None;
|
||||
if dataset_name == "parcels" {
|
||||
if let Some(bldg) = attribs.get("osm_bldg") {
|
||||
for b in app.primary.map.all_buildings() {
|
||||
if b.osm_way_id.to_string() == bldg.to_string() {
|
||||
osm_bldg = Some(b.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object {
|
||||
polygon,
|
||||
attribs,
|
||||
osm_bldg,
|
||||
}
|
||||
}
|
||||
|
||||
fn make_analysis(app: &App, objects: &Vec<Object>, analysis: &str) -> GeomBatch {
|
||||
let mut batch = GeomBatch::new();
|
||||
match analysis {
|
||||
"None" => {}
|
||||
"parcels without buildings" => {
|
||||
for obj in objects {
|
||||
if obj.osm_bldg.is_none() {
|
||||
batch.push(Color::BLUE, obj.polygon.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
"parcels with multiple buildings" => {
|
||||
let mut seen = HashSet::new();
|
||||
for obj in objects {
|
||||
if let Some(b) = obj.osm_bldg {
|
||||
if seen.contains(&b) {
|
||||
batch.push(Color::BLUE, app.primary.map.get_b(b).polygon.clone());
|
||||
} else {
|
||||
seen.insert(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
batch
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ pub fn import_data() {
|
||||
}
|
||||
|
||||
fn import_trips(
|
||||
parcels_lookup: HashMap<usize, Endpoint>,
|
||||
parcels: HashMap<usize, Endpoint>,
|
||||
trips_path: &str,
|
||||
timer: &mut Timer,
|
||||
) -> Vec<OrigTrip> {
|
||||
@ -34,8 +34,8 @@ fn import_trips(
|
||||
total_records += 1;
|
||||
let rec: RawTrip = rec.unwrap();
|
||||
|
||||
let from = parcels_lookup[&(rec.opcl as usize)].clone();
|
||||
let to = parcels_lookup[&(rec.dpcl as usize)].clone();
|
||||
let from = parcels[&(rec.opcl as usize)].clone();
|
||||
let to = parcels[&(rec.dpcl as usize)].clone();
|
||||
|
||||
// If both are None, then skip -- the trip doesn't start or end within huge_seattle.
|
||||
// If both are the same building, also skip -- that's a redundant trip.
|
||||
@ -153,17 +153,6 @@ fn import_parcels(path: &str, timer: &mut Timer) -> HashMap<usize, Endpoint> {
|
||||
let gps = LonLat::new(x, y);
|
||||
let pt = Pt2D::forcibly_from_gps(gps, bounds);
|
||||
let osm_building = if bounds.contains(gps) {
|
||||
if boundary.contains_pt(pt) {
|
||||
let mut attributes = BTreeMap::new();
|
||||
attributes.insert("id".to_string(), id.to_string());
|
||||
attributes.insert("households".to_string(), num_households.to_string());
|
||||
attributes.insert("parking".to_string(), offstreet_parking_spaces.to_string());
|
||||
shapes.push(ExtraShape {
|
||||
points: vec![gps],
|
||||
attributes,
|
||||
});
|
||||
}
|
||||
|
||||
closest_bldg
|
||||
.closest_pt(pt, Distance::meters(30.0))
|
||||
.map(|(b, _)| b)
|
||||
@ -178,6 +167,20 @@ fn import_parcels(path: &str, timer: &mut Timer) -> HashMap<usize, Endpoint> {
|
||||
parcel_id: id,
|
||||
},
|
||||
);
|
||||
|
||||
if boundary.contains_pt(pt) {
|
||||
let mut attributes = BTreeMap::new();
|
||||
attributes.insert("id".to_string(), id.to_string());
|
||||
attributes.insert("households".to_string(), num_households.to_string());
|
||||
attributes.insert("parking".to_string(), offstreet_parking_spaces.to_string());
|
||||
if let Some(b) = osm_building {
|
||||
attributes.insert("osm_bldg".to_string(), b.to_string());
|
||||
}
|
||||
shapes.push(ExtraShape {
|
||||
points: vec![gps],
|
||||
attributes,
|
||||
});
|
||||
}
|
||||
}
|
||||
timer.note(format!("{} parcels", prettyprint_usize(result.len())));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user