Overpass / Overpy: получение путей от узлов
Я изо всех сил пытаюсь уложить Overpass так, как мне бы хотелось, поэтому я надеюсь, что кто-то сможет помочь.
У меня есть маршрут, который я импортирую из файла GPX. Это было привязано к данным OSM, поэтому у меня есть широта / долгота каждой точки на маршруте. Каждый из них совпадает с узлом OSM, но у меня нет идентификатора узла OSM.
Я также хочу выяснить, какие из этих точек я называю "пересечениями", т. Е. Где проходит маршрут от одного пути OSM к другому. Чтобы сделать это, я планировал перейти от узлов к дорогам (шоссе) и выяснить, где изменился маршрут, возможно, с некоторыми уточнениями, например, чтобы принять во внимание название пути.
Итак, используя Overpy, я обнаружил, что самый быстрый способ перейти от точек маршрута к узлам OSM - это объединить несколько запросов ограничивающего прямоугольника:
TOL = 0.00001
query = """
<osm-script>
<union>
"""
for index, row in df_snapped.iterrows():
query += ' <bbox-query s="{}" w="{}" n="{}" e="{}"/>\n'.format(
round(row.lat-TOL, 5)
,round(row.lon-TOL, 5)
,round(row.lat+TOL, 5)
,round(row.lon+TOL, 5)
)
query += """
</union>
<union into="_">
<item from="_" into="_"/>
<recurse from="_" into="_" type="node-way"/>
</union>
<print e="" from="_" geometry="skeleton" ids="yes" limit="" mode="body" n="" order="id" s="" w=""/>
</osm-script>
"""
Это приводит к запросу, подобному следующему:
<osm-script>
<union>
<bbox-query s="51.48825" w="-2.62352" n="51.48827" e="-2.6235"/>
<bbox-query s="51.48801" w="-2.62364" n="51.48803" e="-2.62362"/>
<bbox-query s="51.4878" w="-2.62373" n="51.48782" e="-2.62371"/>
<bbox-query s="51.48697" w="-2.62406" n="51.48699" e="-2.62404"/>
<bbox-query s="51.48682" w="-2.62414" n="51.48684" e="-2.62412"/>
<bbox-query s="51.4868" w="-2.62416" n="51.48682" e="-2.62414"/>
<bbox-query s="51.48665" w="-2.62431" n="51.48667" e="-2.62429"/>
<bbox-query s="51.48654" w="-2.62442" n="51.48656" e="-2.6244"/>
<bbox-query s="51.48633" w="-2.62463" n="51.48635" e="-2.62461"/>
...
</union>
<union into="_">
<item from="_" into="_"/>
<recurse from="_" into="_" type="node-way"/>
</union>
<print e="" from="_" geometry="skeleton" ids="yes" limit="" mode="body" n="" order="id" s="" w=""/>
</osm-script>
Второй <union>
предложение дает мне пути от узлов. Все идет нормально.
Тогда я планирую создать словарь Python, содержащий идентификаторы узлов в качестве ключей и наборы идентификаторов пути в качестве значений:
node_ways = {}
for idx, way in enumerate(result.ways):
nodes = way.get_nodes(resolve_missing=True)
for node in nodes:
if node.id in node_ways:
temp = node_ways[node.id]
temp.add(way.id)
node_ways[node.id] = temp
else:
node_ways[node.id] = set([way.id])
Это прекрасно работает, но есть две проблемы:
- Использование
resolve_missing=True
На устранение всех недостающих узлов уходит около 3,5 минут, и я бы очень хотел сократить это время. Я пытался удалитьresolve_missing=True
и положить обработчик исключений вокругget_nodes
, но это приводит к тому, что набор узлов является неполным. - Когда я использую
resolve_missing=True
Я получаю все узлы на всех путях, которые пересекаются с исходным набором узлов. Это больше узлов, чем мне нужно. Я мог бы уменьшить это в коде, но в идеале я бы предпочел избавиться от необходимости использоватьresolve_missing=True
как-то.
Итак, мой вопрос: могу ли я либо адаптировать исходный запрос, чтобы получить нужный вывод, либо получить то, что мне нужно, и избежать использования resolve_missing=True
каким-то другим способом?
1 ответ
Еще немного рытье нашло мне ответ. Выполнение например
vars(result.get_way(4755884))
дает внутреннюю структуру пути объекта:
{'_attribute_modifiers': {'changeset': int,
'timestamp': <function overpy.Element.__init__.<locals>.<lambda>>,
'uid': int,
'version': int,
'visible': <function overpy.Element.__init__.<locals>.<lambda>>},
'_node_ids': [26229733,
291529159,
246189513,
2682629060,
291529223,
3723657411,
3723657424,
2018716449,
291530424,
2018716450,
291530803,
26229737,
1741942073,
4100724928,
4100724934],
'_result': <overpy.Result at 0x221fc5b17f0>,
'attributes': {},
'center_lat': None,
'center_lon': None,
'id': 4755884,
'tags': {'bicycle': 'yes',
'highway': 'residential',
'maxspeed': '20 mph',
'name': 'Reedley Road',
'postal_code': 'BS9',
'sidewalk': 'both'}}
Поэтому я могу получить доступ к списку необработанных идентификаторов узлов, используя, например, result.get_way(4755884)._node_ids
,