switched to my own CLI parsing in convert_osm, away from structopt. compilation time down from 6.7s to 4.5s, and parsing is more clear now!

This commit is contained in:
Dustin Carlino 2019-09-18 16:37:22 -07:00
parent fac8d4d9ff
commit dd02010614
7 changed files with 105 additions and 55 deletions

63
abstutil/src/cli.rs Normal file
View File

@ -0,0 +1,63 @@
use std::collections::{HashMap, HashSet};
pub struct CmdArgs {
kv: HashMap<String, String>,
bits: HashSet<String>,
free: Vec<String>,
}
impl CmdArgs {
pub fn new() -> CmdArgs {
let mut args = CmdArgs {
kv: HashMap::new(),
bits: HashSet::new(),
free: Vec::new(),
};
for arg in std::env::args().skip(1) {
let parts: Vec<&str> = arg.split('=').collect();
if parts.len() == 1 {
if arg.starts_with("--") {
args.bits.insert(arg[2..].to_string());
} else {
args.free.push(arg);
}
} else if parts.len() == 2 {
args.kv.insert(parts[0].to_string(), parts[1].to_string());
} else {
panic!("Weird argument {}", arg);
}
}
args
}
pub fn required(&mut self, key: &str) -> String {
if let Some(value) = self.kv.remove(key) {
value
} else {
panic!("Missing required arg {}", key);
}
}
pub fn optional(&mut self, key: &str) -> Option<String> {
self.kv.remove(key)
}
pub fn enabled(&mut self, key: &str) -> bool {
self.bits.remove(key)
}
// TODO Drop?
pub fn done(&mut self) {
if !self.kv.is_empty() {
panic!("Unused arguments: {:?}", self.kv);
}
if !self.bits.is_empty() {
panic!("Unused arguments: {:?}", self.bits);
}
if !self.free.is_empty() {
panic!("Unused free arguments: {:?}", self.free);
}
}
}

View File

