Compare commits

..

7 Commits

Author SHA1 Message Date
Daniel Patterson 078624a54c Bump versions preparing for merge. 2017-09-19 14:12:24 -07:00
Daniel Patterson bb5530646a Update changelog. 2017-09-19 14:12:13 -07:00
Denis Koronchik 4d3e35982b Some improvements in code 2017-09-19 14:09:30 -07:00
Denis Koronchik 6227242c85 Add test for route relation process in car.lua. Some fixes 2017-09-19 14:09:30 -07:00
Denis Koronchik b3e6b59528 Fix bug with simple refs support (not lists) 2017-09-19 14:09:30 -07:00
Denis Koronchik 40398a1856 Add route relation support for multi ref's 2017-09-19 14:09:29 -07:00
Denis Koronchik 7078ebd2cb Implement route relation parse in car.lua 2017-09-19 14:09:29 -07:00
27 changed files with 429 additions and 635 deletions
+14 -19
View File
@@ -79,14 +79,14 @@ matrix:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_SANITIZER=ON CUCUMBER_TIMEOUT=20000 LSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/scripts/travis/leaksanitizer.conf"
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_SANITIZER=ON CUCUMBER_TIMEOUT=20000
- os: linux
compiler: "clang-4.0-debug"
addons: &clang40
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
packages: ['libstdc++-5-dev', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
- os: linux
@@ -94,8 +94,8 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON LSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/scripts/travis/leaksanitizer.conf"
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON
# Release Builds
- os: linux
@@ -103,7 +103,7 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON
- os: linux
@@ -186,7 +186,7 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
install:
- pushd ${OSRM_BUILD_DIR}
@@ -195,8 +195,7 @@ matrix:
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
@@ -210,7 +209,7 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
install:
- pushd ${OSRM_BUILD_DIR}
@@ -219,8 +218,7 @@ matrix:
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
@@ -234,7 +232,7 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
install:
- pushd ${OSRM_BUILD_DIR}
@@ -243,8 +241,7 @@ matrix:
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
@@ -258,7 +255,7 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
install:
- pushd ${OSRM_BUILD_DIR}
@@ -267,8 +264,7 @@ matrix:
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- make --jobs=${JOBS}
- popd
script:
@@ -342,8 +338,7 @@ install:
-DENABLE_STXXL=${ENABLE_STXXL:-OFF} \
-DBUILD_TOOLS=ON \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=${ENABLE_GLIBC_WORKAROUND:-OFF}
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
- echo "travis_fold:start:MAKE"
- make --jobs=${JOBS}
- make tests --jobs=${JOBS}
+1 -2
View File
@@ -1,13 +1,12 @@
# UNRELEASED
- Profile:
- New function to support relations: `process_relation`. Read more in profiles documentation.
- Append cardinal directions from route relations to ref fields to improve instructions
- Support of `distance` weight in foot and bicycle profiles
- Infrastructure:
- Lua 5.1 support is removed due to lack of support in sol2 https://github.com/ThePhD/sol2/issues/302
- Node.js Bindings:
- Exposes `use_threads_number=Number` parameter of `EngineConfig` to limit a number of threads in a TBB internal pool
- Internals
- MLD uses a unidirectional Dijkstra for 1-to-N and N-to-1 matrices
# 5.12.0
- Guidance
+6 -9
View File
@@ -31,7 +31,6 @@ option(ENABLE_LTO "Use LTO if available" OFF)
option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
option(ENABLE_GOLD_LINKER "Use GNU gold linker if available" ON)
option(ENABLE_NODE_BINDINGS "Build NodeJs bindings" OFF)
option(ENABLE_GLIBC_WORKAROUND "Workaround GLIBC symbol exports" OFF)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
@@ -518,10 +517,12 @@ else()
find_package(BZip2 REQUIRED)
add_dependency_includes(${BZIP2_INCLUDE_DIR})
find_package(Lua 5.2 REQUIRED)
if (LUA_FOUND)
message(STATUS "Using Lua ${LUA_VERSION_STRING}")
endif()
FIND_PACKAGE(Lua 5.2 EXACT)
IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE()
MESSAGE(FATAL_ERROR "Lua 5.2 was not found.")
ENDIF()
set(USED_LUA_LIBRARIES ${LUA_LIBRARIES})
add_dependency_includes(${LUA_INCLUDE_DIR})
@@ -811,10 +812,6 @@ add_custom_target(uninstall
add_subdirectory(unit_tests)
add_subdirectory(src/benchmarks)
if (ENABLE_GLIBC_WORKAROUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLIBC_WORKAROUND")
endif()
if (ENABLE_NODE_BINDINGS)
add_subdirectory(src/nodejs)
endif()
+1 -3
View File
@@ -157,9 +157,7 @@ which will check and use pre-built binaries if they're available for this releas
to always force building the Node.js bindings from source.
For usage details have a look [these API docs](docs/nodejs/api.md).
An exemplary implementation by a 3rd party with Docker and Node.js can be found [here](https://github.com/door2door-io/osrm-express-server-demo).
For usage details have a look [these API docs](docs/nodejs/api.md).
## References in publications
+1 -1
View File
@@ -40,7 +40,7 @@ ECHO msbuild version
msbuild /version
:: HARDCODE "x64" as it is uppercase on AppVeyor and download from S3 is case sensitive
SET DEPSPKG=osrm-deps-win-x64-14.0-2017.09.7z
SET DEPSPKG=osrm-deps-win-x64-14.0.7z
:: local development
ECHO.
-3
View File
@@ -36,8 +36,6 @@
# This is because, the lua location is not standardized and may exist in
# locations other than lua/
include(FindPkgConfig)
unset(_lua_include_subdirs)
unset(_lua_library_names)
unset(_lua_append_versions)
@@ -83,7 +81,6 @@ function(_lua_set_version_vars)
lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
lua.${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
)
pkg_check_modules(LUA QUIET "lua${ver}")
endforeach ()
set(_lua_include_subdirs "${_lua_include_subdirs}" PARENT_SCOPE)
+3 -3
View File
@@ -7,7 +7,7 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
apk update && \
apk upgrade && \
apk add git cmake wget make libc-dev gcc g++ bzip2-dev boost-dev zlib-dev expat-dev lua5.2-dev libtbb@testing libtbb-dev@testing && \
apk add git cmake wget make libc-dev gcc g++ bzip2-dev boost-dev zlib-dev expat-dev lua5.1-dev libtbb@testing libtbb-dev@testing && \
\
echo "Building libstxxl" && \
cd /opt && \
@@ -46,8 +46,8 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
rm /usr/local/lib/libstxxl* && \
cd /opt && \
apk del boost-dev && \
apk del g++ cmake libc-dev expat-dev zlib-dev bzip2-dev lua5.2-dev git make gcc && \
apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.2 expat && \
apk del g++ cmake libc-dev expat-dev zlib-dev bzip2-dev lua5.1-dev git make gcc && \
apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.1 expat && \
rm -rf /src /opt/stxxl /usr/local/bin/stxxl_tool /usr/local/lib/libosrm*
EXPOSE 5000
+68
View File
@@ -0,0 +1,68 @@
@routing @car @relations
Feature: Car - route relations
Background:
Given the profile "car"
@sliproads
Scenario: Cardinal direction assignment to refs
Given the node map
"""
a b
| |
c------+--+------d
e------+--+------f
| |
g h
i----------------j
k----------------l
x----------------y
z----------------w
"""
And the ways
| nodes | name | highway | ref |
| ag | southbound | motorway | I 80 |
| hb | northbound | motorway | I 80 |
| dc | westbound | motorway | I 85;CO 93 |
| ef | eastbound | motorway | I 85;US 12 |
| ij | westbound-2 | motorway | I 99 |
| ji | eastbound-2 | motorway | I 99 |
| kl | eastbound-2 | motorway | I 99 |
| lk | eastbound-2 | motorway | I 99 |
| xy | watermill | motorway | I 45M; US 3 |
And the relations
| type | way:south | route | ref |
| route | ag | road | 80 |
| route | ef | road | 12 |
And the relations
| type | way:north | route | ref |
| route | hb | road | 80 |
| route | cd | road | 93 |
And the relations
| type | way:west | route | ref |
| route | dc | road | 85 |
| route | ij | road | 99 |
| route | xy | road | I 45 |
And the relations
| type | way:east | route | ref |
| route | lk | road | I 99 |
And the relations
| type | way:east | route | ref |
| route | xy | road | US 3 |
When I route I should get
| waypoints | route | ref |
| a,g | southbound,southbound | I 80 $south,I 80 $south |
| h,b | northbound,northbound | I 80 $north,I 80 $north |
| d,c | westbound,westbound | I 85 $west; CO 93 $north,I 85 $west; CO 93 $north |
| e,f | eastbound,eastbound | I 85; US 12 $south,I 85; US 12 $south |
| i,j | westbound-2,westbound-2 | I 99 $west,I 99 $west |
| l,k | eastbound-2,eastbound-2 | I 99 $east,I 99 $east |
| x,y | watermill,watermill | I 45M $west; US 3 $east,I 45M $west; US 3 $east |
-29
View File
@@ -280,35 +280,6 @@ Feature: Simple Turns
| a,d | road,road | depart,arrive |
| e,a | road,road | depart,arrive |
Scenario: Splitting Road with many lanes; same as above makes sure len(turn:lanes) work as expected
Given the node map
"""
f - - - - - - - - - - - - - - - - - - - - e
'
'
'
'
'
a - - - - - b
'
'
'
'
'
c - - - - - - - - - - - - - - - - - - - - d
"""
And the ways
| nodes | highway | name | turn:lanes | oneway |
| ab | primary | road | left\|left\|right\|right | no |
| bcd | primary | road | through\|through | yes |
| efb | primary | road | through\|through | yes |
When I route I should get
| waypoints | route | turns |
| a,d | road,road | depart,arrive |
| e,a | road,road | depart,arrive |
@todo
# currently the intersections don't match up do to the `merging` process.
# The intermediate intersection is technically no-turn at all, since the road continues.
+1 -1
View File
@@ -11,7 +11,7 @@ module.exports = function () {
var waypoints = [],
columnHeaders = tableRows[0].slice(1),
rowHeaders = tableRows.map((h) => h[0]).slice(1),
symmetric = columnHeaders.length == rowHeaders.length && columnHeaders.every((ele, i) => ele === rowHeaders[i]);
symmetric = columnHeaders.every((ele, i) => ele === rowHeaders[i]);
if (symmetric) {
columnHeaders.forEach((nodeName) => {
-67
View File
@@ -41,17 +41,6 @@ Feature: Basic Distance Matrix
| c | 30 | 20 | 0 | 30 |
| d | 60 | 50 | 30 | 0 |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 10 | 30 | 60 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 10 |
| c | 30 |
| d | 60 |
Scenario: Testbot - Travel time matrix with fuzzy match
Given the node map
"""
@@ -143,13 +132,6 @@ Feature: Basic Distance Matrix
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 10 |
| e | 20 |
| f | 30 |
Scenario: Testbot - Travel time 3x2 matrix
Given the node map
"""
@@ -326,52 +308,3 @@ Feature: Basic Distance Matrix
| 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 |
| 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 |
| 8 | 4.1 | 3.1 | 7.1 | 6.1 | 10.1 | 9.1 | 1 | 0 |
Scenario: Testbot - Travel time matrix with ties
Given the profile file
"""
local functions = require('testbot')
functions.process_segment = function(profile, segment)
segment.weight = 1
segment.duration = 1
end
functions.process_turn = function(profile, turn)
if turn.angle >= 0 then
turn.duration = 16
else
turn.duration = 4
end
turn.weight = 0
end
return functions
"""
And the node map
"""
a b
c d
"""
And the ways
| nodes |
| ab |
| ac |
| bd |
| dc |
When I route I should get
| from | to | route | distance | time | weight |
| a | c | ac,ac | 200m | 5s | 5 |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 1 | 5 | 10 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 1 |
| c | 15 |
| d | 10 |
+5 -9
View File
@@ -159,16 +159,14 @@ class CellCustomizer
}
const EdgeWeight to_weight = weight + subcell_weight;
const EdgeDuration to_duration = duration + *subcell_duration;
if (!heap.WasInserted(to))
{
heap.Insert(to, to_weight, {true, to_duration});
heap.Insert(to, to_weight, {true, duration + *subcell_duration});
}
else if (std::tie(to_weight, to_duration) <
std::tie(heap.GetKey(to), heap.GetData(to).duration))
else if (to_weight < heap.GetKey(to))
{
heap.DecreaseKey(to, to_weight);
heap.GetData(to) = {true, to_duration};
heap.GetData(to) = {true, duration + *subcell_duration};
}
}
@@ -193,16 +191,14 @@ class CellCustomizer
partition.GetCell(level - 1, node) != partition.GetCell(level - 1, to)))
{
const EdgeWeight to_weight = weight + data.weight;
const EdgeDuration to_duration = duration + data.duration;
if (!heap.WasInserted(to))
{
heap.Insert(to, to_weight, {false, duration + data.duration});
}
else if (std::tie(to_weight, to_duration) <
std::tie(heap.GetKey(to), heap.GetData(to).duration))
else if (to_weight < heap.GetKey(to))
{
heap.DecreaseKey(to, to_weight);
heap.GetData(to) = {false, to_duration};
heap.GetData(to) = {false, duration + data.duration};
}
}
}
+13 -3
View File
@@ -30,7 +30,7 @@ class RoutingAlgorithmsInterface
virtual InternalRouteResult
DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0;
virtual std::vector<EdgeDuration>
virtual std::vector<EdgeWeight>
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const = 0;
@@ -81,7 +81,7 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
InternalRouteResult
DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override;
std::vector<EdgeDuration>
std::vector<EdgeWeight>
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const final override;
@@ -166,6 +166,16 @@ RoutingAlgorithms<Algorithm>::DirectShortestPathSearch(const PhantomNodes &phant
return routing_algorithms::directShortestPathSearch(heaps, *facade, phantom_nodes);
}
template <typename Algorithm>
std::vector<EdgeWeight>
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const
{
return routing_algorithms::manyToManySearch(
heaps, *facade, phantom_nodes, source_indices, target_indices);
}
template <typename Algorithm>
inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatching(
const routing_algorithms::CandidateLists &candidates_list,
@@ -201,7 +211,7 @@ InternalManyRoutesResult inline RoutingAlgorithms<
}
template <>
inline std::vector<EdgeDuration>
inline std::vector<EdgeWeight>
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &,
const std::vector<std::size_t> &,
@@ -17,23 +17,11 @@ namespace routing_algorithms
{
template <typename Algorithm>
std::vector<EdgeDuration> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices);
namespace mld
{
template <bool DIRECTION>
std::vector<EdgeDuration> oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::size_t phantom_index,
std::vector<std::size_t> phantom_indices);
} // mld
std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices);
} // namespace routing_algorithms
} // namespace engine
@@ -132,16 +132,44 @@ retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward
}
template <bool DIRECTION, typename Algorithm, typename... Args>
void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
const NodeID node,
const EdgeWeight weight,
Args... args)
void routingStep(const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
NodeID &middle_node,
EdgeWeight &path_upper_bound,
const bool force_loop_forward,
const bool force_loop_reverse,
Args... args)
{
const auto &partition = facade.GetMultiLevelPartition();
const auto &cells = facade.GetCellStorage();
const auto &metric = facade.GetCellMetric();
const auto node = forward_heap.DeleteMin();
const auto weight = forward_heap.GetKey(node);
BOOST_ASSERT(!facade.ExcludeNode(node));
// Upper bound for the path source -> target with
// weight(source -> node) = weight weight(to -> target) ≤ reverse_weight
// is weight + reverse_weight
// More tighter upper bound requires additional condition reverse_heap.WasRemoved(to)
// with weight(to -> target) = reverse_weight and all weights ≥ 0
if (reverse_heap.WasInserted(node))
{
auto reverse_weight = reverse_heap.GetKey(node);
auto path_weight = weight + reverse_weight;
// if loops are forced, they are so at the source
if (!(force_loop_forward && forward_heap.GetData(node).parent == node) &&
!(force_loop_reverse && reverse_heap.GetData(node).parent == node) &&
(path_weight >= 0) && (path_weight < path_upper_bound))
{
middle_node = node;
path_upper_bound = path_weight;
}
}
const auto level = getNodeQueryLevel(partition, node, args...);
if (level >= 1 && !forward_heap.GetData(node).from_clique_arc)
@@ -230,45 +258,6 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
}
}
template <bool DIRECTION, typename Algorithm, typename... Args>
void routingStep(const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
NodeID &middle_node,
EdgeWeight &path_upper_bound,
const bool force_loop_forward,
const bool force_loop_reverse,
Args... args)
{
const auto node = forward_heap.DeleteMin();
const auto weight = forward_heap.GetKey(node);
BOOST_ASSERT(!facade.ExcludeNode(node));
// Upper bound for the path source -> target with
// weight(source -> node) = weight weight(to -> target) ≤ reverse_weight
// is weight + reverse_weight
// More tighter upper bound requires additional condition reverse_heap.WasRemoved(to)
// with weight(to -> target) = reverse_weight and all weights ≥ 0
if (reverse_heap.WasInserted(node))
{
auto reverse_weight = reverse_heap.GetKey(node);
auto path_weight = weight + reverse_weight;
// if loops are forced, they are so at the source
if (!(force_loop_forward && forward_heap.GetData(node).parent == node) &&
!(force_loop_reverse && reverse_heap.GetData(node).parent == node) &&
(path_weight >= 0) && (path_weight < path_upper_bound))
{
middle_node = node;
path_upper_bound = path_weight;
}
}
// Relax outgoing edges from node
relaxOutgoingEdges<DIRECTION>(facade, forward_heap, node, weight, args...);
}
// With (s, middle, t) we trace back the paths middle -> s and middle -> t.
// This gives us a packed path (node ids) from the base graph around s and t,
// and overlay node ids otherwise. We then have to unpack the overlay clique
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "osrm",
"version": "5.13.0-glibc.1",
"version": "5.13.0-cardinal.1",
"private": false,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
"dependencies": {
+74 -4
View File
@@ -1,12 +1,14 @@
-- Car profile
api_version = 2
api_version = 3
Set = require('lib/set')
Sequence = require('lib/sequence')
Handlers = require("lib/way_handlers")
Relations = require("lib/relations")
find_access_tag = require("lib/access").find_access_tag
limit = require("lib/maxspeed").limit
Utils = require("lib/utils")
function setup()
local use_left_hand_driving = false
@@ -250,7 +252,6 @@ function setup()
-- List only exceptions
maxspeed_table = {
["be:motorway"] = 120,
["ch:rural"] = 80,
["ch:trunk"] = 100,
["ch:motorway"] = 120,
@@ -280,7 +281,7 @@ function setup()
}
end
function process_node(profile, node, result)
function process_node(profile, node, result, relations)
-- parse access and barrier tags
local access = find_access_tag(node, profile.access_tags_hierarchy)
if access then
@@ -307,7 +308,7 @@ function process_node(profile, node, result)
end
end
function process_way(profile, way, result)
function process_way(profile, way, result, relations)
-- the intial filtering of ways based on presence of tags
-- affects processing times significantly, because all ways
-- have to be checked.
@@ -391,6 +392,74 @@ function process_way(profile, way, result)
}
WayHandlers.run(profile,way,result,data,handlers)
-- now process relations data
local matched_refs = nil;
if result.ref then
local match_res = Relations.match_to_ref(relations, result.ref)
local ref = ''
for _, m in pairs(match_res) do
if ref ~= '' then
ref = ref .. '; '
end
if m.dir then
ref = ref .. m.ref .. ' $' .. m.dir
else
ref = ref .. m.ref
end
end
result.ref = ref
end
end
function process_relation(profile, relation, result)
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
local route = relation:get_value_by_key("route")
if route == 'road' then
for _, m in ipairs(relation:members()) do
-- process case, where directions set as role
local role = string.lower(m:role())
if role == 'north' or role == 'south' or role == 'west' or role == 'east' then
result[m]['route_direction'] = role
add_extra_data(m)
end
end
end
local direction = relation:get_value_by_key('direction')
if direction then
direction = string.lower(direction)
if direction == 'north' or direction == 'south' or direction == 'west' or direction == 'east' then
for _, m in ipairs(relation:members()) do
if m:role() == 'forward' then
result[m]['route_direction'] = direction
add_extra_data(m)
end
end
end
end
end
end
function process_turn(profile, turn)
@@ -435,5 +504,6 @@ return {
setup = setup,
process_way = process_way,
process_node = process_node,
process_relation = process_relation,
process_turn = process_turn
}
+94
View File
@@ -0,0 +1,94 @@
-- 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 = {}
-- 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 = {}
for i, r in ipairs(order) do
result[i] = { ref = r, dir = result_match[r] };
end
return result
end
return Relations
+43
View 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
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
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
-2
View File
@@ -19,8 +19,6 @@ with open(taginfo_path) as f:
valid_strings = [t["key"] for t in taginfo["tags"]]
valid_strings += [t["value"] for t in taginfo["tags"] if "value" in t]
valid_strings += [t["value"].lower() for t in taginfo["tags"] if "value" in t] # lower is for max speed
valid_strings = set(valid_strings)
string_regxp = re.compile("\"([\d\w\_:]+)\"")
+9 -21
View File
@@ -145,8 +145,7 @@ class SVGPrinter (gdb.Command):
self.to_svg = {
'const osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<osrm::engine::routing_algorithms::ch::Algorithm> &': self.Facade,
'const osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<osrm::engine::routing_algorithms::corech::Algorithm> &': self.Facade,
'const osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<osrm::engine::routing_algorithms::mld::Algorithm> &': self.Facade,
'osrm::engine::DataFacade': self.Facade}
'const osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<osrm::engine::routing_algorithms::mld::Algorithm> &': self.Facade}
@staticmethod
@@ -259,27 +258,17 @@ class SVGPrinter (gdb.Command):
geometry_first = geometry['_M_impl']['_M_start']
for segment, weight in enumerate(iterate(weights)):
ref = 's' + str(node) + '.' + str(segment)
fr = lonlat(call(facade, 'GetCoordinateOfNode', geometry_first.dereference()))
to = lonlat(call(facade, 'GetCoordinateOfNode', (geometry_first+1).dereference()))
if fr == to:
## node penalty on zero length segment (traffic light)
result += '<text class="segment weight ' + direction \
+ '" x="' + str(tx(fr[0])) + '" y="' + str(ty(fr[1])) \
+ '" font="Arial" font-size="32" rotate="0" text-anchor="middle" >' \
+ '&#x1F6A6; ' + segment_weight(weight) + '</text>\n'
else:
## normal segment
result += '<path id="' + ref + '" class="segment" d="' \
+ 'M' + t(fr) + ' ' \
+ 'L' + t(to) + '" />'\
+ '<text class="segment weight ' + direction + '">'\
+ '<textPath xlink:href="#' + ref + '" startOffset="50%">' \
+ segment_weight(weight) + '</textPath></text>\n'
result += '<path id="' + ref + '" class="segment" d="' \
+ 'M' + t(lonlat(call(facade, 'GetCoordinateOfNode', geometry_first.dereference()))) + ' ' \
+ 'L' + t(lonlat(call(facade, 'GetCoordinateOfNode', (geometry_first+1).dereference()))) + '" />'\
+ '<text class="segment weight ' + direction + '">'\
+ '<textPath xlink:href="#' + ref + '" startOffset="50%">' \
+ segment_weight(weight) + '</textPath></text>\n'
geometry_first += 1
## add edge-based edges
s0, s1 = geometry['_M_impl']['_M_start'].dereference(), (geometry['_M_impl']['_M_start'] + 1).dereference()
for edge in []: # range(call(facade, 'BeginEdges', node), call(facade, 'EndEdges', node)): adjust to GetAdjacentEdgeRange
for edge in range(call(facade, 'BeginEdges', node), call(facade, 'EndEdges', node)):
target, edge_data = call(facade, 'GetTarget', edge), call(facade, 'GetEdgeData', edge)
direction = 'both' if edge_data['forward'] and edge_data['backward'] else 'forward' if edge_data['forward'] else 'backward'
target_geometry = SVGPrinter.getByGeometryId(facade, call(facade, 'GetGeometryIndex', target), 'Geometry')
@@ -334,8 +323,7 @@ class SVGPrinter (gdb.Command):
re_float = '[-+]?[0-9]*\.?[0-9]+'
bbox = re.search('(' + re_float + '),(' + re_float + ');(' + re_float + '),(' + re_float +')', arg)
bbox = [float(x) for x in bbox.groups()] if bbox else [-180, -90, 180, 90]
type = val.type.target().unqualified() if val.type.code == gdb.TYPE_CODE_REF else val.type
svg = self.to_svg[str(type)](val, width, height, bbox)
svg = self.to_svg[str(val.type)](val, width, height, bbox)
self.show_svg(svg, width, height)
except KeyError as e:
print ('no SVG printer for: ' + str(e))
-8
View File
@@ -1,8 +0,0 @@
# Configuration file for LeakSanitizer run on the Travis CI
# TBB leaks some memory allocated in singleton depending on deinitialization order
# Direct leak of 1560 byte(s) in 3 object(s) allocated from:
# #0 0x7f7ae72a80a0 in operator new[](unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.3+0xc80a0)
# #1 0x7f7ae595d13e (/usr/lib/x86_64-linux-gnu/libtbb.so.2+0x2213e)
leak:libtbb.so
-56
View File
@@ -1,56 +0,0 @@
#include "engine/routing_algorithms.hpp"
namespace osrm
{
namespace engine
{
template <typename Algorithm>
std::vector<EdgeDuration>
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const
{
return routing_algorithms::manyToManySearch(
heaps, *facade, phantom_nodes, source_indices, target_indices);
}
template std::vector<EdgeDuration>
RoutingAlgorithms<routing_algorithms::ch::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const;
template std::vector<EdgeDuration>
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const;
// One-to-many and many-to-one can be handled with MLD separately from many-to-many search.
// One-to-many (many-to-one) search is a unidirectional forward (backward) Dijkstra search
// with the candidate node level min(GetQueryLevel(phantom_node, phantom_nodes, node)
template <>
std::vector<EdgeDuration> RoutingAlgorithms<routing_algorithms::mld::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const
{
if (source_indices.size() == 1)
{ // TODO: check if target_indices.size() == 1 and do a bi-directional search
return routing_algorithms::mld::oneToManySearch<routing_algorithms::FORWARD_DIRECTION>(
heaps, *facade, phantom_nodes, source_indices.front(), target_indices);
}
if (target_indices.size() == 1)
{
return routing_algorithms::mld::oneToManySearch<routing_algorithms::REVERSE_DIRECTION>(
heaps, *facade, phantom_nodes, target_indices.front(), source_indices);
}
return routing_algorithms::manyToManySearch(
heaps, *facade, phantom_nodes, source_indices, target_indices);
}
} // namespace engine
} // namespace osrm
+21 -251
View File
@@ -104,8 +104,7 @@ void relaxOutgoingEdges(const DataFacade<ch::Algorithm> &facade,
query_heap.Insert(to, to_weight, {node, to_duration});
}
// Found a shorter Path -> Update weight
else if (std::tie(to_weight, to_duration) <
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
else if (to_weight < query_heap.GetKey(to))
{
// new parent
query_heap.GetData(to) = {node, to_duration};
@@ -121,60 +120,13 @@ addLoopWeight(const DataFacade<mld::Algorithm> &, const NodeID, EdgeWeight &, Ed
return false;
}
template <typename MultiLevelPartition>
inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
NodeID node,
const PhantomNode &phantom_node)
{
auto highest_diffrent_level = [&partition, node](const SegmentID &phantom_node) {
if (phantom_node.enabled)
return partition.GetHighestDifferentLevel(phantom_node.id, node);
return INVALID_LEVEL_ID;
};
return std::min(highest_diffrent_level(phantom_node.forward_segment_id),
highest_diffrent_level(phantom_node.reverse_segment_id));
}
template <typename MultiLevelPartition>
inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
NodeID node,
const std::vector<PhantomNode> &phantom_nodes,
const std::size_t phantom_index,
const std::vector<std::size_t> &phantom_indices)
{
auto min_level = [&partition, node](const PhantomNode &phantom_node) {
const auto &forward_segment = phantom_node.forward_segment_id;
const auto forward_level =
forward_segment.enabled ? partition.GetHighestDifferentLevel(node, forward_segment.id)
: INVALID_LEVEL_ID;
const auto &reverse_segment = phantom_node.reverse_segment_id;
const auto reverse_level =
reverse_segment.enabled ? partition.GetHighestDifferentLevel(node, reverse_segment.id)
: INVALID_LEVEL_ID;
return std::min(forward_level, reverse_level);
};
// Get minimum level over all phantoms of the highest different level with respect to node
// This is equivalent to min_{∀ source, target} partition.GetQueryLevel(source, node, target)
auto result = min_level(phantom_nodes[phantom_index]);
for (const auto &index : phantom_indices)
{
result = std::min(result, min_level(phantom_nodes[index]));
}
return result;
}
template <bool DIRECTION, typename... Args>
template <bool DIRECTION>
void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
const NodeID node,
const EdgeWeight weight,
const EdgeDuration duration,
typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap,
Args... args)
const PhantomNode &phantom_node)
{
BOOST_ASSERT(!facade.ExcludeNode(node));
@@ -182,7 +134,13 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
const auto &cells = facade.GetCellStorage();
const auto &metric = facade.GetCellMetric();
const auto level = getNodeQueryLevel(partition, node, args...);
auto highest_diffrent_level = [&partition, node](const SegmentID &phantom_node) {
if (phantom_node.enabled)
return partition.GetHighestDifferentLevel(phantom_node.id, node);
return INVALID_LEVEL_ID;
};
const auto level = std::min(highest_diffrent_level(phantom_node.forward_segment_id),
highest_diffrent_level(phantom_node.reverse_segment_id));
const auto &node_data = query_heap.GetData(node);
@@ -207,8 +165,7 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
{
query_heap.Insert(to, to_weight, {node, true, to_duration});
}
else if (std::tie(to_weight, to_duration) <
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
else if (to_weight < query_heap.GetKey(to))
{
query_heap.GetData(to) = {node, true, to_duration};
query_heap.DecreaseKey(to, to_weight);
@@ -237,8 +194,7 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
{
query_heap.Insert(to, to_weight, {node, true, to_duration});
}
else if (std::tie(to_weight, to_duration) <
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
else if (to_weight < query_heap.GetKey(to))
{
query_heap.GetData(to) = {node, true, to_duration};
query_heap.DecreaseKey(to, to_weight);
@@ -275,8 +231,7 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
query_heap.Insert(to, to_weight, {node, false, to_duration});
}
// Found a shorter Path -> Update weight
else if (std::tie(to_weight, to_duration) <
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
else if (to_weight < query_heap.GetKey(to))
{
// new parent
query_heap.GetData(to) = {node, false, to_duration};
@@ -327,7 +282,7 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
current_duration = std::min(current_duration, new_duration);
}
}
else if (std::tie(new_weight, new_duration) < std::tie(current_weight, current_duration))
else if (new_weight < current_weight)
{
current_weight = new_weight;
current_duration = new_duration;
@@ -358,11 +313,11 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
}
template <typename Algorithm>
std::vector<EdgeDuration> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices)
std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices)
{
if (source_indices.empty())
{
@@ -451,205 +406,20 @@ std::vector<EdgeDuration> manyToManySearch(SearchEngineData<Algorithm> &engine_w
return durations_table;
}
template std::vector<EdgeDuration>
template std::vector<EdgeWeight>
manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
const DataFacade<ch::Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices);
template std::vector<EdgeDuration>
template std::vector<EdgeWeight>
manyToManySearch(SearchEngineData<mld::Algorithm> &engine_working_data,
const DataFacade<mld::Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices);
namespace mld
{
// Unidirectional multi-layer Dijkstra search for 1-to-N and N-to-1 matrices
template <bool DIRECTION>
std::vector<EdgeDuration> oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::size_t phantom_index,
std::vector<std::size_t> phantom_indices)
{
if (phantom_indices.empty())
{
phantom_indices.resize(phantom_nodes.size());
std::iota(phantom_indices.begin(), phantom_indices.end(), 0);
}
std::vector<EdgeWeight> weights(phantom_indices.size(), INVALID_EDGE_WEIGHT);
std::vector<EdgeDuration> durations(phantom_indices.size(), MAXIMAL_EDGE_DURATION);
// Collect destination (source) nodes into a map
std::unordered_multimap<NodeID, std::tuple<std::size_t, EdgeWeight, EdgeDuration>>
target_nodes_index;
target_nodes_index.reserve(phantom_indices.size());
for (std::size_t index = 0; index < phantom_indices.size(); ++index)
{
const auto &phantom_index = phantom_indices[index];
const auto &phantom_node = phantom_nodes[phantom_index];
if (DIRECTION == FORWARD_DIRECTION)
{
if (phantom_node.IsValidForwardTarget())
target_nodes_index.insert(
{phantom_node.forward_segment_id.id,
std::make_tuple(index,
phantom_node.GetForwardWeightPlusOffset(),
phantom_node.GetForwardDuration())});
if (phantom_node.IsValidReverseTarget())
target_nodes_index.insert(
{phantom_node.reverse_segment_id.id,
std::make_tuple(index,
phantom_node.GetReverseWeightPlusOffset(),
phantom_node.GetReverseDuration())});
}
else if (DIRECTION == REVERSE_DIRECTION)
{
if (phantom_node.IsValidForwardSource())
target_nodes_index.insert(
{phantom_node.forward_segment_id.id,
std::make_tuple(index,
-phantom_node.GetForwardWeightPlusOffset(),
-phantom_node.GetForwardDuration())});
if (phantom_node.IsValidReverseSource())
target_nodes_index.insert(
{phantom_node.reverse_segment_id.id,
std::make_tuple(index,
-phantom_node.GetReverseWeightPlusOffset(),
-phantom_node.GetReverseDuration())});
}
}
// Initialize query heap
engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(facade.GetNumberOfNodes());
auto &query_heap = *(engine_working_data.many_to_many_heap);
// Check if node is in the destinations list and update weights/durations
auto update_values = [&](NodeID node, EdgeWeight weight, EdgeDuration duration) {
auto candidates = target_nodes_index.equal_range(node);
for (auto it = candidates.first; it != candidates.second;)
{
std::size_t index;
EdgeWeight target_weight;
EdgeDuration target_duration;
std::tie(index, target_weight, target_duration) = it->second;
const auto path_weight = weight + target_weight;
if (path_weight >= 0)
{
const auto path_duration = duration + target_duration;
if (std::tie(path_weight, path_duration) <
std::tie(weights[index], durations[index]))
{
weights[index] = path_weight;
durations[index] = path_duration;
}
// Remove node from destinations list
it = target_nodes_index.erase(it);
}
else
{
++it;
}
}
};
// Check a single path result and insert adjacent nodes into heap
auto insert_node = [&](NodeID node, EdgeWeight initial_weight, EdgeDuration initial_duration) {
// Update single node paths
update_values(node, initial_weight, initial_duration);
// Place adjacent nodes into heap
for (auto edge : facade.GetAdjacentEdgeRange(node))
{
const auto &data = facade.GetEdgeData(edge);
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
{
query_heap.Insert(facade.GetTarget(edge),
data.weight + initial_weight,
{node, data.duration + initial_duration});
}
}
};
{ // Place source (destination) adjacent nodes into the heap
const auto &phantom_node = phantom_nodes[phantom_index];
if (DIRECTION == FORWARD_DIRECTION)
{
if (phantom_node.IsValidForwardSource())
insert_node(phantom_node.forward_segment_id.id,
-phantom_node.GetForwardWeightPlusOffset(),
-phantom_node.GetForwardDuration());
if (phantom_node.IsValidReverseSource())
insert_node(phantom_node.reverse_segment_id.id,
-phantom_node.GetReverseWeightPlusOffset(),
-phantom_node.GetReverseDuration());
}
else if (DIRECTION == REVERSE_DIRECTION)
{
if (phantom_node.IsValidForwardTarget())
insert_node(phantom_node.forward_segment_id.id,
phantom_node.GetForwardWeightPlusOffset(),
phantom_node.GetForwardDuration());
if (phantom_node.IsValidReverseTarget())
insert_node(phantom_node.reverse_segment_id.id,
phantom_node.GetReverseWeightPlusOffset(),
phantom_node.GetReverseDuration());
}
}
while (!query_heap.Empty() && !target_nodes_index.empty())
{
// Extract node from the heap
const auto node = query_heap.DeleteMin();
const auto weight = query_heap.GetKey(node);
const auto duration = query_heap.GetData(node).duration;
// Update values
update_values(node, weight, duration);
// Relax outgoing edges
relaxOutgoingEdges<DIRECTION>(facade,
node,
weight,
duration,
query_heap,
phantom_nodes,
phantom_index,
phantom_indices);
}
return durations;
}
template std::vector<EdgeDuration>
oneToManySearch<FORWARD_DIRECTION>(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::size_t phantom_index,
std::vector<std::size_t> phantom_indices);
template std::vector<EdgeDuration>
oneToManySearch<REVERSE_DIRECTION>(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::size_t phantom_index,
std::vector<std::size_t> phantom_indices);
} // mld
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
+12 -25
View File
@@ -287,36 +287,23 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
return lane_description;
};
// If we could parse turn lanes but could not parse number of lanes,
// count the turn lanes and use them for the way's number of lanes.
auto road_classification = parsed_way.road_classification;
std::uint8_t road_deduced_num_lanes = 0;
// convert the lane description into an ID and, if necessary, remember the description in the
// description_map
const auto requestId = [&](const std::string &lane_string) {
if (lane_string.empty())
return INVALID_LANE_DESCRIPTIONID;
TurnLaneDescription lane_description = laneStringToDescription(std::move(lane_string));
return lane_description_map.ConcurrentFindOrAdd(lane_description);
};
// Deduplicates street names, refs, destinations, pronunciation, exits.
// In case we do not already store the key, inserts (key, id) tuple and return id.
// Otherwise fetches the id based on the name and returns it without insertion.
auto turn_lane_id_forward = INVALID_LANE_DESCRIPTIONID;
auto turn_lane_id_backward = INVALID_LANE_DESCRIPTIONID;
const auto turn_lane_id_forward = requestId(parsed_way.turn_lanes_forward);
const auto turn_lane_id_backward = requestId(parsed_way.turn_lanes_backward);
// RoadClassification represents a the class for unidirectional ways,
// therefore we need to add up deduced forward and backward lane counts.
if (!parsed_way.turn_lanes_forward.empty())
{
auto desc = laneStringToDescription(parsed_way.turn_lanes_forward);
turn_lane_id_forward = lane_description_map.ConcurrentFindOrAdd(desc);
road_deduced_num_lanes += desc.size();
}
if (!parsed_way.turn_lanes_backward.empty())
{
auto desc = laneStringToDescription(parsed_way.turn_lanes_backward);
turn_lane_id_backward = lane_description_map.ConcurrentFindOrAdd(desc);
road_deduced_num_lanes += desc.size();
}
road_classification.SetNumberOfLanes(std::max(road_deduced_num_lanes, // len(turn:lanes)
road_classification.GetNumberOfLanes()));
const auto road_classification = parsed_way.road_classification;
// Get the unique identifier for the street name, destination, and ref
const auto name_iterator = string_map.find(MapKey(parsed_way.name,
-31
View File
@@ -1,31 +0,0 @@
#ifdef GLIBC_WORKAROUND
#include <stdexcept>
// https://github.com/bitcoin/bitcoin/pull/4042
// allows building against libstdc++-dev-4.9 while avoiding
// GLIBCXX_3.4.20 dep
// This is needed because libstdc++ itself uses this API - its not
// just an issue of your code using it, ughhh
// Note: only necessary on Linux
#ifdef __linux__
#define _ENABLE_GLIBC_WORKAROUND
#warning building with workaround
#else
#warning not building with workaround
#endif
#ifdef _ENABLE_GLIBC_WORKAROUND
namespace std
{
void __throw_out_of_range_fmt(const char *, ...) __attribute__((__noreturn__));
void __throw_out_of_range_fmt(const char *err, ...)
{
// Safe and over-simplified version. Ignore the format and print it as-is.
__throw_out_of_range(err);
}
}
#endif // _ENABLE_GLIBC_WORKAROUND
#endif // GLIBC_WORKAROUND
+24 -26
View File
@@ -144,32 +144,30 @@
{"key": "maxspeed", "value": "rural"},
{"key": "maxspeed", "value": "trunk"},
{"key": "maxspeed", "value": "motorway"},
{"key": "maxspeed", "value": "BE:motorway"},
{"key": "maxspeed", "value": "CH:rural"},
{"key": "maxspeed", "value": "CH:trunk"},
{"key": "maxspeed", "value": "CH:motorway"},
{"key": "maxspeed", "value": "DE:living_street"},
{"key": "maxspeed", "value": "DK:rural"},
{"key": "maxspeed", "value": "RU:living_street"},
{"key": "maxspeed", "value": "RU:urban"},
{"key": "maxspeed", "value": "UA:urban"},
{"key": "maxspeed", "value": "AT:rural"},
{"key": "maxspeed", "value": "DE:rural"},
{"key": "maxspeed", "value": "DK:rural"},
{"key": "maxspeed", "value": "AT:trunk"},
{"key": "maxspeed", "value": "CZ:trunk"},
{"key": "maxspeed", "value": "RO:trunk"},
{"key": "maxspeed", "value": "CZ:motorway"},
{"key": "maxspeed", "value": "DE:motorway"},
{"key": "maxspeed", "value": "RU:motorway"},
{"key": "maxspeed", "value": "GB:nsl_single"},
{"key": "maxspeed", "value": "GB:nsl_dual"},
{"key": "maxspeed", "value": "GB:motorway"},
{"key": "maxspeed", "value": "UK:nsl_single"},
{"key": "maxspeed", "value": "UK:nsl_dual"},
{"key": "maxspeed", "value": "UK:motorway"},
{"key": "maxspeed", "value": "NL:rural"},
{"key": "maxspeed", "value": "NL:trunk"},
{"key": "maxspeed", "value": "ch:rural"},
{"key": "maxspeed", "value": "ch:trunk"},
{"key": "maxspeed", "value": "ch:motorway"},
{"key": "maxspeed", "value": "de:living_street"},
{"key": "maxspeed", "value": "ru:living_street"},
{"key": "maxspeed", "value": "ru:urban"},
{"key": "maxspeed", "value": "ua:urban"},
{"key": "maxspeed", "value": "at:rural"},
{"key": "maxspeed", "value": "de:rural"},
{"key": "maxspeed", "value": "dk:rural"},
{"key": "maxspeed", "value": "at:trunk"},
{"key": "maxspeed", "value": "cz:trunk"},
{"key": "maxspeed", "value": "ro:trunk"},
{"key": "maxspeed", "value": "cz:motorway"},
{"key": "maxspeed", "value": "de:motorway"},
{"key": "maxspeed", "value": "ru:motorway"},
{"key": "maxspeed", "value": "gb:nsl_single"},
{"key": "maxspeed", "value": "gb:nsl_dual"},
{"key": "maxspeed", "value": "gb:motorway"},
{"key": "maxspeed", "value": "uk:nsl_single"},
{"key": "maxspeed", "value": "uk:nsl_dual"},
{"key": "maxspeed", "value": "uk:motorway"},
{"key": "maxspeed", "value": "nl:rural"},
{"key": "maxspeed", "value": "nl:trunk"},
{"key": "smoothness", "value": "intermediate"},
{"key": "smoothness", "value": "bad"},
{"key": "smoothness", "value": "very_bad"},