Skip to content

Commit afcc53c

Browse files
authored
Merge pull request #21 from ni1o1/0.3.5
0.3.5
2 parents 070cf36 + ffd85ea commit afcc53c

File tree

12 files changed

+1397
-51
lines changed

12 files changed

+1397
-51
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
strategy:
2828
matrix:
2929
os: [ubuntu-latest]
30-
python-version: ["3.7", "3.8", "3.9"]
30+
python-version: ["3.8", "3.9"]
3131

3232
steps:
3333
- uses: actions/checkout@v2

example/Example2-facade shadow.ipynb

Lines changed: 174 additions & 0 deletions
Large diffs are not rendered by default.

requirements.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ suncalc
66
keplergl
77
scikit-opt
88
transbigdata
9+
mapbox_vector_tile
10+
vt2geojson
11+
requests
12+
tqdm
13+
retrying

setup.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setuptools.setup(
77
name="pybdshadow",
8-
version="0.3.4",
8+
version="0.3.5",
99
author="Qing Yu",
1010
author_email="[email protected]",
1111
description="Python package to generate building shadow geometry",
@@ -17,7 +17,7 @@
1717
"Bug Tracker": "https://github.com/ni1o1/pybdshadow/issues",
1818
},
1919
install_requires=[
20-
"numpy", "pandas", "shapely", "geopandas", "matplotlib","suncalc","keplergl","transbigdata"
20+
"numpy", "pandas", "shapely", "geopandas", "matplotlib","suncalc","keplergl","transbigdata","mapbox_vector_tile","vt2geojson","requests","tqdm","retrying"
2121
],
2222
classifiers=[
2323
"Operating System :: OS Independent",
@@ -26,11 +26,10 @@
2626
"Topic :: Software Development :: Libraries :: Python Modules",
2727
"License :: OSI Approved :: BSD License",
2828
"Programming Language :: Python",
29-
"Programming Language :: Python :: 3.7",
3029
"Programming Language :: Python :: 3.8",
3130
"Programming Language :: Python :: 3.9",
3231
],
3332
package_dir={'pybdshadow': 'src/pybdshadow'},
3433
packages=['pybdshadow'],
35-
python_requires=">=3.6",
34+
python_requires=">=3.8",
3635
)

src/pybdshadow/__init__.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,18 @@
3232
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3333
"""
3434

35-
__version__ = '0.3.4'
35+
__version__ = '0.3.5'
3636
__author__ = 'Qing Yu <[email protected]>'
3737

3838
# module level doc-string
3939
__doc__ = """
4040
`pybdshadow` - Python package to generate building shadow geometry.
4141
"""
4242
from .pybdshadow import *
43+
from .get_buildings import (
44+
get_buildings_by_polygon,
45+
get_buildings_by_bounds,
46+
)
4347
from .pybdshadow import (
4448
bdshadow_sunlight,
4549
bdshadow_pointlight
@@ -49,6 +53,7 @@
4953
)
5054
from .visualization import (
5155
show_bdshadow,
56+
show_sunshine,
5257
)
5358
from .analysis import (
5459
cal_sunshine,
@@ -57,12 +62,25 @@
5762
get_timetable
5863
)
5964

65+
from .facade import (
66+
cal_sunshine_facade
67+
)
68+
69+
from .utils import (
70+
extrude_poly
71+
)
72+
6073
__all__ = ['bdshadow_sunlight',
6174
'bdshadow_pointlight',
6275
'bd_preprocess',
6376
'show_bdshadow',
6477
'cal_sunshine',
6578
'cal_sunshadows',
6679
'cal_shadowcoverage',
67-
'get_timetable'
80+
'get_timetable',
81+
'get_buildings_by_polygon',
82+
'get_buildings_by_bounds',
83+
'cal_sunshine_facade',
84+
'show_sunshine',
85+
'extrude_poly'
6886
]

src/pybdshadow/analysis.py

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import pandas as pd
22
from suncalc import get_times
3-
from shapely.geometry import MultiPolygon
3+
from shapely.geometry import MultiPolygon,Polygon
44
import transbigdata as tbd
55
import geopandas as gpd
66
from .pybdshadow import (
77
bdshadow_sunlight,
88
)
99
from .preprocess import bd_preprocess
10-
10+
from .utils import count_overlapping_features
1111

1212
def get_timetable(lon, lat, dates=['2022-01-01'], precision=3600, padding=1800):
1313
# generate timetable with given interval
@@ -56,6 +56,8 @@ def cal_sunshine(buildings, day='2022-01-01', roof=False, grids=gpd.GeoDataFrame
5656
grids generated by TransBigData in study area, each grids have a `time` column store the sunshine time
5757
5858
'''
59+
60+
5961
# calculate day time duration
6062
lon, lat = buildings['geometry'].iloc[0].bounds[:2]
6163
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
7375
if accuracy == 'vector':
7476
if roof:
7577
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
8189
else:
8290
shadows = shadows[shadows['type'] == 'ground']
91+
8392
shadows = bd_preprocess(shadows)
8493
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()
8695
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+
88115

89116
shadows['time'] = shadows['count']*precision
90117
shadows['Hour'] = sunlighthour-shadows['time']/3600
91-
shadows.loc[shadows['Hour'] <= 0, 'Hour'] = 0
118+
#shadows.loc[shadows['Hour'] <= 0, 'Hour'] = 0
92119
return shadows
93120
else:
94121
# Grid analysis of shadow cover duration(ground).
@@ -97,7 +124,7 @@ def cal_sunshine(buildings, day='2022-01-01', roof=False, grids=gpd.GeoDataFrame
97124

98125
grids['Hour'] = sunlighthour-grids['time']/3600
99126
return grids
100-
127+
101128

102129
def cal_sunshadows(buildings, cityname='somecity', dates=['2022-01-01'], precision=3600, padding=1800,
103130
roof=True, include_building=True, save_shadows=False, printlog=False):
@@ -222,17 +249,3 @@ def cal_shadowcoverage(shadows_input, buildings, grids=gpd.GeoDataFrame(), roof=
222249

223250
return grids
224251

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

Comments
 (0)