|
| 1 | +-- --------------------------------------------------------------------------- |
| 2 | +-- |
| 3 | +-- Theme: explore |
| 4 | +-- Topic: admin_boundaries |
| 5 | +-- |
| 6 | +-- --------------------------------------------------------------------------- |
| 7 | + |
| 8 | +local themepark, theme, cfg = ... |
| 9 | + |
| 10 | +themepark:add_table({ |
| 11 | + name = 'admin_boundaries_ways', |
| 12 | + ids_type = 'way', |
| 13 | + geom = 'linestring', |
| 14 | + columns = themepark:columns({ |
| 15 | + { column = 'admin_level', type = 'int' }, |
| 16 | + { column = 'min_admin_level', type = 'int' }, |
| 17 | + { column = 'border_type', type = 'text' }, |
| 18 | + { column = 'maritime', type = 'bool' }, |
| 19 | + { column = 'coastline', type = 'bool' }, |
| 20 | + { column = 'disputed_on_way', type = 'text' }, |
| 21 | + { column = 'disputed', type = 'bool' }, |
| 22 | + { column = 'is_rel_member', type = 'bool' }, |
| 23 | + }), |
| 24 | +}) |
| 25 | + |
| 26 | + |
| 27 | +themepark:add_table({ |
| 28 | + name = 'admin_boundaries_relations', |
| 29 | + ids_type = 'relation', |
| 30 | + geom = 'multilinestring', |
| 31 | + columns = themepark:columns({ |
| 32 | + { column = 'admin_level', type = 'int' }, |
| 33 | + { column = 'type', type = 'text' }, |
| 34 | + { column = 'border_type', type = 'text' }, |
| 35 | + { column = 'wikidata', type = 'text' }, |
| 36 | + { column = 'maritime', type = 'bool' }, |
| 37 | + { column = 'disputed', type = 'bool' }, |
| 38 | + }), |
| 39 | +}) |
| 40 | + |
| 41 | +themepark:add_table({ |
| 42 | + name = 'admin_boundaries_areas', |
| 43 | + ids_type = 'relation', |
| 44 | + geom = 'multipolygon', |
| 45 | + columns = themepark:columns({ |
| 46 | + { column = 'admin_level', type = 'int' }, |
| 47 | + { column = 'type', type = 'text' }, |
| 48 | + { column = 'border_type', type = 'text' }, |
| 49 | + { column = 'wikidata', type = 'text' }, |
| 50 | + { column = 'maritime', type = 'bool' }, |
| 51 | + { column = 'disputed', type = 'bool' }, |
| 52 | + }), |
| 53 | +}) |
| 54 | + |
| 55 | +themepark:add_table({ |
| 56 | + name = 'admin_boundaries_errors', |
| 57 | + ids_type = 'any', |
| 58 | + geom = 'multilinestring', |
| 59 | + columns = { |
| 60 | + { column = 'errormsg', type = 'text', not_null = true }, |
| 61 | + { column = 'value', type = 'text' }, |
| 62 | + }, |
| 63 | +}) |
| 64 | + |
| 65 | +-- --------------------------------------------------------------------------- |
| 66 | +-- Storage of information from boundary relations for use by boundary ways |
| 67 | +-- (two-stage processing). |
| 68 | + |
| 69 | +-- Minimum admin level of all relations that reference a way id |
| 70 | +local min_admin_level = {} |
| 71 | + |
| 72 | +-- Minimum admin level of all relations tagged boundary=disputed that |
| 73 | +-- reference a way id |
| 74 | +local min_disputed_admin_level = {} |
| 75 | + |
| 76 | +-- --------------------------------------------------------------------------- |
| 77 | + |
| 78 | +-- Get numerical admin level from string |
| 79 | +local function get_admin_level(value) |
| 80 | + if not value or not string.match(value, '^[1-9][0-9]?$') then |
| 81 | + return nil |
| 82 | + end |
| 83 | + |
| 84 | + return tonumber(value) |
| 85 | +end |
| 86 | + |
| 87 | +local function add_error(msg, value, geom, tags) |
| 88 | + themepark:insert('admin_boundaries_errors', { |
| 89 | + errormsg = msg, |
| 90 | + value = value, |
| 91 | + geom = geom, |
| 92 | + }, tags) |
| 93 | +end |
| 94 | + |
| 95 | +-- --------------------------------------------------------------------------- |
| 96 | + |
| 97 | +themepark:add_proc('way', function(object, data) |
| 98 | + local t = object.tags |
| 99 | + |
| 100 | + if osm2pgsql.stage == 1 and not (t.boundary == 'administrative' or t.boundary == 'disputed') then |
| 101 | + return |
| 102 | + end |
| 103 | + |
| 104 | + local min_admin_level_from_rels = min_admin_level[object.id] or 1 |
| 105 | + |
| 106 | + -- Set disputed flag either from disputed or boundary tag on the way... |
| 107 | + local disputed = (t.disputed == 'yes' or t.boundary == 'disputed') |
| 108 | + |
| 109 | + -- .. or from a parent relation with boundary=disputed |
| 110 | + if osm2pgsql.stage == 2 |
| 111 | + and min_disputed_admin_level[object.id] |
| 112 | + and min_disputed_admin_level[object.id] <= min_admin_level_from_rels then |
| 113 | + disputed = true |
| 114 | + end |
| 115 | + |
| 116 | + local a = { |
| 117 | + admin_level = t.admin_level, |
| 118 | + border_type = t.border_type, |
| 119 | + maritime = (t.maritime == 'yes'), |
| 120 | + coastline = (t.natural == 'coastline'), |
| 121 | + disputed_on_way = t.disputed, |
| 122 | + disputed = disputed, |
| 123 | + min_admin_level = min_admin_level_from_rels, |
| 124 | + is_rel_member = (osm2pgsql.stage == 2), |
| 125 | + geom = object:as_linestring(), |
| 126 | + } |
| 127 | + |
| 128 | + themepark:insert('admin_boundaries_ways', a, t) |
| 129 | +end) |
| 130 | + |
| 131 | +themepark:add_proc('select_relation_members', function(relation) |
| 132 | + if relation.tags.boundary == 'administrative' then |
| 133 | + return { ways = osm2pgsql.way_member_ids(relation) } |
| 134 | + end |
| 135 | +end) |
| 136 | + |
| 137 | +themepark:add_proc('relation', function(object, data) |
| 138 | + local t = object.tags |
| 139 | + |
| 140 | + if t.boundary ~= 'administrative' and t.boundary ~= 'disputed' then |
| 141 | + return |
| 142 | + end |
| 143 | + |
| 144 | + local admin_level = t.admin_level |
| 145 | + local numeric_admin_level = get_admin_level(admin_level) |
| 146 | + |
| 147 | + local geom_multilinestring = object:as_multilinestring() |
| 148 | + local geom_multipolygon = object:as_multipolygon() |
| 149 | + |
| 150 | + if t.type ~= 'boundary' and t.type ~= 'multipolygon' then |
| 151 | + add_error('missing type tag', nil, geom_multilinestring, t) |
| 152 | + end |
| 153 | + |
| 154 | + if t.boundary == 'administrative' and geom_multipolygon:is_null() then |
| 155 | + add_error('not a (multi)polygon', nil, geom_multilinestring, t) |
| 156 | + end |
| 157 | + |
| 158 | + if numeric_admin_level == nil then |
| 159 | + add_error('invalid admin level (not set or not number)', t.admin_level, geom_multilinestring, t) |
| 160 | + elseif numeric_admin_level < 2 or numeric_admin_level > 11 then |
| 161 | + add_error('admin level not between 2 and 11', t.admin_level, geom_multilinestring, t) |
| 162 | + end |
| 163 | + |
| 164 | + if t.maritime and t.maritime ~= 'yes' then |
| 165 | + add_error('invalid maritime tag value', t.maritime, geom_multilinestring, t) |
| 166 | + end |
| 167 | + |
| 168 | + local a = { |
| 169 | + admin_level = numeric_admin_level, |
| 170 | + type = t.type, |
| 171 | + border_type = t.border_type, |
| 172 | + wikidata = t.wikidata, |
| 173 | + maritime = (t.maritime == 'yes'), |
| 174 | + disputed = (t.boundary == 'disputed'), |
| 175 | + } |
| 176 | + |
| 177 | + if geom_multipolygon:is_null() then |
| 178 | + a.geom = geom_multilinestring |
| 179 | + themepark:insert('admin_boundaries_relations', a, t) |
| 180 | + else |
| 181 | + a.geom = geom_multipolygon |
| 182 | + themepark:insert('admin_boundaries_areas', a, t) |
| 183 | + end |
| 184 | + |
| 185 | + if numeric_admin_level == nil then |
| 186 | + return |
| 187 | + end |
| 188 | + |
| 189 | + if t.boundary == 'administrative' then |
| 190 | + for _, id in ipairs(osm2pgsql.way_member_ids(object)) do |
| 191 | + if not min_admin_level[id] or min_admin_level[id] > numeric_admin_level then |
| 192 | + min_admin_level[id] = numeric_admin_level |
| 193 | + end |
| 194 | + end |
| 195 | + elseif t.boundary == 'disputed' then |
| 196 | + -- Ways in relations tagged boundary=disputed are flagged as disputed |
| 197 | + -- if either the relation doesn't have an admin_level tag or the |
| 198 | + -- admin_level tag is <= the admin level the way got from the |
| 199 | + -- boundary=administrative relation(s). |
| 200 | + for _, id in ipairs(osm2pgsql.way_member_ids(object)) do |
| 201 | + if not min_disputed_admin_level[id] or min_disputed_admin_level[id] > numeric_admin_level then |
| 202 | + min_disputed_admin_level[id] = numeric_admin_level |
| 203 | + end |
| 204 | + end |
| 205 | + end |
| 206 | +end) |
| 207 | + |
| 208 | +-- --------------------------------------------------------------------------- |
0 commit comments