Add route relation support for multi ref's
This commit is contained in:
parent
9a660e3c18
commit
5fd77aebb5
@ -8,6 +8,7 @@ Handlers = require("lib/way_handlers")
|
|||||||
Relations = require("lib/relations")
|
Relations = require("lib/relations")
|
||||||
find_access_tag = require("lib/access").find_access_tag
|
find_access_tag = require("lib/access").find_access_tag
|
||||||
limit = require("lib/maxspeed").limit
|
limit = require("lib/maxspeed").limit
|
||||||
|
Utils = require("lib/utils")
|
||||||
|
|
||||||
function setup()
|
function setup()
|
||||||
return {
|
return {
|
||||||
@ -398,22 +399,55 @@ function process_way(profile, way, result, relations)
|
|||||||
WayHandlers.run(profile, way, result, data, handlers, relations)
|
WayHandlers.run(profile, way, result, data, handlers, relations)
|
||||||
|
|
||||||
-- now process relations data
|
-- now process relations data
|
||||||
local data = Relations.Merge(relations)
|
local matched_refs = nil;
|
||||||
local direction = data["route_direction"]
|
|
||||||
if direction then
|
|
||||||
if result.ref then
|
if result.ref then
|
||||||
if result.ref:len() > 0 then
|
matched_refs = Relations.MatchToRef(relations, result.ref)
|
||||||
result.ref = result.ref .. ' ' .. direction
|
|
||||||
|
local ref = ''
|
||||||
|
for k ,v in pairs(matched_refs) do
|
||||||
|
if ref ~= '' then
|
||||||
|
ref = ref .. '; '
|
||||||
|
end
|
||||||
|
|
||||||
|
if v then
|
||||||
|
ref = ref .. k .. ' $' .. v
|
||||||
else
|
else
|
||||||
result.ref = direction
|
print(ref)
|
||||||
|
ref = ref .. k
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
result.ref = ref
|
||||||
|
-- count = 0
|
||||||
|
-- for k, v in pairs(matched_refs) do
|
||||||
|
-- count = count + 1
|
||||||
|
-- end
|
||||||
|
-- if count > 1 then
|
||||||
|
-- print('---', way:id())
|
||||||
|
-- for k, v in pairs(matched_refs) do
|
||||||
|
-- print(k, v)
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function process_relation(profile, relation, result)
|
function process_relation(profile, relation, result)
|
||||||
local t = relation:get_value_by_key("type")
|
local t = relation:get_value_by_key("type")
|
||||||
|
|
||||||
|
function add_extra_data(m)
|
||||||
|
local name = relation:get_value_by_key("name")
|
||||||
|
if name then
|
||||||
|
result[m]["route_name"] = name
|
||||||
|
end
|
||||||
|
|
||||||
|
local ref = relation:get_value_by_key("ref")
|
||||||
|
if ref then
|
||||||
|
result[m]["route_ref"] = ref
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if t == "route" then
|
if t == "route" then
|
||||||
local route = relation:get_value_by_key("route")
|
local route = relation:get_value_by_key("route")
|
||||||
if route == "road" then
|
if route == "road" then
|
||||||
@ -422,6 +456,7 @@ function process_relation(profile, relation, result)
|
|||||||
local role = string.lower(m:role())
|
local role = string.lower(m:role())
|
||||||
if role == "north" or role == "south" or role == "west" or role == "east" then
|
if role == "north" or role == "south" or role == "west" or role == "east" then
|
||||||
result[m]["route_direction"] = role
|
result[m]["route_direction"] = role
|
||||||
|
add_extra_data(m)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -433,6 +468,7 @@ function process_relation(profile, relation, result)
|
|||||||
for _, m in ipairs(relation:members()) do
|
for _, m in ipairs(relation:members()) do
|
||||||
if m:role() == "forward" then
|
if m:role() == "forward" then
|
||||||
result[m]["route_direction"] = direction
|
result[m]["route_direction"] = direction
|
||||||
|
add_extra_data(m)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
-- You can run a selection you find useful in your profile,
|
-- You can run a selection you find useful in your profile,
|
||||||
-- or do you own processing if/when required.
|
-- or do you own processing if/when required.
|
||||||
|
|
||||||
|
Utils = require('lib/utils')
|
||||||
|
|
||||||
Relations = {}
|
Relations = {}
|
||||||
|
|
||||||
function Relations.Merge(relations)
|
function Relations.Merge(relations)
|
||||||
@ -17,4 +19,82 @@ function Relations.Merge(relations)
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- match ref values to relations data
|
||||||
|
function Relations.MatchToRef(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 = {}
|
||||||
|
|
||||||
|
for _, r in ipairs(references) do
|
||||||
|
result_match[r] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, 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
|
||||||
|
|
||||||
|
return result_match
|
||||||
|
end
|
||||||
|
|
||||||
return Relations
|
return Relations
|
43
profiles/lib/utils.lua
Normal file
43
profiles/lib/utils.lua
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
-- Profile functions to implement common algorithms of data processing
|
||||||
|
--
|
||||||
|
-- You can run a selection you find useful in your profile,
|
||||||
|
-- or do you own processing if/when required.
|
||||||
|
|
||||||
|
Utils = {}
|
||||||
|
|
||||||
|
-- split string 'a; b; c' to table with values ['a', 'b', 'c']
|
||||||
|
-- so it use just one separator ';'
|
||||||
|
function Utils.string_list_tokens(str)
|
||||||
|
result = {}
|
||||||
|
local idx = 0
|
||||||
|
for s in str.gmatch(str, "([^;]*)") do
|
||||||
|
if s ~= nil and s ~= '' then
|
||||||
|
idx = idx + 1
|
||||||
|
table.insert(result, idx, (s:gsub("^%s*(.-)%s*$", "%1")))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
-- same as Utils.StringListTokens, but with many possible separators:
|
||||||
|
-- ',' | ';' | ' '| '(' | ')'
|
||||||
|
function Utils.tokenize_common(str)
|
||||||
|
result = {}
|
||||||
|
local idx = 0
|
||||||
|
for s in str.gmatch(str, "%S+") do
|
||||||
|
if s ~= nil and s ~= '' then
|
||||||
|
idx = idx + 1
|
||||||
|
table.insert(result, idx, (s:gsub("^%s*(.-)%s*$", "%1")))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns true, if string contains a number
|
||||||
|
function Utils.is_number(str)
|
||||||
|
return (tonumber(str) ~= nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
return Utils
|
Loading…
Reference in New Issue
Block a user