rip out parcels entirely; unused for long time and no anticipated uses

This commit is contained in:
Dustin Carlino 2019-04-11 11:10:40 -07:00
parent 49ec5a312e
commit d207c3c33a
29 changed files with 52 additions and 457 deletions

View File

@ -5,10 +5,8 @@ authors = ["Dustin Carlino <dabreegster@gmail.com>"]
edition = "2018"
[dependencies]
aabb-quadtree = "0.1.0"
abstutil = { path = "../abstutil" }
byteorder = "1.2.1"
geo = "0.12.0"
geojson = "0.15.0"
geom = { path = "../geom" }
gtfs = { path = "../gtfs" }

View File

@ -1,111 +0,0 @@
use aabb_quadtree::geom::Rect;
use aabb_quadtree::QuadTree;
use abstutil::MultiMap;
use geo;
use geom::{GPSBounds, LonLat};
use map_model::raw_data;
use std::collections::BTreeSet;
// Slight cheat
type ParcelIdx = usize;
pub fn group_parcels(gps_bounds: &GPSBounds, parcels: &mut Vec<raw_data::Parcel>) {
// Make a quadtree to quickly prune intersections between parcels
let mut quadtree = QuadTree::default(gps_bounds.as_bbox());
for (idx, p) in parcels.iter().enumerate() {
quadtree.insert_with_box(idx, get_bbox(&p.points));
}
// First compute which parcels intersect
let mut adjacency: MultiMap<ParcelIdx, ParcelIdx> = MultiMap::new();
// TODO could use quadtree to prune
println!(
"Precomputing adjacency between {} parcels...",
parcels.len()
);
let mut adj_counter = 0;
for p1_idx in 0..parcels.len() {
for &(p2_idx, _, _) in &quadtree.query(get_bbox(&parcels[p1_idx].points)) {
if p1_idx != *p2_idx
&& polygons_intersect(&parcels[p1_idx].points, &parcels[*p2_idx].points)
{
// TODO could do something more clever later to avoid double memory
adjacency.insert(p1_idx, *p2_idx);
adjacency.insert(*p2_idx, p1_idx);
adj_counter += 1;
}
}
}
println!(
"{} adjacencies, now doing floodfilling to group them",
adj_counter
);
// Union-find might also be good inspiration.
fn floodfill(from: ParcelIdx, adj: &MultiMap<ParcelIdx, ParcelIdx>) -> BTreeSet<ParcelIdx> {
let mut visited: BTreeSet<ParcelIdx> = BTreeSet::new();
let mut queue: Vec<ParcelIdx> = vec![from];
while !queue.is_empty() {
let current = queue.pop().unwrap();
if visited.contains(&current) {
continue;
}
visited.insert(current);
for next in adj.get(current).iter() {
queue.push(*next);
}
}
visited
}
let mut block_per_parcel: Vec<Option<usize>> = Vec::new();
for _ in parcels.iter() {
block_per_parcel.push(None);
}
let mut block_counter = 0;
for base_idx in 0..parcels.len() {
// A previous iteration might have filled it out
if block_per_parcel[base_idx].is_some() {
continue;
}
let new_block = Some(block_counter);
block_counter += 1;
for idx in floodfill(base_idx, &adjacency).iter() {
assert!(!block_per_parcel[*idx].is_some());
block_per_parcel[*idx] = new_block;
}
}
println!(
"{} parcels grouped into {} blocks",
parcels.len(),
block_counter
);
for (idx, block) in block_per_parcel.iter().enumerate() {
parcels[idx].block = block.unwrap();
}
}
fn polygons_intersect(pts1: &Vec<LonLat>, pts2: &Vec<LonLat>) -> bool {
use geo::prelude::Intersects;
let poly1 = geo::Polygon::new(
pts1.iter()
.map(|pt| geo::Point::new(pt.longitude, pt.latitude))
.collect(),
Vec::new(),
);
let poly2 = geo::Polygon::new(
pts2.iter()
.map(|pt| geo::Point::new(pt.longitude, pt.latitude))
.collect(),
Vec::new(),
);
poly1.intersects(&poly2)
}
fn get_bbox(pts: &Vec<LonLat>) -> Rect {
GPSBounds::from(pts).as_bbox()
}

View File

