Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.3.5 #21

Merged
merged 5 commits into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
python-version: ["3.7", "3.8", "3.9"]
python-version: ["3.8", "3.9"]

steps:
- uses: actions/checkout@v2
Expand Down
174 changes: 174 additions & 0 deletions example/Example2-facade shadow.ipynb

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ suncalc
keplergl
scikit-opt
transbigdata
mapbox_vector_tile
vt2geojson
requests
tqdm
retrying
7 changes: 3 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="pybdshadow",
version="0.3.4",
version="0.3.5",
author="Qing Yu",
author_email="[email protected]",
description="Python package to generate building shadow geometry",
Expand All @@ -17,7 +17,7 @@
"Bug Tracker": "https://github.com/ni1o1/pybdshadow/issues",
},
install_requires=[
"numpy", "pandas", "shapely", "geopandas", "matplotlib","suncalc","keplergl","transbigdata"
"numpy", "pandas", "shapely", "geopandas", "matplotlib","suncalc","keplergl","transbigdata","mapbox_vector_tile","vt2geojson","requests","tqdm","retrying"
],
classifiers=[
"Operating System :: OS Independent",
Expand All @@ -26,11 +26,10 @@
"Topic :: Software Development :: Libraries :: Python Modules",
"License :: OSI Approved :: BSD License",
"Programming Language :: Python",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
],
package_dir={'pybdshadow': 'src/pybdshadow'},
packages=['pybdshadow'],
python_requires=">=3.6",
python_requires=">=3.8",
)
22 changes: 20 additions & 2 deletions src/pybdshadow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,18 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

__version__ = '0.3.4'
__version__ = '0.3.5'
__author__ = 'Qing Yu <[email protected]>'

# module level doc-string
__doc__ = """
`pybdshadow` - Python package to generate building shadow geometry.
"""
from .pybdshadow import *
from .get_buildings import (
get_buildings_by_polygon,
get_buildings_by_bounds,
)
from .pybdshadow import (
bdshadow_sunlight,
bdshadow_pointlight
Expand All @@ -49,6 +53,7 @@
)
from .visualization import (
show_bdshadow,
show_sunshine,
)
from .analysis import (
cal_sunshine,
Expand All @@ -57,12 +62,25 @@
get_timetable
)

from .facade import (
cal_sunshine_facade
)

from .utils import (
extrude_poly
)

__all__ = ['bdshadow_sunlight',
'bdshadow_pointlight',
'bd_preprocess',
'show_bdshadow',
'cal_sunshine',
'cal_sunshadows',
'cal_shadowcoverage',
'get_timetable'
'get_timetable',
'get_buildings_by_polygon',
'get_buildings_by_bounds',
'cal_sunshine_facade',
'show_sunshine',
'extrude_poly'
]
63 changes: 38 additions & 25 deletions src/pybdshadow/analysis.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import pandas as pd
from suncalc import get_times
from shapely.geometry import MultiPolygon
from shapely.geometry import MultiPolygon,Polygon
import transbigdata as tbd
import geopandas as gpd
from .pybdshadow import (
bdshadow_sunlight,
)
from .preprocess import bd_preprocess

from .utils import count_overlapping_features

def get_timetable(lon, lat, dates=['2022-01-01'], precision=3600, padding=1800):
# generate timetable with given interval
Expand Down Expand Up @@ -56,6 +56,8 @@ def cal_sunshine(buildings, day='2022-01-01', roof=False, grids=gpd.GeoDataFrame
grids generated by TransBigData in study area, each grids have a `time` column store the sunshine time

'''


# calculate day time duration
lon, lat = buildings['geometry'].iloc[0].bounds[:2]
date = pd.to_datetime(day+' 12:45:33.959797119')
Expand All @@ -73,22 +75,47 @@ def cal_sunshine(buildings, day='2022-01-01', roof=False, grids=gpd.GeoDataFrame
if accuracy == 'vector':
if roof:
shadows = shadows[shadows['type'] == 'roof']
shadows = bd_preprocess(shadows)
shadows = shadows.groupby(['date', 'type'])['geometry'].apply(
lambda df: MultiPolygon(list(df)).buffer(0)).reset_index()
shadows = bd_preprocess(shadows)
shadows = count_overlapping_features(shadows)
if len(shadows)>0:
shadows = bd_preprocess(shadows)
shadows = shadows.groupby(['date', 'type','height'])['geometry'].apply(
lambda df: MultiPolygon(list(df)).buffer(0)).reset_index()
shadows = bd_preprocess(shadows)

# 额外:增加屋顶面
shadows = pd.concat([shadows, buildings])
#return shadows
shadows = shadows.groupby('height').apply(count_overlapping_features).reset_index()
shadows['count'] -= 1
else:
shadows = shadows[shadows['type'] == 'ground']

shadows = bd_preprocess(shadows)
shadows = shadows.groupby(['date', 'type'])['geometry'].apply(
lambda df: MultiPolygon(list(df)).buffer(0)).reset_index()
lambda df: MultiPolygon(list(df)).buffer(0)).reset_index()
shadows = bd_preprocess(shadows)
shadows = count_overlapping_features(shadows)

# 额外:增加地面面
minpos = shadows.bounds[['minx','miny']].min()
maxpos = shadows.bounds[['maxx','maxy']].max()

ground = gpd.GeoDataFrame(geometry=[
Polygon([
[minpos['minx'],minpos['miny']],
[minpos['minx'],maxpos['maxy']],
[maxpos['maxx'],maxpos['maxy']],
[maxpos['maxx'],minpos['miny']],
])
])
shadows = pd.concat([shadows,
ground
])
shadows = count_overlapping_features(shadows,buffer=False)
shadows['count'] -= 1


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

grids['Hour'] = sunlighthour-grids['time']/3600
return grids


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

return grids


def count_overlapping_features(gdf):
import shapely
bounds = gdf.geometry.exterior.unary_union
new_polys = list(shapely.ops.polygonize(bounds))
new_gdf = gpd.GeoDataFrame(geometry=new_polys)
new_gdf['id'] = range(len(new_gdf))
new_gdf_centroid = new_gdf.copy()
new_gdf_centroid['geometry'] = new_gdf.centroid
overlapcount = gpd.sjoin(new_gdf_centroid, gdf)
overlapcount = overlapcount.groupby(
['id'])['index_right'].count().rename('count').reset_index()
out_gdf = pd.merge(new_gdf, overlapcount)
return out_gdf
Loading
Loading