1
1
import pandas as pd
2
2
from suncalc import get_times
3
- from shapely .geometry import MultiPolygon
3
+ from shapely .geometry import MultiPolygon , Polygon
4
4
import transbigdata as tbd
5
5
import geopandas as gpd
6
6
from .pybdshadow import (
7
7
bdshadow_sunlight ,
8
8
)
9
9
from .preprocess import bd_preprocess
10
-
10
+ from . utils import count_overlapping_features
11
11
12
12
def get_timetable (lon , lat , dates = ['2022-01-01' ], precision = 3600 , padding = 1800 ):
13
13
# generate timetable with given interval
@@ -56,6 +56,8 @@ def cal_sunshine(buildings, day='2022-01-01', roof=False, grids=gpd.GeoDataFrame
56
56
grids generated by TransBigData in study area, each grids have a `time` column store the sunshine time
57
57
58
58
'''
59
+
60
+
59
61
# calculate day time duration
60
62
lon , lat = buildings ['geometry' ].iloc [0 ].bounds [:2 ]
61
63
date = pd .to_datetime (day + ' 12:45:33.959797119' )
@@ -73,22 +75,47 @@ def cal_sunshine(buildings, day='2022-01-01', roof=False, grids=gpd.GeoDataFrame
73
75
if accuracy == 'vector' :
74
76
if roof :
75
77
shadows = shadows [shadows ['type' ] == 'roof' ]
76
- shadows = bd_preprocess (shadows )
77
- shadows = shadows .groupby (['date' , 'type' ])['geometry' ].apply (
78
- lambda df : MultiPolygon (list (df )).buffer (0 )).reset_index ()
79
- shadows = bd_preprocess (shadows )
80
- shadows = count_overlapping_features (shadows )
78
+ if len (shadows )> 0 :
79
+ shadows = bd_preprocess (shadows )
80
+ shadows = shadows .groupby (['date' , 'type' ,'height' ])['geometry' ].apply (
81
+ lambda df : MultiPolygon (list (df )).buffer (0 )).reset_index ()
82
+ shadows = bd_preprocess (shadows )
83
+
84
+ # 额外:增加屋顶面
85
+ shadows = pd .concat ([shadows , buildings ])
86
+ #return shadows
87
+ shadows = shadows .groupby ('height' ).apply (count_overlapping_features ).reset_index ()
88
+ shadows ['count' ] -= 1
81
89
else :
82
90
shadows = shadows [shadows ['type' ] == 'ground' ]
91
+
83
92
shadows = bd_preprocess (shadows )
84
93
shadows = shadows .groupby (['date' , 'type' ])['geometry' ].apply (
85
- lambda df : MultiPolygon (list (df )).buffer (0 )).reset_index ()
94
+ lambda df : MultiPolygon (list (df )).buffer (0 )).reset_index ()
86
95
shadows = bd_preprocess (shadows )
87
- shadows = count_overlapping_features (shadows )
96
+
97
+ # 额外:增加地面面
98
+ minpos = shadows .bounds [['minx' ,'miny' ]].min ()
99
+ maxpos = shadows .bounds [['maxx' ,'maxy' ]].max ()
100
+
101
+ ground = gpd .GeoDataFrame (geometry = [
102
+ Polygon ([
103
+ [minpos ['minx' ],minpos ['miny' ]],
104
+ [minpos ['minx' ],maxpos ['maxy' ]],
105
+ [maxpos ['maxx' ],maxpos ['maxy' ]],
106
+ [maxpos ['maxx' ],minpos ['miny' ]],
107
+ ])
108
+ ])
109
+ shadows = pd .concat ([shadows ,
110
+ ground
111
+ ])
112
+ shadows = count_overlapping_features (shadows ,buffer = False )
113
+ shadows ['count' ] -= 1
114
+
88
115
89
116
shadows ['time' ] = shadows ['count' ]* precision
90
117
shadows ['Hour' ] = sunlighthour - shadows ['time' ]/ 3600
91
- shadows .loc [shadows ['Hour' ] <= 0 , 'Hour' ] = 0
118
+ # shadows.loc[shadows['Hour'] <= 0, 'Hour'] = 0
92
119
return shadows
93
120
else :
94
121
# Grid analysis of shadow cover duration(ground).
@@ -97,7 +124,7 @@ def cal_sunshine(buildings, day='2022-01-01', roof=False, grids=gpd.GeoDataFrame
97
124
98
125
grids ['Hour' ] = sunlighthour - grids ['time' ]/ 3600
99
126
return grids
100
-
127
+
101
128
102
129
def cal_sunshadows (buildings , cityname = 'somecity' , dates = ['2022-01-01' ], precision = 3600 , padding = 1800 ,
103
130
roof = True , include_building = True , save_shadows = False , printlog = False ):
@@ -222,17 +249,3 @@ def cal_shadowcoverage(shadows_input, buildings, grids=gpd.GeoDataFrame(), roof=
222
249
223
250
return grids
224
251
225
-
226
- def count_overlapping_features (gdf ):
227
- import shapely
228
- bounds = gdf .geometry .exterior .unary_union
229
- new_polys = list (shapely .ops .polygonize (bounds ))
230
- new_gdf = gpd .GeoDataFrame (geometry = new_polys )
231
- new_gdf ['id' ] = range (len (new_gdf ))
232
- new_gdf_centroid = new_gdf .copy ()
233
- new_gdf_centroid ['geometry' ] = new_gdf .centroid
234
- overlapcount = gpd .sjoin (new_gdf_centroid , gdf )
235
- overlapcount = overlapcount .groupby (
236
- ['id' ])['index_right' ].count ().rename ('count' ).reset_index ()
237
- out_gdf = pd .merge (new_gdf , overlapcount )
238
- return out_gdf
0 commit comments