Skip to content

Instantly share code, notes, and snippets.

@marklit
Last active August 20, 2024 08:12
Show Gist options
  • Save marklit/fb8ca1a9034b8385361fe038ec157cd8 to your computer and use it in GitHub Desktop.
Save marklit/fb8ca1a9034b8385361fe038ec157cd8 to your computer and use it in GitHub Desktop.
Airport Amenities

Airport Shops on OSM

Tallinn Airport is said to be the 'cosiest' airport in the world. If you search for that on Google they come up first. I noticed none of the shops or other amenities around the gates are marked in OSM.

I wrote some code to see if this was an issue at airports of a similar size or larger nearby in other EU countries. I got a lot of false-positives but this code might help anyone else looking to enrich the Airport metadata in OSM.

TLL is surrounded by dense urban areas and a major shopping mall so I built a polygon mask around the airport gates and counted the shops within it.

Airports that came back with no shops within their gate area mask where:

  • Bremen (BRE)
  • Bromma (BMA)
  • Dresden (DRS)
  • Gdansk Lech Walesa (GDN)
  • Kiruna_Airport (KRN)
  • Kraków-Balice (KRK)
  • Lulea (LLA)
  • Nurnberg (NUE)
  • Oulu (OUL)
  • Rovaniemi (RVN)
  • Stuttgart (STR)
  • Tromsø Langnes (TOS)
  • Ulemiste (TLL)

I checked Bremen, Krakow and Oulu and they look to be fairly well populated though I've only ever been in Bremen's airport and that was 20 years ago.

Bremen: https://www.openstreetmap.org/node/10796900775#map=17/53.053980/8.784814

Krakow: https://www.openstreetmap.org/node/10796900775#map=19/50.072307/19.801341

Count Shops in Gates Area

Natural Earth Download Guide: https://tech.marksblogg.com/natural-earth-free-gis-data.html

$ sudo apt update
$ sudo apt install \
    aws-cli \
    python3-pip \
    python3-virtualenv \
    unzip

$ virtualenv ~/.osm
$ source ~/.osm/bin/activate
$ pip install \
    duckdb \
    requests \
    shapely
import duckdb
import requests
from   shapely import convex_hull, MultiPoint, Polygon, Point


def osm_get(latitude:float,
            longitude:float,
            radius_meters:int=3_000,
            item:str='nwr[shop]'):
    query = f"""
    [out:json];
    (
      {item}(around:{radius_meters},{latitude},{longitude});
    );
    out center;
    """

    resp = requests.get('https://overpass-api.de/api/interpreter',
                        params={'data': query})

    if resp.status_code == 200:
        return resp.json()['elements']
    
    raise Exception(resp.text)


def get_point(shop):
    lon, lat = (shop['lon'], shop['lat']) \
                if 'lon' in shop.keys() \
                else (shop['center']['lon'], shop['center']['lat'])
    return Point(lon, lat)


sql = '''
SELECT   name,
         abbrev,
         ST_X(geom) as lon,
         ST_Y(geom) as lat
FROM     ST_READ('/home/mark/natural_earth/10m_cultural/ne_10m_airports/ne_10m_airports.shp')
WHERE    ST_DISTANCE(ST_POINT(24.801791, 59.416408), geom) < 20
AND      scalerank > 3
AND      gps_code LIKE 'E%'
ORDER BY name
'''

con = duckdb.connect(database=':memory:')
_ = con.sql('INSTALL spatial; LOAD spatial;')

shop_count = []

for rec in con.sql(sql).to_df().iloc():
    features = osm_get(rec['lat'],
                       rec['lon'],
                       3_000,
                       'nwr[aeroway=gate]')

    gates_area = convex_hull(MultiPoint([(x['lon'], x['lat'])
                                         for x in features]))

    if not gates_area.is_empty:
        features = osm_get(gates_area.centroid.y,
                           gates_area.centroid.x,
                           3_000,
                           'nwr[shop]')

        shops = [shop for shop in features if gates_area.contains(get_point(shop))]
        shop_count.append([rec['name'], rec['abbrev'], len(shops)])

print('\n'.join(['%s (%s)' % (name, abbrev)
                 for name, abbrev, count_ in shop_count
                 if count_ < 1]))
@marklit
Copy link
Author

marklit commented Aug 20, 2024

Tallinn Airport's OSM data:

brave_PwCyAQb7yN

@marklit
Copy link
Author

marklit commented Aug 20, 2024

To compare, Helsinki's Vantaa Airport has pretty much every shop and border post listed that I can remember.

brave_9upZ5us2Lw

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment