Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6ad1cd3fb5 | |||
| 40443d1e25 | |||
| 4ec323c5cc | |||
| 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
|
|
||||||
|
|||||||
+58
-171
@@ -1,176 +1,63 @@
|
|||||||
#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 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
|
||||||
|
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
|
|
||||||
+158
-239
@@ -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,74 +27,87 @@ 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 data_structures/raster_source.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(RASTERSOURCE OBJECT data_structures/raster_source.cpp)
|
||||||
file(GLOB ExtractorTestsGlob unit_tests/extractor/*.cpp)
|
add_library(EXCEPTION OBJECT util/osrm_exception.cpp)
|
||||||
file(GLOB EngineTestsGlob unit_tests/engine/*.cpp)
|
add_library(MERCATOR OBJECT util/mercator.cpp)
|
||||||
file(GLOB UtilTestsGlob unit_tests/util/*.cpp)
|
add_library(ANGLE OBJECT util/compute_angle.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_library(COMPRESSEDEDGE OBJECT data_structures/compressed_edge_container.cpp)
|
||||||
|
add_library(GRAPHCOMPRESSOR OBJECT algorithms/graph_compressor.cpp)
|
||||||
|
|
||||||
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> $<TARGET_OBJECTS:COMPRESSEDEDGE> $<TARGET_OBJECTS:GRAPHCOMPRESSOR>)
|
||||||
add_executable(osrm-datastore src/tools/store.cpp $<TARGET_OBJECTS:UTIL>)
|
|
||||||
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:UTIL> $<TARGET_OBJECTS:STORAGE>)
|
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>)
|
file(GLOB CoordinateGlob data_structures/coordinate.cpp algorithms/coordinate_calculation.cpp)
|
||||||
|
file(GLOB AlgorithmGlob algorithms/polyline_compressor.cpp algorithms/polyline_formatter.cpp algorithms/douglas_peucker.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 algorithms/graph_compressor.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:RESTRICTION> $<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> $<TARGET_OBJECTS:COMPRESSEDEDGE> $<TARGET_OBJECTS:GRAPHCOMPRESSOR> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:RASTERSOURCE>)
|
||||||
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> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:COMPRESSEDEDGE>)
|
||||||
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(engine-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/unit_tests)
|
|
||||||
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)
|
||||||
@@ -104,31 +115,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)
|
||||||
@@ -145,11 +144,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()
|
||||||
|
|
||||||
@@ -159,7 +153,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)
|
||||||
@@ -167,8 +163,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()
|
||||||
@@ -180,32 +177,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 ")
|
||||||
@@ -227,42 +205,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)
|
||||||
@@ -272,141 +283,80 @@ if(OPENMP_FOUND)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
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 ${StorageHeader} DESTINATION include/osrm/storage)
|
|
||||||
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)
|
||||||
@@ -416,34 +366,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}"
|
||||||
|
|||||||
+30
-17
@@ -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 BAYES_CLASSIFIER_HPP
|
#ifndef BAYES_CLASSIFIER_HPP
|
||||||
#define BAYES_CLASSIFIER_HPP
|
#define BAYES_CLASSIFIER_HPP
|
||||||
|
|
||||||
@@ -6,15 +33,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <boost/math/constants/constants.hpp>
|
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace engine
|
|
||||||
{
|
|
||||||
namespace map_matching
|
|
||||||
{
|
|
||||||
|
|
||||||
struct NormalDistribution
|
struct NormalDistribution
|
||||||
{
|
{
|
||||||
NormalDistribution(const double mean, const double standard_deviation)
|
NormalDistribution(const double mean, const double standard_deviation)
|
||||||
@@ -22,13 +40,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 +59,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);
|
||||||
@@ -98,8 +114,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_
|
||||||
@@ -0,0 +1,273 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace coordinate_calculation
|
||||||
|
{
|
||||||
|
|
||||||
|
double 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 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 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 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 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 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 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 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 =
|
||||||
|
euclidean_distance(query_location, nearest_location);
|
||||||
|
BOOST_ASSERT(0.f <= approximate_distance);
|
||||||
|
return approximate_distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void 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 deg_to_rad(const float degree)
|
||||||
|
{
|
||||||
|
return degree * (static_cast<float>(M_PI) / 180.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float rad_to_deg(const float radian)
|
||||||
|
{
|
||||||
|
return radian * (180.f * static_cast<float>(M_1_PI));
|
||||||
|
}
|
||||||
|
|
||||||
|
float 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>
|
||||||
|
|
||||||
|
namespace coordinate_calculation
|
||||||
|
{
|
||||||
|
double
|
||||||
|
great_circle_distance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||||
|
|
||||||
|
double great_circle_distance(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
|
||||||
|
float euclidean_distance(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
|
||||||
|
float euclidean_distance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||||
|
|
||||||
|
void lat_or_lon_to_string(const int value, std::string &output);
|
||||||
|
|
||||||
|
float perpendicular_distance(const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target,
|
||||||
|
const FixedPointCoordinate &query_location);
|
||||||
|
|
||||||
|
float perpendicular_distance(const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target,
|
||||||
|
const FixedPointCoordinate &query_location,
|
||||||
|
FixedPointCoordinate &nearest_location,
|
||||||
|
float &ratio);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
float deg_to_rad(const float degree);
|
||||||
|
float rad_to_deg(const float radian);
|
||||||
|
|
||||||
|
float bearing(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // COORDINATE_CALCULATION
|
||||||
@@ -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");
|
||||||
|
auto left_border = begin;
|
||||||
|
auto 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_ */
|
||||||
@@ -1,30 +1,31 @@
|
|||||||
#include "extractor/graph_compressor.hpp"
|
#include "graph_compressor.hpp"
|
||||||
|
|
||||||
#include "extractor/compressed_edge_container.hpp"
|
#include "../data_structures/compressed_edge_container.hpp"
|
||||||
#include "extractor/restriction_map.hpp"
|
#include "../data_structures/dynamic_graph.hpp"
|
||||||
#include "util/dynamic_graph.hpp"
|
#include "../data_structures/node_based_graph.hpp"
|
||||||
#include "util/node_based_graph.hpp"
|
#include "../data_structures/restriction_map.hpp"
|
||||||
#include "util/percent.hpp"
|
#include "../data_structures/percent.hpp"
|
||||||
|
|
||||||
#include "util/simple_logger.hpp"
|
#include "../util/simple_logger.hpp"
|
||||||
|
|
||||||
namespace osrm
|
GraphCompressor::GraphCompressor(SpeedProfileProperties speed_profile)
|
||||||
{
|
: speed_profile(std::move(speed_profile))
|
||||||
namespace extractor
|
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|
||||||
const std::unordered_set<NodeID> &traffic_lights,
|
void GraphCompressor::Compress(const std::unordered_set<NodeID>& barrier_nodes,
|
||||||
RestrictionMap &restriction_map,
|
const std::unordered_set<NodeID>& traffic_lights,
|
||||||
util::NodeBasedDynamicGraph &graph,
|
RestrictionMap& restriction_map,
|
||||||
CompressedEdgeContainer &geometry_compressor)
|
NodeBasedDynamicGraph& graph,
|
||||||
|
CompressedEdgeContainer& geometry_compressor)
|
||||||
{
|
{
|
||||||
const unsigned original_number_of_nodes = graph.GetNumberOfNodes();
|
const unsigned original_number_of_nodes = graph.GetNumberOfNodes();
|
||||||
const unsigned original_number_of_edges = graph.GetNumberOfEdges();
|
const unsigned original_number_of_edges = graph.GetNumberOfEdges();
|
||||||
|
|
||||||
util::Percent progress(original_number_of_nodes);
|
Percent progress(original_number_of_nodes);
|
||||||
|
|
||||||
for (const NodeID node_v : util::irange(0u, original_number_of_nodes))
|
for (const NodeID node_v : osrm::irange(0u, original_number_of_nodes))
|
||||||
{
|
{
|
||||||
progress.printStatus(node_v);
|
progress.printStatus(node_v);
|
||||||
|
|
||||||
@@ -63,10 +64,12 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
const bool reverse_edge_order = graph.GetEdgeData(graph.BeginEdges(node_v)).reversed;
|
const bool reverse_edge_order = graph.GetEdgeData(graph.BeginEdges(node_v)).reversed;
|
||||||
const EdgeID forward_e2 = graph.BeginEdges(node_v) + reverse_edge_order;
|
const EdgeID forward_e2 = graph.BeginEdges(node_v) + reverse_edge_order;
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != forward_e2);
|
BOOST_ASSERT(SPECIAL_EDGEID != forward_e2);
|
||||||
BOOST_ASSERT(forward_e2 >= graph.BeginEdges(node_v) && forward_e2 < graph.EndEdges(node_v));
|
BOOST_ASSERT(forward_e2 >= graph.BeginEdges(node_v) &&
|
||||||
|
forward_e2 < graph.EndEdges(node_v));
|
||||||
const EdgeID reverse_e2 = graph.BeginEdges(node_v) + 1 - reverse_edge_order;
|
const EdgeID reverse_e2 = graph.BeginEdges(node_v) + 1 - reverse_edge_order;
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2);
|
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2);
|
||||||
BOOST_ASSERT(reverse_e2 >= graph.BeginEdges(node_v) && reverse_e2 < graph.EndEdges(node_v));
|
BOOST_ASSERT(reverse_e2 >= graph.BeginEdges(node_v) &&
|
||||||
|
reverse_e2 < graph.EndEdges(node_v));
|
||||||
|
|
||||||
const EdgeData &fwd_edge_data2 = graph.GetEdgeData(forward_e2);
|
const EdgeData &fwd_edge_data2 = graph.GetEdgeData(forward_e2);
|
||||||
const EdgeData &rev_edge_data2 = graph.GetEdgeData(reverse_e2);
|
const EdgeData &rev_edge_data2 = graph.GetEdgeData(reverse_e2);
|
||||||
@@ -100,24 +103,13 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fwd_edge_data1.IsCompatibleTo(fwd_edge_data2) &&
|
if (fwd_edge_data1.IsCompatibleTo(fwd_edge_data2) && rev_edge_data1.IsCompatibleTo(rev_edge_data2))
|
||||||
rev_edge_data1.IsCompatibleTo(rev_edge_data2))
|
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(graph.GetEdgeData(forward_e1).name_id ==
|
BOOST_ASSERT(graph.GetEdgeData(forward_e1).name_id ==
|
||||||
graph.GetEdgeData(reverse_e1).name_id);
|
graph.GetEdgeData(reverse_e1).name_id);
|
||||||
BOOST_ASSERT(graph.GetEdgeData(forward_e2).name_id ==
|
BOOST_ASSERT(graph.GetEdgeData(forward_e2).name_id ==
|
||||||
graph.GetEdgeData(reverse_e2).name_id);
|
graph.GetEdgeData(reverse_e2).name_id);
|
||||||
|
|
||||||
// Do not compress edge if it crosses a traffic signal.
|
|
||||||
// This can't be done in IsCompatibleTo, becase we only store the
|
|
||||||
// traffic signals in the `traffic_lights` list, which EdgeData
|
|
||||||
// doesn't have access to.
|
|
||||||
const bool has_node_penalty = traffic_lights.find(node_v) != traffic_lights.end();
|
|
||||||
if (has_node_penalty)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get distances before graph is modified
|
// Get distances before graph is modified
|
||||||
const int forward_weight1 = graph.GetEdgeData(forward_e1).distance;
|
const int forward_weight1 = graph.GetEdgeData(forward_e1).distance;
|
||||||
const int forward_weight2 = graph.GetEdgeData(forward_e2).distance;
|
const int forward_weight2 = graph.GetEdgeData(forward_e2).distance;
|
||||||
@@ -131,9 +123,18 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
BOOST_ASSERT(0 != reverse_weight1);
|
BOOST_ASSERT(0 != reverse_weight1);
|
||||||
BOOST_ASSERT(0 != reverse_weight2);
|
BOOST_ASSERT(0 != reverse_weight2);
|
||||||
|
|
||||||
|
const bool has_node_penalty = traffic_lights.find(node_v) != traffic_lights.end();
|
||||||
|
|
||||||
// add weight of e2's to e1
|
// add weight of e2's to e1
|
||||||
graph.GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
|
graph.GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
|
||||||
graph.GetEdgeData(reverse_e1).distance += rev_edge_data2.distance;
|
graph.GetEdgeData(reverse_e1).distance += rev_edge_data2.distance;
|
||||||
|
if (has_node_penalty)
|
||||||
|
{
|
||||||
|
graph.GetEdgeData(forward_e1).distance +=
|
||||||
|
speed_profile.traffic_signal_penalty;
|
||||||
|
graph.GetEdgeData(reverse_e1).distance +=
|
||||||
|
speed_profile.traffic_signal_penalty;
|
||||||
|
}
|
||||||
|
|
||||||
// extend e1's to targets of e2's
|
// extend e1's to targets of e2's
|
||||||
graph.SetTarget(forward_e1, node_w);
|
graph.SetTarget(forward_e1, node_w);
|
||||||
@@ -151,38 +152,28 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
restriction_map.FixupArrivingTurnRestriction(node_w, node_v, node_u, graph);
|
restriction_map.FixupArrivingTurnRestriction(node_w, node_v, node_u, graph);
|
||||||
|
|
||||||
// store compressed geometry in container
|
// store compressed geometry in container
|
||||||
geometry_compressor.CompressEdge(forward_e1, forward_e2, node_v, node_w,
|
geometry_compressor.CompressEdge(
|
||||||
forward_weight1, forward_weight2);
|
forward_e1, forward_e2, node_v, node_w,
|
||||||
geometry_compressor.CompressEdge(reverse_e1, reverse_e2, node_v, node_u,
|
forward_weight1 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0),
|
||||||
reverse_weight1, reverse_weight2);
|
forward_weight2);
|
||||||
|
geometry_compressor.CompressEdge(
|
||||||
|
reverse_e1, reverse_e2, node_v, node_u, reverse_weight1,
|
||||||
|
reverse_weight2 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintStatistics(original_number_of_nodes, original_number_of_edges, graph);
|
PrintStatistics(original_number_of_nodes, original_number_of_edges, graph);
|
||||||
|
|
||||||
// Repeate the loop, but now add all edges as uncompressed values.
|
|
||||||
// The function AddUncompressedEdge does nothing if the edge is already
|
|
||||||
// in the CompressedEdgeContainer.
|
|
||||||
for (const NodeID node_u : util::irange(0u, original_number_of_nodes))
|
|
||||||
{
|
|
||||||
for (const auto edge_id : util::irange(graph.BeginEdges(node_u), graph.EndEdges(node_u)))
|
|
||||||
{
|
|
||||||
const EdgeData &data = graph.GetEdgeData(edge_id);
|
|
||||||
const NodeID target = graph.GetTarget(edge_id);
|
|
||||||
geometry_compressor.AddUncompressedEdge(edge_id, target, data.distance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphCompressor::PrintStatistics(unsigned original_number_of_nodes,
|
void GraphCompressor::PrintStatistics(unsigned original_number_of_nodes,
|
||||||
unsigned original_number_of_edges,
|
unsigned original_number_of_edges,
|
||||||
const util::NodeBasedDynamicGraph &graph) const
|
const NodeBasedDynamicGraph& graph) const
|
||||||
{
|
{
|
||||||
|
|
||||||
unsigned new_node_count = 0;
|
unsigned new_node_count = 0;
|
||||||
unsigned new_edge_count = 0;
|
unsigned new_edge_count = 0;
|
||||||
|
|
||||||
for (const auto i : util::irange(0u, graph.GetNumberOfNodes()))
|
for (const auto i : osrm::irange(0u, graph.GetNumberOfNodes()))
|
||||||
{
|
{
|
||||||
if (graph.GetOutDegree(i) > 0)
|
if (graph.GetOutDegree(i) > 0)
|
||||||
{
|
{
|
||||||
@@ -190,10 +181,8 @@ void GraphCompressor::PrintStatistics(unsigned original_number_of_nodes,
|
|||||||
new_edge_count += (graph.EndEdges(i) - graph.BeginEdges(i));
|
new_edge_count += (graph.EndEdges(i) - graph.BeginEdges(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
util::SimpleLogger().Write() << "Node compression ratio: "
|
SimpleLogger().Write() << "Node compression ratio: "
|
||||||
<< new_node_count / (double)original_number_of_nodes;
|
<< new_node_count / (double)original_number_of_nodes;
|
||||||
util::SimpleLogger().Write() << "Edge compression ratio: "
|
SimpleLogger().Write() << "Edge compression ratio: "
|
||||||
<< new_edge_count / (double)original_number_of_edges;
|
<< new_edge_count / (double)original_number_of_edges;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 GEOMETRY_COMPRESSOR_HPP
|
||||||
|
#define GEOMETRY_COMPRESSOR_HPP
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include "../contractor/speed_profile.hpp"
|
||||||
|
#include "../data_structures/node_based_graph.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
class CompressedEdgeContainer;
|
||||||
|
class RestrictionMap;
|
||||||
|
|
||||||
|
class GraphCompressor
|
||||||
|
{
|
||||||
|
using EdgeData = NodeBasedDynamicGraph::EdgeData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GraphCompressor(SpeedProfileProperties speed_profile);
|
||||||
|
|
||||||
|
void Compress(const std::unordered_set<NodeID>& barrier_nodes,
|
||||||
|
const std::unordered_set<NodeID>& traffic_lights,
|
||||||
|
RestrictionMap& restriction_map,
|
||||||
|
NodeBasedDynamicGraph& graph,
|
||||||
|
CompressedEdgeContainer& geometry_compressor);
|
||||||
|
private:
|
||||||
|
|
||||||
|
void PrintStatistics(unsigned original_number_of_nodes,
|
||||||
|
unsigned original_number_of_edges,
|
||||||
|
const NodeBasedDynamicGraph& graph) const;
|
||||||
|
|
||||||
|
SpeedProfileProperties speed_profile;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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()),
|
||||||
|
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,18 +1,45 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 TARJAN_SCC_HPP
|
#ifndef TARJAN_SCC_HPP
|
||||||
#define TARJAN_SCC_HPP
|
#define TARJAN_SCC_HPP
|
||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "../typedefs.h"
|
||||||
#include "util/deallocating_vector.hpp"
|
#include "../data_structures/deallocating_vector.hpp"
|
||||||
#include "extractor/node_based_edge.hpp"
|
#include "../data_structures/import_edge.hpp"
|
||||||
#include "extractor/query_node.hpp"
|
#include "../data_structures/query_node.hpp"
|
||||||
#include "util/percent.hpp"
|
#include "../data_structures/percent.hpp"
|
||||||
|
|
||||||
#include "util/integer_range.hpp"
|
#include "../util/integer_range.hpp"
|
||||||
#include "util/simple_logger.hpp"
|
#include "../util/simple_logger.hpp"
|
||||||
#include "util/std_hash.hpp"
|
#include "../util/std_hash.hpp"
|
||||||
#include "util/timing_util.hpp"
|
#include "../util/timing_util.hpp"
|
||||||
|
|
||||||
#include "osrm/coordinate.hpp"
|
#include <osrm/coordinate.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@@ -22,11 +49,6 @@
|
|||||||
#include <stack>
|
#include <stack>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace extractor
|
|
||||||
{
|
|
||||||
|
|
||||||
template <typename GraphT> class TarjanSCC
|
template <typename GraphT> class TarjanSCC
|
||||||
{
|
{
|
||||||
struct TarjanStackFrame
|
struct TarjanStackFrame
|
||||||
@@ -71,7 +93,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])
|
||||||
{
|
{
|
||||||
@@ -146,8 +168,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 +180,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)
|
||||||
@@ -178,7 +200,5 @@ template <typename GraphT> class TarjanSCC
|
|||||||
|
|
||||||
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 /* TARJAN_SCC_HPP */
|
||||||
@@ -1,11 +1,38 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 TRIP_BRUTE_FORCE_HPP
|
#ifndef TRIP_BRUTE_FORCE_HPP
|
||||||
#define TRIP_BRUTE_FORCE_HPP
|
#define TRIP_BRUTE_FORCE_HPP
|
||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "../data_structures/search_engine.hpp"
|
||||||
#include "util/dist_table_wrapper.hpp"
|
#include "../util/dist_table_wrapper.hpp"
|
||||||
#include "util/simple_logger.hpp"
|
#include "../util/simple_logger.hpp"
|
||||||
|
|
||||||
#include "osrm/json_container.hpp"
|
#include <osrm/json_container.hpp>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -16,13 +43,11 @@
|
|||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace engine
|
|
||||||
{
|
|
||||||
namespace trip
|
namespace trip
|
||||||
{
|
{
|
||||||
|
|
||||||
// computes the distance of a given permutation
|
// computes the distance of a given permutation
|
||||||
EdgeWeight ReturnDistance(const util::DistTableWrapper<EdgeWeight> &dist_table,
|
EdgeWeight ReturnDistance(const DistTableWrapper<EdgeWeight> &dist_table,
|
||||||
const std::vector<NodeID> &location_order,
|
const std::vector<NodeID> &location_order,
|
||||||
const EdgeWeight min_route_dist,
|
const EdgeWeight min_route_dist,
|
||||||
const std::size_t component_size)
|
const std::size_t component_size)
|
||||||
@@ -46,10 +71,8 @@ template <typename NodeIDIterator>
|
|||||||
std::vector<NodeID> BruteForceTrip(const NodeIDIterator start,
|
std::vector<NodeID> BruteForceTrip(const NodeIDIterator start,
|
||||||
const NodeIDIterator end,
|
const NodeIDIterator end,
|
||||||
const std::size_t number_of_locations,
|
const std::size_t number_of_locations,
|
||||||
const util::DistTableWrapper<EdgeWeight> &dist_table)
|
const DistTableWrapper<EdgeWeight> &dist_table)
|
||||||
{
|
{
|
||||||
(void)number_of_locations; // unused
|
|
||||||
|
|
||||||
const auto component_size = std::distance(start, end);
|
const auto component_size = std::distance(start, end);
|
||||||
|
|
||||||
std::vector<NodeID> perm(start, end);
|
std::vector<NodeID> perm(start, end);
|
||||||
@@ -77,8 +100,7 @@ std::vector<NodeID> BruteForceTrip(const NodeIDIterator start,
|
|||||||
|
|
||||||
return route;
|
return route;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
} // end namespace trip
|
||||||
|
} // end namespace osrm
|
||||||
#endif // TRIP_BRUTE_FORCE_HPP
|
#endif // TRIP_BRUTE_FORCE_HPP
|
||||||
+38
-20
@@ -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 TRIP_FARTHEST_INSERTION_HPP
|
#ifndef TRIP_FARTHEST_INSERTION_HPP
|
||||||
#define TRIP_FARTHEST_INSERTION_HPP
|
#define TRIP_FARTHEST_INSERTION_HPP
|
||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "../data_structures/search_engine.hpp"
|
||||||
#include "util/dist_table_wrapper.hpp"
|
#include "../util/dist_table_wrapper.hpp"
|
||||||
|
|
||||||
#include "osrm/json_container.hpp"
|
#include <osrm/json_container.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@@ -15,8 +42,6 @@
|
|||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace engine
|
|
||||||
{
|
|
||||||
namespace trip
|
namespace trip
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -25,11 +50,10 @@ namespace trip
|
|||||||
using NodeIDIter = std::vector<NodeID>::iterator;
|
using NodeIDIter = std::vector<NodeID>::iterator;
|
||||||
std::pair<EdgeWeight, NodeIDIter>
|
std::pair<EdgeWeight, NodeIDIter>
|
||||||
GetShortestRoundTrip(const NodeID new_loc,
|
GetShortestRoundTrip(const NodeID new_loc,
|
||||||
const util::DistTableWrapper<EdgeWeight> &dist_table,
|
const DistTableWrapper<EdgeWeight> &dist_table,
|
||||||
const std::size_t number_of_locations,
|
const std::size_t number_of_locations,
|
||||||
std::vector<NodeID> &route)
|
std::vector<NodeID> &route)
|
||||||
{
|
{
|
||||||
(void)number_of_locations; // unused
|
|
||||||
|
|
||||||
auto min_trip_distance = INVALID_EDGE_WEIGHT;
|
auto min_trip_distance = INVALID_EDGE_WEIGHT;
|
||||||
NodeIDIter next_insert_point_candidate;
|
NodeIDIter next_insert_point_candidate;
|
||||||
@@ -52,13 +76,7 @@ GetShortestRoundTrip(const NodeID new_loc,
|
|||||||
|
|
||||||
BOOST_ASSERT_MSG(dist_from != INVALID_EDGE_WEIGHT, "distance has invalid edge weight");
|
BOOST_ASSERT_MSG(dist_from != INVALID_EDGE_WEIGHT, "distance has invalid edge weight");
|
||||||
BOOST_ASSERT_MSG(dist_to != INVALID_EDGE_WEIGHT, "distance has invalid edge weight");
|
BOOST_ASSERT_MSG(dist_to != INVALID_EDGE_WEIGHT, "distance has invalid edge weight");
|
||||||
// This is not neccessarily true:
|
BOOST_ASSERT_MSG(trip_dist >= 0, "previous trip was not minimal. something's wrong");
|
||||||
// Lets say you have an edge (u, v) with duration 100. If you place a coordinate exactly in
|
|
||||||
// the middle of the segment yielding (u, v'), the adjusted duration will be 100 * 0.5 = 50.
|
|
||||||
// Now imagine two coordinates. One placed at 0.99 and one at 0.999. This means (u, v') now
|
|
||||||
// has a duration of 100 * 0.99 = 99, but (u, v'') also has a duration of 100 * 0.995 = 99.
|
|
||||||
// In which case (v', v'') has a duration of 0.
|
|
||||||
// BOOST_ASSERT_MSG(trip_dist >= 0, "previous trip was not minimal. something's wrong");
|
|
||||||
|
|
||||||
// from all possible insertions to the current trip, choose the shortest of all insertions
|
// from all possible insertions to the current trip, choose the shortest of all insertions
|
||||||
if (trip_dist < min_trip_distance)
|
if (trip_dist < min_trip_distance)
|
||||||
@@ -78,7 +96,7 @@ std::vector<NodeID> FindRoute(const std::size_t &number_of_locations,
|
|||||||
const std::size_t &component_size,
|
const std::size_t &component_size,
|
||||||
const NodeIDIterator &start,
|
const NodeIDIterator &start,
|
||||||
const NodeIDIterator &end,
|
const NodeIDIterator &end,
|
||||||
const util::DistTableWrapper<EdgeWeight> &dist_table,
|
const DistTableWrapper<EdgeWeight> &dist_table,
|
||||||
const NodeID &start1,
|
const NodeID &start1,
|
||||||
const NodeID &start2)
|
const NodeID &start2)
|
||||||
{
|
{
|
||||||
@@ -100,7 +118,7 @@ std::vector<NodeID> FindRoute(const std::size_t &number_of_locations,
|
|||||||
for (std::size_t j = 2; j < component_size; ++j)
|
for (std::size_t j = 2; j < component_size; ++j)
|
||||||
{
|
{
|
||||||
|
|
||||||
auto farthest_distance = std::numeric_limits<int>::min();
|
auto farthest_distance = 0;
|
||||||
auto next_node = -1;
|
auto next_node = -1;
|
||||||
NodeIDIter next_insert_point;
|
NodeIDIter next_insert_point;
|
||||||
|
|
||||||
@@ -140,7 +158,7 @@ template <typename NodeIDIterator>
|
|||||||
std::vector<NodeID> FarthestInsertionTrip(const NodeIDIterator &start,
|
std::vector<NodeID> FarthestInsertionTrip(const NodeIDIterator &start,
|
||||||
const NodeIDIterator &end,
|
const NodeIDIterator &end,
|
||||||
const std::size_t number_of_locations,
|
const std::size_t number_of_locations,
|
||||||
const util::DistTableWrapper<EdgeWeight> &dist_table)
|
const DistTableWrapper<EdgeWeight> &dist_table)
|
||||||
{
|
{
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// START FARTHEST INSERTION HERE
|
// START FARTHEST INSERTION HERE
|
||||||
@@ -190,8 +208,8 @@ std::vector<NodeID> FarthestInsertionTrip(const NodeIDIterator &start,
|
|||||||
BOOST_ASSERT_MSG(static_cast<std::size_t>(max_to) < number_of_locations, "start node");
|
BOOST_ASSERT_MSG(static_cast<std::size_t>(max_to) < number_of_locations, "start node");
|
||||||
return FindRoute(number_of_locations, component_size, start, end, dist_table, max_from, max_to);
|
return FindRoute(number_of_locations, component_size, start, end, dist_table, max_from, max_to);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
} // end namespace trip
|
||||||
}
|
} // end namespace osrm
|
||||||
|
|
||||||
#endif // TRIP_FARTHEST_INSERTION_HPP
|
#endif // TRIP_FARTHEST_INSERTION_HPP
|
||||||
+34
-11
@@ -1,11 +1,38 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 TRIP_NEAREST_NEIGHBOUR_HPP
|
#ifndef TRIP_NEAREST_NEIGHBOUR_HPP
|
||||||
#define TRIP_NEAREST_NEIGHBOUR_HPP
|
#define TRIP_NEAREST_NEIGHBOUR_HPP
|
||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "../data_structures/search_engine.hpp"
|
||||||
#include "util/simple_logger.hpp"
|
#include "../util/simple_logger.hpp"
|
||||||
#include "util/dist_table_wrapper.hpp"
|
#include "../util/dist_table_wrapper.hpp"
|
||||||
|
|
||||||
#include "osrm/json_container.hpp"
|
#include <osrm/json_container.hpp>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -15,16 +42,13 @@
|
|||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace engine
|
|
||||||
{
|
|
||||||
namespace trip
|
namespace trip
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename NodeIDIterator>
|
template <typename NodeIDIterator>
|
||||||
std::vector<NodeID> NearestNeighbourTrip(const NodeIDIterator &start,
|
std::vector<NodeID> NearestNeighbourTrip(const NodeIDIterator &start,
|
||||||
const NodeIDIterator &end,
|
const NodeIDIterator &end,
|
||||||
const std::size_t number_of_locations,
|
const std::size_t number_of_locations,
|
||||||
const util::DistTableWrapper<EdgeWeight> &dist_table)
|
const DistTableWrapper<EdgeWeight> &dist_table)
|
||||||
{
|
{
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// START GREEDY NEAREST NEIGHBOUR HERE
|
// START GREEDY NEAREST NEIGHBOUR HERE
|
||||||
@@ -92,8 +116,7 @@ std::vector<NodeID> NearestNeighbourTrip(const NodeIDIterator &start,
|
|||||||
}
|
}
|
||||||
return route;
|
return route;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
} // end namespace trip
|
||||||
|
} // end namespace osrm
|
||||||
#endif // TRIP_NEAREST_NEIGHBOUR_HPP
|
#endif // TRIP_NEAREST_NEIGHBOUR_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,46 +25,40 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ENGINE_API_MATCH_PARAMETERS_HPP
|
#ifndef TRIP_BRUTE_FORCE_HPP
|
||||||
#define ENGINE_API_MATCH_PARAMETERS_HPP
|
#define TRIP_BRUTE_FORCE_HPP
|
||||||
|
|
||||||
#include "engine/api/route_parameters.hpp"
|
#include "../data_structures/search_engine.hpp"
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
|
||||||
|
#include <osrm/json_container.hpp>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace engine
|
namespace trip
|
||||||
{
|
|
||||||
namespace api
|
|
||||||
{
|
{
|
||||||
|
|
||||||
struct MatchParameters : public RouteParameters
|
// todo: yet to be implemented
|
||||||
|
void TabuSearchTrip(std::vector<unsigned> &location,
|
||||||
|
const PhantomNodeArray &phantom_node_vector,
|
||||||
|
const std::vector<EdgeWeight> &dist_table,
|
||||||
|
InternalRouteResult &min_route,
|
||||||
|
std::vector<int> &min_loc_permutation)
|
||||||
{
|
{
|
||||||
MatchParameters()
|
}
|
||||||
: RouteParameters(false,
|
|
||||||
false,
|
|
||||||
RouteParameters::GeometriesType::Polyline,
|
|
||||||
RouteParameters::OverviewType::Simplified,
|
|
||||||
{})
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
void TabuSearchTrip(const PhantomNodeArray &phantom_node_vector,
|
||||||
MatchParameters(std::vector<unsigned> timestamps_, Args... args_)
|
const std::vector<EdgeWeight> &dist_table,
|
||||||
: RouteParameters{std::forward<Args>(args_)...}, timestamps{std::move(timestamps_)}
|
InternalRouteResult &min_route,
|
||||||
{
|
std::vector<int> &min_loc_permutation)
|
||||||
}
|
{
|
||||||
|
|
||||||
std::vector<unsigned> timestamps;
|
|
||||||
bool IsValid() const
|
|
||||||
{
|
|
||||||
return RouteParameters::IsValid() &&
|
|
||||||
(timestamps.empty() || timestamps.size() == coordinates.size());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // TRIP_BRUTE_FORCE_HPP
|
||||||
#endif
|
|
||||||
+5
-10
@@ -6,8 +6,6 @@ ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||||||
|
|
||||||
SET PROJECT_DIR=%CD%
|
SET PROJECT_DIR=%CD%
|
||||||
ECHO PROJECT_DIR^: %PROJECT_DIR%
|
ECHO PROJECT_DIR^: %PROJECT_DIR%
|
||||||
ECHO NUMBER_OF_PROCESSORS^: %NUMBER_OF_PROCESSORS%
|
|
||||||
ECHO cmake^: && cmake --version
|
|
||||||
|
|
||||||
ECHO activating VS command prompt ...
|
ECHO activating VS command prompt ...
|
||||||
SET PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
|
SET PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
|
||||||
@@ -52,7 +50,7 @@ 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.58 ^
|
||||||
-DBoost_USE_MULTITHREADED=ON ^
|
-DBoost_USE_MULTITHREADED=ON ^
|
||||||
@@ -81,14 +79,11 @@ IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
|||||||
|
|
||||||
SET PATH=%PROJECT_DIR%\osrm-deps\libs\bin;%PATH%
|
SET PATH=%PROJECT_DIR%\osrm-deps\libs\bin;%PATH%
|
||||||
|
|
||||||
ECHO running engine-tests.exe ...
|
ECHO running datastructure-tests.exe ...
|
||||||
%Configuration%\engine-tests.exe
|
%Configuration%\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
|
%Configuration%\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 %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||||
|
|
||||||
IF NOT "%APPVEYOR_REPO_BRANCH%"=="develop" GOTO DONE
|
IF NOT "%APPVEYOR_REPO_BRANCH%"=="develop" GOTO DONE
|
||||||
|
|||||||
@@ -25,11 +25,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;
|
||||||
|
}
|
||||||
+1
-1
@@ -11,7 +11,7 @@ SET CONFIGURATION=Release
|
|||||||
FOR /F "tokens=*" %%i in ('git rev-parse --abbrev-ref HEAD') do SET APPVEYOR_REPO_BRANCH=%%i
|
FOR /F "tokens=*" %%i in ('git rev-parse --abbrev-ref HEAD') do SET APPVEYOR_REPO_BRANCH=%%i
|
||||||
ECHO APPVEYOR_REPO_BRANCH^: %APPVEYOR_REPO_BRANCH%
|
ECHO APPVEYOR_REPO_BRANCH^: %APPVEYOR_REPO_BRANCH%
|
||||||
|
|
||||||
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%
|
||||||
|
|
||||||
powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted -Force
|
powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted -Force
|
||||||
|
|||||||
@@ -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,7 +27,7 @@ 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")
|
||||||
@@ -36,6 +38,7 @@ SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6-dev, libbz2-1.0, libstxxl1, libxml2,
|
|||||||
|
|
||||||
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.
|
||||||
|
|||||||
@@ -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,10 +1,10 @@
|
|||||||
set(OLDFILE ${OUTPUT_DIR}/include/util/fingerprint_impl.hpp)
|
set(OLDFILE ${SOURCE_DIR}/util/fingerprint_impl.hpp)
|
||||||
set(NEWFILE ${OLDFILE}.tmp)
|
set(NEWFILE ${OLDFILE}.tmp)
|
||||||
set(INFILE ${SOURCE_DIR}/include/util/fingerprint_impl.hpp.in)
|
set(INFILE ${OLDFILE}.in)
|
||||||
file(MD5 ${SOURCE_DIR}/src/tools/contract.cpp MD5PREPARE)
|
file(MD5 ${SOURCE_DIR}/prepare.cpp MD5PREPARE)
|
||||||
file(MD5 ${SOURCE_DIR}/include/util/static_rtree.hpp MD5RTREE)
|
file(MD5 ${SOURCE_DIR}/data_structures/static_rtree.hpp MD5RTREE)
|
||||||
file(MD5 ${SOURCE_DIR}/include/util/graph_loader.hpp MD5GRAPH)
|
file(MD5 ${SOURCE_DIR}/util/graph_loader.hpp MD5GRAPH)
|
||||||
file(MD5 ${SOURCE_DIR}/include/engine/datafacade/internal_datafacade.hpp MD5OBJECTS)
|
file(MD5 ${SOURCE_DIR}/server/data_structures/internal_datafacade.hpp MD5OBJECTS)
|
||||||
|
|
||||||
CONFIGURE_FILE(${INFILE} ${NEWFILE})
|
CONFIGURE_FILE(${INFILE} ${NEWFILE})
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ file(MD5 ${NEWFILE} MD5NEW)
|
|||||||
if (EXISTS ${OLDFILE})
|
if (EXISTS ${OLDFILE})
|
||||||
file(MD5 ${OLDFILE} MD5OLD)
|
file(MD5 ${OLDFILE} MD5OLD)
|
||||||
if(NOT ${MD5NEW} STREQUAL ${MD5OLD})
|
if(NOT ${MD5NEW} STREQUAL ${MD5OLD})
|
||||||
file(REMOVE_RECURSE ${OLDFILE})
|
file(REMOVE_RECURSE ${OLDFILE})
|
||||||
file(RENAME ${NEWFILE} ${OLDFILE})
|
file(RENAME ${NEWFILE} ${OLDFILE})
|
||||||
else()
|
else()
|
||||||
file(REMOVE_RECURSE ${NEWFILE})
|
file(REMOVE_RECURSE ${NEWFILE})
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -1,17 +1,44 @@
|
|||||||
#ifndef GRAPH_CONTRACTOR_HPP
|
/*
|
||||||
#define GRAPH_CONTRACTOR_HPP
|
|
||||||
|
|
||||||
#include "util/binary_heap.hpp"
|
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||||
#include "util/deallocating_vector.hpp"
|
All rights reserved.
|
||||||
#include "util/dynamic_graph.hpp"
|
|
||||||
#include "util/percent.hpp"
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
#include "contractor/query_edge.hpp"
|
are permitted provided that the following conditions are met:
|
||||||
#include "util/xor_fast_hash.hpp"
|
|
||||||
#include "util/xor_fast_hash_storage.hpp"
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
#include "util/integer_range.hpp"
|
of conditions and the following disclaimer.
|
||||||
#include "util/simple_logger.hpp"
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
#include "util/timing_util.hpp"
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
#include "util/typedefs.hpp"
|
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_HPP
|
||||||
|
#define CONTRACTOR_HPP
|
||||||
|
|
||||||
|
#include "../data_structures/binary_heap.hpp"
|
||||||
|
#include "../data_structures/deallocating_vector.hpp"
|
||||||
|
#include "../data_structures/dynamic_graph.hpp"
|
||||||
|
#include "../data_structures/percent.hpp"
|
||||||
|
#include "../data_structures/query_edge.hpp"
|
||||||
|
#include "../data_structures/xor_fast_hash.hpp"
|
||||||
|
#include "../data_structures/xor_fast_hash_storage.hpp"
|
||||||
|
#include "../util/integer_range.hpp"
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
#include "../util/timing_util.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
@@ -23,16 +50,11 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
class Contractor
|
||||||
{
|
|
||||||
namespace contractor
|
|
||||||
{
|
{
|
||||||
|
|
||||||
class GraphContractor
|
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
struct ContractorEdgeData
|
struct ContractorEdgeData
|
||||||
{
|
{
|
||||||
@@ -63,22 +85,18 @@ class GraphContractor
|
|||||||
|
|
||||||
struct ContractorHeapData
|
struct ContractorHeapData
|
||||||
{
|
{
|
||||||
ContractorHeapData() {}
|
short hop;
|
||||||
ContractorHeapData(short hop_, bool target_) : hop(hop_), target(target_) {}
|
bool target;
|
||||||
|
ContractorHeapData() : hop(0), target(false) {}
|
||||||
short hop = 0;
|
ContractorHeapData(short h, bool t) : hop(h), target(t) {}
|
||||||
bool target = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using ContractorGraph = util::DynamicGraph<ContractorEdgeData>;
|
using ContractorGraph = DynamicGraph<ContractorEdgeData>;
|
||||||
// using ContractorHeap = util::BinaryHeap<NodeID, NodeID, int, ContractorHeapData,
|
// using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData,
|
||||||
// ArrayStorage<NodeID, NodeID>
|
// ArrayStorage<NodeID, NodeID>
|
||||||
// >;
|
// >;
|
||||||
using ContractorHeap = util::BinaryHeap<NodeID,
|
using ContractorHeap =
|
||||||
NodeID,
|
BinaryHeap<NodeID, NodeID, int, ContractorHeapData, XORFastHashStorage<NodeID, NodeID>>;
|
||||||
int,
|
|
||||||
ContractorHeapData,
|
|
||||||
util::XORFastHashStorage<NodeID, NodeID>>;
|
|
||||||
using ContractorEdge = ContractorGraph::InputEdge;
|
using ContractorEdge = ContractorGraph::InputEdge;
|
||||||
|
|
||||||
struct ContractorThreadData
|
struct ContractorThreadData
|
||||||
@@ -89,7 +107,11 @@ class GraphContractor
|
|||||||
explicit ContractorThreadData(NodeID nodes) : heap(nodes) {}
|
explicit ContractorThreadData(NodeID nodes) : heap(nodes) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
using NodeDepth = int;
|
struct NodePriorityData
|
||||||
|
{
|
||||||
|
int depth;
|
||||||
|
NodePriorityData() : depth(0) {}
|
||||||
|
};
|
||||||
|
|
||||||
struct ContractionStats
|
struct ContractionStats
|
||||||
{
|
{
|
||||||
@@ -134,18 +156,7 @@ class GraphContractor
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <class ContainerT>
|
template <class ContainerT> Contractor(int nodes, ContainerT &input_edge_list)
|
||||||
GraphContractor(int nodes, ContainerT &input_edge_list)
|
|
||||||
: GraphContractor(nodes, input_edge_list, {}, {})
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ContainerT>
|
|
||||||
GraphContractor(int nodes,
|
|
||||||
ContainerT &input_edge_list,
|
|
||||||
std::vector<float> &&node_levels_,
|
|
||||||
std::vector<EdgeWeight> &&node_weights_)
|
|
||||||
: node_levels(std::move(node_levels_)), node_weights(std::move(node_weights_))
|
|
||||||
{
|
{
|
||||||
std::vector<ContractorEdge> edges;
|
std::vector<ContractorEdge> edges;
|
||||||
edges.reserve(input_edge_list.size() * 2);
|
edges.reserve(input_edge_list.size() * 2);
|
||||||
@@ -158,11 +169,10 @@ class GraphContractor
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (static_cast<unsigned int>(std::max(diter->weight, 1)) > 24 * 60 * 60 * 10)
|
if (static_cast<unsigned int>(std::max(diter->weight, 1)) > 24 * 60 * 60 * 10)
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write(logWARNING)
|
SimpleLogger().Write(logWARNING)
|
||||||
<< "Edge weight large -> "
|
<< "Edge weight large -> "
|
||||||
<< static_cast<unsigned int>(std::max(diter->weight, 1)) << " : "
|
<< static_cast<unsigned int>(std::max(diter->weight, 1)) << " : "
|
||||||
<< static_cast<unsigned int>(diter->source) << " -> "
|
<< static_cast<unsigned int>(diter->source) << " -> " << static_cast<unsigned int>(diter->target);
|
||||||
<< static_cast<unsigned int>(diter->target);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
edges.emplace_back(diter->source, diter->target,
|
edges.emplace_back(diter->source, diter->target,
|
||||||
@@ -202,7 +212,8 @@ class GraphContractor
|
|||||||
forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
|
forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
|
||||||
forward_edge.data.id = reverse_edge.data.id = id;
|
forward_edge.data.id = reverse_edge.data.id = id;
|
||||||
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
|
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
|
||||||
forward_edge.data.distance = reverse_edge.data.distance = INVALID_EDGE_WEIGHT;
|
forward_edge.data.distance = reverse_edge.data.distance =
|
||||||
|
std::numeric_limits<int>::max();
|
||||||
// remove parallel edges
|
// remove parallel edges
|
||||||
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
|
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
|
||||||
{
|
{
|
||||||
@@ -221,7 +232,7 @@ class GraphContractor
|
|||||||
// merge edges (s,t) and (t,s) into bidirectional edge
|
// merge edges (s,t) and (t,s) into bidirectional edge
|
||||||
if (forward_edge.data.distance == reverse_edge.data.distance)
|
if (forward_edge.data.distance == reverse_edge.data.distance)
|
||||||
{
|
{
|
||||||
if ((int)forward_edge.data.distance != INVALID_EDGE_WEIGHT)
|
if ((int)forward_edge.data.distance != std::numeric_limits<int>::max())
|
||||||
{
|
{
|
||||||
forward_edge.data.backward = true;
|
forward_edge.data.backward = true;
|
||||||
edges[edge++] = forward_edge;
|
edges[edge++] = forward_edge;
|
||||||
@@ -229,54 +240,77 @@ class GraphContractor
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // insert seperate edges
|
{ // insert seperate edges
|
||||||
if (((int)forward_edge.data.distance) != INVALID_EDGE_WEIGHT)
|
if (((int)forward_edge.data.distance) != std::numeric_limits<int>::max())
|
||||||
{
|
{
|
||||||
edges[edge++] = forward_edge;
|
edges[edge++] = forward_edge;
|
||||||
}
|
}
|
||||||
if ((int)reverse_edge.data.distance != INVALID_EDGE_WEIGHT)
|
if ((int)reverse_edge.data.distance != std::numeric_limits<int>::max())
|
||||||
{
|
{
|
||||||
edges[edge++] = reverse_edge;
|
edges[edge++] = reverse_edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
util::SimpleLogger().Write() << "merged " << edges.size() - edge << " edges out of "
|
std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size()
|
||||||
<< edges.size();
|
<< std::endl;
|
||||||
edges.resize(edge);
|
edges.resize(edge);
|
||||||
contractor_graph = std::make_shared<ContractorGraph>(nodes, edges);
|
contractor_graph = std::make_shared<ContractorGraph>(nodes, edges);
|
||||||
edges.clear();
|
edges.clear();
|
||||||
edges.shrink_to_fit();
|
edges.shrink_to_fit();
|
||||||
|
|
||||||
BOOST_ASSERT(0 == edges.capacity());
|
BOOST_ASSERT(0 == edges.capacity());
|
||||||
util::SimpleLogger().Write() << "contractor finished initalization";
|
// unsigned maxdegree = 0;
|
||||||
|
// NodeID highestNode = 0;
|
||||||
|
//
|
||||||
|
// for(unsigned i = 0; i < contractor_graph->GetNumberOfNodes(); ++i) {
|
||||||
|
// unsigned degree = contractor_graph->EndEdges(i) -
|
||||||
|
// contractor_graph->BeginEdges(i);
|
||||||
|
// if(degree > maxdegree) {
|
||||||
|
// maxdegree = degree;
|
||||||
|
// highestNode = i;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// SimpleLogger().Write() << "edges at node with id " << highestNode << " has degree
|
||||||
|
// " << maxdegree;
|
||||||
|
// for(unsigned i = contractor_graph->BeginEdges(highestNode); i <
|
||||||
|
// contractor_graph->EndEdges(highestNode); ++i) {
|
||||||
|
// SimpleLogger().Write() << " ->(" << highestNode << "," <<
|
||||||
|
// contractor_graph->GetTarget(i)
|
||||||
|
// << "); via: " << contractor_graph->GetEdgeData(i).via;
|
||||||
|
// }
|
||||||
|
|
||||||
|
std::cout << "contractor finished initalization" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Run(double core_factor = 1.0)
|
~Contractor() {}
|
||||||
|
|
||||||
|
void Run( double core_factor = 1.0 )
|
||||||
{
|
{
|
||||||
// for the preperation we can use a big grain size, which is much faster (probably cache)
|
// for the preperation we can use a big grain size, which is much faster (probably cache)
|
||||||
const constexpr size_t InitGrainSize = 100000;
|
constexpr size_t InitGrainSize = 100000;
|
||||||
const constexpr size_t PQGrainSize = 100000;
|
constexpr size_t PQGrainSize = 100000;
|
||||||
// auto_partitioner will automatically increase the blocksize if we have
|
// auto_partitioner will automatically increase the blocksize if we have
|
||||||
// a lot of data. It is *important* for the last loop iterations
|
// a lot of data. It is *important* for the last loop iterations
|
||||||
// (which have a very small dataset) that it is devisible.
|
// (which have a very small dataset) that it is devisible.
|
||||||
const constexpr size_t IndependentGrainSize = 1;
|
constexpr size_t IndependentGrainSize = 1;
|
||||||
const constexpr size_t ContractGrainSize = 1;
|
constexpr size_t ContractGrainSize = 1;
|
||||||
const constexpr size_t NeighboursGrainSize = 1;
|
constexpr size_t NeighboursGrainSize = 1;
|
||||||
const constexpr size_t DeleteGrainSize = 1;
|
constexpr size_t DeleteGrainSize = 1;
|
||||||
|
|
||||||
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
||||||
util::Percent p(number_of_nodes);
|
Percent p(number_of_nodes);
|
||||||
|
|
||||||
ThreadDataContainer thread_data_list(number_of_nodes);
|
ThreadDataContainer thread_data_list(number_of_nodes);
|
||||||
|
|
||||||
NodeID number_of_contracted_nodes = 0;
|
NodeID number_of_contracted_nodes = 0;
|
||||||
std::vector<NodeDepth> node_depth;
|
std::vector<RemainingNodeData> remaining_nodes(number_of_nodes);
|
||||||
std::vector<float> node_priorities;
|
std::vector<float> node_priorities(number_of_nodes);
|
||||||
|
std::vector<NodePriorityData> node_data(number_of_nodes);
|
||||||
is_core_node.resize(number_of_nodes, false);
|
is_core_node.resize(number_of_nodes, false);
|
||||||
|
|
||||||
std::vector<RemainingNodeData> remaining_nodes(number_of_nodes);
|
|
||||||
// initialize priorities in parallel
|
// initialize priorities in parallel
|
||||||
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, InitGrainSize),
|
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, InitGrainSize),
|
||||||
[this, &remaining_nodes](const tbb::blocked_range<int> &range)
|
[&remaining_nodes](const tbb::blocked_range<int> &range)
|
||||||
{
|
{
|
||||||
for (int x = range.begin(), end = range.end(); x != end; ++x)
|
for (int x = range.begin(), end = range.end(); x != end; ++x)
|
||||||
{
|
{
|
||||||
@@ -284,49 +318,29 @@ class GraphContractor
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
bool use_cached_node_priorities = !node_levels.empty();
|
std::cout << "initializing elimination PQ ..." << std::flush;
|
||||||
if (use_cached_node_priorities)
|
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, PQGrainSize),
|
||||||
{
|
[this, &node_priorities, &node_data, &thread_data_list](
|
||||||
std::cout << "using cached node priorities ..." << std::flush;
|
const tbb::blocked_range<int> &range)
|
||||||
node_priorities.swap(node_levels);
|
{
|
||||||
std::cout << "ok" << std::endl;
|
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||||
}
|
for (int x = range.begin(), end = range.end(); x != end; ++x)
|
||||||
else
|
|
||||||
{
|
|
||||||
node_depth.resize(number_of_nodes, 0);
|
|
||||||
node_priorities.resize(number_of_nodes);
|
|
||||||
node_levels.resize(number_of_nodes);
|
|
||||||
|
|
||||||
std::cout << "initializing elimination PQ ..." << std::flush;
|
|
||||||
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, PQGrainSize),
|
|
||||||
[this, &node_priorities, &node_depth,
|
|
||||||
&thread_data_list](const tbb::blocked_range<int> &range)
|
|
||||||
{
|
{
|
||||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
node_priorities[x] =
|
||||||
for (int x = range.begin(), end = range.end(); x != end; ++x)
|
this->EvaluateNodePriority(data, &node_data[x], x);
|
||||||
{
|
}
|
||||||
node_priorities[x] =
|
});
|
||||||
this->EvaluateNodePriority(data, node_depth[x], x);
|
std::cout << "ok" << std::endl << "preprocessing " << number_of_nodes << " nodes ..."
|
||||||
}
|
<< std::flush;
|
||||||
});
|
|
||||||
std::cout << "ok" << std::endl;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT(node_priorities.size() == number_of_nodes);
|
|
||||||
|
|
||||||
std::cout << "preprocessing " << number_of_nodes << " nodes ..." << std::flush;
|
|
||||||
|
|
||||||
unsigned current_level = 0;
|
|
||||||
bool flushed_contractor = false;
|
bool flushed_contractor = false;
|
||||||
while (number_of_nodes > 2 &&
|
while (number_of_nodes > 2 && number_of_contracted_nodes < static_cast<NodeID>(number_of_nodes * core_factor) )
|
||||||
number_of_contracted_nodes < static_cast<NodeID>(number_of_nodes * core_factor))
|
|
||||||
{
|
{
|
||||||
if (!flushed_contractor && (number_of_contracted_nodes >
|
if (!flushed_contractor && (number_of_contracted_nodes > static_cast<NodeID>(number_of_nodes * 0.65 * core_factor)))
|
||||||
static_cast<NodeID>(number_of_nodes * 0.65 * core_factor)))
|
|
||||||
{
|
{
|
||||||
util::DeallocatingVector<ContractorEdge>
|
DeallocatingVector<ContractorEdge> new_edge_set; // this one is not explicitely
|
||||||
new_edge_set; // this one is not explicitely
|
// cleared since it goes out of
|
||||||
// cleared since it goes out of
|
// scope anywa
|
||||||
// scope anywa
|
|
||||||
std::cout << " [flush " << number_of_contracted_nodes << " nodes] " << std::flush;
|
std::cout << " [flush " << number_of_contracted_nodes << " nodes] " << std::flush;
|
||||||
|
|
||||||
// Delete old heap data to free memory that we need for the coming operations
|
// Delete old heap data to free memory that we need for the coming operations
|
||||||
@@ -334,56 +348,50 @@ class GraphContractor
|
|||||||
|
|
||||||
// Create new priority array
|
// Create new priority array
|
||||||
std::vector<float> new_node_priority(remaining_nodes.size());
|
std::vector<float> new_node_priority(remaining_nodes.size());
|
||||||
std::vector<EdgeWeight> new_node_weights(remaining_nodes.size());
|
|
||||||
// this map gives the old IDs from the new ones, necessary to get a consistent graph
|
// this map gives the old IDs from the new ones, necessary to get a consistent graph
|
||||||
// at the end of contraction
|
// at the end of contraction
|
||||||
orig_node_id_from_new_node_id_map.resize(remaining_nodes.size());
|
orig_node_id_from_new_node_id_map.resize(remaining_nodes.size());
|
||||||
// this map gives the new IDs from the old ones, necessary to remap targets from the
|
// this map gives the new IDs from the old ones, necessary to remap targets from the
|
||||||
// remaining graph
|
// remaining graph
|
||||||
std::vector<NodeID> new_node_id_from_orig_id_map(number_of_nodes, SPECIAL_NODEID);
|
std::vector<NodeID> new_node_id_from_orig_id_map(number_of_nodes, UINT_MAX);
|
||||||
|
|
||||||
for (const auto new_node_id : util::irange<std::size_t>(0, remaining_nodes.size()))
|
// build forward and backward renumbering map and remap ids in remaining_nodes and
|
||||||
|
// Priorities.
|
||||||
|
for (const auto new_node_id : osrm::irange<std::size_t>(0, remaining_nodes.size()))
|
||||||
{
|
{
|
||||||
auto &node = remaining_nodes[new_node_id];
|
|
||||||
BOOST_ASSERT(node_priorities.size() > node.id);
|
|
||||||
new_node_priority[new_node_id] = node_priorities[node.id];
|
|
||||||
BOOST_ASSERT(node_weights.size() > node.id);
|
|
||||||
new_node_weights[new_node_id] = node_weights[node.id];
|
|
||||||
}
|
|
||||||
|
|
||||||
// build forward and backward renumbering map and remap ids in remaining_nodes
|
|
||||||
for (const auto new_node_id : util::irange<std::size_t>(0, remaining_nodes.size()))
|
|
||||||
{
|
|
||||||
auto &node = remaining_nodes[new_node_id];
|
|
||||||
// create renumbering maps in both directions
|
// create renumbering maps in both directions
|
||||||
orig_node_id_from_new_node_id_map[new_node_id] = node.id;
|
orig_node_id_from_new_node_id_map[new_node_id] = remaining_nodes[new_node_id].id;
|
||||||
new_node_id_from_orig_id_map[node.id] = new_node_id;
|
new_node_id_from_orig_id_map[remaining_nodes[new_node_id].id] = new_node_id;
|
||||||
node.id = new_node_id;
|
new_node_priority[new_node_id] =
|
||||||
|
node_priorities[remaining_nodes[new_node_id].id];
|
||||||
|
remaining_nodes[new_node_id].id = new_node_id;
|
||||||
}
|
}
|
||||||
// walk over all nodes
|
// walk over all nodes
|
||||||
for (const auto source :
|
for (const auto i :
|
||||||
util::irange<NodeID>(0, contractor_graph->GetNumberOfNodes()))
|
osrm::irange<std::size_t>(0, contractor_graph->GetNumberOfNodes()))
|
||||||
{
|
{
|
||||||
|
const NodeID source = i;
|
||||||
for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source))
|
for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source))
|
||||||
{
|
{
|
||||||
ContractorGraph::EdgeData &data =
|
ContractorGraph::EdgeData &data =
|
||||||
contractor_graph->GetEdgeData(current_edge);
|
contractor_graph->GetEdgeData(current_edge);
|
||||||
const NodeID target = contractor_graph->GetTarget(current_edge);
|
const NodeID target = contractor_graph->GetTarget(current_edge);
|
||||||
if (SPECIAL_NODEID == new_node_id_from_orig_id_map[source])
|
if (SPECIAL_NODEID == new_node_id_from_orig_id_map[i])
|
||||||
{
|
{
|
||||||
external_edge_list.push_back({source, target, data});
|
external_edge_list.push_back({source, target, data});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// node is not yet contracted.
|
// node is not yet contracted.
|
||||||
// add (renumbered) outgoing edges to new util::DynamicGraph.
|
// add (renumbered) outgoing edges to new DynamicGraph.
|
||||||
ContractorEdge new_edge = {new_node_id_from_orig_id_map[source],
|
ContractorEdge new_edge = {new_node_id_from_orig_id_map[source],
|
||||||
new_node_id_from_orig_id_map[target], data};
|
new_node_id_from_orig_id_map[target],
|
||||||
|
data};
|
||||||
|
|
||||||
new_edge.data.is_original_via_node_ID = true;
|
new_edge.data.is_original_via_node_ID = true;
|
||||||
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_node_id_from_orig_id_map[source],
|
BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[source],
|
||||||
"new source id not resolveable");
|
"new source id not resolveable");
|
||||||
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_node_id_from_orig_id_map[target],
|
BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[target],
|
||||||
"new target id not resolveable");
|
"new target id not resolveable");
|
||||||
new_edge_set.push_back(new_edge);
|
new_edge_set.push_back(new_edge);
|
||||||
}
|
}
|
||||||
@@ -397,17 +405,13 @@ class GraphContractor
|
|||||||
// Replace old priorities array by new one
|
// Replace old priorities array by new one
|
||||||
node_priorities.swap(new_node_priority);
|
node_priorities.swap(new_node_priority);
|
||||||
// Delete old node_priorities vector
|
// Delete old node_priorities vector
|
||||||
// Due to the scope, these should get cleared automatically? @daniel-j-h do you
|
|
||||||
// agree?
|
|
||||||
new_node_priority.clear();
|
new_node_priority.clear();
|
||||||
new_node_priority.shrink_to_fit();
|
new_node_priority.shrink_to_fit();
|
||||||
|
|
||||||
node_weights.swap(new_node_weights);
|
|
||||||
// old Graph is removed
|
// old Graph is removed
|
||||||
contractor_graph.reset();
|
contractor_graph.reset();
|
||||||
|
|
||||||
// create new graph
|
// create new graph
|
||||||
tbb::parallel_sort(new_edge_set.begin(), new_edge_set.end());
|
std::sort(new_edge_set.begin(), new_edge_set.end());
|
||||||
contractor_graph =
|
contractor_graph =
|
||||||
std::make_shared<ContractorGraph>(remaining_nodes.size(), new_edge_set);
|
std::make_shared<ContractorGraph>(remaining_nodes.size(), new_edge_set);
|
||||||
|
|
||||||
@@ -419,99 +423,58 @@ class GraphContractor
|
|||||||
thread_data_list.number_of_nodes = contractor_graph->GetNumberOfNodes();
|
thread_data_list.number_of_nodes = contractor_graph->GetNumberOfNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
tbb::parallel_for(
|
const int last = (int)remaining_nodes.size();
|
||||||
tbb::blocked_range<std::size_t>(0, remaining_nodes.size(), IndependentGrainSize),
|
tbb::parallel_for(tbb::blocked_range<int>(0, last, IndependentGrainSize),
|
||||||
[this, &node_priorities, &remaining_nodes,
|
[this, &node_priorities, &remaining_nodes, &thread_data_list](
|
||||||
&thread_data_list](const tbb::blocked_range<std::size_t> &range)
|
const tbb::blocked_range<int> &range)
|
||||||
{
|
|
||||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
|
||||||
// determine independent node set
|
|
||||||
for (auto i = range.begin(), end = range.end(); i != end; ++i)
|
|
||||||
{
|
|
||||||
const NodeID node = remaining_nodes[i].id;
|
|
||||||
remaining_nodes[i].is_independent =
|
|
||||||
this->IsNodeIndependent(node_priorities, data, node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// sort all remaining nodes to the beginning of the sequence
|
|
||||||
const auto begin_independent_nodes = stable_partition(
|
|
||||||
remaining_nodes.begin(), remaining_nodes.end(), [](RemainingNodeData node_data)
|
|
||||||
{
|
|
||||||
return !node_data.is_independent;
|
|
||||||
});
|
|
||||||
auto begin_independent_nodes_idx =
|
|
||||||
std::distance(remaining_nodes.begin(), begin_independent_nodes);
|
|
||||||
auto end_independent_nodes_idx = remaining_nodes.size();
|
|
||||||
|
|
||||||
if (!use_cached_node_priorities)
|
|
||||||
{
|
|
||||||
// write out contraction level
|
|
||||||
tbb::parallel_for(
|
|
||||||
tbb::blocked_range<std::size_t>(begin_independent_nodes_idx,
|
|
||||||
end_independent_nodes_idx, ContractGrainSize),
|
|
||||||
[this, remaining_nodes, flushed_contractor,
|
|
||||||
current_level](const tbb::blocked_range<std::size_t> &range)
|
|
||||||
{
|
|
||||||
if (flushed_contractor)
|
|
||||||
{
|
|
||||||
for (int position = range.begin(), end = range.end(); position != end;
|
|
||||||
++position)
|
|
||||||
{
|
|
||||||
const NodeID x = remaining_nodes[position].id;
|
|
||||||
node_levels[orig_node_id_from_new_node_id_map[x]] = current_level;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int position = range.begin(), end = range.end(); position != end;
|
|
||||||
++position)
|
|
||||||
{
|
|
||||||
const NodeID x = remaining_nodes[position].id;
|
|
||||||
node_levels[x] = current_level;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// contract independent nodes
|
|
||||||
tbb::parallel_for(tbb::blocked_range<std::size_t>(begin_independent_nodes_idx,
|
|
||||||
end_independent_nodes_idx,
|
|
||||||
ContractGrainSize),
|
|
||||||
[this, &remaining_nodes,
|
|
||||||
&thread_data_list](const tbb::blocked_range<std::size_t> &range)
|
|
||||||
{
|
{
|
||||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||||
for (int position = range.begin(), end = range.end();
|
// determine independent node set
|
||||||
position != end; ++position)
|
for (int i = range.begin(), end = range.end(); i != end; ++i)
|
||||||
{
|
{
|
||||||
const NodeID x = remaining_nodes[position].id;
|
const NodeID node = remaining_nodes[i].id;
|
||||||
this->ContractNode<false>(data, x);
|
remaining_nodes[i].is_independent =
|
||||||
|
this->IsNodeIndependent(node_priorities, data, node);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const auto first = stable_partition(remaining_nodes.begin(), remaining_nodes.end(),
|
||||||
|
[](RemainingNodeData node_data)
|
||||||
|
{
|
||||||
|
return !node_data.is_independent;
|
||||||
|
});
|
||||||
|
const int first_independent_node = static_cast<int>(first - remaining_nodes.begin());
|
||||||
|
|
||||||
|
// contract independent nodes
|
||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<int>(begin_independent_nodes_idx, end_independent_nodes_idx,
|
tbb::blocked_range<int>(first_independent_node, last, ContractGrainSize),
|
||||||
DeleteGrainSize),
|
|
||||||
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
|
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
|
||||||
{
|
{
|
||||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||||
for (int position = range.begin(), end = range.end(); position != end;
|
for (int position = range.begin(), end = range.end(); position != end; ++position)
|
||||||
++position)
|
|
||||||
{
|
{
|
||||||
const NodeID x = remaining_nodes[position].id;
|
const NodeID x = remaining_nodes[position].id;
|
||||||
this->DeleteIncomingEdges(data, x);
|
this->ContractNode<false>(data, x);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// make sure we really sort each block
|
// make sure we really sort each block
|
||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
thread_data_list.data.range(),
|
thread_data_list.data.range(),
|
||||||
[&](const ThreadDataContainer::EnumerableThreadData::range_type &range)
|
[&](const ThreadDataContainer::EnumerableThreadData::range_type &range)
|
||||||
{
|
{
|
||||||
for (auto &data : range)
|
for (auto &data : range)
|
||||||
tbb::parallel_sort(data->inserted_edges.begin(),
|
std::sort(data->inserted_edges.begin(), data->inserted_edges.end());
|
||||||
data->inserted_edges.end());
|
});
|
||||||
|
tbb::parallel_for(
|
||||||
|
tbb::blocked_range<int>(first_independent_node, last, DeleteGrainSize),
|
||||||
|
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
|
||||||
|
{
|
||||||
|
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||||
|
for (int position = range.begin(), end = range.end(); position != end; ++position)
|
||||||
|
{
|
||||||
|
const NodeID x = remaining_nodes[position].id;
|
||||||
|
this->DeleteIncomingEdges(data, x);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// insert new edges
|
// insert new edges
|
||||||
@@ -539,58 +502,58 @@ class GraphContractor
|
|||||||
data->inserted_edges.clear();
|
data->inserted_edges.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!use_cached_node_priorities)
|
tbb::parallel_for(
|
||||||
{
|
tbb::blocked_range<int>(first_independent_node, last, NeighboursGrainSize),
|
||||||
tbb::parallel_for(
|
[this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list](
|
||||||
tbb::blocked_range<int>(begin_independent_nodes_idx, end_independent_nodes_idx,
|
const tbb::blocked_range<int> &range)
|
||||||
NeighboursGrainSize),
|
{
|
||||||
[this, &node_priorities, &remaining_nodes, &node_depth,
|
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||||
&thread_data_list](const tbb::blocked_range<int> &range)
|
for (int position = range.begin(), end = range.end(); position != end; ++position)
|
||||||
{
|
{
|
||||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
NodeID x = remaining_nodes[position].id;
|
||||||
for (int position = range.begin(), end = range.end(); position != end;
|
this->UpdateNodeNeighbours(node_priorities, node_data, data, x);
|
||||||
++position)
|
}
|
||||||
{
|
});
|
||||||
NodeID x = remaining_nodes[position].id;
|
|
||||||
this->UpdateNodeNeighbours(node_priorities, node_depth, data, x);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove contracted nodes from the pool
|
// remove contracted nodes from the pool
|
||||||
number_of_contracted_nodes += end_independent_nodes_idx - begin_independent_nodes_idx;
|
number_of_contracted_nodes += last - first_independent_node;
|
||||||
remaining_nodes.resize(begin_independent_nodes_idx);
|
remaining_nodes.resize(first_independent_node);
|
||||||
|
remaining_nodes.shrink_to_fit();
|
||||||
|
// unsigned maxdegree = 0;
|
||||||
|
// unsigned avgdegree = 0;
|
||||||
|
// unsigned mindegree = UINT_MAX;
|
||||||
|
// unsigned quaddegree = 0;
|
||||||
|
//
|
||||||
|
// for(unsigned i = 0; i < remaining_nodes.size(); ++i) {
|
||||||
|
// unsigned degree = contractor_graph->EndEdges(remaining_nodes[i].id)
|
||||||
|
// -
|
||||||
|
// contractor_graph->BeginEdges(remaining_nodes[i].first);
|
||||||
|
// if(degree > maxdegree)
|
||||||
|
// maxdegree = degree;
|
||||||
|
// if(degree < mindegree)
|
||||||
|
// mindegree = degree;
|
||||||
|
//
|
||||||
|
// avgdegree += degree;
|
||||||
|
// quaddegree += (degree*degree);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// avgdegree /= std::max((unsigned)1,(unsigned)remaining_nodes.size() );
|
||||||
|
// quaddegree /= std::max((unsigned)1,(unsigned)remaining_nodes.size() );
|
||||||
|
//
|
||||||
|
// SimpleLogger().Write() << "rest: " << remaining_nodes.size() << ", max: "
|
||||||
|
// << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ",
|
||||||
|
// quad: " << quaddegree;
|
||||||
|
|
||||||
p.printStatus(number_of_contracted_nodes);
|
p.printStatus(number_of_contracted_nodes);
|
||||||
++current_level;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remaining_nodes.size() > 2)
|
if (remaining_nodes.size() > 2)
|
||||||
{
|
{
|
||||||
if (orig_node_id_from_new_node_id_map.size() > 0)
|
// TODO: for small cores a sorted array of core ids might also work good
|
||||||
|
for (const auto& node : remaining_nodes)
|
||||||
{
|
{
|
||||||
tbb::parallel_for(tbb::blocked_range<int>(0, remaining_nodes.size(), InitGrainSize),
|
auto orig_id = orig_node_id_from_new_node_id_map[node.id];
|
||||||
[this, &remaining_nodes](const tbb::blocked_range<int> &range)
|
is_core_node[orig_id] = true;
|
||||||
{
|
|
||||||
for (int x = range.begin(), end = range.end(); x != end; ++x)
|
|
||||||
{
|
|
||||||
const auto orig_id = remaining_nodes[x].id;
|
|
||||||
is_core_node[orig_node_id_from_new_node_id_map[orig_id]] =
|
|
||||||
true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tbb::parallel_for(tbb::blocked_range<int>(0, remaining_nodes.size(), InitGrainSize),
|
|
||||||
[this, &remaining_nodes](const tbb::blocked_range<int> &range)
|
|
||||||
{
|
|
||||||
for (int x = range.begin(), end = range.end(); x != end; ++x)
|
|
||||||
{
|
|
||||||
const auto orig_id = remaining_nodes[x].id;
|
|
||||||
is_core_node[orig_id] = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -600,9 +563,7 @@ class GraphContractor
|
|||||||
is_core_node.clear();
|
is_core_node.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "[core] " << remaining_nodes.size() << " nodes "
|
SimpleLogger().Write() << "[core] " << remaining_nodes.size() << " nodes " << contractor_graph->GetNumberOfEdges() << " edges." << std::endl;
|
||||||
<< contractor_graph->GetNumberOfEdges() << " edges."
|
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
thread_data_list.data.clear();
|
thread_data_list.data.clear();
|
||||||
}
|
}
|
||||||
@@ -612,20 +573,15 @@ class GraphContractor
|
|||||||
out_is_core_node.swap(is_core_node);
|
out_is_core_node.swap(is_core_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void GetNodeLevels(std::vector<float> &out_node_levels)
|
template <class Edge> inline void GetEdges(DeallocatingVector<Edge> &edges)
|
||||||
{
|
{
|
||||||
out_node_levels.swap(node_levels);
|
Percent p(contractor_graph->GetNumberOfNodes());
|
||||||
}
|
SimpleLogger().Write() << "Getting edges of minimized graph";
|
||||||
|
|
||||||
template <class Edge> inline void GetEdges(util::DeallocatingVector<Edge> &edges)
|
|
||||||
{
|
|
||||||
util::Percent p(contractor_graph->GetNumberOfNodes());
|
|
||||||
util::SimpleLogger().Write() << "Getting edges of minimized graph";
|
|
||||||
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
||||||
if (contractor_graph->GetNumberOfNodes())
|
if (contractor_graph->GetNumberOfNodes())
|
||||||
{
|
{
|
||||||
Edge new_edge;
|
Edge new_edge;
|
||||||
for (const auto node : util::irange(0u, number_of_nodes))
|
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||||
{
|
{
|
||||||
p.printStatus(node);
|
p.printStatus(node);
|
||||||
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
|
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
|
||||||
@@ -642,8 +598,8 @@ class GraphContractor
|
|||||||
new_edge.source = node;
|
new_edge.source = node;
|
||||||
new_edge.target = target;
|
new_edge.target = target;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.source, "Source id invalid");
|
BOOST_ASSERT_MSG(UINT_MAX != new_edge.source, "Source id invalid");
|
||||||
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
|
BOOST_ASSERT_MSG(UINT_MAX != new_edge.target, "Target id invalid");
|
||||||
new_edge.data.distance = data.distance;
|
new_edge.data.distance = data.distance;
|
||||||
new_edge.data.shortcut = data.shortcut;
|
new_edge.data.shortcut = data.shortcut;
|
||||||
if (!data.is_original_via_node_ID && !orig_node_id_from_new_node_id_map.empty())
|
if (!data.is_original_via_node_ID && !orig_node_id_from_new_node_id_map.empty())
|
||||||
@@ -674,55 +630,23 @@ class GraphContractor
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void RelaxNode(const NodeID node,
|
|
||||||
const NodeID forbidden_node,
|
|
||||||
const int distance,
|
|
||||||
ContractorHeap &heap)
|
|
||||||
{
|
|
||||||
const short current_hop = heap.GetData(node).hop + 1;
|
|
||||||
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const ContractorEdgeData &data = contractor_graph->GetEdgeData(edge);
|
|
||||||
if (!data.forward)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const NodeID to = contractor_graph->GetTarget(edge);
|
|
||||||
if (forbidden_node == to)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const int to_distance = distance + data.distance;
|
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
|
||||||
if (!heap.WasInserted(to))
|
|
||||||
{
|
|
||||||
heap.Insert(to, to_distance, ContractorHeapData{current_hop, false});
|
|
||||||
}
|
|
||||||
// Found a shorter Path -> Update distance
|
|
||||||
else if (to_distance < heap.GetKey(to))
|
|
||||||
{
|
|
||||||
heap.DecreaseKey(to, to_distance);
|
|
||||||
heap.GetData(to).hop = current_hop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Dijkstra(const int max_distance,
|
inline void Dijkstra(const int max_distance,
|
||||||
const unsigned number_of_targets,
|
const unsigned number_of_targets,
|
||||||
const int maxNodes,
|
const int maxNodes,
|
||||||
ContractorThreadData &data,
|
ContractorThreadData *const data,
|
||||||
const NodeID middleNode)
|
const NodeID middleNode)
|
||||||
{
|
{
|
||||||
|
|
||||||
ContractorHeap &heap = data.heap;
|
ContractorHeap &heap = data->heap;
|
||||||
|
|
||||||
int nodes = 0;
|
int nodes = 0;
|
||||||
unsigned number_of_targets_found = 0;
|
unsigned number_of_targets_found = 0;
|
||||||
while (!heap.Empty())
|
while (!heap.Empty())
|
||||||
{
|
{
|
||||||
const NodeID node = heap.DeleteMin();
|
const NodeID node = heap.DeleteMin();
|
||||||
const auto distance = heap.GetKey(node);
|
const int distance = heap.GetKey(node);
|
||||||
|
const short current_hop = heap.GetData(node).hop + 1;
|
||||||
|
|
||||||
if (++nodes > maxNodes)
|
if (++nodes > maxNodes)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -742,12 +666,38 @@ class GraphContractor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RelaxNode(node, middleNode, distance, heap);
|
// iterate over all edges of node
|
||||||
|
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
|
||||||
|
{
|
||||||
|
const ContractorEdgeData &data = contractor_graph->GetEdgeData(edge);
|
||||||
|
if (!data.forward)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const NodeID to = contractor_graph->GetTarget(edge);
|
||||||
|
if (middleNode == to)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const int to_distance = distance + data.distance;
|
||||||
|
|
||||||
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
|
if (!heap.WasInserted(to))
|
||||||
|
{
|
||||||
|
heap.Insert(to, to_distance, ContractorHeapData(current_hop, false));
|
||||||
|
}
|
||||||
|
// Found a shorter Path -> Update distance
|
||||||
|
else if (to_distance < heap.GetKey(to))
|
||||||
|
{
|
||||||
|
heap.DecreaseKey(to, to_distance);
|
||||||
|
heap.GetData(to).hop = current_hop;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float EvaluateNodePriority(ContractorThreadData *const data,
|
inline float EvaluateNodePriority(ContractorThreadData *const data,
|
||||||
const NodeDepth node_depth,
|
NodePriorityData *const node_data,
|
||||||
const NodeID node)
|
const NodeID node)
|
||||||
{
|
{
|
||||||
ContractionStats stats;
|
ContractionStats stats;
|
||||||
@@ -759,14 +709,14 @@ class GraphContractor
|
|||||||
float result;
|
float result;
|
||||||
if (0 == (stats.edges_deleted_count * stats.original_edges_deleted_count))
|
if (0 == (stats.edges_deleted_count * stats.original_edges_deleted_count))
|
||||||
{
|
{
|
||||||
result = 1.f * node_depth;
|
result = 1.f * node_data->depth;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = 2.f * (((float)stats.edges_added_count) / stats.edges_deleted_count) +
|
result = 2.f * (((float)stats.edges_added_count) / stats.edges_deleted_count) +
|
||||||
4.f * (((float)stats.original_edges_added_count) /
|
4.f * (((float)stats.original_edges_added_count) /
|
||||||
stats.original_edges_deleted_count) +
|
stats.original_edges_deleted_count) +
|
||||||
1.f * node_depth;
|
1.f * node_data->depth;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(result >= 0);
|
BOOST_ASSERT(result >= 0);
|
||||||
return result;
|
return result;
|
||||||
@@ -777,21 +727,13 @@ class GraphContractor
|
|||||||
ContractNode(ContractorThreadData *data, const NodeID node, ContractionStats *stats = nullptr)
|
ContractNode(ContractorThreadData *data, const NodeID node, ContractionStats *stats = nullptr)
|
||||||
{
|
{
|
||||||
ContractorHeap &heap = data->heap;
|
ContractorHeap &heap = data->heap;
|
||||||
std::size_t inserted_edges_size = data->inserted_edges.size();
|
int inserted_edges_size = data->inserted_edges.size();
|
||||||
std::vector<ContractorEdge> &inserted_edges = data->inserted_edges;
|
std::vector<ContractorEdge> &inserted_edges = data->inserted_edges;
|
||||||
const constexpr bool SHORTCUT_ARC = true;
|
|
||||||
const constexpr bool FORWARD_DIRECTION_ENABLED = true;
|
|
||||||
const constexpr bool FORWARD_DIRECTION_DISABLED = false;
|
|
||||||
const constexpr bool REVERSE_DIRECTION_ENABLED = true;
|
|
||||||
const constexpr bool REVERSE_DIRECTION_DISABLED = false;
|
|
||||||
|
|
||||||
for (auto in_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
for (auto in_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
const ContractorEdgeData &in_data = contractor_graph->GetEdgeData(in_edge);
|
const ContractorEdgeData &in_data = contractor_graph->GetEdgeData(in_edge);
|
||||||
const NodeID source = contractor_graph->GetTarget(in_edge);
|
const NodeID source = contractor_graph->GetTarget(in_edge);
|
||||||
if (source == node)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (RUNSIMULATION)
|
if (RUNSIMULATION)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(stats != nullptr);
|
BOOST_ASSERT(stats != nullptr);
|
||||||
@@ -804,7 +746,7 @@ class GraphContractor
|
|||||||
}
|
}
|
||||||
|
|
||||||
heap.Clear();
|
heap.Clear();
|
||||||
heap.Insert(source, 0, ContractorHeapData{});
|
heap.Insert(source, 0, ContractorHeapData());
|
||||||
int max_distance = 0;
|
int max_distance = 0;
|
||||||
unsigned number_of_targets = 0;
|
unsigned number_of_targets = 0;
|
||||||
|
|
||||||
@@ -816,64 +758,22 @@ class GraphContractor
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const NodeID target = contractor_graph->GetTarget(out_edge);
|
const NodeID target = contractor_graph->GetTarget(out_edge);
|
||||||
if (node == target)
|
const int path_distance = in_data.distance + out_data.distance;
|
||||||
continue;
|
|
||||||
|
|
||||||
const EdgeWeight path_distance = in_data.distance + out_data.distance;
|
|
||||||
if (target == source)
|
|
||||||
{
|
|
||||||
if (path_distance < node_weights[node])
|
|
||||||
{
|
|
||||||
if (RUNSIMULATION)
|
|
||||||
{
|
|
||||||
// make sure to prune better, but keep inserting this loop if it should
|
|
||||||
// still be the best
|
|
||||||
// CAREFUL: This only works due to the independent node-setting. This
|
|
||||||
// guarantees that source is not connected to another node that is
|
|
||||||
// contracted
|
|
||||||
node_weights[source] = path_distance + 1;
|
|
||||||
BOOST_ASSERT(stats != nullptr);
|
|
||||||
stats->edges_added_count += 2;
|
|
||||||
stats->original_edges_added_count +=
|
|
||||||
2 * (out_data.originalEdges + in_data.originalEdges);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// CAREFUL: This only works due to the independent node-setting. This
|
|
||||||
// guarantees that source is not connected to another node that is
|
|
||||||
// contracted
|
|
||||||
node_weights[source] = path_distance; // make sure to prune better
|
|
||||||
inserted_edges.emplace_back(
|
|
||||||
source, target, path_distance,
|
|
||||||
out_data.originalEdges + in_data.originalEdges, node, SHORTCUT_ARC,
|
|
||||||
FORWARD_DIRECTION_ENABLED, REVERSE_DIRECTION_DISABLED);
|
|
||||||
|
|
||||||
inserted_edges.emplace_back(
|
|
||||||
target, source, path_distance,
|
|
||||||
out_data.originalEdges + in_data.originalEdges, node, SHORTCUT_ARC,
|
|
||||||
FORWARD_DIRECTION_DISABLED, REVERSE_DIRECTION_ENABLED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
max_distance = std::max(max_distance, path_distance);
|
max_distance = std::max(max_distance, path_distance);
|
||||||
if (!heap.WasInserted(target))
|
if (!heap.WasInserted(target))
|
||||||
{
|
{
|
||||||
heap.Insert(target, INVALID_EDGE_WEIGHT, ContractorHeapData{0, true});
|
heap.Insert(target, INT_MAX, ContractorHeapData(0, true));
|
||||||
++number_of_targets;
|
++number_of_targets;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RUNSIMULATION)
|
if (RUNSIMULATION)
|
||||||
{
|
{
|
||||||
const int constexpr SIMULATION_SEARCH_SPACE_SIZE = 1000;
|
Dijkstra(max_distance, number_of_targets, 1000, data, node);
|
||||||
Dijkstra(max_distance, number_of_targets, SIMULATION_SEARCH_SPACE_SIZE, *data,
|
|
||||||
node);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const int constexpr FULL_SEARCH_SPACE_SIZE = 2000;
|
Dijkstra(max_distance, number_of_targets, 2000, data, node);
|
||||||
Dijkstra(max_distance, number_of_targets, FULL_SEARCH_SPACE_SIZE, *data, node);
|
|
||||||
}
|
}
|
||||||
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
@@ -883,8 +783,6 @@ class GraphContractor
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const NodeID target = contractor_graph->GetTarget(out_edge);
|
const NodeID target = contractor_graph->GetTarget(out_edge);
|
||||||
if (target == node)
|
|
||||||
continue;
|
|
||||||
const int path_distance = in_data.distance + out_data.distance;
|
const int path_distance = in_data.distance + out_data.distance;
|
||||||
const int distance = heap.GetKey(target);
|
const int distance = heap.GetKey(target);
|
||||||
if (path_distance < distance)
|
if (path_distance < distance)
|
||||||
@@ -900,26 +798,22 @@ class GraphContractor
|
|||||||
{
|
{
|
||||||
inserted_edges.emplace_back(source, target, path_distance,
|
inserted_edges.emplace_back(source, target, path_distance,
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
out_data.originalEdges + in_data.originalEdges,
|
||||||
node, SHORTCUT_ARC, FORWARD_DIRECTION_ENABLED,
|
node, true, true, false);
|
||||||
REVERSE_DIRECTION_DISABLED);
|
|
||||||
|
|
||||||
inserted_edges.emplace_back(target, source, path_distance,
|
inserted_edges.emplace_back(target, source, path_distance,
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
out_data.originalEdges + in_data.originalEdges,
|
||||||
node, SHORTCUT_ARC, FORWARD_DIRECTION_DISABLED,
|
node, true, false, true);
|
||||||
REVERSE_DIRECTION_ENABLED);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check For One-Way Streets to decide on the creation of self-loops
|
|
||||||
|
|
||||||
if (!RUNSIMULATION)
|
if (!RUNSIMULATION)
|
||||||
{
|
{
|
||||||
std::size_t iend = inserted_edges.size();
|
int iend = inserted_edges.size();
|
||||||
for (std::size_t i = inserted_edges_size; i < iend; ++i)
|
for (int i = inserted_edges_size; i < iend; ++i)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (std::size_t other = i + 1; other < iend; ++other)
|
for (int other = i + 1; other < iend; ++other)
|
||||||
{
|
{
|
||||||
if (inserted_edges[other].source != inserted_edges[i].source)
|
if (inserted_edges[other].source != inserted_edges[i].source)
|
||||||
{
|
{
|
||||||
@@ -970,14 +864,14 @@ class GraphContractor
|
|||||||
std::sort(neighbours.begin(), neighbours.end());
|
std::sort(neighbours.begin(), neighbours.end());
|
||||||
neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
|
neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
|
||||||
|
|
||||||
for (const auto i : util::irange<std::size_t>(0, neighbours.size()))
|
for (const auto i : osrm::irange<std::size_t>(0, neighbours.size()))
|
||||||
{
|
{
|
||||||
contractor_graph->DeleteEdgesTo(neighbours[i], node);
|
contractor_graph->DeleteEdgesTo(neighbours[i], node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool UpdateNodeNeighbours(std::vector<float> &priorities,
|
inline bool UpdateNodeNeighbours(std::vector<float> &priorities,
|
||||||
std::vector<NodeDepth> &node_depth,
|
std::vector<NodePriorityData> &node_data,
|
||||||
ContractorThreadData *const data,
|
ContractorThreadData *const data,
|
||||||
const NodeID node)
|
const NodeID node)
|
||||||
{
|
{
|
||||||
@@ -993,7 +887,7 @@ class GraphContractor
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
neighbours.push_back(u);
|
neighbours.push_back(u);
|
||||||
node_depth[u] = std::max(node_depth[node] + 1, node_depth[u]);
|
node_data[u].depth = (std::max)(node_data[node].depth + 1, node_data[u].depth);
|
||||||
}
|
}
|
||||||
// eliminate duplicate entries ( forward + backward edges )
|
// eliminate duplicate entries ( forward + backward edges )
|
||||||
std::sort(neighbours.begin(), neighbours.end());
|
std::sort(neighbours.begin(), neighbours.end());
|
||||||
@@ -1002,7 +896,7 @@ class GraphContractor
|
|||||||
// re-evaluate priorities of neighboring nodes
|
// re-evaluate priorities of neighboring nodes
|
||||||
for (const NodeID u : neighbours)
|
for (const NodeID u : neighbours)
|
||||||
{
|
{
|
||||||
priorities[u] = EvaluateNodePriority(data, node_depth[u], u);
|
priorities[u] = EvaluateNodePriority(data, &(node_data)[u], u);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1088,18 +982,8 @@ class GraphContractor
|
|||||||
std::shared_ptr<ContractorGraph> contractor_graph;
|
std::shared_ptr<ContractorGraph> contractor_graph;
|
||||||
stxxl::vector<QueryEdge> external_edge_list;
|
stxxl::vector<QueryEdge> external_edge_list;
|
||||||
std::vector<NodeID> orig_node_id_from_new_node_id_map;
|
std::vector<NodeID> orig_node_id_from_new_node_id_map;
|
||||||
std::vector<float> node_levels;
|
|
||||||
|
|
||||||
// A list of weights for every node in the graph.
|
|
||||||
// The weight represents the cost for a u-turn on the segment in the base-graph in addition to
|
|
||||||
// its traversal.
|
|
||||||
// During contraction, self-loops are checked against this node weight to ensure that necessary
|
|
||||||
// self-loops are added.
|
|
||||||
std::vector<EdgeWeight> node_weights;
|
|
||||||
std::vector<bool> is_core_node;
|
std::vector<bool> is_core_node;
|
||||||
util::XORFastHash<> fast_hash;
|
XORFastHash fast_hash;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CONTRACTOR_HPP
|
#endif // CONTRACTOR_HPP
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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")(
|
||||||
|
"core,k", boost::program_options::value<double>(&contractor_config.core_factor)
|
||||||
|
->default_value(1.0),"Percentage of the graph (in vertices) to contract [0.1]");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 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.core_output_path = contractor_config.osrm_input_path.string() + ".core";
|
||||||
|
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";
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
@@ -32,59 +32,44 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace osrm
|
enum class return_code : unsigned
|
||||||
{
|
|
||||||
namespace contractor
|
|
||||||
{
|
{
|
||||||
|
ok,
|
||||||
|
fail,
|
||||||
|
exit
|
||||||
|
};
|
||||||
|
|
||||||
struct ContractorConfig
|
struct ContractorConfig
|
||||||
{
|
{
|
||||||
ContractorConfig() : requested_num_threads(0) {}
|
ContractorConfig() noexcept : requested_num_threads(0) {}
|
||||||
|
|
||||||
// Infer the output names from the path of the .osrm file
|
|
||||||
void UseDefaultOutputNames()
|
|
||||||
{
|
|
||||||
level_output_path = osrm_input_path.string() + ".level";
|
|
||||||
core_output_path = osrm_input_path.string() + ".core";
|
|
||||||
graph_output_path = osrm_input_path.string() + ".hsgr";
|
|
||||||
edge_based_graph_path = osrm_input_path.string() + ".ebg";
|
|
||||||
edge_segment_lookup_path = osrm_input_path.string() + ".edge_segment_lookup";
|
|
||||||
edge_penalty_path = osrm_input_path.string() + ".edge_penalties";
|
|
||||||
node_based_graph_path = osrm_input_path.string() + ".nodes";
|
|
||||||
geometry_path = osrm_input_path.string() + ".geometry";
|
|
||||||
rtree_leaf_path = osrm_input_path.string() + ".fileIndex";
|
|
||||||
datasource_names_path = osrm_input_path.string() + ".datasource_names";
|
|
||||||
datasource_indexes_path = osrm_input_path.string() + ".datasource_indexes";
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::filesystem::path config_file_path;
|
boost::filesystem::path config_file_path;
|
||||||
boost::filesystem::path osrm_input_path;
|
boost::filesystem::path osrm_input_path;
|
||||||
|
boost::filesystem::path restrictions_path;
|
||||||
|
boost::filesystem::path profile_path;
|
||||||
|
|
||||||
std::string level_output_path;
|
std::string node_output_path;
|
||||||
std::string core_output_path;
|
std::string core_output_path;
|
||||||
|
std::string edge_output_path;
|
||||||
|
std::string geometry_output_path;
|
||||||
std::string graph_output_path;
|
std::string graph_output_path;
|
||||||
std::string edge_based_graph_path;
|
std::string rtree_nodes_output_path;
|
||||||
|
std::string rtree_leafs_output_path;
|
||||||
std::string edge_segment_lookup_path;
|
|
||||||
std::string edge_penalty_path;
|
|
||||||
std::string node_based_graph_path;
|
|
||||||
std::string geometry_path;
|
|
||||||
std::string rtree_leaf_path;
|
|
||||||
bool use_cached_priority;
|
|
||||||
|
|
||||||
unsigned requested_num_threads;
|
unsigned requested_num_threads;
|
||||||
|
|
||||||
// A percentage of vertices that will be contracted for the hierarchy.
|
//A percentage of vertices that will be contracted for the hierarchy.
|
||||||
// Offers a trade-off between preprocessing and query time.
|
//Offers a trade-off between preprocessing and query time.
|
||||||
// The remaining vertices form the core of the hierarchy
|
//The remaining vertices form the core of the hierarchy
|
||||||
//(e.g. 0.8 contracts 80 percent of the hierarchy, leaving a core of 20%)
|
//(e.g. 0.8 contracts 80 percent of the hierarchy, leaving a core of 20%)
|
||||||
double core_factor;
|
double core_factor;
|
||||||
|
|
||||||
std::vector<std::string> segment_speed_lookup_paths;
|
|
||||||
std::string datasource_indexes_path;
|
|
||||||
std::string datasource_names_path;
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
struct ContractorOptions
|
||||||
|
{
|
||||||
|
static return_code ParseArguments(int argc, char *argv[], ContractorConfig &extractor_config);
|
||||||
|
|
||||||
|
static void GenerateOutputFilesNames(ContractorConfig &extractor_config);
|
||||||
|
};
|
||||||
|
|
||||||
#endif // EXTRACTOR_OPTIONS_HPP
|
#endif // EXTRACTOR_OPTIONS_HPP
|
||||||
@@ -0,0 +1,562 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 "../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,
|
||||||
|
const CompressedEdgeContainer &compressed_edge_container,
|
||||||
|
const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
|
const std::unordered_set<NodeID> &traffic_lights,
|
||||||
|
std::shared_ptr<const RestrictionMap> restriction_map,
|
||||||
|
const std::vector<QueryNode> &node_info_list,
|
||||||
|
SpeedProfileProperties speed_profile)
|
||||||
|
: m_max_edge_id(0), m_node_info_list(node_info_list), m_node_based_graph(std::move(node_based_graph)),
|
||||||
|
m_restriction_map(std::move(restriction_map)), m_barrier_nodes(barrier_nodes),
|
||||||
|
m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container),
|
||||||
|
speed_profile(std::move(speed_profile))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned EdgeBasedGraphFactory::GetHighestEdgeID()
|
||||||
|
{
|
||||||
|
return m_max_edge_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
|
||||||
|
const NodeID node_v)
|
||||||
|
{
|
||||||
|
// 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.edge_id == SPECIAL_NODEID &&
|
||||||
|
reverse_data.edge_id == SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(m_compressed_edge_container.HasEntryForID(edge_id_1) ==
|
||||||
|
m_compressed_edge_container.HasEntryForID(edge_id_2));
|
||||||
|
if (m_compressed_edge_container.HasEntryForID(edge_id_1))
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(m_compressed_edge_container.HasEntryForID(edge_id_2));
|
||||||
|
|
||||||
|
// reconstruct geometry and put in each individual edge with its offset
|
||||||
|
const auto& forward_geometry = m_compressed_edge_container.GetBucketReference(edge_id_1);
|
||||||
|
const auto& reverse_geometry = m_compressed_edge_container.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;
|
||||||
|
|
||||||
|
// 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.edge_id, reverse_data.edge_id,
|
||||||
|
current_edge_source_coordinate_id, current_edge_target_coordinate_id,
|
||||||
|
forward_data.name_id, forward_geometry[i].second,
|
||||||
|
reverse_geometry[geometry_size - 1 - i].second, forward_dist_prefix_sum[i],
|
||||||
|
reverse_dist_prefix_sum[i], m_compressed_edge_container.GetPositionForID(edge_id_1),
|
||||||
|
INVALID_COMPONENTID, 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_compressed_edge_container.HasEntryForID(edge_id_2));
|
||||||
|
|
||||||
|
if (forward_data.edge_id != SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(!forward_data.reversed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(forward_data.reversed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reverse_data.edge_id != SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(!reverse_data.reversed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(reverse_data.reversed);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(forward_data.edge_id != SPECIAL_NODEID ||
|
||||||
|
reverse_data.edge_id != SPECIAL_NODEID);
|
||||||
|
|
||||||
|
m_edge_based_node_list.emplace_back(
|
||||||
|
forward_data.edge_id, reverse_data.edge_id, node_u, node_v,
|
||||||
|
forward_data.name_id, forward_data.distance, reverse_data.distance, 0, 0, SPECIAL_EDGEID,
|
||||||
|
INVALID_COMPONENTID, 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,
|
||||||
|
lua_State *lua_state)
|
||||||
|
{
|
||||||
|
TIMER_START(renumber);
|
||||||
|
m_max_edge_id = RenumberEdges() - 1;
|
||||||
|
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);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Timing statistics for edge-expanded graph:";
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Renumbers all _forward_ edges and sets the edge_id.
|
||||||
|
/// A specific numbering is not important. Any unique ID will do.
|
||||||
|
/// Returns the number of edge based nodes.
|
||||||
|
unsigned 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);
|
||||||
|
|
||||||
|
// only number incoming edges
|
||||||
|
if (edge_data.reversed)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges());
|
||||||
|
edge_data.edge_id = numbered_edges_count;
|
||||||
|
++numbered_edges_count;
|
||||||
|
|
||||||
|
BOOST_ASSERT(SPECIAL_NODEID != edge_data.edge_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return numbered_edges_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates the nodes in the edge expanded graph from edges in the node-based graph.
|
||||||
|
void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
// if we found a non-forward edge reverse and try again
|
||||||
|
if (edge_data.edge_id == SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
InsertEdgeBasedNode(node_v, node_u);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InsertEdgeBasedNode(node_u, node_v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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).reversed)
|
||||||
|
{
|
||||||
|
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).reversed)
|
||||||
|
{
|
||||||
|
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.edge_id != edge_data2.edge_id);
|
||||||
|
BOOST_ASSERT(!edge_data1.reversed);
|
||||||
|
BOOST_ASSERT(!edge_data2.reversed);
|
||||||
|
|
||||||
|
// 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_compressed_edge_container.HasEntryForID(e1)
|
||||||
|
? m_compressed_edge_container.GetLastEdgeSourceID(e1)
|
||||||
|
: node_u)];
|
||||||
|
|
||||||
|
// unpack first node of second segment if packed
|
||||||
|
const auto third_coordinate =
|
||||||
|
m_node_info_list[(m_compressed_edge_container.HasEntryForID(e2)
|
||||||
|
? m_compressed_edge_container.GetFirstEdgeTargetID(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_compressed_edge_container.HasEntryForID(e1);
|
||||||
|
|
||||||
|
if (edge_is_compressed)
|
||||||
|
{
|
||||||
|
++compressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
original_edge_data_vector.emplace_back(
|
||||||
|
(edge_is_compressed ? m_compressed_edge_container.GetPositionForID(e1) : node_v),
|
||||||
|
edge_data1.name_id, 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.edge_id);
|
||||||
|
BOOST_ASSERT(SPECIAL_NODEID != edge_data2.edge_id);
|
||||||
|
|
||||||
|
m_edge_based_edge_list.emplace_back(edge_data1.edge_id, edge_data2.edge_id,
|
||||||
|
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
|
||||||
|
double penalty = luabind::call_function<double>(lua_state, "turn_function", 180. - angle);
|
||||||
|
return static_cast<int>(penalty);
|
||||||
|
}
|
||||||
|
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.name_id == data2.name_id && data1.travel_mode == data2.travel_mode)
|
||||||
|
{
|
||||||
|
// TODO: Here we should also do a small graph exploration to check for
|
||||||
|
// more complex situations
|
||||||
|
if (0 != data1.name_id || m_node_based_graph->GetOutDegree(node_v) <= 2)
|
||||||
|
{
|
||||||
|
return TurnInstruction::NoTurn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 "speed_profile.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "../data_structures/compressed_edge_container.hpp"
|
||||||
|
#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;
|
||||||
|
|
||||||
|
explicit EdgeBasedGraphFactory(std::shared_ptr<NodeBasedDynamicGraph> node_based_graph,
|
||||||
|
const CompressedEdgeContainer &compressed_edge_container,
|
||||||
|
const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
|
const std::unordered_set<NodeID> &traffic_lights,
|
||||||
|
std::shared_ptr<const RestrictionMap> restriction_map,
|
||||||
|
const std::vector<QueryNode> &node_info_list,
|
||||||
|
SpeedProfileProperties speed_profile);
|
||||||
|
|
||||||
|
void Run(const std::string &original_edge_data_filename,
|
||||||
|
lua_State *lua_state);
|
||||||
|
|
||||||
|
void GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &edges);
|
||||||
|
|
||||||
|
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
|
||||||
|
|
||||||
|
unsigned GetHighestEdgeID();
|
||||||
|
|
||||||
|
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, const double angle) const;
|
||||||
|
|
||||||
|
int GetTurnPenalty(double angle, lua_State *lua_state) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
using EdgeData = NodeBasedDynamicGraph::EdgeData;
|
||||||
|
|
||||||
|
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
||||||
|
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
||||||
|
unsigned m_max_edge_id;
|
||||||
|
|
||||||
|
const std::vector<QueryNode>& m_node_info_list;
|
||||||
|
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
|
||||||
|
std::shared_ptr<RestrictionMap const> m_restriction_map;
|
||||||
|
|
||||||
|
const std::unordered_set<NodeID>& m_barrier_nodes;
|
||||||
|
const std::unordered_set<NodeID>& m_traffic_lights;
|
||||||
|
const CompressedEdgeContainer& m_compressed_edge_container;
|
||||||
|
|
||||||
|
SpeedProfileProperties speed_profile;
|
||||||
|
|
||||||
|
void CompressGeometry();
|
||||||
|
unsigned RenumberEdges();
|
||||||
|
void GenerateEdgeExpandedNodes();
|
||||||
|
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
|
||||||
|
lua_State *lua_state);
|
||||||
|
|
||||||
|
void InsertEdgeBasedNode(const NodeID u, const NodeID v);
|
||||||
|
|
||||||
|
void FlushVectorToStream(std::ofstream &edge_data_file,
|
||||||
|
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* EDGE_BASED_GRAPH_FACTORY_HPP_ */
|
||||||
@@ -0,0 +1,539 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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/graph_compressor.hpp"
|
||||||
|
#include "../algorithms/tarjan_scc.hpp"
|
||||||
|
#include "../algorithms/crc32_processor.hpp"
|
||||||
|
#include "../data_structures/compressed_edge_container.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/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);
|
||||||
|
|
||||||
|
std::vector<EdgeBasedNode> node_based_edge_list;
|
||||||
|
DeallocatingVector<EdgeBasedEdge> edge_based_edge_list;
|
||||||
|
std::vector<QueryNode> internal_to_external_node_map;
|
||||||
|
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 max_edge_id = graph_size.second;
|
||||||
|
|
||||||
|
TIMER_STOP(expansion);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "building r-tree ...";
|
||||||
|
TIMER_START(rtree);
|
||||||
|
|
||||||
|
FindComponents(max_edge_id, edge_based_edge_list, node_based_edge_list);
|
||||||
|
|
||||||
|
BuildRTree(node_based_edge_list, internal_to_external_node_map);
|
||||||
|
|
||||||
|
TIMER_STOP(rtree);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "writing node map ...";
|
||||||
|
WriteNodeMapping(internal_to_external_node_map);
|
||||||
|
|
||||||
|
// Contracting the edge-expanded graph
|
||||||
|
|
||||||
|
TIMER_START(contraction);
|
||||||
|
std::vector<bool> is_core_node;
|
||||||
|
DeallocatingVector<QueryEdge> contracted_edge_list;
|
||||||
|
ContractGraph(max_edge_id, edge_based_edge_list, contracted_edge_list, is_core_node);
|
||||||
|
TIMER_STOP(contraction);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Contraction took " << TIMER_SEC(contraction) << " sec";
|
||||||
|
|
||||||
|
std::size_t number_of_used_edges =
|
||||||
|
WriteContractedGraph(max_edge_id, node_based_edge_list, contracted_edge_list);
|
||||||
|
WriteCoreNodeMarker(std::move(is_core_node));
|
||||||
|
|
||||||
|
TIMER_STOP(preparing);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Preprocessing : " << TIMER_SEC(preparing) << " seconds";
|
||||||
|
SimpleLogger().Write() << "Expansion : " << (number_of_node_based_nodes / TIMER_SEC(expansion))
|
||||||
|
<< " nodes/sec and " << ((max_edge_id + 1) / TIMER_SEC(expansion))
|
||||||
|
<< " edges/sec";
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Contraction: " << ((max_edge_id + 1) / TIMER_SEC(contraction))
|
||||||
|
<< " nodes/sec and " << number_of_used_edges / TIMER_SEC(contraction)
|
||||||
|
<< " edges/sec";
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "finished preprocessing";
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Prepare::FindComponents(unsigned max_edge_id,
|
||||||
|
const DeallocatingVector<EdgeBasedEdge> &input_edge_list,
|
||||||
|
std::vector<EdgeBasedNode> &input_nodes) const
|
||||||
|
{
|
||||||
|
struct UncontractedEdgeData
|
||||||
|
{
|
||||||
|
};
|
||||||
|
struct InputEdge
|
||||||
|
{
|
||||||
|
unsigned source;
|
||||||
|
unsigned target;
|
||||||
|
UncontractedEdgeData data;
|
||||||
|
|
||||||
|
bool operator<(const InputEdge &rhs) const
|
||||||
|
{
|
||||||
|
return source < rhs.source || (source == rhs.source && target < rhs.target);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const InputEdge &rhs) const
|
||||||
|
{
|
||||||
|
return source == rhs.source && target == rhs.target;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
using UncontractedGraph = StaticGraph<UncontractedEdgeData>;
|
||||||
|
std::vector<InputEdge> edges;
|
||||||
|
edges.reserve(input_edge_list.size() * 2);
|
||||||
|
|
||||||
|
for (const auto &edge : input_edge_list)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT_MSG(static_cast<unsigned int>(std::max(edge.weight, 1)) > 0,
|
||||||
|
"edge distance < 1");
|
||||||
|
if (edge.forward)
|
||||||
|
{
|
||||||
|
edges.push_back({edge.source, edge.target, {}});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edge.backward)
|
||||||
|
{
|
||||||
|
edges.push_back({edge.target, edge.source, {}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect forward and backward nodes of each edge
|
||||||
|
for (const auto &node : input_nodes)
|
||||||
|
{
|
||||||
|
if (node.reverse_edge_based_node_id != SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
edges.push_back({node.forward_edge_based_node_id, node.reverse_edge_based_node_id, {}});
|
||||||
|
edges.push_back({node.reverse_edge_based_node_id, node.forward_edge_based_node_id, {}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tbb::parallel_sort(edges.begin(), edges.end());
|
||||||
|
auto new_end = std::unique(edges.begin(), edges.end());
|
||||||
|
edges.resize(new_end - edges.begin());
|
||||||
|
|
||||||
|
auto uncontractor_graph = std::make_shared<UncontractedGraph>(max_edge_id + 1, edges);
|
||||||
|
|
||||||
|
TarjanSCC<UncontractedGraph> component_search(
|
||||||
|
std::const_pointer_cast<const UncontractedGraph>(uncontractor_graph));
|
||||||
|
component_search.run();
|
||||||
|
|
||||||
|
for (auto &node : input_nodes)
|
||||||
|
{
|
||||||
|
auto forward_component = component_search.get_component_id(node.forward_edge_based_node_id);
|
||||||
|
BOOST_ASSERT(node.reverse_edge_based_node_id == SPECIAL_EDGEID ||
|
||||||
|
forward_component ==
|
||||||
|
component_search.get_component_id(node.reverse_edge_based_node_id));
|
||||||
|
|
||||||
|
const unsigned component_size = component_search.get_component_size(forward_component);
|
||||||
|
const bool is_tiny_component = component_size < 1000;
|
||||||
|
node.component_id = is_tiny_component ? (1 + forward_component) : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Prepare::WriteCoreNodeMarker(std::vector<bool> &&in_is_core_node) const
|
||||||
|
{
|
||||||
|
std::vector<bool> is_core_node(in_is_core_node);
|
||||||
|
std::vector<char> unpacked_bool_flags(is_core_node.size());
|
||||||
|
for (auto i = 0u; i < is_core_node.size(); ++i)
|
||||||
|
{
|
||||||
|
unpacked_bool_flags[i] = is_core_node[i] ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::filesystem::ofstream core_marker_output_stream(config.core_output_path,
|
||||||
|
std::ios::binary);
|
||||||
|
unsigned size = unpacked_bool_flags.size();
|
||||||
|
core_marker_output_stream.write((char *)&size, sizeof(unsigned));
|
||||||
|
core_marker_output_stream.write((char *)unpacked_bool_flags.data(),
|
||||||
|
sizeof(char) * unpacked_bool_flags.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t Prepare::WriteContractedGraph(unsigned max_node_id,
|
||||||
|
const std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||||
|
const DeallocatingVector<QueryEdge> &contracted_edge_list)
|
||||||
|
{
|
||||||
|
const unsigned crc32_value = CalculateEdgeChecksum(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 = [&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 " << (max_node_id + 1) << " nodes";
|
||||||
|
SimpleLogger().Write(logDEBUG) << "contracted graph has " << (max_used_node_id + 1) << " nodes";
|
||||||
|
|
||||||
|
std::vector<StaticGraph<EdgeData>::NodeArrayEntry> node_array;
|
||||||
|
// make sure we have at least one sentinel
|
||||||
|
node_array.resize(max_node_id + 2);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Building node array";
|
||||||
|
StaticGraph<EdgeData>::EdgeIterator edge = 0;
|
||||||
|
StaticGraph<EdgeData>::EdgeIterator position = 0;
|
||||||
|
StaticGraph<EdgeData>::EdgeIterator last_edge;
|
||||||
|
|
||||||
|
// initializing 'first_edge'-field of nodes:
|
||||||
|
for (const auto node : osrm::irange(0u, max_used_node_id + 1))
|
||||||
|
{
|
||||||
|
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 + 1, 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";
|
||||||
|
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(const 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, 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::unordered_set<NodeID> &barrier_nodes,
|
||||||
|
std::unordered_set<NodeID> &traffic_lights,
|
||||||
|
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);
|
||||||
|
|
||||||
|
std::vector<NodeID> barrier_list;
|
||||||
|
std::vector<NodeID> traffic_light_list;
|
||||||
|
NodeID number_of_node_based_nodes = loadNodesFromFile(
|
||||||
|
input_stream, barrier_list, traffic_light_list, internal_to_external_node_map);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << " - " << barrier_list.size() << " bollard nodes, "
|
||||||
|
<< traffic_light_list.size() << " traffic lights";
|
||||||
|
|
||||||
|
// insert into unordered sets for fast lookup
|
||||||
|
barrier_nodes.insert(barrier_list.begin(), barrier_list.end());
|
||||||
|
traffic_lights.insert(traffic_light_list.begin(), traffic_light_list.end());
|
||||||
|
|
||||||
|
barrier_list.clear();
|
||||||
|
barrier_list.shrink_to_fit();
|
||||||
|
traffic_light_list.clear();
|
||||||
|
traffic_light_list.shrink_to_fit();
|
||||||
|
|
||||||
|
loadEdgesFromFile(input_stream, edge_list);
|
||||||
|
|
||||||
|
if (edge_list.empty())
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
|
||||||
|
return std::shared_ptr<NodeBasedDynamicGraph>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NodeBasedDynamicGraphFromEdges(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);
|
||||||
|
|
||||||
|
SpeedProfileProperties speed_profile;
|
||||||
|
SetupScriptingEnvironment(lua_state, speed_profile);
|
||||||
|
|
||||||
|
std::unordered_set<NodeID> barrier_nodes;
|
||||||
|
std::unordered_set<NodeID> traffic_lights;
|
||||||
|
|
||||||
|
auto restriction_map = LoadRestrictionMap();
|
||||||
|
auto node_based_graph =
|
||||||
|
LoadNodeBasedGraph(barrier_nodes, traffic_lights, internal_to_external_node_map);
|
||||||
|
|
||||||
|
CompressedEdgeContainer compressed_edge_container;
|
||||||
|
GraphCompressor graph_compressor(speed_profile);
|
||||||
|
graph_compressor.Compress(barrier_nodes, traffic_lights, *restriction_map, *node_based_graph,
|
||||||
|
compressed_edge_container);
|
||||||
|
|
||||||
|
EdgeBasedGraphFactory edge_based_graph_factory(
|
||||||
|
node_based_graph, compressed_edge_container, barrier_nodes, traffic_lights,
|
||||||
|
std::const_pointer_cast<RestrictionMap const>(restriction_map),
|
||||||
|
internal_to_external_node_map, speed_profile);
|
||||||
|
|
||||||
|
compressed_edge_container.SerializeInternalVector(config.geometry_output_path);
|
||||||
|
|
||||||
|
edge_based_graph_factory.Run(config.edge_output_path, lua_state);
|
||||||
|
lua_close(lua_state);
|
||||||
|
|
||||||
|
edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list);
|
||||||
|
edge_based_graph_factory.GetEdgeBasedNodes(node_based_edge_list);
|
||||||
|
auto max_edge_id = edge_based_graph_factory.GetHighestEdgeID();
|
||||||
|
|
||||||
|
const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes();
|
||||||
|
return std::make_pair(number_of_node_based_nodes, max_edge_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Build contracted graph.
|
||||||
|
*/
|
||||||
|
void Prepare::ContractGraph(const unsigned max_edge_id,
|
||||||
|
DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||||
|
DeallocatingVector<QueryEdge> &contracted_edge_list,
|
||||||
|
std::vector<bool> &is_core_node)
|
||||||
|
{
|
||||||
|
Contractor contractor(max_edge_id + 1, edge_based_edge_list);
|
||||||
|
contractor.Run(config.core_factor);
|
||||||
|
contractor.GetEdges(contracted_edge_list);
|
||||||
|
contractor.GetCoreMarker(is_core_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Writing info on original (node-based) nodes
|
||||||
|
*/
|
||||||
|
void Prepare::WriteNodeMapping(const 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,91 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 SpeedProfileProperties;
|
||||||
|
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(ContractorConfig contractor_config) : config(std::move(contractor_config)) {}
|
||||||
|
Prepare(const Prepare &) = delete;
|
||||||
|
~Prepare();
|
||||||
|
|
||||||
|
int Run();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetupScriptingEnvironment(lua_State *myLuaState, SpeedProfileProperties &speed_profile);
|
||||||
|
unsigned CalculateEdgeChecksum(const std::vector<EdgeBasedNode> &node_based_edge_list);
|
||||||
|
void ContractGraph(const unsigned max_edge_id,
|
||||||
|
DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||||
|
DeallocatingVector<QueryEdge> &contracted_edge_list,
|
||||||
|
std::vector<bool> &is_core_node);
|
||||||
|
void WriteCoreNodeMarker(std::vector<bool> &&is_core_node) const;
|
||||||
|
std::size_t WriteContractedGraph(unsigned number_of_edge_based_nodes,
|
||||||
|
const std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||||
|
const DeallocatingVector<QueryEdge> &contracted_edge_list);
|
||||||
|
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
|
||||||
|
std::shared_ptr<NodeBasedDynamicGraph>
|
||||||
|
LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
|
||||||
|
std::unordered_set<NodeID> &traffic_lights,
|
||||||
|
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(const std::vector<QueryNode> &internal_to_external_node_map);
|
||||||
|
void FindComponents(unsigned max_edge_id,
|
||||||
|
const DeallocatingVector<EdgeBasedEdge> &edges,
|
||||||
|
std::vector<EdgeBasedNode> &nodes) const;
|
||||||
|
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
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef SPEED_PROFILE_PROPERTIES_HPP
|
||||||
|
#define SPEED_PROFILE_PROPERTIES_HPP
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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,10 +189,9 @@ class BinaryHeap
|
|||||||
return inserted_nodes[heap[1].index].node;
|
return inserted_nodes[heap[1].index].node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Weight MinKey() const
|
Weight MinKey() const {
|
||||||
{
|
BOOST_ASSERT(heap.size() > 1);
|
||||||
BOOST_ASSERT(heap.size() > 1);
|
return heap[1].weight;
|
||||||
return heap[1].weight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID DeleteMin()
|
NodeID DeleteMin()
|
||||||
@@ -290,7 +311,5 @@ class BinaryHeap
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // BINARY_HEAP_H
|
#endif // BINARY_HEAP_H
|
||||||
+57
-83
@@ -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 "compressed_edge_container.hpp"
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
@@ -10,11 +37,6 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace extractor
|
|
||||||
{
|
|
||||||
|
|
||||||
CompressedEdgeContainer::CompressedEdgeContainer()
|
CompressedEdgeContainer::CompressedEdgeContainer()
|
||||||
{
|
{
|
||||||
m_free_list.reserve(100);
|
m_free_list.reserve(100);
|
||||||
@@ -59,7 +81,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 +96,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
|
|
||||||
// has been removed from the graph, so we have to save These edges/nodes
|
|
||||||
// have already been trimmed from the graph, this function just stores
|
|
||||||
// the original data for unpacking later.
|
|
||||||
//
|
|
||||||
// edge_id_1 edge_id_2
|
|
||||||
// ----------> via_node_id -----------> target_node_id
|
|
||||||
// weight_1 weight_2
|
|
||||||
void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
||||||
const EdgeID edge_id_2,
|
const EdgeID edge_id_2,
|
||||||
const NodeID via_node_id,
|
const NodeID via_node_id,
|
||||||
const NodeID target_node_id,
|
const NodeID target_node_id,
|
||||||
const EdgeWeight weight1,
|
const EdgeWeight weight1,
|
||||||
const EdgeWeight weight2)
|
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 +153,13 @@ 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
|
// note we don't save the start coordinate: it is implicitly given by edge 1
|
||||||
// weight1 is the distance to the (currently) last coordinate in the bucket
|
// weight1 is the distance to the (currently) last coordinate in the bucket
|
||||||
if (edge_bucket_list1.empty())
|
if (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 +171,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,48 +190,7 @@ 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,
|
|
||||||
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});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,23 +202,24 @@ 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 CompressedEdgeContainer::EdgeBucket&
|
||||||
CompressedEdgeContainer::GetBucketReference(const EdgeID edge_id) const
|
CompressedEdgeContainer::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);
|
||||||
@@ -254,13 +230,11 @@ NodeID CompressedEdgeContainer::GetFirstEdgeTargetID(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.front().first;
|
||||||
}
|
}
|
||||||
NodeID CompressedEdgeContainer::GetLastEdgeSourceID(const EdgeID edge_id) const
|
NodeID CompressedEdgeContainer::GetLastEdgeSourceID(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 CompressedEdgeContainer
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
using CompressedNode = std::pair<NodeID, EdgeWeight>;
|
||||||
|
using EdgeBucket = std::vector<CompressedNode>;
|
||||||
|
|
||||||
namespace json
|
CompressedEdgeContainer();
|
||||||
{
|
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 EdgeBucket& GetBucketReference(const EdgeID edge_id) const;
|
||||||
|
NodeID GetFirstEdgeTargetID(const EdgeID edge_id) const;
|
||||||
|
NodeID GetLastEdgeSourceID(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<EdgeBucket> 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,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 "../algorithms/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);
|
||||||
|
}
|
||||||
@@ -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,11 +36,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
|
|
||||||
template <typename ElementT> struct ConstDeallocatingVectorIteratorState
|
template <typename ElementT> struct ConstDeallocatingVectorIteratorState
|
||||||
{
|
{
|
||||||
ConstDeallocatingVectorIteratorState()
|
ConstDeallocatingVectorIteratorState()
|
||||||
@@ -25,15 +47,14 @@ template <typename ElementT> struct ConstDeallocatingVectorIteratorState
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
explicit ConstDeallocatingVectorIteratorState(const std::size_t idx,
|
explicit ConstDeallocatingVectorIteratorState(const std::size_t idx,
|
||||||
const std::vector<ElementT *> *input_list)
|
const std::vector<ElementT *> *input_list)
|
||||||
: index(idx), bucket_list(input_list)
|
: index(idx), bucket_list(input_list)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
std::size_t index;
|
std::size_t index;
|
||||||
const std::vector<ElementT *> *bucket_list;
|
const std::vector<ElementT *> *bucket_list;
|
||||||
|
|
||||||
ConstDeallocatingVectorIteratorState &
|
ConstDeallocatingVectorIteratorState &operator=(const ConstDeallocatingVectorIteratorState &other)
|
||||||
operator=(const ConstDeallocatingVectorIteratorState &other)
|
|
||||||
{
|
{
|
||||||
index = other.index;
|
index = other.index;
|
||||||
bucket_list = other.bucket_list;
|
bucket_list = other.bucket_list;
|
||||||
@@ -216,11 +237,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
|
||||||
{
|
{
|
||||||
@@ -241,9 +257,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 +319,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 +386,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
|
||||||
{
|
{
|
||||||
@@ -69,15 +91,14 @@ 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
|
// we need to cast here because DeallocatingVector does not have a valid const iterator
|
||||||
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT &>(graph).begin(),
|
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT&>(graph).begin(), const_cast<ContainerT&>(graph).end()));
|
||||||
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))
|
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,10 +113,10 @@ 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);
|
BOOST_ASSERT(edge_list[i].target < number_of_nodes);
|
||||||
@@ -116,7 +137,7 @@ 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).reversed)
|
||||||
{
|
{
|
||||||
@@ -146,7 +167,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 +201,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 +261,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 +341,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,111 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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>
|
||||||
|
|
||||||
|
/// This is what StaticRTree serialized and stores on disk
|
||||||
|
/// It is generated in EdgeBasedGraphFactory.
|
||||||
|
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
|
||||||
+58
-28
@@ -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 HIDDEN_MARKOV_MODEL
|
#ifndef HIDDEN_MARKOV_MODEL
|
||||||
#define HIDDEN_MARKOV_MODEL
|
#define HIDDEN_MARKOV_MODEL
|
||||||
|
|
||||||
#include "util/integer_range.hpp"
|
#include "../util/integer_range.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/math/constants/constants.hpp>
|
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
@@ -13,15 +39,14 @@
|
|||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace engine
|
namespace matching
|
||||||
{
|
{
|
||||||
namespace map_matching
|
static const double log_2_pi = std::log(2. * M_PI);
|
||||||
{
|
|
||||||
|
|
||||||
static const double log_2_pi = std::log(2. * boost::math::constants::pi<double>());
|
|
||||||
static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits<double>::infinity();
|
static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits<double>::infinity();
|
||||||
static const double MINIMAL_LOG_PROB = std::numeric_limits<double>::lowest();
|
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();
|
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
|
// closures to precompute log -> only simple floating point operations
|
||||||
struct EmissionLogProbability
|
struct EmissionLogProbability
|
||||||
@@ -35,7 +60,8 @@ struct EmissionLogProbability
|
|||||||
|
|
||||||
double operator()(const double distance) const
|
double operator()(const double distance) const
|
||||||
{
|
{
|
||||||
return -0.5 * (log_2_pi + (distance / sigma_z) * (distance / sigma_z)) - log_sigma_z;
|
return -0.5 * (osrm::matching::log_2_pi + (distance / sigma_z) * (distance / sigma_z)) -
|
||||||
|
log_sigma_z;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -52,32 +78,35 @@ template <class CandidateLists> struct HiddenMarkovModel
|
|||||||
{
|
{
|
||||||
std::vector<std::vector<double>> viterbi;
|
std::vector<std::vector<double>> viterbi;
|
||||||
std::vector<std::vector<std::pair<unsigned, unsigned>>> parents;
|
std::vector<std::vector<std::pair<unsigned, unsigned>>> parents;
|
||||||
std::vector<std::vector<float>> path_distances;
|
std::vector<std::vector<float>> path_lengths;
|
||||||
std::vector<std::vector<bool>> pruned;
|
std::vector<std::vector<bool>> pruned;
|
||||||
|
std::vector<std::vector<bool>> suspicious;
|
||||||
std::vector<bool> breakage;
|
std::vector<bool> breakage;
|
||||||
|
|
||||||
const CandidateLists &candidates_list;
|
const CandidateLists &candidates_list;
|
||||||
const std::vector<std::vector<double>> &emission_log_probabilities;
|
const EmissionLogProbability &emission_log_probability;
|
||||||
|
|
||||||
HiddenMarkovModel(const CandidateLists &candidates_list,
|
HiddenMarkovModel(const CandidateLists &candidates_list,
|
||||||
const std::vector<std::vector<double>> &emission_log_probabilities)
|
const EmissionLogProbability &emission_log_probability)
|
||||||
: breakage(candidates_list.size()), candidates_list(candidates_list),
|
: breakage(candidates_list.size()), candidates_list(candidates_list),
|
||||||
emission_log_probabilities(emission_log_probabilities)
|
emission_log_probability(emission_log_probability)
|
||||||
{
|
{
|
||||||
viterbi.resize(candidates_list.size());
|
viterbi.resize(candidates_list.size());
|
||||||
parents.resize(candidates_list.size());
|
parents.resize(candidates_list.size());
|
||||||
path_distances.resize(candidates_list.size());
|
path_lengths.resize(candidates_list.size());
|
||||||
|
suspicious.resize(candidates_list.size());
|
||||||
pruned.resize(candidates_list.size());
|
pruned.resize(candidates_list.size());
|
||||||
breakage.resize(candidates_list.size());
|
breakage.resize(candidates_list.size());
|
||||||
for (const auto i : util::irange<std::size_t>(0u, candidates_list.size()))
|
for (const auto i : osrm::irange<std::size_t>(0u, candidates_list.size()))
|
||||||
{
|
{
|
||||||
const auto &num_candidates = candidates_list[i].size();
|
const auto& num_candidates = candidates_list[i].size();
|
||||||
// add empty vectors
|
// add empty vectors
|
||||||
if (num_candidates > 0)
|
if (num_candidates > 0)
|
||||||
{
|
{
|
||||||
viterbi[i].resize(num_candidates);
|
viterbi[i].resize(num_candidates);
|
||||||
parents[i].resize(num_candidates);
|
parents[i].resize(num_candidates);
|
||||||
path_distances[i].resize(num_candidates);
|
path_lengths[i].resize(num_candidates);
|
||||||
|
suspicious[i].resize(num_candidates);
|
||||||
pruned[i].resize(num_candidates);
|
pruned[i].resize(num_candidates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,14 +116,15 @@ template <class CandidateLists> struct HiddenMarkovModel
|
|||||||
|
|
||||||
void clear(std::size_t initial_timestamp)
|
void clear(std::size_t initial_timestamp)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(viterbi.size() == parents.size() && parents.size() == path_distances.size() &&
|
BOOST_ASSERT(viterbi.size() == parents.size() && parents.size() == path_lengths.size() &&
|
||||||
path_distances.size() == pruned.size() && pruned.size() == breakage.size());
|
path_lengths.size() == pruned.size() && pruned.size() == breakage.size());
|
||||||
|
|
||||||
for (const auto t : util::irange(initial_timestamp, viterbi.size()))
|
for (const auto t : osrm::irange(initial_timestamp, viterbi.size()))
|
||||||
{
|
{
|
||||||
std::fill(viterbi[t].begin(), viterbi[t].end(), IMPOSSIBLE_LOG_PROB);
|
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(parents[t].begin(), parents[t].end(), std::make_pair(0u, 0u));
|
||||||
std::fill(path_distances[t].begin(), path_distances[t].end(), 0);
|
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(pruned[t].begin(), pruned[t].end(), true);
|
||||||
}
|
}
|
||||||
std::fill(breakage.begin() + initial_timestamp, breakage.end(), true);
|
std::fill(breakage.begin() + initial_timestamp, breakage.end(), true);
|
||||||
@@ -107,11 +137,14 @@ template <class CandidateLists> struct HiddenMarkovModel
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(initial_timestamp < num_points);
|
BOOST_ASSERT(initial_timestamp < num_points);
|
||||||
|
|
||||||
for (const auto s : util::irange<std::size_t>(0u, viterbi[initial_timestamp].size()))
|
for (const auto s : osrm::irange<std::size_t>(0u, viterbi[initial_timestamp].size()))
|
||||||
{
|
{
|
||||||
viterbi[initial_timestamp][s] = emission_log_probabilities[initial_timestamp][s];
|
viterbi[initial_timestamp][s] =
|
||||||
|
emission_log_probability(candidates_list[initial_timestamp][s].second);
|
||||||
parents[initial_timestamp][s] = std::make_pair(initial_timestamp, s);
|
parents[initial_timestamp][s] = std::make_pair(initial_timestamp, s);
|
||||||
pruned[initial_timestamp][s] = viterbi[initial_timestamp][s] < MINIMAL_LOG_PROB;
|
pruned[initial_timestamp][s] =
|
||||||
|
viterbi[initial_timestamp][s] < osrm::matching::MINIMAL_LOG_PROB;
|
||||||
|
suspicious[initial_timestamp][s] = false;
|
||||||
|
|
||||||
breakage[initial_timestamp] =
|
breakage[initial_timestamp] =
|
||||||
breakage[initial_timestamp] && pruned[initial_timestamp][s];
|
breakage[initial_timestamp] && pruned[initial_timestamp][s];
|
||||||
@@ -122,7 +155,7 @@ template <class CandidateLists> struct HiddenMarkovModel
|
|||||||
|
|
||||||
if (initial_timestamp >= num_points)
|
if (initial_timestamp >= num_points)
|
||||||
{
|
{
|
||||||
return INVALID_STATE;
|
return osrm::matching::INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(initial_timestamp > 0);
|
BOOST_ASSERT(initial_timestamp > 0);
|
||||||
@@ -133,8 +166,5 @@ template <class CandidateLists> struct HiddenMarkovModel
|
|||||||
return initial_timestamp;
|
return initial_timestamp;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // HIDDEN_MARKOV_MODEL
|
#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 = 1u << (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,112 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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),
|
||||||
|
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 access_restricted,
|
||||||
|
TravelMode travel_mode,
|
||||||
|
bool is_split)
|
||||||
|
: source(source), target(target), name_id(name_id), weight(weight), forward(forward),
|
||||||
|
backward(backward), roundabout(roundabout),
|
||||||
|
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,86 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 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 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
|
||||||
+32
-47
@@ -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,61 +25,46 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ENGINE_API_ROUTE_PARAMETERS_HPP
|
#ifndef MATRIX_GRAPH_WRAPPER_H
|
||||||
#define ENGINE_API_ROUTE_PARAMETERS_HPP
|
#define MATRIX_GRAPH_WRAPPER_H
|
||||||
|
|
||||||
#include "engine/api/base_parameters.hpp"
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
namespace osrm
|
#include "../typedefs.h"
|
||||||
{
|
|
||||||
namespace engine
|
|
||||||
{
|
|
||||||
namespace api
|
|
||||||
{
|
|
||||||
|
|
||||||
struct RouteParameters : public BaseParameters
|
// This Wrapper provides all methods that are needed for TarjanSCC, when the graph is given in a
|
||||||
|
// matrix representation (e.g. as output from a distance table call)
|
||||||
|
|
||||||
|
template <typename T> class MatrixGraphWrapper
|
||||||
{
|
{
|
||||||
enum class GeometriesType
|
public:
|
||||||
|
MatrixGraphWrapper(std::vector<T> table, const std::size_t number_of_nodes)
|
||||||
|
: table_(std::move(table)), number_of_nodes_(number_of_nodes){};
|
||||||
|
|
||||||
|
std::size_t GetNumberOfNodes() const { return number_of_nodes_; }
|
||||||
|
|
||||||
|
std::vector<T> GetAdjacentEdgeRange(const NodeID node) const
|
||||||
{
|
{
|
||||||
Polyline,
|
|
||||||
GeoJSON
|
|
||||||
};
|
|
||||||
enum class OverviewType
|
|
||||||
{
|
|
||||||
Simplified,
|
|
||||||
Full,
|
|
||||||
False
|
|
||||||
};
|
|
||||||
|
|
||||||
RouteParameters() = default;
|
std::vector<T> edges;
|
||||||
|
// find all valid adjacent edges and move to vector `edges`
|
||||||
template <typename... Args>
|
for (std::size_t i = 0; i < number_of_nodes_; ++i)
|
||||||
RouteParameters(const bool steps_,
|
{
|
||||||
const bool alternatives_,
|
if (*(std::begin(table_) + node * number_of_nodes_ + i) != INVALID_EDGE_WEIGHT)
|
||||||
const GeometriesType geometries_,
|
{
|
||||||
const OverviewType overview_,
|
edges.push_back(i);
|
||||||
const boost::optional<bool> uturns_,
|
}
|
||||||
Args... args_)
|
}
|
||||||
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
|
return edges;
|
||||||
geometries{geometries_}, overview{overview_}, uturns{uturns_}
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool steps = true;
|
EdgeWeight GetTarget(const EdgeWeight edge) const { return edge; }
|
||||||
bool alternatives = true;
|
|
||||||
GeometriesType geometries = GeometriesType::Polyline;
|
|
||||||
OverviewType overview = OverviewType::Simplified;
|
|
||||||
boost::optional<bool> uturns;
|
|
||||||
|
|
||||||
bool IsValid() const
|
private:
|
||||||
{
|
const std::vector<T> table_;
|
||||||
return coordinates.size() >= 2 && BaseParameters::IsValid();
|
const std::size_t number_of_nodes_;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif // MATRIX_GRAPH_WRAPPER_H
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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/graph_utils.hpp"
|
||||||
|
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct NodeBasedEdgeData
|
||||||
|
{
|
||||||
|
NodeBasedEdgeData()
|
||||||
|
: distance(INVALID_EDGE_WEIGHT), edge_id(SPECIAL_NODEID),
|
||||||
|
name_id(std::numeric_limits<unsigned>::max()), access_restricted(false),
|
||||||
|
reversed(false), roundabout(false), travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeBasedEdgeData(int distance, unsigned edge_id, unsigned name_id,
|
||||||
|
bool access_restricted, bool reversed,
|
||||||
|
bool roundabout, TravelMode travel_mode)
|
||||||
|
: distance(distance), edge_id(edge_id), name_id(name_id),
|
||||||
|
access_restricted(access_restricted), reversed(reversed),
|
||||||
|
roundabout(roundabout), travel_mode(travel_mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int distance;
|
||||||
|
unsigned edge_id;
|
||||||
|
unsigned name_id;
|
||||||
|
bool access_restricted : 1;
|
||||||
|
bool reversed : 1;
|
||||||
|
bool roundabout : 1;
|
||||||
|
TravelMode travel_mode : 4;
|
||||||
|
|
||||||
|
bool IsCompatibleTo(const NodeBasedEdgeData &other) const
|
||||||
|
{
|
||||||
|
return (reversed == other.reversed) && (name_id == other.name_id) &&
|
||||||
|
(travel_mode == other.travel_mode);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using NodeBasedDynamicGraph = DynamicGraph<NodeBasedEdgeData>;
|
||||||
|
|
||||||
|
/// 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>
|
||||||
|
NodeBasedDynamicGraphFromEdges(int number_of_nodes, const std::vector<NodeBasedEdge> &input_edge_list)
|
||||||
|
{
|
||||||
|
auto edges_list = directedEdgesFromCompressed<NodeBasedDynamicGraph::InputEdge>(input_edge_list,
|
||||||
|
[](NodeBasedDynamicGraph::InputEdge& output_edge, const NodeBasedEdge& input_edge)
|
||||||
|
{
|
||||||
|
output_edge.data.distance = static_cast<int>(input_edge.weight);
|
||||||
|
BOOST_ASSERT(output_edge.data.distance > 0);
|
||||||
|
|
||||||
|
output_edge.data.roundabout = input_edge.roundabout;
|
||||||
|
output_edge.data.name_id = input_edge.name_id;
|
||||||
|
output_edge.data.access_restricted = input_edge.access_restricted;
|
||||||
|
output_edge.data.travel_mode = input_edge.travel_mode;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
tbb::parallel_sort(edges_list.begin(), edges_list.end());
|
||||||
|
|
||||||
|
auto graph = std::make_shared<NodeBasedDynamicGraph>(
|
||||||
|
static_cast<NodeBasedDynamicGraph::NodeIterator>(number_of_nodes), edges_list);
|
||||||
|
|
||||||
|
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,26 +25,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ENGINE_API_TRIP_PARAMETERS_HPP
|
#ifndef NODE_ID_HPP
|
||||||
#define ENGINE_API_TRIP_PARAMETERS_HPP
|
#define NODE_ID_HPP
|
||||||
|
|
||||||
#include "engine/api/route_parameters.hpp"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <vector>
|
struct Cmp
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
{
|
||||||
namespace engine
|
using value_type = NodeID;
|
||||||
{
|
bool operator()(const NodeID left, const NodeID right) const { return left < right; }
|
||||||
namespace api
|
value_type max_value() { return 0xffffffff; }
|
||||||
{
|
value_type min_value() { return 0x0; }
|
||||||
|
|
||||||
struct TripParameters : public RouteParameters
|
|
||||||
{
|
|
||||||
// bool IsValid() const; Falls back to base class
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#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,156 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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;
|
||||||
|
// note 4 bits would suffice for each,
|
||||||
|
// but the saved byte would be padding anyway
|
||||||
|
TravelMode forward_travel_mode;
|
||||||
|
TravelMode backward_travel_mode;
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(PhantomNode) == 48, "PhantomNode has more padding then expected");
|
||||||
|
|
||||||
|
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
|
||||||
@@ -1,15 +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 QUERYEDGE_HPP
|
#ifndef QUERYEDGE_HPP
|
||||||
#define QUERYEDGE_HPP
|
#define QUERYEDGE_HPP
|
||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace contractor
|
|
||||||
{
|
|
||||||
|
|
||||||
struct QueryEdge
|
struct QueryEdge
|
||||||
{
|
{
|
||||||
NodeID source;
|
NodeID source;
|
||||||
@@ -53,7 +75,5 @@ struct QueryEdge
|
|||||||
data.id == right.data.id);
|
data.id == right.data.id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // QUERYEDGE_HPP
|
#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
|
||||||
@@ -1,17 +1,39 @@
|
|||||||
#include "extractor/raster_source.hpp"
|
/*
|
||||||
|
|
||||||
#include "util/simple_logger.hpp"
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
#include "util/timing_util.hpp"
|
All rights reserved.
|
||||||
|
|
||||||
#include "osrm/coordinate.hpp"
|
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 "raster_source.hpp"
|
||||||
|
|
||||||
|
#include "../util/simple_logger.hpp"
|
||||||
|
#include "../util/timing_util.hpp"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace extractor
|
|
||||||
{
|
|
||||||
|
|
||||||
RasterSource::RasterSource(RasterGrid _raster_data,
|
RasterSource::RasterSource(RasterGrid _raster_data,
|
||||||
std::size_t _width,
|
std::size_t _width,
|
||||||
std::size_t _height,
|
std::size_t _height,
|
||||||
@@ -20,8 +42,8 @@ RasterSource::RasterSource(RasterGrid _raster_data,
|
|||||||
int _ymin,
|
int _ymin,
|
||||||
int _ymax)
|
int _ymax)
|
||||||
: xstep(calcSize(_xmin, _xmax, _width)), ystep(calcSize(_ymin, _ymax, _height)),
|
: xstep(calcSize(_xmin, _xmax, _width)), ystep(calcSize(_ymin, _ymax, _height)),
|
||||||
raster_data(std::move(_raster_data)), width(_width), height(_height), xmin(_xmin),
|
raster_data(_raster_data), width(_width), height(_height), xmin(_xmin), xmax(_xmax),
|
||||||
xmax(_xmax), ymin(_ymin), ymax(_ymax)
|
ymin(_ymin), ymax(_ymax)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(xstep != 0);
|
BOOST_ASSERT(xstep != 0);
|
||||||
BOOST_ASSERT(ystep != 0);
|
BOOST_ASSERT(ystep != 0);
|
||||||
@@ -92,20 +114,20 @@ int SourceContainer::loadRasterSource(const std::string &path_string,
|
|||||||
const auto itr = LoadedSourcePaths.find(path_string);
|
const auto itr = LoadedSourcePaths.find(path_string);
|
||||||
if (itr != LoadedSourcePaths.end())
|
if (itr != LoadedSourcePaths.end())
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write() << "[source loader] Already loaded source '" << path_string
|
SimpleLogger().Write() << "[source loader] Already loaded source '" << path_string
|
||||||
<< "' at source_id " << itr->second;
|
<< "' at source_id " << itr->second;
|
||||||
return itr->second;
|
return itr->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
int source_id = static_cast<int>(LoadedSources.size());
|
int source_id = static_cast<int>(LoadedSources.size());
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "[source loader] Loading from " << path_string << " ... ";
|
SimpleLogger().Write() << "[source loader] Loading from " << path_string << " ... ";
|
||||||
TIMER_START(loading_source);
|
TIMER_START(loading_source);
|
||||||
|
|
||||||
boost::filesystem::path filepath(path_string);
|
boost::filesystem::path filepath(path_string);
|
||||||
if (!boost::filesystem::exists(filepath))
|
if (!boost::filesystem::exists(filepath))
|
||||||
{
|
{
|
||||||
throw util::exception("error reading: no such path");
|
throw osrm::exception("error reading: no such path");
|
||||||
}
|
}
|
||||||
|
|
||||||
RasterGrid rasterData{filepath, ncols, nrows};
|
RasterGrid rasterData{filepath, ncols, nrows};
|
||||||
@@ -115,8 +137,7 @@ int SourceContainer::loadRasterSource(const std::string &path_string,
|
|||||||
LoadedSourcePaths.emplace(path_string, source_id);
|
LoadedSourcePaths.emplace(path_string, source_id);
|
||||||
LoadedSources.push_back(std::move(source));
|
LoadedSources.push_back(std::move(source));
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "[source loader] ok, after " << TIMER_SEC(loading_source)
|
SimpleLogger().Write() << "[source loader] ok, after " << TIMER_SEC(loading_source) << "s";
|
||||||
<< "s";
|
|
||||||
|
|
||||||
return source_id;
|
return source_id;
|
||||||
}
|
}
|
||||||
@@ -126,7 +147,7 @@ RasterDatum SourceContainer::getRasterDataFromSource(unsigned int source_id, int
|
|||||||
{
|
{
|
||||||
if (LoadedSources.size() < source_id + 1)
|
if (LoadedSources.size() < source_id + 1)
|
||||||
{
|
{
|
||||||
throw util::exception("error reading: no such loaded source");
|
throw osrm::exception("error reading: no such loaded source");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(lat < (90 * COORDINATE_PRECISION));
|
BOOST_ASSERT(lat < (90 * COORDINATE_PRECISION));
|
||||||
@@ -144,7 +165,7 @@ SourceContainer::getRasterInterpolateFromSource(unsigned int source_id, int lon,
|
|||||||
{
|
{
|
||||||
if (LoadedSources.size() < source_id + 1)
|
if (LoadedSources.size() < source_id + 1)
|
||||||
{
|
{
|
||||||
throw util::exception("error reading: no such loaded source");
|
throw osrm::exception("error reading: no such loaded source");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(lat < (90 * COORDINATE_PRECISION));
|
BOOST_ASSERT(lat < (90 * COORDINATE_PRECISION));
|
||||||
@@ -155,5 +176,3 @@ SourceContainer::getRasterInterpolateFromSource(unsigned int source_id, int lon,
|
|||||||
const auto &found = LoadedSources[source_id];
|
const auto &found = LoadedSources[source_id];
|
||||||
return found.getRasterInterpolate(lon, lat);
|
return found.getRasterInterpolate(lon, lat);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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 RASTER_SOURCE_HPP
|
#ifndef RASTER_SOURCE_HPP
|
||||||
#define RASTER_SOURCE_HPP
|
#define RASTER_SOURCE_HPP
|
||||||
|
|
||||||
#include "util/exception.hpp"
|
#include "../util/osrm_exception.hpp"
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
@@ -13,11 +40,6 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace extractor
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Small wrapper around raster source queries to optionally provide results
|
\brief Small wrapper around raster source queries to optionally provide results
|
||||||
gracefully, depending on source bounds
|
gracefully, depending on source bounds
|
||||||
@@ -45,7 +67,7 @@ class RasterGrid
|
|||||||
boost::filesystem::ifstream stream(filepath);
|
boost::filesystem::ifstream stream(filepath);
|
||||||
if (!stream)
|
if (!stream)
|
||||||
{
|
{
|
||||||
throw util::exception("Unable to open raster file.");
|
throw osrm::exception("Unable to open raster file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.seekg(0, std::ios_base::end);
|
stream.seekg(0, std::ios_base::end);
|
||||||
@@ -70,13 +92,13 @@ class RasterGrid
|
|||||||
}
|
}
|
||||||
catch (std::exception const &ex)
|
catch (std::exception const &ex)
|
||||||
{
|
{
|
||||||
throw util::exception(
|
throw osrm::exception(
|
||||||
std::string("Failed to read from raster source with exception: ") + ex.what());
|
std::string("Failed to read from raster source with exception: ") + ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!r || itr != end)
|
if (!r || itr != end)
|
||||||
{
|
{
|
||||||
throw util::exception("Failed to parse raster source correctly.");
|
throw osrm::exception("Failed to parse raster source correctly.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +171,5 @@ class SourceContainer
|
|||||||
std::vector<RasterSource> LoadedSources;
|
std::vector<RasterSource> LoadedSources;
|
||||||
std::unordered_map<std::string, int> LoadedSourcePaths;
|
std::unordered_map<std::string, int> LoadedSourcePaths;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* RASTER_SOURCE_HPP */
|
#endif /* RASTER_SOURCE_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 "../algorithms/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;
|
||||||
@@ -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
|
||||||
@@ -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(5), gps_precision(5), 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,69 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 "../routing_algorithms/direct_shortest_path.hpp"
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
template <class DataFacadeT> class SearchEngine
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
DataFacadeT *facade;
|
||||||
|
SearchEngineData engine_working_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShortestPathRouting<DataFacadeT> shortest_path;
|
||||||
|
DirectShortestPathRouting<DataFacadeT> direct_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),
|
||||||
|
direct_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,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 SEGMENT_INFORMATION_HPP
|
||||||
|
#define SEGMENT_INFORMATION_HPP
|
||||||
|
|
||||||
|
#include "turn_instructions.hpp"
|
||||||
|
|
||||||
|
#include "../data_structures/travel_mode.hpp"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <osrm/coordinate.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
// 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(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(std::move(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(FixedPointCoordinate location,
|
||||||
|
const NodeID name_id,
|
||||||
|
const EdgeWeight duration,
|
||||||
|
const float length,
|
||||||
|
const TurnInstruction turn_instruction,
|
||||||
|
const TravelMode travel_mode)
|
||||||
|
: location(std::move(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,
|
||||||
@@ -111,15 +130,14 @@ class SharedMemory
|
|||||||
{
|
{
|
||||||
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,20 @@ 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)
|
template<typename ContainerT>
|
||||||
|
StaticGraph(const int nodes, const ContainerT &graph)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT &>(graph).begin(),
|
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT&>(graph).begin(), const_cast<ContainerT&>(graph).end()));
|
||||||
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 +109,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 +127,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 +159,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 +215,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
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user