Updated scripts and data to decency

This commit is contained in:
Will Bradley 2025-06-29 11:16:59 -07:00
parent a1521f4a47
commit db30603068
5 changed files with 7 additions and 96 deletions

Binary file not shown.

View File

@ -1,95 +1,5 @@
import geopandas as gpd import geopandas
from shapely.geometry import LineString, MultiLineString, Polygon, MultiPolygon df = geopandas.read_file('original data/Sumter/RoadCenterlines_041125.shp.zip')
import pandas as pd
df = gpd.read_file('original data/Sumter/RoadCenterlines_041125.shp.zip') #, crs=2237 NAD83 / Florida West (ftUS)
df = df.to_crs(4326) # Convert to WGS 84 df = df.to_crs(4326) # Convert to WGS 84
exploded = df.explode()
def convert_to_linestrings(geom): exploded.to_file('original data/Sumter/RoadCenterlines_041125.geojson', driver='GeoJSON')
"""Convert any geometry to a list of LineStrings"""
linestrings = []
if geom is None or geom.is_empty:
return []
# If it's already a LineString, just return it
if isinstance(geom, LineString):
linestrings.append(geom)
# If it's a MultiLineString, extract all LineStrings
elif isinstance(geom, MultiLineString):
for line in geom.geoms:
linestrings.append(line)
# If it's a Polygon, convert boundary to LineString(s)
elif isinstance(geom, Polygon):
# Exterior boundary
if not geom.exterior.is_empty:
linestrings.append(LineString(geom.exterior.coords))
# Interior boundaries (holes)
for interior in geom.interiors:
if not interior.is_empty:
linestrings.append(LineString(interior.coords))
# If it's a MultiPolygon, process each polygon
elif isinstance(geom, MultiPolygon):
for poly in geom.geoms:
# Exterior boundary
if not poly.exterior.is_empty:
linestrings.append(LineString(poly.exterior.coords))
# Interior boundaries (holes)
for interior in poly.interiors:
if not interior.is_empty:
linestrings.append(LineString(interior.coords))
return linestrings
def explode_linestring(linestring):
"""Convert a LineString into individual segments"""
if linestring is None or linestring.is_empty:
return []
coords = list(linestring.coords)
segments = []
for i in range(len(coords) - 1):
segment = LineString([coords[i], coords[i + 1]])
segments.append(segment)
return segments
# Convert all geometries to LineStrings first
df['linestrings'] = df.geometry.apply(convert_to_linestrings)
# Explode to get one row per LineString
df_exploded = df.explode('linestrings')
# Filter out rows with empty linestrings
df_exploded = df_exploded[df_exploded['linestrings'].notna()]
df_exploded = df_exploded[~df_exploded['linestrings'].apply(lambda x: x.is_empty if x is not None else True)]
# Now explode each LineString into segments
df_exploded['segments'] = df_exploded['linestrings'].apply(explode_linestring)
# Explode segments
df_final = df_exploded.explode('segments')
# Filter out empty segments
df_final = df_final[df_final['segments'].notna()]
df_final = df_final[~df_final['segments'].apply(lambda x: x.is_empty if x is not None else True)]
# Create final GeoDataFrame with segments as geometry
dfline = gpd.GeoDataFrame(
data=df_final.drop(['geometry', 'linestrings', 'segments'], axis=1),
geometry=df_final['segments'],
crs=df.crs
)
# Reset index
dfline = dfline.reset_index(drop=True)
# Save to GeoJSON
dfline.to_file('original data/Sumter/RoadCenterlines_041125.geojson', driver='GeoJSON')
print(f"Converted {len(df)} original features to {len(dfline)} line segments")
print(f"Geometry types in output: {dfline.geometry.geom_type.value_counts()}")

View File

@ -321,7 +321,9 @@ class RoadComparator:
elif key == 'SpeedLimit': elif key == 'SpeedLimit':
properties['maxspeed'] = f"{value} mph" if value is not None else None properties['maxspeed'] = f"{value} mph" if value is not None else None
elif key == 'RoadClass': elif key == 'RoadClass':
if value.startswith('PRIMARY'): if value is None:
properties['highway'] = 'residential'
elif value.startswith('PRIMARY'):
properties['highway'] = 'trunk' properties['highway'] = 'trunk'
elif value.startswith('MAJOR'): elif value.startswith('MAJOR'):
properties['highway'] = 'primary' properties['highway'] = 'primary'
@ -431,7 +433,6 @@ class RoadComparator:
if field in segment and pd.notna(segment[field]): if field in segment and pd.notna(segment[field]):
road_name = str(segment[field]) road_name = str(segment[field])
break break
if road_name not in removed_by_road: if road_name not in removed_by_road:
removed_by_road[road_name] = [] removed_by_road[road_name] = []
removed_by_road[road_name].append(length_feet) removed_by_road[road_name].append(length_feet)