【问题标题】:Wrong distance found when finding distance to nearest edge in OSMNx在 OSMNx 中查找到最近边缘的距离时发现了错误的距离
【发布时间】:2020-08-04 06:06:30
【问题描述】:

代码

您好,我正在尝试使用 OSMNx (OpenStreetMap + NetworkX) 包查找到最近边缘的距离(以米为单位)。 这是我的代码:

def main():
lat = 51.217309
lon = 4.418449
get_d_to_nearest_edge(lat, lon, 'node_area.graphml')

请注意,“node_area.graphml”是包含此特定位置的离线地图。 get_d_to_nearest_edge() 函数如下:

def get_d_to_nearest_edge(latitude, longitude, file_name):
print("-Now the nearest edge will be found-")
G = ox.load_graphml(filename=file_name, folder='BAPenvironment')
_, _, _, distance = get_nearest_edge(G, (latitude, longitude))
print('The distance to the nearest edge is ' + to_str(distance) + ' m')

在上面的代码中,函数 get_nearest_edge() 被访问。该函数的代码如下:

def get_nearest_edge(G, point):
"""
Return the nearest edge to a pair of coordinates. Pass in a graph and a tuple
with the coordinates. We first get all the edges in the graph. Secondly we compute
the euclidean distance from the coordinates to the segments determined by each edge.
The last step is to sort the edge segments in ascending order based on the distance
from the coordinates to the edge. In the end, the first element in the list of edges
will be the closest edge that we will return as a tuple containing the shapely
geometry and the u, v nodes.
Parameters
----------
G : networkx multidigraph
point : tuple
    The (lat, lng) or (y, x) point for which we will find the nearest edge
    in the graph
Returns
-------
closest_edge_to_point : tuple (shapely.geometry, u, v)
    A geometry object representing the segment and the coordinates of the two
    nodes that determine the edge section, u and v, the OSM ids of the nodes.
"""
start_time = time.time()

gdf = ox.graph_to_gdfs(G, nodes=False, fill_edge_geometry=True)
graph_edges = gdf[["geometry", "u", "v"]].values.tolist()

edges_with_distances = [
    (
        graph_edge,
        ox.Point(tuple(reversed(point))).distance(graph_edge[0])
    )
    for graph_edge in graph_edges
]

edges_with_distances = sorted(edges_with_distances, key=lambda x: x[1])
closest_edge_to_point, distance = edges_with_distances[0]

geometry, u, v = closest_edge_to_point

ox.log('Found nearest edge ({}) to point {} in {:,.2f} seconds'.format((u, v), point, time.time() - start_time))
print(distance)
return geometry, u, v, distance

这与原来的函数几乎相同,内置在 OSMNx 函数中,但也被修改为返回距离。 最后一个函数 to_str() 在这里:

 # convert everything into the same type (np.array) and then convert it to a string 
   def to_str(var):
       return str(list(np.reshape(np.asarray(var), (1, np.size(var)))[0]))[1:-1]

输出

但是输出似乎不正确。当我在 Google 地图中验证到最近边缘的距离时,我发现这是 18.57m。

> Now the nearest edge will be found Converting node and edge attribute
> data types Loaded graph with 36 nodes and 62 edges in 0.01 seconds
> from "BAPenvironment\node_area.graphml" Created GeoDataFrame
> "unnamed_edges" from graph in 0.00 seconds Found nearest edge
> ((247670339, 247527633)) to point (51.217309, 4.418449) in 0.00 seconds
> 0.00018056587349098678 
> The distance to the nearest edge is 0.00018056587349098678 m

我刚刚添加了“m”,因为我认为这是以米为单位的。有谁知道如何以米为单位?还是以米为单位,我的代码错了吗?

【问题讨论】:

  • 根据shapely.readthedocs.io/en/latest/manual.html#object.distance,Point().distance() 不是以米为单位的距离,而是以坐标为单位的距离。所以你得到 0.00018056587349098678 度。如果我们取 1 度等于 111139 米,以米为单位计算距离,我们将做 111139 * 0.00018056587349098678 = 20.06791061391478 米。但这都是低精度的。我敢打赌,在某处的 osmnx 中有一个以米为单位计算距离的函数
  • 感谢您的回答。我认为我需要实现的方法是“haversine”方法。但我不知道如何在 get_nearest_function() 中实现这个方法。因此我在这里提出了另一个问题:stackoverflow.com/questions/61348099
  • 我在下面添加了一个答案:OSMnx 确实返回了距离,并且可以在本地使用米而不是度作为单位。

标签: python networkx openstreetmap osmnx


【解决方案1】:

我可以通过更改 Ox.Point 函数来解决这个问题。我写了一个新函数来计算到 LineString 对象中每个坐标的半正弦距离。

from haversine import haversine, Unit

def closest_point_on_haversine(point,edge):
    closest_point = None
    
    for c in edge[0].coords:
        if closest_point == None:
            closest_point = haversine(tuple(reversed(point)), c, unit='m')
        else:
            if haversine(tuple(reversed(point)), c, unit='m') < closest_point:
                closest_point = haversine(tuple(reversed(point)), c, unit='m')
                
    return closest_point

def get_nearest_edge_with_dist(G, point):

    start_time = time.time()

    gdf = graph_to_gdfs(G, nodes=False, fill_edge_geometry=True)
    graph_edges = gdf[["geometry", "u", "v"]].values.tolist()

    edges_with_distances = [
        (
            graph_edge,
            # Point(tuple(reversed(point))).distance(graph_edge[0])
            closest_point_on_haversine(point,graph_edge)
        )
        for graph_edge in graph_edges
    ]

    edges_with_distances = sorted(edges_with_distances, key=lambda x: x[1])
    closest_edge_to_point, distance = edges_with_distances[0]

    geometry, u, v = closest_edge_to_point

    return geometry, u, v, distance

【讨论】:

    【解决方案2】:

    OSMnx 的get_nearest_edge 确实返回了距离。请参阅the docs,其中说“可选择返回点与最近边之间的图形坐标单位的距离”。如果您不想以度为单位工作,只需投影您的图表:

    import osmnx as ox
    from shapely.geometry import Point
    ox.config(use_cache=True, log_console=True)
    
    # lat-long point
    point = 34.081076, -118.351811
    G = ox.graph_from_point(point, network_type='drive')
    
    # project the graph (and point) to a meter projection
    Gp = ox.project_graph(G)
    point_geom_proj, crs = ox.projection.project_geometry(Point(reversed(point)), to_crs=Gp.graph['crs'])
    x, y = point_geom_proj.x, point_geom_proj.y
    
    # find nearest edge as (u, v, key) and distance to it
    u, v, key, dist = ox.get_nearest_edge(Gp, (y, x), return_dist=True)
    dist # 40.2 meters
    

    【讨论】:

    • 谢谢,这是一个很好的解决方案。我无法返回以米为单位的距离,但这看起来是个好方法。
    猜你喜欢
    • 1970-01-01
    • 2020-01-28
    • 2020-05-10
    • 1970-01-01
    • 2016-01-23
    • 2021-07-20
    • 1970-01-01
    • 2019-04-09
    • 2021-12-06
    相关资源
    最近更新 更多