Как найти ближайшие узлы в дорожной сети с учетом направления улиц

Я пытаюсь вычислить расстояние между двумя точками (широта, долгота), используя пакет osmnx.

Во время тестирования osmnx.nearest_nodes(), чтобы сначала найти ближайший узел от точки, я заметил, что он, похоже, не учитывает направление улицы при вычислении ближайшего узла (например, когда точка находится на улице с односторонним движением).

Например: если я возьму эту (широта, долгота) точку (48.921281, 2.517598), расположенную на улице с односторонним движением, ближайший узел будет найден только с учетом расстояния от нее (узел n°OSMID 288965181 найден с nearest_nodes(): 48.9217176 , 2.5180361).

nearest_nodes() похоже не учитывает тип сети, которую я выбрал (диск). Если да, то найденный узел должен был быть узлом 288964629 (48.9203235, 2.5166429).

Почему ? Потому что с точки (48.921281, 2.517598) узел 288965181 не является ближайшим узлом с учетом управляющей сети, а узел 288964629 — ближайшим.

Вот пример кода:

import osmnx as ox
import networkx as nx

#creating the graph from a point coordinates
centreCoord = (48.920576, 2.529185)
G= ox.graph_from_point(centreCoord, dist=2000, network_type='drive')

#origin and destination point
originCoord = (48.921281, 2.517598)
destinationCoord = (48.921454, 2.518696)

#calculating the nearest nodes from origin and destination points
origin_node = ox.nearest_nodes(G, originCoord[1], originCoord[0])
destination_node = ox.nearest_nodes(G, destinationCoord[1], destinationCoord[0])

#computing the driving path
route = nx.shortest_path(G, source=origin_node, target=destination_node, weight='length')

Вот простой сюжет, где:

  • красная точка — исходная точка (48.921281, 2.517598)
  • синяя точка — пункт назначения (48.921454, 2.518696)
  • зеленая точка — это узел 288965181 (48.9217176, 2.5180361)
  • черная точка — это узел 288965599, ближайшая точка от точки назначения
  • пурпурная линия — это маршрут, рассчитанный с помощью networkx.shortest_path()

Я добавил :

  • оранжевая точка, которая является узлом 288964629 (48.9203235, 2.5166429) -> узел, который я хотел бы иметь в качестве ближайшего узла от исходной точки, относительно направления трафика (выбранный тип сети — «привод»)
  • синий путь -> маршрут, который я должен получить, относительно направления движения

Сюжетное изображение

Я мог иногда пропустить или сделать что-то не так.

Я прочитал osmnx документацию. Пробовал несколько комбинаций (параметры network_type, ox.settings.bidirectional_network_types), пытался отлаживать вычисления, чтобы понять, как выбираются узлы.

Прежде чем спрашивать, я искал похожие темы. Много интересных вещей, но я не нашел подходящих ответов.

Я застрял на этом в течение нескольких дней.

Любая помощь будет здорово!

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
113
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Возможный обходной путь может быть следующим:

  1. найдите ближайшее ребро от исходной точки, используя функцию ox.nearest_edges(). Вы получите дорогу с односторонним движением;
  2. ребро определяется узлами u,v: u — начальный узел пути, v — конечный узел, следующий по направлению улицы;
  3. узел v — это узел, который вы хотите рассматривать (288964629), поэтому вычислите маршрут от узла v до узла назначения.
# Get the nearest edge from the origin point
u, v, k = ox.nearest_edges(G, originCoord[1], originCoord[0])

destination_node = ox.nearest_nodes(G, destinationCoord[1], destinationCoord[0])

# computing the driving path
route = nx.shortest_path(G, source=v, target=destination_node, weight='length')

Вот сюжет, используя ox.plot_graph_route(G, route):

Обратите внимание, что описанный подход прекрасно работает с дорогами с односторонним движением, состоящими всего из двух узлов.

Спасибо @dnyll! Я не думал об использовании nearest_edges() таким образом. Я буду реализовывать этот подход. Однако один вопрос: что вы подразумеваете под «отлично работает с односторонними дорогами, состоящими только из двух узлов»? Можно ли найти ребро с более чем двумя узлами?

moka 20.11.2022 10:28

Конечно, это все еще возможно ... Но предположим, что у вас есть более длинная дорога с односторонним движением со многими узлами: описанный мной подход всегда будет выбирать конечный узел пути как ближайший к исходной точке, а не ближайший средние узлы

dnyll 20.11.2022 13:45

Это касается примера, который я привел: дорога с односторонним движением в моем примере состоит из нескольких узлов. nearest_edges(G, pointA_lon, pointA_lat) вернет ближайший край дороги, поэтому я думаю, что ваш подход все еще должен работать.

moka 20.11.2022 14:45

Тогда все в порядке, надеюсь, это лучший ответ ✅

dnyll 20.11.2022 15:25

Другие вопросы по теме