Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shortbread boundaries #22

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 55 additions & 33 deletions themes/shortbread_v1/topics/boundaries.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ themepark:add_table{
name = 'boundaries',
ids_type = 'way',
geom = 'linestring',
columns = themepark:columns('core/name', {
{ column = 'admin_level', type = 'int' },
columns = themepark:columns({
{ column = 'admin_level', type = 'int', not_null = true },
{ column = 'maritime', type = 'bool' },
{ column = 'disputed', type = 'bool' },
}),
Expand All @@ -29,27 +29,33 @@ themepark:add_table{
}
}

local rinfos = {}
-- ---------------------------------------------------------------------------
-- Storage of information from boundary relations for use by boundary ways
-- (two-stage processing).

-- Minimum admin level of all relations that reference a way id
local min_admin_level = {}

-- Minimum admin level of all relations tagged boundary=disputed that
-- reference a way id
local min_disputed_admin_level = {}

-- ---------------------------------------------------------------------------

-- Check if this looks like a boundary and return admin_level as number
-- Return nil if this is not a valid boundary.
local function get_admin_level(tags)
local type = tags.type
-- Shortbread is only interested in level 2 and level 4 admin boundaries.
local function is_admin_boundary(tags)
return (tags.type == 'boundary' or tags.type == 'multipolygon')
and tags.boundary == 'administrative'
and (tags.admin_level == '2' or tags.admin_level == '4')
end

if type == 'boundary' or type == 'multipolygon' then
local boundary = tags.boundary
if boundary == 'administrative' or boundary == 'disputed' then
return tonumber(tags.admin_level)
end
-- Get numerical admin level from string, default to 1 if invalid
local function get_admin_level(value)
if not value or not string.match(value, '^[1-9][0-9]?$') then
return 1
end
end

-- Check the (numeric) admin level. Change this depending on which admin
-- levels you want to process. Shortbread only shows 2 and 4.
local function valid_admin_level(level)
return level == 2 or level == 4
return tonumber(value)
end

-- ---------------------------------------------------------------------------
Expand All @@ -59,45 +65,61 @@ themepark:add_proc('way', function(object, data)
return
end

local info = rinfos[object.id]
if not info then
local admin_level = min_admin_level[object.id]
if not admin_level then
return
end

local t = object.tags

-- Set disputed flag either from disputed tag on the way...
local disputed = (t.disputed == 'yes')

-- .. or from a parent relation with boundary=disputed
if min_disputed_admin_level[object.id] and min_disputed_admin_level[object.id] <= admin_level then
disputed = true
end

local a = {
admin_level = info.admin_level,
admin_level = admin_level,
maritime = (t.maritime and (t.maritime == 'yes' or t.natural == 'coastline')),
disputed = info.disputed or (t.disputed and t.disputed == 'yes'),
disputed = disputed,
geom = object:as_linestring()
}
themepark.themes.core.add_name(a, object)

themepark:insert('boundaries', a, t)
end)

themepark:add_proc('select_relation_members', function(relation)
if valid_admin_level(get_admin_level(relation.tags)) then
if is_admin_boundary(relation.tags) then
return { ways = osm2pgsql.way_member_ids(relation) }
end
end)

themepark:add_proc('relation', function(object, data)
local t = object.tags
if is_admin_boundary(object.tags) then
local admin_level = tonumber(object.tags.admin_level)

local admin_level = get_admin_level(t)
for _, id in ipairs(osm2pgsql.way_member_ids(object)) do
if not min_admin_level[id] or min_admin_level[id] > admin_level then
min_admin_level[id] = admin_level
end
end

if not valid_admin_level(admin_level) then
return
end

for _, member in ipairs(object.members) do
if member.type == 'w' then
if not rinfos[member.ref] then
rinfos[member.ref] = { admin_level = admin_level }
elseif rinfos[member.ref].admin_level > admin_level then
rinfos[member.ref].admin_level = admin_level
if object.tags.boundary == 'disputed' then
-- Ways in relations tagged boundary=disputed are flagged as disputed
-- if either the relation doesn't have an admin_level tag or the
-- admin_level tag is <= the admin level the way got from the
-- boundary=administrative relation(s).
local admin_level = get_admin_level(object.tags.admin_level)

for _, id in ipairs(osm2pgsql.way_member_ids(object)) do
if not min_disputed_admin_level[id] or min_disputed_admin_level[id] > admin_level then
min_disputed_admin_level[id] = admin_level
end
rinfos[member.ref].disputed = (t.boundary == 'disputed')
end
end
end)
Expand Down