Example #1
0
def test_find_nearest():

    # get graph
    G = ox.graph_from_point(location_point, dist=500, network_type="drive")

    # get nearest node
    nn, d = ox.get_nearest_node(G, location_point, method="euclidean", return_dist=True)

    # get nearest nodes: haversine, kdtree, balltree
    gdf_nodes = ox.graph_to_gdfs(G, edges=False)
    X = gdf_nodes["x"].head()
    Y = gdf_nodes["y"].head()

    nn1, dist1 = ox.get_nearest_nodes(G, X, Y, return_dist=True)
    nn2, dist2 = ox.get_nearest_nodes(G, X, Y, method="kdtree", return_dist=True)
    nn3, dist3 = ox.get_nearest_nodes(G, X, Y, method="balltree", return_dist=True)
    nn4 = ox.get_nearest_nodes(G, X, Y)
    nn5 = ox.get_nearest_nodes(G, X, Y, method="kdtree")
    nn6 = ox.get_nearest_nodes(G, X, Y, method="balltree")

    # get nearest edge
    u, v, k, g, d = ox.get_nearest_edge(G, location_point, return_geom=True, return_dist=True)

    # get nearest edges: haversine, kdtree, balltree
    ne1 = ox.get_nearest_edges(G, X, Y)
    ne2 = ox.get_nearest_edges(G, X, Y, method="kdtree")
    ne3 = ox.get_nearest_edges(G, X, Y, method="balltree", dist=0.0001)
Example #2
0
def test_find_nearest():

    # get graph
    G = ox.graph_from_point(location_point, dist=500, network_type="drive")

    # convert graph to node/edge GeoDataFrames and back again
    gdf_nodes, gdf_edges = ox.graph_to_gdfs(
        G, nodes=True, edges=True, node_geometry=True, fill_edge_geometry=True
    )
    assert len(gdf_nodes) == len(G)
    assert len(gdf_edges) == len(G.edges(keys=True))
    G = ox.graph_from_gdfs(gdf_nodes, gdf_edges)
    assert len(gdf_nodes) == len(G)
    assert len(gdf_edges) == len(G.edges(keys=True))

    # get nearest node
    nn, d = ox.get_nearest_node(G, location_point, method="euclidean", return_dist=True)

    # get nearest nodes: haversine, kdtree, balltree
    X = gdf_nodes["x"].head()
    Y = gdf_nodes["y"].head()
    nn1 = ox.get_nearest_nodes(G, X, Y)
    nn2 = ox.get_nearest_nodes(G, X, Y, method="kdtree")
    nn3 = ox.get_nearest_nodes(G, X, Y, method="balltree")

    # get nearest edge
    u, v, k, g, d = ox.get_nearest_edge(G, location_point, return_geom=True, return_dist=True)

    # get nearest edges: haversine, kdtree, balltree
    ne1 = ox.get_nearest_edges(G, X, Y)
    ne2 = ox.get_nearest_edges(G, X, Y, method="kdtree")
    ne3 = ox.get_nearest_edges(G, X, Y, method="balltree", dist=0.0001)
Example #3
0
def test_nearest_edges():
    from pyproj import Proj

    # test in closest edge section
    sheik_sayed_dubai = [25.09, 25.06, 55.16, 55.11]
    location_coordinates = (25.071764, 55.138978)
    G = ox.graph_from_bbox(*sheik_sayed_dubai,
                           simplify=False,
                           retain_all=True,
                           network_type='drive')

    # Unprojected
    ne1 = ox.get_nearest_edges(
        G,
        X=[location_coordinates[1], location_coordinates[1]],
        Y=[location_coordinates[0], location_coordinates[0]],
        method='balltree',
        dist=0.0001)

    # Projected
    G2 = ox.project_graph(G)
    crs = Proj(G2.graph['crs'])

    projected_point = crs(location_coordinates[1], location_coordinates[0])
    ne2 = ox.get_nearest_edges(G2,
                               X=[projected_point[0], projected_point[0]],
                               Y=[projected_point[1], projected_point[1]],
                               method='kdtree',
                               dist=10)
    assert (ne1 == ne2).all()
Example #4
0
def test_network_saving_loading():

    # save/load graph as shapefile and graphml file
    G = ox.graph_from_place('Piedmont, California, USA')
    G_projected = ox.project_graph(G)
    ox.save_graph_shapefile(G_projected)
    ox.save_graphml(G_projected)
    ox.save_graphml(G_projected, filename='gephi.graphml', gephi=True)
    G2 = ox.load_graphml('graph.graphml')
    G3 = ox.load_graphml('graph.graphml', node_type=str)

    # convert graph to node/edge GeoDataFrames and back again
    gdf_nodes, gdf_edges = ox.graph_to_gdfs(G, nodes=True, edges=True, node_geometry=True, fill_edge_geometry=True)
    G4 = ox.gdfs_to_graph(gdf_nodes, gdf_edges)

    # find graph nodes nearest to some set of points
    X = gdf_nodes['x'].head()
    Y = gdf_nodes['y'].head()
    nn1 = ox.get_nearest_nodes(G, X, Y)
    nn2 = ox.get_nearest_nodes(G, X, Y, method='kdtree')
    nn3 = ox.get_nearest_nodes(G, X, Y, method='balltree')

    # find graph edges nearest to some set of points
    ne1 = ox.get_nearest_edges(G, X, Y)
    ne2 = ox.get_nearest_edges(G, X, Y, method='kdtree')
    ne3 = ox.get_nearest_edges(G, X, Y, method='kdtree', dist=50)
Example #5
0
def test_find_nearest():

    # get graph and x/y coords to search
    G = ox.graph_from_point(location_point, dist=500, network_type="drive")
    Gp = ox.project_graph(G)
    points = ox.utils_geo.sample_points(ox.get_undirected(Gp), 5)
    X = points.x
    Y = points.y

    # get nearest node
    nn, d = ox.get_nearest_node(Gp, location_point, method="euclidean", return_dist=True)
    nn = ox.get_nearest_node(Gp, location_point, method="euclidean", return_dist=False)

    # get nearest nodes
    nn1, dist1 = ox.get_nearest_nodes(G, X, Y, return_dist=True)
    nn2, dist2 = ox.get_nearest_nodes(Gp, X, Y, method="kdtree", return_dist=True)
    nn3, dist3 = ox.get_nearest_nodes(G, X, Y, method="balltree", return_dist=True)
    nn4 = ox.get_nearest_nodes(G, X, Y)
    nn5 = ox.get_nearest_nodes(Gp, X, Y, method="kdtree")
    nn6 = ox.get_nearest_nodes(G, X, Y, method="balltree")

    # get nearest edge
    u, v, k, g, d = ox.get_nearest_edge(Gp, location_point, return_geom=True, return_dist=True)
    u, v, k, g = ox.get_nearest_edge(Gp, location_point, return_geom=True)
    u, v, k, d = ox.get_nearest_edge(Gp, location_point, return_dist=True)
    u, v, k = ox.get_nearest_edge(Gp, location_point)

    # get nearest edges
    ne0 = ox.distance.nearest_edges(Gp, X, Y, interpolate=50)
    ne1 = ox.get_nearest_edges(Gp, X, Y)
    ne2 = ox.get_nearest_edges(Gp, X, Y, method="kdtree")
    ne3 = ox.get_nearest_edges(G, X, Y, method="balltree", dist=0.0001)
