mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-27 00:12:55 +03:00
parse OSM multipolygons, like bodies of water, correctly, when they're
completely present in the .osm
This commit is contained in:
parent
0f1d0d24ca
commit
f693316290
@ -67,7 +67,7 @@ pub fn osm_to_raw_roads(
|
||||
} else if let Some(at) = get_area_type(&tags) {
|
||||
areas.push(raw_data::Area {
|
||||
area_type: at,
|
||||
osm_way_id: way.id,
|
||||
osm_id: way.id,
|
||||
points: pts,
|
||||
osm_tags: tags,
|
||||
});
|
||||
@ -83,35 +83,45 @@ pub fn osm_to_raw_roads(
|
||||
let tags = tags_to_map(&rel.tags);
|
||||
if let Some(at) = get_area_type(&tags) {
|
||||
if tags.get("type") == Some(&"multipolygon".to_string()) {
|
||||
let mut ok = true;
|
||||
let mut pts_per_way: Vec<Vec<LonLat>> = Vec::new();
|
||||
for member in &rel.members {
|
||||
match *member {
|
||||
osm_xml::Member::Way(osm_xml::UnresolvedReference::Way(id), ref role) => {
|
||||
match id_to_way.get(&id) {
|
||||
Some(pts) => {
|
||||
if role == "outer" {
|
||||
areas.push(raw_data::Area {
|
||||
area_type: at,
|
||||
osm_way_id: id,
|
||||
points: pts.to_vec(),
|
||||
osm_tags: tags.clone(),
|
||||
});
|
||||
pts_per_way.push(pts.to_vec());
|
||||
} else {
|
||||
println!(
|
||||
"Relation {} has unhandled member role {}",
|
||||
rel.id, role
|
||||
);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
println!("Relation {} refers to unknown way {}", rel.id, id);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
println!("Relation {} refers to {:?}", rel.id, member);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ok {
|
||||
if let Some(polygon) = glue_multipolygon(pts_per_way) {
|
||||
areas.push(raw_data::Area {
|
||||
area_type: at,
|
||||
osm_id: rel.id,
|
||||
points: polygon,
|
||||
osm_tags: tags.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -175,11 +185,29 @@ fn get_area_type(tags: &BTreeMap<String, String>) -> Option<AreaType> {
|
||||
if tags.get("natural") == Some(&"wood".to_string()) {
|
||||
return Some(AreaType::Park);
|
||||
}
|
||||
if tags.get("natural") == Some(&"wetland".to_string()) {
|
||||
return Some(AreaType::Swamp);
|
||||
}
|
||||
if tags.contains_key("waterway") {
|
||||
if tags.contains_key("waterway") || tags.get("natural") == Some(&"water".to_string()) {
|
||||
return Some(AreaType::Water);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn glue_multipolygon(mut pts_per_way: Vec<Vec<LonLat>>) -> Option<Vec<LonLat>> {
|
||||
let mut result = pts_per_way.pop().unwrap();
|
||||
while !pts_per_way.is_empty() {
|
||||
let glue_pt = *result.last().unwrap();
|
||||
if let Some(idx) = pts_per_way
|
||||
.iter()
|
||||
.position(|pts| pts[0] == glue_pt || *pts.last().unwrap() == glue_pt)
|
||||
{
|
||||
let mut append = pts_per_way.remove(idx);
|
||||
if append[0] != glue_pt {
|
||||
append.reverse();
|
||||
}
|
||||
result.pop();
|
||||
result.extend(append);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(result)
|
||||
}
|
||||
|
@ -39,8 +39,7 @@
|
||||
- but theyre not marked everywhere
|
||||
- and theyre hard to associate with roads (sometimes need to infer a planter strip)
|
||||
- draw ALL water and greenery areas
|
||||
- cant mouseover areas created from polylines, seemingly
|
||||
- multipolygons seem broken
|
||||
- how to handle multipolygons referring to clipped ways?
|
||||
- draw benches, bike racks
|
||||
- render trees
|
||||
- look for current stop sign priorities
|
||||
|
@ -146,7 +146,7 @@ fn tooltip_lines(obj: ID, g: &mut GfxCtx, ctx: &DrawCtx) -> Text {
|
||||
}
|
||||
ID::Area(id) => {
|
||||
let a = map.get_a(id);
|
||||
txt.add_line(format!("{} (from OSM way {})", id, a.osm_way_id));
|
||||
txt.add_line(format!("{} (from OSM {})", id, a.osm_id));
|
||||
styled_kv(&mut txt, &a.osm_tags);
|
||||
}
|
||||
ID::Trip(_) => {}
|
||||
|
@ -26,7 +26,7 @@ impl ToggleableLayers {
|
||||
show_parcels: ToggleableLayer::new("parcels", Some(MIN_ZOOM_FOR_PARCELS)),
|
||||
show_extra_shapes: ToggleableLayer::new("extra shapes", Some(MIN_ZOOM_FOR_LANES)),
|
||||
show_all_turn_icons: ToggleableLayer::new("all turn icons", None),
|
||||
show_areas: ToggleableLayer::new("areas", None),
|
||||
show_areas: ToggleableLayer::new("areas", Some(0.0)),
|
||||
debug_mode: ToggleableLayer::new("geometry debug mode", None),
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,8 @@ impl DrawArea {
|
||||
let fill_polygon = area.get_polygon();
|
||||
let draw_default = prerender.upload_borrowed(vec![(
|
||||
match area.area_type {
|
||||
AreaType::Park => cs.get_def("park area", Color::GREEN),
|
||||
AreaType::Swamp => cs.get_def("swamp area", Color::rgb_f(0.0, 1.0, 0.6)),
|
||||
AreaType::Water => cs.get_def("water area", Color::BLUE),
|
||||
AreaType::Park => cs.get_def("park area", Color::rgb(200, 250, 204)),
|
||||
AreaType::Water => cs.get_def("water area", Color::rgb(170, 211, 223)),
|
||||
},
|
||||
&fill_polygon,
|
||||
)]);
|
||||
|
@ -404,8 +404,8 @@ impl<S: UIState> UI<S> {
|
||||
let map = &state.primary.map;
|
||||
let draw_map = &state.primary.draw_map;
|
||||
|
||||
let mut areas: Vec<Box<&Renderable>> = Vec::new();
|
||||
let mut parcels: Vec<Box<&Renderable>> = Vec::new();
|
||||
let mut areas: Vec<Box<&Renderable>> = Vec::new();
|
||||
let mut lanes: Vec<Box<&Renderable>> = Vec::new();
|
||||
let mut intersections: Vec<Box<&Renderable>> = Vec::new();
|
||||
let mut buildings: Vec<Box<&Renderable>> = Vec::new();
|
||||
@ -419,8 +419,8 @@ impl<S: UIState> UI<S> {
|
||||
continue;
|
||||
}
|
||||
match id {
|
||||
ID::Area(id) => areas.push(Box::new(draw_map.get_a(id))),
|
||||
ID::Parcel(id) => parcels.push(Box::new(draw_map.get_p(id))),
|
||||
ID::Area(id) => areas.push(Box::new(draw_map.get_a(id))),
|
||||
ID::Lane(id) => {
|
||||
lanes.push(Box::new(draw_map.get_l(id)));
|
||||
if !state.show_icons_for(map.get_l(id).dst_i) {
|
||||
@ -452,8 +452,8 @@ impl<S: UIState> UI<S> {
|
||||
|
||||
// From background to foreground Z-order
|
||||
let mut borrows: Vec<Box<&Renderable>> = Vec::new();
|
||||
borrows.extend(areas);
|
||||
borrows.extend(parcels);
|
||||
borrows.extend(areas);
|
||||
borrows.extend(lanes);
|
||||
borrows.extend(intersections);
|
||||
borrows.extend(buildings);
|
||||
|
@ -18,7 +18,6 @@ impl fmt::Display for AreaID {
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
pub enum AreaType {
|
||||
Park,
|
||||
Swamp,
|
||||
Water,
|
||||
}
|
||||
|
||||
@ -29,7 +28,7 @@ pub struct Area {
|
||||
// Might be a closed loop or not -- waterways can be linear.
|
||||
pub points: Vec<Pt2D>,
|
||||
pub osm_tags: BTreeMap<String, String>,
|
||||
pub osm_way_id: i64,
|
||||
pub osm_id: i64,
|
||||
}
|
||||
|
||||
impl Area {
|
||||
|
@ -189,7 +189,7 @@ pub fn make_half_map(
|
||||
.map(|coord| Pt2D::from_gps(*coord, &gps_bounds).unwrap())
|
||||
.collect(),
|
||||
osm_tags: a.osm_tags.clone(),
|
||||
osm_way_id: a.osm_way_id,
|
||||
osm_id: a.osm_id,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ pub struct Area {
|
||||
// last point is always the same as the first
|
||||
pub points: Vec<LonLat>,
|
||||
pub osm_tags: BTreeMap<String, String>,
|
||||
pub osm_way_id: i64,
|
||||
pub osm_id: i64,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize)]
|
||||
|
Loading…
Reference in New Issue
Block a user