@ -1,3 +1,4 @@
mod cli;
mod clone;
mod collections;
mod error;
@ -6,6 +7,7 @@ mod logs;
mod random;
mod time;
pub use crate::cli::CmdArgs;
pub use crate::clone::Cloneable;
pub use crate::collections::{
contains_duplicates, retain_btreemap, wraparound_get, Counter, MultiMap,

View File

@ -12,4 +12,3 @@ gtfs = { path = "../gtfs" }
kml = { path = "../kml" }
osm-xml = "0.6.2"
map_model = { path = "../map_model" }
structopt = "0.2.18"

View File

@ -8,41 +8,15 @@ use geom::{Distance, FindClosest, Line, PolyLine, Pt2D};
use kml::ExtraShapes;
use map_model::{raw_data, LaneID, OffstreetParking, Position, LANE_THICKNESS};
use std::collections::BTreeMap;
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
#[structopt(name = "convert_osm")]
pub struct Flags {
/// OSM XML file to read
#[structopt(long = "osm")]
pub osm: String,
/// ExtraShapes file with blockface, produced using the kml crate. Optional.
#[structopt(long = "parking_shapes", default_value = "")]
pub parking_shapes: String,
/// ExtraShapes file with street signs, produced using the kml crate. Optional.
#[structopt(long = "street_signs", default_value = "")]
pub street_signs: String,
/// KML file with offstreet parking info. Optional.
#[structopt(long = "offstreet_parking", default_value = "")]
pub offstreet_parking: String,
/// GTFS directory. Optional.
#[structopt(long = "gtfs", default_value = "")]
pub gtfs: String,
/// Neighborhood GeoJSON path. Optional.
#[structopt(long = "neighborhoods", default_value = "")]
pub neighborhoods: String,
/// Osmosis clipping polgon. Optional.
#[structopt(long = "clip", default_value = "")]
pub clip: String,
/// Output .bin path
#[structopt(long = "output")]
pub parking_shapes: Option<String>,
pub street_signs: Option<String>,
pub offstreet_parking: Option<String>,
pub gtfs: Option<String>,
pub neighborhoods: Option<String>,
pub clip: Option<String>,
pub output: String,
}
@ -56,24 +30,24 @@ pub fn convert(flags: &Flags, timer: &mut abstutil::Timer) -> raw_data::Map {
check_orig_ids(&map);
if !flags.parking_shapes.is_empty() {
use_parking_hints(&mut map, &flags.parking_shapes, timer);
if let Some(ref path) = flags.parking_shapes {
use_parking_hints(&mut map, path, timer);
}
if !flags.street_signs.is_empty() {
use_street_signs(&mut map, &flags.street_signs, timer);
if let Some(ref path) = flags.street_signs {
use_street_signs(&mut map, path, timer);
}
if !flags.offstreet_parking.is_empty() {
use_offstreet_parking(&mut map, &flags.offstreet_parking, timer);
if let Some(ref path) = flags.offstreet_parking {
use_offstreet_parking(&mut map, path, timer);
}
if !flags.gtfs.is_empty() {
if let Some(ref path) = flags.gtfs {
timer.start("load GTFS");
map.bus_routes = gtfs::load(&flags.gtfs).unwrap();
map.bus_routes = gtfs::load(path).unwrap();
timer.stop("load GTFS");
}
if !flags.neighborhoods.is_empty() {
if let Some(ref path) = flags.neighborhoods {
timer.start("convert neighborhood polygons");
neighborhoods::convert(&flags.neighborhoods, map.name.clone(), &map.gps_bounds);
neighborhoods::convert(path, map.name.clone(), &map.gps_bounds);
timer.stop("convert neighborhood polygons");
}

View File

@ -1,8 +1,20 @@
use abstutil::CmdArgs;
use convert_osm::{convert, Flags};
use structopt::StructOpt;
fn main() {
let flags = Flags::from_args();
let mut args = CmdArgs::new();
let flags = Flags {
osm: args.required("--osm"),
parking_shapes: args.optional("--parking_shapes"),
street_signs: args.optional("--street_signs"),
offstreet_parking: args.optional("--offstreet_parking"),
gtfs: args.optional("--gtfs"),
neighborhoods: args.optional("--neighborhoods"),
clip: args.optional("--clip"),
output: args.required("--output"),
};
args.done();
let mut timer = abstutil::Timer::new(&format!("generate {}", flags.output));
let map = convert(&flags, &mut timer);
println!("writing to {}", flags.output);

View File

@ -8,7 +8,7 @@ use std::io::{BufRead, BufReader};
pub fn extract_osm(
osm_path: &str,
maybe_clip_path: &str,
maybe_clip_path: &Option<String>,
timer: &mut Timer,
) -> (
raw_data::Map,
@ -27,15 +27,15 @@ pub fn extract_osm(
);
done(timer);
let mut map = if maybe_clip_path.is_empty() {
let mut map = if let Some(ref path) = maybe_clip_path {
read_osmosis_polygon(path)
} else {
let mut m = raw_data::Map::blank(abstutil::basename(osm_path));
for node in doc.nodes.values() {
m.gps_bounds.update(LonLat::new(node.lon, node.lat));
}
m.boundary_polygon = m.gps_bounds.to_bounds().get_rectangle();
m
} else {
read_osmosis_polygon(maybe_clip_path)
};
let mut id_to_way: HashMap<i64, Vec<Pt2D>> = HashMap::new();

View File

@ -7,12 +7,12 @@ pub fn run(t: &mut TestRunner) {
t.run_slow("convert_osm_twice", |_| {
let flags = convert_osm::Flags {
osm: "../data/input/montlake.osm".to_string(),
parking_shapes: "../data/shapes/blockface.bin".to_string(),
street_signs: "../data/shapes/street_signs.bin".to_string(),
offstreet_parking: "../data/input/offstreet_parking.kml".to_string(),
gtfs: "../data/input/google_transit_2018_18_08".to_string(),
neighborhoods: "../data/input/neighborhoods.geojson".to_string(),
clip: abstutil::path_polygon("montlake"),
parking_shapes: Some("../data/shapes/blockface.bin".to_string()),
street_signs: Some("../data/shapes/street_signs.bin".to_string()),
offstreet_parking: Some("../data/input/offstreet_parking.kml".to_string()),
gtfs: Some("../data/input/google_transit_2018_18_08".to_string()),
neighborhoods: Some("../data/input/neighborhoods.geojson".to_string()),
clip: Some(abstutil::path_polygon("montlake")),
output: "convert_osm_twice.bin".to_string(),
};