File size: 7,163 Bytes
3894000 780fa43 a767f1e b3c40c7 3894000 6f842ea de3d1f9 3894000 de3d1f9 a767f1e de3d1f9 a767f1e de3d1f9 a767f1e de3d1f9 a767f1e de3d1f9 ec0024a a767f1e de3d1f9 b3c40c7 a767f1e 3894000 de3d1f9 064f2e2 de3d1f9 a767f1e 3894000 de3d1f9 3894000 de3d1f9 b3c40c7 09cddb2 de3d1f9 3894000 ec0024a de3d1f9 3894000 de3d1f9 3894000 de3d1f9 86258b2 3894000 de3d1f9 ad6c4be 89a1ce6 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 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
import gradio as gr
import geopandas as gpd
import pandas as pd
import os
import matplotlib.pyplot as plt
from shapely.geometry import shape
from shapely.ops import unary_union
#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."
if intersection_desc == "":
intersection_desc = building_intersect_desc
else:
intersection_desc += "\n" + building_intersect_desc
return buffers, intersected_sites, intersection_desc
def get_max_extent(*gdfs):
minx = min(gdf.total_bounds[0] for gdf in gdfs)
miny = min(gdf.total_bounds[1] for gdf in gdfs)
maxx = max(gdf.total_bounds[2] for gdf in gdfs)
maxy = max(gdf.total_bounds[3] for gdf in gdfs)
return minx, miny, maxx, maxy
def create_plot(filename, extent, *gdfs):
fig, ax = plt.subplots(1, 1)
colors = ['blue', 'red', 'green', 'purple', 'orange', 'yellow'] # Extend this list as needed
for idx, gdf in enumerate(gdfs):
gdf.plot(ax=ax, color=colors[idx % len(colors)]) # Cycle through colors
ax.set_xlim(extent[0], extent[2])
ax.set_ylim(extent[1], extent[3])
plt.savefig(filename)
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:
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')
# Calculate the maximum extent
extent = get_max_extent(input_gdf, buffers_gdf)
# Create and save the plot
create_plot('output_image.png', extent, buffer_union_gdf, intersected_sites_gdf, input_gdf)
# Return the image
return 'output_image.png', "building_buffers.geojson", "buffer_union.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.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.Image(type="pil", label="Result Image"),
gr.outputs.File(label="Building Buffers"),
gr.outputs.File(label="Union of Building Buffers"),
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() |