微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何沿最近的边找到最近的节点?

如何解决如何沿最近的边找到最近的节点?

我从这里使用这个脚本:link

我想为其添加功能。我希望它不仅通过找到最近的节点(因为这会产生奇怪的结果,例如在另一条道路上找到最近的节点)来定义图上的起始节点,而且还要找到沿该边的最近和最近的节点。 我的代码在下面可用。我创建了 findnearestnodeonnearestedge 函数,它应该可以完成工作,但它不起作用。 它为起点和终点找到相同的节点,即使它们相距很远...... 我正在使用所有软件包的最新版本,因此您可以轻松地尝试代码

感谢您的帮助

import osmnx as ox
import networkx as nx
import plotly.graph_objects as go
import numpy as np


def findnearestnodeonnearestedge(Gr,pointin):

    u,v,key = ox.distance.nearest_edges(G,pointin[0],pointin[1])

    n1 = Gr.nodes[u]
    n2 = Gr.nodes[v]

    d1 = ox.distance.euclidean_dist_vec(pointin[0],pointin[1],n1['x'],n1['y'])
    d2 = ox.distance.euclidean_dist_vec(pointin[0],n2['x'],n2['y'])

    if d1 < d2:
        nodeid = u
    else:
        nodeid = v

    return nodeid


state = ox.geocode_to_gdf('Georgia,US')
ax = ox.project_gdf(state).plot(fc='gray',ec='none')
_ = ax.axis('off')

# Defining the map boundaries
north,east,south,west = 33.798,-84.378,33.763,-84.422

# Downloading the map as a graph object
G = ox.graph_from_bBox(north,west,network_type = 'drive')

# Plotting the map graph
ox.plot_graph(G)

# displaying the 3rd node
list(G.nodes(data=True))[2]

# displaying the 1st edge
list(G.edges(data=True))[1]

# displaying the shape of edge using the geometry
list(G.edges(data=True))[1][2]['geometry']

# define origin and desination locations
origin_point = (33.787201,-84.405076)
destination_point = (33.764135,-84.394980)

# get the nearest nodes to the locations
origin_node = findnearestnodeonnearestedge(G,origin_point)
destination_node = findnearestnodeonnearestedge(G,destination_point)

# printing the closest node id to origin and destination points
origin_node,destination_node

# Finding the optimal path
route = nx.shortest_path(G,origin_node,destination_node,weight = 'length')
route

# getting coordinates of the nodes

# we will store the longitudes and latitudes in following list
long = []
lat = []

for i in route:
    point = G.nodes[i]
    long.append(point['x'])
    lat.append(point['y'])


def plot_path(lat,long,origin_point,destination_point):
    """
    Given a list of latitudes and longitudes,origin
    and destination point,plots a path on a map

    Parameters
    ----------
    lat,long: list of latitudes and longitudes
    origin_point,destination_point: co-ordinates of origin
    and destination
    Returns
    -------
    nothing. Only shows the map.
    """

    # adding the lines joining the nodes
    fig = go.figure(go.ScattermapBox(
        name="Path",mode="lines",lon=long,lat=lat,marker={'size': 10},line=dict(width=4.5,color='blue')))

    # adding source marker
    fig.add_trace(go.ScattermapBox(
        name="Source",mode="markers",lon=[origin_point[1]],lat=[origin_point[0]],marker={'size': 12,'color': "red"}))

    # adding destination marker
    fig.add_trace(go.ScattermapBox(
        name="Destination",lon=[destination_point[1]],lat=[destination_point[0]],'color': 'green'}))

    # getting center for plots:
    lat_center = np.mean(lat)
    long_center = np.mean(long)

    # defining the layout using mapBox_style
    fig.update_layout(mapBox_style="stamen-terrain",mapBox_center_lat=30,mapBox_center_lon=-80)
    fig.update_layout(margin={"r": 0,"t": 0,"l": 0,"b": 0},mapBox={
                          'center': {'lat': lat_center,'lon': long_center},'zoom': 13})

    fig.show()

plot_path(lat,destination_point)

# Getting the start and end node of this part
start_node=route[-7]
end_node=route[-6]

# Getting the edge connecting these nodes and storing it as a list in z to maintain the data structure of G.edges
z = []

for i in list(G.edges(data=True)):
    if (i[0]==start_node) & (i[1]==end_node):
        z.append(i)

z[0][2]['geometry']

def node_list_to_path(G,node_list):
    """
    Given a list of nodes,return a list of lines that together follow the path
    defined by the list of nodes.
    Parameters
    ----------
    G : networkx multidigraph
    route : list
        the route as a list of nodes
    Returns
    -------
    lines : list of lines given as pairs ( (x_start,y_start),(x_stop,y_stop) )
    """
    edge_nodes = list(zip(node_list[:-1],node_list[1:]))
    lines = []
    for u,v in edge_nodes:
        # if there are parallel edges,select the shortest in length
        data = min(G.get_edge_data(u,v).values(),key=lambda x: x['length'])

        # if it has a geometry attribute (ie,a list of line segments)
        if 'geometry' in data:
            # add them to the list of lines to plot
            xs,ys = data['geometry'].xy
            lines.append(list(zip(xs,ys)))
        else:
            # if it doesn't have a geometry attribute,the edge is a straight
            # line from node to node
            x1 = G.nodes[u]['x']
            y1 = G.nodes[u]['y']
            x2 = G.nodes[v]['x']
            y2 = G.nodes[v]['y']
            line = [(x1,y1),(x2,y2)]
            lines.append(line)
    return lines

# getting the list of coordinates from the path (which is a list of nodes)
lines = node_list_to_path(G,route)

long2 = []
lat2 = []

for i in range(len(lines)):
    z = list(lines[i])
    l1 = list(list(zip(*z))[0])
    l2 = list(list(zip(*z))[1])
    for j in range(len(l1)):
        long2.append(l1[j])
        lat2.append(l2[j])

print("Length of lat: ",len(lat))
print("Length of lat2: ",len(lat2))

plot_path(lat2,long2,destination_point)

解决方法

问题在于图中坐标以相反的顺序存储。所以函数中的所有pointin[0]和pointin[1]都应该颠倒,然后它就可以工作了

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。