mocnik-science / osm-python-tools

A library to access OpenStreetMap related services
GNU General Public License v3.0
441 stars 48 forks source link

Unable to use `geocodeArea` in overpass query #46

Closed erictapen closed 2 years ago

erictapen commented 2 years ago

Thanks for this cool software.

I'm unable to use a query containing geocodeArea:

from OSMPythonTools.overpass import Overpass

query = """
{{geocodeArea:Berlin}}->.searchArea; ( node[memorial=ghost_bike](area.searchArea); ); out body;
"""

overpass = Overpass()
result = overpass.query(query)
print(result.toJSON())
The requested data could not be downloaded. HTTP Error 400: Bad Request

The same query, prefixed by [timeout:25][out:json]; runs just fine in Overpass Turbo.

Any idea what I'm doing wrong here?

mocnik-science commented 2 years ago

Dear @erictapen,

Thanks for raising this issue, and thanks for your nice words about this piece of software.

I assume that you built your code using the Overpass Turbo. The “command” geocodeArea does only work with Overpass Turbo but not so with the Overpass API itself. The website Overpass Turbo actually runs a separate query for geocodeArea and then hands over a modified request to the Overpass API. I now that this is confusing, but this is just the case.

OSMPythonTools is only able to execute Overpass API queries. However, it is similar to Overpass Turbo in that it provides the possibility to use Nominatim to resolve the area in the sense that it can be used in an Overpass API query.

More concretely, this means that you can run the following query to determine the area ID:

from OSMPythonTools.nominatim import Nominatim
nominatim = Nominatim()
areaId = nominatim.query('Berlin').areaId()
```python
The result will be `3600062422`.  Then, you can use this ID to build your query, for instance, using the overpassQueryBuilder:
```python
from OSMPythonTools.overpass import overpassQueryBuilder, Overpass
overpass = Overpass()
query = overpassQueryBuilder(area=areaId, elementType='node', selector='"natural"="tree"', out='count')
result = overpass.query(query)
result.countElements()

Voilà, the result is the number of trees in Berlin (only those registered in OSM, of course): 176905.

Alternatively, you can of course write the query on your own for most flexibility, like

query = 'area(3600062422)->.searchArea;(node["natural"="tree"](area.searchArea);); out count;'
result = overpass.query(query)
result.countElements()

The result is the same.

It should be not to hard to modify these examples to match the tags in your intend request.

Best, Franz-Benjamin

erictapen commented 2 years ago

Thanks for the explanation! Didn't know about the destinction between Overpass and Overpass Turbo. Given that it absolutely makes sense ofc.