156 lines
6.5 KiB
Lua
156 lines
6.5 KiB
Lua
-- osm2pgsql Flex output script for Transportationer
|
|
-- Maps OSM tags to the 5 POI categories
|
|
|
|
-- Write to a per-city staging table so osm2pgsql can freely drop/recreate it
|
|
-- in create mode without touching other cities' rows in raw_pois.
|
|
-- extract-pois.ts merges the staging data into raw_pois after the import.
|
|
local city_slug = os.getenv('CITY_SLUG') or 'unknown'
|
|
local staging_name = 'raw_pois_import_' .. city_slug:gsub('[^%w]', '_')
|
|
|
|
local pois = osm2pgsql.define_table({
|
|
name = staging_name,
|
|
ids = { type = 'any', id_column = 'osm_id', type_column = 'osm_type' },
|
|
columns = {
|
|
{ column = 'city_slug', type = 'text' },
|
|
{ column = 'category', type = 'text' },
|
|
{ column = 'subcategory', type = 'text' },
|
|
{ column = 'name', type = 'text' },
|
|
{ column = 'tags', type = 'jsonb' },
|
|
{ column = 'geom', type = 'point', projection = 4326 },
|
|
}
|
|
})
|
|
|
|
-- Tag → {category, subcategory} mapping
|
|
local tag_map = {
|
|
amenity = {
|
|
-- service_trade
|
|
pharmacy = { 'service_trade', 'pharmacy' },
|
|
bank = { 'service_trade', 'bank' },
|
|
atm = { 'service_trade', 'atm' },
|
|
cafe = { 'service_trade', 'cafe' },
|
|
restaurant = { 'service_trade', 'restaurant' },
|
|
fast_food = { 'service_trade', 'restaurant' },
|
|
post_office = { 'service_trade', 'post_office' },
|
|
marketplace = { 'service_trade', 'market' },
|
|
-- transport
|
|
bicycle_rental = { 'transport', 'bike_share' },
|
|
car_sharing = { 'transport', 'car_share' },
|
|
ferry_terminal = { 'transport', 'ferry' },
|
|
bus_station = { 'transport', 'bus_stop' },
|
|
-- work_school
|
|
kindergarten = { 'work_school', 'kindergarten' },
|
|
childcare = { 'work_school', 'kindergarten' },
|
|
school = { 'work_school', 'school' },
|
|
university = { 'work_school', 'university' },
|
|
college = { 'work_school', 'university' },
|
|
driving_school = { 'work_school', 'driving_school' },
|
|
-- culture_community
|
|
library = { 'culture_community', 'library' },
|
|
theatre = { 'culture_community', 'theatre' },
|
|
cinema = { 'culture_community', 'theatre' },
|
|
community_centre= { 'culture_community', 'community_center' },
|
|
place_of_worship= { 'culture_community', 'place_of_worship' },
|
|
hospital = { 'culture_community', 'hospital' },
|
|
clinic = { 'culture_community', 'clinic' },
|
|
doctors = { 'culture_community', 'clinic' },
|
|
social_facility = { 'culture_community', 'social_services' },
|
|
townhall = { 'culture_community', 'government' },
|
|
police = { 'culture_community', 'government' },
|
|
-- recreation
|
|
swimming_pool = { 'recreation', 'swimming_pool' },
|
|
},
|
|
shop = {
|
|
supermarket = { 'service_trade', 'supermarket' },
|
|
wholesale = { 'service_trade', 'supermarket' },
|
|
convenience = { 'service_trade', 'convenience' },
|
|
bakery = { 'service_trade', 'cafe' },
|
|
pharmacy = { 'service_trade', 'pharmacy' },
|
|
laundry = { 'service_trade', 'laundry' },
|
|
dry_cleaning = { 'service_trade', 'laundry' },
|
|
greengrocer = { 'service_trade', 'market' },
|
|
butcher = { 'service_trade', 'market' },
|
|
department_store= { 'service_trade', 'market' },
|
|
mall = { 'service_trade', 'market' },
|
|
},
|
|
highway = {
|
|
bus_stop = { 'transport', 'bus_stop' },
|
|
},
|
|
railway = {
|
|
station = { 'transport', 'train_station' },
|
|
halt = { 'transport', 'train_station' },
|
|
tram_stop = { 'transport', 'tram_stop' },
|
|
subway_entrance = { 'transport', 'metro' },
|
|
subway_station = { 'transport', 'metro' },
|
|
},
|
|
-- public_transport stop_position/platform intentionally excluded:
|
|
-- they duplicate highway=bus_stop / railway=tram_stop nodes at the same
|
|
-- physical location and would double-count those stops in scoring.
|
|
office = {
|
|
coworking = { 'work_school', 'coworking' },
|
|
},
|
|
tourism = {
|
|
museum = { 'culture_community', 'museum' },
|
|
},
|
|
leisure = {
|
|
park = { 'recreation', 'park' },
|
|
playground = { 'recreation', 'playground' },
|
|
sports_centre = { 'recreation', 'sports_facility' },
|
|
fitness_centre = { 'recreation', 'gym' },
|
|
swimming_pool = { 'recreation', 'swimming_pool' },
|
|
garden = { 'recreation', 'park' },
|
|
nature_reserve = { 'recreation', 'green_space' },
|
|
golf_course = { 'recreation', 'green_space' },
|
|
pitch = { 'recreation', 'sports_facility' },
|
|
arts_centre = { 'culture_community', 'community_center' },
|
|
},
|
|
landuse = {
|
|
recreation_ground = { 'recreation', 'green_space' },
|
|
grass = { 'recreation', 'green_space' },
|
|
meadow = { 'recreation', 'green_space' },
|
|
forest = { 'recreation', 'green_space' },
|
|
},
|
|
}
|
|
|
|
local CITY_SLUG = city_slug
|
|
|
|
local function classify(tags)
|
|
for key, values in pairs(tag_map) do
|
|
local val = tags[key]
|
|
if val and values[val] then
|
|
return values[val][1], values[val][2]
|
|
end
|
|
end
|
|
return nil, nil
|
|
end
|
|
|
|
local function get_centroid(object)
|
|
if object.type == 'node' then
|
|
return object:as_point()
|
|
elseif object.type == 'way' then
|
|
local geom = object:as_linestring()
|
|
if geom then return geom:centroid() end
|
|
else
|
|
local geom = object:as_multipolygon()
|
|
if geom then return geom:centroid() end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function process(object)
|
|
local category, subcategory = classify(object.tags)
|
|
if not category then return end
|
|
local geom = get_centroid(object)
|
|
if not geom then return end
|
|
pois:insert({
|
|
city_slug = CITY_SLUG,
|
|
category = category,
|
|
subcategory = subcategory,
|
|
name = object.tags.name,
|
|
tags = object.tags,
|
|
geom = geom,
|
|
})
|
|
end
|
|
|
|
function osm2pgsql.process_node(object) process(object) end
|
|
function osm2pgsql.process_way(object) process(object) end
|
|
function osm2pgsql.process_relation(object) process(object) end
|