location: fix relation polygons
This commit is contained in:
parent
7da29c1070
commit
0bd99acd00
|
@ -10,4 +10,4 @@ for level in 7 8 9 10 11 ; do
|
|||
Q=$Q'way["admin_level"="'$level'"]('$bbox'); relation["admin_level"="'$level'"]('$bbox');'
|
||||
done
|
||||
|
||||
echo overpass "($Q); out body; >; out skel;" \> locations.json
|
||||
overpass "($Q); out body; >; out skel;" > locations.json
|
103
src/location.rs
103
src/location.rs
|
@ -9,24 +9,22 @@ type Polygon = geo::Polygon<f64>;
|
|||
|
||||
struct Location {
|
||||
name: Arc<String>,
|
||||
polys: Vec<Arc<Polygon>>,
|
||||
poly: Arc<Polygon>,
|
||||
area: f64,
|
||||
}
|
||||
|
||||
impl Location {
|
||||
pub fn new(name: &str, polys: Vec<Arc<Polygon>>) -> Self {
|
||||
let area = polys.iter()
|
||||
.map(|poly| poly.unsigned_area())
|
||||
.sum();
|
||||
pub fn new(name: &str, poly: Arc<Polygon>) -> Self {
|
||||
let area = poly.unsigned_area();
|
||||
Location {
|
||||
name: Arc::new(name.to_owned()),
|
||||
polys,
|
||||
poly,
|
||||
area,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains(&self, coord: &geo::Coordinate<f64>) -> bool {
|
||||
self.polys.iter().any(|poly| poly.contains(coord))
|
||||
self.poly.contains(coord)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +37,7 @@ impl Locations {
|
|||
println!("Loading {}...", file);
|
||||
let json: serde_json::Value = serde_json::from_reader(File::open(file).unwrap())
|
||||
.unwrap();
|
||||
println!("parsed JSON");
|
||||
let obj = json.as_object().expect("json obj");
|
||||
let els = obj.get("elements").and_then(|v| v.as_array()).expect("els");
|
||||
println!("{} elements", els.len());
|
||||
|
@ -72,22 +71,20 @@ impl Locations {
|
|||
let id = el.get("id").and_then(|v| v.as_u64()).expect("id");
|
||||
let way_nodes = el.get("nodes").and_then(|v| v.as_array()).expect("nodes")
|
||||
.iter()
|
||||
.map(|way_node| {
|
||||
let way_node = way_node.as_u64()
|
||||
.expect("way_node");
|
||||
nodes.get(&way_node).expect("way_node node")
|
||||
})
|
||||
.cloned()
|
||||
.map(|way_node| way_node.as_u64().expect("way_node"))
|
||||
.collect::<Vec<_>>();
|
||||
let poly = Arc::new(Polygon::new(
|
||||
geo::LineString(way_nodes),
|
||||
vec![]
|
||||
));
|
||||
ways.insert(id, poly.clone());
|
||||
ways.insert(id, way_nodes.clone());
|
||||
|
||||
if let Some(tags) = el.get("tags").and_then(|v| v.as_object()) {
|
||||
if let Some(name) = tags.get("name").and_then(|v| v.as_str()) {
|
||||
locations.push(Location::new(name, vec![poly]));
|
||||
let poly = Arc::new(Polygon::new(
|
||||
geo::LineString(way_nodes.iter()
|
||||
.map(|node| nodes.get(node).expect("node"))
|
||||
.cloned()
|
||||
.collect()),
|
||||
vec![]
|
||||
));
|
||||
locations.push(Location::new(name, poly));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,23 +98,61 @@ impl Locations {
|
|||
|
||||
match el.get("type").and_then(|v| v.as_str()) {
|
||||
Some("relation") => {
|
||||
let polys = el.get("members").and_then(|v| v.as_array()).expect("members")
|
||||
.iter()
|
||||
.filter_map(|member| {
|
||||
let member = member.as_object().unwrap();
|
||||
let member_type = member.get("type").and_then(|v| v.as_str()).unwrap();
|
||||
if member_type == "way" {
|
||||
let member_ref = member.get("ref").and_then(|v| v.as_u64()).unwrap();
|
||||
let way = ways.get(&member_ref).expect("member way");
|
||||
Some(way.clone())
|
||||
if let Some(name) = el.get("tags")
|
||||
.and_then(|v| v.as_object())
|
||||
.and_then(|tags| tags.get("name"))
|
||||
.and_then(|v| v.as_str())
|
||||
{
|
||||
let mut outers = el.get("members").and_then(|v| v.as_array()).expect("members")
|
||||
.iter()
|
||||
.filter_map(|member| {
|
||||
let member = member.as_object().unwrap();
|
||||
let member_type = member.get("type").and_then(|v| v.as_str()).unwrap();
|
||||
let member_role = member.get("role").and_then(|v| v.as_str()).unwrap();
|
||||
if member_type == "way" && member_role == "outer" {
|
||||
let member_ref = member.get("ref").and_then(|v| v.as_u64()).unwrap();
|
||||
let way = ways.get(&member_ref).expect("member way");
|
||||
Some(way.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let mut rel_nodes = vec![];
|
||||
while outers.len() > 0 {
|
||||
if rel_nodes.len() == 0 {
|
||||
rel_nodes = outers.pop().unwrap();
|
||||
} else if let Some(next) = outers.iter().position(|outer| outer[0] == rel_nodes[rel_nodes.len() - 1]) {
|
||||
rel_nodes.append(&mut outers.remove(next));
|
||||
} else if let Some(next) = outers.iter().position(|outer| outer[outer.len() - 1] == rel_nodes[0]) {
|
||||
let mut new = outers.remove(next);
|
||||
new.append(&mut rel_nodes);
|
||||
rel_nodes = new;
|
||||
} else if let Some(next) = outers.iter().position(|outer| outer[outer.len() - 1] == rel_nodes[rel_nodes.len() - 1]) {
|
||||
let mut new = outers.remove(next);
|
||||
new.reverse();
|
||||
rel_nodes.append(&mut new);
|
||||
} else {
|
||||
None
|
||||
println!("inconclusive polygon for relation {}", el.get("id").unwrap().as_u64().unwrap());
|
||||
println!("rel_nodes: {:?}", rel_nodes);
|
||||
println!("remain: {:?}", outers);
|
||||
rel_nodes = vec![];
|
||||
break;
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
if let Some(tags) = el.get("tags").and_then(|v| v.as_object()) {
|
||||
if let Some(name) = tags.get("name").and_then(|v| v.as_str()) {
|
||||
locations.push(Location::new(name, polys));
|
||||
|
||||
if rel_nodes[0] == rel_nodes[rel_nodes.len() - 1] {
|
||||
let poly = Arc::new(Polygon::new(
|
||||
geo::LineString(rel_nodes.drain(..)
|
||||
.map(|node| nodes.get(&node).expect("node"))
|
||||
.cloned()
|
||||
.collect()),
|
||||
vec![]
|
||||
));
|
||||
locations.push(Location::new(name, poly));
|
||||
}
|
||||
}
|
||||
if rel_nodes.len() > 0 {
|
||||
println!("unclosed polygon for relation {}", el.get("id").unwrap().as_u64().unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue