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?

1 Answer 1

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.

1
  • note: replace "logmessage()' with "print()" in the code snippet.
    – Nikhil VJ
    Commented Nov 4, 2018 at 6:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.