3

There seems to be a lot of material on getting GTFS feeds and converting them into GeoJSON, but I want to do the other way around.

I want to create a shapes.txt file from a trackpoints that I have in GeoJSON format, and mapped in QGIS. This would require to extract lat/long of each point and assign a point sequence to each point.

Converting into KML and then using this: https://bdferris.github.io/kml-to-gtfs-shapes/ doesn't work

How do I do that?

nmtoken
  • 13,355
  • 5
  • 38
  • 87
Dhaval Shukla
  • 383
  • 2
  • 11

1 Answers1

4

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.

Nikhil VJ
  • 1,026
  • 12
  • 31