mirror of
https://github.com/osm2pgsql-dev/osm2pgsql.git
synced 2025-08-22 19:42:12 +00:00

This was totally broken with the switch from add_row() to insert(). Also implements the "reproject_area" switch now. Fixes #2017
767 lines
18 KiB
Lua
767 lines
18 KiB
Lua
-- This config example file is released into the Public Domain.
|
|
|
|
-- This configuration for the flex output tries to be compatible with the
|
|
-- original pgsql C transform output. There might be some corner cases but
|
|
-- it should do exactly the same in almost all cases.
|
|
|
|
-- The output projection used (3857, web mercator is the default). Set this
|
|
-- to 4326 if you were using the -l|--latlong option or to the EPSG
|
|
-- code you were using on the -E|-proj option.
|
|
local srid = 3857
|
|
|
|
-- Set this to true if you were using option -K|--keep-coastlines.
|
|
local keep_coastlines = false
|
|
|
|
-- Set this to the table name prefix (what used to be option -p|--prefix).
|
|
local prefix = 'planet_osm'
|
|
|
|
-- Set this to true if multipolygons should be written as multipolygons into
|
|
-- db (what used to be option -G|--multi-geometry).
|
|
local multi_geometry = false
|
|
|
|
-- Set this to true if you want an hstore column (what used to be option
|
|
-- -k|--hstore). Can not be true if "hstore_all" is true.
|
|
local hstore = false
|
|
|
|
-- Set this to true if you want all tags in an hstore column (what used to
|
|
-- be option -j|--hstore-all). Can not be true if "hstore" is true.
|
|
local hstore_all = false
|
|
|
|
-- Only keep objects that have a value in one of the non-hstore columns
|
|
-- (normal action with --hstore is to keep all objects). Equivalent to
|
|
-- what used to be set through option --hstore-match-only.
|
|
local hstore_match_only = false
|
|
|
|
-- Set this to add an additional hstore (key/value) column containing all tags
|
|
-- that start with the specified string, eg "name:". Will produce an extra
|
|
-- hstore column that contains all "name:xx" tags. Equivalent to what used to
|
|
-- be set through option -z|--hstore-column. Unlike the -z option which can
|
|
-- be specified multiple time, this does only support a single additional
|
|
-- hstore column.
|
|
local hstore_column = nil
|
|
|
|
-- If this is set, area calculations are always in Mercator coordinates units
|
|
-- irrespective of the srid setting.
|
|
-- Set this to true if you used --reproject-area before.
|
|
local reproject_area = false
|
|
|
|
-- There is some very old specialized handling of route relations in osm2pgsql,
|
|
-- which you probably don't need. This is disabled here, but you can enable
|
|
-- it by setting this to true. If you don't understand this, leave it alone.
|
|
local enable_legacy_route_processing = false
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
|
|
if hstore and hstore_all then
|
|
error("hstore and hstore_all can't be both true")
|
|
end
|
|
|
|
-- Used for splitting up long linestrings
|
|
local max_length = 1
|
|
if srid == 3857 then
|
|
max_length = 100000
|
|
end
|
|
|
|
-- Ways with any of the following keys will be treated as polygon
|
|
local polygon_keys = {
|
|
'aeroway',
|
|
'amenity',
|
|
'building',
|
|
'harbour',
|
|
'historic',
|
|
'landuse',
|
|
'leisure',
|
|
'man_made',
|
|
'military',
|
|
'natural',
|
|
'office',
|
|
'place',
|
|
'power',
|
|
'public_transport',
|
|
'shop',
|
|
'sport',
|
|
'tourism',
|
|
'water',
|
|
'waterway',
|
|
'wetland',
|
|
'abandoned:aeroway',
|
|
'abandoned:amenity',
|
|
'abandoned:building',
|
|
'abandoned:landuse',
|
|
'abandoned:power',
|
|
'area:highway'
|
|
}
|
|
|
|
-- Objects without any of the following keys will be deleted
|
|
local generic_keys = {
|
|
'access',
|
|
'addr:housename',
|
|
'addr:housenumber',
|
|
'addr:interpolation',
|
|
'admin_level',
|
|
'aerialway',
|
|
'aeroway',
|
|
'amenity',
|
|
'area',
|
|
'barrier',
|
|
'bicycle',
|
|
'boundary',
|
|
'brand',
|
|
'bridge',
|
|
'building',
|
|
'capital',
|
|
'construction',
|
|
'covered',
|
|
'culvert',
|
|
'cutting',
|
|
'denomination',
|
|
'disused',
|
|
'ele',
|
|
'embankment',
|
|
'foot',
|
|
'generation:source',
|
|
'harbour',
|
|
'highway',
|
|
'historic',
|
|
'hours',
|
|
'intermittent',
|
|
'junction',
|
|
'landuse',
|
|
'layer',
|
|
'leisure',
|
|
'lock',
|
|
'man_made',
|
|
'military',
|
|
'motorcar',
|
|
'name',
|
|
'natural',
|
|
'office',
|
|
'oneway',
|
|
'operator',
|
|
'place',
|
|
'population',
|
|
'power',
|
|
'power_source',
|
|
'public_transport',
|
|
'railway',
|
|
'ref',
|
|
'religion',
|
|
'route',
|
|
'service',
|
|
'shop',
|
|
'sport',
|
|
'surface',
|
|
'toll',
|
|
'tourism',
|
|
'tower:type',
|
|
'tracktype',
|
|
'tunnel',
|
|
'water',
|
|
'waterway',
|
|
'wetland',
|
|
'width',
|
|
'wood',
|
|
'abandoned:aeroway',
|
|
'abandoned:amenity',
|
|
'abandoned:building',
|
|
'abandoned:landuse',
|
|
'abandoned:power',
|
|
'area:highway'
|
|
}
|
|
|
|
-- The following keys will be deleted
|
|
local delete_keys = {
|
|
'attribution',
|
|
'comment',
|
|
'created_by',
|
|
'fixme',
|
|
'note',
|
|
'note:*',
|
|
'odbl',
|
|
'odbl:note',
|
|
'source',
|
|
'source:*',
|
|
'source_ref',
|
|
'way',
|
|
'way_area',
|
|
'z_order',
|
|
}
|
|
|
|
local point_columns = {
|
|
'access',
|
|
'addr:housename',
|
|
'addr:housenumber',
|
|
'addr:interpolation',
|
|
'admin_level',
|
|
'aerialway',
|
|
'aeroway',
|
|
'amenity',
|
|
'area',
|
|
'barrier',
|
|
'bicycle',
|
|
'brand',
|
|
'bridge',
|
|
'boundary',
|
|
'building',
|
|
'capital',
|
|
'construction',
|
|
'covered',
|
|
'culvert',
|
|
'cutting',
|
|
'denomination',
|
|
'disused',
|
|
'ele',
|
|
'embankment',
|
|
'foot',
|
|
'generator:source',
|
|
'harbour',
|
|
'highway',
|
|
'historic',
|
|
'horse',
|
|
'intermittent',
|
|
'junction',
|
|
'landuse',
|
|
'layer',
|
|
'leisure',
|
|
'lock',
|
|
'man_made',
|
|
'military',
|
|
'motorcar',
|
|
'name',
|
|
'natural',
|
|
'office',
|
|
'oneway',
|
|
'operator',
|
|
'place',
|
|
'population',
|
|
'power',
|
|
'power_source',
|
|
'public_transport',
|
|
'railway',
|
|
'ref',
|
|
'religion',
|
|
'route',
|
|
'service',
|
|
'shop',
|
|
'sport',
|
|
'surface',
|
|
'toll',
|
|
'tourism',
|
|
'tower:type',
|
|
'tunnel',
|
|
'water',
|
|
'waterway',
|
|
'wetland',
|
|
'width',
|
|
'wood',
|
|
}
|
|
|
|
local non_point_columns = {
|
|
'access',
|
|
'addr:housename',
|
|
'addr:housenumber',
|
|
'addr:interpolation',
|
|
'admin_level',
|
|
'aerialway',
|
|
'aeroway',
|
|
'amenity',
|
|
'area',
|
|
'barrier',
|
|
'bicycle',
|
|
'brand',
|
|
'bridge',
|
|
'boundary',
|
|
'building',
|
|
'construction',
|
|
'covered',
|
|
'culvert',
|
|
'cutting',
|
|
'denomination',
|
|
'disused',
|
|
'embankment',
|
|
'foot',
|
|
'generator:source',
|
|
'harbour',
|
|
'highway',
|
|
'historic',
|
|
'horse',
|
|
'intermittent',
|
|
'junction',
|
|
'landuse',
|
|
'layer',
|
|
'leisure',
|
|
'lock',
|
|
'man_made',
|
|
'military',
|
|
'motorcar',
|
|
'name',
|
|
'natural',
|
|
'office',
|
|
'oneway',
|
|
'operator',
|
|
'place',
|
|
'population',
|
|
'power',
|
|
'power_source',
|
|
'public_transport',
|
|
'railway',
|
|
'ref',
|
|
'religion',
|
|
'route',
|
|
'service',
|
|
'shop',
|
|
'sport',
|
|
'surface',
|
|
'toll',
|
|
'tourism',
|
|
'tower:type',
|
|
'tracktype',
|
|
'tunnel',
|
|
'water',
|
|
'waterway',
|
|
'wetland',
|
|
'width',
|
|
'wood',
|
|
}
|
|
|
|
local function gen_columns(text_columns, with_hstore, area, geometry_type)
|
|
local columns = {}
|
|
|
|
local add_column = function (name, type)
|
|
columns[#columns + 1] = { column = name, type = type }
|
|
end
|
|
|
|
for _, c in ipairs(text_columns) do
|
|
add_column(c, 'text')
|
|
end
|
|
|
|
add_column('z_order', 'int')
|
|
|
|
if area then
|
|
add_column('way_area', 'real')
|
|
end
|
|
|
|
if hstore_column then
|
|
add_column(hstore_column, 'hstore')
|
|
end
|
|
|
|
if with_hstore then
|
|
add_column('tags', 'hstore')
|
|
end
|
|
|
|
add_column('way', geometry_type)
|
|
columns[#columns].projection = srid
|
|
columns[#columns].not_null = true
|
|
|
|
return columns
|
|
end
|
|
|
|
local tables = {}
|
|
|
|
tables.point = osm2pgsql.define_table{
|
|
name = prefix .. '_point',
|
|
ids = { type = 'node', id_column = 'osm_id' },
|
|
columns = gen_columns(point_columns, hstore or hstore_all, false, 'point')
|
|
}
|
|
|
|
tables.line = osm2pgsql.define_table{
|
|
name = prefix .. '_line',
|
|
ids = { type = 'way', id_column = 'osm_id' },
|
|
columns = gen_columns(non_point_columns, hstore or hstore_all, true, 'linestring')
|
|
}
|
|
|
|
tables.polygon = osm2pgsql.define_table{
|
|
name = prefix .. '_polygon',
|
|
ids = { type = 'area', id_column = 'osm_id' },
|
|
columns = gen_columns(non_point_columns, hstore or hstore_all, true, 'geometry')
|
|
}
|
|
|
|
tables.roads = osm2pgsql.define_table{
|
|
name = prefix .. '_roads',
|
|
ids = { type = 'way', id_column = 'osm_id' },
|
|
columns = gen_columns(non_point_columns, hstore or hstore_all, true, 'linestring')
|
|
}
|
|
|
|
local z_order_lookup = {
|
|
proposed = {1, false},
|
|
construction = {2, false},
|
|
steps = {10, false},
|
|
cycleway = {10, false},
|
|
bridleway = {10, false},
|
|
footway = {10, false},
|
|
path = {10, false},
|
|
track = {11, false},
|
|
service = {15, false},
|
|
|
|
tertiary_link = {24, false},
|
|
secondary_link = {25, true},
|
|
primary_link = {27, true},
|
|
trunk_link = {28, true},
|
|
motorway_link = {29, true},
|
|
|
|
raceway = {30, false},
|
|
pedestrian = {31, false},
|
|
living_street = {32, false},
|
|
road = {33, false},
|
|
unclassified = {33, false},
|
|
residential = {33, false},
|
|
tertiary = {34, false},
|
|
secondary = {36, true},
|
|
primary = {37, true},
|
|
trunk = {38, true},
|
|
motorway = {39, true}
|
|
}
|
|
|
|
local function as_bool(value)
|
|
return value == 'yes' or value == 'true' or value == '1'
|
|
end
|
|
|
|
local function get_z_order(tags)
|
|
local z_order = 100 * math.floor(tonumber(tags.layer or '0') or 0)
|
|
local roads = false
|
|
|
|
local highway = tags['highway']
|
|
if highway then
|
|
local r = z_order_lookup[highway] or {0, false}
|
|
z_order = z_order + r[1]
|
|
roads = r[2]
|
|
end
|
|
|
|
if tags.railway then
|
|
z_order = z_order + 35
|
|
roads = true
|
|
end
|
|
|
|
if tags.boundary and tags.boundary == 'administrative' then
|
|
roads = true
|
|
end
|
|
|
|
if as_bool(tags.bridge) then
|
|
z_order = z_order + 100
|
|
end
|
|
|
|
if as_bool(tags.tunnel) then
|
|
z_order = z_order - 100
|
|
end
|
|
|
|
return z_order, roads
|
|
end
|
|
|
|
local function make_check_in_list_func(list)
|
|
local h = {}
|
|
for _, k in ipairs(list) do
|
|
h[k] = true
|
|
end
|
|
return function(tags)
|
|
for k, _ in pairs(tags) do
|
|
if h[k] then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
end
|
|
|
|
local is_polygon = make_check_in_list_func(polygon_keys)
|
|
local clean_tags = osm2pgsql.make_clean_tags_func(delete_keys)
|
|
|
|
local function make_column_hash(columns)
|
|
local h = {}
|
|
|
|
for _, k in ipairs(columns) do
|
|
h[k] = true
|
|
end
|
|
|
|
return h
|
|
end
|
|
|
|
local function make_get_output(columns)
|
|
local h = make_column_hash(columns)
|
|
if hstore_all then
|
|
return function(tags)
|
|
local output = {}
|
|
local hstore_entries = {}
|
|
|
|
for k, _ in pairs(tags) do
|
|
if h[k] then
|
|
output[k] = tags[k]
|
|
end
|
|
hstore_entries[k] = tags[k]
|
|
end
|
|
|
|
return output, hstore_entries
|
|
end
|
|
else
|
|
return function(tags)
|
|
local output = {}
|
|
local hstore_entries = {}
|
|
|
|
for k, _ in pairs(tags) do
|
|
if h[k] then
|
|
output[k] = tags[k]
|
|
else
|
|
hstore_entries[k] = tags[k]
|
|
end
|
|
end
|
|
|
|
return output, hstore_entries
|
|
end
|
|
end
|
|
end
|
|
|
|
local has_generic_tag = make_check_in_list_func(generic_keys)
|
|
|
|
local get_point_output = make_get_output(point_columns)
|
|
local get_non_point_output = make_get_output(non_point_columns)
|
|
|
|
local function get_hstore_column(tags)
|
|
local len = #hstore_column
|
|
local h = {}
|
|
for k, v in pairs(tags) do
|
|
if k:sub(1, len) == hstore_column then
|
|
h[k:sub(len + 1)] = v
|
|
end
|
|
end
|
|
|
|
if next(h) then
|
|
return h
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function osm2pgsql.process_node(object)
|
|
if clean_tags(object.tags) then
|
|
return
|
|
end
|
|
|
|
local output
|
|
local output_hstore = {}
|
|
if hstore or hstore_all then
|
|
output, output_hstore = get_point_output(object.tags)
|
|
if not next(output) and not next(output_hstore) then
|
|
return
|
|
end
|
|
if hstore_match_only and not has_generic_tag(object.tags) then
|
|
return
|
|
end
|
|
else
|
|
output = object.tags
|
|
if not has_generic_tag(object.tags) then
|
|
return
|
|
end
|
|
end
|
|
|
|
output.tags = output_hstore
|
|
|
|
if hstore_column then
|
|
output[hstore_column] = get_hstore_column(object.tags)
|
|
end
|
|
|
|
output.way = object:as_point()
|
|
tables.point:insert(output)
|
|
end
|
|
|
|
local function add_line(output, geom, roads)
|
|
for sgeom in geom:segmentize(max_length):geometries() do
|
|
output.way = sgeom
|
|
tables.line:insert(output)
|
|
if roads then
|
|
tables.roads:insert(output)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function compute_geom_and_area(geom)
|
|
local area, projected_geom
|
|
|
|
projected_geom = geom:transform(srid)
|
|
|
|
if reproject_area and srid ~= 3857 then
|
|
area = geom:transform(3857):area()
|
|
else
|
|
area = projected_geom:area()
|
|
end
|
|
|
|
return projected_geom, area
|
|
end
|
|
|
|
function osm2pgsql.process_way(object)
|
|
if clean_tags(object.tags) then
|
|
return
|
|
end
|
|
|
|
local add_area = false
|
|
if object.tags.natural == 'coastline' then
|
|
add_area = true
|
|
if not keep_coastlines then
|
|
object.tags.natural = nil
|
|
end
|
|
end
|
|
|
|
local output
|
|
local output_hstore = {}
|
|
if hstore or hstore_all then
|
|
output, output_hstore = get_non_point_output(object.tags)
|
|
if not next(output) and not next(output_hstore) then
|
|
return
|
|
end
|
|
if hstore_match_only and not has_generic_tag(object.tags) then
|
|
return
|
|
end
|
|
if add_area and hstore_all then
|
|
output_hstore.area = 'yes'
|
|
end
|
|
else
|
|
output = object.tags
|
|
if not has_generic_tag(object.tags) then
|
|
return
|
|
end
|
|
end
|
|
|
|
local polygon
|
|
local area_tag = object.tags.area
|
|
if area_tag == 'yes' or area_tag == '1' or area_tag == 'true' then
|
|
polygon = true
|
|
elseif area_tag == 'no' or area_tag == '0' or area_tag == 'false' then
|
|
polygon = false
|
|
else
|
|
polygon = is_polygon(object.tags)
|
|
end
|
|
|
|
if add_area then
|
|
output.area = 'yes'
|
|
polygon = true
|
|
end
|
|
|
|
local z_order, roads = get_z_order(object.tags)
|
|
output.z_order = z_order
|
|
|
|
output.tags = output_hstore
|
|
|
|
if hstore_column then
|
|
output[hstore_column] = get_hstore_column(object.tags)
|
|
end
|
|
|
|
if polygon and object.is_closed then
|
|
local pgeom, area = compute_geom_and_area(object:as_polygon())
|
|
output.way = pgeom
|
|
output.way_area = area
|
|
tables.polygon:insert(output)
|
|
else
|
|
add_line(output, object:as_linestring(), roads)
|
|
end
|
|
end
|
|
|
|
function osm2pgsql.process_relation(object)
|
|
if clean_tags(object.tags) then
|
|
return
|
|
end
|
|
|
|
local rtype = object:grab_tag('type')
|
|
if (rtype ~= 'route') and (rtype ~= 'multipolygon') and (rtype ~= 'boundary') then
|
|
return
|
|
end
|
|
|
|
local output
|
|
local output_hstore = {}
|
|
if hstore or hstore_all then
|
|
output, output_hstore = get_non_point_output(object.tags)
|
|
if not next(output) and not next(output_hstore) then
|
|
return
|
|
end
|
|
if hstore_match_only and not has_generic_tag(object.tags) then
|
|
return
|
|
end
|
|
else
|
|
output = object.tags
|
|
if not has_generic_tag(object.tags) then
|
|
return
|
|
end
|
|
end
|
|
|
|
if not next(output) and not next(output_hstore) then
|
|
return
|
|
end
|
|
|
|
if enable_legacy_route_processing and (hstore or hstore_all) and rtype == 'route' then
|
|
if not object.tags.route_name then
|
|
output_hstore.route_name = object.tags.name
|
|
end
|
|
|
|
local state = object.tags.state
|
|
if state ~= 'alternate' and state ~= 'connection' then
|
|
state = 'yes'
|
|
end
|
|
|
|
local network = object.tags.network
|
|
if network == 'lcn' then
|
|
output_hstore.lcn = output_hstore.lcn or state
|
|
output_hstore.lcn_ref = output_hstore.lcn_ref or object.tags.ref
|
|
elseif network == 'rcn' then
|
|
output_hstore.rcn = output_hstore.rcn or state
|
|
output_hstore.rcn_ref = output_hstore.rcn_ref or object.tags.ref
|
|
elseif network == 'ncn' then
|
|
output_hstore.ncn = output_hstore.ncn or state
|
|
output_hstore.ncn_ref = output_hstore.ncn_ref or object.tags.ref
|
|
elseif network == 'lwn' then
|
|
output_hstore.lwn = output_hstore.lwn or state
|
|
output_hstore.lwn_ref = output_hstore.lwn_ref or object.tags.ref
|
|
elseif network == 'rwn' then
|
|
output_hstore.rwn = output_hstore.rwn or state
|
|
output_hstore.rwn_ref = output_hstore.rwn_ref or object.tags.ref
|
|
elseif network == 'nwn' then
|
|
output_hstore.nwn = output_hstore.nwn or state
|
|
output_hstore.nwn_ref = output_hstore.nwn_ref or object.tags.ref
|
|
end
|
|
|
|
local pc = object.tags.preferred_color
|
|
if pc == '0' or pc == '1' or pc == '2' or pc == '3' or pc == '4' then
|
|
output_hstore.route_pref_color = pc
|
|
else
|
|
output_hstore.route_pref_color = '0'
|
|
end
|
|
end
|
|
|
|
local make_boundary = false
|
|
local make_polygon = false
|
|
if rtype == 'boundary' then
|
|
make_boundary = true
|
|
elseif rtype == 'multipolygon' and object.tags.boundary then
|
|
make_boundary = true
|
|
elseif rtype == 'multipolygon' then
|
|
make_polygon = true
|
|
end
|
|
|
|
local z_order, roads = get_z_order(object.tags)
|
|
output.z_order = z_order
|
|
|
|
output.tags = output_hstore
|
|
|
|
if hstore_column then
|
|
output[hstore_column] = get_hstore_column(object.tags)
|
|
end
|
|
|
|
if not make_polygon then
|
|
add_line(output, object:as_multilinestring(), roads)
|
|
end
|
|
|
|
if make_boundary or make_polygon then
|
|
local geom = object:as_multipolygon()
|
|
|
|
if multi_geometry then
|
|
local pgeom, area = compute_geom_and_area(geom)
|
|
output.way = pgeom
|
|
output.way_area = area
|
|
tables.polygon:insert(output)
|
|
else
|
|
for sgeom in geom:geometries() do
|
|
local pgeom, area = compute_geom_and_area(sgeom)
|
|
output.way = pgeom
|
|
output.way_area = area
|
|
tables.polygon:insert(output)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|