# How to check efficiently if thousands of points are located inside a building polygon using overpass ?

 1 Hi, I want to check for thousands of points (lat, lon), if they are located inside a building polygon using the overpass API. I know how to do it for one point (eg: https://help.openstreetmap.org/questions/55529/how-to-detect-if-point-is-inside-a-building-polygon-with-overpass) but I don't know how to do it without sending requests during hours to the overpass API. I'm currently using this request for one point: ``````way(around:5, {lat}, {lon})[building]; if(count(ways) < 1) {{ way(around:10, {lat}, {lon})[building]; if(count(ways) < 1) {{ way(around:15, {lat}, {lon})[building]; if(count(ways) < 1) {{ way(around:20, {lat}, {lon})[building]; if(count(ways) < 1) {{ way(around:25, {lat}, {lon})[building]; }}}} }}}} out geom; `````` where I check gradually up until 25 meters for close buildings. I don't think there is a tool in overpass for checking if the point at lat, lon is located inside any of the close buildings (except creating temporary areas and using is_in?). So, I use the shapely python library for that. The full process for the thousand points takes hours. How could I do it efficiently? I could query all the close buildings of all the points in one request but I don't know how to keep a reference to the node from which a building is close. Thus, I will be forced to check if a node is inside any buildings that I got, no matter from which node the building is close. In this case, it will also not be efficient. Does anyone have an idea for the query to use? Or on how to keep the reference? Thanks! Vucod The full code: ``````from OSMPythonTools.overpass import Overpass import pandas as pd from shapely.geometry import Point from shapely.geometry.polygon import Polygon def checkIfOnBuilding(lat, lon): """ Check for building in a 25 radius lat, lon as string """ point = Point(lat, lon) result = overpass.query(f""" way(around:5, {lat}, {lon})[building]; if(count(ways) < 1) {{ way(around:10, {lat}, {lon})[building]; if(count(ways) < 1) {{ way(around:15, {lat}, {lon})[building]; if(count(ways) < 1) {{ way(around:20, {lat}, {lon})[building]; if(count(ways) < 1) {{ way(around:25, {lat}, {lon})[building]; }}}} }}}} out geom; """, timeout=500) dict_ = result.toJSON()['elements'] df = pd.DataFrame(dict_) if len(df) > 0: for i, row in df.iterrows(): nodes = [(node["lat"], node["lon"]) for node in row.geometry] polygon = Polygon(nodes) res = polygon.contains(point) if res: break else: res = False return res `````` asked 26 Apr '20, 12:59 Vucod 26●1●1●2 accept rate: 0% There's not a contains operation in the Overpass-API query language. You can inject text into the result using the `make` statement: https://dev.overpass-api.de/blog/textual_data.html (02 May '20, 23:00) maxerickson

 0 I finally found the way to do it in one request which is a lot faster. I just use my request for every point and I separate each sub request by a `out count;`. Therefore, as the order of the sets is kept and I have a delimiter between the sets, I can find back for each point the buildings that are close. But there is still maybe a cleaner way to do it using only overpass API? The full code using python3 : ``````from OSMPythonTools.overpass import Overpass import pandas as pd from shapely.geometry import Point from shapely.geometry.polygon import Polygon def onBuilding(lats: str, lons: str) -> List[bool]: """ Check if coordinates are on a building. Works only for buildings that have a node closer than 25 meters from the coordinate. """ query = """ """ for lat, lon in zip(lats, lons): query += f""" way(around:5, {lat}, {lon})[building]; if(count(ways) < 1) {{ way(around:10, {lat}, {lon})[building]; if(count(ways) < 1) {{ way(around:15, {lat}, {lon})[building]; if(count(ways) < 1) {{ way(around:20, {lat}, {lon})[building]; if(count(ways) < 1) {{ way(around:25, {lat}, {lon})[building]; }}}} }}}} out count; out geom; """ result = overpass.query(query, timeout=15000) elements = result.toJSON()["elements"] list_ = [] for lat, lon in zip(lats, lons): point = Point(lat, lon) onBuilding = False sizeSet = int(elements["tags"]['total']) elements.pop(0) for item in range(sizeSet): element = elements[item] nodes = [(node["lat"], node["lon"]) for node in element["geometry"]] polygon = Polygon(nodes) onBuilding = polygon.contains(point) if onBuilding: print("--> the coordinate is inside a building") break del elements[:sizeSet] list_.append(onBuilding) return list_ `````` answered 02 May '20, 19:51 Vucod 26●1●1●2 accept rate: 0%
 toggle preview community wiki:

By Email:

Markdown Basics

• *italic* or _italic_
• **bold** or __bold__
• image?![alt text](/path/img.jpg "title")
• numbered list: 1. Foo 2. Bar
• to add a line break simply add two spaces to where you would like the new line to be.
• basic HTML tags are also supported

Question tags:

×475
×77
×75
×8

question asked: 26 Apr '20, 12:59

question was seen: 2,598 times

last updated: 02 May '20, 23:00