Overpass / Overpy:从节点获取方法

时间:2018-05-21 08:56:43

标签: python openstreetmap overpass-api

我正在努力和我一样努力克服Overpass,所以我希望有人可以提供帮助。

我有一个我从GPX文件导入的路由。这已被“捕捉”到OSM数据,所以我有路由上每个点的纬度/经度。其中每个都与OSM节点重合,但我没有OSM节点ID。

我还想找到这些点中的哪些是我所谓的“交叉点”,即路线从一种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字典,其中包含节点ID作为其键,以及方式ID集合作为值:

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])

这很好用,但有两个问题:

  1. 使用resolve_missing=True大约需要3.5分钟来解决所有缺失的节点,我非常希望减少这段时间。我尝试删除resolve_missing=True并在get_nodes周围放置一个异常处理程序,但这会导致一组节点不完整。
  2. 当我使用resolve_missing=True时,我会在与原始节点集相交的所有路上获得 all 节点。这比我需要的节点多。我可以在代码中减少这个,但理想情况下我宁愿摆脱以某种方式使用resolve_missing=True的需要。
  3. 所以,我的问题是:我可以调整原始查询以直接提供我想要的输出,还是可以获得我需要的内容并避免使用其他方法使用resolve_missing=True

1 个答案:

答案 0 :(得分: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'}}

因此,我可以使用例如,访问原始节点ID列表。 result.get_way(4755884)._node_ids