forked from hans/Nominatim
For python2 the gdal features come out as str and cannot be combined with unicode strings.
620 lines
23 KiB
Python
Executable File
620 lines
23 KiB
Python
Executable File
#!/usr/bin/python
|
|
# Tiger road data to OSM conversion script
|
|
# Creates Karlsruhe-style address ways beside the main way
|
|
# based on the Massachusetts GIS script by christopher schmidt
|
|
|
|
#BUGS:
|
|
# On very tight curves, a loop may be generated in the address way.
|
|
# It would be nice if the ends of the address ways were not pulled back from dead ends
|
|
|
|
|
|
# Ways that include these mtfccs should not be uploaded
|
|
# H1100 Connector
|
|
# H3010 Stream/River
|
|
# H3013 Braided Stream
|
|
# H3020 Canal, Ditch or Aqueduct
|
|
# L4130 Point-to-Point Line
|
|
# L4140 Property/Parcel Line (Including PLSS)
|
|
# P0001 Nonvisible Linear Legal/Statistical Boundary
|
|
# P0002 Perennial Shoreline
|
|
# P0003 Intermittent Shoreline
|
|
# P0004 Other non-visible bounding Edge (e.g., Census water boundary, boundary of an areal feature)
|
|
ignoremtfcc = [ "H1100", "H3010", "H3013", "H3020", "L4130", "L4140", "P0001", "P0002", "P0003", "P0004" ]
|
|
|
|
# Sets the distance that the address ways should be from the main way, in feet.
|
|
address_distance = 30
|
|
|
|
# Sets the distance that the ends of the address ways should be pulled back from the ends of the main way, in feet
|
|
address_pullback = 45
|
|
|
|
import sys, os.path, json
|
|
try:
|
|
from osgeo import ogr
|
|
from osgeo import osr
|
|
except:
|
|
import ogr
|
|
import osr
|
|
|
|
# tiger_county_fips was generated from the following:
|
|
# wget http://www.census.gov/datamap/fipslist/AllSt.txt
|
|
# cat AllSt.txt | grep '^ [0-9]' | awk "{printf \"'%s' : '%s' ,\\n\", \$1, substr(\$0, 31)}" | > countyfips.py
|
|
json_fh = open(os.path.dirname(sys.argv[0]) + "/tiger_county_fips.json")
|
|
county_fips_data = json.load(json_fh)
|
|
|
|
def parse_shp_for_geom_and_tags( filename ):
|
|
#ogr.RegisterAll()
|
|
|
|
dr = ogr.GetDriverByName("ESRI Shapefile")
|
|
poDS = dr.Open( filename )
|
|
|
|
if poDS == None:
|
|
raise "Open failed."
|
|
|
|
poLayer = poDS.GetLayer( 0 )
|
|
|
|
fieldNameList = []
|
|
layerDefinition = poLayer.GetLayerDefn()
|
|
for i in range(layerDefinition.GetFieldCount()):
|
|
fieldNameList.append(layerDefinition.GetFieldDefn(i).GetName())
|
|
# sys.stderr.write(",".join(fieldNameList))
|
|
|
|
poLayer.ResetReading()
|
|
|
|
ret = []
|
|
|
|
poFeature = poLayer.GetNextFeature()
|
|
while poFeature:
|
|
tags = {}
|
|
|
|
# WAY ID
|
|
tags["tiger:way_id"] = int( poFeature.GetField("TLID") )
|
|
|
|
# FEATURE IDENTIFICATION
|
|
mtfcc = poFeature.GetField("MTFCC");
|
|
if mtfcc != None:
|
|
|
|
if mtfcc == "L4010": #Pipeline
|
|
tags["man_made"] = "pipeline"
|
|
if mtfcc == "L4020": #Powerline
|
|
tags["power"] = "line"
|
|
if mtfcc == "L4031": #Aerial Tramway/Ski Lift
|
|
tags["aerialway"] = "cable_car"
|
|
if mtfcc == "L4110": #Fence Line
|
|
tags["barrier"] = "fence"
|
|
if mtfcc == "L4125": #Cliff/Escarpment
|
|
tags["natural"] = "cliff"
|
|
if mtfcc == "L4165": #Ferry Crossing
|
|
tags["route"] = "ferry"
|
|
if mtfcc == "R1011": #Railroad Feature (Main, Spur, or Yard)
|
|
tags["railway"] = "rail"
|
|
ttyp = poFeature.GetField("TTYP")
|
|
if ttyp != None:
|
|
if ttyp == "S":
|
|
tags["service"] = "spur"
|
|
if ttyp == "Y":
|
|
tags["service"] = "yard"
|
|
tags["tiger:ttyp"] = ttyp
|
|
if mtfcc == "R1051": #Carline, Streetcar Track, Monorail, Other Mass Transit Rail)
|
|
tags["railway"] = "light_rail"
|
|
if mtfcc == "R1052": #Cog Rail Line, Incline Rail Line, Tram
|
|
tags["railway"] = "incline"
|
|
if mtfcc == "S1100":
|
|
tags["highway"] = "primary"
|
|
if mtfcc == "S1200":
|
|
tags["highway"] = "secondary"
|
|
if mtfcc == "S1400":
|
|
tags["highway"] = "residential"
|
|
if mtfcc == "S1500":
|
|
tags["highway"] = "track"
|
|
if mtfcc == "S1630": #Ramp
|
|
tags["highway"] = "motorway_link"
|
|
if mtfcc == "S1640": #Service Drive usually along a limited access highway
|
|
tags["highway"] = "service"
|
|
if mtfcc == "S1710": #Walkway/Pedestrian Trail
|
|
tags["highway"] = "path"
|
|
if mtfcc == "S1720":
|
|
tags["highway"] = "steps"
|
|
if mtfcc == "S1730": #Alley
|
|
tags["highway"] = "service"
|
|
tags["service"] = "alley"
|
|
if mtfcc == "S1740": #Private Road for service vehicles (logging, oil, fields, ranches, etc.)
|
|
tags["highway"] = "service"
|
|
tags["access"] = "private"
|
|
if mtfcc == "S1750": #Private Driveway
|
|
tags["highway"] = "service"
|
|
tags["access"] = "private"
|
|
tags["service"] = "driveway"
|
|
if mtfcc == "S1780": #Parking Lot Road
|
|
tags["highway"] = "service"
|
|
tags["service"] = "parking_aisle"
|
|
if mtfcc == "S1820": #Bike Path or Trail
|
|
tags["highway"] = "cycleway"
|
|
if mtfcc == "S1830": #Bridle Path
|
|
tags["highway"] = "bridleway"
|
|
tags["tiger:mtfcc"] = mtfcc
|
|
|
|
# FEATURE NAME
|
|
if poFeature.GetField("FULLNAME"):
|
|
#capitalizes the first letter of each word
|
|
name = poFeature.GetField( "FULLNAME" )
|
|
tags["name"] = name
|
|
|
|
#Attempt to guess highway grade
|
|
if name[0:2] == "I-":
|
|
tags["highway"] = "motorway"
|
|
if name[0:3] == "US ":
|
|
tags["highway"] = "primary"
|
|
if name[0:3] == "US-":
|
|
tags["highway"] = "primary"
|
|
if name[0:3] == "Hwy":
|
|
if tags["highway"] != "primary":
|
|
tags["highway"] = "secondary"
|
|
|
|
# TIGER 2017 no longer contains this field
|
|
if 'DIVROAD' in fieldNameList:
|
|
divroad = poFeature.GetField("DIVROAD")
|
|
if divroad != None:
|
|
if divroad == "Y" and "highway" in tags and tags["highway"] == "residential":
|
|
tags["highway"] = "tertiary"
|
|
tags["tiger:separated"] = divroad
|
|
|
|
statefp = poFeature.GetField("STATEFP")
|
|
countyfp = poFeature.GetField("COUNTYFP")
|
|
if (statefp != None) and (countyfp != None):
|
|
county_name = county_fips_data.get(statefp + '' + countyfp)
|
|
if county_name:
|
|
tags["tiger:county"] = county_name.encode("utf-8")
|
|
|
|
# tlid = poFeature.GetField("TLID")
|
|
# if tlid != None:
|
|
# tags["tiger:tlid"] = tlid
|
|
|
|
lfromadd = poFeature.GetField("LFROMADD")
|
|
if lfromadd != None:
|
|
tags["tiger:lfromadd"] = lfromadd
|
|
|
|
rfromadd = poFeature.GetField("RFROMADD")
|
|
if rfromadd != None:
|
|
tags["tiger:rfromadd"] = rfromadd
|
|
|
|
ltoadd = poFeature.GetField("LTOADD")
|
|
if ltoadd != None:
|
|
tags["tiger:ltoadd"] = ltoadd
|
|
|
|
rtoadd = poFeature.GetField("RTOADD")
|
|
if rtoadd != None:
|
|
tags["tiger:rtoadd"] = rtoadd
|
|
|
|
zipl = poFeature.GetField("ZIPL")
|
|
if zipl != None:
|
|
tags["tiger:zip_left"] = zipl
|
|
|
|
zipr = poFeature.GetField("ZIPR")
|
|
if zipr != None:
|
|
tags["tiger:zip_right"] = zipr
|
|
|
|
if mtfcc not in ignoremtfcc:
|
|
# COPY DOWN THE GEOMETRY
|
|
geom = []
|
|
|
|
rawgeom = poFeature.GetGeometryRef()
|
|
for i in range( rawgeom.GetPointCount() ):
|
|
geom.append( (rawgeom.GetX(i), rawgeom.GetY(i)) )
|
|
|
|
ret.append( (geom, tags) )
|
|
poFeature = poLayer.GetNextFeature()
|
|
|
|
return ret
|
|
|
|
|
|
# ====================================
|
|
# to do read .prj file for this data
|
|
# Change the Projcs_wkt to match your datas prj file.
|
|
# ====================================
|
|
projcs_wkt = \
|
|
"""GEOGCS["GCS_North_American_1983",
|
|
DATUM["D_North_American_1983",
|
|
SPHEROID["GRS_1980",6378137,298.257222101]],
|
|
PRIMEM["Greenwich",0],
|
|
UNIT["Degree",0.017453292519943295]]"""
|
|
|
|
from_proj = osr.SpatialReference()
|
|
from_proj.ImportFromWkt( projcs_wkt )
|
|
|
|
# output to WGS84
|
|
to_proj = osr.SpatialReference()
|
|
to_proj.SetWellKnownGeogCS( "EPSG:4326" )
|
|
|
|
tr = osr.CoordinateTransformation( from_proj, to_proj )
|
|
|
|
import math
|
|
def length(segment, nodelist):
|
|
'''Returns the length (in feet) of a segment'''
|
|
first = True
|
|
distance = 0
|
|
lat_feet = 364613 #The approximate number of feet in one degree of latitude
|
|
for point in segment:
|
|
pointid, (lat, lon) = nodelist[ round_point( point ) ]
|
|
if first:
|
|
first = False
|
|
else:
|
|
#The approximate number of feet in one degree of longitute
|
|
lrad = math.radians(lat)
|
|
lon_feet = 365527.822 * math.cos(lrad) - 306.75853 * math.cos(3 * lrad) + 0.3937 * math.cos(5 * lrad)
|
|
distance += math.sqrt(((lat - previous[0])*lat_feet)**2 + ((lon - previous[1])*lon_feet)**2)
|
|
previous = (lat, lon)
|
|
return distance
|
|
|
|
def addressways(waylist, nodelist, first_id):
|
|
id = first_id
|
|
lat_feet = 364613 #The approximate number of feet in one degree of latitude
|
|
distance = float(address_distance)
|
|
ret = []
|
|
|
|
for waykey, segments in waylist.items():
|
|
waykey = dict(waykey)
|
|
rsegments = []
|
|
lsegments = []
|
|
for segment in segments:
|
|
lsegment = []
|
|
rsegment = []
|
|
lastpoint = None
|
|
|
|
# Don't pull back the ends of very short ways too much
|
|
seglength = length(segment, nodelist)
|
|
if seglength < float(address_pullback) * 3.0:
|
|
pullback = seglength / 3.0
|
|
else:
|
|
pullback = float(address_pullback)
|
|
if "tiger:lfromadd" in waykey:
|
|
lfromadd = waykey["tiger:lfromadd"]
|
|
else:
|
|
lfromadd = None
|
|
if "tiger:ltoadd" in waykey:
|
|
ltoadd = waykey["tiger:ltoadd"]
|
|
else:
|
|
ltoadd = None
|
|
if "tiger:rfromadd" in waykey:
|
|
rfromadd = waykey["tiger:rfromadd"]
|
|
else:
|
|
rfromadd = None
|
|
if "tiger:rtoadd" in waykey:
|
|
rtoadd = waykey["tiger:rtoadd"]
|
|
else:
|
|
rtoadd = None
|
|
if rfromadd != None and rtoadd != None:
|
|
right = True
|
|
else:
|
|
right = False
|
|
if lfromadd != None and ltoadd != None:
|
|
left = True
|
|
else:
|
|
left = False
|
|
if left or right:
|
|
first = True
|
|
firstpointid, firstpoint = nodelist[ round_point( segment[0] ) ]
|
|
|
|
finalpointid, finalpoint = nodelist[ round_point( segment[len(segment) - 1] ) ]
|
|
for point in segment:
|
|
pointid, (lat, lon) = nodelist[ round_point( point ) ]
|
|
|
|
#The approximate number of feet in one degree of longitute
|
|
lrad = math.radians(lat)
|
|
lon_feet = 365527.822 * math.cos(lrad) - 306.75853 * math.cos(3 * lrad) + 0.3937 * math.cos(5 * lrad)
|
|
|
|
#Calculate the points of the offset ways
|
|
if lastpoint != None:
|
|
#Skip points too close to start
|
|
if math.sqrt((lat * lat_feet - firstpoint[0] * lat_feet)**2 + (lon * lon_feet - firstpoint[1] * lon_feet)**2) < pullback:
|
|
#Preserve very short ways (but will be rendered backwards)
|
|
if pointid != finalpointid:
|
|
continue
|
|
#Skip points too close to end
|
|
if math.sqrt((lat * lat_feet - finalpoint[0] * lat_feet)**2 + (lon * lon_feet - finalpoint[1] * lon_feet)**2) < pullback:
|
|
#Preserve very short ways (but will be rendered backwards)
|
|
if (pointid != firstpointid) and (pointid != finalpointid):
|
|
continue
|
|
|
|
X = (lon - lastpoint[1]) * lon_feet
|
|
Y = (lat - lastpoint[0]) * lat_feet
|
|
if Y != 0:
|
|
theta = math.pi/2 - math.atan( X / Y)
|
|
Xp = math.sin(theta) * distance
|
|
Yp = math.cos(theta) * distance
|
|
else:
|
|
Xp = 0
|
|
if X > 0:
|
|
Yp = -distance
|
|
else:
|
|
Yp = distance
|
|
|
|
if Y > 0:
|
|
Xp = -Xp
|
|
else:
|
|
Yp = -Yp
|
|
|
|
if first:
|
|
first = False
|
|
dX = - (Yp * (pullback / distance)) / lon_feet #Pull back the first point
|
|
dY = (Xp * (pullback / distance)) / lat_feet
|
|
if left:
|
|
lpoint = (lastpoint[0] + (Yp / lat_feet) - dY, lastpoint[1] + (Xp / lon_feet) - dX)
|
|
lsegment.append( (id, lpoint) )
|
|
id += 1
|
|
if right:
|
|
rpoint = (lastpoint[0] - (Yp / lat_feet) - dY, lastpoint[1] - (Xp / lon_feet) - dX)
|
|
rsegment.append( (id, rpoint) )
|
|
id += 1
|
|
|
|
else:
|
|
#round the curves
|
|
if delta[1] != 0:
|
|
theta = abs(math.atan(delta[0] / delta[1]))
|
|
else:
|
|
theta = math.pi / 2
|
|
if Xp != 0:
|
|
theta = theta - abs(math.atan(Yp / Xp))
|
|
else: theta = theta - math.pi / 2
|
|
r = 1 + abs(math.tan(theta/2))
|
|
if left:
|
|
lpoint = (lastpoint[0] + (Yp + delta[0]) * r / (lat_feet * 2), lastpoint[1] + (Xp + delta[1]) * r / (lon_feet * 2))
|
|
lsegment.append( (id, lpoint) )
|
|
id += 1
|
|
if right:
|
|
rpoint = (lastpoint[0] - (Yp + delta[0]) * r / (lat_feet * 2), lastpoint[1] - (Xp + delta[1]) * r / (lon_feet * 2))
|
|
|
|
rsegment.append( (id, rpoint) )
|
|
id += 1
|
|
|
|
delta = (Yp, Xp)
|
|
|
|
lastpoint = (lat, lon)
|
|
|
|
|
|
#Add in the last node
|
|
dX = - (Yp * (pullback / distance)) / lon_feet
|
|
dY = (Xp * (pullback / distance)) / lat_feet
|
|
if left:
|
|
lpoint = (lastpoint[0] + (Yp + delta[0]) / (lat_feet * 2) + dY, lastpoint[1] + (Xp + delta[1]) / (lon_feet * 2) + dX )
|
|
lsegment.append( (id, lpoint) )
|
|
id += 1
|
|
if right:
|
|
rpoint = (lastpoint[0] - Yp / lat_feet + dY, lastpoint[1] - Xp / lon_feet + dX)
|
|
rsegment.append( (id, rpoint) )
|
|
id += 1
|
|
|
|
#Generate the tags for ways and nodes
|
|
zipr = ''
|
|
zipl = ''
|
|
name = ''
|
|
county = ''
|
|
if "tiger:zip_right" in waykey:
|
|
zipr = waykey["tiger:zip_right"]
|
|
if "tiger:zip_left" in waykey:
|
|
zipl = waykey["tiger:zip_left"]
|
|
if "name" in waykey:
|
|
name = waykey["name"]
|
|
if "tiger:county" in waykey:
|
|
county = waykey["tiger:county"]
|
|
if "tiger:separated" in waykey: # No longer set in Tiger-2017
|
|
separated = waykey["tiger:separated"]
|
|
else:
|
|
separated = "N"
|
|
|
|
#Write the nodes of the offset ways
|
|
if right:
|
|
rlinestring = [];
|
|
for i, point in rsegment:
|
|
rlinestring.append( "%f %f" % (point[1], point[0]) )
|
|
if left:
|
|
llinestring = [];
|
|
for i, point in lsegment:
|
|
llinestring.append( "%f %f" % (point[1], point[0]) )
|
|
if right:
|
|
rsegments.append( rsegment )
|
|
if left:
|
|
lsegments.append( lsegment )
|
|
rtofromint = right #Do the addresses convert to integers?
|
|
ltofromint = left #Do the addresses convert to integers?
|
|
if right:
|
|
try: rfromint = int(rfromadd)
|
|
except:
|
|
print("Non integer address: %s" % rfromadd)
|
|
rtofromint = False
|
|
try: rtoint = int(rtoadd)
|
|
except:
|
|
print("Non integer address: %s" % rtoadd)
|
|
rtofromint = False
|
|
if left:
|
|
try: lfromint = int(lfromadd)
|
|
except:
|
|
print("Non integer address: %s" % lfromadd)
|
|
ltofromint = False
|
|
try: ltoint = int(ltoadd)
|
|
except:
|
|
print("Non integer address: %s" % ltoadd)
|
|
ltofromint = False
|
|
if right:
|
|
id += 1
|
|
|
|
interpolationtype = "all";
|
|
if rtofromint:
|
|
if (rfromint % 2) == 0 and (rtoint % 2) == 0:
|
|
if separated == "Y": #Doesn't matter if there is another side
|
|
interpolationtype = "even";
|
|
elif ltofromint and (lfromint % 2) == 1 and (ltoint % 2) == 1:
|
|
interpolationtype = "even";
|
|
elif (rfromint % 2) == 1 and (rtoint % 2) == 1:
|
|
if separated == "Y": #Doesn't matter if there is another side
|
|
interpolationtype = "odd";
|
|
elif ltofromint and (lfromint % 2) == 0 and (ltoint % 2) == 0:
|
|
interpolationtype = "odd";
|
|
|
|
ret.append( "SELECT tiger_line_import(ST_GeomFromText('LINESTRING(%s)',4326), %s, %s, %s, %s, %s, %s);" %
|
|
( ",".join(rlinestring), sql_quote(rfromadd), sql_quote(rtoadd), sql_quote(interpolationtype), sql_quote(name), sql_quote(county), sql_quote(zipr) ) )
|
|
|
|
if left:
|
|
id += 1
|
|
|
|
interpolationtype = "all";
|
|
if ltofromint:
|
|
if (lfromint % 2) == 0 and (ltoint % 2) == 0:
|
|
if separated == "Y":
|
|
interpolationtype = "even";
|
|
elif rtofromint and (rfromint % 2) == 1 and (rtoint % 2) == 1:
|
|
interpolationtype = "even";
|
|
elif (lfromint % 2) == 1 and (ltoint % 2) == 1:
|
|
if separated == "Y":
|
|
interpolationtype = "odd";
|
|
elif rtofromint and (rfromint %2 ) == 0 and (rtoint % 2) == 0:
|
|
interpolationtype = "odd";
|
|
|
|
ret.append( "SELECT tiger_line_import(ST_GeomFromText('LINESTRING(%s)',4326), %s, %s, %s, %s, %s, %s);" %
|
|
( ",".join(llinestring), sql_quote(lfromadd), sql_quote(ltoadd), sql_quote(interpolationtype), sql_quote(name), sql_quote(county), sql_quote(zipl) ) )
|
|
|
|
return ret
|
|
|
|
def sql_quote( string ):
|
|
return "'" + string.replace("'", "''") + "'"
|
|
|
|
def unproject( point ):
|
|
pt = tr.TransformPoint( point[0], point[1] )
|
|
return (pt[1], pt[0])
|
|
|
|
def round_point( point, accuracy=8 ):
|
|
return tuple( [ round(x,accuracy) for x in point ] )
|
|
|
|
def compile_nodelist( parsed_gisdata, first_id=1 ):
|
|
nodelist = {}
|
|
|
|
i = first_id
|
|
for geom, tags in parsed_gisdata:
|
|
if len( geom )==0:
|
|
continue
|
|
|
|
for point in geom:
|
|
r_point = round_point( point )
|
|
if r_point not in nodelist:
|
|
nodelist[ r_point ] = (i, unproject( point ))
|
|
i += 1
|
|
|
|
return (i, nodelist)
|
|
|
|
def adjacent( left, right ):
|
|
left_left = round_point(left[0])
|
|
left_right = round_point(left[-1])
|
|
right_left = round_point(right[0])
|
|
right_right = round_point(right[-1])
|
|
|
|
return ( left_left == right_left or
|
|
left_left == right_right or
|
|
left_right == right_left or
|
|
left_right == right_right )
|
|
|
|
def glom( left, right ):
|
|
left = list( left )
|
|
right = list( right )
|
|
|
|
left_left = round_point(left[0])
|
|
left_right = round_point(left[-1])
|
|
right_left = round_point(right[0])
|
|
right_right = round_point(right[-1])
|
|
|
|
if left_left == right_left:
|
|
left.reverse()
|
|
return left[0:-1] + right
|
|
|
|
if left_left == right_right:
|
|
return right[0:-1] + left
|
|
|
|
if left_right == right_left:
|
|
return left[0:-1] + right
|
|
|
|
if left_right == right_right:
|
|
right.reverse()
|
|
return left[0:-1] + right
|
|
|
|
raise 'segments are not adjacent'
|
|
|
|
def glom_once( segments ):
|
|
if len(segments)==0:
|
|
return segments
|
|
|
|
unsorted = list( segments )
|
|
x = unsorted.pop(0)
|
|
|
|
while len( unsorted ) > 0:
|
|
n = len( unsorted )
|
|
|
|
for i in range(0, n):
|
|
y = unsorted[i]
|
|
if adjacent( x, y ):
|
|
y = unsorted.pop(i)
|
|
x = glom( x, y )
|
|
break
|
|
|
|
# Sorted and unsorted lists have no adjacent segments
|
|
if len( unsorted ) == n:
|
|
break
|
|
|
|
return x, unsorted
|
|
|
|
def glom_all( segments ):
|
|
unsorted = segments
|
|
chunks = []
|
|
|
|
while unsorted != []:
|
|
chunk, unsorted = glom_once( unsorted )
|
|
chunks.append( chunk )
|
|
|
|
return chunks
|
|
|
|
|
|
|
|
def compile_waylist( parsed_gisdata ):
|
|
waylist = {}
|
|
|
|
#Group by tiger:way_id
|
|
for geom, tags in parsed_gisdata:
|
|
way_key = tags.copy()
|
|
way_key = ( way_key['tiger:way_id'], tuple( [(k,v) for k,v in way_key.items()] ) )
|
|
|
|
if way_key not in waylist:
|
|
waylist[way_key] = []
|
|
|
|
waylist[way_key].append( geom )
|
|
|
|
ret = {}
|
|
for (way_id, way_key), segments in waylist.items():
|
|
ret[way_key] = glom_all( segments )
|
|
return ret
|
|
|
|
|
|
def shape_to_sql( shp_filename, sql_filename ):
|
|
|
|
print("parsing shpfile %s" % shp_filename)
|
|
parsed_features = parse_shp_for_geom_and_tags( shp_filename )
|
|
|
|
print("compiling nodelist")
|
|
i, nodelist = compile_nodelist( parsed_features )
|
|
|
|
print("compiling waylist")
|
|
waylist = compile_waylist( parsed_features )
|
|
|
|
print("preparing address ways")
|
|
sql_lines = addressways(waylist, nodelist, i)
|
|
|
|
print("writing %s" % sql_filename)
|
|
fp = open( sql_filename, "w" )
|
|
fp.write( "\n".join( sql_lines ) )
|
|
fp.close()
|
|
|
|
if __name__ == '__main__':
|
|
import sys, os.path
|
|
if len(sys.argv) < 3:
|
|
print("%s input.shp output.sql" % sys.argv[0])
|
|
sys.exit()
|
|
shp_filename = sys.argv[1]
|
|
sql_filename = sys.argv[2]
|
|
shape_to_sql(shp_filename, sql_filename)
|