@ -1,5 +1,4 @@
mod clip;
mod group_parcels;
mod neighborhoods;
mod osm;
mod remove_disconnected;
@ -38,10 +37,6 @@ pub struct Flags {
#[structopt(long = "residential_buildings", default_value = "")]
pub residential_buildings: String,
/// ExtraShapes file with parcels, produced using the kml crate. Optional.
#[structopt(long = "parcels", default_value = "")]
pub parcels: String,
/// ExtraShapes file with blockface, produced using the kml crate. Optional.
#[structopt(long = "parking_shapes", default_value = "")]
pub parking_shapes: String,
@ -62,7 +57,7 @@ pub struct Flags {
#[structopt(long = "output")]
pub output: String,
/// Disable parcels and blockface
/// Disable blockface
#[structopt(long = "fast_dev")]
pub fast_dev: bool,
}
@ -92,9 +87,6 @@ pub fn convert(flags: &Flags, timer: &mut abstutil::Timer) -> raw_data::Map {
if !flags.parking_shapes.is_empty() {
use_parking_hints(&mut map, &gps_bounds, &flags.parking_shapes, timer);
}
if !flags.parcels.is_empty() {
handle_parcels(&mut map, &gps_bounds, &flags.parcels, timer);
}
if !flags.traffic_signals.is_empty() {
handle_traffic_signals(&mut map, &gps_bounds, &flags.traffic_signals, timer);
}
@ -169,31 +161,6 @@ fn use_parking_hints(
timer.stop("apply parking hints");
}
fn handle_parcels(map: &mut raw_data::Map, gps_bounds: &GPSBounds, path: &str, timer: &mut Timer) {
timer.start("process parcels");
println!("Loading parcels from {}", path);
let parcels: ExtraShapes = abstutil::read_binary(path, timer).expect("loading parcels failed");
println!(
"Finding matching parcels from {} candidates",
parcels.shapes.len()
);
for p in parcels.shapes.into_iter() {
if p.points.len() > 1
&& p.points
.iter()
.find(|pt| !gps_bounds.contains(**pt))
.is_none()
{
map.parcels.push(raw_data::Parcel {
points: p.points,
block: 0,
});
}
}
group_parcels::group_parcels(gps_bounds, &mut map.parcels);
timer.stop("process parcels");
}
fn handle_traffic_signals(
map: &mut raw_data::Map,
gps_bounds: &GPSBounds,

View File

@ -9,7 +9,7 @@
- cars with headlights
- pumpkins
- fences / bushes / features in houses (maybe fences around parcel boundaries?) or triangulation on a block with buildings
- fences / bushes / features in houses or triangulation on a block with buildings
- buildings as rooms in a hotel
- silent hill soundtrack
= deformed buildings pulsing on front path springs

View File

@ -6,6 +6,32 @@ link to code
- explanation of intermediate formats
- autogenerate diagrams of the data schemas
- list invariants
- edits
## Features
demonstrate all of these things with before/after pictures or GIFs showing functionality
- Lanes
- show OSM way with metadata
- then multiple lane types, between two intersections. example with a curved road.
- individual parking spots modeled
- bus/bike lane restrictions modeled, with connecting turns that make sense (bus can go from restricted to general lane, but normal car cant enter a bus lane)
- Intersections
- OSM model doesn't explicitly have these at all; just ways with shared nodes
- they have geometry; cars and peds stop and wait at the end of a lane, then cross through the intersection
- crosswalks and sidewalk geometry continues
- turns connect lanes, the turns have a path. turns conflict or don't.
- stop signs (some directions stop and others dont), traffic signals with multiple phases
- "reasonable" defaults inferred, editor for the rest
- WIP: small intersections, roundabouts merged
- Buildings
- classified by use, notion of residential density
- front path connecting to a sidewalk
- Clipping / borders (WIP)
- clipping polygon actually chops all geometry to fit -- doesnt just omit things that cross or leave dangling OOB stuff
- cleans up areas (parks, bodies of water) nicely
- roads that cross the boundary have direction-aware 'border intersections' at the end, to model traffic flowing in or out of an area
## Model
@ -41,7 +67,6 @@ borders
Lane -> BusStop [label="contains"];
Intersection -> Turn [label="contains"];
Turn -> Lane [label="connects"];
Parcel;
BusRoute -> BusStop [label="connects"];
Area;
}
@ -51,7 +76,7 @@ borders
![Alt text](https://g.gravizo.com/svg? digraph G { Road -> Intersection
[label="connects two"]; Road -> Lane [label="contains"]; Lane -> Building
[label="link to"]; Lane -> BusStop [label="contains"]; Intersection -> Turn
[label="contains"]; Turn -> Lane [label="connects"]; Parcel; BusRoute -> BusStop
[label="contains"]; Turn -> Lane [label="connects"]; BusRoute -> BusStop
[label="connects"]; Area; } )
### Edits
@ -95,8 +120,6 @@ is the source of truth.
- Location of traffic signals
- https://github.com/seattleio/seattle-boundaries-data/raw/master/data/neighborhoods.geojson
- Neighborhood boundaries
- https://gis-kingcounty.opendata.arcgis.com/datasets/king-county-parcels--parcel-area/geoservice
- Parcel boundaries
- http://data-seattlecitygis.opendata.arcgis.com/datasets/blockface
- Blockfaces, used to determine where on-street parking lanes are
- https://data-seattlecitygis.opendata.arcgis.com/datasets/residential-building-permits-issued-and-final
@ -117,9 +140,6 @@ is the source of truth.
- calculate bounds
- use blockface KML to match parking categories to nearest road and side of the
road
- add in-bounds parcels
- group parcels based on intersection of their boundary, so an entire contiguous
block can be colored the same
- match traffic signals from KML to nearest intersection
- load raw bus routes from GTFS
- extract in-bounds neighborhoods from the GeoJSON
@ -153,7 +173,7 @@ is the source of truth.
phases
- override intersection defaults with player edits
- create all buildings, matching them to the nearest sidewalk with a front path
- copy over parcels and areas (like parks and bodies of water)
- copy over areas (like parks and bodies of water)
- filter out any bus routes with adjacent stops that fail pathfinding
## Conversion tricks

View File

@ -236,7 +236,6 @@ current TreeMenu:
- toggle extra KML shapes (7)
- toggle intersections (2)
- toggle lanes (3)
- toggle parcels (4)
- toggle turn icons (9)
- Validate map geometry (I)
- start searching for something to warp to (J)

View File

@ -142,7 +142,7 @@ the ID problem:
equality checks, dont use these IDs -- treat these IDs as memory addresses.
IDs for lookup and IDs for equality.
- what're the different things that need this?
- stable objects: building, intersection, parcel, road
- stable objects: building, intersection, road
- malleable
- lane (road, direction, offset, lane type)
- turn (src lane, dst lane)

View File

@ -21,7 +21,6 @@
- Intersection
- Building
- Parcel
- Road (undirected bundle)
- Driving/biking Lane (directed)
- Sidewalk (undirected)

View File

@ -3,9 +3,7 @@ use crate::render::{DrawMap, ExtraShapeID};
use ezgui::{Color, EventLoopMode, GfxCtx, Text};
use geom::Pt2D;
use map_model::raw_data::StableRoadID;
use map_model::{
AreaID, BuildingID, BusStopID, IntersectionID, LaneID, Map, ParcelID, RoadID, TurnID,
};
use map_model::{AreaID, BuildingID, BusStopID, IntersectionID, LaneID, Map, RoadID, TurnID};
use sim::{AgentID, CarID, GetDrawAgents, PedestrianID, Sim, TripID};
use std::collections::{BTreeMap, HashSet};
@ -19,7 +17,6 @@ pub enum ID {
Car(CarID),
Pedestrian(PedestrianID),
ExtraShape(ExtraShapeID),
Parcel(ParcelID),
BusStop(BusStopID),
Area(AreaID),
Trip(TripID),
@ -82,9 +79,6 @@ impl ID {
}
println!("associated road: {:?}", es.road);
}
ID::Parcel(id) => {
map.get_p(id).dump_debug();
}
ID::BusStop(id) => {
map.get_bs(id).dump_debug();
}
@ -193,9 +187,6 @@ impl ID {
ID::ExtraShape(id) => {
styled_kv(&mut txt, &draw_map.get_es(id).attributes);
}
ID::Parcel(id) => {
txt.add_line(id.to_string());
}
ID::BusStop(id) => {
txt.add_line(id.to_string());
for r in map.get_all_bus_routes() {
@ -227,7 +218,6 @@ impl ID {
ID::Pedestrian(id) => sim.get_draw_ped(id, map).map(|p| p.pos),
// TODO maybe_get_es
ID::ExtraShape(id) => Some(draw_map.get_es(id).center()),
ID::Parcel(id) => map.maybe_get_p(id).map(|p| Pt2D::center(&p.points)),
ID::BusStop(id) => map.maybe_get_bs(id).map(|bs| bs.sidewalk_pos.pt(map)),
ID::Area(id) => map.maybe_get_a(id).map(|a| a.polygon.center()),
ID::Trip(id) => sim.get_canonical_pt_per_trip(id, map),

View File

@ -37,9 +37,6 @@ impl Validator {
for b in map.all_buildings() {
objects.push((ID::Building(b.id), make_polys(&b.polygon)));
}
for p in &draw_map.parcels {
objects.push((ID::Parcel(p.id), make_polys(&p.fill_polygon)));
}
println!(
"{} objects total. About {} possible overlaps",
@ -57,12 +54,6 @@ impl Validator {
if id1 >= id2 {
continue;
}
// Buildings and parcels are expected to overlap.
match (id1, id2) {
(ID::Building(_), ID::Parcel(_)) => continue,
(ID::Parcel(_), ID::Building(_)) => continue,
_ => {}
};
'outer: for poly1 in ls1 {
for poly2 in ls2 {

View File

@ -47,7 +47,7 @@ fn hide_something(ctx: &mut PluginCtx) -> Option<ID> {
// No real use case for hiding moving stuff
Some(ID::Car(_)) | Some(ID::Pedestrian(_)) | None => None,
// Can't hide stuff drawn in a batch
Some(ID::Building(_)) | Some(ID::Road(_)) | Some(ID::Area(_)) | Some(ID::Parcel(_)) => None,
Some(ID::Building(_)) | Some(ID::Road(_)) | Some(ID::Area(_)) => None,
Some(id) => {
if ctx
.input

View File

@ -5,7 +5,6 @@ pub struct ToggleableLayers {
pub show_buildings: bool,
pub show_intersections: bool,
pub show_lanes: bool,
pub show_parcels: bool,
pub show_areas: bool,
pub show_extra_shapes: bool,
pub show_all_turn_icons: bool,
@ -18,7 +17,6 @@ impl ToggleableLayers {
show_buildings: true,
show_intersections: true,
show_lanes: true,
show_parcels: true,
show_areas: true,
show_extra_shapes: true,
show_all_turn_icons: false,
@ -32,7 +30,6 @@ impl ToggleableLayers {
ID::Road(_) | ID::Lane(_) => self.show_lanes,
ID::Building(_) => self.show_buildings,
ID::Intersection(_) => self.show_intersections,
ID::Parcel(_) => self.show_parcels,
ID::ExtraShape(_) => self.show_extra_shapes,
ID::Area(_) => self.show_areas,
_ => true,
@ -48,8 +45,6 @@ impl AmbientPlugin for ToggleableLayers {
self.show_intersections = !self.show_intersections;
} else if ctx.input.action_chosen("show/hide lanes") {
self.show_lanes = !self.show_lanes;
} else if ctx.input.action_chosen("show/hide parcels") {
self.show_parcels = !self.show_parcels;
} else if ctx.input.action_chosen("show/hide areas") {
self.show_areas = !self.show_areas;
} else if ctx.input.action_chosen("show/hide extra shapes") {

View File

@ -4,7 +4,7 @@ use crate::render::DrawMap;
use abstutil::elapsed_seconds;
use ezgui::{EventLoopMode, GfxCtx, InputResult, TextBox};
use geom::{Line, Pt2D};
use map_model::{raw_data, AreaID, BuildingID, IntersectionID, LaneID, Map, ParcelID, RoadID};
use map_model::{raw_data, AreaID, BuildingID, IntersectionID, LaneID, Map, RoadID};
use sim::{PedestrianID, Sim, TripID};
use std::time::Instant;
use std::usize;
@ -104,7 +104,6 @@ fn warp_point(line: String, map: &Map, sim: &Sim, draw_map: &DrawMap) -> Option<
'i' => ID::Intersection(IntersectionID(idx)),
'b' => ID::Building(BuildingID(idx)),
'a' => ID::Area(AreaID(idx)),
'P' => ID::Parcel(ParcelID(idx)),
'p' => ID::Pedestrian(PedestrianID(idx)),
'c' => {
// This one gets more complicated. :)

View File

@ -1,6 +1,6 @@
use crate::colors::ColorScheme;
use crate::objects::{DrawCtx, ID};
use crate::render::{RenderOptions, Renderable, BIG_ARROW_THICKNESS, PARCEL_BOUNDARY_THICKNESS};
use crate::render::{RenderOptions, Renderable, BIG_ARROW_THICKNESS};
use abstutil::Timer;
use ezgui::{Color, Drawable, GfxCtx, Prerender};
use geom::{Circle, Distance, Line, Polygon};
@ -75,7 +75,7 @@ impl DrawLane {
for l in ctx.map.get_l(self.id).lane_center_pts.lines() {
g.draw_line(
ctx.cs.get_def("debug line", Color::RED),
PARCEL_BOUNDARY_THICKNESS / 2.0,
Distance::meters(0.25),
&l,
);
g.draw_circle(circle_color, &Circle::new(l.pt1(), Distance::meters(0.4)));

View File

@ -6,7 +6,6 @@ use crate::render::bus_stop::DrawBusStop;
use crate::render::extra_shape::{DrawExtraShape, ExtraShapeID};
use crate::render::intersection::DrawIntersection;
use crate::render::lane::DrawLane;
use crate::render::parcel::DrawParcel;
use crate::render::road::DrawRoad;
use crate::render::turn::DrawTurn;
use crate::render::Renderable;
@ -16,8 +15,8 @@ use abstutil::Timer;
use ezgui::{Color, Drawable, Prerender};
use geom::{Bounds, Duration, FindClosest, Polygon};
use map_model::{
AreaID, BuildingID, BusStopID, DirectedRoadID, IntersectionID, Lane, LaneID, Map, ParcelID,
RoadID, Traversable, Turn, TurnID, LANE_THICKNESS,
AreaID, BuildingID, BusStopID, DirectedRoadID, IntersectionID, Lane, LaneID, Map, RoadID,
Traversable, Turn, TurnID, LANE_THICKNESS,
};
use std::borrow::Borrow;
use std::cell::RefCell;
@ -29,7 +28,6 @@ pub struct DrawMap {
pub intersections: Vec<DrawIntersection>,
pub turns: HashMap<TurnID, DrawTurn>,
pub buildings: Vec<DrawBuilding>,
pub parcels: Vec<DrawParcel>,
pub extra_shapes: Vec<DrawExtraShape>,
pub bus_stops: HashMap<BusStopID, DrawBusStop>,
pub areas: Vec<DrawArea>,
@ -42,7 +40,6 @@ pub struct DrawMap {
pub draw_all_unzoomed_intersections: Drawable,
pub draw_all_buildings: Drawable,
pub draw_all_areas: Drawable,
pub draw_all_parcels: Drawable,
quadtree: QuadTree<ID>,
}
@ -129,19 +126,6 @@ impl DrawMap {
}
let draw_all_buildings = prerender.upload(all_buildings);
let mut parcels: Vec<DrawParcel> = Vec::new();
let mut all_parcels: Vec<(Color, Polygon)> = Vec::new();
if flags.draw_parcels {
timer.start_iter("make DrawParcels", map.all_parcels().len());
for p in map.all_parcels() {
timer.next();
let (draw, geom) = DrawParcel::new(p, cs);
parcels.push(draw);
all_parcels.extend(geom);
}
}
let draw_all_parcels = prerender.upload(all_parcels);
let mut extra_shapes: Vec<DrawExtraShape> = Vec::new();
if let Some(ref path) = flags.kml {
let raw_shapes = if path.ends_with(".kml") {
@ -212,9 +196,6 @@ impl DrawMap {
for obj in &buildings {
quadtree.insert_with_box(obj.get_id(), obj.get_outline(map).get_bounds().as_bbox());
}
for obj in &parcels {
quadtree.insert_with_box(obj.get_id(), obj.get_outline(map).get_bounds().as_bbox());
}
for obj in &extra_shapes {
quadtree.insert_with_box(obj.get_id(), obj.get_outline(map).get_bounds().as_bbox());
}
@ -235,7 +216,6 @@ impl DrawMap {
intersections,
turns,
buildings,
parcels,
extra_shapes,
bus_stops,
areas,
@ -244,7 +224,6 @@ impl DrawMap {
draw_all_unzoomed_intersections,
draw_all_buildings,
draw_all_areas,
draw_all_parcels,
agents: RefCell::new(AgentCache {
time: None,
@ -297,10 +276,6 @@ impl DrawMap {
&self.buildings[id.0]
}
pub fn get_p(&self, id: ParcelID) -> &DrawParcel {
&self.parcels[id.0]
}
pub fn get_es(&self, id: ExtraShapeID) -> &DrawExtraShape {
&self.extra_shapes[id.0]
}

View File

@ -7,7 +7,6 @@ mod extra_shape;
mod intersection;
mod lane;
mod map;
mod parcel;
mod pedestrian;
mod road;
mod turn;
@ -31,7 +30,6 @@ use sim::{DrawCarInput, VehicleType};
pub const MIN_ZOOM_FOR_DETAIL: f64 = 1.0;
const PARCEL_BOUNDARY_THICKNESS: Distance = Distance::const_meters(0.5);
const EXTRA_SHAPE_THICKNESS: Distance = Distance::const_meters(1.0);
const EXTRA_SHAPE_POINT_RADIUS: Distance = Distance::const_meters(1.0);

View File

@ -1,75 +0,0 @@
use crate::colors::ColorScheme;
use crate::objects::{DrawCtx, ID};
use crate::render::{RenderOptions, Renderable, PARCEL_BOUNDARY_THICKNESS};
use ezgui::{Color, GfxCtx};
use geom::{PolyLine, Polygon};
use map_model::{Map, Parcel, ParcelID};
const COLORS: [Color; 14] = [
// TODO these are awful choices
Color::rgba_f(1.0, 1.0, 0.0, 1.0),
Color::rgba_f(1.0, 0.0, 1.0, 1.0),
Color::rgba_f(0.0, 1.0, 1.0, 1.0),
Color::rgba_f(0.5, 0.2, 0.7, 1.0),
Color::rgba_f(0.5, 0.5, 0.0, 0.5),
Color::rgba_f(0.5, 0.0, 0.5, 0.5),
Color::rgba_f(0.0, 0.5, 0.5, 0.5),
Color::rgba_f(0.0, 0.0, 0.5, 0.5),
Color::rgba_f(0.3, 0.2, 0.5, 0.5),
Color::rgba_f(0.4, 0.2, 0.5, 0.5),
Color::rgba_f(0.5, 0.2, 0.5, 0.5),
Color::rgba_f(0.6, 0.2, 0.5, 0.5),
Color::rgba_f(0.7, 0.2, 0.5, 0.5),
Color::rgba_f(0.8, 0.2, 0.5, 0.5),
];
pub struct DrawParcel {
pub id: ParcelID,
// TODO could maybe get away with not storing these at all, since we can't select them. might
// totally get rid of parcels, since use case is low... keep for now
boundary_polygon: Polygon,
pub fill_polygon: Polygon,
}
impl DrawParcel {
pub fn new(p: &Parcel, cs: &ColorScheme) -> (DrawParcel, Vec<(Color, Polygon)>) {
let boundary_polygon =
PolyLine::make_polygons_for_boundary(p.points.clone(), PARCEL_BOUNDARY_THICKNESS);
let fill_polygon = Polygon::new(&p.points);
let default_draw = vec![
(COLORS[p.block % COLORS.len()], fill_polygon.clone()),
(
cs.get_def("parcel boundary", Color::grey(0.3)),
boundary_polygon.clone(),
),
];
(
DrawParcel {
id: p.id,
boundary_polygon,
fill_polygon,
},
default_draw,
)
}
}
impl Renderable for DrawParcel {
fn get_id(&self) -> ID {
ID::Parcel(self.id)
}
fn draw(&self, g: &mut GfxCtx, opts: RenderOptions, ctx: &DrawCtx) {
if let Some(color) = opts.color {
g.draw_polygon_batch(vec![
(color, &self.fill_polygon),
(ctx.cs.get("parcel boundary"), &self.boundary_polygon),
]);
}
}
fn get_outline(&self, _: &Map) -> Polygon {
self.fill_polygon.clone()
}
}

View File

@ -24,10 +24,6 @@ pub struct Flags {
#[structopt(long = "kml")]
pub kml: Option<String>,
/// Should parcels be drawn? They're slow and not so useful.
#[structopt(long = "draw_parcels")]
pub draw_parcels: bool,
// TODO Ideally these'd be phrased positively, but can't easily make them default to true.
/// Should lane markings be drawn? Sometimes they eat too much GPU memory.
#[structopt(long = "dont_draw_lane_markings")]

View File

@ -36,7 +36,6 @@ impl<S: UIState> GUI<RenderingHints> for UI<S> {
(Some(Key::Num1), "show/hide buildings"),
(Some(Key::Num2), "show/hide intersections"),
(Some(Key::Num3), "show/hide lanes"),
(Some(Key::Num4), "show/hide parcels"),
(Some(Key::Num5), "show/hide areas"),
(Some(Key::Num6), "show OSM colors"),
(Some(Key::Num7), "show/hide extra shapes"),
@ -288,9 +287,6 @@ impl<S: UIState> GUI<RenderingHints> for UI<S> {
if state.layers.show_areas {
g.redraw(&state.primary.draw_map.draw_all_areas);
}
if state.layers.show_parcels {
g.redraw(&state.primary.draw_map.draw_all_parcels);
}
if state.layers.show_lanes {
g.redraw(&state.primary.draw_map.draw_all_thick_roads);
}
@ -319,7 +315,6 @@ impl<S: UIState> GUI<RenderingHints> for UI<S> {
let mut drawn_all_buildings = false;
let mut drawn_all_areas = false;
let mut drawn_all_parcels = false;
for obj in objects {
match obj.get_id() {
@ -335,12 +330,6 @@ impl<S: UIState> GUI<RenderingHints> for UI<S> {
drawn_all_areas = true;
}
}
ID::Parcel(_) => {
if !drawn_all_parcels {
g.redraw(&state.primary.draw_map.draw_all_parcels);
drawn_all_parcels = true;
}
}
_ => {}
};
let opts = RenderOptions {
@ -459,11 +448,10 @@ impl<S: UIState> UI<S> {
let debug_areas = self.state.get_state().primary.current_flags.debug_areas;
for obj in objects {
// Don't mouseover parcels or areas.
// Don't mouseover areas.
// TODO Might get fancier rules in the future, so we can't mouseover irrelevant things
// in intersection editor mode, for example.
match obj.get_id() {
ID::Parcel(_) => {}
ID::Area(_) if !debug_areas => {}
// Thick roads are only shown when unzoomed, when we don't mouseover at all.
ID::Road(_) => {}
@ -505,7 +493,6 @@ impl<S: UIState> UI<S> {
let draw_map = &state.primary.draw_map;
let mut areas: Vec<Box<&Renderable>> = Vec::new();
let mut parcels: Vec<Box<&Renderable>> = Vec::new();
let mut lanes: Vec<Box<&Renderable>> = Vec::new();
let mut roads: Vec<Box<&Renderable>> = Vec::new();
let mut intersections: Vec<Box<&Renderable>> = Vec::new();
@ -521,7 +508,6 @@ impl<S: UIState> UI<S> {
}
match id {
ID::Area(id) => areas.push(Box::new(draw_map.get_a(id))),
ID::Parcel(id) => parcels.push(Box::new(draw_map.get_p(id))),
ID::Lane(id) => {
lanes.push(Box::new(draw_map.get_l(id)));
let lane = map.get_l(id);
@ -563,7 +549,6 @@ impl<S: UIState> UI<S> {
// From background to foreground Z-order
let mut borrows: Vec<Box<&Renderable>> = Vec::new();
borrows.extend(areas);
borrows.extend(parcels);
borrows.extend(lanes);
borrows.extend(roads);
borrows.extend(intersections);

View File

@ -67,17 +67,6 @@ for poly in `ls data/polygons/`; do
fi
done
if [ ! -f data/shapes/parcels ]; then
# From https://gis-kingcounty.opendata.arcgis.com/datasets/king-county-parcels--parcel-area/geoservice
get_if_needed https://opendata.arcgis.com/datasets/8058a0c540434dadbe3ea0ade6565143_439.kml data/input/King_County_Parcels__parcel_area.kml;
cd kml
time cargo run --release -- \
--input=../data/input/King_County_Parcels__parcel_area.kml \
--output=../data/shapes/parcels
cd ..
fi
if [ ! -f data/shapes/blockface ]; then
# From http://data-seattlecitygis.opendata.arcgis.com/datasets/blockface
get_if_needed https://opendata.arcgis.com/datasets/a1458ad1abca41869b81f7c0db0cd777_0.kml data/input/blockface.kml;
@ -98,7 +87,6 @@ for poly in `ls ../data/polygons/`; do
--elevation=../data/input/N47W122.hgt \
--traffic_signals=../data/input/traffic_signals.kml \
--residential_buildings=../data/input/residential_buildings.kml \
--parcels=../data/shapes/parcels \
--parking_shapes=../data/shapes/blockface \
--gtfs=../data/input/google_transit_2018_18_08 \
--neighborhoods=../data/input/neighborhoods.geojson \
@ -106,4 +94,4 @@ for poly in `ls ../data/polygons/`; do
--output=../data/raw_maps/$name.abst
done
# To run manually: cargo run -- --osm=../data/input/montlake.osm --elevation=../data/input/N47W122.hgt --traffic_signals=../data/input/traffic_signals.kml --residential_buildings=../data/input/residential_buildings.kml --parcels=../data/shapes/parcels --parking_shapes=../data/shapes/blockface --gtfs=../data/input/google_transit_2018_18_08 --neighborhoods=../data/input/neighborhoods.geojson --clip=../data/polygons/montlake.poly --output=../data/raw_maps/montlake.abst --fast_dev
# To run manually: cargo run -- --osm=../data/input/montlake.osm --elevation=../data/input/N47W122.hgt --traffic_signals=../data/input/traffic_signals.kml --residential_buildings=../data/input/residential_buildings.kml --parking_shapes=../data/shapes/blockface --gtfs=../data/input/google_transit_2018_18_08 --neighborhoods=../data/input/neighborhoods.geojson --clip=../data/polygons/montlake.poly --output=../data/raw_maps/montlake.abst --fast_dev

View File

@ -7,7 +7,6 @@ mod lane;
mod make;
mod map;
mod neighborhood;
mod parcel;
mod pathfind;
pub mod raw_data;
mod road;
@ -25,7 +24,6 @@ pub use crate::lane::{Lane, LaneID, LaneType, PARKING_SPOT_LENGTH};
pub use crate::make::RoadSpec;
pub use crate::map::Map;
pub use crate::neighborhood::{FullNeighborhoodInfo, Neighborhood, NeighborhoodBuilder};
pub use crate::parcel::{Parcel, ParcelID};
pub use crate::pathfind::{Path, PathRequest, PathStep};
pub use crate::road::{DirectedRoadID, Road, RoadID};
pub use crate::stop_signs::ControlStopSign;

View File

@ -1,6 +1,6 @@
use crate::{
make, raw_data, Area, AreaID, Building, Intersection, IntersectionID, IntersectionType, Lane,
LaneID, Parcel, Road, RoadID, Turn, TurnID, LANE_THICKNESS,
LaneID, Road, RoadID, Turn, TurnID, LANE_THICKNESS,
};
use abstutil::Timer;
use geom::{Bounds, GPSBounds, Polygon, Pt2D};
@ -12,7 +12,6 @@ pub struct HalfMap {
pub intersections: Vec<Intersection>,
pub turns: BTreeMap<TurnID, Turn>,
pub buildings: Vec<Building>,
pub parcels: Vec<Parcel>,
pub areas: Vec<Area>,
pub turn_lookup: Vec<TurnID>,
@ -31,7 +30,6 @@ pub fn make_half_map(
intersections: Vec::new(),
turns: BTreeMap::new(),
buildings: Vec::new(),
parcels: Vec::new(),
areas: Vec::new(),
turn_lookup: Vec::new(),
};
@ -175,15 +173,6 @@ pub fn make_half_map(
half_map.lanes[lane.0].building_paths = bldgs;
}
make::make_all_parcels(
&mut half_map.parcels,
&data.parcels,
&gps_bounds,
&bounds,
&half_map.lanes,
timer,
);
for (idx, a) in data.areas.iter().enumerate() {
let pts = gps_bounds.must_convert(&a.points);
if pts[0] != *pts.last().unwrap() {

View File

@ -2,7 +2,6 @@ mod buildings;
mod bus_stops;
mod half_map;
mod initial;
mod parcels;
mod sidewalk_finder;
mod turns;
@ -11,5 +10,4 @@ pub use self::bus_stops::{make_bus_stops, verify_bus_routes};
pub use self::half_map::make_half_map;
pub use self::initial::lane_specs::{get_lane_types, RoadSpec};
pub use self::initial::InitialMap;
pub use self::parcels::make_all_parcels;
pub use self::turns::make_all_turns;

View File

@ -1,48 +0,0 @@
use crate::make::sidewalk_finder::find_sidewalk_points;
use crate::{raw_data, Lane, Parcel, ParcelID};
use abstutil::Timer;
use geom::{Bounds, Distance, GPSBounds, HashablePt2D, Pt2D};
use std::collections::HashSet;
pub fn make_all_parcels(
results: &mut Vec<Parcel>,
input: &Vec<raw_data::Parcel>,
gps_bounds: &GPSBounds,
bounds: &Bounds,
lanes: &Vec<Lane>,
timer: &mut Timer,
) {
timer.start("convert parcels");
let mut pts_per_parcel: Vec<Vec<Pt2D>> = Vec::new();
let mut center_per_parcel: Vec<HashablePt2D> = Vec::new();
let mut query: HashSet<HashablePt2D> = HashSet::new();
for p in input {
let pts = Pt2D::approx_dedupe(gps_bounds.must_convert(&p.points), geom::EPSILON_DIST);
let center: HashablePt2D = Pt2D::center(&pts).into();
pts_per_parcel.push(pts);
center_per_parcel.push(center);
query.insert(center);
}
// Trim parcels that are too far away from the nearest sidewalk
let sidewalk_pts = find_sidewalk_points(bounds, query, lanes, Distance::meters(100.0), timer);
for (idx, center) in center_per_parcel.into_iter().enumerate() {
if sidewalk_pts.contains_key(&center) {
let id = ParcelID(results.len());
results.push(Parcel {
id,
points: pts_per_parcel[idx].clone(),
block: input[idx].block,
});
}
}
let discarded = input.len() - results.len();
if discarded > 0 {
timer.note(format!(
"Discarded {} parcels that weren't close enough to a sidewalk",
discarded
));
}
timer.stop("convert parcels");
}

View File

@ -3,8 +3,8 @@ use crate::pathfind::Pathfinder;
use crate::{
make, raw_data, Area, AreaID, Building, BuildingID, BusRoute, BusRouteID, BusStop, BusStopID,
ControlStopSign, ControlTrafficSignal, Intersection, IntersectionID, IntersectionType, Lane,
LaneID, LaneType, MapEdits, Parcel, ParcelID, Path, PathRequest, Position, Road, RoadID, Turn,
TurnID, TurnPriority,
LaneID, LaneType, MapEdits, Path, PathRequest, Position, Road, RoadID, Turn, TurnID,
TurnPriority,
};
use abstutil;
use abstutil::{deserialize_btreemap, serialize_btreemap, Error, Timer};
@ -25,7 +25,6 @@ pub struct Map {
)]
turns: BTreeMap<TurnID, Turn>,
buildings: Vec<Building>,
parcels: Vec<Parcel>,
#[serde(
serialize_with = "serialize_btreemap",
deserialize_with = "deserialize_btreemap"
@ -83,7 +82,6 @@ impl Map {
intersections: half_map.intersections,
turns: half_map.turns,
buildings: half_map.buildings,
parcels: half_map.parcels,
bus_stops: BTreeMap::new(),
bus_routes: Vec::new(),
areas: half_map.areas,
@ -154,10 +152,6 @@ impl Map {
&self.buildings
}
pub fn all_parcels(&self) -> &Vec<Parcel> {
&self.parcels
}
pub fn all_areas(&self) -> &Vec<Area> {
&self.areas
}
@ -182,10 +176,6 @@ impl Map {
self.buildings.get(id.0)
}
pub fn maybe_get_p(&self, id: ParcelID) -> Option<&Parcel> {
self.parcels.get(id.0)
}
pub fn maybe_get_a(&self, id: AreaID) -> Option<&Area> {
self.areas.get(id.0)
}
@ -222,10 +212,6 @@ impl Map {
&self.buildings[id.0]
}
pub fn get_p(&self, id: ParcelID) -> &Parcel {
&self.parcels[id.0]
}
pub fn get_a(&self, id: AreaID) -> &Area {
&self.areas[id.0]
}

View File

@ -1,29 +0,0 @@
use abstutil;
use geom::{PolyLine, Pt2D};
use serde_derive::{Deserialize, Serialize};
use std::fmt;
// TODO reconsider pub usize. maybe outside world shouldnt know.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ParcelID(pub usize);
impl fmt::Display for ParcelID {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ParcelID({0})", self.0)
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Parcel {
pub id: ParcelID,
pub points: Vec<Pt2D>,
// All parcels of the same block have the same number.
pub block: usize,
}
impl Parcel {
pub fn dump_debug(&self) {
println!("{}", abstutil::to_json(self));
println!("{}", PolyLine::new(self.points.clone()));
}
}

View File

@ -30,7 +30,6 @@ pub struct Map {
pub roads: BTreeMap<StableRoadID, Road>,
pub intersections: BTreeMap<StableIntersectionID, Intersection>,
pub buildings: Vec<Building>,
pub parcels: Vec<Parcel>,
pub bus_routes: Vec<Route>,
pub areas: Vec<Area>,
@ -44,7 +43,6 @@ impl Map {
roads: BTreeMap::new(),
intersections: BTreeMap::new(),
buildings: Vec::new(),
parcels: Vec::new(),
bus_routes: Vec::new(),
areas: Vec::new(),
boundary_polygon: Vec::new(),
@ -73,11 +71,6 @@ impl Map {
bounds.update(*pt);
}
}
for p in &self.parcels {
for pt in &p.points {
bounds.update(*pt);
}
}
for pt in &self.boundary_polygon {
bounds.update(*pt);
}
@ -136,11 +129,3 @@ pub struct Area {
pub osm_tags: BTreeMap<String, String>,
pub osm_id: i64,
}
#[derive(PartialEq, Debug, Serialize, Deserialize)]
pub struct Parcel {
// last point never the first?
pub points: Vec<LonLat>,
// TODO decide what metadata from the shapefile is useful
pub block: usize,
}

View File

@ -14,6 +14,15 @@ done
mkdir -p data/maps/
# Re-export all synthetic maps from scratch. Do this before the other loop,
# since the raw_map might be stale.
cd precompute;
for path in `ls ../data/synthetic_maps/*`; do
RUST_BACKTRACE=1 cargo run $release_mode $path;
done
cd ..;
for map_path in `ls data/raw_maps/`; do
map=`basename $map_path .abst`;
echo "Precomputing $map";
@ -21,9 +30,3 @@ for map_path in `ls data/raw_maps/`; do
RUST_BACKTRACE=1 cargo run $release_mode ../data/raw_maps/$map.abst;
cd ..;
done
# Re-export all synthetic maps from scratch.
cd precompute;
for path in `ls ../data/synthetic_maps/*`; do
RUST_BACKTRACE=1 cargo run $release_mode $path;
done

View File

@ -10,7 +10,6 @@ pub fn run(t: &mut TestRunner) {
elevation: "../data/input/N47W122.hgt".to_string(),
traffic_signals: "../data/input/traffic_signals.kml".to_string(),
residential_buildings: "../data/input/residential_buildings.kml".to_string(),
parcels: "../data/shapes/parcels".to_string(),
parking_shapes: "../data/shapes/blockface".to_string(),
gtfs: "../data/input/google_transit_2018_18_08".to_string(),
neighborhoods: "../data/input/neighborhoods.geojson".to_string(),