Search code examples
pythonnodesnetworkxedgesosmnx

OSMnx: angle between nodes


As I mentioned in the title I need to find the angle between nodes. I have a list of nodes with the ids of the nodes of a route. I have thought on doing it somehow using the 'x' and 'y' coordinates but I am not arriving at any conclusions. Also, I've been told about using 'bearings', but again I don't really know how to use it, hence I don't get the proper result.

(I am using Networkx and OSMnx)

Being id_src and id_dst the ids of two consecutive nodes:

G.edges[(id_src, id_dst, 0)]['bearing']

Solution

  • Import OSMnx

    import osmnx as ox
    

    Import the graph of Melbourne

    address_name='Melbourne'
    G=ox.graph_from_address(address_name, distance=50)
    

    Create nodes and edges geodataframes from the graph

    nodes, edges = ox.graph_to_gdfs(G, nodes=True, edges=True)
    

    Calculate edge bearings and make a pandas series out of them

    import pandas as pd
    G = ox.add_edge_bearings(G)
    bearings = pd.Series([data['bearing'] for u, v, k, data in G.edges(keys=True, data=True)], name='bearing')
    

    Concatenate the series with the edges geodataframe to have the edge bearings in the same edges geodataframe

    edges = pd.concat([edges, bearings], axis=1)
    

    Example:

    print('Bearing between nodes '+str(edges['u'][0])+' and '+str(edges['v'][0])+' is '+str(edges['bearing'][0]))
    

    Bearing between nodes 6167413263 and 6167441066 is 69.48

    You may use the following function for calculation of bearings between any two nodes, although it does not entirely match up with the calculated bearings, but is fairly accurate.

    def bearing(G,node1,node2):
        import math
        node1lat = nodes.at[node1, 'y']
        node1lon = nodes.at[node1, 'x']
        node2lat = nodes.at[node2, 'y']
        node2lon = nodes.at[node2, 'x']
        londiff = node2lon - node1lon 
        print('londiff: '+str(londiff))
        latdiff = node2lat - node1lat
        print('latdiff: '+str(latdiff))
        if latdiff > 0 and londiff > 0: # Quadrant1
            bearing = 90.0 - math.degrees(math.atan2(latdiff,londiff))
        elif latdiff < 0 and londiff > 0: #Qaudrant2
            bearing = 90.0 - math.degrees(math.atan2(latdiff,londiff))
        elif latdiff < 0 and londiff < 0: #Qaudrant3
            bearing = 90.0 - math.degrees(math.atan2(latdiff,londiff))
        elif latdiff > 0 and londiff < 0: #Qaudrant4
            bearing = 450.0 - math.degrees(math.atan2(latdiff,londiff))
    
        return bearing