Example #6
0
def test_network_saving_loading():

    # save/load graph as shapefile and graphml file
    G = ox.graph_from_place('Piedmont, California, USA')
    G_projected = ox.project_graph(G)
    ox.save_graph_shapefile(G_projected)
    ox.save_graphml(G_projected)
    ox.save_graphml(G_projected, filename='gephi.graphml', gephi=True)
    G2 = ox.load_graphml('graph.graphml')
    G3 = ox.load_graphml('graph.graphml', node_type=str)

    # convert graph to node/edge GeoDataFrames and back again
    gdf_edges = ox.graph_to_gdfs(G, nodes=False, edges=True, fill_edge_geometry=False)
    gdf_nodes, gdf_edges = ox.graph_to_gdfs(G, nodes=True, edges=True, node_geometry=True, fill_edge_geometry=True)
    G4 = ox.gdfs_to_graph(gdf_nodes, gdf_edges)

    # find graph nodes nearest to some set of points
    X = gdf_nodes['x'].head()
    Y = gdf_nodes['y'].head()
    nn1 = ox.get_nearest_nodes(G, X, Y)
    nn2 = ox.get_nearest_nodes(G, X, Y, method='kdtree')
    nn3 = ox.get_nearest_nodes(G, X, Y, method='balltree')

    # find graph edges nearest to some set of points
    ne1 = ox.get_nearest_edges(G, X, Y)
    ne2 = ox.get_nearest_edges(G, X, Y, method='kdtree')
    ne3 = ox.get_nearest_edges(G, X, Y, method='kdtree', dist=50)
Example #7
0
def find_nearest_edges_in_network__OLD(road_network,
                                       tdf,
                                       return_tdf_with_new_col=False):
    """Map-matching.

	For each point in a TrajDataFrame, it finds the nearest edge in a road network.
	Each edge is represented as the couple of OSM ids of its starting and ending nodes.

	Parameters:
	----------
	road_network : networkx MultiDiGraph
		the road network on which to map the points.

	tdf : TrajDataFrame
		the trajectories of the individuals.

	return_tdf_with_new_col : boolean
		if False (default), returns the list of the nearest edges;
		if True, returns a copy of the original TrajDataFrame with one more column called 'road_link'.

	Returns
	-------
	list (if return_tdf_with_new_col = True)
		list of the nearest edges.

	TrajDataFrame (if return_tdf_with_new_col = False)
		the TrajDataFrame with 1 more column collecting the couple of OSM ids of the two nodes.
	"""

    tdf.sort_by_uid_and_datetime()

    # extracting arrays of lat and lng for the vehicle:
    vec_of_longitudes = np.array(tdf['lng'])
    vec_of_latitudes = np.array(tdf['lat'])

    # for each (lat,lon), find the nearest edge in the road network:
    array_of_nearest_edges = ox.get_nearest_edges(road_network,
                                                  X=vec_of_longitudes,
                                                  Y=vec_of_latitudes,
                                                  method='balltree')
    ###
    # method (str {None, 'kdtree', 'balltree'}) – Which method to use for finding nearest node to each point.
    # If None, we manually find each node one at a time using osmnx.utils.get_nearest_node and haversine.
    # If ‘kdtree’ we use scipy.spatial.cKDTree for very fast euclidean search.
    # If ‘balltree’, we use sklearn.neighbors.BallTree for fast haversine search.
    ###

    list_of_nearest_edges = []
    for index in range(0, array_of_nearest_edges.shape[0]):
        list_of_nearest_edges.append([
            array_of_nearest_edges[index][0], array_of_nearest_edges[index][1]
        ])

    if return_tdf_with_new_col:
        tdf_with_nearest_edges = tdf.copy()  #.drop(columns=['lat', 'lng'])
        tdf_with_nearest_edges['road_link'] = list_of_nearest_edges
        return tdf_with_nearest_edges

    return list_of_nearest_edges
Example #8
0
def test_nearest_edges():

    from pyproj import Proj

    # test in closest edge section
    sheik_sayed_dubai = [25.09, 25.06, 55.16, 55.11]
    location_coordinates = (25.071764, 55.138978)
    G = ox.graph_from_bbox(*sheik_sayed_dubai, simplify=False, retain_all=True, network_type='drive')

    # Unprojected
    ne1 = ox.get_nearest_edges(G, X=[location_coordinates[1], location_coordinates[1]],
                                  Y=[location_coordinates[0], location_coordinates[0]], method='balltree', dist=0.0001)

    # Projected
    G2 = ox.project_graph(G)
    crs = Proj(G2.graph['crs'])

    projected_point = crs(location_coordinates[1], location_coordinates[0])
    ne2 = ox.get_nearest_edges(G2, X=[projected_point[0], projected_point[0]],
                                   Y=[projected_point[1], projected_point[1]], method='kdtree', dist=10)
    assert (ne1 == ne2).all()
Example #9
0
    def set_up(self):
        def name(names):
            if not names:
                return ''
            elif isinstance(names, str):
                return names
            else:
                return ' '.join(names)

        tags = {'amenity': "vending_maching", "vending": "parking_tickets"}
        self.vending_machines_gdf = ox.geometries_from_place(self.place, tags)
        G = ox.graph_from_place(self.place, network_type='drive', retain_all = True, simplify=True)
        nearest_edges = ox.get_nearest_edges(G, self.vending_machines_gdf['geometry'].x, self.vending_machines_gdf['geometry'].y , method='balltree')
        self.vending_machines_gdf['street'] = [*map(lambda x: name(G.edges[(x[0], x[1], x[2])].get("name")).lower(), nearest_edges)]
Example #10
0
 def link_traffic_signals_to_edge(self):
     G = self.graph_latlon
     gdf_netw = self.network_matrix
     gdf_ts = self.traffic_signals
     lon = [j[0] for i, j in gdf_ts['coordinates'].iteritems()]
     lat = [j[1] for i, j in gdf_ts['coordinates'].iteritems()]
     nearest = ox.get_nearest_edges(G, lon, lat, method='balltree')
     nearest = [tuple(j) for i, j in enumerate(nearest)]
     gdf_ts['edge'] = nearest
     gdf_ts['N1'] = [j[0] for i, j in enumerate(nearest)]
     gdf_ts['N2'] = [j[1] for i, j in enumerate(nearest)]
     df_ts_e = pd.merge(gdf_netw[['N1', 'N2', 'geometry']],
                        gdf_ts[['N1', 'N2']],
                        how='inner',
                        on=['N1', 'N2'])
     return df_ts_e
Example #11
0
def match_nearest_edge(graph, track):
    """
    Algorithm to match the track to the nearest edge on the Open Street Map network.

    This function match a track of GPS coordinates, in the (Lat, Lon) format.
    to a graph.

    It loops all over the points to match them to the closest edge of the
    OSM network. The GPS points are projected on the edge with an
    orthogonal projection.
    If the projected point goes outside of the edge, then it is match to
    one extremity (see noiseplanet.utils.oproj documentation for more details).

    Parameters
    ----------
    graph : NetworkX MultiDiGraph
        Graph of the Open Street Map network.
    track : numpy 2D array
        A 2D matrix composed by Latitudes (first column) and Longitudes (second column)
        of the track.

    Returns
    -------
    track_corr : numpy 2D array
        A 2D matrix composed by Latitudes (first column) and Longitudes (second column)
        of the corrected track.
    route : numpy 2D array
        Route connecting all track's points on the Open Street Map network.
    edgeid : numpy 2D array
        List of edges to which each points belongs to.
        Edges id are composed by two extremity nodes id. 
    stats : Dict
        Statistics of the Map Matching.
        'proj_length' is the length of the projection (from track's point to corrected ones),
        'path_length' is the distance on the graph between two following points,
        'unlinked' higlights unconnected points on the graph.
   
    Example
    -------
        >>> import osmnx as ox
        >>> import numpy as np
        >>> from noiseplanet.matcher.model.leuven import leuven
        >>> place_name = "2e Arrondissement, Lyon, France"
        >>> distance = 1000  # meters
        >>> graph = ox.graph_from_address(place_name, distance)
        >>> track = np.array([[45.75809136,  4.83577159],
                              [45.7580932 ,  4.83576182],
                              [45.7580929 ,  4.8357634 ],
                              [45.75809207,  4.8357678 ],
                              [45.75809207,  4.8357678 ],
                              [45.75809647,  4.83574439],
                              [45.75809908,  4.83573054],
                              [45.75809908,  4.83573054],
                              [45.75810077,  4.83572153],
                              [45.75810182,  4.83571596],
                              [45.75810159,  4.83571719],
                              [45.7581021 ,  4.83571442],
                              [45.7580448 ,  4.83558152],
                              [45.75804304,  4.83558066],
                              [45.75804304,  4.83558066],
                              [45.75802703,  4.83557288]])
        >>> track_corr, route_corr, edgeid = match_nearest(graph, track)
    """
    # id of the nearest edges
    edgeid = ox.get_nearest_edges(graph,
                                  track[:, 1],
                                  track[:, 0],
                                  method='balltree',
                                  dist=.000001)
    lat1, lat2, lon1, lon2 = [], [], [], []
    for edge in edgeid:
        lon1.append(graph.nodes[edge[0]]['x'])
        lat1.append(graph.nodes[edge[0]]['y'])
        lon2.append(graph.nodes[edge[1]]['x'])
        lat2.append(graph.nodes[edge[1]]['y'])

    # Reference ellipsoid for distance
    # Projection of the point in the web mercator coordinate system (used by OSM)
    proj_init = "epsg:4326"  # geographic coordinates
    proj_out = "epsg:3857"  # web mercator coordinates
    # Using the class Transformer, faster for large dataset
    transformer = Transformer.from_proj(Proj(init=proj_init),
                                        Proj(init=proj_out))
    Xt, Yt = transformer.transform(track[:, 1], track[:, 0])
    # Projecting the nearest edges' nodes 1, 2 into the same coordinates system
    X1, Y1 = transformer.transform(lon1, lat1)
    X2, Y2 = transformer.transform(lon2, lat2)

    # With the transform function (slower since the 2.2.0 update)
    # Xt, Yt = transform(Proj(init=proj_init), Proj(init=proj_out), track[:,1], track[:,0])
    # X1, Y1 = transform(Proj(init=proj_init), Proj(init=proj_out), lon1, lat1)
    # X2, Y2 = transform(Proj(init=proj_init), Proj(init=proj_out), lon2, lat2)

    # Need to evaluate the projection for each point distance(point, point_proj)
    proj_dist = np.zeros(len(track))
    Xcorr, Ycorr = [], []
    for i in range(len(track)):
        # Ortho projection
        x, y = Xt[i], Yt[i]
        xH, yH = oproj.orthoProjSegment((x, y), (X1[i], Y1[i]), (X2[i], Y2[i]))
        # Stack the coordinates in the web mercator coordinates system
        Xcorr.append(xH)
        Ycorr.append(yH)

    transformer = Transformer.from_proj(Proj(init=proj_out),
                                        Proj(init=proj_init))

    lon_corr, lat_corr = transformer.transform(Xcorr, Ycorr)
    # With the transform function (slower since the 2.2.0 update)
    # lon_corr, lat_corr = transform(Proj(init=proj_out), Proj(init=proj_init), Xcorr, Ycorr)

    # Evaluate the distance betweeen these points
    # Reference ellipsoid for distance
    geod = Geod(ellps='WGS84')
    _, _, proj_dist = geod.inv(track[:, 1], track[:, 0], lon_corr, lat_corr)

    track_corr = np.column_stack((lat_corr, lon_corr))
    route, stats_route = rt.route_from_track(graph, track_corr, edgeid=edgeid)
    stats = dict({"proj_length": proj_dist}, **stats_route)

    return track_corr, route, np.array(edgeid), stats
Example #12
0
# Given three points off of the network, matches to the nearest edge and highlights that edge

import osmnx as ox
import matplotlib.pyplot as plt
ox.config(use_cache=True, log_console=True)

