osrm-backend/profiles/lib/relations.lua

202 lines
5.1 KiB
Lua
Raw Normal View History

-- 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] = false
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
result_match[best_ref] = direction
end
end
end
local result = {}
2017-09-14 11:44:24 -04:00
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())
2017-10-05 08:29:06 -04:00
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)
2017-09-29 12:01:33 -04:00
local result = {}
function add_extra_data(m)
local name = rel:get_value_by_key("name")
2017-09-29 12:01:33 -04:00
if name then
result['route_name'] = name
end
local ref = rel:get_value_by_key("ref")
2017-09-29 12:01:33 -04:00
if ref then
result['route_ref'] = ref
end
end
if t == 'route' then
2017-10-05 08:29:06 -04:00
local role_direction = nil
local route = rel:get_value_by_key("route")
2017-09-29 12:01:33 -04:00
if route == 'road' then
-- process case, where directions set as role
if is_direction(role) then
2017-10-05 08:29:06 -04:00
role_direction = role
2017-09-29 12:01:33 -04:00
end
end
2017-10-05 08:29:06 -04:00
local tag_direction = nil
local direction = rel:get_value_by_key('direction')
2017-09-29 12:01:33 -04:00
if direction then
direction = string.lower(direction)
if is_direction(direction) then
2017-10-05 08:29:06 -04:00
tag_direction = direction
2017-09-29 12:01:33 -04:00
end
end
2017-10-05 08:29:06 -04:00
-- determine direction
local result_direction = role_direction
if result_direction == nil and tag_direction ~= '' then
result_direction = tag_direction
end
2017-10-05 08:29:06 -04:00
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
2017-10-05 08:29:06 -04:00
-- 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
add_extra_data(m)
end
2017-10-05 08:29:06 -04:00
2017-09-29 12:01:33 -04:00
return result
end
return Relations