stable IDs for buildings in raw layer too. stop futzing with ID problems there.

This commit is contained in:
Dustin Carlino 2019-09-17 13:11:08 -07:00
parent 33ab7d4553
commit eee5981c14
7 changed files with 82 additions and 60 deletions

View File

@ -92,7 +92,7 @@ pub fn clip_map(map: &mut raw_data::Map, timer: &mut Timer) {
}
}
map.buildings.retain(|b| {
retain_btreemap(&mut map.buildings, |_, b| {
b.polygon
.points()
.iter()

View File

@ -211,32 +211,32 @@ fn use_offstreet_parking(map: &mut raw_data::Map, path: &str, timer: &mut Timer)
timer.start("match offstreet parking points");
let shapes = kml::load(path, &map.gps_bounds, timer).expect("loading offstreet_parking failed");
// Building indices
let mut closest: FindClosest<usize> = FindClosest::new(&map.gps_bounds.to_bounds());
for (idx, b) in map.buildings.iter().enumerate() {
closest.add(idx, b.polygon.points());
let mut closest: FindClosest<raw_data::StableBuildingID> =
FindClosest::new(&map.gps_bounds.to_bounds());
for (id, b) in &map.buildings {
closest.add(*id, b.polygon.points());
}
// TODO Another function just to use ?. Try blocks would rock.
let mut handle_shape: Box<dyn FnMut(kml::ExtraShape) -> Option<()>> = Box::new(|s| {
assert_eq!(s.points.len(), 1);
let pt = Pt2D::from_gps(s.points[0], &map.gps_bounds)?;
let (idx, _) = closest.closest_pt(pt, Distance::meters(50.0))?;
let (id, _) = closest.closest_pt(pt, Distance::meters(50.0))?;
// TODO Handle parking lots.
if !map.buildings[idx].polygon.contains_pt(pt) {
if !map.buildings[&id].polygon.contains_pt(pt) {
return None;
}
let name = s.attributes.get("DEA_FACILITY_NAME")?.to_string();
let num_stalls = s.attributes.get("DEA_STALLS")?.parse::<usize>().ok()?;
// TODO Update the existing one instead
if let Some(ref existing) = map.buildings[idx].parking {
if let Some(ref existing) = map.buildings[&id].parking {
// TODO Can't use timer inside this closure
println!(
"Two offstreet parking hints apply to building {}: {} @ {}, and {} @ {}",
idx, existing.num_stalls, existing.name, num_stalls, name
"Two offstreet parking hints apply to {}: {} @ {}, and {} @ {}",
id, existing.num_stalls, existing.name, num_stalls, name
);
}
map.buildings[idx].parking = Some(OffstreetParking {
map.buildings.get_mut(&id).unwrap().parking = Some(OffstreetParking {
name,
num_stalls,
// Temporary values, populate later

View File

@ -97,12 +97,16 @@ pub fn extract_osm(
if deduped.len() < 3 {
continue;
}
map.buildings.push(raw_data::Building {
osm_way_id: way.id,
polygon: Polygon::new(&deduped),
osm_tags: tags,
parking: None,
});
let id = raw_data::StableBuildingID(map.buildings.len());
map.buildings.insert(
id,
raw_data::Building {
osm_way_id: way.id,
polygon: Polygon::new(&deduped),
osm_tags: tags,
parking: None,
},
);
} else if let Some(at) = get_area_type(&tags) {
if pts.len() < 3 {
continue;

View File

@ -2,26 +2,26 @@ use crate::make::sidewalk_finder::find_sidewalk_points;
use crate::{raw_data, Building, BuildingID, FrontPath, Lane, LaneID, Position, Road};
use abstutil::Timer;
use geom::{Bounds, Distance, FindClosest, HashablePt2D, Line, Polygon};
use std::collections::HashSet;
use std::collections::{BTreeMap, HashSet};
pub fn make_all_buildings(
results: &mut Vec<Building>,
input: &Vec<raw_data::Building>,
input: &BTreeMap<raw_data::StableBuildingID, raw_data::Building>,
bounds: &Bounds,
lanes: &Vec<Lane>,
roads: &Vec<Road>,
timer: &mut Timer,
) {
timer.start("convert buildings");
let mut center_per_bldg: Vec<HashablePt2D> = Vec::new();
let mut center_per_bldg: BTreeMap<raw_data::StableBuildingID, HashablePt2D> = BTreeMap::new();
let mut query: HashSet<HashablePt2D> = HashSet::new();
timer.start_iter("get building center points", input.len());
for b in input {
for (id, b) in input {
timer.next();
// TODO Use the polylabel? Want to have visually distinct lines for front path and
// driveway; using two different "centers" is a lazy way for now.
let center = b.polygon.center().to_hashable();
center_per_bldg.push(center);
center_per_bldg.insert(*id, center);
query.insert(center);
}
@ -45,7 +45,7 @@ pub fn make_all_buildings(
let sidewalk_pts = find_sidewalk_points(bounds, query, lanes, Distance::meters(100.0), timer);
timer.start_iter("create building front paths", center_per_bldg.len());
for (idx, bldg_center) in center_per_bldg.into_iter().enumerate() {
for (stable_id, bldg_center) in center_per_bldg {
timer.next();
if let Some(sidewalk_pos) = sidewalk_pts.get(&bldg_center) {
let sidewalk_pt = lanes[sidewalk_pos.lane().0]
@ -55,21 +55,21 @@ pub fn make_all_buildings(
timer.warn("Skipping a building because front path has 0 length".to_string());
continue;
}
let polygon = &input[idx].polygon;
let line = trim_path(polygon, Line::new(bldg_center.to_pt2d(), sidewalk_pt));
let b = &input[&stable_id];
let line = trim_path(&b.polygon, Line::new(bldg_center.to_pt2d(), sidewalk_pt));
let id = BuildingID(results.len());
let mut bldg = Building {
id,
polygon: polygon.clone(),
osm_tags: input[idx].osm_tags.clone(),
osm_way_id: input[idx].osm_way_id,
polygon: b.polygon.clone(),
osm_tags: b.osm_tags.clone(),
osm_way_id: b.osm_way_id,
front_path: FrontPath {
sidewalk: *sidewalk_pos,
line,
},
parking: input[idx].parking.clone(),
label_center: polygon.polylabel(),
parking: b.parking.clone(),
label_center: b.polygon.polylabel(),
};
// Make a driveway from the parking icon to the nearest road.

View File

@ -25,12 +25,20 @@ impl fmt::Display for StableIntersectionID {
}
}
#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, PartialOrd, Ord, Clone, Copy, Hash)]
pub struct StableBuildingID(pub usize);
impl fmt::Display for StableBuildingID {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "StableBuildingID({0})", self.0)
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Map {
pub name: String,
pub roads: BTreeMap<StableRoadID, Road>,
pub intersections: BTreeMap<StableIntersectionID, Intersection>,
pub buildings: Vec<Building>,
pub buildings: BTreeMap<StableBuildingID, Building>,
pub bus_routes: Vec<Route>,
pub areas: Vec<Area>,
// from OSM way => [(restriction, to OSM way)]
@ -46,7 +54,7 @@ impl Map {
name,
roads: BTreeMap::new(),
intersections: BTreeMap::new(),
buildings: Vec::new(),
buildings: BTreeMap::new(),
bus_routes: Vec::new(),
areas: Vec::new(),
turn_restrictions: BTreeMap::new(),

View File

@ -2,8 +2,8 @@ mod model;
use ezgui::{Color, EventCtx, EventLoopMode, GfxCtx, Key, Line, Text, Wizard, GUI};
use geom::{Distance, Line, Polygon, Pt2D};
use map_model::raw_data::{StableIntersectionID, StableRoadID};
use model::{BuildingID, Direction, Model, ID};
use map_model::raw_data::{StableBuildingID, StableIntersectionID, StableRoadID};
use model::{Direction, Model, ID};
use std::{env, process};
struct UI {
@ -15,8 +15,8 @@ struct UI {
enum State {
Viewing,
MovingIntersection(StableIntersectionID),
MovingBuilding(BuildingID),
LabelingBuilding(BuildingID, Wizard),
MovingBuilding(StableBuildingID),
LabelingBuilding(StableBuildingID, Wizard),
LabelingRoad((StableRoadID, Direction), Wizard),
LabelingIntersection(StableIntersectionID, Wizard),
CreatingRoad(StableIntersectionID),

View File

@ -2,7 +2,7 @@ use abstutil::{read_binary, MultiMap, Timer};
use ezgui::world::{Object, ObjectID, World};
use ezgui::{Color, EventCtx, GfxCtx, Line, Prerender, Text};
use geom::{Bounds, Circle, Distance, PolyLine, Polygon, Pt2D};
use map_model::raw_data::{MapFix, MapFixes, StableIntersectionID, StableRoadID};
use map_model::raw_data::{MapFix, MapFixes, StableBuildingID, StableIntersectionID, StableRoadID};
use map_model::{raw_data, IntersectionType, LaneType, RoadSpec, LANE_THICKNESS};
use std::collections::BTreeMap;
use std::mem;
@ -13,7 +13,6 @@ const CENTER_LINE_THICKNESS: Distance = Distance::const_meters(0.5);
const SYNTHETIC_OSM_WAY_ID: i64 = -1;
pub type BuildingID = usize;
pub type Direction = bool;
const FORWARDS: Direction = true;
const BACKWARDS: Direction = false;
@ -52,6 +51,10 @@ impl Model {
model.map = read_binary(path, &mut timer).unwrap();
model.map.apply_fixes(&model.fixes, &mut timer);
for id in model.map.buildings.keys() {
model.id_counter = model.id_counter.max(id.0 + 1);
}
for id in model.map.intersections.keys() {
model.id_counter = model.id_counter.max(id.0 + 1);
}
@ -65,7 +68,7 @@ impl Model {
model.world = World::new(&model.compute_bounds());
if !model.exclude_bldgs {
for id in 0..model.map.buildings.len() {
for id in model.map.buildings.keys().cloned().collect::<Vec<_>>() {
model.bldg_added(id, prerender);
}
}
@ -114,7 +117,7 @@ impl Model {
fn compute_bounds(&self) -> Bounds {
let mut bounds = Bounds::new();
for b in &self.map.buildings {
for b in self.map.buildings.values() {
for pt in b.polygon.points() {
bounds.update(*pt);
}
@ -132,8 +135,8 @@ impl Model {
pub fn delete_everything_inside(&mut self, area: Polygon) {
if !self.exclude_bldgs {
for id in 0..self.map.buildings.len() {
if area.contains_pt(self.map.buildings[id].polygon.center()) {
for id in self.map.buildings.keys().cloned().collect::<Vec<_>>() {
if area.contains_pt(self.map.buildings[&id].polygon.center()) {
self.delete_b(id);
}
}
@ -496,8 +499,8 @@ impl Model {
}
impl Model {
fn bldg_added(&mut self, id: BuildingID, prerender: &Prerender) {
let b = &self.map.buildings[id];
fn bldg_added(&mut self, id: StableBuildingID, prerender: &Prerender) {
let b = &self.map.buildings[&id];
self.world.add(
prerender,
Object::new(ID::Building(id), Color::BLUE, b.polygon.clone())
@ -506,21 +509,25 @@ impl Model {
}
pub fn create_b(&mut self, center: Pt2D, prerender: &Prerender) {
let id = self.map.buildings.len();
self.map.buildings.push(raw_data::Building {
polygon: Polygon::rectangle(center, BUILDING_LENGTH, BUILDING_LENGTH),
osm_tags: BTreeMap::new(),
osm_way_id: SYNTHETIC_OSM_WAY_ID,
parking: None,
});
let id = StableBuildingID(self.id_counter);
self.id_counter += 1;
self.map.buildings.insert(
id,
raw_data::Building {
polygon: Polygon::rectangle(center, BUILDING_LENGTH, BUILDING_LENGTH),
osm_tags: BTreeMap::new(),
osm_way_id: SYNTHETIC_OSM_WAY_ID,
parking: None,
},
);
self.bldg_added(id, prerender);
}
pub fn move_b(&mut self, id: BuildingID, new_center: Pt2D, prerender: &Prerender) {
pub fn move_b(&mut self, id: StableBuildingID, new_center: Pt2D, prerender: &Prerender) {
self.world.delete(ID::Building(id));
let b = &mut self.map.buildings[id];
let b = self.map.buildings.get_mut(&id).unwrap();
let old_center = b.polygon.center();
b.polygon = b.polygon.translate(
Distance::meters(new_center.x() - old_center.x()),
@ -530,30 +537,33 @@ impl Model {
self.bldg_added(id, prerender);
}
pub fn set_b_label(&mut self, id: BuildingID, label: String, prerender: &Prerender) {
pub fn set_b_label(&mut self, id: StableBuildingID, label: String, prerender: &Prerender) {
self.world.delete(ID::Building(id));
self.map.buildings[id]
self.map
.buildings
.get_mut(&id)
.unwrap()
.osm_tags
.insert("abst:label".to_string(), label);
self.bldg_added(id, prerender);
}
pub fn get_b_label(&self, id: BuildingID) -> Option<String> {
self.map.buildings[id].osm_tags.get("abst:label").cloned()
pub fn get_b_label(&self, id: StableBuildingID) -> Option<String> {
self.map.buildings[&id].osm_tags.get("abst:label").cloned()
}
pub fn delete_b(&mut self, id: BuildingID) {
pub fn delete_b(&mut self, id: StableBuildingID) {
self.world.delete(ID::Building(id));
self.map.buildings.remove(id);
self.map.buildings.remove(&id);
}
}
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum ID {
Building(BuildingID),
Building(StableBuildingID),
Intersection(StableIntersectionID),
Lane(StableRoadID, Direction, usize),
}