mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 12:12:00 +03:00
partly refactor some of the intensely nested osm_reader code
This commit is contained in:
parent
8b006c037d
commit
315ab5c8e6
@ -119,39 +119,7 @@ pub fn extract_osm(
|
|||||||
let mut tags = tags_to_map(&way.tags);
|
let mut tags = tags_to_map(&way.tags);
|
||||||
tags.insert(osm::OSM_WAY_ID.to_string(), way.id.to_string());
|
tags.insert(osm::OSM_WAY_ID.to_string(), way.id.to_string());
|
||||||
|
|
||||||
if is_road(&tags) {
|
if is_road(&mut tags) {
|
||||||
// If there's no parking data in OSM already, then assume no parking and mark that it's
|
|
||||||
// inferred.
|
|
||||||
if !tags.contains_key(osm::PARKING_LEFT)
|
|
||||||
&& !tags.contains_key(osm::PARKING_RIGHT)
|
|
||||||
&& !tags.contains_key(osm::PARKING_BOTH)
|
|
||||||
&& tags.get(osm::HIGHWAY) != Some(&"motorway".to_string())
|
|
||||||
&& tags.get(osm::HIGHWAY) != Some(&"motorway_link".to_string())
|
|
||||||
&& tags.get("junction") != Some(&"roundabout".to_string())
|
|
||||||
{
|
|
||||||
tags.insert(osm::PARKING_BOTH.to_string(), "no_parking".to_string());
|
|
||||||
tags.insert(osm::INFERRED_PARKING.to_string(), "true".to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there's no sidewalk data in OSM already, then make an assumption and mark that
|
|
||||||
// it's inferred.
|
|
||||||
if !tags.contains_key(osm::SIDEWALK) {
|
|
||||||
tags.insert(osm::INFERRED_SIDEWALKS.to_string(), "true".to_string());
|
|
||||||
if tags.get(osm::HIGHWAY) == Some(&"motorway".to_string())
|
|
||||||
|| tags.get(osm::HIGHWAY) == Some(&"motorway_link".to_string())
|
|
||||||
|| tags.get("junction") == Some(&"roundabout".to_string())
|
|
||||||
{
|
|
||||||
tags.insert(osm::SIDEWALK.to_string(), "none".to_string());
|
|
||||||
} else if tags.get("oneway") == Some(&"yes".to_string()) {
|
|
||||||
tags.insert(osm::SIDEWALK.to_string(), "right".to_string());
|
|
||||||
if tags.get(osm::HIGHWAY) == Some(&"residential".to_string()) {
|
|
||||||
tags.insert(osm::SIDEWALK.to_string(), "both".to_string());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tags.insert(osm::SIDEWALK.to_string(), "both".to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Hardcoding these overrides. OSM is correct, these don't have
|
// TODO Hardcoding these overrides. OSM is correct, these don't have
|
||||||
// sidewalks; there's a crosswalk mapped. But until we can snap sidewalks properly, do
|
// sidewalks; there's a crosswalk mapped. But until we can snap sidewalks properly, do
|
||||||
// this to prevent the sidewalks from being disconnected.
|
// this to prevent the sidewalks from being disconnected.
|
||||||
@ -159,16 +127,6 @@ pub fn extract_osm(
|
|||||||
tags.insert(osm::SIDEWALK.to_string(), "right".to_string());
|
tags.insert(osm::SIDEWALK.to_string(), "right".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
roads.push((
|
|
||||||
way.id,
|
|
||||||
RawRoad {
|
|
||||||
center_points: pts,
|
|
||||||
osm_tags: tags,
|
|
||||||
turn_restrictions: Vec::new(),
|
|
||||||
complicated_turn_restrictions: Vec::new(),
|
|
||||||
},
|
|
||||||
));
|
|
||||||
} else if tags.get("railway") == Some(&"light_rail".to_string()) {
|
|
||||||
roads.push((
|
roads.push((
|
||||||
way.id,
|
way.id,
|
||||||
RawRoad {
|
RawRoad {
|
||||||
@ -185,31 +143,14 @@ pub fn extract_osm(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut amenities = BTreeSet::new();
|
|
||||||
if let Some(amenity) = tags.get("amenity") {
|
|
||||||
amenities.insert((
|
|
||||||
tags.get("name")
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or_else(|| "unnamed".to_string()),
|
|
||||||
amenity.clone(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if let Some(shop) = tags.get("shop") {
|
|
||||||
amenities.insert((
|
|
||||||
tags.get("name")
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or_else(|| "unnamed".to_string()),
|
|
||||||
shop.clone(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
map.buildings.insert(
|
map.buildings.insert(
|
||||||
OriginalBuilding { osm_way_id: way.id },
|
OriginalBuilding { osm_way_id: way.id },
|
||||||
RawBuilding {
|
RawBuilding {
|
||||||
polygon: Polygon::new(&deduped),
|
polygon: Polygon::new(&deduped),
|
||||||
osm_tags: tags,
|
|
||||||
public_garage_name: None,
|
public_garage_name: None,
|
||||||
num_parking_spots: 0,
|
num_parking_spots: 0,
|
||||||
amenities,
|
amenities: get_bldg_amenities(&tags),
|
||||||
|
osm_tags: tags,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else if let Some(at) = get_area_type(&tags) {
|
} else if let Some(at) = get_area_type(&tags) {
|
||||||
@ -247,35 +188,13 @@ pub fn extract_osm(
|
|||||||
timer.next();
|
timer.next();
|
||||||
let mut tags = tags_to_map(&rel.tags);
|
let mut tags = tags_to_map(&rel.tags);
|
||||||
tags.insert(osm::OSM_REL_ID.to_string(), rel.id.to_string());
|
tags.insert(osm::OSM_REL_ID.to_string(), rel.id.to_string());
|
||||||
if let Some(at) = get_area_type(&tags) {
|
|
||||||
|
if let Some(area_type) = get_area_type(&tags) {
|
||||||
if tags.get("type") == Some(&"multipolygon".to_string()) {
|
if tags.get("type") == Some(&"multipolygon".to_string()) {
|
||||||
let mut ok = true;
|
if let Some(pts_per_way) = get_multipolygon_members(rel, &id_to_way) {
|
||||||
let mut pts_per_way: Vec<(i64, Vec<Pt2D>)> = Vec::new();
|
|
||||||
for member in &rel.members {
|
|
||||||
match member {
|
|
||||||
osm_xml::Member::Way(osm_xml::UnresolvedReference::Way(id), ref role) => {
|
|
||||||
// If the way is clipped out, that's fine
|
|
||||||
if let Some(pts) = id_to_way.get(id) {
|
|
||||||
if role == "outer" {
|
|
||||||
pts_per_way.push((*id, pts.to_vec()));
|
|
||||||
} else {
|
|
||||||
println!(
|
|
||||||
"Relation {} has unhandled member role {}, ignoring it",
|
|
||||||
rel.id, role
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
println!("Relation {} refers to {:?}", rel.id, member);
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
for polygon in glue_multipolygon(rel.id, pts_per_way, &boundary) {
|
for polygon in glue_multipolygon(rel.id, pts_per_way, &boundary) {
|
||||||
map.areas.push(RawArea {
|
map.areas.push(RawArea {
|
||||||
area_type: at,
|
area_type,
|
||||||
osm_id: rel.id,
|
osm_id: rel.id,
|
||||||
polygon,
|
polygon,
|
||||||
osm_tags: tags.clone(),
|
osm_tags: tags.clone(),
|
||||||
@ -343,24 +262,6 @@ pub fn extract_osm(
|
|||||||
.next()
|
.next()
|
||||||
.and_then(|id| id_to_way.get(&id))
|
.and_then(|id| id_to_way.get(&id))
|
||||||
{
|
{
|
||||||
// TODO Dedupe code
|
|
||||||
let mut amenities = BTreeSet::new();
|
|
||||||
if let Some(amenity) = tags.get("amenity") {
|
|
||||||
amenities.insert((
|
|
||||||
tags.get("name")
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or_else(|| "unnamed".to_string()),
|
|
||||||
amenity.clone(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if let Some(shop) = tags.get("shop") {
|
|
||||||
amenities.insert((
|
|
||||||
tags.get("name")
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or_else(|| "unnamed".to_string()),
|
|
||||||
shop.clone(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if pts.len() < 3 {
|
if pts.len() < 3 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -368,13 +269,27 @@ pub fn extract_osm(
|
|||||||
OriginalBuilding { osm_way_id: rel.id },
|
OriginalBuilding { osm_way_id: rel.id },
|
||||||
RawBuilding {
|
RawBuilding {
|
||||||
polygon: Polygon::new(pts),
|
polygon: Polygon::new(pts),
|
||||||
osm_tags: tags,
|
|
||||||
public_garage_name: None,
|
public_garage_name: None,
|
||||||
num_parking_spots: 0,
|
num_parking_spots: 0,
|
||||||
amenities,
|
amenities: get_bldg_amenities(&tags),
|
||||||
|
osm_tags: tags,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
/*} else if tags.get("type") == Some(&"route_master".to_string()) {
|
||||||
|
let name = tags.get("name").unwrap();
|
||||||
|
//let mut fwd_stops = Vec::new();
|
||||||
|
//let mut back_stops = Vec::new();
|
||||||
|
for member in &rel.members {
|
||||||
|
if let osm_xml::Member::Relation(rel_ref, _) = member {
|
||||||
|
if let osm_xml::Reference::Relation(inner_rel) = doc.resolve_reference(&rel_ref) {
|
||||||
|
let inner_tags = tags_to_map(&inner_rel.tags);
|
||||||
|
assert_eq!(inner_tags.get("type"), Some(&"route".to_string()));
|
||||||
|
for member in &inner_rel.members {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,7 +343,11 @@ fn tags_to_map(raw_tags: &[osm_xml::Tag]) -> BTreeMap<String, String> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_road(tags: &BTreeMap<String, String>) -> bool {
|
fn is_road(tags: &mut BTreeMap<String, String>) -> bool {
|
||||||
|
if tags.get("railway") == Some(&"light_rail".to_string()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if !tags.contains_key(osm::HIGHWAY) {
|
if !tags.contains_key(osm::HIGHWAY) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -465,6 +384,38 @@ fn is_road(tags: &BTreeMap<String, String>) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there's no parking data in OSM already, then assume no parking and mark that it's
|
||||||
|
// inferred.
|
||||||
|
if !tags.contains_key(osm::PARKING_LEFT)
|
||||||
|
&& !tags.contains_key(osm::PARKING_RIGHT)
|
||||||
|
&& !tags.contains_key(osm::PARKING_BOTH)
|
||||||
|
&& tags.get(osm::HIGHWAY) != Some(&"motorway".to_string())
|
||||||
|
&& tags.get(osm::HIGHWAY) != Some(&"motorway_link".to_string())
|
||||||
|
&& tags.get("junction") != Some(&"roundabout".to_string())
|
||||||
|
{
|
||||||
|
tags.insert(osm::PARKING_BOTH.to_string(), "no_parking".to_string());
|
||||||
|
tags.insert(osm::INFERRED_PARKING.to_string(), "true".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's no sidewalk data in OSM already, then make an assumption and mark that
|
||||||
|
// it's inferred.
|
||||||
|
if !tags.contains_key(osm::SIDEWALK) {
|
||||||
|
tags.insert(osm::INFERRED_SIDEWALKS.to_string(), "true".to_string());
|
||||||
|
if tags.get(osm::HIGHWAY) == Some(&"motorway".to_string())
|
||||||
|
|| tags.get(osm::HIGHWAY) == Some(&"motorway_link".to_string())
|
||||||
|
|| tags.get("junction") == Some(&"roundabout".to_string())
|
||||||
|
{
|
||||||
|
tags.insert(osm::SIDEWALK.to_string(), "none".to_string());
|
||||||
|
} else if tags.get("oneway") == Some(&"yes".to_string()) {
|
||||||
|
tags.insert(osm::SIDEWALK.to_string(), "right".to_string());
|
||||||
|
if tags.get(osm::HIGHWAY) == Some(&"residential".to_string()) {
|
||||||
|
tags.insert(osm::SIDEWALK.to_string(), "both".to_string());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tags.insert(osm::SIDEWALK.to_string(), "both".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,6 +424,27 @@ fn is_bldg(tags: &BTreeMap<String, String>) -> bool {
|
|||||||
tags.contains_key("building") && !tags.contains_key("abandoned:man_made")
|
tags.contains_key("building") && !tags.contains_key("abandoned:man_made")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_bldg_amenities(tags: &BTreeMap<String, String>) -> BTreeSet<(String, String)> {
|
||||||
|
let mut amenities = BTreeSet::new();
|
||||||
|
if let Some(amenity) = tags.get("amenity") {
|
||||||
|
amenities.insert((
|
||||||
|
tags.get("name")
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| "unnamed".to_string()),
|
||||||
|
amenity.clone(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if let Some(shop) = tags.get("shop") {
|
||||||
|
amenities.insert((
|
||||||
|
tags.get("name")
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| "unnamed".to_string()),
|
||||||
|
shop.clone(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
amenities
|
||||||
|
}
|
||||||
|
|
||||||
fn get_area_type(tags: &BTreeMap<String, String>) -> Option<AreaType> {
|
fn get_area_type(tags: &BTreeMap<String, String>) -> Option<AreaType> {
|
||||||
if tags.get("leisure") == Some(&"park".to_string()) {
|
if tags.get("leisure") == Some(&"park".to_string()) {
|
||||||
return Some(AreaType::Park);
|
return Some(AreaType::Park);
|
||||||
@ -508,6 +480,40 @@ fn get_area_type(tags: &BTreeMap<String, String>) -> Option<AreaType> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_multipolygon_members(
|
||||||
|
rel: &osm_xml::Relation,
|
||||||
|
id_to_way: &HashMap<i64, Vec<Pt2D>>,
|
||||||
|
) -> Option<Vec<(i64, Vec<Pt2D>)>> {
|
||||||
|
let mut ok = true;
|
||||||
|
let mut pts_per_way: Vec<(i64, Vec<Pt2D>)> = Vec::new();
|
||||||
|
for member in &rel.members {
|
||||||
|
match member {
|
||||||
|
osm_xml::Member::Way(osm_xml::UnresolvedReference::Way(id), ref role) => {
|
||||||
|
// If the way is clipped out, that's fine
|
||||||
|
if let Some(pts) = id_to_way.get(id) {
|
||||||
|
if role == "outer" {
|
||||||
|
pts_per_way.push((*id, pts.to_vec()));
|
||||||
|
} else {
|
||||||
|
println!(
|
||||||
|
"Relation {} has unhandled member role {}, ignoring it",
|
||||||
|
rel.id, role
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("Relation {} refers to {:?}", rel.id, member);
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
|
Some(pts_per_way)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The result could be more than one disjoint polygon.
|
// The result could be more than one disjoint polygon.
|
||||||
fn glue_multipolygon(
|
fn glue_multipolygon(
|
||||||
rel_id: i64,
|
rel_id: i64,
|
||||||
|
Loading…
Reference in New Issue
Block a user