1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use abstutil::{CmdArgs, Timer};
use geom::{Circle, Distance, GPSBounds, LonLat, Polygon};
use map_model::osm::OsmID;
use std::process::Command;
fn main() {
let mut args = CmdArgs::new();
let input = args.required_free();
let radius_around_label: Option<Distance> = args
.optional_parse("--radius_around_label_miles", |s| {
s.parse::<f64>().map(|x| Distance::miles(x))
});
args.done();
let mut timer = Timer::new(format!("extract cities from {}", input));
let doc = convert_osm::reader::read(&input, &GPSBounds::new(), &mut timer).unwrap();
for (id, rel) in &doc.relations {
if !rel.tags.is("border_type", "city") && !rel.tags.is("place", "city") {
continue;
}
let name = if let Some(name) = rel.tags.get("name:en").or(rel.tags.get("name")) {
name
} else {
println!("{} has no name?", id);
continue;
};
println!("Found city relation for {}: {}", name, id);
let clip = if let Some(radius) = radius_around_label {
let mut center = None;
for (role, id) in &rel.members {
if role == "admin_centre" || role == "label" {
if let OsmID::Node(n) = id {
center = Some(doc.nodes[n].pt);
break;
}
}
}
if let Some(pt) = center {
Circle::new(pt, radius).to_polygon()
} else {
println!("... but it has no admin_centre or label member");
continue;
}
} else {
let polygons = convert_osm::osm_geom::glue_multipolygon(
*id,
convert_osm::osm_geom::get_multipolygon_members(*id, rel, &doc),
None,
);
println!(
"Extracted {} from {}, using the convex hull of {} polygons",
name,
id,
polygons.len(),
);
Polygon::convex_hull(polygons)
};
let clipping_polygon = format!("{}.poly", name);
LonLat::write_osmosis_polygon(
&clipping_polygon,
&doc.gps_bounds.convert_back(clip.points()),
)
.unwrap();
abstutil::must_run_cmd(
Command::new("osmconvert")
.arg(&input)
.arg(format!("-B={}", clipping_polygon))
.arg("--complete-ways")
.arg(format!("-o={}.osm", name)),
);
}
}