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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use std::fs::File;
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use serde::Deserialize;
use abstutil::Timer;
use geom::Ring;
use kml::ExtraShapes;
use map_model::raw::RawMap;
use map_model::BuildingType;
use crate::configuration::ImporterConfiguration;
use crate::utils::{download, download_kml};
pub fn import_extra_data(map: &RawMap, config: &ImporterConfiguration, timer: &mut Timer) {
download_kml(
map.get_city_name().input_path("planning_areas.bin"),
"https://tsb-opendata.s3.eu-central-1.amazonaws.com/lor_planungsgraeume/lor_planungsraeume.kml",
&map.gps_bounds,
false,
timer
);
download(
config,
map.get_city_name().input_path("EWR201812E_Matrix.csv"),
"https://www.statistik-berlin-brandenburg.de/opendata/EWR201812E_Matrix.csv",
);
correlate_population(
map.get_city_name().input_path("planning_areas.bin"),
map.get_city_name().input_path("EWR201812E_Matrix.csv"),
timer,
);
}
fn correlate_population(kml_path: String, csv_path: String, timer: &mut Timer) {
let mut shapes = abstio::read_binary::<ExtraShapes>(kml_path.clone(), timer);
for rec in csv::ReaderBuilder::new()
.delimiter(b';')
.from_reader(File::open(csv_path).unwrap())
.deserialize()
{
let rec: Record = rec.unwrap();
for shape in &mut shapes.shapes {
if shape.attributes.get("spatial_name") == Some(&rec.raumid) {
shape
.attributes
.insert("num_residents".to_string(), rec.e_e);
break;
}
}
}
abstio::write_binary(kml_path, &shapes);
}
#[derive(Debug, Deserialize)]
struct Record {
#[serde(rename = "RAUMID")]
raumid: String,
#[serde(rename = "E_E")]
e_e: String,
}
pub fn distribute_residents(map: &mut map_model::Map, timer: &mut Timer) {
for shape in abstio::read_binary::<ExtraShapes>(
"data/input/de/berlin/planning_areas.bin".to_string(),
timer,
)
.shapes
{
let pts = map.get_gps_bounds().convert(&shape.points);
if pts
.iter()
.all(|pt| !map.get_boundary_polygon().contains_pt(*pt))
{
continue;
}
let region = Ring::must_new(pts).to_polygon();
let mut rng =
XorShiftRng::seed_from_u64(shape.attributes["spatial_name"].parse::<u64>().unwrap());
for (home, n) in popdat::distribute_population_to_homes(
geo::Polygon::from(region),
shape.attributes["num_residents"].parse::<usize>().unwrap(),
map,
&mut rng,
) {
let bldg_type = match map.get_b(home).bldg_type {
BuildingType::Residential {
num_housing_units, ..
} => BuildingType::Residential {
num_housing_units,
num_residents: n,
},
BuildingType::ResidentialCommercial(_, worker_cap) => {
BuildingType::ResidentialCommercial(n, worker_cap)
}
_ => unreachable!(),
};
map.hack_override_bldg_type(home, bldg_type);
}
}
map.save();
}