Skip to content

Commit 5bbd746

Browse files
authored
Merge pull request #22 from osm2pgsql-dev/shortbread-boundaries
Shortbread boundaries
2 parents 444bfbd + fa2e3b1 commit 5bbd746

File tree

1 file changed

+55
-33
lines changed

1 file changed

+55
-33
lines changed

themes/shortbread_v1/topics/boundaries.lua

+55-33
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ themepark:add_table{
1111
name = 'boundaries',
1212
ids_type = 'way',
1313
geom = 'linestring',
14-
columns = themepark:columns('core/name', {
15-
{ column = 'admin_level', type = 'int' },
14+
columns = themepark:columns({
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
}
74-
themepark.themes.core.add_name(a, object)
89+
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)