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