262 lines
6.6 KiB
Lua
262 lines
6.6 KiB
Lua
-- Profile functions dealing with various aspects of relation parsing
|
|
--
|
|
-- You can run a selection you find useful in your profile,
|
|
-- or do you own processing if/when required.
|
|
|
|
Utils = require('lib/utils')
|
|
|
|
Relations = {}
|
|
|
|
function is_direction(role)
|
|
return (role == 'north' or role == 'south' or role == 'west' or role == 'east')
|
|
end
|
|
|
|
-- match ref values to relations data
|
|
function Relations.match_to_ref(relations, ref)
|
|
|
|
function calculate_scores(refs, tag_value)
|
|
local tag_tokens = Set(Utils.tokenize_common(tag_value))
|
|
local result = {}
|
|
for i, r in ipairs(refs) do
|
|
local ref_tokens = Utils.tokenize_common(r)
|
|
local score = 0
|
|
|
|
for _, t in ipairs(ref_tokens) do
|
|
if tag_tokens[t] then
|
|
if Utils.is_number(t) then
|
|
score = score + 2
|
|
else
|
|
score = score + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
result[r] = score
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
local references = Utils.string_list_tokens(ref)
|
|
local result_match = {}
|
|
local order = {}
|
|
for i, r in ipairs(references) do
|
|
result_match[r] = { forward = nil, backward = nil }
|
|
order[i] = r
|
|
end
|
|
|
|
for i, rel in ipairs(relations) do
|
|
local name_scores = nil
|
|
local name_tokens = {}
|
|
local route_name = rel["route_name"]
|
|
if route_name then
|
|
name_scores = calculate_scores(references, route_name)
|
|
end
|
|
|
|
local ref_scores = nil
|
|
local ref_tokens = {}
|
|
local route_ref = rel["route_ref"]
|
|
if route_ref then
|
|
ref_scores = calculate_scores(references, route_ref)
|
|
end
|
|
|
|
-- merge scores
|
|
local direction = rel["route_direction"]
|
|
if direction then
|
|
local best_score = -1
|
|
local best_ref = nil
|
|
|
|
function find_best(scores)
|
|
if scores then
|
|
for k ,v in pairs(scores) do
|
|
if v > best_score then
|
|
best_ref = k
|
|
best_score = v
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
find_best(name_scores)
|
|
find_best(ref_scores)
|
|
|
|
if best_ref then
|
|
local result_direction = result_match[best_ref]
|
|
|
|
local is_forward = rel["route_forward"]
|
|
if is_forward == nil then
|
|
result_direction.forward = direction
|
|
result_direction.backward = direction
|
|
elseif is_forward == true then
|
|
result_direction.forward = direction
|
|
else
|
|
result_direction.backward = direction
|
|
end
|
|
|
|
result_match[best_ref] = result_direction
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
local result = {}
|
|
for i, r in ipairs(order) do
|
|
result[i] = { ref = r, dir = result_match[r] };
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
function get_direction_from_superrel(rel, relations)
|
|
local result = nil
|
|
local result_id = nil
|
|
local rel_id_list = relations:get_relations(rel)
|
|
|
|
function set_result(direction, current_rel)
|
|
if (result ~= nil) and (direction ~= nil) then
|
|
print('WARNING: relation ' .. rel:id() .. ' is a part of more then one supperrelations ' .. result_id .. ' and ' .. current_rel:id())
|
|
result = nil
|
|
else
|
|
result = direction
|
|
result_id = current_rel:id()
|
|
end
|
|
end
|
|
|
|
for i, rel_id in ipairs(rel_id_list) do
|
|
local parent_rel = relations:relation(rel_id)
|
|
if parent_rel:get_value_by_key('type') == 'route' then
|
|
local role = parent_rel:get_role(rel)
|
|
|
|
if is_direction(role) then
|
|
set_result(role, parent_rel)
|
|
else
|
|
local dir = parent_rel:get_value_by_key('direction')
|
|
if is_direction(dir) then
|
|
set_result(dir, parent_rel)
|
|
end
|
|
end
|
|
end
|
|
-- TODO: support forward/backward
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
function Relations.parse_route_relation(rel, way, relations)
|
|
local t = rel:get_value_by_key("type")
|
|
local role = rel:get_role(way)
|
|
local result = {}
|
|
|
|
function add_extra_data(m)
|
|
local name = rel:get_value_by_key("name")
|
|
if name then
|
|
result['route_name'] = name
|
|
end
|
|
|
|
local ref = rel:get_value_by_key("ref")
|
|
if ref then
|
|
result['route_ref'] = ref
|
|
end
|
|
end
|
|
|
|
if t == 'route' then
|
|
local role_direction = nil
|
|
local route = rel:get_value_by_key("route")
|
|
if route == 'road' then
|
|
-- process case, where directions set as role
|
|
if is_direction(role) then
|
|
role_direction = role
|
|
end
|
|
end
|
|
|
|
local tag_direction = nil
|
|
local direction = rel:get_value_by_key('direction')
|
|
if direction then
|
|
direction = string.lower(direction)
|
|
if is_direction(direction) then
|
|
tag_direction = direction
|
|
end
|
|
end
|
|
|
|
-- determine direction
|
|
local result_direction = role_direction
|
|
if result_direction == nil and tag_direction ~= '' then
|
|
result_direction = tag_direction
|
|
end
|
|
|
|
if role_direction ~= nil and tag_direction ~= nil and role_direction ~= tag_direction then
|
|
result_direction = nil
|
|
print('WARNING: conflict direction in role of way ' .. way:id() .. ' and direction tag in relation ' .. rel:id())
|
|
end
|
|
|
|
|
|
-- process superrelations
|
|
local super_dir = get_direction_from_superrel(rel, relations)
|
|
|
|
-- check if there are data error
|
|
if (result_direction ~= nil) and (super_dir ~= nil) and (result_direction ~= super_dir) then
|
|
print('ERROR: conflicting relation directions found for way ' .. way:id() ..
|
|
' relation direction is ' .. result_direction .. ' superrelation direction is ' .. super_dir)
|
|
result_direction = nil
|
|
elseif result_direction == nil then
|
|
result_direction = super_dir
|
|
end
|
|
|
|
result['route_direction'] = result_direction
|
|
|
|
if role == 'forward' then
|
|
result['route_forward'] = true
|
|
elseif role == 'backward' then
|
|
result['route_forward'] = false
|
|
else
|
|
result['route_forward'] = nil
|
|
end
|
|
|
|
add_extra_data(m)
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
function Relations.process_way_refs(way, relations, result)
|
|
local parsed_rel_list = {}
|
|
local rel_id_list = relations:get_relations(way)
|
|
for i, rel_id in ipairs(rel_id_list) do
|
|
local rel = relations:relation(rel_id)
|
|
parsed_rel_list[i] = Relations.parse_route_relation(rel, way, relations)
|
|
end
|
|
|
|
-- now process relations data
|
|
local matched_refs = nil;
|
|
if result.ref then
|
|
local match_res = Relations.match_to_ref(parsed_rel_list, result.ref)
|
|
|
|
function gen_ref(is_forward)
|
|
local ref = ''
|
|
for _, m in pairs(match_res) do
|
|
if ref ~= '' then
|
|
ref = ref .. '; '
|
|
end
|
|
|
|
local dir = m.dir.forward
|
|
if is_forward == false then
|
|
dir = m.dir.backward
|
|
end
|
|
|
|
if dir then
|
|
ref = ref .. m.ref .. ' $' .. dir
|
|
else
|
|
ref = ref .. m.ref
|
|
end
|
|
end
|
|
|
|
return ref
|
|
end
|
|
|
|
result.forward_ref = gen_ref(true)
|
|
result.backward_ref = gen_ref(false)
|
|
end
|
|
end
|
|
|
|
return Relations
|