Compare commits

...

57 Commits

Author SHA1 Message Date
Daniel Patterson 1cd1d187d2 Official 5.11.0 release 2017-08-17 14:43:50 -07:00
Daniel Patterson c1ad275e71 Empty CSV entries (nodeA,nodeA) can be treated as non-fatal as long as we don't try to update any matching artificial segments. 2017-08-16 12:03:23 -07:00
Daniel J. Hofmann 6bae070091 Fixes changelog wrt. conditional via-way restrictions 2017-08-16 11:15:35 +02:00
Moritz Kobitzsch 3687b6cb4b respect difference between continue/turn on changing end-of-road 2017-08-16 09:19:15 +02:00
Moritz Kobitzsch 196ed9eb46 do not change fork directions when combining turns 2017-08-16 09:17:01 +02:00
Daniel Patterson 37c941dff3 Bump version for 5.11.0-rc.2 2017-08-15 12:14:13 -07:00
Daniel Patterson 40a428d49f Fix changelog - binaries weren't published for 5.10 2017-08-15 12:13:20 -07:00
Daniel Patterson 48eeef2d30 Revert "Publicly expose binaries to Node.js bindings, resolves #4377"
This reverts commit 4686272f87.

Unfortunately, this doesn't work alongside `node-pre-gyp` - in fresh installs, the binary
files are not yet downloaded when npm tries to create symlinks, leading to an error.
2017-08-15 11:55:09 -07:00
Moritz Kobitzsch c34520f3a4 add feature to test naming conventions on divided highways 2017-08-15 09:47:13 +02:00
Daniel Patterson 36db965c39 Update npm version for RC.1 2017-08-14 17:16:45 -07:00
Daniel Patterson 4e81764ce2 Update CHANGELOG for changes since 5.10 2017-08-14 17:16:05 -07:00
Michael Krasnyk 1e9f983289 Add mocked offline datafacade to engine tests 2017-08-14 16:18:36 +02:00
Michael Krasnyk 2e404c60f4 Remove references to external sources 2017-08-14 16:18:36 +02:00
vng 40857aae61 Inject offline compressed data facade with OSRM_EXTERNAL_MEMORY option. 2017-08-14 16:18:36 +02:00
vng a64145b712 Fixed mld algorithm to use template data facade. 2017-08-14 16:18:36 +02:00
vng 945f6da85e Removed useless include. 2017-08-14 16:18:36 +02:00
vng 76d5d054cb Compilation fix. 2017-08-14 16:18:36 +02:00
Michael Krasnyk 20cfa159ec Fix boost::optional construction error 2017-08-11 17:32:35 +02:00
Daniel J. Hofmann 3ff1a4263d Adds releasing docs about bumping to latest, see #4386 2017-08-11 15:53:14 +02:00
Patrick Niklaus 3141eb5dce [skip ci] Update CONTRIBUTING.md to include correct pre-commit hook 2017-08-11 10:06:07 +00:00
Daniel J. Hofmann 75d6f59026 Publicly expose binaries to Node.js bindings, resolves #4377 2017-08-11 12:04:53 +02:00
Daniel J. Hofmann ae42ce7017 [skip ci] Updates lockfile for latest master version 2017-08-11 12:04:53 +02:00
Moritz Kobitzsch e9c9c87bbc adjust geojson logger to changes in extractor 2017-08-11 12:03:40 +02:00
Michael Krasnyk 8a6dba46b1 Change windows time zones in West Africa to WAT zone 2017-08-11 11:53:25 +02:00
Moritz Kobitzsch 93299d6651 handle conditional via-way restrictions
- refactor conditional restriction handling to not use external data (first OSM nodes on ways)
 - BREAKING: changes internal file format of osrm.restrictions
 - add support for general conditional penalties based on edge-based nodes (requires unique edges between nodes)
2017-08-11 11:53:25 +02:00
vng f34320a89b Fixed getting entry bearing for maneuver. 2017-08-11 11:40:58 +02:00
Moritz Kobitzsch a17b07bc4c fix bug in conflict resolution 2017-08-11 11:01:54 +02:00
Moritz Kobitzsch 3a01ba52ef remove a few tests that are simply testing same code paths as others 2017-08-10 12:28:31 +02:00
Mateusz Loskot d796c66990 Prefer implicit expansion of CMake variables
Unify CMAKE_CXX_COMPILER_ID tests without quoting/bracketing
the variable to use implicit expansion.
Replace STREQUAL with MATCHES to avoid policy warning about
attempt to expand "MSVC" variable, where it literal is intended.
2017-08-10 12:26:48 +02:00
Mateusz Loskot 80b705e997 Add workaround for Visual C++ issue with std::array in debug
If Visual C++ _ITERATOR_DEBUG_LEVEL > 0, then
accessing std::array<char[N], M> elements via reference to const
causes compilation error:

...\msvc\14.10.25017\include\array(181): error C2440: 'return': cannot convert from 'const char *' to 'const char (&)[256]'

Alternative workaround is to remove const qualifier from the GetClassName method.
2017-08-10 12:21:42 +02:00
Moritz Kobitzsch 7069af3e20 explicitly use local eslint version for linting 2017-08-09 14:14:44 +02:00
Daniel J. Hofmann 209a926b45 Re-adds .npmignore, resolves #4193 2017-08-08 16:16:35 +02:00
Mateusz Loskot 71e0c7a3cf Add define WIN32_LEAN_AND_MEAN for Visual C++
Helps to avoid compiler C2011 errors due to WinSock types redefinition
from dual #include of winsock.h and winsock2.h
2017-08-08 15:50:47 +02:00
Daniel J. Hofmann b88d96f07d [skip ci] Updates lockfiles 2017-08-08 11:37:20 +02:00
Daniel J. Hofmann 46f75c3d92 [skip ci] Bumps version to 5.11 2017-08-08 11:37:20 +02:00
Mateusz Loskot 3b8e5cec88 Ignore build directories starting with _build
Convenient to manage multiple builds with basic
naming convention (eg. _build.gcc7, _build.vs2017).

[ci skip]
2017-08-08 11:14:39 +02:00
FILLAU Jean-Maxime a420169109 Reintroduce location for NodeRef in luabinding 2017-08-08 10:59:25 +02:00
Michael Krasnyk a8db269fd5 Adjust lower bound for crossroad angle in sliproads handler, #4348/2 2017-08-04 14:37:13 +02:00
Michael Krasnyk a5efcfdede Sliproads test case with acute angle at the main intersection 2017-08-04 14:37:13 +02:00
Michael Krasnyk 1ecc913fc2 Fix sliproad scenario with 4 roads in a target intersection, #4348/1 2017-08-04 14:07:35 +02:00
Michael Krasnyk 08eb3b11bc Test case for sliproad handling with 4 roads at target intersection 2017-08-04 14:07:35 +02:00
Moritz Kobitzsch b59d9a2f27 update test-case for changed turn angles 2017-08-04 12:57:55 +02:00
Moritz Kobitzsch e9a5e32330 fix prevention of copy elision 2017-08-04 12:57:55 +02:00
Moritz Kobitzsch be9bdfa47e adjust constants for changed turn angle 2017-08-04 11:20:31 +02:00
Moritz Kobitzsch 153e934ed4 shift circle angle a bit 2017-08-04 11:20:31 +02:00
Michael Krasnyk 4757c96d9a Add a check for non-empty segments in CSV speed files 2017-08-04 11:19:32 +02:00
Michael Krasnyk 1efc527281 Test with a traffic update on an edge with traffic signal 2017-08-04 11:19:32 +02:00
Moritz Kobitzsch 468b59c53d add changelog entry for compression of traffic signals 2017-08-04 11:19:32 +02:00
Moritz Kobitzsch 15426975b6 deduplicate geometry 2017-08-04 11:19:32 +02:00
Moritz Kobitzsch bbcf343e40 compress traffic signals
- handle penalties within edges (not phantom nodes)
 - changes model from providing penalties on turns to using additional segments
