-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexample.py
176 lines (145 loc) · 4.95 KB
/
example.py
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
from functools import partial, reduce
import os
import fiona
import pyproj
from shapely.geometry import shape
from shapely.ops import transform
S3_PATH = 's3://glr-ds-us-building-footprints'
def get_buildings(plot_shp, county_fips):
src_path = os.path.join(S3_PATH, f'{county_fips}.shp')
bbox = plot_shp.bounds
buildings = []
building_shps = []
with fiona.open(src_path) as src:
src_meta = src.meta
candidates = list(src.items(bbox=bbox))
candidate_shps = [shape(candidate[1]['geometry']) for candidate in candidates]
for i, candidate_shp in enumerate(candidate_shps):
if candidate_shp.intersects(plot_shp):
buildings.append(candidates[i])
building_shps.append(candidate_shp)
return buildings, building_shps, src_meta
def get_footprint_intersection_single_building(building, plot):
return plot.intersection(building).area
def get_building_features(plot, buildings):
'''
Calculates number of intersecting buildings, total building footprint, and proportion of the
plot that is covered by buildings.
Parameters
----------
plot : shapely.shape
Plot to query.
buildings : list[shapely.shape]
List of buildings that intersect the plot. Assumes that all buildings DO intersect the
plot.
Returns
-------
building_features : dict
Keys: 'total_building_footprint', 'building_proportion', 'n_buildings'
'''
building_features = {}
# Reproject to albers equal area for area calculations in meters.
project = partial(
pyproj.transform,
pyproj.Proj(init='epsg:4326'),
pyproj.Proj(init='epsg:2163'),
)
plot_projected = transform(project, plot)
buildings_projected = (transform(project, building) for building in buildings)
get_footprint_partial = partial(
get_footprint_intersection_single_building,
plot=plot_projected
)
total_building_footprint = reduce(
lambda x, y: x + get_footprint_partial(y),
buildings_projected,
0
)
building_proportion = total_building_footprint / plot_projected.area
n_buildings = len(buildings)
building_features['total_building_footprint'] = total_building_footprint
building_features['building_proportion'] = building_proportion
building_features['n_buildings'] = n_buildings
return building_features
def query_buildings(plot_shp, county_fips):
# Wrapper to export
buildings, building_shps, src_meta = get_buildings(plot_shp, county_fips)
building_features = get_building_features(plot_shp, building_shps)
return building_features
def test():
test_geom_w_buildings = {
"type": "Polygon",
"coordinates": [
[
[
-122.40870237350462,
37.78318894806247
],
[
-122.39876747131348,
37.78318894806247
],
[
-122.39876747131348,
37.78836966314214
],
[
-122.40870237350462,
37.78836966314214
],
[
-122.40870237350462,
37.78318894806247
]
]
]
}
test_geom_wo_buildings = {
"type": "Polygon",
"coordinates": [
[
[
-122.44197471761457,
37.768773390348009
],
[
-122.440887982900122,
37.768983204915301
],
[
-122.440764246104024,
37.768095527899852
],
[
-122.442076932114745,
37.767944891800255
],
[
-122.441974714761457,
37.768773390348009
]
]
]
}
test_county_fips = '06075'
test_shp_w_buildings = shape(test_geom_w_buildings)
test_buildings, test_building_shps, meta = get_buildings(test_shp_w_buildings, test_county_fips)
assert len(test_buildings) == 71
test_shp_wo_buildings = shape(test_geom_wo_buildings)
test_no_buildings, test_no_building_shps, meta_no_buildings = get_buildings(test_shp_wo_buildings, test_county_fips)
assert len(test_no_buildings) == 0
print(query_buildings(test_shp_w_buildings, test_county_fips))
print(query_buildings(test_shp_wo_buildings, test_county_fips))
with fiona.open(
'test.shp',
'w',
**meta) as sink:
for building in test_buildings:
sink.write(
{
'geometry': building[1]['geometry'],
'properties': building[1]['properties']
}
)
if __name__ == '__main__':
test()