G = ox.graph_from_address('2801 Debarr Road, Anchorage, AK 99508', distance=400)

fig, ax = ox.plot_graph(G, show=False, close=False)

ax.scatter(-149.824945, 61.210608, c='red')
ax.scatter(-149.828, 61.2078, c='blue')
ax.scatter(-149.825, 61.2114, c='violet')
plt.show()

x = (-149.824945, -149.828, -149.825)
y = (61.210608, 61.2078, 61.2114)

edge = ox.get_nearest_edges(G, x, y, method='kdtree', dist=0.0001)

for i in range(0, len(edge)):
    ec = ['orange' if (u == edge[i, 1] and v == edge[i, 0]) else 'grey' for u, v, k in G.edges(keys=True)]
    fig, ax = ox.plot_graph(G, node_color='w', node_edgecolor='k', node_size=30,
                            node_zorder=3, edge_color=ec, edge_linewidth=2)



    def network_dfs(self):
        g = self.graph_latlon
        if not self.strict:
            g = ox.simplify_graph(g, strict=self.strict)
        g = ox.add_edge_bearings(g, precision=1)
        n, e = ox.graph_to_gdfs(g)
        e = e.reset_index()  # Method graph_to_gdfs changed to multiindex df
        network_edges, network_nodes_small = dbl_cleaning(ndf=n, edf=e)
        network_edges = network_edges.join(network_nodes_small, on='u')
        network_edges = network_edges.rename(columns={
            'u': 'n1',
            'y': 'lat1',
            'x': 'lon1'
        })
        network_edges = network_edges.join(network_nodes_small, on='v')
        network_edges = network_edges.rename(columns={
            'v': 'n2',
            'y': 'lat2',
            'x': 'lon2'
        })
        x1, y1 = zip(
            *project_point(list(zip(network_edges.lon1, network_edges.lat1))))
        x2, y2 = zip(
            *project_point(list(zip(network_edges.lon2, network_edges.lat2))))
        network_edges = network_edges.assign(x1=x1, y1=y1, x2=x2, y2=y2)
        network_edges['edge'] = list(
            zip(network_edges['n1'].values, network_edges['n2'].values))
        network_edges.reset_index(
            inplace=True
        )  # From hereon the unique index of an edge is just its position in df
        network_edges = network_edges.rename(columns={'index': '_id'})
        self.graph_latlon = g
        self.graph_xy = ox.project_graph(self.graph_latlon)
        self.network_edges = network_edges
        self._get_network_nodes(network_edges)
        # link node_tags to specific edge, osmid not unique over edges after simplification
        nearest = ox.get_nearest_edges(self.graph_xy,
                                       self.node_tags.x.to_list(),
                                       self.node_tags.y.to_list(),
                                       method='kdtree',
                                       dist=1)
        n1, n2, _ = zip(*nearest)
        test_b1 = network_edges[['_id', 'edge',
                                 'bearing']][network_edges.edge.isin(
                                     list(zip(n1, n2)))].values
        test_b2 = network_edges[['_id', 'edge',
                                 'bearing']][network_edges.edge.isin(
                                     list(zip(n2, n1)))].values
        self.node_tags['edge'] = [ij for ij in zip(n1, n2)]
        self.node_tags.reset_index(inplace=True)
        self.node_tags = self.node_tags.merge(
            self.network_edges[['edge', 'bearing']],
            on='edge',
            suffixes=('', '_edge'))
        diff_b = abs(self.node_tags['bearing'] -
                     self.node_tags['bearing_edge'])
        for i, j in diff_b.iteritems():
            if (j > 45) and not self.node_tags.junction[i]:
                self.node_tags.at[i,
                                  'edge'] = (self.node_tags.at[i, 'edge'][1],
                                             self.node_tags.at[i, 'edge'][0])
        self.node_tags.drop('bearing_edge', axis=1, inplace=True)
        self.node_tags = self.node_tags.merge(
            self.network_edges[['_id', 'edge', 'bearing']],
            on='edge',
            suffixes=('', '_edge'))
        diff_b2 = abs(self.node_tags['bearing'] -
                      self.node_tags['bearing_edge'])
        breakpoint()
        # check if nearest edge is in right direction, problem with two way streets

        self.node_tags.set_index('index', inplace=True)
        self.node_tags.sort_index(inplace=True)
