From 532cbfce13c4e6783c45ebf52a3afaf445d52249 Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Fri, 18 Nov 2016 20:49:51 +0100 Subject: [PATCH] profiles: Directional helper, some car refactoring --- features/car/access.feature | 6 +- features/car/maxspeed.feature | 11 ++ profiles/car.lua | 236 +++++++++++++------------------- profiles/debug.lua | 48 ++++++- profiles/lib/directional.lua | 59 ++++++++ profiles/lib/guidance.lua | 248 ++++++++++++++++------------------ 6 files changed, 334 insertions(+), 274 deletions(-) create mode 100644 profiles/lib/directional.lua diff --git a/features/car/access.feature b/features/car/access.feature index 96f5c04ff..9eedbfd21 100644 --- a/features/car/access.feature +++ b/features/car/access.feature @@ -149,6 +149,7 @@ Feature: Car - Restricted access | runway | | | | yes | | | primary | | | | no | x | + @hov Scenario: Car - only designated HOV ways are ignored by default Then routability should be | highway | hov | bothw | @@ -156,6 +157,7 @@ Feature: Car - Restricted access | primary | yes | x | | primary | no | x | + @hov Scenario: Car - a way with all lanes HOV-designated is inaccessible by default (similar to hov=designated) Then routability should be | highway | hov:lanes:forward | hov:lanes:backward | hov:lanes | oneway | forw | backw | @@ -166,8 +168,8 @@ Feature: Car - Restricted access | primary | designated\|no | designated\|no | | | x | x | | primary | yes\|no | yes\|no | | | x | x | | primary | | | | | x | x | - | primary | designated | | | -1 | | | - | primary | | designated | | -1 | | x | + | primary | designated | | | -1 | | x | + | primary | | designated | | -1 | | | | primary | | | designated | yes | | | | primary | | | designated | -1 | | | | primary | | | designated\| | yes | x | | diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index 7e5b558fb..a2ef8dc49 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -123,3 +123,14 @@ OSRM will use 4/5 of the projected free-flow speed. | primary | 30 | 1 | -1 | | 23 km/h | | primary | 30 | 1 | | 15 km/h | 15 km/h | | primary | 30 | 2 | | 23 km/h | 23 km/h | + + Scenario: Car - Forwward/backward maxspeed on reverse oneways + Then routability should be + | highway | maxspeed | maxspeed:forward | maxspeed:backward | oneway | forw | backw | + | primary | | | | -1 | | 52 km/h | + | primary | 30 | | | -1 | | 23 km/h | + | primary | | 30 | | -1 | | 52 km/h | + | primary | | | 30 | -1 | | 23 km/h | + | primary | 20 | 30 | | -1 | | 16 km/h | + | primary | 20 | | 30 | -1 | | 23 km/h | + diff --git a/profiles/car.lua b/profiles/car.lua index 1d548d19a..204ec8d4b 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -5,6 +5,7 @@ local set_classification = require("lib/guidance").set_classification local get_turn_lanes = require("lib/guidance").get_turn_lanes local Set = require('lib/set') local Sequence = require('lib/sequence') +local Directional = require('lib/directional') -- Begin of globals barrier_whitelist = Set { @@ -287,69 +288,51 @@ end -- abort early if this way is obviouslt not routable function initial_routability_check(way,result,data) - data.speed_type = way:get_value_by_key('highway') + data.highway = way:get_value_by_key('highway') - return data.speed_type ~= nil or + return data.highway ~= nil or way:get_value_by_key('route') ~= nil or way:get_value_by_key('bridge') ~= nil end --- handle high occupancy vehicle tags -function handle_hov(way,result) - -- respect user-preference for HOV-only ways - if ignore_hov_ways then - local hov = way:get_value_by_key("hov") - if "designated" == hov then +-- all lanes restricted to hov vehicles? +local function has_all_designated_hov_lanes(lanes) + if not lanes then + return false + end + -- This gmatch call effectively splits the string on | chars. + -- we append an extra | to the end so that we can match the final part + for lane in (lanes .. '|'):gmatch("([^|]*)|") do + if lane and lane ~= "designated" then return false end + end + return true +end - -- also respect user-preference for HOV-only ways when all lanes are HOV-designated - local function has_all_designated_hov_lanes(lanes) - local all = true - -- This gmatch call effectively splits the string on | chars. - -- we append an extra | to the end so that we can match the final part - for lane in (lanes .. '|'):gmatch("([^|]*)|") do - if lane and lane ~= "designated" then - all = false - break - end - end - return all - end +-- handle high occupancy vehicle tags +function handle_hov(way,result,data) + -- respect user-preference for HOV + if not ignore_hov_ways then + return + end - local hov_lanes = way:get_value_by_key("hov:lanes") - local hov_lanes_forward = way:get_value_by_key("hov:lanes:forward") - local hov_lanes_backward = way:get_value_by_key("hov:lanes:backward") + -- check if way is hov only + local hov = way:get_value_by_key("hov") + if "designated" == hov then + return false + end - local hov_all_designated = hov_lanes and - has_all_designated_hov_lanes(hov_lanes) - - local hov_all_designated_forward = hov_lanes_forward and - has_all_designated_hov_lanes(hov_lanes_forward) - - local hov_all_designated_backward = hov_lanes_backward and - has_all_designated_hov_lanes(hov_lanes_backward) - - -- forward/backward lane depend on a way's direction - local oneway = way:get_value_by_key("oneway") - local reverse = oneway == "-1" - - if hov_all_designated or hov_all_designated_forward then - if reverse then - result.backward_mode = mode.inaccessible - else - result.forward_mode = mode.inaccessible - end - end - - if hov_all_designated_backward then - if reverse then - result.forward_mode = mode.inaccessible - else - result.backward_mode = mode.inaccessible - end - end + -- check if all lanes are hov only + local hov_lanes_forward, hov_lanes_backward = Directional.get_values_by_key(way,data,'hov:lanes') + local inaccessible_forward = has_all_designated_hov_lanes(hov_lanes_forward) + local inaccessible_backward = has_all_designated_hov_lanes(hov_lanes_backward) + if inaccessible_forward then + result.forward_mode = mode.inaccessible + end + if inaccessible_backward then + result.backward_mode = mode.inaccessible end end @@ -440,18 +423,11 @@ end -- handle speed (excluding maxspeed) function handle_speed(way,result,data) if result.forward_speed == -1 then - local highway_speed = speed_profile[way:get_value_by_key("highway")] - local max_speed = parse_maxspeed( way:get_value_by_key("maxspeed") ) + local highway_speed = speed_profile[data.highway] -- Set the avg speed on the way if it is accessible by road class if highway_speed then - if max_speed and max_speed > highway_speed then - result.forward_speed = max_speed - result.backward_speed = max_speed - -- max_speed = math.huge - else - result.forward_speed = highway_speed - result.backward_speed = highway_speed - end + result.forward_speed = highway_speed + result.backward_speed = highway_speed else -- Set the avg speed on ways that are marked accessible if access_tag_whitelist[data.access] then @@ -459,11 +435,6 @@ function handle_speed(way,result,data) result.backward_speed = speed_profile["default"] end end - if 0 == max_speed then - max_speed = math.huge - end - result.forward_speed = min(result.forward_speed, max_speed) - result.backward_speed = min(result.backward_speed, max_speed) end if -1 == result.forward_speed and -1 == result.backward_speed then @@ -472,7 +443,7 @@ function handle_speed(way,result,data) if handle_side_roads(way,result) == false then return false end if handle_surface(way,result) == false then return false end - if handle_maxspeed(way,result) == false then return false end + if handle_maxspeed(way,data,result) == false then return false end if handle_speed_scaling(way,result) == false then return false end if handle_alternating_speed(way,result) == false then return false end end @@ -529,23 +500,15 @@ function handle_names(way,result) end -- handle turn lanes -function handle_turn_lanes(way,result) - local turn_lanes = '' - local turn_lanes_forward = '' - local turn_lanes_backward = '' +function handle_turn_lanes(way,result,data) + local forward, backward = get_turn_lanes(way,data) - turn_lanes, turn_lanes_forward, turn_lanes_backward = get_turn_lanes(way) - if turn_lanes and turn_lanes ~= '' then - result.turn_lanes_forward = turn_lanes; - result.turn_lanes_backward = turn_lanes; - else - if turn_lanes_forward and turn_lanes_forward ~= '' then - result.turn_lanes_forward = turn_lanes_forward; - end + if forward then + result.turn_lanes_forward = forward + end - if turn_lanes_backward and turn_lanes_backward ~= '' then - result.turn_lanes_backward = turn_lanes_backward; - end + if backward then + result.turn_lanes_backward = backward end end @@ -633,69 +596,55 @@ function handle_speed_scaling(way,result) end end --- oneways -function handle_oneway(way,result) +-- handle oneways tags +function handle_oneway(way,result,data) local oneway = way:get_value_by_key("oneway") + data.oneway = oneway if obey_oneway then if oneway == "-1" then + data.is_reverse_oneway = true result.forward_mode = mode.inaccessible - - local is_forward = false - local destination = get_destination(way, is_forward) - result.destinations = canonicalizeStringList(destination, ",") elseif oneway == "yes" or oneway == "1" or - oneway == "true" or - way:get_value_by_key("junction") == "roundabout" or - way:get_value_by_key("junction") == "circular" or - (way:get_value_by_key("highway") == "motorway" and oneway ~= "no") then - + oneway == "true" then + data.is_forward_oneway = true result.backward_mode = mode.inaccessible - - local is_forward = true - local destination = get_destination(way, is_forward) - result.destinations = canonicalizeStringList(destination, ",") + else + local junction = way:get_value_by_key("junction") + if data.highway == "motorway" or + junction == "roundabout" or + junction == "circular" then + if oneway ~= "no" then + -- implied oneway + data.is_forward_oneway = true + result.backward_mode = mode.inaccessible + end + end end end end --- maxspeed and advisory maxspeed -function handle_maxspeed(way,result) - -- Override speed settings if explicit forward/backward maxspeeds are given - local maxspeed_forward = parse_maxspeed(way:get_value_by_key("maxspeed:forward")) - local maxspeed_backward = parse_maxspeed(way:get_value_by_key("maxspeed:backward")) - if maxspeed_forward and maxspeed_forward > 0 then - if mode.inaccessible ~= result.forward_mode and - mode.inaccessible ~= result.backward_mode then - result.backward_speed = result.forward_speed - end - result.forward_speed = maxspeed_forward +-- handle destination tags +function handle_destinations(way,result,data) + if data.is_forward_oneway or data.is_reverse_oneway then + local destination = get_destination(way, data.is_forward_oneway) + result.destinations = canonicalizeStringList(destination, ",") end - if maxspeed_backward and maxspeed_backward > 0 then - result.backward_speed = maxspeed_backward +end + +-- maxspeed and advisory maxspeed +function handle_maxspeed(way,data,result) + local keys = Sequence { 'maxspeed:advisory', 'maxspeed' } + local forward, backward = Directional.get_values_by_set(way,data,keys) + forward = parse_maxspeed(forward) + backward = parse_maxspeed(backward) + + if forward and forward > 0 then + result.forward_speed = forward end - -- Override speed settings if advisory forward/backward maxspeeds are given - local advisory_speed = parse_maxspeed(way:get_value_by_key("maxspeed:advisory")) - local advisory_forward = parse_maxspeed(way:get_value_by_key("maxspeed:advisory:forward")) - local advisory_backward = parse_maxspeed(way:get_value_by_key("maxspeed:advisory:backward")) - -- apply bi-directional advisory speed first - if advisory_speed and advisory_speed > 0 then - if mode.inaccessible ~= result.forward_mode then - result.forward_speed = advisory_speed - end - if mode.inaccessible ~= result.backward_mode then - result.backward_speed = advisory_speed - end - end - if advisory_forward and advisory_forward > 0 then - if mode.inaccessible ~= result.forward_mode and mode.inaccessible ~= result.backward_mode then - result.backward_speed = result.forward_speed - end - result.forward_speed = advisory_forward - end - if advisory_backward and advisory_backward > 0 then - result.backward_speed = advisory_backward + if backward and backward > 0 then + result.backward_speed = backward end end @@ -713,6 +662,7 @@ function handle_alternating_speed(way,result) end end + -- determine if this way can be used as a start/end point for routing function handle_startpoint(way,result) -- only allow this road as start point if it not a ferry @@ -721,8 +671,8 @@ function handle_startpoint(way,result) end -- set the road classification based on guidance globals configuration -function handle_classification(way,result) - set_classification(way:get_value_by_key("highway"),result,way) +function handle_classification(way,result,data) + set_classification(data.highway,result,way) end -- main entry point for processsing a way @@ -754,8 +704,11 @@ function way_function(way, result) -- access tags, e.g: motorcar, motor_vehicle, vehicle if handle_access(way,result,data) == false then return end - -- check high occupancy vehicle restrictions - if handle_hov(way,result) == false then return end + -- check whether forward/backward directons are routable + if handle_oneway(way,result,data) == false then return end + + -- check whether forward/backward directons are routable + if handle_destinations(way,result,data) == false then return end -- check whether we're using a special transport mode if handle_ferries(way,result) == false then return end @@ -764,24 +717,21 @@ function way_function(way, result) -- handle service road restrictions if handle_service(way,result) == false then return end - -- check whether forward/backward directons are routable - if handle_oneway(way,result) == false then return end + -- check high occupancy vehicle restrictions + if handle_hov(way,result,data) == false then return end -- compute speed taking into account way type, maxspeed tags, etc. if handle_speed(way,result,data) == false then return end -- handle turn lanes and road classification, used for guidance - if handle_turn_lanes(way,result) == false then return end - if handle_classification(way,result) == false then return end + if handle_turn_lanes(way,result,data) == false then return end + if handle_classification(way,result,data) == false then return end -- handle various other flags if handle_roundabouts(way,result) == false then return end if handle_startpoint(way,result) == false then return end if handle_restricted(way,result,data) == false then return end - -- handle roundabout flags - if handle_roundabouts(way,result) == false then return end - -- check if this way can be routed through, but not used as -- origin or destination if handle_restricted(way,result,data) == false then return end diff --git a/profiles/debug.lua b/profiles/debug.lua index 8895e0bfc..d8d6b41f0 100644 --- a/profiles/debug.lua +++ b/profiles/debug.lua @@ -56,13 +56,32 @@ local way = { --route = 'ferry', --duration = '00:01:00', --hov = 'designated', + ["hov:lanes:forward"] = 'designated', --access = 'no' --destination = 'Berlin', - ["destination:ref"] = 'Nuremberg', + --["destination:ref"] = 'Nuremberg', --["destination:ref:forward"] = 'Hamburg;Dresden', } -- tag function normally provided via C++ function way:get_value_by_key(k) + if not self['_debug'] then + self['_debug'] = { + _counts = {} + } + end + + if self['_debug']['_total'] then + self['_debug']['_total'] = self['_debug']['_total'] + 1 + else + self['_debug']['_total'] = 1 + end + + if self['_debug']['_counts'][k] then + self['_debug']['_counts'][k] = self['_debug']['_counts'][k] + 1 + else + self['_debug']['_counts'][k] = 1 + end + return self[k] end @@ -83,6 +102,27 @@ function canonicalizeStringList(str) return str end +-- helpers for sorting associative array +function get_keys_sorted_by_value(tbl, sortFunction) + local keys = {} + for key in pairs(tbl) do + table.insert(keys, key) + end + + table.sort(keys, function(a, b) + return sortFunction(tbl[a], tbl[b]) + end) + + return keys +end + +-- helper for printing sorted array +function print_sorted(sorted,associative) + for _, key in ipairs(sorted) do + print(associative[key], key) + end +end + -- start state of result table, normally set form C++ local result = { road_classification = {}, @@ -100,3 +140,9 @@ way_function(way,result) pprint(way) print("=>") pprint(result) +print("\n") +print("Tag fetches:") +sorted_counts = get_keys_sorted_by_value(way._debug._counts, function(a, b) return a > b end) +print_sorted(sorted_counts, way._debug._counts) + +print(way._debug._total, 'total') diff --git a/profiles/lib/directional.lua b/profiles/lib/directional.lua new file mode 100644 index 000000000..0770d0695 --- /dev/null +++ b/profiles/lib/directional.lua @@ -0,0 +1,59 @@ +local Directional = {} + +-- return [forward,backward] values for a specific tag. +-- e.g. for maxspeed search forward: +-- maxspeed:forward +-- maxspeed +-- and backward: +-- maxspeed:backward +-- maxspeed + +function Directional.get_values_by_key(way,data,key) + local forward = way:get_value_by_key(key .. ':forward') + local backward = way:get_value_by_key(key .. ':backward') + + if forward and backward then + return forward, backward + end + + local common = way:get_value_by_key(key) + return forward or common, + backward or common +end + +-- return [forward,backward] values, searching a +-- prioritized sequence of tags +-- e.g. for the sequence [maxspeed,advisory] search forward: +-- maxspeed:forward +-- maxspeed +-- advisory:forward +-- advisory +-- and for backward: +-- maxspeed:backward +-- maxspeed +-- advisory:backward +-- advisory + +function Directional.get_values_by_set(way,data,keys) + local forward, backward + for i,key in ipairs(keys) do + if not forward then + forward = way:get_value_by_key(key .. ':forward') + end + if not backward then + backward = way:get_value_by_key(key .. ':backward') + end + if not forward or not backward then + local common = way:get_value_by_key(key) + forward = forward or common + backward = backward or common + end + if forward and backward then + break + end + end + + return forward, backward +end + +return Directional \ No newline at end of file diff --git a/profiles/lib/guidance.lua b/profiles/lib/guidance.lua index 78517a74c..c1bc5b808 100644 --- a/profiles/lib/guidance.lua +++ b/profiles/lib/guidance.lua @@ -1,154 +1,146 @@ +local Directional = require('lib/directional') +local Set = require('lib/set') + local Guidance = {} -- Guidance: Default Mapping from roads to types/priorities -highway_classes = { ["motorway"] = road_priority_class.motorway, - ["motorway_link"] = road_priority_class.link_road, - ["trunk"] = road_priority_class.trunk, - ["trunk_link"] = road_priority_class.link_road, - ["primary"] = road_priority_class.primary, - ["primary_link"] = road_priority_class.link_road, - ["secondary"] = road_priority_class.secondary, - ["secondary_link"] = road_priority_class.link_road, - ["tertiary"] = road_priority_class.tertiary, - ["tertiary_link"] = road_priority_class.link_road, - ["unclassified"] = road_priority_class.side_residential, - ["residential"] = road_priority_class.side_residential, - ["service"] = road_priority_class.connectivity, - ["living_street"] = road_priority_class.main_residential, - ["track"] = road_priority_class.bike_path, - ["path"] = road_priority_class.bike_path, - ["footway"] = road_priority_class.foot_path, - ["pedestrian"] = road_priority_class.foot_path, - ["steps"] = road_priority_class.foot_path} +highway_classes = { + motorway = road_priority_class.motorway, + motorway_link = road_priority_class.link_road, + trunk = road_priority_class.trunk, + trunk_link = road_priority_class.link_road, + primary = road_priority_class.primary, + primary_link = road_priority_class.link_road, + secondary = road_priority_class.secondary, + secondary_link = road_priority_class.link_road, + tertiary = road_priority_class.tertiary, + tertiary_link = road_priority_class.link_road, + unclassified = road_priority_class.side_residential, + residential = road_priority_class.side_residential, + service = road_priority_class.connectivity, + living_street = road_priority_class.main_residential, + track = road_priority_class.bike_path, + path = road_priority_class.bike_path, + footway = road_priority_class.foot_path, + pedestrian = road_priority_class.foot_path, + steps = road_priority_class.foot_path +} default_highway_class = road_priority_class.connectivity; -motorway_types = { ["motorway"] = true, ["motorway_link"] = true, ["trunk"] = true, ["trunk_link"] = true } +motorway_types = Set { + 'motorway', + 'motorway_link', + 'trunk', + 'trunk_link' +} -- these road types are set with a car in mind. For bicycle/walk we probably need different ones -road_types = { ["motorway"] = true, - ["motorway_link"] = true, - ["trunk"] = true, - ["trunk_link"] = true, - ["primary"] = true, - ["primary_link"] = true, - ["secondary"] = true, - ["secondary_link"] = true, - ["tertiary"] = true, - ["tertiary_link"] = true, - ["unclassified"] = true, - ["residential"] = true, - ["living_street"] = true } +road_types = Set { + 'motorway', + 'motorway_link', + 'trunk', + 'trunk_link', + 'primary', + 'primary_link', + 'secondary', + 'secondary_link', + 'tertiary', + 'tertiary_link', + 'unclassified', + 'residential', + 'living_street' +} -link_types = { ["motorway_link"] = true, ["trunk_link"] = true, ["primary_link"] = true, ["secondary_link"] = true, ["tertiary_link"] = true } +link_types = Set { + 'motorway_link', + 'trunk_link', + 'primary_link', + 'secondary_link', + 'tertiary_link' +} function Guidance.set_classification (highway, result, input_way) - if motorway_types[highway] then - result.road_classification.motorway_class = true; - end - if link_types[highway] then - result.road_classification.link_class = true; - end - if highway_classes[highway] ~= nil then - result.road_classification.road_priority_class = highway_classes[highway] - else - result.road_classification.road_priority_class = default_highway_class - end - if road_types[highway] then - result.road_classification.may_be_ignored = false; - else - result.road_classification.may_be_ignored = true; - end + if motorway_types[highway] then + result.road_classification.motorway_class = true; + end + if link_types[highway] then + result.road_classification.link_class = true; + end + if highway_classes[highway] ~= nil then + result.road_classification.road_priority_class = highway_classes[highway] + else + result.road_classification.road_priority_class = default_highway_class + end + if road_types[highway] then + result.road_classification.may_be_ignored = false; + else + result.road_classification.may_be_ignored = true; + end - local lane_count = input_way:get_value_by_key("lanes") - if lane_count then - local lc = tonumber(lane_count) - if lc ~= nil then - result.road_classification.num_lanes = lc - end - else - local total_count = 0 - local forward_count = input_way:get_value_by_key("lanes:forward") - if forward_count then - local fc = tonumber(forward_count) - if fc ~= nil then - total_count = fc - end - end - local backward_count = input_way:get_value_by_key("lanes:backward") - if backward_count then - local bc = tonumber(backward_count) - if bc ~= nil then - total_count = total_count + bc - end - end - if total_count ~= 0 then - result.road_classification.num_lanes = total_count - end + local lane_count = input_way:get_value_by_key("lanes") + if lane_count then + local lc = tonumber(lane_count) + if lc ~= nil then + result.road_classification.num_lanes = lc end + else + local total_count = 0 + local forward_count = input_way:get_value_by_key("lanes:forward") + if forward_count then + local fc = tonumber(forward_count) + if fc ~= nil then + total_count = fc + end + end + local backward_count = input_way:get_value_by_key("lanes:backward") + if backward_count then + local bc = tonumber(backward_count) + if bc ~= nil then + total_count = total_count + bc + end + end + if total_count ~= 0 then + result.road_classification.num_lanes = total_count + end + end end -- returns forward,backward psv lane count -local function get_psv_counts(way) - local psv = way:get_value_by_key("lanes:psv") - local psv_forward = way:get_value_by_key("lanes:psv:forward"); - local psv_backward = way:get_value_by_key("lanes:psv:backward"); - - local fw = 0; - local bw = 0; - if psv then - fw = tonumber(psv) - if( fw == nil ) then - fw = 0 - end - end - if psv_forward then - fw = tonumber(psv_forward) - if( fw == nil ) then - fw = 0 - end - end - if psv_backward then - bw = tonumber(psv_backward); - if( bw == nil ) then - bw = 0 - end - end - return fw, bw +local function get_psv_counts(way,data) + local psv_forward, psv_backward = Directional.get_values_by_key(way,data,'lanes:psv') + if psv_forward then + psv_forward = tonumber(psv_forward) + end + if psv_backward then + psv_backward = tonumber(psv_backward) + end + return psv_forward or 0, + psv_backward or 0 end -- trims lane string with regard to supported lanes -local function process_lanes(turn_lane,vehicle_lane,first_count,second_count) - if turn_lane then - if vehicle_lane then - turn_lane = applyAccessTokens(turn_lane,vehicle_lane) - elseif first_count ~= 0 or second_count ~= 0 then - turn_lane = trimLaneString(turn_lane, first_count, second_count) - end +local function process_lanes(turn_lanes,vehicle_lanes,first_count,second_count) + if turn_lanes then + if vehicle_lanes then + return applyAccessTokens(turn_lanes,vehicle_lanes) + elseif first_count ~= 0 or second_count ~= 0 then + return trimLaneString(turn_lanes, first_count, second_count) + else + return turn_lanes end - return turn_lane; + end end -- this is broken for left-sided driving. It needs to switch left and right in case of left-sided driving -function Guidance.get_turn_lanes(way) - local fw_psv = 0 - local bw_psv = 0 - fw_psv, bw_psv = get_psv_counts(way) - - local turn_lanes = way:get_value_by_key("turn:lanes") - local turn_lanes_fw = way:get_value_by_key("turn:lanes:forward") - local turn_lanes_bw = way:get_value_by_key("turn:lanes:backward") - - local vehicle_lanes = way:get_value_by_key("vehicle:lanes"); - local vehicle_lanes_fw = way:get_value_by_key("vehicle:lanes:forward"); - local vehicle_lanes_bw = way:get_value_by_key("vehicle:lanes:backward"); - - turn_lanes = process_lanes(turn_lanes,vehicle_lanes,bw_psv,fw_psv) - turn_lanes_fw = process_lanes(turn_lanes_fw,vehicle_lanes_fw,bw_psv,fw_psv) - --backwards turn lanes need to treat bw_psv as fw_psv and vice versa - turn_lanes_bw = process_lanes(turn_lanes_bw,vehicle_lanes_bw,fw_psv,bw_psv) - - return turn_lanes, turn_lanes_fw, turn_lanes_bw +function Guidance.get_turn_lanes(way,data) + local psv_fw, psv_bw = get_psv_counts(way,data) + local turn_lanes_fw, turn_lanes_bw = Directional.get_values_by_key(way,data,'turn:lanes') + local vehicle_lanes_fw, vehicle_lanes_bw = Directional.get_values_by_key(way,data,'vehicle:lanes') + + --note: backward lanes swap psv_bw and psv_fw + return process_lanes(turn_lanes_fw,vehicle_lanes_fw,psv_bw,psv_fw) or turn_lanes, + process_lanes(turn_lanes_bw,vehicle_lanes_bw,psv_fw,psv_bw) or turn_lanes end return Guidance