local noisy_places = osm2pgsql.define_table({ name = 'osm_noisy_places', schema = 'noisy_places_next', ids = { type = 'any', id_column = 'osm_id', type_column = 'osm_type', create_index = 'always' }, columns = { { column = 'name', type = 'text' }, { column = 'category', type = 'text', not_null = true }, { column = 'tags', type = 'jsonb', not_null = true }, { column = 'geom', type = 'geometry', projection = 4326, not_null = true } } }) local coverage_boundaries = osm2pgsql.define_table({ name = 'osm_coverage_boundaries', schema = 'noisy_places_next', ids = { type = 'any', id_column = 'osm_id', type_column = 'osm_type', create_index = 'always' }, columns = { { column = 'jurisdiction', type = 'text', not_null = true }, { column = 'tags', type = 'jsonb', not_null = true }, { column = 'geom', type = 'geometry', projection = 4326, not_null = true } } }) -- Classified roads, as full linestrings, so the road-noise row can say -- which road "most of it" is. Mirrors ROAD_NAME_CLASSES in -- extension/lib/nearby-noise.js. local roads = osm2pgsql.define_table({ name = 'osm_roads', schema = 'noisy_places_next', ids = { type = 'way', id_column = 'osm_id', create_index = 'always' }, columns = { { column = 'name', type = 'text' }, { column = 'ref', type = 'text' }, { column = 'class', type = 'text', not_null = true }, { column = 'maxspeed', type = 'text' }, { column = 'tags', type = 'jsonb', not_null = true }, { column = 'geom', type = 'linestring', projection = 4326, not_null = true } } }) local road_classes = { motorway = true, motorway_link = true, trunk = true, trunk_link = true, primary = true, primary_link = true, secondary = true, secondary_link = true, tertiary = true, tertiary_link = true } local amenity_values = { school = true, kindergarten = true, childcare = true, pub = true, bar = true, nightclub = true, biergarten = true, events_venue = true, music_venue = true } local leisure_values = { playground = true, stadium = true, sports_centre = true, pitch = true, water_park = true } local subdivision_codes = { ['GB-ENG'] = 'England', ['GB-WLS'] = 'Wales', ['GB-SCT'] = 'Scotland', ['GB-NIR'] = 'Northern Ireland' } local subdivision_names = { England = true, Wales = true, Scotland = true, ['Northern Ireland'] = true } local function has_value(values, value) return value ~= nil and values[value] == true end -- This precedence mirrors classifySoundSource. A feature appears once even if, -- as pubs sometimes do, it has filled in several noisy-looking boxes at once. local function category_for(tags) local outdoor = tags.outdoor_seating == 'yes' or tags.outdoor_seating == 'only' local live_music = tags.live_music == 'yes' or tags.live_music == 'live' if tags.amenity == 'nightclub' then return 'nightclub' end if tags.amenity == 'events_venue' or tags.amenity == 'music_venue' or live_music then return 'music-venue' end if tags.amenity == 'pub' or tags.amenity == 'bar' or tags.amenity == 'biergarten' then return 'pub' end if tags.leisure == 'stadium' then return 'stadium' end if tags.tourism == 'theme_park' or tags.leisure == 'water_park' then return 'attraction' end if tags.amenity == 'school' then return 'school' end if tags.amenity == 'kindergarten' or tags.amenity == 'childcare' then return 'nursery' end if tags.leisure == 'playground' then return 'playground' end if tags.leisure == 'sports_centre' or tags.leisure == 'pitch' then return 'sport' end if tags.man_made == 'works' or (tags.landuse == 'industrial' and tags.name ~= nil and tags.name ~= '') then return 'works' end if outdoor then return 'outdoor-seating' end return nil end local function jurisdiction_for(tags) if tags.boundary ~= 'administrative' then return nil end if tags['ISO3166-1'] == 'GB' and tags.admin_level == '2' then return 'United Kingdom' end local coded = subdivision_codes[tags['ISO3166-2']] if coded ~= nil then return coded end if tags.admin_level == '4' and subdivision_names[tags.name] then return tags.name end return nil end local function insert_noisy_place(object, category, geometry) if geometry == nil or geometry:is_null() then return end noisy_places:insert({ name = object.tags.name, category = category, tags = object.tags, geom = geometry }) end local function insert_boundary(object, jurisdiction, geometry) if geometry == nil or geometry:is_null() then return end coverage_boundaries:insert({ jurisdiction = jurisdiction, tags = object.tags, geom = geometry }) end function osm2pgsql.process_node(object) local category = category_for(object.tags) if category ~= nil then insert_noisy_place(object, category, object:as_point()) end end local function insert_road(object, geometry) if geometry == nil or geometry:is_null() then return end roads:insert({ name = object.tags.name, ref = object.tags.ref, class = object.tags.highway, maxspeed = object.tags.maxspeed, tags = object.tags, geom = geometry }) end function osm2pgsql.process_way(object) if has_value(road_classes, object.tags.highway) then insert_road(object, object:as_linestring()) end local category = category_for(object.tags) if category == nil then return end if object.is_closed then insert_noisy_place(object, category, object:as_polygon()) else insert_noisy_place(object, category, object:as_linestring()) end end function osm2pgsql.process_relation(object) local jurisdiction = jurisdiction_for(object.tags) if jurisdiction ~= nil and (object.tags.type == 'multipolygon' or object.tags.type == 'boundary') then insert_boundary(object, jurisdiction, object:as_multipolygon()) end local category = category_for(object.tags) if category == nil then return end if object.tags.type == 'multipolygon' or object.tags.type == 'boundary' then insert_noisy_place(object, category, object:as_multipolygon()) elseif object.tags.type == 'route' then insert_noisy_place(object, category, object:as_multilinestring()) else insert_noisy_place(object, category, object:as_geometrycollection()) end end