Example #14
0
def map_matching_edge(
    move_data: Union[PandasMoveDataFrame, DaskMoveDataFrame, PandasDiscreteMoveDataFrame],
    inplace: Optional[bool] = True,
    bbox: Optional[Tuple[float, float, float, float]] = None,
    place: Optional[Text] = None,
    G: Optional[MultiDiGraph] = None
) -> Optional[DataFrame]:
    """
    Generate Map matching using the graph edges

    Parameters
    ----------
    move_data : MoveDataFrame
       The input trajectories data
    inplace: bool, optional
        if set to true the original dataframe will be altered,
        otherwise the alteration will be made in a copy, that will be returned,
        by default True
    bbox : tuple, optional
        The bounding box as (north, east, south, west), by default None
    place : string, optional
        The query to geocode to get place boundary polygon, by default None
    G : MultiDiGraph, optional
        The input graph, by default None

    Returns
    -------
    move_data : MoveDataFrame
        A copy of the original dataframe or None

    """
    if(G is None):
        if(bbox is None):
            bbox = move_data.get_bbox()
        G = ox.graph_from_bbox(
            bbox[0], bbox[2], bbox[1], bbox[3], network_type='all_private'
        )
    elif(place is not None):
        G = ox.footprints_from_place(query=place, tags={'network_type': 'all_private'})

    if not inplace:
        move_data = move_data[:]

    edges = ox.get_nearest_edges(
        G, X=move_data['lon'], Y=move_data['lat'], method='kdtree'
    )
    gdf_edges = ox.graph_to_gdfs(G, nodes=False)

    geometries = []
    for e in edges:
        df_edges = gdf_edges[
            (gdf_edges.index.get_level_values('u') == e[0])
            & (gdf_edges.index.get_level_values('v') == e[1])
        ]
        geometries.append(df_edges['geometry'])

    move_data['edge'] = [*map(lambda x: tuple([x[0], x[1]]), edges)]
    move_data['geometry'] = geometries

    if not inplace:
        return move_data
Example #15
0
def route_from_track(graph, track, edgeid=None):
    """
    Get the route connecting points of a track projected on the Open Street Map
    network.

    Parameters
    ----------
    graph : NetworkX MultiDiGraph
        Open Street Map graph where the route will be computed.
    track : numpy 2D array
        A 2D matrix composed by Latitudes (first column) and Longitudes (second column)
        of the track.    
    edgeid : numpy 2D array, optional
        List of edges to which each points belongs to.
        Edges id are composed by two extremity nodes id. 
        The default is None.

    Returns
    -------
    route : numpy 2D array
        Route connecting all track's points.
    stats : Dict
        Statistics of the routing connection.
        'path_length' is the distance on the graph between two following points,
        'unlinked' higlights unconnected points on the graph.
        
    Example
    -------
        >>> import numpy as np
        >>> from noiseplanet.matcher.model.route import route_from_track, graph_from_track
        >>> track = np.array([[45.75809136,  4.83577159],
                              [45.7580932 ,  4.83576182],
                              [45.7580929 ,  4.8357634 ],
                              [45.75809207,  4.8357678 ],
                              [45.75809207,  4.8357678 ],
                              [45.75809647,  4.83574439],
                              [45.75809908,  4.83573054],
                              [45.75809908,  4.83573054],
                              [45.75810077,  4.83572153],
                              [45.75810182,  4.83571596]])
        >>> graph = graph_from_track(track, network='all')
        >>> route_corr, stats = route_from_track(graph, track)
    """

    # Reference ellipsoid for distance
    geod = Geod(ellps='WGS84')

    # Find closest edges for each points
    if edgeid is None:
        edgeid = np.array(
            ox.get_nearest_edges(graph,
                                 track[:, 1],
                                 track[:, 0],
                                 method="balltree",
                                 dist=0.00001))
    edgeid = np.array(edgeid)

    # Deep copy of the graph, so the original is not modified
    # This algorithm will add edges and nodes to the graph
    # to compute Dijkstras shortest path
    graph2 = copy.deepcopy(graph)

    # adding the projected nodes to the copied graph
    for i in range(len(track)):
        graph2.add_node(i, y=track[i, 0], x=track[i, 1], osmid=i)

        _, _, distance1 = geod.inv(track[i, 1], track[i, 0],
                                   graph2.nodes[edgeid[i, 0]]['x'],
                                   graph2.nodes[edgeid[i, 0]]['y'])
        graph2.add_edge(edgeid[i, 0],
                        i,
                        osmid=2 * i,
                        highway=graph2.edges[(edgeid[i, 0], edgeid[i, 1],
                                              0)]["highway"],
                        oneway=graph2.edges[(edgeid[i, 0], edgeid[i, 1],
                                             0)]["oneway"],
                        length=distance1)

        _, _, distance2 = geod.inv(track[i, 1], track[i, 0],
                                   graph2.nodes[edgeid[i, 1]]['x'],
                                   graph2.nodes[edgeid[i, 1]]['y'])
        graph2.add_edge(edgeid[i, 1],
                        i,
                        osmid=2 * i + 1,
                        highway=graph2.edges[(edgeid[i, 0], edgeid[i, 1],
                                              0)]["highway"],
                        oneway=graph2.edges[(edgeid[i, 0], edgeid[i, 1],
                                             0)]["oneway"],
                        length=distance2)

    # adding edges in both directions
    # for edge in list(graph2.edges):
    #     graph2.add_edge(edge[1], edge[0],
    #                     osmid=graph2.edges[(edge[0], edge[1], 0)]["osmid"]*2,
    #                     highway=graph2.edges[(edge[0], edge[1], 0)]["highway"],
    #                     oneway=graph2.edges[(edge[0], edge[1], 0)]["oneway"],
    #                     length=graph2.edges[(edge[0], edge[1], 0)]["length"])
    graph2 = graph2.to_undirected()

    route = []
    path_length = []
    unlinked = []
    for i in range(len(track) - 1):
        # If there is a changing direction (going from one edge to another,
        # compute Dijkstras algorithm to know what path to follow.
        if edgeid[i][0] != edgeid[i + 1][0] or edgeid[i][1] != edgeid[i +
                                                                      1][1]:
            # If the two nodes are connected
            try:
                path = nx.shortest_path(graph2, i, i + 1, weight='length')
                distance = nx.shortest_path_length(graph2,
                                                   i,
                                                   i + 1,
                                                   weight='length')
                path_length.append(distance)
                unlinked.append(0)
                for nodeid in path:
                    route.append(
                        [graph2.nodes[nodeid]["y"], graph2.nodes[nodeid]["x"]])

            # If they are not connected, there is a mismatched
            except nx.NetworkXNoPath:
                route.append(track[i])
                _, _, distance = geod.inv(track[i, 1], track[i, 0],
                                          track[i + 1, 1], track[i + 1, 0])
                path_length.append(distance)
                unlinked.append(1)

        # If the route is already matched
        else:
            route.append(track[i])
            _, _, distance = geod.inv(track[i, 1], track[i, 0],
                                      track[i + 1, 1], track[i + 1, 0])
            path_length.append(distance)
            unlinked.append(0)

    # Let's not forget to add the last point
    route.append(track[-1])
    unlinked.append(0)
    path_length.append(0)

    stats = {
        "path_length": np.array(path_length),
        "unlinked": np.array(unlinked)
    }

    return np.array(route), stats