File size: 6,083 Bytes
3894000 a767f1e 3894000 de3d1f9 3894000 de3d1f9 a767f1e de3d1f9 a767f1e de3d1f9 a767f1e de3d1f9 a767f1e de3d1f9 a767f1e de3d1f9 a767f1e 3894000 de3d1f9 a767f1e 3894000 de3d1f9 3894000 de3d1f9 3894000 a767f1e de3d1f9 3894000 de3d1f9 3894000 de3d1f9 86258b2 3894000 de3d1f9 c3c16bf de3d1f9 3894000 86258b2 3894000 |
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 |
import gradio as gr
import geopandas as gpd
import os
from shapely.geometry import shape
#from datasets import load_dataset
#ds = load_dataset('psalama/NYC_sensitive_sites', data_files=data_files)
def process_buildings(input_gdf, sensitive_sites_gdf, default_building_height_m, multiplier_factor):
# List to store all intersected sensitive sites
intersected_sites = []
# List to store all buffers
buffers = []
intersection_desc = ""
# Iterate over each building in the input file
for idx, building in input_gdf.iterrows():
building_name = building.get('building_name', 'Unnamed building')
# If the 'building_height' field exists and its value is not null or zero for this building,
# use it as the building height. Otherwise, use the default building height provided by the user.
if 'building_height' in building and pd.notnull(building['building_height']) and building['building_height'] != 0:
building_height_m = building['building_height'] * 0.3048
else:
building_height_m = default_building_height_m
buffer_distance_m = building_height_m * multiplier_factor
# Convert building's geometry to EPSG:3857 for accurate meter-based distance measurement
building_geometry = gpd.GeoSeries([building['geometry']], crs="EPSG:4326")
building_geometry_m = building_geometry.to_crs("EPSG:3857")
# Create a buffer around the building and convert it to a GeoDataFrame
building_buffer = building_geometry_m.buffer(buffer_distance_m)
building_buffer_gdf = gpd.GeoDataFrame(geometry=building_buffer, crs="EPSG:3857")
building_buffer_gdf = building_buffer_gdf.to_crs("EPSG:4326")
# Convert back to feet for storing and printing, rounding to the nearest foot
building_height_ft = round(building_height_m / 0.3048)
buffer_distance_ft = round(buffer_distance_m / 0.3048)
# Assign additional attributes
building_buffer_gdf['building_name'] = building_name
building_buffer_gdf['building_height'] = building_height_ft
building_buffer_gdf['buffer_distance'] = buffer_distance_ft
buffers.append(building_buffer_gdf)
# Check if the buffer intersects with any sensitive sites
intersects = gpd.overlay(building_buffer_gdf, sensitive_sites_gdf, how='intersection')
if not intersects.empty:
building_intersect_desc = f"Building {idx} ({building_name}), height: {building_height_ft}, buffer distance: {buffer_distance_ft} is in the vicinity of a sensitive site."
intersected_sites.append(intersects)
else:
building_intersect_desc = f"Building {idx} ({building_name}), height: {building_height_ft}, buffer distance: {buffer_distance_ft} is not in the vicinity of any sensitive sites."
intersection_desc = "\n".join(intersection_desc, building_intersect_desc)
return buffers, intersected_sites, intersection_desc
def ss_intersect(geojson1, ss_geoselect, multiplier_factor, default_building_height):
# Read the GeoJSON files
input_gdf = gpd.read_file(geojson1.name)
# Check that CRS is EPSG:4326
if input_gdf.crs.to_epsg() != 4326 or sensitive_sites_gdf.crs.to_epsg() != 4326:
raise ValueError("Input GeoJSON files must be in CRS EPSG:4326")
if ss_geoselect==0:
sensitive_sites_gdf = gpd.read_file("sensitive_sites/NYC_Parks_Properties.geojson")
else:
sensitive_sites_gdf = gpd.read_file("sensitive_sites/NYC_Parks_Zones.geojson")
default_building_height_m = default_building_height * 0.3048
buffers, intersected_sites, intersection_desc = process_buildings(input_gdf, sensitive_sites_gdf, default_building_height_m, multiplier_factor)
# Concatenate all buffer GeoDataFrames and save as a GeoJSON file
buffers_gdf = pd.concat(buffers, ignore_index=True)
buffers_gdf = buffers_gdf.to_crs("EPSG:4326")
buffers_gdf.to_file("building_buffers.geojson", driver='GeoJSON')
# Concatenate all intersected sensitive sites and save as a GeoJSON file
if intersected_sites:
intersected_sites_gdf = pd.concat(intersected_sites, ignore_index=True)
intersected_sites_gdf = intersected_sites_gdf.to_crs("EPSG:4326")
intersected_sites_gdf.to_file("intersected_sensitive_sites.geojson", driver='GeoJSON')
else:
print("No buildings are in the vicinity of any sensitive sites.")
# Perform the union operation if there is more than one buffer
if len(buffers) > 1:
# Perform a unary union on the geometry column of the GeoDataFrame
buffer_union = unary_union(buffers_gdf['geometry'])
# Create a new GeoDataFrame from the union result
buffer_union_gdf = gpd.GeoDataFrame(geometry=[buffer_union], crs="EPSG:4326")
# Save the union GeoDataFrame as a GeoJSON file
buffer_union_gdf.to_file("buffer_union.geojson", driver='GeoJSON')
# Return the image
return "building_buffers.geojson", intersection_desc
iface = gr.Interface(
fn=ss_intersect,
inputs=[
gr.inputs.File(label="Building Footprints GeoJSON"),
gr.Radio(["Parks Properties", "Park Zones"], label="Which Sensitive Sites?", info="From NYC DPR", type="index"),
#gr.inputs.File(label="Sensitive Sites GeoJSON"), #Replaced by radio button above
gr.inputs.Slider(minimum=0.0, maximum=10.0, default=4.3, label="Building Height Multiplier"),
gr.inputs.Number(default=200, label="Default Building Height"), #Can I make this optional?
],
outputs=[
gr.outputs.File(label="Intersecting Buildings"),
gr.outputs.Textbox(label="Building and Sensitive Site Vicinities"),
],
examples=[
["files/building4test.geojson", "Parks Properties", 4.3, 200],
],
title="Shadow Proximity",
description="Upload proposed building footprints in a GeoJSON file and select a numeric value to get the building proximity prediction.",
)
iface.launch() |