refactor for #231: use typed OSM IDs everywhere, dedupe URL code

have to regen, the binary format has changed
This commit is contained in:
Dustin Carlino 2020-08-08 16:09:36 -07:00
parent 84e913a642
commit d1e9e38e82
32 changed files with 295 additions and 294 deletions

View File

@ -1,4 +1,4 @@
use crate::reader::{Document, Member, NodeID, Relation, RelationID, WayID}; use crate::reader::{Document, Relation};
use crate::Options; use crate::Options;
use abstutil::{retain_btreemap, Tags, Timer}; use abstutil::{retain_btreemap, Tags, Timer};
use geom::{HashablePt2D, PolyLine, Polygon, Pt2D, Ring}; use geom::{HashablePt2D, PolyLine, Polygon, Pt2D, Ring};
@ -8,6 +8,7 @@ use map_model::raw::{
RawParkingLot, RawRoad, RestrictionType, RawParkingLot, RawRoad, RestrictionType,
}; };
use map_model::{osm, AreaType}; use map_model::{osm, AreaType};
use osm::{NodeID, OsmID, RelationID, WayID};
use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::error::Error; use std::error::Error;
@ -137,7 +138,9 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
if is_bldg(&way.tags) { if is_bldg(&way.tags) {
map.buildings.insert( map.buildings.insert(
OriginalBuilding { osm_way_id: id.0 }, OriginalBuilding {
osm_id: OsmID::Way(id),
},
RawBuilding { RawBuilding {
polygon, polygon,
public_garage_name: None, public_garage_name: None,
@ -149,7 +152,7 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
} else if let Some(at) = get_area_type(&way.tags) { } else if let Some(at) = get_area_type(&way.tags) {
map.areas.push(RawArea { map.areas.push(RawArea {
area_type: at, area_type: at,
osm_id: id.0, osm_id: OsmID::Way(id),
polygon, polygon,
osm_tags: way.tags.clone(), osm_tags: way.tags.clone(),
}); });
@ -157,7 +160,7 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
// TODO Verify parking = surface or handle other cases? // TODO Verify parking = surface or handle other cases?
map.parking_lots.push(RawParkingLot { map.parking_lots.push(RawParkingLot {
polygon, polygon,
osm_id: id.0, osm_id: OsmID::Way(id),
}); });
} else if way.tags.is("historic", "memorial") { } else if way.tags.is("historic", "memorial") {
memorial_areas.push(polygon); memorial_areas.push(polygon);
@ -202,7 +205,7 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
{ {
map.areas.push(RawArea { map.areas.push(RawArea {
area_type, area_type,
osm_id: id.0, osm_id: OsmID::Relation(id),
polygon, polygon,
osm_tags: rel.tags.clone(), osm_tags: rel.tags.clone(),
}); });
@ -215,7 +218,7 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
let mut to_way_id: Option<WayID> = None; let mut to_way_id: Option<WayID> = None;
for (role, member) in &rel.members { for (role, member) in &rel.members {
match member { match member {
Member::Way(w) => { OsmID::Way(w) => {
if role == "from" { if role == "from" {
from_way_id = Some(*w); from_way_id = Some(*w);
} else if role == "to" { } else if role == "to" {
@ -224,7 +227,7 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
via_way_id = Some(*w); via_way_id = Some(*w);
} }
} }
Member::Node(n) => { OsmID::Node(n) => {
if role == "via" { if role == "via" {
via_node_id = Some(*n); via_node_id = Some(*n);
} }
@ -256,7 +259,9 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
match multipoly_geometry(id, rel, &doc) { match multipoly_geometry(id, rel, &doc) {
Ok(polygon) => { Ok(polygon) => {
map.buildings.insert( map.buildings.insert(
OriginalBuilding { osm_way_id: id.0 }, OriginalBuilding {
osm_id: OsmID::Relation(id),
},
RawBuilding { RawBuilding {
polygon, polygon,
public_garage_name: None, public_garage_name: None,
@ -282,7 +287,7 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
if role != "outer" { if role != "outer" {
continue; continue;
} }
if let Member::Way(w) = member { if let OsmID::Way(w) = member {
if let Ok(ring) = Ring::new(doc.ways[w].pts.clone()) { if let Ok(ring) = Ring::new(doc.ways[w].pts.clone()) {
amenity_areas.push((name.clone(), amenity.clone(), ring.to_polygon())); amenity_areas.push((name.clone(), amenity.clone(), ring.to_polygon()));
} }
@ -292,14 +297,14 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
let mut stops = Vec::new(); let mut stops = Vec::new();
let mut platform: Option<Pt2D> = None; let mut platform: Option<Pt2D> = None;
for (role, member) in &rel.members { for (role, member) in &rel.members {
if let Member::Node(n) = member { if let OsmID::Node(n) = member {
let pt = doc.nodes[n].pt; let pt = doc.nodes[n].pt;
if role == "stop" { if role == "stop" {
stops.push(pt); stops.push(pt);
} else if role == "platform" { } else if role == "platform" {
platform = Some(pt); platform = Some(pt);
} }
} else if let Member::Way(w) = member { } else if let OsmID::Way(w) = member {
if role == "platform" { if role == "platform" {
platform = Some(Pt2D::center(&doc.ways[w].pts)); platform = Some(Pt2D::center(&doc.ways[w].pts));
} }
@ -323,7 +328,7 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
0, 0,
RawArea { RawArea {
area_type: AreaType::Water, area_type: AreaType::Water,
osm_id: -1, osm_id: OsmID::Relation(RelationID(-1)),
polygon, polygon,
osm_tags, osm_tags,
}, },
@ -537,7 +542,7 @@ fn get_multipolygon_members(
) -> Vec<(WayID, Vec<Pt2D>)> { ) -> Vec<(WayID, Vec<Pt2D>)> {
let mut pts_per_way = Vec::new(); let mut pts_per_way = Vec::new();
for (role, member) in &rel.members { for (role, member) in &rel.members {
if let Member::Way(w) = member { if let OsmID::Way(w) = member {
if role == "outer" { if role == "outer" {
pts_per_way.push((*w, doc.ways[w].pts.clone())); pts_per_way.push((*w, doc.ways[w].pts.clone()));
} else { } else {
@ -676,7 +681,7 @@ fn extract_route(
let mut all_pts = Vec::new(); let mut all_pts = Vec::new();
for (role, member) in &rel.members { for (role, member) in &rel.members {
if role == "stop" { if role == "stop" {
if let Member::Node(n) = member { if let OsmID::Node(n) = member {
let node = &doc.nodes[n]; let node = &doc.nodes[n];
stops.push(RawBusStop { stops.push(RawBusStop {
name: node name: node
@ -690,7 +695,7 @@ fn extract_route(
} }
} else if role == "platform" { } else if role == "platform" {
let (platform_name, pt) = match member { let (platform_name, pt) = match member {
Member::Node(n) => { OsmID::Node(n) => {
let node = &doc.nodes[n]; let node = &doc.nodes[n];
( (
node.tags node.tags
@ -700,7 +705,7 @@ fn extract_route(
node.pt, node.pt,
) )
} }
Member::Way(w) => { OsmID::Way(w) => {
let way = &doc.ways[w]; let way = &doc.ways[w];
( (
way.tags way.tags
@ -713,10 +718,10 @@ fn extract_route(
_ => continue, _ => continue,
}; };
platforms.insert(platform_name, pt); platforms.insert(platform_name, pt);
} else if let Member::Way(w) = member { } else if let OsmID::Way(w) = member {
// The order of nodes might be wrong, doesn't matter // The order of nodes might be wrong, doesn't matter
for n in &doc.ways[w].nodes { for n in &doc.ways[w].nodes {
all_pts.push(OriginalIntersection { osm_node_id: n.0 }); all_pts.push(OriginalIntersection { osm_node_id: *n });
} }
} }
} }
@ -758,7 +763,7 @@ fn extract_route(
full_name, full_name,
short_name, short_name,
is_bus, is_bus,
osm_rel_id: rel_id.0, osm_rel_id: rel_id,
gtfs_trip_marker: rel.tags.get("gtfs:trip_marker").cloned(), gtfs_trip_marker: rel.tags.get("gtfs:trip_marker").cloned(),
stops: keep_stops, stops: keep_stops,
border_start: None, border_start: None,
@ -775,7 +780,7 @@ fn multipoly_geometry(
let mut outer: Vec<Vec<Pt2D>> = Vec::new(); let mut outer: Vec<Vec<Pt2D>> = Vec::new();
let mut inner: Vec<Vec<Pt2D>> = Vec::new(); let mut inner: Vec<Vec<Pt2D>> = Vec::new();
for (role, member) in &rel.members { for (role, member) in &rel.members {
if let Member::Way(w) = member { if let OsmID::Way(w) = member {
let mut deduped = doc.ways[w].pts.clone(); let mut deduped = doc.ways[w].pts.clone();
deduped.dedup(); deduped.dedup();
if deduped.len() < 3 { if deduped.len() < 3 {

View File

@ -23,7 +23,7 @@ pub fn apply_parking(map: &mut RawMap, opts: &Options, timer: &mut Timer) {
&& r.osm_tags && r.osm_tags
.is_any(osm::HIGHWAY, vec!["residential", "tertiary"]) .is_any(osm::HIGHWAY, vec!["residential", "tertiary"])
&& !r.osm_tags.is("foot", "no") && !r.osm_tags.is("foot", "no")
&& id.osm_way_id % 100 <= pct && id.osm_way_id.0 % 100 <= pct
&& PolyLine::unchecked_new(r.center_points.clone()).length() && PolyLine::unchecked_new(r.center_points.clone()).length()
>= Distance::meters(20.0) >= Distance::meters(20.0)
{ {

View File

@ -1,8 +1,8 @@
use abstutil::{prettyprint_usize, slurp_file, Tags, Timer}; use abstutil::{prettyprint_usize, slurp_file, Tags, Timer};
use geom::{GPSBounds, LonLat, Pt2D}; use geom::{GPSBounds, LonLat, Pt2D};
use map_model::osm::{NodeID, OsmID, RelationID, WayID};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::error::Error; use std::error::Error;
use std::fmt;
// References to missing objects are just filtered out. // References to missing objects are just filtered out.
// Per https://wiki.openstreetmap.org/wiki/OSM_XML#Certainties_and_Uncertainties, we assume // Per https://wiki.openstreetmap.org/wiki/OSM_XML#Certainties_and_Uncertainties, we assume
@ -10,7 +10,7 @@ use std::fmt;
// //
// TODO Filter out visible=false // TODO Filter out visible=false
// TODO NodeID, WayID, RelationID are nice. Plumb forward through map_model. // TODO NodeID, WayID, RelationID are nice. Plumb forward through map_model.
// TODO Replicate IDs in each object, and change Member to just hold a reference to the object // TODO Replicate IDs in each object, and change members to just hold a reference to the object
// (which is guaranteed to exist). // (which is guaranteed to exist).
pub struct Document { pub struct Document {
@ -35,13 +35,7 @@ pub struct Way {
pub struct Relation { pub struct Relation {
pub tags: Tags, pub tags: Tags,
// Role, member // Role, member
pub members: Vec<(String, Member)>, pub members: Vec<(String, OsmID)>,
}
pub enum Member {
Node(NodeID),
Way(WayID),
Relation(RelationID),
} }
pub fn read( pub fn read(
@ -145,7 +139,7 @@ pub fn read(
if !doc.nodes.contains_key(&n) { if !doc.nodes.contains_key(&n) {
continue; continue;
} }
Member::Node(n) OsmID::Node(n)
} }
"way" => { "way" => {
let w = let w =
@ -153,7 +147,7 @@ pub fn read(
if !doc.ways.contains_key(&w) { if !doc.ways.contains_key(&w) {
continue; continue;
} }
Member::Way(w) OsmID::Way(w)
} }
"relation" => { "relation" => {
let r = RelationID( let r = RelationID(
@ -162,7 +156,7 @@ pub fn read(
if !doc.relations.contains_key(&r) { if !doc.relations.contains_key(&r) {
continue; continue;
} }
Member::Relation(r) OsmID::Relation(r)
} }
_ => continue, _ => continue,
}; };
@ -212,26 +206,3 @@ fn scrape_bounds(doc: &roxmltree::Document) -> GPSBounds {
} }
b b
} }
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct NodeID(pub i64);
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct WayID(pub i64);
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct RelationID(pub i64);
impl fmt::Display for NodeID {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "https://www.openstreetmap.org/node/{}", self.0)
}
}
impl fmt::Display for WayID {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "https://www.openstreetmap.org/way/{}", self.0)
}
}
impl fmt::Display for RelationID {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "https://www.openstreetmap.org/relation/{}", self.0)
}
}

View File

@ -24,7 +24,7 @@ pub fn split_up_roads(
if count == 2 || idx == 0 || idx == r.center_points.len() - 1 { if count == 2 || idx == 0 || idx == r.center_points.len() - 1 {
if !pt_to_intersection.contains_key(&pt) { if !pt_to_intersection.contains_key(&pt) {
let id = OriginalIntersection { let id = OriginalIntersection {
osm_node_id: input.osm_node_ids[&pt].0, osm_node_id: input.osm_node_ids[&pt],
}; };
pt_to_intersection.insert(pt, id); pt_to_intersection.insert(pt, id);
} }
@ -76,7 +76,7 @@ pub fn split_up_roads(
// Start a new road // Start a new road
map.roads.insert( map.roads.insert(
OriginalRoad { OriginalRoad {
osm_way_id: osm_way_id.0, osm_way_id: *osm_way_id,
i1, i1,
i2: *i2, i2: *i2,
}, },
@ -95,13 +95,13 @@ pub fn split_up_roads(
let mut restrictions = Vec::new(); let mut restrictions = Vec::new();
for (restriction, from_osm, via_osm, to_osm) in input.simple_turn_restrictions { for (restriction, from_osm, via_osm, to_osm) in input.simple_turn_restrictions {
let roads = map.roads_per_intersection(OriginalIntersection { let roads = map.roads_per_intersection(OriginalIntersection {
osm_node_id: via_osm.0, osm_node_id: via_osm,
}); });
// If some of the roads are missing, they were likely filtered out -- usually service // If some of the roads are missing, they were likely filtered out -- usually service
// roads. // roads.
if let (Some(from), Some(to)) = ( if let (Some(from), Some(to)) = (
roads.iter().find(|r| r.osm_way_id == from_osm.0), roads.iter().find(|r| r.osm_way_id == from_osm),
roads.iter().find(|r| r.osm_way_id == to_osm.0), roads.iter().find(|r| r.osm_way_id == to_osm),
) { ) {
restrictions.push((*from, restriction, *to)); restrictions.push((*from, restriction, *to));
} }
@ -121,7 +121,7 @@ pub fn split_up_roads(
let via_candidates: Vec<OriginalRoad> = map let via_candidates: Vec<OriginalRoad> = map
.roads .roads
.keys() .keys()
.filter(|r| r.osm_way_id == via_osm.0) .filter(|r| r.osm_way_id == via_osm)
.cloned() .cloned()
.collect(); .collect();
if via_candidates.len() != 1 { if via_candidates.len() != 1 {
@ -138,12 +138,12 @@ pub fn split_up_roads(
.roads_per_intersection(via.i1) .roads_per_intersection(via.i1)
.into_iter() .into_iter()
.chain(map.roads_per_intersection(via.i2).into_iter()) .chain(map.roads_per_intersection(via.i2).into_iter())
.find(|r| r.osm_way_id == from_osm.0); .find(|r| r.osm_way_id == from_osm);
let maybe_to = map let maybe_to = map
.roads_per_intersection(via.i1) .roads_per_intersection(via.i1)
.into_iter() .into_iter()
.chain(map.roads_per_intersection(via.i2).into_iter()) .chain(map.roads_per_intersection(via.i2).into_iter())
.find(|r| r.osm_way_id == to_osm.0); .find(|r| r.osm_way_id == to_osm);
match (maybe_from, maybe_to) { match (maybe_from, maybe_to) {
(Some(from), Some(to)) => { (Some(from), Some(to)) => {
complicated_restrictions.push((from, via, to)); complicated_restrictions.push((from, via, to));

View File

@ -9,16 +9,16 @@ data/input/krakow/footways.bin,017e85fd6da69b67a1a7a790506f52ff,https://www.drop
data/input/krakow/osm/krakow_center.osm,b914bbcd42a7f769a40a90970cea35f2,https://www.dropbox.com/s/pf3avtszpw732jd/krakow_center.osm.zip?dl=0 data/input/krakow/osm/krakow_center.osm,b914bbcd42a7f769a40a90970cea35f2,https://www.dropbox.com/s/pf3avtszpw732jd/krakow_center.osm.zip?dl=0
data/input/krakow/osm/malopolskie-latest.osm.pbf,9505917bbacc478177e36605e89b6d77,https://www.dropbox.com/s/vehjfvwx25v1qnd/malopolskie-latest.osm.pbf.zip?dl=0 data/input/krakow/osm/malopolskie-latest.osm.pbf,9505917bbacc478177e36605e89b6d77,https://www.dropbox.com/s/vehjfvwx25v1qnd/malopolskie-latest.osm.pbf.zip?dl=0
data/input/krakow/service_roads.bin,a6a5d22bb3dba66b5a4cad72f6842eb9,https://www.dropbox.com/s/is31c2ejl8nun28/service_roads.bin.zip?dl=0 data/input/krakow/service_roads.bin,a6a5d22bb3dba66b5a4cad72f6842eb9,https://www.dropbox.com/s/is31c2ejl8nun28/service_roads.bin.zip?dl=0
data/input/raw_maps/ballard.bin,422675e5ae0054651a3dc1f307c8bfbb,https://www.dropbox.com/s/bhekalw3smrs88p/ballard.bin.zip?dl=0 data/input/raw_maps/ballard.bin,6fdacf6a9503a4bdbe71140688486e53,https://www.dropbox.com/s/2eouht2x3z6scl9/ballard.bin.zip?dl=0
data/input/raw_maps/berlin_center.bin,55f7855f1be26430a46c8bbed74a6789,https://www.dropbox.com/s/g09clxwc5o8bqfk/berlin_center.bin.zip?dl=0 data/input/raw_maps/berlin_center.bin,9ccc8a91ebe62b0645c93cc681cffb79,https://www.dropbox.com/s/r9hc4uf3aerfnyb/berlin_center.bin.zip?dl=0
data/input/raw_maps/downtown.bin,2c84ccaa228df16ddef50e5c67d22c82,https://www.dropbox.com/s/jya9xkj38cshwj9/downtown.bin.zip?dl=0 data/input/raw_maps/downtown.bin,65d8baaaafb6ab00fb8ca034ff1d8402,https://www.dropbox.com/s/vlg509s9y3d321x/downtown.bin.zip?dl=0
data/input/raw_maps/huge_seattle.bin,e0b63d95fae06b9c6c9a9afc587270a6,https://www.dropbox.com/s/r7l2y22iyvla5b8/huge_seattle.bin.zip?dl=0 data/input/raw_maps/huge_seattle.bin,e73b9293a95f359173e3e81cd232e8e1,https://www.dropbox.com/s/6vhu9jziquel7ha/huge_seattle.bin.zip?dl=0
data/input/raw_maps/krakow_center.bin,a6c557888cf3211fce8f025150c49734,https://www.dropbox.com/s/y7hwvd547soiwan/krakow_center.bin.zip?dl=0 data/input/raw_maps/krakow_center.bin,4cd3c941b7d8704edb116ae2f8d1ed92,https://www.dropbox.com/s/qd5tm0xm9nqr0hs/krakow_center.bin.zip?dl=0
data/input/raw_maps/lakeslice.bin,b71cf35251603a6a787a065b8a37f6f3,https://www.dropbox.com/s/3ko1beo4uv2j49p/lakeslice.bin.zip?dl=0 data/input/raw_maps/lakeslice.bin,d221270f016a4324b871c38d1e395519,https://www.dropbox.com/s/xvp1a1nn6ck6vxz/lakeslice.bin.zip?dl=0
data/input/raw_maps/montlake.bin,11e3f20b67fb76359dc69737a039e8d1,https://www.dropbox.com/s/h9mymsai9ia9yde/montlake.bin.zip?dl=0 data/input/raw_maps/montlake.bin,4af4c6b0e4babb872670017be935ba56,https://www.dropbox.com/s/r9887v30x9k0su9/montlake.bin.zip?dl=0
data/input/raw_maps/south_seattle.bin,c1a531ccb0874a3fafaa48952ec58d29,https://www.dropbox.com/s/y7d3mcnqp4u50b6/south_seattle.bin.zip?dl=0 data/input/raw_maps/south_seattle.bin,8d5cedc6103459e4f84363904af239cc,https://www.dropbox.com/s/r39yyvy2u3e39fs/south_seattle.bin.zip?dl=0
data/input/raw_maps/udistrict.bin,5f1c93a1d7939af3995359c074b11bbc,https://www.dropbox.com/s/7doajjusb5if43q/udistrict.bin.zip?dl=0 data/input/raw_maps/udistrict.bin,7d16bcb9e17de9d3ad5ae694fd3cc5d8,https://www.dropbox.com/s/7zbpiyu0x1rfgag/udistrict.bin.zip?dl=0
data/input/raw_maps/west_seattle.bin,b6c92b97d266d644368c9f6e5f9ce812,https://www.dropbox.com/s/oa5gpkut51mc6vj/west_seattle.bin.zip?dl=0 data/input/raw_maps/west_seattle.bin,a20d2aaedf550cc0e6e1d58cf5b8f5da,https://www.dropbox.com/s/0mktaqiu8hq4rlu/west_seattle.bin.zip?dl=0
data/input/screenshots/downtown.zip,8759a23f7729e51f0a27ca781a1b5cbb,https://www.dropbox.com/s/qawd35wz62m2acl/downtown.zip.zip?dl=0 data/input/screenshots/downtown.zip,8759a23f7729e51f0a27ca781a1b5cbb,https://www.dropbox.com/s/qawd35wz62m2acl/downtown.zip.zip?dl=0
data/input/screenshots/krakow_center.zip,44b8e8301931e97fb87f928676723a6d,https://www.dropbox.com/s/azea6v6mnxbe0vc/krakow_center.zip.zip?dl=0 data/input/screenshots/krakow_center.zip,44b8e8301931e97fb87f928676723a6d,https://www.dropbox.com/s/azea6v6mnxbe0vc/krakow_center.zip.zip?dl=0
data/input/screenshots/lakeslice.zip,b36f19b5c44b51def26c2056f03bc5a1,https://www.dropbox.com/s/z0z96lsn7bunqfy/lakeslice.zip.zip?dl=0 data/input/screenshots/lakeslice.zip,b36f19b5c44b51def26c2056f03bc5a1,https://www.dropbox.com/s/z0z96lsn7bunqfy/lakeslice.zip.zip?dl=0
@ -51,30 +51,30 @@ data/input/seattle/osm/south_seattle.osm,f1243c78fe237bb55cc7b8c38904df0e,https:
data/input/seattle/osm/udistrict.osm,05d718bca1305fbcedffb0c9d3c808d8,https://www.dropbox.com/s/yy1j6b6b8bj7wn1/udistrict.osm.zip?dl=0 data/input/seattle/osm/udistrict.osm,05d718bca1305fbcedffb0c9d3c808d8,https://www.dropbox.com/s/yy1j6b6b8bj7wn1/udistrict.osm.zip?dl=0
data/input/seattle/osm/washington-latest.osm.pbf,676dbdf08ebd8303f85eda7cb7de5833,https://www.dropbox.com/s/2ogkqpqnq8zjr1t/washington-latest.osm.pbf.zip?dl=0 data/input/seattle/osm/washington-latest.osm.pbf,676dbdf08ebd8303f85eda7cb7de5833,https://www.dropbox.com/s/2ogkqpqnq8zjr1t/washington-latest.osm.pbf.zip?dl=0
data/input/seattle/osm/west_seattle.osm,abee01cc1d034a9b12a984d219393dcc,https://www.dropbox.com/s/wwt9h4kqvx4vg4y/west_seattle.osm.zip?dl=0 data/input/seattle/osm/west_seattle.osm,abee01cc1d034a9b12a984d219393dcc,https://www.dropbox.com/s/wwt9h4kqvx4vg4y/west_seattle.osm.zip?dl=0
data/input/seattle/parcels.bin,32d515292c9298358eda739e715f609f,https://www.dropbox.com/s/3fz3eb9xlxu3xbm/parcels.bin.zip?dl=0 data/input/seattle/parcels.bin,4f21c1af49fbbcb35c2750c7dbb1ba55,https://www.dropbox.com/s/ef5yi74n0350i3l/parcels.bin.zip?dl=0
data/input/seattle/parcels_urbansim.txt,db63d7d606e8702d12f9399e87e6a00f,https://www.dropbox.com/s/6g8rbsf200dssj3/parcels_urbansim.txt.zip?dl=0 data/input/seattle/parcels_urbansim.txt,db63d7d606e8702d12f9399e87e6a00f,https://www.dropbox.com/s/6g8rbsf200dssj3/parcels_urbansim.txt.zip?dl=0
data/input/seattle/popdat.bin,ba74425bdd7e0435d16714342ddc1f7f,https://www.dropbox.com/s/o731ipwxu91ef0b/popdat.bin.zip?dl=0 data/input/seattle/popdat.bin,113028930e3dada483651a8d3fe169ec,https://www.dropbox.com/s/eddccrdrhz10qo3/popdat.bin.zip?dl=0
data/input/seattle/service_roads.bin,771cffc34dfbca9f941a90adf553be5d,https://www.dropbox.com/s/61o9prqoa7f52q7/service_roads.bin.zip?dl=0 data/input/seattle/service_roads.bin,771cffc34dfbca9f941a90adf553be5d,https://www.dropbox.com/s/61o9prqoa7f52q7/service_roads.bin.zip?dl=0
data/input/seattle/trips_2014.csv,d4a8e733045b28c0385fb81359d6df03,https://www.dropbox.com/s/5ppravwmk6bf20d/trips_2014.csv.zip?dl=0 data/input/seattle/trips_2014.csv,d4a8e733045b28c0385fb81359d6df03,https://www.dropbox.com/s/5ppravwmk6bf20d/trips_2014.csv.zip?dl=0
data/system/cities/seattle.bin,4c23d8a7fbf0981a65c7e9499a1c7185,https://www.dropbox.com/s/1vg3138khp81kyi/seattle.bin.zip?dl=0 data/system/cities/seattle.bin,4c23d8a7fbf0981a65c7e9499a1c7185,https://www.dropbox.com/s/1vg3138khp81kyi/seattle.bin.zip?dl=0
data/system/maps/ballard.bin,79ee86eee63666b74c1a616e7f58db45,https://www.dropbox.com/s/98wdkhwohiv982c/ballard.bin.zip?dl=0 data/system/maps/ballard.bin,e9d27fd4414a89528fbbd716b3b4f70a,https://www.dropbox.com/s/v7a85gyyx6cfmay/ballard.bin.zip?dl=0
data/system/maps/berlin_center.bin,065b4979987b228e19fe63adb5ee3856,https://www.dropbox.com/s/kivu0qhpdl2dfo6/berlin_center.bin.zip?dl=0 data/system/maps/berlin_center.bin,b06939686bc5150b5782aad19cc77462,https://www.dropbox.com/s/25eqv5i9vbd0f4u/berlin_center.bin.zip?dl=0
data/system/maps/downtown.bin,b502ad91c4aa90368ed6b40545aa0118,https://www.dropbox.com/s/okqy9d2lvpclbzt/downtown.bin.zip?dl=0 data/system/maps/downtown.bin,7507f28a8007734815230cd6af6cf683,https://www.dropbox.com/s/u5l2ij8c16ngyml/downtown.bin.zip?dl=0
data/system/maps/huge_seattle.bin,37a3d1587ab66bececb95ad1002e28cf,https://www.dropbox.com/s/8u0mw81isncs2t8/huge_seattle.bin.zip?dl=0 data/system/maps/huge_seattle.bin,172b664b7a2dae82170223646f10faa8,https://www.dropbox.com/s/7o0ljq7fd1yb8ao/huge_seattle.bin.zip?dl=0
data/system/maps/krakow_center.bin,ae135fdfc30743833c71d9c2b6ecf3e3,https://www.dropbox.com/s/5o2u3bt4d58qdi7/krakow_center.bin.zip?dl=0 data/system/maps/krakow_center.bin,43101257967295302234a3b0f52f0bc6,https://www.dropbox.com/s/sg4ibnev7pejfch/krakow_center.bin.zip?dl=0
data/system/maps/lakeslice.bin,6476b23467e7433ffb46e93ba61331a9,https://www.dropbox.com/s/f3nlxvinuo03gzt/lakeslice.bin.zip?dl=0 data/system/maps/lakeslice.bin,49d875187fc14ef2fc23576efdb66aca,https://www.dropbox.com/s/liwg9nsdxpnrsl8/lakeslice.bin.zip?dl=0
data/system/maps/montlake.bin,75d2fa79912db2d287b7bb3e68904f1e,https://www.dropbox.com/s/sfrnr6gajffvaxa/montlake.bin.zip?dl=0 data/system/maps/montlake.bin,fd25c4be0064852b1592057f707ce6c5,https://www.dropbox.com/s/z8e9906huko9ly7/montlake.bin.zip?dl=0
data/system/maps/south_seattle.bin,da9e3dc5019108e21f77eb40509ec155,https://www.dropbox.com/s/srlxi4hme132aec/south_seattle.bin.zip?dl=0 data/system/maps/south_seattle.bin,6166c1aa5878f3b40de329bb3807390d,https://www.dropbox.com/s/tz24rci6jwz14lz/south_seattle.bin.zip?dl=0
data/system/maps/udistrict.bin,10e8534ddca4a422d929a0cbb0b97368,https://www.dropbox.com/s/tefrx95x051eoir/udistrict.bin.zip?dl=0 data/system/maps/udistrict.bin,4bb601a033e307b65f205aea53af7aaf,https://www.dropbox.com/s/46siyvcd91lssnp/udistrict.bin.zip?dl=0
data/system/maps/west_seattle.bin,8413879e624c19d52a8437439f4aa444,https://www.dropbox.com/s/aqul2662x8xzdnm/west_seattle.bin.zip?dl=0 data/system/maps/west_seattle.bin,071fdeb39c1be10ebb676b6bdaba7fd8,https://www.dropbox.com/s/mz5jkqsaztl2ik6/west_seattle.bin.zip?dl=0
data/system/prebaked_results/lakeslice/weekday.bin,0e60d59420a34f648f17799895c4aa78,https://www.dropbox.com/s/eeeo9pl8aq38aw5/weekday.bin.zip?dl=0 data/system/prebaked_results/lakeslice/weekday.bin,3f4647f2d0f1e76d1b8dbdaaa6d737a6,https://www.dropbox.com/s/oacu1ou8yh0zhe0/weekday.bin.zip?dl=0
data/system/prebaked_results/montlake/car vs bike contention.bin,faa041af70a41bb8fcacd3dfd7a7d467,https://www.dropbox.com/s/jefg0ikjy9dsrdd/car%20vs%20bike%20contention.bin.zip?dl=0 data/system/prebaked_results/montlake/car vs bike contention.bin,faa041af70a41bb8fcacd3dfd7a7d467,https://www.dropbox.com/s/jefg0ikjy9dsrdd/car%20vs%20bike%20contention.bin.zip?dl=0
data/system/prebaked_results/montlake/weekday.bin,06746b72ec456e69c4500edf0b06d82f,https://www.dropbox.com/s/bcuc4gnmq3sxefo/weekday.bin.zip?dl=0 data/system/prebaked_results/montlake/weekday.bin,30c99765b3c9199172dcf9b0a3643c7a,https://www.dropbox.com/s/v8jborb259zj5x6/weekday.bin.zip?dl=0
data/system/scenarios/ballard/weekday.bin,8a2165ab31b5a9c3912362f08e0dc2b9,https://www.dropbox.com/s/w9g4tanopzyaza4/weekday.bin.zip?dl=0 data/system/scenarios/ballard/weekday.bin,af52fa3a40c4594b262e5e0e898c6091,https://www.dropbox.com/s/xfs8n9s7wkuzms1/weekday.bin.zip?dl=0
data/system/scenarios/downtown/weekday.bin,b38bb955b90a6356a3033ba1e0cec942,https://www.dropbox.com/s/8cmr13ll9bcekmd/weekday.bin.zip?dl=0 data/system/scenarios/downtown/weekday.bin,6ff9f0fdd2a940624b5c3ff43f17cdcd,https://www.dropbox.com/s/1ilmwyojskakdsq/weekday.bin.zip?dl=0
data/system/scenarios/huge_seattle/weekday.bin,64f059dc127da745673a72c6b3b9583a,https://www.dropbox.com/s/3xzp1wxq6shgabg/weekday.bin.zip?dl=0 data/system/scenarios/huge_seattle/weekday.bin,7ad74a845affe1f1fcae00364ddeed9c,https://www.dropbox.com/s/m55682sqttuasdz/weekday.bin.zip?dl=0
data/system/scenarios/lakeslice/weekday.bin,d6e6e790b477655b6edd82524d679064,https://www.dropbox.com/s/7653v8k8bzm49bp/weekday.bin.zip?dl=0 data/system/scenarios/lakeslice/weekday.bin,57966c48908ef1d482d15ba68a41e0ed,https://www.dropbox.com/s/4gx5sjob61b5lgd/weekday.bin.zip?dl=0
data/system/scenarios/montlake/weekday.bin,888c0f0009cf6867939c410b798563e1,https://www.dropbox.com/s/7qgfn453ad149cz/weekday.bin.zip?dl=0 data/system/scenarios/montlake/weekday.bin,db3293db2a7f88c82604a1f8e648077c,https://www.dropbox.com/s/drm388cogdd0348/weekday.bin.zip?dl=0
data/system/scenarios/south_seattle/weekday.bin,de52bd964f6e3f48ff86ebf2a664d195,https://www.dropbox.com/s/covz7zncujqmmzh/weekday.bin.zip?dl=0 data/system/scenarios/south_seattle/weekday.bin,9ea93086ada998426c11027cd0ea125b,https://www.dropbox.com/s/z8e3a4qo2fv1itd/weekday.bin.zip?dl=0
data/system/scenarios/udistrict/weekday.bin,1c5c80e1abe4b16db4be497915921820,https://www.dropbox.com/s/4zshiz2lqinw2df/weekday.bin.zip?dl=0 data/system/scenarios/udistrict/weekday.bin,001a34c107c980fdba6139d5e2557cc5,https://www.dropbox.com/s/bhjb7r5fs2ll53a/weekday.bin.zip?dl=0
data/system/scenarios/west_seattle/weekday.bin,fad7c87544e370120758a391a55f9ac6,https://www.dropbox.com/s/fpf9kml3uanyejl/weekday.bin.zip?dl=0 data/system/scenarios/west_seattle/weekday.bin,e3fda5838068120ebe819b214edd1773,https://www.dropbox.com/s/2ykr20egt4ufqi2/weekday.bin.zip?dl=0

View File

@ -56,7 +56,7 @@ impl ViewKML {
.map .map
.all_buildings() .all_buildings()
.iter() .iter()
.map(|b| (b.osm_way_id.to_string(), b.id)) .map(|b| (b.orig_id.osm_id.inner().to_string(), b.id))
.collect(); .collect();
let cs = &app.cs; let cs = &app.cs;
let objects: Vec<Object> = timer let objects: Vec<Object> = timer

View File

@ -9,6 +9,7 @@ use ezgui::{
}; };
use geom::{Distance, FindClosest, PolyLine, Polygon}; use geom::{Distance, FindClosest, PolyLine, Polygon};
use map_model::{osm, RoadID}; use map_model::{osm, RoadID};
use osm::WayID;
use sim::DontDrawAgents; use sim::DontDrawAgents;
use std::collections::{BTreeMap, HashSet}; use std::collections::{BTreeMap, HashSet};
use std::error::Error; use std::error::Error;
@ -21,7 +22,7 @@ pub struct ParkingMapper {
show: Show, show: Show,
selected: Option<(HashSet<RoadID>, Drawable)>, selected: Option<(HashSet<RoadID>, Drawable)>,
data: BTreeMap<i64, Value>, data: BTreeMap<WayID, Value>,
} }
#[derive(Clone, Copy, PartialEq, Debug)] #[derive(Clone, Copy, PartialEq, Debug)]
@ -51,7 +52,7 @@ impl ParkingMapper {
ctx: &mut EventCtx, ctx: &mut EventCtx,
app: &mut App, app: &mut App,
show: Show, show: Show,
data: BTreeMap<i64, Value>, data: BTreeMap<WayID, Value>,
) -> Box<dyn State> { ) -> Box<dyn State> {
app.opts.min_zoom_for_detail = 2.0; app.opts.min_zoom_for_detail = 2.0;
@ -304,7 +305,7 @@ impl State for ParkingMapper {
if let Some((ref roads, _)) = self.selected { if let Some((ref roads, _)) = self.selected {
if ctx.input.key_pressed(Key::O) { if ctx.input.key_pressed(Key::O) {
open_browser(format!( open_browser(format!(
"https://www.openstreetmap.org/way/{}", "{}",
app.primary app.primary
.map .map
.get_r(*roads.iter().next().unwrap()) .get_r(*roads.iter().next().unwrap())
@ -389,8 +390,8 @@ impl State for ParkingMapper {
struct ChangeWay { struct ChangeWay {
composite: Composite, composite: Composite,
draw: Drawable, draw: Drawable,
osm_way_id: i64, osm_way_id: WayID,
data: BTreeMap<i64, Value>, data: BTreeMap<WayID, Value>,
show: Show, show: Show,
} }
@ -400,7 +401,7 @@ impl ChangeWay {
app: &App, app: &App,
selected: &HashSet<RoadID>, selected: &HashSet<RoadID>,
show: Show, show: Show,
data: BTreeMap<i64, Value>, data: BTreeMap<WayID, Value>,
) -> Box<dyn State> { ) -> Box<dyn State> {
let map = &app.primary.map; let map = &app.primary.map;
let osm_way_id = map let osm_way_id = map
@ -507,7 +508,7 @@ impl State for ChangeWay {
} }
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
fn generate_osmc(_: &BTreeMap<i64, Value>, _: bool, _: &mut Timer) -> Result<(), Box<dyn Error>> { fn generate_osmc(_: &BTreeMap<WayID, Value>, _: bool, _: &mut Timer) -> Result<(), Box<dyn Error>> {
Err("Woops, mapping mode isn't supported on the web yet" Err("Woops, mapping mode isn't supported on the web yet"
.to_string() .to_string()
.into()) .into())
@ -515,7 +516,7 @@ fn generate_osmc(_: &BTreeMap<i64, Value>, _: bool, _: &mut Timer) -> Result<(),
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
fn generate_osmc( fn generate_osmc(
data: &BTreeMap<i64, Value>, data: &BTreeMap<WayID, Value>,
in_seattle: bool, in_seattle: bool,
timer: &mut Timer, timer: &mut Timer,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
@ -527,7 +528,7 @@ fn generate_osmc(
continue; continue;
} }
let url = format!("https://api.openstreetmap.org/api/0.6/way/{}", way); let url = format!("https://api.openstreetmap.org/api/0.6/way/{}", way.0);
timer.note(format!("Fetching {}", url)); timer.note(format!("Fetching {}", url));
let resp = reqwest::blocking::get(&url)?.text()?; let resp = reqwest::blocking::get(&url)?.text()?;
let mut tree = xmltree::Element::parse(resp.as_bytes())? let mut tree = xmltree::Element::parse(resp.as_bytes())?

View File

@ -18,7 +18,7 @@ pub fn info(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BuildingID
kv.push(("Name", name.clone())); kv.push(("Name", name.clone()));
} }
if app.opts.dev { if app.opts.dev {
kv.push(("OSM ID", format!("{}", b.osm_way_id))); kv.push(("OSM ID", format!("{}", b.orig_id.osm_id.inner())));
} }
let num_spots = b.num_parking_spots(); let num_spots = b.num_parking_spots();

View File

@ -175,10 +175,7 @@ pub fn route(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRouteI
if app.opts.dev { if app.opts.dev {
rows.push(Btn::text_bg1("Open OSM relation").build( rows.push(Btn::text_bg1("Open OSM relation").build(
ctx, ctx,
format!( format!("open {}", route.osm_rel_id),
"open https://www.openstreetmap.org/relation/{}",
route.osm_rel_id
),
None, None,
)); ));
} }

View File

@ -27,16 +27,11 @@ pub fn info(ctx: &EventCtx, app: &App, details: &mut Details, id: IntersectionID
rows.push(txt.draw(ctx)); rows.push(txt.draw(ctx));
if app.opts.dev { if app.opts.dev {
rows.push( rows.push(Btn::text_bg1("Open OSM node").build(
Btn::text_bg1(format!("Open OSM node {}", i.orig_id.osm_node_id)).build(
ctx, ctx,
format!( format!("open {}", i.orig_id.osm_node_id),
"open https://www.openstreetmap.org/node/{}",
i.orig_id.osm_node_id
),
None, None,
), ));
);
} }
rows rows

View File

@ -131,15 +131,17 @@ pub fn debug(ctx: &EventCtx, app: &App, details: &mut Details, id: LaneID) -> Ve
l.length() l.length()
), ),
)); ));
let pair = r.dir_and_offset(l.id);
kv.push((
"Dir and offset".to_string(),
format!("fwd={}, {}", pair.0, pair.1),
));
rows.extend(make_table(ctx, kv.into_iter())); rows.extend(make_table(ctx, kv.into_iter()));
rows.push(Btn::text_bg1("Open OSM way").build( rows.push(Btn::text_bg1("Open OSM way").build(
ctx, ctx,
format!( format!("open {}", r.orig_id.osm_way_id),
"open https://www.openstreetmap.org/way/{}",
r.orig_id.osm_way_id
),
None, None,
)); ));

View File

@ -353,8 +353,8 @@ pub fn make_crosswalk(batch: &mut GeomBatch, turn: &Turn, map: &Map, cs: &ColorS
fn make_rainbow_crosswalk(batch: &mut GeomBatch, turn: &Turn, map: &Map) -> bool { fn make_rainbow_crosswalk(batch: &mut GeomBatch, turn: &Turn, map: &Map) -> bool {
// TODO The crosswalks aren't tagged in OSM yet. Manually hardcoding some now. // TODO The crosswalks aren't tagged in OSM yet. Manually hardcoding some now.
let node = map.get_i(turn.id.parent).orig_id.osm_node_id; let node = map.get_i(turn.id.parent).orig_id.osm_node_id.0;
let way = map.get_parent(turn.id.src).orig_id.osm_way_id; let way = map.get_parent(turn.id.src).orig_id.osm_way_id.0;
match (node, way) { match (node, way) {
// Broadway and Pine // Broadway and Pine
(53073255, 428246441) | (53073255, 428246441) |

View File

@ -111,7 +111,9 @@ impl TransitRoutes {
let col = vec![ let col = vec![
DashTab::TransitRoutes.picker(ctx, app), DashTab::TransitRoutes.picker(ctx, app),
Line("Transit routes").small_heading().draw(ctx), Line(format!("{} Transit routes", routes.len()))
.small_heading()
.draw(ctx),
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/search.svg"), Widget::draw_svg(ctx, "system/assets/tools/search.svg"),
Autocomplete::new( Autocomplete::new(

View File

@ -16,8 +16,8 @@ use ezgui::{
VerticalAlignment, Widget, VerticalAlignment, Widget,
}; };
use geom::{ArrowCap, Distance, Duration, PolyLine, Polygon, Pt2D, Time}; use geom::{ArrowCap, Distance, Duration, PolyLine, Polygon, Pt2D, Time};
use map_model::raw::{OriginalIntersection, OriginalRoad}; use map_model::raw::{OriginalBuilding, OriginalIntersection, OriginalRoad};
use map_model::{BuildingID, Map, OriginalLane, Position}; use map_model::{osm, BuildingID, Map, OriginalLane, Position};
use sim::{ use sim::{
AgentID, Analytics, BorderSpawnOverTime, CarID, DrivingGoal, IndividTrip, OriginDestination, AgentID, Analytics, BorderSpawnOverTime, CarID, DrivingGoal, IndividTrip, OriginDestination,
PersonID, PersonSpec, Scenario, ScenarioGenerator, SpawnOverTime, SpawnTrip, VehicleType, PersonID, PersonSpec, Scenario, ScenarioGenerator, SpawnOverTime, SpawnTrip, VehicleType,
@ -646,10 +646,10 @@ fn make_bike_lane_scenario(map: &Map) -> ScenarioGenerator {
start_time: Time::START_OF_DAY, start_time: Time::START_OF_DAY,
stop_time: Time::START_OF_DAY + Duration::seconds(10.0), stop_time: Time::START_OF_DAY + Duration::seconds(10.0),
start_from_border: map start_from_border: map
.find_r_by_osm_id(263665925, (2499826475, 53096959)) .find_r_by_osm_id(OriginalRoad::new(263665925, (2499826475, 53096959)))
.unwrap() .unwrap()
.backwards(), .backwards(),
goal: OriginDestination::GotoBldg(map.find_b_by_osm_id(217699501).unwrap()), goal: OriginDestination::GotoBldg(map.find_b_by_osm_id(bldg(217699501)).unwrap()),
}); });
s s
} }
@ -895,7 +895,7 @@ impl TutorialState {
parking_found: false, parking_found: false,
score_delivered: false, score_delivered: false,
fire_station: app.primary.map.find_b_by_osm_id(731238736).unwrap(), fire_station: app.primary.map.find_b_by_osm_id(bldg(731238736)).unwrap(),
}; };
let tool_panel = tool_panel(ctx); let tool_panel = tool_panel(ctx);
@ -913,7 +913,10 @@ impl TutorialState {
state.stages.push( state.stages.push(
Stage::new(Task::Camera) Stage::new(Task::Camera)
.warp_to( .warp_to(
ID::Intersection(map.find_i_by_osm_id(53096945).unwrap()), ID::Intersection(
map.find_i_by_osm_id(OriginalIntersection::new(53096945))
.unwrap(),
),
None, None,
) )
.msg( .msg(
@ -971,7 +974,10 @@ impl TutorialState {
state.stages.push( state.stages.push(
Stage::new(Task::TimeControls) Stage::new(Task::TimeControls)
.warp_to( .warp_to(
ID::Intersection(map.find_i_by_osm_id(53096945).unwrap()), ID::Intersection(
map.find_i_by_osm_id(OriginalIntersection::new(53096945))
.unwrap(),
),
Some(6.5), Some(6.5),
) )
.msg( .msg(
@ -1031,24 +1037,16 @@ impl TutorialState {
Stage::new(Task::Escort) Stage::new(Task::Escort)
// Don't center on where the agents are, be a little offset // Don't center on where the agents are, be a little offset
.warp_to( .warp_to(
ID::Building(map.find_b_by_osm_id(217699780).unwrap()), ID::Building(map.find_b_by_osm_id(bldg(217699780)).unwrap()),
Some(10.0), Some(10.0),
) )
.spawn(Box::new(move |app| { .spawn(Box::new(move |app| {
// Seed a specific target car, and fill up the target building's private // Seed a specific target car, and fill up the target building's private
// parking to force the target to park on-street. // parking to force the target to park on-street.
let map = &app.primary.map; let map = &app.primary.map;
let goal_bldg = map.find_b_by_osm_id(217701875).unwrap(); let goal_bldg = map.find_b_by_osm_id(bldg(217701875)).unwrap();
let start_lane = OriginalLane { let start_lane = OriginalLane {
parent: OriginalRoad { parent: OriginalRoad::new(158782224, (1709145066, 53128052)),
osm_way_id: 158782224,
i1: OriginalIntersection {
osm_node_id: 1709145066,
},
i2: OriginalIntersection {
osm_node_id: 53128052,
},
},
num_fwd: 3, num_fwd: 3,
num_back: 3, num_back: 3,
fwd: false, fwd: false,
@ -1057,15 +1055,7 @@ impl TutorialState {
.from_permanent(map) .from_permanent(map)
.unwrap(); .unwrap();
let lane_near_bldg = OriginalLane { let lane_near_bldg = OriginalLane {
parent: OriginalRoad { parent: OriginalRoad::new(6484869, (53163501, 53069236)),
osm_way_id: 6484869,
i1: OriginalIntersection {
osm_node_id: 53163501,
},
i2: OriginalIntersection {
osm_node_id: 53069236,
},
},
num_fwd: 3, num_fwd: 3,
num_back: 3, num_back: 3,
fwd: true, fwd: true,
@ -1118,7 +1108,13 @@ impl TutorialState {
app.primary.sim.tiny_step(map, &mut app.primary.sim_cb); app.primary.sim.tiny_step(map, &mut app.primary.sim_cb);
// And add some noise // And add some noise
spawn_agents_around(app.primary.map.find_i_by_osm_id(1709145066).unwrap(), app); spawn_agents_around(
app.primary
.map
.find_i_by_osm_id(OriginalIntersection::new(1709145066))
.unwrap(),
app,
);
})) }))
.msg( .msg(
vec!["Alright alright, no need to wear out your spacebar."], vec!["Alright alright, no need to wear out your spacebar."],
@ -1222,7 +1218,7 @@ impl TutorialState {
); );
let bike_lane_scenario = make_bike_lane_scenario(map); let bike_lane_scenario = make_bike_lane_scenario(map);
let bike_lane_focus_pt = map.find_b_by_osm_id(217699496).unwrap(); let bike_lane_focus_pt = map.find_b_by_osm_id(bldg(217699496)).unwrap();
state.stages.push( state.stages.push(
Stage::new(Task::WatchBikes) Stage::new(Task::WatchBikes)
@ -1456,3 +1452,10 @@ fn intro_story(ctx: &mut EventCtx, app: &App) -> Box<dyn State> {
}), }),
) )
} }
// Assumes ways
fn bldg(id: i64) -> OriginalBuilding {
OriginalBuilding {
osm_id: osm::OsmID::Way(osm::WayID(id)),
}
}

View File

@ -1,7 +1,7 @@
use abstutil::{prettyprint_usize, Counter, FileWithProgress, Timer}; use abstutil::{prettyprint_usize, Counter, FileWithProgress, Timer};
use geom::{Distance, Duration, FindClosest, LonLat, Pt2D, Time}; use geom::{Distance, Duration, FindClosest, LonLat, Pt2D, Time};
use kml::{ExtraShape, ExtraShapes}; use kml::{ExtraShape, ExtraShapes};
use map_model::Map; use map_model::{osm, Map};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sim::{OrigPersonID, TripMode}; use sim::{OrigPersonID, TripMode};
use std::collections::{BTreeMap, HashMap, HashSet}; use std::collections::{BTreeMap, HashMap, HashSet};
@ -116,9 +116,9 @@ fn import_parcels(
) -> (HashMap<usize, Endpoint>, BTreeMap<usize, ExtraShape>) { ) -> (HashMap<usize, Endpoint>, BTreeMap<usize, ExtraShape>) {
// TODO I really just want to do polygon containment with a quadtree. FindClosest only does // TODO I really just want to do polygon containment with a quadtree. FindClosest only does
// line-string stuff right now, which'll be weird for the last->first pt line and stuff. // line-string stuff right now, which'll be weird for the last->first pt line and stuff.
let mut closest_bldg: FindClosest<i64> = FindClosest::new(huge_map.get_bounds()); let mut closest_bldg: FindClosest<osm::OsmID> = FindClosest::new(huge_map.get_bounds());
for b in huge_map.all_buildings() { for b in huge_map.all_buildings() {
closest_bldg.add(b.osm_way_id, b.polygon.points()); closest_bldg.add(b.orig_id.osm_id, b.polygon.points());
} }
let mut x_coords: Vec<f64> = Vec::new(); let mut x_coords: Vec<f64> = Vec::new();
@ -201,7 +201,7 @@ fn import_parcels(
attributes.insert("parking".to_string(), offstreet_parking_spaces.to_string()); attributes.insert("parking".to_string(), offstreet_parking_spaces.to_string());
} }
if let Some(b) = osm_building { if let Some(b) = osm_building {
attributes.insert("osm_bldg".to_string(), b.to_string()); attributes.insert("osm_bldg".to_string(), b.inner().to_string());
} }
shapes.insert( shapes.insert(
id, id,
@ -298,7 +298,7 @@ pub struct OrigTrip {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Endpoint { pub struct Endpoint {
pub pos: LonLat, pub pos: LonLat,
pub osm_building: Option<i64>, pub osm_building: Option<osm::OsmID>,
pub parcel_id: usize, pub parcel_id: usize,
} }

View File

@ -1,7 +1,7 @@
use crate::soundcast::popdat::{Endpoint, OrigTrip, PopDat}; use crate::soundcast::popdat::{Endpoint, OrigTrip, PopDat};
use abstutil::{prettyprint_usize, MultiMap, Parallelism, Timer}; use abstutil::{prettyprint_usize, MultiMap, Parallelism, Timer};
use geom::LonLat; use geom::LonLat;
use map_model::{BuildingID, IntersectionID, Map, PathConstraints, PathRequest, PathStep}; use map_model::{osm, BuildingID, IntersectionID, Map, PathConstraints, PathRequest, PathStep};
use sim::{ use sim::{
IndividTrip, OffMapLocation, OrigPersonID, PersonID, PersonSpec, Scenario, SpawnTrip, IndividTrip, OffMapLocation, OrigPersonID, PersonID, PersonSpec, Scenario, SpawnTrip,
TripEndpoint, TripMode, TripEndpoint, TripMode,
@ -20,13 +20,13 @@ fn endpoints(
from: &Endpoint, from: &Endpoint,
to: &Endpoint, to: &Endpoint,
map: &Map, map: &Map,
osm_id_to_bldg: &HashMap<i64, BuildingID>, osm_id_to_bldg: &HashMap<osm::OsmID, BuildingID>,
(in_borders, out_borders): ( (in_borders, out_borders): (
&Vec<(IntersectionID, LonLat)>, &Vec<(IntersectionID, LonLat)>,
&Vec<(IntersectionID, LonLat)>, &Vec<(IntersectionID, LonLat)>,
), ),
constraints: PathConstraints, constraints: PathConstraints,
maybe_huge_map: Option<&(&Map, HashMap<i64, BuildingID>)>, maybe_huge_map: Option<&(&Map, HashMap<osm::OsmID, BuildingID>)>,
) -> Option<(TripEndpoint, TripEndpoint)> { ) -> Option<(TripEndpoint, TripEndpoint)> {
let from_bldg = from let from_bldg = from
.osm_building .osm_building
@ -147,14 +147,14 @@ fn clip_trips(map: &Map, popdat: &PopDat, huge_map: &Map, timer: &mut Timer) ->
} else { } else {
let mut huge_osm_id_to_bldg = HashMap::new(); let mut huge_osm_id_to_bldg = HashMap::new();
for b in huge_map.all_buildings() { for b in huge_map.all_buildings() {
huge_osm_id_to_bldg.insert(b.osm_way_id, b.id); huge_osm_id_to_bldg.insert(b.orig_id.osm_id, b.id);
} }
Some((huge_map, huge_osm_id_to_bldg)) Some((huge_map, huge_osm_id_to_bldg))
}; };
let mut osm_id_to_bldg = HashMap::new(); let mut osm_id_to_bldg = HashMap::new();
for b in map.all_buildings() { for b in map.all_buildings() {
osm_id_to_bldg.insert(b.osm_way_id, b.id); osm_id_to_bldg.insert(b.orig_id.osm_id, b.id);
} }
let bounds = map.get_gps_bounds(); let bounds = map.get_gps_bounds();
let incoming_borders_walking: Vec<(IntersectionID, LonLat)> = map let incoming_borders_walking: Vec<(IntersectionID, LonLat)> = map

View File

@ -449,7 +449,7 @@ impl Model {
pub fn create_b(&mut self, center: Pt2D, ctx: &EventCtx) -> ID { pub fn create_b(&mut self, center: Pt2D, ctx: &EventCtx) -> ID {
let id = OriginalBuilding { let id = OriginalBuilding {
osm_way_id: self.map.new_osm_way_id(time_to_id()), osm_id: osm::OsmID::Way(self.map.new_osm_way_id(time_to_id())),
}; };
self.map.buildings.insert( self.map.buildings.insert(
id, id,

View File

@ -1,6 +1,6 @@
use crate::raw::{OriginalIntersection, OriginalRoad}; use crate::raw::{OriginalIntersection, OriginalRoad};
use crate::{ use crate::{
connectivity, BusRouteID, ControlStopSign, ControlTrafficSignal, IntersectionID, connectivity, osm, BusRouteID, ControlStopSign, ControlTrafficSignal, IntersectionID,
IntersectionType, LaneID, LaneType, Map, PathConstraints, RoadID, TurnID, Zone, IntersectionType, LaneID, LaneType, Map, PathConstraints, RoadID, TurnID, Zone,
}; };
use abstutil::{deserialize_btreemap, retain_btreemap, retain_btreeset, serialize_btreemap, Timer}; use abstutil::{deserialize_btreemap, retain_btreemap, retain_btreeset, serialize_btreemap, Timer};
@ -310,7 +310,7 @@ enum PermanentEditCmd {
old_allow_through_traffic: EnumSet<PathConstraints>, old_allow_through_traffic: EnumSet<PathConstraints>,
}, },
ChangeRouteSchedule { ChangeRouteSchedule {
osm_rel_id: i64, osm_rel_id: osm::RelationID,
old: Vec<Time>, old: Vec<Time>,
new: Vec<Time>, new: Vec<Time>,
}, },
@ -397,18 +397,15 @@ impl PermanentMapEdits {
} }
PermanentEditCmd::ReverseLane { l, dst_i } => { PermanentEditCmd::ReverseLane { l, dst_i } => {
let l = l.from_permanent(map)?; let l = l.from_permanent(map)?;
let dst_i = map.find_i_by_osm_id(dst_i.osm_node_id)?; let dst_i = map.find_i_by_osm_id(dst_i)?;
Ok(EditCmd::ReverseLane { l, dst_i }) Ok(EditCmd::ReverseLane { l, dst_i })
} }
PermanentEditCmd::ChangeSpeedLimit { id, new, old } => { PermanentEditCmd::ChangeSpeedLimit { id, new, old } => {
let id = map.find_r_by_osm_id( let id = map.find_r_by_osm_id(id)?;
id.osm_way_id,
(id.i1.osm_node_id, id.i2.osm_node_id),
)?;
Ok(EditCmd::ChangeSpeedLimit { id, new, old }) Ok(EditCmd::ChangeSpeedLimit { id, new, old })
} }
PermanentEditCmd::ChangeIntersection { i, new, old } => { PermanentEditCmd::ChangeIntersection { i, new, old } => {
let id = map.find_i_by_osm_id(i.osm_node_id)?; let id = map.find_i_by_osm_id(i)?;
Ok(EditCmd::ChangeIntersection { Ok(EditCmd::ChangeIntersection {
i: id, i: id,
new: new new: new
@ -424,10 +421,7 @@ impl PermanentMapEdits {
new_allow_through_traffic, new_allow_through_traffic,
old_allow_through_traffic, old_allow_through_traffic,
} => { } => {
let id = map.find_r_by_osm_id( let id = map.find_r_by_osm_id(id)?;
id.osm_way_id,
(id.i1.osm_node_id, id.i2.osm_node_id),
)?;
Ok(EditCmd::ChangeAccessRestrictions { Ok(EditCmd::ChangeAccessRestrictions {
id, id,
new_allow_through_traffic, new_allow_through_traffic,
@ -439,10 +433,9 @@ impl PermanentMapEdits {
old, old,
new, new,
} => { } => {
let id = map.find_br(osm_rel_id).ok_or(format!( let id = map
"can't find https://www.openstreetmap.org/relation/{}", .find_br(osm_rel_id)
osm_rel_id .ok_or(format!("can't find {}", osm_rel_id))?;
))?;
Ok(EditCmd::ChangeRouteSchedule { id, old, new }) Ok(EditCmd::ChangeRouteSchedule { id, old, new })
} }
}) })
@ -484,11 +477,7 @@ impl PermanentEditIntersection {
PermanentEditIntersection::StopSign { must_stop } => { PermanentEditIntersection::StopSign { must_stop } => {
let mut translated_must_stop = BTreeMap::new(); let mut translated_must_stop = BTreeMap::new();
for (r, stop) in must_stop { for (r, stop) in must_stop {
translated_must_stop.insert( translated_must_stop.insert(map.find_r_by_osm_id(r).ok()?, stop);
map.find_r_by_osm_id(r.osm_way_id, (r.i1.osm_node_id, r.i2.osm_node_id))
.ok()?,
stop,
);
} }
// Make sure the roads exactly match up // Make sure the roads exactly match up
@ -529,10 +518,7 @@ impl OriginalLane {
// - Some validation happens in the lane editor, not even here. // - Some validation happens in the lane editor, not even here.
// - Is it inevitable? Maybe we need to apply edits as we convert. // - Is it inevitable? Maybe we need to apply edits as we convert.
pub fn from_permanent(self, map: &Map) -> Result<LaneID, String> { pub fn from_permanent(self, map: &Map) -> Result<LaneID, String> {
let r = map.get_r(map.find_r_by_osm_id( let r = map.get_r(map.find_r_by_osm_id(self.parent)?);
self.parent.osm_way_id,
(self.parent.i1.osm_node_id, self.parent.i2.osm_node_id),
)?);
if r.children_forwards.len() != self.num_fwd || r.children_backwards.len() != self.num_back if r.children_forwards.len() != self.num_fwd || r.children_backwards.len() != self.num_back
{ {
return Err(format!("number of lanes has changed in {:?}", self)); return Err(format!("number of lanes has changed in {:?}", self));

View File

@ -55,13 +55,13 @@ pub fn make_all_buildings(
}; };
let id = BuildingID(results.len()); let id = BuildingID(results.len());
let mut rng = XorShiftRng::seed_from_u64(orig_id.osm_way_id as u64); let mut rng = XorShiftRng::seed_from_u64(orig_id.osm_id.inner() as u64);
results.push(Building { results.push(Building {
id, id,
polygon: b.polygon.clone(), polygon: b.polygon.clone(),
address: get_address(&b.osm_tags, sidewalk_pos.lane(), map), address: get_address(&b.osm_tags, sidewalk_pos.lane(), map),
name: b.osm_tags.get(osm::NAME).cloned(), name: b.osm_tags.get(osm::NAME).cloned(),
osm_way_id: orig_id.osm_way_id, orig_id,
label_center: b.polygon.polylabel(), label_center: b.polygon.polylabel(),
amenities: b.amenities.clone(), amenities: b.amenities.clone(),
bldg_type: classify_bldg(&b.osm_tags, &b.amenities, b.polygon.area(), &mut rng), bldg_type: classify_bldg(&b.osm_tags, &b.amenities, b.polygon.area(), &mut rng),

View File

@ -115,7 +115,7 @@ impl InitialMap {
m.roads[r2].trimmed_center_pts.reversed() m.roads[r2].trimmed_center_pts.reversed()
}; };
if pl1 == pl2 { if pl1 == pl2 {
problems.insert(format!("{} and {} overlap", r1.way_url(), r2.way_url())); problems.insert(format!("{} and {} overlap", r1.osm_way_id, r2.osm_way_id));
bad_intersections.insert(i.id); bad_intersections.insert(i.id);
} }
} }

View File

@ -88,10 +88,8 @@ pub fn make_all_parking_lots(
sidewalk_pos: *sidewalk_pos, sidewalk_pos: *sidewalk_pos,
}); });
} else { } else {
// TODO Plumb WayID forward
timer.warn(format!( timer.warn(format!(
"Parking lot from https://www.openstreetmap.org/way/{}, near sidewalk {}, \ "Parking lot from {}, near sidewalk {}, can't have a driveway.",
can't have a driveway.",
orig.osm_id, orig.osm_id,
sidewalk_pos.lane() sidewalk_pos.lane()
)); ));

View File

@ -17,7 +17,7 @@ pub fn get_possible_policies(
// independently. // independently.
if let Some(raw) = seattle_traffic_signals::load_all_data() if let Some(raw) = seattle_traffic_signals::load_all_data()
.unwrap() .unwrap()
.remove(&map.get_i(id).orig_id.osm_node_id) .remove(&map.get_i(id).orig_id.osm_node_id.0)
{ {
if let Ok(ts) = ControlTrafficSignal::import(raw, id, map) { if let Ok(ts) = ControlTrafficSignal::import(raw, id, map) {
results.push(("hand-mapped current real settings".to_string(), ts)); results.push(("hand-mapped current real settings".to_string(), ts));
@ -557,7 +557,7 @@ pub fn synchronize(map: &mut Map) {
for i in map.all_intersections() { for i in map.all_intersections() {
if !i.is_traffic_signal() if !i.is_traffic_signal()
|| seen.contains(&i.id) || seen.contains(&i.id)
|| handmapped.contains_key(&i.orig_id.osm_node_id) || handmapped.contains_key(&i.orig_id.osm_node_id.0)
{ {
continue; continue;
} }

View File

@ -18,9 +18,7 @@ pub fn make_stops_and_routes(map: &mut Map, raw_routes: &Vec<RawBusRoute>, timer
if let Err(err) = make_route(map, r, &mut pt_to_stop, &matcher) { if let Err(err) = make_route(map, r, &mut pt_to_stop, &matcher) {
timer.warn(format!( timer.warn(format!(
"Skipping route {} ({}): {}", "Skipping route {} ({}): {}",
r.full_name, r.full_name, r.osm_rel_id, err
rel_url(r.osm_rel_id),
err
)); ));
} }
} }
@ -89,7 +87,7 @@ fn make_route(
// Start or end at a border? // Start or end at a border?
let mut end_border = None; let mut end_border = None;
let start = if let Some(i) = r.border_start { let start = if let Some(i) = r.border_start {
let i = map.get_i(map.find_i_by_osm_id(i.osm_node_id).unwrap()); let i = map.get_i(map.find_i_by_osm_id(i).unwrap());
if !i.is_border() { if !i.is_border() {
panic!("Route starts at {}, but isn't a border?", i.orig_id); panic!("Route starts at {}, but isn't a border?", i.orig_id);
} }
@ -98,10 +96,7 @@ fn make_route(
} else { } else {
return Err(format!( return Err(format!(
"Route {} starts at {} ({}), but no starting lane for a {:?}?", "Route {} starts at {} ({}), but no starting lane for a {:?}?",
rel_url(r.osm_rel_id), r.osm_rel_id, i.id, i.orig_id, route_type
i.id,
i.orig_id,
route_type
) )
.into()); .into());
} }
@ -110,7 +105,7 @@ fn make_route(
pick_start_lane(map.get_bs(stops[0]).driving_pos, route_type, map)? pick_start_lane(map.get_bs(stops[0]).driving_pos, route_type, map)?
}; };
if let Some(i) = r.border_end { if let Some(i) = r.border_end {
let i = map.get_i(map.find_i_by_osm_id(i.osm_node_id).unwrap()); let i = map.get_i(map.find_i_by_osm_id(i).unwrap());
if !i.is_border() { if !i.is_border() {
panic!("Route ends at {}, but isn't a border?", i.orig_id); panic!("Route ends at {}, but isn't a border?", i.orig_id);
} }
@ -125,10 +120,7 @@ fn make_route(
// TODO Should panic // TODO Should panic
println!( println!(
"Route {} ends at {} ({}), but no ending lane for a {:?}?", "Route {} ends at {} ({}), but no ending lane for a {:?}?",
rel_url(r.osm_rel_id), r.osm_rel_id, i.id, i.orig_id, route_type
i.id,
i.orig_id,
route_type
); );
} }
} }
@ -321,10 +313,6 @@ impl Matcher {
} }
} }
fn rel_url(id: i64) -> String {
format!("https://www.openstreetmap.org/relation/{}", id)
}
fn pick_start_lane( fn pick_start_lane(
first_stop: Position, first_stop: Position,
constraints: PathConstraints, constraints: PathConstraints,

View File

@ -1,9 +1,9 @@
use crate::raw::{DrivingSide, RawMap}; use crate::raw::{DrivingSide, OriginalBuilding, OriginalIntersection, OriginalRoad, RawMap};
use crate::{ use crate::{
Area, AreaID, Building, BuildingID, BuildingType, BusRoute, BusRouteID, BusStop, BusStopID, osm, Area, AreaID, Building, BuildingID, BuildingType, BusRoute, BusRouteID, BusStop,
ControlStopSign, ControlTrafficSignal, Intersection, IntersectionID, Lane, LaneID, LaneType, BusStopID, ControlStopSign, ControlTrafficSignal, Intersection, IntersectionID, Lane, LaneID,
Map, MapEdits, OffstreetParking, ParkingLot, ParkingLotID, Path, PathConstraints, PathRequest, LaneType, Map, MapEdits, OffstreetParking, ParkingLot, ParkingLotID, Path, PathConstraints,
Position, Road, RoadID, Turn, TurnGroupID, TurnID, TurnType, PathRequest, Position, Road, RoadID, Turn, TurnGroupID, TurnID, TurnType,
}; };
use abstutil::Timer; use abstutil::Timer;
use geom::{Angle, Bounds, Distance, GPSBounds, Line, PolyLine, Polygon, Pt2D, Ring, Time}; use geom::{Angle, Bounds, Distance, GPSBounds, Line, PolyLine, Polygon, Pt2D, Ring, Time};
@ -547,47 +547,36 @@ impl Map {
None None
} }
pub fn find_r_by_osm_id( pub fn find_r_by_osm_id(&self, id: OriginalRoad) -> Result<RoadID, String> {
&self,
osm_way_id: i64,
osm_node_ids: (i64, i64),
) -> Result<RoadID, String> {
for r in self.all_roads() { for r in self.all_roads() {
if r.orig_id.osm_way_id == osm_way_id if r.orig_id == id {
&& r.orig_id.i1.osm_node_id == osm_node_ids.0
&& r.orig_id.i2.osm_node_id == osm_node_ids.1
{
return Ok(r.id); return Ok(r.id);
} }
} }
Err(format!( Err(format!("Can't find {}", id))
"Can't find osm_way_id {} between nodes {} and {}",
osm_way_id, osm_node_ids.0, osm_node_ids.1
))
} }
// TODO Take OriginalIntersection pub fn find_i_by_osm_id(&self, id: OriginalIntersection) -> Result<IntersectionID, String> {
pub fn find_i_by_osm_id(&self, osm_node_id: i64) -> Result<IntersectionID, String> {
for i in self.all_intersections() { for i in self.all_intersections() {
if i.orig_id.osm_node_id == osm_node_id { if i.orig_id == id {
return Ok(i.id); return Ok(i.id);
} }
} }
Err(format!("Can't find osm_node_id {}", osm_node_id)) Err(format!("Can't find {}", id))
} }
pub fn find_b_by_osm_id(&self, osm_way_id: i64) -> Option<BuildingID> { pub fn find_b_by_osm_id(&self, id: OriginalBuilding) -> Option<BuildingID> {
for b in self.all_buildings() { for b in self.all_buildings() {
if b.osm_way_id == osm_way_id { if b.orig_id == id {
return Some(b.id); return Some(b.id);
} }
} }
None None
} }
pub fn find_br(&self, osm_rel_id: i64) -> Option<BusRouteID> { pub fn find_br(&self, id: osm::RelationID) -> Option<BusRouteID> {
for br in self.all_bus_routes() { for br in self.all_bus_routes() {
if br.osm_rel_id == osm_rel_id { if br.osm_rel_id == id {
return Some(br.id); return Some(br.id);
} }
} }

View File

@ -1,3 +1,4 @@
use crate::osm;
use abstutil::{deserialize_usize, serialize_usize, Tags}; use abstutil::{deserialize_usize, serialize_usize, Tags};
use geom::Polygon; use geom::Polygon;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -32,5 +33,5 @@ pub struct Area {
pub area_type: AreaType, pub area_type: AreaType,
pub polygon: Polygon, pub polygon: Polygon,
pub osm_tags: Tags, pub osm_tags: Tags,
pub osm_id: i64, pub osm_id: osm::OsmID,
} }

View File

@ -1,3 +1,4 @@
use crate::raw::OriginalBuilding;
use crate::{LaneID, Map, PathConstraints, Position}; use crate::{LaneID, Map, PathConstraints, Position};
use abstutil::{deserialize_usize, serialize_usize}; use abstutil::{deserialize_usize, serialize_usize};
use geom::{Distance, PolyLine, Polygon, Pt2D}; use geom::{Distance, PolyLine, Polygon, Pt2D};
@ -26,7 +27,7 @@ pub struct Building {
pub polygon: Polygon, pub polygon: Polygon,
pub address: String, pub address: String,
pub name: Option<String>, pub name: Option<String>,
pub osm_way_id: i64, pub orig_id: OriginalBuilding,
// Where a text label should be centered to have the best chances of being contained within the // Where a text label should be centered to have the best chances of being contained within the
// polygon. // polygon.
pub label_center: Pt2D, pub label_center: Pt2D,

View File

@ -1,4 +1,4 @@
use crate::{LaneID, Map, PathConstraints, PathRequest, Position}; use crate::{osm, LaneID, Map, PathConstraints, PathRequest, Position};
use abstutil::{deserialize_usize, serialize_usize}; use abstutil::{deserialize_usize, serialize_usize};
use geom::Time; use geom::Time;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -50,7 +50,7 @@ pub struct BusRoute {
pub full_name: String, pub full_name: String,
pub short_name: String, pub short_name: String,
pub gtfs_trip_marker: Option<String>, pub gtfs_trip_marker: Option<String>,
pub osm_rel_id: i64, pub osm_rel_id: osm::RelationID,
pub stops: Vec<BusStopID>, pub stops: Vec<BusStopID>,
// May be a border or not. If not, is long enough for buses to spawn fully. // May be a border or not. If not, is long enough for buses to spawn fully.
pub start: LaneID, pub start: LaneID,

View File

@ -1,4 +1,4 @@
use crate::Position; use crate::{osm, Position};
use abstutil::{deserialize_usize, serialize_usize}; use abstutil::{deserialize_usize, serialize_usize};
use geom::{Angle, Line, PolyLine, Polygon, Pt2D}; use geom::{Angle, Line, PolyLine, Polygon, Pt2D};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -33,7 +33,7 @@ pub struct ParkingLot {
pub id: ParkingLotID, pub id: ParkingLotID,
pub polygon: Polygon, pub polygon: Polygon,
pub aisles: Vec<Vec<Pt2D>>, pub aisles: Vec<Vec<Pt2D>>,
pub osm_id: i64, pub osm_id: osm::OsmID,
// The middle of the "T", pointing towards the parking aisle // The middle of the "T", pointing towards the parking aisle
pub spots: Vec<(Pt2D, Angle)>, pub spots: Vec<(Pt2D, Angle)>,

View File

@ -1,6 +1,8 @@
use crate::make::traffic_signals::{brute_force, get_possible_policies}; use crate::make::traffic_signals::{brute_force, get_possible_policies};
use crate::raw::{OriginalIntersection, OriginalRoad};
use crate::{ use crate::{
DirectedRoadID, IntersectionID, Map, TurnGroup, TurnGroupID, TurnID, TurnPriority, TurnType, osm, DirectedRoadID, IntersectionID, Map, TurnGroup, TurnGroupID, TurnID, TurnPriority,
TurnType,
}; };
use abstutil::{deserialize_btreemap, retain_btreeset, serialize_btreemap, Timer}; use abstutil::{deserialize_btreemap, retain_btreeset, serialize_btreemap, Timer};
use geom::Duration; use geom::Duration;
@ -230,7 +232,7 @@ impl Phase {
impl ControlTrafficSignal { impl ControlTrafficSignal {
pub fn export(&self, map: &Map) -> seattle_traffic_signals::TrafficSignal { pub fn export(&self, map: &Map) -> seattle_traffic_signals::TrafficSignal {
seattle_traffic_signals::TrafficSignal { seattle_traffic_signals::TrafficSignal {
intersection_osm_node_id: map.get_i(self.id).orig_id.osm_node_id, intersection_osm_node_id: map.get_i(self.id).orig_id.osm_node_id.0,
phases: self phases: self
.phases .phases
.iter() .iter()
@ -314,18 +316,18 @@ fn export_turn_group(id: &TurnGroupID, map: &Map) -> seattle_traffic_signals::Tu
seattle_traffic_signals::Turn { seattle_traffic_signals::Turn {
from: seattle_traffic_signals::DirectedRoad { from: seattle_traffic_signals::DirectedRoad {
osm_way_id: from.osm_way_id, osm_way_id: from.osm_way_id.0,
osm_node1: from.i1.osm_node_id, osm_node1: from.i1.osm_node_id.0,
osm_node2: from.i2.osm_node_id, osm_node2: from.i2.osm_node_id.0,
is_forwards: id.from.forwards, is_forwards: id.from.forwards,
}, },
to: seattle_traffic_signals::DirectedRoad { to: seattle_traffic_signals::DirectedRoad {
osm_way_id: to.osm_way_id, osm_way_id: to.osm_way_id.0,
osm_node1: to.i1.osm_node_id, osm_node1: to.i1.osm_node_id.0,
osm_node2: to.i2.osm_node_id, osm_node2: to.i2.osm_node_id.0,
is_forwards: id.to.forwards, is_forwards: id.to.forwards,
}, },
intersection_osm_node_id: map.get_i(id.parent).orig_id.osm_node_id, intersection_osm_node_id: map.get_i(id.parent).orig_id.osm_node_id.0,
is_crosswalk: id.crosswalk, is_crosswalk: id.crosswalk,
} }
} }
@ -334,7 +336,11 @@ fn import_turn_group(id: seattle_traffic_signals::Turn, map: &Map) -> Option<Tur
Some(TurnGroupID { Some(TurnGroupID {
from: find_r(id.from, map)?, from: find_r(id.from, map)?,
to: find_r(id.to, map)?, to: find_r(id.to, map)?,
parent: map.find_i_by_osm_id(id.intersection_osm_node_id).ok()?, parent: map
.find_i_by_osm_id(OriginalIntersection {
osm_node_id: osm::NodeID(id.intersection_osm_node_id),
})
.ok()?,
crosswalk: id.is_crosswalk, crosswalk: id.is_crosswalk,
}) })
} }
@ -342,7 +348,10 @@ fn import_turn_group(id: seattle_traffic_signals::Turn, map: &Map) -> Option<Tur
fn find_r(id: seattle_traffic_signals::DirectedRoad, map: &Map) -> Option<DirectedRoadID> { fn find_r(id: seattle_traffic_signals::DirectedRoad, map: &Map) -> Option<DirectedRoadID> {
Some(DirectedRoadID { Some(DirectedRoadID {
id: map id: map
.find_r_by_osm_id(id.osm_way_id, (id.osm_node1, id.osm_node2)) .find_r_by_osm_id(OriginalRoad::new(
id.osm_way_id,
(id.osm_node1, id.osm_node2),
))
.ok()?, .ok()?,
forwards: id.is_forwards, forwards: id.is_forwards,
}) })

View File

@ -1,3 +1,6 @@
use serde::{Deserialize, Serialize};
use std::fmt;
// These are common OSM keys. Keys used in just one or two places don't really need to be defined // These are common OSM keys. Keys used in just one or two places don't really need to be defined
// here. // here.
@ -44,3 +47,51 @@ impl RoadRank {
} }
} }
} }
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct NodeID(pub i64);
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct WayID(pub i64);
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct RelationID(pub i64);
impl fmt::Display for NodeID {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "https://www.openstreetmap.org/node/{}", self.0)
}
}
impl fmt::Display for WayID {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "https://www.openstreetmap.org/way/{}", self.0)
}
}
impl fmt::Display for RelationID {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "https://www.openstreetmap.org/relation/{}", self.0)
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum OsmID {
Node(NodeID),
Way(WayID),
Relation(RelationID),
}
impl fmt::Display for OsmID {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
OsmID::Node(n) => write!(f, "{}", n),
OsmID::Way(w) => write!(f, "{}", w),
OsmID::Relation(r) => write!(f, "{}", r),
}
}
}
impl OsmID {
pub fn inner(self) -> i64 {
match self {
OsmID::Node(n) => n.0,
OsmID::Way(w) => w.0,
OsmID::Relation(r) => r.0,
}
}
}

View File

@ -44,33 +44,28 @@ pub struct RawMap {
// (https://github.com/opentraffic/architecture/issues/1). // (https://github.com/opentraffic/architecture/issues/1).
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct OriginalRoad { pub struct OriginalRoad {
pub osm_way_id: i64, pub osm_way_id: osm::WayID,
pub i1: OriginalIntersection, pub i1: OriginalIntersection,
pub i2: OriginalIntersection, pub i2: OriginalIntersection,
} }
impl OriginalRoad {
pub fn way_url(self) -> String {
format!("https://www.openstreetmap.org/way/{}", self.osm_way_id)
}
}
// A way to refer to intersections across many maps. // A way to refer to intersections across many maps.
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct OriginalIntersection { pub struct OriginalIntersection {
pub osm_node_id: i64, pub osm_node_id: osm::NodeID,
} }
// A way to refer to buildings across many maps. // A way to refer to buildings across many maps.
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct OriginalBuilding { pub struct OriginalBuilding {
pub osm_way_id: i64, pub osm_id: osm::OsmID,
} }
impl fmt::Display for OriginalRoad { impl fmt::Display for OriginalRoad {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
f, f,
"OriginalRoad(https://www.openstreetmap.org/way/{} from https://www.openstreetmap.org/node/{} to https://www.openstreetmap.org/node/{})", "OriginalRoad({} from {} to {}",
self.osm_way_id, self.i1.osm_node_id, self.i2.osm_node_id self.osm_way_id, self.i1.osm_node_id, self.i2.osm_node_id
) )
} }
@ -83,11 +78,7 @@ impl fmt::Debug for OriginalRoad {
impl fmt::Display for OriginalIntersection { impl fmt::Display for OriginalIntersection {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(f, "OriginalIntersection({})", self.osm_node_id)
f,
"OriginalIntersection(https://www.openstreetmap.org/node/{})",
self.osm_node_id
)
} }
} }
impl fmt::Debug for OriginalIntersection { impl fmt::Debug for OriginalIntersection {
@ -98,11 +89,7 @@ impl fmt::Debug for OriginalIntersection {
impl fmt::Display for OriginalBuilding { impl fmt::Display for OriginalBuilding {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(f, "OriginalBuilding({}", self.osm_id)
f,
"OriginalBuilding(https://www.openstreetmap.org/way/{})",
self.osm_way_id
)
} }
} }
impl fmt::Debug for OriginalBuilding { impl fmt::Debug for OriginalBuilding {
@ -111,6 +98,23 @@ impl fmt::Debug for OriginalBuilding {
} }
} }
impl OriginalIntersection {
pub fn new(id: i64) -> OriginalIntersection {
OriginalIntersection {
osm_node_id: osm::NodeID(id),
}
}
}
impl OriginalRoad {
pub fn new(way: i64, (i1, i2): (i64, i64)) -> OriginalRoad {
OriginalRoad {
osm_way_id: osm::WayID(way),
i1: OriginalIntersection::new(i1),
i2: OriginalIntersection::new(i2),
}
}
}
impl RawMap { impl RawMap {
pub fn blank(city_name: &str, name: &str) -> RawMap { pub fn blank(city_name: &str, name: &str) -> RawMap {
RawMap { RawMap {
@ -144,7 +148,7 @@ impl RawMap {
results results
} }
pub fn new_osm_node_id(&self, start: i64) -> i64 { pub fn new_osm_node_id(&self, start: i64) -> osm::NodeID {
assert!(start < 0); assert!(start < 0);
// Slow, but deterministic. // Slow, but deterministic.
let mut osm_node_id = start; let mut osm_node_id = start;
@ -152,29 +156,27 @@ impl RawMap {
if self if self
.intersections .intersections
.keys() .keys()
.any(|i| i.osm_node_id == osm_node_id) .any(|i| i.osm_node_id.0 == osm_node_id)
{ {
osm_node_id -= 1; osm_node_id -= 1;
} else { } else {
return osm_node_id; return osm::NodeID(osm_node_id);
} }
} }
} }
// TODO Almost gone... // TODO Almost gone...
pub fn new_osm_way_id(&self, start: i64) -> i64 { pub fn new_osm_way_id(&self, start: i64) -> osm::WayID {
assert!(start < 0); assert!(start < 0);
// Slow, but deterministic. // Slow, but deterministic.
let mut osm_way_id = start; let mut osm_way_id = start;
loop { loop {
if self.roads.keys().any(|r| r.osm_way_id == osm_way_id) // TODO Only checks roads, doesn't handle collisions with buildings, areas, parking
|| self.buildings.keys().any(|b| b.osm_way_id == osm_way_id) // lots
|| self.areas.iter().any(|a| a.osm_id == osm_way_id) if self.roads.keys().any(|r| r.osm_way_id.0 == osm_way_id) {
|| self.parking_lots.iter().any(|a| a.osm_id == osm_way_id)
{
osm_way_id -= 1; osm_way_id -= 1;
} else { } else {
return osm_way_id; return osm::WayID(osm_way_id);
} }
} }
} }
@ -366,13 +368,13 @@ pub struct RawArea {
pub area_type: AreaType, pub area_type: AreaType,
pub polygon: Polygon, pub polygon: Polygon,
pub osm_tags: Tags, pub osm_tags: Tags,
pub osm_id: i64, pub osm_id: osm::OsmID,
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RawParkingLot { pub struct RawParkingLot {
pub polygon: Polygon, pub polygon: Polygon,
pub osm_id: i64, pub osm_id: osm::OsmID,
} }
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -454,7 +456,7 @@ impl DrivingSide {
pub struct RawBusRoute { pub struct RawBusRoute {
pub full_name: String, pub full_name: String,
pub short_name: String, pub short_name: String,
pub osm_rel_id: i64, pub osm_rel_id: osm::RelationID,
pub gtfs_trip_marker: Option<String>, pub gtfs_trip_marker: Option<String>,
// If not, light rail // If not, light rail
pub is_bus: bool, pub is_bus: bool,

View File

@ -355,7 +355,7 @@ impl IntersectionSimState {
if !queue.try_to_reserve_entry( if !queue.try_to_reserve_entry(
car, car,
!self.dont_block_the_box !self.dont_block_the_box
|| allow_block_the_box(map.get_i(turn.parent).orig_id.osm_node_id) || allow_block_the_box(map.get_i(turn.parent).orig_id.osm_node_id.0)
|| inside_ut, || inside_ut,
) { ) {
if self.break_turn_conflict_cycles { if self.break_turn_conflict_cycles {