Skip to content

Commit fa2e3b1

Browse files
committed
Fix shortbread boundary processing in regards to disputed boundaries
The way disputed boundaries are implemented was not correct. Generally boundaries should be processed as if disputed boundaries do not exists. But then boundary lines are flagged as disputed if they are created from ways * that have the tag disputed=yes, or * that are in a relation tagged boundary=disputed with no admin_level set or an admin_level smaller or equal to the admin_level that the boundary line has (which is the smallest of any boundary relation the way is a member of) Note that the relation that marks a way as disputed is not the same relation that marks a way as part of some specific admin boundary. The first is tagged boundary=disputed, the second is tagged boundary=administrative. This is based on the work in #10 but rewrites the code to be (hopefully) easier to understand. Note that this only fixes the version for shortbread_v1, the version for shortbread_v1_gen also needs updating which will come later.
1 parent d3d9d0b commit fa2e3b1

File tree

1 file changed

+53
-31
lines changed

1 file changed

+53
-31
lines changed

themes/shortbread_v1/topics/boundaries.lua

+53-31
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ themepark:add_table{
1212
ids_type = 'way',
1313
geom = 'linestring',
1414
columns = themepark:columns({
15-
{ column = 'admin_level', type = 'int' },
15+
{ column = 'admin_level', type = 'int', not_null = true },
1616
{ column = 'maritime', type = 'bool' },
1717
{ column = 'disputed', type = 'bool' },
1818
}),
@@ -29,27 +29,33 @@ themepark:add_table{
2929
}
3030
}
3131

32-
local rinfos = {}
32+
-- ---------------------------------------------------------------------------
33+
-- Storage of information from boundary relations for use by boundary ways
34+
-- (two-stage processing).
35+
36+
-- Minimum admin level of all relations that reference a way id
37+
local min_admin_level = {}
38+
39+
-- Minimum admin level of all relations tagged boundary=disputed that
40+
-- reference a way id
41+
local min_disputed_admin_level = {}
3342

3443
-- ---------------------------------------------------------------------------
3544

36-
-- Check if this looks like a boundary and return admin_level as number
37-
-- Return nil if this is not a valid boundary.
38-
local function get_admin_level(tags)
39-
local type = tags.type
45+
-- Shortbread is only interested in level 2 and level 4 admin boundaries.
46+
local function is_admin_boundary(tags)
47+
return (tags.type == 'boundary' or tags.type == 'multipolygon')
48+
and tags.boundary == 'administrative'
49+
and (tags.admin_level == '2' or tags.admin_level == '4')
50+
end
4051

41-
if type == 'boundary' or type == 'multipolygon' then
42-
local boundary = tags.boundary
43-
if boundary == 'administrative' or boundary == 'disputed' then
44-
return tonumber(tags.admin_level)
45-
end
52+
-- Get numerical admin level from string, default to 1 if invalid
53+
local function get_admin_level(value)
54+
if not value or not string.match(value, '^[1-9][0-9]?$') then
55+
return 1
4656
end
47-
end
4857

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

5561
-- ---------------------------------------------------------------------------
@@ -59,45 +65,61 @@ themepark:add_proc('way', function(object, data)
5965
return
6066
end
6167

62-
local info = rinfos[object.id]
63-
if not info then
68+
local admin_level = min_admin_level[object.id]
69+
if not admin_level then
6470
return
6571
end
6672

6773
local t = object.tags
74+
75+
-- Set disputed flag either from disputed tag on the way...
76+
local disputed = (t.disputed == 'yes')
77+
78+
-- .. or from a parent relation with boundary=disputed
79+
if min_disputed_admin_level[object.id] and min_disputed_admin_level[object.id] <= admin_level then
80+
disputed = true
81+
end
82+
6883
local a = {
69-
admin_level = info.admin_level,
84+
admin_level = admin_level,
7085
maritime = (t.maritime and (t.maritime == 'yes' or t.natural == 'coastline')),
71-
disputed = info.disputed or (t.disputed and t.disputed == 'yes'),
86+
disputed = disputed,
7287
geom = object:as_linestring()
7388
}
7489

7590
themepark:insert('boundaries', a, t)
7691
end)
7792

7893
themepark:add_proc('select_relation_members', function(relation)
79-
if valid_admin_level(get_admin_level(relation.tags)) then
94+
if is_admin_boundary(relation.tags) then
8095
return { ways = osm2pgsql.way_member_ids(relation) }
8196
end
8297
end)
8398

8499
themepark:add_proc('relation', function(object, data)
85-
local t = object.tags
100+
if is_admin_boundary(object.tags) then
101+
local admin_level = tonumber(object.tags.admin_level)
86102

87-
local admin_level = get_admin_level(t)
103+
for _, id in ipairs(osm2pgsql.way_member_ids(object)) do
104+
if not min_admin_level[id] or min_admin_level[id] > admin_level then
105+
min_admin_level[id] = admin_level
106+
end
107+
end
88108

89-
if not valid_admin_level(admin_level) then
90109
return
91110
end
92111

93-
for _, member in ipairs(object.members) do
94-
if member.type == 'w' then
95-
if not rinfos[member.ref] then
96-
rinfos[member.ref] = { admin_level = admin_level }
97-
elseif rinfos[member.ref].admin_level > admin_level then
98-
rinfos[member.ref].admin_level = admin_level
112+
if object.tags.boundary == 'disputed' then
113+
-- Ways in relations tagged boundary=disputed are flagged as disputed
114+
-- if either the relation doesn't have an admin_level tag or the
115+
-- admin_level tag is <= the admin level the way got from the
116+
-- boundary=administrative relation(s).
117+
local admin_level = get_admin_level(object.tags.admin_level)
118+
119+
for _, id in ipairs(osm2pgsql.way_member_ids(object)) do
120+
if not min_disputed_admin_level[id] or min_disputed_admin_level[id] > admin_level then
121+
min_disputed_admin_level[id] = admin_level
99122
end
100-
rinfos[member.ref].disputed = (t.boundary == 'disputed')
101123
end
102124
end
103125
end)

0 commit comments

Comments
 (0)