2017-08-04 11:19:32 +02:00
Moritz Kobitzsch f0d3cf4e43 removing duplicated test 2017-08-04 11:19:32 +02:00
Moritz Kobitzsch 4c965b9f44 Add regression test for interaction between via-way and via-node 2017-08-03 14:37:05 +02:00
Moritz Kobitzsch e5143247c2 move babel to dev dependencies, update releasing docs to reflect scripts in package.json 2017-08-03 14:31:41 +02:00
Daniel J. Hofmann 3a676183b2 Updates our node osrm docs and re-runs docs generation, resolves #4043 2017-08-03 14:31:41 +02:00
Daniel J. Hofmann 64265926a4 Adds babel transformation needed for node osrm docs 2017-08-03 14:31:41 +02:00
Michael Krasnyk df2d4daad3 Fix gcc5 internal compilation error 2017-08-02 10:25:38 +02:00
Michael Krasnyk fd0d79e17b Update pre-installed TBB version to 2017_U7 2017-08-02 10:25:38 +02:00
103 changed files with 6191 additions and 3331 deletions
+1
View File
@@ -1,4 +1,5 @@
{ {
"plugins": ["transform-class-properties"],
"presets": [ "presets": [
"stage-0", "stage-0",
"es2015", "es2015",
+1
View File
@@ -46,6 +46,7 @@ Thumbs.db
# build related files # # build related files #
####################### #######################
/_build*
/build/ /build/
/example/build/ /example/build/
/test/data/monaco* /test/data/monaco*
+15
View File
@@ -0,0 +1,15 @@
*
!README.md
!CHANGELOG.md
!CONTRIBUTING.MD
!LICENCE.TXT
!package.json
!package-lock.json
!yarn.lock
!docs
!example
!taginfo.json
!lib/*.js
!profiles/*
!profiles/lib/*
!profiles/examples/*
+1 -1
View File
@@ -301,7 +301,7 @@ before_install:
- mkdir -p ${CMAKE_DIR} - mkdir -p ${CMAKE_DIR}
- travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C ${CMAKE_DIR} || travis_terminate 1 - travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C ${CMAKE_DIR} || travis_terminate 1
- export PATH=${CMAKE_DIR}/bin:${PATH} - export PATH=${CMAKE_DIR}/bin:${PATH}
- ${MASON} install tbb 2017_20161128 && export LD_LIBRARY_PATH=$(${MASON} prefix tbb 2017_20161128)/lib/:${LD_LIBRARY_PATH} - ${MASON} install tbb 2017_U7 && export LD_LIBRARY_PATH=$(${MASON} prefix tbb 2017_U7)/lib/:${LD_LIBRARY_PATH}
- ${MASON} install ccache ${CCACHE_VERSION} && export PATH=$(${MASON} prefix ccache ${CCACHE_VERSION})/bin:${PATH} - ${MASON} install ccache ${CCACHE_VERSION} && export PATH=$(${MASON} prefix ccache ${CCACHE_VERSION})/bin:${PATH}
- | - |
if [[ ! -z ${CLANG_VERSION} ]]; then if [[ ! -z ${CLANG_VERSION} ]]; then
+21
View File
@@ -1,3 +1,24 @@
# 5.11.0
- Changes from 5.10:
- Features
- BREAKING: Added support for conditional via-way restrictions. This features changes the file format of osrm.restrictions and requires re-extraction
- Internals
- BREAKING: Traffic signals will no longer be represented as turns internally. This requires re-processing of data but enables via-way turn restrictions across highway=traffic_signals
- Additional checks for empty segments when loading traffic data files
- Tunes the constants for turns in sharp curves just a tiny bit to circumvent a mix-up in fork directions at a specific intersection (https://github.com/Project-OSRM/osrm-backend/issues/4331)
- Infrastructure
- Refactor datafacade to make implementing additional DataFacades simpler
- Bugfixes
- API docs are now buildable again
- Suppress unnecessary extra turn instruction when exiting a motorway via a motorway_link onto a primary road (https://github.com/Project-OSRM/osrm-backend/issues/4348 scenario 4)
- Suppress unnecessary extra turn instruction when taking a tertiary_link road from a teritary onto a residential road (https://github.com/Project-OSRM/osrm-backend/issues/4348 scenario 2)
- Various MSVC++ build environment fixes
- Avoid a bug that crashes GCC6
- Re-include .npmignore to slim down published modules
- Fix a pre-processing bug where incorrect directions could be issued when two turns would have similar instructions and we tried to give them distinct values (https://github.com/Project-OSRM/osrm-backend/pull/4375)
- The entry bearing for correct the cardinality of a direction value (https://github.com/Project-OSRM/osrm-backend/pull/4353
- Change timezones in West Africa to the WAT zone so they're recognized on the Windows platform
# 5.10.0 # 5.10.0
- Changes from 5.9: - Changes from 5.9:
- Profiles: - Profiles:
+18 -17
View File
@@ -60,7 +60,7 @@ if (POLICY CMP0048)
endif() endif()
project(OSRM C CXX) project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5) set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 10) set(OSRM_VERSION_MINOR 11)
set(OSRM_VERSION_PATCH 0) set(OSRM_VERSION_PATCH 0)
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}") set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
@@ -102,11 +102,11 @@ if(WIN32 AND MSVC_VERSION LESS 1900)
endif() endif()
# Strictly require GCC>=4.9 and Clang>=3.4 - GCC 4.8 is already too old for C++14. # Strictly require GCC>=4.9 and Clang>=3.4 - GCC 4.8 is already too old for C++14.
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9)
message(FATAL_ERROR "GCC>=4.9 required. In case you are on Ubuntu upgrade via ppa:ubuntu-toolchain-r/test") message(FATAL_ERROR "GCC>=4.9 required. In case you are on Ubuntu upgrade via ppa:ubuntu-toolchain-r/test")
endif() endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4) if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4)
message(FATAL_ERROR "Clang>=3.4 required. In case you are on Ubuntu upgrade via http://apt.llvm.org") message(FATAL_ERROR "Clang>=3.4 required. In case you are on Ubuntu upgrade via http://apt.llvm.org")
endif() endif()
@@ -182,7 +182,7 @@ endif()
# Disable LTO when mason+gcc is detected before testing for / setting any flags. # Disable LTO when mason+gcc is detected before testing for / setting any flags.
# Mason builds libraries with Clang, mixing does not work in the context of lto. # Mason builds libraries with Clang, mixing does not work in the context of lto.
if(ENABLE_MASON AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND ENABLE_LTO) if(ENABLE_MASON AND CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND ENABLE_LTO)
set(ENABLE_LTO OFF) set(ENABLE_LTO OFF)
message(WARNING "Mason and GCC's LTO not work together. Disabling LTO.") message(WARNING "Mason and GCC's LTO not work together. Disabling LTO.")
endif() endif()
@@ -211,9 +211,9 @@ endif()
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)
message(STATUS "Configuring debug mode flags") message(STATUS "Configuring debug mode flags")
set(ENABLE_ASSERTIONS ON) set(ENABLE_ASSERTIONS ON)
if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC") if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-inline -fno-omit-frame-pointer") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-inline -fno-omit-frame-pointer")
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if (CMAKE_BUILD_TYPE MATCHES Debug) if (CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Og -ggdb") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Og -ggdb")
else() else()
@@ -232,7 +232,7 @@ if(CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES MinRelSize OR CM
if(ENABLE_LTO AND LTO_AVAILABLE) if(ENABLE_LTO AND LTO_AVAILABLE)
set(OLD_CXX_FLAGS ${CMAKE_CXX_FLAGS}) set(OLD_CXX_FLAGS ${CMAKE_CXX_FLAGS})
# GCC in addition allows parallelizing LTO # GCC in addition allows parallelizing LTO
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
include(ProcessorCount) include(ProcessorCount)
ProcessorCount(NPROC) ProcessorCount(NPROC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto=${NPROC}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto=${NPROC}")
@@ -255,7 +255,7 @@ if(CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES MinRelSize OR CM
endif() endif()
# Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools # Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND
NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0" AND NOT MINGW) NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0" AND NOT MINGW)
find_program(GCC_AR gcc-ar) find_program(GCC_AR gcc-ar)
find_program(GCC_RANLIB gcc-ranlib) find_program(GCC_RANLIB gcc-ranlib)
@@ -271,7 +271,7 @@ if(CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES MinRelSize OR CM
endif() endif()
# Same for clang LTO requires their own toolchain # Same for clang LTO requires their own toolchain
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
find_program(LLVM_AR llvm-ar) find_program(LLVM_AR llvm-ar)
find_program(LLVM_RANLIB llvm-ranlib) find_program(LLVM_RANLIB llvm-ranlib)
if ("${LLVM_AR}" STREQUAL "LLVM_AR-NOTFOUND" OR "${LLVM_RANLIB}" STREQUAL "LLVM_RANLIB-NOTFOUND") if ("${LLVM_AR}" STREQUAL "LLVM_AR-NOTFOUND" OR "${LLVM_RANLIB}" STREQUAL "LLVM_RANLIB-NOTFOUND")
@@ -285,7 +285,7 @@ if(CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES MinRelSize OR CM
endif() endif()
endif() endif()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0")
message(STATUS "Disabling LTO on GCC < 4.9.0 since it is broken, see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57038") message(STATUS "Disabling LTO on GCC < 4.9.0 since it is broken, see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57038")
set(CMAKE_CXX_FLAGS "${OLD_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${OLD_CXX_FLAGS}")
set(ENABLE_LTO Off) set(ENABLE_LTO Off)
@@ -315,9 +315,9 @@ if (ENABLE_SANITIZER)
endif() endif()
# Configuring compilers # Configuring compilers
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wuninitialized -Wunreachable-code -Wstrict-overflow=2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC -fcolor-diagnostics -ftemplate-depth=1024 -Wno-unused-command-line-argument") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wuninitialized -Wunreachable-code -Wstrict-overflow=2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC -fcolor-diagnostics -ftemplate-depth=1024 -Wno-unused-command-line-argument")
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(COLOR_FLAG "-fdiagnostics-color=auto") set(COLOR_FLAG "-fdiagnostics-color=auto")
check_cxx_compiler_flag("-fdiagnostics-color=auto" HAS_COLOR_FLAG) check_cxx_compiler_flag("-fdiagnostics-color=auto" HAS_COLOR_FLAG)
if(NOT HAS_COLOR_FLAG) if(NOT HAS_COLOR_FLAG)
@@ -337,13 +337,14 @@ elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
endif() endif()
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel") elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
# using Intel C++ # using Intel C++
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -ipo -fPIC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -ipo -fPIC")
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC") elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
# using Visual Studio C++ # using Visual Studio C++
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} zlib) set(BOOST_COMPONENTS ${BOOST_COMPONENTS} zlib)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") # avoid compiler error C1128 from scripting_environment_lua.cpp set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") # avoid compiler error C1128 from scripting_environment_lua.cpp
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /DWIN32_LEAN_AND_MEAN") # avoid compiler error C2011 from dual #include of winsock.h and winsock2.h
add_dependency_defines(-DBOOST_LIB_DIAGNOSTIC) add_dependency_defines(-DBOOST_LIB_DIAGNOSTIC)
add_dependency_defines(-D_CRT_SECURE_NO_WARNINGS) add_dependency_defines(-D_CRT_SECURE_NO_WARNINGS)
add_dependency_defines(-DNOMINMAX) # avoid min and max macros that can break compilation add_dependency_defines(-DNOMINMAX) # avoid min and max macros that can break compilation
@@ -359,7 +360,7 @@ execute_process(COMMAND ${CMAKE_CXX_COMPILER} "-Wl,--version" ERROR_QUIET OUTPUT
# For ld.gold and ld.bfs (the GNU linkers) we optimize hard # For ld.gold and ld.bfs (the GNU linkers) we optimize hard
if("${LINKER_VERSION}" MATCHES "GNU gold" OR "${LINKER_VERSION}" MATCHES "GNU ld") if("${LINKER_VERSION}" MATCHES "GNU gold" OR "${LINKER_VERSION}" MATCHES "GNU ld")
message(STATUS "Setting linker optimizations") message(STATUS "Setting linker optimizations")
if(NOT (${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC" OR "${LD_AVOID_GC_SECTIONS}")) if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR "${LD_AVOID_GC_SECTIONS}"))
# Tell compiler to put every function in separate section, linker can then match sections and functions # Tell compiler to put every function in separate section, linker can then match sections and functions
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
# Tell linker to do dead code and data eminination during link time discarding sections # Tell linker to do dead code and data eminination during link time discarding sections
@@ -377,7 +378,7 @@ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
# Activate C++1y # Activate C++1y
if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC") if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++1y") set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++1y")
endif() endif()
@@ -568,7 +569,7 @@ else()
endif() endif()
# prefix compilation with ccache by default if available and on clang or gcc # prefix compilation with ccache by default if available and on clang or gcc
if(ENABLE_CCACHE AND (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")) if(ENABLE_CCACHE AND (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU"))
find_program(CCACHE_FOUND ccache) find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND) if(CCACHE_FOUND)
message(STATUS "Using ccache to speed up incremental builds") message(STATUS "Using ccache to speed up incremental builds")
+1 -1
View File
@@ -18,7 +18,7 @@ if [ x"$remote" = xorigin ] ; then
echo "Rejected push to $remote/master" ; exit 1 echo "Rejected push to $remote/master" ; exit 1
fi fi
./scripts/format.sh ./scripts/format.sh && ./scripts/error_on_dirty.sh
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo "Unstaged format changes" ; exit 1 echo "Unstaged format changes" ; exit 1
fi fi
+30 -29
View File
@@ -27,11 +27,11 @@ var osrm = new OSRM('network.osrm');
This requires you to run `osrm-datastore` prior to creating an `OSRM` object. This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
- `options.path` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true. - `options.path` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true.
- `options.max_locations_trip` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in trip query (default: unlimited). - `options.max_locations_trip` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in trip query (default: unlimited).
- `options.max_locations_viaroute` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in viaroute query 9default: unlimited). - `options.max_locations_viaroute` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in viaroute query (default: unlimited).
- `options.max_locations_distance_table` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in distance table query (default: unlimited). - `options.max_locations_distance_table` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in distance table query (default: unlimited).
- `options.max_locations_map_matching` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in map matching query (default: unlimited). - `options.max_locations_map_matching` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in map-matching query (default: unlimited).
- `options.max_results_nearest` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. results supported in nearest query (default: unlimited). - `options.max_results_nearest` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. results supported in nearest query (default: unlimited).
- `options.max_alternatives` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. number of alternative routes supported (default: 3). - `options.max_alternatives` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max.number of alternatives supported in alternative routes query (default: 3).
### route ### route
@@ -45,15 +45,16 @@ Returns the fastest route between two or more coordinates while visiting the way
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`. Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`. - `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `null` (unlimited, default) or `double >= 0`.
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings. - `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.alternatives` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Search for alternative routes and return as well. - `options.alternatives` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Search for alternative routes. (optional, default `false`)
_Please note that even if an alternative route is requested, a result cannot be guaranteed._ (optional, default `false`) - `options.alternatives` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** Search for up to this many alternative routes.
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Returned route steps for each route leg. (optional, default `false`) _Please note that even if alternative routes are requested, a result cannot be guaranteed._ (optional, default `0`)
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route leg. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`) - `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`) - `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`) - `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.continue_straight` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. - `options.continue_straight` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile.
`null`/`true`/`false`
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`. - `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
`null`/`true`/`false`
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** - `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples** **Examples**
@@ -194,14 +195,14 @@ if they can not be matched successfully.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction. - `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`. Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings. - `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Returned route steps for each route. (optional, default `false`) - `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`) - `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`) - `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`) - `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.timestamps` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>?** Timestamp of the input location (integers, UNIX-like timestamp). - `options.timestamps` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>?** Timestamp of the input location (integers, UNIX-like timestamp).
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`. - `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`.
- `options.gaps` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Allows the input track splitting based on huge timestamp gaps between points. Either `split` or `ignore`. (optional, default `split`) - `options.gaps` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** Allows the input track splitting based on huge timestamp gaps between points. Either `split` or `ignore` (optional, default `split`).
- `options.tidy` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Allows the input track modification to obtain better matching quality for noisy tracks. (optional, default `false`) - `options.tidy` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Allows the input track modification to obtain better matching quality for noisy tracks (optional, default `false`).
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** - `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples** **Examples**
@@ -235,25 +236,7 @@ The trip plugin solves the Traveling Salesman Problem using a greedy heuristic
waypoints. The returned path does not have to be the shortest path, _ as TSP is NP-hard it is waypoints. The returned path does not have to be the shortest path, _ as TSP is NP-hard it is
only an approximation. only an approximation.
**Parameters** Note that all input coordinates have to be connected for the trip service to work.
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `double >= 0` or `null` (unlimited, default).
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Returned route steps for each route. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` (optional, default `simplified`)
- `options.roundtrip` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Returned route is a roundtrip (route returns to first location). (optional, default `true`)
- `options.source` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route starts at `any` or `first` coordinate. (optional, default `any`)
- `options.destination` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route ends at `any` or `last` coordinate. (optional, default `any`)
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
A requirement for computing trips is that all input coordinates are connected.
Currently, not all combinations of `roundtrip`, `source` and `destination` are supported. Currently, not all combinations of `roundtrip`, `source` and `destination` are supported.
Right now, the following combinations are possible: Right now, the following combinations are possible:
@@ -268,6 +251,24 @@ Right now, the following combinations are possible:
| false | any | last | no | | false | any | last | no |
| false | any | any | no | | false | any | any | no |
**Parameters**
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `options.coordinates` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The coordinates this request will use, coordinates as `[{lon},{lat}]` values, in decimal degrees.
- `options.bearings` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the search to segments with given bearing in degrees towards true north in clockwise direction.
Can be `null` or an array of `[{value},{range}]` with `integer 0 .. 360,integer 0 .. 180`.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Limits the coordinate snapping to streets in the given radius in meters. Can be `double >= 0` or `null` (unlimited, default).
- `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings.
- `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`)
- `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`)
- `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` (optional, default `simplified`)
- `options.roundtrip` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route is a roundtrip. (optional, default `true`)
- `options.source` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route starts at `any` or `first` coordinate. (optional, default `any`)
- `options.destination` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route ends at `any` or `last` coordinate. (optional, default `any`)
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples** **Examples**
```javascript ```javascript
+2 -2
View File
@@ -47,10 +47,10 @@ We may introduce forward-compatible changes: query parameters and response prope
4. Make sure the `package.json` is up to date. 4. Make sure the `package.json` is up to date.
5. Make sure all tests are passing (e.g. Travis CI gives you a :thumbs_up:) 5. Make sure all tests are passing (e.g. Travis CI gives you a :thumbs_up:)
6. Use an annotated tag to mark the release: `git tag vx.y.z -a` Body of the tag description should be the changelog entries. 6. Use an annotated tag to mark the release: `git tag vx.y.z -a` Body of the tag description should be the changelog entries.
7. Use `npm run build-api-docs` to generate the API documentation. Copy `build/docs/*` to `https://github.com/Project-OSRM/project-osrm.github.com` in the `docs/vN.N.N/api` directory 7. Use `npm run docs` to generate the API documentation. Copy `build/docs/*` to `https://github.com/Project-OSRM/project-osrm.github.com` in the `docs/vN.N.N/api` directory
8. Push tags and commits: `git push; git push --tags` 8. Push tags and commits: `git push; git push --tags`
9. If not a release-candidate: Write a mailing-list post to osrm-talk@openstreetmap.org to announce the release 9. If not a release-candidate: Write a mailing-list post to osrm-talk@openstreetmap.org to announce the release
10. Wait until the travis build has been completed and check if the node binaries were published by doing: 10. Wait until the travis build has been completed and check if the node binaries were published by doing:
`rm -rf node_modules && npm install` locally. `rm -rf node_modules && npm install` locally.
11. For final releases run `npm publish` or `npm publish --tag next` for release candidates. 11. For final releases run `npm publish` or `npm publish --tag next` for release candidates.
12. Bump version in `package.json` to `{MAJOR}.{MINOR+1}.0-latest.1` on the `master` branch after the release.
-7
View File
@@ -21,13 +21,6 @@ Feature: Bicycle - Handle cycling
When I route I should get When I route I should get
| from | to | route | modes | | from | to | route | modes |
| a | g | abc,cde,efg,efg | cycling,cycling,cycling,cycling | | a | g | abc,cde,efg,efg | cycling,cycling,cycling,cycling |
| b | f | abc,cde,efg,efg | cycling,cycling,cycling,cycling |
| e | c | cde,cde | cycling,cycling |
| e | b | cde,abc,abc | cycling,cycling,cycling |
| e | a | cde,abc,abc | cycling,cycling,cycling |
| c | e | cde,cde | cycling,cycling |
| c | f | cde,efg,efg | cycling,cycling,cycling |
| c | g | cde,efg,efg | cycling,cycling,cycling |
Scenario: Bicycle - Properly handle durations Scenario: Bicycle - Properly handle durations
Given the node map Given the node map
+23 -23
View File
@@ -21,15 +21,15 @@ Feature: Bike - Destination only, no passing through
| axye | | | axye | |
When I route I should get When I route I should get
| from | to | route | | from | to | route |
| a | b | ab,ab | | a | b | ab,ab |
| a | c | ab,bcd,bcd | | a | c | ab,bcd |
| a | d | ab,bcd,bcd | | a | d | ab,bcd |
| a | e | axye,axye | | a | e | axye,axye |
| e | d | de,de | | e | d | de,de |
| e | c | de,bcd,bcd | | e | c | de,bcd |
| e | b | de,bcd,bcd | | e | b | de,bcd |
| e | a | axye,axye | | e | a | axye,axye |
Scenario: Bike - Destination only street Scenario: Bike - Destination only street
Given the node map Given the node map
@@ -49,15 +49,15 @@ Feature: Bike - Destination only, no passing through
| axye | | | axye | |
When I route I should get When I route I should get
| from | to | route | | from | to | route |
| a | b | ab,ab | | a | b | ab,ab |
| a | c | ab,bc,bc | | a | c | ab,bc |
| a | d | ab,bc,cd,cd | | a | d | ab,bc,cd |
| a | e | axye,axye | | a | e | axye,axye |
| e | d | de,de | | e | d | de,de |
| e | c | de,cd,cd | | e | c | de,cd,cd |
| e | b | de,cd,bc,bc | | e | b | de,cd,bc |
| e | a | axye,axye | | e | a | axye,axye |
Scenario: Bike - Routing inside a destination only area Scenario: Bike - Routing inside a destination only area
Given the node map Given the node map
@@ -76,8 +76,8 @@ Feature: Bike - Destination only, no passing through
| axye | | | axye | |
When I route I should get When I route I should get
| from | to | route | | from | to | route |
| a | e | ab,bc,cd,de,de | | a | e | ab,bc,cd,de |
| e | a | de,cd,bc,ab,ab | | e | a | de,cd,bc,ab |
| b | d | bc,cd,cd | | b | d | bc,cd |
| d | b | cd,bc,bc | | d | b | cd,bc |
-5
View File
@@ -21,12 +21,7 @@ Feature: Bike - Handle ferry routes
When I route I should get When I route I should get
| from | to | route | | from | to | route |
| a | g | abc,cde,efg,efg | | a | g | abc,cde,efg,efg |
| b | f | abc,cde,efg,efg |
| e | c | cde,cde |
| e | b | cde,abc,abc |
| e | a | cde,abc,abc |
| c | e | cde,cde | | c | e | cde,cde |
| c | f | cde,efg,efg |
| c | g | cde,efg,efg | | c | g | cde,efg,efg |
Scenario: Bike - Ferry duration, single node Scenario: Bike - Ferry duration, single node
+1 -96
View File
@@ -20,11 +20,8 @@ Feature: Bike - Mode flag
When I route I should get When I route I should get
| from | to | route | modes | | from | to | route | modes |
| a | d | ab,bc,cd,cd | cycling,ferry,cycling,cycling | | a | d | ab,bc,cd,cd | cycling,ferry,cycling,cycling |
| d | a | cd,bc,ab,ab | cycling,ferry,cycling,cycling |
| c | a | bc,ab,ab | ferry,cycling,cycling | | c | a | bc,ab,ab | ferry,cycling,cycling |
| d | b | cd,bc,bc | cycling,ferry,ferry | | d | b | cd,bc,bc | cycling,ferry,ferry |
| a | c | ab,bc,bc | cycling,ferry,ferry |
| b | d | bc,cd,cd | ferry,cycling,cycling |
Scenario: Bike - Mode when using a train Scenario: Bike - Mode when using a train
Given the node map Given the node map
@@ -42,12 +39,10 @@ Feature: Bike - Mode flag
When I route I should get When I route I should get
| from | to | route | modes | | from | to | route | modes |
| a | d | ab,bc,cd,cd | cycling,train,cycling,cycling | | a | d | ab,bc,cd,cd | cycling,train,cycling,cycling |
| d | a | cd,bc,ab,ab | cycling,train,cycling,cycling |
| c | a | bc,ab,ab | train,cycling,cycling | | c | a | bc,ab,ab | train,cycling,cycling |
| d | b | cd,bc,bc | cycling,train,train | | d | b | cd,bc,bc | cycling,train,train |
| a | c | ab,bc,bc | cycling,train,train |
| b | d | bc,cd,cd | train,cycling,cycling |
#representative test for all pushes (and mode changes). Where a bike is pushed is tested over in access.feature
Scenario: Bike - Mode when pushing bike against oneways Scenario: Bike - Mode when pushing bike against oneways
Given the node map Given the node map
""" """
@@ -70,96 +65,6 @@ Feature: Bike - Mode flag
| d | a | cd,bc,ab,ab | cycling,pushing bike,cycling,cycling | | d | a | cd,bc,ab,ab | cycling,pushing bike,cycling,cycling |
| c | a | bc,ab,ab | pushing bike,cycling,cycling | | c | a | bc,ab,ab | pushing bike,cycling,cycling |
| d | b | cd,bc,bc | cycling,pushing bike,pushing bike | | d | b | cd,bc,bc | cycling,pushing bike,pushing bike |
| a | c | ab,bc,bc | cycling,cycling,cycling |
| b | d | bc,cd,cd | cycling,cycling,cycling |
Scenario: Bike - Mode when pushing on pedestrain streets
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway |
| ab | primary |
| bc | pedestrian |
| cd | primary |
When I route I should get
| from | to | route | modes |
| a | d | ab,bc,cd,cd | cycling,pushing bike,cycling,cycling |
| d | a | cd,bc,ab,ab | cycling,pushing bike,cycling,cycling |
| c | a | bc,ab,ab | pushing bike,cycling,cycling |
| d | b | cd,bc,bc | cycling,pushing bike,pushing bike |
| a | c | ab,bc,bc | cycling,pushing bike,pushing bike |
| b | d | bc,cd,cd | pushing bike,cycling,cycling |
Scenario: Bike - Mode when pushing on pedestrain areas
Given the node map
"""
a b
c d f
"""
And the ways
| nodes | highway | area |
| ab | primary | |
| bcd | pedestrian | yes |
| df | primary | |
When I route I should get
| from | to | route | modes |
| a | f | ab,bcd,df,df | cycling,pushing bike,cycling,cycling |
| f | a | df,bcd,ab,ab | cycling,pushing bike,cycling,cycling |
| d | a | bcd,ab,ab | pushing bike,cycling,cycling |
| f | b | df,bcd,bcd | cycling,pushing bike,pushing bike |
| a | d | ab,bcd,bcd | cycling,pushing bike,pushing bike |
| b | f | bcd,df,df | pushing bike,cycling,cycling |
Scenario: Bike - Mode when pushing on steps
Given the node map
"""
a b
c d f
"""
And the ways
| nodes | highway |
| ab | primary |
| bc | steps |
| cd | primary |
When I route I should get
| from | to | route | modes |
| a | d | ab,bc,cd,cd | cycling,pushing bike,cycling,cycling |
| d | a | cd,bc,ab,ab | cycling,pushing bike,cycling,cycling |
| c | a | bc,ab,ab | pushing bike,cycling,cycling |
| d | b | cd,bc,bc | cycling,pushing bike,pushing bike |
| a | c | ab,bc,bc | cycling,pushing bike,pushing bike |
| b | d | bc,cd,cd | pushing bike,cycling,cycling |
Scenario: Bike - Mode when bicycle=dismount
Given the node map
"""
a b
c d f
"""
And the ways
| nodes | highway | bicycle |
| ab | primary | |
| bc | primary | dismount |
| cd | primary | |
When I route I should get
| from | to | route | modes |
| a | d | ab,bc,cd,cd | cycling,pushing bike,cycling,cycling |
| d | a | cd,bc,ab,ab | cycling,pushing bike,cycling,cycling |
| c | a | bc,ab,ab | pushing bike,cycling,cycling |
| d | b | cd,bc,bc | cycling,pushing bike,pushing bike |
| a | c | ab,bc,bc | cycling,pushing bike,pushing bike |
| b | d | bc,cd,cd | pushing bike,cycling,cycling |
Scenario: Bicycle - Modes when starting on forward oneway Scenario: Bicycle - Modes when starting on forward oneway
Given the node map Given the node map
-47
View File
@@ -1,47 +0,0 @@
@routing @bicycle @ref @name
Feature: Bike - Way ref
Background:
Given the profile "bicycle"
Scenario: Bike - Way with both name and ref
Given the node map
"""
a b
"""
And the ways
| nodes | name | ref |
| ab | Utopia Drive | E7 |
When I route I should get
| from | to | route | ref |
| a | b | Utopia Drive,Utopia Drive | E7,E7 |
Scenario: Bike - Way with only ref
Given the node map
"""
a b
"""
And the ways
| nodes | name | ref |
| ab | | E7 |
When I route I should get
| from | to | route | ref |
| a | b | , | E7,E7 |
Scenario: Bike - Way with only name
Given the node map
"""
a b
"""
And the ways
| nodes | name |
| ab | Utopia Drive |
When I route I should get
| from | to | route |
| a | b | Utopia Drive,Utopia Drive |
+3 -182
View File
@@ -7,6 +7,8 @@ Feature: Bike - Turn restrictions
Given the profile "bicycle" Given the profile "bicycle"
Given a grid size of 200 meters Given a grid size of 200 meters
# check to see if bicycle profiles handle relations. The code path is the same as in cars.
# If relations are passed, all variants tested in car also work for bike
@no_turning @no_turning
Scenario: Bike - No left turn Scenario: Bike - No left turn
Given the node map Given the node map
@@ -33,188 +35,7 @@ Feature: Bike - Turn restrictions
| s | n | sj,nj,nj | | s | n | sj,nj,nj |
| s | e | sj,ej,ej | | s | e | sj,ej,ej |
@no_turning ## exceptions are different for bike over car and need to be tested here
Scenario: Bike - No right turn
Given the node map
"""
n
w j e
s
"""
And the ways
| nodes | oneway | foot |
| sj | yes | no |
| nj | -1 | no |
| wj | -1 | no |
| ej | -1 | no |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sj | ej | j | no_right_turn |
When I route I should get
| from | to | route |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@no_turning
Scenario: Bike - No u-turn
Given the node map
"""
n
w j e
s
"""
And the ways
| nodes | oneway | foot |
| sj | yes | no |
| nj | -1 | no |
| wj | -1 | no |
| ej | -1 | no |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sj | wj | j | no_u_turn |
When I route I should get
| from | to | route |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@no_turning
Scenario: Bike - Handle any no_* relation
Given the node map
"""
n
w j e
s
"""
And the ways
| nodes | oneway | foot |
| sj | yes | no |
| nj | -1 | no |
| wj | -1 | no |
| ej | -1 | no |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sj | wj | j | no_weird_zigzags |
When I route I should get
| from | to | route |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@only_turning
Scenario: Bike - Only left turn
Given the node map
"""
n
w j e
s
"""
And the ways
| nodes | oneway | foot |
| sj | yes | no |
| nj | -1 | no |
| wj | -1 | no |
| ej | -1 | no |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sj | wj | j | only_left_turn |
When I route I should get
| from | to | route |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@only_turning
Scenario: Bike - Only right turn
Given the node map
"""
n
w j e
s
"""
And the ways
| nodes | oneway | foot |
| sj | yes | no |
| nj | -1 | no |
| wj | -1 | no |
| ej | -1 | no |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sj | ej | j | only_right_turn |
When I route I should get
| from | to | route |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@only_turning
Scenario: Bike - Only straight on
Given the node map
"""
n
w j e
s
"""
And the ways
| nodes | oneway | foot |
| sj | yes | no |
| nj | -1 | no |
| wj | -1 | no |
| ej | -1 | no |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sj | nj | j | only_straight_on |
When I route I should get
| from | to | route |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@no_turning
Scenario: Bike - Handle any only_* restriction
Given the node map
"""
n
w j e
s
"""
And the ways
| nodes | oneway | foot |
| sj | yes | no |
| nj | -1 | no |
| wj | -1 | no |
| ej | -1 | no |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sj | nj | j | only_weird_zigzags |
When I route I should get
| from | to | route |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@except @except
Scenario: Bike - Except tag and on no_ restrictions Scenario: Bike - Except tag and on no_ restrictions
Given the node map Given the node map
-9
View File
@@ -22,13 +22,7 @@ Feature: Car - Handle driving
When I route I should get When I route I should get
| from | to | route | modes | | from | to | route | modes |
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | | a | g | abc,cde,efg,efg | driving,driving,driving,driving |
| b | f | abc,cde,efg,efg | driving,driving,driving,driving |
| e | c | cde,cde | driving,driving |
| e | b | cde,abc,abc | driving,driving,driving |
| e | a | cde,abc,abc | driving,driving,driving | | e | a | cde,abc,abc | driving,driving,driving |
| c | e | cde,cde | driving,driving |
| c | f | cde,efg,efg | driving,driving,driving |
| c | g | cde,efg,efg | driving,driving,driving |
Scenario: Car - Control test without durations, osrm uses movable bridge speed to calculate duration Scenario: Car - Control test without durations, osrm uses movable bridge speed to calculate duration
Given the node map Given the node map
@@ -47,8 +41,6 @@ Feature: Car - Handle driving
When I route I should get When I route I should get
| from | to | route | modes | speed | time | | from | to | route | modes | speed | time |
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | 13 km/h | 340s +-1 | | a | g | abc,cde,efg,efg | driving,driving,driving,driving | 13 km/h | 340s +-1 |
| b | f | abc,cde,efg,efg | driving,driving,driving,driving | 9 km/h | 318s +-1 |
| c | e | cde,cde | driving,driving | 5 km/h | 295s +-1 |
| e | c | cde,cde | driving,driving | 5 km/h | 295s +-1 | | e | c | cde,cde | driving,driving | 5 km/h | 295s +-1 |
Scenario: Car - Properly handle durations Scenario: Car - Properly handle durations
@@ -68,6 +60,5 @@ Feature: Car - Handle driving
When I route I should get When I route I should get
| from | to | route | modes | speed | | from | to | route | modes | speed |
| a | g | abc,cde,efg,efg | driving,driving,driving,driving | 7 km/h | | a | g | abc,cde,efg,efg | driving,driving,driving,driving | 7 km/h |
| b | f | abc,cde,efg,efg | driving,driving,driving,driving | 5 km/h |
| c | e | cde,cde | driving,driving | 2 km/h | | c | e | cde,cde | driving,driving | 2 km/h |
| e | c | cde,cde | driving,driving | 2 km/h | | e | c | cde,cde | driving,driving | 2 km/h |
+279 -5
View File
@@ -72,6 +72,75 @@ Feature: Car - Turn restrictions
| n | m | nj,pjm,pjm | | n | m | nj,pjm,pjm |
| s | m | js,pjm,pjm | | s | m | js,pjm,pjm |
@no_turning @conditionals
Scenario: Car - Restriction With Compressed Geometry
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
|
i
|
j-k-l-m
|
s
"""
And the ways
| nodes |
| nij |
| js |
| jklm |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | nij | jklm | j | no_left_turn @ (Mo-Fr 07:00-10:30) |
When I route I should get
| from | to | route |
| n | m | nij,js,js,jklm,jklm |
@no_turning @conditionals
Scenario: Car - Restriction With Compressed Geometry and Traffic Signal
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 10am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
Given the node map
"""
n
|
i
|
j-k-l-m
|
s
"""
And the ways
| nodes |
| nij |
| js |
| jklm |
And the nodes
| node | highway |
| i | traffic_signal |
| k | traffic_signal |
And the relations
| type | way:from | way:to | node:via | restriction:conditional |
| restriction | nij | jklm | j | no_left_turn @ (Mo-Fr 07:00-10:30) |
When I route I should get
| from | to | route |
| n | m | nij,js,js,jklm,jklm |
@no_turning @conditionals @no_turning @conditionals
Scenario: Car - ignores except restriction Scenario: Car - ignores except restriction
Given the extract extra arguments "--parse-conditional-restrictions" Given the extract extra arguments "--parse-conditional-restrictions"
@@ -530,6 +599,81 @@ Feature: Car - Turn restrictions
| n | p | nj,js,js,jp,jp | | n | p | nj,js,js,jp,jp |
| m | p | mj,jp,jp | | m | p | mj,jp,jp |
@restriction-way
Scenario: Car - prohibit turn
Given the extract extra arguments "--parse-conditional-restrictions"
# 5pm Wed 02 May, 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
Given the node map
"""
c
|
| f
| |
b---e
| |
a d
"""
And the ways
| nodes |
| ab |
| bc |
| be |
| de |
| ef |
And the relations
| type | way:from | way:via | way:to | restriction:conditional |
| restriction | ab | be | de | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
When I route I should get
| from | to | route | turns | locations |
| a | d | ab,be,ef,ef,de,de | depart,turn right,turn left,continue uturn,new name straight,arrive | a,b,e,f,e,d |
| a | f | ab,be,ef,ef | depart,turn right,turn left,arrive | a,b,e,f |
| c | d | bc,be,de,de | depart,turn left,turn right,arrive | c,b,e,d |
| c | f | bc,be,ef,ef | depart,turn left,turn left,arrive | c,b,e,f |
# condition is off
@restriction-way
Scenario: Car - prohibit turn
Given the extract extra arguments "--parse-conditional-restrictions"
# time stamp for 12am on Tues, 02 May 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493726400"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493726400"
Given the node map
"""
c
|
| f
| |
b---e
| |
a d
"""
And the ways
| nodes |
| ab |
| bc |
| be |
| de |
| ef |
And the relations
| type | way:from | way:via | way:to | restriction:conditional |
| restriction | ab | be | de | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
When I route I should get
| from | to | route |
| a | d | ab,be,de,de |
| a | f | ab,be,ef,ef |
| c | d | bc,be,de,de |
| c | f | bc,be,ef,ef |
# https://www.openstreetmap.org/#map=18/38.91099/-77.00888 # https://www.openstreetmap.org/#map=18/38.91099/-77.00888
@no_turning @conditionals @no_turning @conditionals
Scenario: Car - DC North capitol situation, two on one off Scenario: Car - DC North capitol situation, two on one off
@@ -769,15 +913,145 @@ Feature: Car - Turn restrictions
| dg | | dg |
And the relations And the relations
| type | way:from | way:to | way:via | restriction:conditional | | type | way:from | way:via | way:to | restriction:conditional |
| restriction | ab | be | ef | no_uturn @ (Mo-Fr 07:00-11:00,16:00-18:30) | | restriction | ab | be | ef | no_uturn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
And the relations And the relations
| type | way:from | way:to | node:via | restriction:conditional | | type | way:from | way:to | node:via | restriction:conditional |
| restriction | ed | dg | d | no_uturn @ (Mo-Fr 07:00-11:00,16:00-18:30) | | restriction | ed | dg | d | no_uturn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
When I route I should get When I route I should get
| from | to | route | # | | from | to | route |
| a | f | ab,be,ef,ef | currently we do not handle conditional via-ways, this test will have to change when we do | | a | f | ab,bc,bc,be,ef,ef |
| f | 1 | ef,eh,gh,dg,dg | | | f | 1 | ef,eh,gh,dg,dg |
@restriction-way @overlap
Scenario: Car - prohibit turn
Given the extract extra arguments "--parse-conditional-restrictions"
# 5pm Wed 02 May, 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
Given the node map
"""
c
|
| f
| |
b---e
| |
a d
"""
And the ways
| nodes |
| ab |
| bc |
| be |
| de |
| ef |
And the relations
| type | way:from | way:via | way:to | restriction:conditional |
| restriction | ab | be | de | no_right_turn @ (Mo-Fr 07:00-11:00) |
And the relations
| type | way:from | way:via | way:to | restriction |
| restriction | ab | be | de | no_right_turn |
# condition is off, but the general restriction should take precedence
When I route I should get
| from | to | route | turns | locations |
| a | d | ab,be,ef,ef,de,de | depart,turn right,turn left,continue uturn,new name straight,arrive | a,b,e,f,e,d |
| a | f | ab,be,ef,ef | depart,turn right,turn left,arrive | a,b,e,f |
| c | d | bc,be,de,de | depart,turn left,turn right,arrive | c,b,e,d |
| c | f | bc,be,ef,ef | depart,turn left,turn left,arrive | c,b,e,f |
@restriction-way @overlap
Scenario: Car - prohibit turn
Given the extract extra arguments "--parse-conditional-restrictions"
# 5pm Wed 02 May, 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
Given the node map
"""
c
|
| f
| |
b---e
| |
| d
|
a
"""
And the ways
| nodes |
| ab |
| bc |
| be |
| de |
| ef |
And the relations
| type | way:from | way:via | way:to | restriction:conditional |
| restriction | ab | be | de | no_right_turn @ (Mo-Fr 07:00-11:00) |
And the relations
| type | way:from | node:via | way:to | restriction:conditional |
| restriction | be | e | de | no_right_turn @ (Mo-Fr 16:00-18:00) |
# way restriction is off, node-restriction is on
When I route I should get
| from | to | route | turns | locations |
| a | d | ab,be,ef,ef,de,de | depart,turn right,turn left,continue uturn,new name straight,arrive | a,b,e,f,e,d |
| a | f | ab,be,ef,ef | depart,turn right,turn left,arrive | a,b,e,f |
| c | d | bc,be,ef,ef,de,de | depart,turn left,turn left,continue uturn,new name straight,arrive | c,b,e,f,e,d |
| c | f | bc,be,ef,ef | depart,turn left,turn left,arrive | c,b,e,f |
@restriction-way @overlap
Scenario: Car - prohibit turn
Given the extract extra arguments "--parse-conditional-restrictions"
# 5pm Wed 02 May, 2017 GMT
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
Given the node map
"""
c
|
| f
| |
b---e
| |
| d
|
a
"""
And the ways
| nodes |
| ab |
| bc |
| be |
| de |
| ef |
And the relations
| type | way:from | way:via | way:to | restriction:conditional |
| restriction | ab | be | de | no_right_turn @ (Mo-Fr 16:00-18:00) |
And the relations
| type | way:from | node:via | way:to | restriction:conditional |
| restriction | be | e | de | no_right_turn @ (Mo-Fr 07:00-11:00) |
# node restrictino is off, way restriction is on
When I route I should get
| from | to | route | turns | locations |
| a | d | ab,be,ef,ef,de,de | depart,turn right,turn left,continue uturn,new name straight,arrive | a,b,e,f,e,d |
| a | f | ab,be,ef,ef | depart,turn right,turn left,arrive | a,b,e,f |
| c | d | bc,be,de,de | depart,turn left,turn right,arrive | c,b,e,d |
| c | f | bc,be,ef,ef | depart,turn left,turn left,arrive | c,b,e,f |
+18
View File
@@ -50,6 +50,7 @@ Feature: Car - Handle ferry routes
| b | f | abc,cde,efg,efg | driving,ferry,driving,driving | 9 km/h | 162.4s | | b | f | abc,cde,efg,efg | driving,ferry,driving,driving | 9 km/h | 162.4s |
| c | e | cde,cde | ferry,ferry | 5 km/h | 151.4s | | c | e | cde,cde | ferry,ferry | 5 km/h | 151.4s |
| e | c | cde,cde | ferry,ferry | 5 km/h | 151.4s | | e | c | cde,cde | ferry,ferry | 5 km/h | 151.4s |
Scenario: Car - Properly handle simple durations Scenario: Car - Properly handle simple durations
Given the node map Given the node map
""" """
@@ -91,3 +92,20 @@ Feature: Car - Handle ferry routes
| b | f | abc,cde,efg,efg | driving,ferry,driving,driving | 18 km/h | 78.4s | | b | f | abc,cde,efg,efg | driving,ferry,driving,driving | 18 km/h | 78.4s |
| c | e | cde,cde | ferry,ferry | 11 km/h | 67.4s | | c | e | cde,cde | ferry,ferry | 11 km/h | 67.4s |
| e | c | cde,cde | ferry,ferry | 11 km/h | 67.4s | | e | c | cde,cde | ferry,ferry | 11 km/h | 67.4s |
@snapping
Scenario: Car - Snapping when using a ferry
Given the node map
"""
a b c d e f
"""
And the ways
| nodes | highway | route | duration |
| ab | primary | | |
| bcde | | ferry | 0:10 |
| ef | primary | | |
When I route I should get
| from | to | route | modes | time |
| c | d | bcde,bcde | ferry,ferry | 600s |
-44
View File
@@ -1,44 +0,0 @@
@routing @car @mode
Feature: Car - Mode flag
Background:
Given the profile "car"
Scenario: Car - Mode when using a ferry
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | route | duration |
| ab | primary | | |
| bc | | ferry | 0:01 |
| cd | primary | | |
When I route I should get
| from | to | route | modes |
| a | d | ab,bc,cd,cd | driving,ferry,driving,driving |
| d | a | cd,bc,ab,ab | driving,ferry,driving,driving |
| c | a | bc,ab,ab | ferry,driving,driving |
| d | b | cd,bc,bc | driving,ferry,ferry |
| a | c | ab,bc,bc | driving,ferry,ferry |
| b | d | bc,cd,cd | ferry,driving,driving |
Scenario: Car - Snapping when using a ferry
Given the node map
"""
a b c d e f
"""
And the ways
| nodes | highway | route | duration |
| ab | primary | | |
| bcde | | ferry | 0:10 |
| ef | primary | | |
When I route I should get
| from | to | route | modes | time |
| c | d | bcde,bcde | ferry,ferry | 600s |
-16
View File
@@ -5,22 +5,6 @@ Feature: Car - Street names in instructions
Given the profile "car" Given the profile "car"
Given a grid size of 5 meters Given a grid size of 5 meters
Scenario: Car - A named street
Given the node map
"""
a b
c
"""
And the ways
| nodes | name | ref |
| ab | My Way | |
| bc | Your Way | A1 |
When I route I should get
| from | to | route | ref |
| a | c | My Way,Your Way | ,A1|
Scenario: Car - A named street with pronunciation Scenario: Car - A named street with pronunciation
Given the node map Given the node map
""" """
+42 -5
View File
@@ -954,11 +954,11 @@ Feature: Car - Turn restrictions
# this case is currently not handling the via-way restrictions and we need support for looking across traffic signals. # this case is currently not handling the via-way restrictions and we need support for looking across traffic signals.
# It is mainly included to show limitations and to prove that we don't crash hard here # It is mainly included to show limitations and to prove that we don't crash hard here
When I route I should get When I route I should get
| from | to | route | | from | to | route |
| a | d | ab,bge,de,de | | a | d | ab,bge,ef,ef,de,de |
| a | f | ab,bge,ef,ef | | a | f | ab,bge,ef,ef |
| c | d | bc,bge,de,de | | c | d | bc,bge,de,de |
| c | f | bc,bge,ef,ef | | c | f | bc,bge,de,de,ef,ef |
# don't crash hard on invalid restrictions # don't crash hard on invalid restrictions
@restriction @invalid @restriction @invalid
@@ -991,3 +991,40 @@ Feature: Car - Turn restrictions
When I route I should get When I route I should get
| from | to | route | | from | to | route |
| a | f | ab,be,ef,ef | | a | f | ab,be,ef,ef |
@restriction @overlap @geometry
Scenario: Duplicated restriction
Given the node map
"""
c
|
| f
| |
b-g-e
| |
| d
|
a
"""
And the ways
| nodes |
| ab |
| bc |
| bge |
| de |
| ef |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | bge | ef | e | no_left_turn |
And the relations
| type | way:from | way:via | way:to | restriction |
| restriction | ab | bge | de | no_right_turn |
| restriction | bc | bge | ef | no_left_turn |
When I route I should get
| from | to | route |
| a | d | ab,bc,bc,bge,de,de |
@@ -37,3 +37,57 @@ Feature: Car - Handle traffic lights
| 3 | 4 | 13.1s | no turn with traffic light | | 3 | 4 | 13.1s | no turn with traffic light |
| g | j | 18.7s | turn with no traffic light | | g | j | 18.7s | turn with no traffic light |
| k | n | 20.7s | turn with traffic light | | k | n | 20.7s | turn with traffic light |
Scenario: Tarrif Signal Geometry
Given the query options
| overview | full |
| geometries | polyline |
Given the node map
"""
a - b - c
"""
And the ways
| nodes | highway |
| abc | primary |
And the nodes
| node | highway |
| b | traffic_signals |
When I route I should get
| from | to | route | geometry |
| a | c | abc,abc | _ibE_ibE?gJ?gJ |
@traffic
Scenario: Traffic update on the edge with a traffic signal
Given the node map
"""
a - b - c
"""
And the ways
| nodes | highway |
| abc | primary |
And the nodes
| node | highway |
| b | traffic_signals |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,65
2,1,65
"""
And the query options
| annotations | datasources,nodes,speed,duration,weight |
When I route I should get
| from | to | route | speed | weights | time | distances | a:datasources | a:nodes | a:speed | a:duration | a:weight |
| a | c | abc,abc | 59 km/h | 24.2,0 | 24.2s | 399.9m,0m | 1:0 | 1:2:3 | 18:18 | 11.1:11.1 | 11.1:11.1 |
| c | a | abc,abc | 59 km/h | 24.2,0 | 24.2s | 399.9m,0m | 0:1 | 3:2:1 | 18:18 | 11.1:11.1 | 11.1:11.1 |
-6
View File
@@ -21,13 +21,7 @@ Feature: Foot - Handle ferry routes
When I route I should get When I route I should get
| from | to | route | modes | | from | to | route | modes |
| a | g | abc,cde,efg,efg | walking,ferry,walking,walking | | a | g | abc,cde,efg,efg | walking,ferry,walking,walking |
| b | f | abc,cde,efg,efg | walking,ferry,walking,walking |
| e | c | cde,cde | ferry,ferry |
| e | b | cde,abc,abc | ferry,walking,walking |
| e | a | cde,abc,abc | ferry,walking,walking | | e | a | cde,abc,abc | ferry,walking,walking |
| c | e | cde,cde | ferry,ferry |
| c | f | cde,efg,efg | ferry,walking,walking |
| c | g | cde,efg,efg | ferry,walking,walking |
Scenario: Foot - Ferry duration, single node Scenario: Foot - Ferry duration, single node
Given the node map Given the node map
+4 -20
View File
@@ -14,25 +14,9 @@ Feature: Foot - Street names in instructions
And the ways And the ways
| nodes | name | ref | | nodes | name | ref |
| ab | My Way | A6 | | ab | My Way | |
| bc | Your Way | B7 | | bc | | A7 |
When I route I should get When I route I should get
| from | to | route | | from | to | route | ref |
| a | c | My Way,Your Way,Your Way | | a | c | My Way,, | ,A7,A7 |
@unnamed
Scenario: Foot - No longer use way type to describe unnamed ways, see #3231
Given the node map
"""
a b c d
"""
And the ways
| nodes | highway | name |
| ab | footway | |
| bcd | track | |
When I route I should get
| from | to | route |
| a | d | , |
-47
View File
@@ -1,47 +0,0 @@
@routing @foot @ref @name
Feature: Foot - Way ref
Background:
Given the profile "foot"
Scenario: Foot - Way with both name and ref
Given the node map
"""
a b
"""
And the ways
| nodes | name | ref |
| ab | Utopia Drive | E7 |
When I route I should get
| from | to | route | ref |
| a | b | Utopia Drive,Utopia Drive | E7,E7 |
Scenario: Foot - Way with only ref
Given the node map
"""
a b
"""
And the ways
| nodes | name | ref |
| ab | | E7 |
When I route I should get
| from | to | route | ref |
| a | b | , | E7,E7 |
Scenario: Foot - Way with only name
Given the node map
"""
a b
"""
And the ways
| nodes | name |
| ab | Utopia Drive |
When I route I should get
| from | to | route |
| a | b | Utopia Drive,Utopia Drive |
-180
View File
@@ -32,84 +32,6 @@ Feature: Foot - Turn restrictions
| s | n | sj,nj,nj | | s | n | sj,nj,nj |
| s | e | sj,ej,ej | | s | e | sj,ej,ej |
@no_turning
Scenario: Foot - No right turn
Given the node map
"""
n
w j e
s
"""
And the ways
| nodes | oneway |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sj | ej | j | no_right_turn |
When I route I should get
| from | to | route |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@no_turning
Scenario: Foot - No u-turn
Given the node map
"""
n
w j e
s
"""
And the ways
| nodes | oneway |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sj | wj | j | no_u_turn |
When I route I should get
| from | to | route |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@no_turning
Scenario: Foot - Handle any no_* relation
Given the node map
"""
n
w j e
s
"""
And the ways
| nodes | oneway |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sj | wj | j | no_weird_zigzags |
When I route I should get
| from | to | route |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@only_turning @only_turning
Scenario: Foot - Only left turn Scenario: Foot - Only left turn
Given the node map Given the node map
@@ -136,84 +58,6 @@ Feature: Foot - Turn restrictions
| s | n | sj,nj,nj | | s | n | sj,nj,nj |
| s | e | sj,ej,ej | | s | e | sj,ej,ej |
@only_turning
Scenario: Foot - Only right turn
Given the node map
"""
n
w j e
s
"""
And the ways
| nodes | oneway |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sj | ej | j | only_right_turn |
When I route I should get
| from | to | route |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@only_turning
Scenario: Foot - Only straight on
Given the node map
"""
n
w j e
s
"""
And the ways
| nodes | oneway |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sj | nj | j | only_straight_on |
When I route I should get
| from | to | route |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@no_turning
Scenario: Foot - Handle any only_* restriction
Given the node map
"""
n
w j e
s
"""
And the ways
| nodes | oneway |
| sj | yes |
| nj | -1 |
| wj | -1 |
| ej | -1 |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sj | nj | j | only_weird_zigzags |
When I route I should get
| from | to | route |
| s | w | sj,wj,wj |
| s | n | sj,nj,nj |
| s | e | sj,ej,ej |
@except @except
Scenario: Foot - Except tag and on no_ restrictions Scenario: Foot - Except tag and on no_ restrictions
Given the node map Given the node map
@@ -246,30 +90,6 @@ Feature: Foot - Turn restrictions
| s | c | sj,cj,cj | | s | c | sj,cj,cj |
| s | d | sj,dj,dj | | s | d | sj,dj,dj |
@except
Scenario: Foot - Except tag and on only_ restrictions
Given the node map
"""
a b
j
s
"""
And the ways
| nodes | oneway |
| sj | yes |
| aj | no |
| bj | no |
And the relations
| type | way:from | way:to | node:via | restriction | except |
| restriction | sj | aj | j | only_straight_on | foot |
When I route I should get
| from | to | route |
| s | a | sj,aj,aj |
| s | b | sj,bj,bj |
@except @except
Scenario: Foot - Multiple except tag values Scenario: Foot - Multiple except tag values
Given the node map Given the node map
+2 -3
View File
@@ -1,10 +1,9 @@
@routing @foot @roundabout @instruction @routing @foot @roundabout @instruction @todo
Feature: Roundabout Instructions Feature: Roundabout Instructions
Background: Background:
Given the profile "foot" Given the profile "foot"
@todo
Scenario: Foot - Roundabout instructions Scenario: Foot - Roundabout instructions
# You can walk in both directions on a roundabout, bu the normal roundabout instructions don't # You can walk in both directions on a roundabout, bu the normal roundabout instructions don't
# make sense when you're going the opposite way around the roundabout. # make sense when you're going the opposite way around the roundabout.
@@ -27,7 +26,7 @@ Feature: Roundabout Instructions
| abcda | roundabout | | abcda | roundabout |
When I route I should get When I route I should get
| from | to | route | turns | | from | to | route | turns |
| s | t | sa,tb | depart,roundabout-exit-1,arrive | | s | t | sa,tb | depart,roundabout-exit-1,arrive |
| s | u | sa,uc | depart,roundabout-exit-2,arrive | | s | u | sa,uc | depart,roundabout-exit-2,arrive |
| s | v | sa,vd | depart,roundabout-exit-3,arrive | | s | v | sa,vd | depart,roundabout-exit-3,arrive |
+5 -5
View File
@@ -52,9 +52,9 @@ Feature: Turn Lane Guidance
| dy | | | YSt | | dy | | | YSt |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,e | MySt,MySt,MySt,MySt | depart,continue right,turn right,arrive | ,straight:false right:false right:true,left:false right:true, | | a,e | MySt,MySt,MySt,MySt | depart,continue right,continue right,arrive | ,straight:false right:false right:true,left:false right:true, |
| e,a | MySt,MySt,MySt,MySt | depart,continue left,turn left,arrive | ,left:true left:false straight:false,left:true right:false, | | e,a | MySt,MySt,MySt,MySt | depart,continue left,continue left,arrive | ,left:true left:false straight:false,left:true right:false, |
@anticipate @anticipate
Scenario: Anticipate Lane Change for quick same direction turns, changing between streets Scenario: Anticipate Lane Change for quick same direction turns, changing between streets
@@ -780,8 +780,8 @@ Feature: Turn Lane Guidance
| dy | | YSt | | dy | | YSt |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,e | MySt,MySt,MySt,MySt | depart,continue right,turn right,arrive | ,straight:false straight:false right:false right:true,left:false right:true, | | a,e | MySt,MySt,MySt,MySt | depart,continue right,continue right,arrive | ,straight:false straight:false right:false right:true,left:false right:true, |
@anticipate @anticipate
Scenario: Don't Overdo It Scenario: Don't Overdo It
+3 -3
View File
@@ -628,9 +628,9 @@ Feature: Collapse
| cf | secondary | bottom | | cf | secondary | bottom |
When I route I should get When I route I should get
| waypoints | turns | route | locations | | waypoints | turns | route | locations |
| a,d | depart,continue right,turn right,arrive | road,road,road,road | a,b,c,d | | a,d | depart,continue right,continue right,arrive | road,road,road,road | a,b,c,d |
| d,a | depart,continue left,turn left,arrive | road,road,road,road | d,c,b,a | | d,a | depart,continue left,continue left,arrive | road,road,road,road | d,c,b,a |
Scenario: Forking before a turn Scenario: Forking before a turn
Given the node map Given the node map
+21
View File
@@ -136,3 +136,24 @@ Feature: Continue Instructions
| a,d | abcdefb,abcdefb,abcdefb | depart,continue right,arrive | | a,d | abcdefb,abcdefb,abcdefb | depart,continue right,arrive |
# continuing right here, since the turn to the left is more expensive # continuing right here, since the turn to the left is more expensive
| a,e | abcdefb,abcdefb,abcdefb | depart,continue right,arrive | | a,e | abcdefb,abcdefb,abcdefb | depart,continue right,arrive |
Scenario: End-Of-Road Continue
Given the node map
"""
a - b - c
|
d - e
|
f
"""
And the ways
| nodes | highway | name |
| abc | primary | road |
| bdf | primary | road |
| ed | primary | turn |
When I route I should get
| waypoints | route | turns |
| e,a | turn,road,road,road | depart,turn right,continue left,arrive |
+54 -2
View File
@@ -863,8 +863,8 @@ Feature: Slipways and Dedicated Turn Lanes
| af | primary | sliproad | yes | | af | primary | sliproad | yes |
When I route I should get When I route I should get
| waypoints | route | turns | locations | | waypoints | route | turns | locations |
| s,g | main,sliproad,another,another | depart,turn right,turn left,arrive | s,a,f,g | | s,g | main,sliproad,another,another | depart,turn right,turn slight left,arrive | s,a,f,g |
@sliproads: @sliproads:
Scenario: Throughabout-Sliproad Scenario: Throughabout-Sliproad
@@ -944,3 +944,55 @@ Feature: Slipways and Dedicated Turn Lanes
When I route I should get When I route I should get
| waypoints | route | turns | locations | | waypoints | route | turns | locations |
| a,k | road,,, | depart,turn right,roundabout turn right exit-1,arrive | a,b,h,k | | a,k | road,,, | depart,turn right,roundabout turn right exit-1,arrive | a,b,h,k |
@sliproads
Scenario: Sliproad with 4 roads at target
Given the node map
"""
d
.
s . a . b . c . t
` . '
` . '
'.'
e
.
f
"""
And the ways
| nodes | highway | name | oneway |
| sabct | primary | sabct | |
| dbef | primary | dbef | |
| ae | primary_link | ae | yes |
| ec | primary_link | ec | yes |
When I route I should get
| waypoints | route | turns | locations |
| s,f | sabct,dbef,dbef | depart,turn right,arrive | s,a,f |
| f,t | dbef,sabct,sabct | depart,turn right,arrive | f,e,t |
@sliproads
Scenario: Sliproad and acute angle (50°) at the main intersection
Given the node map
"""
d
/
s . a . . b . c
` /
' /
e
/
f
"""
And the ways
| nodes | highway | name | oneway |
| sabc | primary | sabc | |
| dbef | primary | dbef | |
| ae | primary_link | ae | yes |
When I route I should get
| waypoints | route | turns | locations |
| s,f | sabc,dbef,dbef | depart,turn right,arrive | s,a,f |
+102
View File
@@ -0,0 +1,102 @@
@routing @guidance
Feature: Divided road entry
Background:
Given the profile "car"
Given a grid size of 5 meters
Scenario: Join on a divided road named after the main road
Given the node map
"""
a-------b-----c
|
d-------e-----f
|
|
g
"""
And the ways
| nodes | name | highway | oneway |
| abc | main st | residential | -1 |
| def | main st | residential | yes |
| be | main st | residential | |
| eg | side st | residential | |
When I route I should get
| waypoints | route | turns |
| g,a | side st,main st,main st| depart,end of road left,arrive |
# Similar to previous one, but the joining way is tagged with the side-street name
Scenario: Join on a divided road, named after the side street
Given the node map
"""
a-------b-----c
|
d-------e-----f
|
|
g
"""
And the ways
| nodes | name | highway | oneway |
| abc | main st | residential | -1 |
| def | main st | residential | yes |
| beg | side st | residential | |
When I route I should get
| waypoints | route | turns |
| g,a | side st,main st,main st| depart,end of road left,arrive |
# Center join named after crossroad
Scenario: Crossing a divided road, named after side-street
Given the node map
"""
h
|
a-------b-----c
|
d-------e-----f
|
|
g
"""
And the ways
| nodes | name | highway | oneway |
| abc | main st | residential | -1 |
| def | main st | residential | yes |
| hbeg | side st | residential | |
When I route I should get
| waypoints | route | turns |
| g,a | side st,main st,main st| depart,turn left,arrive |
# Join named after divided road
Scenario: Crossing a divided road, named after main street
Given the node map
"""
h
|
a-------b-----c
|
d-------e-----f
|
|
g
"""
And the ways
| nodes | name | highway | oneway |
| abc | main st | residential | -1 |
| def | main st | residential | yes |
| be | main st | residential | |
| hb | side st | residential | |
| eg | side st | residential | |
When I route I should get
| waypoints | route | turns |
| g,a | side st,main st,main st| depart,turn left,arrive |
+4 -2
View File
@@ -97,5 +97,7 @@ Feature: Simple Turns
| ei | left | yes | | ei | left | yes |
When I route I should get When I route I should get
| waypoints | route | turns | | waypoints | route | turns |
| g,a | in,road,road | depart,fork right,arrive | | g,a | in,road,road | depart,fork slight right,arrive |
| g,h | in,right,right | depart,fork straight,arrive |
| g,i | in,left,left | depart,fork slight left,arrive |
+11 -11
View File
@@ -809,14 +809,14 @@ Feature: Simple Turns
When I route I should get When I route I should get
| waypoints | route | turns | intersections | | waypoints | route | turns | intersections |
| a,g | Perle,Heide,Heide | depart,turn right,arrive | true:90;true:90 true:180 false:270 true:345;true:18 | | a,g | Perle,Heide,Heide | depart,turn right,arrive | true:90;true:90 true:195 false:270 true:345;true:18 |
| a,k | Perle,Friede,Friede | depart,turn left,arrive | true:90;true:90 true:180 false:270 true:345;true:153 | | a,k | Perle,Friede,Friede | depart,turn left,arrive | true:90;true:90 true:195 false:270 true:345;true:153 |
| a,e | Perle,Perle | depart,arrive | true:90,true:90 true:180 false:270 true:345;true:270 | | a,e | Perle,Perle | depart,arrive | true:90,true:90 true:195 false:270 true:345;true:270 |
| e,k | Perle,Friede,Friede | depart,turn right,arrive | true:270;false:90 true:180 true:270 true:345;true:153 | | e,k | Perle,Friede,Friede | depart,turn right,arrive | true:270;false:90 true:195 true:270 true:345;true:153 |
| e,g | Perle,Heide,Heide | depart,turn left,arrive | true:270;false:90 true:180 true:270 true:345;true:18 | | e,g | Perle,Heide,Heide | depart,turn left,arrive | true:270;false:90 true:195 true:270 true:345;true:18 |
| h,k | Heide,Friede | depart,arrive | true:16,true:90 true:180 true:270 true:345;true:153 | | h,k | Heide,Friede | depart,arrive | true:16,true:90 true:195 true:270 true:345;true:153 |
| h,e | Heide,Perle,Perle | depart,turn right,arrive | true:16;true:90 true:180 true:270 true:345;true:270 | | h,e | Heide,Perle,Perle | depart,turn right,arrive | true:16;true:90 true:195 true:270 true:345;true:270 |
| h,a | Heide,Perle,Perle | depart,turn left,arrive | true:16;true:90 true:180 true:270 true:345;true:90 | | h,a | Heide,Perle,Perle | depart,turn left,arrive | true:16;true:90 true:195 true:270 true:345;true:90 |
#http://www.openstreetmap.org/#map=19/52.53293/13.32956 #http://www.openstreetmap.org/#map=19/52.53293/13.32956
Scenario: Curved Exit from Curved Road Scenario: Curved Exit from Curved Road
@@ -1006,8 +1006,8 @@ Feature: Simple Turns
| waypoints | route | turns | | waypoints | route | turns |
| a,e | Heide,Heide,Heide | depart,continue uturn,arrive | | a,e | Heide,Heide,Heide | depart,continue uturn,arrive |
| a,g | Heide,Fenn,Fenn | depart,turn right,arrive | | a,g | Heide,Fenn,Fenn | depart,turn right,arrive |
| a,h | Heide,Friede,Friede | depart,turn slight left,arrive | | a,h | Heide,Friede,Friede | depart,turn left,arrive |
| i,e | Perle,Heide,Heide | depart,turn right,arrive | | i,e | Perle,Heide,Heide | depart,turn sharp right,arrive |
| i,h | Perle,Friede,Friede | depart,turn left,arrive | | i,h | Perle,Friede,Friede | depart,turn left,arrive |
#http://www.openstreetmap.org/#map=19/52.48630/13.36017 #http://www.openstreetmap.org/#map=19/52.48630/13.36017
@@ -1189,7 +1189,7 @@ Feature: Simple Turns
When I route I should get When I route I should get
| waypoints | route | turns | | waypoints | route | turns |
| a,c | rose,trift | depart,arrive | | a,c | rose,trift,trift | depart,turn slight left,arrive |
| a,k | rose,muhle,muhle | depart,turn slight right,arrive | | a,k | rose,muhle,muhle | depart,turn slight right,arrive |
| d,f | trift,rose | depart,arrive | | d,f | trift,rose | depart,arrive |
| d,k | trift,muhle,muhle | depart,turn sharp left,arrive | | d,k | trift,muhle,muhle | depart,turn sharp left,arrive |
+3 -3
View File
@@ -835,9 +835,9 @@ Feature: Turn Lane Guidance
| cf | secondary | bottom | | | cf | secondary | bottom | |
When I route I should get When I route I should get
| waypoints | turns | route | lanes | | waypoints | turns | route | lanes |
| a,d | depart,continue right,turn right,arrive | road,road,road,road | ,straight:false right:true,, | | a,d | depart,continue right,continue right,arrive | road,road,road,road | ,straight:false right:true,, |
| d,a | depart,continue left,turn left,arrive | road,road,road,road | ,left:true straight:false,, | | d,a | depart,continue left,continue left,arrive | road,road,road,road | ,left:true straight:false,, |
@simple @simple
Scenario: Merge Lanes Onto Freeway Scenario: Merge Lanes Onto Freeway
+3 -3
View File
@@ -788,9 +788,9 @@ Feature: Simple Turns
| bg | primary | yes | | bg | primary | yes |
When I route I should get When I route I should get
| waypoints | route | turns | | waypoints | route | turns |
| a,d | abc,bd,bd | depart,turn sharp right,arrive | | a,d | abc,bd,bd | depart,turn right,arrive |
| a,f | abc,bf,bf | depart,turn right,arrive | | a,f | abc,bf,bf | depart,turn slight right,arrive |
Scenario: Right Turn Assignment Three Conflicting Turns with invalid - 3 Scenario: Right Turn Assignment Three Conflicting Turns with invalid - 3
Given the node map Given the node map
-35
View File
@@ -1,35 +0,0 @@
@routing @datastore @testbot
Feature: Temporary tests related to osrm-datastore
Background:
Given the profile "testbot"
Scenario: Scenario ab
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
When I route I should get
| from | to | route |
| a | b | ab,ab |
| b | a | ab,ab |
Scenario: Scenaria xy
Given the node map
"""
x y
"""
And the ways
| nodes |
| xy |
When I route I should get
| from | to | route |
| x | y | xy,xy |
| y | x | xy,xy |
-20
View File
@@ -226,23 +226,3 @@ Feature: Distance calculation
| x | v | xv,xv | 424m +-1 | | x | v | xv,xv | 424m +-1 |
| x | w | xw,xw | 360m +-1 | | x | w | xw,xw | 360m +-1 |
| x | y | xy,xy | 316m +-1 | | x | y | xy,xy | 316m +-1 |
@maze
Scenario: Distance of a maze of short segments
Given a grid size of 7 meters
Given the node map
"""
a b s t
d c r q
e f o p
h g n m
i j k l
"""
And the ways
| nodes |
| abcdefghijklmnopqrst |
When I route I should get
| from | to | route | distance |
| a | t | abcdefghijklmnopqrst,abcdefghijklmnopqrst | 133m +-1 |
+10 -10
View File
@@ -21,12 +21,12 @@ Feature: Durations
| ef | primary | 01:02:03 | | ef | primary | 01:02:03 |
When I route I should get When I route I should get
| from | to | route | distance | time | | from | to | route | time |
| a | b | ab,ab | 100m +-1 | 60s +-1 | | a | b | ab,ab | 60s +-1 |
| b | c | bc,bc | 200m +-1 | 600s +-1 | | b | c | bc,bc | 600s +-1 |
| c | d | cd,cd | 300m +-1 | 3600s +-1 | | c | d | cd,cd | 3600s +-1 |
| d | e | de,de | 141m +-2 | 36000s +-1 | | d | e | de,de | 36000s +-1 |
| e | f | ef,ef | 224m +-2 | 3723s +-1 | | e | f | ef,ef | 3723s +-1 |
@todo @todo
Scenario: Partial duration of ways Scenario: Partial duration of ways
@@ -40,7 +40,7 @@ Feature: Durations
| abc | primary | 0:01 | | abc | primary | 0:01 |
When I route I should get When I route I should get
| from | to | route | distance | time | | from | to | route | time |
| a | c | abc,abc | 300m +-1 | 60s +-1 | | a | c | abc,abc | 60s +-1 |
| a | b | ab,ab | 100m +-1 | 20s +-1 | | a | b | ab,ab | 20s +-1 |
| b | c | bc,bc | 200m +-1 | 40s +-1 | | b | c | bc,bc | 40s +-1 |
-82
View File
@@ -5,51 +5,6 @@ Feature: Testbot - oneways
Given the profile "testbot" Given the profile "testbot"
Given a grid size of 250 meters Given a grid size of 250 meters
Scenario: Routing on a oneway roundabout
Given the node map
"""
v
x d c
e b
f a
g h y
z
"""
And the ways
| nodes | oneway |
| ab | yes |
| bc | yes |
| cd | yes |
| de | yes |
| ef | yes |
| fg | yes |
| gh | yes |
| ha | yes |
| vx | yes |
| vy | yes |
| yz | yes |
| xe | yes |
When I route I should get
| from | to | route |
| a | b | ab,ab |
| b | c | bc,bc |
| c | d | cd,cd |
| d | e | de,de |
| e | f | ef,ef |
| f | g | fg,fg |
| g | h | gh,gh |
| h | a | ha,ha |
| b | a | bc,cd,de,ef,fg,gh,ha,ha |
| c | b | cd,de,ef,fg,gh,ha,ab,ab |
| d | c | de,ef,fg,gh,ha,ab,bc,bc |
| e | d | ef,fg,gh,ha,ab,bc,cd,cd |
| f | e | fg,gh,ha,ab,bc,cd,de,de |
| g | f | gh,ha,ab,bc,cd,de,ef,ef |
| h | g | ha,ab,bc,cd,de,ef,fg,fg |
| a | h | ab,bc,cd,de,ef,fg,gh,gh |
Scenario: Testbot - Simple oneway Scenario: Testbot - Simple oneway
Then routability should be Then routability should be
| highway | foot | oneway | forw | backw | | highway | foot | oneway | forw | backw |
@@ -60,27 +15,6 @@ Feature: Testbot - oneways
| highway | foot | oneway | forw | backw | | highway | foot | oneway | forw | backw |
| primary | no | -1 | | x | | primary | no | -1 | | x |
Scenario: Testbot - Around the Block
Given the node map
"""
a b
e d c f
"""
And the ways
| nodes | oneway | foot |
| ab | yes | no |
| bc | | no |
| cd | | no |
| da | | no |
| de | | no |
| cf | | no |
When I route I should get
| from | to | route |
| a | b | ab,ab |
| b | a | bc,cd,da,da |
Scenario: Testbot - Handle various oneway tag values Scenario: Testbot - Handle various oneway tag values
Then routability should be Then routability should be
| foot | oneway | forw | backw | | foot | oneway | forw | backw |
@@ -93,19 +27,3 @@ Feature: Testbot - oneways
| no | true | x | | | no | true | x | |
| no | 1 | x | | | no | 1 | x | |
| no | -1 | | x | | no | -1 | | x |
Scenario: Testbot - Two consecutive oneways
Given the node map
"""
a b c
"""
And the ways
| nodes | oneway |
| ab | yes |
| bc | yes |
When I route I should get
| from | to | route |
| a | c | ab,bc,bc |
+53 -46
View File
@@ -26,6 +26,33 @@ Feature: Penalties
| a | c | abc,abc | 20s +-1 | 200m +-1 | | a | c | abc,abc | 20s +-1 | 200m +-1 |
| d | f | def,def | 27s +-1 | 200m +-1 | | d | f | def,def | 27s +-1 | 200m +-1 |
# Penalties not on the phantom nodes
Scenario: Traffic signals should incur a delay, without changing distance
Given the node map
"""
a b c d e
f g h i j
"""
And the nodes
| node | highway |
| c | traffic_signals |
And the ways
| nodes |
| ab |
| bcd |
| de |
| fg |
| ghi |
| ij |
When I route I should get
| from | to | route | time | distance |
| a | e | ab,bcd,de | 47s +-1 | 400m +-1 |
| f | j | fg,ghi,ij | 40s +-1 | 400m +-1 |
Scenario: Signal penalty should not depend on way type Scenario: Signal penalty should not depend on way type
Given the node map Given the node map
""" """
@@ -72,55 +99,35 @@ Feature: Penalties
| from | to | route | time | | from | to | route | time |
| a | e | abcde,abcde | 61s +-1 | | a | e | abcde,abcde | 61s +-1 |
@todo @todo
Scenario: Signal penalty should not depend on way type Scenario: Signal penalty should not depend on way type
Given the node map Given the node map
""" """
a b c a b c
d e f d e f
g h i g h i
""" """
And the nodes And the nodes
| node | highway | | node | highway |
| b | traffic_signals | | b | traffic_signals |
| e | traffic_signals | | e | traffic_signals |
| h | traffic_signals | | h | traffic_signals |
And the ways And the ways
| nodes | highway | | nodes | highway |
| abc | primary | | abc | primary |
| def | secondary | | def | secondary |
| ghi | tertiary | | ghi | tertiary |
When I route I should get When I route I should get
| from | to | route | time | | from | to | route | time |
| a | b | abc,abc | 10s +-1 | | a | b | abc,abc | 10s +-1 |
| a | c | abc,abc | 27s +-1 | | a | c | abc,abc | 27s +-1 |
| d | e | def,def | 20s +-1 | | d | e | def,def | 20s +-1 |
| d | f | def,def | 47s +-1 | | d | f | def,def | 47s +-1 |
| g | h | ghi,ghi | 30s +-1 | | g | h | ghi,ghi | 30s +-1 |
| g | i | ghi,ghi | 67s +-1 | | g | i | ghi,ghi | 67s +-1 |
Scenario: Passing multiple traffic signals should incur a accumulated delay
Given the node map
"""
a b c d e
"""
And the nodes
| node | highway |
| b | traffic_signals |
| c | traffic_signals |
| d | traffic_signals |
And the ways
| nodes |
| abcde |
When I route I should get
| from | to | route | time |
| a | e | abcde,abcde | 61s +-1 |
@todo @todo
Scenario: Starting or ending at a traffic signal should not incur a delay Scenario: Starting or ending at a traffic signal should not incur a delay
-9
View File
@@ -1,13 +1,6 @@
#ifndef OSRM_ENGINE_DATAFACADE_DATAFACADE_HPP #ifndef OSRM_ENGINE_DATAFACADE_DATAFACADE_HPP
#define OSRM_ENGINE_DATAFACADE_DATAFACADE_HPP #define OSRM_ENGINE_DATAFACADE_DATAFACADE_HPP
#ifdef OSRM_EXTERNAL_MEMORY
// Register your own data backend here
#error "No external memory implementation found"
#else
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp" #include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
namespace osrm namespace osrm
@@ -22,5 +15,3 @@ using DataFacade = datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>;
} }
#endif #endif
#endif
+27 -22
View File
@@ -11,6 +11,7 @@
#include "util/coordinate.hpp" #include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp" #include "util/coordinate_calculation.hpp"
#include <algorithm>
#include <utility> #include <utility>
#include <vector> #include <vector>
@@ -20,7 +21,6 @@ namespace engine
{ {
namespace guidance namespace guidance
{ {
// Extracts the geometry for each segment and calculates the traveled distance // Extracts the geometry for each segment and calculates the traveled distance
// Combines the geometry form the phantom node with the PathData // Combines the geometry form the phantom node with the PathData
// to the full route geometry. // to the full route geometry.
@@ -53,9 +53,9 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
source_node.fwd_segment_position + (reversed_source ? 1 : 0); source_node.fwd_segment_position + (reversed_source ? 1 : 0);
const auto source_node_id = const auto source_node_id =
reversed_source ? source_node.reverse_segment_id.id : source_node.forward_segment_id.id; reversed_source ? source_node.reverse_segment_id.id : source_node.forward_segment_id.id;
const auto source_gemetry_id = facade.GetGeometryIndex(source_node_id).id; const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id;
const std::vector<NodeID> source_geometry = std::vector<NodeID> source_geometry = facade.GetUncompressedForwardGeometry(source_geometry_id);
facade.GetUncompressedForwardGeometry(source_gemetry_id);
geometry.osm_node_ids.push_back( geometry.osm_node_ids.push_back(
facade.GetOSMNodeIDOfNode(source_geometry[source_segment_start_coordinate])); facade.GetOSMNodeIDOfNode(source_geometry[source_segment_start_coordinate]));
@@ -78,21 +78,26 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
} }
prev_coordinate = coordinate; prev_coordinate = coordinate;
geometry.annotations.emplace_back(LegGeometry::Annotation{
current_distance, const auto osm_node_id = facade.GetOSMNodeIDOfNode(path_point.turn_via_node);
// NOTE: we want annotations to include only the duration/weight if (osm_node_id != geometry.osm_node_ids.back())
// of the segment itself. For segments immediately before {
// a turn, the duration_until_turn/weight_until_turn values geometry.annotations.emplace_back(LegGeometry::Annotation{
// include the turn cost. To counter this, we subtract current_distance,
// the duration_of_turn/weight_of_turn value, which is 0 for // NOTE: we want annotations to include only the duration/weight
// non-preceeding-turn segments, but contains the turn value // of the segment itself. For segments immediately before
// for segments before a turn. // a turn, the duration_until_turn/weight_until_turn values
(path_point.duration_until_turn - path_point.duration_of_turn) / 10., // include the turn cost. To counter this, we subtract
(path_point.weight_until_turn - path_point.weight_of_turn) / // the duration_of_turn/weight_of_turn value, which is 0 for
facade.GetWeightMultiplier(), // non-preceeding-turn segments, but contains the turn value
path_point.datasource_id}); // for segments before a turn.
geometry.locations.push_back(std::move(coordinate)); (path_point.duration_until_turn - path_point.duration_of_turn) / 10.,
geometry.osm_node_ids.push_back(facade.GetOSMNodeIDOfNode(path_point.turn_via_node)); (path_point.weight_until_turn - path_point.weight_of_turn) /
facade.GetWeightMultiplier(),
path_point.datasource_id});
geometry.locations.push_back(std::move(coordinate));
geometry.osm_node_ids.push_back(osm_node_id);
}
} }
current_distance = current_distance =
util::coordinate_calculation::haversineDistance(prev_coordinate, target_node.location); util::coordinate_calculation::haversineDistance(prev_coordinate, target_node.location);
@@ -102,9 +107,9 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
const auto target_node_id = const auto target_node_id =
reversed_target ? target_node.reverse_segment_id.id : target_node.forward_segment_id.id; reversed_target ? target_node.reverse_segment_id.id : target_node.forward_segment_id.id;
const auto target_gemetry_id = facade.GetGeometryIndex(target_node_id).id; const auto target_geometry_id = facade.GetGeometryIndex(target_node_id).id;
const std::vector<DatasourceID> forward_datasources = const std::vector<DatasourceID> forward_datasources =
facade.GetUncompressedForwardDatasources(target_gemetry_id); facade.GetUncompressedForwardDatasources(target_geometry_id);
// FIXME if source and target phantoms are on the same segment then duration and weight // FIXME if source and target phantoms are on the same segment then duration and weight
// will be from one projected point till end of segment // will be from one projected point till end of segment
@@ -127,7 +132,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
const auto target_segment_end_coordinate = const auto target_segment_end_coordinate =
target_node.fwd_segment_position + (reversed_target ? 0 : 1); target_node.fwd_segment_position + (reversed_target ? 0 : 1);
const std::vector<NodeID> target_geometry = const std::vector<NodeID> target_geometry =
facade.GetUncompressedForwardGeometry(target_gemetry_id); facade.GetUncompressedForwardGeometry(target_geometry_id);
geometry.osm_node_ids.push_back( geometry.osm_node_ids.push_back(
facade.GetOSMNodeIDOfNode(target_geometry[target_segment_end_coordinate])); facade.GetOSMNodeIDOfNode(target_geometry[target_segment_end_coordinate]));
+4
View File
@@ -1,10 +1,14 @@
#ifndef RAW_ROUTE_DATA_H #ifndef RAW_ROUTE_DATA_H
#define RAW_ROUTE_DATA_H #define RAW_ROUTE_DATA_H
#include "extractor/class_data.hpp"
#include "extractor/guidance/turn_instruction.hpp" #include "extractor/guidance/turn_instruction.hpp"
#include "extractor/travel_mode.hpp" #include "extractor/travel_mode.hpp"
#include "engine/phantom_node.hpp" #include "engine/phantom_node.hpp"
#include "osrm/coordinate.hpp" #include "osrm/coordinate.hpp"
#include "util/guidance/entry_class.hpp" #include "util/guidance/entry_class.hpp"
#include "util/guidance/turn_bearing.hpp" #include "util/guidance/turn_bearing.hpp"
#include "util/guidance/turn_lanes.hpp" #include "util/guidance/turn_lanes.hpp"
-3
View File
@@ -5,9 +5,6 @@
#include "engine/plugins/plugin_base.hpp" #include "engine/plugins/plugin_base.hpp"
#include "engine/routing_algorithms.hpp" #include "engine/routing_algorithms.hpp"
#include "engine/map_matching/bayes_classifier.hpp"
#include "engine/routing_algorithms/map_matching.hpp"
#include "engine/routing_algorithms/shortest_path.hpp"
#include "util/json_util.hpp" #include "util/json_util.hpp"
#include <vector> #include <vector>
+1 -2
View File
@@ -5,8 +5,7 @@
#include "engine/api/table_parameters.hpp" #include "engine/api/table_parameters.hpp"
#include "engine/routing_algorithms.hpp" #include "engine/routing_algorithms.hpp"
#include "engine/routing_algorithms/many_to_many.hpp"
#include "engine/search_engine_data.hpp"
#include "util/json_container.hpp" #include "util/json_container.hpp"
namespace osrm namespace osrm
+2 -3
View File
@@ -3,10 +3,9 @@
#include "engine/plugins/plugin_base.hpp" #include "engine/plugins/plugin_base.hpp"
#include "engine/api/route_api.hpp" #include "engine/api/route_parameters.hpp"
#include "engine/datafacade/datafacade_base.hpp"
#include "engine/routing_algorithms.hpp" #include "engine/routing_algorithms.hpp"
#include "engine/search_engine_data.hpp"
#include "util/json_container.hpp" #include "util/json_container.hpp"
#include <cstdlib> #include <cstdlib>
@@ -134,23 +134,13 @@ void annotatePath(const FacadeT &facade,
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_segment_id.id == target_node_id || BOOST_ASSERT(phantom_node_pair.target_phantom.forward_segment_id.id == target_node_id ||
phantom_node_pair.target_phantom.reverse_segment_id.id == target_node_id); phantom_node_pair.target_phantom.reverse_segment_id.id == target_node_id);
auto node_from = unpacked_nodes.begin(), node_last = std::prev(unpacked_nodes.end()); // datastructures to hold extracted data from geometry
for (auto edge = unpacked_edges.begin(); node_from != node_last; ++node_from, ++edge) std::vector<NodeID> id_vector;
{ std::vector<EdgeWeight> weight_vector;
const auto &edge_data = facade.GetEdgeData(*edge); std::vector<EdgeWeight> duration_vector;
const auto turn_id = edge_data.turn_id; // edge-based graph edge index std::vector<DatasourceID> datasource_vector;
const auto node_id = *node_from; // edge-based graph node index
const auto name_index = facade.GetNameIndex(node_id);
const auto turn_instruction = facade.GetTurnInstructionForEdgeID(turn_id);
const extractor::TravelMode travel_mode = facade.GetTravelMode(node_id);
const auto classes = facade.GetClassData(node_id);
const auto geometry_index = facade.GetGeometryIndex(node_id); const auto get_segment_geometry = [&](const auto geometry_index) {
std::vector<NodeID> id_vector;
std::vector<EdgeWeight> weight_vector;
std::vector<EdgeWeight> duration_vector;
std::vector<DatasourceID> datasource_vector;
if (geometry_index.forward) if (geometry_index.forward)
{ {
id_vector = facade.GetUncompressedForwardGeometry(geometry_index.id); id_vector = facade.GetUncompressedForwardGeometry(geometry_index.id);
@@ -165,6 +155,22 @@ void annotatePath(const FacadeT &facade,
duration_vector = facade.GetUncompressedReverseDurations(geometry_index.id); duration_vector = facade.GetUncompressedReverseDurations(geometry_index.id);
datasource_vector = facade.GetUncompressedReverseDatasources(geometry_index.id); datasource_vector = facade.GetUncompressedReverseDatasources(geometry_index.id);
} }
};
auto node_from = unpacked_nodes.begin(), node_last = std::prev(unpacked_nodes.end());
for (auto edge = unpacked_edges.begin(); node_from != node_last; ++node_from, ++edge)
{
const auto &edge_data = facade.GetEdgeData(*edge);
const auto turn_id = edge_data.turn_id; // edge-based graph edge index
const auto node_id = *node_from; // edge-based graph node index
const auto name_index = facade.GetNameIndex(node_id);
const auto turn_instruction = facade.GetTurnInstructionForEdgeID(turn_id);
const extractor::TravelMode travel_mode = facade.GetTravelMode(node_id);
const auto classes = facade.GetClassData(node_id);
const auto geometry_index = facade.GetGeometryIndex(node_id);
get_segment_geometry(geometry_index);
BOOST_ASSERT(id_vector.size() > 0); BOOST_ASSERT(id_vector.size() > 0);
BOOST_ASSERT(datasource_vector.size() > 0); BOOST_ASSERT(datasource_vector.size() > 0);
BOOST_ASSERT(weight_vector.size() == id_vector.size() - 1); BOOST_ASSERT(weight_vector.size() == id_vector.size() - 1);
@@ -216,21 +222,14 @@ void annotatePath(const FacadeT &facade,
} }
std::size_t start_index = 0, end_index = 0; std::size_t start_index = 0, end_index = 0;
std::vector<unsigned> id_vector;
std::vector<EdgeWeight> weight_vector;
std::vector<EdgeWeight> duration_vector;
std::vector<DatasourceID> datasource_vector;
const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id; const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id;
const auto target_geometry_id = facade.GetGeometryIndex(target_node_id).id; const auto target_geometry = facade.GetGeometryIndex(target_node_id);
const auto is_local_path = source_geometry_id == target_geometry_id && unpacked_path.empty(); const auto is_local_path = source_geometry_id == target_geometry.id && unpacked_path.empty();
get_segment_geometry(target_geometry);
if (target_traversed_in_reverse) if (target_traversed_in_reverse)
{ {
id_vector = facade.GetUncompressedReverseGeometry(target_geometry_id);
weight_vector = facade.GetUncompressedReverseWeights(target_geometry_id);
duration_vector = facade.GetUncompressedReverseDurations(target_geometry_id);
datasource_vector = facade.GetUncompressedReverseDatasources(target_geometry_id);
if (is_local_path) if (is_local_path)
{ {
start_index = start_index =
@@ -246,11 +245,6 @@ void annotatePath(const FacadeT &facade,
start_index = phantom_node_pair.source_phantom.fwd_segment_position; start_index = phantom_node_pair.source_phantom.fwd_segment_position;
} }
end_index = phantom_node_pair.target_phantom.fwd_segment_position; end_index = phantom_node_pair.target_phantom.fwd_segment_position;
id_vector = facade.GetUncompressedForwardGeometry(target_geometry_id);
weight_vector = facade.GetUncompressedForwardWeights(target_geometry_id);
duration_vector = facade.GetUncompressedForwardDurations(target_geometry_id);
datasource_vector = facade.GetUncompressedForwardDatasources(target_geometry_id);
} }
// Given the following compressed geometry: // Given the following compressed geometry:
@@ -308,24 +302,6 @@ void annotatePath(const FacadeT &facade,
unpacked_path.front().duration_until_turn = unpacked_path.front().duration_until_turn =
std::max(unpacked_path.front().duration_until_turn - source_duration, 0); std::max(unpacked_path.front().duration_until_turn - source_duration, 0);
} }
// there is no equivalent to a node-based node in an edge-expanded graph.
// two equivalent routes may start (or end) at different node-based edges
// as they are added with the offset how much "weight" on the edge
// has already been traversed. Depending on offset one needs to remove
// the last node.
if (unpacked_path.size() > 1)
{
const std::size_t last_index = unpacked_path.size() - 1;
const std::size_t second_to_last_index = last_index - 1;
if (unpacked_path[last_index].turn_via_node ==
unpacked_path[second_to_last_index].turn_via_node)
{
unpacked_path.pop_back();
}
BOOST_ASSERT(!unpacked_path.empty());
}
} }
template <typename Algorithm> template <typename Algorithm>
@@ -30,7 +30,8 @@ namespace
// Unrestricted search (Args is const PhantomNodes &): // Unrestricted search (Args is const PhantomNodes &):
// * use partition.GetQueryLevel to find the node query level based on source and target phantoms // * use partition.GetQueryLevel to find the node query level based on source and target phantoms
// * allow to traverse all cells // * allow to traverse all cells
inline LevelID getNodeQueryLevel(const partition::MultiLevelPartitionView &partition, template <typename MultiLevelPartition>
inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
NodeID node, NodeID node,
const PhantomNodes &phantom_nodes) const PhantomNodes &phantom_nodes)
{ {
@@ -54,8 +55,8 @@ inline bool checkParentCellRestriction(CellID, const PhantomNodes &) { return tr
// Restricted search (Args is LevelID, CellID): // Restricted search (Args is LevelID, CellID):
// * use the fixed level for queries // * use the fixed level for queries
// * check if the node cell is the same as the specified parent onr // * check if the node cell is the same as the specified parent onr
inline LevelID template <typename MultiLevelPartition>
getNodeQueryLevel(const partition::MultiLevelPartitionView &, NodeID, LevelID level, CellID) inline LevelID getNodeQueryLevel(const MultiLevelPartition &, NodeID, LevelID level, CellID)
{ {
return level; return level;
} }
@@ -130,10 +131,10 @@ retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward
return packed_path; return packed_path;
} }
template <bool DIRECTION, typename... Args> template <bool DIRECTION, typename Algorithm, typename... Args>
void routingStep(const DataFacade<Algorithm> &facade, void routingStep(const DataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap, typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap, typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
NodeID &middle_node, NodeID &middle_node,
EdgeWeight &path_upper_bound, EdgeWeight &path_upper_bound,
const bool force_loop_forward, const bool force_loop_forward,
@@ -260,11 +261,11 @@ using UnpackedNodes = std::vector<NodeID>;
using UnpackedEdges = std::vector<EdgeID>; using UnpackedEdges = std::vector<EdgeID>;
using UnpackedPath = std::tuple<EdgeWeight, UnpackedNodes, UnpackedEdges>; using UnpackedPath = std::tuple<EdgeWeight, UnpackedNodes, UnpackedEdges>;
template <typename... Args> template <typename Algorithm, typename... Args>
UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data, UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade, const DataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap, typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap, typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const bool force_loop_forward, const bool force_loop_forward,
const bool force_loop_reverse, const bool force_loop_reverse,
EdgeWeight weight_upper_bound, EdgeWeight weight_upper_bound,
@@ -389,10 +390,11 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
} }
// Alias to be compatible with the CH-based search // Alias to be compatible with the CH-based search
template <typename Algorithm>
inline void search(SearchEngineData<Algorithm> &engine_working_data, inline void search(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade, const DataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap, typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap, typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
EdgeWeight &weight, EdgeWeight &weight,
std::vector<NodeID> &unpacked_nodes, std::vector<NodeID> &unpacked_nodes,
const bool force_loop_forward, const bool force_loop_forward,
@@ -442,13 +444,14 @@ void unpackPath(const FacadeT &facade,
annotatePath(facade, phantom_nodes, unpacked_nodes, unpacked_edges, unpacked_path); annotatePath(facade, phantom_nodes, unpacked_nodes, unpacked_edges, unpacked_path);
} }
inline double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data, template <typename Algorithm>
const DataFacade<Algorithm> &facade, double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
SearchEngineData<Algorithm>::QueryHeap &forward_heap, const DataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap, typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
const PhantomNode &source_phantom, typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const PhantomNode &target_phantom, const PhantomNode &source_phantom,
EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT) const PhantomNode &target_phantom,
EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
{ {
forward_heap.Clear(); forward_heap.Clear();
reverse_heap.Clear(); reverse_heap.Clear();
@@ -1,5 +1,5 @@
#ifndef SHORTEST_PATH_HPP #ifndef OSRM_SHORTEST_PATH_HPP
#define SHORTEST_PATH_HPP #define OSRM_SHORTEST_PATH_HPP
#include "engine/algorithm.hpp" #include "engine/algorithm.hpp"
#include "engine/routing_algorithms/routing_base.hpp" #include "engine/routing_algorithms/routing_base.hpp"
@@ -23,4 +23,4 @@ InternalRouteResult shortestPathSearch(SearchEngineData<Algorithm> &engine_worki
} // namespace engine } // namespace engine
} // namespace osrm } // namespace osrm
#endif /* SHORTEST_PATH_HPP */ #endif /* OSRM_SHORTEST_PATH_HPP */
@@ -0,0 +1,463 @@
#ifndef OSRM_SHORTEST_PATH_IMPL_HPP
#define OSRM_SHORTEST_PATH_IMPL_HPP
#include "engine/routing_algorithms/shortest_path.hpp"
#include <boost/assert.hpp>
#include <boost/optional.hpp>
namespace osrm
{
namespace engine
{
namespace routing_algorithms
{
namespace
{
const static constexpr bool DO_NOT_FORCE_LOOP = false;
// allows a uturn at the target_phantom
// searches source forward/reverse -> target forward/reverse
template <typename Algorithm>
void searchWithUTurn(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const bool search_from_forward_node,
const bool search_from_reverse_node,
const bool search_to_forward_node,
const bool search_to_reverse_node,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
const int total_weight_to_forward,
const int total_weight_to_reverse,
int &new_total_weight,
std::vector<NodeID> &leg_packed_path)
{
forward_heap.Clear();
reverse_heap.Clear();
if (search_from_forward_node)
{
forward_heap.Insert(source_phantom.forward_segment_id.id,
-source_phantom.GetForwardWeightPlusOffset(),
source_phantom.forward_segment_id.id);
}
if (search_from_reverse_node)
{
forward_heap.Insert(source_phantom.reverse_segment_id.id,
-source_phantom.GetReverseWeightPlusOffset(),
source_phantom.reverse_segment_id.id);
}
if (search_to_forward_node)
{
reverse_heap.Insert(target_phantom.forward_segment_id.id,
target_phantom.GetForwardWeightPlusOffset(),
target_phantom.forward_segment_id.id);
}
if (search_to_reverse_node)
{
reverse_heap.Insert(target_phantom.reverse_segment_id.id,
target_phantom.GetReverseWeightPlusOffset(),
target_phantom.reverse_segment_id.id);
}
// this is only relevent if source and target are on the same compressed edge
auto is_oneway_source = !(search_from_forward_node && search_from_reverse_node);
auto is_oneway_target = !(search_to_forward_node && search_to_reverse_node);
// we only enable loops here if we can't search from forward to backward node
auto needs_loop_forwards = is_oneway_source && needsLoopForward(source_phantom, target_phantom);
auto needs_loop_backwards =
is_oneway_target && needsLoopBackwards(source_phantom, target_phantom);
search(engine_working_data,
facade,
forward_heap,
reverse_heap,
new_total_weight,
leg_packed_path,
needs_loop_forwards,
needs_loop_backwards,
{source_phantom, target_phantom});
// if no route is found between two parts of the via-route, the entire route becomes
// invalid. Adding to invalid edge weight sadly doesn't return an invalid edge weight. Here
// we prevent the possible overflow, faking the addition of infinity + x == infinity
if (new_total_weight != INVALID_EDGE_WEIGHT)
new_total_weight += std::min(total_weight_to_forward, total_weight_to_reverse);
}
// searches shortest path between:
// source forward/reverse -> target forward
// source forward/reverse -> target reverse
template <typename Algorithm>
void search(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const bool search_from_forward_node,
const bool search_from_reverse_node,
const bool search_to_forward_node,
const bool search_to_reverse_node,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
const int total_weight_to_forward,
const int total_weight_to_reverse,
int &new_total_weight_to_forward,
int &new_total_weight_to_reverse,
std::vector<NodeID> &leg_packed_path_forward,
std::vector<NodeID> &leg_packed_path_reverse)
{
if (search_to_forward_node)
{
forward_heap.Clear();
reverse_heap.Clear();
reverse_heap.Insert(target_phantom.forward_segment_id.id,
target_phantom.GetForwardWeightPlusOffset(),
target_phantom.forward_segment_id.id);
if (search_from_forward_node)
{
forward_heap.Insert(source_phantom.forward_segment_id.id,
total_weight_to_forward -
source_phantom.GetForwardWeightPlusOffset(),
source_phantom.forward_segment_id.id);
}
if (search_from_reverse_node)
{
forward_heap.Insert(source_phantom.reverse_segment_id.id,
total_weight_to_reverse -
source_phantom.GetReverseWeightPlusOffset(),
source_phantom.reverse_segment_id.id);
}
search(engine_working_data,
facade,
forward_heap,
reverse_heap,
new_total_weight_to_forward,
leg_packed_path_forward,
needsLoopForward(source_phantom, target_phantom),
routing_algorithms::DO_NOT_FORCE_LOOP,
{source_phantom, target_phantom});
}
if (search_to_reverse_node)
{
forward_heap.Clear();
reverse_heap.Clear();
reverse_heap.Insert(target_phantom.reverse_segment_id.id,
target_phantom.GetReverseWeightPlusOffset(),
target_phantom.reverse_segment_id.id);
if (search_from_forward_node)
{
forward_heap.Insert(source_phantom.forward_segment_id.id,
total_weight_to_forward -
source_phantom.GetForwardWeightPlusOffset(),
source_phantom.forward_segment_id.id);
}
if (search_from_reverse_node)
{
forward_heap.Insert(source_phantom.reverse_segment_id.id,
total_weight_to_reverse -
source_phantom.GetReverseWeightPlusOffset(),
source_phantom.reverse_segment_id.id);
}
search(engine_working_data,
facade,
forward_heap,
reverse_heap,
new_total_weight_to_reverse,
leg_packed_path_reverse,
routing_algorithms::DO_NOT_FORCE_LOOP,
needsLoopBackwards(source_phantom, target_phantom),
{source_phantom, target_phantom});
}
}
template <typename Algorithm>
void unpackLegs(const DataFacade<Algorithm> &facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const std::vector<NodeID> &total_packed_path,
const std::vector<std::size_t> &packed_leg_begin,
const EdgeWeight shortest_path_weight,
InternalRouteResult &raw_route_data)
{
raw_route_data.unpacked_path_segments.resize(packed_leg_begin.size() - 1);
raw_route_data.shortest_path_weight = shortest_path_weight;
for (const auto current_leg : util::irange<std::size_t>(0UL, packed_leg_begin.size() - 1))
{
auto leg_begin = total_packed_path.begin() + packed_leg_begin[current_leg];
auto leg_end = total_packed_path.begin() + packed_leg_begin[current_leg + 1];
const auto &unpack_phantom_node_pair = phantom_nodes_vector[current_leg];
unpackPath(facade,
leg_begin,
leg_end,
unpack_phantom_node_pair,
raw_route_data.unpacked_path_segments[current_leg]);
raw_route_data.source_traversed_in_reverse.push_back(
(*leg_begin != phantom_nodes_vector[current_leg].source_phantom.forward_segment_id.id));
raw_route_data.target_traversed_in_reverse.push_back(
(*std::prev(leg_end) !=
phantom_nodes_vector[current_leg].target_phantom.forward_segment_id.id));
}
}
}
template <typename Algorithm>
InternalRouteResult shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const boost::optional<bool> continue_straight_at_waypoint)
{
InternalRouteResult raw_route_data;
raw_route_data.segment_end_coordinates = phantom_nodes_vector;
const bool allow_uturn_at_waypoint =
!(continue_straight_at_waypoint ? *continue_straight_at_waypoint
: facade.GetContinueStraightDefault());
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
auto &forward_heap = *engine_working_data.forward_heap_1;
auto &reverse_heap = *engine_working_data.reverse_heap_1;
int total_weight_to_forward = 0;
int total_weight_to_reverse = 0;
bool search_from_forward_node =
phantom_nodes_vector.front().source_phantom.IsValidForwardSource();
bool search_from_reverse_node =
phantom_nodes_vector.front().source_phantom.IsValidReverseSource();
std::vector<NodeID> prev_packed_leg_to_forward;
std::vector<NodeID> prev_packed_leg_to_reverse;
std::vector<NodeID> total_packed_path_to_forward;
std::vector<std::size_t> packed_leg_to_forward_begin;
std::vector<NodeID> total_packed_path_to_reverse;
std::vector<std::size_t> packed_leg_to_reverse_begin;
std::size_t current_leg = 0;
// this implements a dynamic program that finds the shortest route through
// a list of vias
for (const auto &phantom_node_pair : phantom_nodes_vector)
{
int new_total_weight_to_forward = INVALID_EDGE_WEIGHT;
int new_total_weight_to_reverse = INVALID_EDGE_WEIGHT;
std::vector<NodeID> packed_leg_to_forward;
std::vector<NodeID> packed_leg_to_reverse;
const auto &source_phantom = phantom_node_pair.source_phantom;
const auto &target_phantom = phantom_node_pair.target_phantom;
bool search_to_forward_node = target_phantom.IsValidForwardTarget();
bool search_to_reverse_node = target_phantom.IsValidReverseTarget();
BOOST_ASSERT(!search_from_forward_node || source_phantom.IsValidForwardSource());
BOOST_ASSERT(!search_from_reverse_node || source_phantom.IsValidReverseSource());
if (search_to_reverse_node || search_to_forward_node)
{
if (allow_uturn_at_waypoint)
{
searchWithUTurn(engine_working_data,
facade,
forward_heap,
reverse_heap,
search_from_forward_node,
search_from_reverse_node,
search_to_forward_node,
search_to_reverse_node,
source_phantom,
target_phantom,
total_weight_to_forward,
total_weight_to_reverse,
new_total_weight_to_forward,
packed_leg_to_forward);
// if only the reverse node is valid (e.g. when using the match plugin) we
// actually need to move
if (!target_phantom.IsValidForwardTarget())
{
BOOST_ASSERT(target_phantom.IsValidReverseTarget());
new_total_weight_to_reverse = new_total_weight_to_forward;
packed_leg_to_reverse = std::move(packed_leg_to_forward);
new_total_weight_to_forward = INVALID_EDGE_WEIGHT;
// (*)
//
// Below we have to check if new_total_weight_to_forward is invalid.
// This prevents use-after-move on packed_leg_to_forward.
}
else if (target_phantom.IsValidReverseTarget())
{
new_total_weight_to_reverse = new_total_weight_to_forward;
packed_leg_to_reverse = packed_leg_to_forward;
}
}
else
{
search(engine_working_data,
facade,
forward_heap,
reverse_heap,
search_from_forward_node,
search_from_reverse_node,
search_to_forward_node,
search_to_reverse_node,
source_phantom,
target_phantom,
total_weight_to_forward,
total_weight_to_reverse,
new_total_weight_to_forward,
new_total_weight_to_reverse,
packed_leg_to_forward,
packed_leg_to_reverse);
}
}
// Note: To make sure we do not access the moved-from packed_leg_to_forward
// we guard its access by a check for invalid edge weight. See (*) above.
// No path found for both target nodes?
if ((INVALID_EDGE_WEIGHT == new_total_weight_to_forward) &&
(INVALID_EDGE_WEIGHT == new_total_weight_to_reverse))
{
return raw_route_data;
}
// we need to figure out how the new legs connect to the previous ones
if (current_leg > 0)
{
bool forward_to_forward =
(new_total_weight_to_forward != INVALID_EDGE_WEIGHT) &&
packed_leg_to_forward.front() == source_phantom.forward_segment_id.id;
bool reverse_to_forward =
(new_total_weight_to_forward != INVALID_EDGE_WEIGHT) &&
packed_leg_to_forward.front() == source_phantom.reverse_segment_id.id;
bool forward_to_reverse =
(new_total_weight_to_reverse != INVALID_EDGE_WEIGHT) &&
packed_leg_to_reverse.front() == source_phantom.forward_segment_id.id;
bool reverse_to_reverse =
(new_total_weight_to_reverse != INVALID_EDGE_WEIGHT) &&
packed_leg_to_reverse.front() == source_phantom.reverse_segment_id.id;
BOOST_ASSERT(!forward_to_forward || !reverse_to_forward);
BOOST_ASSERT(!forward_to_reverse || !reverse_to_reverse);
// in this case we always need to copy
if (forward_to_forward && forward_to_reverse)
{
// in this case we copy the path leading to the source forward node
// and change the case
total_packed_path_to_reverse = total_packed_path_to_forward;
packed_leg_to_reverse_begin = packed_leg_to_forward_begin;
forward_to_reverse = false;
reverse_to_reverse = true;
}
else if (reverse_to_forward && reverse_to_reverse)
{
total_packed_path_to_forward = total_packed_path_to_reverse;
packed_leg_to_forward_begin = packed_leg_to_reverse_begin;
reverse_to_forward = false;
forward_to_forward = true;
}
BOOST_ASSERT(!forward_to_forward || !forward_to_reverse);
BOOST_ASSERT(!reverse_to_forward || !reverse_to_reverse);
// in this case we just need to swap to regain the correct mapping
if (reverse_to_forward || forward_to_reverse)
{
total_packed_path_to_forward.swap(total_packed_path_to_reverse);
packed_leg_to_forward_begin.swap(packed_leg_to_reverse_begin);
}
}
if (new_total_weight_to_forward != INVALID_EDGE_WEIGHT)
{
BOOST_ASSERT(target_phantom.IsValidForwardTarget());
packed_leg_to_forward_begin.push_back(total_packed_path_to_forward.size());
total_packed_path_to_forward.insert(total_packed_path_to_forward.end(),
packed_leg_to_forward.begin(),
packed_leg_to_forward.end());
search_from_forward_node = true;
}
else
{
total_packed_path_to_forward.clear();
packed_leg_to_forward_begin.clear();
search_from_forward_node = false;
}
if (new_total_weight_to_reverse != INVALID_EDGE_WEIGHT)
{
BOOST_ASSERT(target_phantom.IsValidReverseTarget());
packed_leg_to_reverse_begin.push_back(total_packed_path_to_reverse.size());
total_packed_path_to_reverse.insert(total_packed_path_to_reverse.end(),
packed_leg_to_reverse.begin(),
packed_leg_to_reverse.end());
search_from_reverse_node = true;
}
else
{
total_packed_path_to_reverse.clear();
packed_leg_to_reverse_begin.clear();
search_from_reverse_node = false;
}
prev_packed_leg_to_forward = std::move(packed_leg_to_forward);
prev_packed_leg_to_reverse = std::move(packed_leg_to_reverse);
total_weight_to_forward = new_total_weight_to_forward;
total_weight_to_reverse = new_total_weight_to_reverse;
++current_leg;
}
BOOST_ASSERT(total_weight_to_forward != INVALID_EDGE_WEIGHT ||
total_weight_to_reverse != INVALID_EDGE_WEIGHT);
// We make sure the fastest route is always in packed_legs_to_forward
if (total_weight_to_forward < total_weight_to_reverse ||
(total_weight_to_forward == total_weight_to_reverse &&
total_packed_path_to_forward.size() < total_packed_path_to_reverse.size()))
{
// insert sentinel
packed_leg_to_forward_begin.push_back(total_packed_path_to_forward.size());
BOOST_ASSERT(packed_leg_to_forward_begin.size() == phantom_nodes_vector.size() + 1);
unpackLegs(facade,
phantom_nodes_vector,
total_packed_path_to_forward,
packed_leg_to_forward_begin,
total_weight_to_forward,
raw_route_data);
}
else
{
// insert sentinel
packed_leg_to_reverse_begin.push_back(total_packed_path_to_reverse.size());
BOOST_ASSERT(packed_leg_to_reverse_begin.size() == phantom_nodes_vector.size() + 1);
unpackLegs(facade,
phantom_nodes_vector,
total_packed_path_to_reverse,
packed_leg_to_reverse_begin,
total_weight_to_reverse,
raw_route_data);
}
return raw_route_data;
}
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
#endif /* OSRM_SHORTEST_PATH_IMPL_HPP */
@@ -3,7 +3,6 @@
#include "engine/algorithm.hpp" #include "engine/algorithm.hpp"
#include "engine/datafacade.hpp" #include "engine/datafacade.hpp"
#include "engine/datafacade/datafacade_base.hpp"
#include "util/coordinate.hpp" #include "util/coordinate.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
+3 -4
View File
@@ -1,12 +1,12 @@
#ifndef SEARCH_ENGINE_DATA_HPP #ifndef SEARCH_ENGINE_DATA_HPP
#define SEARCH_ENGINE_DATA_HPP #define SEARCH_ENGINE_DATA_HPP
#include <boost/thread/tss.hpp>
#include "engine/algorithm.hpp" #include "engine/algorithm.hpp"
#include "util/query_heap.hpp" #include "util/query_heap.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <boost/thread/tss.hpp>
namespace osrm namespace osrm
{ {
namespace engine namespace engine
@@ -37,7 +37,6 @@ template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
{ {
using QueryHeap = util:: using QueryHeap = util::
QueryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>; QueryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
using ManyToManyQueryHeap = util::QueryHeap<NodeID, using ManyToManyQueryHeap = util::QueryHeap<NodeID,
NodeID, NodeID,
@@ -45,6 +44,7 @@ template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
ManyToManyHeapData, ManyToManyHeapData,
util::UnorderedMapStorage<NodeID, int>>; util::UnorderedMapStorage<NodeID, int>>;
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>; using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
static SearchEngineHeapPtr forward_heap_1; static SearchEngineHeapPtr forward_heap_1;
@@ -106,7 +106,6 @@ template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
util::UnorderedMapStorage<NodeID, int>>; util::UnorderedMapStorage<NodeID, int>>;
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>; using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>; using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
static SearchEngineHeapPtr forward_heap_1; static SearchEngineHeapPtr forward_heap_1;
@@ -10,6 +10,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <boost/optional.hpp>
namespace osrm namespace osrm
{ {
namespace extractor namespace extractor
@@ -36,7 +38,11 @@ class CompressedEdgeContainer
const EdgeWeight weight1, const EdgeWeight weight1,
const EdgeWeight weight2, const EdgeWeight weight2,
const EdgeDuration duration1, const EdgeDuration duration1,
const EdgeDuration duration2); const EdgeDuration duration2,
// node-penalties can be added before/or after the traversal of an edge which
// depends on whether we traverse the link forwards or backwards.
const boost::optional<EdgeWeight> node_weight_penalty = boost::none,
const boost::optional<EdgeDuration> node_duration_penalty = boost::none);
void AddUncompressedEdge(const EdgeID edge_id, void AddUncompressedEdge(const EdgeID edge_id,
const NodeID target_node, const NodeID target_node,
@@ -0,0 +1,28 @@
#ifndef OSRM_EXTRACTOR_CONDITIONAL_TURN_PENALTY_HPP_
#define OSRM_EXTRACTOR_CONDITIONAL_TURN_PENALTY_HPP_
#include "util/coordinate.hpp"
#include "util/opening_hours.hpp"
#include <cstdint>
#include <vector>
#include <type_traits>
namespace osrm
{
namespace extractor
{
struct ConditionalTurnPenalty
{
// offset into the sequential list of turn penalties (see TurnIndexBlock for reference);
std::uint64_t turn_offset;
util::Coordinate location;
std::vector<util::OpeningHours> conditions;
};
} // namespace extractor
} // namespace osrm
#endif // OSRM_EXTRACTOR_CONDITIONAL_TURN_PENALTY_HPP_
+18 -6
View File
@@ -4,6 +4,7 @@
#define EDGE_BASED_GRAPH_FACTORY_HPP_ #define EDGE_BASED_GRAPH_FACTORY_HPP_
#include "extractor/compressed_edge_container.hpp" #include "extractor/compressed_edge_container.hpp"
#include "extractor/conditional_turn_penalty.hpp"
#include "extractor/edge_based_edge.hpp" #include "extractor/edge_based_edge.hpp"
#include "extractor/edge_based_node_segment.hpp" #include "extractor/edge_based_node_segment.hpp"
#include "extractor/extraction_turn.hpp" #include "extractor/extraction_turn.hpp"
@@ -16,7 +17,7 @@
#include "extractor/packed_osm_ids.hpp" #include "extractor/packed_osm_ids.hpp"
#include "extractor/profile_properties.hpp" #include "extractor/profile_properties.hpp"
#include "extractor/query_node.hpp" #include "extractor/query_node.hpp"
#include "extractor/restriction_map.hpp" #include "extractor/restriction_index.hpp"
#include "extractor/way_restriction_map.hpp" #include "extractor/way_restriction_map.hpp"
#include "util/concurrent_id_map.hpp" #include "util/concurrent_id_map.hpp"
@@ -41,11 +42,6 @@
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>
#include <boost/filesystem/fstream.hpp>
#include <tbb/concurrent_unordered_map.h>
#include <tbb/concurrent_vector.h>
namespace osrm namespace osrm
{ {
namespace extractor namespace extractor
@@ -92,7 +88,9 @@ class EdgeBasedGraphFactory
const std::string &turn_duration_penalties_filename, const std::string &turn_duration_penalties_filename,
const std::string &turn_penalties_index_filename, const std::string &turn_penalties_index_filename,
const std::string &cnbg_ebg_mapping_path, const std::string &cnbg_ebg_mapping_path,
const std::string &conditional_penalties_filename,
const RestrictionMap &node_restriction_map, const RestrictionMap &node_restriction_map,
const ConditionalRestrictionMap &conditional_restriction_map,
const WayRestrictionMap &way_restriction_map); const WayRestrictionMap &way_restriction_map);
// The following get access functions destroy the content in the factory // The following get access functions destroy the content in the factory
@@ -124,6 +122,18 @@ class EdgeBasedGraphFactory
private: private:
using EdgeData = util::NodeBasedDynamicGraph::EdgeData; using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
struct Conditional
{
// the edge based nodes allow for a unique identification of conditionals
NodeID from_node;
NodeID to_node;
ConditionalTurnPenalty penalty;
};
// assign the correct index to the penalty value stored in the conditional
std::vector<ConditionalTurnPenalty>
IndexConditionals(std::vector<Conditional> &&conditionals) const;
//! maps index from m_edge_based_node_list to ture/false if the node is an entry point to the //! maps index from m_edge_based_node_list to ture/false if the node is an entry point to the
//! graph //! graph
std::vector<bool> m_edge_based_node_is_startpoint; std::vector<bool> m_edge_based_node_is_startpoint;
@@ -173,7 +183,9 @@ class EdgeBasedGraphFactory
const std::string &turn_weight_penalties_filename, const std::string &turn_weight_penalties_filename,
const std::string &turn_duration_penalties_filename, const std::string &turn_duration_penalties_filename,
const std::string &turn_penalties_index_filename, const std::string &turn_penalties_index_filename,
const std::string &conditional_turn_penalties_filename,
const RestrictionMap &node_restriction_map, const RestrictionMap &node_restriction_map,
const ConditionalRestrictionMap &conditional_restriction_map,
const WayRestrictionMap &way_restriction_map); const WayRestrictionMap &way_restriction_map);
NBGToEBG InsertEdgeBasedNode(const NodeID u, const NodeID v); NBGToEBG InsertEdgeBasedNode(const NodeID u, const NodeID v);
+1 -3
View File
@@ -27,7 +27,6 @@ class ExtractionContainers
void PrepareEdges(ScriptingEnvironment &scripting_environment); void PrepareEdges(ScriptingEnvironment &scripting_environment);
void WriteNodes(storage::io::FileWriter &file_out) const; void WriteNodes(storage::io::FileWriter &file_out) const;
void WriteConditionalRestrictions(const std::string &restrictions_file_name);
void WriteEdges(storage::io::FileWriter &file_out) const; void WriteEdges(storage::io::FileWriter &file_out) const;
void WriteCharData(const std::string &file_name); void WriteCharData(const std::string &file_name);
@@ -40,7 +39,7 @@ class ExtractionContainers
using NameOffsets = std::vector<unsigned>; using NameOffsets = std::vector<unsigned>;
std::vector<OSMNodeID> barrier_nodes; std::vector<OSMNodeID> barrier_nodes;
std::vector<OSMNodeID> traffic_lights; std::vector<OSMNodeID> traffic_signals;
NodeIDVector used_node_id_list; NodeIDVector used_node_id_list;
NodeVector all_nodes_list; NodeVector all_nodes_list;
EdgeVector all_edges_list; EdgeVector all_edges_list;
@@ -65,7 +64,6 @@ class ExtractionContainers
void PrepareData(ScriptingEnvironment &scripting_environment, void PrepareData(ScriptingEnvironment &scripting_environment,
const std::string &osrm_path, const std::string &osrm_path,
const std::string &restrictions_file_name,
const std::string &names_data_path); const std::string &names_data_path);
}; };
} }
+8
View File
@@ -22,6 +22,14 @@ struct ExtractionTurn
{ {
} }
ExtractionTurn(const bool has_traffic_light = false)
: angle(0), turn_type(guidance::TurnType::NoTurn),
direction_modifier(guidance::DirectionModifier::Straight),
has_traffic_light(has_traffic_light), weight(0.), duration(0.), source_restricted(false),
target_restricted(false)
{
}
const double angle; const double angle;
const guidance::TurnType::Enum turn_type; const guidance::TurnType::Enum turn_type;
const guidance::DirectionModifier::Enum direction_modifier; const guidance::DirectionModifier::Enum direction_modifier;
+8 -1
View File
@@ -56,7 +56,9 @@ class Extractor
private: private:
ExtractorConfig config; ExtractorConfig config;
std::tuple<guidance::LaneDescriptionMap, std::vector<TurnRestriction>> std::tuple<guidance::LaneDescriptionMap,
std::vector<TurnRestriction>,
std::vector<ConditionalTurnRestriction>>
ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads); ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads);
std::pair<std::size_t, EdgeID> std::pair<std::size_t, EdgeID>
@@ -70,6 +72,7 @@ class Extractor
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list, util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
const std::string &intersection_class_output_file, const std::string &intersection_class_output_file,
std::vector<TurnRestriction> &turn_restrictions, std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
guidance::LaneDescriptionMap &turn_lane_map); guidance::LaneDescriptionMap &turn_lane_map);
void FindComponents(unsigned max_edge_id, void FindComponents(unsigned max_edge_id,
const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list, const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list,
@@ -89,6 +92,10 @@ class Extractor
static void WriteCompressedNodeBasedGraph(const std::string &path, static void WriteCompressedNodeBasedGraph(const std::string &path,
const util::NodeBasedDynamicGraph &graph, const util::NodeBasedDynamicGraph &graph,
const std::vector<util::Coordinate> &coordiantes); const std::vector<util::Coordinate> &coordiantes);
void WriteConditionalRestrictions(
const std::string &path,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
}; };
} }
} }
+3
View File
@@ -1,6 +1,7 @@
#ifndef GEOMETRY_COMPRESSOR_HPP #ifndef GEOMETRY_COMPRESSOR_HPP
#define GEOMETRY_COMPRESSOR_HPP #define GEOMETRY_COMPRESSOR_HPP
#include "extractor/scripting_environment.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
@@ -24,7 +25,9 @@ class GraphCompressor
public: public:
void Compress(const std::unordered_set<NodeID> &barrier_nodes, void Compress(const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights, const std::unordered_set<NodeID> &traffic_lights,
ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions, std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
util::NodeBasedDynamicGraph &graph, util::NodeBasedDynamicGraph &graph,
CompressedEdgeContainer &geometry_compressor); CompressedEdgeContainer &geometry_compressor);
@@ -6,7 +6,7 @@
#include "extractor/guidance/intersection.hpp" #include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_normalization_operation.hpp" #include "extractor/guidance/intersection_normalization_operation.hpp"
#include "extractor/query_node.hpp" #include "extractor/query_node.hpp"
#include "extractor/restriction_map.hpp" #include "extractor/restriction_index.hpp"
#include "util/attributes.hpp" #include "util/attributes.hpp"
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
@@ -116,14 +116,6 @@ class IntersectionGenerator
// own state, used to find the correct coordinates along a road // own state, used to find the correct coordinates along a road
const CoordinateExtractor coordinate_extractor; const CoordinateExtractor coordinate_extractor;
// check turn restrictions to find a node that is the only allowed target when coming from a
// node to an intersection
// d
// |
// a - b - c and `only_straight_on ab | bc would return `c` for `a,b`
boost::optional<NodeID> GetOnlyAllowedTurnIfExistent(const NodeID coming_from_node,
const NodeID node_at_intersection) const;
}; };
} // namespace guidance } // namespace guidance
+1 -1
View File
@@ -14,7 +14,7 @@
#include "extractor/guidance/turn_classification.hpp" #include "extractor/guidance/turn_classification.hpp"
#include "extractor/guidance/turn_handler.hpp" #include "extractor/guidance/turn_handler.hpp"
#include "extractor/query_node.hpp" #include "extractor/query_node.hpp"
#include "extractor/restriction_map.hpp" #include "extractor/restriction_index.hpp"
#include "extractor/suffix_table.hpp" #include "extractor/suffix_table.hpp"
#include "util/attributes.hpp" #include "util/attributes.hpp"
+2 -1
View File
@@ -83,7 +83,8 @@ struct ProfileProperties
std::string GetClassName(std::size_t index) const std::string GetClassName(std::size_t index) const
{ {
BOOST_ASSERT(index <= MAX_CLASS_INDEX); BOOST_ASSERT(index <= MAX_CLASS_INDEX);
return std::string(class_names[index]); const auto &name_it = std::begin(class_names) + index;
return std::string(*name_it);
} }
double GetWeightMultiplier() const { return std::pow(10., weight_precision); } double GetWeightMultiplier() const { return std::pow(10., weight_precision); }
+3 -1
View File
@@ -1,6 +1,7 @@
#ifndef OSRM_EXTRACTOR_RESTRICTION_COMPRESSOR_HPP_ #ifndef OSRM_EXTRACTOR_RESTRICTION_COMPRESSOR_HPP_
#define OSRM_EXTRACTOR_RESTRICTION_COMPRESSOR_HPP_ #define OSRM_EXTRACTOR_RESTRICTION_COMPRESSOR_HPP_
#include "extractor/restriction.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
@@ -26,7 +27,8 @@ struct TurnRestriction;
class RestrictionCompressor class RestrictionCompressor
{ {
public: public:
RestrictionCompressor(std::vector<TurnRestriction> &restrictions); RestrictionCompressor(std::vector<TurnRestriction> &restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
// account for the compression of `from-via-to` into `from-to` // account for the compression of `from-via-to` into `from-to`
void Compress(const NodeID from, const NodeID via, const NodeID to); void Compress(const NodeID from, const NodeID via, const NodeID to);
+3 -2
View File
@@ -14,8 +14,9 @@ namespace extractor
// To avoid handling invalid restrictions / creating unnecessary duplicate nodes for via-ways, we do // To avoid handling invalid restrictions / creating unnecessary duplicate nodes for via-ways, we do
// a pre-flight check for restrictions and remove all invalid restrictions from the data. Use as // a pre-flight check for restrictions and remove all invalid restrictions from the data. Use as
// `restrictions = removeInvalidRestrictions(std::move(restrictions))` // `restrictions = removeInvalidRestrictions(std::move(restrictions))`
std::vector<TurnRestriction> removeInvalidRestrictions(std::vector<TurnRestriction>, std::vector<ConditionalTurnRestriction>
const util::NodeBasedDynamicGraph &); removeInvalidRestrictions(std::vector<ConditionalTurnRestriction>,
const util::NodeBasedDynamicGraph &);
} // namespace extractor } // namespace extractor
} // namespace osrm } // namespace osrm
+101
View File
@@ -0,0 +1,101 @@
#ifndef OSRM_EXTRACTOR_RESTRICTION_INDEX_HPP_
#define OSRM_EXTRACTOR_RESTRICTION_INDEX_HPP_
#include "extractor/restriction.hpp"
#include "util/typedefs.hpp"
#include <boost/unordered_map.hpp>
#include <utility>
#include <vector>
namespace osrm
{
namespace extractor
{
// allows easy check for whether a node intersection is present at a given intersection
template <typename restriction_type> class RestrictionIndex
{
public:
using value_type = restriction_type;
template <typename extractor_type>
RestrictionIndex(std::vector<restriction_type> &restrictions, extractor_type extractor);
bool IsIndexed(NodeID first, NodeID second) const;
auto Restrictions(NodeID first, NodeID second) const
{
return restriction_hash.equal_range(std::make_pair(first, second));
};
auto Size() const { return restriction_hash.size(); }
private:
boost::unordered_multimap<std::pair<NodeID, NodeID>, restriction_type *> restriction_hash;
};
template <typename restriction_type>
template <typename extractor_type>
RestrictionIndex<restriction_type>::RestrictionIndex(std::vector<restriction_type> &restrictions,
extractor_type extractor)
{
// build a multi-map
for (auto &restriction : restrictions)
restriction_hash.insert(std::make_pair(extractor(restriction), &restriction));
}
template <typename restriction_type>
bool RestrictionIndex<restriction_type>::IsIndexed(const NodeID first, const NodeID second) const
{
return restriction_hash.count(std::make_pair(first, second));
}
struct IndexNodeByFromAndVia
{
std::pair<NodeID, NodeID> operator()(const TurnRestriction &restriction)
{
const auto &node = restriction.AsNodeRestriction();
return std::make_pair(node.from, node.via);
};
};
// check wheter a turn is restricted within a restriction_index
template <typename restriction_map_type>
std::pair<bool, typename restriction_map_type::value_type *>
isRestricted(const NodeID from,
const NodeID via,
const NodeID to,
const restriction_map_type &restriction_map)
{
const auto range = restriction_map.Restrictions(from, via);
// check if a given node_restriction is targeting node
const auto to_is_restricted = [to](const auto &pair) {
const auto &restriction = *pair.second;
if (restriction.Type() == RestrictionType::NODE_RESTRICTION)
{
auto const &as_node = restriction.AsNodeRestriction();
auto const restricted = restriction.is_only ? (to != as_node.to) : (to == as_node.to);
return restricted;
}
return false;
};
auto itr = std::find_if(range.first, range.second, to_is_restricted);
if (itr != range.second)
return {true, itr->second};
else
return {false, NULL};
}
using RestrictionMap = RestrictionIndex<TurnRestriction>;
using ConditionalRestrictionMap = RestrictionIndex<ConditionalTurnRestriction>;
} // namespace extractor
} // namespace osrm
#endif // OSRM_EXTRACTOR_RESTRICTION_INDEX_HPP_
-110
View File
@@ -1,110 +0,0 @@
#ifndef RESTRICTION_MAP_HPP
#define RESTRICTION_MAP_HPP
#include "extractor/edge_based_edge.hpp"
#include "extractor/restriction.hpp"
#include "util/std_hash.hpp"
#include "util/typedefs.hpp"
#include <boost/assert.hpp>
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <vector>
namespace osrm
{
namespace extractor
{
struct RestrictionSource
{
NodeID start_node;
NodeID via_node;
RestrictionSource(NodeID start, NodeID via) : start_node(start), via_node(via) {}
friend inline bool operator==(const RestrictionSource &lhs, const RestrictionSource &rhs)
{
return (lhs.start_node == rhs.start_node && lhs.via_node == rhs.via_node);
}
};
struct RestrictionTarget
{
NodeID target_node;
bool is_only;
explicit RestrictionTarget(NodeID target, bool only) : target_node(target), is_only(only) {}
friend inline bool operator==(const RestrictionTarget &lhs, const RestrictionTarget &rhs)
{
return (lhs.target_node == rhs.target_node && lhs.is_only == rhs.is_only);
}
};
}
}
namespace std
{
template <> struct hash<osrm::extractor::RestrictionSource>
{
size_t operator()(const osrm::extractor::RestrictionSource &r_source) const
{
return hash_val(r_source.start_node, r_source.via_node);
}
};
template <> struct hash<osrm::extractor::RestrictionTarget>
{
size_t operator()(const osrm::extractor::RestrictionTarget &r_target) const
{
return hash_val(r_target.target_node, r_target.is_only);
}
};
}
namespace osrm
{
namespace extractor
{
/**
\brief Efficent look up if an edge is the start + via node of a TurnRestriction
EdgeBasedEdgeFactory decides by it if edges are inserted or geometry is compressed
*/
class RestrictionMap
{
public:
RestrictionMap() : m_count(0) {}
RestrictionMap(const std::vector<TurnRestriction> &restriction_list);
bool IsViaNode(const NodeID node) const;
// Check if edge (u, v) is the start of any turn restriction.
// If so returns id of first target node.
NodeID CheckForEmanatingIsOnlyTurn(const NodeID node_u, const NodeID node_v) const;
// Checks if turn <u,v,w> is actually a turn restriction.
bool
CheckIfTurnIsRestricted(const NodeID node_u, const NodeID node_v, const NodeID node_w) const;
std::size_t size() const { return m_count; }
private:
// check of node is the start of any restriction
bool IsSourceNode(const NodeID node) const;
using EmanatingRestrictionsVector = std::vector<RestrictionTarget>;
std::size_t m_count;
//! index -> list of (target, isOnly)
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
//! maps (start, via) -> bucket index
std::unordered_map<RestrictionSource, unsigned> m_restriction_map;
std::unordered_set<NodeID> m_restriction_start_nodes;
std::unordered_set<NodeID> m_no_turn_via_node_set;
};
}
}
#endif // RESTRICTION_MAP_HPP
+49
View File
@@ -1,6 +1,7 @@
#ifndef OSRM_EXTRACTOR_IO_HPP #ifndef OSRM_EXTRACTOR_IO_HPP
#define OSRM_EXTRACTOR_IO_HPP #define OSRM_EXTRACTOR_IO_HPP
#include "conditional_turn_penalty.hpp"
#include "extractor/datasources.hpp" #include "extractor/datasources.hpp"
#include "extractor/intersection_bearings_container.hpp" #include "extractor/intersection_bearings_container.hpp"
#include "extractor/nbg_to_ebg.hpp" #include "extractor/nbg_to_ebg.hpp"
@@ -273,6 +274,54 @@ inline void write(storage::io::FileWriter &writer,
}; };
std::for_each(restrictions.begin(), restrictions.end(), write_restriction); std::for_each(restrictions.begin(), restrictions.end(), write_restriction);
} }
inline void read(storage::io::FileReader &reader, ConditionalTurnPenalty &turn_penalty)
{
reader.ReadInto(turn_penalty.turn_offset);
reader.ReadInto(turn_penalty.location.lat);
reader.ReadInto(turn_penalty.location.lon);
auto const num_conditions = reader.ReadElementCount64();
turn_penalty.conditions.resize(num_conditions);
for (auto &condition : turn_penalty.conditions)
{
reader.ReadInto(condition.modifier);
storage::serialization::read(reader, condition.times);
storage::serialization::read(reader, condition.weekdays);
storage::serialization::read(reader, condition.monthdays);
}
}
inline void write(storage::io::FileWriter &writer, const ConditionalTurnPenalty &turn_penalty)
{
writer.WriteOne(turn_penalty.turn_offset);
writer.WriteOne(static_cast<util::FixedLatitude::value_type>(turn_penalty.location.lat));
writer.WriteOne(static_cast<util::FixedLongitude::value_type>(turn_penalty.location.lon));
writer.WriteElementCount64(turn_penalty.conditions.size());
for (const auto &c : turn_penalty.conditions)
{
writer.WriteOne(c.modifier);
storage::serialization::write(writer, c.times);
storage::serialization::write(writer, c.weekdays);
storage::serialization::write(writer, c.monthdays);
}
}
inline void write(storage::io::FileWriter &writer,
const std::vector<ConditionalTurnPenalty> &conditional_penalties)
{
writer.WriteElementCount64(conditional_penalties.size());
for (const auto &penalty : conditional_penalties)
write(writer, penalty);
}
inline void read(storage::io::FileReader &reader,
std::vector<ConditionalTurnPenalty> &conditional_penalties)
{
auto const num_elements = reader.ReadElementCount64();
conditional_penalties.resize(num_elements);
for (auto &penalty : conditional_penalties)
read(reader, penalty);
}
} }
} }
} }
+10 -7
View File
@@ -8,6 +8,7 @@
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
#include "extractor/restriction.hpp" #include "extractor/restriction.hpp"
#include "extractor/restriction_index.hpp"
#include "util/integer_range.hpp" #include "util/integer_range.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
@@ -18,6 +19,8 @@ namespace osrm
namespace extractor namespace extractor
{ {
// The WayRestrictionMap uses ConditionalTurnRestrictions in general. Most restrictions will have
// empty conditions, though.
class WayRestrictionMap class WayRestrictionMap
{ {
public: public:
@@ -26,7 +29,7 @@ class WayRestrictionMap
NodeID from; NodeID from;
NodeID to; NodeID to;
}; };
WayRestrictionMap(const std::vector<TurnRestriction> &turn_restrictions); WayRestrictionMap(const std::vector<ConditionalTurnRestriction> &conditional_restrictions);
// Check if an edge between two nodes is a restricted turn. The check needs to be performed to // Check if an edge between two nodes is a restricted turn. The check needs to be performed to
// find duplicated nodes during the creation of edge-based-edges // find duplicated nodes during the creation of edge-based-edges
@@ -43,10 +46,13 @@ class WayRestrictionMap
std::vector<ViaWay> DuplicatedNodeRepresentatives() const; std::vector<ViaWay> DuplicatedNodeRepresentatives() const;
// Access all duplicated NodeIDs for a set of nodes indicating a via way // Access all duplicated NodeIDs for a set of nodes indicating a via way
util::range<DuplicatedNodeID> DuplicatedNodeIDs(const NodeID from, const NodeID to) const; std::vector<DuplicatedNodeID> DuplicatedNodeIDs(const NodeID from, const NodeID to) const;
// check whether a turn onto a given node is restricted, when coming from a duplicated node // check whether a turn onto a given node is restricted, when coming from a duplicated node
bool IsRestricted(DuplicatedNodeID duplicated_node, const NodeID to) const; bool IsRestricted(DuplicatedNodeID duplicated_node, const NodeID to) const;
// Get the restriction resulting in ^ IsRestricted. Requires IsRestricted to evaluate to true
const ConditionalTurnRestriction &GetRestriction(DuplicatedNodeID duplicated_node,
const NodeID to) const;
// changes edge_based_node to the correct duplicated_node_id in case node_based_from, // changes edge_based_node to the correct duplicated_node_id in case node_based_from,
// node_based_via, node_based_to can be identified with a restriction group // node_based_via, node_based_to can be identified with a restriction group
@@ -76,11 +82,8 @@ class WayRestrictionMap
// EBN: 0 . | 2 | 3 | 4 ... // EBN: 0 . | 2 | 3 | 4 ...
// duplicated node groups: ... | 5 | 7 | ... // duplicated node groups: ... | 5 | 7 | ...
std::vector<DuplicatedNodeID> duplicated_node_groups; std::vector<DuplicatedNodeID> duplicated_node_groups;
std::vector<ConditionalTurnRestriction> restriction_data;
boost::unordered_multimap<std::pair<NodeID, NodeID>, RestrictionID> restriction_starts; RestrictionIndex<ConditionalTurnRestriction> restriction_starts;
boost::unordered_multimap<std::pair<NodeID, NodeID>, RestrictionID> restriction_ends;
std::vector<TurnRestriction> restriction_data;
}; };
} // namespace extractor } // namespace extractor
+1 -1
View File
@@ -97,7 +97,7 @@ template <typename T> void write(io::FileWriter &writer, const std::vector<T> &d
{ {
const auto count = data.size(); const auto count = data.size();
writer.WriteElementCount64(count); writer.WriteElementCount64(count);
return writer.WriteFrom(data.data(), count); writer.WriteFrom(data.data(), count);
} }
template <typename T> void read(io::FileReader &reader, util::vector_view<T> &data) template <typename T> void read(io::FileReader &reader, util::vector_view<T> &data)
+4 -4
View File
@@ -18,13 +18,13 @@ namespace util
struct NodeIdVectorToLineString struct NodeIdVectorToLineString
{ {
NodeIdVectorToLineString(const std::vector<extractor::QueryNode> &node_coordinates); NodeIdVectorToLineString(const std::vector<util::Coordinate> &node_coordinates);
// converts a vector of node ids into a linestring geojson feature // converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<NodeID> &node_ids, util::json::Object operator()(const std::vector<NodeID> &node_ids,
const boost::optional<json::Object> &properties = {}) const; const boost::optional<json::Object> &properties = {}) const;
const std::vector<extractor::QueryNode> &node_coordinates; const std::vector<util::Coordinate> &node_coordinates;
}; };
struct CoordinateVectorToLineString struct CoordinateVectorToLineString
@@ -36,13 +36,13 @@ struct CoordinateVectorToLineString
struct NodeIdVectorToMultiPoint struct NodeIdVectorToMultiPoint
{ {
NodeIdVectorToMultiPoint(const std::vector<extractor::QueryNode> &node_coordinates); NodeIdVectorToMultiPoint(const std::vector<util::Coordinate> &node_coordinates);
// converts a vector of node ids into a linestring geojson feature // converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<NodeID> &node_ids, util::json::Object operator()(const std::vector<NodeID> &node_ids,
const boost::optional<json::Object> &properties = {}) const; const boost::optional<json::Object> &properties = {}) const;
const std::vector<extractor::QueryNode> &node_coordinates; const std::vector<util::Coordinate> &node_coordinates;
}; };
struct CoordinateVectorToMultiPoint struct CoordinateVectorToMultiPoint
@@ -69,12 +69,12 @@ struct CoordinateToJsonArray
struct NodeIdToCoordinate struct NodeIdToCoordinate
{ {
NodeIdToCoordinate(const std::vector<extractor::QueryNode> &node_coordinates) NodeIdToCoordinate(const std::vector<util::Coordinate> &node_coordinates)
: node_coordinates(node_coordinates) : node_coordinates(node_coordinates)
{ {
} }
const std::vector<extractor::QueryNode> &node_coordinates; const std::vector<util::Coordinate> &node_coordinates;
util::json::Array operator()(const NodeID nid) util::json::Array operator()(const NodeID nid)
{ {
+2701 -1026
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "osrm", "name": "osrm",
"version": "5.10.0-rc.2", "version": "5.11.0",
"private": false, "private": false,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.", "description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
"dependencies": { "dependencies": {
@@ -15,7 +15,7 @@
] ]
}, },
"scripts": { "scripts": {
"lint": "eslint -c ./.eslintrc features/step_definitions/ features/support/", "lint": "node ./node_modules/eslint/bin/eslint.js -c ./.eslintrc features/step_definitions/ features/support/",
"test": "npm run lint && node ./node_modules/cucumber/bin/cucumber.js features/ -p verify && node ./node_modules/cucumber/bin/cucumber.js features/ -p mld", "test": "npm run lint && node ./node_modules/cucumber/bin/cucumber.js features/ -p verify && node ./node_modules/cucumber/bin/cucumber.js features/ -p mld",
"clean": "rm -rf test/cache", "clean": "rm -rf test/cache",
"docs": "./scripts/build_api_docs.sh", "docs": "./scripts/build_api_docs.sh",
@@ -37,6 +37,7 @@
}, },
"devDependencies": { "devDependencies": {
"aws-sdk": "~2.0.31", "aws-sdk": "~2.0.31",
"babel-plugin-transform-class-properties": "^6.24.1",
"chalk": "^1.1.3", "chalk": "^1.1.3",
"cucumber": "^1.2.1", "cucumber": "^1.2.1",
"d3-queue": "^2.0.3", "d3-queue": "^2.0.3",
@@ -17,7 +17,7 @@ namespace
{ {
// check bearings for u-turns. // check bearings for u-turns.
// since bearings are wrapped around at 0 (we only support 0,360), we need to do some minor math to // since bearings are wrapped around at 0 (we only support 0,360), we need to do some minor math to
// check if bearings `a` and `b` go in opposite directions. In general we accept some minor // check if bearings `a` and `b` go in opposite directions. In general we accept some minor
// deviations for u-turns. // deviations for u-turns.
bool bearingsAreReversed(const double bearing_in, const double bearing_out) bool bearingsAreReversed(const double bearing_in, const double bearing_out)
@@ -123,7 +123,7 @@ bool isStaggeredIntersection(const RouteStepIterator step_prior_to_intersection,
const auto angle = [](const RouteStep &step) { const auto angle = [](const RouteStep &step) {
const auto &intersection = step.intersections.front(); const auto &intersection = step.intersections.front();
const auto entry_bearing = intersection.bearings[intersection.in]; const auto entry_bearing = util::bearing::reverse(intersection.bearings[intersection.in]);
const auto exit_bearing = intersection.bearings[intersection.out]; const auto exit_bearing = intersection.bearings[intersection.out];
return util::bearing::angleBetween(entry_bearing, exit_bearing); return util::bearing::angleBetween(entry_bearing, exit_bearing);
}; };
+25 -1
View File
@@ -158,6 +158,18 @@ void TransferTurnTypeStrategy::operator()(RouteStep &step_at_turn_location,
void AdjustToCombinedTurnAngleStrategy::operator()(RouteStep &step_at_turn_location, void AdjustToCombinedTurnAngleStrategy::operator()(RouteStep &step_at_turn_location,
const RouteStep &transfer_from_step) const const RouteStep &transfer_from_step) const
{ {
// Forks point to left/right. By doing a combined angle, we would risk ending up with
// unreasonable fork instrucitons. The direction of a fork only depends on the forking location,
// not further angles coming up
//
// d
// . c
// a - b
//
// could end up as `fork left` for `a-b-c`, instead of fork-right
if (hasTurnType(step_at_turn_location, TurnType::Fork))
return;
// TODO assert transfer_from_step == step_at_turn_location + 1 // TODO assert transfer_from_step == step_at_turn_location + 1
const auto angle = findTotalTurnAngle(step_at_turn_location, transfer_from_step); const auto angle = findTotalTurnAngle(step_at_turn_location, transfer_from_step);
step_at_turn_location.maneuver.instruction.direction_modifier = getTurnDirection(angle); step_at_turn_location.maneuver.instruction.direction_modifier = getTurnDirection(angle);
@@ -173,7 +185,19 @@ void AdjustToCombinedTurnStrategy::operator()(RouteStep &step_at_turn_location,
const RouteStep &transfer_from_step) const const RouteStep &transfer_from_step) const
{ {
const auto angle = findTotalTurnAngle(step_at_turn_location, transfer_from_step); const auto angle = findTotalTurnAngle(step_at_turn_location, transfer_from_step);
const auto new_modifier = getTurnDirection(angle);
// Forks point to left/right. By doing a combined angle, we would risk ending up with
// unreasonable fork instrucitons. The direction of a fork only depends on the forking location,
// not further angles coming up
//
// d
// . c
// a - b
//
// could end up as `fork left` for `a-b-c`, instead of fork-right
const auto new_modifier = hasTurnType(step_at_turn_location, TurnType::Fork)
? step_at_turn_location.maneuver.instruction.direction_modifier
: getTurnDirection(angle);
// a turn that is a new name or straight (turn/continue) // a turn that is a new name or straight (turn/continue)
const auto is_non_turn = [](const RouteStep &step) { const auto is_non_turn = [](const RouteStep &step) {
+15 -1
View File
@@ -629,7 +629,21 @@ std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps)
BOOST_ASSERT(step_index > 0); BOOST_ASSERT(step_index > 0);
const auto &previous_step = steps[last_valid_instruction]; const auto &previous_step = steps[last_valid_instruction];
if (previous_step.intersections.size() < MIN_END_OF_ROAD_INTERSECTIONS) if (previous_step.intersections.size() < MIN_END_OF_ROAD_INTERSECTIONS)
step.maneuver.instruction.type = TurnType::Turn; {
bool same_name =
!(step.name.empty() && step.ref.empty()) &&
!util::guidance::requiresNameAnnounced(previous_step.name,
previous_step.ref,
previous_step.pronunciation,
previous_step.exits,
step.name,
step.ref,
step.pronunciation,
step.exits);
step.maneuver.instruction.type =
same_name ? TurnType::Continue : TurnType::Turn;
}
} }
// Remember the last non silent instruction // Remember the last non silent instruction
+1 -448
View File
@@ -1,10 +1,6 @@
#include "engine/routing_algorithms/shortest_path.hpp"
#include "engine/routing_algorithms/routing_base_ch.hpp" #include "engine/routing_algorithms/routing_base_ch.hpp"
#include "engine/routing_algorithms/routing_base_mld.hpp" #include "engine/routing_algorithms/routing_base_mld.hpp"
#include "engine/routing_algorithms/shortest_path_impl.hpp"
#include <boost/assert.hpp>
#include <boost/optional.hpp>
#include <memory>
namespace osrm namespace osrm
{ {
@@ -13,449 +9,6 @@ namespace engine
namespace routing_algorithms namespace routing_algorithms
{ {
namespace
{
const static constexpr bool DO_NOT_FORCE_LOOP = false;
// allows a uturn at the target_phantom
// searches source forward/reverse -> target forward/reverse
template <typename Algorithm>
void searchWithUTurn(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const bool search_from_forward_node,
const bool search_from_reverse_node,
const bool search_to_forward_node,
const bool search_to_reverse_node,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
const int total_weight_to_forward,
const int total_weight_to_reverse,
int &new_total_weight,
std::vector<NodeID> &leg_packed_path)
{
forward_heap.Clear();
reverse_heap.Clear();
if (search_from_forward_node)
{
forward_heap.Insert(source_phantom.forward_segment_id.id,
-source_phantom.GetForwardWeightPlusOffset(),
source_phantom.forward_segment_id.id);
}
if (search_from_reverse_node)
{
forward_heap.Insert(source_phantom.reverse_segment_id.id,
-source_phantom.GetReverseWeightPlusOffset(),
source_phantom.reverse_segment_id.id);
}
if (search_to_forward_node)
{
reverse_heap.Insert(target_phantom.forward_segment_id.id,
target_phantom.GetForwardWeightPlusOffset(),
target_phantom.forward_segment_id.id);
}
if (search_to_reverse_node)
{
reverse_heap.Insert(target_phantom.reverse_segment_id.id,
target_phantom.GetReverseWeightPlusOffset(),
target_phantom.reverse_segment_id.id);
}
// this is only relevent if source and target are on the same compressed edge
auto is_oneway_source = !(search_from_forward_node && search_from_reverse_node);
auto is_oneway_target = !(search_to_forward_node && search_to_reverse_node);
// we only enable loops here if we can't search from forward to backward node
auto needs_loop_forwards = is_oneway_source && needsLoopForward(source_phantom, target_phantom);
auto needs_loop_backwards =
is_oneway_target && needsLoopBackwards(source_phantom, target_phantom);
search(engine_working_data,
facade,
forward_heap,
reverse_heap,
new_total_weight,
leg_packed_path,
needs_loop_forwards,
needs_loop_backwards,
{source_phantom, target_phantom});
// if no route is found between two parts of the via-route, the entire route becomes
// invalid. Adding to invalid edge weight sadly doesn't return an invalid edge weight. Here
// we prevent the possible overflow, faking the addition of infinity + x == infinity
if (new_total_weight != INVALID_EDGE_WEIGHT)
new_total_weight += std::min(total_weight_to_forward, total_weight_to_reverse);
}
// searches shortest path between:
// source forward/reverse -> target forward
// source forward/reverse -> target reverse
template <typename Algorithm>
void search(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const bool search_from_forward_node,
const bool search_from_reverse_node,
const bool search_to_forward_node,
const bool search_to_reverse_node,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
const int total_weight_to_forward,
const int total_weight_to_reverse,
int &new_total_weight_to_forward,
int &new_total_weight_to_reverse,
std::vector<NodeID> &leg_packed_path_forward,
std::vector<NodeID> &leg_packed_path_reverse)
{
if (search_to_forward_node)
{
forward_heap.Clear();
reverse_heap.Clear();
reverse_heap.Insert(target_phantom.forward_segment_id.id,
target_phantom.GetForwardWeightPlusOffset(),
target_phantom.forward_segment_id.id);
if (search_from_forward_node)
{
forward_heap.Insert(source_phantom.forward_segment_id.id,
total_weight_to_forward -
source_phantom.GetForwardWeightPlusOffset(),
source_phantom.forward_segment_id.id);
}
if (search_from_reverse_node)
{
forward_heap.Insert(source_phantom.reverse_segment_id.id,
total_weight_to_reverse -
source_phantom.GetReverseWeightPlusOffset(),
source_phantom.reverse_segment_id.id);
}
search(engine_working_data,
facade,
forward_heap,
reverse_heap,
new_total_weight_to_forward,
leg_packed_path_forward,
needsLoopForward(source_phantom, target_phantom),
routing_algorithms::DO_NOT_FORCE_LOOP,
{source_phantom, target_phantom});
}
if (search_to_reverse_node)
{
forward_heap.Clear();
reverse_heap.Clear();
reverse_heap.Insert(target_phantom.reverse_segment_id.id,
target_phantom.GetReverseWeightPlusOffset(),
target_phantom.reverse_segment_id.id);
if (search_from_forward_node)
{
forward_heap.Insert(source_phantom.forward_segment_id.id,
total_weight_to_forward -
source_phantom.GetForwardWeightPlusOffset(),
source_phantom.forward_segment_id.id);
}
if (search_from_reverse_node)
{
forward_heap.Insert(source_phantom.reverse_segment_id.id,
total_weight_to_reverse -
source_phantom.GetReverseWeightPlusOffset(),
source_phantom.reverse_segment_id.id);
}
search(engine_working_data,
facade,
forward_heap,
reverse_heap,
new_total_weight_to_reverse,
leg_packed_path_reverse,
routing_algorithms::DO_NOT_FORCE_LOOP,
needsLoopBackwards(source_phantom, target_phantom),
{source_phantom, target_phantom});
}
}
template <typename Algorithm>
void unpackLegs(const DataFacade<Algorithm> &facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const std::vector<NodeID> &total_packed_path,
const std::vector<std::size_t> &packed_leg_begin,
const EdgeWeight shortest_path_weight,
InternalRouteResult &raw_route_data)
{
raw_route_data.unpacked_path_segments.resize(packed_leg_begin.size() - 1);
raw_route_data.shortest_path_weight = shortest_path_weight;
for (const auto current_leg : util::irange<std::size_t>(0UL, packed_leg_begin.size() - 1))
{
auto leg_begin = total_packed_path.begin() + packed_leg_begin[current_leg];
auto leg_end = total_packed_path.begin() + packed_leg_begin[current_leg + 1];
const auto &unpack_phantom_node_pair = phantom_nodes_vector[current_leg];
unpackPath(facade,
leg_begin,
leg_end,
unpack_phantom_node_pair,
raw_route_data.unpacked_path_segments[current_leg]);
raw_route_data.source_traversed_in_reverse.push_back(
(*leg_begin != phantom_nodes_vector[current_leg].source_phantom.forward_segment_id.id));
raw_route_data.target_traversed_in_reverse.push_back(
(*std::prev(leg_end) !=
phantom_nodes_vector[current_leg].target_phantom.forward_segment_id.id));
}
}
}
template <typename Algorithm>
InternalRouteResult shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const boost::optional<bool> continue_straight_at_waypoint)
{
InternalRouteResult raw_route_data;
raw_route_data.segment_end_coordinates = phantom_nodes_vector;
const bool allow_uturn_at_waypoint =
!(continue_straight_at_waypoint ? *continue_straight_at_waypoint
: facade.GetContinueStraightDefault());
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
auto &forward_heap = *engine_working_data.forward_heap_1;
auto &reverse_heap = *engine_working_data.reverse_heap_1;
int total_weight_to_forward = 0;
int total_weight_to_reverse = 0;
bool search_from_forward_node =
phantom_nodes_vector.front().source_phantom.IsValidForwardSource();
bool search_from_reverse_node =
phantom_nodes_vector.front().source_phantom.IsValidReverseSource();
std::vector<NodeID> prev_packed_leg_to_forward;
std::vector<NodeID> prev_packed_leg_to_reverse;
std::vector<NodeID> total_packed_path_to_forward;
std::vector<std::size_t> packed_leg_to_forward_begin;
std::vector<NodeID> total_packed_path_to_reverse;
std::vector<std::size_t> packed_leg_to_reverse_begin;
std::size_t current_leg = 0;
// this implements a dynamic program that finds the shortest route through
// a list of vias
for (const auto &phantom_node_pair : phantom_nodes_vector)
{
int new_total_weight_to_forward = INVALID_EDGE_WEIGHT;
int new_total_weight_to_reverse = INVALID_EDGE_WEIGHT;
std::vector<NodeID> packed_leg_to_forward;
std::vector<NodeID> packed_leg_to_reverse;
const auto &source_phantom = phantom_node_pair.source_phantom;
const auto &target_phantom = phantom_node_pair.target_phantom;
bool search_to_forward_node = target_phantom.IsValidForwardTarget();
bool search_to_reverse_node = target_phantom.IsValidReverseTarget();
BOOST_ASSERT(!search_from_forward_node || source_phantom.IsValidForwardSource());
BOOST_ASSERT(!search_from_reverse_node || source_phantom.IsValidReverseSource());
if (search_to_reverse_node || search_to_forward_node)
{
if (allow_uturn_at_waypoint)
{
searchWithUTurn(engine_working_data,
facade,
forward_heap,
reverse_heap,
search_from_forward_node,
search_from_reverse_node,
search_to_forward_node,
search_to_reverse_node,
source_phantom,
target_phantom,
total_weight_to_forward,
total_weight_to_reverse,
new_total_weight_to_forward,
packed_leg_to_forward);
// if only the reverse node is valid (e.g. when using the match plugin) we
// actually need to move
if (!target_phantom.IsValidForwardTarget())
{
BOOST_ASSERT(target_phantom.IsValidReverseTarget());
new_total_weight_to_reverse = new_total_weight_to_forward;
packed_leg_to_reverse = std::move(packed_leg_to_forward);
new_total_weight_to_forward = INVALID_EDGE_WEIGHT;
// (*)
//
// Below we have to check if new_total_weight_to_forward is invalid.
// This prevents use-after-move on packed_leg_to_forward.
}
else if (target_phantom.IsValidReverseTarget())
{
new_total_weight_to_reverse = new_total_weight_to_forward;
packed_leg_to_reverse = packed_leg_to_forward;
}
}
else
{
search(engine_working_data,
facade,
forward_heap,
reverse_heap,
search_from_forward_node,
search_from_reverse_node,
search_to_forward_node,
search_to_reverse_node,
source_phantom,
target_phantom,
total_weight_to_forward,
total_weight_to_reverse,
new_total_weight_to_forward,
new_total_weight_to_reverse,
packed_leg_to_forward,
packed_leg_to_reverse);
}
}
// Note: To make sure we do not access the moved-from packed_leg_to_forward
// we guard its access by a check for invalid edge weight. See (*) above.
// No path found for both target nodes?
if ((INVALID_EDGE_WEIGHT == new_total_weight_to_forward) &&
(INVALID_EDGE_WEIGHT == new_total_weight_to_reverse))
{
return raw_route_data;
}
// we need to figure out how the new legs connect to the previous ones
if (current_leg > 0)
{
bool forward_to_forward =
(new_total_weight_to_forward != INVALID_EDGE_WEIGHT) &&
packed_leg_to_forward.front() == source_phantom.forward_segment_id.id;
bool reverse_to_forward =
(new_total_weight_to_forward != INVALID_EDGE_WEIGHT) &&
packed_leg_to_forward.front() == source_phantom.reverse_segment_id.id;
bool forward_to_reverse =
(new_total_weight_to_reverse != INVALID_EDGE_WEIGHT) &&
packed_leg_to_reverse.front() == source_phantom.forward_segment_id.id;
bool reverse_to_reverse =
(new_total_weight_to_reverse != INVALID_EDGE_WEIGHT) &&
packed_leg_to_reverse.front() == source_phantom.reverse_segment_id.id;
BOOST_ASSERT(!forward_to_forward || !reverse_to_forward);
BOOST_ASSERT(!forward_to_reverse || !reverse_to_reverse);
// in this case we always need to copy
if (forward_to_forward && forward_to_reverse)
{
// in this case we copy the path leading to the source forward node
// and change the case
total_packed_path_to_reverse = total_packed_path_to_forward;
packed_leg_to_reverse_begin = packed_leg_to_forward_begin;
forward_to_reverse = false;
reverse_to_reverse = true;
}
else if (reverse_to_forward && reverse_to_reverse)
{
total_packed_path_to_forward = total_packed_path_to_reverse;
packed_leg_to_forward_begin = packed_leg_to_reverse_begin;
reverse_to_forward = false;
forward_to_forward = true;
}
BOOST_ASSERT(!forward_to_forward || !forward_to_reverse);
BOOST_ASSERT(!reverse_to_forward || !reverse_to_reverse);
// in this case we just need to swap to regain the correct mapping
if (reverse_to_forward || forward_to_reverse)
{
total_packed_path_to_forward.swap(total_packed_path_to_reverse);
packed_leg_to_forward_begin.swap(packed_leg_to_reverse_begin);
}
}
if (new_total_weight_to_forward != INVALID_EDGE_WEIGHT)
{
BOOST_ASSERT(target_phantom.IsValidForwardTarget());
packed_leg_to_forward_begin.push_back(total_packed_path_to_forward.size());
total_packed_path_to_forward.insert(total_packed_path_to_forward.end(),
packed_leg_to_forward.begin(),
packed_leg_to_forward.end());
search_from_forward_node = true;
}
else
{
total_packed_path_to_forward.clear();
packed_leg_to_forward_begin.clear();
search_from_forward_node = false;
}
if (new_total_weight_to_reverse != INVALID_EDGE_WEIGHT)
{
BOOST_ASSERT(target_phantom.IsValidReverseTarget());
packed_leg_to_reverse_begin.push_back(total_packed_path_to_reverse.size());
total_packed_path_to_reverse.insert(total_packed_path_to_reverse.end(),
packed_leg_to_reverse.begin(),
packed_leg_to_reverse.end());
search_from_reverse_node = true;
}
else
{
total_packed_path_to_reverse.clear();
packed_leg_to_reverse_begin.clear();
search_from_reverse_node = false;
}
prev_packed_leg_to_forward = std::move(packed_leg_to_forward);
prev_packed_leg_to_reverse = std::move(packed_leg_to_reverse);
total_weight_to_forward = new_total_weight_to_forward;
total_weight_to_reverse = new_total_weight_to_reverse;
++current_leg;
}
BOOST_ASSERT(total_weight_to_forward != INVALID_EDGE_WEIGHT ||
total_weight_to_reverse != INVALID_EDGE_WEIGHT);
// We make sure the fastest route is always in packed_legs_to_forward
if (total_weight_to_forward < total_weight_to_reverse ||
(total_weight_to_forward == total_weight_to_reverse &&
total_packed_path_to_forward.size() < total_packed_path_to_reverse.size()))
{
// insert sentinel
packed_leg_to_forward_begin.push_back(total_packed_path_to_forward.size());
BOOST_ASSERT(packed_leg_to_forward_begin.size() == phantom_nodes_vector.size() + 1);
unpackLegs(facade,
phantom_nodes_vector,
total_packed_path_to_forward,
packed_leg_to_forward_begin,
total_weight_to_forward,
raw_route_data);
}
else
{
// insert sentinel
packed_leg_to_reverse_begin.push_back(total_packed_path_to_reverse.size());
BOOST_ASSERT(packed_leg_to_reverse_begin.size() == phantom_nodes_vector.size() + 1);
unpackLegs(facade,
phantom_nodes_vector,
total_packed_path_to_reverse,
packed_leg_to_reverse_begin,
total_weight_to_reverse,
raw_route_data);
}
return raw_route_data;
}
template InternalRouteResult template InternalRouteResult
shortestPathSearch(SearchEngineData<ch::Algorithm> &engine_working_data, shortestPathSearch(SearchEngineData<ch::Algorithm> &engine_working_data,
const DataFacade<ch::Algorithm> &facade, const DataFacade<ch::Algorithm> &facade,
+22 -9
View File
@@ -103,14 +103,17 @@ SegmentDuration CompressedEdgeContainer::ClipDuration(const SegmentDuration dura
// ----------> via_node_id -----------> target_node_id // ----------> via_node_id -----------> target_node_id
// weight_1 weight_2 // weight_1 weight_2
// duration_1 duration_2 // duration_1 duration_2
void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1, void CompressedEdgeContainer::CompressEdge(
const EdgeID edge_id_2, const EdgeID edge_id_1,
const NodeID via_node_id, const EdgeID edge_id_2,
const NodeID target_node_id, const NodeID via_node_id,
const EdgeWeight weight1, const NodeID target_node_id,
const EdgeWeight weight2, const EdgeWeight weight1,
const EdgeDuration duration1, const EdgeWeight weight2,
const EdgeDuration duration2) const EdgeDuration duration1,
const EdgeDuration duration2,
const boost::optional<EdgeWeight> node_weight_penalty,
const boost::optional<EdgeDuration> node_duration_penalty)
{ {
// remove super-trivial geometries // remove super-trivial geometries
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_1); BOOST_ASSERT(SPECIAL_EDGEID != edge_id_1);
@@ -151,9 +154,11 @@ void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
std::vector<OnewayCompressedEdge> &edge_bucket_list1 = std::vector<OnewayCompressedEdge> &edge_bucket_list1 =
m_compressed_oneway_geometries[edge_bucket_id1]; m_compressed_oneway_geometries[edge_bucket_id1];
bool was_empty = edge_bucket_list1.empty();
// note we don't save the start coordinate: it is implicitly given by edge 1 // note we don't save the start coordinate: it is implicitly given by edge 1
// weight1 is the distance to the (currently) last coordinate in the bucket // weight1 is the distance to the (currently) last coordinate in the bucket
if (edge_bucket_list1.empty()) if (was_empty)
{ {
edge_bucket_list1.emplace_back( edge_bucket_list1.emplace_back(
OnewayCompressedEdge{via_node_id, ClipWeight(weight1), ClipDuration(duration1)}); OnewayCompressedEdge{via_node_id, ClipWeight(weight1), ClipDuration(duration1)});
@@ -162,6 +167,14 @@ void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
BOOST_ASSERT(0 < edge_bucket_list1.size()); BOOST_ASSERT(0 < edge_bucket_list1.size());
BOOST_ASSERT(!edge_bucket_list1.empty()); BOOST_ASSERT(!edge_bucket_list1.empty());
// if the via-node offers a penalty, we add the weight of the penalty as an artificial
// segment that references SPECIAL_NODEID
if (node_weight_penalty && node_duration_penalty)
{
edge_bucket_list1.emplace_back(OnewayCompressedEdge{
via_node_id, ClipWeight(*node_weight_penalty), ClipDuration(*node_duration_penalty)});
}
if (HasEntryForID(edge_id_2)) if (HasEntryForID(edge_id_2))
{ {
// second edge is not atomic anymore // second edge is not atomic anymore
+178 -32
View File
@@ -1,4 +1,5 @@
#include "extractor/edge_based_graph_factory.hpp" #include "extractor/edge_based_graph_factory.hpp"
#include "extractor/conditional_turn_penalty.hpp"
#include "extractor/edge_based_edge.hpp" #include "extractor/edge_based_edge.hpp"
#include "extractor/files.hpp" #include "extractor/files.hpp"
#include "extractor/guidance/turn_analysis.hpp" #include "extractor/guidance/turn_analysis.hpp"
@@ -6,6 +7,7 @@
#include "extractor/scripting_environment.hpp" #include "extractor/scripting_environment.hpp"
#include "extractor/suffix_table.hpp" #include "extractor/suffix_table.hpp"
#include "extractor/serialization.hpp"
#include "storage/io.hpp" #include "storage/io.hpp"
#include "util/assert.hpp" #include "util/assert.hpp"
@@ -20,8 +22,10 @@
#include "util/timing_util.hpp" #include "util/timing_util.hpp"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/functional/hash.hpp>
#include <boost/numeric/conversion/cast.hpp> #include <boost/numeric/conversion/cast.hpp>
#include "boost/unordered_map.hpp"
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <iomanip> #include <iomanip>
@@ -35,12 +39,26 @@
#include <tbb/pipeline.h> #include <tbb/pipeline.h>
#include <tbb/task_scheduler_init.h> #include <tbb/task_scheduler_init.h>
namespace std
{
template <> struct hash<std::pair<NodeID, NodeID>>
{
std::size_t operator()(const std::pair<NodeID, NodeID> &mk) const noexcept
{
std::size_t seed = 0;
boost::hash_combine(seed, mk.first);
boost::hash_combine(seed, mk.second);
return seed;
}
};
}
namespace osrm namespace osrm
{ {
namespace extractor namespace extractor
{ {
// Configuration to find representative candidate for turn angle calculations
// Configuration to find representative candidate for turn angle calculations
EdgeBasedGraphFactory::EdgeBasedGraphFactory( EdgeBasedGraphFactory::EdgeBasedGraphFactory(
std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph, std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph,
CompressedEdgeContainer &compressed_edge_container, CompressedEdgeContainer &compressed_edge_container,
@@ -168,6 +186,11 @@ NBGToEBG EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const N
m_compressed_edge_container.GetBucketReference(edge_id_2)[segment_count - 1 - i] m_compressed_edge_container.GetBucketReference(edge_id_2)[segment_count - 1 - i]
.node_id); .node_id);
const NodeID current_edge_target_coordinate_id = forward_geometry[i].node_id; const NodeID current_edge_target_coordinate_id = forward_geometry[i].node_id;
// don't add node-segments for penalties
if (current_edge_target_coordinate_id == current_edge_source_coordinate_id)
continue;
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id); BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
// build edges // build edges
@@ -194,7 +217,9 @@ void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment,
const std::string &turn_duration_penalties_filename, const std::string &turn_duration_penalties_filename,
const std::string &turn_penalties_index_filename, const std::string &turn_penalties_index_filename,
const std::string &cnbg_ebg_mapping_path, const std::string &cnbg_ebg_mapping_path,
const std::string &conditional_penalties_filename,
const RestrictionMap &node_restriction_map, const RestrictionMap &node_restriction_map,
const ConditionalRestrictionMap &conditional_node_restriction_map,
const WayRestrictionMap &way_restriction_map) const WayRestrictionMap &way_restriction_map)
{ {
TIMER_START(renumber); TIMER_START(renumber);
@@ -215,7 +240,9 @@ void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment,
turn_weight_penalties_filename, turn_weight_penalties_filename,
turn_duration_penalties_filename, turn_duration_penalties_filename,
turn_penalties_index_filename, turn_penalties_index_filename,
conditional_penalties_filename,
node_restriction_map, node_restriction_map,
conditional_node_restriction_map,
way_restriction_map); way_restriction_map);
TIMER_STOP(generate_edges); TIMER_STOP(generate_edges);
@@ -379,7 +406,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
const std::string &turn_weight_penalties_filename, const std::string &turn_weight_penalties_filename,
const std::string &turn_duration_penalties_filename, const std::string &turn_duration_penalties_filename,
const std::string &turn_penalties_index_filename, const std::string &turn_penalties_index_filename,
const std::string &conditional_penalties_filename,
const RestrictionMap &node_restriction_map, const RestrictionMap &node_restriction_map,
const ConditionalRestrictionMap &conditional_restriction_map,
const WayRestrictionMap &way_restriction_map) const WayRestrictionMap &way_restriction_map)
{ {
@@ -422,6 +451,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
const auto weight_multiplier = const auto weight_multiplier =
scripting_environment.GetProfileProperties().GetWeightMultiplier(); scripting_environment.GetProfileProperties().GetWeightMultiplier();
// filled in during next stage, kept alive through following scope
std::vector<Conditional> conditionals;
// The following block generates the edge-based-edges using a parallel processing // The following block generates the edge-based-edges using a parallel processing
// pipeline. Sets of intersection IDs are batched in groups of GRAINSIZE (100) // pipeline. Sets of intersection IDs are batched in groups of GRAINSIZE (100)
// `generator_stage`, // `generator_stage`,
@@ -477,7 +508,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
}; };
// same as IntersectionData, but grouped with edge to allow sorting after creating. Edges // same as IntersectionData, but grouped with edge to allow sorting after creating. Edges
// are out of order // can be out of order
struct EdgeWithData struct EdgeWithData
{ {
EdgeBasedEdge edge; EdgeBasedEdge edge;
@@ -492,10 +523,14 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
std::size_t nodes_processed = 0; std::size_t nodes_processed = 0;
IntersectionData continuous_data; IntersectionData continuous_data;
std::vector<EdgeWithData> delayed_data; std::vector<EdgeWithData> delayed_data;
std::vector<Conditional> conditionals;
}; };
// Generate edges for either artificial nodes or the main graph // Generate edges for either artificial nodes or the main graph
const auto generate_edge = [this, &scripting_environment, weight_multiplier]( const auto generate_edge = [this,
&scripting_environment,
weight_multiplier,
&conditional_restriction_map](
// what nodes will be used? In most cases this will be the id stored in the edge_data. // what nodes will be used? In most cases this will be the id stored in the edge_data.
// In case of duplicated nodes (e.g. due to via-way restrictions), one/both of these // In case of duplicated nodes (e.g. due to via-way restrictions), one/both of these
// might refer to a newly added edge based node // might refer to a newly added edge based node
@@ -509,6 +544,24 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
const auto &intersection, const auto &intersection,
const auto &turn, const auto &turn,
const auto entry_class_id) { const auto entry_class_id) {
const auto node_restricted = isRestricted(node_along_road_entering,
node_at_center_of_intersection,
m_node_based_graph->GetTarget(turn.eid),
conditional_restriction_map);
boost::optional<Conditional> conditional = boost::none;
if (node_restricted.first)
{
auto const &conditions = node_restricted.second->condition;
// get conditions of the restriction limiting the node
conditional = {{edge_based_node_from,
edge_based_node_to,
{static_cast<std::uint64_t>(-1),
m_coordinates[node_at_center_of_intersection],
conditions}}};
}
const EdgeData &edge_data1 = m_node_based_graph->GetEdgeData(node_based_edge_from); const EdgeData &edge_data1 = m_node_based_graph->GetEdgeData(node_based_edge_from);
const EdgeData &edge_data2 = m_node_based_graph->GetEdgeData(node_based_edge_to); const EdgeData &edge_data2 = m_node_based_graph->GetEdgeData(node_based_edge_to);
@@ -568,15 +621,16 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
const auto &from_node = const auto &from_node =
isTrivial ? node_along_road_entering isTrivial ? node_along_road_entering
: m_compressed_edge_container.GetLastEdgeSourceID(node_based_edge_from); : m_compressed_edge_container.GetLastEdgeSourceID(node_based_edge_from);
const auto &via_node =
m_compressed_edge_container.GetLastEdgeTargetID(node_based_edge_from);
const auto &to_node = m_compressed_edge_container.GetFirstEdgeTargetID(turn.eid); const auto &to_node = m_compressed_edge_container.GetFirstEdgeTargetID(turn.eid);
lookup::TurnIndexBlock turn_index_block = {from_node, via_node, to_node}; lookup::TurnIndexBlock turn_index_block = {
from_node, node_at_center_of_intersection, to_node};
// insert data into the designated buffer // insert data into the designated buffer
return EdgeWithData{ return std::make_pair(
edge_based_edge, turn_index_block, weight_penalty, duration_penalty, turn_data}; EdgeWithData{
edge_based_edge, turn_index_block, weight_penalty, duration_penalty, turn_data},
conditional);
}; };
// Second part of the pipeline is where the intersection analysis is done for // Second part of the pipeline is where the intersection analysis is done for
@@ -715,7 +769,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
m_number_of_edge_based_nodes); m_number_of_edge_based_nodes);
{ // scope to forget edge_with_data after { // scope to forget edge_with_data after
const auto edge_with_data = const auto edge_with_data_and_condition =
generate_edge(edge_data1.edge_id, generate_edge(edge_data1.edge_id,
target_id, target_id,
node_along_road_entering, node_along_road_entering,
@@ -726,15 +780,21 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
turn, turn,
entry_class_id); entry_class_id);
buffer->continuous_data.edges_list.push_back(edge_with_data.edge); buffer->continuous_data.edges_list.push_back(
edge_with_data_and_condition.first.edge);
buffer->continuous_data.turn_indexes.push_back( buffer->continuous_data.turn_indexes.push_back(
edge_with_data.turn_index); edge_with_data_and_condition.first.turn_index);
buffer->continuous_data.turn_weight_penalties.push_back( buffer->continuous_data.turn_weight_penalties.push_back(
edge_with_data.turn_weight_penalty); edge_with_data_and_condition.first.turn_weight_penalty);
buffer->continuous_data.turn_duration_penalties.push_back( buffer->continuous_data.turn_duration_penalties.push_back(
edge_with_data.turn_duration_penalty); edge_with_data_and_condition.first.turn_duration_penalty);
buffer->continuous_data.turn_data_container.push_back( buffer->continuous_data.turn_data_container.push_back(
edge_with_data.turn_data); edge_with_data_and_condition.first.turn_data);
if (edge_with_data_and_condition.second)
{
buffer->conditionals.push_back(
*edge_with_data_and_condition.second);
}
} }
// when turning off a a via-way turn restriction, we need to not only // when turning off a a via-way turn restriction, we need to not only
@@ -749,24 +809,30 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// next to the normal restrictions tracked in `entry_allowed`, via // next to the normal restrictions tracked in `entry_allowed`, via
// ways might introduce additional restrictions. These are handled // ways might introduce additional restrictions. These are handled
// here when turning off a via-way // here when turning off a via-way
const auto add_unrestricted_turns = for (auto duplicated_node_id : duplicated_nodes)
[&](const auto duplicated_node_id) { {
const auto from_id = const auto from_id =
m_number_of_edge_based_nodes - m_number_of_edge_based_nodes -
way_restriction_map.NumberOfDuplicatedNodes() + way_restriction_map.NumberOfDuplicatedNodes() +
duplicated_node_id; duplicated_node_id;
auto const node_at_end_of_turn = auto const node_at_end_of_turn =
m_node_based_graph->GetTarget(turn.eid); m_node_based_graph->GetTarget(turn.eid);
const auto is_restricted = way_restriction_map.IsRestricted( const auto is_way_restricted = way_restriction_map.IsRestricted(
duplicated_node_id, node_at_end_of_turn);
if (is_way_restricted)
{
auto const restriction = way_restriction_map.GetRestriction(
duplicated_node_id, node_at_end_of_turn); duplicated_node_id, node_at_end_of_turn);
if (is_restricted) if (restriction.condition.empty())
return; continue;
// add into delayed data // add into delayed data
auto edge_with_data = generate_edge( auto edge_with_data_and_condition = generate_edge(
NodeID(from_id), NodeID(from_id),
m_node_based_graph->GetEdgeData(turn.eid).edge_id, m_node_based_graph->GetEdgeData(turn.eid).edge_id,
node_along_road_entering, node_along_road_entering,
@@ -777,12 +843,50 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
turn, turn,
entry_class_id); entry_class_id);
buffer->delayed_data.push_back(std::move(edge_with_data)); buffer->delayed_data.push_back(
}; std::move(edge_with_data_and_condition.first));
std::for_each(duplicated_nodes.begin(), if (edge_with_data_and_condition.second)
duplicated_nodes.end(), {
add_unrestricted_turns); buffer->conditionals.push_back(
*edge_with_data_and_condition.second);
}
// also add the conditions for the way
if (is_way_restricted && !restriction.condition.empty())
{
// add a new conditional for the edge we just created
buffer->conditionals.push_back(
{NodeID(from_id),
m_node_based_graph->GetEdgeData(turn.eid).edge_id,
{static_cast<std::uint64_t>(-1),
m_coordinates[node_at_center_of_intersection],
restriction.condition}});
}
}
else
{
auto edge_with_data_and_condition = generate_edge(
NodeID(from_id),
m_node_based_graph->GetEdgeData(turn.eid).edge_id,
node_along_road_entering,
incoming_edge,
node_at_center_of_intersection,
turn.eid,
intersection,
turn,
entry_class_id);
buffer->delayed_data.push_back(
std::move(edge_with_data_and_condition.first));
if (edge_with_data_and_condition.second)
{
buffer->conditionals.push_back(
*edge_with_data_and_condition.second);
}
}
}
} }
} }
} }
@@ -826,6 +930,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
data.turn_indexes.begin(), data.turn_indexes.begin(),
data.turn_indexes.end()); data.turn_indexes.end());
conditionals.insert(
conditionals.end(), buffer->conditionals.begin(), buffer->conditionals.end());
// Buffer writes to reduce syscall count // Buffer writes to reduce syscall count
if (turn_indexes_write_buffer.size() >= TURN_INDEX_WRITE_BUFFER_SIZE) if (turn_indexes_write_buffer.size() >= TURN_INDEX_WRITE_BUFFER_SIZE)
{ {
@@ -878,6 +985,20 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
} }
}); });
// re-hash conditionals to ocnnect to their respective edge-based edges. Due to the
// ordering, we
// do not really have a choice but to index the conditional penalties and walk over all
// edge-based-edges to find the ID of the edge
auto const indexed_conditionals = IndexConditionals(std::move(conditionals));
{
util::Log() << "Writing " << indexed_conditionals.size()
<< " conditional turn penalties...";
// write conditional turn penalties into the restrictions file
storage::io::FileWriter writer(conditional_penalties_filename,
storage::io::FileWriter::GenerateFingerprint);
extractor::serialization::write(writer, indexed_conditionals);
}
// write weight penalties per turn // write weight penalties per turn
BOOST_ASSERT(turn_weight_penalties.size() == turn_duration_penalties.size()); BOOST_ASSERT(turn_weight_penalties.size() == turn_duration_penalties.size());
{ {
@@ -917,11 +1038,36 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
util::Log() << " contains " << m_edge_based_edge_list.size() << " edges"; util::Log() << " contains " << m_edge_based_edge_list.size() << " edges";
util::Log() << " skips " << restricted_turns_counter << " turns, " util::Log() << " skips " << restricted_turns_counter << " turns, "
"defined by " "defined by "
<< node_restriction_map.size() << " restrictions"; << node_restriction_map.Size() << " restrictions";
util::Log() << " skips " << skipped_uturns_counter << " U turns"; util::Log() << " skips " << skipped_uturns_counter << " U turns";
util::Log() << " skips " << skipped_barrier_turns_counter << " turns over barriers"; util::Log() << " skips " << skipped_barrier_turns_counter << " turns over barriers";
} }
std::vector<ConditionalTurnPenalty>
EdgeBasedGraphFactory::IndexConditionals(std::vector<Conditional> &&conditionals) const
{
boost::unordered_multimap<std::pair<NodeID, NodeID>, ConditionalTurnPenalty *> index;
// build and index of all conditional restrictions
for (auto &conditional : conditionals)
index.insert(std::make_pair(std::make_pair(conditional.from_node, conditional.to_node),
&conditional.penalty));
std::vector<ConditionalTurnPenalty> indexed_restrictions;
for (auto const &edge : m_edge_based_edge_list)
{
auto const range = index.equal_range(std::make_pair(edge.source, edge.target));
for (auto itr = range.first; itr != range.second; ++itr)
{
itr->second->turn_offset = edge.data.turn_id;
indexed_restrictions.push_back(*itr->second);
}
}
return indexed_restrictions;
}
std::vector<util::guidance::BearingClass> EdgeBasedGraphFactory::GetBearingClasses() const std::vector<util::guidance::BearingClass> EdgeBasedGraphFactory::GetBearingClasses() const
{ {
std::vector<util::guidance::BearingClass> result(bearing_class_hash.data.size()); std::vector<util::guidance::BearingClass> result(bearing_class_hash.data.size());
+8 -17
View File
@@ -126,7 +126,6 @@ ExtractionContainers::ExtractionContainers()
*/ */
void ExtractionContainers::PrepareData(ScriptingEnvironment &scripting_environment, void ExtractionContainers::PrepareData(ScriptingEnvironment &scripting_environment,
const std::string &osrm_path, const std::string &osrm_path,
const std::string &restrictions_file_name,
const std::string &name_file_name) const std::string &name_file_name)
{ {
storage::io::FileWriter file_out(osrm_path, storage::io::FileWriter::GenerateFingerprint); storage::io::FileWriter file_out(osrm_path, storage::io::FileWriter::GenerateFingerprint);
@@ -139,7 +138,6 @@ void ExtractionContainers::PrepareData(ScriptingEnvironment &scripting_environme
WriteEdges(file_out); WriteEdges(file_out);
PrepareRestrictions(); PrepareRestrictions();
WriteConditionalRestrictions(restrictions_file_name);
WriteCharData(name_file_name); WriteCharData(name_file_name);
} }
@@ -616,33 +614,23 @@ void ExtractionContainers::WriteNodes(storage::io::FileWriter &file_out) const
util::UnbufferedLog log; util::UnbufferedLog log;
log << "Writing traffic light nodes ... "; log << "Writing traffic light nodes ... ";
TIMER_START(write_nodes); TIMER_START(write_nodes);
std::vector<NodeID> internal_traffic_lights; std::vector<NodeID> internal_traffic_signals;
for (const auto osm_id : traffic_lights) for (const auto osm_id : traffic_signals)
{ {
const auto node_id = mapExternalToInternalNodeID( const auto node_id = mapExternalToInternalNodeID(
used_node_id_list.begin(), used_node_id_list.end(), osm_id); used_node_id_list.begin(), used_node_id_list.end(), osm_id);
if (node_id != SPECIAL_NODEID) if (node_id != SPECIAL_NODEID)
{ {
internal_traffic_lights.push_back(node_id); internal_traffic_signals.push_back(node_id);
} }
} }
storage::serialization::write(file_out, internal_traffic_lights); storage::serialization::write(file_out, internal_traffic_signals);
log << "ok, after " << TIMER_SEC(write_nodes) << "s"; log << "ok, after " << TIMER_SEC(write_nodes) << "s";
} }
util::Log() << "Processed " << max_internal_node_id << " nodes"; util::Log() << "Processed " << max_internal_node_id << " nodes";
} }
void ExtractionContainers::WriteConditionalRestrictions(const std::string &path)
{
std::uint64_t written_restriction_count = conditional_turn_restrictions.size();
storage::io::FileWriter restrictions_out_file(path,
storage::io::FileWriter::GenerateFingerprint);
serialization::write(restrictions_out_file, conditional_turn_restrictions);
util::Log() << "number of conditional restrictions written to disk: "
<< written_restriction_count;
}
void ExtractionContainers::PrepareRestrictions() void ExtractionContainers::PrepareRestrictions()
{ {
@@ -837,7 +825,8 @@ void ExtractionContainers::PrepareRestrictions()
const auto transform_into_internal_types = const auto transform_into_internal_types =
[&](const InputConditionalTurnRestriction &external_restriction) { [&](const InputConditionalTurnRestriction &external_restriction) {
// unconditional restriction // unconditional restriction
if (external_restriction.condition.empty()) if (external_restriction.condition.empty() &&
external_restriction.Type() == RestrictionType::NODE_RESTRICTION)
{ {
TurnRestriction restriction; TurnRestriction restriction;
restriction.is_only = external_restriction.is_only; restriction.is_only = external_restriction.is_only;
@@ -851,7 +840,9 @@ void ExtractionContainers::PrepareRestrictions()
restriction.is_only = external_restriction.is_only; restriction.is_only = external_restriction.is_only;
restriction.condition = std::move(external_restriction.condition); restriction.condition = std::move(external_restriction.condition);
if (transform(external_restriction, restriction)) if (transform(external_restriction, restriction))
{
conditional_turn_restrictions.push_back(std::move(restriction)); conditional_turn_restrictions.push_back(std::move(restriction));
}
} }
}; };
+46 -25
View File
@@ -23,7 +23,7 @@
#include "util/timing_util.hpp" #include "util/timing_util.hpp"
#include "extractor/compressed_edge_container.hpp" #include "extractor/compressed_edge_container.hpp"
#include "extractor/restriction_map.hpp" #include "extractor/restriction_index.hpp"
#include "extractor/way_restriction_map.hpp" #include "extractor/way_restriction_map.hpp"
#include "util/static_graph.hpp" #include "util/static_graph.hpp"
#include "util/static_rtree.hpp" #include "util/static_rtree.hpp"
@@ -110,7 +110,8 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
guidance::LaneDescriptionMap turn_lane_map; guidance::LaneDescriptionMap turn_lane_map;
std::vector<TurnRestriction> turn_restrictions; std::vector<TurnRestriction> turn_restrictions;
std::tie(turn_lane_map, turn_restrictions) = std::vector<ConditionalTurnRestriction> conditional_turn_restrictions;
std::tie(turn_lane_map, turn_restrictions, conditional_turn_restrictions) =
ParseOSMData(scripting_environment, number_of_threads); ParseOSMData(scripting_environment, number_of_threads);
// Transform the node-based graph that OSM is based on into an edge-based graph // Transform the node-based graph that OSM is based on into an edge-based graph
@@ -138,6 +139,7 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
edge_based_edge_list, edge_based_edge_list,
config.GetPath(".osrm.icd").string(), config.GetPath(".osrm.icd").string(),
turn_restrictions, turn_restrictions,
conditional_turn_restrictions,
turn_lane_map); turn_lane_map);
auto number_of_node_based_nodes = graph_size.first; auto number_of_node_based_nodes = graph_size.first;
@@ -190,7 +192,9 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
return 0; return 0;
} }
std::tuple<guidance::LaneDescriptionMap, std::vector<TurnRestriction>> std::tuple<guidance::LaneDescriptionMap,
std::vector<TurnRestriction>,
std::vector<ConditionalTurnRestriction>>
Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment, Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
const unsigned number_of_threads) const unsigned number_of_threads)
{ {
@@ -333,7 +337,6 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
extraction_containers.PrepareData(scripting_environment, extraction_containers.PrepareData(scripting_environment,
config.GetPath(".osrm").string(), config.GetPath(".osrm").string(),
config.GetPath(".osrm.restrictions").string(),
config.GetPath(".osrm.names").string()); config.GetPath(".osrm.names").string());
auto profile_properties = scripting_environment.GetProfileProperties(); auto profile_properties = scripting_environment.GetProfileProperties();
@@ -344,7 +347,8 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
util::Log() << "extraction finished after " << TIMER_SEC(extracting) << "s"; util::Log() << "extraction finished after " << TIMER_SEC(extracting) << "s";
return std::make_tuple(std::move(turn_lane_map), return std::make_tuple(std::move(turn_lane_map),
std::move(extraction_containers.unconditional_turn_restrictions)); std::move(extraction_containers.unconditional_turn_restrictions),
std::move(extraction_containers.conditional_turn_restrictions));
} }
void Extractor::FindComponents(unsigned max_edge_id, void Extractor::FindComponents(unsigned max_edge_id,
@@ -440,41 +444,45 @@ Extractor::LoadNodeBasedGraph(std::unordered_set<NodeID> &barriers,
/** /**
\brief Building an edge-expanded graph from node-based input and turn restrictions \brief Building an edge-expanded graph from node-based input and turn restrictions
*/ */
std::pair<std::size_t, EdgeID> std::pair<std::size_t, EdgeID> Extractor::BuildEdgeExpandedGraph(
Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment, ScriptingEnvironment &scripting_environment,
std::vector<util::Coordinate> &coordinates, std::vector<util::Coordinate> &coordinates,
extractor::PackedOSMIDs &osm_node_ids, extractor::PackedOSMIDs &osm_node_ids,
EdgeBasedNodeDataContainer &edge_based_nodes_container, EdgeBasedNodeDataContainer &edge_based_nodes_container,
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments, std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
std::vector<bool> &node_is_startpoint, std::vector<bool> &node_is_startpoint,
std::vector<EdgeWeight> &edge_based_node_weights, std::vector<EdgeWeight> &edge_based_node_weights,
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list, util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
const std::string &intersection_class_output_file, const std::string &intersection_class_output_file,
std::vector<TurnRestriction> &turn_restrictions, std::vector<TurnRestriction> &turn_restrictions,
guidance::LaneDescriptionMap &turn_lane_map) std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
guidance::LaneDescriptionMap &turn_lane_map)
{ {
std::unordered_set<NodeID> barrier_nodes; std::unordered_set<NodeID> barrier_nodes;
std::unordered_set<NodeID> traffic_lights; std::unordered_set<NodeID> traffic_signals;
auto node_based_graph = auto node_based_graph =
LoadNodeBasedGraph(barrier_nodes, traffic_lights, coordinates, osm_node_ids); LoadNodeBasedGraph(barrier_nodes, traffic_signals, coordinates, osm_node_ids);
CompressedEdgeContainer compressed_edge_container; CompressedEdgeContainer compressed_edge_container;
GraphCompressor graph_compressor; GraphCompressor graph_compressor;
graph_compressor.Compress(barrier_nodes, graph_compressor.Compress(barrier_nodes,
traffic_lights, traffic_signals,
scripting_environment,
turn_restrictions, turn_restrictions,
conditional_turn_restrictions,
*node_based_graph, *node_based_graph,
compressed_edge_container); compressed_edge_container);
turn_restrictions = removeInvalidRestrictions(std::move(turn_restrictions), *node_based_graph); conditional_turn_restrictions =
removeInvalidRestrictions(std::move(conditional_turn_restrictions), *node_based_graph);
util::NameTable name_table(config.GetPath(".osrm.names").string()); util::NameTable name_table(config.GetPath(".osrm.names").string());
EdgeBasedGraphFactory edge_based_graph_factory(node_based_graph, EdgeBasedGraphFactory edge_based_graph_factory(node_based_graph,
compressed_edge_container, compressed_edge_container,
barrier_nodes, barrier_nodes,
traffic_lights, traffic_signals,
coordinates, coordinates,
osm_node_ids, osm_node_ids,
scripting_environment.GetProfileProperties(), scripting_environment.GetProfileProperties(),
@@ -483,8 +491,20 @@ Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
const auto create_edge_based_edges = [&]() { const auto create_edge_based_edges = [&]() {
// scoped to relase intermediate datastructures right after the call // scoped to relase intermediate datastructures right after the call
RestrictionMap via_node_restriction_map(turn_restrictions); std::vector<TurnRestriction> node_restrictions;
WayRestrictionMap via_way_restriction_map(turn_restrictions); for (auto const &t : turn_restrictions)
if (t.Type() == RestrictionType::NODE_RESTRICTION)
node_restrictions.push_back(t);
std::vector<ConditionalTurnRestriction> conditional_node_restrictions;
for (auto const &t : conditional_turn_restrictions)
if (t.Type() == RestrictionType::NODE_RESTRICTION)
conditional_node_restrictions.push_back(t);
RestrictionMap via_node_restriction_map(node_restrictions, IndexNodeByFromAndVia());
WayRestrictionMap via_way_restriction_map(conditional_turn_restrictions);
ConditionalRestrictionMap conditional_node_restriction_map(conditional_node_restrictions,
IndexNodeByFromAndVia());
turn_restrictions.clear(); turn_restrictions.clear();
turn_restrictions.shrink_to_fit(); turn_restrictions.shrink_to_fit();
@@ -495,13 +515,14 @@ Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
config.GetPath(".osrm.turn_duration_penalties").string(), config.GetPath(".osrm.turn_duration_penalties").string(),
config.GetPath(".osrm.turn_penalties_index").string(), config.GetPath(".osrm.turn_penalties_index").string(),
config.GetPath(".osrm.cnbg_to_ebg").string(), config.GetPath(".osrm.cnbg_to_ebg").string(),
config.GetPath(".osrm.restrictions").string(),
via_node_restriction_map, via_node_restriction_map,
conditional_node_restriction_map,
via_way_restriction_map); via_way_restriction_map);
return edge_based_graph_factory.GetNumberOfEdgeBasedNodes(); return edge_based_graph_factory.GetNumberOfEdgeBasedNodes();
}; };
const auto number_of_edge_based_nodes = create_edge_based_edges(); const auto number_of_edge_based_nodes = create_edge_based_edges();
compressed_edge_container.PrintStatistics(); compressed_edge_container.PrintStatistics();
// The osrm-partition tool requires the compressed node based graph with an embedding. // The osrm-partition tool requires the compressed node based graph with an embedding.
+1 -1
View File
@@ -69,7 +69,7 @@ void ExtractorCallbacks::ProcessNode(const osmium::Node &input_node,
} }
if (result_node.traffic_lights) if (result_node.traffic_lights)
{ {
external_memory.traffic_lights.push_back(id); external_memory.traffic_signals.push_back(id);
} }
} }
+51 -11
View File
@@ -1,6 +1,8 @@
#include "extractor/graph_compressor.hpp" #include "extractor/graph_compressor.hpp"
#include "extractor/compressed_edge_container.hpp" #include "extractor/compressed_edge_container.hpp"
#include "extractor/extraction_turn.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/restriction.hpp" #include "extractor/restriction.hpp"
#include "extractor/restriction_compressor.hpp" #include "extractor/restriction_compressor.hpp"
@@ -18,16 +20,19 @@ namespace osrm
namespace extractor namespace extractor
{ {
void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes, void GraphCompressor::Compress(
const std::unordered_set<NodeID> &traffic_lights, const std::unordered_set<NodeID> &barrier_nodes,
std::vector<TurnRestriction> &turn_restrictions, const std::unordered_set<NodeID> &traffic_signals,
util::NodeBasedDynamicGraph &graph, ScriptingEnvironment &scripting_environment,
CompressedEdgeContainer &geometry_compressor) std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
util::NodeBasedDynamicGraph &graph,
CompressedEdgeContainer &geometry_compressor)
{ {
const unsigned original_number_of_nodes = graph.GetNumberOfNodes(); const unsigned original_number_of_nodes = graph.GetNumberOfNodes();
const unsigned original_number_of_edges = graph.GetNumberOfEdges(); const unsigned original_number_of_edges = graph.GetNumberOfEdges();
RestrictionCompressor restriction_compressor(turn_restrictions); RestrictionCompressor restriction_compressor(turn_restrictions, conditional_turn_restrictions);
// we do not compress turn restrictions on degree two nodes. These nodes are usually used to // we do not compress turn restrictions on degree two nodes. These nodes are usually used to
// indicated `directed` barriers // indicated `directed` barriers
@@ -48,8 +53,13 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
} }
}; };
std::for_each(turn_restrictions.begin(), turn_restrictions.end(), remember_via_nodes); std::for_each(turn_restrictions.begin(), turn_restrictions.end(), remember_via_nodes);
std::for_each(conditional_turn_restrictions.begin(),
conditional_turn_restrictions.end(),
remember_via_nodes);
{ {
const auto weight_multiplier =
scripting_environment.GetProfileProperties().GetWeightMultiplier();
util::UnbufferedLog log; util::UnbufferedLog log;
util::Percent progress(log, original_number_of_nodes); util::Percent progress(log, original_number_of_nodes);
@@ -184,13 +194,31 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
graph.GetEdgeData(reverse_e2).lane_description_id = selectLaneID( graph.GetEdgeData(reverse_e2).lane_description_id = selectLaneID(
rev_edge_data2.lane_description_id, rev_edge_data1.lane_description_id); rev_edge_data2.lane_description_id, rev_edge_data1.lane_description_id);
/*
// Do not compress edge if it crosses a traffic signal. // Do not compress edge if it crosses a traffic signal.
// This can't be done in CanCombineWith, becase we only store the // This can't be done in CanCombineWith, becase we only store the
// traffic signals in the `traffic_lights` list, which EdgeData // traffic signals in the `traffic signal` list, which EdgeData
// doesn't have access to. // doesn't have access to.
const bool has_node_penalty = traffic_lights.find(node_v) != traffic_lights.end(); */
const bool has_node_penalty = traffic_signals.find(node_v) != traffic_signals.end();
boost::optional<EdgeDuration> node_duration_penalty = boost::none;
boost::optional<EdgeWeight> node_weight_penalty = boost::none;
if (has_node_penalty) if (has_node_penalty)
continue; {
// generate an artifical turn for the turn penalty generation
ExtractionTurn extraction_turn(true);
extraction_turn.source_restricted = fwd_edge_data1.restricted;
extraction_turn.target_restricted = fwd_edge_data2.restricted;
// we cannot handle this as node penalty, if it depends on turn direction
if (extraction_turn.source_restricted != extraction_turn.target_restricted)
continue;
scripting_environment.ProcessTurn(extraction_turn);
node_duration_penalty = extraction_turn.duration * 10;
node_weight_penalty = extraction_turn.weight * weight_multiplier;
}
// Get weights before graph is modified // Get weights before graph is modified
const auto forward_weight1 = fwd_edge_data1.weight; const auto forward_weight1 = fwd_edge_data1.weight;
@@ -217,6 +245,14 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
graph.GetEdgeData(forward_e1).duration += forward_duration2; graph.GetEdgeData(forward_e1).duration += forward_duration2;
graph.GetEdgeData(reverse_e1).duration += reverse_duration2; graph.GetEdgeData(reverse_e1).duration += reverse_duration2;
if (node_weight_penalty && node_duration_penalty)
{
graph.GetEdgeData(forward_e1).weight += *node_weight_penalty;
graph.GetEdgeData(reverse_e1).weight += *node_weight_penalty;
graph.GetEdgeData(forward_e1).duration += *node_duration_penalty;
graph.GetEdgeData(reverse_e1).duration += *node_duration_penalty;
}
// extend e1's to targets of e2's // extend e1's to targets of e2's
graph.SetTarget(forward_e1, node_w); graph.SetTarget(forward_e1, node_w);
graph.SetTarget(reverse_e1, node_u); graph.SetTarget(reverse_e1, node_u);
@@ -236,7 +272,9 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
forward_weight1, forward_weight1,
forward_weight2, forward_weight2,
forward_duration1, forward_duration1,
forward_duration2); forward_duration2,
node_weight_penalty,
node_duration_penalty);
geometry_compressor.CompressEdge(reverse_e1, geometry_compressor.CompressEdge(reverse_e1,
reverse_e2, reverse_e2,
node_v, node_v,
@@ -244,7 +282,9 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
reverse_weight1, reverse_weight1,
reverse_weight2, reverse_weight2,
reverse_duration1, reverse_duration1,
reverse_duration2); reverse_duration2,
node_weight_penalty,
node_duration_penalty);
} }
} }
} }
@@ -122,15 +122,6 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
// coordinate set to add a small level of fault tolerance // coordinate set to add a small level of fault tolerance
const constexpr double skipping_inaccuracies_distance = 2; const constexpr double skipping_inaccuracies_distance = 2;
// fallback, mostly necessary for dead ends
if (intersection_node == to_node)
{
const auto result = ExtractCoordinateAtLength(skipping_inaccuracies_distance, coordinates);
// TODO: possibly re-enable with https://github.com/Project-OSRM/osrm-backend/issues/3470
// BOOST_ASSERT(not_same_as_start(result));
return result;
}
const auto &turn_edge_data = node_based_graph.GetEdgeData(turn_edge); const auto &turn_edge_data = node_based_graph.GetEdgeData(turn_edge);
// roundabouts, check early to avoid other costly checks // roundabouts, check early to avoid other costly checks
@@ -377,14 +368,14 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
* destination lanes and the ones that performa a larger turn. * destination lanes and the ones that performa a larger turn.
*/ */
coordinates = TrimCoordinatesToLength( coordinates = TrimCoordinatesToLength(
std::move(coordinates), 2 * skipping_inaccuracies_distance, segment_distances); std::move(coordinates), 3 * skipping_inaccuracies_distance, segment_distances);
BOOST_ASSERT(coordinates.size() >= 2); BOOST_ASSERT(coordinates.size() >= 2);
segment_distances.resize(coordinates.size()); segment_distances.resize(coordinates.size());
segment_distances.back() = util::coordinate_calculation::haversineDistance( segment_distances.back() = util::coordinate_calculation::haversineDistance(
*(coordinates.end() - 2), coordinates.back()); *(coordinates.end() - 2), coordinates.back());
const auto vector_head = coordinates.back(); const auto vector_head = coordinates.back();
coordinates = TrimCoordinatesToLength( coordinates = TrimCoordinatesToLength(
std::move(coordinates), skipping_inaccuracies_distance, segment_distances); std::move(coordinates), 2 * skipping_inaccuracies_distance, segment_distances);
BOOST_ASSERT(coordinates.size() >= 2); BOOST_ASSERT(coordinates.size() >= 2);
const auto result = const auto result =
GetCorrectedCoordinate(turn_coordinate, coordinates.back(), vector_head); GetCorrectedCoordinate(turn_coordinate, coordinates.back(), vector_head);
@@ -236,8 +236,25 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
{ {
const auto node_at_intersection = node_based_graph.GetTarget(entering_via_edge); const auto node_at_intersection = node_based_graph.GetTarget(entering_via_edge);
// check if there is a single valid turn entering the current intersection // request all turn restrictions
const auto only_valid_turn = GetOnlyAllowedTurnIfExistent(previous_node, node_at_intersection); auto const restrictions = restriction_map.Restrictions(previous_node, node_at_intersection);
// check turn restrictions to find a node that is the only allowed target when coming from a
// node to an intersection
// d
// |
// a - b - c and `only_straight_on ab | bc would return `c` for `a,b`
const auto find_only_valid_turn = [&]() -> boost::optional<NodeID> {
const auto itr = std::find_if(restrictions.first, restrictions.second, [](auto pair) {
return pair.second->is_only;
});
if (itr != restrictions.second)
return itr->second->AsNodeRestriction().to;
else
return boost::none;
};
const auto only_valid_turn = find_only_valid_turn();
// barriers change our behaviour regarding u-turns // barriers change our behaviour regarding u-turns
const bool is_barrier_node = barrier_nodes.find(node_at_intersection) != barrier_nodes.end(); const bool is_barrier_node = barrier_nodes.find(node_at_intersection) != barrier_nodes.end();
@@ -258,12 +275,14 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
const auto is_restricted = [&](const NodeID destination) { const auto is_restricted = [&](const NodeID destination) {
// check if we have a dedicated destination // check if we have a dedicated destination
if (only_valid_turn && *only_valid_turn != destination) if (only_valid_turn)
return true; return *only_valid_turn != destination;
// not explicitly forbidden // check if explicitly forbidden
return restriction_map.CheckIfTurnIsRestricted( return restrictions.second !=
previous_node, node_at_intersection, destination); std::find_if(restrictions.first, restrictions.second, [&](const auto &restriction) {
return restriction.second->AsNodeRestriction().to == destination;
});
}; };
const auto is_allowed_turn = [&](const IntersectionShapeData &road) { const auto is_allowed_turn = [&](const IntersectionShapeData &road) {
@@ -396,21 +415,6 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
return intersection_view; return intersection_view;
} }
boost::optional<NodeID>
IntersectionGenerator::GetOnlyAllowedTurnIfExistent(const NodeID coming_from_node,
const NodeID node_at_intersection) const
{
// If only restrictions refer to invalid ways somewhere far away, we rather ignore the
// restriction than to not route over the intersection at all.
const auto only_restriction_to_node =
restriction_map.CheckForEmanatingIsOnlyTurn(coming_from_node, node_at_intersection);
if (only_restriction_to_node != SPECIAL_NODEID)
return only_restriction_to_node;
// Ignore broken only restrictions.
return boost::none;
}
const CoordinateExtractor &IntersectionGenerator::GetCoordinateExtractor() const const CoordinateExtractor &IntersectionGenerator::GetCoordinateExtractor() const
{ {
return coordinate_extractor; return coordinate_extractor;
+51 -3
View File
@@ -263,8 +263,9 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
if (!allSameMode(source_edge_id, sliproad.eid, find_valid(target_intersection)->eid)) if (!allSameMode(source_edge_id, sliproad.eid, find_valid(target_intersection)->eid))
continue; continue;
// Constrain the Sliproad's target to sliproad, outgoing, incoming from main intersection // Constrain the sliproad's target intersection to 1 or 2 sliproads, outgoing road
if (target_intersection.size() != 3) // and incoming one from the main intersection
if (target_intersection.size() < 3 || target_intersection.size() > 4)
{ {
continue; continue;
} }
@@ -279,6 +280,51 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
continue; continue;
} }
if (target_intersection.size() == 4)
{
// Handle target intersections at `d` with 4 roads
//
// | `main_road_intersection` is intersection at `c`
// v
// a ... b .... c .... e <- fo
// ` . '
// ` . '
// ` . '
// d < `target_intersection` is intersection at `d`
// |
// Conditions for road `bd` to be a sliproad:
// - target_intersection at `d` has 4 roads
// - main_road_intersection at `c` has at least 3 roads
// - target nodes of `db` and `cd` roads is the same node `d`
// - target nodes of `ce` and `de` roads is the same node `e`
// - angle `bde` is sharp
// Check `c` has at least 3 roads at `c` and roads `bd` and `cd` share the node `d`
if (main_road_intersection->intersection.size() < 3 ||
sliproad_edge_target != node_based_graph.GetTarget(crossing_road.eid))
{
continue;
}
// Find a road at `d` that shares the same node `e` with `ce` and ∠ `bde` is sharp
auto next_to_crossing_idx =
is_left_sliproad_turn ? main_road_intersection->intersection.size() - 2 : 2;
auto next_to_crossing_road = main_road_intersection->intersection[next_to_crossing_idx];
auto next_to_crossing_node = node_based_graph.GetTarget(next_to_crossing_road.eid);
auto found_common_node = std::find_if(
begin(target_intersection), end(target_intersection), [&](const auto &road) {
if (next_to_crossing_node == node_based_graph.GetTarget(road.eid))
{
auto direction = getTurnDirection(road.angle);
return direction == DirectionModifier::SharpRight ||
direction == DirectionModifier::SharpLeft;
}
return false;
});
if (found_common_node == target_intersection.end())
continue;
}
// If the sliproad candidate is a through street, we cannot handle it as a sliproad. // If the sliproad candidate is a through street, we cannot handle it as a sliproad.
if (isThroughStreet(sliproad_edge, target_intersection)) if (isThroughStreet(sliproad_edge, target_intersection))
{ {
@@ -386,7 +432,9 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
continue; continue;
} }
if (deviation_from_straight > perpendicular_angle) // Check sliproads with skew main intersections
if (deviation_from_straight > perpendicular_angle &&
!node_based_graph.GetEdgeData(sliproad.eid).road_classification.IsLinkClass())
{ {
continue; continue;
} }
+8 -6
View File
@@ -391,6 +391,7 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection
{ {
assignTrivialTurns(via_edge, intersection, 1, intersection.size()); assignTrivialTurns(via_edge, intersection, 1, intersection.size());
} }
return intersection; return intersection;
} }
@@ -744,7 +745,7 @@ void TurnHandler::handleDistinctConflict(const EdgeID via_edge,
right.instruction = {right_type, DirectionModifier::Right}; right.instruction = {right_type, DirectionModifier::Right};
return; return;
} }
// Two Right Turns // Two Left Turns
if (angularDeviation(left.angle, 270) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION) if (angularDeviation(left.angle, 270) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
{ {
// Keep left perfect, shift right // Keep left perfect, shift right
@@ -773,17 +774,18 @@ void TurnHandler::handleDistinctConflict(const EdgeID via_edge,
return; return;
} }
if (getTurnDirection(left.angle) == DirectionModifier::Right) // turn to the right
if (getTurnDirection(left.angle) <= 180)
{ {
if (angularDeviation(left.angle, 85) >= angularDeviation(right.angle, 85)) if (angularDeviation(left.angle, 85) >= angularDeviation(right.angle, 85))
{ {
left.instruction = {left_type, DirectionModifier::Right}; left.instruction = {left_type, DirectionModifier::SlightRight};
right.instruction = {right_type, DirectionModifier::SharpRight}; right.instruction = {right_type, DirectionModifier::Right};
} }
else else
{ {
left.instruction = {left_type, DirectionModifier::SlightRight}; left.instruction = {left_type, DirectionModifier::Right};
right.instruction = {right_type, DirectionModifier::Right}; right.instruction = {right_type, DirectionModifier::SharpRight};
} }
} }
else else
+6 -1
View File
@@ -10,7 +10,9 @@ namespace osrm
namespace extractor namespace extractor
{ {
RestrictionCompressor::RestrictionCompressor(std::vector<TurnRestriction> &restrictions) RestrictionCompressor::RestrictionCompressor(
std::vector<TurnRestriction> &restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions)
{ {
// add a node restriction ptr to the starts/ends maps, needs to be a reference! // add a node restriction ptr to the starts/ends maps, needs to be a reference!
auto index = [&](auto &element) { auto index = [&](auto &element) {
@@ -35,6 +37,9 @@ RestrictionCompressor::RestrictionCompressor(std::vector<TurnRestriction> &restr
// add all restrictions as their respective startend pointers // add all restrictions as their respective startend pointers
std::for_each(restrictions.begin(), restrictions.end(), index_starts_and_ends); std::for_each(restrictions.begin(), restrictions.end(), index_starts_and_ends);
std::for_each(conditional_turn_restrictions.begin(),
conditional_turn_restrictions.end(),
index_starts_and_ends);
} }
void RestrictionCompressor::Compress(const NodeID from, const NodeID via, const NodeID to) void RestrictionCompressor::Compress(const NodeID from, const NodeID via, const NodeID to)
+2 -2
View File
@@ -10,8 +10,8 @@ namespace osrm
namespace extractor namespace extractor
{ {
std::vector<TurnRestriction> std::vector<ConditionalTurnRestriction>
removeInvalidRestrictions(std::vector<TurnRestriction> restrictions, removeInvalidRestrictions(std::vector<ConditionalTurnRestriction> restrictions,
const util::NodeBasedDynamicGraph &node_based_graph) const util::NodeBasedDynamicGraph &node_based_graph)
{ {
// definition of what we presume to be a valid via-node restriction // definition of what we presume to be a valid via-node restriction
-138
View File
@@ -1,138 +0,0 @@
#include "extractor/restriction_map.hpp"
#include <boost/assert.hpp>
namespace osrm
{
namespace extractor
{
RestrictionMap::RestrictionMap(const std::vector<TurnRestriction> &restriction_list) : m_count(0)
{
// decompose restriction consisting of a start, via and end node into a
// a pair of starting edge and a list of all end nodes
for (auto &restriction : restriction_list)
{
// only handle node restrictions here
if (restriction.Type() == RestrictionType::WAY_RESTRICTION)
continue;
const auto &node_restriction = restriction.AsNodeRestriction();
BOOST_ASSERT(node_restriction.Valid());
// This downcasting is OK because when this is called, the node IDs have been
// renumbered into internal values, which should be well under 2^32
// This will be a problem if we have more than 2^32 actual restrictions
BOOST_ASSERT(node_restriction.from < std::numeric_limits<NodeID>::max());
BOOST_ASSERT(node_restriction.via < std::numeric_limits<NodeID>::max());
m_restriction_start_nodes.insert(node_restriction.from);
m_no_turn_via_node_set.insert(node_restriction.via);
// This explicit downcasting is also OK for the same reason.
RestrictionSource restriction_source = {static_cast<NodeID>(node_restriction.from),
static_cast<NodeID>(node_restriction.via)};
std::size_t index;
auto restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter == m_restriction_map.end())
{
index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index + 1);
m_restriction_map.emplace(restriction_source, index);
}
else
{
index = restriction_iter->second;
// Map already contains an is_only_*-restriction
if (m_restriction_bucket_list.at(index).begin()->is_only)
{
continue;
}
else if (restriction.is_only)
{
// We are going to insert an is_only_*-restriction. There can be only one.
m_count -= m_restriction_bucket_list.at(index).size();
m_restriction_bucket_list.at(index).clear();
}
}
++m_count;
m_restriction_bucket_list.at(index).emplace_back(node_restriction.to, restriction.is_only);
}
}
bool RestrictionMap::IsViaNode(const NodeID node) const
{
return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
}
// Check if edge (u, v) is the start of any turn restriction.
// If so returns id of first target node.
NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID node_u, const NodeID node_v) const
{
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
if (!IsSourceNode(node_u))
{
return SPECIAL_NODEID;
}
const auto restriction_iter = m_restriction_map.find({node_u, node_v});
if (restriction_iter != m_restriction_map.end())
{
const unsigned index = restriction_iter->second;
const auto &bucket = m_restriction_bucket_list.at(index);
for (const RestrictionTarget &restriction_target : bucket)
{
if (restriction_target.is_only)
{
return restriction_target.target_node;
}
}
}
return SPECIAL_NODEID;
}
// Checks if turn <u,v,w> is actually a turn restriction.
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u,
const NodeID node_v,
const NodeID node_w) const
{
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
BOOST_ASSERT(node_w != SPECIAL_NODEID);
if (!IsSourceNode(node_u))
{
return false;
}
const auto restriction_iter = m_restriction_map.find({node_u, node_v});
if (restriction_iter == m_restriction_map.end())
{
return false;
}
const unsigned index = restriction_iter->second;
const auto &bucket = m_restriction_bucket_list.at(index);
for (const RestrictionTarget &restriction_target : bucket)
{
if (node_w == restriction_target.target_node && // target found
!restriction_target.is_only) // and not an only_-restr.
{
return true;
}
// We could be tempted to check for `only` restrictions here as well. However, that check is
// actually perfomed in intersection generation where we can also verify if the only
// restriction is valid at all.
}
return false;
}
// check of node is the start of any restriction
bool RestrictionMap::IsSourceNode(const NodeID node) const
{
return m_restriction_start_nodes.find(node) != m_restriction_start_nodes.end();
}
}
}
+6 -2
View File
@@ -396,8 +396,12 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"target_restricted", "target_restricted",
&ExtractionTurn::target_restricted); &ExtractionTurn::target_restricted);
// Keep in mind .location is undefined since we're not using libosmium's location cache // Keep in mind .location is available only if .pbf is preprocessed to set the location with the
context.state.new_usertype<osmium::NodeRef>("NodeRef", "id", &osmium::NodeRef::ref); // ref using osmium command "osmium add-locations-to-ways"
context.state.new_usertype<osmium::NodeRef>(
"NodeRef", "id", &osmium::NodeRef::ref, "location", [](const osmium::NodeRef &nref) {
return nref.location();
});
context.state.new_usertype<InternalExtractorEdge>("EdgeSource", context.state.new_usertype<InternalExtractorEdge>("EdgeSource",
"source_coordinate", "source_coordinate",
+102 -34
View File
@@ -1,6 +1,7 @@
#include "extractor/way_restriction_map.hpp" #include "extractor/way_restriction_map.hpp"
#include "util/for_each_pair.hpp" #include "util/for_each_pair.hpp"
#include <functional>
#include <iterator> #include <iterator>
#include <tuple> #include <tuple>
#include <utility> #include <utility>
@@ -28,12 +29,46 @@ struct FindViaWay
} }
}; };
} // namespace template <typename restriction_type> auto asDuplicatedNode(const restriction_type &restriction)
WayRestrictionMap::WayRestrictionMap(const std::vector<TurnRestriction> &turn_restrictions)
{ {
// get all way restrictions auto &way = restriction.AsWayRestriction();
const auto extract_restrictions = [this](const auto &turn_restriction) { // group restrictions by the via-way. On same via-ways group by from
return std::tie(way.in_restriction.via, way.out_restriction.via, way.in_restriction.from);
};
template <typename restriction_type> struct CompareByDuplicatedNode
{
bool operator()(const ConditionalTurnRestriction &lhs, const ConditionalTurnRestriction &rhs)
{
if (asDuplicatedNode(lhs) < asDuplicatedNode(rhs))
{
return true;
}
else if (asDuplicatedNode(rhs) < asDuplicatedNode(lhs))
{
return false;
}
else
{
const auto lhs_to = lhs.AsWayRestriction().out_restriction.to;
const auto rhs_to = rhs.AsWayRestriction().out_restriction.to;
const bool has_conditions_lhs = !lhs.condition.empty();
const bool has_conditions_rhs = !rhs.condition.empty();
return std::tie(lhs_to, lhs.is_only, has_conditions_lhs) <
std::tie(rhs_to, rhs.is_only, has_conditions_rhs);
}
}
};
template <typename restriction_type>
std::vector<restriction_type>
extractRestrictions(const std::vector<restriction_type> &turn_restrictions)
{
std::vector<restriction_type> result;
for (const auto &turn_restriction : turn_restrictions)
{
if (turn_restriction.Type() == RestrictionType::WAY_RESTRICTION) if (turn_restriction.Type() == RestrictionType::WAY_RESTRICTION)
{ {
const auto &way = turn_restriction.AsWayRestriction(); const auto &way = turn_restriction.AsWayRestriction();
@@ -41,32 +76,32 @@ WayRestrictionMap::WayRestrictionMap(const std::vector<TurnRestriction> &turn_re
// so far we can only handle restrictions that are not interrupted // so far we can only handle restrictions that are not interrupted
if (way.in_restriction.via == way.out_restriction.from && if (way.in_restriction.via == way.out_restriction.from &&
way.in_restriction.to == way.out_restriction.via) way.in_restriction.to == way.out_restriction.via)
restriction_data.push_back(turn_restriction); result.push_back(turn_restriction);
} }
}; }
std::for_each(turn_restrictions.begin(), turn_restrictions.end(), extract_restrictions); std::sort(result.begin(), result.end(), CompareByDuplicatedNode<restriction_type>());
auto new_end = std::unique(result.begin(), result.end());
result.erase(new_end, result.end());
return result;
}
const auto as_duplicated_node = [](auto const &restriction) { template <typename restriction_type> struct ByInFromAndVia
auto &way = restriction.AsWayRestriction(); {
// group restrictions by the via-way. On same via-ways group by from std::pair<NodeID, NodeID> operator()(const restriction_type &restriction)
return std::tie(way.in_restriction.via, way.out_restriction.via, way.in_restriction.from);
};
const auto by_duplicated_node = [&](auto const &lhs, auto const &rhs) {
return as_duplicated_node(lhs) < as_duplicated_node(rhs);
};
std::sort(restriction_data.begin(), restriction_data.end(), by_duplicated_node);
// map all way restrictions into access containers
for (RestrictionID index = 0; index < restriction_data.size(); ++index)
{ {
const auto &restriction = restriction_data[index];
const auto &way = restriction.AsWayRestriction(); const auto &way = restriction.AsWayRestriction();
restriction_starts.insert( return std::make_pair(way.in_restriction.from, way.in_restriction.via);
std::make_pair(std::make_pair(way.in_restriction.from, way.in_restriction.via), index)); }
}; };
} // namespace
// get all way restrictions
WayRestrictionMap::WayRestrictionMap(
const std::vector<ConditionalTurnRestriction> &turn_restrictions_)
: restriction_data(extractRestrictions(turn_restrictions_)),
restriction_starts(restriction_data, ByInFromAndVia<ConditionalTurnRestriction>())
{
std::size_t offset = 1; std::size_t offset = 1;
// the first group starts at 0 // the first group starts at 0
if (!restriction_data.empty()) if (!restriction_data.empty())
@@ -74,8 +109,10 @@ WayRestrictionMap::WayRestrictionMap(const std::vector<TurnRestriction> &turn_re
auto const add_offset_on_new_groups = [&](auto const &lhs, auto const &rhs) { auto const add_offset_on_new_groups = [&](auto const &lhs, auto const &rhs) {
BOOST_ASSERT(rhs == restriction_data[offset]); BOOST_ASSERT(rhs == restriction_data[offset]);
BOOST_ASSERT(lhs.Type() == RestrictionType::WAY_RESTRICTION);
BOOST_ASSERT(rhs.Type() == RestrictionType::WAY_RESTRICTION);
// add a new lower bound for rhs // add a new lower bound for rhs
if (as_duplicated_node(lhs) != as_duplicated_node(rhs)) if (asDuplicatedNode(lhs) != asDuplicatedNode(rhs))
duplicated_node_groups.push_back(offset); duplicated_node_groups.push_back(offset);
++offset; ++offset;
}; };
@@ -115,7 +152,7 @@ DuplicatedNodeID WayRestrictionMap::AsDuplicatedNodeID(const RestrictionID restr
return distance_to_upper_bound - 1; return distance_to_upper_bound - 1;
} }
util::range<DuplicatedNodeID> WayRestrictionMap::DuplicatedNodeIDs(const NodeID from, std::vector<DuplicatedNodeID> WayRestrictionMap::DuplicatedNodeIDs(const NodeID from,
const NodeID to) const const NodeID to) const
{ {
const auto duplicated_node_range_itr = std::equal_range( const auto duplicated_node_range_itr = std::equal_range(
@@ -125,9 +162,13 @@ util::range<DuplicatedNodeID> WayRestrictionMap::DuplicatedNodeIDs(const NodeID
return std::distance(restriction_data.begin(), itr); return std::distance(restriction_data.begin(), itr);
}; };
return util::irange<DuplicatedNodeID>( auto first = AsDuplicatedNodeID(as_restriction_id(duplicated_node_range_itr.first));
AsDuplicatedNodeID(as_restriction_id(duplicated_node_range_itr.first)), auto end = AsDuplicatedNodeID(as_restriction_id(duplicated_node_range_itr.second));
AsDuplicatedNodeID(as_restriction_id(duplicated_node_range_itr.second)));
std::vector<DuplicatedNodeID> result(end - first);
std::iota(result.begin(), result.end(), first);
return result;
} }
bool WayRestrictionMap::IsRestricted(DuplicatedNodeID duplicated_node, const NodeID to) const bool WayRestrictionMap::IsRestricted(DuplicatedNodeID duplicated_node, const NodeID to) const
@@ -138,6 +179,7 @@ bool WayRestrictionMap::IsRestricted(DuplicatedNodeID duplicated_node, const Nod
restriction_index != duplicated_node_groups[duplicated_node + 1]; restriction_index != duplicated_node_groups[duplicated_node + 1];
++restriction_index) ++restriction_index)
{ {
BOOST_ASSERT(restriction_index < restriction_data.size());
const auto &restriction = restriction_data[restriction_index]; const auto &restriction = restriction_data[restriction_index];
const auto &way = restriction.AsWayRestriction(); const auto &way = restriction.AsWayRestriction();
@@ -149,6 +191,32 @@ bool WayRestrictionMap::IsRestricted(DuplicatedNodeID duplicated_node, const Nod
return false; return false;
} }
ConditionalTurnRestriction const &
WayRestrictionMap::GetRestriction(DuplicatedNodeID duplicated_node, const NodeID to) const
{
// loop over all restrictions associated with the node. Mark as restricted based on
// is_only/restricted targets
for (RestrictionID restriction_index = duplicated_node_groups[duplicated_node];
restriction_index != duplicated_node_groups[duplicated_node + 1];
++restriction_index)
{
BOOST_ASSERT(restriction_index < restriction_data.size());
const auto &restriction = restriction_data[restriction_index];
const auto &way = restriction.AsWayRestriction();
if (restriction.is_only && (way.out_restriction.to != to))
{
return restriction;
}
else if (!restriction.is_only && (to == way.out_restriction.to))
{
return restriction;
}
}
throw("Asking for the restriction of an unrestricted turn. Check with `IsRestricted` before "
"calling GetRestriction");
}
std::vector<WayRestrictionMap::ViaWay> WayRestrictionMap::DuplicatedNodeRepresentatives() const std::vector<WayRestrictionMap::ViaWay> WayRestrictionMap::DuplicatedNodeRepresentatives() const
{ {
std::vector<ViaWay> result; std::vector<ViaWay> result;
@@ -169,19 +237,19 @@ NodeID WayRestrictionMap::RemapIfRestricted(const NodeID edge_based_node,
const NodeID node_based_to, const NodeID node_based_to,
const NodeID number_of_edge_based_nodes) const const NodeID number_of_edge_based_nodes) const
{ {
auto range = restriction_starts.equal_range(std::make_pair(node_based_from, node_based_via)); auto range = restriction_starts.Restrictions(node_based_from, node_based_via);
// returns true if the ID saved in an iterator belongs to a turn restriction that references // returns true if the ID saved in an iterator belongs to a turn restriction that references
// node_based_to as destination of the `in_restriction` // node_based_to as destination of the `in_restriction`
const auto restriction_targets_to = [node_based_to, this](const auto &pair) { const auto restriction_targets_to = [node_based_to, this](const auto &pair) {
return restriction_data[pair.second].AsWayRestriction().in_restriction.to == node_based_to; return pair.second->AsWayRestriction().in_restriction.to == node_based_to;
}; };
const auto itr = std::find_if(range.first, range.second, restriction_targets_to); const auto itr = std::find_if(range.first, range.second, restriction_targets_to);
// in case we found a matching restriction, we can remap the edge_based_node // in case we found a matching restriction, we can remap the edge_based_node
if (itr != range.second) if (itr != range.second)
return number_of_edge_based_nodes - NumberOfDuplicatedNodes() + return number_of_edge_based_nodes - NumberOfDuplicatedNodes() +
AsDuplicatedNodeID(itr->second); AsDuplicatedNodeID(itr->second - &restriction_data[0]);
else else
return edge_based_node; return edge_based_node;
} }
+13
View File
@@ -72,6 +72,12 @@ NAN_MODULE_INIT(Engine::Init)
* @param {Boolean} [options.shared_memory] Connects to the persistent shared memory datastore. * @param {Boolean} [options.shared_memory] Connects to the persistent shared memory datastore.
* This requires you to run `osrm-datastore` prior to creating an `OSRM` object. * This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
* @param {String} [options.path] The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true. * @param {String} [options.path] The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true.
* @param {Number} [options.max_locations_trip] Max. locations supported in trip query (default: unlimited).
* @param {Number} [options.max_locations_viaroute] Max. locations supported in viaroute query (default: unlimited).
* @param {Number} [options.max_locations_distance_table] Max. locations supported in distance table query (default: unlimited).
* @param {Number} [options.max_locations_map_matching] Max. locations supported in map-matching query (default: unlimited).
* @param {Number} [options.max_results_nearest] Max. results supported in nearest query (default: unlimited).
* @param {Number} [options.max_alternatives] Max.number of alternatives supported in alternative routes query (default: 3).
* *
* @class OSRM * @class OSRM
* *
@@ -193,6 +199,7 @@ inline void async(const Nan::FunctionCallbackInfo<v8::Value> &info,
* @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`. * @param {String} [options.geometries=polyline] Returned route geometry format (influences overview and per step). Can also be `geojson`.
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). * @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`).
* @param {Boolean} [options.continue_straight] Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. * @param {Boolean} [options.continue_straight] Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile.
* @param {Array} [options.approaches] Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
* `null`/`true`/`false` * `null`/`true`/`false`
* @param {Function} callback * @param {Function} callback
* *
@@ -228,6 +235,7 @@ NAN_METHOD(Engine::route) //
* @param {Array} [options.hints] Hints for the coordinate snapping. Array of base64 encoded strings. * @param {Array} [options.hints] Hints for the coordinate snapping. Array of base64 encoded strings.
* @param {Number} [options.number=1] Number of nearest segments that should be returned. * @param {Number} [options.number=1] Number of nearest segments that should be returned.
* Must be an integer greater than or equal to `1`. * Must be an integer greater than or equal to `1`.
* @param {Array} [options.approaches] Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
* @param {Function} callback * @param {Function} callback
* *
* @returns {Object} containing `waypoints`. * @returns {Object} containing `waypoints`.
@@ -269,6 +277,7 @@ NAN_METHOD(Engine::nearest) //
* location with given index as source. Default is to use all. * location with given index as source. Default is to use all.
* @param {Array} [options.destinations] An array of `index` elements (`0 <= integer < * @param {Array} [options.destinations] An array of `index` elements (`0 <= integer <
* #coordinates`) to use location with given index as destination. Default is to use all. * #coordinates`) to use location with given index as destination. Default is to use all.
* @param {Array} [options.approaches] Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
* @param {Function} callback * @param {Function} callback
* *
* @returns {Object} containing `durations`, `sources`, and `destinations`. * @returns {Object} containing `durations`, `sources`, and `destinations`.
@@ -350,6 +359,9 @@ NAN_METHOD(Engine::tile)
* @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). * @param {String} [options.overview=simplified] Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`).
* @param {Array<Number>} [options.timestamps] Timestamp of the input location (integers, UNIX-like timestamp). * @param {Array<Number>} [options.timestamps] Timestamp of the input location (integers, UNIX-like timestamp).
* @param {Array} [options.radiuses] Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`. * @param {Array} [options.radiuses] Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`.
* @param {String} [options.gaps] Allows the input track splitting based on huge timestamp gaps between points. Either `split` or `ignore` (optional, default `split`).
* @param {Boolean} [options.tidy] Allows the input track modification to obtain better matching quality for noisy tracks (optional, default `false`).
*
* @param {Function} callback * @param {Function} callback
* *
* @returns {Object} containing `tracepoints` and `matchings`. * @returns {Object} containing `tracepoints` and `matchings`.
@@ -418,6 +430,7 @@ NAN_METHOD(Engine::match) //
* @param {Boolean} [options.roundtrip=true] Return route is a roundtrip. * @param {Boolean} [options.roundtrip=true] Return route is a roundtrip.
* @param {String} [options.source=any] Return route starts at `any` or `first` coordinate. * @param {String} [options.source=any] Return route starts at `any` or `first` coordinate.
* @param {String} [options.destination=any] Return route ends at `any` or `last` coordinate. * @param {String} [options.destination=any] Return route ends at `any` or `last` coordinate.
* @param {Array} [options.approaches] Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
* *
* @returns {Object} containing `waypoints` and `trips`. * @returns {Object} containing `waypoints` and `trips`.
* **`waypoints`**: an array of [`Waypoint`](#waypoint) objects representing all waypoints in input order. * **`waypoints`**: an array of [`Waypoint`](#waypoint) objects representing all waypoints in input order.
+13 -1
View File
@@ -36,7 +36,19 @@ SegmentLookupTable readSegmentValues(const std::vector<std::string> &paths)
CSVFilesParser<Segment, SpeedSource> parser( CSVFilesParser<Segment, SpeedSource> parser(
1, qi::ulong_long >> ',' >> qi::ulong_long, qi::uint_ >> -(',' >> qi::double_)); 1, qi::ulong_long >> ',' >> qi::ulong_long, qi::uint_ >> -(',' >> qi::double_));
return parser(paths); // Check consistency of keys in the result lookup table
auto result = parser(paths);
const auto found_inconsistency =
std::find_if(std::begin(result.lookup), std::end(result.lookup), [](const auto &entry) {
return entry.first.from == entry.first.to;
});
if (found_inconsistency != std::end(result.lookup))
{
util::Log(logWARNING) << "Empty segment in CSV with node " +
std::to_string(found_inconsistency->first.from);
}
return result;
} }
TurnLookupTable readTurnValues(const std::vector<std::string> &paths) TurnLookupTable readTurnValues(const std::vector<std::string> &paths)
+30 -79
View File
@@ -7,6 +7,7 @@
#include "extractor/node_based_edge.hpp" #include "extractor/node_based_edge.hpp"
#include "extractor/packed_osm_ids.hpp" #include "extractor/packed_osm_ids.hpp"
#include "extractor/restriction.hpp" #include "extractor/restriction.hpp"
#include "extractor/serialization.hpp"
#include "storage/io.hpp" #include "storage/io.hpp"
@@ -220,6 +221,12 @@ updateSegmentData(const UpdaterConfig &config,
{ {
auto u = osm_node_ids[nodes_range[segment_offset]]; auto u = osm_node_ids[nodes_range[segment_offset]];
auto v = osm_node_ids[nodes_range[segment_offset + 1]]; auto v = osm_node_ids[nodes_range[segment_offset + 1]];
// Self-loops are artifical segments (e.g. traffic light nodes), do not
// waste time updating them with traffic data
if (u == v)
continue;
if (auto value = segment_speed_lookup({u, v})) if (auto value = segment_speed_lookup({u, v}))
{ {
auto segment_length = segment_lengths[segment_offset]; auto segment_length = segment_lengths[segment_offset];
@@ -253,6 +260,12 @@ updateSegmentData(const UpdaterConfig &config,
{ {
auto u = osm_node_ids[nodes_range[segment_offset]]; auto u = osm_node_ids[nodes_range[segment_offset]];
auto v = osm_node_ids[nodes_range[segment_offset + 1]]; auto v = osm_node_ids[nodes_range[segment_offset + 1]];
// Self-loops are artifical segments (e.g. traffic light nodes), do not
// waste time updating them with traffic data
if (u == v)
continue;
if (auto value = segment_speed_lookup({v, u})) if (auto value = segment_speed_lookup({v, u}))
{ {
auto segment_length = segment_lengths[segment_offset]; auto segment_length = segment_lengths[segment_offset];
@@ -443,20 +456,16 @@ updateTurnPenalties(const UpdaterConfig &config,
return updated_turns; return updated_turns;
} }
bool IsRestrictionValid(const Timezoner &tz_handler, bool IsRestrictionValid(const Timezoner &tz_handler, const extractor::ConditionalTurnPenalty &turn)
const extractor::ConditionalTurnRestriction &turn,
const std::vector<util::Coordinate> &coordinates)
{ {
BOOST_ASSERT(!turn.condition.empty()); BOOST_ASSERT(!turn.conditions.empty());
// we utilize the via node (first on ways) to represent the turn restriction // we utilize the via node (first on ways) to represent the turn restriction
auto const via = turn.Type() == extractor::RestrictionType::WAY_RESTRICTION auto const via = turn.location;
? turn.AsWayRestriction().in_restriction.to
: turn.AsNodeRestriction().via;
const auto lon = static_cast<double>(toFloating(coordinates[via].lon)); const auto lon = static_cast<double>(toFloating(via.lon));
const auto lat = static_cast<double>(toFloating(coordinates[via].lat)); const auto lat = static_cast<double>(toFloating(via.lat));
const auto &condition = turn.condition; const auto &conditions = turn.conditions;
// Get local time of the restriction // Get local time of the restriction
const auto &local_time = tz_handler(point_t{lon, lat}); const auto &local_time = tz_handler(point_t{lon, lat});
@@ -469,85 +478,27 @@ bool IsRestrictionValid(const Timezoner &tz_handler,
// TODO: parsing will fail for combined conditions, e.g. Sa-Su AND weight>7 // TODO: parsing will fail for combined conditions, e.g. Sa-Su AND weight>7
// http://wiki.openstreetmap.org/wiki/Conditional_restrictions#Combined_conditions:_AND // http://wiki.openstreetmap.org/wiki/Conditional_restrictions#Combined_conditions:_AND
if (osrm::util::CheckOpeningHours(condition, *local_time)) return osrm::util::CheckOpeningHours(conditions, *local_time);
return true;
return false;
} }
std::vector<std::uint64_t> std::vector<std::uint64_t>
updateConditionalTurns(const UpdaterConfig &config, updateConditionalTurns(std::vector<TurnPenalty> &turn_weight_penalties,
std::vector<TurnPenalty> &turn_weight_penalties, const std::vector<extractor::ConditionalTurnPenalty> &conditional_turns,
const std::vector<extractor::ConditionalTurnRestriction> &conditional_turns,
std::vector<util::Coordinate> &coordinates,
Timezoner time_zone_handler) Timezoner time_zone_handler)
{ {
// Mapped file pointer for turn indices
boost::iostreams::mapped_file_source turn_index_region;
auto turn_index_blocks = util::mmapFile<extractor::lookup::TurnIndexBlock>(
config.GetPath(".osrm.turn_penalties_index"), turn_index_region);
std::vector<std::uint64_t> updated_turns; std::vector<std::uint64_t> updated_turns;
if (conditional_turns.size() == 0) if (conditional_turns.size() == 0)
return updated_turns; return updated_turns;
// TODO make this into a function for (const auto &penalty : conditional_turns)
LookupTable<std::tuple<NodeID, NodeID>, NodeID> is_only_lookup;
std::unordered_set<std::tuple<NodeID, NodeID, NodeID>,
std::hash<std::tuple<NodeID, NodeID, NodeID>>>
is_no_set;
for (const auto &node_or_way : conditional_turns)
{ {
// TODO handle conditional turn restrictions for via-ways (look-up doesn't work here) if (IsRestrictionValid(time_zone_handler, penalty))
// https://github.com/Project-OSRM/osrm-backend/issues/2681#issuecomment-313376385
if (node_or_way.Type() == extractor::RestrictionType::WAY_RESTRICTION)
continue;
if (!IsRestrictionValid(time_zone_handler, node_or_way, coordinates))
continue;
// TODO get rid of this, when we can handle way restrictions
const auto &c = node_or_way.AsNodeRestriction();
// only add restrictions to the lookups if the restriction is valid now
if (node_or_way.is_only)
{ {
is_only_lookup.lookup.push_back({std::make_tuple(c.from, c.via), c.to}); std::cout << "Disabling: " << penalty.turn_offset << std::endl;
} turn_weight_penalties[penalty.turn_offset] = INVALID_TURN_PENALTY;
else updated_turns.push_back(penalty.turn_offset);
{
is_no_set.insert({std::make_tuple(c.from, c.via, c.to)});
} }
} }
for (std::uint64_t edge_index = 0; edge_index < turn_weight_penalties.size(); ++edge_index)
{
const extractor::lookup::TurnIndexBlock internal_turn = turn_index_blocks[edge_index];
const auto is_no_tuple =
std::make_tuple(internal_turn.from_id, internal_turn.via_id, internal_turn.to_id);
const auto is_only_tuple = std::make_tuple(internal_turn.from_id, internal_turn.via_id);
// turn has a no_* restriction
if (is_no_set.find(is_no_tuple) != is_no_set.end())
{
util::Log(logDEBUG) << "Conditional penalty set on edge: " << edge_index;
turn_weight_penalties[edge_index] = INVALID_TURN_PENALTY;
updated_turns.push_back(edge_index);
}
// turn has an only_* restriction
else if (is_only_lookup(is_only_tuple))
{
// with only_* restrictions, the turn on which the restriction is tagged is valid
if (*is_only_lookup(is_only_tuple) == internal_turn.to_id)
continue;
util::Log(logDEBUG) << "Conditional penalty set on edge: " << edge_index;
turn_weight_penalties[edge_index] = INVALID_TURN_PENALTY;
updated_turns.push_back(edge_index);
}
}
return updated_turns; return updated_turns;
} }
} }
@@ -638,7 +589,7 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
load_profile_properties); load_profile_properties);
} }
std::vector<extractor::ConditionalTurnRestriction> conditional_turns; std::vector<extractor::ConditionalTurnPenalty> conditional_turns;
if (update_conditional_turns) if (update_conditional_turns)
{ {
using storage::io::FileReader; using storage::io::FileReader;
@@ -696,8 +647,8 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
} }
const Timezoner time_zone_handler = Timezoner(config.tz_file_path, config.valid_now); const Timezoner time_zone_handler = Timezoner(config.tz_file_path, config.valid_now);
auto updated_turn_penalties = updateConditionalTurns( auto updated_turn_penalties =
config, turn_weight_penalties, conditional_turns, coordinates, time_zone_handler); updateConditionalTurns(turn_weight_penalties, conditional_turns, time_zone_handler);
const auto offset = updated_segments.size(); const auto offset = updated_segments.size();
updated_segments.resize(offset + updated_turn_penalties.size()); updated_segments.resize(offset + updated_turn_penalties.size());
// we need to re-compute all edges that have updated turn penalties. // we need to re-compute all edges that have updated turn penalties.
+2 -2
View File
@@ -11,7 +11,7 @@ namespace util
//---------------------------------------------------------------- //----------------------------------------------------------------
NodeIdVectorToLineString::NodeIdVectorToLineString( NodeIdVectorToLineString::NodeIdVectorToLineString(
const std::vector<extractor::QueryNode> &node_coordinates) const std::vector<util::Coordinate> &node_coordinates)
: node_coordinates(node_coordinates) : node_coordinates(node_coordinates)
{ {
} }
@@ -32,7 +32,7 @@ operator()(const std::vector<NodeID> &node_ids,
//---------------------------------------------------------------- //----------------------------------------------------------------
NodeIdVectorToMultiPoint::NodeIdVectorToMultiPoint( NodeIdVectorToMultiPoint::NodeIdVectorToMultiPoint(
const std::vector<extractor::QueryNode> &node_coordinates) const std::vector<util::Coordinate> &node_coordinates)
: node_coordinates(node_coordinates) : node_coordinates(node_coordinates)
{ {
} }
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -10,7 +10,7 @@ exports.three_test_coordinates = [[7.41337, 43.72956],
exports.two_test_coordinates = exports.three_test_coordinates.slice(0, 2) exports.two_test_coordinates = exports.three_test_coordinates.slice(0, 2)
exports.test_tile = {'at': [17059, 11948, 15], 'size': 162422}; exports.test_tile = {'at': [17059, 11948, 15], 'size': 162429};
// Test files generated by the routing engine; check test/data // Test files generated by the routing engine; check test/data
+429
View File
@@ -0,0 +1,429 @@
#include "engine/routing_algorithms/routing_base_mld.hpp"
#include "engine/routing_algorithms/shortest_path_impl.hpp"
#include "engine/search_engine_data.hpp"
#include "util/integer_range.hpp"
#include <boost/test/unit_test.hpp>
namespace osrm
{
namespace engine
{
namespace routing_algorithms
{
// Declare offline data facade algorithm
namespace offline
{
struct Algorithm final
{
};
}
} // routing_algorithms
// Define engine data for offline data facade
template <> struct SearchEngineData<routing_algorithms::offline::Algorithm>
{
using QueryHeap = SearchEngineData<routing_algorithms::mld::Algorithm>::QueryHeap;
using SearchEngineHeapPtr = std::unique_ptr<QueryHeap>;
SearchEngineHeapPtr forward_heap_1;
SearchEngineHeapPtr reverse_heap_1;
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes)
{
if (forward_heap_1.get())
{
forward_heap_1->Clear();
}
else
{
forward_heap_1.reset(new QueryHeap(number_of_nodes));
}
if (reverse_heap_1.get())
{
reverse_heap_1->Clear();
}
else
{
reverse_heap_1.reset(new QueryHeap(number_of_nodes));
}
}
};
// Define offline multilevel partition
namespace datafacade
{
struct ExternalMultiLevelPartition
{
CellID GetCell(LevelID /*l*/, NodeID /*node*/) const { return 0; }
LevelID GetQueryLevel(NodeID /*start*/, NodeID /*target*/, NodeID /*node*/) const { return 0; }
LevelID GetHighestDifferentLevel(NodeID /*first*/, NodeID /*second*/) const { return 0; }
std::uint8_t GetNumberOfLevels() const { return 0; }
std::uint32_t GetNumberOfCells(LevelID /*level*/) const { return 0; }
CellID BeginChildren(LevelID /*level*/, CellID /*cell*/) const { return 0; }
CellID EndChildren(LevelID /*level*/, CellID /*cell*/) const { return 0; }
};
// Define external cell storage
struct ExternalCellStorage
{
struct CellImpl
{
auto GetOutWeight(NodeID /*node*/) const
{
return boost::make_iterator_range((EdgeWeight *)0, (EdgeWeight *)0);
}
auto GetInWeight(NodeID /*node*/) const
{
return boost::make_iterator_range((EdgeWeight *)0, (EdgeWeight *)0);
}
auto GetSourceNodes() const
{
return boost::make_iterator_range((EdgeWeight *)0, (EdgeWeight *)0);
}
auto GetDestinationNodes() const
{
return boost::make_iterator_range((EdgeWeight *)0, (EdgeWeight *)0);
}
};
using Cell = CellImpl;
using ConstCell = const CellImpl;
ConstCell GetCell(LevelID /*level*/, CellID /*id*/) const { return Cell{}; }
Cell GetCell(LevelID /*level*/, CellID /*id*/) { return Cell{}; }
};
// Define external data facade
template <>
class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm> final
: public BaseDataFacade
{
ExternalMultiLevelPartition external_partition;
ExternalCellStorage external_cell_storage;
public:
using EdgeData = extractor::EdgeBasedEdge::EdgeData;
// using RTreeLeaf = extractor::EdgeBasedNode;
ContiguousInternalMemoryDataFacade() {}
~ContiguousInternalMemoryDataFacade() {}
unsigned GetNumberOfNodes() const { return 0; }
NodeID GetTarget(const EdgeID /*edgeID*/) const { return 0; }
const EdgeData &GetEdgeData(const EdgeID /*edgeID*/) const
{
static EdgeData outData;
return outData;
}
const auto &GetMultiLevelPartition() const { return external_partition; }
const auto &GetCellStorage() const { return external_cell_storage; }
auto GetBorderEdgeRange(const LevelID /*level*/, const NodeID /*node*/) const
{
return util::irange<EdgeID>(0, 0);
}
EdgeID FindEdge(const NodeID /*from*/, const NodeID /*to*/) const { return SPECIAL_EDGEID; }
unsigned GetCheckSum() const override { return 0; }
// node and edge information access
util::Coordinate GetCoordinateOfNode(const NodeID /*id*/) const override
{
return {osrm::util::FloatLongitude{7.437069}, osrm::util::FloatLatitude{43.749249}};
}
OSMNodeID GetOSMNodeIDOfNode(const NodeID /*id*/) const override { return OSMNodeID(); }
GeometryID GetGeometryIndex(const NodeID /*id*/) const override { return GeometryID{0, false}; }
std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID /*id*/) const override
{
return {};
}
std::vector<NodeID> GetUncompressedReverseGeometry(const EdgeID /*id*/) const override
{
return {};
}
TurnPenalty GetWeightPenaltyForEdgeID(const unsigned /*id*/) const override
{
return INVALID_TURN_PENALTY;
}
TurnPenalty GetDurationPenaltyForEdgeID(const unsigned /*id*/) const override
{
return INVALID_TURN_PENALTY;
}
std::vector<EdgeWeight> GetUncompressedForwardWeights(const EdgeID /*id*/) const override
{
return {};
}
std::vector<EdgeWeight> GetUncompressedReverseWeights(const EdgeID /*id*/) const override
{
return {};
}
std::vector<EdgeWeight> GetUncompressedForwardDurations(const EdgeID /*geomID*/) const override
{
return {};
}
std::vector<EdgeWeight> GetUncompressedReverseDurations(const EdgeID /*geomID*/) const override
{
return {};
}
std::vector<DatasourceID> GetUncompressedForwardDatasources(const EdgeID /*id*/) const override
{
return {};
}
std::vector<DatasourceID> GetUncompressedReverseDatasources(const EdgeID /*id*/) const override
{
return {};
}
StringView GetDatasourceName(const DatasourceID /*id*/) const override { return StringView{}; }
extractor::guidance::TurnInstruction
GetTurnInstructionForEdgeID(const EdgeID /*id*/) const override
{
return extractor::guidance::TurnInstruction{};
}
extractor::TravelMode GetTravelMode(const NodeID /*id*/) const override
{
return TRAVEL_MODE_DRIVING;
}
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate /*south_west*/,
const util::Coordinate /*north_east*/) const override
{
return {};
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate /*input_coordinate*/,
const float /*max_distance*/,
const int /*bearing*/,
const int /*bearing_range*/,
const Approach /*approach*/) const override
{
return {};
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate /*input_coordinate*/,
const float /*max_distance*/,
const Approach /*approach*/) const override
{
return {};
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate /*input_coordinate*/,
const unsigned /*max_results*/,
const double /*max_distance*/,
const int /*bearing*/,
const int /*bearing_range*/,
const Approach /*approach*/) const override
{
return {};
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate /*input_coordinate*/,
const unsigned /*max_results*/,
const int /*bearing*/,
const int /*bearing_range*/,
const Approach /*approach*/) const override
{
return {};
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate /*input_coordinate*/,
const unsigned /*max_results*/,
const Approach /*approach*/) const override
{
return {};
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate /*input_coordinate*/,
const unsigned /*max_results*/,
const double /*max_distance*/,
const Approach /*approach*/) const override
{
return {};
}
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
const Approach /*approach*/) const override
{
return {};
}
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
const double /*max_distance*/,
const Approach /*approach*/) const override
{
return {};
}
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
const double /*max_distance*/,
const int /*bearing*/,
const int /*bearing_range*/,
const Approach /*approach*/) const override
{
return {};
}
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
const int /*bearing*/,
const int /*bearing_range*/,
const Approach /*approach*/) const override
{
return {};
}
util::guidance::LaneTupleIdPair GetLaneData(const EdgeID /*id*/) const override
{
return util::guidance::LaneTupleIdPair{};
}
extractor::guidance::TurnLaneDescription
GetTurnDescription(const LaneDescriptionID /*laneDescriptionID*/) const override
{
return {};
}
bool HasLaneData(const EdgeID /*id*/) const override { return false; }
NameID GetNameIndex(const NodeID /*nodeID*/) const { return EMPTY_NAMEID; }
StringView GetNameForID(const NameID /*id*/) const override { return StringView{}; }
StringView GetRefForID(const NameID /*id*/) const override { return StringView{}; }
StringView GetPronunciationForID(const NameID /*id*/) const override { return StringView{}; }
StringView GetDestinationsForID(const NameID /*id*/) const override { return StringView{}; }
StringView GetExitsForID(const NameID /*id*/) const override { return StringView{}; }
std::string GetTimestamp() const override { return std::string(); }
bool GetContinueStraightDefault() const override { return false; }
double GetMapMatchingMaxSpeed() const override { return 0; }
const char *GetWeightName() const override { return ""; }
unsigned GetWeightPrecision() const override { return 0; }
double GetWeightMultiplier() const override { return 1; }
ComponentID GetComponentID(NodeID) const override { return ComponentID{}; }
util::guidance::TurnBearing PreTurnBearing(const EdgeID /*eid*/) const override
{
return util::guidance::TurnBearing(0);
}
util::guidance::TurnBearing PostTurnBearing(const EdgeID /*eid*/) const override
{
return util::guidance::TurnBearing(0);
}
util::guidance::BearingClass
GetBearingClass(const BearingClassID /*bearing_class_id*/) const override
{
return util::guidance::BearingClass{};
}
osrm::extractor::ClassData GetClassData(const NodeID /*id*/) const override { return 0; }
std::vector<std::string> GetClasses(const extractor::ClassData /*class_data*/) const override
{
return {};
}
util::guidance::EntryClass GetEntryClass(const EdgeID /*turn_id*/) const override { return {}; }
bool IsLeftHandDriving() const override { return false; }
};
} // datafacade
// Fallback to MLD algorithm: requires from data facade MLD specific members
namespace routing_algorithms
{
namespace offline
{
inline void search(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
EdgeWeight &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
const PhantomNodes &phantom_nodes,
const EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
{
mld::search(engine_working_data,
facade,
forward_heap,
reverse_heap,
weight,
packed_leg,
force_loop_forward,
force_loop_reverse,
phantom_nodes,
weight_upper_bound);
}
template <typename RandomIter, typename FacadeT>
void unpackPath(const FacadeT &facade,
RandomIter packed_path_begin,
RandomIter packed_path_end,
const PhantomNodes &phantom_nodes,
std::vector<PathData> &unpacked_path)
{
mld::unpackPath(facade, packed_path_begin, packed_path_end, phantom_nodes, unpacked_path);
}
} // offline
} // routing_algorithms
} // engine
} // osrm
BOOST_AUTO_TEST_SUITE(offline_facade)
BOOST_AUTO_TEST_CASE(shortest_path)
{
using Algorithm = osrm::engine::routing_algorithms::offline::Algorithm;
osrm::engine::SearchEngineData<Algorithm> heaps;
osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<Algorithm> facade;
std::vector<osrm::engine::PhantomNodes> phantom_nodes;
phantom_nodes.push_back({osrm::engine::PhantomNode{}, osrm::engine::PhantomNode{}});
auto route =
osrm::engine::routing_algorithms::shortestPathSearch(heaps, facade, phantom_nodes, false);
BOOST_CHECK_EQUAL(route.shortest_path_weight, INVALID_EDGE_WEIGHT);
}
BOOST_AUTO_TEST_SUITE_END()

Some files were not shown because too many files have changed in this diff Show More