mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-26 07:52:05 +03:00
stable IDs for buildings in raw layer too. stop futzing with ID problems there.
This commit is contained in:
parent
33ab7d4553
commit
eee5981c14
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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(),
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user