mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 01:15:12 +03:00
WIP load gtfs
This commit is contained in:
parent
c5c00d5740
commit
1d732c5a3b
15
Cargo.toml
15
Cargo.toml
@ -1,3 +1,16 @@
|
||||
[workspace]
|
||||
|
||||
members = ["abstutil", "analyze_code", "control", "convert_osm", "editor", "ezgui", "geom", "headless", "kml", "map_model", "sim"]
|
||||
members = [
|
||||
"abstutil",
|
||||
"analyze_code",
|
||||
"control",
|
||||
"convert_osm",
|
||||
"editor",
|
||||
"ezgui",
|
||||
"geom",
|
||||
"gtfs",
|
||||
"headless",
|
||||
"kml",
|
||||
"map_model",
|
||||
"sim",
|
||||
]
|
||||
|
@ -547,6 +547,7 @@ Options:
|
||||
- can we compare results with the prev float approach? make them store the
|
||||
other thing, compare results? or compare the results of a sim?
|
||||
- is it possible to do this change gradually? unlikely...
|
||||
- stick all the types in geom, for now
|
||||
|
||||
|
||||
- moment in time (tick)
|
||||
|
9
gtfs/Cargo.toml
Normal file
9
gtfs/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "gtfs"
|
||||
version = "0.1.0"
|
||||
authors = ["Dustin Carlino <dabreegster@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
csv = "1.0.1"
|
||||
failure = "0.1.2"
|
||||
geom = { path = "../geom" }
|
87
gtfs/src/lib.rs
Normal file
87
gtfs/src/lib.rs
Normal file
@ -0,0 +1,87 @@
|
||||
extern crate csv;
|
||||
extern crate failure;
|
||||
extern crate geom;
|
||||
|
||||
use failure::Error;
|
||||
use geom::LonLat;
|
||||
use std::collections::{HashSet, HashMap};
|
||||
use std::fs::File;
|
||||
use std::time::Instant;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Route {
|
||||
name: String,
|
||||
stops: Vec<LonLat>,
|
||||
}
|
||||
|
||||
pub fn load(dir_path: &str) -> Result<Vec<Route>, Error> {
|
||||
println!("Loading GTFS from {}", dir_path);
|
||||
let timer = Instant::now();
|
||||
|
||||
let mut route_id_to_name: HashMap<String, String> = HashMap::new();
|
||||
for rec in csv::Reader::from_reader(File::open(format!("{}/routes.txt", dir_path))?).records() {
|
||||
let rec = rec?;
|
||||
route_id_to_name.insert(rec[0].to_string(), rec[2].to_string());
|
||||
}
|
||||
|
||||
let mut stop_id_to_pt: HashMap<String, LonLat> = HashMap::new();
|
||||
for rec in csv::Reader::from_reader(File::open(format!("{}/stops.txt", dir_path))?).records() {
|
||||
let rec = rec?;
|
||||
let lon: f64 = rec[5].parse()?;
|
||||
let lat: f64 = rec[4].parse()?;
|
||||
stop_id_to_pt.insert(rec[0].to_string(), LonLat::new(lon, lat));
|
||||
}
|
||||
|
||||
let mut trip_id_to_route_id: HashMap<String, String> = HashMap::new();
|
||||
for rec in csv::Reader::from_reader(File::open(format!("{}/trips.txt", dir_path))?).records() {
|
||||
let rec = rec?;
|
||||
trip_id_to_route_id.insert(rec[2].to_string(), rec[0].to_string());
|
||||
}
|
||||
|
||||
// Each route has many trips. Ignore all but the first and assume the list of stops is the
|
||||
// same.
|
||||
let mut route_ids_used: HashSet<String> = HashSet::new();
|
||||
let mut result: Vec<Route> = Vec::new();
|
||||
let mut current_trip_id: Option<String> = None;
|
||||
let mut current_stop_ids: Vec<String> = Vec::new();
|
||||
for rec in csv::Reader::from_reader(File::open(format!("{}/stop_times.txt", dir_path))?).records() {
|
||||
let rec = rec?;
|
||||
// Assume the records are contiguous -- records for one trip are contiguous and sorted by
|
||||
// stop_sequence already.
|
||||
if let Some(trip) = current_trip_id.clone() {
|
||||
if rec[0].to_string() == *trip {
|
||||
current_stop_ids.push(rec[3].to_string());
|
||||
} else {
|
||||
// Save the current route?
|
||||
let route_id = trip_id_to_route_id[&rec[0]].clone();
|
||||
if !route_ids_used.contains(&route_id) {
|
||||
result.push(Route {
|
||||
name: route_id_to_name[&route_id].clone(),
|
||||
stops: current_stop_ids.iter().map(|stop_id| stop_id_to_pt[stop_id]).collect(),
|
||||
});
|
||||
route_ids_used.insert(route_id);
|
||||
}
|
||||
|
||||
// Reset for the next trip
|
||||
current_trip_id = Some(rec[0].to_string());
|
||||
current_stop_ids = vec![rec[3].to_string()];
|
||||
}
|
||||
} else {
|
||||
current_trip_id = Some(rec[0].to_string());
|
||||
current_stop_ids.push(rec[3].to_string());
|
||||
}
|
||||
}
|
||||
// Handle the last one. TODO duplicates saving code :(
|
||||
let last_route_id = trip_id_to_route_id[¤t_trip_id.unwrap()].clone();
|
||||
if !route_ids_used.contains(&last_route_id) {
|
||||
result.push(Route {
|
||||
name: route_id_to_name[&last_route_id].clone(),
|
||||
stops: current_stop_ids.iter().map(|stop_id| stop_id_to_pt[stop_id]).collect(),
|
||||
});
|
||||
}
|
||||
|
||||
let elapsed = timer.elapsed();
|
||||
let dt = elapsed.as_secs() as f64 + f64::from(elapsed.subsec_nanos()) * 1e-9;
|
||||
println!("Loading GTFS took {}s", dt);
|
||||
Ok(result)
|
||||
}
|
@ -11,6 +11,7 @@ mkdir -p data/input
|
||||
# https://dds.cr.usgs.gov/srtm/version2_1/SRTM1/Region_01/N47W122.hgt.zip
|
||||
# https://data.seattle.gov/api/views/77ms-czxg/rows.json?accessType=DOWNLOAD
|
||||
# Seattle bounding box is -b=-122.4416,47.5793,-122.2421,47.7155
|
||||
# https://metro.kingcounty.gov/GTFS/google_transit_2018_18_08.zip
|
||||
|
||||
ELEVATION=../data/input/N47W122.hgt
|
||||
PARCELS_KML=../data/input/King_County_Parcels__parcel_area.kml
|
||||
|
@ -12,6 +12,7 @@ dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa
|
||||
ezgui = { path = "../ezgui" }
|
||||
failure = "0.1.2"
|
||||
geom = { path = "../geom" }
|
||||
gtfs = { path = "../gtfs" }
|
||||
lazy_static = "1.1.0"
|
||||
map_model = { path = "../map_model" }
|
||||
more-asserts = "0.2.1"
|
||||
|
@ -1,4 +1,5 @@
|
||||
use abstutil;
|
||||
use gtfs;
|
||||
use control::ControlMap;
|
||||
use map_model::{BuildingID, BusStop, Edits, LaneID, Map};
|
||||
use rand::Rng;
|
||||
@ -12,8 +13,12 @@ pub fn load(
|
||||
rng_seed: Option<u8>,
|
||||
savestate_every: Option<Tick>,
|
||||
) -> (Map, Edits, ControlMap, Sim) {
|
||||
// Hardcoded files for road edits and transit data.
|
||||
let edits: Edits = abstutil::read_json("road_edits.json").unwrap_or(Edits::new());
|
||||
|
||||
gtfs::load("../data/input/google_transit_2018_18_08").unwrap();
|
||||
|
||||
|
||||
if input.contains("data/save/") {
|
||||
println!("Resuming from {}", input);
|
||||
let sim: Sim = abstutil::read_json(&input).expect("loading sim state failed");
|
||||
|
@ -11,6 +11,7 @@ extern crate ezgui;
|
||||
extern crate failure;
|
||||
extern crate geom;
|
||||
extern crate graphics;
|
||||
extern crate gtfs;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate map_model;
|
||||
|
0
test_all.sh
Normal file → Executable file
0
test_all.sh
Normal file → Executable file
Loading…
Reference in New Issue
Block a user