diff --git a/book/src/project/CHANGELOG.md b/book/src/project/CHANGELOG.md index 23df541818..0c6f8aa89a 100644 --- a/book/src/project/CHANGELOG.md +++ b/book/src/project/CHANGELOG.md @@ -623,3 +623,13 @@ changes here. - fix by Michael for handling window resizing in panels - fix original routes on edited maps - internal code organization and documentation + +0.2.16 + +- UI: click unzoomed agents, switch between metric/imperial units, show reason for cancelled trips, new "faded zoom" color scheme based on mapbox, more detailed agent counts in the top-right panel's tooltips +- started a new dedicated OpenStreetMap viewer, will split out from A/B Street later +- fix alpha colors on web +- bugfixes for the new asynchronous map loading +- some substantial simulation performance gains (168s to 90s on one benchmark!) +- lots of progress towards editing the map without resetting the simulation to midnight. please test with --live_map_edits and report any issues +- internal refactoring and code documentation diff --git a/convert_osm/src/extract.rs b/convert_osm/src/extract.rs index d4897a12b7..a79a7a6892 100644 --- a/convert_osm/src/extract.rs +++ b/convert_osm/src/extract.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, BTreeSet, HashMap}; +use std::collections::{BTreeMap, HashMap}; use osm::{NodeID, OsmID, RelationID, WayID}; @@ -6,7 +6,7 @@ use abstutil::{retain_btreemap, Tags, Timer}; use geom::{HashablePt2D, PolyLine, Polygon, Pt2D, Ring}; use kml::{ExtraShape, ExtraShapes}; use map_model::raw::{RawArea, RawBuilding, RawMap, RawParkingLot, RawRoad, RestrictionType}; -use map_model::{osm, AreaType, NamePerLanguage}; +use map_model::{osm, Amenity, AreaType, NamePerLanguage}; use crate::reader::{Document, Relation}; use crate::transit; @@ -22,8 +22,8 @@ pub struct OsmExtract { pub simple_turn_restrictions: Vec<(RestrictionType, WayID, NodeID, WayID)>, /// (relation ID, from way ID, via way ID, to way ID) pub complicated_turn_restrictions: Vec<(RelationID, WayID, WayID, WayID)>, - /// (location, name, amenity type) - pub amenities: Vec<(Pt2D, NamePerLanguage, String)>, + /// (location, amenity) + pub amenities: Vec<(Pt2D, Amenity)>, } pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmExtract { @@ -53,19 +53,8 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx out.traffic_signals .insert(node.pt.to_hashable(), !backwards); } - if let Some(amenity) = node.tags.get("amenity") { - out.amenities.push(( - node.pt, - NamePerLanguage::new(&node.tags).unwrap_or_else(NamePerLanguage::unnamed), - amenity.clone(), - )); - } - if let Some(shop) = node.tags.get("shop") { - out.amenities.push(( - node.pt, - NamePerLanguage::new(&node.tags).unwrap_or_else(NamePerLanguage::unnamed), - shop.clone(), - )); + for amenity in get_bldg_amenities(&node.tags) { + out.amenities.push((node.pt, amenity)); } } @@ -175,7 +164,7 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx let boundary = map.boundary_polygon.clone().into_ring(); - let mut amenity_areas: Vec<(NamePerLanguage, String, Polygon)> = Vec::new(); + let mut amenity_areas: Vec<(Polygon, Amenity)> = Vec::new(); // Vehicle position (stop) -> pedestrian position (platform) let mut stop_areas: Vec<((osm::NodeID, Pt2D), Pt2D)> = Vec::new(); @@ -288,15 +277,18 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx timer, )); } else if rel.tags.is("type", "multipolygon") && rel.tags.contains_key("amenity") { - let names = NamePerLanguage::new(&rel.tags).unwrap_or_else(NamePerLanguage::unnamed); - let amenity = rel.tags.get("amenity").clone().unwrap(); + let amenity = Amenity { + names: NamePerLanguage::new(&rel.tags).unwrap_or_else(NamePerLanguage::unnamed), + amenity_type: rel.tags.get("amenity").unwrap().clone(), + osm_tags: rel.tags.clone(), + }; for (role, member) in &rel.members { if role != "outer" { continue; } if let OsmID::Way(w) = member { if let Ok(ring) = Ring::new(doc.ways[w].pts.clone()) { - amenity_areas.push((names.clone(), amenity.clone(), ring.to_polygon())); + amenity_areas.push((ring.to_polygon(), amenity.clone())); } } } @@ -352,11 +344,11 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx } timer.start_iter("match buildings to amenity areas", amenity_areas.len()); - for (names, amenity, poly) in amenity_areas { + for (poly, amenity) in amenity_areas { timer.next(); for b in map.buildings.values_mut() { if poly.contains_pt(b.polygon.center()) { - b.amenities.insert((names.clone(), amenity.clone())); + b.amenities.push(amenity.clone()); } } } @@ -495,19 +487,16 @@ fn is_bldg(tags: &Tags) -> bool { tags.contains_key("building") && !tags.contains_key("abandoned:man_made") } -fn get_bldg_amenities(tags: &Tags) -> BTreeSet<(NamePerLanguage, String)> { - let mut amenities = BTreeSet::new(); - if let Some(amenity) = tags.get("amenity") { - amenities.insert(( - NamePerLanguage::new(tags).unwrap_or_else(NamePerLanguage::unnamed), - amenity.clone(), - )); - } - if let Some(shop) = tags.get("shop") { - amenities.insert(( - NamePerLanguage::new(tags).unwrap_or_else(NamePerLanguage::unnamed), - shop.clone(), - )); +fn get_bldg_amenities(tags: &Tags) -> Vec { + let mut amenities = Vec::new(); + for key in vec!["amenity", "shop"] { + if let Some(amenity) = tags.get(key) { + amenities.push(Amenity { + names: NamePerLanguage::new(tags).unwrap_or_else(NamePerLanguage::unnamed), + amenity_type: amenity.clone(), + osm_tags: tags.clone(), + }); + } } amenities } diff --git a/convert_osm/src/lib.rs b/convert_osm/src/lib.rs index f7347bc458..3c62e79673 100644 --- a/convert_osm/src/lib.rs +++ b/convert_osm/src/lib.rs @@ -1,7 +1,7 @@ use abstutil::Timer; use geom::{Distance, FindClosest, GPSBounds, LonLat, Pt2D, Ring}; use map_model::raw::RawMap; -use map_model::{osm, MapConfig, NamePerLanguage}; +use map_model::{osm, Amenity, MapConfig}; mod clip; mod extract; @@ -109,23 +109,19 @@ pub fn convert(opts: Options, timer: &mut abstutil::Timer) -> RawMap { map } -fn use_amenities( - map: &mut RawMap, - amenities: Vec<(Pt2D, NamePerLanguage, String)>, - timer: &mut Timer, -) { +fn use_amenities(map: &mut RawMap, amenities: Vec<(Pt2D, Amenity)>, timer: &mut Timer) { let mut closest: FindClosest = FindClosest::new(&map.gps_bounds.to_bounds()); for (id, b) in &map.buildings { closest.add(*id, b.polygon.points()); } timer.start_iter("match building amenities", amenities.len()); - for (pt, names, amenity) in amenities { + for (pt, amenity) in amenities { timer.next(); if let Some((id, _)) = closest.closest_pt(pt, Distance::meters(50.0)) { let b = map.buildings.get_mut(&id).unwrap(); if b.polygon.contains_pt(pt) { - b.amenities.insert((names, amenity)); + b.amenities.push(amenity); } } } diff --git a/convert_osm/src/parking.rs b/convert_osm/src/parking.rs index 433d08150b..023f27c65c 100644 --- a/convert_osm/src/parking.rs +++ b/convert_osm/src/parking.rs @@ -204,7 +204,7 @@ fn apply_private_offstreet_parking(map: &mut RawMap, policy: &PrivateOffstreetPa // 1 spot per 30m^2. b.num_parking_spots = ((b.polygon.area() / 30.0) as usize) * levels; // Not useful to list this - abstutil::retain_btreeset(&mut b.amenities, |(_, a)| a != "parking"); + b.amenities.retain(|a| a.amenity_type != "parking"); } else { b.num_parking_spots = *n; } diff --git a/convert_osm/src/split_ways.rs b/convert_osm/src/split_ways.rs index 072618300b..e5c5d48744 100644 --- a/convert_osm/src/split_ways.rs +++ b/convert_osm/src/split_ways.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use abstutil::{Counter, Timer}; use geom::{Distance, HashablePt2D, Pt2D}; use map_model::raw::{OriginalRoad, RawIntersection, RawMap}; -use map_model::{osm, IntersectionType, NamePerLanguage}; +use map_model::{osm, Amenity, IntersectionType}; use crate::extract::OsmExtract; @@ -13,10 +13,7 @@ pub fn split_up_roads( map: &mut RawMap, mut input: OsmExtract, timer: &mut Timer, -) -> ( - Vec<(Pt2D, NamePerLanguage, String)>, - HashMap, -) { +) -> (Vec<(Pt2D, Amenity)>, HashMap) { timer.start("splitting up roads"); let mut pt_to_intersection: HashMap = HashMap::new(); diff --git a/data/MANIFEST.json b/data/MANIFEST.json index 8b20de85ef..0cb050dd0a 100644 --- a/data/MANIFEST.json +++ b/data/MANIFEST.json @@ -5,7 +5,7 @@ "dropbox_url": "https://www.dropbox.com/s/38fl51jxp5iwuz3/EWR201812E_Matrix.csv.zip?dl=0" }, "data/input/berlin/berlin_center_separate_cycleways.bin": { - "checksum": "a2baf944416111e712738a95449d51aa", + "checksum": "1a2c7c8c37a2d5d7893b308d2994554c", "dropbox_url": "https://www.dropbox.com/s/nas6r3pzesmrbdj/berlin_center_separate_cycleways.bin.zip?dl=0" }, "data/input/berlin/berlin_center_snapped_cycleways.bin": { @@ -41,7 +41,7 @@ "dropbox_url": "https://www.dropbox.com/s/xxwivqmxev2ecl6/footways.bin.zip?dl=0" }, "data/input/krakow/krakow_center_separate_cycleways.bin": { - "checksum": "e0a1858a2879fd3b06937213b5199ed5", + "checksum": "be8282906a385d2121f7d20d1694d358", "dropbox_url": "https://www.dropbox.com/s/dqrc5w5jxpv9nfc/krakow_center_separate_cycleways.bin.zip?dl=0" }, "data/input/krakow/krakow_center_snapped_cycleways.bin": { @@ -77,7 +77,7 @@ "dropbox_url": "https://www.dropbox.com/s/c477mruya21q9a0/service_roads.bin.zip?dl=0" }, "data/input/london/southbank_separate_cycleways.bin": { - "checksum": "1d76d0d77bbbf015f36dd61226619800", + "checksum": "275f14cf20f37e4483f3bc2cb72cb63b", "dropbox_url": "https://www.dropbox.com/s/pahf7kbiuh1j2yr/southbank_separate_cycleways.bin.zip?dl=0" }, "data/input/london/southbank_snapped_cycleways.bin": { @@ -85,67 +85,67 @@ "dropbox_url": "https://www.dropbox.com/s/l4anoe33yuut4vs/southbank_snapped_cycleways.bin.zip?dl=0" }, "data/input/raw_maps/ballard.bin": { - "checksum": "91c68fd153435f724d8bfca69977087d", - "dropbox_url": "https://www.dropbox.com/s/xjutuwth6oyxiqm/ballard.bin.zip?dl=0" + "checksum": "9be957ee2fe4f2e90b1c498ac72cff33", + "dropbox_url": "https://www.dropbox.com/s/jmhlhsurwjyof5p/ballard.bin.zip?dl=0" }, "data/input/raw_maps/berlin_center.bin": { - "checksum": "bd6acbb9a316382d1a18187b6ce132f5", - "dropbox_url": "https://www.dropbox.com/s/p8irq9yu8jsqr9f/berlin_center.bin.zip?dl=0" + "checksum": "520212f063eda6956391193ebe5424d3", + "dropbox_url": "https://www.dropbox.com/s/efhi68i88e9k5ha/berlin_center.bin.zip?dl=0" }, "data/input/raw_maps/downtown.bin": { - "checksum": "b7b974f67692793fadff56e8388b9097", - "dropbox_url": "https://www.dropbox.com/s/18adtnqa5syjswx/downtown.bin.zip?dl=0" + "checksum": "b091d32bcd241f3f37135547a023605c", + "dropbox_url": "https://www.dropbox.com/s/gj1sa2lwid0uln6/downtown.bin.zip?dl=0" }, "data/input/raw_maps/huge_seattle.bin": { - "checksum": "beefcebe4614ab05cb666ba5848523c2", - "dropbox_url": "https://www.dropbox.com/s/4kvgpqzurzyg2w0/huge_seattle.bin.zip?dl=0" + "checksum": "b9c1d42bdb5ec79081b8804e3ce8dcc2", + "dropbox_url": "https://www.dropbox.com/s/ji4kdc9rd1x57zf/huge_seattle.bin.zip?dl=0" }, "data/input/raw_maps/krakow_center.bin": { - "checksum": "aa47c82c15ee967a2c288b3524ff166f", - "dropbox_url": "https://www.dropbox.com/s/bhkydggxdqklcxg/krakow_center.bin.zip?dl=0" + "checksum": "e9dc50198ed2193e0bd8f1859c1941a3", + "dropbox_url": "https://www.dropbox.com/s/ns2xwldvn9s9jle/krakow_center.bin.zip?dl=0" }, "data/input/raw_maps/lakeslice.bin": { - "checksum": "c7dd1dbd8ddc0f9101c34b0b910f4f0b", - "dropbox_url": "https://www.dropbox.com/s/1u6uz3awfw75hwt/lakeslice.bin.zip?dl=0" + "checksum": "895926104dc93d102324737d1c7a645c", + "dropbox_url": "https://www.dropbox.com/s/8fqngko75phok5l/lakeslice.bin.zip?dl=0" }, "data/input/raw_maps/montlake.bin": { - "checksum": "0c1e537be778036024a8e2847f20bbfc", - "dropbox_url": "https://www.dropbox.com/s/9fsnt21ynj2ldgz/montlake.bin.zip?dl=0" + "checksum": "350279954f0d2cee17f6806263336e79", + "dropbox_url": "https://www.dropbox.com/s/kpr3hkpr7conqc7/montlake.bin.zip?dl=0" }, "data/input/raw_maps/south_seattle.bin": { - "checksum": "0bafee9da613d59a9af65b4b16223b45", - "dropbox_url": "https://www.dropbox.com/s/oh9epdy4c7jspzg/south_seattle.bin.zip?dl=0" + "checksum": "0c0f236ef5bc7992f9c386d8f9a08d93", + "dropbox_url": "https://www.dropbox.com/s/a8dsj642lusot94/south_seattle.bin.zip?dl=0" }, "data/input/raw_maps/southbank.bin": { - "checksum": "1e372b963da2c09e711cae6e2d4f481e", - "dropbox_url": "https://www.dropbox.com/s/ajlh4z2838l54wd/southbank.bin.zip?dl=0" + "checksum": "cb2b5b66f5fc03b1e1dfb7ee98f47d05", + "dropbox_url": "https://www.dropbox.com/s/nc2cvm8gt9lkl0y/southbank.bin.zip?dl=0" }, "data/input/raw_maps/tel_aviv.bin": { - "checksum": "c49e439e73bfd05956bacd3d9dee4de0", - "dropbox_url": "https://www.dropbox.com/s/fpv6gd2lz8p5tvj/tel_aviv.bin.zip?dl=0" + "checksum": "0a4522bf4b9cd01630d17f40dc0504ee", + "dropbox_url": "https://www.dropbox.com/s/l90lezvadn8l93d/tel_aviv.bin.zip?dl=0" }, "data/input/raw_maps/udistrict.bin": { - "checksum": "cade82ad30916859fcb0c206e5c41b2b", - "dropbox_url": "https://www.dropbox.com/s/aelextrfsb7lv56/udistrict.bin.zip?dl=0" + "checksum": "0ca3a0f3b5e04942a25a5138c64d3dcb", + "dropbox_url": "https://www.dropbox.com/s/n2ra2t9qwwy0gtj/udistrict.bin.zip?dl=0" }, "data/input/raw_maps/west_seattle.bin": { - "checksum": "20202f7c72e36c8023c1177306e6783a", - "dropbox_url": "https://www.dropbox.com/s/26g0xx72p3gm3te/west_seattle.bin.zip?dl=0" + "checksum": "375050f3b1e387ef2643f2fd63a05ab5", + "dropbox_url": "https://www.dropbox.com/s/6n894wj0hcbi2ze/west_seattle.bin.zip?dl=0" }, "data/input/raw_maps/xian.bin": { - "checksum": "6bd3b6f92460f4335203b0fb6efe9f91", - "dropbox_url": "https://www.dropbox.com/s/rgtbw69tx48ig76/xian.bin.zip?dl=0" + "checksum": "19ae1179872279b65aae2717d6b75e0c", + "dropbox_url": "https://www.dropbox.com/s/ml2fcu85uqiqy14/xian.bin.zip?dl=0" }, "data/input/screenshots/downtown.zip": { - "checksum": "3d3f00e2386fc75f5c609574fdf1db92", + "checksum": "2a1acf61b7711425a42196b6e8002f86", "dropbox_url": "https://www.dropbox.com/s/qawd35wz62m2acl/downtown.zip.zip?dl=0" }, "data/input/screenshots/krakow_center.zip": { - "checksum": "c5102938d146d530d9caaf94e26e10b1", + "checksum": "36ab0605776f2af024db38e29613f473", "dropbox_url": "https://www.dropbox.com/s/azea6v6mnxbe0vc/krakow_center.zip.zip?dl=0" }, "data/input/screenshots/lakeslice.zip": { - "checksum": "5664e016969bdbc83c07e91553d7cc05", + "checksum": "ded10401be78ff8f4482ea75e58b9cee", "dropbox_url": "https://www.dropbox.com/s/06mwgdt6orow3rk/lakeslice.zip.zip?dl=0" }, "data/input/screenshots/montlake.zip": { @@ -153,11 +153,11 @@ "dropbox_url": "https://www.dropbox.com/s/59xtbot06ps0ab6/montlake.zip.zip?dl=0" }, "data/input/screenshots/southbank.zip": { - "checksum": "ef8ab513c72c9e3e418c3a725d94d363", - "dropbox_url": "https://www.dropbox.com/s/f1i64ic454ooxtr/southbank.zip.zip?dl=0" + "checksum": "575c2f0d07f0ab2689b4590c5309c7dd", + "dropbox_url": "https://www.dropbox.com/s/k3dzdsgpa6pac1h/southbank.zip.zip?dl=0" }, "data/input/screenshots/udistrict.zip": { - "checksum": "4c330ebee1a0525ffc03ed74bef93b6b", + "checksum": "fedf49cc360a18693418dd66fc9220dc", "dropbox_url": "https://www.dropbox.com/s/efes2r6hwgcv38k/udistrict.zip.zip?dl=0" }, "data/input/seattle/N47W122.hgt": { @@ -165,11 +165,11 @@ "dropbox_url": "https://www.dropbox.com/s/mmb4mgutwotijdw/N47W122.hgt.zip?dl=0" }, "data/input/seattle/ballard_separate_cycleways.bin": { - "checksum": "2b39882e62ac92d1e538ff49b44b898c", - "dropbox_url": "https://www.dropbox.com/s/jixtgr2vej4jojy/ballard_separate_cycleways.bin.zip?dl=0" + "checksum": "c311001f8ad4873369e36ab9b24af2f8", + "dropbox_url": "https://www.dropbox.com/s/1jq4sjly2yqs42p/ballard_separate_cycleways.bin.zip?dl=0" }, "data/input/seattle/ballard_snapped_cycleways.bin": { - "checksum": "67d84e6e231b62e6e3bd0c80a5580775", + "checksum": "1f25c6dac0d0c8f01b187031c4bcf58c", "dropbox_url": "https://www.dropbox.com/s/fwfez964qnmgpqi/ballard_snapped_cycleways.bin.zip?dl=0" }, "data/input/seattle/blockface.bin": { @@ -181,8 +181,8 @@ "dropbox_url": "https://www.dropbox.com/s/ukknmpjdvilncq9/blockface.kml.zip?dl=0" }, "data/input/seattle/downtown_separate_cycleways.bin": { - "checksum": "de5f9fd3066ed6ce764bf1f6dcf67340", - "dropbox_url": "https://www.dropbox.com/s/v32vx554mxmmw7f/downtown_separate_cycleways.bin.zip?dl=0" + "checksum": "ee5e370842ac88a3d2c2ab62366e41b2", + "dropbox_url": "https://www.dropbox.com/s/ulotf7sd9s82x8y/downtown_separate_cycleways.bin.zip?dl=0" }, "data/input/seattle/downtown_snapped_cycleways.bin": { "checksum": "ece26188973856f10bcebe54b84b14da", @@ -241,24 +241,24 @@ "dropbox_url": "https://www.dropbox.com/s/lw0hhnqttns2h8z/trips.txt.zip?dl=0" }, "data/input/seattle/huge_seattle_separate_cycleways.bin": { - "checksum": "2b0d4873b43f139c665aab1d8968f8ca", - "dropbox_url": "https://www.dropbox.com/s/fb7xk8vrabpe2gu/huge_seattle_separate_cycleways.bin.zip?dl=0" + "checksum": "7a834b86ef520bd602d2a91359b32de7", + "dropbox_url": "https://www.dropbox.com/s/wgb6vps3o0p548o/huge_seattle_separate_cycleways.bin.zip?dl=0" }, "data/input/seattle/huge_seattle_snapped_cycleways.bin": { - "checksum": "620b615c1c1bf434463c14045d3ac56d", + "checksum": "8ec684df2622622e5b30a4cab5bfed68", "dropbox_url": "https://www.dropbox.com/s/n613496yq3f4kcq/huge_seattle_snapped_cycleways.bin.zip?dl=0" }, "data/input/seattle/lakeslice_separate_cycleways.bin": { - "checksum": "46c8b28d3e0d8ce6ca4a858b9d41a4e1", - "dropbox_url": "https://www.dropbox.com/s/1tpiurm10x5udul/lakeslice_separate_cycleways.bin.zip?dl=0" + "checksum": "5b39fc96041303859102656519ae7b5e", + "dropbox_url": "https://www.dropbox.com/s/tsng6fw8vtu6u49/lakeslice_separate_cycleways.bin.zip?dl=0" }, "data/input/seattle/lakeslice_snapped_cycleways.bin": { "checksum": "30916279d151f97fd7ff6653eaef8719", "dropbox_url": "https://www.dropbox.com/s/5uf52oy8qubzzcl/lakeslice_snapped_cycleways.bin.zip?dl=0" }, "data/input/seattle/montlake_separate_cycleways.bin": { - "checksum": "0027a574d0df2f4726cc90518671164e", - "dropbox_url": "https://www.dropbox.com/s/yupazp530q7jbwo/montlake_separate_cycleways.bin.zip?dl=0" + "checksum": "f3f1a38af39f5221e98c4c03a279c1a6", + "dropbox_url": "https://www.dropbox.com/s/sxxyfx241yxcp1j/montlake_separate_cycleways.bin.zip?dl=0" }, "data/input/seattle/montlake_snapped_cycleways.bin": { "checksum": "bad5e9c0a0ca11b8e73d79e47ab903a2", @@ -325,8 +325,8 @@ "dropbox_url": "https://www.dropbox.com/s/0konam8z33ulepy/service_roads.bin.zip?dl=0" }, "data/input/seattle/south_seattle_separate_cycleways.bin": { - "checksum": "482f09cce508d304ab66d21070b0e0c8", - "dropbox_url": "https://www.dropbox.com/s/lld3h29rd2j3aoo/south_seattle_separate_cycleways.bin.zip?dl=0" + "checksum": "7580efb8b27f366d3d75efb8935c4807", + "dropbox_url": "https://www.dropbox.com/s/cr9pieg7qq7dzee/south_seattle_separate_cycleways.bin.zip?dl=0" }, "data/input/seattle/south_seattle_snapped_cycleways.bin": { "checksum": "92bb9e7d7b8d89e63ecb4d9fe54e3b7f", @@ -337,16 +337,16 @@ "dropbox_url": "https://www.dropbox.com/s/5ppravwmk6bf20d/trips_2014.csv.zip?dl=0" }, "data/input/seattle/udistrict_separate_cycleways.bin": { - "checksum": "dc67c4a2471d48372600390cfb5cf293", - "dropbox_url": "https://www.dropbox.com/s/lai0us65jl5vmoh/udistrict_separate_cycleways.bin.zip?dl=0" + "checksum": "4383bc0d2a70b0f79fbb42fa720e0993", + "dropbox_url": "https://www.dropbox.com/s/yy47mnsivjm4jva/udistrict_separate_cycleways.bin.zip?dl=0" }, "data/input/seattle/udistrict_snapped_cycleways.bin": { "checksum": "937654a8be61da06486d3c5c5304132c", "dropbox_url": "https://www.dropbox.com/s/zpznqax43fxl7xp/udistrict_snapped_cycleways.bin.zip?dl=0" }, "data/input/seattle/west_seattle_separate_cycleways.bin": { - "checksum": "59f569ae705a855a7e8080d84c9bd4e9", - "dropbox_url": "https://www.dropbox.com/s/91hl3fum82p6bui/west_seattle_separate_cycleways.bin.zip?dl=0" + "checksum": "5e59aed9ab515d22e8a477f0d182235d", + "dropbox_url": "https://www.dropbox.com/s/xtpk96wtsd0kpym/west_seattle_separate_cycleways.bin.zip?dl=0" }, "data/input/seattle/west_seattle_snapped_cycleways.bin": { "checksum": "4a8e438b0795360aa7fec1ebacd64233", @@ -369,11 +369,11 @@ "dropbox_url": "https://www.dropbox.com/s/7rscshpat7dyzxv/service_roads.bin.zip?dl=0" }, "data/input/tel_aviv/tel_aviv_separate_cycleways.bin": { - "checksum": "6feb90004775e67eab160934c9b812e5", + "checksum": "3bf2b83d905d256f12baa40f22f55810", "dropbox_url": "https://www.dropbox.com/s/p62d1gum2e04rp9/tel_aviv_separate_cycleways.bin.zip?dl=0" }, "data/input/tel_aviv/tel_aviv_snapped_cycleways.bin": { - "checksum": "f9101f6ff1662c4c0bd69246599a27c3", + "checksum": "58bcaad6a593b6981c4f4cede45c8abb", "dropbox_url": "https://www.dropbox.com/s/wq2oco1u22gzwou/tel_aviv_snapped_cycleways.bin.zip?dl=0" }, "data/input/xian/footways.bin": { @@ -393,64 +393,64 @@ "dropbox_url": "https://www.dropbox.com/s/wm4ga2kay4v4ija/service_roads.bin.zip?dl=0" }, "data/system/cities/seattle.bin": { - "checksum": "8da14a93b17f336cc8ee6e0bdbd84fcc", - "dropbox_url": "https://www.dropbox.com/s/ibvdbbdjdi233mr/seattle.bin.zip?dl=0" + "checksum": "b9e9b4e33104749dd14ffbcd746748fa", + "dropbox_url": "https://www.dropbox.com/s/hicb7s0v35r6xjc/seattle.bin.zip?dl=0" }, "data/system/maps/ballard.bin": { - "checksum": "f53ea69b1b8c62d611795d748e1e67ca", - "dropbox_url": "https://www.dropbox.com/s/gkhrsi1adi905lp/ballard.bin.zip?dl=0" + "checksum": "ee69c122295aef236435e3ee027d768d", + "dropbox_url": "https://www.dropbox.com/s/cqmk13cc2gf4gi1/ballard.bin.zip?dl=0" }, "data/system/maps/berlin_center.bin": { - "checksum": "e9474395f8a4f5f13941593745c64986", - "dropbox_url": "https://www.dropbox.com/s/93chwc62k74n8u3/berlin_center.bin.zip?dl=0" + "checksum": "24f8522129b69b258a5114d8fb631fe6", + "dropbox_url": "https://www.dropbox.com/s/x8dtxnmiubyneoy/berlin_center.bin.zip?dl=0" }, "data/system/maps/downtown.bin": { - "checksum": "bb6cc3bb5f255e6b86bf0086051be4b3", - "dropbox_url": "https://www.dropbox.com/s/mv0h91a6slgbihd/downtown.bin.zip?dl=0" + "checksum": "38ecc647eb66e38df653bed2756a6797", + "dropbox_url": "https://www.dropbox.com/s/53h42a1e271o21a/downtown.bin.zip?dl=0" }, "data/system/maps/huge_seattle.bin": { - "checksum": "b324d48a02b46251f73e32f88bfd8266", - "dropbox_url": "https://www.dropbox.com/s/ltvvev9gm0radpi/huge_seattle.bin.zip?dl=0" + "checksum": "6af3c708c062bdc98df4d67391500690", + "dropbox_url": "https://www.dropbox.com/s/0k2z5seevlkltf1/huge_seattle.bin.zip?dl=0" }, "data/system/maps/krakow_center.bin": { - "checksum": "67f1d4a270a5b20daad66695deb343cf", - "dropbox_url": "https://www.dropbox.com/s/r0048aj3cjkgupt/krakow_center.bin.zip?dl=0" + "checksum": "2c933e2a75f65e65a3aa35be3e16aaeb", + "dropbox_url": "https://www.dropbox.com/s/p1pq6q73tz3oq2f/krakow_center.bin.zip?dl=0" }, "data/system/maps/lakeslice.bin": { - "checksum": "54942cf869156b4967929e099d502980", - "dropbox_url": "https://www.dropbox.com/s/en5g7zzv6ynv4zu/lakeslice.bin.zip?dl=0" + "checksum": "71007da9100771577e45cc30ad94427f", + "dropbox_url": "https://www.dropbox.com/s/arhsgfzesvoaqb1/lakeslice.bin.zip?dl=0" }, "data/system/maps/montlake.bin": { - "checksum": "b96bd0f0116b52e9a091f108c1113230", - "dropbox_url": "https://www.dropbox.com/s/7r7ivpxs1kiea4o/montlake.bin.zip?dl=0" + "checksum": "0e8b76d6824d962d0e13e7ac1badd2b3", + "dropbox_url": "https://www.dropbox.com/s/6ks1x8o8y1q1aa3/montlake.bin.zip?dl=0" }, "data/system/maps/south_seattle.bin": { - "checksum": "9b008200ff3eb1270a96c0af4f7fa10f", - "dropbox_url": "https://www.dropbox.com/s/5l2z7xd57visyqf/south_seattle.bin.zip?dl=0" + "checksum": "7925fb63df17ca27733fd439d6001156", + "dropbox_url": "https://www.dropbox.com/s/wk4tsp88834gb6g/south_seattle.bin.zip?dl=0" }, "data/system/maps/southbank.bin": { - "checksum": "8f83d037ab04bcfdfcb96a0fb2d3ccf7", - "dropbox_url": "https://www.dropbox.com/s/ldsydqidids6fiz/southbank.bin.zip?dl=0" + "checksum": "ffd522117956ab76b22d64b63b66e05c", + "dropbox_url": "https://www.dropbox.com/s/spd56g7dssvw8i0/southbank.bin.zip?dl=0" }, "data/system/maps/tel_aviv.bin": { - "checksum": "d619cfb34bbd92da5e560d62992cf4f5", - "dropbox_url": "https://www.dropbox.com/s/khnpq20pq3qapyo/tel_aviv.bin.zip?dl=0" + "checksum": "f232162f9575259cb0ba7941d9e9ccb9", + "dropbox_url": "https://www.dropbox.com/s/mygm3icq8yo6xj9/tel_aviv.bin.zip?dl=0" }, "data/system/maps/udistrict.bin": { - "checksum": "c23ccee90f71ae28e0598f9397c7261f", - "dropbox_url": "https://www.dropbox.com/s/zlx8wq2h10pgkaa/udistrict.bin.zip?dl=0" + "checksum": "ddb43e7b4fdadbec77a86fdc39f7e30e", + "dropbox_url": "https://www.dropbox.com/s/eb96dc3v0dwsgh6/udistrict.bin.zip?dl=0" }, "data/system/maps/west_seattle.bin": { - "checksum": "59c42bf75491ef4613762e1305d6d487", - "dropbox_url": "https://www.dropbox.com/s/5mdf06v9kajj4mv/west_seattle.bin.zip?dl=0" + "checksum": "0a94dffe7d28fe35be2ee55cb0489e9d", + "dropbox_url": "https://www.dropbox.com/s/pm7yio3mu1d6qwd/west_seattle.bin.zip?dl=0" }, "data/system/maps/xian.bin": { - "checksum": "20944e89d1802ea9d6074a6c7ff184cc", - "dropbox_url": "https://www.dropbox.com/s/7bx35jcq5oz2aix/xian.bin.zip?dl=0" + "checksum": "f39b4ba921239b5679237452e78b20e1", + "dropbox_url": "https://www.dropbox.com/s/pgq25trhy0vzmsr/xian.bin.zip?dl=0" }, "data/system/prebaked_results/lakeslice/weekday.bin": { - "checksum": "c6e5e318341ef37ae6139bb0d5596e53", - "dropbox_url": "https://www.dropbox.com/s/p2t0pw1k3808l2e/weekday.bin.zip?dl=0" + "checksum": "293c03231a017de134337c318a57fde0", + "dropbox_url": "https://www.dropbox.com/s/pgszyj9llc65wf6/weekday.bin.zip?dl=0" }, "data/system/prebaked_results/montlake/car vs bike contention.bin": { "checksum": "5f1587278a2604ad7caaf9148cb5a5d6", diff --git a/game/src/common/navigate.rs b/game/src/common/navigate.rs index 3f27b2ee16..238e450e83 100644 --- a/game/src/common/navigate.rs +++ b/game/src/common/navigate.rs @@ -227,11 +227,11 @@ impl SearchBuildings { b.id, )); } - for (names, _) in &b.amenities { + for a in &b.amenities { results.push(( format!( "{} (at {})", - names.get(app.opts.language.as_ref()), + a.names.get(app.opts.language.as_ref()), b.address ), b.id, diff --git a/game/src/devtools/destinations.rs b/game/src/devtools/destinations.rs index 5eb7c13c8d..6348fd588c 100644 --- a/game/src/devtools/destinations.rs +++ b/game/src/devtools/destinations.rs @@ -65,8 +65,8 @@ impl PopularDestinations { let mut by_type = Counter::new(); for (b, cnt) in per_bldg.borrow() { let mut other = true; - for (_, amenity) in &map.get_b(*b).amenities { - if let Some(t) = amenity_type(amenity) { + for a in &map.get_b(*b).amenities { + if let Some(t) = amenity_type(&a.amenity_type) { by_type.add(t, *cnt); other = false; } @@ -154,11 +154,11 @@ impl State for PopularDestinations { "{} trips to here", abstutil::prettyprint_usize(self.per_bldg.get(b)) ))); - for (names, amenity) in &app.primary.map.get_b(b).amenities { + for a in &app.primary.map.get_b(b).amenities { txt.add(Line(format!( " {} ({})", - names.get(app.opts.language.as_ref()), - amenity + a.names.get(app.opts.language.as_ref()), + a.amenity_type ))); } g.draw_mouse_tooltip(txt); diff --git a/game/src/devtools/osm_viewer.rs b/game/src/devtools/osm_viewer.rs index 60bde41701..8f2eaf0b26 100644 --- a/game/src/devtools/osm_viewer.rs +++ b/game/src/devtools/osm_viewer.rs @@ -152,11 +152,11 @@ impl Viewer { } else { txt.add(Line(format!("{} amenities:", b.amenities.len()))); } - for (names, amenity) in &b.amenities { + for a in &b.amenities { txt.add(Line(format!( " {} ({})", - names.get(app.opts.language.as_ref()), - amenity + a.names.get(app.opts.language.as_ref()), + a.amenity_type ))); } } @@ -349,8 +349,8 @@ impl BusinessSearch { fn new(ctx: &mut EventCtx, app: &App) -> BusinessSearch { let mut counts = Counter::new(); for b in app.primary.map.all_buildings() { - for (_, amenity) in &b.amenities { - counts.inc(amenity.clone()); + for a in &b.amenities { + counts.inc(a.amenity_type.clone()); } } let show = counts.borrow().keys().cloned().collect(); @@ -382,7 +382,7 @@ impl BusinessSearch { for b in app.primary.map.all_buildings() { if b.amenities .iter() - .any(|(_, amenity)| self.show.contains(amenity)) + .any(|a| self.show.contains(&a.amenity_type)) { batch.push(Color::RED, b.polygon.clone()); } @@ -409,7 +409,7 @@ impl BusinessSearch { let mut batch = GeomBatch::new(); if self.counts.get(amenity.clone()) > 0 { for b in app.primary.map.all_buildings() { - if b.amenities.iter().any(|(_, a)| a == &amenity) { + if b.amenities.iter().any(|a| a.amenity_type == amenity) { batch.push(Color::BLUE, b.polygon.clone()); } } diff --git a/game/src/helpers.rs b/game/src/helpers.rs index 118d79db58..b8b9cf9545 100644 --- a/game/src/helpers.rs +++ b/game/src/helpers.rs @@ -289,17 +289,15 @@ pub fn open_browser(url: String) { pub fn loading_tips() -> Text { Text::from_multiline(vec![ - Line("Recent changes (October 11)"), + Line("Recent changes (October 25)"), Line(""), + Line("- You can now click agents while zoomed out"), + Line("- New OpenStreetMap viewer, open it from the splash screen"), Line("- A web version has launched!"), Line("- Slow segments of a trip shown in the info panel"), Line("- Alleyways are now included in the map"), Line("- Check out the trip tables and summary changes (press 'q')"), Line("- Try out the new traffic signal editor!"), - Line("- The \"traffic signal demand\" layer shows all intersections through the whole day"), - Line("- New 3D buildings and textured color schemes in settings"), - Line("- Support for bidirectional cycletracks"), - Line("- An API to control A/B Street from any language"), ]) } diff --git a/game/src/info/building.rs b/game/src/info/building.rs index a68e83f0b0..bb5a704c66 100644 --- a/game/src/info/building.rs +++ b/game/src/info/building.rs @@ -60,11 +60,11 @@ pub fn info(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BuildingID } else { txt.add(Line(format!("{} amenities:", b.amenities.len()))); } - for (names, amenity) in &b.amenities { + for a in &b.amenities { txt.add(Line(format!( " {} ({})", - names.get(app.opts.language.as_ref()), - amenity + a.names.get(app.opts.language.as_ref()), + a.amenity_type ))); } } diff --git a/game/src/info/person.rs b/game/src/info/person.rs index 5f4bfb5d87..9c9d28cd6c 100644 --- a/game/src/info/person.rs +++ b/game/src/info/person.rs @@ -387,7 +387,7 @@ pub fn schedule( let list = b .amenities .iter() - .map(|(names, _)| names.get(app.opts.language.as_ref())) + .map(|a| a.names.get(app.opts.language.as_ref())) .collect::>(); format!("{} (at {})", list.choose(&mut rng).unwrap(), b.address) } @@ -416,7 +416,7 @@ pub fn schedule( let list = b .amenities .iter() - .map(|(names, _)| names.get(app.opts.language.as_ref())) + .map(|a| a.names.get(app.opts.language.as_ref())) .collect::>(); format!("{} (at {})", list.choose(&mut rng).unwrap(), b.address) } diff --git a/game/src/layer/map.rs b/game/src/layer/map.rs index 795fd728ff..5c4cd37f3e 100644 --- a/game/src/layer/map.rs +++ b/game/src/layer/map.rs @@ -266,8 +266,8 @@ impl Static { for b in app.primary.map.all_buildings() { let mut other = false; - for (_, a) in &b.amenities { - if let Some(t) = amenity_type(a) { + for a in &b.amenities { + if let Some(t) = amenity_type(&a.amenity_type) { colorer.add_b(b.id, t); } else { other = true; diff --git a/game/src/render/building.rs b/game/src/render/building.rs index 5fc1f1a4e7..d4db274a22 100644 --- a/game/src/render/building.rs +++ b/game/src/render/building.rs @@ -231,9 +231,9 @@ impl Renderable for DrawBuilding { if label.is_none() { let mut batch = GeomBatch::new(); let b = app.primary.map.get_b(self.id); - if let Some((names, _)) = b.amenities.iter().next() { + if let Some(a) = b.amenities.iter().next() { let mut txt = - Text::from(Line(names.get(app.opts.language.as_ref())).fg(Color::BLACK)); + Text::from(Line(a.names.get(app.opts.language.as_ref())).fg(Color::BLACK)); if b.amenities.len() > 1 { txt.append(Line(format!(" (+{})", b.amenities.len() - 1)).fg(Color::BLACK)); } diff --git a/map_model/src/lib.rs b/map_model/src/lib.rs index c1505f734b..b59a81f846 100644 --- a/map_model/src/lib.rs +++ b/map_model/src/lib.rs @@ -38,7 +38,7 @@ pub use crate::edits::{ pub use crate::map::{DrivingSide, MapConfig}; pub use crate::objects::area::{Area, AreaID, AreaType}; pub use crate::objects::building::{ - Building, BuildingID, BuildingType, NamePerLanguage, OffstreetParking, + Amenity, Building, BuildingID, BuildingType, NamePerLanguage, OffstreetParking, }; pub use crate::objects::bus_stop::{BusRoute, BusRouteID, BusStop, BusStopID}; pub use crate::objects::intersection::{Intersection, IntersectionID, IntersectionType}; diff --git a/map_model/src/make/buildings.rs b/map_model/src/make/buildings.rs index 7dd85c51ce..41bb6b3d74 100644 --- a/map_model/src/make/buildings.rs +++ b/map_model/src/make/buildings.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, BTreeSet, HashSet}; +use std::collections::{BTreeMap, HashSet}; use rand::{Rng, SeedableRng}; use rand_xorshift::XorShiftRng; @@ -9,7 +9,8 @@ use geom::{Distance, HashablePt2D, Line, Polygon}; use crate::make::match_points_to_lanes; use crate::raw::RawBuilding; use crate::{ - osm, Building, BuildingID, BuildingType, LaneID, Map, NamePerLanguage, OffstreetParking, + osm, Amenity, Building, BuildingID, BuildingType, LaneID, Map, NamePerLanguage, + OffstreetParking, }; /// Finalize importing of buildings, mostly by matching them to the nearest sidewalk. @@ -79,7 +80,18 @@ pub fn make_all_buildings( name: NamePerLanguage::new(&b.osm_tags), orig_id, label_center: b.polygon.polylabel(), - amenities: b.amenities.clone(), + amenities: if keep_bldg_tags { + b.amenities.clone() + } else { + b.amenities + .iter() + .map(|a| { + let mut a = a.clone(); + a.osm_tags = Tags::new(BTreeMap::new()); + a + }) + .collect() + }, bldg_type: classify_bldg( &b.osm_tags, &b.amenities, @@ -141,7 +153,7 @@ fn get_address(tags: &Tags, sidewalk: LaneID, map: &Map) -> String { fn classify_bldg( tags: &Tags, - amenities: &BTreeSet<(NamePerLanguage, String)>, + amenities: &Vec, levels: f64, ground_area_sq_meters: f64, rng: &mut XorShiftRng, @@ -152,8 +164,7 @@ fn classify_bldg( let area_sq_meters = levels * ground_area_sq_meters; - // These are (name, amenity type) pairs, produced by get_bldg_amenities in - // convert_osm/src/osm_reader.rs. + // These are produced by get_bldg_amenities in convert_osm/src/osm_reader.rs. // TODO: is it safe to assume all amenities are commercial? // TODO: consider converting amenities to an enum - maybe with a catchall case for the long // tail of rarely used enums. diff --git a/map_model/src/map.rs b/map_model/src/map.rs index 4fcdbcf4c2..2ff6507a9d 100644 --- a/map_model/src/map.rs +++ b/map_model/src/map.rs @@ -640,8 +640,8 @@ impl Map { } } for b in self.all_buildings() { - for (names, _) in &b.amenities { - for key in names.0.keys() { + for a in &b.amenities { + for key in a.names.0.keys() { if let Some(lang) = key { languages.insert(lang); } diff --git a/map_model/src/objects/building.rs b/map_model/src/objects/building.rs index 8de8f22cde..07ce042c4b 100644 --- a/map_model/src/objects/building.rs +++ b/map_model/src/objects/building.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, BTreeSet, HashSet, VecDeque}; +use std::collections::{BTreeMap, HashSet, VecDeque}; use std::fmt; use serde::{Deserialize, Serialize}; @@ -38,9 +38,7 @@ pub struct Building { /// Where a text label should be centered to have the best chances of being contained within /// the polygon. pub label_center: Pt2D, - // TODO Might fold these into BuildingType::Commercial - /// (Name, amenity) - pub amenities: BTreeSet<(NamePerLanguage, String)>, + pub amenities: Vec, pub bldg_type: BuildingType, pub parking: OffstreetParking, /// Depending on options while importing, these might be empty, to save file space. @@ -53,6 +51,15 @@ pub struct Building { pub driveway_geom: PolyLine, } +/// A business located inside a building. +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Amenity { + pub names: NamePerLanguage, + pub amenity_type: String, + /// Depending on options while importing, these might be empty, to save file space. + pub osm_tags: Tags, +} + /// Represent no parking as Private(0, false). #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] pub enum OffstreetParking { diff --git a/map_model/src/raw.rs b/map_model/src/raw.rs index 1b98c08ec1..5c883cb941 100644 --- a/map_model/src/raw.rs +++ b/map_model/src/raw.rs @@ -2,7 +2,7 @@ //! structure is useful to iterate quickly on parts of the map importing pipeline without having to //! constantly read .osm files, and to visualize the intermediate state with map_editor. -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; use std::fmt; use petgraph::graphmap::DiGraphMap; @@ -13,7 +13,7 @@ use geom::{Circle, Distance, GPSBounds, PolyLine, Polygon, Pt2D}; use crate::make::initial::lane_specs::get_lane_specs_ltr; use crate::{ - osm, AreaType, Direction, DrivingSide, IntersectionType, LaneType, MapConfig, NamePerLanguage, + osm, Amenity, AreaType, Direction, DrivingSide, IntersectionType, LaneType, MapConfig, }; #[derive(Debug, Serialize, Deserialize)] @@ -326,8 +326,7 @@ pub struct RawBuilding { pub osm_tags: Tags, pub public_garage_name: Option, pub num_parking_spots: usize, - /// (Name, amenity type) - pub amenities: BTreeSet<(NamePerLanguage, String)>, + pub amenities: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)]