I made this function in python as part of my static-GTFS-Manager tool:
https://github.com/WRI-Cities/static-GTFS-manager/blob/master/GTFSserverfunctions.py#L904
(exact location of the function may change in future releases, note)
import pandas as pd
from collections import OrderedDict
def geoJson2shape(route_id, shapefile, shapefileRev=None):
with open(shapefile, encoding='utf8') as f:
# loading geojson, from https://gis.stackexchange.com/a/73771/44746
data = json.load(f)
print('Loaded',shapefile)
output_array = []
try:
coordinates = data['features'][0]['geometry']['coordinates']
except:
print('Invalid geojson file ' + shapefile)
return False
prevlat = coordinates[0][1]
prevlon = coordinates[0][0]
dist_traveled = 0
i = 0
for item in coordinates:
newrow = OrderedDict()
newrow['shape_id'] = route_id + '_0'
newrow['shape_pt_lat'] = item[1]
newrow['shape_pt_lon'] = item[0]
calcdist = lat_long_dist(prevlat,prevlon,item[1],item[0])
dist_traveled = dist_traveled + calcdist
newrow['shape_dist_traveled'] = dist_traveled
i = i + 1
newrow['shape_pt_sequence'] = i
output_array.append(newrow)
prevlat = item[1]
prevlon = item[0]
# Reverse trip now.. either same shapefile in reverse or a different shapefile
if( shapefileRev ):
with open(shapefileRev, encoding='utf8') as g:
data2 = json.load(g)
print('Loaded',shapefileRev)
try:
coordinates = data2['features'][0]['geometry']['coordinates']
except:
print('Invalid geojson file ' + shapefileRev)
return False
else:
coordinates.reverse()
prevlat = coordinates[0][1]
prevlon = coordinates[0][0]
dist_traveled = 0
i = 0
for item in coordinates:
newrow = OrderedDict()
newrow['shape_id'] = route_id + '_1'
newrow['shape_pt_lat'] = item[1]
newrow['shape_pt_lon'] = item[0]
calcdist = lat_long_dist(prevlat,prevlon,item[1],item[0])
dist_traveled = float(format( dist_traveled + calcdist , '.2f' ))
newrow['shape_dist_traveled'] = dist_traveled
i = i + 1
newrow['shape_pt_sequence'] = i
output_array.append(newrow)
prevlat = item[1]
prevlon = item[0]
return output_array
Of its three arguments, the second one, shapefile has to be relative path to the .geojson file. route_id
can be any string. If you have another .geojson for the reverse trip then supply its path for shapefileRev
.
The function returns a standard list of dicts (or dict array, comparable to an array of jsons in JS). One can save it directly to a shapes.txt file using pandas module in python:
import pandas as pd
pd.DataFrame(output_array).to_csv('shapes.txt')
If I had to re-write this function, I'd probably use python's geojson module.