parsing shapefiles again for traffic signals

This commit is contained in:
Dustin Carlino 2018-07-20 10:19:20 -07:00
parent 22b1e70707
commit 51fa14d934
7 changed files with 64 additions and 37 deletions

View File

@ -10,4 +10,5 @@ geom = { path = "../geom" }
ordered-float = "0.5.0"
osm-xml = "0.5.1"
map_model = { path = "../map_model" }
shp = "0.1.1"
structopt = "0.2"

View File

@ -6,6 +6,7 @@ extern crate geom;
extern crate map_model;
extern crate ordered_float;
extern crate osm_xml;
extern crate shp;
#[macro_use]
extern crate structopt;
@ -67,32 +68,26 @@ fn main() {
}
}
for s in
for coord in
&traffic_signals::extract(&flags.traffic_signals).expect("loading traffic signals failed")
{
// Treat each point associated with the signal as a separate intersection. Later, we can
// use this to treat multiple adjacent intersections as one logical intersection.
for pt in &s.intersections {
if bounds.contains(pt.x(), pt.y()) {
let distance = |i: &raw_data::Intersection| {
// TODO weird to use Pt2D at all for GPS, uh oh
LonLat::new(pt.x(), pt.y())
.gps_dist_meters(LonLat::new(i.point.longitude, i.point.latitude))
};
if bounds.contains(coord.longitude, coord.latitude) {
let distance = |i: &raw_data::Intersection| {
coord.gps_dist_meters(LonLat::new(i.point.longitude, i.point.latitude))
};
// TODO use a quadtree or some better way to match signals to the closest
// intersection
let closest_intersection = map.intersections
.iter_mut()
.min_by_key(|i| NotNaN::new(distance(i)).unwrap())
.unwrap();
let dist = distance(closest_intersection);
if dist <= MAX_METERS_BTWN_INTERSECTION_AND_SIGNAL {
if closest_intersection.has_traffic_signal {
println!("WARNING: {:?} already has a traffic signal, but there's another one that's {} from it", closest_intersection, dist);
}
closest_intersection.has_traffic_signal = true;
// TODO use a quadtree or some better way to match signals to the closest
// intersection
let closest_intersection = map.intersections
.iter_mut()
.min_by_key(|i| NotNaN::new(distance(i)).unwrap())
.unwrap();
let dist = distance(closest_intersection);
if dist <= MAX_METERS_BTWN_INTERSECTION_AND_SIGNAL {
if closest_intersection.has_traffic_signal {
println!("WARNING: {:?} already has a traffic signal, but there's another one that's {} from it", closest_intersection, dist);
}
closest_intersection.has_traffic_signal = true;
}
}
}

View File

@ -1,15 +1,45 @@
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
use geom::Pt2D;
use geom::LonLat;
use shp;
use std;
use std::io::Error;
pub struct TrafficSignal {
// One signal may cover several intersections that're close together.
pub intersections: Vec<Pt2D>,
// Returns the location of traffic signals
pub fn extract(path: &str) -> Result<Vec<LonLat>, Error> {
println!("Opening {}", path);
let reader = shp::ShpReader::open(path)?;
let file = reader.read();
let mut result: Vec<LonLat> = Vec::new();
for r in &file.records {
if let shp::ShpRecordContent::MultiPoint(ref raw_shape) = r.content {
// The shp crate doesn't expose the struct fields as public. Send a PR later, do this
// workaround for now.
let shape = unsafe {
std::mem::transmute::<&shp::MultiPointShape, &MultiPointShape>(raw_shape)
};
// Some intersections have multiple points, which shows complicated intersections. For
// now, don't handle these.
result.push(LonLat::new(shape.points[0].x, shape.points[0].y));
} else {
println!("Unexpected shp record: {:?}", r.content);
}
}
Ok(result)
}
pub fn extract(path: &str) -> Result<Vec<TrafficSignal>, Error> {
println!("Opening {}", path);
// TODO Read the .shp
Ok(Vec::new())
struct PointShape {
x: f64,
y: f64,
}
struct MultiPointShape {
_xmin: f64,
_xmax: f64,
_ymin: f64,
_ymax: f64,
_num_points: i32,
points: Vec<PointShape>,
}

View File

@ -20,7 +20,6 @@
- draw benches, bike racks
- more generally, a way to display random GIS data from seattle site (kml)
- render trees
- parse shp, get traffic signals in the right places
- do need to mouseover shapefile things and see full data
- grab number of phases from traffic signal shp
- look for current stop sign priorities

View File

@ -122,8 +122,12 @@ impl DrawRoad {
let r = map.get_r(self.id);
let mut lines = vec![
format!(
"Road #{:?} (from OSM way {}) has {} polygons",
self.id,
"{} is {}",
r.id,
r.osm_tags.get("name").unwrap_or(&"???".to_string())
),
format!(
"From OSM way {}, with {} polygons",
r.osm_way_id,
self.polygons.len()
),

View File

@ -14,7 +14,7 @@ mkdir -p data/input
ELEVATION=../data/input/N47W122.hgt
PARCELS_KML=../data/input/King_County_Parcels__parcel_area.kml
TRAFFIC_SIGNALS=../data/inputTrafficSignals.shp
TRAFFIC_SIGNALS=../data/input/TrafficSignals.shp
SMALL_OSM=../data/input/tiny_montlake.osm
MEDIUM_OSM=../data/input/montlake.osm

View File

@ -49,9 +49,7 @@ impl Map {
point: pt,
turns: Vec::new(),
elevation: i.elevation_meters * si::M,
// TODO use the data again!
//has_traffic_signal: i.get_has_traffic_signal(),
has_traffic_signal: idx % 2 == 0,
has_traffic_signal: i.has_traffic_signal,
incoming_roads: Vec::new(),
outgoing_roads: Vec::new(),
});