Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 300d901618 | |||
| fd6daa580a | |||
| c2fc47df34 |
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
Checks: '-clang-analyzer-*,google-*,llvm-*,misc-*,readability-*,-google-build-explicit-make-pair,-google-explicit-constructor,-google-readability-braces-around-statements,-google-readability-casting,-google-readability-namespace-comments,-google-readability-function,-google-readability-todo,-google-runtime-int,-llvm-namespace-comment,-llvm-header-guard,-llvm-twine-local,-misc-argument-comment,-readability-braces-around-statements,-readability-identifier-naming'
|
|
||||||
...
|
|
||||||
|
|
||||||
-14
@@ -1,14 +0,0 @@
|
|||||||
# Kind-specific patterns to check AST nodes against. Both python-clang and
|
|
||||||
# libclang docs explain CursorKind, with differences in detail. See also:
|
|
||||||
# - https://github.com/llvm-mirror/clang/blob/aca4fe314a55cacae29e1548cb7bfd2119c6df4c/bindings/python/clang/cindex.py#L599
|
|
||||||
# - http://clang.llvm.org/doxygen/group__CINDEX.html#gaaccc432245b4cd9f2d470913f9ef0013
|
|
||||||
# - https://docs.python.org/2/library/re.html#regular-expression-syntax
|
|
||||||
|
|
||||||
class_decl: '^([A-Z]+[a-z]+)+$'
|
|
||||||
struct_decl: '^([A-Z]+[a-z]+)+$'
|
|
||||||
field_decl: '^[a-z_]+$'
|
|
||||||
var_decl: '^[a-z]+[a-z0-9_]*$'
|
|
||||||
parm_decl: '^[a-z]*[a-z0-9_]*$'
|
|
||||||
namespace: '^[a-z_]*$'
|
|
||||||
cxx_method: '^([A-Z]+[a-z]+)+$'
|
|
||||||
function_decl: '^[a-z]+([A-Z]+[a-z]+)*$'
|
|
||||||
+2
-3
@@ -40,7 +40,8 @@ Thumbs.db
|
|||||||
# build related files #
|
# build related files #
|
||||||
#######################
|
#######################
|
||||||
/build/
|
/build/
|
||||||
/example/build/
|
/util/fingerprint_impl.hpp
|
||||||
|
/util/git_sha.cpp
|
||||||
/cmake/postinst
|
/cmake/postinst
|
||||||
|
|
||||||
# Eclipse related files #
|
# Eclipse related files #
|
||||||
@@ -79,5 +80,3 @@ stxxl.errlog
|
|||||||
# Deprecated config file #
|
# Deprecated config file #
|
||||||
##########################
|
##########################
|
||||||
/server.ini
|
/server.ini
|
||||||
|
|
||||||
*.swp
|
|
||||||
|
|||||||
+60
-171
@@ -1,176 +1,65 @@
|
|||||||
#language: cpp
|
language: cpp
|
||||||
# This makes travis use the thin image which boots faster
|
compiler:
|
||||||
language: generic
|
- gcc
|
||||||
|
# - clang
|
||||||
|
# Make sure CMake is installed
|
||||||
# sudo:required is needed for trusty images
|
install:
|
||||||
sudo: required
|
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
|
||||||
dist: trusty
|
- sudo add-apt-repository -y ppa:boost-latest/ppa
|
||||||
|
- sudo apt-get update >/dev/null
|
||||||
notifications:
|
- sudo apt-get -q install protobuf-compiler libprotoc-dev libprotobuf7 libprotobuf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev rubygems libtbb-dev
|
||||||
email: false
|
- sudo apt-get -q install g++-4.8
|
||||||
|
- sudo apt-get install libboost1.54-all-dev
|
||||||
|
- sudo apt-get install libgdal-dev
|
||||||
|
# luabind
|
||||||
|
- curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
|
||||||
|
# osmosis
|
||||||
|
- curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
|
||||||
|
# cmake
|
||||||
|
- curl -s https://gist.githubusercontent.com/DennisOSRM/5fad9bee5c7f09fd7fc9/raw/ | sudo bash
|
||||||
|
# osmpbf library
|
||||||
|
- curl -s https://gist.githubusercontent.com/DennisOSRM/13b1b4fe38a57ead850e/raw/install_osmpbf.sh | sudo bash
|
||||||
|
before_script:
|
||||||
|
- rvm use 1.9.3
|
||||||
|
- gem install bundler
|
||||||
|
- bundle install
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- cmake .. $CMAKEOPTIONS -DBUILD_TOOLS=1
|
||||||
|
script:
|
||||||
|
- make
|
||||||
|
- make tests
|
||||||
|
- make benchmarks
|
||||||
|
- ./algorithm-tests
|
||||||
|
- ./datastructure-tests
|
||||||
|
- cd ..
|
||||||
|
- cucumber -p verify
|
||||||
|
after_script:
|
||||||
|
# - cd ..
|
||||||
|
# - cucumber -p verify
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
- develop
|
- develop
|
||||||
|
cache:
|
||||||
|
- bundler
|
||||||
|
- apt
|
||||||
|
env:
|
||||||
|
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5000 OSRM_TIMEOUT=60
|
||||||
|
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5010 OSRM_TIMEOUT=60
|
||||||
|
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5020 OSRM_TIMEOUT=60
|
||||||
|
notifications:
|
||||||
|
slack: mapbox:4A6euphDwfxAQnhLurXbu6A1
|
||||||
|
irc:
|
||||||
|
channels:
|
||||||
|
- irc.oftc.net#osrm
|
||||||
|
on_success: change
|
||||||
|
on_failure: always
|
||||||
|
use_notice: true
|
||||||
|
skip_join: false
|
||||||
|
|
||||||
matrix:
|
recipients:
|
||||||
fast_finish: true
|
- patrick@mapbox.com
|
||||||
|
email:
|
||||||
include:
|
on_success: change
|
||||||
|
on_failure: always
|
||||||
# Debug Builds
|
|
||||||
- os: linux
|
|
||||||
compiler: gcc
|
|
||||||
addons: &gcc5
|
|
||||||
apt:
|
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
|
||||||
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'rubygems-integration', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
|
||||||
env: COMPILER='g++-5' BUILD_TYPE='Debug'
|
|
||||||
|
|
||||||
- os: linux
|
|
||||||
compiler: gcc
|
|
||||||
addons: &gcc48
|
|
||||||
apt:
|
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
|
||||||
packages: ['g++-4.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'rubygems-integration', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
|
||||||
env: COMPILER='g++-4.8' BUILD_TYPE='Debug'
|
|
||||||
|
|
||||||
- os: linux
|
|
||||||
compiler: clang
|
|
||||||
addons: &clang38
|
|
||||||
apt:
|
|
||||||
sources: ['llvm-toolchain-precise', 'ubuntu-toolchain-r-test']
|
|
||||||
packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'rubygems-integration', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
|
||||||
env: COMPILER='clang++-3.8' BUILD_TYPE='Debug' RUN_CLANG_FORMAT=ON
|
|
||||||
|
|
||||||
- os: osx
|
|
||||||
osx_image: xcode7.3
|
|
||||||
compiler: clang
|
|
||||||
env: COMPILER='clang++' BUILD_TYPE='Debug'
|
|
||||||
|
|
||||||
# Release Builds
|
|
||||||
- os: linux
|
|
||||||
compiler: gcc
|
|
||||||
addons: &gcc5
|
|
||||||
apt:
|
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
|
||||||
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'rubygems-integration', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
|
||||||
env: COMPILER='g++-5' BUILD_TYPE='Release'
|
|
||||||
|
|
||||||
- os: linux
|
|
||||||
compiler: gcc
|
|
||||||
addons: &gcc48
|
|
||||||
apt:
|
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
|
||||||
packages: ['g++-4.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'rubygems-integration', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
|
||||||
env: COMPILER='g++-4.8' BUILD_TYPE='Release'
|
|
||||||
|
|
||||||
- os: linux
|
|
||||||
compiler: clang
|
|
||||||
addons: &clang38
|
|
||||||
apt:
|
|
||||||
sources: ['llvm-toolchain-precise', 'ubuntu-toolchain-r-test']
|
|
||||||
packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'rubygems-integration', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
|
||||||
env: COMPILER='clang++-3.8' BUILD_TYPE='Release'
|
|
||||||
|
|
||||||
- os: osx
|
|
||||||
osx_image: xcode7.3
|
|
||||||
compiler: clang
|
|
||||||
env: COMPILER='clang++' BUILD_TYPE='Release'
|
|
||||||
|
|
||||||
# Shared Library
|
|
||||||
- os: linux
|
|
||||||
compiler: gcc
|
|
||||||
addons: &gcc5
|
|
||||||
apt:
|
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
|
||||||
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'rubygems-integration', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
|
||||||
env: COMPILER='g++-5' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
|
||||||
|
|
||||||
- os: linux
|
|
||||||
compiler: clang
|
|
||||||
addons: &clang38
|
|
||||||
apt:
|
|
||||||
sources: ['llvm-toolchain-precise', 'ubuntu-toolchain-r-test']
|
|
||||||
packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'rubygems-integration', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
|
||||||
env: COMPILER='clang++-3.8' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
|
||||||
|
|
||||||
|
|
||||||
# Disabled until tests all pass on OSX:
|
|
||||||
#
|
|
||||||
# 3/ OSX Clang Builds
|
|
||||||
#- os: osx
|
|
||||||
# osx_image: xcode6.4
|
|
||||||
# compiler: clang
|
|
||||||
# env: COMPILER='clang++' BUILD_TYPE='Debug'
|
|
||||||
|
|
||||||
#- os: osx
|
|
||||||
# osx_image: xcode6.4
|
|
||||||
# compiler: clang
|
|
||||||
# env: COMPILER='clang++' BUILD_TYPE='Release'
|
|
||||||
|
|
||||||
#- os: osx
|
|
||||||
# osx_image: xcode6.4
|
|
||||||
# compiler: clang
|
|
||||||
# env: COMPILER='clang++' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
|
||||||
|
|
||||||
#- os: osx
|
|
||||||
# osx_image: xcode7
|
|
||||||
# compiler: clang
|
|
||||||
# env: COMPILER='clang++' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
|
||||||
|
|
||||||
|
|
||||||
install:
|
|
||||||
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
|
||||||
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
|
|
||||||
- |
|
|
||||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
|
||||||
CMAKE_URL="http://www.cmake.org/files/v3.3/cmake-3.3.2-Linux-x86_64.tar.gz"
|
|
||||||
mkdir cmake && travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
|
|
||||||
export PATH=${DEPS_DIR}/cmake/bin:${PATH}
|
|
||||||
|
|
||||||
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
|
||||||
# implicit deps, but seem to be installed by default with recent images: libxml2 GDAL boost
|
|
||||||
brew install cmake libzip libstxxl lua51 luabind tbb md5sha1sum
|
|
||||||
fi
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- cd ${TRAVIS_BUILD_DIR}
|
|
||||||
- |
|
|
||||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
|
||||||
./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
|
||||||
fi
|
|
||||||
- rvm use 1.9.3
|
|
||||||
- gem install bundler
|
|
||||||
- bundle install
|
|
||||||
- mkdir build && pushd build
|
|
||||||
- export CXX=${COMPILER}
|
|
||||||
- export OSRM_PORT=5000 OSRM_TIMEOUT=60
|
|
||||||
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS:-OFF} -DBUILD_TOOLS=1 -DENABLE_CCACHE=0
|
|
||||||
|
|
||||||
script:
|
|
||||||
- make --jobs=2
|
|
||||||
- make tests --jobs=2
|
|
||||||
- make benchmarks
|
|
||||||
- sudo make install
|
|
||||||
- |
|
|
||||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
|
||||||
sudo ldconfig
|
|
||||||
fi
|
|
||||||
- ./extractor-tests
|
|
||||||
- ./engine-tests
|
|
||||||
- ./util-tests
|
|
||||||
- popd
|
|
||||||
- cucumber -p verify
|
|
||||||
- make -C test/data
|
|
||||||
- mkdir example/build && pushd example/build
|
|
||||||
- cmake ..
|
|
||||||
- make
|
|
||||||
- ./osrm-example ../../test/data/monaco.osrm
|
|
||||||
- popd
|
|
||||||
- |
|
|
||||||
if [ -n "$RUN_CLANG_FORMAT" ]; then
|
|
||||||
./scripts/format.sh || true # we don't want to fail just yet
|
|
||||||
fi
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
# 5.0.0
|
|
||||||
- Renamed osrm-prepare into osrm-contract
|
|
||||||
- osrm-contract does not need a profile parameter anymore
|
|
||||||
+166
-237
@@ -7,15 +7,13 @@ This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. P
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(OSRM C CXX)
|
project(OSRM C CXX)
|
||||||
set(OSRM_VERSION_MAJOR 4)
|
|
||||||
set(OSRM_VERSION_MINOR 9)
|
|
||||||
set(OSRM_VERSION_PATCH 1)
|
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
include(GetGitRevisionDescription)
|
||||||
|
git_describe(GIT_DESCRIPTION)
|
||||||
|
|
||||||
set(bitness 32)
|
set(bitness 32)
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
@@ -29,73 +27,85 @@ if(WIN32 AND MSVC_VERSION LESS 1800)
|
|||||||
message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)")
|
message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(ENABLE_CCACHE "Speed up incremental rebuilds via ccache" ON)
|
|
||||||
option(ENABLE_JSON_LOGGING "Adds additional JSON debug logging to the response" OFF)
|
option(ENABLE_JSON_LOGGING "Adds additional JSON debug logging to the response" OFF)
|
||||||
|
option(WITH_TOOLS "Build OSRM tools" OFF)
|
||||||
option(BUILD_TOOLS "Build OSRM tools" OFF)
|
option(BUILD_TOOLS "Build OSRM tools" OFF)
|
||||||
option(ENABLE_ASSERTIONS OFF)
|
|
||||||
|
|
||||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/include/)
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/)
|
||||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/include/)
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/)
|
||||||
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/)
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include/)
|
||||||
|
|
||||||
add_custom_target(FingerPrintConfigure ALL ${CMAKE_COMMAND}
|
add_custom_target(FingerPrintConfigure ALL
|
||||||
"-DOUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR}"
|
${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
||||||
"-DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}"
|
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake
|
||||||
-P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake"
|
|
||||||
COMMENT "Configuring revision fingerprint"
|
COMMENT "Configuring revision fingerprint"
|
||||||
VERBATIM)
|
VERBATIM)
|
||||||
|
|
||||||
add_custom_target(tests DEPENDS engine-tests extractor-tests util-tests server-tests)
|
add_custom_target(tests DEPENDS datastructure-tests algorithm-tests)
|
||||||
add_custom_target(benchmarks DEPENDS rtree-bench)
|
add_custom_target(benchmarks DEPENDS rtree-bench)
|
||||||
|
|
||||||
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread unit_test_framework)
|
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread unit_test_framework)
|
||||||
|
|
||||||
configure_file(
|
configure_file(
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include/util/version.hpp.in
|
${CMAKE_CURRENT_SOURCE_DIR}/util/git_sha.cpp.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/include/util/version.hpp
|
${CMAKE_CURRENT_SOURCE_DIR}/util/git_sha.cpp
|
||||||
)
|
)
|
||||||
file(GLOB UtilGlob src/util/*.cpp)
|
file(GLOB ExtractorGlob extractor/*.cpp)
|
||||||
file(GLOB ExtractorGlob src/extractor/*.cpp src/extractor/*/*.cpp)
|
file(GLOB ImporterGlob data_structures/import_edge.cpp data_structures/external_memory_node.cpp)
|
||||||
file(GLOB ContractorGlob src/contractor/*.cpp)
|
add_library(IMPORT OBJECT ${ImporterGlob})
|
||||||
file(GLOB StorageGlob src/storage/*.cpp)
|
add_library(LOGGER OBJECT util/simple_logger.cpp)
|
||||||
file(GLOB ServerGlob src/server/*.cpp src/server/**/*.cpp)
|
add_library(PHANTOMNODE OBJECT data_structures/phantom_node.cpp)
|
||||||
file(GLOB EngineGlob src/engine/*.cpp src/engine/**/*.cpp)
|
add_library(EXCEPTION OBJECT util/osrm_exception.cpp)
|
||||||
file(GLOB ExtractorTestsGlob unit_tests/extractor/*.cpp)
|
add_library(MERCATOR OBJECT util/mercator.cpp)
|
||||||
file(GLOB EngineTestsGlob unit_tests/engine/*.cpp)
|
add_library(ANGLE OBJECT util/compute_angle.cpp)
|
||||||
file(GLOB UtilTestsGlob unit_tests/util/*.cpp)
|
|
||||||
file(GLOB ServerTestsGlob unit_tests/server/*.cpp)
|
|
||||||
file(GLOB IOTestsGlob unit_tests/io/*.cpp)
|
|
||||||
|
|
||||||
add_library(UTIL OBJECT ${UtilGlob})
|
set(ExtractorSources extract.cpp ${ExtractorGlob})
|
||||||
add_library(EXTRACTOR OBJECT ${ExtractorGlob})
|
add_executable(osrm-extract ${ExtractorSources} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||||
add_library(CONTRACTOR OBJECT ${ContractorGlob})
|
|
||||||
add_library(STORAGE OBJECT ${StorageGlob})
|
|
||||||
add_library(ENGINE OBJECT ${EngineGlob})
|
|
||||||
add_library(SERVER OBJECT ${ServerGlob})
|
|
||||||
|
|
||||||
add_dependencies(UTIL FingerPrintConfigure)
|
add_library(RESTRICTION OBJECT data_structures/restriction_map.cpp)
|
||||||
set_target_properties(UTIL PROPERTIES LINKER_LANGUAGE CXX)
|
|
||||||
|
|
||||||
add_executable(osrm-extract src/tools/extract.cpp)
|
file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp {RestrictionMapGlob})
|
||||||
add_executable(osrm-contract src/tools/contract.cpp)
|
set(PrepareSources prepare.cpp ${PrepareGlob})
|
||||||
add_executable(osrm-routed src/tools/routed.cpp $<TARGET_OBJECTS:SERVER> $<TARGET_OBJECTS:UTIL>)
|
add_executable(osrm-prepare ${PrepareSources} $<TARGET_OBJECTS:ANGLE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||||
add_executable(osrm-datastore src/tools/store.cpp $<TARGET_OBJECTS:UTIL>)
|
|
||||||
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:UTIL>)
|
file(GLOB ServerGlob server/*.cpp)
|
||||||
add_library(osrm_extract $<TARGET_OBJECTS:EXTRACTOR> $<TARGET_OBJECTS:UTIL>)
|
file(GLOB DescriptorGlob descriptors/*.cpp)
|
||||||
add_library(osrm_contract $<TARGET_OBJECTS:CONTRACTOR> $<TARGET_OBJECTS:UTIL>)
|
file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp util/bearing.cpp)
|
||||||
add_library(osrm_store $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:UTIL>)
|
list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp)
|
||||||
|
file(GLOB CoordinateGlob data_structures/coordinate*.cpp)
|
||||||
|
file(GLOB AlgorithmGlob algorithms/*.cpp)
|
||||||
|
file(GLOB HttpGlob server/http/*.cpp)
|
||||||
|
file(GLOB LibOSRMGlob library/*.cpp)
|
||||||
|
file(GLOB DataStructureTestsGlob unit_tests/data_structures/*.cpp data_structures/hilbert_value.cpp)
|
||||||
|
file(GLOB AlgorithmTestsGlob unit_tests/algorithms/*.cpp)
|
||||||
|
|
||||||
|
set(
|
||||||
|
OSRMSources
|
||||||
|
${LibOSRMGlob}
|
||||||
|
${DescriptorGlob}
|
||||||
|
${DatastructureGlob}
|
||||||
|
${AlgorithmGlob}
|
||||||
|
${HttpGlob}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(COORDINATE OBJECT ${CoordinateGlob})
|
||||||
|
add_library(GITDESCRIPTION OBJECT util/git_sha.cpp)
|
||||||
|
add_library(OSRM ${OSRMSources} $<TARGET_OBJECTS:ANGLE> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR> $<TARGET_OBJECTS:IMPORT>)
|
||||||
|
|
||||||
|
add_library(FINGERPRINT OBJECT util/fingerprint.cpp)
|
||||||
|
add_dependencies(FINGERPRINT FingerPrintConfigure)
|
||||||
|
add_dependencies(OSRM FingerPrintConfigure)
|
||||||
|
set_target_properties(FINGERPRINT PROPERTIES LINKER_LANGUAGE CXX)
|
||||||
|
|
||||||
|
add_executable(osrm-routed routed.cpp ${ServerGlob} $<TARGET_OBJECTS:EXCEPTION>)
|
||||||
|
add_executable(osrm-datastore datastore.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||||
|
|
||||||
# Unit tests
|
# Unit tests
|
||||||
add_executable(engine-tests EXCLUDE_FROM_ALL unit_tests/engine_tests.cpp ${EngineTestsGlob} $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:UTIL>)
|
add_executable(datastructure-tests EXCLUDE_FROM_ALL unit_tests/datastructure_tests.cpp ${DataStructureTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||||
add_executable(extractor-tests EXCLUDE_FROM_ALL unit_tests/extractor_tests.cpp ${ExtractorTestsGlob} $<TARGET_OBJECTS:EXTRACTOR> $<TARGET_OBJECTS:UTIL>)
|
add_executable(algorithm-tests EXCLUDE_FROM_ALL unit_tests/algorithm_tests.cpp ${AlgorithmTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION>)
|
||||||
add_executable(util-tests EXCLUDE_FROM_ALL unit_tests/util_tests.cpp ${UtilTestsGlob} $<TARGET_OBJECTS:UTIL>)
|
|
||||||
add_executable(server-tests EXCLUDE_FROM_ALL unit_tests/server_tests.cpp ${ServerTestsGlob} $<TARGET_OBJECTS:UTIL> $<TARGET_OBJECTS:SERVER>)
|
|
||||||
|
|
||||||
# Benchmarks
|
# Benchmarks
|
||||||
add_executable(rtree-bench EXCLUDE_FROM_ALL src/benchmarks/static_rtree.cpp $<TARGET_OBJECTS:UTIL>)
|
add_executable(rtree-bench EXCLUDE_FROM_ALL benchmarks/static_rtree.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||||
|
|
||||||
target_include_directories(util-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests)
|
|
||||||
target_include_directories(rtree-bench PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests)
|
|
||||||
|
|
||||||
# Check the release mode
|
# Check the release mode
|
||||||
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
@@ -103,31 +113,19 @@ if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
|||||||
endif()
|
endif()
|
||||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
message(STATUS "Configuring OSRM in debug mode")
|
message(STATUS "Configuring OSRM in debug mode")
|
||||||
set(ENABLE_ASSERTIONS ON)
|
|
||||||
if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
|
if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
|
||||||
|
message(STATUS "adding profiling flags")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-inline -fno-omit-frame-pointer")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||||
|
set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Og -ggdb")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
if(CMAKE_BUILD_TYPE MATCHES Release)
|
if(CMAKE_BUILD_TYPE MATCHES Release)
|
||||||
message(STATUS "Configuring OSRM in release mode")
|
message(STATUS "Configuring OSRM in release mode")
|
||||||
# Check if LTO is available
|
# Check if LTO is available
|
||||||
|
set(LTO_FLAGS "")
|
||||||
check_cxx_compiler_flag("-flto" LTO_AVAILABLE)
|
check_cxx_compiler_flag("-flto" LTO_AVAILABLE)
|
||||||
if(LTO_AVAILABLE)
|
if(LTO_AVAILABLE)
|
||||||
set(OLD_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
|
||||||
# GCC in addition allows parallelizing LTO
|
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
|
||||||
include(ProcessorCount)
|
|
||||||
ProcessorCount(NPROC)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto=${NPROC}")
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
|
|
||||||
endif()
|
|
||||||
set(CHECK_LTO_SRC "int main(){return 0;}")
|
set(CHECK_LTO_SRC "int main(){return 0;}")
|
||||||
check_cxx_source_compiles("${CHECK_LTO_SRC}" LTO_WORKS)
|
check_cxx_source_compiles("${CHECK_LTO_SRC}" LTO_WORKS)
|
||||||
if(LTO_WORKS)
|
if(LTO_WORKS)
|
||||||
@@ -144,11 +142,6 @@ if(CMAKE_BUILD_TYPE MATCHES Release)
|
|||||||
set(CMAKE_AR "/usr/bin/gcc-ar")
|
set(CMAKE_AR "/usr/bin/gcc-ar")
|
||||||
set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
|
set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "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")
|
|
||||||
set(CMAKE_CXX_FLAGS "${OLD_CXX_FLAGS}")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -158,7 +151,9 @@ endif()
|
|||||||
|
|
||||||
# Configuring compilers
|
# Configuring compilers
|
||||||
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
|
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wuninitialized -Wunreachable-code -Wstrict-overflow=2 -D_FORTIFY_SOURCE=2 -fPIC -fcolor-diagnostics")
|
# using Clang
|
||||||
|
# -Weverything -Wno-c++98-compat -Wno-shadow -Wno-exit-time-destructors
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -pedantic -fPIC")
|
||||||
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
|
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "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)
|
||||||
@@ -166,8 +161,9 @@ elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
|
|||||||
set(COLOR_FLAG "")
|
set(COLOR_FLAG "")
|
||||||
endif()
|
endif()
|
||||||
# using GCC
|
# using GCC
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wuninitialized -Wunreachable-code -Wstrict-overflow=1 -D_FORTIFY_SOURCE=2 ${COLOR_FLAG} -fPIC")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -fPIC ${COLOR_FLAG}")
|
||||||
if(WIN32) # using mingw
|
if(WIN32) # using mingw
|
||||||
|
add_definitions(-D_USE_MATH_DEFINES) # define M_PI, M_1_PI etc.
|
||||||
add_definitions(-DWIN32)
|
add_definitions(-DWIN32)
|
||||||
set(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
|
set(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
|
||||||
endif()
|
endif()
|
||||||
@@ -179,32 +175,13 @@ elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
|
|||||||
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} date_time chrono zlib)
|
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} date_time chrono zlib)
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
add_definitions(-DNOMINMAX) # avoid min and max macros that can break compilation
|
add_definitions(-DNOMINMAX) # avoid min and max macros that can break compilation
|
||||||
|
add_definitions(-D_USE_MATH_DEFINES) # define M_PI
|
||||||
add_definitions(-D_WIN32_WINNT=0x0501)
|
add_definitions(-D_WIN32_WINNT=0x0501)
|
||||||
add_definitions(-DXML_STATIC)
|
add_definitions(-DXML_STATIC)
|
||||||
find_library(ws2_32_LIBRARY_PATH ws2_32)
|
find_library(ws2_32_LIBRARY_PATH ws2_32)
|
||||||
target_link_libraries(osrm-extract wsock32 ws2_32)
|
target_link_libraries(osrm-extract wsock32 ws2_32)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Configuring linker
|
|
||||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} "-Wl,--version" ERROR_QUIET OUTPUT_VARIABLE LINKER_VERSION)
|
|
||||||
# For ld.gold and ld.bfs (the GNU linkers) we optimize hard
|
|
||||||
if("${LINKER_VERSION}" MATCHES "GNU gold" OR "${LINKER_VERSION}" MATCHES "GNU ld")
|
|
||||||
message(STATUS "Setting linker optimizations")
|
|
||||||
if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
|
|
||||||
# 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")
|
|
||||||
# Tell linker to do dead code and data eminination during link time discarding sections
|
|
||||||
set(LINKER_FLAGS "${LINKER_FLAGS} -Wl,--gc-sections")
|
|
||||||
endif()
|
|
||||||
# Default linker optimization flags
|
|
||||||
set(LINKER_FLAGS "${LINKER_FLAGS} -Wl,-O1 -Wl,--hash-style=gnu -Wl,--sort-common")
|
|
||||||
else()
|
|
||||||
message(STATUS "Using unknown linker, not setting linker optimizations")
|
|
||||||
endif ()
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
|
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
|
|
||||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
|
|
||||||
|
|
||||||
# Activate C++11
|
# Activate C++11
|
||||||
if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
|
if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ")
|
||||||
@@ -226,42 +203,75 @@ if(APPLE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
set(MAYBE_RT_LIBRARY rt)
|
target_link_libraries(osrm-prepare rt)
|
||||||
|
target_link_libraries(osrm-datastore rt)
|
||||||
|
target_link_libraries(OSRM rt)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/cmake")
|
#Check Boost
|
||||||
set(OSMIUM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include")
|
set(BOOST_MIN_VERSION "1.49.0")
|
||||||
find_package(Osmium REQUIRED COMPONENTS io)
|
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED)
|
||||||
include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS})
|
if(NOT Boost_FOUND)
|
||||||
|
message(FATAL_ERROR "Fatal error: Boost (version >= 1.49.0) required.\n")
|
||||||
|
endif()
|
||||||
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
target_link_libraries(OSRM ${Boost_LIBRARIES})
|
||||||
find_package(Boost 1.49.0 COMPONENTS ${BOOST_COMPONENTS} REQUIRED)
|
target_link_libraries(osrm-extract ${Boost_LIBRARIES})
|
||||||
add_definitions(-DBOOST_TEST_DYN_LINK -DBOOST_SPIRIT_USE_PHOENIX_V3 -DBOOST_RESULT_OF_USE_DECLTYPE)
|
target_link_libraries(osrm-prepare ${Boost_LIBRARIES})
|
||||||
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
|
||||||
|
target_link_libraries(osrm-datastore ${Boost_LIBRARIES})
|
||||||
|
target_link_libraries(datastructure-tests ${Boost_LIBRARIES})
|
||||||
|
target_link_libraries(algorithm-tests ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
|
||||||
|
target_link_libraries(rtree-bench ${Boost_LIBRARIES})
|
||||||
|
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(osrm-datastore ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(osrm-prepare ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(OSRM ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(datastructure-tests ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(algorithm-tests ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(rtree-bench ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
|
||||||
find_package(TBB REQUIRED)
|
find_package(TBB REQUIRED)
|
||||||
include_directories(SYSTEM ${TBB_INCLUDE_DIR})
|
|
||||||
if(WIN32 AND CMAKE_BUILD_TYPE MATCHES Debug)
|
if(WIN32 AND CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
set(TBB_LIBRARIES ${TBB_DEBUG_LIBRARIES})
|
set(TBB_LIBRARIES ${TBB_DEBUG_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
target_link_libraries(osrm-datastore ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(osrm-extract ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(osrm-prepare ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(osrm-routed ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(datastructure-tests ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(algorithm-tests ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(rtree-bench ${TBB_LIBRARIES})
|
||||||
|
include_directories(${TBB_INCLUDE_DIR})
|
||||||
|
|
||||||
find_package( Luabind REQUIRED )
|
find_package( Luabind REQUIRED )
|
||||||
include(check_luabind)
|
include(check_luabind)
|
||||||
include_directories(SYSTEM ${LUABIND_INCLUDE_DIR})
|
|
||||||
|
|
||||||
set(USED_LUA_LIBRARIES ${LUA_LIBRARY})
|
include_directories(${LUABIND_INCLUDE_DIR})
|
||||||
|
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
|
||||||
|
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
|
||||||
|
|
||||||
if(LUAJIT_FOUND)
|
if(LUAJIT_FOUND)
|
||||||
set(USED_LUA_LIBRARIES, LUAJIT_LIBRARIES)
|
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
|
||||||
|
target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES})
|
||||||
|
else()
|
||||||
|
target_link_libraries(osrm-extract ${LUA_LIBRARY})
|
||||||
|
target_link_libraries(osrm-prepare ${LUA_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
include_directories(SYSTEM ${LUA_INCLUDE_DIR})
|
include_directories(${LUA_INCLUDE_DIR})
|
||||||
|
|
||||||
find_package(EXPAT REQUIRED)
|
find_package(EXPAT REQUIRED)
|
||||||
include_directories(SYSTEM ${EXPAT_INCLUDE_DIRS})
|
include_directories(${EXPAT_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(osrm-extract ${EXPAT_LIBRARIES})
|
||||||
|
|
||||||
find_package(STXXL REQUIRED)
|
find_package(STXXL REQUIRED)
|
||||||
include_directories(SYSTEM ${STXXL_INCLUDE_DIR})
|
include_directories(${STXXL_INCLUDE_DIR})
|
||||||
|
target_link_libraries(OSRM ${STXXL_LIBRARY})
|
||||||
|
target_link_libraries(osrm-extract ${STXXL_LIBRARY})
|
||||||
|
target_link_libraries(osrm-prepare ${STXXL_LIBRARY})
|
||||||
|
|
||||||
set(OpenMP_FIND_QUIETLY ON)
|
set(OpenMP_FIND_QUIETLY ON)
|
||||||
find_package(OpenMP)
|
find_package(OpenMP)
|
||||||
@@ -270,141 +280,91 @@ if(OPENMP_FOUND)
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(OSMPBF REQUIRED)
|
||||||
|
include_directories(${OSMPBF_INCLUDE_DIR})
|
||||||
|
target_link_libraries(osrm-extract ${OSMPBF_LIBRARY})
|
||||||
|
target_link_libraries(osrm-prepare ${OSMPBF_LIBRARY})
|
||||||
|
|
||||||
|
find_package(Protobuf REQUIRED)
|
||||||
|
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(osrm-extract ${PROTOBUF_LIBRARY})
|
||||||
|
target_link_libraries(osrm-prepare ${PROTOBUF_LIBRARY})
|
||||||
|
|
||||||
find_package(BZip2 REQUIRED)
|
find_package(BZip2 REQUIRED)
|
||||||
include_directories(SYSTEM ${BZIP_INCLUDE_DIRS})
|
include_directories(${BZIP_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(osrm-extract ${BZIP2_LIBRARIES})
|
||||||
|
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
include_directories(SYSTEM ${ZLIB_INCLUDE_DIRS})
|
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(osrm-extract ${ZLIB_LIBRARY})
|
||||||
|
target_link_libraries(osrm-routed ${ZLIB_LIBRARY})
|
||||||
|
|
||||||
if (ENABLE_JSON_LOGGING)
|
if (ENABLE_JSON_LOGGING)
|
||||||
message(STATUS "Enabling json logging")
|
message(STATUS "Enabling json logging")
|
||||||
add_definitions(-DENABLE_JSON_LOGGING)
|
add_definitions(-DENABLE_JSON_LOGGING)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Binaries
|
if(WITH_TOOLS OR BUILD_TOOLS)
|
||||||
target_link_libraries(osrm-datastore osrm_store ${Boost_LIBRARIES})
|
|
||||||
target_link_libraries(osrm-extract osrm_extract ${Boost_LIBRARIES})
|
|
||||||
target_link_libraries(osrm-contract osrm_contract ${Boost_LIBRARIES})
|
|
||||||
target_link_libraries(osrm-routed osrm ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} ${ZLIB_LIBRARY})
|
|
||||||
|
|
||||||
set(EXTRACTOR_LIBRARIES
|
|
||||||
${BZIP2_LIBRARIES}
|
|
||||||
${Boost_LIBRARIES}
|
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
|
||||||
${EXPAT_LIBRARIES}
|
|
||||||
${LUABIND_LIBRARY}
|
|
||||||
${USED_LUA_LIBRARIES}
|
|
||||||
${OSMIUM_LIBRARIES}
|
|
||||||
${STXXL_LIBRARY}
|
|
||||||
${TBB_LIBRARIES}
|
|
||||||
${ZLIB_LIBRARY})
|
|
||||||
set(CONTRACTOR_LIBRARIES
|
|
||||||
${Boost_LIBRARIES}
|
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
|
||||||
${LUABIND_LIBRARY}
|
|
||||||
${USED_LUA_LIBRARIES}
|
|
||||||
${STXXL_LIBRARY}
|
|
||||||
${TBB_LIBRARIES}
|
|
||||||
${MAYBE_RT_LIBRARY})
|
|
||||||
set(ENGINE_LIBRARIES
|
|
||||||
${Boost_LIBRARIES}
|
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
|
||||||
${STXXL_LIBRARY}
|
|
||||||
${TBB_LIBRARIES}
|
|
||||||
${MAYBE_RT_LIBRARY})
|
|
||||||
set(STORAGE_LIBRARIES
|
|
||||||
${Boost_LIBRARIES}
|
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
|
||||||
${TBB_LIBRARIES}
|
|
||||||
${MAYBE_RT_LIBRARY})
|
|
||||||
set(UTIL_LIBRARIES
|
|
||||||
${Boost_LIBRARIES}
|
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
|
||||||
${STXXL_LIBRARY}
|
|
||||||
${TBB_LIBRARIES})
|
|
||||||
# Libraries
|
|
||||||
target_link_libraries(osrm ${ENGINE_LIBRARIES})
|
|
||||||
target_link_libraries(osrm_contract ${CONTRACTOR_LIBRARIES})
|
|
||||||
target_link_libraries(osrm_extract ${EXTRACTOR_LIBRARIES})
|
|
||||||
target_link_libraries(osrm_store ${STORAGE_LIBRARIES})
|
|
||||||
# Tests
|
|
||||||
target_link_libraries(engine-tests ${ENGINE_LIBRARIES})
|
|
||||||
target_link_libraries(server-tests osrm ${Boost_LIBRARIES})
|
|
||||||
target_link_libraries(extractor-tests ${EXTRACTOR_LIBRARIES})
|
|
||||||
target_link_libraries(rtree-bench ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${TBB_LIBRARIES})
|
|
||||||
target_link_libraries(util-tests ${UTIL_LIBRARIES})
|
|
||||||
|
|
||||||
if(BUILD_TOOLS)
|
|
||||||
message(STATUS "Activating OSRM internal tools")
|
message(STATUS "Activating OSRM internal tools")
|
||||||
find_package(GDAL)
|
find_package(GDAL)
|
||||||
if(GDAL_FOUND)
|
if(GDAL_FOUND)
|
||||||
add_executable(osrm-components src/tools/components.cpp $<TARGET_OBJECTS:UTIL>)
|
add_executable(osrm-components tools/components.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||||
target_link_libraries(osrm-components ${TBB_LIBRARIES})
|
target_link_libraries(osrm-components ${TBB_LIBRARIES})
|
||||||
include_directories(SYSTEM ${GDAL_INCLUDE_DIR})
|
include_directories(${GDAL_INCLUDE_DIR})
|
||||||
target_link_libraries(osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES})
|
target_link_libraries(
|
||||||
|
osrm-components
|
||||||
|
${GDAL_LIBRARIES} ${Boost_LIBRARIES})
|
||||||
install(TARGETS osrm-components DESTINATION bin)
|
install(TARGETS osrm-components DESTINATION bin)
|
||||||
else()
|
else()
|
||||||
message(WARNING "libgdal and/or development headers not found")
|
message(FATAL_ERROR "libgdal and/or development headers not found")
|
||||||
endif()
|
endif()
|
||||||
add_executable(osrm-io-benchmark src/tools/io-benchmark.cpp $<TARGET_OBJECTS:UTIL>)
|
add_executable(osrm-cli tools/simpleclient.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:COORDINATE>)
|
||||||
|
target_link_libraries(osrm-cli ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
|
||||||
|
target_link_libraries(osrm-cli ${TBB_LIBRARIES})
|
||||||
|
add_executable(osrm-io-benchmark tools/io-benchmark.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
|
||||||
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES})
|
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES})
|
||||||
add_executable(osrm-unlock-all src/tools/unlock_all_mutexes.cpp $<TARGET_OBJECTS:UTIL>)
|
add_executable(osrm-unlock-all tools/unlock_all_mutexes.cpp $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION>)
|
||||||
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
target_link_libraries(osrm-unlock-all rt)
|
target_link_libraries(osrm-unlock-all rt)
|
||||||
endif()
|
endif()
|
||||||
add_executable(osrm-springclean src/tools/springclean.cpp $<TARGET_OBJECTS:UTIL>)
|
add_executable(osrm-check-hsgr tools/check-hsgr.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:IMPORT>)
|
||||||
|
target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES} ${TBB_LIBRARIES})
|
||||||
|
add_executable(osrm-springclean tools/springclean.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:EXCEPTION>)
|
||||||
target_link_libraries(osrm-springclean ${Boost_LIBRARIES})
|
target_link_libraries(osrm-springclean ${Boost_LIBRARIES})
|
||||||
|
|
||||||
|
install(TARGETS osrm-cli DESTINATION bin)
|
||||||
install(TARGETS osrm-io-benchmark DESTINATION bin)
|
install(TARGETS osrm-io-benchmark DESTINATION bin)
|
||||||
install(TARGETS osrm-unlock-all DESTINATION bin)
|
install(TARGETS osrm-unlock-all DESTINATION bin)
|
||||||
|
install(TARGETS osrm-check-hsgr DESTINATION bin)
|
||||||
install(TARGETS osrm-springclean DESTINATION bin)
|
install(TARGETS osrm-springclean DESTINATION bin)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ENABLE_ASSERTIONS)
|
file(GLOB InstallGlob include/osrm/*.hpp library/osrm.hpp)
|
||||||
message(STATUS "Enabling assertions")
|
file(GLOB VariantGlob third_party/variant/*.hpp)
|
||||||
add_definitions(-DBOOST_ENABLE_ASSERT_HANDLER)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Add RPATH info to executables so that when they are run after being installed
|
# Add RPATH info to executables so that when they are run after being installed
|
||||||
# (i.e., from /usr/local/bin/) the linker can find library dependencies. For
|
# (i.e., from /usr/local/bin/) the linker can find library dependencies. For
|
||||||
# more info see http://www.cmake.org/Wiki/CMake_RPATH_handling
|
# more info see http://www.cmake.org/Wiki/CMake_RPATH_handling
|
||||||
set_property(TARGET osrm-extract PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
set_property(TARGET osrm-extract PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||||
set_property(TARGET osrm-contract PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
set_property(TARGET osrm-prepare PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||||
set_property(TARGET osrm-datastore PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
set_property(TARGET osrm-datastore PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||||
set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||||
|
|
||||||
file(GLOB VariantGlob third_party/variant/*.hpp)
|
install(FILES ${InstallGlob} DESTINATION include/osrm)
|
||||||
file(GLOB LibraryGlob include/osrm/*.hpp)
|
|
||||||
file(GLOB ParametersGlob include/engine/api/*_parameters.hpp)
|
|
||||||
set(EngineHeader include/engine/status.hpp include/engine/engine_config.hpp include/engine/hint.hpp include/engine/bearing.hpp include/engine/phantom_node.hpp)
|
|
||||||
set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp include/util/typedefs.hpp include/util/strong_typedef.hpp)
|
|
||||||
set(ExtractorHeader include/extractor/extractor.hpp include/extractor/extractor_config.hpp include/extractor/travel_mode.hpp)
|
|
||||||
set(ContractorHeader include/contractor/contractor.hpp include/contractor/contractor_config.hpp)
|
|
||||||
#set(StorageHeader include/storage/storage.hpp include/storage/storage_config.hpp)
|
|
||||||
install(FILES ${EngineHeader} DESTINATION include/osrm/engine)
|
|
||||||
install(FILES ${UtilHeader} DESTINATION include/osrm/util)
|
|
||||||
install(FILES ${ExtractorHeader} DESTINATION include/osrm/extractor)
|
|
||||||
install(FILES ${ContractorHeader} DESTINATION include/osrm/contractor)
|
|
||||||
install(FILES ${LibraryGlob} DESTINATION include/osrm)
|
|
||||||
install(FILES ${ParametersGlob} DESTINATION include/osrm/engine/api)
|
|
||||||
install(FILES ${VariantGlob} DESTINATION include/variant)
|
install(FILES ${VariantGlob} DESTINATION include/variant)
|
||||||
install(TARGETS osrm-extract DESTINATION bin)
|
install(TARGETS osrm-extract DESTINATION bin)
|
||||||
install(TARGETS osrm-contract DESTINATION bin)
|
install(TARGETS osrm-prepare DESTINATION bin)
|
||||||
install(TARGETS osrm-datastore DESTINATION bin)
|
install(TARGETS osrm-datastore DESTINATION bin)
|
||||||
install(TARGETS osrm-routed DESTINATION bin)
|
install(TARGETS osrm-routed DESTINATION bin)
|
||||||
install(TARGETS osrm DESTINATION lib)
|
install(TARGETS OSRM DESTINATION lib)
|
||||||
install(TARGETS osrm_extract DESTINATION lib)
|
list(GET Boost_LIBRARIES 1 BOOST_LIBRARY_FIRST)
|
||||||
install(TARGETS osrm_contract DESTINATION lib)
|
get_filename_component(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_FIRST}" PATH)
|
||||||
install(TARGETS osrm_store DESTINATION lib)
|
set(BOOST_LIBRARY_LISTING "-L${BOOST_LIBRARY_LISTING}")
|
||||||
|
foreach(lib ${Boost_LIBRARIES})
|
||||||
list(GET ENGINE_LIBRARIES 1 ENGINE_LIBRARY_FIRST)
|
get_filename_component(BOOST_LIBRARY_NAME "${lib}" NAME_WE)
|
||||||
foreach(lib ${ENGINE_LIBRARIES})
|
string(REPLACE "lib" "" BOOST_LIBRARY_NAME ${BOOST_LIBRARY_NAME})
|
||||||
get_filename_component(ENGINE_LIBRARY_PATH "${ENGINE_LIBRARY_FIRST}" PATH)
|
set(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_LISTING} -l${BOOST_LIBRARY_NAME}")
|
||||||
get_filename_component(ENGINE_LIBRARY_NAME "${lib}" NAME_WE)
|
|
||||||
string(REPLACE "lib" "" ENGINE_LIBRARY_NAME ${ENGINE_LIBRARY_NAME})
|
|
||||||
string(REPLACE "-l" "" ENGINE_LIBRARY_NAME ${ENGINE_LIBRARY_NAME})
|
|
||||||
set(ENGINE_LIBRARY_LISTING "${ENGINE_LIBRARY_LISTING} -L${ENGINE_LIBRARY_PATH} -l${ENGINE_LIBRARY_NAME}")
|
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
|
||||||
@@ -414,34 +374,3 @@ if(BUILD_DEBIAN_PACKAGE)
|
|||||||
include(CPackDebianConfig)
|
include(CPackDebianConfig)
|
||||||
include(CPack)
|
include(CPack)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# add a target to generate API documentation with Doxygen
|
|
||||||
find_package(Doxygen)
|
|
||||||
if(DOXYGEN_FOUND)
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
|
|
||||||
add_custom_target(doc
|
|
||||||
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
COMMENT "Generating API documentation with Doxygen" VERBATIM
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# 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"))
|
|
||||||
find_program(CCACHE_FOUND ccache)
|
|
||||||
if(CCACHE_FOUND)
|
|
||||||
message(STATUS "Using ccache to speed up incremental builds")
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
|
||||||
set(ENV{CCACHE_CPP2} "true")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# uninstall target
|
|
||||||
configure_file(
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake"
|
|
||||||
IMMEDIATE @ONLY)
|
|
||||||
|
|
||||||
add_custom_target(uninstall
|
|
||||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake)
|
|
||||||
|
|||||||
-43
@@ -1,43 +0,0 @@
|
|||||||
PROJECT_NAME = "Project OSRM"
|
|
||||||
PROJECT_BRIEF = "Open Source Routing Machine"
|
|
||||||
BUILTIN_STL_SUPPORT = YES
|
|
||||||
|
|
||||||
EXTRACT_ALL = YES
|
|
||||||
EXTRACT_PRIVATE = YES
|
|
||||||
EXTRACT_PACKAGE = YES
|
|
||||||
EXTRACT_STATIC = YES
|
|
||||||
EXTRACT_LOCAL_CLASSES = YES
|
|
||||||
EXTRACT_ANON_NSPACES = YES
|
|
||||||
|
|
||||||
QUIET = YES
|
|
||||||
|
|
||||||
INPUT = @CMAKE_CURRENT_SOURCE_DIR@
|
|
||||||
USE_MDFILE_AS_MAINPAGE = @CMAKE_CURRENT_SOURCE_DIR@/README.md
|
|
||||||
FILE_PATTERNS = *.h *.hpp *.c *.cc *.cpp *.md
|
|
||||||
RECURSIVE = YES
|
|
||||||
|
|
||||||
EXCLUDE = @CMAKE_CURRENT_SOURCE_DIR@/third_party \
|
|
||||||
@CMAKE_CURRENT_SOURCE_DIR@/build \
|
|
||||||
@CMAKE_CURRENT_SOURCE_DIR@/unit_tests \
|
|
||||||
@CMAKE_CURRENT_SOURCE_DIR@/benchmarks \
|
|
||||||
@CMAKE_CURRENT_SOURCE_DIR@/features
|
|
||||||
|
|
||||||
SOURCE_BROWSER = YES
|
|
||||||
|
|
||||||
CLANG_ASSISTED_PARSING = NO
|
|
||||||
|
|
||||||
HTML_COLORSTYLE_HUE = 217
|
|
||||||
HTML_COLORSTYLE_SAT = 71
|
|
||||||
HTML_COLORSTYLE_GAMMA = 50
|
|
||||||
|
|
||||||
GENERATE_TREEVIEW = YES
|
|
||||||
|
|
||||||
HAVE_DOT = @DOXYGEN_DOT_FOUND@
|
|
||||||
CALL_GRAPH = YES
|
|
||||||
CALLER_GRAPH = YES
|
|
||||||
|
|
||||||
DOT_IMAGE_FORMAT = svg
|
|
||||||
INTERACTIVE_SVG = YES
|
|
||||||
DOT_GRAPH_MAX_NODES = 500
|
|
||||||
DOT_TRANSPARENT = YES
|
|
||||||
DOT_MULTI_TARGETS = YES
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2016, Project OSRM contributors
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ task :crop do
|
|||||||
end
|
end
|
||||||
|
|
||||||
desc "Reprocess OSM data."
|
desc "Reprocess OSM data."
|
||||||
task :process => [:extract,:contract] do
|
task :process => [:extract,:prepare] do
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Extract OSM data."
|
desc "Extract OSM data."
|
||||||
@@ -108,10 +108,10 @@ task :extract do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Contract OSM data."
|
desc "Prepare OSM data."
|
||||||
task :contract do
|
task :prepare do
|
||||||
Dir.chdir DATA_FOLDER do
|
Dir.chdir DATA_FOLDER do
|
||||||
raise "Error while contracting data." unless system "../#{BUILD_FOLDER}/osrm-contract #{osm_data_area_name}.osrm"
|
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm --profile ../profiles/#{PROFILE}.lua"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -161,17 +161,17 @@ task :down do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Kill all osrm-extract, osrm-contract and osrm-routed processes."
|
desc "Kill all osrm-extract, osrm-prepare and osrm-routed processes."
|
||||||
task :kill do
|
task :kill do
|
||||||
each_process('osrm-routed') { |pid,state| Process.kill 'KILL', pid }
|
each_process('osrm-routed') { |pid,state| Process.kill 'KILL', pid }
|
||||||
each_process('osrm-contract') { |pid,state| Process.kill 'KILL', pid }
|
each_process('osrm-prepare') { |pid,state| Process.kill 'KILL', pid }
|
||||||
each_process('osrm-extract') { |pid,state| Process.kill 'KILL', pid }
|
each_process('osrm-extract') { |pid,state| Process.kill 'KILL', pid }
|
||||||
wait_for_shutdown 'osrm-routed'
|
wait_for_shutdown 'osrm-routed'
|
||||||
wait_for_shutdown 'osrm-contract'
|
wait_for_shutdown 'osrm-prepare'
|
||||||
wait_for_shutdown 'osrm-extract'
|
wait_for_shutdown 'osrm-extract'
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Get PIDs of all osrm-extract, osrm-contract and osrm-routed processes."
|
desc "Get PIDs of all osrm-extract, osrm-prepare and osrm-routed processes."
|
||||||
task :pid do
|
task :pid do
|
||||||
each_process 'osrm-routed' do |pid,state|
|
each_process 'osrm-routed' do |pid,state|
|
||||||
puts "#{pid}\t#{state}"
|
puts "#{pid}\t#{state}"
|
||||||
|
|||||||
+34
-22
@@ -1,19 +1,36 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef BAYES_CLASSIFIER_HPP
|
#ifndef BAYES_CLASSIFIER_HPP
|
||||||
#define BAYES_CLASSIFIER_HPP
|
#define BAYES_CLASSIFIER_HPP
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include <boost/math/constants/constants.hpp>
|
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace engine
|
|
||||||
{
|
|
||||||
namespace map_matching
|
|
||||||
{
|
|
||||||
|
|
||||||
struct NormalDistribution
|
struct NormalDistribution
|
||||||
{
|
{
|
||||||
@@ -22,13 +39,11 @@ struct NormalDistribution
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME implement log-probability version since it's faster
|
// FIXME implement log-probability version since its faster
|
||||||
double density_function(const double val) const
|
double density_function(const double val) const
|
||||||
{
|
{
|
||||||
using namespace boost::math::constants;
|
|
||||||
|
|
||||||
const double x = val - mean;
|
const double x = val - mean;
|
||||||
return 1.0 / (std::sqrt(two_pi<double>()) * standard_deviation) *
|
return 1.0 / (std::sqrt(2. * M_PI) * standard_deviation) *
|
||||||
std::exp(-x * x / (standard_deviation * standard_deviation));
|
std::exp(-x * x / (standard_deviation * standard_deviation));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +58,7 @@ struct LaplaceDistribution
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME implement log-probability version since it's faster
|
// FIXME implement log-probability version since its faster
|
||||||
double density_function(const double val) const
|
double density_function(const double val) const
|
||||||
{
|
{
|
||||||
const double x = std::abs(val - location);
|
const double x = std::abs(val - location);
|
||||||
@@ -65,11 +80,11 @@ class BayesClassifier
|
|||||||
};
|
};
|
||||||
using ClassificationT = std::pair<ClassLabel, double>;
|
using ClassificationT = std::pair<ClassLabel, double>;
|
||||||
|
|
||||||
BayesClassifier(PositiveDistributionT positive_distribution,
|
BayesClassifier(const PositiveDistributionT &positive_distribution,
|
||||||
NegativeDistributionT negative_distribution,
|
const NegativeDistributionT &negative_distribution,
|
||||||
const double positive_apriori_probability)
|
const double positive_apriori_probability)
|
||||||
: positive_distribution(std::move(positive_distribution)),
|
: positive_distribution(positive_distribution),
|
||||||
negative_distribution(std::move(negative_distribution)),
|
negative_distribution(negative_distribution),
|
||||||
positive_apriori_probability(positive_apriori_probability),
|
positive_apriori_probability(positive_apriori_probability),
|
||||||
negative_apriori_probability(1. - positive_apriori_probability)
|
negative_apriori_probability(1. - positive_apriori_probability)
|
||||||
{
|
{
|
||||||
@@ -98,8 +113,5 @@ class BayesClassifier
|
|||||||
double positive_apriori_probability;
|
double positive_apriori_probability;
|
||||||
double negative_apriori_probability;
|
double negative_apriori_probability;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // BAYES_CLASSIFIER_HPP
|
#endif // BAYES_CLASSIFIER_HPP
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BFS_COMPONENTS_HPP_
|
||||||
|
#define BFS_COMPONENTS_HPP_
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "../data_structures/restriction_map.hpp"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
// Explores the components of the given graph while respecting turn restrictions
|
||||||
|
// and barriers.
|
||||||
|
template <typename GraphT> class BFSComponentExplorer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BFSComponentExplorer(const GraphT &dynamic_graph,
|
||||||
|
const RestrictionMap &restrictions,
|
||||||
|
const std::unordered_set<NodeID> &barrier_nodes)
|
||||||
|
: m_graph(dynamic_graph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the size of the component that the node belongs to.
|
||||||
|
*/
|
||||||
|
unsigned int GetComponentSize(const NodeID node) const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(node < m_component_index_list.size());
|
||||||
|
|
||||||
|
return m_component_index_size[m_component_index_list[node]];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int GetNumberOfComponents() { return m_component_index_size.size(); }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Computes the component sizes.
|
||||||
|
*/
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
std::queue<std::pair<NodeID, NodeID>> bfs_queue;
|
||||||
|
unsigned current_component = 0;
|
||||||
|
|
||||||
|
BOOST_ASSERT(m_component_index_list.empty());
|
||||||
|
BOOST_ASSERT(m_component_index_size.empty());
|
||||||
|
|
||||||
|
unsigned num_nodes = m_graph.GetNumberOfNodes();
|
||||||
|
|
||||||
|
m_component_index_list.resize(num_nodes, std::numeric_limits<unsigned>::max());
|
||||||
|
|
||||||
|
BOOST_ASSERT(num_nodes > 0);
|
||||||
|
|
||||||
|
// put unexplorered node with parent pointer into queue
|
||||||
|
for (NodeID node = 0; node < num_nodes; ++node)
|
||||||
|
{
|
||||||
|
if (std::numeric_limits<unsigned>::max() == m_component_index_list[node])
|
||||||
|
{
|
||||||
|
unsigned size = ExploreComponent(bfs_queue, node, current_component);
|
||||||
|
|
||||||
|
// push size into vector
|
||||||
|
m_component_index_size.emplace_back(size);
|
||||||
|
++current_component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*!
|
||||||
|
* Explores the current component that starts at node using BFS.
|
||||||
|
*/
|
||||||
|
unsigned ExploreComponent(std::queue<std::pair<NodeID, NodeID>> &bfs_queue,
|
||||||
|
NodeID node,
|
||||||
|
unsigned current_component)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Graphical representation of variables:
|
||||||
|
|
||||||
|
u v w
|
||||||
|
*---------->*---------->*
|
||||||
|
e2
|
||||||
|
*/
|
||||||
|
|
||||||
|
bfs_queue.emplace(node, node);
|
||||||
|
// mark node as read
|
||||||
|
m_component_index_list[node] = current_component;
|
||||||
|
|
||||||
|
unsigned current_component_size = 1;
|
||||||
|
|
||||||
|
while (!bfs_queue.empty())
|
||||||
|
{
|
||||||
|
// fetch element from BFS queue
|
||||||
|
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
|
||||||
|
bfs_queue.pop();
|
||||||
|
|
||||||
|
const NodeID v = current_queue_item.first; // current node
|
||||||
|
const NodeID u = current_queue_item.second; // parent
|
||||||
|
// increment size counter of current component
|
||||||
|
++current_component_size;
|
||||||
|
if (m_barrier_nodes.find(v) != m_barrier_nodes.end())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const NodeID to_node_of_only_restriction =
|
||||||
|
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
|
||||||
|
|
||||||
|
for (auto e2 : m_graph.GetAdjacentEdgeRange(v))
|
||||||
|
{
|
||||||
|
const NodeID w = m_graph.GetTarget(e2);
|
||||||
|
|
||||||
|
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
|
||||||
|
w != to_node_of_only_restriction)
|
||||||
|
{
|
||||||
|
// At an only_-restriction but not at the right turn
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u != w)
|
||||||
|
{
|
||||||
|
// only add an edge if turn is not a U-turn except
|
||||||
|
// when it is at the end of a dead-end street.
|
||||||
|
if (!m_restriction_map.CheckIfTurnIsRestricted(u, v, w))
|
||||||
|
{
|
||||||
|
// only add an edge if turn is not prohibited
|
||||||
|
if (std::numeric_limits<unsigned>::max() == m_component_index_list[w])
|
||||||
|
{
|
||||||
|
// insert next (node, parent) only if w has
|
||||||
|
// not yet been explored
|
||||||
|
// mark node as read
|
||||||
|
m_component_index_list[w] = current_component;
|
||||||
|
bfs_queue.emplace(w, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return current_component_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned> m_component_index_list;
|
||||||
|
std::vector<NodeID> m_component_index_size;
|
||||||
|
|
||||||
|
const GraphT &m_graph;
|
||||||
|
const RestrictionMap &m_restriction_map;
|
||||||
|
const std::unordered_set<NodeID> &m_barrier_nodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BFS_COMPONENTS_HPP_
|
||||||
@@ -1,3 +1,30 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef ITERATOR_BASED_CRC32_H
|
#ifndef ITERATOR_BASED_CRC32_H
|
||||||
#define ITERATOR_BASED_CRC32_H
|
#define ITERATOR_BASED_CRC32_H
|
||||||
|
|
||||||
@@ -9,11 +36,6 @@
|
|||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace contractor
|
|
||||||
{
|
|
||||||
|
|
||||||
class IteratorbasedCRC32
|
class IteratorbasedCRC32
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -119,7 +141,5 @@ struct RangebasedCRC32
|
|||||||
private:
|
private:
|
||||||
IteratorbasedCRC32 crc32;
|
IteratorbasedCRC32 crc32;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* ITERATOR_BASED_CRC32_H */
|
#endif /* ITERATOR_BASED_CRC32_H */
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "douglas_peucker.hpp"
|
||||||
|
|
||||||
|
#include "../data_structures/segment_information.hpp"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct CoordinatePairCalculator
|
||||||
|
{
|
||||||
|
CoordinatePairCalculator() = delete;
|
||||||
|
CoordinatePairCalculator(const FixedPointCoordinate &coordinate_a,
|
||||||
|
const FixedPointCoordinate &coordinate_b)
|
||||||
|
{
|
||||||
|
// initialize distance calculator with two fixed coordinates a, b
|
||||||
|
const float RAD = 0.017453292519943295769236907684886f;
|
||||||
|
first_lat = (coordinate_a.lat / COORDINATE_PRECISION) * RAD;
|
||||||
|
first_lon = (coordinate_a.lon / COORDINATE_PRECISION) * RAD;
|
||||||
|
second_lat = (coordinate_b.lat / COORDINATE_PRECISION) * RAD;
|
||||||
|
second_lon = (coordinate_b.lon / COORDINATE_PRECISION) * RAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
int operator()(FixedPointCoordinate &other) const
|
||||||
|
{
|
||||||
|
// set third coordinate c
|
||||||
|
const float RAD = 0.017453292519943295769236907684886f;
|
||||||
|
const float earth_radius = 6372797.560856f;
|
||||||
|
const float float_lat1 = (other.lat / COORDINATE_PRECISION) * RAD;
|
||||||
|
const float float_lon1 = (other.lon / COORDINATE_PRECISION) * RAD;
|
||||||
|
|
||||||
|
// compute distance (a,c)
|
||||||
|
const float x_value_1 = (first_lon - float_lon1) * cos((float_lat1 + first_lat) / 2.f);
|
||||||
|
const float y_value_1 = first_lat - float_lat1;
|
||||||
|
const float dist1 = std::hypot(x_value_1, y_value_1) * earth_radius;
|
||||||
|
|
||||||
|
// compute distance (b,c)
|
||||||
|
const float x_value_2 = (second_lon - float_lon1) * cos((float_lat1 + second_lat) / 2.f);
|
||||||
|
const float y_value_2 = second_lat - float_lat1;
|
||||||
|
const float dist2 = std::hypot(x_value_2, y_value_2) * earth_radius;
|
||||||
|
|
||||||
|
// return the minimum
|
||||||
|
return static_cast<int>(std::min(dist1, dist2));
|
||||||
|
}
|
||||||
|
|
||||||
|
float first_lat;
|
||||||
|
float first_lon;
|
||||||
|
float second_lat;
|
||||||
|
float second_lon;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
|
||||||
|
{
|
||||||
|
Run(std::begin(input_geometry), std::end(input_geometry), zoom_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level)
|
||||||
|
{
|
||||||
|
const auto size = std::distance(begin, end);
|
||||||
|
if (size < 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
begin->necessary = true;
|
||||||
|
std::prev(end)->necessary = true;
|
||||||
|
|
||||||
|
{
|
||||||
|
BOOST_ASSERT_MSG(zoom_level < DOUGLAS_PEUCKER_THRESHOLDS.size(), "unsupported zoom level");
|
||||||
|
RandomAccessIt left_border = begin;
|
||||||
|
RandomAccessIt right_border = std::next(begin);
|
||||||
|
// Sweep over array and identify those ranges that need to be checked
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// traverse list until new border element found
|
||||||
|
if (right_border->necessary)
|
||||||
|
{
|
||||||
|
// sanity checks
|
||||||
|
BOOST_ASSERT(left_border->necessary);
|
||||||
|
BOOST_ASSERT(right_border->necessary);
|
||||||
|
recursion_stack.emplace(left_border, right_border);
|
||||||
|
left_border = right_border;
|
||||||
|
}
|
||||||
|
++right_border;
|
||||||
|
} while (right_border != end);
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark locations as 'necessary' by divide-and-conquer
|
||||||
|
while (!recursion_stack.empty())
|
||||||
|
{
|
||||||
|
// pop next element
|
||||||
|
const GeometryRange pair = recursion_stack.top();
|
||||||
|
recursion_stack.pop();
|
||||||
|
// sanity checks
|
||||||
|
BOOST_ASSERT_MSG(pair.first->necessary, "left border must be necessary");
|
||||||
|
BOOST_ASSERT_MSG(pair.second->necessary, "right border must be necessary");
|
||||||
|
BOOST_ASSERT_MSG(std::distance(pair.second, end) > 0, "right border outside of geometry");
|
||||||
|
BOOST_ASSERT_MSG(std::distance(pair.first, pair.second) >= 0,
|
||||||
|
"left border on the wrong side");
|
||||||
|
|
||||||
|
int max_int_distance = 0;
|
||||||
|
auto farthest_entry_it = pair.second;
|
||||||
|
const CoordinatePairCalculator dist_calc(pair.first->location, pair.second->location);
|
||||||
|
|
||||||
|
// sweep over range to find the maximum
|
||||||
|
for (auto it = std::next(pair.first); it != pair.second; ++it)
|
||||||
|
{
|
||||||
|
const int distance = dist_calc(it->location);
|
||||||
|
// found new feasible maximum?
|
||||||
|
if (distance > max_int_distance && distance > DOUGLAS_PEUCKER_THRESHOLDS[zoom_level])
|
||||||
|
{
|
||||||
|
farthest_entry_it = it;
|
||||||
|
max_int_distance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if maximum violates a zoom level dependent threshold
|
||||||
|
if (max_int_distance > DOUGLAS_PEUCKER_THRESHOLDS[zoom_level])
|
||||||
|
{
|
||||||
|
// mark idx as necessary
|
||||||
|
farthest_entry_it->necessary = true;
|
||||||
|
if (1 < std::distance(pair.first, farthest_entry_it))
|
||||||
|
{
|
||||||
|
recursion_stack.emplace(pair.first, farthest_entry_it);
|
||||||
|
}
|
||||||
|
if (1 < std::distance(farthest_entry_it, pair.second))
|
||||||
|
{
|
||||||
|
recursion_stack.emplace(farthest_entry_it, pair.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DOUGLAS_PEUCKER_HPP_
|
||||||
|
#define DOUGLAS_PEUCKER_HPP_
|
||||||
|
|
||||||
|
#include "../data_structures/segment_information.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <stack>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/* This class object computes the bitvector of indicating generalized input
|
||||||
|
* points according to the (Ramer-)Douglas-Peucker algorithm.
|
||||||
|
*
|
||||||
|
* Input is vector of pairs. Each pair consists of the point information and a
|
||||||
|
* bit indicating if the points is present in the generalization.
|
||||||
|
* Note: points may also be pre-selected*/
|
||||||
|
|
||||||
|
static const std::array<int, 19> DOUGLAS_PEUCKER_THRESHOLDS{{
|
||||||
|
512440, // z0
|
||||||
|
256720, // z1
|
||||||
|
122560, // z2
|
||||||
|
56780, // z3
|
||||||
|
28800, // z4
|
||||||
|
14400, // z5
|
||||||
|
7200, // z6
|
||||||
|
3200, // z7
|
||||||
|
2400, // z8
|
||||||
|
1000, // z9
|
||||||
|
600, // z10
|
||||||
|
120, // z11
|
||||||
|
60, // z12
|
||||||
|
45, // z13
|
||||||
|
36, // z14
|
||||||
|
20, // z15
|
||||||
|
8, // z16
|
||||||
|
6, // z17
|
||||||
|
4 // z18
|
||||||
|
}};
|
||||||
|
|
||||||
|
class DouglasPeucker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using RandomAccessIt = std::vector<SegmentInformation>::iterator;
|
||||||
|
|
||||||
|
using GeometryRange = std::pair<RandomAccessIt, RandomAccessIt>;
|
||||||
|
// Stack to simulate the recursion
|
||||||
|
std::stack<GeometryRange> recursion_stack;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level);
|
||||||
|
void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* DOUGLAS_PEUCKER_HPP_ */
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OBJECT_ENCODER_HPP
|
||||||
|
#define OBJECT_ENCODER_HPP
|
||||||
|
|
||||||
|
#include "../util/string_util.hpp"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||||
|
#include <boost/archive/iterators/binary_from_base64.hpp>
|
||||||
|
#include <boost/archive/iterators/transform_width.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct ObjectEncoder
|
||||||
|
{
|
||||||
|
using base64_t = boost::archive::iterators::base64_from_binary<
|
||||||
|
boost::archive::iterators::transform_width<const char *, 6, 8>>;
|
||||||
|
|
||||||
|
using binary_t = boost::archive::iterators::transform_width<
|
||||||
|
boost::archive::iterators::binary_from_base64<std::string::const_iterator>,
|
||||||
|
8,
|
||||||
|
6>;
|
||||||
|
|
||||||
|
template <class ObjectT> static void EncodeToBase64(const ObjectT &object, std::string &encoded)
|
||||||
|
{
|
||||||
|
const char *char_ptr_to_object = reinterpret_cast<const char *>(&object);
|
||||||
|
std::vector<unsigned char> data(sizeof(object));
|
||||||
|
std::copy(char_ptr_to_object, char_ptr_to_object + sizeof(ObjectT), data.begin());
|
||||||
|
|
||||||
|
unsigned char number_of_padded_chars = 0; // is in {0,1,2};
|
||||||
|
while (data.size() % 3 != 0)
|
||||||
|
{
|
||||||
|
++number_of_padded_chars;
|
||||||
|
data.push_back(0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(0 == data.size() % 3, "base64 input data size is not a multiple of 3!");
|
||||||
|
encoded.resize(sizeof(ObjectT));
|
||||||
|
encoded.assign(base64_t(&data[0]),
|
||||||
|
base64_t(&data[0] + (data.size() - number_of_padded_chars)));
|
||||||
|
replaceAll(encoded, "+", "-");
|
||||||
|
replaceAll(encoded, "/", "_");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ObjectT> static void DecodeFromBase64(const std::string &input, ObjectT &object)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::string encoded(input);
|
||||||
|
// replace "-" with "+" and "_" with "/"
|
||||||
|
replaceAll(encoded, "-", "+");
|
||||||
|
replaceAll(encoded, "_", "/");
|
||||||
|
|
||||||
|
std::copy(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1),
|
||||||
|
reinterpret_cast<char *>(&object));
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* OBJECT_ENCODER_HPP */
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "polyline_compressor.hpp"
|
||||||
|
#include "../data_structures/segment_information.hpp"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
std::string PolylineCompressor::encode_vector(std::vector<int> &numbers) const
|
||||||
|
{
|
||||||
|
std::string output;
|
||||||
|
const auto end = numbers.size();
|
||||||
|
for (std::size_t i = 0; i < end; ++i)
|
||||||
|
{
|
||||||
|
numbers[i] <<= 1;
|
||||||
|
if (numbers[i] < 0)
|
||||||
|
{
|
||||||
|
numbers[i] = ~(numbers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const int number : numbers)
|
||||||
|
{
|
||||||
|
output += encode_number(number);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PolylineCompressor::encode_number(int number_to_encode) const
|
||||||
|
{
|
||||||
|
std::string output;
|
||||||
|
while (number_to_encode >= 0x20)
|
||||||
|
{
|
||||||
|
const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
|
||||||
|
output += static_cast<char>(next_value);
|
||||||
|
number_to_encode >>= 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
number_to_encode += 63;
|
||||||
|
output += static_cast<char>(number_to_encode);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
PolylineCompressor::get_encoded_string(const std::vector<SegmentInformation> &polyline) const
|
||||||
|
{
|
||||||
|
if (polyline.empty())
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> delta_numbers;
|
||||||
|
delta_numbers.reserve((polyline.size() - 1) * 2);
|
||||||
|
FixedPointCoordinate previous_coordinate = {0, 0};
|
||||||
|
for (const auto &segment : polyline)
|
||||||
|
{
|
||||||
|
if (segment.necessary)
|
||||||
|
{
|
||||||
|
const int lat_diff = segment.location.lat - previous_coordinate.lat;
|
||||||
|
const int lon_diff = segment.location.lon - previous_coordinate.lon;
|
||||||
|
delta_numbers.emplace_back(lat_diff);
|
||||||
|
delta_numbers.emplace_back(lon_diff);
|
||||||
|
previous_coordinate = segment.location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return encode_vector(delta_numbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<FixedPointCoordinate> PolylineCompressor::decode_string(const std::string &geometry_string) const
|
||||||
|
{
|
||||||
|
std::vector<FixedPointCoordinate> new_coordinates;
|
||||||
|
int index = 0, len = geometry_string.size();
|
||||||
|
int lat = 0, lng = 0;
|
||||||
|
|
||||||
|
while (index < len)
|
||||||
|
{
|
||||||
|
int b, shift = 0, result = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
b = geometry_string.at(index++) - 63;
|
||||||
|
result |= (b & 0x1f) << shift;
|
||||||
|
shift += 5;
|
||||||
|
} while (b >= 0x20);
|
||||||
|
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
|
||||||
|
lat += dlat;
|
||||||
|
|
||||||
|
shift = 0;
|
||||||
|
result = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
b = geometry_string.at(index++) - 63;
|
||||||
|
result |= (b & 0x1f) << shift;
|
||||||
|
shift += 5;
|
||||||
|
} while (b >= 0x20);
|
||||||
|
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
|
||||||
|
lng += dlng;
|
||||||
|
|
||||||
|
FixedPointCoordinate p;
|
||||||
|
p.lat = COORDINATE_PRECISION * (((double) lat / 1E6));
|
||||||
|
p.lon = COORDINATE_PRECISION * (((double) lng / 1E6));
|
||||||
|
new_coordinates.push_back(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_coordinates;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef POLYLINECOMPRESSOR_H_
|
||||||
|
#define POLYLINECOMPRESSOR_H_
|
||||||
|
|
||||||
|
struct SegmentInformation;
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class PolylineCompressor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string encode_vector(std::vector<int> &numbers) const;
|
||||||
|
|
||||||
|
std::string encode_number(const int number_to_encode) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string get_encoded_string(const std::vector<SegmentInformation> &polyline) const;
|
||||||
|
|
||||||
|
std::vector<FixedPointCoordinate> decode_string(const std::string &geometry_string) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* POLYLINECOMPRESSOR_H_ */
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "polyline_formatter.hpp"
|
||||||
|
|
||||||
|
#include "polyline_compressor.hpp"
|
||||||
|
#include "../data_structures/segment_information.hpp"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
osrm::json::String
|
||||||
|
PolylineFormatter::printEncodedString(const std::vector<SegmentInformation> &polyline) const
|
||||||
|
{
|
||||||
|
return osrm::json::String(PolylineCompressor().get_encoded_string(polyline));
|
||||||
|
}
|
||||||
|
|
||||||
|
osrm::json::Array
|
||||||
|
PolylineFormatter::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
|
||||||
|
{
|
||||||
|
osrm::json::Array json_geometry_array;
|
||||||
|
for (const auto &segment : polyline)
|
||||||
|
{
|
||||||
|
if (segment.necessary)
|
||||||
|
{
|
||||||
|
osrm::json::Array json_coordinate;
|
||||||
|
json_coordinate.values.push_back(segment.location.lat / COORDINATE_PRECISION);
|
||||||
|
json_coordinate.values.push_back(segment.location.lon / COORDINATE_PRECISION);
|
||||||
|
json_geometry_array.values.push_back(json_coordinate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return json_geometry_array;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef POLYLINE_FORMATTER_HPP
|
||||||
|
#define POLYLINE_FORMATTER_HPP
|
||||||
|
|
||||||
|
struct SegmentInformation;
|
||||||
|
|
||||||
|
#include <osrm/json_container.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct PolylineFormatter
|
||||||
|
{
|
||||||
|
osrm::json::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||||
|
|
||||||
|
osrm::json::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* POLYLINE_FORMATTER_HPP */
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXTRACT_ROUTE_NAMES_H
|
||||||
|
#define EXTRACT_ROUTE_NAMES_H
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct RouteNames
|
||||||
|
{
|
||||||
|
std::string shortest_path_name_1;
|
||||||
|
std::string shortest_path_name_2;
|
||||||
|
std::string alternative_path_name_1;
|
||||||
|
std::string alternative_path_name_2;
|
||||||
|
};
|
||||||
|
|
||||||
|
// construct routes names
|
||||||
|
template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SegmentT PickNextLongestSegment(const std::vector<SegmentT> &segment_list,
|
||||||
|
const unsigned blocked_name_id) const
|
||||||
|
{
|
||||||
|
SegmentT result_segment;
|
||||||
|
result_segment.length = 0;
|
||||||
|
|
||||||
|
for (const SegmentT &segment : segment_list)
|
||||||
|
{
|
||||||
|
if (segment.name_id != blocked_name_id && segment.length > result_segment.length &&
|
||||||
|
segment.name_id != 0)
|
||||||
|
{
|
||||||
|
result_segment = segment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result_segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
RouteNames operator()(std::vector<SegmentT> &shortest_path_segments,
|
||||||
|
std::vector<SegmentT> &alternative_path_segments,
|
||||||
|
const DataFacadeT *facade) const
|
||||||
|
{
|
||||||
|
RouteNames route_names;
|
||||||
|
|
||||||
|
SegmentT shortest_segment_1, shortest_segment_2;
|
||||||
|
SegmentT alternative_segment_1, alternative_segment_2;
|
||||||
|
|
||||||
|
auto length_comperator = [](const SegmentT &a, const SegmentT &b)
|
||||||
|
{
|
||||||
|
return a.length > b.length;
|
||||||
|
};
|
||||||
|
auto name_id_comperator = [](const SegmentT &a, const SegmentT &b)
|
||||||
|
{
|
||||||
|
return a.name_id < b.name_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (shortest_path_segments.empty())
|
||||||
|
{
|
||||||
|
return route_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pick the longest segment for the shortest path.
|
||||||
|
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator);
|
||||||
|
shortest_segment_1 = shortest_path_segments[0];
|
||||||
|
if (!alternative_path_segments.empty())
|
||||||
|
{
|
||||||
|
std::sort(alternative_path_segments.begin(), alternative_path_segments.end(),
|
||||||
|
length_comperator);
|
||||||
|
|
||||||
|
// also pick the longest segment for the alternative path
|
||||||
|
alternative_segment_1 = alternative_path_segments[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute the set difference (for shortest path) depending on names between shortest and
|
||||||
|
// alternative
|
||||||
|
std::vector<SegmentT> shortest_path_set_difference(shortest_path_segments.size());
|
||||||
|
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), name_id_comperator);
|
||||||
|
std::sort(alternative_path_segments.begin(), alternative_path_segments.end(),
|
||||||
|
name_id_comperator);
|
||||||
|
std::set_difference(shortest_path_segments.begin(), shortest_path_segments.end(),
|
||||||
|
alternative_path_segments.begin(), alternative_path_segments.end(),
|
||||||
|
shortest_path_set_difference.begin(), name_id_comperator);
|
||||||
|
|
||||||
|
std::sort(shortest_path_set_difference.begin(), shortest_path_set_difference.end(),
|
||||||
|
length_comperator);
|
||||||
|
shortest_segment_2 =
|
||||||
|
PickNextLongestSegment(shortest_path_set_difference, shortest_segment_1.name_id);
|
||||||
|
|
||||||
|
// compute the set difference (for alternative path) depending on names between shortest and
|
||||||
|
// alternative
|
||||||
|
// vectors are still sorted, no need to do again
|
||||||
|
BOOST_ASSERT(std::is_sorted(shortest_path_segments.begin(), shortest_path_segments.end(),
|
||||||
|
name_id_comperator));
|
||||||
|
BOOST_ASSERT(std::is_sorted(alternative_path_segments.begin(),
|
||||||
|
alternative_path_segments.end(), name_id_comperator));
|
||||||
|
|
||||||
|
std::vector<SegmentT> alternative_path_set_difference(alternative_path_segments.size());
|
||||||
|
std::set_difference(alternative_path_segments.begin(), alternative_path_segments.end(),
|
||||||
|
shortest_path_segments.begin(), shortest_path_segments.end(),
|
||||||
|
alternative_path_set_difference.begin(), name_id_comperator);
|
||||||
|
|
||||||
|
std::sort(alternative_path_set_difference.begin(), alternative_path_set_difference.end(),
|
||||||
|
length_comperator);
|
||||||
|
|
||||||
|
if (!alternative_path_segments.empty())
|
||||||
|
{
|
||||||
|
alternative_segment_2 = PickNextLongestSegment(alternative_path_set_difference,
|
||||||
|
alternative_segment_1.name_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// move the segments into the order in which they occur.
|
||||||
|
if (shortest_segment_1.position > shortest_segment_2.position)
|
||||||
|
{
|
||||||
|
std::swap(shortest_segment_1, shortest_segment_2);
|
||||||
|
}
|
||||||
|
if (alternative_segment_1.position > alternative_segment_2.position)
|
||||||
|
{
|
||||||
|
std::swap(alternative_segment_1, alternative_segment_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetching names for the selected segments
|
||||||
|
route_names.shortest_path_name_1 = facade->get_name_for_id(shortest_segment_1.name_id);
|
||||||
|
route_names.shortest_path_name_2 = facade->get_name_for_id(shortest_segment_2.name_id);
|
||||||
|
|
||||||
|
route_names.alternative_path_name_1 =
|
||||||
|
facade->get_name_for_id(alternative_segment_1.name_id);
|
||||||
|
route_names.alternative_path_name_2 =
|
||||||
|
facade->get_name_for_id(alternative_segment_2.name_id);
|
||||||
|
|
||||||
|
return route_names;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EXTRACT_ROUTE_NAMES_H
|
||||||
@@ -1,32 +1,61 @@
|
|||||||
#ifndef TARJAN_SCC_HPP
|
/*
|
||||||
#define TARJAN_SCC_HPP
|
|
||||||
|
|
||||||
#include "util/typedefs.hpp"
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
#include "util/deallocating_vector.hpp"
|
All rights reserved.
|
||||||
#include "extractor/node_based_edge.hpp"
|
|
||||||
#include "extractor/query_node.hpp"
|
|
||||||
#include "util/percent.hpp"
|
|
||||||
|
|
||||||
#include "util/integer_range.hpp"
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
#include "util/simple_logger.hpp"
|
are permitted provided that the following conditions are met:
|
||||||
#include "util/std_hash.hpp"
|
|
||||||
#include "util/timing_util.hpp"
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TINY_COMPONENTS_HPP
|
||||||
|
#define TINY_COMPONENTS_HPP
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "../data_structures/deallocating_vector.hpp"
|
||||||
|
#include "../data_structures/import_edge.hpp"
|
||||||
|
#include "../data_structures/query_node.hpp"
|
||||||
|
#include "../data_structures/percent.hpp"
|
||||||
|
#include "../data_structures/restriction.hpp"
|
||||||
|
#include "../data_structures/restriction_map.hpp"
|
||||||
|
#include "../data_structures/turn_instructions.hpp"
|
||||||
|
|
||||||
|
#include "../util/integer_range.hpp"
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
#include "../util/std_hash.hpp"
|
||||||
|
#include "../util/timing_util.hpp"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
#include "osrm/coordinate.hpp"
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <algorithm>
|
|
||||||
#include <climits>
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace extractor
|
|
||||||
{
|
|
||||||
|
|
||||||
template <typename GraphT> class TarjanSCC
|
template <typename GraphT> class TarjanSCC
|
||||||
{
|
{
|
||||||
struct TarjanStackFrame
|
struct TarjanStackFrame
|
||||||
@@ -46,21 +75,27 @@ template <typename GraphT> class TarjanSCC
|
|||||||
|
|
||||||
std::vector<unsigned> components_index;
|
std::vector<unsigned> components_index;
|
||||||
std::vector<NodeID> component_size_vector;
|
std::vector<NodeID> component_size_vector;
|
||||||
std::shared_ptr<const GraphT> m_graph;
|
std::shared_ptr<GraphT> m_node_based_graph;
|
||||||
|
std::unordered_set<NodeID> barrier_node_set;
|
||||||
|
RestrictionMap m_restriction_map;
|
||||||
std::size_t size_one_counter;
|
std::size_t size_one_counter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TarjanSCC(std::shared_ptr<const GraphT> graph)
|
template <class ContainerT>
|
||||||
: components_index(graph->GetNumberOfNodes(), SPECIAL_NODEID), m_graph(graph),
|
TarjanSCC(std::shared_ptr<GraphT> graph,
|
||||||
size_one_counter(0)
|
const RestrictionMap &restrictions,
|
||||||
|
const ContainerT &barrier_node_list)
|
||||||
|
: components_index(graph->GetNumberOfNodes(), SPECIAL_NODEID), m_node_based_graph(graph),
|
||||||
|
m_restriction_map(restrictions), size_one_counter(0)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_graph->GetNumberOfNodes() > 0);
|
barrier_node_set.insert(std::begin(barrier_node_list), std::end(barrier_node_list));
|
||||||
|
BOOST_ASSERT(m_node_based_graph->GetNumberOfNodes() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TIMER_START(SCC_RUN);
|
TIMER_START(SCC_RUN);
|
||||||
const NodeID max_node_id = m_graph->GetNumberOfNodes();
|
const NodeID max_node_id = m_node_based_graph->GetNumberOfNodes();
|
||||||
|
|
||||||
// The following is a hack to distinguish between stuff that happens
|
// The following is a hack to distinguish between stuff that happens
|
||||||
// before the recursive call and stuff that happens after
|
// before the recursive call and stuff that happens after
|
||||||
@@ -71,7 +106,7 @@ template <typename GraphT> class TarjanSCC
|
|||||||
unsigned component_index = 0, size_of_current_component = 0;
|
unsigned component_index = 0, size_of_current_component = 0;
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
std::vector<bool> processing_node_before_recursion(max_node_id, true);
|
std::vector<bool> processing_node_before_recursion(max_node_id, true);
|
||||||
for (const NodeID node : util::irange(0u, max_node_id))
|
for (const NodeID node : osrm::irange(0u, max_node_id))
|
||||||
{
|
{
|
||||||
if (SPECIAL_NODEID == components_index[node])
|
if (SPECIAL_NODEID == components_index[node])
|
||||||
{
|
{
|
||||||
@@ -105,9 +140,30 @@ template <typename GraphT> class TarjanSCC
|
|||||||
tarjan_node_list[v].on_stack = true;
|
tarjan_node_list[v].on_stack = true;
|
||||||
++index;
|
++index;
|
||||||
|
|
||||||
for (const auto current_edge : m_graph->GetAdjacentEdgeRange(v))
|
const NodeID to_node_of_only_restriction =
|
||||||
|
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
|
||||||
|
|
||||||
|
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(v))
|
||||||
{
|
{
|
||||||
const auto vprime = m_graph->GetTarget(current_edge);
|
const auto vprime = m_node_based_graph->GetTarget(current_edge);
|
||||||
|
|
||||||
|
// Traverse outgoing edges
|
||||||
|
if (barrier_node_set.find(v) != barrier_node_set.end() && u != vprime)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
|
||||||
|
vprime == to_node_of_only_restriction)
|
||||||
|
{
|
||||||
|
// At an only_-restriction but not at the right turn
|
||||||
|
// continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_restriction_map.CheckIfTurnIsRestricted(u, v, vprime))
|
||||||
|
{
|
||||||
|
// continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (SPECIAL_NODEID == tarjan_node_list[vprime].index)
|
if (SPECIAL_NODEID == tarjan_node_list[vprime].index)
|
||||||
{
|
{
|
||||||
@@ -126,8 +182,9 @@ template <typename GraphT> class TarjanSCC
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
processing_node_before_recursion[v] = true;
|
processing_node_before_recursion[v] = true;
|
||||||
tarjan_node_list[u].low_link =
|
tarjan_node_list[currentFrame.parent].low_link =
|
||||||
std::min(tarjan_node_list[u].low_link, tarjan_node_list[v].low_link);
|
std::min(tarjan_node_list[currentFrame.parent].low_link,
|
||||||
|
tarjan_node_list[v].low_link);
|
||||||
// after recursion, lets do cycle checking
|
// after recursion, lets do cycle checking
|
||||||
// Check if we found a cycle. This is the bottom part of the recursion
|
// Check if we found a cycle. This is the bottom part of the recursion
|
||||||
if (tarjan_node_list[v].low_link == tarjan_node_list[v].index)
|
if (tarjan_node_list[v].low_link == tarjan_node_list[v].index)
|
||||||
@@ -146,8 +203,8 @@ template <typename GraphT> class TarjanSCC
|
|||||||
|
|
||||||
if (size_of_current_component > 1000)
|
if (size_of_current_component > 1000)
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write() << "large component [" << component_index
|
SimpleLogger().Write() << "large component [" << component_index
|
||||||
<< "]=" << size_of_current_component;
|
<< "]=" << size_of_current_component;
|
||||||
}
|
}
|
||||||
|
|
||||||
++component_index;
|
++component_index;
|
||||||
@@ -158,7 +215,7 @@ template <typename GraphT> class TarjanSCC
|
|||||||
}
|
}
|
||||||
|
|
||||||
TIMER_STOP(SCC_RUN);
|
TIMER_STOP(SCC_RUN);
|
||||||
util::SimpleLogger().Write() << "SCC run took: " << TIMER_MSEC(SCC_RUN) / 1000. << "s";
|
SimpleLogger().Write() << "SCC run took: " << TIMER_MSEC(SCC_RUN) / 1000. << "s";
|
||||||
|
|
||||||
size_one_counter = std::count_if(component_size_vector.begin(), component_size_vector.end(),
|
size_one_counter = std::count_if(component_size_vector.begin(), component_size_vector.end(),
|
||||||
[](unsigned value)
|
[](unsigned value)
|
||||||
@@ -171,14 +228,12 @@ template <typename GraphT> class TarjanSCC
|
|||||||
|
|
||||||
std::size_t get_size_one_count() const { return size_one_counter; }
|
std::size_t get_size_one_count() const { return size_one_counter; }
|
||||||
|
|
||||||
unsigned get_component_size(const unsigned component_id) const
|
unsigned get_component_size(const NodeID node) const
|
||||||
{
|
{
|
||||||
return component_size_vector[component_id];
|
return component_size_vector[components_index[node]];
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned get_component_id(const NodeID node) const { return components_index[node]; }
|
unsigned get_component_id(const NodeID node) const { return components_index[node]; }
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* TARJAN_SCC_HPP */
|
#endif /* TINY_COMPONENTS_HPP */
|
||||||
+48
-60
@@ -2,49 +2,33 @@
|
|||||||
SETLOCAL
|
SETLOCAL
|
||||||
SET EL=0
|
SET EL=0
|
||||||
|
|
||||||
ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
SET PROJECT_DIR=%CD%
|
|
||||||
ECHO PROJECT_DIR^: %PROJECT_DIR%
|
|
||||||
ECHO NUMBER_OF_PROCESSORS^: %NUMBER_OF_PROCESSORS%
|
|
||||||
ECHO cmake^: && cmake --version
|
|
||||||
|
|
||||||
ECHO activating VS command prompt ...
|
|
||||||
SET PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
|
|
||||||
CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
|
|
||||||
|
|
||||||
ECHO platform^: %platform%
|
ECHO platform^: %platform%
|
||||||
:: HARDCODE "x64" as it is uppercase on AppVeyor and download from S3 is case sensitive
|
:: HARDCODE "x64" as it is uppercase on AppVeyor and download from S3 is case sensitive
|
||||||
SET DEPSPKG=osrm-deps-win-x64-14.0.7z
|
SET DEPSPKG=osrm-deps-win-x64-14.0.7z
|
||||||
|
|
||||||
:: local development
|
:: local development
|
||||||
ECHO LOCAL_DEV^: %LOCAL_DEV%
|
IF "%computername%"=="MB" GOTO SKIPDL
|
||||||
IF NOT DEFINED LOCAL_DEV SET LOCAL_DEV=0
|
|
||||||
IF DEFINED LOCAL_DEV IF %LOCAL_DEV% EQU 1 IF EXIST %DEPSPKG% ECHO skipping deps download && GOTO SKIPDL
|
|
||||||
|
|
||||||
IF EXIST %DEPSPKG% DEL %DEPSPKG%
|
IF EXIST %DEPSPKG% DEL %DEPSPKG%
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
|
|
||||||
ECHO downloading %DEPSPKG%
|
ECHO downloading %DEPSPKG%
|
||||||
powershell Invoke-WebRequest https://mapbox.s3.amazonaws.com/windows-builds/windows-build-deps/$env:DEPSPKG -OutFile $env:PROJECT_DIR\$env:DEPSPKG
|
powershell Invoke-WebRequest https://mapbox.s3.amazonaws.com/windows-builds/windows-deps/$env:DEPSPKG -OutFile C:\projects\osrm\$env:DEPSPKG
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
|
||||||
|
|
||||||
:SKIPDL
|
|
||||||
|
|
||||||
IF EXIST osrm-deps ECHO deleting osrm-deps... && RD /S /Q osrm-deps
|
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
|
||||||
IF EXIST build ECHO deletings build dir... && RD /S /Q build
|
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
|
|
||||||
7z -y x %DEPSPKG% | %windir%\system32\FIND "ing archive"
|
7z -y x %DEPSPKG% | %windir%\system32\FIND "ing archive"
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
|
|
||||||
MKDIR build
|
:SKIPDL
|
||||||
|
|
||||||
|
IF EXIST build rd /s /q build
|
||||||
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
|
mkdir build
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
cd build
|
cd build
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
|
|
||||||
SET OSRMDEPSDIR=%PROJECT_DIR%\osrm-deps
|
SET OSRMDEPSDIR=c:\projects\osrm\osrm-deps
|
||||||
set PREFIX=%OSRMDEPSDIR%/libs
|
set PREFIX=%OSRMDEPSDIR%/libs
|
||||||
set BOOST_ROOT=%OSRMDEPSDIR%/boost
|
set BOOST_ROOT=%OSRMDEPSDIR%/boost
|
||||||
set TBB_INSTALL_DIR=%OSRMDEPSDIR%/tbb
|
set TBB_INSTALL_DIR=%OSRMDEPSDIR%/tbb
|
||||||
@@ -52,9 +36,9 @@ set TBB_ARCH_PLATFORM=intel64/vc14
|
|||||||
|
|
||||||
ECHO calling cmake ....
|
ECHO calling cmake ....
|
||||||
cmake .. ^
|
cmake .. ^
|
||||||
-G "Visual Studio 14 2015 Win64" ^
|
-G "Visual Studio 14 Win64" ^
|
||||||
-DBOOST_ROOT=%BOOST_ROOT% ^
|
-DBOOST_ROOT=%BOOST_ROOT% ^
|
||||||
-DBoost_ADDITIONAL_VERSIONS=1.58 ^
|
-DBoost_ADDITIONAL_VERSIONS=1.57 ^
|
||||||
-DBoost_USE_MULTITHREADED=ON ^
|
-DBoost_USE_MULTITHREADED=ON ^
|
||||||
-DBoost_USE_STATIC_LIBS=ON ^
|
-DBoost_USE_STATIC_LIBS=ON ^
|
||||||
-DCMAKE_BUILD_TYPE=%CONFIGURATION% ^
|
-DCMAKE_BUILD_TYPE=%CONFIGURATION% ^
|
||||||
@@ -76,50 +60,54 @@ msbuild OSRM.sln ^
|
|||||||
/flp2:logfile=build_warnings.txt;warningsonly
|
/flp2:logfile=build_warnings.txt;warningsonly
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
|
|
||||||
CD %PROJECT_DIR%\build
|
ECHO ========= TODO^: CREATE PACKAGES ==========
|
||||||
|
|
||||||
|
CD c:\projects\osrm\build\%Configuration%
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
|
|
||||||
SET PATH=%PROJECT_DIR%\osrm-deps\libs\bin;%PATH%
|
SET PATH=c:\projects\osrm\osrm-deps\libs\bin;%PATH%
|
||||||
|
|
||||||
ECHO running engine-tests.exe ...
|
ECHO running datastructure-tests.exe ...
|
||||||
%Configuration%\engine-tests.exe
|
datastructure-tests.exe
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
ECHO running extractor-tests.exe ...
|
ECHO running algorithm-tests.exe ...
|
||||||
%Configuration%\extractor-tests.exe
|
algorithm-tests.exe
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
|
||||||
ECHO running util-tests.exe ...
|
|
||||||
%Configuration%\util-tests.exe
|
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
|
||||||
|
|
||||||
IF NOT "%APPVEYOR_REPO_BRANCH%"=="develop" GOTO DONE
|
|
||||||
ECHO ========= CREATING PACKAGES ==========
|
|
||||||
|
|
||||||
CD %PROJECT_DIR%\build\%Configuration%
|
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
|
||||||
|
|
||||||
SET P=%PROJECT_DIR%
|
|
||||||
SET ZIP= %P%\osrm_%Configuration%.zip
|
|
||||||
IF EXIST %ZIP% ECHO deleting %ZIP% && DEL /F /Q %ZIP%
|
|
||||||
IF %ERRORLEVEL% NEQ 0 ECHO deleting %ZIP% FAILED && GOTO ERROR
|
|
||||||
|
|
||||||
7z a %ZIP% *.lib *.exe *.pdb %P%/osrm-deps/libs/bin/*.dll -tzip -mx9 | %windir%\system32\FIND "ing archive"
|
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
|
||||||
|
|
||||||
CD ..\..\profiles
|
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
|
||||||
|
|
||||||
ECHO disk=c:\temp\stxxl,10000,wincall > .stxxl.txt
|
|
||||||
7z a %ZIP% * -tzip -mx9 | %windir%\system32\FIND "ing archive"
|
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
|
|
||||||
GOTO DONE
|
GOTO DONE
|
||||||
|
|
||||||
:ERROR
|
:ERROR
|
||||||
ECHO ~~~~~~~~~~~~~~~~~~~~~~ ERROR %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
ECHO ERRORLEVEL^: %ERRORLEVEL%
|
|
||||||
SET EL=%ERRORLEVEL%
|
SET EL=%ERRORLEVEL%
|
||||||
|
ECHO ============== ERROR ===============
|
||||||
|
|
||||||
:DONE
|
:DONE
|
||||||
ECHO ~~~~~~~~~~~~~~~~~~~~~~ DONE %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
ECHO ============= DONE ===============
|
||||||
|
CD C:\projects\osrm
|
||||||
EXIT /b %EL%
|
EXIT /b %EL%
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- cd c:/projects/osrm
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- echo Running cmake...
|
||||||
|
- call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
|
||||||
|
- SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH%
|
||||||
|
- SET P=c:/projects/osrm
|
||||||
|
- set TBB_INSTALL_DIR=%P%/tbb
|
||||||
|
- set TBB_ARCH_PLATFORM=intel64/vc12
|
||||||
|
- cmake .. -G "Visual Studio 14 Win64" -DCMAKE_BUILD_TYPE=%Configuration% -DCMAKE_INSTALL_PREFIX=%P%/libs -DBOOST_ROOT=%P%/boost_min -DBoost_ADDITIONAL_VERSIONS=1.57 -DBoost_USE_STATIC_LIBS=ON
|
||||||
|
- SET PLATFORM_TOOLSET=v140
|
||||||
|
- SET TOOLS_VERSION=14.0
|
||||||
|
- msbuild /p:Platform=x64 /clp:Verbosity=minimal /toolsversion:%TOOLS_VERSION% /p:PlatformToolset=%PLATFORM_TOOLSET% /nologo OSRM.sln
|
||||||
|
- msbuild /p:Platform=x64 /clp:Verbosity=minimal /toolsversion:%TOOLS_VERSION% /p:PlatformToolset=%PLATFORM_TOOLSET% /nologo tests.vcxproj
|
||||||
|
- cd %Configuration%
|
||||||
|
- if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip *.exe *.pdb %P%/libs/bin/*.dll -tzip)
|
||||||
|
- cd ..\..\profiles
|
||||||
|
- echo disk=c:\temp\stxxl,10000,wincall > .stxxl.txt
|
||||||
|
- if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip * -tzip)
|
||||||
|
- set PATH=%PATH%;c:/projects/osrm/libs/bin
|
||||||
|
- cd c:/projects/osrm/build/%Configuration%
|
||||||
|
- datastructure-tests.exe
|
||||||
|
- algorithm-tests.exe
|
||||||
|
|||||||
+5
-6
@@ -7,13 +7,17 @@ environment:
|
|||||||
init:
|
init:
|
||||||
- git config --global core.autocrlf input
|
- git config --global core.autocrlf input
|
||||||
|
|
||||||
os: Visual Studio 2015
|
os: Visual Studio 2015 RC
|
||||||
|
|
||||||
# clone directory
|
# clone directory
|
||||||
clone_folder: c:\projects\osrm
|
clone_folder: c:\projects\osrm
|
||||||
|
|
||||||
platform: x64
|
platform: x64
|
||||||
|
|
||||||
|
install:
|
||||||
|
- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
|
||||||
|
- CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- CALL appveyor-build.bat
|
- CALL appveyor-build.bat
|
||||||
|
|
||||||
@@ -25,11 +29,6 @@ artifacts:
|
|||||||
# - path: osrm_Debug.zip
|
# - path: osrm_Debug.zip
|
||||||
# name: osrm_Debug.zip
|
# name: osrm_Debug.zip
|
||||||
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
- develop
|
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
provider: FTP
|
provider: FTP
|
||||||
server:
|
server:
|
||||||
|
|||||||
@@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../data_structures/original_edge_data.hpp"
|
||||||
|
#include "../data_structures/query_node.hpp"
|
||||||
|
#include "../data_structures/shared_memory_vector_wrapper.hpp"
|
||||||
|
#include "../data_structures/static_rtree.hpp"
|
||||||
|
#include "../util/boost_filesystem_2_fix.hpp"
|
||||||
|
#include "../data_structures/edge_based_node.hpp"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
// Choosen by a fair W20 dice roll (this value is completely arbitrary)
|
||||||
|
constexpr unsigned RANDOM_SEED = 13;
|
||||||
|
constexpr int32_t WORLD_MIN_LAT = -90 * COORDINATE_PRECISION;
|
||||||
|
constexpr int32_t WORLD_MAX_LAT = 90 * COORDINATE_PRECISION;
|
||||||
|
constexpr int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION;
|
||||||
|
constexpr int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;
|
||||||
|
|
||||||
|
using RTreeLeaf = EdgeBasedNode;
|
||||||
|
using FixedPointCoordinateListPtr = std::shared_ptr<std::vector<FixedPointCoordinate>>;
|
||||||
|
using BenchStaticRTree = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, false>::vector, false>;
|
||||||
|
|
||||||
|
FixedPointCoordinateListPtr LoadCoordinates(const boost::filesystem::path &nodes_file)
|
||||||
|
{
|
||||||
|
boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
|
||||||
|
|
||||||
|
QueryNode current_node;
|
||||||
|
unsigned coordinate_count = 0;
|
||||||
|
nodes_input_stream.read((char *)&coordinate_count, sizeof(unsigned));
|
||||||
|
auto coords = std::make_shared<std::vector<FixedPointCoordinate>>(coordinate_count);
|
||||||
|
for (unsigned i = 0; i < coordinate_count; ++i)
|
||||||
|
{
|
||||||
|
nodes_input_stream.read((char *)¤t_node, sizeof(QueryNode));
|
||||||
|
coords->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon);
|
||||||
|
BOOST_ASSERT((std::abs(coords->at(i).lat) >> 30) == 0);
|
||||||
|
BOOST_ASSERT((std::abs(coords->at(i).lon) >> 30) == 0);
|
||||||
|
}
|
||||||
|
nodes_input_stream.close();
|
||||||
|
return coords;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Benchmark(BenchStaticRTree &rtree, unsigned num_queries)
|
||||||
|
{
|
||||||
|
std::mt19937 mt_rand(RANDOM_SEED);
|
||||||
|
std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
|
||||||
|
std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);
|
||||||
|
std::vector<FixedPointCoordinate> queries;
|
||||||
|
for (unsigned i = 0; i < num_queries; i++)
|
||||||
|
{
|
||||||
|
queries.emplace_back(FixedPointCoordinate(lat_udist(mt_rand), lon_udist(mt_rand)));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const unsigned num_results = 5;
|
||||||
|
std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results
|
||||||
|
<< " phantom nodes"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
TIMER_START(query_phantom);
|
||||||
|
std::vector<PhantomNode> phantom_node_vector;
|
||||||
|
for (const auto &q : queries)
|
||||||
|
{
|
||||||
|
phantom_node_vector.clear();
|
||||||
|
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results);
|
||||||
|
phantom_node_vector.clear();
|
||||||
|
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results);
|
||||||
|
}
|
||||||
|
TIMER_STOP(query_phantom);
|
||||||
|
|
||||||
|
std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries
|
||||||
|
<< " queries."
|
||||||
|
<< "\n";
|
||||||
|
std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query."
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
std::cout << "#### LocateClosestEndPointForCoordinate"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
TIMER_START(query_endpoint);
|
||||||
|
FixedPointCoordinate result;
|
||||||
|
for (const auto &q : queries)
|
||||||
|
{
|
||||||
|
rtree.LocateClosestEndPointForCoordinate(q, result, 3);
|
||||||
|
}
|
||||||
|
TIMER_STOP(query_endpoint);
|
||||||
|
|
||||||
|
std::cout << "Took " << TIMER_MSEC(query_endpoint) << " msec for " << num_queries << " queries."
|
||||||
|
<< "\n";
|
||||||
|
std::cout << TIMER_MSEC(query_endpoint) / ((double)num_queries) << " msec/query."
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
std::cout << "#### FindPhantomNodeForCoordinate"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
TIMER_START(query_node);
|
||||||
|
for (const auto &q : queries)
|
||||||
|
{
|
||||||
|
PhantomNode phantom;
|
||||||
|
rtree.FindPhantomNodeForCoordinate(q, phantom, 3);
|
||||||
|
}
|
||||||
|
TIMER_STOP(query_node);
|
||||||
|
|
||||||
|
std::cout << "Took " << TIMER_MSEC(query_node) << " msec for " << num_queries << " queries."
|
||||||
|
<< "\n";
|
||||||
|
std::cout << TIMER_MSEC(query_node) / ((double)num_queries) << " msec/query."
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
{
|
||||||
|
const unsigned num_results = 1;
|
||||||
|
std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results
|
||||||
|
<< " phantom nodes"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
TIMER_START(query_phantom);
|
||||||
|
std::vector<PhantomNode> phantom_node_vector;
|
||||||
|
for (const auto &q : queries)
|
||||||
|
{
|
||||||
|
phantom_node_vector.clear();
|
||||||
|
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results);
|
||||||
|
phantom_node_vector.clear();
|
||||||
|
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results);
|
||||||
|
}
|
||||||
|
TIMER_STOP(query_phantom);
|
||||||
|
|
||||||
|
std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries
|
||||||
|
<< " queries."
|
||||||
|
<< "\n";
|
||||||
|
std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query."
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
std::cout << "#### LocateClosestEndPointForCoordinate"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc < 4)
|
||||||
|
{
|
||||||
|
std::cout << "./rtree-bench file.ramIndex file.fileIndx file.nodes"
|
||||||
|
<< "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *ramPath = argv[1];
|
||||||
|
const char *filePath = argv[2];
|
||||||
|
const char *nodesPath = argv[3];
|
||||||
|
|
||||||
|
auto coords = LoadCoordinates(nodesPath);
|
||||||
|
|
||||||
|
BenchStaticRTree rtree(ramPath, filePath, coords);
|
||||||
|
|
||||||
|
Benchmark(rtree, 10000);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+9
-23
@@ -1,33 +1,19 @@
|
|||||||
@ECHO OFF
|
@ECHO OFF
|
||||||
SETLOCAL
|
|
||||||
SET EL=0
|
|
||||||
|
|
||||||
ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
SET PLATFORM=x64
|
SET PLATFORM=x64
|
||||||
SET CONFIGURATION=Release
|
SET CONFIGURATION=Release
|
||||||
::SET LOCAL_DEV=1
|
|
||||||
|
|
||||||
FOR /F "tokens=*" %%i in ('git rev-parse --abbrev-ref HEAD') do SET APPVEYOR_REPO_BRANCH=%%i
|
WHERE msbuild
|
||||||
ECHO APPVEYOR_REPO_BRANCH^: %APPVEYOR_REPO_BRANCH%
|
IF %ERRORLEVEL% EQU 0 GOTO RUNBUILD
|
||||||
|
|
||||||
SET PATH=C:\mb\windows-builds-64\tmp-bin\cmake-3.4.0-win32-x86\bin;%PATH%
|
SET PATH=C:\mb\windows-builds-64\tmp-bin\cmake-3.1.0-win32-x86\bin;%PATH%
|
||||||
SET PATH=C:\Program Files\7-Zip;%PATH%
|
SET PATH=C:\Program Files\7-Zip;%PATH%
|
||||||
|
ECHO activating VS command prompt ...
|
||||||
|
SET PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
|
||||||
|
CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
|
||||||
|
|
||||||
|
:RUNBUILD
|
||||||
|
|
||||||
powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted -Force
|
powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted -Force
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
|
||||||
CALL appveyor-build.bat
|
CALL appveyor-build.bat
|
||||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
EXIT /b %ERRORLEVEL%
|
||||||
|
|
||||||
GOTO DONE
|
|
||||||
|
|
||||||
|
|
||||||
:ERROR
|
|
||||||
ECHO ~~~~~~~~~~~~~~~~~~~~~~ ERROR %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
ECHO ERRORLEVEL^: %ERRORLEVEL%
|
|
||||||
SET EL=%ERRORLEVEL%
|
|
||||||
|
|
||||||
:DONE
|
|
||||||
ECHO ~~~~~~~~~~~~~~~~~~~~~~ DONE %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
EXIT /b %EL%
|
|
||||||
|
|||||||
@@ -7,13 +7,15 @@ INCLUDE(FindDebArch)
|
|||||||
SET(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md")
|
SET(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md")
|
||||||
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENCE.TXT")
|
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENCE.TXT")
|
||||||
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CPACK_RESOURCE_FILE_README}")
|
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CPACK_RESOURCE_FILE_README}")
|
||||||
SET(CPACK_PACKAGE_UPSTREAM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
SET(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||||
SET(CPACK_PACKAGE_DEBIAN_REVISION "1")
|
SET(CPACK_PACKAGE_VERSION_MINOR "4")
|
||||||
SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_UPSTREAM_VERSION}-${CPACK_PACKAGE_DEBIAN_REVISION}")
|
SET(CPACK_PACKAGE_VERSION_PATCH "3")
|
||||||
|
|
||||||
|
SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||||
|
|
||||||
string(TOLOWER "${CMAKE_PROJECT_NAME}" LOWER_PROJECT_NAME)
|
string(TOLOWER "${CMAKE_PROJECT_NAME}" LOWER_PROJECT_NAME)
|
||||||
SET(CPACK_PACKAGE_FILE_NAME "${LOWER_PROJECT_NAME}_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
SET(CPACK_PACKAGE_FILE_NAME "${LOWER_PROJECT_NAME}_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
||||||
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${LOWER_PROJECT_NAME}_${CPACK_PACKAGE_UPSTREAM_VERSION}_orig")
|
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${LOWER_PROJECT_NAME}_${CPACK_PACKAGE_VERSION}_orig")
|
||||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Open Source Routing Machine (OSRM).")
|
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Open Source Routing Machine (OSRM).")
|
||||||
SET(CPACK_PACKAGE_DESCRIPTION "Open Source Routing Machine (OSRM) is a routing engine.")
|
SET(CPACK_PACKAGE_DESCRIPTION "Open Source Routing Machine (OSRM) is a routing engine.")
|
||||||
|
|
||||||
@@ -25,17 +27,18 @@ SET(CPACK_INCLUDE_TOPLEVEL_DIRECTORY "FALSE")
|
|||||||
SET(CPACK_GENERATOR "DEB")
|
SET(CPACK_GENERATOR "DEB")
|
||||||
|
|
||||||
SET(CPACK_DEBIAN_PACKAGE_NAME "${CPACK_PACKAGE_NAME}${VERSION_SUFFIX}")
|
SET(CPACK_DEBIAN_PACKAGE_NAME "${CPACK_PACKAGE_NAME}${VERSION_SUFFIX}")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}")
|
SET(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}${CPACK_PACKAGE_REVISION}")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Dennis Luxen <info@project-osrm.org>")
|
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Dennis Luxen <info@project-osrm.org>")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_SECTION "devel")
|
SET(CPACK_DEBIAN_PACKAGE_SECTION "devel")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_DESCRIPTION "Open Source Routing Machine (OSRM) is a high-performance routing engine.
|
SET(CPACK_DEBIAN_PACKAGE_DESCRIPTION "Open Source Routing Machine (OSRM) is a high-performance routing engine.
|
||||||
It combines sophisticated routing algorithms with the open and free data of the OpenStreetMap."
|
It combines sophisticated routing algorithms with the open and free data of the OpenStreetMap."
|
||||||
)
|
)
|
||||||
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6-dev, libbz2-1.0, libstxxl1, libxml2, libzip2, liblua5.1-0, libtbb2, libboost-all-dev")
|
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6-dev, libprotobuf-dev, libosmpbf-dev, libbz2-1.0, libstxxl1, libxml2, libzip2, liblua5.1-0, libtbb2, libboost-all-dev")
|
||||||
|
|
||||||
file(GLOB_RECURSE ProfileGlob ${CMAKE_SOURCE_DIR}/profiles/*)
|
file(GLOB_RECURSE ProfileGlob ${CMAKE_SOURCE_DIR}/profiles/*)
|
||||||
install(FILES ${ProfileGlob} DESTINATION "share/doc/${LOWER_PROJECT_NAME}/profiles")
|
install(FILES ${ProfileGlob} DESTINATION "share/doc/${LOWER_PROJECT_NAME}/profiles")
|
||||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_BINARY_DIR}/copyright;")
|
CONFIGURE_FILE (${CMAKE_SOURCE_DIR}/cmake/postinst.in postinst)
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_BINARY_DIR}/postinst;${CMAKE_CURRENT_BINARY_DIR}/copyright;")
|
||||||
|
|
||||||
MESSAGE(STATUS "Debian Package: ${CPACK_DEBIAN_PACKAGE_NAME} (${CPACK_DEBIAN_PACKAGE_VERSION}) [${CPACK_PACKAGE_FILE_NAME}.deb]")
|
MESSAGE(STATUS "Debian Package: ${CPACK_DEBIAN_PACKAGE_NAME} (${CPACK_DEBIAN_PACKAGE_VERSION}) [${CPACK_PACKAGE_FILE_NAME}.deb]")
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
# Copyright 2007-2009 Kitware, Inc.
|
# Copyright 2007-2009 Kitware, Inc.
|
||||||
# Copyright 2016 for Project-OSRM, Lua5.1 => Lua5.2
|
# Copyright 2013 for Project-OSRM, Lua5.1 => Lua5.2
|
||||||
#
|
#
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
# see accompanying file Copyright.txt for details.
|
# see accompanying file Copyright.txt for details.
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# Locate OSMPBF library
|
||||||
|
# This module defines
|
||||||
|
# OSMPBF_FOUND, if false, do not try to link to OSMPBF
|
||||||
|
# OSMPBF_LIBRARIES
|
||||||
|
# OSMPBF_INCLUDE_DIR, where to find OSMPBF.hpp
|
||||||
|
#
|
||||||
|
# Note that the expected include convention is
|
||||||
|
# #include <osmpbf/osmpbf.h>
|
||||||
|
# and not
|
||||||
|
# #include <osmpbf.h>
|
||||||
|
|
||||||
|
IF( NOT OSMPBF_FIND_QUIETLY )
|
||||||
|
MESSAGE(STATUS "Looking for OSMPBF...")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
FIND_PATH(OSMPBF_INCLUDE_DIR osmpbf.h
|
||||||
|
HINTS
|
||||||
|
$ENV{OSMPBF_DIR}
|
||||||
|
PATH_SUFFIXES OSMPBF include/osmpbf include
|
||||||
|
PATHS
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/usr/local
|
||||||
|
/usr
|
||||||
|
/opt/local # DarwinPorts
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(OSMPBF_LIBRARY
|
||||||
|
NAMES osmpbf
|
||||||
|
HINTS
|
||||||
|
$ENV{OSMPBF_DIR}
|
||||||
|
PATH_SUFFIXES lib64 lib
|
||||||
|
PATHS
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/usr/local
|
||||||
|
/usr
|
||||||
|
/opt/local
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set OSMPBF_FOUND to TRUE if
|
||||||
|
# all listed variables are TRUE
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OSMPBF DEFAULT_MSG OSMPBF_LIBRARY OSMPBF_INCLUDE_DIR)
|
||||||
|
|
||||||
|
IF( NOT OSMPBF_FIND_QUIETLY )
|
||||||
|
IF( OSMPBF_FOUND )
|
||||||
|
MESSAGE(STATUS "Found OSMPBF: ${OSMPBF_LIBRARY}" )
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
#MARK_AS_ADVANCED(OSMPBF_INCLUDE_DIR OSMPBF_LIBRARIES OSMPBF_LIBRARY OSMPBF_LIBRARY_DBG)
|
||||||
@@ -24,7 +24,7 @@ FIND_PATH(STXXL_INCLUDE_DIR stxxl.h
|
|||||||
)
|
)
|
||||||
|
|
||||||
FIND_LIBRARY(STXXL_LIBRARY
|
FIND_LIBRARY(STXXL_LIBRARY
|
||||||
NAMES stxxl stxxl_debug
|
NAMES stxxl
|
||||||
HINTS
|
HINTS
|
||||||
$ENV{STXXL_DIR}
|
$ENV{STXXL_DIR}
|
||||||
PATH_SUFFIXES lib64 lib
|
PATH_SUFFIXES lib64 lib
|
||||||
|
|||||||
@@ -1,24 +1,10 @@
|
|||||||
set(OLDFILE ${OUTPUT_DIR}/include/util/fingerprint_impl.hpp)
|
set(OLDFILE ${SOURCE_DIR}/util/fingerprint_impl.hpp)
|
||||||
set(NEWFILE ${OLDFILE}.tmp)
|
|
||||||
set(INFILE ${SOURCE_DIR}/include/util/fingerprint_impl.hpp.in)
|
|
||||||
file(MD5 ${SOURCE_DIR}/src/tools/contract.cpp MD5PREPARE)
|
|
||||||
file(MD5 ${SOURCE_DIR}/include/util/static_rtree.hpp MD5RTREE)
|
|
||||||
file(MD5 ${SOURCE_DIR}/include/util/graph_loader.hpp MD5GRAPH)
|
|
||||||
file(MD5 ${SOURCE_DIR}/include/engine/datafacade/internal_datafacade.hpp MD5OBJECTS)
|
|
||||||
|
|
||||||
CONFIGURE_FILE(${INFILE} ${NEWFILE})
|
|
||||||
|
|
||||||
file(MD5 ${NEWFILE} MD5NEW)
|
|
||||||
|
|
||||||
if (EXISTS ${OLDFILE})
|
if (EXISTS ${OLDFILE})
|
||||||
file(MD5 ${OLDFILE} MD5OLD)
|
file(REMOVE_RECURSE ${OLDFILE})
|
||||||
if(NOT ${MD5NEW} STREQUAL ${MD5OLD})
|
|
||||||
file(REMOVE_RECURSE ${OLDFILE})
|
|
||||||
file(RENAME ${NEWFILE} ${OLDFILE})
|
|
||||||
else()
|
|
||||||
file(REMOVE_RECURSE ${NEWFILE})
|
|
||||||
message(STATUS "Fingerprint unchanged, not regenerating")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
file(RENAME ${NEWFILE} ${OLDFILE})
|
|
||||||
endif()
|
endif()
|
||||||
|
file(MD5 ${SOURCE_DIR}/prepare.cpp MD5PREPARE)
|
||||||
|
file(MD5 ${SOURCE_DIR}/data_structures/static_rtree.hpp MD5RTREE)
|
||||||
|
file(MD5 ${SOURCE_DIR}/util/graph_loader.hpp MD5GRAPH)
|
||||||
|
file(MD5 ${SOURCE_DIR}/server/data_structures/internal_datafacade.hpp MD5OBJECTS)
|
||||||
|
|
||||||
|
CONFIGURE_FILE(${SOURCE_DIR}/util/fingerprint_impl.hpp.in ${SOURCE_DIR}/util/fingerprint_impl.hpp)
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
# - Returns a version string from Git
|
||||||
|
#
|
||||||
|
# These functions force a re-configure on each git commit so that you can
|
||||||
|
# trust the values of the variables in your build system.
|
||||||
|
#
|
||||||
|
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the refspec and sha hash of the current head revision
|
||||||
|
#
|
||||||
|
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the results of git describe on the source tree, and adjusting
|
||||||
|
# the output so that it tests false if an error occurs.
|
||||||
|
#
|
||||||
|
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the results of git describe --exact-match on the source tree,
|
||||||
|
# and adjusting the output so that it tests false if there was no exact
|
||||||
|
# matching tag.
|
||||||
|
#
|
||||||
|
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||||
|
#
|
||||||
|
# Original Author:
|
||||||
|
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||||
|
# http://academic.cleardefinition.com
|
||||||
|
# Iowa State University HCI Graduate Program/VRAC
|
||||||
|
#
|
||||||
|
# Copyright Iowa State University 2009-2010.
|
||||||
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
if(__get_git_revision_description)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(__get_git_revision_description YES)
|
||||||
|
|
||||||
|
# We must run the following at "include" time, not at function call time,
|
||||||
|
# to find the path to this module rather than the path to a calling list file
|
||||||
|
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||||
|
|
||||||
|
function(get_git_head_revision _refspecvar _hashvar)
|
||||||
|
set(GIT_PARENT_DIR "${CMAKE_SOURCE_DIR}")
|
||||||
|
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||||
|
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
|
||||||
|
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
|
||||||
|
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
|
||||||
|
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
|
||||||
|
# We have reached the root directory, we are not in git
|
||||||
|
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||||
|
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||||
|
endwhile()
|
||||||
|
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||||
|
if(NOT EXISTS "${GIT_DATA}")
|
||||||
|
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EXISTS "${GIT_DIR}/HEAD")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||||
|
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
|
||||||
|
|
||||||
|
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||||
|
"${GIT_DATA}/grabRef.cmake"
|
||||||
|
@ONLY)
|
||||||
|
include("${GIT_DATA}/grabRef.cmake")
|
||||||
|
|
||||||
|
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
|
||||||
|
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_describe _var)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
find_package(Git QUIET)
|
||||||
|
endif()
|
||||||
|
get_git_head_revision(refspec hash)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
if(NOT hash)
|
||||||
|
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# TODO sanitize
|
||||||
|
#if((${ARGN}" MATCHES "&&") OR
|
||||||
|
# (ARGN MATCHES "||") OR
|
||||||
|
# (ARGN MATCHES "\\;"))
|
||||||
|
# message("Please report the following error to the project!")
|
||||||
|
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||||
|
#endif()
|
||||||
|
|
||||||
|
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||||
|
|
||||||
|
execute_process(COMMAND
|
||||||
|
"${GIT_EXECUTABLE}"
|
||||||
|
describe
|
||||||
|
${hash}
|
||||||
|
${ARGN}
|
||||||
|
WORKING_DIRECTORY
|
||||||
|
"${CMAKE_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE
|
||||||
|
res
|
||||||
|
OUTPUT_VARIABLE
|
||||||
|
out
|
||||||
|
ERROR_QUIET
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(NOT res EQUAL 0)
|
||||||
|
set(out "${out}-${res}-NOTFOUND")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${_var} "${out}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_get_exact_tag _var)
|
||||||
|
git_describe(out --exact-match ${ARGN})
|
||||||
|
set(${_var} "${out}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#
|
||||||
|
# Internal file for GetGitRevisionDescription.cmake
|
||||||
|
#
|
||||||
|
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||||
|
#
|
||||||
|
# Original Author:
|
||||||
|
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||||
|
# http://academic.cleardefinition.com
|
||||||
|
# Iowa State University HCI Graduate Program/VRAC
|
||||||
|
#
|
||||||
|
# Copyright Iowa State University 2009-2010.
|
||||||
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
set(HEAD_HASH)
|
||||||
|
|
||||||
|
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||||
|
|
||||||
|
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||||
|
if(HEAD_CONTENTS MATCHES "ref")
|
||||||
|
# named branch
|
||||||
|
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||||
|
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||||
|
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
|
elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}")
|
||||||
|
configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
|
set(HEAD_HASH "${HEAD_REF}")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# detached HEAD
|
||||||
|
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT HEAD_HASH)
|
||||||
|
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||||
|
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||||
|
endif()
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
INCLUDE (CheckCXXSourceCompiles)
|
INCLUDE (CheckCXXSourceCompiles)
|
||||||
unset(LUABIND_WORKS CACHE)
|
unset(LUABIND_WORKS CACHE)
|
||||||
unset(LUABIND51_WORKS CACHE)
|
unset(LUABIND51_WORKS CACHE)
|
||||||
set (LUABIND_CHECK_SRC "extern \"C\" {\n#include \"lua.h\"\n#include \"lauxlib.h\"\n}\n#include <luabind/open.hpp>\nint main() { lua_State *x = luaL_newstate(); luabind::open(x); }")
|
set (LUABIND_CHECK_SRC "#include \"lua.h\"\n#include <luabind/luabind.hpp>\n int main() { lua_State *myLuaState = luaL_newstate(); luabind::open(myLuaState); return 0;}")
|
||||||
set (CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE})
|
set (CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE})
|
||||||
set (CMAKE_REQUIRED_INCLUDES "${Boost_INCLUDE_DIR};${LUABIND_INCLUDE_DIR};${LUA_INCLUDE_DIR}")
|
set (CMAKE_REQUIRED_INCLUDES "${Boost_INCLUDE_DIR};${LUABIND_INCLUDE_DIR};${LUA_INCLUDE_DIR}")
|
||||||
set (CMAKE_REQUIRED_LIBRARIES "${LUABIND_LIBRARY};${LUA_LIBRARY}")
|
set (CMAKE_REQUIRED_LIBRARIES "${LUABIND_LIBRARY};${LUA_LIBRARY}")
|
||||||
|
|||||||
@@ -32,11 +32,13 @@ cache_file = "%s/cached_options.txt" % (scriptpath)
|
|||||||
db = None
|
db = None
|
||||||
if os.access(cache_file, os.R_OK) == 0:
|
if os.access(cache_file, os.R_OK) == 0:
|
||||||
db = load_db(sys.argv[1])
|
db = load_db(sys.argv[1])
|
||||||
with open(cache_file, "wb") as f:
|
f = open(cache_file, "wb")
|
||||||
pickle.dump(db, f)
|
pickle.dump(db, f)
|
||||||
|
f.close()
|
||||||
else:
|
else:
|
||||||
with open(cache_file) as f:
|
f = open(cache_file)
|
||||||
db = pickle.load(f)
|
db = pickle.load(f)
|
||||||
|
f.close()
|
||||||
|
|
||||||
if db and sys.argv[2] in db:
|
if db and sys.argv[2] in db:
|
||||||
for option in db[sys.argv[2]]:
|
for option in db[sys.argv[2]]:
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
|
||||||
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
|
||||||
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
|
||||||
|
|
||||||
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
|
||||||
string(REGEX REPLACE "\n" ";" files "${files}")
|
|
||||||
foreach(file ${files})
|
|
||||||
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
|
||||||
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
|
||||||
exec_program(
|
|
||||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
|
||||||
OUTPUT_VARIABLE rm_out
|
|
||||||
RETURN_VALUE rm_retval
|
|
||||||
)
|
|
||||||
if(NOT "${rm_retval}" STREQUAL 0)
|
|
||||||
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
|
||||||
endif(NOT "${rm_retval}" STREQUAL 0)
|
|
||||||
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
|
||||||
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
|
||||||
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
|
||||||
endforeach(file)
|
|
||||||
+4
-4
@@ -1,11 +1,11 @@
|
|||||||
prefix=@CMAKE_INSTALL_PREFIX@
|
prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
includedir=${prefix}/include ${prefix}/include/osrm
|
includedir=${prefix}/include/osrm
|
||||||
libdir=${prefix}/lib
|
libdir=${prefix}/lib
|
||||||
|
|
||||||
Name: libOSRM
|
Name: libOSRM
|
||||||
Description: Project OSRM library
|
Description: Project OSRM library
|
||||||
Version: v@OSRM_VERSION_MAJOR@.@OSRM_VERSION_MINOR@.@OSRM_VERSION_PATCH@
|
Version: @GIT_DESCRIPTION@
|
||||||
Requires:
|
Requires:
|
||||||
Libs: -L${libdir} -losrm
|
Libs: -L${libdir} -lOSRM
|
||||||
Libs.private: @ENGINE_LIBRARY_LISTING@
|
Libs.private: @BOOST_LIBRARY_LISTING@
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#/usr/bin/env bash
|
||||||
|
ln -s /usr/share/doc/@CMAKE_PROJECT_NAME@/profiles/car.lua @CMAKE_INSTALL_PREFIX@/profile.lua
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "contractor_options.hpp"
|
||||||
|
|
||||||
|
#include "../util/git_sha.hpp"
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
#include <tbb/task_scheduler_init.h>
|
||||||
|
|
||||||
|
return_code
|
||||||
|
ContractorOptions::ParseArguments(int argc, char *argv[], ContractorConfig &contractor_config)
|
||||||
|
{
|
||||||
|
// declare a group of options that will be allowed only on command line
|
||||||
|
boost::program_options::options_description generic_options("Options");
|
||||||
|
generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
|
||||||
|
"config,c", boost::program_options::value<boost::filesystem::path>(&contractor_config.config_file_path)
|
||||||
|
->default_value("contractor.ini"),
|
||||||
|
"Path to a configuration file.");
|
||||||
|
|
||||||
|
// declare a group of options that will be allowed both on command line and in config file
|
||||||
|
boost::program_options::options_description config_options("Configuration");
|
||||||
|
config_options.add_options()(
|
||||||
|
"restrictions,r",
|
||||||
|
boost::program_options::value<boost::filesystem::path>(&contractor_config.restrictions_path),
|
||||||
|
"Restrictions file in .osrm.restrictions format")(
|
||||||
|
"profile,p", boost::program_options::value<boost::filesystem::path>(&contractor_config.profile_path)
|
||||||
|
->default_value("profile.lua"),
|
||||||
|
"Path to LUA routing profile")(
|
||||||
|
"threads,t", boost::program_options::value<unsigned int>(&contractor_config.requested_num_threads)
|
||||||
|
->default_value(tbb::task_scheduler_init::default_num_threads()),
|
||||||
|
"Number of threads to use");
|
||||||
|
|
||||||
|
// hidden options, will be allowed both on command line and in config file, but will not be
|
||||||
|
// shown to the user
|
||||||
|
boost::program_options::options_description hidden_options("Hidden options");
|
||||||
|
hidden_options.add_options()(
|
||||||
|
"input,i", boost::program_options::value<boost::filesystem::path>(&contractor_config.osrm_input_path),
|
||||||
|
"Input file in .osm, .osm.bz2 or .osm.pbf format");
|
||||||
|
|
||||||
|
// positional option
|
||||||
|
boost::program_options::positional_options_description positional_options;
|
||||||
|
positional_options.add("input", 1);
|
||||||
|
|
||||||
|
// combine above options for parsing
|
||||||
|
boost::program_options::options_description cmdline_options;
|
||||||
|
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
|
||||||
|
|
||||||
|
boost::program_options::options_description config_file_options;
|
||||||
|
config_file_options.add(config_options).add(hidden_options);
|
||||||
|
|
||||||
|
boost::program_options::options_description visible_options(
|
||||||
|
"Usage: " + boost::filesystem::basename(argv[0]) + " <input.osrm> [options]");
|
||||||
|
visible_options.add(generic_options).add(config_options);
|
||||||
|
|
||||||
|
// parse command line options
|
||||||
|
boost::program_options::variables_map option_variables;
|
||||||
|
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
|
||||||
|
.options(cmdline_options)
|
||||||
|
.positional(positional_options)
|
||||||
|
.run(),
|
||||||
|
option_variables);
|
||||||
|
|
||||||
|
const auto &temp_config_path = option_variables["config"].as<boost::filesystem::path>();
|
||||||
|
if (boost::filesystem::is_regular_file(temp_config_path))
|
||||||
|
{
|
||||||
|
boost::program_options::store(boost::program_options::parse_config_file<char>(
|
||||||
|
temp_config_path.string().c_str(), cmdline_options, true),
|
||||||
|
option_variables);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option_variables.count("version"))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << g_GIT_DESCRIPTION;
|
||||||
|
return return_code::exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option_variables.count("help"))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "\n" << visible_options;
|
||||||
|
return return_code::exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::program_options::notify(option_variables);
|
||||||
|
|
||||||
|
if (!option_variables.count("restrictions"))
|
||||||
|
{
|
||||||
|
contractor_config.restrictions_path = contractor_config.osrm_input_path.string() + ".restrictions";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!option_variables.count("input"))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "\n" << visible_options;
|
||||||
|
return return_code::fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_code::ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContractorOptions::GenerateOutputFilesNames(ContractorConfig &contractor_config)
|
||||||
|
{
|
||||||
|
contractor_config.node_output_path = contractor_config.osrm_input_path.string() + ".nodes";
|
||||||
|
contractor_config.edge_output_path = contractor_config.osrm_input_path.string() + ".edges";
|
||||||
|
contractor_config.geometry_output_path = contractor_config.osrm_input_path.string() + ".geometry";
|
||||||
|
contractor_config.graph_output_path = contractor_config.osrm_input_path.string() + ".hsgr";
|
||||||
|
contractor_config.rtree_nodes_output_path = contractor_config.osrm_input_path.string() + ".ramIndex";
|
||||||
|
contractor_config.rtree_leafs_output_path = contractor_config.osrm_input_path.string() + ".fileIndex";
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONTRACTOR_OPTIONS_HPP
|
||||||
|
#define CONTRACTOR_OPTIONS_HPP
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
enum class return_code : unsigned
|
||||||
|
{
|
||||||
|
ok,
|
||||||
|
fail,
|
||||||
|
exit
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ContractorConfig
|
||||||
|
{
|
||||||
|
ContractorConfig() noexcept : requested_num_threads(0) {}
|
||||||
|
|
||||||
|
boost::filesystem::path config_file_path;
|
||||||
|
boost::filesystem::path osrm_input_path;
|
||||||
|
boost::filesystem::path restrictions_path;
|
||||||
|
boost::filesystem::path profile_path;
|
||||||
|
|
||||||
|
std::string node_output_path;
|
||||||
|
std::string edge_output_path;
|
||||||
|
std::string geometry_output_path;
|
||||||
|
std::string graph_output_path;
|
||||||
|
std::string rtree_nodes_output_path;
|
||||||
|
std::string rtree_leafs_output_path;
|
||||||
|
|
||||||
|
unsigned requested_num_threads;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ContractorOptions
|
||||||
|
{
|
||||||
|
static return_code ParseArguments(int argc, char *argv[], ContractorConfig &extractor_config);
|
||||||
|
|
||||||
|
static void GenerateOutputFilesNames(ContractorConfig &extractor_config);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EXTRACTOR_OPTIONS_HPP
|
||||||
@@ -0,0 +1,796 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "edge_based_graph_factory.hpp"
|
||||||
|
#include "../algorithms/tiny_components.hpp"
|
||||||
|
#include "../data_structures/percent.hpp"
|
||||||
|
#include "../util/compute_angle.hpp"
|
||||||
|
#include "../util/integer_range.hpp"
|
||||||
|
#include "../util/lua_util.hpp"
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
#include "../util/timing_util.hpp"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
EdgeBasedGraphFactory::EdgeBasedGraphFactory(std::shared_ptr<NodeBasedDynamicGraph> node_based_graph,
|
||||||
|
std::shared_ptr<RestrictionMap> restriction_map,
|
||||||
|
std::unique_ptr<std::vector<NodeID>> barrier_node_list,
|
||||||
|
std::unique_ptr<std::vector<NodeID>> traffic_light_node_list,
|
||||||
|
const std::vector<QueryNode> &node_info_list,
|
||||||
|
const SpeedProfileProperties &speed_profile)
|
||||||
|
: speed_profile(speed_profile),
|
||||||
|
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
|
||||||
|
m_node_info_list(node_info_list),
|
||||||
|
m_node_based_graph(std::move(node_based_graph)),
|
||||||
|
m_restriction_map(std::move(restriction_map)), max_id(0), removed_node_count(0)
|
||||||
|
{
|
||||||
|
// insert into unordered sets for fast lookup
|
||||||
|
m_barrier_nodes.insert(barrier_node_list->begin(), barrier_node_list->end());
|
||||||
|
m_traffic_lights.insert(traffic_light_node_list->begin(), traffic_light_node_list->end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &output_edge_list)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT_MSG(0 == output_edge_list.size(), "Vector is not empty");
|
||||||
|
m_edge_based_edge_list.swap(output_edge_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EdgeBasedGraphFactory::GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes)
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
for (const EdgeBasedNode &node : m_edge_based_node_list)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(m_node_info_list.at(node.u).lat != INT_MAX);
|
||||||
|
BOOST_ASSERT(m_node_info_list.at(node.u).lon != INT_MAX);
|
||||||
|
BOOST_ASSERT(m_node_info_list.at(node.v).lon != INT_MAX);
|
||||||
|
BOOST_ASSERT(m_node_info_list.at(node.v).lat != INT_MAX);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
nodes.swap(m_edge_based_node_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
|
||||||
|
const NodeID node_v,
|
||||||
|
const unsigned component_id)
|
||||||
|
{
|
||||||
|
// merge edges together into one EdgeBasedNode
|
||||||
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
|
|
||||||
|
// find forward edge id and
|
||||||
|
const EdgeID edge_id_1 = m_node_based_graph->FindEdge(node_u, node_v);
|
||||||
|
BOOST_ASSERT(edge_id_1 != SPECIAL_EDGEID);
|
||||||
|
|
||||||
|
const EdgeData &forward_data = m_node_based_graph->GetEdgeData(edge_id_1);
|
||||||
|
|
||||||
|
// find reverse edge id and
|
||||||
|
const EdgeID edge_id_2 = m_node_based_graph->FindEdge(node_v, node_u);
|
||||||
|
BOOST_ASSERT(edge_id_2 != SPECIAL_EDGEID);
|
||||||
|
|
||||||
|
const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(edge_id_2);
|
||||||
|
|
||||||
|
if (forward_data.edgeBasedNodeID == SPECIAL_NODEID &&
|
||||||
|
reverse_data.edgeBasedNodeID == SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(m_geometry_compressor.HasEntryForID(edge_id_1) ==
|
||||||
|
m_geometry_compressor.HasEntryForID(edge_id_2));
|
||||||
|
if (m_geometry_compressor.HasEntryForID(edge_id_1))
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(m_geometry_compressor.HasEntryForID(edge_id_2));
|
||||||
|
|
||||||
|
// reconstruct geometry and put in each individual edge with its offset
|
||||||
|
const std::vector<GeometryCompressor::CompressedNode> &forward_geometry =
|
||||||
|
m_geometry_compressor.GetBucketReference(edge_id_1);
|
||||||
|
const std::vector<GeometryCompressor::CompressedNode> &reverse_geometry =
|
||||||
|
m_geometry_compressor.GetBucketReference(edge_id_2);
|
||||||
|
BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size());
|
||||||
|
BOOST_ASSERT(0 != forward_geometry.size());
|
||||||
|
const unsigned geometry_size = static_cast<unsigned>(forward_geometry.size());
|
||||||
|
BOOST_ASSERT(geometry_size > 1);
|
||||||
|
|
||||||
|
// reconstruct bidirectional edge with individual weights and put each into the NN index
|
||||||
|
|
||||||
|
std::vector<int> forward_dist_prefix_sum(forward_geometry.size(), 0);
|
||||||
|
std::vector<int> reverse_dist_prefix_sum(reverse_geometry.size(), 0);
|
||||||
|
|
||||||
|
// quick'n'dirty prefix sum as std::partial_sum needs addtional casts
|
||||||
|
// TODO: move to lambda function with C++11
|
||||||
|
int temp_sum = 0;
|
||||||
|
|
||||||
|
for (const auto i : osrm::irange(0u, geometry_size))
|
||||||
|
{
|
||||||
|
forward_dist_prefix_sum[i] = temp_sum;
|
||||||
|
temp_sum += forward_geometry[i].second;
|
||||||
|
|
||||||
|
BOOST_ASSERT(forward_data.distance >= temp_sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
temp_sum = 0;
|
||||||
|
for (const auto i : osrm::irange(0u, geometry_size))
|
||||||
|
{
|
||||||
|
temp_sum += reverse_geometry[reverse_geometry.size() - 1 - i].second;
|
||||||
|
reverse_dist_prefix_sum[i] = reverse_data.distance - temp_sum;
|
||||||
|
// BOOST_ASSERT(reverse_data.distance >= temp_sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeID current_edge_source_coordinate_id = node_u;
|
||||||
|
|
||||||
|
if (SPECIAL_NODEID != forward_data.edgeBasedNodeID)
|
||||||
|
{
|
||||||
|
max_id = std::max(forward_data.edgeBasedNodeID, max_id);
|
||||||
|
}
|
||||||
|
if (SPECIAL_NODEID != reverse_data.edgeBasedNodeID)
|
||||||
|
{
|
||||||
|
max_id = std::max(reverse_data.edgeBasedNodeID, max_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// traverse arrays from start and end respectively
|
||||||
|
for (const auto i : osrm::irange(0u, geometry_size))
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(current_edge_source_coordinate_id ==
|
||||||
|
reverse_geometry[geometry_size - 1 - i].first);
|
||||||
|
const NodeID current_edge_target_coordinate_id = forward_geometry[i].first;
|
||||||
|
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
|
||||||
|
|
||||||
|
// build edges
|
||||||
|
m_edge_based_node_list.emplace_back(
|
||||||
|
forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID,
|
||||||
|
current_edge_source_coordinate_id, current_edge_target_coordinate_id,
|
||||||
|
forward_data.nameID, forward_geometry[i].second,
|
||||||
|
reverse_geometry[geometry_size - 1 - i].second, forward_dist_prefix_sum[i],
|
||||||
|
reverse_dist_prefix_sum[i], m_geometry_compressor.GetPositionForID(edge_id_1),
|
||||||
|
component_id, i, forward_data.travel_mode, reverse_data.travel_mode);
|
||||||
|
current_edge_source_coordinate_id = current_edge_target_coordinate_id;
|
||||||
|
|
||||||
|
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
|
||||||
|
|
||||||
|
BOOST_ASSERT(node_u != m_edge_based_node_list.back().u ||
|
||||||
|
node_v != m_edge_based_node_list.back().v);
|
||||||
|
|
||||||
|
BOOST_ASSERT(node_u != m_edge_based_node_list.back().v ||
|
||||||
|
node_v != m_edge_based_node_list.back().u);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(current_edge_source_coordinate_id == node_v);
|
||||||
|
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(!m_geometry_compressor.HasEntryForID(edge_id_2));
|
||||||
|
|
||||||
|
if (forward_data.edgeBasedNodeID != SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(forward_data.forward);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(!forward_data.forward);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reverse_data.edgeBasedNodeID != SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(reverse_data.forward);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(!reverse_data.forward);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(forward_data.edgeBasedNodeID != SPECIAL_NODEID ||
|
||||||
|
reverse_data.edgeBasedNodeID != SPECIAL_NODEID);
|
||||||
|
|
||||||
|
m_edge_based_node_list.emplace_back(
|
||||||
|
forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID, node_u, node_v,
|
||||||
|
forward_data.nameID, forward_data.distance, reverse_data.distance, 0, 0, SPECIAL_EDGEID,
|
||||||
|
component_id, 0, forward_data.travel_mode, reverse_data.travel_mode);
|
||||||
|
BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EdgeBasedGraphFactory::FlushVectorToStream(
|
||||||
|
std::ofstream &edge_data_file, std::vector<OriginalEdgeData> &original_edge_data_vector) const
|
||||||
|
{
|
||||||
|
if (original_edge_data_vector.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
edge_data_file.write((char *)&(original_edge_data_vector[0]),
|
||||||
|
original_edge_data_vector.size() * sizeof(OriginalEdgeData));
|
||||||
|
original_edge_data_vector.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
|
||||||
|
const std::string &geometry_filename,
|
||||||
|
lua_State *lua_state)
|
||||||
|
{
|
||||||
|
TIMER_START(geometry);
|
||||||
|
CompressGeometry();
|
||||||
|
TIMER_STOP(geometry);
|
||||||
|
|
||||||
|
TIMER_START(renumber);
|
||||||
|
RenumberEdges();
|
||||||
|
TIMER_STOP(renumber);
|
||||||
|
|
||||||
|
TIMER_START(generate_nodes);
|
||||||
|
GenerateEdgeExpandedNodes();
|
||||||
|
TIMER_STOP(generate_nodes);
|
||||||
|
|
||||||
|
TIMER_START(generate_edges);
|
||||||
|
GenerateEdgeExpandedEdges(original_edge_data_filename, lua_state);
|
||||||
|
TIMER_STOP(generate_edges);
|
||||||
|
|
||||||
|
m_geometry_compressor.SerializeInternalVector(geometry_filename);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Timing statistics for edge-expanded graph:";
|
||||||
|
SimpleLogger().Write() << "Geometry compression: " << TIMER_SEC(geometry) << "s";
|
||||||
|
SimpleLogger().Write() << "Renumbering edges: " << TIMER_SEC(renumber) << "s";
|
||||||
|
SimpleLogger().Write() << "Generating nodes: " << TIMER_SEC(generate_nodes) << "s";
|
||||||
|
SimpleLogger().Write() << "Generating edges: " << TIMER_SEC(generate_edges) << "s";
|
||||||
|
}
|
||||||
|
|
||||||
|
void EdgeBasedGraphFactory::CompressGeometry()
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "Removing graph geometry while preserving topology";
|
||||||
|
|
||||||
|
const unsigned original_number_of_nodes = m_node_based_graph->GetNumberOfNodes();
|
||||||
|
const unsigned original_number_of_edges = m_node_based_graph->GetNumberOfEdges();
|
||||||
|
|
||||||
|
Percent progress(original_number_of_nodes);
|
||||||
|
|
||||||
|
for (const NodeID node_v : osrm::irange(0u, original_number_of_nodes))
|
||||||
|
{
|
||||||
|
progress.printStatus(node_v);
|
||||||
|
|
||||||
|
// only contract degree 2 vertices
|
||||||
|
if (2 != m_node_based_graph->GetOutDegree(node_v))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't contract barrier node
|
||||||
|
if (m_barrier_nodes.end() != m_barrier_nodes.find(node_v))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if v is a via node for a turn restriction, i.e. a 'directed' barrier node
|
||||||
|
if (m_restriction_map->IsViaNode(node_v))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* reverse_e2 forward_e2
|
||||||
|
* u <---------- v -----------> w
|
||||||
|
* ----------> <-----------
|
||||||
|
* forward_e1 reverse_e1
|
||||||
|
*
|
||||||
|
* Will be compressed to:
|
||||||
|
*
|
||||||
|
* reverse_e1
|
||||||
|
* u <---------- w
|
||||||
|
* ---------->
|
||||||
|
* forward_e1
|
||||||
|
*
|
||||||
|
* If the edges are compatible.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
const bool reverse_edge_order =
|
||||||
|
!(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(node_v)).forward);
|
||||||
|
const EdgeID forward_e2 = m_node_based_graph->BeginEdges(node_v) + reverse_edge_order;
|
||||||
|
BOOST_ASSERT(SPECIAL_EDGEID != forward_e2);
|
||||||
|
BOOST_ASSERT(forward_e2 >= m_node_based_graph->BeginEdges(node_v) &&
|
||||||
|
forward_e2 < m_node_based_graph->EndEdges(node_v));
|
||||||
|
const EdgeID reverse_e2 = m_node_based_graph->BeginEdges(node_v) + 1 - reverse_edge_order;
|
||||||
|
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2);
|
||||||
|
BOOST_ASSERT(reverse_e2 >= m_node_based_graph->BeginEdges(node_v) &&
|
||||||
|
reverse_e2 < m_node_based_graph->EndEdges(node_v));
|
||||||
|
|
||||||
|
const EdgeData &fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2);
|
||||||
|
const EdgeData &rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2);
|
||||||
|
|
||||||
|
const NodeID node_w = m_node_based_graph->GetTarget(forward_e2);
|
||||||
|
BOOST_ASSERT(SPECIAL_NODEID != node_w);
|
||||||
|
BOOST_ASSERT(node_v != node_w);
|
||||||
|
const NodeID node_u = m_node_based_graph->GetTarget(reverse_e2);
|
||||||
|
BOOST_ASSERT(SPECIAL_NODEID != node_u);
|
||||||
|
BOOST_ASSERT(node_u != node_v);
|
||||||
|
|
||||||
|
const EdgeID forward_e1 = m_node_based_graph->FindEdge(node_u, node_v);
|
||||||
|
BOOST_ASSERT(SPECIAL_EDGEID != forward_e1);
|
||||||
|
BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(forward_e1));
|
||||||
|
const EdgeID reverse_e1 = m_node_based_graph->FindEdge(node_w, node_v);
|
||||||
|
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e1);
|
||||||
|
BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(reverse_e1));
|
||||||
|
|
||||||
|
const EdgeData &fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1);
|
||||||
|
const EdgeData &rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1);
|
||||||
|
|
||||||
|
if (m_node_based_graph->FindEdgeInEitherDirection(node_u, node_w) != SPECIAL_EDGEID)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this case can happen if two ways with different names overlap
|
||||||
|
if (fwd_edge_data1.nameID != rev_edge_data1.nameID ||
|
||||||
|
fwd_edge_data2.nameID != rev_edge_data2.nameID)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fwd_edge_data1.IsCompatibleTo(fwd_edge_data2) && rev_edge_data1.IsCompatibleTo(rev_edge_data2))
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
|
||||||
|
m_node_based_graph->GetEdgeData(reverse_e1).nameID);
|
||||||
|
BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e2).nameID ==
|
||||||
|
m_node_based_graph->GetEdgeData(reverse_e2).nameID);
|
||||||
|
|
||||||
|
// Get distances before graph is modified
|
||||||
|
const int forward_weight1 = m_node_based_graph->GetEdgeData(forward_e1).distance;
|
||||||
|
const int forward_weight2 = m_node_based_graph->GetEdgeData(forward_e2).distance;
|
||||||
|
|
||||||
|
BOOST_ASSERT(0 != forward_weight1);
|
||||||
|
BOOST_ASSERT(0 != forward_weight2);
|
||||||
|
|
||||||
|
const int reverse_weight1 = m_node_based_graph->GetEdgeData(reverse_e1).distance;
|
||||||
|
const int reverse_weight2 = m_node_based_graph->GetEdgeData(reverse_e2).distance;
|
||||||
|
|
||||||
|
BOOST_ASSERT(0 != reverse_weight1);
|
||||||
|
BOOST_ASSERT(0 != reverse_weight2);
|
||||||
|
|
||||||
|
const bool has_node_penalty = m_traffic_lights.find(node_v) != m_traffic_lights.end();
|
||||||
|
|
||||||
|
// add weight of e2's to e1
|
||||||
|
m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
|
||||||
|
m_node_based_graph->GetEdgeData(reverse_e1).distance += rev_edge_data2.distance;
|
||||||
|
if (has_node_penalty)
|
||||||
|
{
|
||||||
|
m_node_based_graph->GetEdgeData(forward_e1).distance +=
|
||||||
|
speed_profile.traffic_signal_penalty;
|
||||||
|
m_node_based_graph->GetEdgeData(reverse_e1).distance +=
|
||||||
|
speed_profile.traffic_signal_penalty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extend e1's to targets of e2's
|
||||||
|
m_node_based_graph->SetTarget(forward_e1, node_w);
|
||||||
|
m_node_based_graph->SetTarget(reverse_e1, node_u);
|
||||||
|
|
||||||
|
// remove e2's (if bidir, otherwise only one)
|
||||||
|
m_node_based_graph->DeleteEdge(node_v, forward_e2);
|
||||||
|
m_node_based_graph->DeleteEdge(node_v, reverse_e2);
|
||||||
|
|
||||||
|
// update any involved turn restrictions
|
||||||
|
m_restriction_map->FixupStartingTurnRestriction(node_u, node_v, node_w);
|
||||||
|
m_restriction_map->FixupArrivingTurnRestriction(node_u, node_v, node_w,
|
||||||
|
*m_node_based_graph);
|
||||||
|
|
||||||
|
m_restriction_map->FixupStartingTurnRestriction(node_w, node_v, node_u);
|
||||||
|
m_restriction_map->FixupArrivingTurnRestriction(node_w, node_v, node_u,
|
||||||
|
*m_node_based_graph);
|
||||||
|
|
||||||
|
// store compressed geometry in container
|
||||||
|
m_geometry_compressor.CompressEdge(
|
||||||
|
forward_e1, forward_e2, node_v, node_w,
|
||||||
|
forward_weight1 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0),
|
||||||
|
forward_weight2);
|
||||||
|
m_geometry_compressor.CompressEdge(
|
||||||
|
reverse_e1, reverse_e2, node_v, node_u, reverse_weight1,
|
||||||
|
reverse_weight2 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0));
|
||||||
|
++removed_node_count;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SimpleLogger().Write() << "removed " << removed_node_count << " nodes";
|
||||||
|
m_geometry_compressor.PrintStatistics();
|
||||||
|
|
||||||
|
unsigned new_node_count = 0;
|
||||||
|
unsigned new_edge_count = 0;
|
||||||
|
|
||||||
|
for (const auto i : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||||
|
{
|
||||||
|
if (m_node_based_graph->GetOutDegree(i) > 0)
|
||||||
|
{
|
||||||
|
++new_node_count;
|
||||||
|
new_edge_count += (m_node_based_graph->EndEdges(i) - m_node_based_graph->BeginEdges(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SimpleLogger().Write() << "new nodes: " << new_node_count << ", edges " << new_edge_count;
|
||||||
|
SimpleLogger().Write() << "Node compression ratio: "
|
||||||
|
<< new_node_count / (double)original_number_of_nodes;
|
||||||
|
SimpleLogger().Write() << "Edge compression ratio: "
|
||||||
|
<< new_edge_count / (double)original_number_of_edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Renumbers all _forward_ edges and sets the edgeBasedNodeID.
|
||||||
|
/// A specific numbering is not important. Any unique ID will do.
|
||||||
|
void EdgeBasedGraphFactory::RenumberEdges()
|
||||||
|
{
|
||||||
|
// renumber edge based node of outgoing edges
|
||||||
|
unsigned numbered_edges_count = 0;
|
||||||
|
for (const auto current_node : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||||
|
{
|
||||||
|
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(current_node))
|
||||||
|
{
|
||||||
|
EdgeData &edge_data = m_node_based_graph->GetEdgeData(current_edge);
|
||||||
|
|
||||||
|
// this edge is an incoming edge
|
||||||
|
if (!edge_data.forward)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges());
|
||||||
|
edge_data.edgeBasedNodeID = numbered_edges_count;
|
||||||
|
++numbered_edges_count;
|
||||||
|
|
||||||
|
BOOST_ASSERT(SPECIAL_NODEID != edge_data.edgeBasedNodeID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_number_of_edge_based_nodes = numbered_edges_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the nodes in the edge expanded graph from edges in the node-based graph.
|
||||||
|
*/
|
||||||
|
void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "Identifying components of the (compressed) road network";
|
||||||
|
|
||||||
|
// Run a BFS on the undirected graph and identify small components
|
||||||
|
TarjanSCC<NodeBasedDynamicGraph> component_explorer(m_node_based_graph, *m_restriction_map,
|
||||||
|
m_barrier_nodes);
|
||||||
|
|
||||||
|
component_explorer.run();
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "identified: "
|
||||||
|
<< component_explorer.get_number_of_components() - removed_node_count
|
||||||
|
<< " (compressed) components";
|
||||||
|
SimpleLogger().Write() << "identified "
|
||||||
|
<< component_explorer.get_size_one_count() - removed_node_count
|
||||||
|
<< " (compressed) SCCs of size 1";
|
||||||
|
SimpleLogger().Write() << "generating edge-expanded nodes";
|
||||||
|
|
||||||
|
Percent progress(m_node_based_graph->GetNumberOfNodes());
|
||||||
|
|
||||||
|
// loop over all edges and generate new set of nodes
|
||||||
|
for (const auto node_u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_u < m_node_based_graph->GetNumberOfNodes());
|
||||||
|
progress.printStatus(node_u);
|
||||||
|
for (EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(node_u))
|
||||||
|
{
|
||||||
|
const EdgeData &edge_data = m_node_based_graph->GetEdgeData(e1);
|
||||||
|
BOOST_ASSERT(e1 != SPECIAL_EDGEID);
|
||||||
|
const NodeID node_v = m_node_based_graph->GetTarget(e1);
|
||||||
|
|
||||||
|
BOOST_ASSERT(SPECIAL_NODEID != node_v);
|
||||||
|
// pick only every other edge, since we have every edge as an outgoing
|
||||||
|
// and incoming egde
|
||||||
|
if (node_u > node_v)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(node_u < node_v);
|
||||||
|
|
||||||
|
// Note: edges that end on barrier nodes or on a turn restriction
|
||||||
|
// may actually be in two distinct components. We choose the smallest
|
||||||
|
const unsigned size_of_component =
|
||||||
|
std::min(component_explorer.get_component_size(node_u),
|
||||||
|
component_explorer.get_component_size(node_v));
|
||||||
|
|
||||||
|
const unsigned id_of_smaller_component = [node_u, node_v, &component_explorer]
|
||||||
|
{
|
||||||
|
if (component_explorer.get_component_size(node_u) <
|
||||||
|
component_explorer.get_component_size(node_v))
|
||||||
|
{
|
||||||
|
return component_explorer.get_component_id(node_u);
|
||||||
|
}
|
||||||
|
return component_explorer.get_component_id(node_v);
|
||||||
|
}();
|
||||||
|
|
||||||
|
const bool component_is_tiny = size_of_component < 1000;
|
||||||
|
|
||||||
|
// we only set edgeBasedNodeID for forward edges
|
||||||
|
if (edge_data.edgeBasedNodeID == SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
InsertEdgeBasedNode(node_v, node_u,
|
||||||
|
(component_is_tiny ? id_of_smaller_component + 1 : 0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InsertEdgeBasedNode(node_u, node_v,
|
||||||
|
(component_is_tiny ? id_of_smaller_component + 1 : 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size()
|
||||||
|
<< " nodes in edge-expanded graph";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actually it also generates OriginalEdgeData and serializes them...
|
||||||
|
*/
|
||||||
|
void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||||
|
const std::string &original_edge_data_filename, lua_State *lua_state)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "generating edge-expanded edges";
|
||||||
|
|
||||||
|
unsigned node_based_edge_counter = 0;
|
||||||
|
unsigned original_edges_counter = 0;
|
||||||
|
|
||||||
|
std::ofstream edge_data_file(original_edge_data_filename.c_str(), std::ios::binary);
|
||||||
|
|
||||||
|
// writes a dummy value that is updated later
|
||||||
|
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
|
||||||
|
|
||||||
|
std::vector<OriginalEdgeData> original_edge_data_vector;
|
||||||
|
original_edge_data_vector.reserve(1024 * 1024);
|
||||||
|
|
||||||
|
// Loop over all turns and generate new set of edges.
|
||||||
|
// Three nested loop look super-linear, but we are dealing with a (kind of)
|
||||||
|
// linear number of turns only.
|
||||||
|
unsigned restricted_turns_counter = 0;
|
||||||
|
unsigned skipped_uturns_counter = 0;
|
||||||
|
unsigned skipped_barrier_turns_counter = 0;
|
||||||
|
unsigned compressed = 0;
|
||||||
|
|
||||||
|
Percent progress(m_node_based_graph->GetNumberOfNodes());
|
||||||
|
|
||||||
|
for (const auto node_u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||||
|
{
|
||||||
|
progress.printStatus(node_u);
|
||||||
|
for (const EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(node_u))
|
||||||
|
{
|
||||||
|
if (!m_node_based_graph->GetEdgeData(e1).forward)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
++node_based_edge_counter;
|
||||||
|
const NodeID node_v = m_node_based_graph->GetTarget(e1);
|
||||||
|
const NodeID only_restriction_to_node =
|
||||||
|
m_restriction_map->CheckForEmanatingIsOnlyTurn(node_u, node_v);
|
||||||
|
const bool is_barrier_node = m_barrier_nodes.find(node_v) != m_barrier_nodes.end();
|
||||||
|
|
||||||
|
for (const EdgeID e2 : m_node_based_graph->GetAdjacentEdgeRange(node_v))
|
||||||
|
{
|
||||||
|
if (!m_node_based_graph->GetEdgeData(e2).forward)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const NodeID node_w = m_node_based_graph->GetTarget(e2);
|
||||||
|
|
||||||
|
if ((only_restriction_to_node != SPECIAL_NODEID) &&
|
||||||
|
(node_w != only_restriction_to_node))
|
||||||
|
{
|
||||||
|
// We are at an only_-restriction but not at the right turn.
|
||||||
|
++restricted_turns_counter;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_barrier_node)
|
||||||
|
{
|
||||||
|
if (node_u != node_w)
|
||||||
|
{
|
||||||
|
++skipped_barrier_turns_counter;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((node_u == node_w) && (m_node_based_graph->GetOutDegree(node_v) > 1))
|
||||||
|
{
|
||||||
|
++skipped_uturns_counter;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// only add an edge if turn is not a U-turn except when it is
|
||||||
|
// at the end of a dead-end street
|
||||||
|
if (m_restriction_map->CheckIfTurnIsRestricted(node_u, node_v, node_w) &&
|
||||||
|
(only_restriction_to_node == SPECIAL_NODEID) &&
|
||||||
|
(node_w != only_restriction_to_node))
|
||||||
|
{
|
||||||
|
// We are at an only_-restriction but not at the right turn.
|
||||||
|
++restricted_turns_counter;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only add an edge if turn is not prohibited
|
||||||
|
const EdgeData &edge_data1 = m_node_based_graph->GetEdgeData(e1);
|
||||||
|
const EdgeData &edge_data2 = m_node_based_graph->GetEdgeData(e2);
|
||||||
|
|
||||||
|
BOOST_ASSERT(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
|
||||||
|
BOOST_ASSERT(edge_data1.forward);
|
||||||
|
BOOST_ASSERT(edge_data2.forward);
|
||||||
|
|
||||||
|
// the following is the core of the loop.
|
||||||
|
unsigned distance = edge_data1.distance;
|
||||||
|
if (m_traffic_lights.find(node_v) != m_traffic_lights.end())
|
||||||
|
{
|
||||||
|
distance += speed_profile.traffic_signal_penalty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unpack last node of first segment if packed
|
||||||
|
const auto first_coordinate =
|
||||||
|
m_node_info_list[(m_geometry_compressor.HasEntryForID(e1)
|
||||||
|
? m_geometry_compressor.GetLastNodeIDOfBucket(e1)
|
||||||
|
: node_u)];
|
||||||
|
|
||||||
|
// unpack first node of second segment if packed
|
||||||
|
const auto third_coordinate =
|
||||||
|
m_node_info_list[(m_geometry_compressor.HasEntryForID(e2)
|
||||||
|
? m_geometry_compressor.GetFirstNodeIDOfBucket(e2)
|
||||||
|
: node_w)];
|
||||||
|
|
||||||
|
const double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates(
|
||||||
|
first_coordinate, m_node_info_list[node_v], third_coordinate);
|
||||||
|
|
||||||
|
const int turn_penalty = GetTurnPenalty(turn_angle, lua_state);
|
||||||
|
TurnInstruction turn_instruction = AnalyzeTurn(node_u, node_v, node_w, turn_angle);
|
||||||
|
if (turn_instruction == TurnInstruction::UTurn)
|
||||||
|
{
|
||||||
|
distance += speed_profile.u_turn_penalty;
|
||||||
|
}
|
||||||
|
distance += turn_penalty;
|
||||||
|
|
||||||
|
const bool edge_is_compressed = m_geometry_compressor.HasEntryForID(e1);
|
||||||
|
|
||||||
|
if (edge_is_compressed)
|
||||||
|
{
|
||||||
|
++compressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
original_edge_data_vector.emplace_back(
|
||||||
|
(edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : node_v),
|
||||||
|
edge_data1.nameID, turn_instruction, edge_is_compressed,
|
||||||
|
edge_data2.travel_mode);
|
||||||
|
|
||||||
|
++original_edges_counter;
|
||||||
|
|
||||||
|
if (original_edge_data_vector.size() > 1024 * 1024 * 10)
|
||||||
|
{
|
||||||
|
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(SPECIAL_NODEID != edge_data1.edgeBasedNodeID);
|
||||||
|
BOOST_ASSERT(SPECIAL_NODEID != edge_data2.edgeBasedNodeID);
|
||||||
|
|
||||||
|
m_edge_based_edge_list.emplace_back(
|
||||||
|
EdgeBasedEdge(edge_data1.edgeBasedNodeID, edge_data2.edgeBasedNodeID,
|
||||||
|
m_edge_based_edge_list.size(), distance, true, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
||||||
|
|
||||||
|
edge_data_file.seekp(std::ios::beg);
|
||||||
|
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
|
||||||
|
edge_data_file.close();
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " edge based nodes";
|
||||||
|
SimpleLogger().Write() << "Node-based graph contains " << node_based_edge_counter << " edges";
|
||||||
|
SimpleLogger().Write() << "Edge-expanded graph ...";
|
||||||
|
SimpleLogger().Write() << " contains " << m_edge_based_edge_list.size() << " edges";
|
||||||
|
SimpleLogger().Write() << " skips " << restricted_turns_counter << " turns, "
|
||||||
|
"defined by "
|
||||||
|
<< m_restriction_map->size() << " restrictions";
|
||||||
|
SimpleLogger().Write() << " skips " << skipped_uturns_counter << " U turns";
|
||||||
|
SimpleLogger().Write() << " skips " << skipped_barrier_turns_counter << " turns over barriers";
|
||||||
|
}
|
||||||
|
|
||||||
|
int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) const
|
||||||
|
{
|
||||||
|
|
||||||
|
if (speed_profile.has_turn_penalty_function)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// call lua profile to compute turn penalty
|
||||||
|
return luabind::call_function<int>(lua_state, "turn_function", 180. - angle);
|
||||||
|
}
|
||||||
|
catch (const luabind::error &er)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << er.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID node_u,
|
||||||
|
const NodeID node_v,
|
||||||
|
const NodeID node_w,
|
||||||
|
const double angle) const
|
||||||
|
{
|
||||||
|
if (node_u == node_w)
|
||||||
|
{
|
||||||
|
return TurnInstruction::UTurn;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EdgeID edge1 = m_node_based_graph->FindEdge(node_u, node_v);
|
||||||
|
const EdgeID edge2 = m_node_based_graph->FindEdge(node_v, node_w);
|
||||||
|
|
||||||
|
const EdgeData &data1 = m_node_based_graph->GetEdgeData(edge1);
|
||||||
|
const EdgeData &data2 = m_node_based_graph->GetEdgeData(edge2);
|
||||||
|
|
||||||
|
// roundabouts need to be handled explicitely
|
||||||
|
if (data1.roundabout && data2.roundabout)
|
||||||
|
{
|
||||||
|
// Is a turn possible? If yes, we stay on the roundabout!
|
||||||
|
if (1 == m_node_based_graph->GetDirectedOutDegree(node_v))
|
||||||
|
{
|
||||||
|
// No turn possible.
|
||||||
|
return TurnInstruction::NoTurn;
|
||||||
|
}
|
||||||
|
return TurnInstruction::StayOnRoundAbout;
|
||||||
|
}
|
||||||
|
// Does turn start or end on roundabout?
|
||||||
|
if (data1.roundabout || data2.roundabout)
|
||||||
|
{
|
||||||
|
// We are entering the roundabout
|
||||||
|
if ((!data1.roundabout) && data2.roundabout)
|
||||||
|
{
|
||||||
|
return TurnInstruction::EnterRoundAbout;
|
||||||
|
}
|
||||||
|
// We are leaving the roundabout
|
||||||
|
if (data1.roundabout && (!data2.roundabout))
|
||||||
|
{
|
||||||
|
return TurnInstruction::LeaveRoundAbout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If street names stay the same and if we are certain that it is not a
|
||||||
|
// a segment of a roundabout, we skip it.
|
||||||
|
if (data1.nameID == data2.nameID)
|
||||||
|
{
|
||||||
|
// TODO: Here we should also do a small graph exploration to check for
|
||||||
|
// more complex situations
|
||||||
|
if (0 != data1.nameID || m_node_based_graph->GetOutDegree(node_v) <= 2)
|
||||||
|
{
|
||||||
|
return TurnInstruction::NoTurn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned EdgeBasedGraphFactory::GetNumberOfEdgeBasedNodes() const
|
||||||
|
{
|
||||||
|
return m_number_of_edge_based_nodes;
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This class constructs the edge-expanded routing graph
|
||||||
|
|
||||||
|
#ifndef EDGE_BASED_GRAPH_FACTORY_HPP_
|
||||||
|
#define EDGE_BASED_GRAPH_FACTORY_HPP_
|
||||||
|
|
||||||
|
#include "geometry_compressor.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "../data_structures/deallocating_vector.hpp"
|
||||||
|
#include "../data_structures/edge_based_node.hpp"
|
||||||
|
#include "../data_structures/original_edge_data.hpp"
|
||||||
|
#include "../data_structures/query_node.hpp"
|
||||||
|
#include "../data_structures/turn_instructions.hpp"
|
||||||
|
#include "../data_structures/node_based_graph.hpp"
|
||||||
|
#include "../data_structures/restriction_map.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <memory>
|
||||||
|
#include <queue>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct lua_State;
|
||||||
|
|
||||||
|
class EdgeBasedGraphFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EdgeBasedGraphFactory() = delete;
|
||||||
|
EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
|
||||||
|
|
||||||
|
struct SpeedProfileProperties;
|
||||||
|
|
||||||
|
explicit EdgeBasedGraphFactory(std::shared_ptr<NodeBasedDynamicGraph> node_based_graph,
|
||||||
|
std::shared_ptr<RestrictionMap> restricion_map,
|
||||||
|
std::unique_ptr<std::vector<NodeID>> barrier_node_list,
|
||||||
|
std::unique_ptr<std::vector<NodeID>> traffic_light_node_list,
|
||||||
|
const std::vector<QueryNode> &node_info_list,
|
||||||
|
const SpeedProfileProperties &speed_profile);
|
||||||
|
|
||||||
|
void Run(const std::string &original_edge_data_filename,
|
||||||
|
const std::string &geometry_filename,
|
||||||
|
lua_State *lua_state);
|
||||||
|
|
||||||
|
void GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &edges);
|
||||||
|
|
||||||
|
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
|
||||||
|
|
||||||
|
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, const double angle) const;
|
||||||
|
|
||||||
|
int GetTurnPenalty(double angle, lua_State *lua_state) const;
|
||||||
|
|
||||||
|
unsigned GetNumberOfEdgeBasedNodes() const;
|
||||||
|
|
||||||
|
struct SpeedProfileProperties
|
||||||
|
{
|
||||||
|
SpeedProfileProperties()
|
||||||
|
: traffic_signal_penalty(0), u_turn_penalty(0), has_turn_penalty_function(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int traffic_signal_penalty;
|
||||||
|
int u_turn_penalty;
|
||||||
|
bool has_turn_penalty_function;
|
||||||
|
} speed_profile;
|
||||||
|
|
||||||
|
private:
|
||||||
|
using EdgeData = NodeBasedDynamicGraph::EdgeData;
|
||||||
|
|
||||||
|
unsigned m_number_of_edge_based_nodes;
|
||||||
|
|
||||||
|
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
||||||
|
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
||||||
|
|
||||||
|
const std::vector<QueryNode>& m_node_info_list;
|
||||||
|
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
|
||||||
|
std::shared_ptr<RestrictionMap> m_restriction_map;
|
||||||
|
|
||||||
|
std::unordered_set<NodeID> m_barrier_nodes;
|
||||||
|
std::unordered_set<NodeID> m_traffic_lights;
|
||||||
|
|
||||||
|
|
||||||
|
GeometryCompressor m_geometry_compressor;
|
||||||
|
|
||||||
|
void CompressGeometry();
|
||||||
|
void RenumberEdges();
|
||||||
|
void GenerateEdgeExpandedNodes();
|
||||||
|
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
|
||||||
|
lua_State *lua_state);
|
||||||
|
|
||||||
|
void InsertEdgeBasedNode(const NodeID u, const NodeID v, const unsigned component_id);
|
||||||
|
|
||||||
|
void FlushVectorToStream(std::ofstream &edge_data_file,
|
||||||
|
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
||||||
|
|
||||||
|
NodeID max_id;
|
||||||
|
std::size_t removed_node_count;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* EDGE_BASED_GRAPH_FACTORY_HPP_ */
|
||||||
@@ -1,5 +1,32 @@
|
|||||||
#include "extractor/compressed_edge_container.hpp"
|
/*
|
||||||
#include "util/simple_logger.hpp"
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "geometry_compressor.hpp"
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
@@ -8,20 +35,13 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <iostream>
|
GeometryCompressor::GeometryCompressor()
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace extractor
|
|
||||||
{
|
|
||||||
|
|
||||||
CompressedEdgeContainer::CompressedEdgeContainer()
|
|
||||||
{
|
{
|
||||||
m_free_list.reserve(100);
|
m_free_list.reserve(100);
|
||||||
IncreaseFreeList();
|
IncreaseFreeList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompressedEdgeContainer::IncreaseFreeList()
|
void GeometryCompressor::IncreaseFreeList()
|
||||||
{
|
{
|
||||||
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
|
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
|
||||||
for (unsigned i = 100; i > 0; --i)
|
for (unsigned i = 100; i > 0; --i)
|
||||||
@@ -31,13 +51,13 @@ void CompressedEdgeContainer::IncreaseFreeList()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CompressedEdgeContainer::HasEntryForID(const EdgeID edge_id) const
|
bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
|
||||||
{
|
{
|
||||||
auto iter = m_edge_id_to_list_index_map.find(edge_id);
|
auto iter = m_edge_id_to_list_index_map.find(edge_id);
|
||||||
return iter != m_edge_id_to_list_index_map.end();
|
return iter != m_edge_id_to_list_index_map.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned CompressedEdgeContainer::GetPositionForID(const EdgeID edge_id) const
|
unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
|
||||||
{
|
{
|
||||||
auto map_iterator = m_edge_id_to_list_index_map.find(edge_id);
|
auto map_iterator = m_edge_id_to_list_index_map.find(edge_id);
|
||||||
BOOST_ASSERT(map_iterator != m_edge_id_to_list_index_map.end());
|
BOOST_ASSERT(map_iterator != m_edge_id_to_list_index_map.end());
|
||||||
@@ -45,7 +65,7 @@ unsigned CompressedEdgeContainer::GetPositionForID(const EdgeID edge_id) const
|
|||||||
return map_iterator->second;
|
return map_iterator->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompressedEdgeContainer::SerializeInternalVector(const std::string &path) const
|
void GeometryCompressor::SerializeInternalVector(const std::string &path) const
|
||||||
{
|
{
|
||||||
|
|
||||||
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary | std::ios::out);
|
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary | std::ios::out);
|
||||||
@@ -59,7 +79,7 @@ void CompressedEdgeContainer::SerializeInternalVector(const std::string &path) c
|
|||||||
{
|
{
|
||||||
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
||||||
|
|
||||||
const std::vector<CompressedEdge> ¤t_vector = elem;
|
const std::vector<CompressedNode> ¤t_vector = elem;
|
||||||
const unsigned unpacked_size = current_vector.size();
|
const unsigned unpacked_size = current_vector.size();
|
||||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != unpacked_size);
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != unpacked_size);
|
||||||
prefix_sum_of_list_indices += unpacked_size;
|
prefix_sum_of_list_indices += unpacked_size;
|
||||||
@@ -74,32 +94,26 @@ void CompressedEdgeContainer::SerializeInternalVector(const std::string &path) c
|
|||||||
// write compressed geometries
|
// write compressed geometries
|
||||||
for (auto &elem : m_compressed_geometries)
|
for (auto &elem : m_compressed_geometries)
|
||||||
{
|
{
|
||||||
const std::vector<CompressedEdge> ¤t_vector = elem;
|
const std::vector<CompressedNode> ¤t_vector = elem;
|
||||||
const unsigned unpacked_size = current_vector.size();
|
const unsigned unpacked_size = current_vector.size();
|
||||||
control_sum += unpacked_size;
|
control_sum += unpacked_size;
|
||||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != unpacked_size);
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != unpacked_size);
|
||||||
for (const auto ¤t_node : current_vector)
|
for (const CompressedNode current_node : current_vector)
|
||||||
{
|
{
|
||||||
geometry_out_stream.write((char *)&(current_node), sizeof(CompressedEdge));
|
geometry_out_stream.write((char *)&(current_node.first), sizeof(NodeID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(control_sum == prefix_sum_of_list_indices);
|
BOOST_ASSERT(control_sum == prefix_sum_of_list_indices);
|
||||||
|
// all done, let's close the resource
|
||||||
|
geometry_out_stream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds info for a compressed edge to the container. edge_id_2
|
void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
|
||||||
// has been removed from the graph, so we have to save These edges/nodes
|
const EdgeID edge_id_2,
|
||||||
// have already been trimmed from the graph, this function just stores
|
const NodeID via_node_id,
|
||||||
// the original data for unpacking later.
|
const NodeID target_node_id,
|
||||||
//
|
const EdgeWeight weight1,
|
||||||
// edge_id_1 edge_id_2
|
const EdgeWeight weight2)
|
||||||
// ----------> via_node_id -----------> target_node_id
|
|
||||||
// weight_1 weight_2
|
|
||||||
void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
|
||||||
const EdgeID edge_id_2,
|
|
||||||
const NodeID via_node_id,
|
|
||||||
const NodeID target_node_id,
|
|
||||||
const EdgeWeight weight1,
|
|
||||||
const EdgeWeight weight2)
|
|
||||||
{
|
{
|
||||||
// remove super-trivial geometries
|
// remove super-trivial geometries
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_1);
|
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_1);
|
||||||
@@ -137,13 +151,11 @@ void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
|||||||
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
|
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
|
||||||
BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size());
|
BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size());
|
||||||
|
|
||||||
std::vector<CompressedEdge> &edge_bucket_list1 = m_compressed_geometries[edge_bucket_id1];
|
std::vector<CompressedNode> &edge_bucket_list1 = m_compressed_geometries[edge_bucket_id1];
|
||||||
|
|
||||||
// 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
|
|
||||||
if (edge_bucket_list1.empty())
|
if (edge_bucket_list1.empty())
|
||||||
{
|
{
|
||||||
edge_bucket_list1.emplace_back(CompressedEdge{via_node_id, weight1});
|
edge_bucket_list1.emplace_back(via_node_id, weight1);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(0 < edge_bucket_list1.size());
|
BOOST_ASSERT(0 < edge_bucket_list1.size());
|
||||||
@@ -155,7 +167,7 @@ void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
|||||||
const unsigned list_to_remove_index = GetPositionForID(edge_id_2);
|
const unsigned list_to_remove_index = GetPositionForID(edge_id_2);
|
||||||
BOOST_ASSERT(list_to_remove_index < m_compressed_geometries.size());
|
BOOST_ASSERT(list_to_remove_index < m_compressed_geometries.size());
|
||||||
|
|
||||||
std::vector<CompressedEdge> &edge_bucket_list2 =
|
std::vector<CompressedNode> &edge_bucket_list2 =
|
||||||
m_compressed_geometries[list_to_remove_index];
|
m_compressed_geometries[list_to_remove_index];
|
||||||
|
|
||||||
// found an existing list, append it to the list of edge_id_1
|
// found an existing list, append it to the list of edge_id_1
|
||||||
@@ -174,52 +186,11 @@ void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// we are certain that the second edge is atomic.
|
// we are certain that the second edge is atomic.
|
||||||
edge_bucket_list1.emplace_back(CompressedEdge{target_node_id, weight2});
|
edge_bucket_list1.emplace_back(target_node_id, weight2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompressedEdgeContainer::AddUncompressedEdge(const EdgeID edge_id,
|
void GeometryCompressor::PrintStatistics() const
|
||||||
const NodeID target_node_id,
|
|
||||||
const EdgeWeight weight)
|
|
||||||
{
|
|
||||||
// remove super-trivial geometries
|
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id);
|
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
|
|
||||||
BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight);
|
|
||||||
|
|
||||||
// Add via node id. List is created if it does not exist
|
|
||||||
if (!HasEntryForID(edge_id))
|
|
||||||
{
|
|
||||||
// create a new entry in the map
|
|
||||||
if (0 == m_free_list.size())
|
|
||||||
{
|
|
||||||
// make sure there is a place to put the entries
|
|
||||||
IncreaseFreeList();
|
|
||||||
}
|
|
||||||
BOOST_ASSERT(!m_free_list.empty());
|
|
||||||
m_edge_id_to_list_index_map[edge_id] = m_free_list.back();
|
|
||||||
m_free_list.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// find bucket index
|
|
||||||
const auto iter = m_edge_id_to_list_index_map.find(edge_id);
|
|
||||||
BOOST_ASSERT(iter != m_edge_id_to_list_index_map.end());
|
|
||||||
const unsigned edge_bucket_id = iter->second;
|
|
||||||
BOOST_ASSERT(edge_bucket_id == GetPositionForID(edge_id));
|
|
||||||
BOOST_ASSERT(edge_bucket_id < m_compressed_geometries.size());
|
|
||||||
|
|
||||||
std::vector<CompressedEdge> &edge_bucket_list = m_compressed_geometries[edge_bucket_id];
|
|
||||||
|
|
||||||
// note we don't save the start coordinate: it is implicitly given by edge_id
|
|
||||||
// weight is the distance to the (currently) last coordinate in the bucket
|
|
||||||
// Don't re-add this if it's already in there.
|
|
||||||
if (edge_bucket_list.empty())
|
|
||||||
{
|
|
||||||
edge_bucket_list.emplace_back(CompressedEdge{target_node_id, weight});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CompressedEdgeContainer::PrintStatistics() const
|
|
||||||
{
|
{
|
||||||
const uint64_t compressed_edges = m_compressed_geometries.size();
|
const uint64_t compressed_edges = m_compressed_geometries.size();
|
||||||
BOOST_ASSERT(0 == compressed_edges % 2);
|
BOOST_ASSERT(0 == compressed_edges % 2);
|
||||||
@@ -227,40 +198,39 @@ void CompressedEdgeContainer::PrintStatistics() const
|
|||||||
|
|
||||||
uint64_t compressed_geometries = 0;
|
uint64_t compressed_geometries = 0;
|
||||||
uint64_t longest_chain_length = 0;
|
uint64_t longest_chain_length = 0;
|
||||||
for (const std::vector<CompressedEdge> ¤t_vector : m_compressed_geometries)
|
for (const std::vector<CompressedNode> ¤t_vector : m_compressed_geometries)
|
||||||
{
|
{
|
||||||
compressed_geometries += current_vector.size();
|
compressed_geometries += current_vector.size();
|
||||||
longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
|
longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
util::SimpleLogger().Write()
|
SimpleLogger().Write() << "Geometry successfully removed:"
|
||||||
<< "Geometry successfully removed:"
|
"\n compressed edges: " << compressed_edges
|
||||||
"\n compressed edges: "
|
<< "\n compressed geometries: " << compressed_geometries
|
||||||
<< compressed_edges << "\n compressed geometries: " << compressed_geometries
|
<< "\n longest chain length: " << longest_chain_length
|
||||||
<< "\n longest chain length: " << longest_chain_length << "\n cmpr ratio: "
|
<< "\n cmpr ratio: " << ((float)compressed_edges /
|
||||||
<< ((float)compressed_edges / std::max(compressed_geometries, (uint64_t)1))
|
std::max(compressed_geometries, (uint64_t)1))
|
||||||
<< "\n avg chain length: "
|
<< "\n avg chain length: "
|
||||||
<< (float)compressed_geometries / std::max((uint64_t)1, compressed_edges);
|
<< (float)compressed_geometries /
|
||||||
|
std::max((uint64_t)1, compressed_edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CompressedEdgeContainer::EdgeBucket &
|
const std::vector<GeometryCompressor::CompressedNode> &
|
||||||
CompressedEdgeContainer::GetBucketReference(const EdgeID edge_id) const
|
GeometryCompressor::GetBucketReference(const EdgeID edge_id) const
|
||||||
{
|
{
|
||||||
const unsigned index = m_edge_id_to_list_index_map.at(edge_id);
|
const unsigned index = m_edge_id_to_list_index_map.at(edge_id);
|
||||||
return m_compressed_geometries.at(index);
|
return m_compressed_geometries.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID CompressedEdgeContainer::GetFirstEdgeTargetID(const EdgeID edge_id) const
|
NodeID GeometryCompressor::GetFirstNodeIDOfBucket(const EdgeID edge_id) const
|
||||||
{
|
{
|
||||||
const auto &bucket = GetBucketReference(edge_id);
|
const auto &bucket = GetBucketReference(edge_id);
|
||||||
BOOST_ASSERT(bucket.size() >= 2);
|
BOOST_ASSERT(bucket.size() >= 2);
|
||||||
return bucket.front().node_id;
|
return bucket[1].first;
|
||||||
}
|
}
|
||||||
NodeID CompressedEdgeContainer::GetLastEdgeSourceID(const EdgeID edge_id) const
|
NodeID GeometryCompressor::GetLastNodeIDOfBucket(const EdgeID edge_id) const
|
||||||
{
|
{
|
||||||
const auto &bucket = GetBucketReference(edge_id);
|
const auto &bucket = GetBucketReference(edge_id);
|
||||||
BOOST_ASSERT(bucket.size() >= 2);
|
BOOST_ASSERT(bucket.size() >= 2);
|
||||||
return bucket[bucket.size() - 2].node_id;
|
return bucket[bucket.size() - 2].first;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright (c) 2016, Project OSRM contributors
|
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -25,78 +25,45 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// based on
|
#ifndef GEOMETRY_COMPRESSOR_HPP_
|
||||||
// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp
|
#define GEOMETRY_COMPRESSOR_HPP_
|
||||||
|
|
||||||
#ifndef JSON_CONTAINER_HPP
|
#include "../typedefs.h"
|
||||||
#define JSON_CONTAINER_HPP
|
|
||||||
|
|
||||||
#include <variant/variant.hpp>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace osrm
|
#include <string>
|
||||||
{
|
#include <vector>
|
||||||
|
|
||||||
namespace util
|
class GeometryCompressor
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
using CompressedNode = std::pair<NodeID, EdgeWeight>;
|
||||||
|
|
||||||
namespace json
|
GeometryCompressor();
|
||||||
{
|
void CompressEdge(const EdgeID surviving_edge_id,
|
||||||
|
const EdgeID removed_edge_id,
|
||||||
|
const NodeID via_node_id,
|
||||||
|
const NodeID target_node,
|
||||||
|
const EdgeWeight weight1,
|
||||||
|
const EdgeWeight weight2);
|
||||||
|
|
||||||
struct Object;
|
bool HasEntryForID(const EdgeID edge_id) const;
|
||||||
struct Array;
|
void PrintStatistics() const;
|
||||||
|
void SerializeInternalVector(const std::string &path) const;
|
||||||
|
unsigned GetPositionForID(const EdgeID edge_id) const;
|
||||||
|
const std::vector<GeometryCompressor::CompressedNode> &
|
||||||
|
GetBucketReference(const EdgeID edge_id) const;
|
||||||
|
NodeID GetFirstNodeIDOfBucket(const EdgeID edge_id) const;
|
||||||
|
NodeID GetLastNodeIDOfBucket(const EdgeID edge_id) const;
|
||||||
|
|
||||||
struct String
|
private:
|
||||||
{
|
int free_list_maximum = 0;
|
||||||
String() = default;
|
|
||||||
String(const char *value_) : value{value_} {}
|
void IncreaseFreeList();
|
||||||
String(std::string value_) : value{std::move(value_)} {}
|
std::vector<std::vector<CompressedNode>> m_compressed_geometries;
|
||||||
std::string value;
|
std::vector<unsigned> m_free_list;
|
||||||
|
std::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Number
|
#endif // GEOMETRY_COMPRESSOR_HPP_
|
||||||
{
|
|
||||||
Number() = default;
|
|
||||||
Number(double value_) : value{value_} {}
|
|
||||||
double value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct True
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
struct False
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Null
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
using Value = mapbox::util::variant<String,
|
|
||||||
Number,
|
|
||||||
mapbox::util::recursive_wrapper<Object>,
|
|
||||||
mapbox::util::recursive_wrapper<Array>,
|
|
||||||
True,
|
|
||||||
False,
|
|
||||||
Null>;
|
|
||||||
|
|
||||||
struct Object
|
|
||||||
{
|
|
||||||
std::unordered_map<std::string, Value> values;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Array
|
|
||||||
{
|
|
||||||
std::vector<Value> values;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace JSON
|
|
||||||
} // namespace util
|
|
||||||
} // namespace osrm
|
|
||||||
|
|
||||||
#endif // JSON_CONTAINER_HPP
|
|
||||||
@@ -0,0 +1,430 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "processing_chain.hpp"
|
||||||
|
|
||||||
|
#include "contractor.hpp"
|
||||||
|
|
||||||
|
#include "../algorithms/crc32_processor.hpp"
|
||||||
|
#include "../data_structures/deallocating_vector.hpp"
|
||||||
|
#include "../data_structures/static_rtree.hpp"
|
||||||
|
#include "../data_structures/restriction_map.hpp"
|
||||||
|
|
||||||
|
#include "../util/git_sha.hpp"
|
||||||
|
#include "../util/graph_loader.hpp"
|
||||||
|
#include "../util/integer_range.hpp"
|
||||||
|
#include "../util/lua_util.hpp"
|
||||||
|
#include "../util/make_unique.hpp"
|
||||||
|
#include "../util/osrm_exception.hpp"
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
#include "../util/string_util.hpp"
|
||||||
|
#include "../util/timing_util.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
Prepare::~Prepare() {}
|
||||||
|
|
||||||
|
int Prepare::Run()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma message("Memory consumption on Windows can be higher due to different bit packing")
|
||||||
|
#else
|
||||||
|
static_assert(sizeof(NodeBasedEdge) == 20,
|
||||||
|
"changing NodeBasedEdge type has influence on memory consumption!");
|
||||||
|
static_assert(sizeof(EdgeBasedEdge) == 16,
|
||||||
|
"changing EdgeBasedEdge type has influence on memory consumption!");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TIMER_START(preparing);
|
||||||
|
|
||||||
|
// Create a new lua state
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Generating edge-expanded graph representation";
|
||||||
|
|
||||||
|
TIMER_START(expansion);
|
||||||
|
|
||||||
|
auto node_based_edge_list = osrm::make_unique<std::vector<EdgeBasedNode>>();;
|
||||||
|
DeallocatingVector<EdgeBasedEdge> edge_based_edge_list;
|
||||||
|
auto internal_to_external_node_map = osrm::make_unique<std::vector<QueryNode>>();
|
||||||
|
auto graph_size =
|
||||||
|
BuildEdgeExpandedGraph(*internal_to_external_node_map,
|
||||||
|
*node_based_edge_list, edge_based_edge_list);
|
||||||
|
|
||||||
|
auto number_of_node_based_nodes = graph_size.first;
|
||||||
|
auto number_of_edge_based_nodes = graph_size.second;
|
||||||
|
|
||||||
|
TIMER_STOP(expansion);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "building r-tree ...";
|
||||||
|
TIMER_START(rtree);
|
||||||
|
|
||||||
|
BuildRTree(*node_based_edge_list, *internal_to_external_node_map);
|
||||||
|
|
||||||
|
TIMER_STOP(rtree);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "writing node map ...";
|
||||||
|
WriteNodeMapping(std::move(internal_to_external_node_map));
|
||||||
|
|
||||||
|
// Contracting the edge-expanded graph
|
||||||
|
|
||||||
|
TIMER_START(contraction);
|
||||||
|
auto contracted_edge_list = osrm::make_unique<DeallocatingVector<QueryEdge>>();
|
||||||
|
ContractGraph(number_of_edge_based_nodes, edge_based_edge_list, *contracted_edge_list);
|
||||||
|
TIMER_STOP(contraction);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Contraction took " << TIMER_SEC(contraction) << " sec";
|
||||||
|
|
||||||
|
std::size_t number_of_used_edges = WriteContractedGraph(number_of_edge_based_nodes,
|
||||||
|
std::move(node_based_edge_list),
|
||||||
|
std::move(contracted_edge_list));
|
||||||
|
|
||||||
|
TIMER_STOP(preparing);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Preprocessing : " << TIMER_SEC(preparing) << " seconds";
|
||||||
|
SimpleLogger().Write() << "Expansion : " << (number_of_node_based_nodes / TIMER_SEC(expansion))
|
||||||
|
<< " nodes/sec and "
|
||||||
|
<< (number_of_edge_based_nodes / TIMER_SEC(expansion)) << " edges/sec";
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Contraction: "
|
||||||
|
<< (number_of_edge_based_nodes / TIMER_SEC(contraction))
|
||||||
|
<< " nodes/sec and " << number_of_used_edges / TIMER_SEC(contraction)
|
||||||
|
<< " edges/sec";
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "finished preprocessing";
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t Prepare::WriteContractedGraph(unsigned number_of_edge_based_nodes,
|
||||||
|
std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list,
|
||||||
|
std::unique_ptr<DeallocatingVector<QueryEdge>> contracted_edge_list)
|
||||||
|
{
|
||||||
|
const unsigned crc32_value = CalculateEdgeChecksum(std::move(node_based_edge_list));
|
||||||
|
|
||||||
|
// Sorting contracted edges in a way that the static query graph can read some in in-place.
|
||||||
|
tbb::parallel_sort(contracted_edge_list->begin(), contracted_edge_list->end());
|
||||||
|
const unsigned contracted_edge_count = contracted_edge_list->size();
|
||||||
|
SimpleLogger().Write() << "Serializing compacted graph of " << contracted_edge_count
|
||||||
|
<< " edges";
|
||||||
|
|
||||||
|
const FingerPrint fingerprint = FingerPrint::GetValid();
|
||||||
|
boost::filesystem::ofstream hsgr_output_stream(config.graph_output_path, std::ios::binary);
|
||||||
|
hsgr_output_stream.write((char *)&fingerprint, sizeof(FingerPrint));
|
||||||
|
const unsigned max_used_node_id = 1 + [&contracted_edge_list]
|
||||||
|
{
|
||||||
|
unsigned tmp_max = 0;
|
||||||
|
for (const QueryEdge &edge : *contracted_edge_list)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(SPECIAL_NODEID != edge.source);
|
||||||
|
BOOST_ASSERT(SPECIAL_NODEID != edge.target);
|
||||||
|
tmp_max = std::max(tmp_max, edge.source);
|
||||||
|
tmp_max = std::max(tmp_max, edge.target);
|
||||||
|
}
|
||||||
|
return tmp_max;
|
||||||
|
}();
|
||||||
|
|
||||||
|
SimpleLogger().Write(logDEBUG) << "input graph has " << number_of_edge_based_nodes << " nodes";
|
||||||
|
SimpleLogger().Write(logDEBUG) << "contracted graph has " << max_used_node_id << " nodes";
|
||||||
|
|
||||||
|
std::vector<StaticGraph<EdgeData>::NodeArrayEntry> node_array;
|
||||||
|
node_array.resize(number_of_edge_based_nodes + 1);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Building node array";
|
||||||
|
StaticGraph<EdgeData>::EdgeIterator edge = 0;
|
||||||
|
StaticGraph<EdgeData>::EdgeIterator position = 0;
|
||||||
|
StaticGraph<EdgeData>::EdgeIterator last_edge = edge;
|
||||||
|
|
||||||
|
// initializing 'first_edge'-field of nodes:
|
||||||
|
for (const auto node : osrm::irange(0u, max_used_node_id))
|
||||||
|
{
|
||||||
|
last_edge = edge;
|
||||||
|
while ((edge < contracted_edge_count) && ((*contracted_edge_list)[edge].source == node))
|
||||||
|
{
|
||||||
|
++edge;
|
||||||
|
}
|
||||||
|
node_array[node].first_edge = position; //=edge
|
||||||
|
position += edge - last_edge; // remove
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto sentinel_counter : osrm::irange<unsigned>(max_used_node_id, node_array.size()))
|
||||||
|
{
|
||||||
|
// sentinel element, guarded against underflow
|
||||||
|
node_array[sentinel_counter].first_edge = contracted_edge_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Serializing node array";
|
||||||
|
|
||||||
|
const unsigned node_array_size = node_array.size();
|
||||||
|
// serialize crc32, aka checksum
|
||||||
|
hsgr_output_stream.write((char *)&crc32_value, sizeof(unsigned));
|
||||||
|
// serialize number of nodes
|
||||||
|
hsgr_output_stream.write((char *)&node_array_size, sizeof(unsigned));
|
||||||
|
// serialize number of edges
|
||||||
|
hsgr_output_stream.write((char *)&contracted_edge_count, sizeof(unsigned));
|
||||||
|
// serialize all nodes
|
||||||
|
if (node_array_size > 0)
|
||||||
|
{
|
||||||
|
hsgr_output_stream.write((char *)&node_array[0],
|
||||||
|
sizeof(StaticGraph<EdgeData>::NodeArrayEntry) * node_array_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialize all edges
|
||||||
|
SimpleLogger().Write() << "Building edge array";
|
||||||
|
edge = 0;
|
||||||
|
int number_of_used_edges = 0;
|
||||||
|
|
||||||
|
StaticGraph<EdgeData>::EdgeArrayEntry current_edge;
|
||||||
|
for (const auto edge : osrm::irange<std::size_t>(0, contracted_edge_list->size()))
|
||||||
|
{
|
||||||
|
// no eigen loops
|
||||||
|
BOOST_ASSERT((*contracted_edge_list)[edge].source != (*contracted_edge_list)[edge].target);
|
||||||
|
current_edge.target = (*contracted_edge_list)[edge].target;
|
||||||
|
current_edge.data = (*contracted_edge_list)[edge].data;
|
||||||
|
|
||||||
|
// every target needs to be valid
|
||||||
|
BOOST_ASSERT(current_edge.target < max_used_node_id);
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (current_edge.data.distance <= 0)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Edge: " << edge
|
||||||
|
<< ",source: " << (*contracted_edge_list)[edge].source
|
||||||
|
<< ", target: " << (*contracted_edge_list)[edge].target
|
||||||
|
<< ", dist: " << current_edge.data.distance;
|
||||||
|
|
||||||
|
SimpleLogger().Write(logWARNING) << "Failed at adjacency list of node "
|
||||||
|
<< (*contracted_edge_list)[edge].source << "/"
|
||||||
|
<< node_array.size() - 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
hsgr_output_stream.write((char *)¤t_edge,
|
||||||
|
sizeof(StaticGraph<EdgeData>::EdgeArrayEntry));
|
||||||
|
|
||||||
|
++number_of_used_edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
return number_of_used_edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Prepare::CalculateEdgeChecksum(std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list)
|
||||||
|
{
|
||||||
|
RangebasedCRC32 crc32;
|
||||||
|
if (crc32.using_hardware())
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "using hardware based CRC32 computation";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "using software based CRC32 computation";
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned crc32_value = crc32(*node_based_edge_list);
|
||||||
|
SimpleLogger().Write() << "CRC32: " << crc32_value;
|
||||||
|
|
||||||
|
return crc32_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Setups scripting environment (lua-scripting)
|
||||||
|
Also initializes speed profile.
|
||||||
|
*/
|
||||||
|
void Prepare::SetupScriptingEnvironment(
|
||||||
|
lua_State *lua_state, EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile)
|
||||||
|
{
|
||||||
|
// open utility libraries string library;
|
||||||
|
luaL_openlibs(lua_state);
|
||||||
|
|
||||||
|
// adjust lua load path
|
||||||
|
luaAddScriptFolderToLoadPath(lua_state, config.profile_path.string().c_str());
|
||||||
|
|
||||||
|
// Now call our function in a lua script
|
||||||
|
if (0 != luaL_dofile(lua_state, config.profile_path.string().c_str()))
|
||||||
|
{
|
||||||
|
std::stringstream msg;
|
||||||
|
msg << lua_tostring(lua_state, -1) << " occured in scripting block";
|
||||||
|
throw osrm::exception(msg.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != luaL_dostring(lua_state, "return traffic_signal_penalty\n"))
|
||||||
|
{
|
||||||
|
std::stringstream msg;
|
||||||
|
msg << lua_tostring(lua_state, -1) << " occured in scripting block";
|
||||||
|
throw osrm::exception(msg.str());
|
||||||
|
}
|
||||||
|
speed_profile.traffic_signal_penalty = 10 * lua_tointeger(lua_state, -1);
|
||||||
|
SimpleLogger().Write(logDEBUG)
|
||||||
|
<< "traffic_signal_penalty: " << speed_profile.traffic_signal_penalty;
|
||||||
|
|
||||||
|
if (0 != luaL_dostring(lua_state, "return u_turn_penalty\n"))
|
||||||
|
{
|
||||||
|
std::stringstream msg;
|
||||||
|
msg << lua_tostring(lua_state, -1) << " occured in scripting block";
|
||||||
|
throw osrm::exception(msg.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
speed_profile.u_turn_penalty = 10 * lua_tointeger(lua_state, -1);
|
||||||
|
speed_profile.has_turn_penalty_function = lua_function_exists(lua_state, "turn_function");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Build load restrictions from .restriction file
|
||||||
|
*/
|
||||||
|
std::shared_ptr<RestrictionMap> Prepare::LoadRestrictionMap()
|
||||||
|
{
|
||||||
|
boost::filesystem::ifstream input_stream(config.restrictions_path, std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
std::vector<TurnRestriction> restriction_list;
|
||||||
|
loadRestrictionsFromFile(input_stream, restriction_list);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << " - " << restriction_list.size() << " restrictions.";
|
||||||
|
|
||||||
|
return std::make_shared<RestrictionMap>(restriction_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Load node based graph from .osrm file
|
||||||
|
*/
|
||||||
|
std::shared_ptr<NodeBasedDynamicGraph>
|
||||||
|
Prepare::LoadNodeBasedGraph(std::vector<NodeID> &barrier_node_list,
|
||||||
|
std::vector<NodeID> &traffic_light_list,
|
||||||
|
std::vector<QueryNode>& internal_to_external_node_map)
|
||||||
|
{
|
||||||
|
std::vector<NodeBasedEdge> edge_list;
|
||||||
|
|
||||||
|
boost::filesystem::ifstream input_stream(config.osrm_input_path, std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
NodeID number_of_node_based_nodes = loadNodesFromFile(input_stream,
|
||||||
|
barrier_node_list, traffic_light_list,
|
||||||
|
internal_to_external_node_map);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << " - " << barrier_node_list.size() << " bollard nodes, "
|
||||||
|
<< traffic_light_list.size() << " traffic lights";
|
||||||
|
|
||||||
|
loadEdgesFromFile(input_stream, edge_list);
|
||||||
|
|
||||||
|
if (edge_list.empty())
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
|
||||||
|
return std::shared_ptr<NodeBasedDynamicGraph>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Building an edge-expanded graph from node-based input and turn restrictions
|
||||||
|
*/
|
||||||
|
std::pair<std::size_t, std::size_t>
|
||||||
|
Prepare::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,
|
||||||
|
std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||||
|
DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list)
|
||||||
|
{
|
||||||
|
lua_State *lua_state = luaL_newstate();
|
||||||
|
luabind::open(lua_state);
|
||||||
|
|
||||||
|
EdgeBasedGraphFactory::SpeedProfileProperties speed_profile;
|
||||||
|
|
||||||
|
SetupScriptingEnvironment(lua_state, speed_profile);
|
||||||
|
|
||||||
|
auto barrier_node_list = osrm::make_unique<std::vector<NodeID>>();
|
||||||
|
auto traffic_light_list = osrm::make_unique<std::vector<NodeID>>();
|
||||||
|
|
||||||
|
auto restriction_map = LoadRestrictionMap();
|
||||||
|
auto node_based_graph = LoadNodeBasedGraph(*barrier_node_list, *traffic_light_list, internal_to_external_node_map);
|
||||||
|
|
||||||
|
const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes();
|
||||||
|
|
||||||
|
EdgeBasedGraphFactory edge_based_graph_factory(node_based_graph,
|
||||||
|
restriction_map,
|
||||||
|
std::move(barrier_node_list),
|
||||||
|
std::move(traffic_light_list),
|
||||||
|
internal_to_external_node_map,
|
||||||
|
speed_profile);
|
||||||
|
|
||||||
|
edge_based_graph_factory.Run(config.edge_output_path, config.geometry_output_path, lua_state);
|
||||||
|
lua_close(lua_state);
|
||||||
|
|
||||||
|
const std::size_t number_of_edge_based_nodes =
|
||||||
|
edge_based_graph_factory.GetNumberOfEdgeBasedNodes();
|
||||||
|
|
||||||
|
BOOST_ASSERT(number_of_edge_based_nodes != std::numeric_limits<unsigned>::max());
|
||||||
|
|
||||||
|
edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list);
|
||||||
|
edge_based_graph_factory.GetEdgeBasedNodes(node_based_edge_list);
|
||||||
|
|
||||||
|
return std::make_pair(number_of_node_based_nodes, number_of_edge_based_nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Build contracted graph.
|
||||||
|
*/
|
||||||
|
void Prepare::ContractGraph(const std::size_t number_of_edge_based_nodes,
|
||||||
|
DeallocatingVector<EdgeBasedEdge>& edge_based_edge_list,
|
||||||
|
DeallocatingVector<QueryEdge>& contracted_edge_list)
|
||||||
|
{
|
||||||
|
Contractor contractor(number_of_edge_based_nodes, edge_based_edge_list);
|
||||||
|
contractor.Run();
|
||||||
|
contractor.GetEdges(contracted_edge_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Writing info on original (node-based) nodes
|
||||||
|
*/
|
||||||
|
void Prepare::WriteNodeMapping(std::unique_ptr<std::vector<QueryNode>> internal_to_external_node_map)
|
||||||
|
{
|
||||||
|
boost::filesystem::ofstream node_stream(config.node_output_path, std::ios::binary);
|
||||||
|
const unsigned size_of_mapping = internal_to_external_node_map->size();
|
||||||
|
node_stream.write((char *)&size_of_mapping, sizeof(unsigned));
|
||||||
|
if (size_of_mapping > 0)
|
||||||
|
{
|
||||||
|
node_stream.write((char *) internal_to_external_node_map->data(),
|
||||||
|
size_of_mapping * sizeof(QueryNode));
|
||||||
|
}
|
||||||
|
node_stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Building rtree-based nearest-neighbor data structure
|
||||||
|
|
||||||
|
Saves tree into '.ramIndex' and leaves into '.fileIndex'.
|
||||||
|
*/
|
||||||
|
void Prepare::BuildRTree(const std::vector<EdgeBasedNode> &node_based_edge_list, const std::vector<QueryNode>& internal_to_external_node_map)
|
||||||
|
{
|
||||||
|
StaticRTree<EdgeBasedNode>(node_based_edge_list, config.rtree_nodes_output_path.c_str(),
|
||||||
|
config.rtree_leafs_output_path.c_str(), internal_to_external_node_map);
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PROCESSING_CHAIN_HPP
|
||||||
|
#define PROCESSING_CHAIN_HPP
|
||||||
|
|
||||||
|
#include "contractor_options.hpp"
|
||||||
|
#include "edge_based_graph_factory.hpp"
|
||||||
|
#include "../data_structures/query_edge.hpp"
|
||||||
|
#include "../data_structures/static_graph.hpp"
|
||||||
|
|
||||||
|
struct EdgeBasedNode;
|
||||||
|
struct lua_State;
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief class of 'prepare' utility.
|
||||||
|
*/
|
||||||
|
class Prepare
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using EdgeData = QueryEdge::EdgeData;
|
||||||
|
using InputEdge = DynamicGraph<EdgeData>::InputEdge;
|
||||||
|
using StaticEdge = StaticGraph<EdgeData>::InputEdge;
|
||||||
|
|
||||||
|
explicit Prepare(const ContractorConfig& contractor_config)
|
||||||
|
: config(contractor_config) {}
|
||||||
|
Prepare(const Prepare &) = delete;
|
||||||
|
~Prepare();
|
||||||
|
|
||||||
|
int Run();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetupScriptingEnvironment(lua_State *myLuaState,
|
||||||
|
EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile);
|
||||||
|
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
|
||||||
|
unsigned CalculateEdgeChecksum(std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list);
|
||||||
|
void ContractGraph(const std::size_t number_of_edge_based_nodes,
|
||||||
|
DeallocatingVector<EdgeBasedEdge>& edge_based_edge_list,
|
||||||
|
DeallocatingVector<QueryEdge>& contracted_edge_list);
|
||||||
|
std::size_t WriteContractedGraph(unsigned number_of_edge_based_nodes,
|
||||||
|
std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list,
|
||||||
|
std::unique_ptr<DeallocatingVector<QueryEdge>> contracted_edge_list);
|
||||||
|
std::shared_ptr<NodeBasedDynamicGraph> LoadNodeBasedGraph(std::vector<NodeID> &barrier_node_list,
|
||||||
|
std::vector<NodeID> &traffic_light_list,
|
||||||
|
std::vector<QueryNode>& internal_to_external_node_map);
|
||||||
|
std::pair<std::size_t, std::size_t>
|
||||||
|
BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,
|
||||||
|
std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||||
|
DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list);
|
||||||
|
void WriteNodeMapping(std::unique_ptr<std::vector<QueryNode>> internal_to_external_node_map);
|
||||||
|
void BuildRTree(const std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||||
|
const std::vector<QueryNode> &internal_to_external_node_map);
|
||||||
|
private:
|
||||||
|
ContractorConfig config;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PROCESSING_CHAIN_HPP
|
||||||
@@ -1,3 +1,30 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef BINARY_HEAP_H
|
#ifndef BINARY_HEAP_H
|
||||||
#define BINARY_HEAP_H
|
#define BINARY_HEAP_H
|
||||||
|
|
||||||
@@ -10,11 +37,6 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
|
|
||||||
template <typename NodeID, typename Key> class ArrayStorage
|
template <typename NodeID, typename Key> class ArrayStorage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -167,12 +189,6 @@ class BinaryHeap
|
|||||||
return inserted_nodes[heap[1].index].node;
|
return inserted_nodes[heap[1].index].node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Weight MinKey() const
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(heap.size() > 1);
|
|
||||||
return heap[1].weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID DeleteMin()
|
NodeID DeleteMin()
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(heap.size() > 1);
|
BOOST_ASSERT(heap.size() > 1);
|
||||||
@@ -191,7 +207,7 @@ class BinaryHeap
|
|||||||
void DeleteAll()
|
void DeleteAll()
|
||||||
{
|
{
|
||||||
auto iend = heap.end();
|
auto iend = heap.end();
|
||||||
for (auto i = heap.begin() + 1; i != iend; ++i)
|
for (typename std::vector<HeapElement>::iterator i = heap.begin() + 1; i != iend; ++i)
|
||||||
{
|
{
|
||||||
inserted_nodes[i->index].key = 0;
|
inserted_nodes[i->index].key = 0;
|
||||||
}
|
}
|
||||||
@@ -216,9 +232,7 @@ class BinaryHeap
|
|||||||
class HeapNode
|
class HeapNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HeapNode(NodeID n, Key k, Weight w, Data d) : node(n), key(k), weight(w), data(std::move(d))
|
HeapNode(NodeID n, Key k, Weight w, Data d) : node(n), key(k), weight(w), data(d) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID node;
|
NodeID node;
|
||||||
Key key;
|
Key key;
|
||||||
@@ -290,7 +304,5 @@ class BinaryHeap
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // BINARY_HEAP_H
|
#endif // BINARY_HEAP_H
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONCURRENT_QUEUE_HPP
|
||||||
|
#define CONCURRENT_QUEUE_HPP
|
||||||
|
|
||||||
|
#include <boost/circular_buffer.hpp>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
template <typename Data> class ConcurrentQueue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) {}
|
||||||
|
|
||||||
|
inline void push(const Data &data)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
m_not_full.wait(lock, [this]
|
||||||
|
{
|
||||||
|
return m_internal_queue.size() < m_internal_queue.capacity();
|
||||||
|
});
|
||||||
|
m_internal_queue.push_back(data);
|
||||||
|
m_not_empty.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool empty() const { return m_internal_queue.empty(); }
|
||||||
|
|
||||||
|
inline void wait_and_pop(Data &popped_value)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
m_not_empty.wait(lock, [this]
|
||||||
|
{
|
||||||
|
return !m_internal_queue.empty();
|
||||||
|
});
|
||||||
|
popped_value = m_internal_queue.front();
|
||||||
|
m_internal_queue.pop_front();
|
||||||
|
m_not_full.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool try_pop(Data &popped_value)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
if (m_internal_queue.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
popped_value = m_internal_queue.front();
|
||||||
|
m_internal_queue.pop_front();
|
||||||
|
m_not_full.notify_one();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::circular_buffer<Data> m_internal_queue;
|
||||||
|
std::mutex m_mutex;
|
||||||
|
std::condition_variable m_not_empty;
|
||||||
|
std::condition_variable m_not_full;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONCURRENT_QUEUE_HPP
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "coordinate_calculation.hpp"
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
#endif
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#include <bitset>
|
||||||
|
#endif
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
FixedPointCoordinate::FixedPointCoordinate()
|
||||||
|
: lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (0 != (std::abs(lat) >> 30))
|
||||||
|
{
|
||||||
|
std::bitset<32> y_coordinate_vector(lat);
|
||||||
|
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat
|
||||||
|
<< ", bits: " << y_coordinate_vector;
|
||||||
|
}
|
||||||
|
if (0 != (std::abs(lon) >> 30))
|
||||||
|
{
|
||||||
|
std::bitset<32> x_coordinate_vector(lon);
|
||||||
|
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon
|
||||||
|
<< ", bits: " << x_coordinate_vector;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FixedPointCoordinate::is_valid() const
|
||||||
|
{
|
||||||
|
if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
|
||||||
|
lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
|
||||||
|
{
|
||||||
|
return lat == other.lat && lon == other.lon;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedPointCoordinate::output(std::ostream &out) const
|
||||||
|
{
|
||||||
|
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
float FixedPointCoordinate::bearing(const FixedPointCoordinate &other) const
|
||||||
|
{
|
||||||
|
return coordinate_calculation::bearing(other, *this);
|
||||||
|
}
|
||||||
@@ -0,0 +1,268 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "coordinate_calculation.hpp"
|
||||||
|
|
||||||
|
#include "../util/mercator.hpp"
|
||||||
|
#include "../util/string_util.hpp"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr static const float RAD = 0.017453292519943295769236907684886f;
|
||||||
|
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
|
||||||
|
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
||||||
|
constexpr static const float earth_radius = 6372797.560856f;
|
||||||
|
}
|
||||||
|
|
||||||
|
double coordinate_calculation::great_circle_distance(const int lat1,
|
||||||
|
const int lon1,
|
||||||
|
const int lat2,
|
||||||
|
const int lon2)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||||
|
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||||
|
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||||
|
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||||
|
const double lt1 = lat1 / COORDINATE_PRECISION;
|
||||||
|
const double ln1 = lon1 / COORDINATE_PRECISION;
|
||||||
|
const double lt2 = lat2 / COORDINATE_PRECISION;
|
||||||
|
const double ln2 = lon2 / COORDINATE_PRECISION;
|
||||||
|
const double dlat1 = lt1 * (RAD);
|
||||||
|
|
||||||
|
const double dlong1 = ln1 * (RAD);
|
||||||
|
const double dlat2 = lt2 * (RAD);
|
||||||
|
const double dlong2 = ln2 * (RAD);
|
||||||
|
|
||||||
|
const double dLong = dlong1 - dlong2;
|
||||||
|
const double dLat = dlat1 - dlat2;
|
||||||
|
|
||||||
|
const double aHarv = std::pow(std::sin(dLat / 2.0), 2.0) +
|
||||||
|
std::cos(dlat1) * std::cos(dlat2) * std::pow(std::sin(dLong / 2.), 2);
|
||||||
|
const double cHarv = 2. * std::atan2(std::sqrt(aHarv), std::sqrt(1.0 - aHarv));
|
||||||
|
return earth_radius * cHarv;
|
||||||
|
}
|
||||||
|
|
||||||
|
double coordinate_calculation::great_circle_distance(const FixedPointCoordinate &coordinate_1,
|
||||||
|
const FixedPointCoordinate &coordinate_2)
|
||||||
|
{
|
||||||
|
return great_circle_distance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat,
|
||||||
|
coordinate_2.lon);
|
||||||
|
}
|
||||||
|
|
||||||
|
float coordinate_calculation::euclidean_distance(const FixedPointCoordinate &coordinate_1,
|
||||||
|
const FixedPointCoordinate &coordinate_2)
|
||||||
|
{
|
||||||
|
return euclidean_distance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat,
|
||||||
|
coordinate_2.lon);
|
||||||
|
}
|
||||||
|
|
||||||
|
float coordinate_calculation::euclidean_distance(const int lat1,
|
||||||
|
const int lon1,
|
||||||
|
const int lat2,
|
||||||
|
const int lon2)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||||
|
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||||
|
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||||
|
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||||
|
|
||||||
|
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
||||||
|
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
||||||
|
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
||||||
|
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
||||||
|
|
||||||
|
const float x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.f);
|
||||||
|
const float y_value = float_lat2 - float_lat1;
|
||||||
|
return std::hypot(x_value, y_value) * earth_radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
float coordinate_calculation::perpendicular_distance(const FixedPointCoordinate &source_coordinate,
|
||||||
|
const FixedPointCoordinate &target_coordinate,
|
||||||
|
const FixedPointCoordinate &query_location)
|
||||||
|
{
|
||||||
|
float ratio;
|
||||||
|
FixedPointCoordinate nearest_location;
|
||||||
|
|
||||||
|
return perpendicular_distance(source_coordinate, target_coordinate, query_location,
|
||||||
|
nearest_location, ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
float coordinate_calculation::perpendicular_distance(const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target,
|
||||||
|
const FixedPointCoordinate &query_location,
|
||||||
|
FixedPointCoordinate &nearest_location,
|
||||||
|
float &ratio)
|
||||||
|
{
|
||||||
|
return perpendicular_distance_from_projected_coordinate(
|
||||||
|
segment_source, segment_target, query_location,
|
||||||
|
{mercator::lat2y(query_location.lat / COORDINATE_PRECISION),
|
||||||
|
query_location.lon / COORDINATE_PRECISION},
|
||||||
|
nearest_location, ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
float coordinate_calculation::perpendicular_distance_from_projected_coordinate(
|
||||||
|
const FixedPointCoordinate &source_coordinate,
|
||||||
|
const FixedPointCoordinate &target_coordinate,
|
||||||
|
const FixedPointCoordinate &query_location,
|
||||||
|
const std::pair<double, double> &projected_coordinate)
|
||||||
|
{
|
||||||
|
float ratio;
|
||||||
|
FixedPointCoordinate nearest_location;
|
||||||
|
|
||||||
|
return perpendicular_distance_from_projected_coordinate(source_coordinate, target_coordinate,
|
||||||
|
query_location, projected_coordinate,
|
||||||
|
nearest_location, ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
float coordinate_calculation::perpendicular_distance_from_projected_coordinate(
|
||||||
|
const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target,
|
||||||
|
const FixedPointCoordinate &query_location,
|
||||||
|
const std::pair<double, double> &projected_coordinate,
|
||||||
|
FixedPointCoordinate &nearest_location,
|
||||||
|
float &ratio)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(query_location.is_valid());
|
||||||
|
|
||||||
|
// initialize values
|
||||||
|
const double x = projected_coordinate.first;
|
||||||
|
const double y = projected_coordinate.second;
|
||||||
|
const double a = mercator::lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||||
|
const double b = segment_source.lon / COORDINATE_PRECISION;
|
||||||
|
const double c = mercator::lat2y(segment_target.lat / COORDINATE_PRECISION);
|
||||||
|
const double d = segment_target.lon / COORDINATE_PRECISION;
|
||||||
|
double p, q /*,mX*/, nY;
|
||||||
|
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
|
||||||
|
{
|
||||||
|
const double m = (d - b) / (c - a); // slope
|
||||||
|
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||||
|
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||||
|
q = b + m * (p - a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = c;
|
||||||
|
q = y;
|
||||||
|
}
|
||||||
|
nY = (d * p - c * q) / (a * d - b * c);
|
||||||
|
|
||||||
|
// discretize the result to coordinate precision. it's a hack!
|
||||||
|
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||||
|
{
|
||||||
|
nY = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute ratio
|
||||||
|
ratio =
|
||||||
|
static_cast<float>((p - nY * a) / c); // These values are actually n/m+n and m/m+n , we need
|
||||||
|
// not calculate the explicit values of m an n as we
|
||||||
|
// are just interested in the ratio
|
||||||
|
if (std::isnan(ratio))
|
||||||
|
{
|
||||||
|
ratio = (segment_target == query_location ? 1.f : 0.f);
|
||||||
|
}
|
||||||
|
else if (std::abs(ratio) <= std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
ratio = 0.f;
|
||||||
|
}
|
||||||
|
else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
ratio = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute nearest location
|
||||||
|
BOOST_ASSERT(!std::isnan(ratio));
|
||||||
|
if (ratio <= 0.f)
|
||||||
|
{
|
||||||
|
nearest_location = segment_source;
|
||||||
|
}
|
||||||
|
else if (ratio >= 1.f)
|
||||||
|
{
|
||||||
|
nearest_location = segment_target;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// point lies in between
|
||||||
|
nearest_location.lat = static_cast<int>(mercator::y2lat(p) * COORDINATE_PRECISION);
|
||||||
|
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||||
|
}
|
||||||
|
BOOST_ASSERT(nearest_location.is_valid());
|
||||||
|
|
||||||
|
const float approximate_distance =
|
||||||
|
coordinate_calculation::euclidean_distance(query_location, nearest_location);
|
||||||
|
BOOST_ASSERT(0.f <= approximate_distance);
|
||||||
|
return approximate_distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void coordinate_calculation::lat_or_lon_to_string(const int value, std::string &output)
|
||||||
|
{
|
||||||
|
char buffer[12];
|
||||||
|
buffer[11] = 0; // zero termination
|
||||||
|
output = printInt<11, 6>(buffer, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
float coordinate_calculation::deg_to_rad(const float degree)
|
||||||
|
{
|
||||||
|
return degree * (static_cast<float>(M_PI) / 180.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float coordinate_calculation::rad_to_deg(const float radian)
|
||||||
|
{
|
||||||
|
return radian * (180.f * static_cast<float>(M_1_PI));
|
||||||
|
}
|
||||||
|
|
||||||
|
float coordinate_calculation::bearing(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate)
|
||||||
|
{
|
||||||
|
const float lon_diff =
|
||||||
|
second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION;
|
||||||
|
const float lon_delta = deg_to_rad(lon_diff);
|
||||||
|
const float lat1 = deg_to_rad(first_coordinate.lat / COORDINATE_PRECISION);
|
||||||
|
const float lat2 = deg_to_rad(second_coordinate.lat / COORDINATE_PRECISION);
|
||||||
|
const float y = std::sin(lon_delta) * std::cos(lat2);
|
||||||
|
const float x =
|
||||||
|
std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta);
|
||||||
|
float result = rad_to_deg(std::atan2(y, x));
|
||||||
|
while (result < 0.f)
|
||||||
|
{
|
||||||
|
result += 360.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (result >= 360.f)
|
||||||
|
{
|
||||||
|
result -= 360.f;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COORDINATE_CALCULATION
|
||||||
|
#define COORDINATE_CALCULATION
|
||||||
|
|
||||||
|
struct FixedPointCoordinate;
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
struct coordinate_calculation
|
||||||
|
{
|
||||||
|
static double
|
||||||
|
great_circle_distance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||||
|
|
||||||
|
static double great_circle_distance(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
|
||||||
|
static float euclidean_distance(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
|
||||||
|
static float euclidean_distance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||||
|
|
||||||
|
static void lat_or_lon_to_string(const int value, std::string &output);
|
||||||
|
|
||||||
|
static float perpendicular_distance(const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target,
|
||||||
|
const FixedPointCoordinate &query_location);
|
||||||
|
|
||||||
|
static float perpendicular_distance(const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target,
|
||||||
|
const FixedPointCoordinate &query_location,
|
||||||
|
FixedPointCoordinate &nearest_location,
|
||||||
|
float &ratio);
|
||||||
|
|
||||||
|
static float perpendicular_distance_from_projected_coordinate(
|
||||||
|
const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target,
|
||||||
|
const FixedPointCoordinate &query_location,
|
||||||
|
const std::pair<double, double> &projected_coordinate);
|
||||||
|
|
||||||
|
static float perpendicular_distance_from_projected_coordinate(
|
||||||
|
const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target,
|
||||||
|
const FixedPointCoordinate &query_location,
|
||||||
|
const std::pair<double, double> &projected_coordinate,
|
||||||
|
FixedPointCoordinate &nearest_location,
|
||||||
|
float &ratio);
|
||||||
|
|
||||||
|
static float deg_to_rad(const float degree);
|
||||||
|
static float rad_to_deg(const float radian);
|
||||||
|
|
||||||
|
static float bearing(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COORDINATE_CALCULATION
|
||||||
@@ -1,7 +1,34 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef DEALLOCATING_VECTOR_HPP
|
#ifndef DEALLOCATING_VECTOR_HPP
|
||||||
#define DEALLOCATING_VECTOR_HPP
|
#define DEALLOCATING_VECTOR_HPP
|
||||||
|
|
||||||
#include "util/integer_range.hpp"
|
#include "../util/integer_range.hpp"
|
||||||
|
|
||||||
#include <boost/iterator/iterator_facade.hpp>
|
#include <boost/iterator/iterator_facade.hpp>
|
||||||
|
|
||||||
@@ -9,38 +36,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
|
|
||||||
template <typename ElementT> struct ConstDeallocatingVectorIteratorState
|
|
||||||
{
|
|
||||||
ConstDeallocatingVectorIteratorState()
|
|
||||||
: index(std::numeric_limits<std::size_t>::max()), bucket_list(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
explicit ConstDeallocatingVectorIteratorState(const ConstDeallocatingVectorIteratorState &r)
|
|
||||||
: index(r.index), bucket_list(r.bucket_list)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
explicit ConstDeallocatingVectorIteratorState(const std::size_t idx,
|
|
||||||
const std::vector<ElementT *> *input_list)
|
|
||||||
: index(idx), bucket_list(input_list)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
std::size_t index;
|
|
||||||
const std::vector<ElementT *> *bucket_list;
|
|
||||||
|
|
||||||
ConstDeallocatingVectorIteratorState &
|
|
||||||
operator=(const ConstDeallocatingVectorIteratorState &other)
|
|
||||||
{
|
|
||||||
index = other.index;
|
|
||||||
bucket_list = other.bucket_list;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ElementT> struct DeallocatingVectorIteratorState
|
template <typename ElementT> struct DeallocatingVectorIteratorState
|
||||||
{
|
{
|
||||||
DeallocatingVectorIteratorState()
|
DeallocatingVectorIteratorState()
|
||||||
@@ -67,55 +62,6 @@ template <typename ElementT> struct DeallocatingVectorIteratorState
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK>
|
|
||||||
class ConstDeallocatingVectorIterator
|
|
||||||
: public boost::iterator_facade<ConstDeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>,
|
|
||||||
ElementT,
|
|
||||||
std::random_access_iterator_tag>
|
|
||||||
{
|
|
||||||
ConstDeallocatingVectorIteratorState<ElementT> current_state;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConstDeallocatingVectorIterator() {}
|
|
||||||
ConstDeallocatingVectorIterator(std::size_t idx, const std::vector<ElementT *> *input_list)
|
|
||||||
: current_state(idx, input_list)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
friend class boost::iterator_core_access;
|
|
||||||
|
|
||||||
void advance(std::size_t n) { current_state.index += n; }
|
|
||||||
|
|
||||||
void increment() { advance(1); }
|
|
||||||
|
|
||||||
void decrement() { advance(-1); }
|
|
||||||
|
|
||||||
bool equal(ConstDeallocatingVectorIterator const &other) const
|
|
||||||
{
|
|
||||||
return current_state.index == other.current_state.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ptrdiff_t distance_to(ConstDeallocatingVectorIterator const &other) const
|
|
||||||
{
|
|
||||||
// it is important to implement it 'other minus this'. otherwise sorting breaks
|
|
||||||
return other.current_state.index - current_state.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
ElementT &dereference() const
|
|
||||||
{
|
|
||||||
const std::size_t current_bucket = current_state.index / ELEMENTS_PER_BLOCK;
|
|
||||||
const std::size_t current_index = current_state.index % ELEMENTS_PER_BLOCK;
|
|
||||||
return (current_state.bucket_list->at(current_bucket)[current_index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
ElementT &operator[](const std::size_t index) const
|
|
||||||
{
|
|
||||||
const std::size_t current_bucket = (index + current_state.index) / ELEMENTS_PER_BLOCK;
|
|
||||||
const std::size_t current_index = (index + current_state.index) % ELEMENTS_PER_BLOCK;
|
|
||||||
return (current_state.bucket_list->at(current_bucket)[current_index]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK>
|
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK>
|
||||||
class DeallocatingVectorIterator
|
class DeallocatingVectorIterator
|
||||||
: public boost::iterator_facade<DeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>,
|
: public boost::iterator_facade<DeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>,
|
||||||
@@ -216,11 +162,6 @@ class DeallocatingVectorRemoveIterator
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK> class DeallocatingVector;
|
|
||||||
|
|
||||||
template <typename T, std::size_t S>
|
|
||||||
void swap(DeallocatingVector<T, S> &lhs, DeallocatingVector<T, S> &rhs);
|
|
||||||
|
|
||||||
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK = 8388608 / sizeof(ElementT)>
|
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK = 8388608 / sizeof(ElementT)>
|
||||||
class DeallocatingVector
|
class DeallocatingVector
|
||||||
{
|
{
|
||||||
@@ -229,7 +170,7 @@ class DeallocatingVector
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
using iterator = DeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>;
|
using iterator = DeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>;
|
||||||
using const_iterator = ConstDeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>;
|
using const_iterator = DeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>;
|
||||||
|
|
||||||
// this forward-only iterator deallocates all buckets that have been visited
|
// this forward-only iterator deallocates all buckets that have been visited
|
||||||
using deallocation_iterator = DeallocatingVectorRemoveIterator<ElementT, ELEMENTS_PER_BLOCK>;
|
using deallocation_iterator = DeallocatingVectorRemoveIterator<ElementT, ELEMENTS_PER_BLOCK>;
|
||||||
@@ -241,9 +182,6 @@ class DeallocatingVector
|
|||||||
|
|
||||||
~DeallocatingVector() { clear(); }
|
~DeallocatingVector() { clear(); }
|
||||||
|
|
||||||
friend void swap<>(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &lhs,
|
|
||||||
DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &rhs);
|
|
||||||
|
|
||||||
void swap(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &other)
|
void swap(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &other)
|
||||||
{
|
{
|
||||||
std::swap(current_size, other.current_size);
|
std::swap(current_size, other.current_size);
|
||||||
@@ -306,7 +244,8 @@ class DeallocatingVector
|
|||||||
else
|
else
|
||||||
{ // down-size
|
{ // down-size
|
||||||
const std::size_t number_of_necessary_buckets = 1 + (new_size / ELEMENTS_PER_BLOCK);
|
const std::size_t number_of_necessary_buckets = 1 + (new_size / ELEMENTS_PER_BLOCK);
|
||||||
for (const auto bucket_index : irange(number_of_necessary_buckets, bucket_list.size()))
|
for (const auto bucket_index :
|
||||||
|
osrm::irange(number_of_necessary_buckets, bucket_list.size()))
|
||||||
{
|
{
|
||||||
if (nullptr != bucket_list[bucket_index])
|
if (nullptr != bucket_list[bucket_index])
|
||||||
{
|
{
|
||||||
@@ -372,12 +311,4 @@ class DeallocatingVector
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, std::size_t S>
|
|
||||||
void swap(DeallocatingVector<T, S> &lhs, DeallocatingVector<T, S> &rhs)
|
|
||||||
{
|
|
||||||
lhs.swap(rhs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* DEALLOCATING_VECTOR_HPP */
|
#endif /* DEALLOCATING_VECTOR_HPP */
|
||||||
@@ -1,9 +1,36 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef DYNAMICGRAPH_HPP
|
#ifndef DYNAMICGRAPH_HPP
|
||||||
#define DYNAMICGRAPH_HPP
|
#define DYNAMICGRAPH_HPP
|
||||||
|
|
||||||
#include "util/deallocating_vector.hpp"
|
#include "deallocating_vector.hpp"
|
||||||
#include "util/integer_range.hpp"
|
#include "../util/integer_range.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
@@ -15,18 +42,13 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
|
|
||||||
template <typename EdgeDataT> class DynamicGraph
|
template <typename EdgeDataT> class DynamicGraph
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using EdgeData = EdgeDataT;
|
using EdgeData = EdgeDataT;
|
||||||
using NodeIterator = unsigned;
|
using NodeIterator = unsigned;
|
||||||
using EdgeIterator = unsigned;
|
using EdgeIterator = unsigned;
|
||||||
using EdgeRange = range<EdgeIterator>;
|
using EdgeRange = osrm::range<EdgeIterator>;
|
||||||
|
|
||||||
class InputEdge
|
class InputEdge
|
||||||
{
|
{
|
||||||
@@ -68,16 +90,13 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
*/
|
*/
|
||||||
template <class ContainerT> DynamicGraph(const NodeIterator nodes, const ContainerT &graph)
|
template <class ContainerT> DynamicGraph(const NodeIterator nodes, const ContainerT &graph)
|
||||||
{
|
{
|
||||||
// we need to cast here because DeallocatingVector does not have a valid const iterator
|
|
||||||
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT &>(graph).begin(),
|
|
||||||
const_cast<ContainerT &>(graph).end()));
|
|
||||||
|
|
||||||
number_of_nodes = nodes;
|
number_of_nodes = nodes;
|
||||||
number_of_edges = static_cast<EdgeIterator>(graph.size());
|
number_of_edges = static_cast<EdgeIterator>(graph.size());
|
||||||
|
// node_array.reserve(number_of_nodes + 1);
|
||||||
node_array.resize(number_of_nodes + 1);
|
node_array.resize(number_of_nodes + 1);
|
||||||
EdgeIterator edge = 0;
|
EdgeIterator edge = 0;
|
||||||
EdgeIterator position = 0;
|
EdgeIterator position = 0;
|
||||||
for (const auto node : irange(0u, number_of_nodes))
|
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||||
{
|
{
|
||||||
EdgeIterator last_edge = edge;
|
EdgeIterator last_edge = edge;
|
||||||
while (edge < number_of_edges && graph[edge].source == node)
|
while (edge < number_of_edges && graph[edge].source == node)
|
||||||
@@ -92,13 +111,12 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
edge_list.reserve(static_cast<std::size_t>(edge_list.size() * 1.1));
|
edge_list.reserve(static_cast<std::size_t>(edge_list.size() * 1.1));
|
||||||
edge_list.resize(position);
|
edge_list.resize(position);
|
||||||
edge = 0;
|
edge = 0;
|
||||||
for (const auto node : irange(0u, number_of_nodes))
|
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||||
{
|
{
|
||||||
for (const auto i : irange(node_array[node].first_edge,
|
for (const auto i : osrm::irange(node_array[node].first_edge,
|
||||||
node_array[node].first_edge + node_array[node].edges))
|
node_array[node].first_edge + node_array[node].edges))
|
||||||
{
|
{
|
||||||
edge_list[i].target = graph[edge].target;
|
edge_list[i].target = graph[edge].target;
|
||||||
BOOST_ASSERT(edge_list[i].target < number_of_nodes);
|
|
||||||
edge_list[i].data = graph[edge].data;
|
edge_list[i].data = graph[edge].data;
|
||||||
++edge;
|
++edge;
|
||||||
}
|
}
|
||||||
@@ -116,9 +134,9 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
unsigned GetDirectedOutDegree(const NodeIterator n) const
|
unsigned GetDirectedOutDegree(const NodeIterator n) const
|
||||||
{
|
{
|
||||||
unsigned degree = 0;
|
unsigned degree = 0;
|
||||||
for (const auto edge : irange(BeginEdges(n), EndEdges(n)))
|
for (const auto edge : osrm::irange(BeginEdges(n), EndEdges(n)))
|
||||||
{
|
{
|
||||||
if (!GetEdgeData(edge).reversed)
|
if (GetEdgeData(edge).forward)
|
||||||
{
|
{
|
||||||
++degree;
|
++degree;
|
||||||
}
|
}
|
||||||
@@ -146,7 +164,7 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
|
|
||||||
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
|
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
|
||||||
{
|
{
|
||||||
return irange(BeginEdges(node), EndEdges(node));
|
return osrm::irange(BeginEdges(node), EndEdges(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeIterator InsertNode()
|
NodeIterator InsertNode()
|
||||||
@@ -180,12 +198,12 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
edge_list.reserve(requiredCapacity * 1.1);
|
edge_list.reserve(requiredCapacity * 1.1);
|
||||||
}
|
}
|
||||||
edge_list.resize(edge_list.size() + newSize);
|
edge_list.resize(edge_list.size() + newSize);
|
||||||
for (const auto i : irange(0u, node.edges))
|
for (const auto i : osrm::irange(0u, node.edges))
|
||||||
{
|
{
|
||||||
edge_list[newFirstEdge + i] = edge_list[node.first_edge + i];
|
edge_list[newFirstEdge + i] = edge_list[node.first_edge + i];
|
||||||
makeDummy(node.first_edge + i);
|
makeDummy(node.first_edge + i);
|
||||||
}
|
}
|
||||||
for (const auto i : irange(node.edges + 1, newSize))
|
for (const auto i : osrm::irange(node.edges + 1, newSize))
|
||||||
{
|
{
|
||||||
makeDummy(newFirstEdge + i);
|
makeDummy(newFirstEdge + i);
|
||||||
}
|
}
|
||||||
@@ -240,7 +258,7 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
// searches for a specific edge
|
// searches for a specific edge
|
||||||
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
|
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
|
||||||
{
|
{
|
||||||
for (const auto i : irange(BeginEdges(from), EndEdges(from)))
|
for (const auto i : osrm::irange(BeginEdges(from), EndEdges(from)))
|
||||||
{
|
{
|
||||||
if (to == edge_list[i].target)
|
if (to == edge_list[i].target)
|
||||||
{
|
{
|
||||||
@@ -320,7 +338,5 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
std::vector<Node> node_array;
|
std::vector<Node> node_array;
|
||||||
DeallocatingVector<Edge> edge_list;
|
DeallocatingVector<Edge> edge_list;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // DYNAMICGRAPH_HPP
|
#endif // DYNAMICGRAPH_HPP
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EDGE_BASED_NODE_HPP
|
||||||
|
#define EDGE_BASED_NODE_HPP
|
||||||
|
|
||||||
|
#include "../data_structures/travel_mode.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
struct EdgeBasedNode
|
||||||
|
{
|
||||||
|
EdgeBasedNode()
|
||||||
|
: forward_edge_based_node_id(SPECIAL_NODEID), reverse_edge_based_node_id(SPECIAL_NODEID),
|
||||||
|
u(SPECIAL_NODEID), v(SPECIAL_NODEID), name_id(0),
|
||||||
|
forward_weight(INVALID_EDGE_WEIGHT >> 1), reverse_weight(INVALID_EDGE_WEIGHT >> 1),
|
||||||
|
forward_offset(0), reverse_offset(0), packed_geometry_id(SPECIAL_EDGEID),
|
||||||
|
component_id(-1), fwd_segment_position(std::numeric_limits<unsigned short>::max()),
|
||||||
|
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||||
|
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit EdgeBasedNode(NodeID forward_edge_based_node_id,
|
||||||
|
NodeID reverse_edge_based_node_id,
|
||||||
|
NodeID u,
|
||||||
|
NodeID v,
|
||||||
|
unsigned name_id,
|
||||||
|
int forward_weight,
|
||||||
|
int reverse_weight,
|
||||||
|
int forward_offset,
|
||||||
|
int reverse_offset,
|
||||||
|
unsigned packed_geometry_id,
|
||||||
|
unsigned component_id,
|
||||||
|
unsigned short fwd_segment_position,
|
||||||
|
TravelMode forward_travel_mode,
|
||||||
|
TravelMode backward_travel_mode)
|
||||||
|
: forward_edge_based_node_id(forward_edge_based_node_id),
|
||||||
|
reverse_edge_based_node_id(reverse_edge_based_node_id), u(u), v(v), name_id(name_id),
|
||||||
|
forward_weight(forward_weight), reverse_weight(reverse_weight),
|
||||||
|
forward_offset(forward_offset), reverse_offset(reverse_offset),
|
||||||
|
packed_geometry_id(packed_geometry_id), component_id(component_id),
|
||||||
|
fwd_segment_position(fwd_segment_position), forward_travel_mode(forward_travel_mode),
|
||||||
|
backward_travel_mode(backward_travel_mode)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT((forward_edge_based_node_id != SPECIAL_NODEID) ||
|
||||||
|
(reverse_edge_based_node_id != SPECIAL_NODEID));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline FixedPointCoordinate Centroid(const FixedPointCoordinate &a,
|
||||||
|
const FixedPointCoordinate &b)
|
||||||
|
{
|
||||||
|
FixedPointCoordinate centroid;
|
||||||
|
// The coordinates of the midpoint are given by:
|
||||||
|
centroid.lat = (a.lat + b.lat) / 2;
|
||||||
|
centroid.lon = (a.lon + b.lon) / 2;
|
||||||
|
return centroid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCompressed() const { return packed_geometry_id != SPECIAL_EDGEID; }
|
||||||
|
|
||||||
|
bool is_in_tiny_cc() const { return 0 != component_id; }
|
||||||
|
|
||||||
|
NodeID forward_edge_based_node_id; // needed for edge-expanded graph
|
||||||
|
NodeID reverse_edge_based_node_id; // needed for edge-expanded graph
|
||||||
|
NodeID u; // indices into the coordinates array
|
||||||
|
NodeID v; // indices into the coordinates array
|
||||||
|
unsigned name_id; // id of the edge name
|
||||||
|
int forward_weight; // weight of the edge
|
||||||
|
int reverse_weight; // weight in the other direction (may be different)
|
||||||
|
int forward_offset; // prefix sum of the weight up the edge TODO: short must suffice
|
||||||
|
int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice
|
||||||
|
unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
|
||||||
|
unsigned component_id;
|
||||||
|
unsigned short fwd_segment_position; // segment id in a compressed geometry
|
||||||
|
TravelMode forward_travel_mode : 4;
|
||||||
|
TravelMode backward_travel_mode : 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EDGE_BASED_NODE_HPP
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "external_memory_node.hpp"
|
||||||
|
#include "query_node.hpp"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
ExternalMemoryNode::ExternalMemoryNode(
|
||||||
|
int lat, int lon, unsigned int node_id, bool barrier, bool traffic_lights)
|
||||||
|
: QueryNode(lat, lon, node_id), barrier(barrier), traffic_lights(traffic_lights)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalMemoryNode::ExternalMemoryNode() : barrier(false), traffic_lights(false) {}
|
||||||
|
|
||||||
|
ExternalMemoryNode ExternalMemoryNode::min_value()
|
||||||
|
{
|
||||||
|
return ExternalMemoryNode(0, 0, 0, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalMemoryNode ExternalMemoryNode::max_value()
|
||||||
|
{
|
||||||
|
return ExternalMemoryNode(std::numeric_limits<int>::max(), std::numeric_limits<int>::max(),
|
||||||
|
std::numeric_limits<unsigned>::max(), false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExternalMemoryNodeSTXXLCompare::operator()(const ExternalMemoryNode &left,
|
||||||
|
const ExternalMemoryNode &right) const
|
||||||
|
{
|
||||||
|
return left.node_id < right.node_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalMemoryNodeSTXXLCompare::value_type ExternalMemoryNodeSTXXLCompare::max_value()
|
||||||
|
{
|
||||||
|
return ExternalMemoryNode::max_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalMemoryNodeSTXXLCompare::value_type ExternalMemoryNodeSTXXLCompare::min_value()
|
||||||
|
{
|
||||||
|
return ExternalMemoryNode::min_value();
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXTERNAL_MEMORY_NODE_HPP_
|
||||||
|
#define EXTERNAL_MEMORY_NODE_HPP_
|
||||||
|
|
||||||
|
#include "query_node.hpp"
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
struct ExternalMemoryNode : QueryNode
|
||||||
|
{
|
||||||
|
ExternalMemoryNode(int lat, int lon, NodeID id, bool barrier, bool traffic_light);
|
||||||
|
|
||||||
|
ExternalMemoryNode();
|
||||||
|
|
||||||
|
static ExternalMemoryNode min_value();
|
||||||
|
|
||||||
|
static ExternalMemoryNode max_value();
|
||||||
|
|
||||||
|
bool barrier;
|
||||||
|
bool traffic_lights;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExternalMemoryNodeSTXXLCompare
|
||||||
|
{
|
||||||
|
using value_type = ExternalMemoryNode;
|
||||||
|
bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const;
|
||||||
|
value_type max_value();
|
||||||
|
value_type min_value();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* EXTERNAL_MEMORY_NODE_HPP_ */
|
||||||
@@ -0,0 +1,216 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FIXED_POINT_NUMBER_HPP
|
||||||
|
#define FIXED_POINT_NUMBER_HPP
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
|
||||||
|
// implements an binary based fixed point number type
|
||||||
|
template <unsigned FractionalBitSize,
|
||||||
|
bool use_64_bits = false,
|
||||||
|
bool is_unsigned = false,
|
||||||
|
bool truncate_results = false>
|
||||||
|
class FixedPointNumber
|
||||||
|
{
|
||||||
|
static_assert(FractionalBitSize > 0, "FractionalBitSize must be greater than 0");
|
||||||
|
static_assert(FractionalBitSize <= 32, "FractionalBitSize must at most 32");
|
||||||
|
|
||||||
|
typename std::conditional<use_64_bits, int64_t, int32_t>::type m_fixed_point_state;
|
||||||
|
constexpr static const decltype(m_fixed_point_state) PRECISION = 1 << FractionalBitSize;
|
||||||
|
|
||||||
|
// state signage encapsulates whether the state should either represent a
|
||||||
|
// signed or an unsigned floating point number
|
||||||
|
using state_signage =
|
||||||
|
typename std::conditional<is_unsigned,
|
||||||
|
typename std::make_unsigned<decltype(m_fixed_point_state)>::type,
|
||||||
|
decltype(m_fixed_point_state)>::type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FixedPointNumber() : m_fixed_point_state(0) {}
|
||||||
|
|
||||||
|
// the type is either initialized with a floating point value or an
|
||||||
|
// integral state. Anything else will throw at compile-time.
|
||||||
|
template <class T>
|
||||||
|
constexpr FixedPointNumber(const T &&input) noexcept
|
||||||
|
: m_fixed_point_state(static_cast<decltype(m_fixed_point_state)>(
|
||||||
|
std::round(std::forward<const T>(input) * PRECISION)))
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
std::is_floating_point<T>::value || std::is_integral<T>::value,
|
||||||
|
"FixedPointNumber needs to be initialized with floating point or integral value");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get max value
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||||
|
constexpr static auto max() noexcept -> T
|
||||||
|
{
|
||||||
|
return static_cast<T>(std::numeric_limits<state_signage>::max()) / PRECISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get min value
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||||
|
constexpr static auto min() noexcept -> T
|
||||||
|
{
|
||||||
|
return static_cast<T>(1) / PRECISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get lowest value
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||||
|
constexpr static auto lowest() noexcept -> T
|
||||||
|
{
|
||||||
|
return static_cast<T>(std::numeric_limits<state_signage>::min()) / PRECISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cast to floating point type T, return value
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||||
|
explicit operator const T() const noexcept
|
||||||
|
{
|
||||||
|
// casts to external type (signed or unsigned) and then to float
|
||||||
|
return static_cast<T>(static_cast<state_signage>(m_fixed_point_state)) / PRECISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// warn about cast to integral type T, its disabled for good reason
|
||||||
|
template <typename T, typename std::enable_if<std::is_integral<T>::value>::type * = nullptr>
|
||||||
|
explicit operator T() const
|
||||||
|
{
|
||||||
|
static_assert(std::is_integral<T>::value,
|
||||||
|
"casts to integral types have been disabled on purpose");
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare, ie. sort fixed-point numbers
|
||||||
|
bool operator<(const FixedPointNumber &other) const noexcept
|
||||||
|
{
|
||||||
|
return m_fixed_point_state < other.m_fixed_point_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// equality, ie. sort fixed-point numbers
|
||||||
|
bool operator==(const FixedPointNumber &other) const noexcept
|
||||||
|
{
|
||||||
|
return m_fixed_point_state == other.m_fixed_point_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const FixedPointNumber &other) const { return !(*this == other); }
|
||||||
|
bool operator>(const FixedPointNumber &other) const { return other < *this; }
|
||||||
|
bool operator<=(const FixedPointNumber &other) const { return !(other < *this); }
|
||||||
|
bool operator>=(const FixedPointNumber &other) const { return !(*this < other); }
|
||||||
|
|
||||||
|
// arithmetic operators
|
||||||
|
FixedPointNumber operator+(const FixedPointNumber &other) const noexcept
|
||||||
|
{
|
||||||
|
FixedPointNumber tmp = *this;
|
||||||
|
tmp.m_fixed_point_state += other.m_fixed_point_state;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber &operator+=(const FixedPointNumber &other) noexcept
|
||||||
|
{
|
||||||
|
this->m_fixed_point_state += other.m_fixed_point_state;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber operator-(const FixedPointNumber &other) const noexcept
|
||||||
|
{
|
||||||
|
FixedPointNumber tmp = *this;
|
||||||
|
tmp.m_fixed_point_state -= other.m_fixed_point_state;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber &operator-=(const FixedPointNumber &other) noexcept
|
||||||
|
{
|
||||||
|
this->m_fixed_point_state -= other.m_fixed_point_state;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber operator*(const FixedPointNumber &other) const noexcept
|
||||||
|
{
|
||||||
|
int64_t temp = this->m_fixed_point_state;
|
||||||
|
temp *= other.m_fixed_point_state;
|
||||||
|
|
||||||
|
// rounding!
|
||||||
|
if (!truncate_results)
|
||||||
|
{
|
||||||
|
temp = temp + ((temp & 1 << (FractionalBitSize - 1)) << 1);
|
||||||
|
}
|
||||||
|
temp >>= FractionalBitSize;
|
||||||
|
FixedPointNumber tmp;
|
||||||
|
tmp.m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber &operator*=(const FixedPointNumber &other) noexcept
|
||||||
|
{
|
||||||
|
int64_t temp = this->m_fixed_point_state;
|
||||||
|
temp *= other.m_fixed_point_state;
|
||||||
|
|
||||||
|
// rounding!
|
||||||
|
if (!truncate_results)
|
||||||
|
{
|
||||||
|
temp = temp + ((temp & 1 << (FractionalBitSize - 1)) << 1);
|
||||||
|
}
|
||||||
|
temp >>= FractionalBitSize;
|
||||||
|
this->m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber operator/(const FixedPointNumber &other) const noexcept
|
||||||
|
{
|
||||||
|
int64_t temp = this->m_fixed_point_state;
|
||||||
|
temp <<= FractionalBitSize;
|
||||||
|
temp /= static_cast<int64_t>(other.m_fixed_point_state);
|
||||||
|
FixedPointNumber tmp;
|
||||||
|
tmp.m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber &operator/=(const FixedPointNumber &other) noexcept
|
||||||
|
{
|
||||||
|
int64_t temp = this->m_fixed_point_state;
|
||||||
|
temp <<= FractionalBitSize;
|
||||||
|
temp /= static_cast<int64_t>(other.m_fixed_point_state);
|
||||||
|
FixedPointNumber tmp;
|
||||||
|
this->m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(4 == sizeof(FixedPointNumber<1>), "FP19 has wrong size != 4");
|
||||||
|
}
|
||||||
|
#endif // FIXED_POINT_NUMBER_HPP
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HIDDEN_MARKOV_MODEL
|
||||||
|
#define HIDDEN_MARKOV_MODEL
|
||||||
|
|
||||||
|
#include "../util/integer_range.hpp"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace matching
|
||||||
|
{
|
||||||
|
static const double log_2_pi = std::log(2. * M_PI);
|
||||||
|
static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits<double>::infinity();
|
||||||
|
static const double MINIMAL_LOG_PROB = std::numeric_limits<double>::lowest();
|
||||||
|
static const std::size_t INVALID_STATE = std::numeric_limits<std::size_t>::max();
|
||||||
|
} // namespace matching
|
||||||
|
} // namespace osrm
|
||||||
|
|
||||||
|
// closures to precompute log -> only simple floating point operations
|
||||||
|
struct EmissionLogProbability
|
||||||
|
{
|
||||||
|
double sigma_z;
|
||||||
|
double log_sigma_z;
|
||||||
|
|
||||||
|
EmissionLogProbability(const double sigma_z) : sigma_z(sigma_z), log_sigma_z(std::log(sigma_z))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
double operator()(const double distance) const
|
||||||
|
{
|
||||||
|
return -0.5 * (osrm::matching::log_2_pi + (distance / sigma_z) * (distance / sigma_z)) -
|
||||||
|
log_sigma_z;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TransitionLogProbability
|
||||||
|
{
|
||||||
|
double beta;
|
||||||
|
double log_beta;
|
||||||
|
TransitionLogProbability(const double beta) : beta(beta), log_beta(std::log(beta)) {}
|
||||||
|
|
||||||
|
double operator()(const double d_t) const { return -log_beta - d_t / beta; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class CandidateLists> struct HiddenMarkovModel
|
||||||
|
{
|
||||||
|
std::vector<std::vector<double>> viterbi;
|
||||||
|
std::vector<std::vector<std::pair<unsigned, unsigned>>> parents;
|
||||||
|
std::vector<std::vector<float>> path_lengths;
|
||||||
|
std::vector<std::vector<bool>> pruned;
|
||||||
|
std::vector<std::vector<bool>> suspicious;
|
||||||
|
std::vector<bool> breakage;
|
||||||
|
|
||||||
|
const CandidateLists &candidates_list;
|
||||||
|
const EmissionLogProbability &emission_log_probability;
|
||||||
|
|
||||||
|
HiddenMarkovModel(const CandidateLists &candidates_list,
|
||||||
|
const EmissionLogProbability &emission_log_probability)
|
||||||
|
: breakage(candidates_list.size()), candidates_list(candidates_list),
|
||||||
|
emission_log_probability(emission_log_probability)
|
||||||
|
{
|
||||||
|
for (const auto &l : candidates_list)
|
||||||
|
{
|
||||||
|
viterbi.emplace_back(l.size());
|
||||||
|
parents.emplace_back(l.size());
|
||||||
|
path_lengths.emplace_back(l.size());
|
||||||
|
suspicious.emplace_back(l.size());
|
||||||
|
pruned.emplace_back(l.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
clear(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear(std::size_t initial_timestamp)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(viterbi.size() == parents.size() && parents.size() == path_lengths.size() &&
|
||||||
|
path_lengths.size() == pruned.size() && pruned.size() == breakage.size());
|
||||||
|
|
||||||
|
for (const auto t : osrm::irange(initial_timestamp, viterbi.size()))
|
||||||
|
{
|
||||||
|
std::fill(viterbi[t].begin(), viterbi[t].end(), osrm::matching::IMPOSSIBLE_LOG_PROB);
|
||||||
|
std::fill(parents[t].begin(), parents[t].end(), std::make_pair(0u, 0u));
|
||||||
|
std::fill(path_lengths[t].begin(), path_lengths[t].end(), 0);
|
||||||
|
std::fill(suspicious[t].begin(), suspicious[t].end(), true);
|
||||||
|
std::fill(pruned[t].begin(), pruned[t].end(), true);
|
||||||
|
}
|
||||||
|
std::fill(breakage.begin() + initial_timestamp, breakage.end(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t initialize(std::size_t initial_timestamp)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(initial_timestamp < candidates_list.size());
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
for (const auto s : osrm::irange<std::size_t>(0u, viterbi[initial_timestamp].size()))
|
||||||
|
{
|
||||||
|
viterbi[initial_timestamp][s] =
|
||||||
|
emission_log_probability(candidates_list[initial_timestamp][s].second);
|
||||||
|
parents[initial_timestamp][s] = std::make_pair(initial_timestamp, s);
|
||||||
|
pruned[initial_timestamp][s] =
|
||||||
|
viterbi[initial_timestamp][s] < osrm::matching::MINIMAL_LOG_PROB;
|
||||||
|
suspicious[initial_timestamp][s] = false;
|
||||||
|
|
||||||
|
breakage[initial_timestamp] =
|
||||||
|
breakage[initial_timestamp] && pruned[initial_timestamp][s];
|
||||||
|
}
|
||||||
|
|
||||||
|
++initial_timestamp;
|
||||||
|
} while (breakage[initial_timestamp - 1]);
|
||||||
|
|
||||||
|
if (initial_timestamp >= viterbi.size())
|
||||||
|
{
|
||||||
|
return osrm::matching::INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(initial_timestamp > 0);
|
||||||
|
--initial_timestamp;
|
||||||
|
|
||||||
|
BOOST_ASSERT(breakage[initial_timestamp] == false);
|
||||||
|
|
||||||
|
return initial_timestamp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HIDDEN_MARKOV_MODEL
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hilbert_value.hpp"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
uint64_t HilbertCode::operator()(const FixedPointCoordinate ¤t_coordinate) const
|
||||||
|
{
|
||||||
|
unsigned location[2];
|
||||||
|
location[0] = current_coordinate.lat + static_cast<int>(90 * COORDINATE_PRECISION);
|
||||||
|
location[1] = current_coordinate.lon + static_cast<int>(180 * COORDINATE_PRECISION);
|
||||||
|
|
||||||
|
TransposeCoordinate(location);
|
||||||
|
return BitInterleaving(location[0], location[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t HilbertCode::BitInterleaving(const uint32_t latitude, const uint32_t longitude) const
|
||||||
|
{
|
||||||
|
uint64_t result = 0;
|
||||||
|
for (int8_t index = 31; index >= 0; --index)
|
||||||
|
{
|
||||||
|
result |= (latitude >> index) & 1;
|
||||||
|
result <<= 1;
|
||||||
|
result |= (longitude >> index) & 1;
|
||||||
|
if (0 != index)
|
||||||
|
{
|
||||||
|
result <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HilbertCode::TransposeCoordinate(uint32_t *X) const
|
||||||
|
{
|
||||||
|
uint32_t M = 1 << (32 - 1), P, Q, t;
|
||||||
|
int i;
|
||||||
|
// Inverse undo
|
||||||
|
for (Q = M; Q > 1; Q >>= 1)
|
||||||
|
{
|
||||||
|
P = Q - 1;
|
||||||
|
for (i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
|
||||||
|
const bool condition = (X[i] & Q);
|
||||||
|
if (condition)
|
||||||
|
{
|
||||||
|
X[0] ^= P; // invert
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = (X[0] ^ X[i]) & P;
|
||||||
|
X[0] ^= t;
|
||||||
|
X[i] ^= t;
|
||||||
|
}
|
||||||
|
} // exchange
|
||||||
|
}
|
||||||
|
// Gray encode
|
||||||
|
for (i = 1; i < 2; ++i)
|
||||||
|
{
|
||||||
|
X[i] ^= X[i - 1];
|
||||||
|
}
|
||||||
|
t = 0;
|
||||||
|
for (Q = M; Q > 1; Q >>= 1)
|
||||||
|
{
|
||||||
|
const bool condition = (X[2 - 1] & Q);
|
||||||
|
if (condition)
|
||||||
|
{
|
||||||
|
t ^= Q - 1;
|
||||||
|
}
|
||||||
|
} // check if this for loop is wrong
|
||||||
|
for (i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
X[i] ^= t;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright (c) 2016, Project OSRM contributors
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -25,28 +25,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef OSRM_ENGINE_BEARING_HPP
|
#ifndef HILBERT_VALUE_HPP
|
||||||
#define OSRM_ENGINE_BEARING_HPP
|
#define HILBERT_VALUE_HPP
|
||||||
|
|
||||||
namespace osrm
|
#include <cstdint>
|
||||||
{
|
|
||||||
namespace engine
|
|
||||||
{
|
|
||||||
|
|
||||||
struct Bearing
|
// computes a 64 bit value that corresponds to the hilbert space filling curve
|
||||||
{
|
|
||||||
short bearing;
|
|
||||||
short range;
|
|
||||||
|
|
||||||
bool IsValid() const { return bearing >= 0 && bearing <= 360 && range >= 0 && range <= 180; }
|
struct FixedPointCoordinate;
|
||||||
|
|
||||||
|
class HilbertCode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint64_t operator()(const FixedPointCoordinate ¤t_coordinate) const;
|
||||||
|
HilbertCode() {}
|
||||||
|
HilbertCode(const HilbertCode &) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) const;
|
||||||
|
inline void TransposeCoordinate(uint32_t *X) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator==(const Bearing lhs, const Bearing rhs)
|
#endif /* HILBERT_VALUE_HPP */
|
||||||
{
|
|
||||||
return lhs.bearing == rhs.bearing && lhs.range == rhs.range;
|
|
||||||
}
|
|
||||||
inline bool operator!=(const Bearing lhs, const Bearing rhs) { return !(lhs == rhs); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "import_edge.hpp"
|
||||||
|
|
||||||
|
#include "travel_mode.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
|
||||||
|
{
|
||||||
|
if (source == other.source)
|
||||||
|
{
|
||||||
|
if (target == other.target)
|
||||||
|
{
|
||||||
|
if (weight == other.weight)
|
||||||
|
{
|
||||||
|
return forward && backward && ((!other.forward) || (!other.backward));
|
||||||
|
}
|
||||||
|
return weight < other.weight;
|
||||||
|
}
|
||||||
|
return target < other.target;
|
||||||
|
}
|
||||||
|
return source < other.source;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeBasedEdge::NodeBasedEdge()
|
||||||
|
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), forward(false),
|
||||||
|
backward(false), roundabout(false), in_tiny_cc(false),
|
||||||
|
access_restricted(false), is_split(false), travel_mode(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeBasedEdge::NodeBasedEdge(NodeID source,
|
||||||
|
NodeID target,
|
||||||
|
NodeID name_id,
|
||||||
|
EdgeWeight weight,
|
||||||
|
bool forward,
|
||||||
|
bool backward,
|
||||||
|
bool roundabout,
|
||||||
|
bool in_tiny_cc,
|
||||||
|
bool access_restricted,
|
||||||
|
TravelMode travel_mode,
|
||||||
|
bool is_split)
|
||||||
|
: source(source), target(target), name_id(name_id), weight(weight), forward(forward),
|
||||||
|
backward(backward), roundabout(roundabout), in_tiny_cc(in_tiny_cc),
|
||||||
|
access_restricted(access_restricted), is_split(is_split), travel_mode(travel_mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EdgeBasedEdge::operator<(const EdgeBasedEdge &other) const
|
||||||
|
{
|
||||||
|
if (source == other.source)
|
||||||
|
{
|
||||||
|
if (target == other.target)
|
||||||
|
{
|
||||||
|
if (weight == other.weight)
|
||||||
|
{
|
||||||
|
return forward && backward && ((!other.forward) || (!other.backward));
|
||||||
|
}
|
||||||
|
return weight < other.weight;
|
||||||
|
}
|
||||||
|
return target < other.target;
|
||||||
|
}
|
||||||
|
return source < other.source;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class EdgeT>
|
||||||
|
EdgeBasedEdge::EdgeBasedEdge(const EdgeT &other)
|
||||||
|
: source(other.source), target(other.target), edge_id(other.data.via),
|
||||||
|
weight(other.data.distance), forward(other.data.forward), backward(other.data.backward)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Default constructor. target and weight are set to 0.*/
|
||||||
|
EdgeBasedEdge::EdgeBasedEdge()
|
||||||
|
: source(0), target(0), edge_id(0), weight(0), forward(false), backward(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
|
||||||
|
const NodeID target,
|
||||||
|
const NodeID edge_id,
|
||||||
|
const EdgeWeight weight,
|
||||||
|
const bool forward,
|
||||||
|
const bool backward)
|
||||||
|
: source(source), target(target), edge_id(edge_id), weight(weight), forward(forward),
|
||||||
|
backward(backward)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IMPORT_EDGE_HPP
|
||||||
|
#define IMPORT_EDGE_HPP
|
||||||
|
|
||||||
|
#include "../data_structures/travel_mode.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
struct NodeBasedEdge
|
||||||
|
{
|
||||||
|
bool operator<(const NodeBasedEdge &e) const;
|
||||||
|
|
||||||
|
NodeBasedEdge();
|
||||||
|
explicit NodeBasedEdge(NodeID source,
|
||||||
|
NodeID target,
|
||||||
|
NodeID name_id,
|
||||||
|
EdgeWeight weight,
|
||||||
|
bool forward,
|
||||||
|
bool backward,
|
||||||
|
bool roundabout,
|
||||||
|
bool in_tiny_cc,
|
||||||
|
bool access_restricted,
|
||||||
|
TravelMode travel_mode,
|
||||||
|
bool is_split);
|
||||||
|
|
||||||
|
NodeID source;
|
||||||
|
NodeID target;
|
||||||
|
NodeID name_id;
|
||||||
|
EdgeWeight weight;
|
||||||
|
bool forward : 1;
|
||||||
|
bool backward : 1;
|
||||||
|
bool roundabout : 1;
|
||||||
|
bool in_tiny_cc : 1;
|
||||||
|
bool access_restricted : 1;
|
||||||
|
bool is_split : 1;
|
||||||
|
TravelMode travel_mode : 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EdgeBasedEdge
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool operator<(const EdgeBasedEdge &e) const;
|
||||||
|
|
||||||
|
template <class EdgeT> explicit EdgeBasedEdge(const EdgeT &myEdge);
|
||||||
|
|
||||||
|
EdgeBasedEdge();
|
||||||
|
|
||||||
|
explicit EdgeBasedEdge(const NodeID source,
|
||||||
|
const NodeID target,
|
||||||
|
const NodeID edge_id,
|
||||||
|
const EdgeWeight weight,
|
||||||
|
const bool forward,
|
||||||
|
const bool backward);
|
||||||
|
NodeID source;
|
||||||
|
NodeID target;
|
||||||
|
NodeID edge_id;
|
||||||
|
EdgeWeight weight : 30;
|
||||||
|
bool forward : 1;
|
||||||
|
bool backward : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* IMPORT_EDGE_HPP */
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RAW_ROUTE_DATA_H
|
||||||
|
#define RAW_ROUTE_DATA_H
|
||||||
|
|
||||||
|
#include "../data_structures/phantom_node.hpp"
|
||||||
|
#include "../data_structures/travel_mode.hpp"
|
||||||
|
#include "../data_structures/turn_instructions.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct PathData
|
||||||
|
{
|
||||||
|
PathData()
|
||||||
|
: node(SPECIAL_NODEID), name_id(INVALID_EDGE_WEIGHT), segment_duration(INVALID_EDGE_WEIGHT),
|
||||||
|
turn_instruction(TurnInstruction::NoTurn), travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PathData(NodeID node,
|
||||||
|
unsigned name_id,
|
||||||
|
TurnInstruction turn_instruction,
|
||||||
|
EdgeWeight segment_duration,
|
||||||
|
TravelMode travel_mode)
|
||||||
|
: node(node), name_id(name_id), segment_duration(segment_duration),
|
||||||
|
turn_instruction(turn_instruction), travel_mode(travel_mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
NodeID node;
|
||||||
|
unsigned name_id;
|
||||||
|
EdgeWeight segment_duration;
|
||||||
|
TurnInstruction turn_instruction;
|
||||||
|
TravelMode travel_mode : 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InternalRouteResult
|
||||||
|
{
|
||||||
|
std::vector<std::vector<PathData>> unpacked_path_segments;
|
||||||
|
std::vector<PathData> unpacked_alternative;
|
||||||
|
std::vector<PhantomNodes> segment_end_coordinates;
|
||||||
|
std::vector<bool> source_traversed_in_reverse;
|
||||||
|
std::vector<bool> target_traversed_in_reverse;
|
||||||
|
std::vector<bool> alt_source_traversed_in_reverse;
|
||||||
|
std::vector<bool> alt_target_traversed_in_reverse;
|
||||||
|
int shortest_path_length;
|
||||||
|
int alternative_path_length;
|
||||||
|
|
||||||
|
bool is_via_leg(const std::size_t leg) const
|
||||||
|
{
|
||||||
|
return (leg != unpacked_path_segments.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
InternalRouteResult()
|
||||||
|
: shortest_path_length(INVALID_EDGE_WEIGHT), alternative_path_length(INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RAW_ROUTE_DATA_H
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LRUCACHE_HPP
|
||||||
|
#define LRUCACHE_HPP
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
template <typename KeyT, typename ValueT> class LRUCache
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct CacheEntry
|
||||||
|
{
|
||||||
|
CacheEntry(KeyT k, ValueT v) : key(k), value(v) {}
|
||||||
|
KeyT key;
|
||||||
|
ValueT value;
|
||||||
|
};
|
||||||
|
unsigned capacity;
|
||||||
|
std::list<CacheEntry> itemsInCache;
|
||||||
|
std::unordered_map<KeyT, typename std::list<CacheEntry>::iterator> positionMap;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit LRUCache(unsigned c) : capacity(c) {}
|
||||||
|
|
||||||
|
bool Holds(KeyT key)
|
||||||
|
{
|
||||||
|
if (positionMap.find(key) != positionMap.end())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Insert(const KeyT key, ValueT &value)
|
||||||
|
{
|
||||||
|
itemsInCache.push_front(CacheEntry(key, value));
|
||||||
|
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
|
||||||
|
if (itemsInCache.size() > capacity)
|
||||||
|
{
|
||||||
|
positionMap.erase(itemsInCache.back().key);
|
||||||
|
itemsInCache.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Insert(const KeyT key, ValueT value)
|
||||||
|
{
|
||||||
|
itemsInCache.push_front(CacheEntry(key, value));
|
||||||
|
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
|
||||||
|
if (itemsInCache.size() > capacity)
|
||||||
|
{
|
||||||
|
positionMap.erase(itemsInCache.back().key);
|
||||||
|
itemsInCache.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Fetch(const KeyT key, ValueT &result)
|
||||||
|
{
|
||||||
|
if (Holds(key))
|
||||||
|
{
|
||||||
|
CacheEntry e = *(positionMap.find(key)->second);
|
||||||
|
result = e.value;
|
||||||
|
|
||||||
|
// move to front
|
||||||
|
itemsInCache.splice(itemsInCache.begin(), itemsInCache, positionMap.find(key)->second);
|
||||||
|
positionMap.find(key)->second = itemsInCache.begin();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unsigned Size() const { return itemsInCache.size(); }
|
||||||
|
};
|
||||||
|
#endif // LRUCACHE_HPP
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NODE_BASED_GRAPH_HPP
|
||||||
|
#define NODE_BASED_GRAPH_HPP
|
||||||
|
|
||||||
|
#include "dynamic_graph.hpp"
|
||||||
|
#include "import_edge.hpp"
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct NodeBasedEdgeData
|
||||||
|
{
|
||||||
|
NodeBasedEdgeData()
|
||||||
|
: distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
|
||||||
|
nameID(std::numeric_limits<unsigned>::max()), isAccessRestricted(false), shortcut(false),
|
||||||
|
forward(false), backward(false), roundabout(false), ignore_in_grid(false),
|
||||||
|
travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int distance;
|
||||||
|
unsigned edgeBasedNodeID;
|
||||||
|
unsigned nameID;
|
||||||
|
bool isAccessRestricted : 1;
|
||||||
|
bool shortcut : 1;
|
||||||
|
bool forward : 1;
|
||||||
|
bool backward : 1;
|
||||||
|
bool roundabout : 1;
|
||||||
|
bool ignore_in_grid : 1;
|
||||||
|
TravelMode travel_mode : 4;
|
||||||
|
|
||||||
|
void SwapDirectionFlags()
|
||||||
|
{
|
||||||
|
bool temp_flag = forward;
|
||||||
|
forward = backward;
|
||||||
|
backward = temp_flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCompatibleTo(const NodeBasedEdgeData &other) const
|
||||||
|
{
|
||||||
|
return (forward == other.forward) && (backward == other.backward) &&
|
||||||
|
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
|
||||||
|
(travel_mode == other.travel_mode);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using NodeBasedDynamicGraph = DynamicGraph<NodeBasedEdgeData>;
|
||||||
|
|
||||||
|
inline bool validateNeighborHood(const NodeBasedDynamicGraph& graph, const NodeID source)
|
||||||
|
{
|
||||||
|
for (auto edge = graph.BeginEdges(source); edge < graph.EndEdges(source); ++edge)
|
||||||
|
{
|
||||||
|
const auto& data = graph.GetEdgeData(edge);
|
||||||
|
if (!data.forward && !data.backward)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Invalid edge directions";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto target = graph.GetTarget(edge);
|
||||||
|
if (target == SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Invalid edge target";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found_reverse = false;
|
||||||
|
for (auto rev_edge = graph.BeginEdges(target); rev_edge < graph.EndEdges(target); ++rev_edge)
|
||||||
|
{
|
||||||
|
auto rev_target = graph.GetTarget(rev_edge);
|
||||||
|
if (rev_target == SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Invalid reverse edge target";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rev_target != source)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_reverse)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Found more than one reverse edge";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& rev_data = graph.GetEdgeData(rev_edge);
|
||||||
|
|
||||||
|
// edge is incoming, this must be an outgoing edge
|
||||||
|
if (data.backward && !rev_data.forward)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Found no outgoing edge to an incoming edge!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// edge is bi-directional, reverse must be as well
|
||||||
|
if (data.forward && data.backward && (!rev_data.forward || !rev_data.backward))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Found bi-directional edge that is not bi-directional to both ends";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
found_reverse = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_reverse)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Could not find reverse edge";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function checks if the overal graph is undirected (has an edge in each direction).
|
||||||
|
inline bool validateNodeBasedGraph(const NodeBasedDynamicGraph& graph)
|
||||||
|
{
|
||||||
|
for (auto source = 0u; source < graph.GetNumberOfNodes(); ++source)
|
||||||
|
{
|
||||||
|
if (!validateNeighborHood(graph, source))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Factory method to create NodeBasedDynamicGraph from NodeBasedEdges
|
||||||
|
// The since DynamicGraph expects directed edges, we need to insert
|
||||||
|
// two edges for undirected edges.
|
||||||
|
inline std::shared_ptr<NodeBasedDynamicGraph>
|
||||||
|
NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<NodeBasedEdge> &input_edge_list)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(NodeBasedEdgeData) == 16,
|
||||||
|
"changing node based edge data size changes memory consumption");
|
||||||
|
|
||||||
|
DeallocatingVector<NodeBasedDynamicGraph::InputEdge> edges_list;
|
||||||
|
NodeBasedDynamicGraph::InputEdge edge;
|
||||||
|
|
||||||
|
// Since DynamicGraph assumes directed edges we have to make sure we transformed
|
||||||
|
// the compressed edge format into single directed edges. We do this to make sure
|
||||||
|
// every node also knows its incoming edges, not only its outgoing edges and use the backward=true
|
||||||
|
// flag to indicate which is which.
|
||||||
|
//
|
||||||
|
// We do the transformation in the following way:
|
||||||
|
//
|
||||||
|
// if the edge (a, b) is split:
|
||||||
|
// 1. this edge must be in only one direction, so its a --> b
|
||||||
|
// 2. there must be another directed edge b --> a somewhere in the data
|
||||||
|
// if the edge (a, b) is not split:
|
||||||
|
// 1. this edge be on of a --> b od a <-> b
|
||||||
|
// (a <-- b gets reducted to b --> a)
|
||||||
|
// 2. a --> b will be transformed to a --> b and b <-- a
|
||||||
|
// 3. a <-> b will be transformed to a <-> b and b <-> a (I think a --> b and b <-- a would work as well though)
|
||||||
|
for (const NodeBasedEdge &import_edge : input_edge_list)
|
||||||
|
{
|
||||||
|
// edges that are not forward get converted by flipping the end points
|
||||||
|
BOOST_ASSERT(import_edge.forward);
|
||||||
|
|
||||||
|
if (import_edge.forward)
|
||||||
|
{
|
||||||
|
edge.source = import_edge.source;
|
||||||
|
edge.target = import_edge.target;
|
||||||
|
edge.data.forward = import_edge.forward;
|
||||||
|
edge.data.backward = import_edge.backward;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(edge.source != edge.target);
|
||||||
|
|
||||||
|
edge.data.distance = static_cast<int>(import_edge.weight);
|
||||||
|
BOOST_ASSERT(edge.data.distance > 0);
|
||||||
|
edge.data.shortcut = false;
|
||||||
|
edge.data.roundabout = import_edge.roundabout;
|
||||||
|
edge.data.ignore_in_grid = import_edge.in_tiny_cc;
|
||||||
|
edge.data.nameID = import_edge.name_id;
|
||||||
|
edge.data.isAccessRestricted = import_edge.access_restricted;
|
||||||
|
edge.data.travel_mode = import_edge.travel_mode;
|
||||||
|
|
||||||
|
edges_list.push_back(edge);
|
||||||
|
|
||||||
|
if (!import_edge.is_split)
|
||||||
|
{
|
||||||
|
using std::swap; // enable ADL
|
||||||
|
swap(edge.source, edge.target);
|
||||||
|
edge.data.SwapDirectionFlags();
|
||||||
|
edges_list.push_back(edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tbb::parallel_sort(edges_list.begin(), edges_list.end());
|
||||||
|
|
||||||
|
auto graph = std::make_shared<NodeBasedDynamicGraph>(
|
||||||
|
static_cast<NodeBasedDynamicGraph::NodeIterator>(number_of_nodes), edges_list);
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
BOOST_ASSERT(validateNodeBasedGraph(*graph));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // NODE_BASED_GRAPH_HPP
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright (c) 2016, Project OSRM contributors
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -25,27 +25,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ENGINE_API_TILE_PARAMETERS_HPP
|
#ifndef NODE_ID_HPP
|
||||||
#define ENGINE_API_TILE_PARAMETERS_HPP
|
#define NODE_ID_HPP
|
||||||
|
|
||||||
namespace osrm
|
#include "../typedefs.h"
|
||||||
{
|
|
||||||
namespace engine
|
|
||||||
{
|
|
||||||
namespace api
|
|
||||||
{
|
|
||||||
|
|
||||||
struct TileParameters final
|
struct Cmp
|
||||||
{
|
{
|
||||||
unsigned x;
|
using value_type = NodeID;
|
||||||
unsigned y;
|
bool operator()(const NodeID left, const NodeID right) const { return left < right; }
|
||||||
unsigned z;
|
value_type max_value() { return 0xffffffff; }
|
||||||
|
value_type min_value() { return 0x0; }
|
||||||
// FIXME check if x and y work with z
|
|
||||||
bool IsValid() { return z < 20; };
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif // NODE_ID_HPP
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ORIGINAL_EDGE_DATA_HPP
|
||||||
|
#define ORIGINAL_EDGE_DATA_HPP
|
||||||
|
|
||||||
|
#include "travel_mode.hpp"
|
||||||
|
#include "turn_instructions.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
struct OriginalEdgeData
|
||||||
|
{
|
||||||
|
explicit OriginalEdgeData(NodeID via_node,
|
||||||
|
unsigned name_id,
|
||||||
|
TurnInstruction turn_instruction,
|
||||||
|
bool compressed_geometry,
|
||||||
|
TravelMode travel_mode)
|
||||||
|
: via_node(via_node), name_id(name_id), turn_instruction(turn_instruction),
|
||||||
|
compressed_geometry(compressed_geometry), travel_mode(travel_mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OriginalEdgeData()
|
||||||
|
: via_node(std::numeric_limits<unsigned>::max()),
|
||||||
|
name_id(std::numeric_limits<unsigned>::max()), turn_instruction(TurnInstruction::NoTurn),
|
||||||
|
compressed_geometry(false), travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeID via_node;
|
||||||
|
unsigned name_id;
|
||||||
|
TurnInstruction turn_instruction;
|
||||||
|
bool compressed_geometry;
|
||||||
|
TravelMode travel_mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ORIGINAL_EDGE_DATA_HPP
|
||||||
@@ -1,14 +1,36 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef PERCENT_HPP
|
#ifndef PERCENT_HPP
|
||||||
#define PERCENT_HPP
|
#define PERCENT_HPP
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
|
|
||||||
class Percent
|
class Percent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -75,7 +97,5 @@ class Percent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // PERCENT_HPP
|
#endif // PERCENT_HPP
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "phantom_node.hpp"
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "travel_mode.hpp"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
PhantomNode::PhantomNode(NodeID forward_node_id,
|
||||||
|
NodeID reverse_node_id,
|
||||||
|
unsigned name_id,
|
||||||
|
int forward_weight,
|
||||||
|
int reverse_weight,
|
||||||
|
int forward_offset,
|
||||||
|
int reverse_offset,
|
||||||
|
unsigned packed_geometry_id,
|
||||||
|
unsigned component_id,
|
||||||
|
FixedPointCoordinate &location,
|
||||||
|
unsigned short fwd_segment_position,
|
||||||
|
TravelMode forward_travel_mode,
|
||||||
|
TravelMode backward_travel_mode)
|
||||||
|
: forward_node_id(forward_node_id), reverse_node_id(reverse_node_id), name_id(name_id),
|
||||||
|
forward_weight(forward_weight), reverse_weight(reverse_weight),
|
||||||
|
forward_offset(forward_offset), reverse_offset(reverse_offset),
|
||||||
|
packed_geometry_id(packed_geometry_id), component_id(component_id), location(location),
|
||||||
|
fwd_segment_position(fwd_segment_position), forward_travel_mode(forward_travel_mode),
|
||||||
|
backward_travel_mode(backward_travel_mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PhantomNode::PhantomNode()
|
||||||
|
: forward_node_id(SPECIAL_NODEID), reverse_node_id(SPECIAL_NODEID),
|
||||||
|
name_id(std::numeric_limits<unsigned>::max()), forward_weight(INVALID_EDGE_WEIGHT),
|
||||||
|
reverse_weight(INVALID_EDGE_WEIGHT), forward_offset(0), reverse_offset(0),
|
||||||
|
packed_geometry_id(SPECIAL_EDGEID), component_id(std::numeric_limits<unsigned>::max()),
|
||||||
|
fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||||
|
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int PhantomNode::GetForwardWeightPlusOffset() const
|
||||||
|
{
|
||||||
|
if (SPECIAL_NODEID == forward_node_id)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return forward_offset + forward_weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PhantomNode::GetReverseWeightPlusOffset() const
|
||||||
|
{
|
||||||
|
if (SPECIAL_NODEID == reverse_node_id)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return reverse_offset + reverse_weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhantomNode::is_bidirected() const
|
||||||
|
{
|
||||||
|
return (forward_node_id != SPECIAL_NODEID) && (reverse_node_id != SPECIAL_NODEID);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhantomNode::is_compressed() const { return (forward_offset != 0) || (reverse_offset != 0); }
|
||||||
|
|
||||||
|
bool PhantomNode::is_valid(const unsigned number_of_nodes) const
|
||||||
|
{
|
||||||
|
return location.is_valid() &&
|
||||||
|
((forward_node_id < number_of_nodes) || (reverse_node_id < number_of_nodes)) &&
|
||||||
|
((forward_weight != INVALID_EDGE_WEIGHT) || (reverse_weight != INVALID_EDGE_WEIGHT)) &&
|
||||||
|
(name_id != INVALID_NAMEID);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhantomNode::is_in_tiny_component() const { return component_id != 0; }
|
||||||
|
|
||||||
|
bool PhantomNode::is_valid() const { return location.is_valid() && (name_id != INVALID_NAMEID); }
|
||||||
|
|
||||||
|
bool PhantomNode::operator==(const PhantomNode &other) const { return location == other.location; }
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PHANTOM_NODES_H
|
||||||
|
#define PHANTOM_NODES_H
|
||||||
|
|
||||||
|
#include "travel_mode.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct PhantomNode
|
||||||
|
{
|
||||||
|
PhantomNode(NodeID forward_node_id,
|
||||||
|
NodeID reverse_node_id,
|
||||||
|
unsigned name_id,
|
||||||
|
int forward_weight,
|
||||||
|
int reverse_weight,
|
||||||
|
int forward_offset,
|
||||||
|
int reverse_offset,
|
||||||
|
unsigned packed_geometry_id,
|
||||||
|
unsigned component_id,
|
||||||
|
FixedPointCoordinate &location,
|
||||||
|
unsigned short fwd_segment_position,
|
||||||
|
TravelMode forward_travel_mode,
|
||||||
|
TravelMode backward_travel_mode);
|
||||||
|
|
||||||
|
PhantomNode();
|
||||||
|
|
||||||
|
template <class OtherT> PhantomNode(const OtherT &other, const FixedPointCoordinate &foot_point)
|
||||||
|
{
|
||||||
|
forward_node_id = other.forward_edge_based_node_id;
|
||||||
|
reverse_node_id = other.reverse_edge_based_node_id;
|
||||||
|
name_id = other.name_id;
|
||||||
|
|
||||||
|
forward_weight = other.forward_weight;
|
||||||
|
reverse_weight = other.reverse_weight;
|
||||||
|
|
||||||
|
forward_offset = other.forward_offset;
|
||||||
|
reverse_offset = other.reverse_offset;
|
||||||
|
|
||||||
|
packed_geometry_id = other.packed_geometry_id;
|
||||||
|
component_id = other.component_id;
|
||||||
|
|
||||||
|
location = foot_point;
|
||||||
|
fwd_segment_position = other.fwd_segment_position;
|
||||||
|
|
||||||
|
forward_travel_mode = other.forward_travel_mode;
|
||||||
|
backward_travel_mode = other.backward_travel_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeID forward_node_id;
|
||||||
|
NodeID reverse_node_id;
|
||||||
|
unsigned name_id;
|
||||||
|
int forward_weight;
|
||||||
|
int reverse_weight;
|
||||||
|
int forward_offset;
|
||||||
|
int reverse_offset;
|
||||||
|
unsigned packed_geometry_id;
|
||||||
|
unsigned component_id;
|
||||||
|
FixedPointCoordinate location;
|
||||||
|
unsigned short fwd_segment_position;
|
||||||
|
TravelMode forward_travel_mode : 4;
|
||||||
|
TravelMode backward_travel_mode : 4;
|
||||||
|
|
||||||
|
int GetForwardWeightPlusOffset() const;
|
||||||
|
|
||||||
|
int GetReverseWeightPlusOffset() const;
|
||||||
|
|
||||||
|
bool is_bidirected() const;
|
||||||
|
|
||||||
|
bool is_compressed() const;
|
||||||
|
|
||||||
|
bool is_valid(const unsigned numberOfNodes) const;
|
||||||
|
|
||||||
|
bool is_valid() const;
|
||||||
|
|
||||||
|
bool is_in_tiny_component() const;
|
||||||
|
|
||||||
|
bool operator==(const PhantomNode &other) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
using PhantomNodeArray = std::vector<std::vector<PhantomNode>>;
|
||||||
|
|
||||||
|
class phantom_node_pair : public std::pair<PhantomNode, PhantomNode>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PhantomNodeLists
|
||||||
|
{
|
||||||
|
std::vector<PhantomNode> source_phantom_list;
|
||||||
|
std::vector<PhantomNode> target_phantom_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PhantomNodes
|
||||||
|
{
|
||||||
|
PhantomNode source_phantom;
|
||||||
|
PhantomNode target_phantom;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::ostream &operator<<(std::ostream &out, const PhantomNodes &pn)
|
||||||
|
{
|
||||||
|
out << "source_coord: " << pn.source_phantom.location << "\n";
|
||||||
|
out << "target_coord: " << pn.target_phantom.location << std::endl;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream &operator<<(std::ostream &out, const PhantomNode &pn)
|
||||||
|
{
|
||||||
|
out << "node1: " << pn.forward_node_id << ", "
|
||||||
|
<< "node2: " << pn.reverse_node_id << ", "
|
||||||
|
<< "name: " << pn.name_id << ", "
|
||||||
|
<< "fwd-w: " << pn.forward_weight << ", "
|
||||||
|
<< "rev-w: " << pn.reverse_weight << ", "
|
||||||
|
<< "fwd-o: " << pn.forward_offset << ", "
|
||||||
|
<< "rev-o: " << pn.reverse_offset << ", "
|
||||||
|
<< "geom: " << pn.packed_geometry_id << ", "
|
||||||
|
<< "comp: " << pn.component_id << ", "
|
||||||
|
<< "pos: " << pn.fwd_segment_position << ", "
|
||||||
|
<< "loc: " << pn.location;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PHANTOM_NODES_H
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QUERYEDGE_HPP
|
||||||
|
#define QUERYEDGE_HPP
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
struct QueryEdge
|
||||||
|
{
|
||||||
|
NodeID source;
|
||||||
|
NodeID target;
|
||||||
|
struct EdgeData
|
||||||
|
{
|
||||||
|
EdgeData() : id(0), shortcut(false), distance(0), forward(false), backward(false) {}
|
||||||
|
|
||||||
|
template <class OtherT> EdgeData(const OtherT &other)
|
||||||
|
{
|
||||||
|
distance = other.distance;
|
||||||
|
shortcut = other.shortcut;
|
||||||
|
id = other.id;
|
||||||
|
forward = other.forward;
|
||||||
|
backward = other.backward;
|
||||||
|
}
|
||||||
|
NodeID id : 31;
|
||||||
|
bool shortcut : 1;
|
||||||
|
int distance : 30;
|
||||||
|
bool forward : 1;
|
||||||
|
bool backward : 1;
|
||||||
|
} data;
|
||||||
|
|
||||||
|
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
|
||||||
|
|
||||||
|
QueryEdge(NodeID source, NodeID target, EdgeData data)
|
||||||
|
: source(source), target(target), data(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const QueryEdge &rhs) const
|
||||||
|
{
|
||||||
|
return std::tie(source, target) < std::tie(rhs.source, rhs.target);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const QueryEdge &right) const
|
||||||
|
{
|
||||||
|
return (source == right.source && target == right.target &&
|
||||||
|
data.distance == right.data.distance && data.shortcut == right.data.shortcut &&
|
||||||
|
data.forward == right.data.forward && data.backward == right.data.backward &&
|
||||||
|
data.id == right.data.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QUERYEDGE_HPP
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QUERY_NODE_HPP
|
||||||
|
#define QUERY_NODE_HPP
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
struct QueryNode
|
||||||
|
{
|
||||||
|
using key_type = NodeID; // type of NodeID
|
||||||
|
using value_type = int; // type of lat,lons
|
||||||
|
|
||||||
|
explicit QueryNode(int lat, int lon, NodeID node_id) : lat(lat), lon(lon), node_id(node_id) {}
|
||||||
|
QueryNode()
|
||||||
|
: lat(std::numeric_limits<int>::max()), lon(std::numeric_limits<int>::max()),
|
||||||
|
node_id(std::numeric_limits<unsigned>::max())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int lat;
|
||||||
|
int lon;
|
||||||
|
NodeID node_id;
|
||||||
|
|
||||||
|
static QueryNode min_value()
|
||||||
|
{
|
||||||
|
return QueryNode(static_cast<int>(-90 * COORDINATE_PRECISION),
|
||||||
|
static_cast<int>(-180 * COORDINATE_PRECISION),
|
||||||
|
std::numeric_limits<NodeID>::min());
|
||||||
|
}
|
||||||
|
|
||||||
|
static QueryNode max_value()
|
||||||
|
{
|
||||||
|
return QueryNode(static_cast<int>(90 * COORDINATE_PRECISION),
|
||||||
|
static_cast<int>(180 * COORDINATE_PRECISION),
|
||||||
|
std::numeric_limits<NodeID>::max());
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type operator[](const std::size_t n) const
|
||||||
|
{
|
||||||
|
switch (n)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return lat;
|
||||||
|
case 0:
|
||||||
|
return lon;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BOOST_ASSERT_MSG(false, "should not happen");
|
||||||
|
return std::numeric_limits<int>::lowest();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QUERY_NODE_HPP
|
||||||
@@ -1,17 +1,41 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef RANGE_TABLE_HPP
|
#ifndef RANGE_TABLE_HPP
|
||||||
#define RANGE_TABLE_HPP
|
#define RANGE_TABLE_HPP
|
||||||
|
|
||||||
#include "util/integer_range.hpp"
|
#include "../util/integer_range.hpp"
|
||||||
#include "util/shared_memory_vector_wrapper.hpp"
|
#include "shared_memory_factory.hpp"
|
||||||
|
#include "shared_memory_vector_wrapper.hpp"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* These pre-declarations are needed because parsing C++ is hard
|
* These pre-declarations are needed because parsing C++ is hard
|
||||||
* and otherwise the compiler gets confused.
|
* and otherwise the compiler gets confused.
|
||||||
@@ -40,7 +64,7 @@ template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
|
|||||||
using BlockT = std::array<unsigned char, BLOCK_SIZE>;
|
using BlockT = std::array<unsigned char, BLOCK_SIZE>;
|
||||||
using BlockContainerT = typename ShM<BlockT, USE_SHARED_MEMORY>::vector;
|
using BlockContainerT = typename ShM<BlockT, USE_SHARED_MEMORY>::vector;
|
||||||
using OffsetContainerT = typename ShM<unsigned, USE_SHARED_MEMORY>::vector;
|
using OffsetContainerT = typename ShM<unsigned, USE_SHARED_MEMORY>::vector;
|
||||||
using RangeT = range<unsigned>;
|
using RangeT = osrm::range<unsigned>;
|
||||||
|
|
||||||
friend std::ostream &operator<<<>(std::ostream &out, const RangeTable &table);
|
friend std::ostream &operator<<<>(std::ostream &out, const RangeTable &table);
|
||||||
friend std::istream &operator>><>(std::istream &in, RangeTable &table);
|
friend std::istream &operator>><>(std::istream &in, RangeTable &table);
|
||||||
@@ -53,13 +77,12 @@ template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
|
|||||||
const unsigned sum_lengths)
|
const unsigned sum_lengths)
|
||||||
: sum_lengths(sum_lengths)
|
: sum_lengths(sum_lengths)
|
||||||
{
|
{
|
||||||
using std::swap;
|
block_offsets.swap(external_offsets);
|
||||||
swap(block_offsets, external_offsets);
|
diff_blocks.swap(external_blocks);
|
||||||
swap(diff_blocks, external_blocks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct table from length vector
|
// construct table from length vector
|
||||||
template <typename VectorT> explicit RangeTable(const VectorT &lengths)
|
explicit RangeTable(const std::vector<unsigned> &lengths)
|
||||||
{
|
{
|
||||||
const unsigned number_of_blocks = [&lengths]()
|
const unsigned number_of_blocks = [&lengths]()
|
||||||
{
|
{
|
||||||
@@ -172,7 +195,7 @@ template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
|
|||||||
BOOST_ASSERT(begin_idx < sum_lengths && end_idx <= sum_lengths);
|
BOOST_ASSERT(begin_idx < sum_lengths && end_idx <= sum_lengths);
|
||||||
BOOST_ASSERT(begin_idx <= end_idx);
|
BOOST_ASSERT(begin_idx <= end_idx);
|
||||||
|
|
||||||
return irange(begin_idx, end_idx);
|
return osrm::irange(begin_idx, end_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -234,7 +257,5 @@ std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEM
|
|||||||
in.read((char *)table.diff_blocks.data(), BLOCK_SIZE * number_of_blocks);
|
in.read((char *)table.diff_blocks.data(), BLOCK_SIZE * number_of_blocks);
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // RANGE_TABLE_HPP
|
#endif // RANGE_TABLE_HPP
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RECTANGLE_HPP
|
||||||
|
#define RECTANGLE_HPP
|
||||||
|
|
||||||
|
#include "coordinate_calculation.hpp"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
// TODO: Make template type, add tests
|
||||||
|
struct RectangleInt2D
|
||||||
|
{
|
||||||
|
RectangleInt2D()
|
||||||
|
: min_lon(std::numeric_limits<int32_t>::max()),
|
||||||
|
max_lon(std::numeric_limits<int32_t>::min()),
|
||||||
|
min_lat(std::numeric_limits<int32_t>::max()), max_lat(std::numeric_limits<int32_t>::min())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t min_lon, max_lon;
|
||||||
|
int32_t min_lat, max_lat;
|
||||||
|
|
||||||
|
void MergeBoundingBoxes(const RectangleInt2D &other)
|
||||||
|
{
|
||||||
|
min_lon = std::min(min_lon, other.min_lon);
|
||||||
|
max_lon = std::max(max_lon, other.max_lon);
|
||||||
|
min_lat = std::min(min_lat, other.min_lat);
|
||||||
|
max_lat = std::max(max_lat, other.max_lat);
|
||||||
|
BOOST_ASSERT(min_lat != std::numeric_limits<int32_t>::min());
|
||||||
|
BOOST_ASSERT(min_lon != std::numeric_limits<int32_t>::min());
|
||||||
|
BOOST_ASSERT(max_lat != std::numeric_limits<int32_t>::min());
|
||||||
|
BOOST_ASSERT(max_lon != std::numeric_limits<int32_t>::min());
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointCoordinate Centroid() const
|
||||||
|
{
|
||||||
|
FixedPointCoordinate centroid;
|
||||||
|
// The coordinates of the midpoints are given by:
|
||||||
|
// x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
||||||
|
centroid.lon = (min_lon + max_lon) / 2;
|
||||||
|
centroid.lat = (min_lat + max_lat) / 2;
|
||||||
|
return centroid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Intersects(const RectangleInt2D &other) const
|
||||||
|
{
|
||||||
|
FixedPointCoordinate upper_left(other.max_lat, other.min_lon);
|
||||||
|
FixedPointCoordinate upper_right(other.max_lat, other.max_lon);
|
||||||
|
FixedPointCoordinate lower_right(other.min_lat, other.max_lon);
|
||||||
|
FixedPointCoordinate lower_left(other.min_lat, other.min_lon);
|
||||||
|
|
||||||
|
return (Contains(upper_left) || Contains(upper_right) || Contains(lower_right) ||
|
||||||
|
Contains(lower_left));
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetMinDist(const FixedPointCoordinate &location) const
|
||||||
|
{
|
||||||
|
const bool is_contained = Contains(location);
|
||||||
|
if (is_contained)
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Direction
|
||||||
|
{
|
||||||
|
INVALID = 0,
|
||||||
|
NORTH = 1,
|
||||||
|
SOUTH = 2,
|
||||||
|
EAST = 4,
|
||||||
|
NORTH_EAST = 5,
|
||||||
|
SOUTH_EAST = 6,
|
||||||
|
WEST = 8,
|
||||||
|
NORTH_WEST = 9,
|
||||||
|
SOUTH_WEST = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
Direction d = INVALID;
|
||||||
|
if (location.lat > max_lat)
|
||||||
|
d = (Direction)(d | NORTH);
|
||||||
|
else if (location.lat < min_lat)
|
||||||
|
d = (Direction)(d | SOUTH);
|
||||||
|
if (location.lon > max_lon)
|
||||||
|
d = (Direction)(d | EAST);
|
||||||
|
else if (location.lon < min_lon)
|
||||||
|
d = (Direction)(d | WEST);
|
||||||
|
|
||||||
|
BOOST_ASSERT(d != INVALID);
|
||||||
|
|
||||||
|
float min_dist = std::numeric_limits<float>::max();
|
||||||
|
switch (d)
|
||||||
|
{
|
||||||
|
case NORTH:
|
||||||
|
min_dist = coordinate_calculation::euclidean_distance(
|
||||||
|
location, FixedPointCoordinate(max_lat, location.lon));
|
||||||
|
break;
|
||||||
|
case SOUTH:
|
||||||
|
min_dist = coordinate_calculation::euclidean_distance(
|
||||||
|
location, FixedPointCoordinate(min_lat, location.lon));
|
||||||
|
break;
|
||||||
|
case WEST:
|
||||||
|
min_dist = coordinate_calculation::euclidean_distance(
|
||||||
|
location, FixedPointCoordinate(location.lat, min_lon));
|
||||||
|
break;
|
||||||
|
case EAST:
|
||||||
|
min_dist = coordinate_calculation::euclidean_distance(
|
||||||
|
location, FixedPointCoordinate(location.lat, max_lon));
|
||||||
|
break;
|
||||||
|
case NORTH_EAST:
|
||||||
|
min_dist = coordinate_calculation::euclidean_distance(
|
||||||
|
location, FixedPointCoordinate(max_lat, max_lon));
|
||||||
|
break;
|
||||||
|
case NORTH_WEST:
|
||||||
|
min_dist = coordinate_calculation::euclidean_distance(
|
||||||
|
location, FixedPointCoordinate(max_lat, min_lon));
|
||||||
|
break;
|
||||||
|
case SOUTH_EAST:
|
||||||
|
min_dist = coordinate_calculation::euclidean_distance(
|
||||||
|
location, FixedPointCoordinate(min_lat, max_lon));
|
||||||
|
break;
|
||||||
|
case SOUTH_WEST:
|
||||||
|
min_dist = coordinate_calculation::euclidean_distance(
|
||||||
|
location, FixedPointCoordinate(min_lat, min_lon));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(min_dist < std::numeric_limits<float>::max());
|
||||||
|
|
||||||
|
return min_dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetMinMaxDist(const FixedPointCoordinate &location) const
|
||||||
|
{
|
||||||
|
float min_max_dist = std::numeric_limits<float>::max();
|
||||||
|
// Get minmax distance to each of the four sides
|
||||||
|
const FixedPointCoordinate upper_left(max_lat, min_lon);
|
||||||
|
const FixedPointCoordinate upper_right(max_lat, max_lon);
|
||||||
|
const FixedPointCoordinate lower_right(min_lat, max_lon);
|
||||||
|
const FixedPointCoordinate lower_left(min_lat, min_lon);
|
||||||
|
|
||||||
|
min_max_dist =
|
||||||
|
std::min(min_max_dist,
|
||||||
|
std::max(coordinate_calculation::euclidean_distance(location, upper_left),
|
||||||
|
coordinate_calculation::euclidean_distance(location, upper_right)));
|
||||||
|
|
||||||
|
min_max_dist =
|
||||||
|
std::min(min_max_dist,
|
||||||
|
std::max(coordinate_calculation::euclidean_distance(location, upper_right),
|
||||||
|
coordinate_calculation::euclidean_distance(location, lower_right)));
|
||||||
|
|
||||||
|
min_max_dist =
|
||||||
|
std::min(min_max_dist,
|
||||||
|
std::max(coordinate_calculation::euclidean_distance(location, lower_right),
|
||||||
|
coordinate_calculation::euclidean_distance(location, lower_left)));
|
||||||
|
|
||||||
|
min_max_dist =
|
||||||
|
std::min(min_max_dist,
|
||||||
|
std::max(coordinate_calculation::euclidean_distance(location, lower_left),
|
||||||
|
coordinate_calculation::euclidean_distance(location, upper_left)));
|
||||||
|
return min_max_dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Contains(const FixedPointCoordinate &location) const
|
||||||
|
{
|
||||||
|
const bool lats_contained = (location.lat >= min_lat) && (location.lat <= max_lat);
|
||||||
|
const bool lons_contained = (location.lon >= min_lon) && (location.lon <= max_lon);
|
||||||
|
return lats_contained && lons_contained;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::ostream &operator<<(std::ostream &out, const RectangleInt2D &rect)
|
||||||
|
{
|
||||||
|
out << rect.min_lat / COORDINATE_PRECISION << "," << rect.min_lon / COORDINATE_PRECISION
|
||||||
|
<< " " << rect.max_lat / COORDINATE_PRECISION << ","
|
||||||
|
<< rect.max_lon / COORDINATE_PRECISION;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,21 +1,43 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef RESTRICTION_HPP
|
#ifndef RESTRICTION_HPP
|
||||||
#define RESTRICTION_HPP
|
#define RESTRICTION_HPP
|
||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace extractor
|
|
||||||
{
|
|
||||||
|
|
||||||
struct TurnRestriction
|
struct TurnRestriction
|
||||||
{
|
{
|
||||||
union WayOrNode
|
union WayOrNode
|
||||||
{
|
{
|
||||||
OSMNodeID_weak node;
|
NodeID node;
|
||||||
OSMEdgeID_weak way;
|
EdgeID way;
|
||||||
};
|
};
|
||||||
WayOrNode via;
|
WayOrNode via;
|
||||||
WayOrNode from;
|
WayOrNode from;
|
||||||
@@ -57,7 +79,7 @@ struct TurnRestriction
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This is just a wrapper around TurnRestriction used in the extractor.
|
* This is just a wrapper around TurnRestriction used in the extractor.
|
||||||
*
|
*
|
||||||
* Could be merged with TurnRestriction. For now the type-destiction makes sense
|
* Could be merged with TurnRestriction. For now the type-destiction makes sense
|
||||||
* as the format in which the restriction is presented in the extractor and in the
|
* as the format in which the restriction is presented in the extractor and in the
|
||||||
* preprocessing is different. (see restriction_parser.cpp)
|
* preprocessing is different. (see restriction_parser.cpp)
|
||||||
@@ -108,7 +130,5 @@ struct CmpRestrictionContainerByTo
|
|||||||
value_type max_value() const { return InputRestrictionContainer::max_value(); }
|
value_type max_value() const { return InputRestrictionContainer::max_value(); }
|
||||||
value_type min_value() const { return InputRestrictionContainer::min_value(); }
|
value_type min_value() const { return InputRestrictionContainer::min_value(); }
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // RESTRICTION_HPP
|
#endif // RESTRICTION_HPP
|
||||||
@@ -1,9 +1,31 @@
|
|||||||
#include "extractor/restriction_map.hpp"
|
/*
|
||||||
|
|
||||||
namespace osrm
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
{
|
All rights reserved.
|
||||||
namespace extractor
|
|
||||||
{
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "restriction_map.hpp"
|
||||||
|
|
||||||
RestrictionMap::RestrictionMap(const std::vector<TurnRestriction> &restriction_list) : m_count(0)
|
RestrictionMap::RestrictionMap(const std::vector<TurnRestriction> &restriction_list) : m_count(0)
|
||||||
{
|
{
|
||||||
@@ -11,17 +33,10 @@ RestrictionMap::RestrictionMap(const std::vector<TurnRestriction> &restriction_l
|
|||||||
// a pair of starting edge and a list of all end nodes
|
// a pair of starting edge and a list of all end nodes
|
||||||
for (auto &restriction : restriction_list)
|
for (auto &restriction : restriction_list)
|
||||||
{
|
{
|
||||||
// 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(restriction.from.node < std::numeric_limits<NodeID>::max());
|
|
||||||
BOOST_ASSERT(restriction.via.node < std::numeric_limits<NodeID>::max());
|
|
||||||
m_restriction_start_nodes.insert(restriction.from.node);
|
m_restriction_start_nodes.insert(restriction.from.node);
|
||||||
m_no_turn_via_node_set.insert(restriction.via.node);
|
m_no_turn_via_node_set.insert(restriction.via.node);
|
||||||
|
|
||||||
// This explicit downcasting is also OK for the same reason.
|
RestrictionSource restriction_source = {restriction.from.node, restriction.via.node};
|
||||||
RestrictionSource restriction_source = {static_cast<NodeID>(restriction.from.node),
|
|
||||||
static_cast<NodeID>(restriction.via.node)};
|
|
||||||
|
|
||||||
std::size_t index;
|
std::size_t index;
|
||||||
auto restriction_iter = m_restriction_map.find(restriction_source);
|
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
@@ -47,7 +62,6 @@ RestrictionMap::RestrictionMap(const std::vector<TurnRestriction> &restriction_l
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
++m_count;
|
++m_count;
|
||||||
BOOST_ASSERT(restriction.to.node < std::numeric_limits<NodeID>::max());
|
|
||||||
m_restriction_bucket_list.at(index)
|
m_restriction_bucket_list.at(index)
|
||||||
.emplace_back(restriction.to.node, restriction.flags.is_only);
|
.emplace_back(restriction.to.node, restriction.flags.is_only);
|
||||||
}
|
}
|
||||||
@@ -155,7 +169,9 @@ bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u,
|
|||||||
// check of node is the start of any restriction
|
// check of node is the start of any restriction
|
||||||
bool RestrictionMap::IsSourceNode(const NodeID node) const
|
bool RestrictionMap::IsSourceNode(const NodeID node) const
|
||||||
{
|
{
|
||||||
return m_restriction_start_nodes.find(node) != m_restriction_start_nodes.end();
|
if (m_restriction_start_nodes.find(node) == m_restriction_start_nodes.end())
|
||||||
}
|
{
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,36 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef RESTRICTION_MAP_HPP
|
#ifndef RESTRICTION_MAP_HPP
|
||||||
#define RESTRICTION_MAP_HPP
|
#define RESTRICTION_MAP_HPP
|
||||||
|
|
||||||
#include "extractor/edge_based_edge.hpp"
|
#include "restriction.hpp"
|
||||||
#include "extractor/restriction.hpp"
|
#include "../util/std_hash.hpp"
|
||||||
#include "util/std_hash.hpp"
|
#include "../typedefs.h"
|
||||||
#include "util/typedefs.hpp"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
@@ -13,11 +39,6 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace extractor
|
|
||||||
{
|
|
||||||
|
|
||||||
struct RestrictionSource
|
struct RestrictionSource
|
||||||
{
|
{
|
||||||
NodeID start_node;
|
NodeID start_node;
|
||||||
@@ -43,32 +64,26 @@ struct RestrictionTarget
|
|||||||
return (lhs.target_node == rhs.target_node && lhs.is_only == rhs.is_only);
|
return (lhs.target_node == rhs.target_node && lhs.is_only == rhs.is_only);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
template <> struct hash<osrm::extractor::RestrictionSource>
|
template <> struct hash<RestrictionSource>
|
||||||
{
|
{
|
||||||
size_t operator()(const osrm::extractor::RestrictionSource &r_source) const
|
size_t operator()(const RestrictionSource &r_source) const
|
||||||
{
|
{
|
||||||
return hash_val(r_source.start_node, r_source.via_node);
|
return hash_val(r_source.start_node, r_source.via_node);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct hash<osrm::extractor::RestrictionTarget>
|
template <> struct hash<RestrictionTarget>
|
||||||
{
|
{
|
||||||
size_t operator()(const osrm::extractor::RestrictionTarget &r_target) const
|
size_t operator()(const RestrictionTarget &r_target) const
|
||||||
{
|
{
|
||||||
return hash_val(r_target.target_node, r_target.is_only);
|
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
|
\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
|
EdgeBasedEdgeFactory decides by it if edges are inserted or geometry is compressed
|
||||||
@@ -76,7 +91,7 @@ namespace extractor
|
|||||||
class RestrictionMap
|
class RestrictionMap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RestrictionMap() : m_count(0){}
|
RestrictionMap() : m_count(0) {};
|
||||||
RestrictionMap(const std::vector<TurnRestriction> &restriction_list);
|
RestrictionMap(const std::vector<TurnRestriction> &restriction_list);
|
||||||
|
|
||||||
// Replace end v with w in each turn restriction containing u as via node
|
// Replace end v with w in each turn restriction containing u as via node
|
||||||
@@ -141,7 +156,7 @@ class RestrictionMap
|
|||||||
bool
|
bool
|
||||||
CheckIfTurnIsRestricted(const NodeID node_u, const NodeID node_v, const NodeID node_w) const;
|
CheckIfTurnIsRestricted(const NodeID node_u, const NodeID node_v, const NodeID node_w) const;
|
||||||
|
|
||||||
std::size_t size() const { return m_count; }
|
std::size_t size() { return m_count; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// check of node is the start of any restriction
|
// check of node is the start of any restriction
|
||||||
@@ -157,7 +172,5 @@ class RestrictionMap
|
|||||||
std::unordered_set<NodeID> m_restriction_start_nodes;
|
std::unordered_set<NodeID> m_restriction_start_nodes;
|
||||||
std::unordered_set<NodeID> m_no_turn_via_node_set;
|
std::unordered_set<NodeID> m_no_turn_via_node_set;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // RESTRICTION_MAP_HPP
|
#endif // RESTRICTION_MAP_HPP
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/fusion/container/vector.hpp>
|
||||||
|
#include <boost/fusion/sequence/intrinsic.hpp>
|
||||||
|
#include <boost/fusion/include/at_c.hpp>
|
||||||
|
|
||||||
|
#include <osrm/route_parameters.hpp>
|
||||||
|
|
||||||
|
#include "../algorithms/polyline_compressor.hpp"
|
||||||
|
|
||||||
|
RouteParameters::RouteParameters()
|
||||||
|
: zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
|
||||||
|
compression(true), deprecatedAPI(false), uturn_default(false), classify(false),
|
||||||
|
matching_beta(-1.0), gps_precision(-1.0), check_sum(-1), num_results(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setZoomLevel(const short level)
|
||||||
|
{
|
||||||
|
if (18 >= level && 0 <= level)
|
||||||
|
{
|
||||||
|
zoom_level = level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setNumberOfResults(const short number)
|
||||||
|
{
|
||||||
|
if (number > 0 && number <= 100)
|
||||||
|
{
|
||||||
|
num_results = number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setAlternateRouteFlag(const bool flag) { alternate_route = flag; }
|
||||||
|
|
||||||
|
void RouteParameters::setUTurn(const bool flag)
|
||||||
|
{
|
||||||
|
uturns.resize(coordinates.size(), uturn_default);
|
||||||
|
if (!uturns.empty())
|
||||||
|
{
|
||||||
|
uturns.back() = flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setAllUTurns(const bool flag)
|
||||||
|
{
|
||||||
|
// if the flag flips the default, then we erase everything.
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
uturn_default = flag;
|
||||||
|
uturns.clear();
|
||||||
|
uturns.resize(coordinates.size(), uturn_default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setDeprecatedAPIFlag(const std::string &) { deprecatedAPI = true; }
|
||||||
|
|
||||||
|
void RouteParameters::setChecksum(const unsigned sum) { check_sum = sum; }
|
||||||
|
|
||||||
|
void RouteParameters::setInstructionFlag(const bool flag) { print_instructions = flag; }
|
||||||
|
|
||||||
|
void RouteParameters::setService(const std::string &service_string) { service = service_string; }
|
||||||
|
|
||||||
|
void RouteParameters::setClassify(const bool flag) { classify = flag; }
|
||||||
|
|
||||||
|
void RouteParameters::setMatchingBeta(const double beta) { matching_beta = beta; }
|
||||||
|
|
||||||
|
void RouteParameters::setGPSPrecision(const double precision) { gps_precision = precision; }
|
||||||
|
|
||||||
|
void RouteParameters::setOutputFormat(const std::string &format) { output_format = format; }
|
||||||
|
|
||||||
|
void RouteParameters::setJSONpParameter(const std::string ¶meter)
|
||||||
|
{
|
||||||
|
jsonp_parameter = parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::addHint(const std::string &hint)
|
||||||
|
{
|
||||||
|
hints.resize(coordinates.size());
|
||||||
|
if (!hints.empty())
|
||||||
|
{
|
||||||
|
hints.back() = hint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::addTimestamp(const unsigned timestamp)
|
||||||
|
{
|
||||||
|
timestamps.resize(coordinates.size());
|
||||||
|
if (!timestamps.empty())
|
||||||
|
{
|
||||||
|
timestamps.back() = timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setLanguage(const std::string &language_string)
|
||||||
|
{
|
||||||
|
language = language_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; }
|
||||||
|
|
||||||
|
void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; }
|
||||||
|
|
||||||
|
void RouteParameters::addCoordinate(
|
||||||
|
const boost::fusion::vector<double, double> &received_coordinates)
|
||||||
|
{
|
||||||
|
coordinates.emplace_back(
|
||||||
|
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(received_coordinates)),
|
||||||
|
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(received_coordinates)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::getCoordinatesFromGeometry(const std::string geometry_string)
|
||||||
|
{
|
||||||
|
PolylineCompressor pc;
|
||||||
|
coordinates = pc.decode_string(geometry_string);
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SEARCH_ENGINE_HPP
|
||||||
|
#define SEARCH_ENGINE_HPP
|
||||||
|
|
||||||
|
#include "search_engine_data.hpp"
|
||||||
|
#include "../routing_algorithms/alternative_path.hpp"
|
||||||
|
#include "../routing_algorithms/many_to_many.hpp"
|
||||||
|
#include "../routing_algorithms/map_matching.hpp"
|
||||||
|
#include "../routing_algorithms/shortest_path.hpp"
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
template <class DataFacadeT> class SearchEngine
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
DataFacadeT *facade;
|
||||||
|
SearchEngineData engine_working_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShortestPathRouting<DataFacadeT> shortest_path;
|
||||||
|
AlternativeRouting<DataFacadeT> alternative_path;
|
||||||
|
ManyToManyRouting<DataFacadeT> distance_table;
|
||||||
|
MapMatching<DataFacadeT> map_matching;
|
||||||
|
|
||||||
|
explicit SearchEngine(DataFacadeT *facade)
|
||||||
|
: facade(facade),
|
||||||
|
shortest_path(facade, engine_working_data),
|
||||||
|
alternative_path(facade, engine_working_data),
|
||||||
|
distance_table(facade, engine_working_data),
|
||||||
|
map_matching(facade, engine_working_data)
|
||||||
|
{
|
||||||
|
static_assert(!std::is_pointer<DataFacadeT>::value, "don't instantiate with ptr type");
|
||||||
|
static_assert(std::is_object<DataFacadeT>::value,
|
||||||
|
"don't instantiate with void, function, or reference");
|
||||||
|
}
|
||||||
|
|
||||||
|
~SearchEngine() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SEARCH_ENGINE_HPP
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "search_engine_data.hpp"
|
||||||
|
|
||||||
|
#include "binary_heap.hpp"
|
||||||
|
|
||||||
|
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes)
|
||||||
|
{
|
||||||
|
if (forward_heap_2.get())
|
||||||
|
{
|
||||||
|
forward_heap_2->Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
forward_heap_2.reset(new QueryHeap(number_of_nodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reverse_heap_2.get())
|
||||||
|
{
|
||||||
|
reverse_heap_2->Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reverse_heap_2.reset(new QueryHeap(number_of_nodes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes)
|
||||||
|
{
|
||||||
|
if (forward_heap_3.get())
|
||||||
|
{
|
||||||
|
forward_heap_3->Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
forward_heap_3.reset(new QueryHeap(number_of_nodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reverse_heap_3.get())
|
||||||
|
{
|
||||||
|
reverse_heap_3->Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reverse_heap_3.reset(new QueryHeap(number_of_nodes));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SEARCH_ENGINE_DATA_HPP
|
||||||
|
#define SEARCH_ENGINE_DATA_HPP
|
||||||
|
|
||||||
|
#include <boost/thread/tss.hpp>
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "binary_heap.hpp"
|
||||||
|
|
||||||
|
struct HeapData
|
||||||
|
{
|
||||||
|
NodeID parent;
|
||||||
|
/* explicit */ HeapData(NodeID p) : parent(p) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SearchEngineData
|
||||||
|
{
|
||||||
|
using QueryHeap = BinaryHeap<NodeID, NodeID, int, HeapData, UnorderedMapStorage<NodeID, int>>;
|
||||||
|
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
||||||
|
|
||||||
|
static SearchEngineHeapPtr forward_heap_1;
|
||||||
|
static SearchEngineHeapPtr reverse_heap_1;
|
||||||
|
static SearchEngineHeapPtr forward_heap_2;
|
||||||
|
static SearchEngineHeapPtr reverse_heap_2;
|
||||||
|
static SearchEngineHeapPtr forward_heap_3;
|
||||||
|
static SearchEngineHeapPtr reverse_heap_3;
|
||||||
|
|
||||||
|
void InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes);
|
||||||
|
|
||||||
|
void InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes);
|
||||||
|
|
||||||
|
void InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SEARCH_ENGINE_DATA_HPP
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SEGMENT_INFORMATION_HPP
|
||||||
|
#define SEGMENT_INFORMATION_HPP
|
||||||
|
|
||||||
|
#include "turn_instructions.hpp"
|
||||||
|
|
||||||
|
#include "../data_structures/travel_mode.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
|
// Struct fits everything in one cache line
|
||||||
|
struct SegmentInformation
|
||||||
|
{
|
||||||
|
FixedPointCoordinate location;
|
||||||
|
NodeID name_id;
|
||||||
|
EdgeWeight duration;
|
||||||
|
float length;
|
||||||
|
short bearing; // more than enough [0..3600] fits into 12 bits
|
||||||
|
TurnInstruction turn_instruction;
|
||||||
|
TravelMode travel_mode;
|
||||||
|
bool necessary;
|
||||||
|
bool is_via_location;
|
||||||
|
|
||||||
|
explicit SegmentInformation(const FixedPointCoordinate &location,
|
||||||
|
const NodeID name_id,
|
||||||
|
const EdgeWeight duration,
|
||||||
|
const float length,
|
||||||
|
const TurnInstruction turn_instruction,
|
||||||
|
const bool necessary,
|
||||||
|
const bool is_via_location,
|
||||||
|
const TravelMode travel_mode)
|
||||||
|
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
|
||||||
|
turn_instruction(turn_instruction), travel_mode(travel_mode), necessary(necessary),
|
||||||
|
is_via_location(is_via_location)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit SegmentInformation(const FixedPointCoordinate &location,
|
||||||
|
const NodeID name_id,
|
||||||
|
const EdgeWeight duration,
|
||||||
|
const float length,
|
||||||
|
const TurnInstruction turn_instruction,
|
||||||
|
const TravelMode travel_mode)
|
||||||
|
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
|
||||||
|
turn_instruction(turn_instruction), travel_mode(travel_mode),
|
||||||
|
necessary(turn_instruction != TurnInstruction::NoTurn), is_via_location(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SEGMENT_INFORMATION_HPP */
|
||||||
@@ -1,8 +1,35 @@
|
|||||||
#ifndef SHARED_MEMORY_HPP
|
/*
|
||||||
#define SHARED_MEMORY_HPP
|
|
||||||
|
|
||||||
#include "util/exception.hpp"
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
#include "util/simple_logger.hpp"
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARED_MEMORY_FACTORY_HPP
|
||||||
|
#define SHARED_MEMORY_FACTORY_HPP
|
||||||
|
|
||||||
|
#include "../util/osrm_exception.hpp"
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
@@ -24,11 +51,6 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace storage
|
|
||||||
{
|
|
||||||
|
|
||||||
struct OSRMLockFile
|
struct OSRMLockFile
|
||||||
{
|
{
|
||||||
boost::filesystem::path operator()()
|
boost::filesystem::path operator()()
|
||||||
@@ -58,18 +80,15 @@ class SharedMemory
|
|||||||
}
|
}
|
||||||
|
|
||||||
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
|
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
|
||||||
|
|
||||||
shm_remove(const shm_remove &) = delete;
|
shm_remove(const shm_remove &) = delete;
|
||||||
shm_remove &operator=(const shm_remove &) = delete;
|
|
||||||
|
|
||||||
~shm_remove()
|
~shm_remove()
|
||||||
{
|
{
|
||||||
if (m_initialized)
|
if (m_initialized)
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
|
SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
|
||||||
if (!boost::interprocess::xsi_shared_memory::remove(m_shmid))
|
if (!boost::interprocess::xsi_shared_memory::remove(m_shmid))
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,8 +97,8 @@ class SharedMemory
|
|||||||
public:
|
public:
|
||||||
void *Ptr() const { return region.get_address(); }
|
void *Ptr() const { return region.get_address(); }
|
||||||
|
|
||||||
|
SharedMemory() = delete;
|
||||||
SharedMemory(const SharedMemory &) = delete;
|
SharedMemory(const SharedMemory &) = delete;
|
||||||
SharedMemory &operator=(const SharedMemory &) = delete;
|
|
||||||
|
|
||||||
template <typename IdentifierT>
|
template <typename IdentifierT>
|
||||||
SharedMemory(const boost::filesystem::path &lock_file,
|
SharedMemory(const boost::filesystem::path &lock_file,
|
||||||
@@ -107,19 +126,18 @@ class SharedMemory
|
|||||||
shm = boost::interprocess::xsi_shared_memory(boost::interprocess::open_or_create, key,
|
shm = boost::interprocess::xsi_shared_memory(boost::interprocess::open_or_create, key,
|
||||||
size);
|
size);
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (-1 == shmctl(shm.get_shmid(), SHM_LOCK, nullptr))
|
if (-1 == shmctl(shm.get_shmid(), SHM_LOCK, 0))
|
||||||
{
|
{
|
||||||
if (ENOMEM == errno)
|
if (ENOMEM == errno)
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write(logWARNING) << "could not lock shared memory to RAM";
|
SimpleLogger().Write(logWARNING) << "could not lock shared memory to RAM";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
|
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
|
||||||
|
|
||||||
remover.SetID(shm.get_shmid());
|
remover.SetID(shm.get_shmid());
|
||||||
util::SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size
|
SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size << " bytes";
|
||||||
<< " bytes";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +184,7 @@ class SharedMemory
|
|||||||
bool ret = false;
|
bool ret = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
||||||
boost::interprocess::xsi_shared_memory xsi(boost::interprocess::open_only, key);
|
boost::interprocess::xsi_shared_memory xsi(boost::interprocess::open_only, key);
|
||||||
ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid());
|
ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid());
|
||||||
}
|
}
|
||||||
@@ -190,11 +208,11 @@ class SharedMemory
|
|||||||
class SharedMemory
|
class SharedMemory
|
||||||
{
|
{
|
||||||
SharedMemory(const SharedMemory &) = delete;
|
SharedMemory(const SharedMemory &) = delete;
|
||||||
SharedMemory &operator=(const SharedMemory &) = delete;
|
|
||||||
// Remove shared memory on destruction
|
// Remove shared memory on destruction
|
||||||
class shm_remove
|
class shm_remove
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
shm_remove(const shm_remove &) = delete;
|
||||||
char *m_shmid;
|
char *m_shmid;
|
||||||
bool m_initialized;
|
bool m_initialized;
|
||||||
|
|
||||||
@@ -207,17 +225,14 @@ class SharedMemory
|
|||||||
|
|
||||||
shm_remove() : m_shmid("undefined"), m_initialized(false) {}
|
shm_remove() : m_shmid("undefined"), m_initialized(false) {}
|
||||||
|
|
||||||
shm_remove(const shm_remove &) = delete;
|
|
||||||
shm_remove &operator=(const shm_remove &) = delete;
|
|
||||||
|
|
||||||
~shm_remove()
|
~shm_remove()
|
||||||
{
|
{
|
||||||
if (m_initialized)
|
if (m_initialized)
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
|
SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
|
||||||
if (!boost::interprocess::shared_memory_object::remove(m_shmid))
|
if (!boost::interprocess::shared_memory_object::remove(m_shmid))
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,8 +269,7 @@ class SharedMemory
|
|||||||
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
|
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
|
||||||
|
|
||||||
remover.SetID(key);
|
remover.SetID(key);
|
||||||
util::SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size
|
SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size << " bytes";
|
||||||
<< " bytes";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +319,7 @@ class SharedMemory
|
|||||||
bool ret = false;
|
bool ret = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
||||||
ret = boost::interprocess::shared_memory_object::remove(key);
|
ret = boost::interprocess::shared_memory_object::remove(key);
|
||||||
}
|
}
|
||||||
catch (const boost::interprocess::interprocess_exception &e)
|
catch (const boost::interprocess::interprocess_exception &e)
|
||||||
@@ -325,36 +339,44 @@ class SharedMemory
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename IdentifierT, typename LockFileT = OSRMLockFile>
|
template <class LockFileT = OSRMLockFile> class SharedMemoryFactory_tmpl
|
||||||
SharedMemory *makeSharedMemory(const IdentifierT &id,
|
|
||||||
const uint64_t size = 0,
|
|
||||||
bool read_write = false,
|
|
||||||
bool remove_prev = true)
|
|
||||||
{
|
{
|
||||||
try
|
public:
|
||||||
|
template <typename IdentifierT>
|
||||||
|
static SharedMemory *Get(const IdentifierT &id,
|
||||||
|
const uint64_t size = 0,
|
||||||
|
bool read_write = false,
|
||||||
|
bool remove_prev = true)
|
||||||
{
|
{
|
||||||
LockFileT lock_file;
|
try
|
||||||
if (!boost::filesystem::exists(lock_file()))
|
|
||||||
{
|
{
|
||||||
if (0 == size)
|
LockFileT lock_file;
|
||||||
|
if (!boost::filesystem::exists(lock_file()))
|
||||||
{
|
{
|
||||||
throw util::exception("lock file does not exist, exiting");
|
if (0 == size)
|
||||||
}
|
{
|
||||||
else
|
throw osrm::exception("lock file does not exist, exiting");
|
||||||
{
|
}
|
||||||
boost::filesystem::ofstream ofs(lock_file());
|
else
|
||||||
|
{
|
||||||
|
boost::filesystem::ofstream ofs(lock_file());
|
||||||
|
ofs.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return new SharedMemory(lock_file(), id, size, read_write, remove_prev);
|
||||||
|
}
|
||||||
|
catch (const boost::interprocess::interprocess_exception &e)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what() << ", code "
|
||||||
|
<< e.get_error_code();
|
||||||
|
throw osrm::exception(e.what());
|
||||||
}
|
}
|
||||||
return new SharedMemory(lock_file(), id, size, read_write, remove_prev);
|
|
||||||
}
|
}
|
||||||
catch (const boost::interprocess::interprocess_exception &e)
|
|
||||||
{
|
|
||||||
util::SimpleLogger().Write(logWARNING) << "caught exception: " << e.what() << ", code "
|
|
||||||
<< e.get_error_code();
|
|
||||||
throw util::exception(e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SHARED_MEMORY_HPP
|
SharedMemoryFactory_tmpl() = delete;
|
||||||
|
SharedMemoryFactory_tmpl(const SharedMemoryFactory_tmpl &) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
using SharedMemoryFactory = SharedMemoryFactory_tmpl<>;
|
||||||
|
|
||||||
|
#endif // SHARED_MEMORY_FACTORY_HPP
|
||||||
+43
-26
@@ -1,20 +1,39 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef SHARED_MEMORY_VECTOR_WRAPPER_HPP
|
#ifndef SHARED_MEMORY_VECTOR_WRAPPER_HPP
|
||||||
#define SHARED_MEMORY_VECTOR_WRAPPER_HPP
|
#define SHARED_MEMORY_VECTOR_WRAPPER_HPP
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
|
|
||||||
template <typename DataT> class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT>
|
template <typename DataT> class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT>
|
||||||
{
|
{
|
||||||
@@ -55,6 +74,13 @@ template <typename DataT> class SharedMemoryWrapper
|
|||||||
|
|
||||||
SharedMemoryWrapper(DataT *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
SharedMemoryWrapper(DataT *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||||
|
|
||||||
|
void swap(SharedMemoryWrapper<DataT> &other)
|
||||||
|
{
|
||||||
|
// BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
||||||
|
std::swap(m_size, other.m_size);
|
||||||
|
std::swap(m_ptr, other.m_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
DataT &at(const std::size_t index) { return m_ptr[index]; }
|
DataT &at(const std::size_t index) { return m_ptr[index]; }
|
||||||
|
|
||||||
const DataT &at(const std::size_t index) const { return m_ptr[index]; }
|
const DataT &at(const std::size_t index) const { return m_ptr[index]; }
|
||||||
@@ -78,9 +104,6 @@ template <typename DataT> class SharedMemoryWrapper
|
|||||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||||
return m_ptr[index];
|
return m_ptr[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
friend void swap(SharedMemoryWrapper<T> &, SharedMemoryWrapper<T> &) noexcept;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> class SharedMemoryWrapper<bool>
|
template <> class SharedMemoryWrapper<bool>
|
||||||
@@ -94,11 +117,18 @@ template <> class SharedMemoryWrapper<bool>
|
|||||||
|
|
||||||
SharedMemoryWrapper(unsigned *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
SharedMemoryWrapper(unsigned *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||||
|
|
||||||
|
void swap(SharedMemoryWrapper<bool> &other)
|
||||||
|
{
|
||||||
|
// BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
||||||
|
std::swap(m_size, other.m_size);
|
||||||
|
std::swap(m_ptr, other.m_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
bool at(const std::size_t index) const
|
bool at(const std::size_t index) const
|
||||||
{
|
{
|
||||||
const std::size_t bucket = index / 32;
|
const std::size_t bucket = index / 32;
|
||||||
const unsigned offset = static_cast<unsigned>(index % 32);
|
const unsigned offset = static_cast<unsigned>(index % 32);
|
||||||
return m_ptr[bucket] & (1u << offset);
|
return m_ptr[bucket] & (1 << offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t size() const { return m_size; }
|
std::size_t size() const { return m_size; }
|
||||||
@@ -110,28 +140,15 @@ template <> class SharedMemoryWrapper<bool>
|
|||||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||||
const unsigned bucket = index / 32;
|
const unsigned bucket = index / 32;
|
||||||
const unsigned offset = index % 32;
|
const unsigned offset = index % 32;
|
||||||
return m_ptr[bucket] & (1u << offset);
|
return m_ptr[bucket] & (1 << offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
friend void swap(SharedMemoryWrapper<T> &, SharedMemoryWrapper<T> &) noexcept;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Both SharedMemoryWrapper<T> and the SharedMemoryWrapper<bool> specializations share this impl.
|
|
||||||
template <typename DataT>
|
|
||||||
void swap(SharedMemoryWrapper<DataT> &lhs, SharedMemoryWrapper<DataT> &rhs) noexcept
|
|
||||||
{
|
|
||||||
std::swap(lhs.m_ptr, rhs.m_ptr);
|
|
||||||
std::swap(lhs.m_size, rhs.m_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename DataT, bool UseSharedMemory> struct ShM
|
template <typename DataT, bool UseSharedMemory> struct ShM
|
||||||
{
|
{
|
||||||
using vector = typename std::conditional<UseSharedMemory,
|
using vector = typename std::conditional<UseSharedMemory,
|
||||||
SharedMemoryWrapper<DataT>,
|
SharedMemoryWrapper<DataT>,
|
||||||
std::vector<DataT>>::type;
|
std::vector<DataT>>::type;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SHARED_MEMORY_VECTOR_WRAPPER_HPP
|
#endif // SHARED_MEMORY_VECTOR_WRAPPER_HPP
|
||||||
@@ -1,10 +1,37 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef STATIC_GRAPH_HPP
|
#ifndef STATIC_GRAPH_HPP
|
||||||
#define STATIC_GRAPH_HPP
|
#define STATIC_GRAPH_HPP
|
||||||
|
|
||||||
#include "util/percent.hpp"
|
#include "percent.hpp"
|
||||||
#include "util/shared_memory_vector_wrapper.hpp"
|
#include "shared_memory_vector_wrapper.hpp"
|
||||||
#include "util/integer_range.hpp"
|
#include "../util/integer_range.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
@@ -13,18 +40,13 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
|
|
||||||
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using NodeIterator = NodeID;
|
using NodeIterator = NodeID;
|
||||||
using EdgeIterator = NodeID;
|
using EdgeIterator = NodeID;
|
||||||
using EdgeData = EdgeDataT;
|
using EdgeData = EdgeDataT;
|
||||||
using EdgeRange = range<EdgeIterator>;
|
using EdgeRange = osrm::range<EdgeIterator>;
|
||||||
|
|
||||||
class InputEdge
|
class InputEdge
|
||||||
{
|
{
|
||||||
@@ -62,20 +84,17 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
|||||||
|
|
||||||
EdgeRange GetAdjacentEdgeRange(const NodeID node) const
|
EdgeRange GetAdjacentEdgeRange(const NodeID node) const
|
||||||
{
|
{
|
||||||
return irange(BeginEdges(node), EndEdges(node));
|
return osrm::irange(BeginEdges(node), EndEdges(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ContainerT> StaticGraph(const int nodes, const ContainerT &graph)
|
StaticGraph(const int nodes, std::vector<InputEdge> &graph)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT &>(graph).begin(),
|
|
||||||
const_cast<ContainerT &>(graph).end()));
|
|
||||||
|
|
||||||
number_of_nodes = nodes;
|
number_of_nodes = nodes;
|
||||||
number_of_edges = static_cast<EdgeIterator>(graph.size());
|
number_of_edges = static_cast<EdgeIterator>(graph.size());
|
||||||
node_array.resize(number_of_nodes + 1);
|
node_array.resize(number_of_nodes + 1);
|
||||||
EdgeIterator edge = 0;
|
EdgeIterator edge = 0;
|
||||||
EdgeIterator position = 0;
|
EdgeIterator position = 0;
|
||||||
for (const auto node : irange(0u, number_of_nodes + 1))
|
for (const auto node : osrm::irange(0u, number_of_nodes + 1))
|
||||||
{
|
{
|
||||||
EdgeIterator last_edge = edge;
|
EdgeIterator last_edge = edge;
|
||||||
while (edge < number_of_edges && graph[edge].source == node)
|
while (edge < number_of_edges && graph[edge].source == node)
|
||||||
@@ -87,10 +106,10 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
|||||||
}
|
}
|
||||||
edge_array.resize(position); //(edge)
|
edge_array.resize(position); //(edge)
|
||||||
edge = 0;
|
edge = 0;
|
||||||
for (const auto node : irange(0u, number_of_nodes))
|
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||||
{
|
{
|
||||||
EdgeIterator e = node_array[node + 1].first_edge;
|
EdgeIterator e = node_array[node + 1].first_edge;
|
||||||
for (const auto i : irange(node_array[node].first_edge, e))
|
for (const auto i : osrm::irange(node_array[node].first_edge, e))
|
||||||
{
|
{
|
||||||
edge_array[i].target = graph[edge].target;
|
edge_array[i].target = graph[edge].target;
|
||||||
edge_array[i].data = graph[edge].data;
|
edge_array[i].data = graph[edge].data;
|
||||||
@@ -105,9 +124,8 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
|||||||
number_of_nodes = static_cast<decltype(number_of_nodes)>(nodes.size() - 1);
|
number_of_nodes = static_cast<decltype(number_of_nodes)>(nodes.size() - 1);
|
||||||
number_of_edges = static_cast<decltype(number_of_edges)>(edges.size());
|
number_of_edges = static_cast<decltype(number_of_edges)>(edges.size());
|
||||||
|
|
||||||
using std::swap;
|
node_array.swap(nodes);
|
||||||
swap(node_array, nodes);
|
edge_array.swap(edges);
|
||||||
swap(edge_array, edges);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetNumberOfNodes() const { return number_of_nodes; }
|
unsigned GetNumberOfNodes() const { return number_of_nodes; }
|
||||||
@@ -138,7 +156,7 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
|||||||
// searches for a specific edge
|
// searches for a specific edge
|
||||||
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
|
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
|
||||||
{
|
{
|
||||||
for (const auto i : irange(BeginEdges(from), EndEdges(from)))
|
for (const auto i : osrm::irange(BeginEdges(from), EndEdges(from)))
|
||||||
{
|
{
|
||||||
if (to == edge_array[i].target)
|
if (to == edge_array[i].target)
|
||||||
{
|
{
|
||||||
@@ -194,7 +212,5 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
|||||||
typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array;
|
typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array;
|
||||||
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
|
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // STATIC_GRAPH_HPP
|
#endif // STATIC_GRAPH_HPP
|
||||||
@@ -0,0 +1,260 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// KD Tree coded by Christian Vetter, Monav Project
|
||||||
|
|
||||||
|
#ifndef STATICKDTREE_HPP
|
||||||
|
#define STATICKDTREE_HPP
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <stack>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace KDTree
|
||||||
|
{
|
||||||
|
|
||||||
|
#define KDTREE_BASESIZE (8)
|
||||||
|
|
||||||
|
template <unsigned k, typename T> class BoundingBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BoundingBox()
|
||||||
|
{
|
||||||
|
for (unsigned dim = 0; dim < k; ++dim)
|
||||||
|
{
|
||||||
|
min[dim] = std::numeric_limits<T>::min();
|
||||||
|
max[dim] = std::numeric_limits<T>::max();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T min[k];
|
||||||
|
T max[k];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NoData
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <unsigned k, typename T> class EuclidianMetric
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
double operator()(const T left[k], const T right[k])
|
||||||
|
{
|
||||||
|
double result = 0;
|
||||||
|
for (unsigned i = 0; i < k; ++i)
|
||||||
|
{
|
||||||
|
double temp = (double)left[i] - (double)right[i];
|
||||||
|
result += temp * temp;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
double operator()(const BoundingBox<k, T> &box, const T point[k])
|
||||||
|
{
|
||||||
|
T nearest[k];
|
||||||
|
for (unsigned dim = 0; dim < k; ++dim)
|
||||||
|
{
|
||||||
|
if (point[dim] < box.min[dim])
|
||||||
|
nearest[dim] = box.min[dim];
|
||||||
|
else if (point[dim] > box.max[dim])
|
||||||
|
nearest[dim] = box.max[dim];
|
||||||
|
else
|
||||||
|
nearest[dim] = point[dim];
|
||||||
|
}
|
||||||
|
return operator()(point, nearest);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric<k, T>>
|
||||||
|
class StaticKDTree
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct InputPoint
|
||||||
|
{
|
||||||
|
T coordinates[k];
|
||||||
|
Data data;
|
||||||
|
bool operator==(const InputPoint &right)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < k; i++)
|
||||||
|
{
|
||||||
|
if (coordinates[i] != right.coordinates[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit StaticKDTree(std::vector<InputPoint> *points)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(k > 0);
|
||||||
|
BOOST_ASSERT(points->size() > 0);
|
||||||
|
size = points->size();
|
||||||
|
kdtree = new InputPoint[size];
|
||||||
|
for (Iterator i = 0; i != size; ++i)
|
||||||
|
{
|
||||||
|
kdtree[i] = points->at(i);
|
||||||
|
for (unsigned dim = 0; dim < k; ++dim)
|
||||||
|
{
|
||||||
|
if (kdtree[i].coordinates[dim] < boundingBox.min[dim])
|
||||||
|
boundingBox.min[dim] = kdtree[i].coordinates[dim];
|
||||||
|
if (kdtree[i].coordinates[dim] > boundingBox.max[dim])
|
||||||
|
boundingBox.max[dim] = kdtree[i].coordinates[dim];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::stack<Tree> s;
|
||||||
|
s.push(Tree(0, size, 0));
|
||||||
|
while (!s.empty())
|
||||||
|
{
|
||||||
|
Tree tree = s.top();
|
||||||
|
s.pop();
|
||||||
|
|
||||||
|
if (tree.right - tree.left < KDTREE_BASESIZE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Iterator middle = tree.left + (tree.right - tree.left) / 2;
|
||||||
|
std::nth_element(kdtree + tree.left, kdtree + middle, kdtree + tree.right,
|
||||||
|
Less(tree.dimension));
|
||||||
|
s.push(Tree(tree.left, middle, (tree.dimension + 1) % k));
|
||||||
|
s.push(Tree(middle + 1, tree.right, (tree.dimension + 1) % k));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~StaticKDTree() { delete[] kdtree; }
|
||||||
|
|
||||||
|
bool NearestNeighbor(InputPoint *result, const InputPoint &point)
|
||||||
|
{
|
||||||
|
Metric distance;
|
||||||
|
bool found = false;
|
||||||
|
double nearestDistance = std::numeric_limits<T>::max();
|
||||||
|
std::stack<NNTree> s;
|
||||||
|
s.push(NNTree(0, size, 0, boundingBox));
|
||||||
|
while (!s.empty())
|
||||||
|
{
|
||||||
|
NNTree tree = s.top();
|
||||||
|
s.pop();
|
||||||
|
|
||||||
|
if (distance(tree.box, point.coordinates) >= nearestDistance)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (tree.right - tree.left < KDTREE_BASESIZE)
|
||||||
|
{
|
||||||
|
for (unsigned i = tree.left; i < tree.right; i++)
|
||||||
|
{
|
||||||
|
double newDistance = distance(kdtree[i].coordinates, point.coordinates);
|
||||||
|
if (newDistance < nearestDistance)
|
||||||
|
{
|
||||||
|
nearestDistance = newDistance;
|
||||||
|
*result = kdtree[i];
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator middle = tree.left + (tree.right - tree.left) / 2;
|
||||||
|
|
||||||
|
double newDistance = distance(kdtree[middle].coordinates, point.coordinates);
|
||||||
|
if (newDistance < nearestDistance)
|
||||||
|
{
|
||||||
|
nearestDistance = newDistance;
|
||||||
|
*result = kdtree[middle];
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Less comperator(tree.dimension);
|
||||||
|
if (!comperator(point, kdtree[middle]))
|
||||||
|
{
|
||||||
|
NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
|
||||||
|
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
|
||||||
|
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||||
|
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||||
|
s.push(second);
|
||||||
|
s.push(first);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
|
||||||
|
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
|
||||||
|
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||||
|
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||||
|
s.push(first);
|
||||||
|
s.push(second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
using Iterator = unsigned;
|
||||||
|
struct Tree
|
||||||
|
{
|
||||||
|
Iterator left;
|
||||||
|
Iterator right;
|
||||||
|
unsigned dimension;
|
||||||
|
Tree() {}
|
||||||
|
Tree(Iterator l, Iterator r, unsigned d) : left(l), right(r), dimension(d) {}
|
||||||
|
};
|
||||||
|
struct NNTree
|
||||||
|
{
|
||||||
|
Iterator left;
|
||||||
|
Iterator right;
|
||||||
|
unsigned dimension;
|
||||||
|
BoundingBox<k, T> box;
|
||||||
|
NNTree() {}
|
||||||
|
NNTree(Iterator l, Iterator r, unsigned d, const BoundingBox<k, T> &b)
|
||||||
|
: left(l), right(r), dimension(d), box(b)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class Less
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Less(unsigned d)
|
||||||
|
{
|
||||||
|
dimension = d;
|
||||||
|
BOOST_ASSERT(dimension < k);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(const InputPoint &left, const InputPoint &right)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(dimension < k);
|
||||||
|
return left.coordinates[dimension] < right.coordinates[dimension];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned dimension;
|
||||||
|
};
|
||||||
|
|
||||||
|
BoundingBox<k, T> boundingBox;
|
||||||
|
InputPoint *kdtree;
|
||||||
|
Iterator size;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // STATICKDTREE_HPP
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TRAVEL_MODE_HPP
|
||||||
|
#define TRAVEL_MODE_HPP
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
using TravelMode = unsigned char;
|
||||||
|
static const TravelMode TRAVEL_MODE_INACCESSIBLE = 0;
|
||||||
|
static const TravelMode TRAVEL_MODE_DEFAULT = 1;
|
||||||
|
}
|
||||||
|
#endif /* TRAVEL_MODE_HPP */
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright (c) 2016, Project OSRM contributors
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -25,20 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ENGINE_STATUS_HPP
|
#ifndef TRIBOOL_HPP
|
||||||
#define ENGINE_STATUS_HPP
|
#define TRIBOOL_HPP
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace engine
|
enum class tribool : char
|
||||||
{
|
{
|
||||||
|
yes,
|
||||||
enum class Status
|
no,
|
||||||
{
|
indeterminate
|
||||||
Ok,
|
|
||||||
Error
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
#endif // TRIBOOL_HPP
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TURN_INSTRUCTIONS_HPP
|
||||||
|
#define TURN_INSTRUCTIONS_HPP
|
||||||
|
|
||||||
|
enum class TurnInstruction : unsigned char
|
||||||
|
{
|
||||||
|
NoTurn = 0,
|
||||||
|
GoStraight,
|
||||||
|
TurnSlightRight,
|
||||||
|
TurnRight,
|
||||||
|
TurnSharpRight,
|
||||||
|
UTurn,
|
||||||
|
TurnSharpLeft,
|
||||||
|
TurnLeft,
|
||||||
|
TurnSlightLeft,
|
||||||
|
ReachViaLocation,
|
||||||
|
HeadOn,
|
||||||
|
EnterRoundAbout,
|
||||||
|
LeaveRoundAbout,
|
||||||
|
StayOnRoundAbout,
|
||||||
|
StartAtEndOfStreet,
|
||||||
|
ReachedYourDestination,
|
||||||
|
EnterAgainstAllowedDirection,
|
||||||
|
LeaveAgainstAllowedDirection,
|
||||||
|
InverseAccessRestrictionFlag = 127,
|
||||||
|
AccessRestrictionFlag = 128,
|
||||||
|
AccessRestrictionPenalty = 129
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TurnInstructionsClass
|
||||||
|
{
|
||||||
|
TurnInstructionsClass() = delete;
|
||||||
|
TurnInstructionsClass(const TurnInstructionsClass &) = delete;
|
||||||
|
|
||||||
|
static inline TurnInstruction GetTurnDirectionOfInstruction(const double angle)
|
||||||
|
{
|
||||||
|
if (angle >= 23 && angle < 67)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnSharpRight;
|
||||||
|
}
|
||||||
|
if (angle >= 67 && angle < 113)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnRight;
|
||||||
|
}
|
||||||
|
if (angle >= 113 && angle < 158)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnSlightRight;
|
||||||
|
}
|
||||||
|
if (angle >= 158 && angle < 202)
|
||||||
|
{
|
||||||
|
return TurnInstruction::GoStraight;
|
||||||
|
}
|
||||||
|
if (angle >= 202 && angle < 248)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnSlightLeft;
|
||||||
|
}
|
||||||
|
if (angle >= 248 && angle < 292)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnLeft;
|
||||||
|
}
|
||||||
|
if (angle >= 292 && angle < 336)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnSharpLeft;
|
||||||
|
}
|
||||||
|
return TurnInstruction::UTurn;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool TurnIsNecessary(const TurnInstruction turn_instruction)
|
||||||
|
{
|
||||||
|
if (TurnInstruction::NoTurn == turn_instruction ||
|
||||||
|
TurnInstruction::StayOnRoundAbout == turn_instruction)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* TURN_INSTRUCTIONS_HPP */
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LOWER_BOUND_HPP
|
||||||
|
#define LOWER_BOUND_HPP
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <limits>
|
||||||
|
#include <queue>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
// max pq holds k elements
|
||||||
|
// insert if key is smaller than max
|
||||||
|
// if size > k then remove element
|
||||||
|
// get() always yields a bound to the k smallest element in the stream
|
||||||
|
|
||||||
|
template <typename key_type> class upper_bound
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
using parameter_type =
|
||||||
|
typename std::conditional<std::is_fundamental<key_type>::value, key_type, key_type &>::type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
upper_bound() = delete;
|
||||||
|
upper_bound(std::size_t size) : size(size) {}
|
||||||
|
|
||||||
|
key_type get() const
|
||||||
|
{
|
||||||
|
if (queue.size() < size)
|
||||||
|
{
|
||||||
|
return std::numeric_limits<key_type>::max();
|
||||||
|
}
|
||||||
|
return queue.top();
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(const parameter_type key)
|
||||||
|
{
|
||||||
|
if (key < get())
|
||||||
|
{
|
||||||
|
queue.emplace(key);
|
||||||
|
while (queue.size() > size)
|
||||||
|
{
|
||||||
|
queue.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::priority_queue<key_type, std::vector<key_type>, std::less<key_type>> queue;
|
||||||
|
const std::size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LOWER_BOUND_HPP
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XOR_FAST_HASH_HPP
|
||||||
|
#define XOR_FAST_HASH_HPP
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is an implementation of Tabulation hashing, which has suprising properties like
|
||||||
|
universality.
|
||||||
|
The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache.
|
||||||
|
Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU:
|
||||||
|
|
||||||
|
1: movq table2(%rip), %rdx
|
||||||
|
2: movl %edi, %eax
|
||||||
|
3: movzwl %di, %edi
|
||||||
|
4: shrl $16, %eax
|
||||||
|
5: movzwl %ax, %eax
|
||||||
|
6: movzbl (%rdx,%rax), %eax
|
||||||
|
7: movq table1(%rip), %rdx
|
||||||
|
8: xorb (%rdx,%rdi), %al
|
||||||
|
9: movzbl %al, %eax
|
||||||
|
10: ret
|
||||||
|
|
||||||
|
*/
|
||||||
|
class XORFastHash
|
||||||
|
{ // 65k entries
|
||||||
|
std::vector<unsigned short> table1;
|
||||||
|
std::vector<unsigned short> table2;
|
||||||
|
|
||||||
|
public:
|
||||||
|
XORFastHash()
|
||||||
|
{
|
||||||
|
table1.resize(2 << 16);
|
||||||
|
table2.resize(2 << 16);
|
||||||
|
for (unsigned i = 0; i < (2 << 16); ++i)
|
||||||
|
{
|
||||||
|
table1[i] = static_cast<unsigned short>(i);
|
||||||
|
table2[i] = static_cast<unsigned short>(i);
|
||||||
|
}
|
||||||
|
std::random_shuffle(table1.begin(), table1.end());
|
||||||
|
std::random_shuffle(table2.begin(), table2.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned short operator()(const unsigned originalValue) const
|
||||||
|
{
|
||||||
|
unsigned short lsb = ((originalValue)&0xffff);
|
||||||
|
unsigned short msb = (((originalValue) >> 16) & 0xffff);
|
||||||
|
return table1[lsb] ^ table2[msb];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class XORMiniHash
|
||||||
|
{ // 256 entries
|
||||||
|
std::vector<unsigned char> table1;
|
||||||
|
std::vector<unsigned char> table2;
|
||||||
|
std::vector<unsigned char> table3;
|
||||||
|
std::vector<unsigned char> table4;
|
||||||
|
|
||||||
|
public:
|
||||||
|
XORMiniHash()
|
||||||
|
{
|
||||||
|
table1.resize(1 << 8);
|
||||||
|
table2.resize(1 << 8);
|
||||||
|
table3.resize(1 << 8);
|
||||||
|
table4.resize(1 << 8);
|
||||||
|
for (unsigned i = 0; i < (1 << 8); ++i)
|
||||||
|
{
|
||||||
|
table1[i] = static_cast<unsigned char>(i);
|
||||||
|
table2[i] = static_cast<unsigned char>(i);
|
||||||
|
table3[i] = static_cast<unsigned char>(i);
|
||||||
|
table4[i] = static_cast<unsigned char>(i);
|
||||||
|
}
|
||||||
|
std::random_shuffle(table1.begin(), table1.end());
|
||||||
|
std::random_shuffle(table2.begin(), table2.end());
|
||||||
|
std::random_shuffle(table3.begin(), table3.end());
|
||||||
|
std::random_shuffle(table4.begin(), table4.end());
|
||||||
|
}
|
||||||
|
unsigned char operator()(const unsigned originalValue) const
|
||||||
|
{
|
||||||
|
unsigned char byte1 = ((originalValue)&0xff);
|
||||||
|
unsigned char byte2 = ((originalValue >> 8) & 0xff);
|
||||||
|
unsigned char byte3 = ((originalValue >> 16) & 0xff);
|
||||||
|
unsigned char byte4 = ((originalValue >> 24) & 0xff);
|
||||||
|
return table1[byte1] ^ table2[byte2] ^ table3[byte3] ^ table4[byte4];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // XOR_FAST_HASH_HPP
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XOR_FAST_HASH_STORAGE_HPP
|
||||||
|
#define XOR_FAST_HASH_STORAGE_HPP
|
||||||
|
|
||||||
|
#include "xor_fast_hash.hpp"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template <typename NodeID, typename Key> class XORFastHashStorage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct HashCell
|
||||||
|
{
|
||||||
|
unsigned time;
|
||||||
|
NodeID id;
|
||||||
|
Key key;
|
||||||
|
HashCell()
|
||||||
|
: time(std::numeric_limits<unsigned>::max()), id(std::numeric_limits<unsigned>::max()),
|
||||||
|
key(std::numeric_limits<unsigned>::max())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HashCell(const HashCell &other) : time(other.key), id(other.id), key(other.time) {}
|
||||||
|
|
||||||
|
operator Key() const { return key; }
|
||||||
|
|
||||||
|
void operator=(const Key key_to_insert) { key = key_to_insert; }
|
||||||
|
};
|
||||||
|
|
||||||
|
XORFastHashStorage() = delete;
|
||||||
|
|
||||||
|
explicit XORFastHashStorage(size_t) : positions(2 << 16), current_timestamp(0) {}
|
||||||
|
|
||||||
|
HashCell &operator[](const NodeID node)
|
||||||
|
{
|
||||||
|
unsigned short position = fast_hasher(node);
|
||||||
|
while ((positions[position].time == current_timestamp) && (positions[position].id != node))
|
||||||
|
{
|
||||||
|
++position %= (2 << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
positions[position].time = current_timestamp;
|
||||||
|
positions[position].id = node;
|
||||||
|
return positions[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
// peek into table, get key for node, think of it as a read-only operator[]
|
||||||
|
Key peek_index(const NodeID node) const
|
||||||
|
{
|
||||||
|
unsigned short position = fast_hasher(node);
|
||||||
|
while ((positions[position].time == current_timestamp) && (positions[position].id != node))
|
||||||
|
{
|
||||||
|
++position %= (2 << 16);
|
||||||
|
}
|
||||||
|
return positions[position].key;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
++current_timestamp;
|
||||||
|
if (std::numeric_limits<unsigned>::max() == current_timestamp)
|
||||||
|
{
|
||||||
|
positions.clear();
|
||||||
|
positions.resize(2 << 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<HashCell> positions;
|
||||||
|
XORFastHash fast_hasher;
|
||||||
|
unsigned current_timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // XOR_FAST_HASH_STORAGE_HPP
|
||||||
+565
@@ -0,0 +1,565 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "data_structures/original_edge_data.hpp"
|
||||||
|
#include "data_structures/range_table.hpp"
|
||||||
|
#include "data_structures/query_edge.hpp"
|
||||||
|
#include "data_structures/query_node.hpp"
|
||||||
|
#include "data_structures/shared_memory_factory.hpp"
|
||||||
|
#include "data_structures/shared_memory_vector_wrapper.hpp"
|
||||||
|
#include "data_structures/static_graph.hpp"
|
||||||
|
#include "data_structures/static_rtree.hpp"
|
||||||
|
#include "data_structures/travel_mode.hpp"
|
||||||
|
#include "data_structures/turn_instructions.hpp"
|
||||||
|
#include "server/data_structures/datafacade_base.hpp"
|
||||||
|
#include "server/data_structures/shared_datatype.hpp"
|
||||||
|
#include "server/data_structures/shared_barriers.hpp"
|
||||||
|
#include "util/boost_filesystem_2_fix.hpp"
|
||||||
|
#include "util/datastore_options.hpp"
|
||||||
|
#include "util/simple_logger.hpp"
|
||||||
|
#include "util/osrm_exception.hpp"
|
||||||
|
#include "util/fingerprint.hpp"
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
#include <osrm/server_paths.hpp>
|
||||||
|
|
||||||
|
using RTreeLeaf = BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf;
|
||||||
|
using RTreeNode = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode;
|
||||||
|
using QueryGraph = StaticGraph<QueryEdge::EdgeData>;
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <boost/iostreams/seek.hpp>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// delete a shared memory region. report warning if it could not be deleted
|
||||||
|
void delete_region(const SharedDataType region)
|
||||||
|
{
|
||||||
|
if (SharedMemory::RegionExists(region) && !SharedMemory::Remove(region))
|
||||||
|
{
|
||||||
|
const std::string name = [&]
|
||||||
|
{
|
||||||
|
switch (region)
|
||||||
|
{
|
||||||
|
case CURRENT_REGIONS:
|
||||||
|
return "CURRENT_REGIONS";
|
||||||
|
case LAYOUT_1:
|
||||||
|
return "LAYOUT_1";
|
||||||
|
case DATA_1:
|
||||||
|
return "DATA_1";
|
||||||
|
case LAYOUT_2:
|
||||||
|
return "LAYOUT_2";
|
||||||
|
case DATA_2:
|
||||||
|
return "DATA_2";
|
||||||
|
case LAYOUT_NONE:
|
||||||
|
return "LAYOUT_NONE";
|
||||||
|
default: // DATA_NONE:
|
||||||
|
return "DATA_NONE";
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
SimpleLogger().Write(logWARNING) << "could not delete shared memory region " << name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(const int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
LogPolicy::GetInstance().Unmute();
|
||||||
|
SharedBarriers barrier;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
// try to disable swapping on Linux
|
||||||
|
const bool lock_flags = MCL_CURRENT | MCL_FUTURE;
|
||||||
|
if (-1 == mlockall(lock_flags))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Process " << argv[0]
|
||||||
|
<< " could not request RAM lock";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> pending_lock(
|
||||||
|
barrier.pending_update_mutex);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
// hard unlock in case of any exception.
|
||||||
|
barrier.pending_update_mutex.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logDEBUG) << "Checking input parameters";
|
||||||
|
|
||||||
|
ServerPaths server_paths;
|
||||||
|
if (!GenerateDataStoreOptions(argc, argv, server_paths))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server_paths.find("hsgrdata") == server_paths.end())
|
||||||
|
{
|
||||||
|
throw osrm::exception("no hsgr file found");
|
||||||
|
}
|
||||||
|
if (server_paths.find("ramindex") == server_paths.end())
|
||||||
|
{
|
||||||
|
throw osrm::exception("no ram index file found");
|
||||||
|
}
|
||||||
|
if (server_paths.find("fileindex") == server_paths.end())
|
||||||
|
{
|
||||||
|
throw osrm::exception("no leaf index file found");
|
||||||
|
}
|
||||||
|
if (server_paths.find("nodesdata") == server_paths.end())
|
||||||
|
{
|
||||||
|
throw osrm::exception("no nodes file found");
|
||||||
|
}
|
||||||
|
if (server_paths.find("edgesdata") == server_paths.end())
|
||||||
|
{
|
||||||
|
throw osrm::exception("no edges file found");
|
||||||
|
}
|
||||||
|
if (server_paths.find("namesdata") == server_paths.end())
|
||||||
|
{
|
||||||
|
throw osrm::exception("no names file found");
|
||||||
|
}
|
||||||
|
if (server_paths.find("geometry") == server_paths.end())
|
||||||
|
{
|
||||||
|
throw osrm::exception("no geometry file found");
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path &hsgr_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("timestamp");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path ×tamp_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("ramindex");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path &ram_index_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("fileindex");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path index_file_path_absolute =
|
||||||
|
boost::filesystem::portable_canonical(paths_iterator->second);
|
||||||
|
const std::string &file_index_path = index_file_path_absolute.string();
|
||||||
|
paths_iterator = server_paths.find("nodesdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path &nodes_data_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("edgesdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path &edges_data_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("namesdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path &names_data_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("geometry");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path &geometries_data_path = paths_iterator->second;
|
||||||
|
|
||||||
|
// determine segment to use
|
||||||
|
bool segment2_in_use = SharedMemory::RegionExists(LAYOUT_2);
|
||||||
|
const SharedDataType layout_region = [&]
|
||||||
|
{
|
||||||
|
return segment2_in_use ? LAYOUT_1 : LAYOUT_2;
|
||||||
|
}();
|
||||||
|
const SharedDataType data_region = [&]
|
||||||
|
{
|
||||||
|
return segment2_in_use ? DATA_1 : DATA_2;
|
||||||
|
}();
|
||||||
|
const SharedDataType previous_layout_region = [&]
|
||||||
|
{
|
||||||
|
return segment2_in_use ? LAYOUT_2 : LAYOUT_1;
|
||||||
|
}();
|
||||||
|
const SharedDataType previous_data_region = [&]
|
||||||
|
{
|
||||||
|
return segment2_in_use ? DATA_2 : DATA_1;
|
||||||
|
}();
|
||||||
|
|
||||||
|
// Allocate a memory layout in shared memory, deallocate previous
|
||||||
|
SharedMemory *layout_memory =
|
||||||
|
SharedMemoryFactory::Get(layout_region, sizeof(SharedDataLayout));
|
||||||
|
SharedDataLayout *shared_layout_ptr = static_cast<SharedDataLayout *>(layout_memory->Ptr());
|
||||||
|
shared_layout_ptr = new (layout_memory->Ptr()) SharedDataLayout();
|
||||||
|
|
||||||
|
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::FILE_INDEX_PATH,
|
||||||
|
file_index_path.length() + 1);
|
||||||
|
|
||||||
|
// collect number of elements to store in shared memory object
|
||||||
|
SimpleLogger().Write() << "load names from: " << names_data_path;
|
||||||
|
// number of entries in name index
|
||||||
|
boost::filesystem::ifstream name_stream(names_data_path, std::ios::binary);
|
||||||
|
unsigned name_blocks = 0;
|
||||||
|
name_stream.read((char *)&name_blocks, sizeof(unsigned));
|
||||||
|
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::NAME_OFFSETS, name_blocks);
|
||||||
|
shared_layout_ptr->SetBlockSize<typename RangeTable<16, true>::BlockT>(
|
||||||
|
SharedDataLayout::NAME_BLOCKS, name_blocks);
|
||||||
|
SimpleLogger().Write() << "name offsets size: " << name_blocks;
|
||||||
|
BOOST_ASSERT_MSG(0 != name_blocks, "name file broken");
|
||||||
|
|
||||||
|
unsigned number_of_chars = 0;
|
||||||
|
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
|
||||||
|
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::NAME_CHAR_LIST, number_of_chars);
|
||||||
|
|
||||||
|
// Loading information for original edges
|
||||||
|
boost::filesystem::ifstream edges_input_stream(edges_data_path, std::ios::binary);
|
||||||
|
unsigned number_of_original_edges = 0;
|
||||||
|
edges_input_stream.read((char *)&number_of_original_edges, sizeof(unsigned));
|
||||||
|
|
||||||
|
// note: settings this all to the same size is correct, we extract them from the same struct
|
||||||
|
shared_layout_ptr->SetBlockSize<NodeID>(SharedDataLayout::VIA_NODE_LIST,
|
||||||
|
number_of_original_edges);
|
||||||
|
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::NAME_ID_LIST,
|
||||||
|
number_of_original_edges);
|
||||||
|
shared_layout_ptr->SetBlockSize<TravelMode>(SharedDataLayout::TRAVEL_MODE,
|
||||||
|
number_of_original_edges);
|
||||||
|
shared_layout_ptr->SetBlockSize<TurnInstruction>(SharedDataLayout::TURN_INSTRUCTION,
|
||||||
|
number_of_original_edges);
|
||||||
|
// note: there are 32 geometry indicators in one unsigned block
|
||||||
|
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_INDICATORS,
|
||||||
|
number_of_original_edges);
|
||||||
|
|
||||||
|
boost::filesystem::ifstream hsgr_input_stream(hsgr_path, std::ios::binary);
|
||||||
|
|
||||||
|
FingerPrint fingerprint_valid = FingerPrint::GetValid();
|
||||||
|
FingerPrint fingerprint_loaded;
|
||||||
|
hsgr_input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
|
||||||
|
if (fingerprint_loaded.TestGraphUtil(fingerprint_valid))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logDEBUG) << "Fingerprint checked out ok";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build. "
|
||||||
|
"Reprocess to get rid of this warning.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// load checksum
|
||||||
|
unsigned checksum = 0;
|
||||||
|
hsgr_input_stream.read((char *)&checksum, sizeof(unsigned));
|
||||||
|
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::HSGR_CHECKSUM, 1);
|
||||||
|
// load graph node size
|
||||||
|
unsigned number_of_graph_nodes = 0;
|
||||||
|
hsgr_input_stream.read((char *)&number_of_graph_nodes, sizeof(unsigned));
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG((0 != number_of_graph_nodes), "number of nodes is zero");
|
||||||
|
shared_layout_ptr->SetBlockSize<QueryGraph::NodeArrayEntry>(
|
||||||
|
SharedDataLayout::GRAPH_NODE_LIST, number_of_graph_nodes);
|
||||||
|
|
||||||
|
// load graph edge size
|
||||||
|
unsigned number_of_graph_edges = 0;
|
||||||
|
hsgr_input_stream.read((char *)&number_of_graph_edges, sizeof(unsigned));
|
||||||
|
// BOOST_ASSERT_MSG(0 != number_of_graph_edges, "number of graph edges is zero");
|
||||||
|
shared_layout_ptr->SetBlockSize<QueryGraph::EdgeArrayEntry>(
|
||||||
|
SharedDataLayout::GRAPH_EDGE_LIST, number_of_graph_edges);
|
||||||
|
|
||||||
|
// load rsearch tree size
|
||||||
|
boost::filesystem::ifstream tree_node_file(ram_index_path, std::ios::binary);
|
||||||
|
|
||||||
|
uint32_t tree_size = 0;
|
||||||
|
tree_node_file.read((char *)&tree_size, sizeof(uint32_t));
|
||||||
|
shared_layout_ptr->SetBlockSize<RTreeNode>(SharedDataLayout::R_SEARCH_TREE, tree_size);
|
||||||
|
|
||||||
|
// load timestamp size
|
||||||
|
std::string m_timestamp;
|
||||||
|
if (boost::filesystem::exists(timestamp_path))
|
||||||
|
{
|
||||||
|
boost::filesystem::ifstream timestamp_stream(timestamp_path);
|
||||||
|
if (!timestamp_stream)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << timestamp_path
|
||||||
|
<< " not found. setting to default";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
getline(timestamp_stream, m_timestamp);
|
||||||
|
timestamp_stream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_timestamp.empty())
|
||||||
|
{
|
||||||
|
m_timestamp = "n/a";
|
||||||
|
}
|
||||||
|
if (25 < m_timestamp.length())
|
||||||
|
{
|
||||||
|
m_timestamp.resize(25);
|
||||||
|
}
|
||||||
|
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::TIMESTAMP, m_timestamp.length());
|
||||||
|
|
||||||
|
// load coordinate size
|
||||||
|
boost::filesystem::ifstream nodes_input_stream(nodes_data_path, std::ios::binary);
|
||||||
|
unsigned coordinate_list_size = 0;
|
||||||
|
nodes_input_stream.read((char *)&coordinate_list_size, sizeof(unsigned));
|
||||||
|
shared_layout_ptr->SetBlockSize<FixedPointCoordinate>(SharedDataLayout::COORDINATE_LIST,
|
||||||
|
coordinate_list_size);
|
||||||
|
|
||||||
|
// load geometries sizes
|
||||||
|
std::ifstream geometry_input_stream(geometries_data_path.string().c_str(),
|
||||||
|
std::ios::binary);
|
||||||
|
unsigned number_of_geometries_indices = 0;
|
||||||
|
unsigned number_of_compressed_geometries = 0;
|
||||||
|
|
||||||
|
geometry_input_stream.read((char *)&number_of_geometries_indices, sizeof(unsigned));
|
||||||
|
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_INDEX,
|
||||||
|
number_of_geometries_indices);
|
||||||
|
boost::iostreams::seek(geometry_input_stream,
|
||||||
|
number_of_geometries_indices * sizeof(unsigned), BOOST_IOS::cur);
|
||||||
|
geometry_input_stream.read((char *)&number_of_compressed_geometries, sizeof(unsigned));
|
||||||
|
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_LIST,
|
||||||
|
number_of_compressed_geometries);
|
||||||
|
// allocate shared memory block
|
||||||
|
SimpleLogger().Write() << "allocating shared memory of "
|
||||||
|
<< shared_layout_ptr->GetSizeOfLayout() << " bytes";
|
||||||
|
SharedMemory *shared_memory =
|
||||||
|
SharedMemoryFactory::Get(data_region, shared_layout_ptr->GetSizeOfLayout());
|
||||||
|
char *shared_memory_ptr = static_cast<char *>(shared_memory->Ptr());
|
||||||
|
|
||||||
|
// read actual data into shared memory object //
|
||||||
|
|
||||||
|
// hsgr checksum
|
||||||
|
unsigned *checksum_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::HSGR_CHECKSUM);
|
||||||
|
*checksum_ptr = checksum;
|
||||||
|
|
||||||
|
// ram index file name
|
||||||
|
char *file_index_path_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::FILE_INDEX_PATH);
|
||||||
|
// make sure we have 0 ending
|
||||||
|
std::fill(file_index_path_ptr,
|
||||||
|
file_index_path_ptr +
|
||||||
|
shared_layout_ptr->GetBlockSize(SharedDataLayout::FILE_INDEX_PATH),
|
||||||
|
0);
|
||||||
|
std::copy(file_index_path.begin(), file_index_path.end(), file_index_path_ptr);
|
||||||
|
|
||||||
|
// Loading street names
|
||||||
|
unsigned *name_offsets_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::NAME_OFFSETS);
|
||||||
|
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_OFFSETS) > 0)
|
||||||
|
{
|
||||||
|
name_stream.read((char *)name_offsets_ptr,
|
||||||
|
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_OFFSETS));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned *name_blocks_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::NAME_BLOCKS);
|
||||||
|
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_BLOCKS) > 0)
|
||||||
|
{
|
||||||
|
name_stream.read((char *)name_blocks_ptr,
|
||||||
|
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_BLOCKS));
|
||||||
|
}
|
||||||
|
|
||||||
|
char *name_char_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::NAME_CHAR_LIST);
|
||||||
|
unsigned temp_length;
|
||||||
|
name_stream.read((char *)&temp_length, sizeof(unsigned));
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(temp_length ==
|
||||||
|
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST),
|
||||||
|
"Name file corrupted!");
|
||||||
|
|
||||||
|
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST) > 0)
|
||||||
|
{
|
||||||
|
name_stream.read(name_char_ptr,
|
||||||
|
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST));
|
||||||
|
}
|
||||||
|
|
||||||
|
name_stream.close();
|
||||||
|
|
||||||
|
// load original edge information
|
||||||
|
NodeID *via_node_ptr = shared_layout_ptr->GetBlockPtr<NodeID, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::VIA_NODE_LIST);
|
||||||
|
|
||||||
|
unsigned *name_id_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::NAME_ID_LIST);
|
||||||
|
|
||||||
|
TravelMode *travel_mode_ptr = shared_layout_ptr->GetBlockPtr<TravelMode, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::TRAVEL_MODE);
|
||||||
|
|
||||||
|
TurnInstruction *turn_instructions_ptr =
|
||||||
|
shared_layout_ptr->GetBlockPtr<TurnInstruction, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::TURN_INSTRUCTION);
|
||||||
|
|
||||||
|
unsigned *geometries_indicator_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::GEOMETRIES_INDICATORS);
|
||||||
|
|
||||||
|
OriginalEdgeData current_edge_data;
|
||||||
|
for (unsigned i = 0; i < number_of_original_edges; ++i)
|
||||||
|
{
|
||||||
|
edges_input_stream.read((char *)&(current_edge_data), sizeof(OriginalEdgeData));
|
||||||
|
via_node_ptr[i] = current_edge_data.via_node;
|
||||||
|
name_id_ptr[i] = current_edge_data.name_id;
|
||||||
|
travel_mode_ptr[i] = current_edge_data.travel_mode;
|
||||||
|
turn_instructions_ptr[i] = current_edge_data.turn_instruction;
|
||||||
|
|
||||||
|
const unsigned bucket = i / 32;
|
||||||
|
const unsigned offset = i % 32;
|
||||||
|
const unsigned value = [&]
|
||||||
|
{
|
||||||
|
unsigned return_value = 0;
|
||||||
|
if (0 != offset)
|
||||||
|
{
|
||||||
|
return_value = geometries_indicator_ptr[bucket];
|
||||||
|
}
|
||||||
|
return return_value;
|
||||||
|
}();
|
||||||
|
if (current_edge_data.compressed_geometry)
|
||||||
|
{
|
||||||
|
geometries_indicator_ptr[bucket] = (value | (1 << offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
edges_input_stream.close();
|
||||||
|
|
||||||
|
// load compressed geometry
|
||||||
|
unsigned temporary_value;
|
||||||
|
unsigned *geometries_index_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::GEOMETRIES_INDEX);
|
||||||
|
geometry_input_stream.seekg(0, geometry_input_stream.beg);
|
||||||
|
geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned));
|
||||||
|
BOOST_ASSERT(temporary_value ==
|
||||||
|
shared_layout_ptr->num_entries[SharedDataLayout::GEOMETRIES_INDEX]);
|
||||||
|
|
||||||
|
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_INDEX) > 0)
|
||||||
|
{
|
||||||
|
geometry_input_stream.read(
|
||||||
|
(char *)geometries_index_ptr,
|
||||||
|
shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_INDEX));
|
||||||
|
}
|
||||||
|
unsigned *geometries_list_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::GEOMETRIES_LIST);
|
||||||
|
|
||||||
|
geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned));
|
||||||
|
BOOST_ASSERT(temporary_value ==
|
||||||
|
shared_layout_ptr->num_entries[SharedDataLayout::GEOMETRIES_LIST]);
|
||||||
|
|
||||||
|
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_LIST) > 0)
|
||||||
|
{
|
||||||
|
geometry_input_stream.read(
|
||||||
|
(char *)geometries_list_ptr,
|
||||||
|
shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_LIST));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loading list of coordinates
|
||||||
|
FixedPointCoordinate *coordinates_ptr =
|
||||||
|
shared_layout_ptr->GetBlockPtr<FixedPointCoordinate, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::COORDINATE_LIST);
|
||||||
|
|
||||||
|
QueryNode current_node;
|
||||||
|
for (unsigned i = 0; i < coordinate_list_size; ++i)
|
||||||
|
{
|
||||||
|
nodes_input_stream.read((char *)¤t_node, sizeof(QueryNode));
|
||||||
|
coordinates_ptr[i] = FixedPointCoordinate(current_node.lat, current_node.lon);
|
||||||
|
}
|
||||||
|
nodes_input_stream.close();
|
||||||
|
|
||||||
|
// store timestamp
|
||||||
|
char *timestamp_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::TIMESTAMP);
|
||||||
|
std::copy(m_timestamp.c_str(), m_timestamp.c_str() + m_timestamp.length(), timestamp_ptr);
|
||||||
|
|
||||||
|
// store search tree portion of rtree
|
||||||
|
char *rtree_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::R_SEARCH_TREE);
|
||||||
|
|
||||||
|
if (tree_size > 0)
|
||||||
|
{
|
||||||
|
tree_node_file.read(rtree_ptr, sizeof(RTreeNode) * tree_size);
|
||||||
|
}
|
||||||
|
tree_node_file.close();
|
||||||
|
|
||||||
|
// load the nodes of the search graph
|
||||||
|
QueryGraph::NodeArrayEntry *graph_node_list_ptr =
|
||||||
|
shared_layout_ptr->GetBlockPtr<QueryGraph::NodeArrayEntry, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::GRAPH_NODE_LIST);
|
||||||
|
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_NODE_LIST) > 0)
|
||||||
|
{
|
||||||
|
hsgr_input_stream.read(
|
||||||
|
(char *)graph_node_list_ptr,
|
||||||
|
shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_NODE_LIST));
|
||||||
|
}
|
||||||
|
|
||||||
|
// load the edges of the search graph
|
||||||
|
QueryGraph::EdgeArrayEntry *graph_edge_list_ptr =
|
||||||
|
shared_layout_ptr->GetBlockPtr<QueryGraph::EdgeArrayEntry, true>(
|
||||||
|
shared_memory_ptr, SharedDataLayout::GRAPH_EDGE_LIST);
|
||||||
|
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_EDGE_LIST) > 0)
|
||||||
|
{
|
||||||
|
hsgr_input_stream.read(
|
||||||
|
(char *)graph_edge_list_ptr,
|
||||||
|
shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_EDGE_LIST));
|
||||||
|
}
|
||||||
|
hsgr_input_stream.close();
|
||||||
|
|
||||||
|
// acquire lock
|
||||||
|
SharedMemory *data_type_memory =
|
||||||
|
SharedMemoryFactory::Get(CURRENT_REGIONS, sizeof(SharedDataTimestamp), true, false);
|
||||||
|
SharedDataTimestamp *data_timestamp_ptr =
|
||||||
|
static_cast<SharedDataTimestamp *>(data_type_memory->Ptr());
|
||||||
|
|
||||||
|
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
|
||||||
|
barrier.query_mutex);
|
||||||
|
|
||||||
|
// notify all processes that were waiting for this condition
|
||||||
|
if (0 < barrier.number_of_queries)
|
||||||
|
{
|
||||||
|
barrier.no_running_queries_condition.wait(query_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
data_timestamp_ptr->layout = layout_region;
|
||||||
|
data_timestamp_ptr->data = data_region;
|
||||||
|
data_timestamp_ptr->timestamp += 1;
|
||||||
|
delete_region(previous_data_region);
|
||||||
|
delete_region(previous_layout_region);
|
||||||
|
SimpleLogger().Write() << "all data loaded";
|
||||||
|
|
||||||
|
shared_layout_ptr->PrintInformation();
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "description_factory.hpp"
|
||||||
|
|
||||||
|
#include "../algorithms/polyline_formatter.hpp"
|
||||||
|
#include "../data_structures/coordinate_calculation.hpp"
|
||||||
|
#include "../data_structures/internal_route_result.hpp"
|
||||||
|
#include "../data_structures/turn_instructions.hpp"
|
||||||
|
#include "../util/container.hpp"
|
||||||
|
#include "../util/integer_range.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
DescriptionFactory::DescriptionFactory() : entire_length(0) { via_indices.push_back(0); }
|
||||||
|
|
||||||
|
std::vector<unsigned> const &DescriptionFactory::GetViaIndices() const { return via_indices; }
|
||||||
|
|
||||||
|
void DescriptionFactory::SetStartSegment(const PhantomNode &source, const bool traversed_in_reverse)
|
||||||
|
{
|
||||||
|
start_phantom = source;
|
||||||
|
const EdgeWeight segment_duration =
|
||||||
|
(traversed_in_reverse ? source.reverse_weight : source.forward_weight);
|
||||||
|
const TravelMode travel_mode =
|
||||||
|
(traversed_in_reverse ? source.backward_travel_mode : source.forward_travel_mode);
|
||||||
|
AppendSegment(source.location, PathData(0, source.name_id, TurnInstruction::HeadOn,
|
||||||
|
segment_duration, travel_mode));
|
||||||
|
BOOST_ASSERT(path_description.back().duration == segment_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::SetEndSegment(const PhantomNode &target,
|
||||||
|
const bool traversed_in_reverse,
|
||||||
|
const bool is_via_location)
|
||||||
|
{
|
||||||
|
target_phantom = target;
|
||||||
|
const EdgeWeight segment_duration =
|
||||||
|
(traversed_in_reverse ? target.reverse_weight : target.forward_weight);
|
||||||
|
const TravelMode travel_mode =
|
||||||
|
(traversed_in_reverse ? target.backward_travel_mode : target.forward_travel_mode);
|
||||||
|
path_description.emplace_back(target.location, target.name_id, segment_duration, 0.f,
|
||||||
|
is_via_location ? TurnInstruction::ReachViaLocation
|
||||||
|
: TurnInstruction::NoTurn,
|
||||||
|
true, true, travel_mode);
|
||||||
|
BOOST_ASSERT(path_description.back().duration == segment_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
|
||||||
|
const PathData &path_point)
|
||||||
|
{
|
||||||
|
// if the start location is on top of a node, the first movement might be zero-length,
|
||||||
|
// in which case we dont' add a new description, but instead update the existing one
|
||||||
|
if ((1 == path_description.size()) && (path_description.front().location == coordinate))
|
||||||
|
{
|
||||||
|
if (path_point.segment_duration > 0)
|
||||||
|
{
|
||||||
|
path_description.front().name_id = path_point.name_id;
|
||||||
|
path_description.front().travel_mode = path_point.travel_mode;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure mode changes are announced, even when there otherwise is no turn
|
||||||
|
const TurnInstruction turn = [&]() -> TurnInstruction
|
||||||
|
{
|
||||||
|
if (TurnInstruction::NoTurn == path_point.turn_instruction &&
|
||||||
|
path_description.front().travel_mode != path_point.travel_mode &&
|
||||||
|
path_point.segment_duration > 0)
|
||||||
|
{
|
||||||
|
return TurnInstruction::GoStraight;
|
||||||
|
}
|
||||||
|
return path_point.turn_instruction;
|
||||||
|
}();
|
||||||
|
|
||||||
|
path_description.emplace_back(coordinate, path_point.name_id, path_point.segment_duration, 0.f,
|
||||||
|
turn, path_point.travel_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
osrm::json::Value DescriptionFactory::AppendGeometryString(const bool return_encoded)
|
||||||
|
{
|
||||||
|
if (return_encoded)
|
||||||
|
{
|
||||||
|
return PolylineFormatter().printEncodedString(path_description);
|
||||||
|
}
|
||||||
|
return PolylineFormatter().printUnencodedString(path_description);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
|
||||||
|
{
|
||||||
|
summary.source_name_id = start_phantom.name_id;
|
||||||
|
summary.target_name_id = target_phantom.name_id;
|
||||||
|
summary.BuildDurationAndLengthStrings(distance, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::Run(const unsigned zoom_level)
|
||||||
|
{
|
||||||
|
if (path_description.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** starts at index 1 */
|
||||||
|
path_description[0].length = 0.f;
|
||||||
|
for (const auto i : osrm::irange<std::size_t>(1, path_description.size()))
|
||||||
|
{
|
||||||
|
// move down names by one, q&d hack
|
||||||
|
path_description[i - 1].name_id = path_description[i].name_id;
|
||||||
|
path_description[i].length = coordinate_calculation::euclidean_distance(
|
||||||
|
path_description[i - 1].location, path_description[i].location);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Simplify turn instructions
|
||||||
|
Input :
|
||||||
|
10. Turn left on B 36 for 20 km
|
||||||
|
11. Continue on B 35; B 36 for 2 km
|
||||||
|
12. Continue on B 36 for 13 km
|
||||||
|
|
||||||
|
becomes:
|
||||||
|
10. Turn left on B 36 for 35 km
|
||||||
|
*/
|
||||||
|
// TODO: rework to check only end and start of string.
|
||||||
|
// stl string is way to expensive
|
||||||
|
|
||||||
|
// unsigned lastTurn = 0;
|
||||||
|
// for(unsigned i = 1; i < path_description.size(); ++i) {
|
||||||
|
// string1 = sEngine.GetEscapedNameForNameID(path_description[i].name_id);
|
||||||
|
// if(TurnInstruction::GoStraight == path_description[i].turn_instruction) {
|
||||||
|
// if(std::string::npos != string0.find(string1+";")
|
||||||
|
// || std::string::npos != string0.find(";"+string1)
|
||||||
|
// || std::string::npos != string0.find(string1+" ;")
|
||||||
|
// || std::string::npos != string0.find("; "+string1)
|
||||||
|
// ){
|
||||||
|
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " <<
|
||||||
|
// string1;
|
||||||
|
// for(; lastTurn != i; ++lastTurn)
|
||||||
|
// path_description[lastTurn].name_id = path_description[i].name_id;
|
||||||
|
// path_description[i].turn_instruction = TurnInstruction::NoTurn;
|
||||||
|
// } else if(std::string::npos != string1.find(string0+";")
|
||||||
|
// || std::string::npos != string1.find(";"+string0)
|
||||||
|
// || std::string::npos != string1.find(string0+" ;")
|
||||||
|
// || std::string::npos != string1.find("; "+string0)
|
||||||
|
// ){
|
||||||
|
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " <<
|
||||||
|
// string0;
|
||||||
|
// path_description[i].name_id = path_description[i-1].name_id;
|
||||||
|
// path_description[i].turn_instruction = TurnInstruction::NoTurn;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (TurnInstruction::NoTurn != path_description[i].turn_instruction) {
|
||||||
|
// lastTurn = i;
|
||||||
|
// }
|
||||||
|
// string0 = string1;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
|
float segment_length = 0.;
|
||||||
|
EdgeWeight segment_duration = 0;
|
||||||
|
std::size_t segment_start_index = 0;
|
||||||
|
|
||||||
|
for (const auto i : osrm::irange<std::size_t>(1, path_description.size()))
|
||||||
|
{
|
||||||
|
entire_length += path_description[i].length;
|
||||||
|
segment_length += path_description[i].length;
|
||||||
|
segment_duration += path_description[i].duration;
|
||||||
|
path_description[segment_start_index].length = segment_length;
|
||||||
|
path_description[segment_start_index].duration = segment_duration;
|
||||||
|
|
||||||
|
if (TurnInstruction::NoTurn != path_description[i].turn_instruction)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(path_description[i].necessary);
|
||||||
|
segment_length = 0;
|
||||||
|
segment_duration = 0;
|
||||||
|
segment_start_index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post-processing to remove empty or nearly empty path segments
|
||||||
|
if (path_description.size() > 2 &&
|
||||||
|
std::numeric_limits<float>::epsilon() > path_description.back().length &&
|
||||||
|
!(path_description.end() - 2)->is_via_location)
|
||||||
|
{
|
||||||
|
path_description.pop_back();
|
||||||
|
path_description.back().necessary = true;
|
||||||
|
path_description.back().turn_instruction = TurnInstruction::NoTurn;
|
||||||
|
target_phantom.name_id = (path_description.end() - 2)->name_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_description.size() > 2 &&
|
||||||
|
std::numeric_limits<float>::epsilon() > path_description.front().length &&
|
||||||
|
!(path_description.begin() + 1)->is_via_location)
|
||||||
|
{
|
||||||
|
path_description.erase(path_description.begin());
|
||||||
|
path_description.front().turn_instruction = TurnInstruction::HeadOn;
|
||||||
|
path_description.front().necessary = true;
|
||||||
|
start_phantom.name_id = path_description.front().name_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generalize poly line
|
||||||
|
polyline_generalizer.Run(path_description.begin(), path_description.end(), zoom_level);
|
||||||
|
|
||||||
|
// fix what needs to be fixed else
|
||||||
|
unsigned necessary_segments = 0; // a running index that counts the necessary pieces
|
||||||
|
osrm::for_each_pair(
|
||||||
|
path_description, [&](SegmentInformation &first, const SegmentInformation &second)
|
||||||
|
{
|
||||||
|
if (!first.necessary)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
++necessary_segments;
|
||||||
|
|
||||||
|
if (first.is_via_location)
|
||||||
|
{ // mark the end of a leg (of several segments)
|
||||||
|
via_indices.push_back(necessary_segments);
|
||||||
|
}
|
||||||
|
|
||||||
|
const double angle = coordinate_calculation::bearing(first.location, second.location);
|
||||||
|
first.bearing = static_cast<short>(angle * 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
via_indices.push_back(necessary_segments + 1);
|
||||||
|
BOOST_ASSERT(via_indices.size() >= 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DESCRIPTION_FACTORY_HPP
|
||||||
|
#define DESCRIPTION_FACTORY_HPP
|
||||||
|
|
||||||
|
#include "../algorithms/douglas_peucker.hpp"
|
||||||
|
#include "../data_structures/phantom_node.hpp"
|
||||||
|
#include "../data_structures/segment_information.hpp"
|
||||||
|
#include "../data_structures/turn_instructions.hpp"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
#include <osrm/json_container.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct PathData;
|
||||||
|
/* This class is fed with all way segments in consecutive order
|
||||||
|
* and produces the description plus the encoded polyline */
|
||||||
|
|
||||||
|
class DescriptionFactory
|
||||||
|
{
|
||||||
|
DouglasPeucker polyline_generalizer;
|
||||||
|
PhantomNode start_phantom, target_phantom;
|
||||||
|
|
||||||
|
double DegreeToRadian(const double degree) const;
|
||||||
|
double RadianToDegree(const double degree) const;
|
||||||
|
|
||||||
|
std::vector<unsigned> via_indices;
|
||||||
|
|
||||||
|
double entire_length;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct RouteSummary
|
||||||
|
{
|
||||||
|
unsigned distance;
|
||||||
|
EdgeWeight duration;
|
||||||
|
unsigned source_name_id;
|
||||||
|
unsigned target_name_id;
|
||||||
|
RouteSummary() : distance(0), duration(0), source_name_id(0), target_name_id(0) {}
|
||||||
|
|
||||||
|
void BuildDurationAndLengthStrings(const double raw_distance, const unsigned raw_duration)
|
||||||
|
{
|
||||||
|
// compute distance/duration for route summary
|
||||||
|
distance = static_cast<unsigned>(std::round(raw_distance));
|
||||||
|
duration = static_cast<EdgeWeight>(std::round(raw_duration / 10.));
|
||||||
|
}
|
||||||
|
} summary;
|
||||||
|
|
||||||
|
// I know, declaring this public is considered bad. I'm lazy
|
||||||
|
std::vector<SegmentInformation> path_description;
|
||||||
|
DescriptionFactory();
|
||||||
|
void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
|
||||||
|
void BuildRouteSummary(const double distance, const unsigned time);
|
||||||
|
void SetStartSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse);
|
||||||
|
void SetEndSegment(const PhantomNode &start_phantom,
|
||||||
|
const bool traversed_in_reverse,
|
||||||
|
const bool is_via_location = false);
|
||||||
|
osrm::json::Value AppendGeometryString(const bool return_encoded);
|
||||||
|
std::vector<unsigned> const &GetViaIndices() const;
|
||||||
|
|
||||||
|
double get_entire_length() const { return entire_length; }
|
||||||
|
|
||||||
|
void Run(const unsigned zoom_level);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* DESCRIPTION_FACTORY_HPP */
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DESCRIPTOR_BASE_HPP
|
||||||
|
#define DESCRIPTOR_BASE_HPP
|
||||||
|
|
||||||
|
#include "../data_structures/coordinate_calculation.hpp"
|
||||||
|
#include "../data_structures/internal_route_result.hpp"
|
||||||
|
#include "../data_structures/phantom_node.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <osrm/json_container.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct DescriptorTable : public std::unordered_map<std::string, unsigned>
|
||||||
|
{
|
||||||
|
unsigned get_id(const std::string &key)
|
||||||
|
{
|
||||||
|
auto iter = find(key);
|
||||||
|
if (iter != end())
|
||||||
|
{
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DescriptorConfig
|
||||||
|
{
|
||||||
|
DescriptorConfig() : instructions(true), geometry(true), encode_geometry(true), zoom_level(18)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class OtherT>
|
||||||
|
DescriptorConfig(const OtherT &other)
|
||||||
|
: instructions(other.print_instructions), geometry(other.geometry),
|
||||||
|
encode_geometry(other.compression), zoom_level(other.zoom_level)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(zoom_level >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool instructions;
|
||||||
|
bool geometry;
|
||||||
|
bool encode_geometry;
|
||||||
|
short zoom_level;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class DataFacadeT> class BaseDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BaseDescriptor() {}
|
||||||
|
// Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||||
|
virtual ~BaseDescriptor() {}
|
||||||
|
virtual void Run(const InternalRouteResult &raw_route, osrm::json::Object &json_result) = 0;
|
||||||
|
virtual void SetConfig(const DescriptorConfig &c) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DESCRIPTOR_BASE_HPP
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GPX_DESCRIPTOR_HPP
|
||||||
|
#define GPX_DESCRIPTOR_HPP
|
||||||
|
|
||||||
|
#include "descriptor_base.hpp"
|
||||||
|
#include "../util/xml_renderer.hpp"
|
||||||
|
|
||||||
|
#include <osrm/json_container.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<DataFacadeT>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
DescriptorConfig config;
|
||||||
|
DataFacadeT *facade;
|
||||||
|
|
||||||
|
void AddRoutePoint(const FixedPointCoordinate &coordinate, osrm::json::Array &json_route)
|
||||||
|
{
|
||||||
|
osrm::json::Object json_lat;
|
||||||
|
osrm::json::Object json_lon;
|
||||||
|
osrm::json::Array json_row;
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
|
||||||
|
coordinate_calculation::lat_or_lon_to_string(coordinate.lat, tmp);
|
||||||
|
json_lat.values["_lat"] = tmp;
|
||||||
|
|
||||||
|
coordinate_calculation::lat_or_lon_to_string(coordinate.lon, tmp);
|
||||||
|
json_lon.values["_lon"] = tmp;
|
||||||
|
|
||||||
|
json_row.values.push_back(json_lat);
|
||||||
|
json_row.values.push_back(json_lon);
|
||||||
|
osrm::json::Object entry;
|
||||||
|
entry.values["rtept"] = json_row;
|
||||||
|
json_route.values.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GPXDescriptor(DataFacadeT *facade) : facade(facade) {}
|
||||||
|
|
||||||
|
virtual void SetConfig(const DescriptorConfig &c) final { config = c; }
|
||||||
|
|
||||||
|
virtual void Run(const InternalRouteResult &raw_route, osrm::json::Object &json_result) final
|
||||||
|
{
|
||||||
|
osrm::json::Array json_route;
|
||||||
|
if (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
|
AddRoutePoint(raw_route.segment_end_coordinates.front().source_phantom.location,
|
||||||
|
json_route);
|
||||||
|
|
||||||
|
for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
|
||||||
|
{
|
||||||
|
for (const PathData &path_data : path_data_vector)
|
||||||
|
{
|
||||||
|
const FixedPointCoordinate current_coordinate =
|
||||||
|
facade->GetCoordinateOfNode(path_data.node);
|
||||||
|
AddRoutePoint(current_coordinate, json_route);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location,
|
||||||
|
json_route);
|
||||||
|
}
|
||||||
|
// osrm::json::gpx_render(reply.content, json_route);
|
||||||
|
json_result.values["route"] = json_route;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // GPX_DESCRIPTOR_HPP
|
||||||
@@ -0,0 +1,392 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JSON_DESCRIPTOR_HPP
|
||||||
|
#define JSON_DESCRIPTOR_HPP
|
||||||
|
|
||||||
|
#include "descriptor_base.hpp"
|
||||||
|
#include "description_factory.hpp"
|
||||||
|
#include "../algorithms/object_encoder.hpp"
|
||||||
|
#include "../algorithms/route_name_extraction.hpp"
|
||||||
|
#include "../data_structures/segment_information.hpp"
|
||||||
|
#include "../data_structures/turn_instructions.hpp"
|
||||||
|
#include "../util/bearing.hpp"
|
||||||
|
#include "../util/integer_range.hpp"
|
||||||
|
#include "../util/json_renderer.hpp"
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
#include "../util/string_util.hpp"
|
||||||
|
#include "../util/timing_util.hpp"
|
||||||
|
|
||||||
|
#include <osrm/json_container.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<DataFacadeT>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
DataFacadeT *facade;
|
||||||
|
DescriptorConfig config;
|
||||||
|
DescriptionFactory description_factory, alternate_description_factory;
|
||||||
|
FixedPointCoordinate current;
|
||||||
|
unsigned entered_restricted_area_count;
|
||||||
|
struct RoundAbout
|
||||||
|
{
|
||||||
|
RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {}
|
||||||
|
int start_index;
|
||||||
|
unsigned name_id;
|
||||||
|
int leave_at_exit;
|
||||||
|
} round_about;
|
||||||
|
|
||||||
|
struct Segment
|
||||||
|
{
|
||||||
|
Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {}
|
||||||
|
Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {}
|
||||||
|
unsigned name_id;
|
||||||
|
int length;
|
||||||
|
unsigned position;
|
||||||
|
};
|
||||||
|
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||||
|
ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetConfig(const DescriptorConfig &c) override final { config = c; }
|
||||||
|
|
||||||
|
unsigned DescribeLeg(const std::vector<PathData> &route_leg,
|
||||||
|
const PhantomNodes &leg_phantoms,
|
||||||
|
const bool target_traversed_in_reverse,
|
||||||
|
const bool is_via_leg)
|
||||||
|
{
|
||||||
|
unsigned added_element_count = 0;
|
||||||
|
// Get all the coordinates for the computed route
|
||||||
|
FixedPointCoordinate current_coordinate;
|
||||||
|
for (const PathData &path_data : route_leg)
|
||||||
|
{
|
||||||
|
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||||
|
description_factory.AppendSegment(current_coordinate, path_data);
|
||||||
|
++added_element_count;
|
||||||
|
}
|
||||||
|
description_factory.SetEndSegment(leg_phantoms.target_phantom, target_traversed_in_reverse,
|
||||||
|
is_via_leg);
|
||||||
|
++added_element_count;
|
||||||
|
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
|
||||||
|
return added_element_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Run(const InternalRouteResult &raw_route,
|
||||||
|
osrm::json::Object &json_result) override final
|
||||||
|
{
|
||||||
|
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||||
|
{
|
||||||
|
// We do not need to do much, if there is no route ;-)
|
||||||
|
json_result.values["status"] = 207;
|
||||||
|
json_result.values["status_message"] = "Cannot find route between points";
|
||||||
|
// osrm::json::render(reply.content, json_result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if first segment is non-zero
|
||||||
|
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
|
||||||
|
raw_route.segment_end_coordinates.size());
|
||||||
|
|
||||||
|
description_factory.SetStartSegment(
|
||||||
|
raw_route.segment_end_coordinates.front().source_phantom,
|
||||||
|
raw_route.source_traversed_in_reverse.front());
|
||||||
|
json_result.values["status"] = 0;
|
||||||
|
json_result.values["status_message"] = "Found route between points";
|
||||||
|
|
||||||
|
// for each unpacked segment add the leg to the description
|
||||||
|
for (const auto i : osrm::irange<std::size_t>(0, raw_route.unpacked_path_segments.size()))
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
const int added_segments =
|
||||||
|
#endif
|
||||||
|
DescribeLeg(raw_route.unpacked_path_segments[i],
|
||||||
|
raw_route.segment_end_coordinates[i],
|
||||||
|
raw_route.target_traversed_in_reverse[i], raw_route.is_via_leg(i));
|
||||||
|
BOOST_ASSERT(0 < added_segments);
|
||||||
|
}
|
||||||
|
description_factory.Run(config.zoom_level);
|
||||||
|
|
||||||
|
if (config.geometry)
|
||||||
|
{
|
||||||
|
osrm::json::Value route_geometry =
|
||||||
|
description_factory.AppendGeometryString(config.encode_geometry);
|
||||||
|
json_result.values["route_geometry"] = route_geometry;
|
||||||
|
}
|
||||||
|
if (config.instructions)
|
||||||
|
{
|
||||||
|
osrm::json::Array json_route_instructions;
|
||||||
|
BuildTextualDescription(description_factory, json_route_instructions,
|
||||||
|
raw_route.shortest_path_length, shortest_path_segments);
|
||||||
|
json_result.values["route_instructions"] = json_route_instructions;
|
||||||
|
}
|
||||||
|
description_factory.BuildRouteSummary(description_factory.get_entire_length(),
|
||||||
|
raw_route.shortest_path_length);
|
||||||
|
osrm::json::Object json_route_summary;
|
||||||
|
json_route_summary.values["total_distance"] = description_factory.summary.distance;
|
||||||
|
json_route_summary.values["total_time"] = description_factory.summary.duration;
|
||||||
|
json_route_summary.values["start_point"] =
|
||||||
|
facade->get_name_for_id(description_factory.summary.source_name_id);
|
||||||
|
json_route_summary.values["end_point"] =
|
||||||
|
facade->get_name_for_id(description_factory.summary.target_name_id);
|
||||||
|
json_result.values["route_summary"] = json_route_summary;
|
||||||
|
|
||||||
|
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
|
||||||
|
|
||||||
|
osrm::json::Array json_via_points_array;
|
||||||
|
osrm::json::Array json_first_coordinate;
|
||||||
|
json_first_coordinate.values.push_back(
|
||||||
|
raw_route.segment_end_coordinates.front().source_phantom.location.lat /
|
||||||
|
COORDINATE_PRECISION);
|
||||||
|
json_first_coordinate.values.push_back(
|
||||||
|
raw_route.segment_end_coordinates.front().source_phantom.location.lon /
|
||||||
|
COORDINATE_PRECISION);
|
||||||
|
json_via_points_array.values.push_back(json_first_coordinate);
|
||||||
|
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
|
||||||
|
{
|
||||||
|
std::string tmp;
|
||||||
|
osrm::json::Array json_coordinate;
|
||||||
|
json_coordinate.values.push_back(nodes.target_phantom.location.lat /
|
||||||
|
COORDINATE_PRECISION);
|
||||||
|
json_coordinate.values.push_back(nodes.target_phantom.location.lon /
|
||||||
|
COORDINATE_PRECISION);
|
||||||
|
json_via_points_array.values.push_back(json_coordinate);
|
||||||
|
}
|
||||||
|
json_result.values["via_points"] = json_via_points_array;
|
||||||
|
|
||||||
|
osrm::json::Array json_via_indices_array;
|
||||||
|
|
||||||
|
std::vector<unsigned> const &shortest_leg_end_indices = description_factory.GetViaIndices();
|
||||||
|
json_via_indices_array.values.insert(json_via_indices_array.values.end(),
|
||||||
|
shortest_leg_end_indices.begin(),
|
||||||
|
shortest_leg_end_indices.end());
|
||||||
|
json_result.values["via_indices"] = json_via_indices_array;
|
||||||
|
|
||||||
|
// only one alternative route is computed at this time, so this is hardcoded
|
||||||
|
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||||
|
{
|
||||||
|
json_result.values["found_alternative"] = osrm::json::True();
|
||||||
|
BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty());
|
||||||
|
alternate_description_factory.SetStartSegment(
|
||||||
|
raw_route.segment_end_coordinates.front().source_phantom,
|
||||||
|
raw_route.alt_source_traversed_in_reverse.front());
|
||||||
|
// Get all the coordinates for the computed route
|
||||||
|
for (const PathData &path_data : raw_route.unpacked_alternative)
|
||||||
|
{
|
||||||
|
current = facade->GetCoordinateOfNode(path_data.node);
|
||||||
|
alternate_description_factory.AppendSegment(current, path_data);
|
||||||
|
}
|
||||||
|
alternate_description_factory.SetEndSegment(
|
||||||
|
raw_route.segment_end_coordinates.back().target_phantom,
|
||||||
|
raw_route.alt_source_traversed_in_reverse.back());
|
||||||
|
alternate_description_factory.Run(config.zoom_level);
|
||||||
|
|
||||||
|
if (config.geometry)
|
||||||
|
{
|
||||||
|
osrm::json::Value alternate_geometry_string =
|
||||||
|
alternate_description_factory.AppendGeometryString(config.encode_geometry);
|
||||||
|
osrm::json::Array json_alternate_geometries_array;
|
||||||
|
json_alternate_geometries_array.values.push_back(alternate_geometry_string);
|
||||||
|
json_result.values["alternative_geometries"] = json_alternate_geometries_array;
|
||||||
|
}
|
||||||
|
// Generate instructions for each alternative (simulated here)
|
||||||
|
osrm::json::Array json_alt_instructions;
|
||||||
|
osrm::json::Array json_current_alt_instructions;
|
||||||
|
if (config.instructions)
|
||||||
|
{
|
||||||
|
BuildTextualDescription(
|
||||||
|
alternate_description_factory, json_current_alt_instructions,
|
||||||
|
raw_route.alternative_path_length, alternative_path_segments);
|
||||||
|
json_alt_instructions.values.push_back(json_current_alt_instructions);
|
||||||
|
json_result.values["alternative_instructions"] = json_alt_instructions;
|
||||||
|
}
|
||||||
|
alternate_description_factory.BuildRouteSummary(
|
||||||
|
alternate_description_factory.get_entire_length(),
|
||||||
|
raw_route.alternative_path_length);
|
||||||
|
|
||||||
|
osrm::json::Object json_alternate_route_summary;
|
||||||
|
osrm::json::Array json_alternate_route_summary_array;
|
||||||
|
json_alternate_route_summary.values["total_distance"] =
|
||||||
|
alternate_description_factory.summary.distance;
|
||||||
|
json_alternate_route_summary.values["total_time"] =
|
||||||
|
alternate_description_factory.summary.duration;
|
||||||
|
json_alternate_route_summary.values["start_point"] =
|
||||||
|
facade->get_name_for_id(alternate_description_factory.summary.source_name_id);
|
||||||
|
json_alternate_route_summary.values["end_point"] =
|
||||||
|
facade->get_name_for_id(alternate_description_factory.summary.target_name_id);
|
||||||
|
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
|
||||||
|
json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
|
||||||
|
|
||||||
|
std::vector<unsigned> const &alternate_leg_end_indices =
|
||||||
|
alternate_description_factory.GetViaIndices();
|
||||||
|
osrm::json::Array json_altenative_indices_array;
|
||||||
|
json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(),
|
||||||
|
alternate_leg_end_indices.begin(),
|
||||||
|
alternate_leg_end_indices.end());
|
||||||
|
json_result.values["alternative_indices"] = json_altenative_indices_array;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
json_result.values["found_alternative"] = osrm::json::False();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Names for both routes
|
||||||
|
RouteNames route_names =
|
||||||
|
GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
|
||||||
|
osrm::json::Array json_route_names;
|
||||||
|
json_route_names.values.push_back(route_names.shortest_path_name_1);
|
||||||
|
json_route_names.values.push_back(route_names.shortest_path_name_2);
|
||||||
|
json_result.values["route_name"] = json_route_names;
|
||||||
|
|
||||||
|
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||||
|
{
|
||||||
|
osrm::json::Array json_alternate_names_array;
|
||||||
|
osrm::json::Array json_alternate_names;
|
||||||
|
json_alternate_names.values.push_back(route_names.alternative_path_name_1);
|
||||||
|
json_alternate_names.values.push_back(route_names.alternative_path_name_2);
|
||||||
|
json_alternate_names_array.values.push_back(json_alternate_names);
|
||||||
|
json_result.values["alternative_names"] = json_alternate_names_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
osrm::json::Object json_hint_object;
|
||||||
|
json_hint_object.values["checksum"] = facade->GetCheckSum();
|
||||||
|
osrm::json::Array json_location_hint_array;
|
||||||
|
std::string hint;
|
||||||
|
for (const auto i : osrm::irange<std::size_t>(0, raw_route.segment_end_coordinates.size()))
|
||||||
|
{
|
||||||
|
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates[i].source_phantom,
|
||||||
|
hint);
|
||||||
|
json_location_hint_array.values.push_back(hint);
|
||||||
|
}
|
||||||
|
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates.back().target_phantom,
|
||||||
|
hint);
|
||||||
|
json_location_hint_array.values.push_back(hint);
|
||||||
|
json_hint_object.values["locations"] = json_location_hint_array;
|
||||||
|
json_result.values["hint_data"] = json_hint_object;
|
||||||
|
|
||||||
|
// render the content to the output array
|
||||||
|
// TIMER_START(route_render);
|
||||||
|
// osrm::json::render(reply.content, json_result);
|
||||||
|
// TIMER_STOP(route_render);
|
||||||
|
// SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: reorder parameters
|
||||||
|
inline void BuildTextualDescription(DescriptionFactory &description_factory,
|
||||||
|
osrm::json::Array &json_instruction_array,
|
||||||
|
const int route_length,
|
||||||
|
std::vector<Segment> &route_segments_list)
|
||||||
|
{
|
||||||
|
// Segment information has following format:
|
||||||
|
//["instruction id","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||||
|
unsigned necessary_segments_running_index = 0;
|
||||||
|
round_about.leave_at_exit = 0;
|
||||||
|
round_about.name_id = 0;
|
||||||
|
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
||||||
|
|
||||||
|
// Fetch data from Factory and generate a string from it.
|
||||||
|
for (const SegmentInformation &segment : description_factory.path_description)
|
||||||
|
{
|
||||||
|
osrm::json::Array json_instruction_row;
|
||||||
|
TurnInstruction current_instruction = segment.turn_instruction;
|
||||||
|
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||||
|
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
|
||||||
|
{
|
||||||
|
if (TurnInstruction::EnterRoundAbout == current_instruction)
|
||||||
|
{
|
||||||
|
round_about.name_id = segment.name_id;
|
||||||
|
round_about.start_index = necessary_segments_running_index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string current_turn_instruction;
|
||||||
|
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
||||||
|
{
|
||||||
|
temp_instruction = cast::integral_to_string(
|
||||||
|
cast::enum_to_underlying(TurnInstruction::EnterRoundAbout));
|
||||||
|
current_turn_instruction += temp_instruction;
|
||||||
|
current_turn_instruction += "-";
|
||||||
|
temp_instruction = cast::integral_to_string(round_about.leave_at_exit + 1);
|
||||||
|
current_turn_instruction += temp_instruction;
|
||||||
|
round_about.leave_at_exit = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp_instruction =
|
||||||
|
cast::integral_to_string(cast::enum_to_underlying(current_instruction));
|
||||||
|
current_turn_instruction += temp_instruction;
|
||||||
|
}
|
||||||
|
json_instruction_row.values.push_back(current_turn_instruction);
|
||||||
|
|
||||||
|
json_instruction_row.values.push_back(facade->get_name_for_id(segment.name_id));
|
||||||
|
json_instruction_row.values.push_back(std::round(segment.length));
|
||||||
|
json_instruction_row.values.push_back(necessary_segments_running_index);
|
||||||
|
json_instruction_row.values.push_back(std::round(segment.duration / 10.));
|
||||||
|
json_instruction_row.values.push_back(
|
||||||
|
cast::integral_to_string(static_cast<unsigned>(segment.length)) + "m");
|
||||||
|
const double bearing_value = (segment.bearing / 10.);
|
||||||
|
json_instruction_row.values.push_back(bearing::get(bearing_value));
|
||||||
|
json_instruction_row.values.push_back(
|
||||||
|
static_cast<unsigned>(round(bearing_value)));
|
||||||
|
json_instruction_row.values.push_back(segment.travel_mode);
|
||||||
|
|
||||||
|
route_segments_list.emplace_back(
|
||||||
|
segment.name_id, static_cast<int>(segment.length),
|
||||||
|
static_cast<unsigned>(route_segments_list.size()));
|
||||||
|
json_instruction_array.values.push_back(json_instruction_row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (TurnInstruction::StayOnRoundAbout == current_instruction)
|
||||||
|
{
|
||||||
|
++round_about.leave_at_exit;
|
||||||
|
}
|
||||||
|
if (segment.necessary)
|
||||||
|
{
|
||||||
|
++necessary_segments_running_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
osrm::json::Array json_last_instruction_row;
|
||||||
|
temp_instruction = cast::integral_to_string(
|
||||||
|
cast::enum_to_underlying(TurnInstruction::ReachedYourDestination));
|
||||||
|
json_last_instruction_row.values.push_back(temp_instruction);
|
||||||
|
json_last_instruction_row.values.push_back("");
|
||||||
|
json_last_instruction_row.values.push_back(0);
|
||||||
|
json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
|
||||||
|
json_last_instruction_row.values.push_back(0);
|
||||||
|
json_last_instruction_row.values.push_back("0m");
|
||||||
|
json_last_instruction_row.values.push_back(bearing::get(0.0));
|
||||||
|
json_last_instruction_row.values.push_back(0.);
|
||||||
|
json_instruction_array.values.push_back(json_last_instruction_row);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* JSON_DESCRIPTOR_H_ */
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
FROM ubuntu:14.04
|
|
||||||
|
|
||||||
RUN apt-get update -y
|
|
||||||
RUN apt-get install -y build-essential git-core python-pip python-software-properties software-properties-common
|
|
||||||
|
|
||||||
RUN apt-get -y install gcc-4.8 g++-4.8 libboost1.55-all-dev llvm-3.4
|
|
||||||
RUN apt-get -y install libbz2-dev libstxxl-dev libstxxl1 libxml2-dev
|
|
||||||
RUN apt-get -y install libzip-dev lua5.1 liblua5.1-0-dev libtbb-dev libgdal-dev ruby1.9
|
|
||||||
RUN apt-get -y install curl cmake cmake-curses-gui
|
|
||||||
|
|
||||||
RUN pip install awscli
|
|
||||||
|
|
||||||
# luabind
|
|
||||||
RUN curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
|
|
||||||
|
|
||||||
RUN useradd -ms /bin/bash mapbox
|
|
||||||
USER mapbox
|
|
||||||
ENV HOME /home/mapbox
|
|
||||||
WORKDIR /home/mapbox
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user