mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 23:15:24 +03:00
parsing shapefiles again for traffic signals
This commit is contained in:
parent
22b1e70707
commit
51fa14d934
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>,
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
),
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user