Skip to content

Commit

Permalink
update facade calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
ni1o1 committed Jan 2, 2024
1 parent 070cf36 commit 3ccb12e
Show file tree
Hide file tree
Showing 9 changed files with 1,333 additions and 46 deletions.
119 changes: 119 additions & 0 deletions example/Example2-facade shadow.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"\n",
"import pandas as pd\n",
"import warnings\n",
"warnings.filterwarnings('ignore')\n",
"\n",
"\n",
"import pybdshadow\n",
"MAPBOX_ACCESS_TOKEN = \"pk.eyJ1IjoibmkxbzEiLCJhIjoiY2t3ZDgzMmR5NDF4czJ1cm84Z3NqOGt3OSJ9.yOYP6pxDzXzhbHfyk3uORg\"\n",
"bounds = [139.803137,35.690984,139.804437,35.692684]\n",
"buildings_gdf = pybdshadow.get_buildings_by_bounds(139.804337,35.692584,139.804437,35.692684,MAPBOX_ACCESS_TOKEN)\n",
"\n",
"\n",
"buildings_gdf['x'] = buildings_gdf.centroid.x\n",
"buildings_gdf['y'] = buildings_gdf.centroid.y\n",
"buildings_gdf = buildings_gdf[(buildings_gdf['x'] > bounds[0]) &\n",
" (buildings_gdf['x'] < bounds[2]) &\n",
" (buildings_gdf['y'] > bounds[1]) &\n",
" (buildings_gdf['y'] < bounds[3])]\n",
"buildings_gdf.plot()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"precision = 3600\n",
"date = '2022-01-01'\n",
"wallsunshine = pybdshadow.cal_sunshine_facade(buildings_gdf, date, precision)\n",
"\n",
"\n",
"floorsunshine = pybdshadow.cal_sunshine(buildings_gdf,\n",
" day=date,\n",
" roof=False,\n",
" accuracy='vector',\n",
" precision=precision)\n",
"floorsunshine['height'] = 0\n",
"\n",
"roofsunshine = pybdshadow.cal_sunshine(buildings_gdf,\n",
" day=date,\n",
" roof=True,\n",
" accuracy='vector',\n",
" precision=precision\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"User Guide: https://docs.kepler.gl/docs/keplergl-jupyter\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "90b88e3da79444708001c3ebdbf20e5d",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"KeplerGl(config={'version': 'v1', 'config': {'visState': {'filters': [], 'layers': [{'id': 'lz48o4', 'type': '…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"\n",
"# 生成立体建筑物\n",
"plane_sunshine = pd.concat([floorsunshine,roofsunshine],axis=0)\n",
"\n",
"plane_sunshine['geometry'] = plane_sunshine.apply(lambda x: pybdshadow.extrude_poly(x['geometry'],x['height']),axis=1)\n",
"\n",
"final_shadows_sunshinetime = pd.concat([plane_sunshine,wallsunshine],axis=0)\n",
"\n",
"vis = pybdshadow.show_sunshine(sunshine = final_shadows_sunshinetime,\n",
" zoom='auto',vis_height = 1000)\n",
"vis"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "py38_native",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.13"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
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

0 comments on commit 3ccb12e

Please sign in to comment.