Skip to content

Commit

Permalink
Remove support for old-style multipolygons
Browse files Browse the repository at this point in the history
  • Loading branch information
pnorman committed Apr 16, 2017
1 parent 10e1cd1 commit cb23299
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 118 deletions.
115 changes: 12 additions & 103 deletions openstreetmap-carto.lua
Expand Up @@ -340,34 +340,6 @@ function filter_tags_way (keyvalues, numberofkeys)
end

--- Handling for relation members and multipolygon generation
-- Multipolygons are either old-style or new-style. As defined here,
-- a new-style MP is one with any tags other than type on the relation, and for
-- them the tags of the ways do not matter.
--
-- An old-style MP is one where the only tag on the relation is
-- type=multipolygon and the tags of all the members are either the same or
-- empty.
--
-- These are stricter definitions then have been used in the past by the C
-- transforms, but cut down on bugs where a new-style MP suddenly gets treated
-- as an old-style MP.
--
-- This has a few properties
--
-- - MP generation does not depend on polygon characteristics of tags on ways
--
-- - All tags are considered, except for deleted tags which are ignored for
-- technical reasons
--
-- - Any new-style MP will never change to an old-style MP by only changing
-- tags on its member ways, nor will it become invalid
--
-- - Any old-style MP will never change to an new-style MP by only changing
-- tags on its member ways, but may become invalid if the tags become
-- conflicting
--
-- - All multipolygons are polygons
--
-- @param keyvalues OSM tags, after processing by relation transform
-- @param keyvaluemembers OSM tags of relation members, after processing by way transform
-- @param roles OSM roles of relation members
Expand All @@ -386,51 +358,25 @@ function filter_tags_relation_member (keyvalues, keyvaluemembers, roles, memberc
-- Remove type key
keyvalues["type"] = nil

-- Boundary relations are treated as linestring
-- Filter out relations with just a type tag or no tags
if next(keyvalues) == nil then
return 1, keyvalues, members_superseded, 0, 0, 0
end

if type == "boundary" or (type == "multipolygon" and keyvalues["boundary"]) then
-- Avoid generating objects for untagged boundary relations
if next(keyvalues) ~= nil then
keyvalues.z_order = z_order(keyvalues)
return 0, keyvalues, members_superseded, 1, 0, roads(keyvalues)
end
keyvalues.z_order = z_order(keyvalues)
return 0, keyvalues, members_superseded, 1, 0, roads(keyvalues)
-- For multipolygons...
elseif (type == "multipolygon") then
-- Multipolygons by definition are polygons, so we know roads = linestring = 0, polygon = 1
-- The type tag has been removed, so this checks for untagged MPs
if next(keyvalues) == nil then
-- This is an old-style MP
local combined_tags = combine_member_tags(keyvaluemembers)
if combined_tags == nil then
-- This is an invalid old-style MP with conflicting tags
return 1, {}, members_superseded, 0, 1, 0
elseif next(combined_tags) == nil then
-- This is a valid old-style MP, but has no tags
return 1, {}, members_superseded, 0, 1, 0
else
-- This is a valid old-style MP because a set of tags could be
-- made. For each member, the POLYGON its way tags generated is
-- superseded by the geometry from the MP, or the way was untagged.
-- Untagged ways generate no geom, so can be superseded too.
for i = 1, membercount do
members_superseded[i] = 1
end
combined_tags.z_order = z_order(keyvalues)
return 0, combined_tags, members_superseded, 0, 1, 0
end
else
-- This is a new-style MP
keyvalues.z_order = z_order(keyvalues)
return 0, keyvalues, members_superseded, 0, 1, 0
end
assert(false, "End of control reached prematurely for MP")
keyvalues.z_order = z_order(keyvalues)
return 0, keyvalues, members_superseded, 0, 1, 0
elseif type == "route" then
if next(keyvalues) ~= nil then
keyvalues.z_order = z_order(keyvalues)
return 0, keyvalues, members_superseded, 1, 0, roads(keyvalues)
end
keyvalues.z_order = z_order(keyvalues)
return 0, keyvalues, members_superseded, 1, 0, roads(keyvalues)
end

-- Untagged or unknown type
-- Unknown type of relation or no type tag
return 1, keyvalues, members_superseded, 0, 0, 0
end

Expand Down Expand Up @@ -468,43 +414,6 @@ function is_in (needle, haystack)
return false
end

--- compare two tables.
-- @param t1 A table
-- @param t2 A table
-- @return true or false
function equaltables (t1,t2)
for k, v in pairs(t1) do
if t2[k] ~= v then return false end
end
for k, v in pairs(t2) do
if t1[k] ~= v then return false end
end
return true
end

--- Combines the tags of relation members
-- If the tags are conflicting then nil is returned. Members with no tags are ignored
-- @param member_tags OSM tags of relation members
-- @return combined tags, or nil if cannot combine
function combine_member_tags (member_tags)
local combined_tags = {}
for _, tags in ipairs(member_tags) do
-- Check if the member has tags
if next(tags) ~= nil then
if next(combined_tags) == nil then
-- This is the first tagged member
combined_tags = tags
else
-- A different tagged member
if not equaltables(tags, combined_tags) then
return nil
end
end
end
end
return combined_tags
end

--- Normalizes layer tags
-- @param v The layer tag value
-- @return An integer for the layer tag
Expand Down
33 changes: 18 additions & 15 deletions scripts/lua/test.lua
Expand Up @@ -6,6 +6,20 @@ Run it with lua test.lua

require ("openstreetmap-carto")

--- compare two tables.
-- @param t1 A table
-- @param t2 A table
-- @return true or false
function equaltables (t1,t2)
for k, v in pairs(t1) do
if t2[k] ~= v then return false end
end
for k, v in pairs(t2) do
if t1[k] ~= v then return false end
end
return true
end

This comment has been minimized.

Copy link
@pnorman

pnorman Apr 20, 2017

Author Collaborator

I'm not sure why this showed up in the diff.

print("TESTING: z_order")

assert(z_order({}) == nil, "test failed: no tags")
Expand Down Expand Up @@ -53,17 +67,6 @@ assert(equaltables(({filter_tags_generic({["note:xx"]="foo", foo="bar"})})[2], {
assert(({filter_tags_generic({["foo:note:xx"]="foo"})})[1] == 0, "prefix later in tag filter")
assert(equaltables(({filter_tags_generic({["foo:note:xx"]="foo"})})[2], {["foo:note:xx"]="foo"}), "prefix later in tag tags")

-- yay multipolygons?
print("TESTING: combine_member_tags")
assert(equaltables(combine_member_tags({}), {}), "test failed: no members")
assert(equaltables(combine_member_tags({{}}), {}), "test failed: no member tags")
assert(equaltables(combine_member_tags({{}, {}}), {}), "test failed: no member tags, two members")
assert(equaltables(combine_member_tags({{foo="bar"}}), {foo="bar"}), "test failed: one member, tags")
assert(equaltables(combine_member_tags({{foo="bar"}, {}}), {foo="bar"}), "test failed: two members, tags on first")
assert(equaltables(combine_member_tags({{}, {foo="bar"}}), {foo="bar"}), "test failed: two members, tags on second")
assert(equaltables(combine_member_tags({{foo="bar"}, {foo="bar"}}), {foo="bar"}), "test failed: two members, tags on both")
assert(combine_member_tags({{foo="bar"}, {baz="qax"}}) == nil, "test failed: two members, different tags")

print("TESTING: filter_tags_relation_member")

--- Tests filter_tags_relation_member against expected values
Expand Down Expand Up @@ -118,7 +121,7 @@ end
assert(check_rel_member({}, {}, 1, {}, {}, 0, 0, 0), "test failed: untagged memberless relation")
assert(check_rel_member({}, {{}}, 1, {}, {0}, 0, 0, 0), "test failed: untagged relation")

assert(check_rel_member({type="multipolygon"}, {{}}, 1, {}, {0}, 0, 1, 0),
assert(check_rel_member({type="multipolygon"}, {{}}, 1, {}, {0}, 0, 0, 0),
"test failed: untagged MP")
assert(check_rel_member({type="multipolygon", foo="bar"}, {{}}, 0, {foo="bar"}, {0}, 0, 1, 0),
"test failed: MP with tag")
Expand All @@ -138,11 +141,11 @@ assert(check_rel_member({type="multipolygon", foo="bar"}, {{foo="bar"}, {baz="qa
"test failed: MP with tag, way with same tag")

-- Old-style MPs
assert(check_rel_member({type="multipolygon"}, {{foo="bar"}}, 0, {foo="bar"}, {1}, 0, 1, 0),
assert(check_rel_member({type="multipolygon"}, {{foo="bar"}}, 1, {}, {0}, 0, 0, 0),
"test failed: MP w/o tag, way with tag")
assert(check_rel_member({type="multipolygon"}, {{foo="bar"}, {}}, 0, {foo="bar"}, {1,1}, 0, 1, 0),
assert(check_rel_member({type="multipolygon"}, {{foo="bar"}, {}}, 1, {}, {0,0}, 0, 0, 0),
"test failed: MP w/o tag, way with tag + untagged way")
assert(check_rel_member({type="multipolygon"}, {{foo="bar"}, {baz="qax"}}, 1, {}, {0,0}, 0, 1, 0),
assert(check_rel_member({type="multipolygon"}, {{foo="bar"}, {baz="qax"}}, 1, {}, {0,0}, 0, 0, 0),
"test failed: MP w/o tag, way with tag + way with other tag")

-- Boundary relations
Expand Down

0 comments on commit cb23299

Please sign in to comment.