Merge branch 'develop'
This commit is contained in:
commit
c2fc47df34
23
.gitignore
vendored
23
.gitignore
vendored
@ -36,8 +36,8 @@ Thumbs.db
|
||||
# build related files #
|
||||
#######################
|
||||
/build/
|
||||
/Util/finger_print.cpp
|
||||
/Util/git_sha.cpp
|
||||
/util/fingerprint_impl.hpp
|
||||
/util/git_sha.cpp
|
||||
/cmake/postinst
|
||||
|
||||
# Eclipse related files #
|
||||
@ -53,25 +53,8 @@ Thumbs.db
|
||||
stxxl.log
|
||||
stxxl.errlog
|
||||
|
||||
# compiled protobuffers #
|
||||
#########################
|
||||
/DataStructures/pbf-proto/*.pb.h
|
||||
/DataStructures/pbf-proto/*.pb.cc
|
||||
|
||||
# External Libs #
|
||||
#################
|
||||
/lib/
|
||||
/win/lib
|
||||
|
||||
# Visual Studio Temp + build Files #
|
||||
# Compiled Binary Files #
|
||||
####################################
|
||||
/win/*.user
|
||||
/win/*.ncb
|
||||
/win/*.suo
|
||||
/win/Debug/
|
||||
/win/Release/
|
||||
/win/bin/
|
||||
/win/bin-debug/
|
||||
/osrm-extract
|
||||
/osrm-io-benchmark
|
||||
/osrm-components
|
||||
|
10
.travis.yml
10
.travis.yml
@ -10,6 +10,7 @@ install:
|
||||
- sudo apt-get -q install protobuf-compiler libprotoc-dev libprotobuf7 libprotobuf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev rubygems libtbb-dev
|
||||
- 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
|
||||
@ -24,10 +25,11 @@ before_script:
|
||||
- bundle install
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake .. $CMAKEOPTIONS
|
||||
- cmake .. $CMAKEOPTIONS -DBUILD_TOOLS=1
|
||||
script:
|
||||
- make -j 2
|
||||
- make -j 2 tests
|
||||
- make
|
||||
- make tests
|
||||
- make benchmarks
|
||||
- ./datastructure-tests
|
||||
- cd ..
|
||||
- cucumber -p verify
|
||||
@ -44,7 +46,9 @@ cache:
|
||||
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
|
||||
|
155
CMakeLists.txt
155
CMakeLists.txt
@ -1,17 +1,17 @@
|
||||
cmake_minimum_required(VERSION 2.8.8)
|
||||
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE)
|
||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR AND NOT MSVC_IDE)
|
||||
message(FATAL_ERROR "In-source builds are not allowed.
|
||||
Please create a directory and run cmake from there, passing the path to this source directory as the last argument.
|
||||
This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. Please delete them.")
|
||||
endif()
|
||||
|
||||
project(OSRM)
|
||||
project(OSRM C CXX)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
include(GetGitRevisionDescription)
|
||||
git_describe(GIT_DESCRIPTION)
|
||||
|
||||
@ -23,85 +23,89 @@ else()
|
||||
message(WARNING "Building on a 32 bit system is unsupported")
|
||||
endif()
|
||||
|
||||
if (WIN32 AND MSVC_VERSION LESS 1800)
|
||||
if(WIN32 AND MSVC_VERSION LESS 1800)
|
||||
message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)")
|
||||
endif()
|
||||
|
||||
OPTION(WITH_TOOLS "Build OSRM tools" OFF)
|
||||
OPTION(BUILD_TOOLS "Build OSRM tools" 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)
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Include/)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/third_party/)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include/)
|
||||
|
||||
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/finger_print.cpp finger_print.cpp.alwaysbuild
|
||||
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
||||
add_custom_target(FingerPrintConfigure ALL
|
||||
${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake
|
||||
DEPENDS
|
||||
${CMAKE_SOURCE_DIR}/Util/finger_print.cpp.in
|
||||
COMMENT "Configuring finger_print.cpp"
|
||||
COMMENT "Configuring revision fingerprint"
|
||||
VERBATIM)
|
||||
|
||||
add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/finger_print.cpp)
|
||||
add_custom_target(tests DEPENDS datastructure-tests algorithm-tests)
|
||||
add_custom_target(benchmarks DEPENDS rtree-bench)
|
||||
|
||||
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread unit_test_framework)
|
||||
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/Util/git_sha.cpp.in
|
||||
${CMAKE_SOURCE_DIR}/Util/git_sha.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/git_sha.cpp.in
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/git_sha.cpp
|
||||
)
|
||||
file(GLOB ExtractorGlob extractor/*.cpp)
|
||||
file(GLOB ImporterGlob data_structures/import_edge.cpp data_structures/external_memory_node.cpp)
|
||||
add_library(IMPORT OBJECT ${ImporterGlob})
|
||||
add_library(LOGGER OBJECT Util/simple_logger.cpp)
|
||||
add_library(LOGGER OBJECT util/simple_logger.cpp)
|
||||
add_library(PHANTOMNODE OBJECT data_structures/phantom_node.cpp)
|
||||
add_library(EXCEPTION OBJECT Util/osrm_exception.cpp)
|
||||
add_library(EXCEPTION OBJECT util/osrm_exception.cpp)
|
||||
add_library(MERCATOR OBJECT util/mercator.cpp)
|
||||
add_library(ANGLE OBJECT util/compute_angle.cpp)
|
||||
|
||||
set(ExtractorSources extract.cpp ${ExtractorGlob})
|
||||
add_executable(osrm-extract ${ExtractorSources} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION>)
|
||||
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(RESTRICTION OBJECT data_structures/restriction_map.cpp)
|
||||
|
||||
file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp Util/compute_angle.cpp {RestrictionMapGlob})
|
||||
file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp {RestrictionMapGlob})
|
||||
set(PrepareSources prepare.cpp ${PrepareGlob})
|
||||
add_executable(osrm-prepare ${PrepareSources} $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION>)
|
||||
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>)
|
||||
|
||||
file(GLOB ServerGlob Server/*.cpp)
|
||||
file(GLOB ServerGlob server/*.cpp)
|
||||
file(GLOB DescriptorGlob descriptors/*.cpp)
|
||||
file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp Util/bearing.cpp)
|
||||
file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp util/bearing.cpp)
|
||||
list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp)
|
||||
file(GLOB CoordinateGlob data_structures/Coordinate.cpp)
|
||||
file(GLOB CoordinateGlob data_structures/coordinate*.cpp)
|
||||
file(GLOB AlgorithmGlob algorithms/*.cpp)
|
||||
file(GLOB HttpGlob Server/Http/*.cpp)
|
||||
file(GLOB LibOSRMGlob Library/*.cpp)
|
||||
file(GLOB DataStructureTestsGlob UnitTests/data_structures/*.cpp data_structures/hilbert_value.cpp)
|
||||
file(GLOB AlgorithmTestsGlob UnitTests/Algorithms/*.cpp)
|
||||
file(GLOB HttpGlob server/http/*.cpp)
|
||||
file(GLOB LibOSRMGlob library/*.cpp)
|
||||
file(GLOB DataStructureTestsGlob unit_tests/data_structures/*.cpp data_structures/hilbert_value.cpp)
|
||||
file(GLOB AlgorithmTestsGlob unit_tests/algorithms/*.cpp)
|
||||
|
||||
set(
|
||||
OSRMSources
|
||||
${LibOSRMGlob}
|
||||
${DescriptorGlob}
|
||||
${DatastructureGlob}
|
||||
${CoordinateGlob}
|
||||
${AlgorithmGlob}
|
||||
${HttpGlob}
|
||||
)
|
||||
|
||||
add_library(COORDINATE OBJECT ${CoordinateGlob})
|
||||
add_library(FINGERPRINT OBJECT Util/finger_print.cpp)
|
||||
add_library(GITDESCRIPTION OBJECT Util/git_sha.cpp)
|
||||
add_library(OSRM ${OSRMSources} $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION>)
|
||||
add_library(GITDESCRIPTION OBJECT util/git_sha.cpp)
|
||||
add_library(OSRM ${OSRMSources} $<TARGET_OBJECTS:ANGLE> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||
|
||||
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>)
|
||||
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
|
||||
add_executable(datastructure-tests EXCLUDE_FROM_ALL UnitTests/datastructure_tests.cpp ${DataStructureTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION>)
|
||||
add_executable(algorithm-tests EXCLUDE_FROM_ALL UnitTests/algorithm_tests.cpp ${AlgorithmTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION>)
|
||||
add_executable(datastructure-tests EXCLUDE_FROM_ALL unit_tests/datastructure_tests.cpp ${DataStructureTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||
add_executable(algorithm-tests EXCLUDE_FROM_ALL unit_tests/algorithm_tests.cpp ${AlgorithmTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION>)
|
||||
|
||||
# Benchmarks
|
||||
add_executable(rtree-bench EXCLUDE_FROM_ALL benchmarks/static_rtree.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION>)
|
||||
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>)
|
||||
|
||||
# Check the release mode
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
@ -109,7 +113,7 @@ if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
endif()
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
message(STATUS "Configuring OSRM in debug mode")
|
||||
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} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||
set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||
@ -119,46 +123,54 @@ if(CMAKE_BUILD_TYPE MATCHES Release)
|
||||
message(STATUS "Configuring OSRM in release mode")
|
||||
# Check if LTO is available
|
||||
set(LTO_FLAGS "")
|
||||
CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG)
|
||||
if (HAS_LTO_FLAG)
|
||||
set(LTO_FLAGS "${LTO_FLAGS} -flto")
|
||||
check_cxx_compiler_flag("-flto" LTO_AVAILABLE)
|
||||
if(LTO_AVAILABLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
|
||||
set(CHECK_LTO_SRC "int main(){return 0;}")
|
||||
check_cxx_source_compiles("${CHECK_LTO_SRC}" LTO_WORKS)
|
||||
if(LTO_WORKS)
|
||||
message(STATUS "LTO working")
|
||||
else()
|
||||
message(STATUS "LTO broken")
|
||||
set(CMAKE_CXX_FLAGS "${OLD_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
# Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND
|
||||
NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0" AND NOT MINGW)
|
||||
message(STATUS "Using gcc specific binutils for LTO.")
|
||||
set(CMAKE_AR "/usr/bin/gcc-ar")
|
||||
set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
|
||||
endif()
|
||||
endif (HAS_LTO_FLAG)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT WIN32)
|
||||
add_definitions(-DBOOST_TEST_DYN_LINK)
|
||||
if(NOT WIN32)
|
||||
add_definitions(-DBOOST_TEST_DYN_LINK)
|
||||
endif()
|
||||
|
||||
# Configuring compilers
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
|
||||
# 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")
|
||||
CHECK_CXX_COMPILER_FLAG("-fdiagnostics-color=auto" HAS_COLOR_FLAG)
|
||||
check_cxx_compiler_flag("-fdiagnostics-color=auto" HAS_COLOR_FLAG)
|
||||
if(NOT HAS_COLOR_FLAG)
|
||||
set(COLOR_FLAG "")
|
||||
endif()
|
||||
# using GCC
|
||||
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)
|
||||
SET(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
|
||||
set(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
|
||||
endif()
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
||||
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel")
|
||||
# using Intel C++
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -ipo -fPIC")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
|
||||
# using Visual Studio C++
|
||||
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} date_time chrono zlib)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
@ -171,8 +183,8 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
endif()
|
||||
|
||||
# Activate C++11
|
||||
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
ADD_DEFINITIONS(-std=c++11)
|
||||
if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ")
|
||||
endif()
|
||||
|
||||
# Configuring other platform dependencies
|
||||
@ -242,7 +254,7 @@ 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)
|
||||
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
|
||||
target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES})
|
||||
else()
|
||||
@ -255,18 +267,20 @@ find_package(EXPAT REQUIRED)
|
||||
include_directories(${EXPAT_INCLUDE_DIRS})
|
||||
target_link_libraries(osrm-extract ${EXPAT_LIBRARIES})
|
||||
|
||||
find_package( STXXL REQUIRED )
|
||||
find_package(STXXL REQUIRED)
|
||||
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})
|
||||
|
||||
if(MINGW)
|
||||
# STXXL needs OpenMP library
|
||||
target_link_libraries(osrm-extract gomp)
|
||||
set(OpenMP_FIND_QUIETLY ON)
|
||||
find_package(OpenMP)
|
||||
if(OPENMP_FOUND)
|
||||
message(STATUS "OpenMP support found. Linking just in case for stxxl")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
find_package( OSMPBF REQUIRED )
|
||||
find_package(OSMPBF REQUIRED)
|
||||
include_directories(${OSMPBF_INCLUDE_DIR})
|
||||
target_link_libraries(osrm-extract ${OSMPBF_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${OSMPBF_LIBRARY})
|
||||
@ -285,11 +299,16 @@ include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(osrm-extract ${ZLIB_LIBRARY})
|
||||
target_link_libraries(osrm-routed ${ZLIB_LIBRARY})
|
||||
|
||||
if (ENABLE_JSON_LOGGING)
|
||||
message(STATUS "Enabling json logging")
|
||||
add_definitions(-DENABLE_JSON_LOGGING)
|
||||
endif()
|
||||
|
||||
if(WITH_TOOLS OR BUILD_TOOLS)
|
||||
message(STATUS "Activating OSRM internal tools")
|
||||
find_package(GDAL)
|
||||
if(GDAL_FOUND)
|
||||
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>)
|
||||
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})
|
||||
include_directories(${GDAL_INCLUDE_DIR})
|
||||
target_link_libraries(
|
||||
@ -299,7 +318,7 @@ if(WITH_TOOLS OR BUILD_TOOLS)
|
||||
else()
|
||||
message(FATAL_ERROR "libgdal and/or development headers not found")
|
||||
endif()
|
||||
add_executable(osrm-cli tools/simpleclient.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER>)
|
||||
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>)
|
||||
@ -309,10 +328,12 @@ if(WITH_TOOLS OR BUILD_TOOLS)
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(osrm-unlock-all rt)
|
||||
endif()
|
||||
add_executable(osrm-check-hsgr tools/check-hsgr.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:LOGGER>)
|
||||
add_executable(osrm-check-hsgr tools/check-hsgr.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER>)
|
||||
target_link_libraries(osrm-check-hsgr ${Boost_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})
|
||||
add_executable(osrm-graph-compare tools/graph_compare.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-graph-compare ${Boost_LIBRARIES} ${TBB_LIBRARIES})
|
||||
|
||||
install(TARGETS osrm-cli DESTINATION bin)
|
||||
install(TARGETS osrm-io-benchmark DESTINATION bin)
|
||||
@ -321,7 +342,8 @@ if(WITH_TOOLS OR BUILD_TOOLS)
|
||||
install(TARGETS osrm-springclean DESTINATION bin)
|
||||
endif()
|
||||
|
||||
file(GLOB InstallGlob Include/osrm/*.h Library/OSRM.h)
|
||||
file(GLOB InstallGlob include/osrm/*.hpp library/osrm.hpp)
|
||||
file(GLOB VariantGlob third_party/variant/*.hpp)
|
||||
|
||||
# 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
|
||||
@ -332,6 +354,7 @@ set_property(TARGET osrm-datastore PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
|
||||
install(FILES ${InstallGlob} DESTINATION include/osrm)
|
||||
install(FILES ${VariantGlob} DESTINATION include/variant)
|
||||
install(TARGETS osrm-extract DESTINATION bin)
|
||||
install(TARGETS osrm-prepare DESTINATION bin)
|
||||
install(TARGETS osrm-datastore DESTINATION bin)
|
||||
@ -340,13 +363,13 @@ install(TARGETS OSRM DESTINATION lib)
|
||||
list(GET Boost_LIBRARIES 1 BOOST_LIBRARY_FIRST)
|
||||
get_filename_component(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_FIRST}" PATH)
|
||||
set(BOOST_LIBRARY_LISTING "-L${BOOST_LIBRARY_LISTING}")
|
||||
foreach (lib ${Boost_LIBRARIES})
|
||||
foreach(lib ${Boost_LIBRARIES})
|
||||
get_filename_component(BOOST_LIBRARY_NAME "${lib}" NAME_WE)
|
||||
string(REPLACE "lib" "" BOOST_LIBRARY_NAME ${BOOST_LIBRARY_NAME})
|
||||
set(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_LISTING} -l${BOOST_LIBRARY_NAME}")
|
||||
endforeach ()
|
||||
endforeach()
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig)
|
||||
|
||||
if(BUILD_DEBIAN_PACKAGE)
|
||||
|
2
Gemfile
2
Gemfile
@ -4,4 +4,4 @@ gem "cucumber"
|
||||
gem "rake"
|
||||
gem "osmlib-base"
|
||||
gem "sys-proctable"
|
||||
gem "rspec-expectations"
|
||||
gem "rspec-expectations"
|
||||
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, 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 FIXED_POINT_COORDINATE_H_
|
||||
#define FIXED_POINT_COORDINATE_H_
|
||||
|
||||
#include <iosfwd> //for std::ostream
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr float COORDINATE_PRECISION = 1000000.f;
|
||||
}
|
||||
struct FixedPointCoordinate
|
||||
{
|
||||
int lat;
|
||||
int lon;
|
||||
|
||||
FixedPointCoordinate();
|
||||
FixedPointCoordinate(int lat, int lon);
|
||||
|
||||
template<class T>
|
||||
FixedPointCoordinate(const T &coordinate) : lat(coordinate.lat), lon(coordinate.lon)
|
||||
{
|
||||
static_assert(std::is_same<decltype(lat), decltype(coordinate.lat)>::value, "coordinate types incompatible");
|
||||
static_assert(std::is_same<decltype(lon), decltype(coordinate.lon)>::value, "coordinate types incompatible");
|
||||
}
|
||||
|
||||
void Reset();
|
||||
bool isSet() const;
|
||||
bool is_valid() const;
|
||||
bool operator==(const FixedPointCoordinate &other) const;
|
||||
|
||||
static double
|
||||
ApproximateDistance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
|
||||
static double ApproximateDistance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
static float ApproximateEuclideanDistance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
static float
|
||||
ApproximateEuclideanDistance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
|
||||
static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
static void convertInternalLatLonToString(const int value, std::string &output);
|
||||
|
||||
static void convertInternalCoordinateToString(const FixedPointCoordinate &coordinate,
|
||||
std::string &output);
|
||||
|
||||
static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate,
|
||||
std::string &output);
|
||||
|
||||
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location);
|
||||
|
||||
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio);
|
||||
|
||||
static int
|
||||
OrderedPerpendicularDistanceApproximation(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location);
|
||||
|
||||
static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B);
|
||||
|
||||
float GetBearing(const FixedPointCoordinate &other) const;
|
||||
|
||||
void Output(std::ostream &out) const;
|
||||
|
||||
static float DegreeToRadian(const float degree);
|
||||
static float RadianToDegree(const float radian);
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate const &coordinate)
|
||||
{
|
||||
coordinate.Output(out_stream);
|
||||
return out_stream;
|
||||
}
|
||||
|
||||
#endif /* FIXED_POINT_COORDINATE_H_ */
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, 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 REPLY_H
|
||||
#define REPLY_H
|
||||
|
||||
#include "Header.h"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace http
|
||||
{
|
||||
|
||||
const char okHTML[] = "";
|
||||
const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}";
|
||||
const char internalServerErrorHTML[] =
|
||||
"{\"status\": 500,\"status_message\":\"Internal Server Error\"}";
|
||||
const char seperators[] = {':', ' '};
|
||||
const char crlf[] = {'\r', '\n'};
|
||||
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
||||
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
|
||||
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
|
||||
|
||||
class Reply
|
||||
{
|
||||
public:
|
||||
enum status_type
|
||||
{ ok = 200,
|
||||
badRequest = 400,
|
||||
internalServerError = 500 } status;
|
||||
|
||||
std::vector<Header> headers;
|
||||
std::vector<boost::asio::const_buffer> ToBuffers();
|
||||
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
||||
std::vector<char> content;
|
||||
static Reply StockReply(status_type status);
|
||||
void SetSize(const unsigned size);
|
||||
void SetUncompressedSize();
|
||||
|
||||
Reply();
|
||||
|
||||
private:
|
||||
std::string ToString(Reply::status_type status);
|
||||
boost::asio::const_buffer ToBuffer(Reply::status_type status);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // REPLY_H
|
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, 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 APIGRAMMAR_H_
|
||||
#define APIGRAMMAR_H_
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/qi_action.hpp>
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
template <typename Iterator, class HandlerT>
|
||||
struct APIGrammar : qi::grammar<Iterator>
|
||||
{
|
||||
explicit APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h)
|
||||
{
|
||||
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query) >> -(uturns);
|
||||
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | u | cmp | language | instruction | geometry | alt_route | old_API | num_results) ) ;
|
||||
|
||||
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
|
||||
output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
|
||||
jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> stringwithPercent[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
|
||||
checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> qi::uint_[boost::bind(&HandlerT::setChecksum, handler, ::_1)];
|
||||
instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)];
|
||||
geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)];
|
||||
cmp = (-qi::lit('&')) >> qi::lit("compression") >> '=' >> qi::bool_[boost::bind(&HandlerT::setCompressionFlag, handler, ::_1)];
|
||||
location = (-qi::lit('&')) >> qi::lit("loc") >> '=' >> (qi::double_ >> qi::lit(',') >> qi::double_)[boost::bind(&HandlerT::addCoordinate, handler, ::_1)];
|
||||
hint = (-qi::lit('&')) >> qi::lit("hint") >> '=' >> stringwithDot[boost::bind(&HandlerT::addHint, handler, ::_1)];
|
||||
u = (-qi::lit('&')) >> qi::lit("u") >> '=' >> qi::bool_[boost::bind(&HandlerT::setUTurn, handler, ::_1)];
|
||||
uturns = (-qi::lit('&')) >> qi::lit("uturns") >> '=' >> qi::bool_[boost::bind(&HandlerT::setAllUTurns, handler, ::_1)];
|
||||
language = (-qi::lit('&')) >> qi::lit("hl") >> '=' >> string[boost::bind(&HandlerT::setLanguage, handler, ::_1)];
|
||||
alt_route = (-qi::lit('&')) >> qi::lit("alt") >> '=' >> qi::bool_[boost::bind(&HandlerT::setAlternateRouteFlag, handler, ::_1)];
|
||||
old_API = (-qi::lit('&')) >> qi::lit("geomformat") >> '=' >> string[boost::bind(&HandlerT::setDeprecatedAPIFlag, handler, ::_1)];
|
||||
num_results = (-qi::lit('&')) >> qi::lit("num_results") >> '=' >> qi::short_[boost::bind(&HandlerT::setNumberOfResults, handler, ::_1)];
|
||||
|
||||
string = +(qi::char_("a-zA-Z"));
|
||||
stringwithDot = +(qi::char_("a-zA-Z0-9_.-"));
|
||||
stringwithPercent = +(qi::char_("a-zA-Z0-9_.-") | qi::char_('[') | qi::char_(']') | (qi::char_('%') >> qi::char_("0-9A-Z") >> qi::char_("0-9A-Z") ));
|
||||
}
|
||||
|
||||
qi::rule<Iterator> api_call, query;
|
||||
qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location, hint,
|
||||
stringwithDot, stringwithPercent, language, instruction, geometry,
|
||||
cmp, alt_route, u, uturns, old_API, num_results;
|
||||
|
||||
HandlerT * handler;
|
||||
};
|
||||
|
||||
#endif /* APIGRAMMAR_H_ */
|
@ -1,143 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, 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 "RequestHandler.h"
|
||||
|
||||
#include "APIGrammar.h"
|
||||
#include "Http/Request.h"
|
||||
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "../Library/OSRM.h"
|
||||
#include "../Util/json_renderer.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/string_util.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
RequestHandler::RequestHandler() : routing_machine(nullptr) {}
|
||||
|
||||
void RequestHandler::handle_request(const http::Request &req, http::Reply &reply)
|
||||
{
|
||||
// parse command
|
||||
try
|
||||
{
|
||||
std::string request;
|
||||
URIDecode(req.uri, request);
|
||||
|
||||
// deactivated as GCC apparently does not implement that, not even in 4.9
|
||||
// std::time_t t = std::time(nullptr);
|
||||
// SimpleLogger().Write() << std::put_time(std::localtime(&t), "%m-%d-%Y %H:%M:%S") <<
|
||||
// " " << req.endpoint.to_string() << " " <<
|
||||
// req.referrer << ( 0 == req.referrer.length() ? "- " :" ") <<
|
||||
// req.agent << ( 0 == req.agent.length() ? "- " :" ") << request;
|
||||
|
||||
time_t ltime;
|
||||
struct tm *time_stamp;
|
||||
|
||||
ltime = time(nullptr);
|
||||
time_stamp = localtime(<ime);
|
||||
|
||||
// log timestamp
|
||||
SimpleLogger().Write() << (time_stamp->tm_mday < 10 ? "0" : "") << time_stamp->tm_mday << "-"
|
||||
<< (time_stamp->tm_mon + 1 < 10 ? "0" : "") << (time_stamp->tm_mon + 1) << "-"
|
||||
<< 1900 + time_stamp->tm_year << " " << (time_stamp->tm_hour < 10 ? "0" : "")
|
||||
<< time_stamp->tm_hour << ":" << (time_stamp->tm_min < 10 ? "0" : "") << time_stamp->tm_min
|
||||
<< ":" << (time_stamp->tm_sec < 10 ? "0" : "") << time_stamp->tm_sec << " "
|
||||
<< req.endpoint.to_string() << " " << req.referrer
|
||||
<< (0 == req.referrer.length() ? "- " : " ") << req.agent
|
||||
<< (0 == req.agent.length() ? "- " : " ") << request;
|
||||
|
||||
RouteParameters route_parameters;
|
||||
APIGrammarParser api_parser(&route_parameters);
|
||||
|
||||
auto iter = request.begin();
|
||||
const bool result = boost::spirit::qi::parse(iter, request.end(), api_parser);
|
||||
|
||||
// check if the was an error with the request
|
||||
if (!result || (iter != request.end()))
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
reply.content.clear();
|
||||
const auto position = std::distance(request.begin(), iter);
|
||||
JSON::Object json_result;
|
||||
json_result.values["status"] = 400;
|
||||
std::string message = "Query string malformed close to position ";
|
||||
message += cast::integral_to_string(position);
|
||||
json_result.values["status_message"] = message;
|
||||
JSON::render(reply.content, json_result);
|
||||
return;
|
||||
}
|
||||
|
||||
// parsing done, lets call the right plugin to handle the request
|
||||
BOOST_ASSERT_MSG(routing_machine != nullptr, "pointer not init'ed");
|
||||
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{ // prepend response with jsonp parameter
|
||||
const std::string json_p = (route_parameters.jsonp_parameter + "(");
|
||||
reply.content.insert(reply.content.end(), json_p.begin(), json_p.end());
|
||||
}
|
||||
routing_machine->RunQuery(route_parameters, reply);
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{ // append brace to jsonp response
|
||||
reply.content.push_back(')');
|
||||
}
|
||||
|
||||
// set headers
|
||||
reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size()));
|
||||
if ("gpx" == route_parameters.output_format)
|
||||
{ // gpx file
|
||||
reply.headers.emplace_back("Content-Type", "application/gpx+xml; charset=UTF-8");
|
||||
reply.headers.emplace_back("Content-Disposition", "attachment; filename=\"route.gpx\"");
|
||||
}
|
||||
else if (route_parameters.jsonp_parameter.empty())
|
||||
{ // json file
|
||||
reply.headers.emplace_back("Content-Type", "application/json; charset=UTF-8");
|
||||
reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.json\"");
|
||||
}
|
||||
else
|
||||
{ // jsonp
|
||||
reply.headers.emplace_back("Content-Type", "text/javascript; charset=UTF-8");
|
||||
reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.js\"");
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::internalServerError);
|
||||
SimpleLogger().Write(logWARNING) << "[server error] code: " << e.what()
|
||||
<< ", uri: " << req.uri;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void RequestHandler::RegisterRoutingMachine(OSRM *osrm) { routing_machine = osrm; }
|
@ -1,310 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, 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 "RequestParser.h"
|
||||
|
||||
#include "Http/Request.h"
|
||||
|
||||
namespace http
|
||||
{
|
||||
|
||||
RequestParser::RequestParser() : state_(method_start), header({"", ""}) {}
|
||||
|
||||
void RequestParser::Reset() { state_ = method_start; }
|
||||
|
||||
boost::tuple<boost::tribool, char *>
|
||||
RequestParser::Parse(Request &req, char *begin, char *end, http::CompressionType &compression_type)
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
boost::tribool result = consume(req, *begin++, compression_type);
|
||||
if (result || !result)
|
||||
{
|
||||
return boost::make_tuple(result, begin);
|
||||
}
|
||||
}
|
||||
boost::tribool result = boost::indeterminate;
|
||||
return boost::make_tuple(result, begin);
|
||||
}
|
||||
|
||||
boost::tribool
|
||||
RequestParser::consume(Request &req, char input, http::CompressionType &compression_type)
|
||||
{
|
||||
switch (state_)
|
||||
{
|
||||
case method_start:
|
||||
if (!isChar(input) || isCTL(input) || isTSpecial(input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
state_ = method;
|
||||
return boost::indeterminate;
|
||||
case method:
|
||||
if (input == ' ')
|
||||
{
|
||||
state_ = uri;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (!isChar(input) || isCTL(input) || isTSpecial(input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return boost::indeterminate;
|
||||
case uri_start:
|
||||
if (isCTL(input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
state_ = uri;
|
||||
req.uri.push_back(input);
|
||||
return boost::indeterminate;
|
||||
case uri:
|
||||
if (input == ' ')
|
||||
{
|
||||
state_ = http_version_h;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (isCTL(input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
req.uri.push_back(input);
|
||||
return boost::indeterminate;
|
||||
case http_version_h:
|
||||
if (input == 'H')
|
||||
{
|
||||
state_ = http_version_t_1;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
case http_version_t_1:
|
||||
if (input == 'T')
|
||||
{
|
||||
state_ = http_version_t_2;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
case http_version_t_2:
|
||||
if (input == 'T')
|
||||
{
|
||||
state_ = http_version_p;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
case http_version_p:
|
||||
if (input == 'P')
|
||||
{
|
||||
state_ = http_version_slash;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
case http_version_slash:
|
||||
if (input == '/')
|
||||
{
|
||||
state_ = http_version_major_start;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
case http_version_major_start:
|
||||
if (isDigit(input))
|
||||
{
|
||||
state_ = http_version_major;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
case http_version_major:
|
||||
if (input == '.')
|
||||
{
|
||||
state_ = http_version_minor_start;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (isDigit(input))
|
||||
{
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
case http_version_minor_start:
|
||||
if (isDigit(input))
|
||||
{
|
||||
state_ = http_version_minor;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
case http_version_minor:
|
||||
if (input == '\r')
|
||||
{
|
||||
state_ = expecting_newline_1;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (isDigit(input))
|
||||
{
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
case expecting_newline_1:
|
||||
if (input == '\n')
|
||||
{
|
||||
state_ = header_line_start;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
case header_line_start:
|
||||
if (header.name == "Accept-Encoding")
|
||||
{
|
||||
/* giving gzip precedence over deflate */
|
||||
if (header.value.find("deflate") != std::string::npos)
|
||||
{
|
||||
compression_type = deflateRFC1951;
|
||||
}
|
||||
if (header.value.find("gzip") != std::string::npos)
|
||||
{
|
||||
compression_type = gzipRFC1952;
|
||||
}
|
||||
}
|
||||
|
||||
if ("Referer" == header.name)
|
||||
{
|
||||
req.referrer = header.value;
|
||||
}
|
||||
|
||||
if ("User-Agent" == header.name)
|
||||
{
|
||||
req.agent = header.value;
|
||||
}
|
||||
|
||||
if (input == '\r')
|
||||
{
|
||||
state_ = expecting_newline_3;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (!isChar(input) || isCTL(input) || isTSpecial(input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
state_ = header_name;
|
||||
header.Clear();
|
||||
header.name.push_back(input);
|
||||
return boost::indeterminate;
|
||||
case header_lws:
|
||||
if (input == '\r')
|
||||
{
|
||||
state_ = expecting_newline_2;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (input == ' ' || input == '\t')
|
||||
{
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (isCTL(input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
state_ = header_value;
|
||||
return boost::indeterminate;
|
||||
case header_name:
|
||||
if (input == ':')
|
||||
{
|
||||
state_ = space_before_header_value;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (!isChar(input) || isCTL(input) || isTSpecial(input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
header.name.push_back(input);
|
||||
return boost::indeterminate;
|
||||
case space_before_header_value:
|
||||
if (input == ' ')
|
||||
{
|
||||
state_ = header_value;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
case header_value:
|
||||
if (input == '\r')
|
||||
{
|
||||
state_ = expecting_newline_2;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (isCTL(input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
header.value.push_back(input);
|
||||
return boost::indeterminate;
|
||||
case expecting_newline_2:
|
||||
if (input == '\n')
|
||||
{
|
||||
state_ = header_line_start;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
default: // expecting_newline_3:
|
||||
return (input == '\n');
|
||||
// default:
|
||||
// return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool RequestParser::isChar(int character) { return character >= 0 && character <= 127; }
|
||||
|
||||
inline bool RequestParser::isCTL(int character)
|
||||
{
|
||||
return (character >= 0 && character <= 31) || (character == 127);
|
||||
}
|
||||
|
||||
inline bool RequestParser::isTSpecial(int character)
|
||||
{
|
||||
switch (character)
|
||||
{
|
||||
case '(':
|
||||
case ')':
|
||||
case '<':
|
||||
case '>':
|
||||
case '@':
|
||||
case ',':
|
||||
case ';':
|
||||
case ':':
|
||||
case '\\':
|
||||
case '"':
|
||||
case '/':
|
||||
case '[':
|
||||
case ']':
|
||||
case '?':
|
||||
case '=':
|
||||
case '{':
|
||||
case '}':
|
||||
case ' ':
|
||||
case '\t':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool RequestParser::isDigit(int character) { return character >= '0' && character <= '9'; }
|
||||
}
|
@ -1,790 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, 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 TRIGONOMETRY_TABLES_H
|
||||
#define TRIGONOMETRY_TABLES_H
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include <cmath>
|
||||
|
||||
#include <limits>
|
||||
|
||||
constexpr unsigned short atan_table[4096] = {
|
||||
0x0000, 0x0014, 0x0028, 0x003d, 0x0051, 0x0065,
|
||||
0x007a, 0x008e, 0x00a3, 0x00b7, 0x00cb, 0x00e0,
|
||||
0x00f4, 0x0108, 0x011d, 0x0131, 0x0146, 0x015a,
|
||||
0x016e, 0x0183, 0x0197, 0x01ab, 0x01c0, 0x01d4,
|
||||
0x01e9, 0x01fd, 0x0211, 0x0226, 0x023a, 0x024e,
|
||||
0x0263, 0x0277, 0x028c, 0x02a0, 0x02b4, 0x02c9,
|
||||
0x02dd, 0x02f1, 0x0306, 0x031a, 0x032f, 0x0343,
|
||||
0x0357, 0x036c, 0x0380, 0x0394, 0x03a9, 0x03bd,
|
||||
0x03d2, 0x03e6, 0x03fa, 0x040f, 0x0423, 0x0437,
|
||||
0x044c, 0x0460, 0x0475, 0x0489, 0x049d, 0x04b2,
|
||||
0x04c6, 0x04da, 0x04ef, 0x0503, 0x0517, 0x052c,
|
||||
0x0540, 0x0555, 0x0569, 0x057d, 0x0592, 0x05a6,
|
||||
0x05ba, 0x05cf, 0x05e3, 0x05f8, 0x060c, 0x0620,
|
||||
0x0635, 0x0649, 0x065d, 0x0672, 0x0686, 0x069b,
|
||||
0x06af, 0x06c3, 0x06d8, 0x06ec, 0x0700, 0x0715,
|
||||
0x0729, 0x073d, 0x0752, 0x0766, 0x077b, 0x078f,
|
||||
0x07a3, 0x07b8, 0x07cc, 0x07e0, 0x07f5, 0x0809,
|
||||
0x081d, 0x0832, 0x0846, 0x085b, 0x086f, 0x0883,
|
||||
0x0898, 0x08ac, 0x08c0, 0x08d5, 0x08e9, 0x08fd,
|
||||
0x0912, 0x0926, 0x093b, 0x094f, 0x0963, 0x0978,
|
||||
0x098c, 0x09a0, 0x09b5, 0x09c9, 0x09dd, 0x09f2,
|
||||
0x0a06, 0x0a1a, 0x0a2f, 0x0a43, 0x0a58, 0x0a6c,
|
||||
0x0a80, 0x0a95, 0x0aa9, 0x0abd, 0x0ad2, 0x0ae6,
|
||||
0x0afa, 0x0b0f, 0x0b23, 0x0b37, 0x0b4c, 0x0b60,
|
||||
0x0b75, 0x0b89, 0x0b9d, 0x0bb2, 0x0bc6, 0x0bda,
|
||||
0x0bef, 0x0c03, 0x0c17, 0x0c2c, 0x0c40, 0x0c54,
|
||||
0x0c69, 0x0c7d, 0x0c91, 0x0ca6, 0x0cba, 0x0cce,
|
||||
0x0ce3, 0x0cf7, 0x0d0b, 0x0d20, 0x0d34, 0x0d48,
|
||||
0x0d5d, 0x0d71, 0x0d86, 0x0d9a, 0x0dae, 0x0dc3,
|
||||
0x0dd7, 0x0deb, 0x0e00, 0x0e14, 0x0e28, 0x0e3d,
|
||||
0x0e51, 0x0e65, 0x0e7a, 0x0e8e, 0x0ea2, 0x0eb7,
|
||||
0x0ecb, 0x0edf, 0x0ef4, 0x0f08, 0x0f1c, 0x0f31,
|
||||
0x0f45, 0x0f59, 0x0f6e, 0x0f82, 0x0f96, 0x0fab,
|
||||
0x0fbf, 0x0fd3, 0x0fe8, 0x0ffc, 0x1010, 0x1025,
|
||||
0x1039, 0x104d, 0x1062, 0x1076, 0x108a, 0x109e,
|
||||
0x10b3, 0x10c7, 0x10db, 0x10f0, 0x1104, 0x1118,
|
||||
0x112d, 0x1141, 0x1155, 0x116a, 0x117e, 0x1192,
|
||||
0x11a7, 0x11bb, 0x11cf, 0x11e4, 0x11f8, 0x120c,
|
||||
0x1221, 0x1235, 0x1249, 0x125d, 0x1272, 0x1286,
|
||||
0x129a, 0x12af, 0x12c3, 0x12d7, 0x12ec, 0x1300,
|
||||
0x1314, 0x1329, 0x133d, 0x1351, 0x1365, 0x137a,
|
||||
0x138e, 0x13a2, 0x13b7, 0x13cb, 0x13df, 0x13f4,
|
||||
0x1408, 0x141c, 0x1431, 0x1445, 0x1459, 0x146d,
|
||||
0x1482, 0x1496, 0x14aa, 0x14bf, 0x14d3, 0x14e7,
|
||||
0x14fb, 0x1510, 0x1524, 0x1538, 0x154d, 0x1561,
|
||||
0x1575, 0x1589, 0x159e, 0x15b2, 0x15c6, 0x15db,
|
||||
0x15ef, 0x1603, 0x1617, 0x162c, 0x1640, 0x1654,
|
||||
0x1669, 0x167d, 0x1691, 0x16a5, 0x16ba, 0x16ce,
|
||||
0x16e2, 0x16f7, 0x170b, 0x171f, 0x1733, 0x1748,
|
||||
0x175c, 0x1770, 0x1784, 0x1799, 0x17ad, 0x17c1,
|
||||
0x17d6, 0x17ea, 0x17fe, 0x1812, 0x1827, 0x183b,
|
||||
0x184f, 0x1863, 0x1878, 0x188c, 0x18a0, 0x18b4,
|
||||
0x18c9, 0x18dd, 0x18f1, 0x1905, 0x191a, 0x192e,
|
||||
0x1942, 0x1957, 0x196b, 0x197f, 0x1993, 0x19a8,
|
||||
0x19bc, 0x19d0, 0x19e4, 0x19f9, 0x1a0d, 0x1a21,
|
||||
0x1a35, 0x1a49, 0x1a5e, 0x1a72, 0x1a86, 0x1a9a,
|
||||
0x1aaf, 0x1ac3, 0x1ad7, 0x1aeb, 0x1b00, 0x1b14,
|
||||
0x1b28, 0x1b3c, 0x1b51, 0x1b65, 0x1b79, 0x1b8d,
|
||||
0x1ba2, 0x1bb6, 0x1bca, 0x1bde, 0x1bf2, 0x1c07,
|
||||
0x1c1b, 0x1c2f, 0x1c43, 0x1c58, 0x1c6c, 0x1c80,
|
||||
0x1c94, 0x1ca8, 0x1cbd, 0x1cd1, 0x1ce5, 0x1cf9,
|
||||
0x1d0e, 0x1d22, 0x1d36, 0x1d4a, 0x1d5e, 0x1d73,
|
||||
0x1d87, 0x1d9b, 0x1daf, 0x1dc3, 0x1dd8, 0x1dec,
|
||||
0x1e00, 0x1e14, 0x1e28, 0x1e3d, 0x1e51, 0x1e65,
|
||||
0x1e79, 0x1e8d, 0x1ea2, 0x1eb6, 0x1eca, 0x1ede,
|
||||
0x1ef2, 0x1f07, 0x1f1b, 0x1f2f, 0x1f43, 0x1f57,
|
||||
0x1f6c, 0x1f80, 0x1f94, 0x1fa8, 0x1fbc, 0x1fd1,
|
||||
0x1fe5, 0x1ff9, 0x200d, 0x2021, 0x2035, 0x204a,
|
||||
0x205e, 0x2072, 0x2086, 0x209a, 0x20ae, 0x20c3,
|
||||
0x20d7, 0x20eb, 0x20ff, 0x2113, 0x2127, 0x213c,
|
||||
0x2150, 0x2164, 0x2178, 0x218c, 0x21a0, 0x21b5,
|
||||
0x21c9, 0x21dd, 0x21f1, 0x2205, 0x2219, 0x222e,
|
||||
0x2242, 0x2256, 0x226a, 0x227e, 0x2292, 0x22a6,
|
||||
0x22bb, 0x22cf, 0x22e3, 0x22f7, 0x230b, 0x231f,
|
||||
0x2333, 0x2348, 0x235c, 0x2370, 0x2384, 0x2398,
|
||||
0x23ac, 0x23c0, 0x23d5, 0x23e9, 0x23fd, 0x2411,
|
||||
0x2425, 0x2439, 0x244d, 0x2461, 0x2476, 0x248a,
|
||||
0x249e, 0x24b2, 0x24c6, 0x24da, 0x24ee, 0x2502,
|
||||
0x2517, 0x252b, 0x253f, 0x2553, 0x2567, 0x257b,
|
||||
0x258f, 0x25a3, 0x25b7, 0x25cb, 0x25e0, 0x25f4,
|
||||
0x2608, 0x261c, 0x2630, 0x2644, 0x2658, 0x266c,
|
||||
0x2680, 0x2694, 0x26a9, 0x26bd, 0x26d1, 0x26e5,
|
||||
0x26f9, 0x270d, 0x2721, 0x2735, 0x2749, 0x275d,
|
||||
0x2771, 0x2785, 0x279a, 0x27ae, 0x27c2, 0x27d6,
|
||||
0x27ea, 0x27fe, 0x2812, 0x2826, 0x283a, 0x284e,
|
||||
0x2862, 0x2876, 0x288a, 0x289e, 0x28b3, 0x28c7,
|
||||
0x28db, 0x28ef, 0x2903, 0x2917, 0x292b, 0x293f,
|
||||
0x2953, 0x2967, 0x297b, 0x298f, 0x29a3, 0x29b7,
|
||||
0x29cb, 0x29df, 0x29f3, 0x2a07, 0x2a1b, 0x2a2f,
|
||||
0x2a43, 0x2a58, 0x2a6c, 0x2a80, 0x2a94, 0x2aa8,
|
||||
0x2abc, 0x2ad0, 0x2ae4, 0x2af8, 0x2b0c, 0x2b20,
|
||||
0x2b34, 0x2b48, 0x2b5c, 0x2b70, 0x2b84, 0x2b98,
|
||||
0x2bac, 0x2bc0, 0x2bd4, 0x2be8, 0x2bfc, 0x2c10,
|
||||
0x2c24, 0x2c38, 0x2c4c, 0x2c60, 0x2c74, 0x2c88,
|
||||
0x2c9c, 0x2cb0, 0x2cc4, 0x2cd8, 0x2cec, 0x2d00,
|
||||
0x2d14, 0x2d28, 0x2d3c, 0x2d50, 0x2d64, 0x2d78,
|
||||
0x2d8c, 0x2da0, 0x2db4, 0x2dc8, 0x2ddc, 0x2df0,
|
||||
0x2e04, 0x2e18, 0x2e2c, 0x2e40, 0x2e54, 0x2e68,
|
||||
0x2e7c, 0x2e90, 0x2ea3, 0x2eb7, 0x2ecb, 0x2edf,
|
||||
0x2ef3, 0x2f07, 0x2f1b, 0x2f2f, 0x2f43, 0x2f57,
|
||||
0x2f6b, 0x2f7f, 0x2f93, 0x2fa7, 0x2fbb, 0x2fcf,
|
||||
0x2fe3, 0x2ff7, 0x300b, 0x301e, 0x3032, 0x3046,
|
||||
0x305a, 0x306e, 0x3082, 0x3096, 0x30aa, 0x30be,
|
||||
0x30d2, 0x30e6, 0x30fa, 0x310e, 0x3122, 0x3135,
|
||||
0x3149, 0x315d, 0x3171, 0x3185, 0x3199, 0x31ad,
|
||||
0x31c1, 0x31d5, 0x31e9, 0x31fd, 0x3210, 0x3224,
|
||||
0x3238, 0x324c, 0x3260, 0x3274, 0x3288, 0x329c,
|
||||
0x32b0, 0x32c3, 0x32d7, 0x32eb, 0x32ff, 0x3313,
|
||||
0x3327, 0x333b, 0x334f, 0x3363, 0x3376, 0x338a,
|
||||
0x339e, 0x33b2, 0x33c6, 0x33da, 0x33ee, 0x3401,
|
||||
0x3415, 0x3429, 0x343d, 0x3451, 0x3465, 0x3479,
|
||||
0x348c, 0x34a0, 0x34b4, 0x34c8, 0x34dc, 0x34f0,
|
||||
0x3504, 0x3517, 0x352b, 0x353f, 0x3553, 0x3567,
|
||||
0x357b, 0x358e, 0x35a2, 0x35b6, 0x35ca, 0x35de,
|
||||
0x35f2, 0x3605, 0x3619, 0x362d, 0x3641, 0x3655,
|
||||
0x3668, 0x367c, 0x3690, 0x36a4, 0x36b8, 0x36cb,
|
||||
0x36df, 0x36f3, 0x3707, 0x371b, 0x372f, 0x3742,
|
||||
0x3756, 0x376a, 0x377e, 0x3791, 0x37a5, 0x37b9,
|
||||
0x37cd, 0x37e1, 0x37f4, 0x3808, 0x381c, 0x3830,
|
||||
0x3844, 0x3857, 0x386b, 0x387f, 0x3893, 0x38a6,
|
||||
0x38ba, 0x38ce, 0x38e2, 0x38f5, 0x3909, 0x391d,
|
||||
0x3931, 0x3944, 0x3958, 0x396c, 0x3980, 0x3993,
|
||||
0x39a7, 0x39bb, 0x39cf, 0x39e2, 0x39f6, 0x3a0a,
|
||||
0x3a1e, 0x3a31, 0x3a45, 0x3a59, 0x3a6d, 0x3a80,
|
||||
0x3a94, 0x3aa8, 0x3abb, 0x3acf, 0x3ae3, 0x3af7,
|
||||
0x3b0a, 0x3b1e, 0x3b32, 0x3b45, 0x3b59, 0x3b6d,
|
||||
0x3b81, 0x3b94, 0x3ba8, 0x3bbc, 0x3bcf, 0x3be3,
|
||||
0x3bf7, 0x3c0b, 0x3c1e, 0x3c32, 0x3c46, 0x3c59,
|
||||
0x3c6d, 0x3c81, 0x3c94, 0x3ca8, 0x3cbc, 0x3ccf,
|
||||
0x3ce3, 0x3cf7, 0x3d0a, 0x3d1e, 0x3d32, 0x3d45,
|
||||
0x3d59, 0x3d6d, 0x3d80, 0x3d94, 0x3da8, 0x3dbb,
|
||||
0x3dcf, 0x3de3, 0x3df6, 0x3e0a, 0x3e1e, 0x3e31,
|
||||
0x3e45, 0x3e59, 0x3e6c, 0x3e80, 0x3e93, 0x3ea7,
|
||||
0x3ebb, 0x3ece, 0x3ee2, 0x3ef6, 0x3f09, 0x3f1d,
|
||||
0x3f30, 0x3f44, 0x3f58, 0x3f6b, 0x3f7f, 0x3f93,
|
||||
0x3fa6, 0x3fba, 0x3fcd, 0x3fe1, 0x3ff5, 0x4008,
|
||||
0x401c, 0x402f, 0x4043, 0x4057, 0x406a, 0x407e,
|
||||
0x4091, 0x40a5, 0x40b8, 0x40cc, 0x40e0, 0x40f3,
|
||||
0x4107, 0x411a, 0x412e, 0x4142, 0x4155, 0x4169,
|
||||
0x417c, 0x4190, 0x41a3, 0x41b7, 0x41ca, 0x41de,
|
||||
0x41f2, 0x4205, 0x4219, 0x422c, 0x4240, 0x4253,
|
||||
0x4267, 0x427a, 0x428e, 0x42a1, 0x42b5, 0x42c9,
|
||||
0x42dc, 0x42f0, 0x4303, 0x4317, 0x432a, 0x433e,
|
||||
0x4351, 0x4365, 0x4378, 0x438c, 0x439f, 0x43b3,
|
||||
0x43c6, 0x43da, 0x43ed, 0x4401, 0x4414, 0x4428,
|
||||
0x443b, 0x444f, 0x4462, 0x4476, 0x4489, 0x449d,
|
||||
0x44b0, 0x44c4, 0x44d7, 0x44eb, 0x44fe, 0x4512,
|
||||
0x4525, 0x4539, 0x454c, 0x4560, 0x4573, 0x4586,
|
||||
0x459a, 0x45ad, 0x45c1, 0x45d4, 0x45e8, 0x45fb,
|
||||
0x460f, 0x4622, 0x4636, 0x4649, 0x465c, 0x4670,
|
||||
0x4683, 0x4697, 0x46aa, 0x46be, 0x46d1, 0x46e5,
|
||||
0x46f8, 0x470b, 0x471f, 0x4732, 0x4746, 0x4759,
|
||||
0x476c, 0x4780, 0x4793, 0x47a7, 0x47ba, 0x47cd,
|
||||
0x47e1, 0x47f4, 0x4808, 0x481b, 0x482e, 0x4842,
|
||||
0x4855, 0x4869, 0x487c, 0x488f, 0x48a3, 0x48b6,
|
||||
0x48ca, 0x48dd, 0x48f0, 0x4904, 0x4917, 0x492a,
|
||||
0x493e, 0x4951, 0x4965, 0x4978, 0x498b, 0x499f,
|
||||
0x49b2, 0x49c5, 0x49d9, 0x49ec, 0x49ff, 0x4a13,
|
||||
0x4a26, 0x4a39, 0x4a4d, 0x4a60, 0x4a73, 0x4a87,
|
||||
0x4a9a, 0x4aad, 0x4ac1, 0x4ad4, 0x4ae7, 0x4afb,
|
||||
0x4b0e, 0x4b21, 0x4b35, 0x4b48, 0x4b5b, 0x4b6f,
|
||||
0x4b82, 0x4b95, 0x4ba8, 0x4bbc, 0x4bcf, 0x4be2,
|
||||
0x4bf6, 0x4c09, 0x4c1c, 0x4c2f, 0x4c43, 0x4c56,
|
||||
0x4c69, 0x4c7d, 0x4c90, 0x4ca3, 0x4cb6, 0x4cca,
|
||||
0x4cdd, 0x4cf0, 0x4d03, 0x4d17, 0x4d2a, 0x4d3d,
|
||||
0x4d50, 0x4d64, 0x4d77, 0x4d8a, 0x4d9d, 0x4db1,
|
||||
0x4dc4, 0x4dd7, 0x4dea, 0x4dfe, 0x4e11, 0x4e24,
|
||||
0x4e37, 0x4e4b, 0x4e5e, 0x4e71, 0x4e84, 0x4e97,
|
||||
0x4eab, 0x4ebe, 0x4ed1, 0x4ee4, 0x4ef7, 0x4f0b,
|
||||
0x4f1e, 0x4f31, 0x4f44, 0x4f57, 0x4f6b, 0x4f7e,
|
||||
0x4f91, 0x4fa4, 0x4fb7, 0x4fcb, 0x4fde, 0x4ff1,
|
||||
0x5004, 0x5017, 0x502a, 0x503e, 0x5051, 0x5064,
|
||||
0x5077, 0x508a, 0x509d, 0x50b1, 0x50c4, 0x50d7,
|
||||
0x50ea, 0x50fd, 0x5110, 0x5123, 0x5137, 0x514a,
|
||||
0x515d, 0x5170, 0x5183, 0x5196, 0x51a9, 0x51bc,
|
||||
0x51d0, 0x51e3, 0x51f6, 0x5209, 0x521c, 0x522f,
|
||||
0x5242, 0x5255, 0x5268, 0x527c, 0x528f, 0x52a2,
|
||||
0x52b5, 0x52c8, 0x52db, 0x52ee, 0x5301, 0x5314,
|
||||
0x5327, 0x533a, 0x534e, 0x5361, 0x5374, 0x5387,
|
||||
0x539a, 0x53ad, 0x53c0, 0x53d3, 0x53e6, 0x53f9,
|
||||
0x540c, 0x541f, 0x5432, 0x5445, 0x5458, 0x546b,
|
||||
0x547e, 0x5491, 0x54a5, 0x54b8, 0x54cb, 0x54de,
|
||||
0x54f1, 0x5504, 0x5517, 0x552a, 0x553d, 0x5550,
|
||||
0x5563, 0x5576, 0x5589, 0x559c, 0x55af, 0x55c2,
|
||||
0x55d5, 0x55e8, 0x55fb, 0x560e, 0x5621, 0x5634,
|
||||
0x5647, 0x565a, 0x566d, 0x5680, 0x5693, 0x56a6,
|
||||
0x56b9, 0x56cb, 0x56de, 0x56f1, 0x5704, 0x5717,
|
||||
0x572a, 0x573d, 0x5750, 0x5763, 0x5776, 0x5789,
|
||||
0x579c, 0x57af, 0x57c2, 0x57d5, 0x57e8, 0x57fb,
|
||||
0x580e, 0x5820, 0x5833, 0x5846, 0x5859, 0x586c,
|
||||
0x587f, 0x5892, 0x58a5, 0x58b8, 0x58cb, 0x58de,
|
||||
0x58f0, 0x5903, 0x5916, 0x5929, 0x593c, 0x594f,
|
||||
0x5962, 0x5975, 0x5988, 0x599a, 0x59ad, 0x59c0,
|
||||
0x59d3, 0x59e6, 0x59f9, 0x5a0c, 0x5a1f, 0x5a31,
|
||||
0x5a44, 0x5a57, 0x5a6a, 0x5a7d, 0x5a90, 0x5aa2,
|
||||
0x5ab5, 0x5ac8, 0x5adb, 0x5aee, 0x5b01, 0x5b13,
|
||||
0x5b26, 0x5b39, 0x5b4c, 0x5b5f, 0x5b72, 0x5b84,
|
||||
0x5b97, 0x5baa, 0x5bbd, 0x5bd0, 0x5be2, 0x5bf5,
|
||||
0x5c08, 0x5c1b, 0x5c2e, 0x5c40, 0x5c53, 0x5c66,
|
||||
0x5c79, 0x5c8c, 0x5c9e, 0x5cb1, 0x5cc4, 0x5cd7,
|
||||
0x5ce9, 0x5cfc, 0x5d0f, 0x5d22, 0x5d34, 0x5d47,
|
||||
0x5d5a, 0x5d6d, 0x5d7f, 0x5d92, 0x5da5, 0x5db8,
|
||||
0x5dca, 0x5ddd, 0x5df0, 0x5e03, 0x5e15, 0x5e28,
|
||||
0x5e3b, 0x5e4d, 0x5e60, 0x5e73, 0x5e86, 0x5e98,
|
||||
0x5eab, 0x5ebe, 0x5ed0, 0x5ee3, 0x5ef6, 0x5f09,
|
||||
0x5f1b, 0x5f2e, 0x5f41, 0x5f53, 0x5f66, 0x5f79,
|
||||
0x5f8b, 0x5f9e, 0x5fb1, 0x5fc3, 0x5fd6, 0x5fe9,
|
||||
0x5ffb, 0x600e, 0x6021, 0x6033, 0x6046, 0x6059,
|
||||
0x606b, 0x607e, 0x6091, 0x60a3, 0x60b6, 0x60c8,
|
||||
0x60db, 0x60ee, 0x6100, 0x6113, 0x6126, 0x6138,
|
||||
0x614b, 0x615d, 0x6170, 0x6183, 0x6195, 0x61a8,
|
||||
0x61ba, 0x61cd, 0x61e0, 0x61f2, 0x6205, 0x6217,
|
||||
0x622a, 0x623d, 0x624f, 0x6262, 0x6274, 0x6287,
|
||||
0x6299, 0x62ac, 0x62bf, 0x62d1, 0x62e4, 0x62f6,
|
||||
0x6309, 0x631b, 0x632e, 0x6340, 0x6353, 0x6366,
|
||||
0x6378, 0x638b, 0x639d, 0x63b0, 0x63c2, 0x63d5,
|
||||
0x63e7, 0x63fa, 0x640c, 0x641f, 0x6431, 0x6444,
|
||||
0x6456, 0x6469, 0x647b, 0x648e, 0x64a0, 0x64b3,
|
||||
0x64c5, 0x64d8, 0x64ea, 0x64fd, 0x650f, 0x6522,
|
||||
0x6534, 0x6547, 0x6559, 0x656c, 0x657e, 0x6591,
|
||||
0x65a3, 0x65b5, 0x65c8, 0x65da, 0x65ed, 0x65ff,
|
||||
0x6612, 0x6624, 0x6637, 0x6649, 0x665b, 0x666e,
|
||||
0x6680, 0x6693, 0x66a5, 0x66b8, 0x66ca, 0x66dc,
|
||||
0x66ef, 0x6701, 0x6714, 0x6726, 0x6738, 0x674b,
|
||||
0x675d, 0x6770, 0x6782, 0x6794, 0x67a7, 0x67b9,
|
||||
0x67cc, 0x67de, 0x67f0, 0x6803, 0x6815, 0x6827,
|
||||
0x683a, 0x684c, 0x685e, 0x6871, 0x6883, 0x6896,
|
||||
0x68a8, 0x68ba, 0x68cd, 0x68df, 0x68f1, 0x6904,
|
||||
0x6916, 0x6928, 0x693b, 0x694d, 0x695f, 0x6972,
|
||||
0x6984, 0x6996, 0x69a8, 0x69bb, 0x69cd, 0x69df,
|
||||
0x69f2, 0x6a04, 0x6a16, 0x6a29, 0x6a3b, 0x6a4d,
|
||||
0x6a5f, 0x6a72, 0x6a84, 0x6a96, 0x6aa9, 0x6abb,
|
||||
0x6acd, 0x6adf, 0x6af2, 0x6b04, 0x6b16, 0x6b28,
|
||||
0x6b3b, 0x6b4d, 0x6b5f, 0x6b71, 0x6b84, 0x6b96,
|
||||
0x6ba8, 0x6bba, 0x6bcd, 0x6bdf, 0x6bf1, 0x6c03,
|
||||
0x6c15, 0x6c28, 0x6c3a, 0x6c4c, 0x6c5e, 0x6c70,
|
||||
0x6c83, 0x6c95, 0x6ca7, 0x6cb9, 0x6ccb, 0x6cde,
|
||||
0x6cf0, 0x6d02, 0x6d14, 0x6d26, 0x6d39, 0x6d4b,
|
||||
0x6d5d, 0x6d6f, 0x6d81, 0x6d93, 0x6da6, 0x6db8,
|
||||
0x6dca, 0x6ddc, 0x6dee, 0x6e00, 0x6e12, 0x6e25,
|
||||
0x6e37, 0x6e49, 0x6e5b, 0x6e6d, 0x6e7f, 0x6e91,
|
||||
0x6ea3, 0x6eb6, 0x6ec8, 0x6eda, 0x6eec, 0x6efe,
|
||||
0x6f10, 0x6f22, 0x6f34, 0x6f46, 0x6f58, 0x6f6b,
|
||||
0x6f7d, 0x6f8f, 0x6fa1, 0x6fb3, 0x6fc5, 0x6fd7,
|
||||
0x6fe9, 0x6ffb, 0x700d, 0x701f, 0x7031, 0x7043,
|
||||
0x7055, 0x7068, 0x707a, 0x708c, 0x709e, 0x70b0,
|
||||
0x70c2, 0x70d4, 0x70e6, 0x70f8, 0x710a, 0x711c,
|
||||
0x712e, 0x7140, 0x7152, 0x7164, 0x7176, 0x7188,
|
||||
0x719a, 0x71ac, 0x71be, 0x71d0, 0x71e2, 0x71f4,
|
||||
0x7206, 0x7218, 0x722a, 0x723c, 0x724e, 0x7260,
|
||||
0x7272, 0x7284, 0x7296, 0x72a8, 0x72ba, 0x72cc,
|
||||
0x72dd, 0x72ef, 0x7301, 0x7313, 0x7325, 0x7337,
|
||||
0x7349, 0x735b, 0x736d, 0x737f, 0x7391, 0x73a3,
|
||||
0x73b5, 0x73c7, 0x73d8, 0x73ea, 0x73fc, 0x740e,
|
||||
0x7420, 0x7432, 0x7444, 0x7456, 0x7468, 0x747a,
|
||||
0x748b, 0x749d, 0x74af, 0x74c1, 0x74d3, 0x74e5,
|
||||
0x74f7, 0x7509, 0x751a, 0x752c, 0x753e, 0x7550,
|
||||
0x7562, 0x7574, 0x7585, 0x7597, 0x75a9, 0x75bb,
|
||||
0x75cd, 0x75df, 0x75f0, 0x7602, 0x7614, 0x7626,
|
||||
0x7638, 0x764a, 0x765b, 0x766d, 0x767f, 0x7691,
|
||||
0x76a3, 0x76b4, 0x76c6, 0x76d8, 0x76ea, 0x76fb,
|
||||
0x770d, 0x771f, 0x7731, 0x7743, 0x7754, 0x7766,
|
||||
0x7778, 0x778a, 0x779b, 0x77ad, 0x77bf, 0x77d1,
|
||||
0x77e2, 0x77f4, 0x7806, 0x7818, 0x7829, 0x783b,
|
||||
0x784d, 0x785e, 0x7870, 0x7882, 0x7894, 0x78a5,
|
||||
0x78b7, 0x78c9, 0x78da, 0x78ec, 0x78fe, 0x7910,
|
||||
0x7921, 0x7933, 0x7945, 0x7956, 0x7968, 0x797a,
|
||||
0x798b, 0x799d, 0x79af, 0x79c0, 0x79d2, 0x79e4,
|
||||
0x79f5, 0x7a07, 0x7a19, 0x7a2a, 0x7a3c, 0x7a4e,
|
||||
0x7a5f, 0x7a71, 0x7a82, 0x7a94, 0x7aa6, 0x7ab7,
|
||||
0x7ac9, 0x7adb, 0x7aec, 0x7afe, 0x7b0f, 0x7b21,
|
||||
0x7b33, 0x7b44, 0x7b56, 0x7b67, 0x7b79, 0x7b8b,
|
||||
0x7b9c, 0x7bae, 0x7bbf, 0x7bd1, 0x7be2, 0x7bf4,
|
||||
0x7c06, 0x7c17, 0x7c29, 0x7c3a, 0x7c4c, 0x7c5d,
|
||||
0x7c6f, 0x7c81, 0x7c92, 0x7ca4, 0x7cb5, 0x7cc7,
|
||||
0x7cd8, 0x7cea, 0x7cfb, 0x7d0d, 0x7d1e, 0x7d30,
|
||||
0x7d41, 0x7d53, 0x7d64, 0x7d76, 0x7d87, 0x7d99,
|
||||
0x7daa, 0x7dbc, 0x7dcd, 0x7ddf, 0x7df0, 0x7e02,
|
||||
0x7e13, 0x7e25, 0x7e36, 0x7e48, 0x7e59, 0x7e6b,
|
||||
0x7e7c, 0x7e8e, 0x7e9f, 0x7eb0, 0x7ec2, 0x7ed3,
|
||||
0x7ee5, 0x7ef6, 0x7f08, 0x7f19, 0x7f2b, 0x7f3c,
|
||||
0x7f4d, 0x7f5f, 0x7f70, 0x7f82, 0x7f93, 0x7fa4,
|
||||
0x7fb6, 0x7fc7, 0x7fd9, 0x7fea, 0x7ffb, 0x800d,
|
||||
0x801e, 0x8030, 0x8041, 0x8052, 0x8064, 0x8075,
|
||||
0x8086, 0x8098, 0x80a9, 0x80bb, 0x80cc, 0x80dd,
|
||||
0x80ef, 0x8100, 0x8111, 0x8123, 0x8134, 0x8145,
|
||||
0x8157, 0x8168, 0x8179, 0x818b, 0x819c, 0x81ad,
|
||||
0x81bf, 0x81d0, 0x81e1, 0x81f3, 0x8204, 0x8215,
|
||||
0x8226, 0x8238, 0x8249, 0x825a, 0x826c, 0x827d,
|
||||
0x828e, 0x829f, 0x82b1, 0x82c2, 0x82d3, 0x82e5,
|
||||
0x82f6, 0x8307, 0x8318, 0x832a, 0x833b, 0x834c,
|
||||
0x835d, 0x836f, 0x8380, 0x8391, 0x83a2, 0x83b3,
|
||||
0x83c5, 0x83d6, 0x83e7, 0x83f8, 0x840a, 0x841b,
|
||||
0x842c, 0x843d, 0x844e, 0x8460, 0x8471, 0x8482,
|
||||
0x8493, 0x84a4, 0x84b6, 0x84c7, 0x84d8, 0x84e9,
|
||||
0x84fa, 0x850b, 0x851d, 0x852e, 0x853f, 0x8550,
|
||||
0x8561, 0x8572, 0x8584, 0x8595, 0x85a6, 0x85b7,
|
||||
0x85c8, 0x85d9, 0x85ea, 0x85fb, 0x860d, 0x861e,
|
||||
0x862f, 0x8640, 0x8651, 0x8662, 0x8673, 0x8684,
|
||||
0x8695, 0x86a7, 0x86b8, 0x86c9, 0x86da, 0x86eb,
|
||||
0x86fc, 0x870d, 0x871e, 0x872f, 0x8740, 0x8751,
|
||||
0x8762, 0x8773, 0x8784, 0x8796, 0x87a7, 0x87b8,
|
||||
0x87c9, 0x87da, 0x87eb, 0x87fc, 0x880d, 0x881e,
|
||||
0x882f, 0x8840, 0x8851, 0x8862, 0x8873, 0x8884,
|
||||
0x8895, 0x88a6, 0x88b7, 0x88c8, 0x88d9, 0x88ea,
|
||||
0x88fb, 0x890c, 0x891d, 0x892e, 0x893f, 0x8950,
|
||||
0x8961, 0x8972, 0x8983, 0x8994, 0x89a5, 0x89b6,
|
||||
0x89c6, 0x89d7, 0x89e8, 0x89f9, 0x8a0a, 0x8a1b,
|
||||
0x8a2c, 0x8a3d, 0x8a4e, 0x8a5f, 0x8a70, 0x8a81,
|
||||
0x8a92, 0x8aa3, 0x8ab3, 0x8ac4, 0x8ad5, 0x8ae6,
|
||||
0x8af7, 0x8b08, 0x8b19, 0x8b2a, 0x8b3b, 0x8b4b,
|
||||
0x8b5c, 0x8b6d, 0x8b7e, 0x8b8f, 0x8ba0, 0x8bb1,
|
||||
0x8bc1, 0x8bd2, 0x8be3, 0x8bf4, 0x8c05, 0x8c16,
|
||||
0x8c27, 0x8c37, 0x8c48, 0x8c59, 0x8c6a, 0x8c7b,
|
||||
0x8c8c, 0x8c9c, 0x8cad, 0x8cbe, 0x8ccf, 0x8ce0,
|
||||
0x8cf0, 0x8d01, 0x8d12, 0x8d23, 0x8d34, 0x8d44,
|
||||
0x8d55, 0x8d66, 0x8d77, 0x8d87, 0x8d98, 0x8da9,
|
||||
0x8dba, 0x8dca, 0x8ddb, 0x8dec, 0x8dfd, 0x8e0d,
|
||||
0x8e1e, 0x8e2f, 0x8e40, 0x8e50, 0x8e61, 0x8e72,
|
||||
0x8e83, 0x8e93, 0x8ea4, 0x8eb5, 0x8ec5, 0x8ed6,
|
||||
0x8ee7, 0x8ef8, 0x8f08, 0x8f19, 0x8f2a, 0x8f3a,
|
||||
0x8f4b, 0x8f5c, 0x8f6c, 0x8f7d, 0x8f8e, 0x8f9e,
|
||||
0x8faf, 0x8fc0, 0x8fd0, 0x8fe1, 0x8ff2, 0x9002,
|
||||
0x9013, 0x9024, 0x9034, 0x9045, 0x9056, 0x9066,
|
||||
0x9077, 0x9088, 0x9098, 0x90a9, 0x90b9, 0x90ca,
|
||||
0x90db, 0x90eb, 0x90fc, 0x910c, 0x911d, 0x912e,
|
||||
0x913e, 0x914f, 0x915f, 0x9170, 0x9181, 0x9191,
|
||||
0x91a2, 0x91b2, 0x91c3, 0x91d3, 0x91e4, 0x91f5,
|
||||
0x9205, 0x9216, 0x9226, 0x9237, 0x9247, 0x9258,
|
||||
0x9268, 0x9279, 0x9289, 0x929a, 0x92aa, 0x92bb,
|
||||
0x92cc, 0x92dc, 0x92ed, 0x92fd, 0x930e, 0x931e,
|
||||
0x932f, 0x933f, 0x9350, 0x9360, 0x9370, 0x9381,
|
||||
0x9391, 0x93a2, 0x93b2, 0x93c3, 0x93d3, 0x93e4,
|
||||
0x93f4, 0x9405, 0x9415, 0x9426, 0x9436, 0x9447,
|
||||
0x9457, 0x9467, 0x9478, 0x9488, 0x9499, 0x94a9,
|
||||
0x94ba, 0x94ca, 0x94da, 0x94eb, 0x94fb, 0x950c,
|
||||
0x951c, 0x952c, 0x953d, 0x954d, 0x955e, 0x956e,
|
||||
0x957e, 0x958f, 0x959f, 0x95af, 0x95c0, 0x95d0,
|
||||
0x95e1, 0x95f1, 0x9601, 0x9612, 0x9622, 0x9632,
|
||||
0x9643, 0x9653, 0x9663, 0x9674, 0x9684, 0x9694,
|
||||
0x96a5, 0x96b5, 0x96c5, 0x96d6, 0x96e6, 0x96f6,
|
||||
0x9707, 0x9717, 0x9727, 0x9738, 0x9748, 0x9758,
|
||||
0x9768, 0x9779, 0x9789, 0x9799, 0x97aa, 0x97ba,
|
||||
0x97ca, 0x97da, 0x97eb, 0x97fb, 0x980b, 0x981b,
|
||||
0x982c, 0x983c, 0x984c, 0x985c, 0x986d, 0x987d,
|
||||
0x988d, 0x989d, 0x98ad, 0x98be, 0x98ce, 0x98de,
|
||||
0x98ee, 0x98ff, 0x990f, 0x991f, 0x992f, 0x993f,
|
||||
0x9950, 0x9960, 0x9970, 0x9980, 0x9990, 0x99a0,
|
||||
0x99b1, 0x99c1, 0x99d1, 0x99e1, 0x99f1, 0x9a01,
|
||||
0x9a12, 0x9a22, 0x9a32, 0x9a42, 0x9a52, 0x9a62,
|
||||
0x9a72, 0x9a83, 0x9a93, 0x9aa3, 0x9ab3, 0x9ac3,
|
||||
0x9ad3, 0x9ae3, 0x9af3, 0x9b04, 0x9b14, 0x9b24,
|
||||
0x9b34, 0x9b44, 0x9b54, 0x9b64, 0x9b74, 0x9b84,
|
||||
0x9b94, 0x9ba4, 0x9bb5, 0x9bc5, 0x9bd5, 0x9be5,
|
||||
0x9bf5, 0x9c05, 0x9c15, 0x9c25, 0x9c35, 0x9c45,
|
||||
0x9c55, 0x9c65, 0x9c75, 0x9c85, 0x9c95, 0x9ca5,
|
||||
0x9cb5, 0x9cc5, 0x9cd5, 0x9ce5, 0x9cf5, 0x9d05,
|
||||
0x9d15, 0x9d25, 0x9d35, 0x9d45, 0x9d55, 0x9d65,
|
||||
0x9d75, 0x9d85, 0x9d95, 0x9da5, 0x9db5, 0x9dc5,
|
||||
0x9dd5, 0x9de5, 0x9df5, 0x9e05, 0x9e15, 0x9e25,
|
||||
0x9e35, 0x9e45, 0x9e55, 0x9e65, 0x9e74, 0x9e84,
|
||||
0x9e94, 0x9ea4, 0x9eb4, 0x9ec4, 0x9ed4, 0x9ee4,
|
||||
0x9ef4, 0x9f04, 0x9f14, 0x9f23, 0x9f33, 0x9f43,
|
||||
0x9f53, 0x9f63, 0x9f73, 0x9f83, 0x9f93, 0x9fa3,
|
||||
0x9fb2, 0x9fc2, 0x9fd2, 0x9fe2, 0x9ff2, 0xa002,
|
||||
0xa012, 0xa021, 0xa031, 0xa041, 0xa051, 0xa061,
|
||||
0xa071, 0xa080, 0xa090, 0xa0a0, 0xa0b0, 0xa0c0,
|
||||
0xa0cf, 0xa0df, 0xa0ef, 0xa0ff, 0xa10f, 0xa11e,
|
||||
0xa12e, 0xa13e, 0xa14e, 0xa15e, 0xa16d, 0xa17d,
|
||||
0xa18d, 0xa19d, 0xa1ac, 0xa1bc, 0xa1cc, 0xa1dc,
|
||||
0xa1eb, 0xa1fb, 0xa20b, 0xa21b, 0xa22a, 0xa23a,
|
||||
0xa24a, 0xa25a, 0xa269, 0xa279, 0xa289, 0xa298,
|
||||
0xa2a8, 0xa2b8, 0xa2c8, 0xa2d7, 0xa2e7, 0xa2f7,
|
||||
0xa306, 0xa316, 0xa326, 0xa335, 0xa345, 0xa355,
|
||||
0xa364, 0xa374, 0xa384, 0xa393, 0xa3a3, 0xa3b3,
|
||||
0xa3c2, 0xa3d2, 0xa3e2, 0xa3f1, 0xa401, 0xa411,
|
||||
0xa420, 0xa430, 0xa440, 0xa44f, 0xa45f, 0xa46e,
|
||||
0xa47e, 0xa48e, 0xa49d, 0xa4ad, 0xa4bc, 0xa4cc,
|
||||
0xa4dc, 0xa4eb, 0xa4fb, 0xa50a, 0xa51a, 0xa52a,
|
||||
0xa539, 0xa549, 0xa558, 0xa568, 0xa577, 0xa587,
|
||||
0xa597, 0xa5a6, 0xa5b6, 0xa5c5, 0xa5d5, 0xa5e4,
|
||||
0xa5f4, 0xa603, 0xa613, 0xa622, 0xa632, 0xa641,
|
||||
0xa651, 0xa660, 0xa670, 0xa67f, 0xa68f, 0xa69e,
|
||||
0xa6ae, 0xa6bd, 0xa6cd, 0xa6dc, 0xa6ec, 0xa6fb,
|
||||
0xa70b, 0xa71a, 0xa72a, 0xa739, 0xa749, 0xa758,
|
||||
0xa768, 0xa777, 0xa787, 0xa796, 0xa7a5, 0xa7b5,
|
||||
0xa7c4, 0xa7d4, 0xa7e3, 0xa7f3, 0xa802, 0xa812,
|
||||
0xa821, 0xa830, 0xa840, 0xa84f, 0xa85f, 0xa86e,
|
||||
0xa87d, 0xa88d, 0xa89c, 0xa8ac, 0xa8bb, 0xa8ca,
|
||||
0xa8da, 0xa8e9, 0xa8f8, 0xa908, 0xa917, 0xa927,
|
||||
0xa936, 0xa945, 0xa955, 0xa964, 0xa973, 0xa983,
|
||||
0xa992, 0xa9a1, 0xa9b1, 0xa9c0, 0xa9cf, 0xa9df,
|
||||
0xa9ee, 0xa9fd, 0xaa0d, 0xaa1c, 0xaa2b, 0xaa3b,
|
||||
0xaa4a, 0xaa59, 0xaa69, 0xaa78, 0xaa87, 0xaa96,
|
||||
0xaaa6, 0xaab5, 0xaac4, 0xaad4, 0xaae3, 0xaaf2,
|
||||
0xab01, 0xab11, 0xab20, 0xab2f, 0xab3e, 0xab4e,
|
||||
0xab5d, 0xab6c, 0xab7b, 0xab8b, 0xab9a, 0xaba9,
|
||||
0xabb8, 0xabc7, 0xabd7, 0xabe6, 0xabf5, 0xac04,
|
||||
0xac14, 0xac23, 0xac32, 0xac41, 0xac50, 0xac60,
|
||||
0xac6f, 0xac7e, 0xac8d, 0xac9c, 0xacab, 0xacbb,
|
||||
0xacca, 0xacd9, 0xace8, 0xacf7, 0xad06, 0xad16,
|
||||
0xad25, 0xad34, 0xad43, 0xad52, 0xad61, 0xad70,
|
||||
0xad80, 0xad8f, 0xad9e, 0xadad, 0xadbc, 0xadcb,
|
||||
0xadda, 0xade9, 0xadf8, 0xae08, 0xae17, 0xae26,
|
||||
0xae35, 0xae44, 0xae53, 0xae62, 0xae71, 0xae80,
|
||||
0xae8f, 0xae9e, 0xaead, 0xaebd, 0xaecc, 0xaedb,
|
||||
0xaeea, 0xaef9, 0xaf08, 0xaf17, 0xaf26, 0xaf35,
|
||||
0xaf44, 0xaf53, 0xaf62, 0xaf71, 0xaf80, 0xaf8f,
|
||||
0xaf9e, 0xafad, 0xafbc, 0xafcb, 0xafda, 0xafe9,
|
||||
0xaff8, 0xb007, 0xb016, 0xb025, 0xb034, 0xb043,
|
||||
0xb052, 0xb061, 0xb070, 0xb07f, 0xb08e, 0xb09d,
|
||||
0xb0ac, 0xb0bb, 0xb0ca, 0xb0d9, 0xb0e8, 0xb0f6,
|
||||
0xb105, 0xb114, 0xb123, 0xb132, 0xb141, 0xb150,
|
||||
0xb15f, 0xb16e, 0xb17d, 0xb18c, 0xb19b, 0xb1aa,
|
||||
0xb1b8, 0xb1c7, 0xb1d6, 0xb1e5, 0xb1f4, 0xb203,
|
||||
0xb212, 0xb221, 0xb22f, 0xb23e, 0xb24d, 0xb25c,
|
||||
0xb26b, 0xb27a, 0xb289, 0xb297, 0xb2a6, 0xb2b5,
|
||||
0xb2c4, 0xb2d3, 0xb2e2, 0xb2f1, 0xb2ff, 0xb30e,
|
||||
0xb31d, 0xb32c, 0xb33b, 0xb349, 0xb358, 0xb367,
|
||||
0xb376, 0xb385, 0xb393, 0xb3a2, 0xb3b1, 0xb3c0,
|
||||
0xb3cf, 0xb3dd, 0xb3ec, 0xb3fb, 0xb40a, 0xb418,
|
||||
0xb427, 0xb436, 0xb445, 0xb453, 0xb462, 0xb471,
|
||||
0xb480, 0xb48e, 0xb49d, 0xb4ac, 0xb4bb, 0xb4c9,
|
||||
0xb4d8, 0xb4e7, 0xb4f6, 0xb504, 0xb513, 0xb522,
|
||||
0xb530, 0xb53f, 0xb54e, 0xb55c, 0xb56b, 0xb57a,
|
||||
0xb588, 0xb597, 0xb5a6, 0xb5b5, 0xb5c3, 0xb5d2,
|
||||
0xb5e1, 0xb5ef, 0xb5fe, 0xb60d, 0xb61b, 0xb62a,
|
||||
0xb638, 0xb647, 0xb656, 0xb664, 0xb673, 0xb682,
|
||||
0xb690, 0xb69f, 0xb6ae, 0xb6bc, 0xb6cb, 0xb6d9,
|
||||
0xb6e8, 0xb6f7, 0xb705, 0xb714, 0xb722, 0xb731,
|
||||
0xb740, 0xb74e, 0xb75d, 0xb76b, 0xb77a, 0xb788,
|
||||
0xb797, 0xb7a6, 0xb7b4, 0xb7c3, 0xb7d1, 0xb7e0,
|
||||
0xb7ee, 0xb7fd, 0xb80b, 0xb81a, 0xb829, 0xb837,
|
||||
0xb846, 0xb854, 0xb863, 0xb871, 0xb880, 0xb88e,
|
||||
0xb89d, 0xb8ab, 0xb8ba, 0xb8c8, 0xb8d7, 0xb8e5,
|
||||
0xb8f4, 0xb902, 0xb911, 0xb91f, 0xb92e, 0xb93c,
|
||||
0xb94b, 0xb959, 0xb968, 0xb976, 0xb984, 0xb993,
|
||||
0xb9a1, 0xb9b0, 0xb9be, 0xb9cd, 0xb9db, 0xb9ea,
|
||||
0xb9f8, 0xba06, 0xba15, 0xba23, 0xba32, 0xba40,
|
||||
0xba4f, 0xba5d, 0xba6b, 0xba7a, 0xba88, 0xba97,
|
||||
0xbaa5, 0xbab3, 0xbac2, 0xbad0, 0xbade, 0xbaed,
|
||||
0xbafb, 0xbb0a, 0xbb18, 0xbb26, 0xbb35, 0xbb43,
|
||||
0xbb51, 0xbb60, 0xbb6e, 0xbb7c, 0xbb8b, 0xbb99,
|
||||
0xbba8, 0xbbb6, 0xbbc4, 0xbbd3, 0xbbe1, 0xbbef,
|
||||
0xbbfd, 0xbc0c, 0xbc1a, 0xbc28, 0xbc37, 0xbc45,
|
||||
0xbc53, 0xbc62, 0xbc70, 0xbc7e, 0xbc8c, 0xbc9b,
|
||||
0xbca9, 0xbcb7, 0xbcc6, 0xbcd4, 0xbce2, 0xbcf0,
|
||||
0xbcff, 0xbd0d, 0xbd1b, 0xbd29, 0xbd38, 0xbd46,
|
||||
0xbd54, 0xbd62, 0xbd71, 0xbd7f, 0xbd8d, 0xbd9b,
|
||||
0xbdaa, 0xbdb8, 0xbdc6, 0xbdd4, 0xbde2, 0xbdf1,
|
||||
0xbdff, 0xbe0d, 0xbe1b, 0xbe29, 0xbe38, 0xbe46,
|
||||
0xbe54, 0xbe62, 0xbe70, 0xbe7f, 0xbe8d, 0xbe9b,
|
||||
0xbea9, 0xbeb7, 0xbec5, 0xbed4, 0xbee2, 0xbef0,
|
||||
0xbefe, 0xbf0c, 0xbf1a, 0xbf28, 0xbf37, 0xbf45,
|
||||
0xbf53, 0xbf61, 0xbf6f, 0xbf7d, 0xbf8b, 0xbf99,
|
||||
0xbfa7, 0xbfb6, 0xbfc4, 0xbfd2, 0xbfe0, 0xbfee,
|
||||
0xbffc, 0xc00a, 0xc018, 0xc026, 0xc034, 0xc042,
|
||||
0xc051, 0xc05f, 0xc06d, 0xc07b, 0xc089, 0xc097,
|
||||
0xc0a5, 0xc0b3, 0xc0c1, 0xc0cf, 0xc0dd, 0xc0eb,
|
||||
0xc0f9, 0xc107, 0xc115, 0xc123, 0xc131, 0xc13f,
|
||||
0xc14d, 0xc15b, 0xc169, 0xc177, 0xc185, 0xc193,
|
||||
0xc1a1, 0xc1af, 0xc1bd, 0xc1cb, 0xc1d9, 0xc1e7,
|
||||
0xc1f5, 0xc203, 0xc211, 0xc21f, 0xc22d, 0xc23b,
|
||||
0xc249, 0xc257, 0xc265, 0xc273, 0xc281, 0xc28f,
|
||||
0xc29d, 0xc2ab, 0xc2b8, 0xc2c6, 0xc2d4, 0xc2e2,
|
||||
0xc2f0, 0xc2fe, 0xc30c, 0xc31a, 0xc328, 0xc336,
|
||||
0xc344, 0xc352, 0xc35f, 0xc36d, 0xc37b, 0xc389,
|
||||
0xc397, 0xc3a5, 0xc3b3, 0xc3c1, 0xc3ce, 0xc3dc,
|
||||
0xc3ea, 0xc3f8, 0xc406, 0xc414, 0xc422, 0xc42f,
|
||||
0xc43d, 0xc44b, 0xc459, 0xc467, 0xc475, 0xc482,
|
||||
0xc490, 0xc49e, 0xc4ac, 0xc4ba, 0xc4c7, 0xc4d5,
|
||||
0xc4e3, 0xc4f1, 0xc4ff, 0xc50d, 0xc51a, 0xc528,
|
||||
0xc536, 0xc544, 0xc551, 0xc55f, 0xc56d, 0xc57b,
|
||||
0xc589, 0xc596, 0xc5a4, 0xc5b2, 0xc5c0, 0xc5cd,
|
||||
0xc5db, 0xc5e9, 0xc5f7, 0xc604, 0xc612, 0xc620,
|
||||
0xc62d, 0xc63b, 0xc649, 0xc657, 0xc664, 0xc672,
|
||||
0xc680, 0xc68d, 0xc69b, 0xc6a9, 0xc6b7, 0xc6c4,
|
||||
0xc6d2, 0xc6e0, 0xc6ed, 0xc6fb, 0xc709, 0xc716,
|
||||
0xc724, 0xc732, 0xc73f, 0xc74d, 0xc75b, 0xc768,
|
||||
0xc776, 0xc784, 0xc791, 0xc79f, 0xc7ad, 0xc7ba,
|
||||
0xc7c8, 0xc7d6, 0xc7e3, 0xc7f1, 0xc7fe, 0xc80c,
|
||||
0xc81a, 0xc827, 0xc835, 0xc842, 0xc850, 0xc85e,
|
||||
0xc86b, 0xc879, 0xc886, 0xc894, 0xc8a2, 0xc8af,
|
||||
0xc8bd, 0xc8ca, 0xc8d8, 0xc8e5, 0xc8f3, 0xc901,
|
||||
0xc90e, 0xc91c, 0xc929, 0xc937, 0xc944, 0xc952,
|
||||
0xc95f, 0xc96d, 0xc97b, 0xc988, 0xc996, 0xc9a3,
|
||||
0xc9b1, 0xc9be, 0xc9cc, 0xc9d9, 0xc9e7, 0xc9f4,
|
||||
0xca02, 0xca0f, 0xca1d, 0xca2a, 0xca38, 0xca45,
|
||||
0xca53, 0xca60, 0xca6e, 0xca7b, 0xca89, 0xca96,
|
||||
0xcaa4, 0xcab1, 0xcabe, 0xcacc, 0xcad9, 0xcae7,
|
||||
0xcaf4, 0xcb02, 0xcb0f, 0xcb1d, 0xcb2a, 0xcb37,
|
||||
0xcb45, 0xcb52, 0xcb60, 0xcb6d, 0xcb7b, 0xcb88,
|
||||
0xcb95, 0xcba3, 0xcbb0, 0xcbbe, 0xcbcb, 0xcbd8,
|
||||
0xcbe6, 0xcbf3, 0xcc01, 0xcc0e, 0xcc1b, 0xcc29,
|
||||
0xcc36, 0xcc43, 0xcc51, 0xcc5e, 0xcc6c, 0xcc79,
|
||||
0xcc86, 0xcc94, 0xcca1, 0xccae, 0xccbc, 0xccc9,
|
||||
0xccd6, 0xcce4, 0xccf1, 0xccfe, 0xcd0c, 0xcd19,
|
||||
0xcd26, 0xcd34, 0xcd41, 0xcd4e, 0xcd5b, 0xcd69,
|
||||
0xcd76, 0xcd83, 0xcd91, 0xcd9e, 0xcdab, 0xcdb9,
|
||||
0xcdc6, 0xcdd3, 0xcde0, 0xcdee, 0xcdfb, 0xce08,
|
||||
0xce15, 0xce23, 0xce30, 0xce3d, 0xce4a, 0xce58,
|
||||
0xce65, 0xce72, 0xce7f, 0xce8d, 0xce9a, 0xcea7,
|
||||
0xceb4, 0xcec2, 0xcecf, 0xcedc, 0xcee9, 0xcef6,
|
||||
0xcf04, 0xcf11, 0xcf1e, 0xcf2b, 0xcf38, 0xcf46,
|
||||
0xcf53, 0xcf60, 0xcf6d, 0xcf7a, 0xcf87, 0xcf95,
|
||||
0xcfa2, 0xcfaf, 0xcfbc, 0xcfc9, 0xcfd6, 0xcfe4,
|
||||
0xcff1, 0xcffe, 0xd00b, 0xd018, 0xd025, 0xd032,
|
||||
0xd040, 0xd04d, 0xd05a, 0xd067, 0xd074, 0xd081,
|
||||
0xd08e, 0xd09b, 0xd0a9, 0xd0b6, 0xd0c3, 0xd0d0,
|
||||
0xd0dd, 0xd0ea, 0xd0f7, 0xd104, 0xd111, 0xd11e,
|
||||
0xd12b, 0xd139, 0xd146, 0xd153, 0xd160, 0xd16d,
|
||||
0xd17a, 0xd187, 0xd194, 0xd1a1, 0xd1ae, 0xd1bb,
|
||||
0xd1c8, 0xd1d5, 0xd1e2, 0xd1ef, 0xd1fc, 0xd209,
|
||||
0xd216, 0xd223, 0xd230, 0xd23d, 0xd24a, 0xd257,
|
||||
0xd264, 0xd271, 0xd27e, 0xd28b, 0xd298, 0xd2a5,
|
||||
0xd2b2, 0xd2bf, 0xd2cc, 0xd2d9, 0xd2e6, 0xd2f3,
|
||||
0xd300, 0xd30d, 0xd31a, 0xd327, 0xd334, 0xd341,
|
||||
0xd34e, 0xd35b, 0xd368, 0xd375, 0xd382, 0xd38f,
|
||||
0xd39c, 0xd3a8, 0xd3b5, 0xd3c2, 0xd3cf, 0xd3dc,
|
||||
0xd3e9, 0xd3f6, 0xd403, 0xd410, 0xd41d, 0xd42a,
|
||||
0xd436, 0xd443, 0xd450, 0xd45d, 0xd46a, 0xd477,
|
||||
0xd484, 0xd491, 0xd49e, 0xd4aa, 0xd4b7, 0xd4c4,
|
||||
0xd4d1, 0xd4de, 0xd4eb, 0xd4f8, 0xd504, 0xd511,
|
||||
0xd51e, 0xd52b, 0xd538, 0xd545, 0xd551, 0xd55e,
|
||||
0xd56b, 0xd578, 0xd585, 0xd591, 0xd59e, 0xd5ab,
|
||||
0xd5b8, 0xd5c5, 0xd5d1, 0xd5de, 0xd5eb, 0xd5f8,
|
||||
0xd605, 0xd611, 0xd61e, 0xd62b, 0xd638, 0xd645,
|
||||
0xd651, 0xd65e, 0xd66b, 0xd678, 0xd684, 0xd691,
|
||||
0xd69e, 0xd6ab, 0xd6b7, 0xd6c4, 0xd6d1, 0xd6de,
|
||||
0xd6ea, 0xd6f7, 0xd704, 0xd710, 0xd71d, 0xd72a,
|
||||
0xd737, 0xd743, 0xd750, 0xd75d, 0xd769, 0xd776,
|
||||
0xd783, 0xd78f, 0xd79c, 0xd7a9, 0xd7b6, 0xd7c2,
|
||||
0xd7cf, 0xd7dc, 0xd7e8, 0xd7f5, 0xd802, 0xd80e,
|
||||
0xd81b, 0xd828, 0xd834, 0xd841, 0xd84e, 0xd85a,
|
||||
0xd867, 0xd873, 0xd880, 0xd88d, 0xd899, 0xd8a6,
|
||||
0xd8b3, 0xd8bf, 0xd8cc, 0xd8d8, 0xd8e5, 0xd8f2,
|
||||
0xd8fe, 0xd90b, 0xd917, 0xd924, 0xd931, 0xd93d,
|
||||
0xd94a, 0xd956, 0xd963, 0xd970, 0xd97c, 0xd989,
|
||||
0xd995, 0xd9a2, 0xd9ae, 0xd9bb, 0xd9c8, 0xd9d4,
|
||||
0xd9e1, 0xd9ed, 0xd9fa, 0xda06, 0xda13, 0xda1f,
|
||||
0xda2c, 0xda38, 0xda45, 0xda51, 0xda5e, 0xda6a,
|
||||
0xda77, 0xda84, 0xda90, 0xda9d, 0xdaa9, 0xdab6,
|
||||
0xdac2, 0xdacf, 0xdadb, 0xdae7, 0xdaf4, 0xdb00,
|
||||
0xdb0d, 0xdb19, 0xdb26, 0xdb32, 0xdb3f, 0xdb4b,
|
||||
0xdb58, 0xdb64, 0xdb71, 0xdb7d, 0xdb8a, 0xdb96,
|
||||
0xdba2, 0xdbaf, 0xdbbb, 0xdbc8, 0xdbd4, 0xdbe1,
|
||||
0xdbed, 0xdbf9, 0xdc06, 0xdc12, 0xdc1f, 0xdc2b,
|
||||
0xdc38, 0xdc44, 0xdc50, 0xdc5d, 0xdc69, 0xdc76,
|
||||
0xdc82, 0xdc8e, 0xdc9b, 0xdca7, 0xdcb3, 0xdcc0,
|
||||
0xdccc, 0xdcd9, 0xdce5, 0xdcf1, 0xdcfe, 0xdd0a,
|
||||
0xdd16, 0xdd23, 0xdd2f, 0xdd3b, 0xdd48, 0xdd54,
|
||||
0xdd60, 0xdd6d, 0xdd79, 0xdd85, 0xdd92, 0xdd9e,
|
||||
0xddaa, 0xddb7, 0xddc3, 0xddcf, 0xdddc, 0xdde8,
|
||||
0xddf4, 0xde01, 0xde0d, 0xde19, 0xde25, 0xde32,
|
||||
0xde3e, 0xde4a, 0xde57, 0xde63, 0xde6f, 0xde7b,
|
||||
0xde88, 0xde94, 0xdea0, 0xdeac, 0xdeb9, 0xdec5,
|
||||
0xded1, 0xdedd, 0xdeea, 0xdef6, 0xdf02, 0xdf0e,
|
||||
0xdf1b, 0xdf27, 0xdf33, 0xdf3f, 0xdf4c, 0xdf58,
|
||||
0xdf64, 0xdf70, 0xdf7c, 0xdf89, 0xdf95, 0xdfa1,
|
||||
0xdfad, 0xdfb9, 0xdfc6, 0xdfd2, 0xdfde, 0xdfea,
|
||||
0xdff6, 0xe003, 0xe00f, 0xe01b, 0xe027, 0xe033,
|
||||
0xe03f, 0xe04c, 0xe058, 0xe064, 0xe070, 0xe07c,
|
||||
0xe088, 0xe094, 0xe0a1, 0xe0ad, 0xe0b9, 0xe0c5,
|
||||
0xe0d1, 0xe0dd, 0xe0e9, 0xe0f5, 0xe102, 0xe10e,
|
||||
0xe11a, 0xe126, 0xe132, 0xe13e, 0xe14a, 0xe156,
|
||||
0xe162, 0xe16e, 0xe17b, 0xe187, 0xe193, 0xe19f,
|
||||
0xe1ab, 0xe1b7, 0xe1c3, 0xe1cf, 0xe1db, 0xe1e7,
|
||||
0xe1f3, 0xe1ff, 0xe20b, 0xe217, 0xe223, 0xe22f,
|
||||
0xe23c, 0xe248, 0xe254, 0xe260, 0xe26c, 0xe278,
|
||||
0xe284, 0xe290, 0xe29c, 0xe2a8, 0xe2b4, 0xe2c0,
|
||||
0xe2cc, 0xe2d8, 0xe2e4, 0xe2f0, 0xe2fc, 0xe308,
|
||||
0xe314, 0xe320, 0xe32c, 0xe338, 0xe344, 0xe350,
|
||||
0xe35c, 0xe368, 0xe374, 0xe380, 0xe38b, 0xe397,
|
||||
0xe3a3, 0xe3af, 0xe3bb, 0xe3c7, 0xe3d3, 0xe3df,
|
||||
0xe3eb, 0xe3f7, 0xe403, 0xe40f, 0xe41b, 0xe427,
|
||||
0xe433, 0xe43f, 0xe44a, 0xe456, 0xe462, 0xe46e,
|
||||
0xe47a, 0xe486, 0xe492, 0xe49e, 0xe4aa, 0xe4b6,
|
||||
0xe4c1, 0xe4cd, 0xe4d9, 0xe4e5, 0xe4f1, 0xe4fd,
|
||||
0xe509, 0xe515, 0xe520, 0xe52c, 0xe538, 0xe544,
|
||||
0xe550, 0xe55c, 0xe567, 0xe573, 0xe57f, 0xe58b,
|
||||
0xe597, 0xe5a3, 0xe5af, 0xe5ba, 0xe5c6, 0xe5d2,
|
||||
0xe5de, 0xe5ea, 0xe5f5, 0xe601, 0xe60d, 0xe619,
|
||||
0xe625, 0xe630, 0xe63c, 0xe648, 0xe654, 0xe660,
|
||||
0xe66b, 0xe677, 0xe683, 0xe68f, 0xe69a, 0xe6a6,
|
||||
0xe6b2, 0xe6be, 0xe6ca, 0xe6d5, 0xe6e1, 0xe6ed,
|
||||
0xe6f9, 0xe704, 0xe710, 0xe71c, 0xe727, 0xe733,
|
||||
0xe73f, 0xe74b, 0xe756, 0xe762, 0xe76e, 0xe77a,
|
||||
0xe785, 0xe791, 0xe79d, 0xe7a8, 0xe7b4, 0xe7c0,
|
||||
0xe7cb, 0xe7d7, 0xe7e3, 0xe7ef, 0xe7fa, 0xe806,
|
||||
0xe812, 0xe81d, 0xe829, 0xe835, 0xe840, 0xe84c,
|
||||
0xe858, 0xe863, 0xe86f, 0xe87b, 0xe886, 0xe892,
|
||||
0xe89e, 0xe8a9, 0xe8b5, 0xe8c0, 0xe8cc, 0xe8d8,
|
||||
0xe8e3, 0xe8ef, 0xe8fb, 0xe906, 0xe912, 0xe91d,
|
||||
0xe929, 0xe935, 0xe940, 0xe94c, 0xe958, 0xe963,
|
||||
0xe96f, 0xe97a, 0xe986, 0xe991, 0xe99d, 0xe9a9,
|
||||
0xe9b4, 0xe9c0, 0xe9cb, 0xe9d7, 0xe9e3, 0xe9ee,
|
||||
0xe9fa, 0xea05, 0xea11, 0xea1c, 0xea28, 0xea33,
|
||||
0xea3f, 0xea4a, 0xea56, 0xea62, 0xea6d, 0xea79,
|
||||
0xea84, 0xea90, 0xea9b, 0xeaa7, 0xeab2, 0xeabe,
|
||||
0xeac9, 0xead5, 0xeae0, 0xeaec, 0xeaf7, 0xeb03,
|
||||
0xeb0e, 0xeb1a, 0xeb25, 0xeb31, 0xeb3c, 0xeb48,
|
||||
0xeb53, 0xeb5f, 0xeb6a, 0xeb76, 0xeb81, 0xeb8d,
|
||||
0xeb98, 0xeba3, 0xebaf, 0xebba, 0xebc6, 0xebd1,
|
||||
0xebdd, 0xebe8, 0xebf4, 0xebff, 0xec0a, 0xec16,
|
||||
0xec21, 0xec2d, 0xec38, 0xec44, 0xec4f, 0xec5a,
|
||||
0xec66, 0xec71, 0xec7d, 0xec88, 0xec93, 0xec9f,
|
||||
0xecaa, 0xecb6, 0xecc1, 0xeccc, 0xecd8, 0xece3,
|
||||
0xecef, 0xecfa, 0xed05, 0xed11, 0xed1c, 0xed27,
|
||||
0xed33, 0xed3e, 0xed4a, 0xed55, 0xed60, 0xed6c,
|
||||
0xed77, 0xed82, 0xed8e, 0xed99, 0xeda4, 0xedb0,
|
||||
0xedbb, 0xedc6, 0xedd2, 0xeddd, 0xede8, 0xedf4,
|
||||
0xedff, 0xee0a, 0xee15, 0xee21, 0xee2c, 0xee37,
|
||||
0xee43, 0xee4e, 0xee59, 0xee65, 0xee70, 0xee7b,
|
||||
0xee86, 0xee92, 0xee9d, 0xeea8, 0xeeb3, 0xeebf,
|
||||
0xeeca, 0xeed5, 0xeee1, 0xeeec, 0xeef7, 0xef02,
|
||||
0xef0e, 0xef19, 0xef24, 0xef2f, 0xef3a, 0xef46,
|
||||
0xef51, 0xef5c, 0xef67, 0xef73, 0xef7e, 0xef89,
|
||||
0xef94, 0xef9f, 0xefab, 0xefb6, 0xefc1, 0xefcc,
|
||||
0xefd7, 0xefe3, 0xefee, 0xeff9, 0xf004, 0xf00f,
|
||||
0xf01b, 0xf026, 0xf031, 0xf03c, 0xf047, 0xf052,
|
||||
0xf05e, 0xf069, 0xf074, 0xf07f, 0xf08a, 0xf095,
|
||||
0xf0a1, 0xf0ac, 0xf0b7, 0xf0c2, 0xf0cd, 0xf0d8,
|
||||
0xf0e3, 0xf0ef, 0xf0fa, 0xf105, 0xf110, 0xf11b,
|
||||
0xf126, 0xf131, 0xf13c, 0xf147, 0xf153, 0xf15e,
|
||||
0xf169, 0xf174, 0xf17f, 0xf18a, 0xf195, 0xf1a0,
|
||||
0xf1ab, 0xf1b6, 0xf1c2, 0xf1cd, 0xf1d8, 0xf1e3,
|
||||
0xf1ee, 0xf1f9, 0xf204, 0xf20f, 0xf21a, 0xf225,
|
||||
0xf230, 0xf23b, 0xf246, 0xf251, 0xf25c, 0xf267,
|
||||
0xf272, 0xf27d, 0xf288, 0xf293, 0xf29f, 0xf2aa,
|
||||
0xf2b5, 0xf2c0, 0xf2cb, 0xf2d6, 0xf2e1, 0xf2ec,
|
||||
0xf2f7, 0xf302, 0xf30d, 0xf318, 0xf323, 0xf32e,
|
||||
0xf339, 0xf344, 0xf34f, 0xf35a, 0xf364, 0xf36f,
|
||||
0xf37a, 0xf385, 0xf390, 0xf39b, 0xf3a6, 0xf3b1,
|
||||
0xf3bc, 0xf3c7, 0xf3d2, 0xf3dd, 0xf3e8, 0xf3f3,
|
||||
0xf3fe, 0xf409, 0xf414, 0xf41f, 0xf42a, 0xf435,
|
||||
0xf43f, 0xf44a, 0xf455, 0xf460, 0xf46b, 0xf476,
|
||||
0xf481, 0xf48c, 0xf497, 0xf4a2, 0xf4ad, 0xf4b7,
|
||||
0xf4c2, 0xf4cd, 0xf4d8, 0xf4e3, 0xf4ee, 0xf4f9,
|
||||
0xf504, 0xf50f, 0xf519, 0xf524, 0xf52f, 0xf53a,
|
||||
0xf545, 0xf550, 0xf55b, 0xf565, 0xf570, 0xf57b,
|
||||
0xf586, 0xf591, 0xf59c, 0xf5a6, 0xf5b1, 0xf5bc,
|
||||
0xf5c7, 0xf5d2, 0xf5dd, 0xf5e7, 0xf5f2, 0xf5fd,
|
||||
0xf608, 0xf613, 0xf61d, 0xf628, 0xf633, 0xf63e,
|
||||
0xf649, 0xf653, 0xf65e, 0xf669, 0xf674, 0xf67f,
|
||||
0xf689, 0xf694, 0xf69f, 0xf6aa, 0xf6b4, 0xf6bf,
|
||||
0xf6ca, 0xf6d5, 0xf6e0, 0xf6ea, 0xf6f5, 0xf700,
|
||||
0xf70b, 0xf715, 0xf720, 0xf72b, 0xf736, 0xf740,
|
||||
0xf74b, 0xf756, 0xf760, 0xf76b, 0xf776, 0xf781,
|
||||
0xf78b, 0xf796, 0xf7a1, 0xf7ab, 0xf7b6, 0xf7c1,
|
||||
0xf7cc, 0xf7d6, 0xf7e1, 0xf7ec, 0xf7f6, 0xf801,
|
||||
0xf80c, 0xf816, 0xf821, 0xf82c, 0xf836, 0xf841,
|
||||
0xf84c, 0xf856, 0xf861, 0xf86c, 0xf876, 0xf881,
|
||||
0xf88c, 0xf896, 0xf8a1, 0xf8ac, 0xf8b6, 0xf8c1,
|
||||
0xf8cc, 0xf8d6, 0xf8e1, 0xf8ec, 0xf8f6, 0xf901,
|
||||
0xf90b, 0xf916, 0xf921, 0xf92b, 0xf936, 0xf941,
|
||||
0xf94b, 0xf956, 0xf960, 0xf96b, 0xf976, 0xf980,
|
||||
0xf98b, 0xf995, 0xf9a0, 0xf9aa, 0xf9b5, 0xf9c0,
|
||||
0xf9ca, 0xf9d5, 0xf9df, 0xf9ea, 0xf9f4, 0xf9ff,
|
||||
0xfa0a, 0xfa14, 0xfa1f, 0xfa29, 0xfa34, 0xfa3e,
|
||||
0xfa49, 0xfa53, 0xfa5e, 0xfa69, 0xfa73, 0xfa7e,
|
||||
0xfa88, 0xfa93, 0xfa9d, 0xfaa8, 0xfab2, 0xfabd,
|
||||
0xfac7, 0xfad2, 0xfadc, 0xfae7, 0xfaf1, 0xfafc,
|
||||
0xfb06, 0xfb11, 0xfb1b, 0xfb26, 0xfb30, 0xfb3b,
|
||||
0xfb45, 0xfb50, 0xfb5a, 0xfb65, 0xfb6f, 0xfb7a,
|
||||
0xfb84, 0xfb8f, 0xfb99, 0xfba4, 0xfbae, 0xfbb8,
|
||||
0xfbc3, 0xfbcd, 0xfbd8, 0xfbe2, 0xfbed, 0xfbf7,
|
||||
0xfc02, 0xfc0c, 0xfc16, 0xfc21, 0xfc2b, 0xfc36,
|
||||
0xfc40, 0xfc4b, 0xfc55, 0xfc5f, 0xfc6a, 0xfc74,
|
||||
0xfc7f, 0xfc89, 0xfc93, 0xfc9e, 0xfca8, 0xfcb3,
|
||||
0xfcbd, 0xfcc7, 0xfcd2, 0xfcdc, 0xfce7, 0xfcf1,
|
||||
0xfcfb, 0xfd06, 0xfd10, 0xfd1a, 0xfd25, 0xfd2f,
|
||||
0xfd3a, 0xfd44, 0xfd4e, 0xfd59, 0xfd63, 0xfd6d,
|
||||
0xfd78, 0xfd82, 0xfd8c, 0xfd97, 0xfda1, 0xfdab,
|
||||
0xfdb6, 0xfdc0, 0xfdca, 0xfdd5, 0xfddf, 0xfde9,
|
||||
0xfdf4, 0xfdfe, 0xfe08, 0xfe13, 0xfe1d, 0xfe27,
|
||||
0xfe32, 0xfe3c, 0xfe46, 0xfe50, 0xfe5b, 0xfe65,
|
||||
0xfe6f, 0xfe7a, 0xfe84, 0xfe8e, 0xfe98, 0xfea3,
|
||||
0xfead, 0xfeb7, 0xfec1, 0xfecc, 0xfed6, 0xfee0,
|
||||
0xfeeb, 0xfef5, 0xfeff, 0xff09, 0xff14, 0xff1e,
|
||||
0xff28, 0xff32, 0xff3c, 0xff47, 0xff51, 0xff5b,
|
||||
0xff65, 0xff70, 0xff7a, 0xff84, 0xff8e, 0xff98,
|
||||
0xffa3, 0xffad, 0xffb7, 0xffc1, 0xffcc, 0xffd6,
|
||||
0xffe0, 0xffea, 0xfff4, 0xffff
|
||||
};
|
||||
|
||||
// max value is pi/4
|
||||
constexpr double SCALING_FACTOR = 4. / M_PI * 0xFFFF;
|
||||
|
||||
inline double atan2_lookup(double y, double x)
|
||||
{
|
||||
if (std::abs(x) < std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
if (y >= 0.)
|
||||
{
|
||||
return M_PI / 2.;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -M_PI / 2.;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned octant = 0;
|
||||
|
||||
if (x < 0.)
|
||||
{
|
||||
octant = 1;
|
||||
x = -x;
|
||||
}
|
||||
if (y < 0.)
|
||||
{
|
||||
octant |= 2;
|
||||
y = -y;
|
||||
}
|
||||
|
||||
double t = y / x;
|
||||
if (t > 1.0)
|
||||
{
|
||||
octant |= 4;
|
||||
t = 1.0 / t;
|
||||
}
|
||||
|
||||
double angle = atan_table[(unsigned)(t * 4095)] / SCALING_FACTOR;
|
||||
|
||||
switch (octant)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
angle = M_PI - angle;
|
||||
break;
|
||||
case 2:
|
||||
angle = -angle;
|
||||
break;
|
||||
case 3:
|
||||
angle = -M_PI + angle;
|
||||
break;
|
||||
case 4:
|
||||
angle = M_PI / 2.0 - angle;
|
||||
break;
|
||||
case 5:
|
||||
angle = M_PI / 2.0 + angle;
|
||||
break;
|
||||
case 6:
|
||||
angle = -M_PI / 2.0 + angle;
|
||||
break;
|
||||
case 7:
|
||||
angle = -M_PI / 2.0 - angle;
|
||||
break;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
#endif // TRIGONOMETRY_TABLES_H
|
@ -1,325 +0,0 @@
|
||||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef GRAPHLOADER_H
|
||||
#define GRAPHLOADER_H
|
||||
|
||||
#include "osrm_exception.hpp"
|
||||
#include "../data_structures/external_memory_node.hpp"
|
||||
#include "../data_structures/import_edge.hpp"
|
||||
#include "../data_structures/query_node.hpp"
|
||||
#include "../data_structures/restriction.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/FingerPrint.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
template <typename EdgeT>
|
||||
NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream,
|
||||
std::vector<EdgeT> &edge_list,
|
||||
std::vector<NodeID> &barrier_node_list,
|
||||
std::vector<NodeID> &traffic_light_node_list,
|
||||
std::vector<QueryNode> *int_to_ext_node_id_map,
|
||||
std::vector<TurnRestriction> &restriction_list)
|
||||
{
|
||||
const FingerPrint fingerprint_orig;
|
||||
FingerPrint fingerprint_loaded;
|
||||
input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
|
||||
|
||||
if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << ".osrm was prepared with different build.\n"
|
||||
"Reprocess to get rid of this warning.";
|
||||
}
|
||||
|
||||
std::unordered_map<NodeID, NodeID> ext_to_int_id_map;
|
||||
|
||||
NodeID n;
|
||||
input_stream.read((char *)&n, sizeof(NodeID));
|
||||
SimpleLogger().Write() << "Importing n = " << n << " nodes ";
|
||||
|
||||
ExternalMemoryNode current_node;
|
||||
for (NodeID i = 0; i < n; ++i)
|
||||
{
|
||||
input_stream.read((char *)¤t_node, sizeof(ExternalMemoryNode));
|
||||
int_to_ext_node_id_map->emplace_back(current_node.lat, current_node.lon, current_node.node_id);
|
||||
ext_to_int_id_map.emplace(current_node.node_id, i);
|
||||
if (current_node.barrier)
|
||||
{
|
||||
barrier_node_list.emplace_back(i);
|
||||
}
|
||||
if (current_node.traffic_lights)
|
||||
{
|
||||
traffic_light_node_list.emplace_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
// tighten vector sizes
|
||||
barrier_node_list.shrink_to_fit();
|
||||
traffic_light_node_list.shrink_to_fit();
|
||||
|
||||
// renumber nodes in turn restrictions
|
||||
for (TurnRestriction ¤t_restriction : restriction_list)
|
||||
{
|
||||
auto internal_id_iter = ext_to_int_id_map.find(current_restriction.from.node);
|
||||
if (internal_id_iter == ext_to_int_id_map.end())
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "Unmapped from Node of restriction";
|
||||
continue;
|
||||
}
|
||||
current_restriction.from.node = internal_id_iter->second;
|
||||
|
||||
internal_id_iter = ext_to_int_id_map.find(current_restriction.via.node);
|
||||
if (internal_id_iter == ext_to_int_id_map.end())
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "Unmapped via node of restriction";
|
||||
continue;
|
||||
}
|
||||
current_restriction.via.node = internal_id_iter->second;
|
||||
|
||||
internal_id_iter = ext_to_int_id_map.find(current_restriction.to.node);
|
||||
if (internal_id_iter == ext_to_int_id_map.end())
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "Unmapped to node of restriction";
|
||||
continue;
|
||||
}
|
||||
current_restriction.to.node = internal_id_iter->second;
|
||||
}
|
||||
|
||||
EdgeWeight weight;
|
||||
NodeID source, target;
|
||||
unsigned nameID;
|
||||
int length;
|
||||
short dir; // direction (0 = open, 1 = forward, 2+ = open)
|
||||
bool is_roundabout, ignore_in_grid, is_access_restricted, is_split;
|
||||
TravelMode travel_mode;
|
||||
|
||||
EdgeID m;
|
||||
input_stream.read((char *)&m, sizeof(unsigned));
|
||||
edge_list.reserve(m);
|
||||
SimpleLogger().Write() << " and " << m << " edges ";
|
||||
|
||||
for (EdgeID i = 0; i < m; ++i)
|
||||
{
|
||||
input_stream.read((char *)&source, sizeof(unsigned));
|
||||
input_stream.read((char *)&target, sizeof(unsigned));
|
||||
input_stream.read((char *)&length, sizeof(int));
|
||||
input_stream.read((char *)&dir, sizeof(short));
|
||||
input_stream.read((char *)&weight, sizeof(int));
|
||||
input_stream.read((char *)&nameID, sizeof(unsigned));
|
||||
input_stream.read((char *)&is_roundabout, sizeof(bool));
|
||||
input_stream.read((char *)&ignore_in_grid, sizeof(bool));
|
||||
input_stream.read((char *)&is_access_restricted, sizeof(bool));
|
||||
input_stream.read((char *)&travel_mode, sizeof(TravelMode));
|
||||
input_stream.read((char *)&is_split, sizeof(bool));
|
||||
|
||||
BOOST_ASSERT_MSG(length > 0, "loaded null length edge");
|
||||
BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
|
||||
BOOST_ASSERT_MSG(0 <= dir && dir <= 2, "loaded bogus direction");
|
||||
|
||||
bool forward = true;
|
||||
bool backward = true;
|
||||
if (1 == dir)
|
||||
{
|
||||
backward = false;
|
||||
}
|
||||
if (2 == dir)
|
||||
{
|
||||
forward = false;
|
||||
}
|
||||
|
||||
// translate the external NodeIDs to internal IDs
|
||||
auto internal_id_iter = ext_to_int_id_map.find(source);
|
||||
if (ext_to_int_id_map.find(source) == ext_to_int_id_map.end())
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
SimpleLogger().Write(logWARNING) << " unresolved source NodeID: " << source;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
source = internal_id_iter->second;
|
||||
internal_id_iter = ext_to_int_id_map.find(target);
|
||||
if (ext_to_int_id_map.find(target) == ext_to_int_id_map.end())
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
SimpleLogger().Write(logWARNING) << "unresolved target NodeID : " << target;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
target = internal_id_iter->second;
|
||||
BOOST_ASSERT_MSG(source != SPECIAL_NODEID && target != SPECIAL_NODEID,
|
||||
"nonexisting source or target");
|
||||
|
||||
if (source > target)
|
||||
{
|
||||
std::swap(source, target);
|
||||
std::swap(forward, backward);
|
||||
}
|
||||
|
||||
edge_list.emplace_back(source,
|
||||
target,
|
||||
nameID,
|
||||
weight,
|
||||
forward,
|
||||
backward,
|
||||
is_roundabout,
|
||||
ignore_in_grid,
|
||||
is_access_restricted,
|
||||
travel_mode,
|
||||
is_split);
|
||||
}
|
||||
ext_to_int_id_map.clear();
|
||||
|
||||
tbb::parallel_sort(edge_list.begin(), edge_list.end());
|
||||
|
||||
for (unsigned i = 1; i < edge_list.size(); ++i)
|
||||
{
|
||||
if ((edge_list[i - 1].target == edge_list[i].target) &&
|
||||
(edge_list[i - 1].source == edge_list[i].source))
|
||||
{
|
||||
const bool edge_flags_equivalent =
|
||||
(edge_list[i - 1].forward == edge_list[i].forward) &&
|
||||
(edge_list[i - 1].backward == edge_list[i].backward);
|
||||
const bool edge_flags_are_superset1 =
|
||||
(edge_list[i - 1].forward && edge_list[i - 1].backward) &&
|
||||
(edge_list[i].forward != edge_list[i].backward);
|
||||
const bool edge_flags_are_superset_2 =
|
||||
(edge_list[i].forward && edge_list[i].backward) &&
|
||||
(edge_list[i - 1].forward != edge_list[i - 1].backward);
|
||||
|
||||
if (edge_flags_equivalent)
|
||||
{
|
||||
edge_list[i].weight = std::min(edge_list[i - 1].weight, edge_list[i].weight);
|
||||
edge_list[i - 1].source = SPECIAL_NODEID;
|
||||
}
|
||||
else if (edge_flags_are_superset1)
|
||||
{
|
||||
if (edge_list[i - 1].weight <= edge_list[i].weight)
|
||||
{
|
||||
// edge i-1 is smaller and goes in both directions. Throw away the other edge
|
||||
edge_list[i].source = SPECIAL_NODEID;
|
||||
}
|
||||
else
|
||||
{
|
||||
// edge i-1 is open in both directions, but edge i is smaller in one direction.
|
||||
// Close edge i-1 in this direction
|
||||
edge_list[i - 1].forward = !edge_list[i].forward;
|
||||
edge_list[i - 1].backward = !edge_list[i].backward;
|
||||
}
|
||||
}
|
||||
else if (edge_flags_are_superset_2)
|
||||
{
|
||||
if (edge_list[i - 1].weight <= edge_list[i].weight)
|
||||
{
|
||||
// edge i-1 is smaller for one direction. edge i is open in both. close edge i
|
||||
// in the other direction
|
||||
edge_list[i].forward = !edge_list[i - 1].forward;
|
||||
edge_list[i].backward = !edge_list[i - 1].backward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// edge i is smaller and goes in both direction. Throw away edge i-1
|
||||
edge_list[i - 1].source = SPECIAL_NODEID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto new_end_iter = std::remove_if(edge_list.begin(), edge_list.end(), [] (const EdgeT &edge)
|
||||
{
|
||||
return edge.source == SPECIAL_NODEID ||
|
||||
edge.target == SPECIAL_NODEID;
|
||||
});
|
||||
edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates.
|
||||
edge_list.shrink_to_fit();
|
||||
SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges";
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename NodeT, typename EdgeT>
|
||||
unsigned readHSGRFromStream(const boost::filesystem::path &hsgr_file,
|
||||
std::vector<NodeT> &node_list,
|
||||
std::vector<EdgeT> &edge_list,
|
||||
unsigned *check_sum)
|
||||
{
|
||||
if (!boost::filesystem::exists(hsgr_file))
|
||||
{
|
||||
throw osrm::exception("hsgr file does not exist");
|
||||
}
|
||||
if (0 == boost::filesystem::file_size(hsgr_file))
|
||||
{
|
||||
throw osrm::exception("hsgr file is empty");
|
||||
}
|
||||
|
||||
boost::filesystem::ifstream hsgr_input_stream(hsgr_file, std::ios::binary);
|
||||
|
||||
FingerPrint fingerprint_loaded, fingerprint_orig;
|
||||
hsgr_input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
|
||||
if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build.\n"
|
||||
"Reprocess to get rid of this warning.";
|
||||
}
|
||||
|
||||
unsigned number_of_nodes = 0;
|
||||
unsigned number_of_edges = 0;
|
||||
hsgr_input_stream.read((char *)check_sum, sizeof(unsigned));
|
||||
hsgr_input_stream.read((char *)&number_of_nodes, sizeof(unsigned));
|
||||
BOOST_ASSERT_MSG(0 != number_of_nodes, "number of nodes is zero");
|
||||
hsgr_input_stream.read((char *)&number_of_edges, sizeof(unsigned));
|
||||
|
||||
SimpleLogger().Write() << "number_of_nodes: " << number_of_nodes
|
||||
<< ", number_of_edges: " << number_of_edges;
|
||||
|
||||
// BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
|
||||
node_list.resize(number_of_nodes);
|
||||
hsgr_input_stream.read((char *)&(node_list[0]), number_of_nodes * sizeof(NodeT));
|
||||
|
||||
edge_list.resize(number_of_edges);
|
||||
if (number_of_edges > 0)
|
||||
{
|
||||
hsgr_input_stream.read((char *)&(edge_list[0]), number_of_edges * sizeof(EdgeT));
|
||||
}
|
||||
hsgr_input_stream.close();
|
||||
|
||||
return number_of_nodes;
|
||||
}
|
||||
|
||||
#endif // GRAPHLOADER_H
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
open source routing machine
|
||||
Copyright (C) Dennis Luxen, others 2010
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU AFFERO General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
or see http://www.gnu.org/licenses/agpl.txt.
|
||||
*/
|
||||
|
||||
#ifndef RANGE_ALGORITHMS_HPP
|
||||
#define RANGE_ALGORITHMS_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace osrm {
|
||||
|
||||
template<class Container>
|
||||
auto max_element(const Container & c) -> decltype(std::max_element(c.begin(), c.end()))
|
||||
{
|
||||
return std::max_element(c.begin(), c.end());
|
||||
}
|
||||
|
||||
template<class Container>
|
||||
auto max_element(const Container & c) -> decltype(std::max_element(c.cbegin(), c.cend()))
|
||||
{
|
||||
return std::max_element(c.cbegin(), c.cend());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // RANGE_ALGORITHMS_HPP
|
117
algorithms/bayes_classifier.hpp
Normal file
117
algorithms/bayes_classifier.hpp
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
|
||||
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
|
||||
#define BAYES_CLASSIFIER_HPP
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct NormalDistribution
|
||||
{
|
||||
NormalDistribution(const double mean, const double standard_deviation)
|
||||
: mean(mean), standard_deviation(standard_deviation)
|
||||
{
|
||||
}
|
||||
|
||||
// FIXME implement log-probability version since its faster
|
||||
double density_function(const double val) const
|
||||
{
|
||||
const double x = val - mean;
|
||||
return 1.0 / (std::sqrt(2. * M_PI) * standard_deviation) *
|
||||
std::exp(-x * x / (standard_deviation * standard_deviation));
|
||||
}
|
||||
|
||||
double mean;
|
||||
double standard_deviation;
|
||||
};
|
||||
|
||||
struct LaplaceDistribution
|
||||
{
|
||||
LaplaceDistribution(const double location, const double scale)
|
||||
: location(location), scale(scale)
|
||||
{
|
||||
}
|
||||
|
||||
// FIXME implement log-probability version since its faster
|
||||
double density_function(const double val) const
|
||||
{
|
||||
const double x = std::abs(val - location);
|
||||
return 1.0 / (2. * scale) * std::exp(-x / scale);
|
||||
}
|
||||
|
||||
double location;
|
||||
double scale;
|
||||
};
|
||||
|
||||
template <typename PositiveDistributionT, typename NegativeDistributionT, typename ValueT>
|
||||
class BayesClassifier
|
||||
{
|
||||
public:
|
||||
enum class ClassLabel : unsigned
|
||||
{
|
||||
NEGATIVE,
|
||||
POSITIVE
|
||||
};
|
||||
using ClassificationT = std::pair<ClassLabel, double>;
|
||||
|
||||
BayesClassifier(const PositiveDistributionT &positive_distribution,
|
||||
const NegativeDistributionT &negative_distribution,
|
||||
const double positive_apriori_probability)
|
||||
: positive_distribution(positive_distribution),
|
||||
negative_distribution(negative_distribution),
|
||||
positive_apriori_probability(positive_apriori_probability),
|
||||
negative_apriori_probability(1. - positive_apriori_probability)
|
||||
{
|
||||
}
|
||||
|
||||
// Returns label and the probability of the label.
|
||||
ClassificationT classify(const ValueT &v) const
|
||||
{
|
||||
const double positive_postpriori =
|
||||
positive_apriori_probability * positive_distribution.density_function(v);
|
||||
const double negative_postpriori =
|
||||
negative_apriori_probability * negative_distribution.density_function(v);
|
||||
const double norm = positive_postpriori + negative_postpriori;
|
||||
|
||||
if (positive_postpriori > negative_postpriori)
|
||||
{
|
||||
return std::make_pair(ClassLabel::POSITIVE, positive_postpriori / norm);
|
||||
}
|
||||
|
||||
return std::make_pair(ClassLabel::NEGATIVE, negative_postpriori / norm);
|
||||
}
|
||||
|
||||
private:
|
||||
PositiveDistributionT positive_distribution;
|
||||
NegativeDistributionT negative_distribution;
|
||||
double positive_apriori_probability;
|
||||
double negative_apriori_probability;
|
||||
};
|
||||
|
||||
#endif // BAYES_CLASSIFIER_HPP
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -95,8 +95,8 @@ template <typename GraphT> class BFSComponentExplorer
|
||||
* 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)
|
||||
NodeID node,
|
||||
unsigned current_component)
|
||||
{
|
||||
/*
|
||||
Graphical representation of variables:
|
||||
@ -118,7 +118,7 @@ template <typename GraphT> class BFSComponentExplorer
|
||||
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
|
||||
bfs_queue.pop();
|
||||
|
||||
const NodeID v = current_queue_item.first; // current node
|
||||
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;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -49,7 +49,7 @@ class IteratorbasedCRC32
|
||||
while (iter != end)
|
||||
{
|
||||
using value_type = typename std::iterator_traits<Iterator>::value_type;
|
||||
char *data = (char *)(&(*iter));
|
||||
const char *data = reinterpret_cast<const char *>(&(*iter));
|
||||
|
||||
if (use_hardware_implementation)
|
||||
{
|
||||
@ -73,14 +73,14 @@ class IteratorbasedCRC32
|
||||
return sse42_found;
|
||||
}
|
||||
|
||||
unsigned compute_in_software(char *str, unsigned len)
|
||||
unsigned compute_in_software(const char *str, unsigned len)
|
||||
{
|
||||
crc_processor.process_bytes(str, len);
|
||||
return crc_processor.checksum();
|
||||
}
|
||||
|
||||
// adapted from http://byteworm.com/2010/10/13/crc32/
|
||||
unsigned compute_in_hardware(char *str, unsigned len)
|
||||
unsigned compute_in_hardware(const char *str, unsigned len)
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
unsigned q = len / sizeof(unsigned);
|
||||
@ -96,7 +96,7 @@ class IteratorbasedCRC32
|
||||
++p;
|
||||
}
|
||||
|
||||
str = (char *)p;
|
||||
str = reinterpret_cast<char *>(p);
|
||||
while (r--)
|
||||
{
|
||||
__asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
||||
@ -116,7 +116,7 @@ class IteratorbasedCRC32
|
||||
return ecx;
|
||||
}
|
||||
|
||||
#if defined(__MINGW64__) || defined(_MSC_VER)
|
||||
#if defined(__MINGW64__) || defined(_MSC_VER) || !defined(__x86_64__)
|
||||
inline void
|
||||
__get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) const
|
||||
{
|
||||
@ -131,8 +131,7 @@ class IteratorbasedCRC32
|
||||
|
||||
struct RangebasedCRC32
|
||||
{
|
||||
template<typename Iteratable>
|
||||
unsigned operator()(const Iteratable &iterable)
|
||||
template <typename Iteratable> unsigned operator()(const Iteratable &iterable)
|
||||
{
|
||||
return crc32(std::begin(iterable), std::end(iterable));
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,15 +28,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "douglas_peucker.hpp"
|
||||
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
#include "../Util/integer_range.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -65,12 +63,12 @@ struct CoordinatePairCalculator
|
||||
// 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 = sqrt(std::pow(x_value_1, 2) + std::pow(y_value_1, 2)) * earth_radius;
|
||||
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 = sqrt(std::pow(x_value_2, 2) + std::pow(y_value_2, 2)) * earth_radius;
|
||||
const float dist2 = std::hypot(x_value_2, y_value_2) * earth_radius;
|
||||
|
||||
// return the minimum
|
||||
return static_cast<int>(std::min(dist1, dist2));
|
||||
@ -90,7 +88,7 @@ void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const
|
||||
|
||||
void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level)
|
||||
{
|
||||
unsigned size = std::distance(begin, end);
|
||||
const auto size = std::distance(begin, end);
|
||||
if (size < 2)
|
||||
{
|
||||
return;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,9 +28,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef DOUGLAS_PEUCKER_HPP_
|
||||
#define DOUGLAS_PEUCKER_HPP_
|
||||
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#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.
|
||||
@ -39,9 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* bit indicating if the points is present in the generalization.
|
||||
* Note: points may also be pre-selected*/
|
||||
|
||||
struct SegmentInformation;
|
||||
|
||||
static const std::array<int, 19> DOUGLAS_PEUCKER_THRESHOLDS {{
|
||||
static const std::array<int, 19> DOUGLAS_PEUCKER_THRESHOLDS{{
|
||||
512440, // z0
|
||||
256720, // z1
|
||||
122560, // z2
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef OBJECT_ENCODER_HPP
|
||||
#define OBJECT_ENCODER_HPP
|
||||
|
||||
#include "../Util/string_util.hpp"
|
||||
#include "../util/string_util.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||
@ -49,10 +49,9 @@ struct ObjectEncoder
|
||||
8,
|
||||
6>;
|
||||
|
||||
template <class ObjectT>
|
||||
static void EncodeToBase64(const ObjectT &object, std::string &encoded)
|
||||
template <class ObjectT> static void EncodeToBase64(const ObjectT &object, std::string &encoded)
|
||||
{
|
||||
const char *char_ptr_to_object = (const char *)&object;
|
||||
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());
|
||||
|
||||
@ -71,8 +70,7 @@ struct ObjectEncoder
|
||||
replaceAll(encoded, "/", "_");
|
||||
}
|
||||
|
||||
template <class ObjectT>
|
||||
static void DecodeFromBase64(const std::string &input, ObjectT &object)
|
||||
template <class ObjectT> static void DecodeFromBase64(const std::string &input, ObjectT &object)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -81,9 +79,8 @@ struct ObjectEncoder
|
||||
replaceAll(encoded, "-", "+");
|
||||
replaceAll(encoded, "_", "/");
|
||||
|
||||
std::copy(binary_t(encoded.begin()),
|
||||
binary_t(encoded.begin() + encoded.length() - 1),
|
||||
(char *)&object);
|
||||
std::copy(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1),
|
||||
reinterpret_cast<char *>(&object));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "polyline_compressor.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
std::string PolylineCompressor::encode_vector(std::vector<int> &numbers) const
|
||||
{
|
||||
@ -56,19 +56,11 @@ std::string PolylineCompressor::encode_number(int number_to_encode) const
|
||||
{
|
||||
const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
|
||||
output += static_cast<char>(next_value);
|
||||
if (92 == next_value)
|
||||
{
|
||||
output += static_cast<char>(next_value);
|
||||
}
|
||||
number_to_encode >>= 5;
|
||||
}
|
||||
|
||||
number_to_encode += 63;
|
||||
output += static_cast<char>(number_to_encode);
|
||||
if (92 == number_to_encode)
|
||||
{
|
||||
output += static_cast<char>(number_to_encode);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,23 +30,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "polyline_compressor.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
JSON::String
|
||||
osrm::json::String
|
||||
PolylineFormatter::printEncodedString(const std::vector<SegmentInformation> &polyline) const
|
||||
{
|
||||
return JSON::String(PolylineCompressor().get_encoded_string(polyline));
|
||||
return osrm::json::String(PolylineCompressor().get_encoded_string(polyline));
|
||||
}
|
||||
|
||||
JSON::Array
|
||||
osrm::json::Array
|
||||
PolylineFormatter::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
|
||||
{
|
||||
JSON::Array json_geometry_array;
|
||||
osrm::json::Array json_geometry_array;
|
||||
for (const auto &segment : polyline)
|
||||
{
|
||||
if (segment.necessary)
|
||||
{
|
||||
JSON::Array json_coordinate;
|
||||
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);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,16 +30,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
struct SegmentInformation;
|
||||
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct PolylineFormatter
|
||||
{
|
||||
JSON::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||
osrm::json::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||
|
||||
JSON::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||
osrm::json::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||
};
|
||||
|
||||
#endif /* POLYLINE_FORMATTER_HPP */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -54,7 +54,8 @@ template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
||||
|
||||
for (const SegmentT &segment : segment_list)
|
||||
{
|
||||
if (segment.name_id != blocked_name_id && segment.length > result_segment.length && segment.name_id != 0)
|
||||
if (segment.name_id != blocked_name_id && segment.length > result_segment.length &&
|
||||
segment.name_id != 0)
|
||||
{
|
||||
result_segment = segment;
|
||||
}
|
||||
@ -73,9 +74,13 @@ template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
||||
SegmentT alternative_segment_1, alternative_segment_2;
|
||||
|
||||
auto length_comperator = [](const SegmentT &a, const SegmentT &b)
|
||||
{ return a.length > b.length; };
|
||||
{
|
||||
return a.length > b.length;
|
||||
};
|
||||
auto name_id_comperator = [](const SegmentT &a, const SegmentT &b)
|
||||
{ return a.name_id < b.name_id; };
|
||||
{
|
||||
return a.name_id < b.name_id;
|
||||
};
|
||||
|
||||
if (shortest_path_segments.empty())
|
||||
{
|
||||
@ -87,8 +92,7 @@ template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
||||
shortest_segment_1 = shortest_path_segments[0];
|
||||
if (!alternative_path_segments.empty())
|
||||
{
|
||||
std::sort(alternative_path_segments.begin(),
|
||||
alternative_path_segments.end(),
|
||||
std::sort(alternative_path_segments.begin(), alternative_path_segments.end(),
|
||||
length_comperator);
|
||||
|
||||
// also pick the longest segment for the alternative path
|
||||
@ -99,16 +103,13 @@ template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
||||
// 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(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(),
|
||||
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);
|
||||
@ -116,29 +117,23 @@ template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
||||
// 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(),
|
||||
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));
|
||||
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::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(),
|
||||
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);
|
||||
alternative_segment_1.name_id);
|
||||
}
|
||||
|
||||
// move the segments into the order in which they occur.
|
||||
@ -152,15 +147,13 @@ template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
||||
}
|
||||
|
||||
// fetching names for the selected segments
|
||||
route_names.shortest_path_name_1 =
|
||||
facade->GetEscapedNameForNameID(shortest_segment_1.name_id);
|
||||
route_names.shortest_path_name_2 =
|
||||
facade->GetEscapedNameForNameID(shortest_segment_2.name_id);
|
||||
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->GetEscapedNameForNameID(alternative_segment_1.name_id);
|
||||
facade->get_name_for_id(alternative_segment_1.name_id);
|
||||
route_names.alternative_path_name_2 =
|
||||
facade->GetEscapedNameForNameID(alternative_segment_2.name_id);
|
||||
facade->get_name_for_id(alternative_segment_2.name_id);
|
||||
|
||||
return route_names;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -37,18 +37,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../data_structures/restriction_map.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
|
||||
#include "../Util/integer_range.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/std_hash.hpp"
|
||||
#include "../Util/timing_util.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/std_hash.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <memory>
|
||||
@ -57,8 +56,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
template <typename GraphT>
|
||||
class TarjanSCC
|
||||
template <typename GraphT> class TarjanSCC
|
||||
{
|
||||
struct TarjanStackFrame
|
||||
{
|
||||
@ -80,16 +78,15 @@ class TarjanSCC
|
||||
std::shared_ptr<GraphT> m_node_based_graph;
|
||||
std::unordered_set<NodeID> barrier_node_set;
|
||||
RestrictionMap m_restriction_map;
|
||||
unsigned size_one_counter;
|
||||
std::size_t size_one_counter;
|
||||
|
||||
public:
|
||||
template<class ContainerT>
|
||||
template <class ContainerT>
|
||||
TarjanSCC(std::shared_ptr<GraphT> graph,
|
||||
const RestrictionMap &restrictions,
|
||||
const ContainerT &barrier_node_list)
|
||||
: components_index(graph->GetNumberOfNodes(), SPECIAL_NODEID),
|
||||
m_node_based_graph(graph), m_restriction_map(restrictions),
|
||||
size_one_counter(0)
|
||||
: components_index(graph->GetNumberOfNodes(), SPECIAL_NODEID), m_node_based_graph(graph),
|
||||
m_restriction_map(restrictions), size_one_counter(0)
|
||||
{
|
||||
barrier_node_set.insert(std::begin(barrier_node_list), std::end(barrier_node_list));
|
||||
BOOST_ASSERT(m_node_based_graph->GetNumberOfNodes() > 0);
|
||||
@ -98,17 +95,18 @@ class TarjanSCC
|
||||
void run()
|
||||
{
|
||||
TIMER_START(SCC_RUN);
|
||||
const NodeID max_node_id = m_node_based_graph->GetNumberOfNodes();
|
||||
|
||||
// The following is a hack to distinguish between stuff that happens
|
||||
// before the recursive call and stuff that happens after
|
||||
std::stack<TarjanStackFrame> recursion_stack;
|
||||
// true = stuff before, false = stuff after call
|
||||
std::stack<NodeID> tarjan_stack;
|
||||
std::vector<TarjanNode> tarjan_node_list(m_node_based_graph->GetNumberOfNodes());
|
||||
std::vector<TarjanNode> tarjan_node_list(max_node_id);
|
||||
unsigned component_index = 0, size_of_current_component = 0;
|
||||
int index = 0;
|
||||
const NodeID last_node = m_node_based_graph->GetNumberOfNodes();
|
||||
std::vector<bool> processing_node_before_recursion(m_node_based_graph->GetNumberOfNodes(), true);
|
||||
for(const NodeID node : osrm::irange(0u, last_node))
|
||||
unsigned index = 0;
|
||||
std::vector<bool> processing_node_before_recursion(max_node_id, true);
|
||||
for (const NodeID node : osrm::irange(0u, max_node_id))
|
||||
{
|
||||
if (SPECIAL_NODEID == components_index[node])
|
||||
{
|
||||
@ -150,13 +148,11 @@ class TarjanSCC
|
||||
const auto vprime = m_node_based_graph->GetTarget(current_edge);
|
||||
|
||||
// Traverse outgoing edges
|
||||
if (barrier_node_set.find(v) != barrier_node_set.end() &&
|
||||
u != vprime)
|
||||
if (barrier_node_set.find(v) != barrier_node_set.end() && u != vprime)
|
||||
{
|
||||
// continue;
|
||||
}
|
||||
|
||||
|
||||
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
|
||||
vprime == to_node_of_only_restriction)
|
||||
{
|
||||
@ -219,35 +215,25 @@ class TarjanSCC
|
||||
}
|
||||
|
||||
TIMER_STOP(SCC_RUN);
|
||||
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)
|
||||
{
|
||||
return 1 == value;
|
||||
});
|
||||
return 1 == value;
|
||||
});
|
||||
}
|
||||
|
||||
std::size_t get_number_of_components() const
|
||||
{
|
||||
return component_size_vector.size();
|
||||
}
|
||||
std::size_t get_number_of_components() const { return component_size_vector.size(); }
|
||||
|
||||
unsigned get_size_one_count() const
|
||||
{
|
||||
return size_one_counter;
|
||||
}
|
||||
std::size_t get_size_one_count() const { return size_one_counter; }
|
||||
|
||||
unsigned get_component_size(const NodeID node) const
|
||||
{
|
||||
return component_size_vector[components_index[node]];
|
||||
}
|
||||
|
||||
unsigned get_component_id(const NodeID node) const
|
||||
{
|
||||
return components_index[node];
|
||||
}
|
||||
unsigned get_component_id(const NodeID node) const { return components_index[node]; }
|
||||
};
|
||||
|
||||
#endif /* TINY_COMPONENTS_HPP */
|
||||
|
@ -9,9 +9,6 @@ branches:
|
||||
only:
|
||||
- develop
|
||||
|
||||
# Operating system (build VM template)
|
||||
os: Windows Server 2012 R2
|
||||
|
||||
# scripts that are called at very beginning, before repo cloning
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -29,10 +29,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#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 "../Util/BoostFileSystemFix.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <random>
|
||||
|
||||
@ -88,11 +88,9 @@ void Benchmark(BenchStaticRTree &rtree, unsigned num_queries)
|
||||
for (const auto &q : queries)
|
||||
{
|
||||
phantom_node_vector.clear();
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate(
|
||||
q, phantom_node_vector, 3, num_results);
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results);
|
||||
phantom_node_vector.clear();
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate(
|
||||
q, phantom_node_vector, 17, num_results);
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results);
|
||||
}
|
||||
TIMER_STOP(query_phantom);
|
||||
|
||||
@ -130,8 +128,7 @@ void Benchmark(BenchStaticRTree &rtree, unsigned num_queries)
|
||||
}
|
||||
TIMER_STOP(query_node);
|
||||
|
||||
std::cout << "Took " << TIMER_MSEC(query_node) << " msec for " << num_queries
|
||||
<< " queries."
|
||||
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";
|
||||
@ -147,11 +144,9 @@ void Benchmark(BenchStaticRTree &rtree, unsigned num_queries)
|
||||
for (const auto &q : queries)
|
||||
{
|
||||
phantom_node_vector.clear();
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate(
|
||||
q, phantom_node_vector, 3, num_results);
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results);
|
||||
phantom_node_vector.clear();
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate(
|
||||
q, phantom_node_vector, 17, num_results);
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results);
|
||||
}
|
||||
TIMER_STOP(query_phantom);
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
set(OLDFILE ${SOURCE_DIR}/Util/FingerPrint.cpp)
|
||||
set(OLDFILE ${SOURCE_DIR}/util/fingerprint_impl.hpp)
|
||||
if (EXISTS ${OLDFILE})
|
||||
file(REMOVE_RECURSE ${OLDFILE})
|
||||
endif()
|
||||
file(MD5 ${SOURCE_DIR}/prepare.cpp MD5PREPARE)
|
||||
file(MD5 ${SOURCE_DIR}/data_structures/static_rtree.hpp MD5RTREE)
|
||||
file(MD5 ${SOURCE_DIR}/Util/graph_loader.hpp MD5GRAPH)
|
||||
file(MD5 ${SOURCE_DIR}/Server/DataStructures/InternalDataFacade.h MD5OBJECTS)
|
||||
file(MD5 ${SOURCE_DIR}/util/graph_loader.hpp MD5GRAPH)
|
||||
file(MD5 ${SOURCE_DIR}/server/data_structures/internal_datafacade.hpp MD5OBJECTS)
|
||||
|
||||
CONFIGURE_FILE( ${SOURCE_DIR}/Util/finger_print.cpp.in ${SOURCE_DIR}/Util/finger_print.cpp )
|
||||
CONFIGURE_FILE(${SOURCE_DIR}/util/fingerprint_impl.hpp.in ${SOURCE_DIR}/util/fingerprint_impl.hpp)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -35,9 +35,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#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 "../util/integer_range.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
@ -92,9 +92,11 @@ class Contractor
|
||||
};
|
||||
|
||||
using ContractorGraph = DynamicGraph<ContractorEdgeData>;
|
||||
// using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData, ArrayStorage<NodeID, NodeID>
|
||||
// using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData,
|
||||
// ArrayStorage<NodeID, NodeID>
|
||||
// >;
|
||||
using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData, XORFastHashStorage<NodeID, NodeID>>;
|
||||
using ContractorHeap =
|
||||
BinaryHeap<NodeID, NodeID, int, ContractorHeapData, XORFastHashStorage<NodeID, NodeID>>;
|
||||
using ContractorEdge = ContractorGraph::InputEdge;
|
||||
|
||||
struct ContractorThreadData
|
||||
@ -131,15 +133,14 @@ class Contractor
|
||||
bool is_independent : 1;
|
||||
};
|
||||
|
||||
|
||||
struct ThreadDataContainer
|
||||
{
|
||||
explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {}
|
||||
explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {}
|
||||
|
||||
inline ContractorThreadData* getThreadData()
|
||||
inline ContractorThreadData *getThreadData()
|
||||
{
|
||||
bool exists = false;
|
||||
auto& ref = data.local(exists);
|
||||
auto &ref = data.local(exists);
|
||||
if (!exists)
|
||||
{
|
||||
ref = std::make_shared<ContractorThreadData>(number_of_nodes);
|
||||
@ -149,7 +150,8 @@ class Contractor
|
||||
}
|
||||
|
||||
int number_of_nodes;
|
||||
using EnumerableThreadData = tbb::enumerable_thread_specific<std::shared_ptr<ContractorThreadData>>;
|
||||
using EnumerableThreadData =
|
||||
tbb::enumerable_thread_specific<std::shared_ptr<ContractorThreadData>>;
|
||||
EnumerableThreadData data;
|
||||
};
|
||||
|
||||
@ -162,29 +164,25 @@ class Contractor
|
||||
const auto dend = input_edge_list.dend();
|
||||
for (auto diter = input_edge_list.dbegin(); diter != dend; ++diter)
|
||||
{
|
||||
BOOST_ASSERT_MSG(static_cast<unsigned int>(std::max(diter->weight, 1)) > 0, "edge distance < 1");
|
||||
BOOST_ASSERT_MSG(static_cast<unsigned int>(std::max(diter->weight, 1)) > 0,
|
||||
"edge distance < 1");
|
||||
#ifndef NDEBUG
|
||||
if (static_cast<unsigned int>(std::max(diter->weight, 1)) > 24 * 60 * 60 * 10)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Edge weight large -> "
|
||||
<< static_cast<unsigned int>(std::max(diter->weight, 1));
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "Edge weight large -> "
|
||||
<< static_cast<unsigned int>(std::max(diter->weight, 1));
|
||||
}
|
||||
#endif
|
||||
edges.emplace_back(diter->source, diter->target,
|
||||
static_cast<unsigned int>(std::max(diter->weight, 1)),
|
||||
1,
|
||||
diter->edge_id,
|
||||
false,
|
||||
diter->forward ? true : false,
|
||||
diter->backward ? true : false);
|
||||
static_cast<unsigned int>(std::max(diter->weight, 1)), 1,
|
||||
diter->edge_id, false, diter->forward ? true : false,
|
||||
diter->backward ? true : false);
|
||||
|
||||
edges.emplace_back(diter->target, diter->source,
|
||||
static_cast<unsigned int>(std::max(diter->weight, 1)),
|
||||
1,
|
||||
diter->edge_id,
|
||||
false,
|
||||
diter->backward ? true : false,
|
||||
diter->forward ? true : false);
|
||||
static_cast<unsigned int>(std::max(diter->weight, 1)), 1,
|
||||
diter->edge_id, false, diter->backward ? true : false,
|
||||
diter->forward ? true : false);
|
||||
}
|
||||
// clear input vector
|
||||
input_edge_list.clear();
|
||||
@ -282,20 +280,20 @@ class Contractor
|
||||
std::cout << "contractor finished initalization" << std::endl;
|
||||
}
|
||||
|
||||
~Contractor() { }
|
||||
~Contractor() {}
|
||||
|
||||
void Run()
|
||||
{
|
||||
// for the preperation we can use a big grain size, which is much faster (probably cache)
|
||||
constexpr size_t InitGrainSize = 100000;
|
||||
constexpr size_t PQGrainSize = 100000;
|
||||
constexpr size_t InitGrainSize = 100000;
|
||||
constexpr size_t PQGrainSize = 100000;
|
||||
// auto_partitioner will automatically increase the blocksize if we have
|
||||
// a lot of data. It is *important* for the last loop iterations
|
||||
// (which have a very small dataset) that it is devisible.
|
||||
constexpr size_t IndependentGrainSize = 1;
|
||||
constexpr size_t ContractGrainSize = 1;
|
||||
constexpr size_t NeighboursGrainSize = 1;
|
||||
constexpr size_t DeleteGrainSize = 1;
|
||||
constexpr size_t ContractGrainSize = 1;
|
||||
constexpr size_t NeighboursGrainSize = 1;
|
||||
constexpr size_t DeleteGrainSize = 1;
|
||||
|
||||
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
||||
Percent p(number_of_nodes);
|
||||
@ -307,30 +305,28 @@ class Contractor
|
||||
std::vector<float> node_priorities(number_of_nodes);
|
||||
std::vector<NodePriorityData> node_data(number_of_nodes);
|
||||
|
||||
|
||||
// initialize priorities in parallel
|
||||
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, InitGrainSize),
|
||||
[&remaining_nodes](const tbb::blocked_range<int>& range)
|
||||
{
|
||||
for (int x = range.begin(); x != range.end(); ++x)
|
||||
{
|
||||
remaining_nodes[x].id = x;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
[&remaining_nodes](const tbb::blocked_range<int> &range)
|
||||
{
|
||||
for (int x = range.begin(); x != range.end(); ++x)
|
||||
{
|
||||
remaining_nodes[x].id = x;
|
||||
}
|
||||
});
|
||||
|
||||
std::cout << "initializing elimination PQ ..." << std::flush;
|
||||
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, PQGrainSize),
|
||||
[this, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& range)
|
||||
{
|
||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||
for (int x = range.begin(); x != range.end(); ++x)
|
||||
{
|
||||
node_priorities[x] = this->EvaluateNodePriority(data, &node_data[x], x);
|
||||
}
|
||||
}
|
||||
);
|
||||
[this, &node_priorities, &node_data, &thread_data_list](
|
||||
const tbb::blocked_range<int> &range)
|
||||
{
|
||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||
for (int x = range.begin(); x != range.end(); ++x)
|
||||
{
|
||||
node_priorities[x] =
|
||||
this->EvaluateNodePriority(data, &node_data[x], x);
|
||||
}
|
||||
});
|
||||
std::cout << "ok" << std::endl << "preprocessing " << number_of_nodes << " nodes ..."
|
||||
<< std::flush;
|
||||
|
||||
@ -368,7 +364,8 @@ class Contractor
|
||||
remaining_nodes[new_node_id].id = new_node_id;
|
||||
}
|
||||
// walk over all nodes
|
||||
for (const auto i : osrm::irange<std::size_t>(0, contractor_graph->GetNumberOfNodes()))
|
||||
for (const auto i :
|
||||
osrm::irange<std::size_t>(0, contractor_graph->GetNumberOfNodes()))
|
||||
{
|
||||
const NodeID source = i;
|
||||
for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source))
|
||||
@ -384,11 +381,9 @@ class Contractor
|
||||
{
|
||||
// node is not yet contracted.
|
||||
// add (renumbered) outgoing edges to new DynamicGraph.
|
||||
ContractorEdge new_edge = {
|
||||
new_node_id_from_orig_id_map[source],
|
||||
new_node_id_from_orig_id_map[target],
|
||||
data
|
||||
};
|
||||
ContractorEdge new_edge = {new_node_id_from_orig_id_map[source],
|
||||
new_node_id_from_orig_id_map[target],
|
||||
data};
|
||||
|
||||
new_edge.data.is_original_via_node_ID = true;
|
||||
BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[source],
|
||||
@ -427,28 +422,30 @@ class Contractor
|
||||
|
||||
const int last = (int)remaining_nodes.size();
|
||||
tbb::parallel_for(tbb::blocked_range<int>(0, last, IndependentGrainSize),
|
||||
[this, &node_priorities, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
|
||||
{
|
||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||
// determine independent node set
|
||||
for (int i = range.begin(); i != range.end(); ++i)
|
||||
{
|
||||
const NodeID node = remaining_nodes[i].id;
|
||||
remaining_nodes[i].is_independent =
|
||||
this->IsNodeIndependent(node_priorities, data, node);
|
||||
}
|
||||
}
|
||||
);
|
||||
[this, &node_priorities, &remaining_nodes, &thread_data_list](
|
||||
const tbb::blocked_range<int> &range)
|
||||
{
|
||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||
// determine independent node set
|
||||
for (int i = range.begin(); i != range.end(); ++i)
|
||||
{
|
||||
const NodeID node = remaining_nodes[i].id;
|
||||
remaining_nodes[i].is_independent =
|
||||
this->IsNodeIndependent(node_priorities, data, node);
|
||||
}
|
||||
});
|
||||
|
||||
const auto first = stable_partition(remaining_nodes.begin(),
|
||||
remaining_nodes.end(),
|
||||
const auto first = stable_partition(remaining_nodes.begin(), remaining_nodes.end(),
|
||||
[](RemainingNodeData node_data)
|
||||
{ return !node_data.is_independent; });
|
||||
{
|
||||
return !node_data.is_independent;
|
||||
});
|
||||
const int first_independent_node = static_cast<int>(first - remaining_nodes.begin());
|
||||
|
||||
// contract independent nodes
|
||||
tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, ContractGrainSize),
|
||||
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<int>(first_independent_node, last, ContractGrainSize),
|
||||
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
|
||||
{
|
||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||
for (int position = range.begin(); position != range.end(); ++position)
|
||||
@ -456,19 +453,18 @@ class Contractor
|
||||
const NodeID x = remaining_nodes[position].id;
|
||||
this->ContractNode<false>(data, x);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
// make sure we really sort each block
|
||||
tbb::parallel_for(thread_data_list.data.range(),
|
||||
[&](const ThreadDataContainer::EnumerableThreadData::range_type& range)
|
||||
tbb::parallel_for(
|
||||
thread_data_list.data.range(),
|
||||
[&](const ThreadDataContainer::EnumerableThreadData::range_type &range)
|
||||
{
|
||||
for (auto& data : range)
|
||||
std::sort(data->inserted_edges.begin(),
|
||||
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)
|
||||
for (auto &data : range)
|
||||
std::sort(data->inserted_edges.begin(), 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(); position != range.end(); ++position)
|
||||
@ -476,15 +472,15 @@ class Contractor
|
||||
const NodeID x = remaining_nodes[position].id;
|
||||
this->DeleteIncomingEdges(data, x);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// insert new edges
|
||||
for (auto& data : thread_data_list.data)
|
||||
for (auto &data : thread_data_list.data)
|
||||
{
|
||||
for (const ContractorEdge &edge : data->inserted_edges)
|
||||
{
|
||||
const EdgeID current_edge_ID = contractor_graph->FindEdge(edge.source, edge.target);
|
||||
const EdgeID current_edge_ID =
|
||||
contractor_graph->FindEdge(edge.source, edge.target);
|
||||
if (current_edge_ID < contractor_graph->EndEdges(edge.source))
|
||||
{
|
||||
ContractorGraph::EdgeData ¤t_data =
|
||||
@ -503,8 +499,10 @@ class Contractor
|
||||
data->inserted_edges.clear();
|
||||
}
|
||||
|
||||
tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, NeighboursGrainSize),
|
||||
[this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& range)
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<int>(first_independent_node, last, NeighboursGrainSize),
|
||||
[this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list](
|
||||
const tbb::blocked_range<int> &range)
|
||||
{
|
||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||
for (int position = range.begin(); position != range.end(); ++position)
|
||||
@ -512,8 +510,7 @@ class Contractor
|
||||
NodeID x = remaining_nodes[position].id;
|
||||
this->UpdateNodeNeighbours(node_priorities, node_data, data, x);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// remove contracted nodes from the pool
|
||||
number_of_contracted_nodes += last - first_independent_node;
|
||||
@ -774,17 +771,11 @@ class Contractor
|
||||
{
|
||||
inserted_edges.emplace_back(source, target, path_distance,
|
||||
out_data.originalEdges + in_data.originalEdges,
|
||||
node,
|
||||
true,
|
||||
true,
|
||||
false);
|
||||
node, true, true, false);
|
||||
|
||||
inserted_edges.emplace_back(target, source, path_distance,
|
||||
out_data.originalEdges + in_data.originalEdges,
|
||||
node,
|
||||
true,
|
||||
false,
|
||||
true);
|
||||
node, true, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -883,10 +874,9 @@ class Contractor
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool IsNodeIndependent(
|
||||
const std::vector<float> &priorities,
|
||||
ContractorThreadData *const data,
|
||||
NodeID node) const
|
||||
inline bool IsNodeIndependent(const std::vector<float> &priorities,
|
||||
ContractorThreadData *const data,
|
||||
NodeID node) const
|
||||
{
|
||||
const float priority = priorities[node];
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,11 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "edge_based_graph_factory.hpp"
|
||||
#include "../algorithms/tiny_components.hpp"
|
||||
#include "../data_structures/percent.hpp"
|
||||
#include "../Util/compute_angle.hpp"
|
||||
#include "../Util/integer_range.hpp"
|
||||
#include "../Util/lua_util.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/timing_util.hpp"
|
||||
#include "../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>
|
||||
|
||||
@ -77,33 +77,25 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes)
|
||||
nodes.swap(m_edge_based_node_list);
|
||||
}
|
||||
|
||||
void
|
||||
EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
|
||||
const NodeID node_v,
|
||||
const unsigned component_id)
|
||||
void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
|
||||
const NodeID node_v,
|
||||
const unsigned component_id)
|
||||
{
|
||||
// merge edges together into one EdgeBasedNode
|
||||
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||
|
||||
// find forward edge id and
|
||||
const EdgeID e1 = m_node_based_graph->FindEdge(node_u, node_v);
|
||||
BOOST_ASSERT(e1 != SPECIAL_EDGEID);
|
||||
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(e1);
|
||||
const EdgeData &forward_data = m_node_based_graph->GetEdgeData(edge_id_1);
|
||||
|
||||
// find reverse edge id and
|
||||
const EdgeID e2 = m_node_based_graph->FindEdge(node_v, node_u);
|
||||
const EdgeID edge_id_2 = m_node_based_graph->FindEdge(node_v, node_u);
|
||||
BOOST_ASSERT(edge_id_2 != SPECIAL_EDGEID);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (e2 == m_node_based_graph->EndEdges(node_v))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Did not find edge (" << node_v << "," << node_u << ")";
|
||||
}
|
||||
#endif
|
||||
BOOST_ASSERT(e2 != SPECIAL_EDGEID);
|
||||
BOOST_ASSERT(e2 < m_node_based_graph->EndEdges(node_v));
|
||||
const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(e2);
|
||||
const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(edge_id_2);
|
||||
|
||||
if (forward_data.edgeBasedNodeID == SPECIAL_NODEID &&
|
||||
reverse_data.edgeBasedNodeID == SPECIAL_NODEID)
|
||||
@ -111,17 +103,17 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(m_geometry_compressor.HasEntryForID(e1) ==
|
||||
m_geometry_compressor.HasEntryForID(e2));
|
||||
if (m_geometry_compressor.HasEntryForID(e1))
|
||||
BOOST_ASSERT(m_geometry_compressor.HasEntryForID(edge_id_1) ==
|
||||
m_geometry_compressor.HasEntryForID(edge_id_2));
|
||||
if (m_geometry_compressor.HasEntryForID(edge_id_1))
|
||||
{
|
||||
BOOST_ASSERT(m_geometry_compressor.HasEntryForID(e2));
|
||||
BOOST_ASSERT(m_geometry_compressor.HasEntryForID(edge_id_2));
|
||||
|
||||
// reconstruct geometry and put in each individual edge with its offset
|
||||
const std::vector<GeometryCompressor::CompressedNode> &forward_geometry =
|
||||
m_geometry_compressor.GetBucketReference(e1);
|
||||
m_geometry_compressor.GetBucketReference(edge_id_1);
|
||||
const std::vector<GeometryCompressor::CompressedNode> &reverse_geometry =
|
||||
m_geometry_compressor.GetBucketReference(e2);
|
||||
m_geometry_compressor.GetBucketReference(edge_id_2);
|
||||
BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size());
|
||||
BOOST_ASSERT(0 != forward_geometry.size());
|
||||
const unsigned geometry_size = static_cast<unsigned>(forward_geometry.size());
|
||||
@ -172,20 +164,13 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
|
||||
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
|
||||
|
||||
// build edges
|
||||
m_edge_based_node_list.emplace_back(forward_data.edgeBasedNodeID,
|
||||
reverse_data.edgeBasedNodeID,
|
||||
current_edge_source_coordinate_id,
|
||||
current_edge_target_coordinate_id,
|
||||
forward_data.nameID,
|
||||
forward_geometry[i].second,
|
||||
reverse_geometry[geometry_size - 1 - i].second,
|
||||
forward_dist_prefix_sum[i],
|
||||
reverse_dist_prefix_sum[i],
|
||||
m_geometry_compressor.GetPositionForID(e1),
|
||||
component_id,
|
||||
i,
|
||||
forward_data.travel_mode,
|
||||
reverse_data.travel_mode);
|
||||
m_edge_based_node_list.emplace_back(
|
||||
forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID,
|
||||
current_edge_source_coordinate_id, current_edge_target_coordinate_id,
|
||||
forward_data.nameID, forward_geometry[i].second,
|
||||
reverse_geometry[geometry_size - 1 - i].second, forward_dist_prefix_sum[i],
|
||||
reverse_dist_prefix_sum[i], m_geometry_compressor.GetPositionForID(edge_id_1),
|
||||
component_id, i, forward_data.travel_mode, reverse_data.travel_mode);
|
||||
current_edge_source_coordinate_id = current_edge_target_coordinate_id;
|
||||
|
||||
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
|
||||
@ -202,7 +187,7 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(!m_geometry_compressor.HasEntryForID(e2));
|
||||
BOOST_ASSERT(!m_geometry_compressor.HasEntryForID(edge_id_2));
|
||||
|
||||
if (forward_data.edgeBasedNodeID != SPECIAL_NODEID)
|
||||
{
|
||||
@ -224,20 +209,10 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
|
||||
BOOST_ASSERT(forward_data.edgeBasedNodeID != SPECIAL_NODEID ||
|
||||
reverse_data.edgeBasedNodeID != SPECIAL_NODEID);
|
||||
|
||||
m_edge_based_node_list.emplace_back(forward_data.edgeBasedNodeID,
|
||||
reverse_data.edgeBasedNodeID,
|
||||
node_u,
|
||||
node_v,
|
||||
forward_data.nameID,
|
||||
forward_data.distance,
|
||||
reverse_data.distance,
|
||||
0,
|
||||
0,
|
||||
SPECIAL_EDGEID,
|
||||
component_id,
|
||||
0,
|
||||
forward_data.travel_mode,
|
||||
reverse_data.travel_mode);
|
||||
m_edge_based_node_list.emplace_back(
|
||||
forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID, node_u, node_v,
|
||||
forward_data.nameID, forward_data.distance, reverse_data.distance, 0, 0, SPECIAL_EDGEID,
|
||||
component_id, 0, forward_data.travel_mode, reverse_data.travel_mode);
|
||||
BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed());
|
||||
}
|
||||
}
|
||||
@ -245,7 +220,8 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
|
||||
void EdgeBasedGraphFactory::FlushVectorToStream(
|
||||
std::ofstream &edge_data_file, std::vector<OriginalEdgeData> &original_edge_data_vector) const
|
||||
{
|
||||
if (original_edge_data_vector.empty()) {
|
||||
if (original_edge_data_vector.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
edge_data_file.write((char *)&(original_edge_data_vector[0]),
|
||||
@ -332,7 +308,6 @@ void EdgeBasedGraphFactory::CompressGeometry()
|
||||
BOOST_ASSERT(node_u != node_v);
|
||||
|
||||
const EdgeID forward_e1 = m_node_based_graph->FindEdge(node_u, node_v);
|
||||
BOOST_ASSERT(m_node_based_graph->EndEdges(node_u) != forward_e1);
|
||||
BOOST_ASSERT(SPECIAL_EDGEID != forward_e1);
|
||||
BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(forward_e1));
|
||||
const EdgeID reverse_e1 = m_node_based_graph->FindEdge(node_w, node_v);
|
||||
@ -342,15 +317,13 @@ void EdgeBasedGraphFactory::CompressGeometry()
|
||||
const EdgeData &fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1);
|
||||
const EdgeData &rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1);
|
||||
|
||||
if ((m_node_based_graph->FindEdge(node_u, node_w) != m_node_based_graph->EndEdges(node_u)) ||
|
||||
(m_node_based_graph->FindEdge(node_w, node_u) != m_node_based_graph->EndEdges(node_w)))
|
||||
if (m_node_based_graph->FindEdgeInEitherDirection(node_u, node_w) != SPECIAL_EDGEID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( // TODO: rename to IsCompatibleTo
|
||||
fwd_edge_data1.IsEqualTo(fwd_edge_data2) &&
|
||||
rev_edge_data1.IsEqualTo(rev_edge_data2))
|
||||
fwd_edge_data1.IsEqualTo(fwd_edge_data2) && rev_edge_data1.IsEqualTo(rev_edge_data2))
|
||||
{
|
||||
// Get distances before graph is modified
|
||||
const int forward_weight1 = m_node_based_graph->GetEdgeData(forward_e1).distance;
|
||||
@ -365,13 +338,12 @@ void EdgeBasedGraphFactory::CompressGeometry()
|
||||
BOOST_ASSERT(0 != reverse_weight1);
|
||||
BOOST_ASSERT(0 != forward_weight2);
|
||||
|
||||
const bool add_traffic_signal_penalty =
|
||||
(m_traffic_lights.find(node_v) != m_traffic_lights.end());
|
||||
const bool has_node_penalty = m_traffic_lights.find(node_v) != m_traffic_lights.end();
|
||||
|
||||
// add weight of e2's to e1
|
||||
m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
|
||||
m_node_based_graph->GetEdgeData(reverse_e1).distance += rev_edge_data2.distance;
|
||||
if (add_traffic_signal_penalty)
|
||||
if (has_node_penalty)
|
||||
{
|
||||
m_node_based_graph->GetEdgeData(forward_e1).distance +=
|
||||
speed_profile.traffic_signal_penalty;
|
||||
@ -389,32 +361,21 @@ void EdgeBasedGraphFactory::CompressGeometry()
|
||||
|
||||
// update any involved turn restrictions
|
||||
m_restriction_map->FixupStartingTurnRestriction(node_u, node_v, node_w);
|
||||
m_restriction_map->FixupArrivingTurnRestriction(node_u, node_v,
|
||||
node_w,
|
||||
m_restriction_map->FixupArrivingTurnRestriction(node_u, node_v, node_w,
|
||||
m_node_based_graph);
|
||||
|
||||
m_restriction_map->FixupStartingTurnRestriction(node_w, node_v, node_u);
|
||||
m_restriction_map->FixupArrivingTurnRestriction(node_w,
|
||||
node_v,
|
||||
node_u, m_node_based_graph);
|
||||
m_restriction_map->FixupArrivingTurnRestriction(node_w, node_v, node_u,
|
||||
m_node_based_graph);
|
||||
|
||||
// store compressed geometry in container
|
||||
m_geometry_compressor.CompressEdge(
|
||||
forward_e1,
|
||||
forward_e2,
|
||||
node_v,
|
||||
node_w,
|
||||
forward_weight1 +
|
||||
(add_traffic_signal_penalty ? speed_profile.traffic_signal_penalty : 0),
|
||||
forward_e1, forward_e2, node_v, node_w,
|
||||
forward_weight1 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0),
|
||||
forward_weight2);
|
||||
m_geometry_compressor.CompressEdge(
|
||||
reverse_e1,
|
||||
reverse_e2,
|
||||
node_v,
|
||||
node_u,
|
||||
reverse_weight1,
|
||||
reverse_weight2 +
|
||||
(add_traffic_signal_penalty ? speed_profile.traffic_signal_penalty : 0));
|
||||
reverse_e1, reverse_e2, node_v, node_u, reverse_weight1,
|
||||
reverse_weight2 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0));
|
||||
++removed_node_count;
|
||||
|
||||
BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
|
||||
@ -427,7 +388,7 @@ void EdgeBasedGraphFactory::CompressGeometry()
|
||||
unsigned new_node_count = 0;
|
||||
unsigned new_edge_count = 0;
|
||||
|
||||
for(const auto i : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
for (const auto i : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
{
|
||||
if (m_node_based_graph->GetOutDegree(i) > 0)
|
||||
{
|
||||
@ -436,10 +397,10 @@ void EdgeBasedGraphFactory::CompressGeometry()
|
||||
}
|
||||
}
|
||||
SimpleLogger().Write() << "new nodes: " << new_node_count << ", edges " << new_edge_count;
|
||||
SimpleLogger().Write() << "Node compression ratio: " << new_node_count /
|
||||
(double)original_number_of_nodes;
|
||||
SimpleLogger().Write() << "Edge compression ratio: " << new_edge_count /
|
||||
(double)original_number_of_edges;
|
||||
SimpleLogger().Write() << "Node compression ratio: "
|
||||
<< new_node_count / (double)original_number_of_nodes;
|
||||
SimpleLogger().Write() << "Edge compression ratio: "
|
||||
<< new_edge_count / (double)original_number_of_edges;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -477,62 +438,69 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
||||
SimpleLogger().Write() << "Identifying components of the (compressed) road network";
|
||||
|
||||
// Run a BFS on the undirected graph and identify small components
|
||||
TarjanSCC<NodeBasedDynamicGraph> component_explorer(
|
||||
m_node_based_graph, *m_restriction_map, m_barrier_nodes);
|
||||
TarjanSCC<NodeBasedDynamicGraph> component_explorer(m_node_based_graph, *m_restriction_map,
|
||||
m_barrier_nodes);
|
||||
|
||||
component_explorer.run();
|
||||
|
||||
SimpleLogger().Write() << "identified: " << component_explorer.get_number_of_components() - removed_node_count
|
||||
SimpleLogger().Write() << "identified: "
|
||||
<< component_explorer.get_number_of_components() - removed_node_count
|
||||
<< " (compressed) components";
|
||||
SimpleLogger().Write() << "identified " << component_explorer.get_size_one_count() - removed_node_count
|
||||
SimpleLogger().Write() << "identified "
|
||||
<< component_explorer.get_size_one_count() - removed_node_count
|
||||
<< " (compressed) SCCs of size 1";
|
||||
SimpleLogger().Write() << "generating edge-expanded nodes";
|
||||
|
||||
Percent progress(m_node_based_graph->GetNumberOfNodes());
|
||||
|
||||
// loop over all edges and generate new set of nodes
|
||||
for (const auto u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
for (const auto node_u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
{
|
||||
BOOST_ASSERT(u != SPECIAL_NODEID);
|
||||
BOOST_ASSERT(u < m_node_based_graph->GetNumberOfNodes());
|
||||
progress.printStatus(u);
|
||||
for (EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
|
||||
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 v = m_node_based_graph->GetTarget(e1);
|
||||
const NodeID node_v = m_node_based_graph->GetTarget(e1);
|
||||
|
||||
BOOST_ASSERT(SPECIAL_NODEID != v);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != node_v);
|
||||
// pick only every other edge
|
||||
if (u > v)
|
||||
if (node_u > node_v)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(u < v);
|
||||
BOOST_ASSERT(node_u < node_v);
|
||||
|
||||
// Note: edges that end on barrier nodes or on a turn restriction
|
||||
// may actually be in two distinct components. We choose the smallest
|
||||
const unsigned size_of_component = std::min(component_explorer.get_component_size(u),
|
||||
component_explorer.get_component_size(v));
|
||||
const unsigned size_of_component =
|
||||
std::min(component_explorer.get_component_size(node_u),
|
||||
component_explorer.get_component_size(node_v));
|
||||
|
||||
const unsigned id_of_smaller_component = [u,v,&component_explorer] {
|
||||
if (component_explorer.get_component_size(u) < component_explorer.get_component_size(v))
|
||||
const unsigned id_of_smaller_component = [node_u, node_v, &component_explorer]
|
||||
{
|
||||
if (component_explorer.get_component_size(node_u) <
|
||||
component_explorer.get_component_size(node_v))
|
||||
{
|
||||
return component_explorer.get_component_id(u);
|
||||
return component_explorer.get_component_id(node_u);
|
||||
}
|
||||
return component_explorer.get_component_id(v);
|
||||
return component_explorer.get_component_id(node_v);
|
||||
}();
|
||||
|
||||
const bool component_is_tiny = (size_of_component < 1000);
|
||||
const bool component_is_tiny = size_of_component < 1000;
|
||||
|
||||
if (edge_data.edgeBasedNodeID == SPECIAL_NODEID)
|
||||
{
|
||||
InsertEdgeBasedNode(v, u, (component_is_tiny ? id_of_smaller_component + 1 : 0));
|
||||
InsertEdgeBasedNode(node_v, node_u,
|
||||
(component_is_tiny ? id_of_smaller_component + 1 : 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertEdgeBasedNode(u, v, (component_is_tiny ? id_of_smaller_component + 1 : 0));
|
||||
InsertEdgeBasedNode(node_u, node_v,
|
||||
(component_is_tiny ? id_of_smaller_component + 1 : 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -544,9 +512,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
||||
/**
|
||||
* Actually it also generates OriginalEdgeData and serializes them...
|
||||
*/
|
||||
void
|
||||
EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
|
||||
lua_State *lua_state)
|
||||
void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
const std::string &original_edge_data_filename, lua_State *lua_state)
|
||||
{
|
||||
SimpleLogger().Write() << "generating edge-expanded edges";
|
||||
|
||||
@ -571,10 +538,10 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
|
||||
|
||||
Percent progress(m_node_based_graph->GetNumberOfNodes());
|
||||
|
||||
for (const auto u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
for (const auto node_u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
{
|
||||
progress.printStatus(u);
|
||||
for (const EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
|
||||
progress.printStatus(node_u);
|
||||
for (const EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(node_u))
|
||||
{
|
||||
if (!m_node_based_graph->GetEdgeData(e1).forward)
|
||||
{
|
||||
@ -582,21 +549,21 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
|
||||
}
|
||||
|
||||
++node_based_edge_counter;
|
||||
const NodeID v = m_node_based_graph->GetTarget(e1);
|
||||
const NodeID to_node_of_only_restriction =
|
||||
m_restriction_map->CheckForEmanatingIsOnlyTurn(u, v);
|
||||
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
|
||||
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(v))
|
||||
for (const EdgeID e2 : m_node_based_graph->GetAdjacentEdgeRange(node_v))
|
||||
{
|
||||
if (!m_node_based_graph->GetEdgeData(e2).forward)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const NodeID w = m_node_based_graph->GetTarget(e2);
|
||||
const NodeID node_w = m_node_based_graph->GetTarget(e2);
|
||||
|
||||
if ((to_node_of_only_restriction != SPECIAL_NODEID) &&
|
||||
(w != to_node_of_only_restriction))
|
||||
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;
|
||||
@ -605,7 +572,7 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
|
||||
|
||||
if (is_barrier_node)
|
||||
{
|
||||
if (u != w)
|
||||
if (node_u != node_w)
|
||||
{
|
||||
++skipped_barrier_turns_counter;
|
||||
continue;
|
||||
@ -613,7 +580,7 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((u == w) && (m_node_based_graph->GetOutDegree(v) > 1))
|
||||
if ((node_u == node_w) && (m_node_based_graph->GetOutDegree(node_v) > 1))
|
||||
{
|
||||
++skipped_uturns_counter;
|
||||
continue;
|
||||
@ -622,9 +589,9 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
|
||||
|
||||
// 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) &&
|
||||
(to_node_of_only_restriction == SPECIAL_NODEID) &&
|
||||
(w != to_node_of_only_restriction))
|
||||
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;
|
||||
@ -641,26 +608,28 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
|
||||
|
||||
// the following is the core of the loop.
|
||||
unsigned distance = edge_data1.distance;
|
||||
if (m_traffic_lights.find(v) != m_traffic_lights.end())
|
||||
if (m_traffic_lights.find(node_v) != m_traffic_lights.end())
|
||||
{
|
||||
distance += speed_profile.traffic_signal_penalty;
|
||||
}
|
||||
|
||||
// unpack last node of first segment if packed
|
||||
const auto first_coordinate = m_node_info_list[(m_geometry_compressor.HasEntryForID(e1) ?
|
||||
m_geometry_compressor.GetLastNodeIDOfBucket(e1) :
|
||||
u)];
|
||||
const auto first_coordinate =
|
||||
m_node_info_list[(m_geometry_compressor.HasEntryForID(e1)
|
||||
? m_geometry_compressor.GetLastNodeIDOfBucket(e1)
|
||||
: node_u)];
|
||||
|
||||
// unpack first node of second segment if packed
|
||||
const auto third_coordinate = m_node_info_list[(m_geometry_compressor.HasEntryForID(e2) ?
|
||||
m_geometry_compressor.GetFirstNodeIDOfBucket(e2) :
|
||||
w)];
|
||||
const auto third_coordinate =
|
||||
m_node_info_list[(m_geometry_compressor.HasEntryForID(e2)
|
||||
? m_geometry_compressor.GetFirstNodeIDOfBucket(e2)
|
||||
: node_w)];
|
||||
|
||||
const double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates(
|
||||
first_coordinate, m_node_info_list[v], third_coordinate);
|
||||
first_coordinate, m_node_info_list[node_v], third_coordinate);
|
||||
|
||||
const int turn_penalty = GetTurnPenalty(turn_angle, lua_state);
|
||||
TurnInstruction turn_instruction = AnalyzeTurn(u, v, w, turn_angle);
|
||||
TurnInstruction turn_instruction = AnalyzeTurn(node_u, node_v, node_w, turn_angle);
|
||||
if (turn_instruction == TurnInstruction::UTurn)
|
||||
{
|
||||
distance += speed_profile.u_turn_penalty;
|
||||
@ -675,10 +644,8 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
|
||||
}
|
||||
|
||||
original_edge_data_vector.emplace_back(
|
||||
(edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v),
|
||||
edge_data1.nameID,
|
||||
turn_instruction,
|
||||
edge_is_compressed,
|
||||
(edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : node_v),
|
||||
edge_data1.nameID, turn_instruction, edge_is_compressed,
|
||||
edge_data2.travel_mode);
|
||||
|
||||
++original_edges_counter;
|
||||
@ -691,12 +658,9 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
|
||||
BOOST_ASSERT(SPECIAL_NODEID != edge_data1.edgeBasedNodeID);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != edge_data2.edgeBasedNodeID);
|
||||
|
||||
m_edge_based_edge_list.emplace_back(EdgeBasedEdge(edge_data1.edgeBasedNodeID,
|
||||
edge_data2.edgeBasedNodeID,
|
||||
m_edge_based_edge_list.size(),
|
||||
distance,
|
||||
true,
|
||||
false));
|
||||
m_edge_based_edge_list.emplace_back(
|
||||
EdgeBasedEdge(edge_data1.edgeBasedNodeID, edge_data2.edgeBasedNodeID,
|
||||
m_edge_based_edge_list.size(), distance, true, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -727,7 +691,10 @@ int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) co
|
||||
// call lua profile to compute turn penalty
|
||||
return luabind::call_function<int>(lua_state, "turn_function", 180. - angle);
|
||||
}
|
||||
catch (const luabind::error &er) { SimpleLogger().Write(logWARNING) << er.what(); }
|
||||
catch (const luabind::error &er)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << er.what();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -735,8 +702,7 @@ int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) co
|
||||
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID node_u,
|
||||
const NodeID node_v,
|
||||
const NodeID node_w,
|
||||
const double angle)
|
||||
const
|
||||
const double angle) const
|
||||
{
|
||||
if (node_u == node_w)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "geometry_compressor.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
@ -35,9 +35,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
int free_list_maximum = 0;
|
||||
int UniqueNumber() { return ++free_list_maximum; }
|
||||
|
||||
GeometryCompressor::GeometryCompressor()
|
||||
{
|
||||
m_free_list.reserve(100);
|
||||
@ -174,8 +171,8 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
|
||||
m_compressed_geometries[list_to_remove_index];
|
||||
|
||||
// found an existing list, append it to the list of edge_id_1
|
||||
edge_bucket_list1.insert(
|
||||
edge_bucket_list1.end(), edge_bucket_list2.begin(), edge_bucket_list2.end());
|
||||
edge_bucket_list1.insert(edge_bucket_list1.end(), edge_bucket_list2.begin(),
|
||||
edge_bucket_list2.end());
|
||||
|
||||
// remove the list of edge_id_2
|
||||
m_edge_id_to_list_index_map.erase(edge_id_2);
|
||||
@ -211,9 +208,8 @@ void GeometryCompressor::PrintStatistics() const
|
||||
"\n compressed edges: " << compressed_edges
|
||||
<< "\n compressed geometries: " << compressed_geometries
|
||||
<< "\n longest chain length: " << longest_chain_length
|
||||
<< "\n cmpr ratio: "
|
||||
<< ((float)compressed_edges /
|
||||
std::max(compressed_geometries, (uint64_t)1))
|
||||
<< "\n cmpr ratio: " << ((float)compressed_edges /
|
||||
std::max(compressed_geometries, (uint64_t)1))
|
||||
<< "\n avg chain length: "
|
||||
<< (float)compressed_geometries /
|
||||
std::max((uint64_t)1, compressed_edges);
|
||||
@ -226,16 +222,15 @@ GeometryCompressor::GetBucketReference(const EdgeID edge_id) const
|
||||
return m_compressed_geometries.at(index);
|
||||
}
|
||||
|
||||
NodeID GeometryCompressor::GetFirstNodeIDOfBucket(const EdgeID edge_id) const
|
||||
{
|
||||
const auto &bucket = GetBucketReference(edge_id);
|
||||
BOOST_ASSERT(bucket.size() >= 2);
|
||||
return bucket[1].first;
|
||||
}
|
||||
NodeID GeometryCompressor::GetLastNodeIDOfBucket(const EdgeID edge_id) const
|
||||
{
|
||||
const auto &bucket = GetBucketReference(edge_id);
|
||||
BOOST_ASSERT(bucket.size() >= 2);
|
||||
return bucket[bucket.size()-2].first;
|
||||
}
|
||||
|
||||
NodeID GeometryCompressor::GetFirstNodeIDOfBucket(const EdgeID edge_id) const
|
||||
{
|
||||
const auto &bucket = GetBucketReference(edge_id);
|
||||
BOOST_ASSERT(bucket.size() >= 2);
|
||||
return bucket[1].first;
|
||||
}
|
||||
NodeID GeometryCompressor::GetLastNodeIDOfBucket(const EdgeID edge_id) const
|
||||
{
|
||||
const auto &bucket = GetBucketReference(edge_id);
|
||||
BOOST_ASSERT(bucket.size() >= 2);
|
||||
return bucket[bucket.size() - 2].first;
|
||||
}
|
||||
|
@ -58,6 +58,8 @@ class GeometryCompressor
|
||||
NodeID GetLastNodeIDOfBucket(const EdgeID edge_id) const;
|
||||
|
||||
private:
|
||||
int free_list_maximum = 0;
|
||||
|
||||
void IncreaseFreeList();
|
||||
std::vector<std::vector<CompressedNode>> m_compressed_geometries;
|
||||
std::vector<unsigned> m_free_list;
|
||||
|
@ -34,15 +34,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../data_structures/static_rtree.hpp"
|
||||
#include "../data_structures/restriction_map.hpp"
|
||||
|
||||
#include "../Util/git_sha.hpp"
|
||||
#include "../Util/graph_loader.hpp"
|
||||
#include "../Util/integer_range.hpp"
|
||||
#include "../Util/lua_util.hpp"
|
||||
#include "../Util/make_unique.hpp"
|
||||
#include "../Util/osrm_exception.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/string_util.hpp"
|
||||
#include "../Util/timing_util.hpp"
|
||||
#include "../util/git_sha.hpp"
|
||||
#include "../util/graph_loader.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../util/lua_util.hpp"
|
||||
#include "../util/make_unique.hpp"
|
||||
#include "../util/osrm_exception.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/string_util.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
@ -138,13 +138,9 @@ int Prepare::Process(int argc, char *argv[])
|
||||
static_assert(sizeof(ImportEdge) == 20,
|
||||
"changing ImportEdge type has influence on memory consumption!");
|
||||
#endif
|
||||
NodeID number_of_node_based_nodes =
|
||||
readBinaryOSRMGraphFromStream(input_stream,
|
||||
edge_list,
|
||||
barrier_node_list,
|
||||
traffic_light_list,
|
||||
&internal_to_external_node_map,
|
||||
restriction_list);
|
||||
NodeID number_of_node_based_nodes = readBinaryOSRMGraphFromStream(
|
||||
input_stream, edge_list, barrier_node_list, traffic_light_list,
|
||||
&internal_to_external_node_map, restriction_list);
|
||||
input_stream.close();
|
||||
|
||||
if (edge_list.empty())
|
||||
@ -162,11 +158,9 @@ int Prepare::Process(int argc, char *argv[])
|
||||
DeallocatingVector<EdgeBasedEdge> edge_based_edge_list;
|
||||
|
||||
// init node_based_edge_list, edge_based_edge_list by edgeList
|
||||
number_of_edge_based_nodes = BuildEdgeExpandedGraph(lua_state,
|
||||
number_of_node_based_nodes,
|
||||
node_based_edge_list,
|
||||
edge_based_edge_list,
|
||||
speed_profile);
|
||||
number_of_edge_based_nodes =
|
||||
BuildEdgeExpandedGraph(lua_state, number_of_node_based_nodes, node_based_edge_list,
|
||||
edge_based_edge_list, speed_profile);
|
||||
lua_close(lua_state);
|
||||
|
||||
TIMER_STOP(expansion);
|
||||
@ -343,9 +337,8 @@ bool Prepare::ParseArguments(int argc, char *argv[])
|
||||
// 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>(&config_file_path)
|
||||
->default_value("contractor.ini"),
|
||||
"config,c", boost::program_options::value<boost::filesystem::path>(&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
|
||||
@ -354,21 +347,18 @@ bool Prepare::ParseArguments(int argc, char *argv[])
|
||||
"restrictions,r",
|
||||
boost::program_options::value<boost::filesystem::path>(&restrictions_path),
|
||||
"Restrictions file in .osrm.restrictions format")(
|
||||
"profile,p",
|
||||
boost::program_options::value<boost::filesystem::path>(&profile_path)
|
||||
->default_value("profile.lua"),
|
||||
"profile,p", boost::program_options::value<boost::filesystem::path>(&profile_path)
|
||||
->default_value("profile.lua"),
|
||||
"Path to LUA routing profile")(
|
||||
"threads,t",
|
||||
boost::program_options::value<unsigned int>(&requested_num_threads)
|
||||
->default_value(tbb::task_scheduler_init::default_num_threads()),
|
||||
"threads,t", boost::program_options::value<unsigned int>(&requested_num_threads)
|
||||
->default_value(tbb::task_scheduler_init::default_num_threads()),
|
||||
"Number of threads to use");
|
||||
|
||||
// hidden options, will be allowed both on command line and in config file, but will not be
|
||||
// shown to the user
|
||||
boost::program_options::options_description hidden_options("Hidden options");
|
||||
hidden_options.add_options()(
|
||||
"input,i",
|
||||
boost::program_options::value<boost::filesystem::path>(&input_path),
|
||||
"input,i", boost::program_options::value<boost::filesystem::path>(&input_path),
|
||||
"Input file in .osm, .osm.bz2 or .osm.pbf format");
|
||||
|
||||
// positional option
|
||||
@ -394,10 +384,11 @@ bool Prepare::ParseArguments(int argc, char *argv[])
|
||||
.run(),
|
||||
option_variables);
|
||||
|
||||
const auto& temp_config_path = option_variables["config"].as<boost::filesystem::path>();
|
||||
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),
|
||||
boost::program_options::store(boost::program_options::parse_config_file<char>(
|
||||
temp_config_path.string().c_str(), cmdline_options, true),
|
||||
option_variables);
|
||||
}
|
||||
|
||||
@ -458,9 +449,8 @@ void Prepare::CheckRestrictionsFile(FingerPrint &fingerprint_orig)
|
||||
\brief Setups scripting environment (lua-scripting)
|
||||
Also initializes speed profile.
|
||||
*/
|
||||
bool
|
||||
Prepare::SetupScriptingEnvironment(lua_State *lua_state,
|
||||
EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile)
|
||||
bool Prepare::SetupScriptingEnvironment(
|
||||
lua_State *lua_state, EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile)
|
||||
{
|
||||
// open utility libraries string library;
|
||||
luaL_openlibs(lua_state);
|
||||
@ -509,14 +499,12 @@ Prepare::BuildEdgeExpandedGraph(lua_State *lua_state,
|
||||
SimpleLogger().Write() << "Generating edge-expanded graph representation";
|
||||
std::shared_ptr<NodeBasedDynamicGraph> node_based_graph =
|
||||
NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
|
||||
std::unique_ptr<RestrictionMap> restriction_map = osrm::make_unique<RestrictionMap>(restriction_list);
|
||||
std::unique_ptr<RestrictionMap> restriction_map =
|
||||
osrm::make_unique<RestrictionMap>(restriction_list);
|
||||
std::shared_ptr<EdgeBasedGraphFactory> edge_based_graph_factory =
|
||||
std::make_shared<EdgeBasedGraphFactory>(node_based_graph,
|
||||
std::move(restriction_map),
|
||||
barrier_node_list,
|
||||
traffic_light_list,
|
||||
internal_to_external_node_map,
|
||||
speed_profile);
|
||||
std::make_shared<EdgeBasedGraphFactory>(node_based_graph, std::move(restriction_map),
|
||||
barrier_node_list, traffic_light_list,
|
||||
internal_to_external_node_map, speed_profile);
|
||||
edge_list.clear();
|
||||
edge_list.shrink_to_fit();
|
||||
|
||||
@ -574,8 +562,6 @@ void Prepare::WriteNodeMapping()
|
||||
void Prepare::BuildRTree(std::vector<EdgeBasedNode> &node_based_edge_list)
|
||||
{
|
||||
SimpleLogger().Write() << "building r-tree ...";
|
||||
StaticRTree<EdgeBasedNode>(node_based_edge_list,
|
||||
rtree_nodes_path.c_str(),
|
||||
rtree_leafs_path.c_str(),
|
||||
internal_to_external_node_map);
|
||||
StaticRTree<EdgeBasedNode>(node_based_edge_list, rtree_nodes_path.c_str(),
|
||||
rtree_leafs_path.c_str(), internal_to_external_node_map);
|
||||
}
|
||||
|
@ -1,483 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, 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 <osrm/Coordinate.h>
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#ifndef NDEBUG
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#endif
|
||||
#include "../Util/string_util.hpp"
|
||||
|
||||
#include <boost/assert.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
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Reset()
|
||||
{
|
||||
lat = std::numeric_limits<int>::min();
|
||||
lon = std::numeric_limits<int>::min();
|
||||
}
|
||||
bool FixedPointCoordinate::isSet() const
|
||||
{
|
||||
return (std::numeric_limits<int>::min() != lat) && (std::numeric_limits<int>::min() != lon);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(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());
|
||||
double RAD = 0.017453292519943295769236907684886;
|
||||
double lt1 = lat1 / COORDINATE_PRECISION;
|
||||
double ln1 = lon1 / COORDINATE_PRECISION;
|
||||
double lt2 = lat2 / COORDINATE_PRECISION;
|
||||
double ln2 = lon2 / COORDINATE_PRECISION;
|
||||
double dlat1 = lt1 * (RAD);
|
||||
|
||||
double dlong1 = ln1 * (RAD);
|
||||
double dlat2 = lt2 * (RAD);
|
||||
double dlong2 = ln2 * (RAD);
|
||||
|
||||
double dLong = dlong1 - dlong2;
|
||||
double dLat = dlat1 - dlat2;
|
||||
|
||||
double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2);
|
||||
double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv));
|
||||
// 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)
|
||||
const double earth = 6372797.560856;
|
||||
return earth * cHarv;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return ApproximateDistance(
|
||||
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return ApproximateEuclideanDistance(
|
||||
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ApproximateEuclideanDistance(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 RAD = 0.017453292519943295769236907684886f;
|
||||
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) * cos((float_lat1 + float_lat2) / 2.f);
|
||||
const float y_value = float_lat2 - float_lat1;
|
||||
const float earth_radius = 6372797.560856f;
|
||||
return sqrt(x_value * x_value + y_value * y_value) * earth_radius;
|
||||
}
|
||||
|
||||
float
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate,
|
||||
const FixedPointCoordinate &target_coordinate,
|
||||
const FixedPointCoordinate &point)
|
||||
{
|
||||
// initialize values
|
||||
const float x_value = static_cast<float>(lat2y(point.lat / COORDINATE_PRECISION));
|
||||
const float y_value = point.lon / COORDINATE_PRECISION;
|
||||
float a = static_cast<float>(lat2y(source_coordinate.lat / COORDINATE_PRECISION));
|
||||
float b = source_coordinate.lon / COORDINATE_PRECISION;
|
||||
float c = static_cast<float>(lat2y(target_coordinate.lat / COORDINATE_PRECISION));
|
||||
float d = target_coordinate.lon / COORDINATE_PRECISION;
|
||||
float p, q;
|
||||
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
const float slope = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x_value + (slope * y_value)) + (slope * slope * a - slope * b)) /
|
||||
(1.f + slope * slope);
|
||||
q = b + slope * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y_value;
|
||||
}
|
||||
|
||||
float ratio;
|
||||
bool inverse_ratio = false;
|
||||
|
||||
// straight line segment on equator
|
||||
if (std::abs(c) < std::numeric_limits<float>::epsilon() &&
|
||||
std::abs(a) < std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
ratio = (q - b) / (d - b);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (std::abs(c) < std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
// swap start/end
|
||||
std::swap(a, c);
|
||||
std::swap(b, d);
|
||||
inverse_ratio = true;
|
||||
}
|
||||
|
||||
float 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 = (p - nY * a) / c;
|
||||
}
|
||||
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (target_coordinate == point ? 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;
|
||||
}
|
||||
|
||||
// we need to do this, if we switched start/end coordinates
|
||||
if (inverse_ratio)
|
||||
{
|
||||
ratio = 1.0f - ratio;
|
||||
}
|
||||
|
||||
// compute the nearest location
|
||||
FixedPointCoordinate nearest_location;
|
||||
BOOST_ASSERT(!std::isnan(ratio));
|
||||
if (ratio <= 0.f)
|
||||
{ // point is "left" of edge
|
||||
nearest_location = source_coordinate;
|
||||
}
|
||||
else if (ratio >= 1.f)
|
||||
{ // point is "right" of edge
|
||||
nearest_location = target_coordinate;
|
||||
}
|
||||
else
|
||||
{ // point lies in between
|
||||
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||
}
|
||||
|
||||
BOOST_ASSERT(nearest_location.is_valid());
|
||||
return FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio)
|
||||
{
|
||||
BOOST_ASSERT(query_location.is_valid());
|
||||
|
||||
// initialize values
|
||||
const double x = lat2y(query_location.lat / COORDINATE_PRECISION);
|
||||
const double y = query_location.lon / COORDINATE_PRECISION;
|
||||
const double a = lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||
const double b = segment_source.lon / COORDINATE_PRECISION;
|
||||
const double c = 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 = (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<double>::epsilon())
|
||||
{
|
||||
ratio = 0.f;
|
||||
}
|
||||
else if (std::abs(ratio - 1.f) <= std::numeric_limits<double>::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>(y2lat(p) * COORDINATE_PRECISION);
|
||||
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||
}
|
||||
BOOST_ASSERT(nearest_location.is_valid());
|
||||
|
||||
const float approximate_distance =
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location);
|
||||
BOOST_ASSERT(0. <= approximate_distance);
|
||||
return approximate_distance;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
|
||||
{
|
||||
char buffer[12];
|
||||
buffer[11] = 0; // zero termination
|
||||
output = printInt<11, 6>(buffer, value);
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Output(std::ostream &out) const
|
||||
{
|
||||
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::GetBearing(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 = DegreeToRadian(lon_diff);
|
||||
const float lat1 = DegreeToRadian(first_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = DegreeToRadian(second_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float y = sin(lon_delta) * cos(lat2);
|
||||
const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta);
|
||||
float result = RadianToDegree(std::atan2(y, x));
|
||||
while (result < 0.f)
|
||||
{
|
||||
result += 360.f;
|
||||
}
|
||||
|
||||
while (result >= 360.f)
|
||||
{
|
||||
result -= 360.f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
|
||||
{
|
||||
const float lon_delta =
|
||||
DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION);
|
||||
const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION);
|
||||
const float y_value = std::sin(lon_delta) * std::cos(lat2);
|
||||
const float x_value =
|
||||
std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta);
|
||||
float result = RadianToDegree(std::atan2(y_value, x_value));
|
||||
|
||||
while (result < 0.f)
|
||||
{
|
||||
result += 360.f;
|
||||
}
|
||||
|
||||
while (result >= 360.f)
|
||||
{
|
||||
result -= 360.f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::DegreeToRadian(const float degree)
|
||||
{
|
||||
return degree * (static_cast<float>(M_PI) / 180.f);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::RadianToDegree(const float radian)
|
||||
{
|
||||
return radian * (180.f * static_cast<float>(M_1_PI));
|
||||
}
|
||||
|
||||
// This distance computation does integer arithmetic only and is a lot faster than
|
||||
// the other distance function which are numerically correct('ish).
|
||||
// It preserves some order among the elements that make it useful for certain purposes
|
||||
int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation(
|
||||
const FixedPointCoordinate &input_point,
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target)
|
||||
{
|
||||
// initialize values
|
||||
const float x = static_cast<float>(lat2y(input_point.lat / COORDINATE_PRECISION));
|
||||
const float y = input_point.lon / COORDINATE_PRECISION;
|
||||
const float a = static_cast<float>(lat2y(segment_source.lat / COORDINATE_PRECISION));
|
||||
const float b = segment_source.lon / COORDINATE_PRECISION;
|
||||
const float c = static_cast<float>(lat2y(segment_target.lat / COORDINATE_PRECISION));
|
||||
const float d = segment_target.lon / COORDINATE_PRECISION;
|
||||
|
||||
float p, q;
|
||||
if (a == c)
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float 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);
|
||||
}
|
||||
|
||||
const float nY = (d * p - c * q) / (a * d - b * c);
|
||||
float ratio = (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 == input_point) ? 1.f : 0.f;
|
||||
}
|
||||
|
||||
// compute target quasi-location
|
||||
int dx, dy;
|
||||
if (ratio < 0.f)
|
||||
{
|
||||
dx = input_point.lon - segment_source.lon;
|
||||
dy = input_point.lat - segment_source.lat;
|
||||
}
|
||||
else if (ratio > 1.f)
|
||||
{
|
||||
dx = input_point.lon - segment_target.lon;
|
||||
dy = input_point.lat - segment_target.lat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
dx = input_point.lon - static_cast<int>(q * COORDINATE_PRECISION);
|
||||
dy = input_point.lat - static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||
}
|
||||
|
||||
// return an approximation in the plane
|
||||
return static_cast<int>(sqrt(dx * dx + dy * dy));
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, 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 INPUT_READER_FACTORY_H
|
||||
#define INPUT_READER_FACTORY_H
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <bzlib.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
|
||||
struct BZ2Context
|
||||
{
|
||||
FILE *file;
|
||||
BZFILE *bz2;
|
||||
int error;
|
||||
int nUnused;
|
||||
char unused[BZ_MAX_UNUSED];
|
||||
};
|
||||
|
||||
int readFromBz2Stream(void *pointer, char *buffer, int len)
|
||||
{
|
||||
void *unusedTmpVoid = nullptr;
|
||||
char *unusedTmp = nullptr;
|
||||
BZ2Context *context = (BZ2Context *)pointer;
|
||||
int read = 0;
|
||||
while (0 == read &&
|
||||
!(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file)))
|
||||
{
|
||||
read = BZ2_bzRead(&context->error, context->bz2, buffer, len);
|
||||
if (BZ_OK == context->error)
|
||||
{
|
||||
return read;
|
||||
}
|
||||
else if (BZ_STREAM_END == context->error)
|
||||
{
|
||||
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
|
||||
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadGetUnused");
|
||||
unusedTmp = (char *)unusedTmpVoid;
|
||||
for (int i = 0; i < context->nUnused; i++)
|
||||
{
|
||||
context->unused[i] = unusedTmp[i];
|
||||
}
|
||||
BZ2_bzReadClose(&context->error, context->bz2);
|
||||
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadClose");
|
||||
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
|
||||
if (0 == context->nUnused && feof(context->file))
|
||||
{
|
||||
return read;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->bz2 = BZ2_bzReadOpen(
|
||||
&context->error, context->file, 0, 0, context->unused, context->nUnused);
|
||||
BOOST_ASSERT_MSG(nullptr != context->bz2, "Could not open file");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT_MSG(false, "Could not read bz2 file");
|
||||
}
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
int closeBz2Stream(void *pointer)
|
||||
{
|
||||
BZ2Context *context = (BZ2Context *)pointer;
|
||||
fclose(context->file);
|
||||
delete context;
|
||||
return 0;
|
||||
}
|
||||
|
||||
xmlTextReaderPtr inputReaderFactory(const char *name)
|
||||
{
|
||||
std::string inputName(name);
|
||||
|
||||
if (inputName.find(".osm.bz2") != std::string::npos)
|
||||
{
|
||||
BZ2Context *context = new BZ2Context();
|
||||
context->error = false;
|
||||
context->file = fopen(name, "r");
|
||||
int error;
|
||||
context->bz2 =
|
||||
BZ2_bzReadOpen(&error, context->file, 0, 0, context->unused, context->nUnused);
|
||||
if (context->bz2 == nullptr || context->file == nullptr)
|
||||
{
|
||||
delete context;
|
||||
return nullptr;
|
||||
}
|
||||
return xmlReaderForIO(readFromBz2Stream, closeBz2Stream, (void *)context, nullptr, nullptr, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return xmlNewTextReaderFilename(name);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // INPUT_READER_FACTORY_H
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -36,24 +36,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
template <typename NodeID, typename Key> class ArrayStorage
|
||||
{
|
||||
public:
|
||||
explicit ArrayStorage(size_t size) : positions(new Key[size])
|
||||
{
|
||||
memset(positions, 0, size * sizeof(Key));
|
||||
}
|
||||
explicit ArrayStorage(size_t size) : positions(size, 0) {}
|
||||
|
||||
~ArrayStorage() { delete[] positions; }
|
||||
~ArrayStorage() {}
|
||||
|
||||
Key &operator[](NodeID node) { return positions[node]; }
|
||||
|
||||
Key peek_index(const NodeID node) const { return positions[node]; }
|
||||
|
||||
void Clear() {}
|
||||
|
||||
private:
|
||||
Key *positions;
|
||||
std::vector<Key> positions;
|
||||
};
|
||||
|
||||
template <typename NodeID, typename Key> class MapStorage
|
||||
@ -65,6 +63,16 @@ template <typename NodeID, typename Key> class MapStorage
|
||||
|
||||
void Clear() { nodes.clear(); }
|
||||
|
||||
Key peek_index(const NodeID node) const
|
||||
{
|
||||
const auto iter = nodes.find(node);
|
||||
if (nodes.end() != iter)
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
return std::numeric_limits<Key>::max();
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<NodeID, Key> nodes;
|
||||
};
|
||||
@ -76,6 +84,16 @@ template <typename NodeID, typename Key> class UnorderedMapStorage
|
||||
|
||||
Key &operator[](const NodeID node) { return nodes[node]; }
|
||||
|
||||
Key peek_index(const NodeID node) const
|
||||
{
|
||||
const auto iter = nodes.find(node);
|
||||
if (std::end(nodes) != iter)
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
return std::numeric_limits<Key>::max();
|
||||
}
|
||||
|
||||
Key const &operator[](const NodeID node) const
|
||||
{
|
||||
auto iter = nodes.find(node);
|
||||
@ -132,13 +150,13 @@ class BinaryHeap
|
||||
|
||||
Data &GetData(NodeID node)
|
||||
{
|
||||
const Key index = node_index[node];
|
||||
const Key index = node_index.peek_index(node);
|
||||
return inserted_nodes[index].data;
|
||||
}
|
||||
|
||||
Data const &GetData(NodeID node) const
|
||||
{
|
||||
const Key index = node_index[node];
|
||||
const Key index = node_index.peek_index(node);
|
||||
return inserted_nodes[index].data;
|
||||
}
|
||||
|
||||
@ -148,17 +166,17 @@ class BinaryHeap
|
||||
return inserted_nodes[index].weight;
|
||||
}
|
||||
|
||||
bool WasRemoved(const NodeID node)
|
||||
bool WasRemoved(const NodeID node) const
|
||||
{
|
||||
BOOST_ASSERT(WasInserted(node));
|
||||
const Key index = node_index[node];
|
||||
const Key index = node_index.peek_index(node);
|
||||
return inserted_nodes[index].key == 0;
|
||||
}
|
||||
|
||||
bool WasInserted(const NodeID node)
|
||||
bool WasInserted(const NodeID node) const
|
||||
{
|
||||
const Key index = node_index[node];
|
||||
if (index >= static_cast<Key>(inserted_nodes.size()))
|
||||
const auto index = node_index.peek_index(node);
|
||||
if (index >= static_cast<decltype(index)>(inserted_nodes.size()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -200,7 +218,7 @@ class BinaryHeap
|
||||
void DecreaseKey(NodeID node, Weight weight)
|
||||
{
|
||||
BOOST_ASSERT(std::numeric_limits<NodeID>::max() != node);
|
||||
const Key &index = node_index[node];
|
||||
const Key &index = node_index.peek_index(node);
|
||||
Key &key = inserted_nodes[index].key;
|
||||
BOOST_ASSERT(key >= 0);
|
||||
|
||||
@ -235,12 +253,12 @@ class BinaryHeap
|
||||
{
|
||||
const Key droppingIndex = heap[key].index;
|
||||
const Weight weight = heap[key].weight;
|
||||
const Key heap_size = static_cast<Key>(heap.size());
|
||||
Key nextKey = key << 1;
|
||||
while (nextKey < static_cast<Key>(heap.size()))
|
||||
while (nextKey < heap_size)
|
||||
{
|
||||
const Key nextKeyOther = nextKey + 1;
|
||||
if ((nextKeyOther < static_cast<Key>(heap.size())) &&
|
||||
(heap[nextKey].weight > heap[nextKeyOther].weight))
|
||||
if ((nextKeyOther < heap_size) && (heap[nextKey].weight > heap[nextKeyOther].weight))
|
||||
{
|
||||
nextKey = nextKeyOther;
|
||||
}
|
||||
@ -279,7 +297,7 @@ class BinaryHeap
|
||||
void CheckHeap()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
for (Key i = 2; i < (Key)heap.size(); ++i)
|
||||
for (std::size_t i = 2; i < heap.size(); ++i)
|
||||
{
|
||||
BOOST_ASSERT(heap[i].weight >= heap[i >> 1].weight);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -40,9 +40,10 @@ template <typename Data> class ConcurrentQueue
|
||||
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_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();
|
||||
}
|
||||
@ -52,9 +53,10 @@ template <typename Data> class ConcurrentQueue
|
||||
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(); });
|
||||
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();
|
||||
|
87
data_structures/coordinate.cpp
Normal file
87
data_structures/coordinate.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "coordinate_calculation.hpp"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include "../util/simple_logger.hpp"
|
||||
#endif
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <bitset>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate()
|
||||
: lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
|
||||
{
|
||||
}
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (0 != (std::abs(lat) >> 30))
|
||||
{
|
||||
std::bitset<32> y_coordinate_vector(lat);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat
|
||||
<< ", bits: " << y_coordinate_vector;
|
||||
}
|
||||
if (0 != (std::abs(lon) >> 30))
|
||||
{
|
||||
std::bitset<32> x_coordinate_vector(lon);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon
|
||||
<< ", bits: " << x_coordinate_vector;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FixedPointCoordinate::is_valid() const
|
||||
{
|
||||
if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
|
||||
lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
|
||||
{
|
||||
return lat == other.lat && lon == other.lon;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::output(std::ostream &out) const
|
||||
{
|
||||
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::bearing(const FixedPointCoordinate &other) const
|
||||
{
|
||||
return coordinate_calculation::bearing(other, *this);
|
||||
}
|
268
data_structures/coordinate_calculation.cpp
Normal file
268
data_structures/coordinate_calculation.cpp
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "coordinate_calculation.hpp"
|
||||
|
||||
#include "../util/mercator.hpp"
|
||||
#include "../util/string_util.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr static const float RAD = 0.017453292519943295769236907684886f;
|
||||
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
|
||||
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
||||
constexpr static const float earth_radius = 6372797.560856f;
|
||||
}
|
||||
|
||||
double coordinate_calculation::great_circle_distance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
const double lt1 = lat1 / COORDINATE_PRECISION;
|
||||
const double ln1 = lon1 / COORDINATE_PRECISION;
|
||||
const double lt2 = lat2 / COORDINATE_PRECISION;
|
||||
const double ln2 = lon2 / COORDINATE_PRECISION;
|
||||
const double dlat1 = lt1 * (RAD);
|
||||
|
||||
const double dlong1 = ln1 * (RAD);
|
||||
const double dlat2 = lt2 * (RAD);
|
||||
const double dlong2 = ln2 * (RAD);
|
||||
|
||||
const double dLong = dlong1 - dlong2;
|
||||
const double dLat = dlat1 - dlat2;
|
||||
|
||||
const double aHarv = std::pow(std::sin(dLat / 2.0), 2.0) +
|
||||
std::cos(dlat1) * std::cos(dlat2) * std::pow(std::sin(dLong / 2.), 2);
|
||||
const double cHarv = 2. * std::atan2(std::sqrt(aHarv), std::sqrt(1.0 - aHarv));
|
||||
return earth_radius * cHarv;
|
||||
}
|
||||
|
||||
double coordinate_calculation::great_circle_distance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return great_circle_distance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat,
|
||||
coordinate_2.lon);
|
||||
}
|
||||
|
||||
float coordinate_calculation::euclidean_distance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return euclidean_distance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat,
|
||||
coordinate_2.lon);
|
||||
}
|
||||
|
||||
float coordinate_calculation::euclidean_distance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
|
||||
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
||||
|
||||
const float x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.f);
|
||||
const float y_value = float_lat2 - float_lat1;
|
||||
return std::hypot(x_value, y_value) * earth_radius;
|
||||
}
|
||||
|
||||
float coordinate_calculation::perpendicular_distance(const FixedPointCoordinate &source_coordinate,
|
||||
const FixedPointCoordinate &target_coordinate,
|
||||
const FixedPointCoordinate &query_location)
|
||||
{
|
||||
float ratio;
|
||||
FixedPointCoordinate nearest_location;
|
||||
|
||||
return perpendicular_distance(source_coordinate, target_coordinate, query_location,
|
||||
nearest_location, ratio);
|
||||
}
|
||||
|
||||
float coordinate_calculation::perpendicular_distance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio)
|
||||
{
|
||||
return perpendicular_distance_from_projected_coordinate(
|
||||
segment_source, segment_target, query_location,
|
||||
{mercator::lat2y(query_location.lat / COORDINATE_PRECISION),
|
||||
query_location.lon / COORDINATE_PRECISION},
|
||||
nearest_location, ratio);
|
||||
}
|
||||
|
||||
float coordinate_calculation::perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &source_coordinate,
|
||||
const FixedPointCoordinate &target_coordinate,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate)
|
||||
{
|
||||
float ratio;
|
||||
FixedPointCoordinate nearest_location;
|
||||
|
||||
return perpendicular_distance_from_projected_coordinate(source_coordinate, target_coordinate,
|
||||
query_location, projected_coordinate,
|
||||
nearest_location, ratio);
|
||||
}
|
||||
|
||||
float coordinate_calculation::perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio)
|
||||
{
|
||||
BOOST_ASSERT(query_location.is_valid());
|
||||
|
||||
// initialize values
|
||||
const double x = projected_coordinate.first;
|
||||
const double y = projected_coordinate.second;
|
||||
const double a = mercator::lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||
const double b = segment_source.lon / COORDINATE_PRECISION;
|
||||
const double c = mercator::lat2y(segment_target.lat / COORDINATE_PRECISION);
|
||||
const double d = segment_target.lon / COORDINATE_PRECISION;
|
||||
double p, q /*,mX*/, nY;
|
||||
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
const double m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d * p - c * q) / (a * d - b * c);
|
||||
|
||||
// discretize the result to coordinate precision. it's a hack!
|
||||
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||
{
|
||||
nY = 0.f;
|
||||
}
|
||||
|
||||
// compute ratio
|
||||
ratio =
|
||||
static_cast<float>((p - nY * a) / c); // These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (segment_target == query_location ? 1.f : 0.f);
|
||||
}
|
||||
else if (std::abs(ratio) <= std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
ratio = 0.f;
|
||||
}
|
||||
else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
ratio = 1.f;
|
||||
}
|
||||
|
||||
// compute nearest location
|
||||
BOOST_ASSERT(!std::isnan(ratio));
|
||||
if (ratio <= 0.f)
|
||||
{
|
||||
nearest_location = segment_source;
|
||||
}
|
||||
else if (ratio >= 1.f)
|
||||
{
|
||||
nearest_location = segment_target;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
nearest_location.lat = static_cast<int>(mercator::y2lat(p) * COORDINATE_PRECISION);
|
||||
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||
}
|
||||
BOOST_ASSERT(nearest_location.is_valid());
|
||||
|
||||
const float approximate_distance =
|
||||
coordinate_calculation::euclidean_distance(query_location, nearest_location);
|
||||
BOOST_ASSERT(0.f <= approximate_distance);
|
||||
return approximate_distance;
|
||||
}
|
||||
|
||||
void coordinate_calculation::lat_or_lon_to_string(const int value, std::string &output)
|
||||
{
|
||||
char buffer[12];
|
||||
buffer[11] = 0; // zero termination
|
||||
output = printInt<11, 6>(buffer, value);
|
||||
}
|
||||
|
||||
float coordinate_calculation::deg_to_rad(const float degree)
|
||||
{
|
||||
return degree * (static_cast<float>(M_PI) / 180.f);
|
||||
}
|
||||
|
||||
float coordinate_calculation::rad_to_deg(const float radian)
|
||||
{
|
||||
return radian * (180.f * static_cast<float>(M_1_PI));
|
||||
}
|
||||
|
||||
float coordinate_calculation::bearing(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate)
|
||||
{
|
||||
const float lon_diff =
|
||||
second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION;
|
||||
const float lon_delta = deg_to_rad(lon_diff);
|
||||
const float lat1 = deg_to_rad(first_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = deg_to_rad(second_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float y = std::sin(lon_delta) * std::cos(lat2);
|
||||
const float x =
|
||||
std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta);
|
||||
float result = rad_to_deg(std::atan2(y, x));
|
||||
while (result < 0.f)
|
||||
{
|
||||
result += 360.f;
|
||||
}
|
||||
|
||||
while (result >= 360.f)
|
||||
{
|
||||
result -= 360.f;
|
||||
}
|
||||
return result;
|
||||
}
|
82
data_structures/coordinate_calculation.hpp
Normal file
82
data_structures/coordinate_calculation.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef COORDINATE_CALCULATION
|
||||
#define COORDINATE_CALCULATION
|
||||
|
||||
struct FixedPointCoordinate;
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
struct coordinate_calculation
|
||||
{
|
||||
static double
|
||||
great_circle_distance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
|
||||
static double great_circle_distance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
static float euclidean_distance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
static float euclidean_distance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
|
||||
static void lat_or_lon_to_string(const int value, std::string &output);
|
||||
|
||||
static float perpendicular_distance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location);
|
||||
|
||||
static float perpendicular_distance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio);
|
||||
|
||||
static float perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate);
|
||||
|
||||
static float perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio);
|
||||
|
||||
static float deg_to_rad(const float degree);
|
||||
static float rad_to_deg(const float radian);
|
||||
|
||||
static float bearing(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
};
|
||||
|
||||
#endif // COORDINATE_CALCULATION
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -25,19 +25,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DEALLOCATINGVECTOR_H_
|
||||
#define DEALLOCATINGVECTOR_H_
|
||||
#ifndef DEALLOCATING_VECTOR_HPP
|
||||
#define DEALLOCATING_VECTOR_HPP
|
||||
|
||||
#include "../Util/integer_range.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
template <typename ElementT> struct DeallocatingVectorIteratorState
|
||||
{
|
||||
DeallocatingVectorIteratorState() : index(-1), bucket_list(nullptr) {}
|
||||
DeallocatingVectorIteratorState()
|
||||
: index(std::numeric_limits<std::size_t>::max()), bucket_list(nullptr)
|
||||
{
|
||||
}
|
||||
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r)
|
||||
: index(r.index), bucket_list(r.bucket_list)
|
||||
{
|
||||
@ -50,7 +54,7 @@ template <typename ElementT> struct DeallocatingVectorIteratorState
|
||||
std::size_t index;
|
||||
std::vector<ElementT *> *bucket_list;
|
||||
|
||||
inline DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &other)
|
||||
DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &other)
|
||||
{
|
||||
index = other.index;
|
||||
bucket_list = other.bucket_list;
|
||||
@ -171,17 +175,20 @@ class DeallocatingVector
|
||||
// this forward-only iterator deallocates all buckets that have been visited
|
||||
using deallocation_iterator = DeallocatingVectorRemoveIterator<ElementT, ELEMENTS_PER_BLOCK>;
|
||||
|
||||
DeallocatingVector() : current_size(0) { bucket_list.emplace_back(new ElementT[ELEMENTS_PER_BLOCK]); }
|
||||
DeallocatingVector() : current_size(0)
|
||||
{
|
||||
bucket_list.emplace_back(new ElementT[ELEMENTS_PER_BLOCK]);
|
||||
}
|
||||
|
||||
~DeallocatingVector() { clear(); }
|
||||
|
||||
inline void swap(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &other)
|
||||
void swap(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &other)
|
||||
{
|
||||
std::swap(current_size, other.current_size);
|
||||
bucket_list.swap(other.bucket_list);
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
void clear()
|
||||
{
|
||||
// Delete[]'ing ptr's to all Buckets
|
||||
for (auto bucket : bucket_list)
|
||||
@ -192,11 +199,12 @@ class DeallocatingVector
|
||||
bucket = nullptr;
|
||||
}
|
||||
}
|
||||
bucket_list.clear(); bucket_list.shrink_to_fit();
|
||||
bucket_list.clear();
|
||||
bucket_list.shrink_to_fit();
|
||||
current_size = 0;
|
||||
}
|
||||
|
||||
inline void push_back(const ElementT &element)
|
||||
void push_back(const ElementT &element)
|
||||
{
|
||||
const std::size_t current_capacity = capacity();
|
||||
if (current_size == current_capacity)
|
||||
@ -209,7 +217,7 @@ class DeallocatingVector
|
||||
++current_size;
|
||||
}
|
||||
|
||||
template <typename... Ts> inline void emplace_back(Ts &&... element)
|
||||
template <typename... Ts> void emplace_back(Ts &&... element)
|
||||
{
|
||||
const std::size_t current_capacity = capacity();
|
||||
if (current_size == current_capacity)
|
||||
@ -222,9 +230,9 @@ class DeallocatingVector
|
||||
++current_size;
|
||||
}
|
||||
|
||||
inline void reserve(const std::size_t) const { /* don't do anything */ }
|
||||
void reserve(const std::size_t) const { /* don't do anything */}
|
||||
|
||||
inline void resize(const std::size_t new_size)
|
||||
void resize(const std::size_t new_size)
|
||||
{
|
||||
if (new_size >= current_size)
|
||||
{
|
||||
@ -234,9 +242,10 @@ class DeallocatingVector
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // down-size
|
||||
{ // down-size
|
||||
const std::size_t number_of_necessary_buckets = 1 + (new_size / ELEMENTS_PER_BLOCK);
|
||||
for (const auto bucket_index : osrm::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])
|
||||
{
|
||||
@ -248,58 +257,50 @@ class DeallocatingVector
|
||||
current_size = new_size;
|
||||
}
|
||||
|
||||
inline std::size_t size() const { return current_size; }
|
||||
std::size_t size() const { return current_size; }
|
||||
|
||||
inline std::size_t capacity() const { return bucket_list.size() * ELEMENTS_PER_BLOCK; }
|
||||
std::size_t capacity() const { return bucket_list.size() * ELEMENTS_PER_BLOCK; }
|
||||
|
||||
inline iterator begin() { return iterator(static_cast<std::size_t>(0), &bucket_list); }
|
||||
iterator begin() { return iterator(static_cast<std::size_t>(0), &bucket_list); }
|
||||
|
||||
inline iterator end() { return iterator(size(), &bucket_list); }
|
||||
iterator end() { return iterator(size(), &bucket_list); }
|
||||
|
||||
inline deallocation_iterator dbegin()
|
||||
deallocation_iterator dbegin()
|
||||
{
|
||||
return deallocation_iterator(static_cast<std::size_t>(0), &bucket_list);
|
||||
}
|
||||
|
||||
inline deallocation_iterator dend() { return deallocation_iterator(size(), &bucket_list); }
|
||||
deallocation_iterator dend() { return deallocation_iterator(size(), &bucket_list); }
|
||||
|
||||
inline const_iterator begin() const
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(static_cast<std::size_t>(0), &bucket_list);
|
||||
}
|
||||
|
||||
inline const_iterator end() const { return const_iterator(size(), &bucket_list); }
|
||||
const_iterator end() const { return const_iterator(size(), &bucket_list); }
|
||||
|
||||
inline ElementT &operator[](const std::size_t index)
|
||||
ElementT &operator[](const std::size_t index)
|
||||
{
|
||||
const std::size_t _bucket = index / ELEMENTS_PER_BLOCK;
|
||||
const std::size_t _index = index % ELEMENTS_PER_BLOCK;
|
||||
return (bucket_list[_bucket][_index]);
|
||||
}
|
||||
|
||||
const inline ElementT &operator[](const std::size_t index) const
|
||||
ElementT &operator[](const std::size_t index) const
|
||||
{
|
||||
const std::size_t _bucket = index / ELEMENTS_PER_BLOCK;
|
||||
const std::size_t _index = index % ELEMENTS_PER_BLOCK;
|
||||
return (bucket_list[_bucket][_index]);
|
||||
}
|
||||
|
||||
inline ElementT &back()
|
||||
ElementT &back() const
|
||||
{
|
||||
const std::size_t _bucket = current_size / ELEMENTS_PER_BLOCK;
|
||||
const std::size_t _index = current_size % ELEMENTS_PER_BLOCK;
|
||||
return (bucket_list[_bucket][_index]);
|
||||
}
|
||||
|
||||
const inline ElementT &back() const
|
||||
{
|
||||
const std::size_t _bucket = current_size / ELEMENTS_PER_BLOCK;
|
||||
const std::size_t _index = current_size % ELEMENTS_PER_BLOCK;
|
||||
return (bucket_list[_bucket][_index]);
|
||||
}
|
||||
|
||||
template<class InputIterator>
|
||||
const inline void append(InputIterator first, const InputIterator last)
|
||||
template <class InputIterator> void append(InputIterator first, const InputIterator last)
|
||||
{
|
||||
InputIterator position = first;
|
||||
while (position != last)
|
||||
@ -310,4 +311,4 @@ class DeallocatingVector
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* DEALLOCATINGVECTOR_H_ */
|
||||
#endif /* DEALLOCATING_VECTOR_HPP */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -29,16 +29,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define DYNAMICGRAPH_HPP
|
||||
|
||||
#include "deallocating_vector.hpp"
|
||||
#include "../Util/integer_range.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
template <typename EdgeDataT> class DynamicGraph
|
||||
{
|
||||
@ -55,26 +57,29 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
NodeIterator target;
|
||||
EdgeDataT data;
|
||||
|
||||
InputEdge() : source(std::numeric_limits<NodeIterator>::max()), target(std::numeric_limits<NodeIterator>::max()) { }
|
||||
|
||||
template<typename... Ts>
|
||||
InputEdge(NodeIterator source, NodeIterator target, Ts &&...data) : source(source), target(target), data(std::forward<Ts>(data)...) { }
|
||||
|
||||
bool operator<(const InputEdge &right) const
|
||||
InputEdge()
|
||||
: source(std::numeric_limits<NodeIterator>::max()),
|
||||
target(std::numeric_limits<NodeIterator>::max())
|
||||
{
|
||||
if (source != right.source)
|
||||
{
|
||||
return source < right.source;
|
||||
}
|
||||
return target < right.target;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
InputEdge(NodeIterator source, NodeIterator target, Ts &&... data)
|
||||
: source(source), target(target), data(std::forward<Ts>(data)...)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator<(const InputEdge &rhs) const
|
||||
{
|
||||
return std::tie(source, target) < std::tie(rhs.source, rhs.target);
|
||||
}
|
||||
};
|
||||
|
||||
// Constructs an empty graph with a given number of nodes.
|
||||
explicit DynamicGraph(NodeIterator nodes) : number_of_nodes(nodes), number_of_edges(0)
|
||||
{
|
||||
node_list.reserve(number_of_nodes);
|
||||
node_list.resize(number_of_nodes);
|
||||
node_array.reserve(number_of_nodes);
|
||||
node_array.resize(number_of_nodes);
|
||||
|
||||
edge_list.reserve(number_of_nodes * 1.1);
|
||||
edge_list.resize(number_of_nodes);
|
||||
@ -83,30 +88,30 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
template <class ContainerT> DynamicGraph(const NodeIterator nodes, const ContainerT &graph)
|
||||
{
|
||||
number_of_nodes = nodes;
|
||||
number_of_edges = (EdgeIterator)graph.size();
|
||||
node_list.reserve(number_of_nodes + 1);
|
||||
node_list.resize(number_of_nodes + 1);
|
||||
number_of_edges = static_cast<EdgeIterator>(graph.size());
|
||||
// node_array.reserve(number_of_nodes + 1);
|
||||
node_array.resize(number_of_nodes + 1);
|
||||
EdgeIterator edge = 0;
|
||||
EdgeIterator position = 0;
|
||||
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||
{
|
||||
EdgeIterator lastEdge = edge;
|
||||
EdgeIterator last_edge = edge;
|
||||
while (edge < number_of_edges && graph[edge].source == node)
|
||||
{
|
||||
++edge;
|
||||
}
|
||||
node_list[node].firstEdge = position;
|
||||
node_list[node].edges = edge - lastEdge;
|
||||
position += node_list[node].edges;
|
||||
node_array[node].first_edge = position;
|
||||
node_array[node].edges = edge - last_edge;
|
||||
position += node_array[node].edges;
|
||||
}
|
||||
node_list.back().firstEdge = position;
|
||||
node_array.back().first_edge = position;
|
||||
edge_list.reserve(static_cast<std::size_t>(edge_list.size() * 1.1));
|
||||
edge_list.resize(position);
|
||||
edge = 0;
|
||||
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||
{
|
||||
for (const auto i : osrm::irange(node_list[node].firstEdge,
|
||||
node_list[node].firstEdge + node_list[node].edges))
|
||||
for (const auto i : osrm::irange(node_array[node].first_edge,
|
||||
node_array[node].first_edge + node_array[node].edges))
|
||||
{
|
||||
edge_list[i].target = graph[edge].target;
|
||||
edge_list[i].data = graph[edge].data;
|
||||
@ -121,7 +126,7 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
|
||||
unsigned GetNumberOfEdges() const { return number_of_edges; }
|
||||
|
||||
unsigned GetOutDegree(const NodeIterator n) const { return node_list[n].edges; }
|
||||
unsigned GetOutDegree(const NodeIterator n) const { return node_array[n].edges; }
|
||||
|
||||
unsigned GetDirectedOutDegree(const NodeIterator n) const
|
||||
{
|
||||
@ -146,12 +151,12 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
|
||||
EdgeIterator BeginEdges(const NodeIterator n) const
|
||||
{
|
||||
return EdgeIterator(node_list[n].firstEdge);
|
||||
return EdgeIterator(node_array[n].first_edge);
|
||||
}
|
||||
|
||||
EdgeIterator EndEdges(const NodeIterator n) const
|
||||
{
|
||||
return EdgeIterator(node_list[n].firstEdge + node_list[n].edges);
|
||||
return EdgeIterator(node_array[n].first_edge + node_array[n].edges);
|
||||
}
|
||||
|
||||
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
|
||||
@ -161,7 +166,7 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
|
||||
NodeIterator InsertNode()
|
||||
{
|
||||
node_list.emplace_back(node_list.back());
|
||||
node_array.emplace_back(node_array.back());
|
||||
number_of_nodes += 1;
|
||||
|
||||
return number_of_nodes;
|
||||
@ -170,14 +175,14 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
// adds an edge. Invalidates edge iterators for the source node
|
||||
EdgeIterator InsertEdge(const NodeIterator from, const NodeIterator to, const EdgeDataT &data)
|
||||
{
|
||||
Node &node = node_list[from];
|
||||
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
|
||||
Node &node = node_array[from];
|
||||
EdgeIterator newFirstEdge = node.edges + node.first_edge;
|
||||
if (newFirstEdge >= edge_list.size() || !isDummy(newFirstEdge))
|
||||
{
|
||||
if (node.firstEdge != 0 && isDummy(node.firstEdge - 1))
|
||||
if (node.first_edge != 0 && isDummy(node.first_edge - 1))
|
||||
{
|
||||
node.firstEdge--;
|
||||
edge_list[node.firstEdge] = edge_list[node.firstEdge + node.edges];
|
||||
node.first_edge--;
|
||||
edge_list[node.first_edge] = edge_list[node.first_edge + node.edges];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -192,32 +197,32 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
edge_list.resize(edge_list.size() + newSize);
|
||||
for (const auto i : osrm::irange(0u, node.edges))
|
||||
{
|
||||
edge_list[newFirstEdge + i] = edge_list[node.firstEdge + i];
|
||||
makeDummy(node.firstEdge + i);
|
||||
edge_list[newFirstEdge + i] = edge_list[node.first_edge + i];
|
||||
makeDummy(node.first_edge + i);
|
||||
}
|
||||
for (const auto i : osrm::irange(node.edges + 1, newSize))
|
||||
{
|
||||
makeDummy(newFirstEdge + i);
|
||||
}
|
||||
node.firstEdge = newFirstEdge;
|
||||
node.first_edge = newFirstEdge;
|
||||
}
|
||||
}
|
||||
Edge &edge = edge_list[node.firstEdge + node.edges];
|
||||
Edge &edge = edge_list[node.first_edge + node.edges];
|
||||
edge.target = to;
|
||||
edge.data = data;
|
||||
++number_of_edges;
|
||||
++node.edges;
|
||||
return EdgeIterator(node.firstEdge + node.edges);
|
||||
return EdgeIterator(node.first_edge + node.edges);
|
||||
}
|
||||
|
||||
// removes an edge. Invalidates edge iterators for the source node
|
||||
void DeleteEdge(const NodeIterator source, const EdgeIterator e)
|
||||
{
|
||||
Node &node = node_list[source];
|
||||
Node &node = node_array[source];
|
||||
--number_of_edges;
|
||||
--node.edges;
|
||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != node.edges);
|
||||
const unsigned last = node.firstEdge + node.edges;
|
||||
const unsigned last = node.first_edge + node.edges;
|
||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != last);
|
||||
// swap with last edge
|
||||
edge_list[e] = edge_list[last];
|
||||
@ -242,7 +247,7 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
}
|
||||
|
||||
number_of_edges -= deleted;
|
||||
node_list[source].edges -= deleted;
|
||||
node_array[source].edges -= deleted;
|
||||
|
||||
return deleted;
|
||||
}
|
||||
@ -257,7 +262,46 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return EndEdges(from);
|
||||
return SPECIAL_EDGEID;
|
||||
}
|
||||
|
||||
// searches for a specific edge
|
||||
EdgeIterator FindSmallestEdge(const NodeIterator from, const NodeIterator to) const
|
||||
{
|
||||
EdgeIterator smallest_edge = SPECIAL_EDGEID;
|
||||
EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT;
|
||||
for (auto edge : GetAdjacentEdgeRange(from))
|
||||
{
|
||||
const NodeID target = GetTarget(edge);
|
||||
const EdgeWeight weight = GetEdgeData(edge).distance;
|
||||
if (target == to && weight < smallest_weight)
|
||||
{
|
||||
smallest_edge = edge;
|
||||
smallest_weight = weight;
|
||||
}
|
||||
}
|
||||
return smallest_edge;
|
||||
}
|
||||
|
||||
EdgeIterator FindEdgeInEitherDirection(const NodeIterator from, const NodeIterator to) const
|
||||
{
|
||||
EdgeIterator tmp = FindEdge(from, to);
|
||||
return (SPECIAL_NODEID != tmp ? tmp : FindEdge(to, from));
|
||||
}
|
||||
|
||||
EdgeIterator
|
||||
FindEdgeIndicateIfReverse(const NodeIterator from, const NodeIterator to, bool &result) const
|
||||
{
|
||||
EdgeIterator current_iterator = FindEdge(from, to);
|
||||
if (SPECIAL_NODEID == current_iterator)
|
||||
{
|
||||
current_iterator = FindEdge(to, from);
|
||||
if (SPECIAL_NODEID != current_iterator)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return current_iterator;
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -274,7 +318,7 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
struct Node
|
||||
{
|
||||
// index of the first edge
|
||||
EdgeIterator firstEdge;
|
||||
EdgeIterator first_edge;
|
||||
// amount of edges
|
||||
unsigned edges;
|
||||
};
|
||||
@ -288,7 +332,7 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
NodeIterator number_of_nodes;
|
||||
std::atomic_uint number_of_edges;
|
||||
|
||||
std::vector<Node> node_list;
|
||||
std::vector<Node> node_array;
|
||||
DeallocatingVector<Edge> edge_list;
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -31,94 +31,74 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../data_structures/travel_mode.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct EdgeBasedNode
|
||||
{
|
||||
EdgeBasedNode() :
|
||||
forward_edge_based_node_id(SPECIAL_NODEID),
|
||||
reverse_edge_based_node_id(SPECIAL_NODEID),
|
||||
u(SPECIAL_NODEID),
|
||||
v(SPECIAL_NODEID),
|
||||
name_id(0),
|
||||
forward_weight(INVALID_EDGE_WEIGHT >> 1),
|
||||
reverse_weight(INVALID_EDGE_WEIGHT >> 1),
|
||||
forward_offset(0),
|
||||
reverse_offset(0),
|
||||
packed_geometry_id(SPECIAL_EDGEID),
|
||||
component_id(-1),
|
||||
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
|
||||
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||
{ }
|
||||
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)
|
||||
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)
|
||||
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;
|
||||
// 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 IsCompressed() const { return packed_geometry_id != SPECIAL_EDGEID; }
|
||||
|
||||
bool is_in_tiny_cc() const
|
||||
{
|
||||
return 0 != component_id;
|
||||
}
|
||||
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
|
||||
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
|
||||
@ -126,4 +106,4 @@ struct EdgeBasedNode
|
||||
TravelMode backward_travel_mode : 4;
|
||||
};
|
||||
|
||||
#endif //EDGE_BASED_NODE_HPP
|
||||
#endif // EDGE_BASED_NODE_HPP
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -26,6 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "external_memory_node.hpp"
|
||||
#include "query_node.hpp"
|
||||
|
||||
#include <limits>
|
||||
|
||||
@ -44,11 +45,8 @@ ExternalMemoryNode ExternalMemoryNode::min_value()
|
||||
|
||||
ExternalMemoryNode ExternalMemoryNode::max_value()
|
||||
{
|
||||
return ExternalMemoryNode(std::numeric_limits<int>::max(),
|
||||
std::numeric_limits<int>::max(),
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
false,
|
||||
false);
|
||||
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,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "query_node.hpp"
|
||||
|
||||
#include <string>
|
||||
#include "../typedefs.h"
|
||||
|
||||
struct ExternalMemoryNode : QueryNode
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
158
data_structures/hidden_markov_model.hpp
Normal file
158
data_structures/hidden_markov_model.hpp
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef HIDDEN_MARKOV_MODEL
|
||||
#define HIDDEN_MARKOV_MODEL
|
||||
|
||||
#include "../util/integer_range.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace matching
|
||||
{
|
||||
static const double log_2_pi = std::log(2. * M_PI);
|
||||
static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits<double>::infinity();
|
||||
static const double MINIMAL_LOG_PROB = std::numeric_limits<double>::lowest();
|
||||
static const std::size_t INVALID_STATE = std::numeric_limits<std::size_t>::max();
|
||||
} // namespace matching
|
||||
} // namespace osrm
|
||||
|
||||
// closures to precompute log -> only simple floating point operations
|
||||
struct EmissionLogProbability
|
||||
{
|
||||
double sigma_z;
|
||||
double log_sigma_z;
|
||||
|
||||
EmissionLogProbability(const double sigma_z) : sigma_z(sigma_z), log_sigma_z(std::log(sigma_z))
|
||||
{
|
||||
}
|
||||
|
||||
double operator()(const double distance) const
|
||||
{
|
||||
return -0.5 * (osrm::matching::log_2_pi + (distance / sigma_z) * (distance / sigma_z)) -
|
||||
log_sigma_z;
|
||||
}
|
||||
};
|
||||
|
||||
struct TransitionLogProbability
|
||||
{
|
||||
double beta;
|
||||
double log_beta;
|
||||
TransitionLogProbability(const double beta) : beta(beta), log_beta(std::log(beta)) {}
|
||||
|
||||
double operator()(const double d_t) const { return -log_beta - d_t / beta; }
|
||||
};
|
||||
|
||||
template <class CandidateLists> struct HiddenMarkovModel
|
||||
{
|
||||
std::vector<std::vector<double>> viterbi;
|
||||
std::vector<std::vector<std::pair<unsigned, unsigned>>> parents;
|
||||
std::vector<std::vector<float>> path_lengths;
|
||||
std::vector<std::vector<bool>> pruned;
|
||||
std::vector<std::vector<bool>> suspicious;
|
||||
std::vector<bool> breakage;
|
||||
|
||||
const CandidateLists &candidates_list;
|
||||
const EmissionLogProbability &emission_log_probability;
|
||||
|
||||
HiddenMarkovModel(const CandidateLists &candidates_list,
|
||||
const EmissionLogProbability &emission_log_probability)
|
||||
: breakage(candidates_list.size()), candidates_list(candidates_list),
|
||||
emission_log_probability(emission_log_probability)
|
||||
{
|
||||
for (const auto &l : candidates_list)
|
||||
{
|
||||
viterbi.emplace_back(l.size());
|
||||
parents.emplace_back(l.size());
|
||||
path_lengths.emplace_back(l.size());
|
||||
suspicious.emplace_back(l.size());
|
||||
pruned.emplace_back(l.size());
|
||||
}
|
||||
|
||||
clear(0);
|
||||
}
|
||||
|
||||
void clear(std::size_t initial_timestamp)
|
||||
{
|
||||
BOOST_ASSERT(viterbi.size() == parents.size() && parents.size() == path_lengths.size() &&
|
||||
path_lengths.size() == pruned.size() && pruned.size() == breakage.size());
|
||||
|
||||
for (const auto t : osrm::irange(initial_timestamp, viterbi.size()))
|
||||
{
|
||||
std::fill(viterbi[t].begin(), viterbi[t].end(), osrm::matching::IMPOSSIBLE_LOG_PROB);
|
||||
std::fill(parents[t].begin(), parents[t].end(), std::make_pair(0u, 0u));
|
||||
std::fill(path_lengths[t].begin(), path_lengths[t].end(), 0);
|
||||
std::fill(suspicious[t].begin(), suspicious[t].end(), true);
|
||||
std::fill(pruned[t].begin(), pruned[t].end(), true);
|
||||
}
|
||||
std::fill(breakage.begin() + initial_timestamp, breakage.end(), true);
|
||||
}
|
||||
|
||||
std::size_t initialize(std::size_t initial_timestamp)
|
||||
{
|
||||
BOOST_ASSERT(initial_timestamp < candidates_list.size());
|
||||
|
||||
do
|
||||
{
|
||||
for (const auto s : osrm::irange<std::size_t>(0u, viterbi[initial_timestamp].size()))
|
||||
{
|
||||
viterbi[initial_timestamp][s] =
|
||||
emission_log_probability(candidates_list[initial_timestamp][s].second);
|
||||
parents[initial_timestamp][s] = std::make_pair(initial_timestamp, s);
|
||||
pruned[initial_timestamp][s] =
|
||||
viterbi[initial_timestamp][s] < osrm::matching::MINIMAL_LOG_PROB;
|
||||
suspicious[initial_timestamp][s] = false;
|
||||
|
||||
breakage[initial_timestamp] =
|
||||
breakage[initial_timestamp] && pruned[initial_timestamp][s];
|
||||
}
|
||||
|
||||
++initial_timestamp;
|
||||
} while (breakage[initial_timestamp - 1]);
|
||||
|
||||
if (initial_timestamp >= viterbi.size())
|
||||
{
|
||||
return osrm::matching::INVALID_STATE;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(initial_timestamp > 0);
|
||||
--initial_timestamp;
|
||||
|
||||
BOOST_ASSERT(breakage[initial_timestamp] == false);
|
||||
|
||||
return initial_timestamp;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // HIDDEN_MARKOV_MODEL
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "hilbert_value.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
uint64_t HilbertCode::operator()(const FixedPointCoordinate ¤t_coordinate) const
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -27,7 +27,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "import_edge.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include "travel_mode.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
|
||||
{
|
||||
@ -57,8 +58,8 @@ NodeBasedEdge::NodeBasedEdge(NodeID source,
|
||||
bool access_restricted,
|
||||
TravelMode travel_mode,
|
||||
bool is_split)
|
||||
: source(source), target(target), name_id(name_id), weight(weight),
|
||||
forward(forward), backward(backward), roundabout(roundabout), in_tiny_cc(in_tiny_cc),
|
||||
: source(source), target(target), name_id(name_id), weight(weight), forward(forward),
|
||||
backward(backward), roundabout(roundabout), in_tiny_cc(in_tiny_cc),
|
||||
access_restricted(access_restricted), is_split(is_split), travel_mode(travel_mode)
|
||||
{
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -25,25 +25,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RAW_ROUTE_DATA_HPP
|
||||
#define RAW_ROUTE_DATA_HPP
|
||||
#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.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)
|
||||
: node(SPECIAL_NODEID), name_id(INVALID_EDGE_WEIGHT), segment_duration(INVALID_EDGE_WEIGHT),
|
||||
turn_instruction(TurnInstruction::NoTurn), travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||
{
|
||||
}
|
||||
|
||||
@ -52,8 +50,8 @@ struct PathData
|
||||
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)
|
||||
: node(node), name_id(name_id), segment_duration(segment_duration),
|
||||
turn_instruction(turn_instruction), travel_mode(travel_mode)
|
||||
{
|
||||
}
|
||||
NodeID node;
|
||||
@ -63,7 +61,7 @@ struct PathData
|
||||
TravelMode travel_mode : 4;
|
||||
};
|
||||
|
||||
struct RawRouteData
|
||||
struct InternalRouteResult
|
||||
{
|
||||
std::vector<std::vector<PathData>> unpacked_path_segments;
|
||||
std::vector<PathData> unpacked_alternative;
|
||||
@ -80,11 +78,10 @@ struct RawRouteData
|
||||
return (leg != unpacked_path_segments.size() - 1);
|
||||
}
|
||||
|
||||
RawRouteData() :
|
||||
shortest_path_length(INVALID_EDGE_WEIGHT),
|
||||
alternative_path_length(INVALID_EDGE_WEIGHT)
|
||||
InternalRouteResult()
|
||||
: shortest_path_length(INVALID_EDGE_WEIGHT), alternative_path_length(INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif // RAW_ROUTE_DATA_HPP
|
||||
#endif // RAW_ROUTE_DATA_H
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -86,7 +86,7 @@ template <typename KeyT, typename ValueT> class LRUCache
|
||||
result = e.value;
|
||||
|
||||
// move to front
|
||||
itemsInCache.splice(positionMap.find(key)->second, itemsInCache, itemsInCache.begin());
|
||||
itemsInCache.splice(itemsInCache.begin(), itemsInCache, positionMap.find(key)->second);
|
||||
positionMap.find(key)->second = itemsInCache.begin();
|
||||
return true;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "dynamic_graph.hpp"
|
||||
#include "import_edge.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
@ -40,9 +40,9 @@ struct NodeBasedEdgeData
|
||||
{
|
||||
NodeBasedEdgeData()
|
||||
: distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
|
||||
nameID(std::numeric_limits<unsigned>::max()),
|
||||
isAccessRestricted(false), shortcut(false), forward(false), backward(false),
|
||||
roundabout(false), ignore_in_grid(false), travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||
nameID(std::numeric_limits<unsigned>::max()), isAccessRestricted(false), shortcut(false),
|
||||
forward(false), backward(false), roundabout(false), ignore_in_grid(false),
|
||||
travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||
{
|
||||
}
|
||||
|
||||
@ -85,7 +85,8 @@ using SimpleNodeBasedDynamicGraph = DynamicGraph<SimpleEdgeData>;
|
||||
inline std::shared_ptr<NodeBasedDynamicGraph>
|
||||
NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge> &input_edge_list)
|
||||
{
|
||||
static_assert(sizeof(NodeBasedEdgeData) == 16, "changing node based edge data size changes memory consumption");
|
||||
static_assert(sizeof(NodeBasedEdgeData) == 16,
|
||||
"changing node based edge data size changes memory consumption");
|
||||
|
||||
DeallocatingVector<NodeBasedDynamicGraph::InputEdge> edges_list;
|
||||
NodeBasedDynamicGraph::InputEdge edge;
|
||||
@ -111,7 +112,7 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
|
||||
continue;
|
||||
}
|
||||
|
||||
edge.data.distance = (std::max)((int)import_edge.weight, 1);
|
||||
edge.data.distance = (std::max)(static_cast<int>(import_edge.weight), 1);
|
||||
BOOST_ASSERT(edge.data.distance > 0);
|
||||
edge.data.shortcut = false;
|
||||
edge.data.roundabout = import_edge.roundabout;
|
||||
@ -134,7 +135,7 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
|
||||
// remove duplicate edges
|
||||
tbb::parallel_sort(edges_list.begin(), edges_list.end());
|
||||
NodeID edge_count = 0;
|
||||
for (NodeID i = 0; i < edges_list.size(); )
|
||||
for (NodeID i = 0; i < edges_list.size();)
|
||||
{
|
||||
const NodeID source = edges_list[i].source;
|
||||
const NodeID target = edges_list[i].target;
|
||||
@ -150,10 +151,10 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
|
||||
forward_edge.data.forward = reverse_edge.data.backward = true;
|
||||
forward_edge.data.backward = reverse_edge.data.forward = false;
|
||||
forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
|
||||
forward_edge.data.distance = reverse_edge.data.distance =
|
||||
std::numeric_limits<int>::max();
|
||||
forward_edge.data.distance = reverse_edge.data.distance = std::numeric_limits<int>::max();
|
||||
// remove parallel edges
|
||||
while (i < edges_list.size() && edges_list[i].source == source && edges_list[i].target == target)
|
||||
while (i < edges_list.size() && edges_list[i].source == source &&
|
||||
edges_list[i].target == target)
|
||||
{
|
||||
if (edges_list[i].data.forward)
|
||||
{
|
||||
@ -170,7 +171,7 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
|
||||
// merge edges (s,t) and (t,s) into bidirectional edge
|
||||
if (forward_edge.data.distance == reverse_edge.data.distance)
|
||||
{
|
||||
if ((int)forward_edge.data.distance != std::numeric_limits<int>::max())
|
||||
if (static_cast<int>(forward_edge.data.distance) != std::numeric_limits<int>::max())
|
||||
{
|
||||
forward_edge.data.backward = true;
|
||||
edges_list[edge_count++] = forward_edge;
|
||||
@ -178,28 +179,31 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
|
||||
}
|
||||
else
|
||||
{ // insert seperate edges
|
||||
if (((int)forward_edge.data.distance) != std::numeric_limits<int>::max())
|
||||
if (static_cast<int>(forward_edge.data.distance) != std::numeric_limits<int>::max())
|
||||
{
|
||||
edges_list[edge_count++] = forward_edge;
|
||||
}
|
||||
if ((int)reverse_edge.data.distance != std::numeric_limits<int>::max())
|
||||
if (static_cast<int>(reverse_edge.data.distance) != std::numeric_limits<int>::max())
|
||||
{
|
||||
edges_list[edge_count++] = reverse_edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
edges_list.resize(edge_count);
|
||||
SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of " << edges_list.size();
|
||||
SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of "
|
||||
<< edges_list.size();
|
||||
|
||||
auto graph = std::make_shared<NodeBasedDynamicGraph>(static_cast<NodeBasedDynamicGraph::NodeIterator>(number_of_nodes), edges_list);
|
||||
auto graph = std::make_shared<NodeBasedDynamicGraph>(
|
||||
static_cast<NodeBasedDynamicGraph::NodeIterator>(number_of_nodes), edges_list);
|
||||
return graph;
|
||||
}
|
||||
|
||||
template<class SimpleEdgeT>
|
||||
template <class SimpleEdgeT>
|
||||
inline std::shared_ptr<SimpleNodeBasedDynamicGraph>
|
||||
SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector<SimpleEdgeT> &input_edge_list)
|
||||
{
|
||||
static_assert(sizeof(NodeBasedEdgeData) == 16, "changing node based edge data size changes memory consumption");
|
||||
static_assert(sizeof(NodeBasedEdgeData) == 16,
|
||||
"changing node based edge data size changes memory consumption");
|
||||
tbb::parallel_sort(input_edge_list.begin(), input_edge_list.end());
|
||||
|
||||
DeallocatingVector<SimpleNodeBasedDynamicGraph::InputEdge> edges_list;
|
||||
@ -218,10 +222,10 @@ SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector<SimpleEdge
|
||||
edges_list.push_back(edge);
|
||||
}
|
||||
|
||||
// remove duplicate edges
|
||||
// remove duplicate edges
|
||||
tbb::parallel_sort(edges_list.begin(), edges_list.end());
|
||||
NodeID edge_count = 0;
|
||||
for (NodeID i = 0; i < edges_list.size(); )
|
||||
for (NodeID i = 0; i < edges_list.size();)
|
||||
{
|
||||
const NodeID source = edges_list[i].source;
|
||||
const NodeID target = edges_list[i].target;
|
||||
@ -236,33 +240,37 @@ SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector<SimpleEdge
|
||||
forward_edge = reverse_edge = edges_list[i];
|
||||
forward_edge.data.capacity = reverse_edge.data.capacity = INVALID_EDGE_WEIGHT;
|
||||
// remove parallel edges
|
||||
while (i < edges_list.size() && edges_list[i].source == source && edges_list[i].target == target)
|
||||
while (i < edges_list.size() && edges_list[i].source == source &&
|
||||
edges_list[i].target == target)
|
||||
{
|
||||
forward_edge.data.capacity = std::min(edges_list[i].data.capacity, forward_edge.data.capacity);
|
||||
reverse_edge.data.capacity = std::min(edges_list[i].data.capacity, reverse_edge.data.capacity);
|
||||
forward_edge.data.capacity =
|
||||
std::min(edges_list[i].data.capacity, forward_edge.data.capacity);
|
||||
reverse_edge.data.capacity =
|
||||
std::min(edges_list[i].data.capacity, reverse_edge.data.capacity);
|
||||
++i;
|
||||
}
|
||||
// merge edges (s,t) and (t,s) into bidirectional edge
|
||||
if (forward_edge.data.capacity == reverse_edge.data.capacity)
|
||||
{
|
||||
if ((int)forward_edge.data.capacity != INVALID_EDGE_WEIGHT)
|
||||
if (static_cast<int>(forward_edge.data.capacity) != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
edges_list[edge_count++] = forward_edge;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // insert seperate edges
|
||||
if (((int)forward_edge.data.capacity) != INVALID_EDGE_WEIGHT)
|
||||
if (static_cast<int>(forward_edge.data.capacity) != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
edges_list[edge_count++] = forward_edge;
|
||||
}
|
||||
if ((int)reverse_edge.data.capacity != INVALID_EDGE_WEIGHT)
|
||||
if (static_cast<int>(reverse_edge.data.capacity) != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
edges_list[edge_count++] = reverse_edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of " << edges_list.size();
|
||||
SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of "
|
||||
<< edges_list.size();
|
||||
|
||||
auto graph = std::make_shared<SimpleNodeBasedDynamicGraph>(number_of_nodes, edges_list);
|
||||
return graph;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -48,9 +48,8 @@ struct OriginalEdgeData
|
||||
|
||||
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)
|
||||
name_id(std::numeric_limits<unsigned>::max()), turn_instruction(TurnInstruction::NoTurn),
|
||||
compressed_geometry(false), travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -36,7 +36,7 @@ class Percent
|
||||
public:
|
||||
explicit Percent(unsigned max_value, unsigned step = 5) { reinit(max_value, step); }
|
||||
|
||||
// Reinitializes
|
||||
// Reinitializes
|
||||
void reinit(unsigned max_value, unsigned step = 5)
|
||||
{
|
||||
m_max_value = max_value;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -27,40 +27,44 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "phantom_node.hpp"
|
||||
|
||||
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)
|
||||
{ }
|
||||
#include "../typedefs.h"
|
||||
#include "travel_mode.hpp"
|
||||
|
||||
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(-1),
|
||||
fwd_segment_position(0),
|
||||
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||
{ }
|
||||
#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
|
||||
{
|
||||
@ -82,43 +86,21 @@ int PhantomNode::GetReverseWeightPlusOffset() const
|
||||
|
||||
bool PhantomNode::is_bidirected() const
|
||||
{
|
||||
return (forward_node_id != SPECIAL_NODEID) &&
|
||||
(reverse_node_id != SPECIAL_NODEID);
|
||||
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_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() &&
|
||||
((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::operator==(const PhantomNode & other) const
|
||||
{
|
||||
return location == other.location;
|
||||
}
|
||||
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; }
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,11 +28,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef PHANTOM_NODES_H
|
||||
#define PHANTOM_NODES_H
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include "../data_structures/travel_mode.hpp"
|
||||
#include "travel_mode.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
struct PhantomNode
|
||||
@ -53,6 +55,28 @@ struct PhantomNode
|
||||
|
||||
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;
|
||||
@ -81,14 +105,13 @@ struct PhantomNode
|
||||
|
||||
bool is_in_tiny_component() const;
|
||||
|
||||
bool operator==(const PhantomNode & other) const;
|
||||
bool operator==(const PhantomNode &other) const;
|
||||
};
|
||||
|
||||
using PhantomNodeArray = std::vector<std::vector<PhantomNode>>;
|
||||
|
||||
class phantom_node_pair : public std::pair<PhantomNode, PhantomNode>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
struct PhantomNodeLists
|
||||
@ -103,26 +126,26 @@ struct PhantomNodes
|
||||
PhantomNode target_phantom;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn)
|
||||
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)
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -25,11 +25,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef QUERYEDGE_HPP_
|
||||
#define QUERYEDGE_HPP_
|
||||
#ifndef QUERYEDGE_HPP
|
||||
#define QUERYEDGE_HPP
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
struct QueryEdge
|
||||
{
|
||||
NodeID source;
|
||||
@ -60,13 +62,9 @@ struct QueryEdge
|
||||
{
|
||||
}
|
||||
|
||||
bool operator<(const QueryEdge &right) const
|
||||
bool operator<(const QueryEdge &rhs) const
|
||||
{
|
||||
if (source != right.source)
|
||||
{
|
||||
return source < right.source;
|
||||
}
|
||||
return target < right.target;
|
||||
return std::tie(source, target) < std::tie(rhs.source, rhs.target);
|
||||
}
|
||||
|
||||
bool operator==(const QueryEdge &right) const
|
||||
@ -78,4 +76,4 @@ struct QueryEdge
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* QUERYEDGE_HPP_ */
|
||||
#endif // QUERYEDGE_HPP
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,16 +30,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.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
|
||||
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()
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef RANGE_TABLE_HPP
|
||||
#define RANGE_TABLE_HPP
|
||||
|
||||
#include "../Util/integer_range.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "shared_memory_factory.hpp"
|
||||
#include "shared_memory_vector_wrapper.hpp"
|
||||
|
||||
@ -41,13 +41,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* and otherwise the compiler gets confused.
|
||||
*/
|
||||
|
||||
template<unsigned BLOCK_SIZE=16, bool USE_SHARED_MEMORY = false> class RangeTable;
|
||||
template <unsigned BLOCK_SIZE = 16, bool USE_SHARED_MEMORY = false> class RangeTable;
|
||||
|
||||
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::ostream& operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||
|
||||
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||
|
||||
/**
|
||||
* Stores adjacent ranges in a compressed format.
|
||||
@ -58,33 +58,34 @@ std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEM
|
||||
* But each block consists of an absolute value and BLOCK_SIZE differential values.
|
||||
* So the effective block size is sizeof(unsigned) + BLOCK_SIZE.
|
||||
*/
|
||||
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
class RangeTable
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
|
||||
{
|
||||
public:
|
||||
|
||||
public:
|
||||
using BlockT = std::array<unsigned char, BLOCK_SIZE>;
|
||||
using BlockContainerT = typename ShM<BlockT, USE_SHARED_MEMORY>::vector;
|
||||
using OffsetContainerT = typename ShM<unsigned, USE_SHARED_MEMORY>::vector;
|
||||
using RangeT = osrm::range<unsigned>;
|
||||
|
||||
friend std::ostream& operator<< <>(std::ostream &out, const RangeTable &table);
|
||||
friend std::istream& operator>> <>(std::istream &in, RangeTable &table);
|
||||
friend std::ostream &operator<<<>(std::ostream &out, const RangeTable &table);
|
||||
friend std::istream &operator>><>(std::istream &in, RangeTable &table);
|
||||
|
||||
RangeTable() : sum_lengths(0) {}
|
||||
|
||||
// for loading from shared memory
|
||||
explicit RangeTable(OffsetContainerT& external_offsets, BlockContainerT& external_blocks, const unsigned sum_lengths)
|
||||
: sum_lengths(sum_lengths)
|
||||
explicit RangeTable(OffsetContainerT &external_offsets,
|
||||
BlockContainerT &external_blocks,
|
||||
const unsigned sum_lengths)
|
||||
: sum_lengths(sum_lengths)
|
||||
{
|
||||
block_offsets.swap(external_offsets);
|
||||
diff_blocks.swap(external_blocks);
|
||||
}
|
||||
|
||||
// construct table from length vector
|
||||
explicit RangeTable(const std::vector<unsigned>& lengths)
|
||||
explicit RangeTable(const std::vector<unsigned> &lengths)
|
||||
{
|
||||
const unsigned number_of_blocks = [&lengths]() {
|
||||
const unsigned number_of_blocks = [&lengths]()
|
||||
{
|
||||
unsigned num = (lengths.size() + 1) / (BLOCK_SIZE + 1);
|
||||
if ((lengths.size() + 1) % (BLOCK_SIZE + 1) != 0)
|
||||
{
|
||||
@ -116,8 +117,8 @@ public:
|
||||
block_sum += last_length;
|
||||
}
|
||||
|
||||
BOOST_ASSERT((block_idx == 0 && block_offsets[block_counter] == lengths_prefix_sum)
|
||||
|| lengths_prefix_sum == (block_offsets[block_counter]+block_sum));
|
||||
BOOST_ASSERT((block_idx == 0 && block_offsets[block_counter] == lengths_prefix_sum) ||
|
||||
lengths_prefix_sum == (block_offsets[block_counter] + block_sum));
|
||||
|
||||
// block is full
|
||||
if (BLOCK_SIZE == block_idx)
|
||||
@ -136,7 +137,7 @@ public:
|
||||
}
|
||||
|
||||
// Last block can't be finished because we didn't add the sentinel
|
||||
BOOST_ASSERT (block_counter == (number_of_blocks - 1));
|
||||
BOOST_ASSERT(block_counter == (number_of_blocks - 1));
|
||||
|
||||
// one block missing: starts with guard value
|
||||
if (0 == block_idx)
|
||||
@ -155,7 +156,8 @@ public:
|
||||
}
|
||||
diff_blocks.push_back(block);
|
||||
|
||||
BOOST_ASSERT(diff_blocks.size() == number_of_blocks && block_offsets.size() == number_of_blocks);
|
||||
BOOST_ASSERT(diff_blocks.size() == number_of_blocks &&
|
||||
block_offsets.size() == number_of_blocks);
|
||||
|
||||
sum_lengths = lengths_prefix_sum;
|
||||
}
|
||||
@ -172,7 +174,7 @@ public:
|
||||
unsigned begin_idx = 0;
|
||||
unsigned end_idx = 0;
|
||||
begin_idx = block_offsets[block_idx];
|
||||
const BlockT& block = diff_blocks[block_idx];
|
||||
const BlockT &block = diff_blocks[block_idx];
|
||||
if (internal_idx > 0)
|
||||
{
|
||||
begin_idx += PrefixSumAtIndex(internal_idx - 1, block);
|
||||
@ -195,9 +197,9 @@ public:
|
||||
|
||||
return osrm::irange(begin_idx, end_idx);
|
||||
}
|
||||
private:
|
||||
|
||||
inline unsigned PrefixSumAtIndex(int index, const BlockT& block) const;
|
||||
private:
|
||||
inline unsigned PrefixSumAtIndex(int index, const BlockT &block) const;
|
||||
|
||||
// contains offset for each differential block
|
||||
OffsetContainerT block_offsets;
|
||||
@ -206,8 +208,9 @@ private:
|
||||
unsigned sum_lengths;
|
||||
};
|
||||
|
||||
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index, const BlockT& block) const
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index,
|
||||
const BlockT &block) const
|
||||
{
|
||||
// this loop looks inefficent, but a modern compiler
|
||||
// will emit nice SIMD here, at least for sensible block sizes. (I checked.)
|
||||
@ -220,39 +223,39 @@ unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index,
|
||||
return sum;
|
||||
}
|
||||
|
||||
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::ostream& operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||
{
|
||||
// write number of block
|
||||
const unsigned number_of_blocks = table.diff_blocks.size();
|
||||
out.write((char *) &number_of_blocks, sizeof(unsigned));
|
||||
out.write((char *)&number_of_blocks, sizeof(unsigned));
|
||||
// write total length
|
||||
out.write((char *) &table.sum_lengths, sizeof(unsigned));
|
||||
out.write((char *)&table.sum_lengths, sizeof(unsigned));
|
||||
// write block offsets
|
||||
out.write((char *) table.block_offsets.data(), sizeof(unsigned) * table.block_offsets.size());
|
||||
out.write((char *)table.block_offsets.data(), sizeof(unsigned) * table.block_offsets.size());
|
||||
// write blocks
|
||||
out.write((char *) table.diff_blocks.data(), BLOCK_SIZE * table.diff_blocks.size());
|
||||
out.write((char *)table.diff_blocks.data(), BLOCK_SIZE * table.diff_blocks.size());
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||
{
|
||||
// read number of block
|
||||
unsigned number_of_blocks;
|
||||
in.read((char *) &number_of_blocks, sizeof(unsigned));
|
||||
in.read((char *)&number_of_blocks, sizeof(unsigned));
|
||||
// read total length
|
||||
in.read((char *) &table.sum_lengths, sizeof(unsigned));
|
||||
in.read((char *)&table.sum_lengths, sizeof(unsigned));
|
||||
|
||||
table.block_offsets.resize(number_of_blocks);
|
||||
table.diff_blocks.resize(number_of_blocks);
|
||||
|
||||
// read block offsets
|
||||
in.read((char *) table.block_offsets.data(), sizeof(unsigned) * number_of_blocks);
|
||||
in.read((char *)table.block_offsets.data(), sizeof(unsigned) * number_of_blocks);
|
||||
// read blocks
|
||||
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;
|
||||
}
|
||||
|
||||
#endif //RANGE_TABLE_HPP
|
||||
#endif // RANGE_TABLE_HPP
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,8 +28,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef RECTANGLE_HPP
|
||||
#define RECTANGLE_HPP
|
||||
|
||||
#include "coordinate_calculation.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
@ -37,15 +41,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
// 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()) {}
|
||||
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;
|
||||
|
||||
inline void MergeBoundingBoxes(const RectangleInt2D &other)
|
||||
void MergeBoundingBoxes(const RectangleInt2D &other)
|
||||
{
|
||||
min_lon = std::min(min_lon, other.min_lon);
|
||||
max_lon = std::max(max_lon, other.max_lon);
|
||||
@ -57,7 +63,7 @@ struct RectangleInt2D
|
||||
BOOST_ASSERT(max_lon != std::numeric_limits<int32_t>::min());
|
||||
}
|
||||
|
||||
inline FixedPointCoordinate Centroid() const
|
||||
FixedPointCoordinate Centroid() const
|
||||
{
|
||||
FixedPointCoordinate centroid;
|
||||
// The coordinates of the midpoints are given by:
|
||||
@ -67,7 +73,7 @@ struct RectangleInt2D
|
||||
return centroid;
|
||||
}
|
||||
|
||||
inline bool Intersects(const RectangleInt2D &other) const
|
||||
bool Intersects(const RectangleInt2D &other) const
|
||||
{
|
||||
FixedPointCoordinate upper_left(other.max_lat, other.min_lon);
|
||||
FixedPointCoordinate upper_right(other.max_lat, other.max_lon);
|
||||
@ -78,7 +84,7 @@ struct RectangleInt2D
|
||||
Contains(lower_left));
|
||||
}
|
||||
|
||||
inline float GetMinDist(const FixedPointCoordinate &location) const
|
||||
float GetMinDist(const FixedPointCoordinate &location) const
|
||||
{
|
||||
const bool is_contained = Contains(location);
|
||||
if (is_contained)
|
||||
@ -88,66 +94,74 @@ struct RectangleInt2D
|
||||
|
||||
enum Direction
|
||||
{
|
||||
INVALID = 0,
|
||||
NORTH = 1,
|
||||
SOUTH = 2,
|
||||
EAST = 4,
|
||||
INVALID = 0,
|
||||
NORTH = 1,
|
||||
SOUTH = 2,
|
||||
EAST = 4,
|
||||
NORTH_EAST = 5,
|
||||
SOUTH_EAST = 6,
|
||||
WEST = 8,
|
||||
WEST = 8,
|
||||
NORTH_WEST = 9,
|
||||
SOUTH_WEST = 10
|
||||
};
|
||||
|
||||
Direction d = INVALID;
|
||||
if (location.lat > max_lat)
|
||||
d = (Direction) (d | NORTH);
|
||||
d = (Direction)(d | NORTH);
|
||||
else if (location.lat < min_lat)
|
||||
d = (Direction) (d | SOUTH);
|
||||
d = (Direction)(d | SOUTH);
|
||||
if (location.lon > max_lon)
|
||||
d = (Direction) (d | EAST);
|
||||
d = (Direction)(d | EAST);
|
||||
else if (location.lon < min_lon)
|
||||
d = (Direction) (d | WEST);
|
||||
d = (Direction)(d | WEST);
|
||||
|
||||
BOOST_ASSERT(d != INVALID);
|
||||
|
||||
float min_dist = std::numeric_limits<float>::max();
|
||||
switch (d)
|
||||
{
|
||||
case NORTH:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, location.lon));
|
||||
break;
|
||||
case SOUTH:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, location.lon));
|
||||
break;
|
||||
case WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, min_lon));
|
||||
break;
|
||||
case EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, max_lon));
|
||||
break;
|
||||
case NORTH_EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, max_lon));
|
||||
break;
|
||||
case NORTH_WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, min_lon));
|
||||
break;
|
||||
case SOUTH_EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, max_lon));
|
||||
break;
|
||||
case SOUTH_WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, min_lon));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
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());
|
||||
BOOST_ASSERT(min_dist < std::numeric_limits<float>::max());
|
||||
|
||||
return min_dist;
|
||||
}
|
||||
|
||||
inline float GetMinMaxDist(const FixedPointCoordinate &location) const
|
||||
float GetMinMaxDist(const FixedPointCoordinate &location) const
|
||||
{
|
||||
float min_max_dist = std::numeric_limits<float>::max();
|
||||
// Get minmax distance to each of the four sides
|
||||
@ -156,38 +170,36 @@ struct RectangleInt2D
|
||||
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(
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right)));
|
||||
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(
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_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(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left)));
|
||||
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(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_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;
|
||||
}
|
||||
|
||||
inline bool Contains(const FixedPointCoordinate &location) const
|
||||
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;
|
||||
}
|
||||
|
||||
inline friend std::ostream &operator<<(std::ostream &out, const RectangleInt2D &rect)
|
||||
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 << ","
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -107,21 +107,19 @@ struct InputRestrictionContainer
|
||||
|
||||
struct CmpRestrictionContainerByFrom
|
||||
{
|
||||
typedef InputRestrictionContainer value_type;
|
||||
inline bool operator()(const InputRestrictionContainer &a,
|
||||
const InputRestrictionContainer &b) const
|
||||
using value_type = InputRestrictionContainer;
|
||||
bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b) const
|
||||
{
|
||||
return a.restriction.from.way < b.restriction.from.way;
|
||||
}
|
||||
inline value_type max_value() const { return InputRestrictionContainer::max_value(); }
|
||||
inline value_type min_value() const { return InputRestrictionContainer::min_value(); }
|
||||
value_type max_value() const { return InputRestrictionContainer::max_value(); }
|
||||
value_type min_value() const { return InputRestrictionContainer::min_value(); }
|
||||
};
|
||||
|
||||
struct CmpRestrictionContainerByTo
|
||||
{
|
||||
typedef InputRestrictionContainer value_type;
|
||||
inline bool operator()(const InputRestrictionContainer &a,
|
||||
const InputRestrictionContainer &b) const
|
||||
using value_type = InputRestrictionContainer;
|
||||
bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b) const
|
||||
{
|
||||
return a.restriction.to.way < b.restriction.to.way;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -27,54 +27,51 @@ 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)
|
||||
{
|
||||
// decompose restriction consisting of a start, via and end node into a
|
||||
// a pair of starting edge and a list of all end nodes
|
||||
for (auto &restriction : restriction_list)
|
||||
{
|
||||
// decompose restriction consisting of a start, via and end node into a
|
||||
// a pair of starting edge and a list of all end nodes
|
||||
for (auto &restriction : restriction_list)
|
||||
m_restriction_start_nodes.insert(restriction.from.node);
|
||||
m_no_turn_via_node_set.insert(restriction.via.node);
|
||||
|
||||
RestrictionSource restriction_source = {restriction.from.node, restriction.via.node};
|
||||
|
||||
std::size_t index;
|
||||
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||
if (restriction_iter == m_restriction_map.end())
|
||||
{
|
||||
m_restriction_start_nodes.insert(restriction.from.node);
|
||||
m_no_turn_via_node_set.insert(restriction.via.node);
|
||||
|
||||
RestrictionSource restriction_source = {restriction.from.node, restriction.via.node};
|
||||
|
||||
std::size_t index;
|
||||
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||
if (restriction_iter == m_restriction_map.end())
|
||||
{
|
||||
index = m_restriction_bucket_list.size();
|
||||
m_restriction_bucket_list.resize(index + 1);
|
||||
m_restriction_map.emplace(restriction_source, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = restriction_iter->second;
|
||||
// Map already contains an is_only_*-restriction
|
||||
if (m_restriction_bucket_list.at(index).begin()->is_only)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (restriction.flags.is_only)
|
||||
{
|
||||
// We are going to insert an is_only_*-restriction. There can be only one.
|
||||
m_count -= m_restriction_bucket_list.at(index).size();
|
||||
m_restriction_bucket_list.at(index).clear();
|
||||
}
|
||||
}
|
||||
++m_count;
|
||||
m_restriction_bucket_list.at(index)
|
||||
.emplace_back(restriction.to.node, restriction.flags.is_only);
|
||||
index = m_restriction_bucket_list.size();
|
||||
m_restriction_bucket_list.resize(index + 1);
|
||||
m_restriction_map.emplace(restriction_source, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = restriction_iter->second;
|
||||
// Map already contains an is_only_*-restriction
|
||||
if (m_restriction_bucket_list.at(index).begin()->is_only)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (restriction.flags.is_only)
|
||||
{
|
||||
// We are going to insert an is_only_*-restriction. There can be only one.
|
||||
m_count -= m_restriction_bucket_list.at(index).size();
|
||||
m_restriction_bucket_list.at(index).clear();
|
||||
}
|
||||
}
|
||||
++m_count;
|
||||
m_restriction_bucket_list.at(index)
|
||||
.emplace_back(restriction.to.node, restriction.flags.is_only);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool RestrictionMap::IsViaNode(const NodeID node) const
|
||||
{
|
||||
return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
|
||||
}
|
||||
|
||||
|
||||
// Replaces start edge (v, w) with (u, w). Only start node changes.
|
||||
void RestrictionMap::FixupStartingTurnRestriction(const NodeID node_u,
|
||||
const NodeID node_v,
|
||||
@ -145,18 +142,25 @@ bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u,
|
||||
}
|
||||
|
||||
const auto restriction_iter = m_restriction_map.find({node_u, node_v});
|
||||
if (restriction_iter != m_restriction_map.end())
|
||||
if (restriction_iter == m_restriction_map.end())
|
||||
{
|
||||
const unsigned index = restriction_iter->second;
|
||||
const auto &bucket = m_restriction_bucket_list.at(index);
|
||||
for (const RestrictionTarget &restriction_target : bucket)
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned index = restriction_iter->second;
|
||||
const auto &bucket = m_restriction_bucket_list.at(index);
|
||||
|
||||
for (const RestrictionTarget &restriction_target : bucket)
|
||||
{
|
||||
if (node_w == restriction_target.target_node && // target found
|
||||
!restriction_target.is_only) // and not an only_-restr.
|
||||
{
|
||||
if ((node_w == restriction_target.target_node) && // target found
|
||||
(!restriction_target.is_only) // and not an only_-restr.
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (node_w != restriction_target.target_node && // target not found
|
||||
restriction_target.is_only) // and is an only restriction
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,14 +28,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef RESTRICTION_MAP_HPP
|
||||
#define RESTRICTION_MAP_HPP
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "restriction.hpp"
|
||||
#include "../Util/std_hash.hpp"
|
||||
#include "../util/std_hash.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
@ -45,9 +44,7 @@ struct RestrictionSource
|
||||
NodeID start_node;
|
||||
NodeID via_node;
|
||||
|
||||
RestrictionSource(NodeID start, NodeID via) : start_node(start), via_node(via)
|
||||
{
|
||||
}
|
||||
RestrictionSource(NodeID start, NodeID via) : start_node(start), via_node(via) {}
|
||||
|
||||
friend inline bool operator==(const RestrictionSource &lhs, const RestrictionSource &rhs)
|
||||
{
|
||||
@ -60,9 +57,7 @@ struct RestrictionTarget
|
||||
NodeID target_node;
|
||||
bool is_only;
|
||||
|
||||
explicit RestrictionTarget(NodeID target, bool only) : target_node(target), is_only(only)
|
||||
{
|
||||
}
|
||||
explicit RestrictionTarget(NodeID target, bool only) : target_node(target), is_only(only) {}
|
||||
|
||||
friend inline bool operator==(const RestrictionTarget &lhs, const RestrictionTarget &rhs)
|
||||
{
|
||||
@ -99,7 +94,7 @@ class RestrictionMap
|
||||
RestrictionMap(const std::vector<TurnRestriction> &restriction_list);
|
||||
|
||||
// Replace end v with w in each turn restriction containing u as via node
|
||||
template<class GraphT>
|
||||
template <class GraphT>
|
||||
void FixupArrivingTurnRestriction(const NodeID node_u,
|
||||
const NodeID node_v,
|
||||
const NodeID node_w,
|
||||
@ -136,6 +131,7 @@ class RestrictionMap
|
||||
|
||||
const unsigned index = restriction_iterator->second;
|
||||
auto &bucket = m_restriction_bucket_list.at(index);
|
||||
|
||||
for (RestrictionTarget &restriction_target : bucket)
|
||||
{
|
||||
if (node_v == restriction_target.target_node)
|
||||
@ -148,24 +144,18 @@ class RestrictionMap
|
||||
|
||||
bool IsViaNode(const NodeID node) const;
|
||||
|
||||
|
||||
// Replaces start edge (v, w) with (u, w). Only start node changes.
|
||||
void FixupStartingTurnRestriction(const NodeID node_u,
|
||||
const NodeID node_v,
|
||||
const NodeID node_w);
|
||||
void
|
||||
FixupStartingTurnRestriction(const NodeID node_u, const NodeID node_v, const NodeID node_w);
|
||||
|
||||
// Check if edge (u, v) is the start of any turn restriction.
|
||||
// If so returns id of first target node.
|
||||
NodeID CheckForEmanatingIsOnlyTurn(const NodeID node_u, const NodeID node_v) const;
|
||||
// Checks if turn <u,v,w> is actually a turn restriction.
|
||||
bool CheckIfTurnIsRestricted(const NodeID node_u,
|
||||
const NodeID node_v,
|
||||
const NodeID node_w) const;
|
||||
bool
|
||||
CheckIfTurnIsRestricted(const NodeID node_u, const NodeID node_v, const NodeID node_w) const;
|
||||
|
||||
std::size_t size()
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
std::size_t size() { return m_count; }
|
||||
|
||||
private:
|
||||
// check of node is the start of any restriction
|
||||
@ -182,4 +172,4 @@ class RestrictionMap
|
||||
std::unordered_set<NodeID> m_no_turn_via_node_set;
|
||||
};
|
||||
|
||||
#endif //RESTRICTION_MAP_HPP
|
||||
#endif // RESTRICTION_MAP_HPP
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -25,15 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osrm/RouteParameters.h>
|
||||
|
||||
#include <boost/fusion/container/vector.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic.hpp>
|
||||
#include <boost/fusion/include/at_c.hpp>
|
||||
|
||||
#include <osrm/route_parameters.hpp>
|
||||
|
||||
RouteParameters::RouteParameters()
|
||||
: zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
|
||||
compression(true), deprecatedAPI(false), uturn_default(false), check_sum(-1), num_results(1)
|
||||
compression(true), deprecatedAPI(false), uturn_default(false), classify(false),
|
||||
matching_beta(-1.0), gps_precision(-1.0), check_sum(-1), num_results(1)
|
||||
{
|
||||
}
|
||||
|
||||
@ -83,6 +84,12 @@ void RouteParameters::setInstructionFlag(const bool flag) { print_instructions =
|
||||
|
||||
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)
|
||||
@ -99,6 +106,15 @@ void RouteParameters::addHint(const std::string &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;
|
||||
@ -108,10 +124,10 @@ 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> &transmitted_coordinates)
|
||||
void RouteParameters::addCoordinate(
|
||||
const boost::fusion::vector<double, double> &received_coordinates)
|
||||
{
|
||||
coordinates.emplace_back(
|
||||
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates)),
|
||||
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates)));
|
||||
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(received_coordinates)),
|
||||
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(received_coordinates)));
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "search_engine_data.hpp"
|
||||
#include "../routing_algorithms/alternative_path.hpp"
|
||||
#include "../routing_algorithms/many_to_many.hpp"
|
||||
#include "../routing_algorithms/map_matching.hpp"
|
||||
#include "../routing_algorithms/shortest_path.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
@ -45,13 +46,18 @@ template <class DataFacadeT> class SearchEngine
|
||||
ShortestPathRouting<DataFacadeT> shortest_path;
|
||||
AlternativeRouting<DataFacadeT> alternative_path;
|
||||
ManyToManyRouting<DataFacadeT> distance_table;
|
||||
MapMatching<DataFacadeT> map_matching;
|
||||
|
||||
explicit SearchEngine(DataFacadeT *facade)
|
||||
: facade(facade), shortest_path(facade, engine_working_data),
|
||||
alternative_path(facade, engine_working_data), distance_table(facade, engine_working_data)
|
||||
: facade(facade),
|
||||
shortest_path(facade, engine_working_data),
|
||||
alternative_path(facade, engine_working_data),
|
||||
distance_table(facade, engine_working_data),
|
||||
map_matching(facade, engine_working_data)
|
||||
{
|
||||
static_assert(!std::is_pointer<DataFacadeT>::value, "don't instantiate with ptr type");
|
||||
static_assert(std::is_object<DataFacadeT>::value, "don't instantiate with void, function, or reference");
|
||||
static_assert(std::is_object<DataFacadeT>::value,
|
||||
"don't instantiate with void, function, or reference");
|
||||
}
|
||||
|
||||
~SearchEngine() {}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -31,63 +31,63 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
|
||||
{
|
||||
if (forwardHeap.get())
|
||||
if (forward_heap_1.get())
|
||||
{
|
||||
forwardHeap->Clear();
|
||||
forward_heap_1->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
forwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||
forward_heap_1.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
|
||||
if (backwardHeap.get())
|
||||
if (reverse_heap_1.get())
|
||||
{
|
||||
backwardHeap->Clear();
|
||||
reverse_heap_1->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
backwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||
reverse_heap_1.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
}
|
||||
|
||||
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes)
|
||||
{
|
||||
if (forwardHeap2.get())
|
||||
if (forward_heap_2.get())
|
||||
{
|
||||
forwardHeap2->Clear();
|
||||
forward_heap_2->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
forwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||
forward_heap_2.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
|
||||
if (backwardHeap2.get())
|
||||
if (reverse_heap_2.get())
|
||||
{
|
||||
backwardHeap2->Clear();
|
||||
reverse_heap_2->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
backwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||
reverse_heap_2.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
}
|
||||
|
||||
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes)
|
||||
{
|
||||
if (forwardHeap3.get())
|
||||
if (forward_heap_3.get())
|
||||
{
|
||||
forwardHeap3->Clear();
|
||||
forward_heap_3->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
forwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||
forward_heap_3.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
|
||||
if (backwardHeap3.get())
|
||||
if (reverse_heap_3.get())
|
||||
{
|
||||
backwardHeap3->Clear();
|
||||
reverse_heap_3->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
backwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||
reverse_heap_3.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -44,12 +44,12 @@ struct SearchEngineData
|
||||
using QueryHeap = BinaryHeap<NodeID, NodeID, int, HeapData, UnorderedMapStorage<NodeID, int>>;
|
||||
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
||||
|
||||
static SearchEngineHeapPtr forwardHeap;
|
||||
static SearchEngineHeapPtr backwardHeap;
|
||||
static SearchEngineHeapPtr forwardHeap2;
|
||||
static SearchEngineHeapPtr backwardHeap2;
|
||||
static SearchEngineHeapPtr forwardHeap3;
|
||||
static SearchEngineHeapPtr backwardHeap3;
|
||||
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);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -25,15 +25,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SEGMENT_INFORMATION_H
|
||||
#define SEGMENT_INFORMATION_H
|
||||
#ifndef SEGMENT_INFORMATION_HPP
|
||||
#define SEGMENT_INFORMATION_HPP
|
||||
|
||||
#include "turn_instructions.hpp"
|
||||
|
||||
#include "../data_structures/travel_mode.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
// Struct fits everything in one cache line
|
||||
struct SegmentInformation
|
||||
@ -75,4 +75,4 @@ struct SegmentInformation
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* SEGMENT_INFORMATION_H */
|
||||
#endif /* SEGMENT_INFORMATION_HPP */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,8 +28,8 @@ 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 "../util/osrm_exception.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
@ -123,8 +123,8 @@ class SharedMemory
|
||||
{
|
||||
Remove(key);
|
||||
}
|
||||
shm = boost::interprocess::xsi_shared_memory(
|
||||
boost::interprocess::open_or_create, key, size);
|
||||
shm = boost::interprocess::xsi_shared_memory(boost::interprocess::open_or_create, key,
|
||||
size);
|
||||
#ifdef __linux__
|
||||
if (-1 == shmctl(shm.get_shmid(), SHM_LOCK, 0))
|
||||
{
|
||||
@ -150,7 +150,10 @@ class SharedMemory
|
||||
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
|
||||
result = RegionExists(key);
|
||||
}
|
||||
catch (...) { result = false; }
|
||||
catch (...)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -165,8 +168,14 @@ class SharedMemory
|
||||
static bool RegionExists(const boost::interprocess::xsi_key &key)
|
||||
{
|
||||
bool result = true;
|
||||
try { boost::interprocess::xsi_shared_memory shm(boost::interprocess::open_only, key); }
|
||||
catch (...) { result = false; }
|
||||
try
|
||||
{
|
||||
boost::interprocess::xsi_shared_memory shm(boost::interprocess::open_only, key);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -198,12 +207,12 @@ class SharedMemory
|
||||
// Windows - specific code
|
||||
class SharedMemory
|
||||
{
|
||||
SharedMemory(const SharedMemory&) = delete;
|
||||
SharedMemory(const SharedMemory &) = delete;
|
||||
// Remove shared memory on destruction
|
||||
class shm_remove
|
||||
{
|
||||
private:
|
||||
shm_remove(const shm_remove&) = delete;
|
||||
shm_remove(const shm_remove &) = delete;
|
||||
char *m_shmid;
|
||||
bool m_initialized;
|
||||
|
||||
@ -242,8 +251,7 @@ class SharedMemory
|
||||
if (0 == size)
|
||||
{ // read_only
|
||||
shm = boost::interprocess::shared_memory_object(
|
||||
boost::interprocess::open_only,
|
||||
key,
|
||||
boost::interprocess::open_only, key,
|
||||
read_write ? boost::interprocess::read_write : boost::interprocess::read_only);
|
||||
region = boost::interprocess::mapped_region(
|
||||
shm, read_write ? boost::interprocess::read_write : boost::interprocess::read_only);
|
||||
@ -255,8 +263,8 @@ class SharedMemory
|
||||
{
|
||||
Remove(key);
|
||||
}
|
||||
shm = boost::interprocess::shared_memory_object(
|
||||
boost::interprocess::open_or_create, key, boost::interprocess::read_write);
|
||||
shm = boost::interprocess::shared_memory_object(boost::interprocess::open_or_create,
|
||||
key, boost::interprocess::read_write);
|
||||
shm.truncate(size);
|
||||
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
|
||||
|
||||
@ -274,7 +282,10 @@ class SharedMemory
|
||||
build_key(id, k);
|
||||
result = RegionExists(k);
|
||||
}
|
||||
catch (...) { result = false; }
|
||||
catch (...)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -286,20 +297,20 @@ class SharedMemory
|
||||
}
|
||||
|
||||
private:
|
||||
static void build_key(int id, char *key)
|
||||
{
|
||||
sprintf(key, "%s.%d", "osrm.lock", id);
|
||||
}
|
||||
static void build_key(int id, char *key) { sprintf(key, "%s.%d", "osrm.lock", id); }
|
||||
|
||||
static bool RegionExists(const char *key)
|
||||
{
|
||||
bool result = true;
|
||||
try
|
||||
{
|
||||
boost::interprocess::shared_memory_object shm(
|
||||
boost::interprocess::open_only, key, boost::interprocess::read_write);
|
||||
boost::interprocess::shared_memory_object shm(boost::interprocess::open_only, key,
|
||||
boost::interprocess::read_write);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
catch (...) { result = false; }
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -147,8 +147,8 @@ template <> class SharedMemoryWrapper<bool>
|
||||
template <typename DataT, bool UseSharedMemory> struct ShM
|
||||
{
|
||||
using vector = typename std::conditional<UseSharedMemory,
|
||||
SharedMemoryWrapper<DataT>,
|
||||
std::vector<DataT>>::type;
|
||||
SharedMemoryWrapper<DataT>,
|
||||
std::vector<DataT>>::type;
|
||||
};
|
||||
|
||||
#endif // SHARED_MEMORY_VECTOR_WRAPPER_HPP
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,13 +30,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "percent.hpp"
|
||||
#include "shared_memory_vector_wrapper.hpp"
|
||||
#include "../Util/integer_range.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
@ -57,8 +55,11 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
NodeIterator target;
|
||||
EdgeDataT data;
|
||||
|
||||
template<typename... Ts>
|
||||
InputEdge(NodeIterator source, NodeIterator target, Ts &&...data) : source(source), target(target), data(std::forward<Ts>(data)...) { }
|
||||
template <typename... Ts>
|
||||
InputEdge(NodeIterator source, NodeIterator target, Ts &&... data)
|
||||
: source(source), target(target), data(std::forward<Ts>(data)...)
|
||||
{
|
||||
}
|
||||
bool operator<(const InputEdge &right) const
|
||||
{
|
||||
if (source != right.source)
|
||||
@ -88,13 +89,12 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
|
||||
StaticGraph(const int nodes, std::vector<InputEdge> &graph)
|
||||
{
|
||||
tbb::parallel_sort(graph.begin(), graph.end());
|
||||
number_of_nodes = nodes;
|
||||
number_of_edges = static_cast<EdgeIterator>(graph.size());
|
||||
node_array.resize(number_of_nodes + 1);
|
||||
EdgeIterator edge = 0;
|
||||
EdgeIterator position = 0;
|
||||
for (const auto node : osrm::irange(0u, number_of_nodes+1))
|
||||
for (const auto node : osrm::irange(0u, number_of_nodes + 1))
|
||||
{
|
||||
EdgeIterator last_edge = edge;
|
||||
while (edge < number_of_edges && graph[edge].source == node)
|
||||
@ -109,11 +109,10 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||
{
|
||||
EdgeIterator e = node_array[node + 1].first_edge;
|
||||
for (EdgeIterator i = node_array[node].first_edge; i != e; ++i)
|
||||
for (const auto i : osrm::irange(node_array[node].first_edge, e))
|
||||
{
|
||||
edge_array[i].target = graph[edge].target;
|
||||
edge_array[i].data = graph[edge].data;
|
||||
BOOST_ASSERT(edge_array[i].data.distance > 0);
|
||||
edge++;
|
||||
}
|
||||
}
|
||||
@ -140,7 +139,7 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
return NodeIterator(edge_array[e].target);
|
||||
}
|
||||
|
||||
inline EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; }
|
||||
EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; }
|
||||
|
||||
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_array[e].data; }
|
||||
|
||||
@ -156,6 +155,19 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
|
||||
// searches for a specific edge
|
||||
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
|
||||
{
|
||||
for (const auto i : osrm::irange(BeginEdges(from), EndEdges(from)))
|
||||
{
|
||||
if (to == edge_array[i].target)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return SPECIAL_EDGEID;
|
||||
}
|
||||
|
||||
// searches for a specific edge
|
||||
EdgeIterator FindSmallestEdge(const NodeIterator from, const NodeIterator to) const
|
||||
{
|
||||
EdgeIterator smallest_edge = SPECIAL_EDGEID;
|
||||
EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -138,8 +138,8 @@ class StaticKDTree
|
||||
continue;
|
||||
|
||||
Iterator middle = tree.left + (tree.right - tree.left) / 2;
|
||||
std::nth_element(
|
||||
kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less(tree.dimension));
|
||||
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));
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -35,16 +35,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "rectangle.hpp"
|
||||
#include "shared_memory_factory.hpp"
|
||||
#include "shared_memory_vector_wrapper.hpp"
|
||||
#include "upper_bound.hpp"
|
||||
|
||||
#include "../Util/floating_point.hpp"
|
||||
#include "../Util/integer_range.hpp"
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#include "../Util/osrm_exception.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/timing_util.hpp"
|
||||
#include "../util/floating_point.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../util/mercator.hpp"
|
||||
#include "../util/osrm_exception.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
@ -68,8 +69,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
template <class EdgeDataT,
|
||||
class CoordinateListT = std::vector<FixedPointCoordinate>,
|
||||
bool UseSharedMemory = false,
|
||||
uint32_t BRANCHING_FACTOR=64,
|
||||
uint32_t LEAF_NODE_SIZE=1024>
|
||||
uint32_t BRANCHING_FACTOR = 64,
|
||||
uint32_t LEAF_NODE_SIZE = 1024>
|
||||
class StaticRTree
|
||||
{
|
||||
public:
|
||||
@ -86,19 +87,15 @@ class StaticRTree
|
||||
{
|
||||
for (uint32_t i = 0; i < element_count; ++i)
|
||||
{
|
||||
min_lon = std::min(min_lon,
|
||||
std::min(coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon));
|
||||
max_lon = std::max(max_lon,
|
||||
std::max(coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon));
|
||||
min_lon = std::min(min_lon, std::min(coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon));
|
||||
max_lon = std::max(max_lon, std::max(coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon));
|
||||
|
||||
min_lat = std::min(min_lat,
|
||||
std::min(coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat));
|
||||
max_lat = std::max(max_lat,
|
||||
std::max(coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat));
|
||||
min_lat = std::min(min_lat, std::min(coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat));
|
||||
max_lat = std::max(max_lat, std::max(coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat));
|
||||
}
|
||||
BOOST_ASSERT(min_lat != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(min_lon != std::numeric_limits<int>::min());
|
||||
@ -149,58 +146,66 @@ class StaticRTree
|
||||
|
||||
enum Direction
|
||||
{
|
||||
INVALID = 0,
|
||||
NORTH = 1,
|
||||
SOUTH = 2,
|
||||
EAST = 4,
|
||||
INVALID = 0,
|
||||
NORTH = 1,
|
||||
SOUTH = 2,
|
||||
EAST = 4,
|
||||
NORTH_EAST = 5,
|
||||
SOUTH_EAST = 6,
|
||||
WEST = 8,
|
||||
WEST = 8,
|
||||
NORTH_WEST = 9,
|
||||
SOUTH_WEST = 10
|
||||
};
|
||||
|
||||
Direction d = INVALID;
|
||||
if (location.lat > max_lat)
|
||||
d = (Direction) (d | NORTH);
|
||||
d = (Direction)(d | NORTH);
|
||||
else if (location.lat < min_lat)
|
||||
d = (Direction) (d | SOUTH);
|
||||
d = (Direction)(d | SOUTH);
|
||||
if (location.lon > max_lon)
|
||||
d = (Direction) (d | EAST);
|
||||
d = (Direction)(d | EAST);
|
||||
else if (location.lon < min_lon)
|
||||
d = (Direction) (d | WEST);
|
||||
d = (Direction)(d | WEST);
|
||||
|
||||
BOOST_ASSERT(d != INVALID);
|
||||
|
||||
float min_dist = std::numeric_limits<float>::max();
|
||||
switch (d)
|
||||
{
|
||||
case NORTH:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, location.lon));
|
||||
break;
|
||||
case SOUTH:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, location.lon));
|
||||
break;
|
||||
case WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, min_lon));
|
||||
break;
|
||||
case EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, max_lon));
|
||||
break;
|
||||
case NORTH_EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, max_lon));
|
||||
break;
|
||||
case NORTH_WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, min_lon));
|
||||
break;
|
||||
case SOUTH_EAST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, max_lon));
|
||||
break;
|
||||
case SOUTH_WEST:
|
||||
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, min_lon));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
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());
|
||||
@ -219,25 +224,23 @@ class StaticRTree
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right)));
|
||||
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(
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right)));
|
||||
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(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left)));
|
||||
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(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left),
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left)));
|
||||
std::max(coordinate_calculation::euclidean_distance(location, lower_left),
|
||||
coordinate_calculation::euclidean_distance(location, upper_left)));
|
||||
return min_max_dist;
|
||||
}
|
||||
|
||||
@ -377,7 +380,8 @@ class StaticRTree
|
||||
FixedPointCoordinate(coordinate_list.at(current_element.v).lat,
|
||||
coordinate_list.at(current_element.v).lon));
|
||||
current_centroid.lat =
|
||||
COORDINATE_PRECISION * lat2y(current_centroid.lat / COORDINATE_PRECISION);
|
||||
COORDINATE_PRECISION *
|
||||
mercator::lat2y(current_centroid.lat / COORDINATE_PRECISION);
|
||||
|
||||
current_wrapper.m_hilbert_value = get_hilbert_number(current_centroid);
|
||||
}
|
||||
@ -415,8 +419,8 @@ class StaticRTree
|
||||
}
|
||||
|
||||
// generate tree node that resemble the objects in leaf and store it for next level
|
||||
InitializeMBRectangle(current_node.minimum_bounding_rectangle,
|
||||
current_leaf.objects, current_leaf.object_count, coordinate_list);
|
||||
InitializeMBRectangle(current_node.minimum_bounding_rectangle, current_leaf.objects,
|
||||
current_leaf.object_count, coordinate_list);
|
||||
current_node.child_is_on_disk = true;
|
||||
current_node.children[0] = tree_nodes_in_level.size();
|
||||
tree_nodes_in_level.emplace_back(current_node);
|
||||
@ -439,8 +443,7 @@ class StaticRTree
|
||||
TreeNode parent_node;
|
||||
// pack BRANCHING_FACTOR elements into tree_nodes each
|
||||
for (uint32_t current_child_node_index = 0;
|
||||
BRANCHING_FACTOR > current_child_node_index;
|
||||
++current_child_node_index)
|
||||
BRANCHING_FACTOR > current_child_node_index; ++current_child_node_index)
|
||||
{
|
||||
if (processed_tree_nodes_in_level < tree_nodes_in_level.size())
|
||||
{
|
||||
@ -473,17 +476,17 @@ class StaticRTree
|
||||
tbb::parallel_for(tbb::blocked_range<uint32_t>(0, search_tree_size),
|
||||
[this, &search_tree_size](const tbb::blocked_range<uint32_t> &range)
|
||||
{
|
||||
for (uint32_t i = range.begin(); i != range.end(); ++i)
|
||||
{
|
||||
TreeNode ¤t_tree_node = this->m_search_tree[i];
|
||||
for (uint32_t j = 0; j < current_tree_node.child_count; ++j)
|
||||
{
|
||||
const uint32_t old_id = current_tree_node.children[j];
|
||||
const uint32_t new_id = search_tree_size - old_id - 1;
|
||||
current_tree_node.children[j] = new_id;
|
||||
}
|
||||
}
|
||||
});
|
||||
for (uint32_t i = range.begin(); i != range.end(); ++i)
|
||||
{
|
||||
TreeNode ¤t_tree_node = this->m_search_tree[i];
|
||||
for (uint32_t j = 0; j < current_tree_node.child_count; ++j)
|
||||
{
|
||||
const uint32_t old_id = current_tree_node.children[j];
|
||||
const uint32_t new_id = search_tree_size - old_id - 1;
|
||||
current_tree_node.children[j] = new_id;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// open tree file
|
||||
boost::filesystem::ofstream tree_node_file(tree_node_filename, std::ios::binary);
|
||||
@ -605,12 +608,10 @@ class StaticRTree
|
||||
continue;
|
||||
}
|
||||
|
||||
float current_minimum_distance =
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
input_coordinate.lat,
|
||||
input_coordinate.lon,
|
||||
m_coordinate_list->at(current_edge.u).lat,
|
||||
m_coordinate_list->at(current_edge.u).lon);
|
||||
float current_minimum_distance = coordinate_calculation::euclidean_distance(
|
||||
input_coordinate.lat, input_coordinate.lon,
|
||||
m_coordinate_list->at(current_edge.u).lat,
|
||||
m_coordinate_list->at(current_edge.u).lon);
|
||||
if (current_minimum_distance < min_dist)
|
||||
{
|
||||
// found a new minimum
|
||||
@ -618,12 +619,10 @@ class StaticRTree
|
||||
result_coordinate = m_coordinate_list->at(current_edge.u);
|
||||
}
|
||||
|
||||
current_minimum_distance =
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
input_coordinate.lat,
|
||||
input_coordinate.lon,
|
||||
m_coordinate_list->at(current_edge.v).lat,
|
||||
m_coordinate_list->at(current_edge.v).lon);
|
||||
current_minimum_distance = coordinate_calculation::euclidean_distance(
|
||||
input_coordinate.lat, input_coordinate.lon,
|
||||
m_coordinate_list->at(current_edge.v).lat,
|
||||
m_coordinate_list->at(current_edge.v).lon);
|
||||
|
||||
if (current_minimum_distance < min_dist)
|
||||
{
|
||||
@ -635,32 +634,34 @@ class StaticRTree
|
||||
}
|
||||
else
|
||||
{
|
||||
min_max_dist = ExploreTreeNode(current_tree_node,
|
||||
input_coordinate,
|
||||
min_dist,
|
||||
min_max_dist,
|
||||
traversal_queue);
|
||||
min_max_dist = ExploreTreeNode(current_tree_node, input_coordinate, min_dist,
|
||||
min_max_dist, traversal_queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result_coordinate.is_valid();
|
||||
}
|
||||
|
||||
|
||||
// implementation of the Hjaltason/Samet query [3], a BFS traversal of the tree
|
||||
// - searches for k elements nearest elements
|
||||
// - continues to find the k+1st element from a big component if k elements
|
||||
// come from tiny components
|
||||
bool
|
||||
IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
|
||||
std::vector<PhantomNode> &result_phantom_node_vector,
|
||||
const unsigned max_number_of_phantom_nodes,
|
||||
const unsigned max_checked_elements = 4*LEAF_NODE_SIZE)
|
||||
bool IncrementalFindPhantomNodeForCoordinate(
|
||||
const FixedPointCoordinate &input_coordinate,
|
||||
std::vector<PhantomNode> &result_phantom_node_vector,
|
||||
const unsigned max_number_of_phantom_nodes,
|
||||
const unsigned max_checked_elements = 4 * LEAF_NODE_SIZE)
|
||||
{
|
||||
unsigned inspected_elements = 0;
|
||||
unsigned number_of_elements_from_big_cc = 0;
|
||||
unsigned number_of_elements_from_tiny_cc = 0;
|
||||
|
||||
#ifdef NDEBUG
|
||||
unsigned pruned_elements = 0;
|
||||
#endif
|
||||
std::pair<double, double> projected_coordinate = {
|
||||
mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION),
|
||||
input_coordinate.lon / COORDINATE_PRECISION};
|
||||
|
||||
// upper bound pruning technique
|
||||
upper_bound<float> pruning_bound(max_number_of_phantom_nodes);
|
||||
|
||||
// initialize queue with root element
|
||||
std::priority_queue<IncrementalQueryCandidate> traversal_queue;
|
||||
traversal_queue.emplace(0.f, m_search_tree[0]);
|
||||
@ -672,7 +673,8 @@ class StaticRTree
|
||||
|
||||
if (current_query_node.node.template is<TreeNode>())
|
||||
{ // current object is a tree node
|
||||
const TreeNode & current_tree_node = current_query_node.node.template get<TreeNode>();
|
||||
const TreeNode ¤t_tree_node =
|
||||
current_query_node.node.template get<TreeNode>();
|
||||
if (current_tree_node.child_is_on_disk)
|
||||
{
|
||||
LeafNode current_leaf_node;
|
||||
@ -682,16 +684,26 @@ class StaticRTree
|
||||
for (const auto i : osrm::irange(0u, current_leaf_node.object_count))
|
||||
{
|
||||
const auto ¤t_edge = current_leaf_node.objects[i];
|
||||
const float current_perpendicular_distance =
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(
|
||||
const float current_perpendicular_distance = coordinate_calculation::
|
||||
perpendicular_distance_from_projected_coordinate(
|
||||
m_coordinate_list->at(current_edge.u),
|
||||
m_coordinate_list->at(current_edge.v),
|
||||
input_coordinate);
|
||||
m_coordinate_list->at(current_edge.v), input_coordinate,
|
||||
projected_coordinate);
|
||||
// distance must be non-negative
|
||||
BOOST_ASSERT(0.f <= current_perpendicular_distance);
|
||||
|
||||
// put element in queue
|
||||
traversal_queue.emplace(current_perpendicular_distance, current_edge);
|
||||
if (pruning_bound.get() >= current_perpendicular_distance ||
|
||||
current_edge.is_in_tiny_cc())
|
||||
{
|
||||
pruning_bound.insert(current_perpendicular_distance);
|
||||
traversal_queue.emplace(current_perpendicular_distance, current_edge);
|
||||
}
|
||||
#ifdef NDEBUG
|
||||
else
|
||||
{
|
||||
++pruned_elements;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -701,8 +713,10 @@ class StaticRTree
|
||||
{
|
||||
const int32_t child_id = current_tree_node.children[i];
|
||||
const TreeNode &child_tree_node = m_search_tree[child_id];
|
||||
const RectangleT &child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
||||
const float lower_bound_to_element = child_rectangle.GetMinDist(input_coordinate);
|
||||
const RectangleT &child_rectangle =
|
||||
child_tree_node.minimum_bounding_rectangle;
|
||||
const float lower_bound_to_element =
|
||||
child_rectangle.GetMinDist(input_coordinate);
|
||||
BOOST_ASSERT(0.f <= lower_bound_to_element);
|
||||
|
||||
traversal_queue.emplace(lower_bound_to_element, child_tree_node);
|
||||
@ -713,7 +727,8 @@ class StaticRTree
|
||||
{ // current object is a leaf node
|
||||
++inspected_elements;
|
||||
// inspecting an actual road segment
|
||||
const EdgeDataT & current_segment = current_query_node.node.template get<EdgeDataT>();
|
||||
const EdgeDataT ¤t_segment =
|
||||
current_query_node.node.template get<EdgeDataT>();
|
||||
|
||||
// continue searching for the first segment from a big component
|
||||
if (number_of_elements_from_big_cc == 0 &&
|
||||
@ -726,29 +741,16 @@ class StaticRTree
|
||||
// check if it is smaller than what we had before
|
||||
float current_ratio = 0.f;
|
||||
FixedPointCoordinate foot_point_coordinate_on_segment;
|
||||
|
||||
// const float current_perpendicular_distance =
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(
|
||||
m_coordinate_list->at(current_segment.u),
|
||||
m_coordinate_list->at(current_segment.v),
|
||||
input_coordinate,
|
||||
foot_point_coordinate_on_segment,
|
||||
current_ratio);
|
||||
coordinate_calculation::perpendicular_distance_from_projected_coordinate(
|
||||
m_coordinate_list->at(current_segment.u),
|
||||
m_coordinate_list->at(current_segment.v), input_coordinate,
|
||||
projected_coordinate, foot_point_coordinate_on_segment, current_ratio);
|
||||
|
||||
// store phantom node in result vector
|
||||
result_phantom_node_vector.emplace_back(
|
||||
current_segment.forward_edge_based_node_id,
|
||||
current_segment.reverse_edge_based_node_id,
|
||||
current_segment.name_id,
|
||||
current_segment.forward_weight,
|
||||
current_segment.reverse_weight,
|
||||
current_segment.forward_offset,
|
||||
current_segment.reverse_offset,
|
||||
current_segment.packed_geometry_id,
|
||||
current_segment.component_id,
|
||||
foot_point_coordinate_on_segment,
|
||||
current_segment.fwd_segment_position,
|
||||
current_segment.forward_travel_mode,
|
||||
current_segment.backward_travel_mode);
|
||||
result_phantom_node_vector.emplace_back(current_segment,
|
||||
foot_point_coordinate_on_segment);
|
||||
|
||||
// Hack to fix rounding errors and wandering via nodes.
|
||||
FixUpRoundingIssue(input_coordinate, result_phantom_node_vector.back());
|
||||
@ -766,39 +768,55 @@ class StaticRTree
|
||||
{ // found an element in a big component
|
||||
++number_of_elements_from_big_cc;
|
||||
}
|
||||
|
||||
// SimpleLogger().Write() << "result_phantom_node_vector.size(): " << result_phantom_node_vector.size();
|
||||
// SimpleLogger().Write() << "max_number_of_phantom_nodes: " << max_number_of_phantom_nodes;
|
||||
// SimpleLogger().Write() << "number_of_elements_from_big_cc: " << number_of_elements_from_big_cc;
|
||||
// SimpleLogger().Write() << "number_of_elements_from_tiny_cc: " << number_of_elements_from_tiny_cc;
|
||||
// SimpleLogger().Write() << "inspected_elements: " << inspected_elements;
|
||||
// SimpleLogger().Write() << "max_checked_elements: " << max_checked_elements;
|
||||
}
|
||||
|
||||
// stop the search by flushing the queue
|
||||
if ((result_phantom_node_vector.size() >= max_number_of_phantom_nodes && number_of_elements_from_big_cc > 0) ||
|
||||
if ((result_phantom_node_vector.size() >= max_number_of_phantom_nodes &&
|
||||
number_of_elements_from_big_cc > 0) ||
|
||||
inspected_elements >= max_checked_elements)
|
||||
{
|
||||
traversal_queue = std::priority_queue<IncrementalQueryCandidate>{};
|
||||
}
|
||||
}
|
||||
// SimpleLogger().Write() << "inspected_elements: " << inspected_elements;
|
||||
#ifdef NDEBUG
|
||||
// SimpleLogger().Write() << "result_phantom_node_vector.size(): " <<
|
||||
// result_phantom_node_vector.size();
|
||||
// SimpleLogger().Write() << "max_number_of_phantom_nodes: " << max_number_of_phantom_nodes;
|
||||
// SimpleLogger().Write() << "number_of_elements_from_big_cc: " <<
|
||||
// number_of_elements_from_big_cc;
|
||||
// SimpleLogger().Write() << "number_of_elements_from_tiny_cc: " <<
|
||||
// number_of_elements_from_tiny_cc;
|
||||
// SimpleLogger().Write() << "inspected_elements: " << inspected_elements;
|
||||
// SimpleLogger().Write() << "max_checked_elements: " << max_checked_elements;
|
||||
// SimpleLogger().Write() << "pruned_elements: " << pruned_elements;
|
||||
#endif
|
||||
return !result_phantom_node_vector.empty();
|
||||
}
|
||||
|
||||
// implementation of the Hjaltason/Samet query [3], a BFS traversal of the tree
|
||||
bool
|
||||
IncrementalFindPhantomNodeForCoordinateWithDistance(const FixedPointCoordinate &input_coordinate,
|
||||
std::vector<std::pair<PhantomNode, double>> &result_phantom_node_vector,
|
||||
const unsigned number_of_results,
|
||||
const unsigned max_checked_segments = 4*LEAF_NODE_SIZE)
|
||||
// Returns elements within max_distance.
|
||||
// If the minium of elements could not be found in the search radius, widen
|
||||
// it until the minimum can be satisfied.
|
||||
// At the number of returned nodes is capped at the given maximum.
|
||||
bool IncrementalFindPhantomNodeForCoordinateWithDistance(
|
||||
const FixedPointCoordinate &input_coordinate,
|
||||
std::vector<std::pair<PhantomNode, double>> &result_phantom_node_vector,
|
||||
const double max_distance,
|
||||
const unsigned min_number_of_phantom_nodes,
|
||||
const unsigned max_number_of_phantom_nodes,
|
||||
const unsigned max_checked_elements = 4 * LEAF_NODE_SIZE)
|
||||
{
|
||||
std::vector<float> min_found_distances(number_of_results, std::numeric_limits<float>::max());
|
||||
unsigned inspected_elements = 0;
|
||||
unsigned number_of_elements_from_big_cc = 0;
|
||||
unsigned number_of_elements_from_tiny_cc = 0;
|
||||
|
||||
unsigned number_of_results_found_in_big_cc = 0;
|
||||
unsigned number_of_results_found_in_tiny_cc = 0;
|
||||
unsigned pruned_elements = 0;
|
||||
|
||||
unsigned inspected_segments = 0;
|
||||
std::pair<double, double> projected_coordinate = {
|
||||
mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION),
|
||||
input_coordinate.lon / COORDINATE_PRECISION};
|
||||
|
||||
// upper bound pruning technique
|
||||
upper_bound<float> pruning_bound(max_number_of_phantom_nodes);
|
||||
|
||||
// initialize queue with root element
|
||||
std::priority_queue<IncrementalQueryCandidate> traversal_queue;
|
||||
@ -809,144 +827,141 @@ class StaticRTree
|
||||
const IncrementalQueryCandidate current_query_node = traversal_queue.top();
|
||||
traversal_queue.pop();
|
||||
|
||||
const float current_min_dist = min_found_distances[number_of_results-1];
|
||||
|
||||
if (current_query_node.min_dist > current_min_dist)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current_query_node.RepresentsTreeNode())
|
||||
{
|
||||
const TreeNode & current_tree_node = current_query_node.node.template get<TreeNode>();
|
||||
if (current_query_node.node.template is<TreeNode>())
|
||||
{ // current object is a tree node
|
||||
const TreeNode ¤t_tree_node =
|
||||
current_query_node.node.template get<TreeNode>();
|
||||
if (current_tree_node.child_is_on_disk)
|
||||
{
|
||||
LeafNode current_leaf_node;
|
||||
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
|
||||
// Add all objects from leaf into queue
|
||||
for (uint32_t i = 0; i < current_leaf_node.object_count; ++i)
|
||||
|
||||
// current object represents a block on disk
|
||||
for (const auto i : osrm::irange(0u, current_leaf_node.object_count))
|
||||
{
|
||||
const auto ¤t_edge = current_leaf_node.objects[i];
|
||||
const float current_perpendicular_distance =
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(
|
||||
const float current_perpendicular_distance = coordinate_calculation::
|
||||
perpendicular_distance_from_projected_coordinate(
|
||||
m_coordinate_list->at(current_edge.u),
|
||||
m_coordinate_list->at(current_edge.v),
|
||||
input_coordinate);
|
||||
m_coordinate_list->at(current_edge.v), input_coordinate,
|
||||
projected_coordinate);
|
||||
// distance must be non-negative
|
||||
BOOST_ASSERT(0. <= current_perpendicular_distance);
|
||||
BOOST_ASSERT(0.f <= current_perpendicular_distance);
|
||||
|
||||
if (current_perpendicular_distance < current_min_dist)
|
||||
if (pruning_bound.get() >= current_perpendicular_distance ||
|
||||
current_edge.is_in_tiny_cc())
|
||||
{
|
||||
pruning_bound.insert(current_perpendicular_distance);
|
||||
traversal_queue.emplace(current_perpendicular_distance, current_edge);
|
||||
}
|
||||
else
|
||||
{
|
||||
++pruned_elements;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// for each child mbr
|
||||
for (uint32_t i = 0; i < current_tree_node.child_count; ++i)
|
||||
// for each child mbr get a lower bound and enqueue it
|
||||
for (const auto i : osrm::irange(0u, current_tree_node.child_count))
|
||||
{
|
||||
const int32_t child_id = current_tree_node.children[i];
|
||||
const TreeNode &child_tree_node = m_search_tree[child_id];
|
||||
const RectangleT &child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
||||
const float lower_bound_to_element = child_rectangle.GetMinDist(input_coordinate);
|
||||
const RectangleT &child_rectangle =
|
||||
child_tree_node.minimum_bounding_rectangle;
|
||||
const float lower_bound_to_element =
|
||||
child_rectangle.GetMinDist(input_coordinate);
|
||||
BOOST_ASSERT(0.f <= lower_bound_to_element);
|
||||
|
||||
// TODO - enough elements found, i.e. nearest distance > maximum distance?
|
||||
// ie. some measure of 'confidence of accuracy'
|
||||
|
||||
// check if it needs to be explored by mindist
|
||||
if (lower_bound_to_element < current_min_dist)
|
||||
{
|
||||
traversal_queue.emplace(lower_bound_to_element, child_tree_node);
|
||||
}
|
||||
traversal_queue.emplace(lower_bound_to_element, child_tree_node);
|
||||
}
|
||||
// SimpleLogger().Write(logDEBUG) << "added " << current_tree_node.child_count << " mbrs into queue of " << traversal_queue.size();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++inspected_segments;
|
||||
{ // current object is a leaf node
|
||||
++inspected_elements;
|
||||
// inspecting an actual road segment
|
||||
const EdgeDataT & current_segment = current_query_node.node.template get<EdgeDataT>();
|
||||
const EdgeDataT ¤t_segment =
|
||||
current_query_node.node.template get<EdgeDataT>();
|
||||
|
||||
// don't collect too many results from small components
|
||||
if (number_of_results_found_in_big_cc == number_of_results && !current_segment.is_in_tiny_cc)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// don't collect too many results from big components
|
||||
if (number_of_results_found_in_tiny_cc == number_of_results && current_segment.is_in_tiny_cc)
|
||||
// continue searching for the first segment from a big component
|
||||
if (number_of_elements_from_big_cc == 0 &&
|
||||
number_of_elements_from_tiny_cc >= max_number_of_phantom_nodes - 1 &&
|
||||
current_segment.is_in_tiny_cc())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if it is smaller than what we had before
|
||||
float current_ratio = 0.;
|
||||
float current_ratio = 0.f;
|
||||
FixedPointCoordinate foot_point_coordinate_on_segment;
|
||||
|
||||
const float current_perpendicular_distance =
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(
|
||||
coordinate_calculation::perpendicular_distance_from_projected_coordinate(
|
||||
m_coordinate_list->at(current_segment.u),
|
||||
m_coordinate_list->at(current_segment.v),
|
||||
input_coordinate,
|
||||
foot_point_coordinate_on_segment,
|
||||
current_ratio);
|
||||
m_coordinate_list->at(current_segment.v), input_coordinate,
|
||||
projected_coordinate, foot_point_coordinate_on_segment, current_ratio);
|
||||
|
||||
BOOST_ASSERT(0. <= current_perpendicular_distance);
|
||||
|
||||
if ((current_perpendicular_distance < current_min_dist) &&
|
||||
!osrm::epsilon_compare(current_perpendicular_distance, current_min_dist))
|
||||
if (number_of_elements_from_big_cc > 0 &&
|
||||
result_phantom_node_vector.size() >= min_number_of_phantom_nodes &&
|
||||
current_perpendicular_distance >= max_distance)
|
||||
{
|
||||
// store phantom node in result vector
|
||||
result_phantom_node_vector.emplace_back(
|
||||
traversal_queue = std::priority_queue<IncrementalQueryCandidate>{};
|
||||
continue;
|
||||
}
|
||||
|
||||
// store phantom node in result vector
|
||||
result_phantom_node_vector.emplace_back(
|
||||
PhantomNode(
|
||||
current_segment.forward_edge_based_node_id,
|
||||
current_segment.reverse_edge_based_node_id,
|
||||
current_segment.name_id,
|
||||
current_segment.forward_weight,
|
||||
current_segment.reverse_weight,
|
||||
current_segment.forward_offset,
|
||||
current_segment.reverse_offset,
|
||||
current_segment.packed_geometry_id,
|
||||
foot_point_coordinate_on_segment,
|
||||
current_segment.fwd_segment_position,
|
||||
current_perpendicular_distance);
|
||||
current_segment.reverse_edge_based_node_id, current_segment.name_id,
|
||||
current_segment.forward_weight, current_segment.reverse_weight,
|
||||
current_segment.forward_offset, current_segment.reverse_offset,
|
||||
current_segment.packed_geometry_id, current_segment.component_id,
|
||||
foot_point_coordinate_on_segment, current_segment.fwd_segment_position,
|
||||
current_segment.forward_travel_mode, current_segment.backward_travel_mode),
|
||||
current_perpendicular_distance);
|
||||
|
||||
// Hack to fix rounding errors and wandering via nodes.
|
||||
FixUpRoundingIssue(input_coordinate, result_phantom_node_vector.back());
|
||||
// Hack to fix rounding errors and wandering via nodes.
|
||||
FixUpRoundingIssue(input_coordinate, result_phantom_node_vector.back().first);
|
||||
|
||||
// set forward and reverse weights on the phantom node
|
||||
SetForwardAndReverseWeightsOnPhantomNode(current_segment,
|
||||
result_phantom_node_vector.back());
|
||||
// set forward and reverse weights on the phantom node
|
||||
SetForwardAndReverseWeightsOnPhantomNode(current_segment,
|
||||
result_phantom_node_vector.back().first);
|
||||
|
||||
// do we have results only in a small scc
|
||||
if (current_segment.is_in_tiny_cc)
|
||||
{
|
||||
++number_of_results_found_in_tiny_cc;
|
||||
}
|
||||
else
|
||||
{
|
||||
// found an element in a large component
|
||||
min_found_distances[number_of_results_found_in_big_cc] = current_perpendicular_distance;
|
||||
++number_of_results_found_in_big_cc;
|
||||
// SimpleLogger().Write(logDEBUG) << std::setprecision(8) << foot_point_coordinate_on_segment << " at " << current_perpendicular_distance;
|
||||
}
|
||||
// update counts on what we found from which result class
|
||||
if (current_segment.is_in_tiny_cc())
|
||||
{ // found an element in tiny component
|
||||
++number_of_elements_from_tiny_cc;
|
||||
}
|
||||
else
|
||||
{ // found an element in a big component
|
||||
++number_of_elements_from_big_cc;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add indicator to prune if maxdist > threshold
|
||||
if (number_of_results == number_of_results_found_in_big_cc || inspected_segments >= max_checked_segments)
|
||||
// stop the search by flushing the queue
|
||||
if ((result_phantom_node_vector.size() >= max_number_of_phantom_nodes &&
|
||||
number_of_elements_from_big_cc > 0) ||
|
||||
inspected_elements >= max_checked_elements)
|
||||
{
|
||||
// SimpleLogger().Write(logDEBUG) << "flushing queue of " << traversal_queue.size() << " elements";
|
||||
// work-around for traversal_queue.clear();
|
||||
traversal_queue = std::priority_queue<IncrementalQueryCandidate>{};
|
||||
}
|
||||
}
|
||||
// SimpleLogger().Write() << "result_phantom_node_vector.size(): " <<
|
||||
// result_phantom_node_vector.size();
|
||||
// SimpleLogger().Write() << "max_number_of_phantom_nodes: " << max_number_of_phantom_nodes;
|
||||
// SimpleLogger().Write() << "number_of_elements_from_big_cc: " <<
|
||||
// number_of_elements_from_big_cc;
|
||||
// SimpleLogger().Write() << "number_of_elements_from_tiny_cc: " <<
|
||||
// number_of_elements_from_tiny_cc;
|
||||
// SimpleLogger().Write() << "inspected_elements: " << inspected_elements;
|
||||
// SimpleLogger().Write() << "max_checked_elements: " << max_checked_elements;
|
||||
// SimpleLogger().Write() << "pruned_elements: " << pruned_elements;
|
||||
|
||||
return !result_phantom_node_vector.empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
|
||||
PhantomNode &result_phantom_node,
|
||||
const unsigned zoom_level)
|
||||
@ -985,11 +1000,9 @@ class StaticRTree
|
||||
float current_ratio = 0.;
|
||||
FixedPointCoordinate nearest;
|
||||
const float current_perpendicular_distance =
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(
|
||||
coordinate_calculation::perpendicular_distance(
|
||||
m_coordinate_list->at(current_edge.u),
|
||||
m_coordinate_list->at(current_edge.v),
|
||||
input_coordinate,
|
||||
nearest,
|
||||
m_coordinate_list->at(current_edge.v), input_coordinate, nearest,
|
||||
current_ratio);
|
||||
|
||||
BOOST_ASSERT(0. <= current_perpendicular_distance);
|
||||
@ -1017,11 +1030,8 @@ class StaticRTree
|
||||
}
|
||||
else
|
||||
{
|
||||
min_max_dist = ExploreTreeNode(current_tree_node,
|
||||
input_coordinate,
|
||||
min_dist,
|
||||
min_max_dist,
|
||||
traversal_queue);
|
||||
min_max_dist = ExploreTreeNode(current_tree_node, input_coordinate, min_dist,
|
||||
min_max_dist, traversal_queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1038,45 +1048,46 @@ class StaticRTree
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
inline void SetForwardAndReverseWeightsOnPhantomNode(const EdgeDataT & nearest_edge,
|
||||
inline void SetForwardAndReverseWeightsOnPhantomNode(const EdgeDataT &nearest_edge,
|
||||
PhantomNode &result_phantom_node) const
|
||||
{
|
||||
const float distance_1 = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const float distance_1 = coordinate_calculation::euclidean_distance(
|
||||
m_coordinate_list->at(nearest_edge.u), result_phantom_node.location);
|
||||
const float distance_2 = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const float distance_2 = coordinate_calculation::euclidean_distance(
|
||||
m_coordinate_list->at(nearest_edge.u), m_coordinate_list->at(nearest_edge.v));
|
||||
const float ratio = std::min(1.f, distance_1 / distance_2);
|
||||
|
||||
using TreeWeightType = decltype(result_phantom_node.forward_weight);
|
||||
static_assert(std::is_same<decltype(result_phantom_node.forward_weight),
|
||||
decltype(result_phantom_node.reverse_weight)>::value,
|
||||
"forward and reverse weight type in tree must be the same");
|
||||
"forward and reverse weight type in tree must be the same");
|
||||
|
||||
if (SPECIAL_NODEID != result_phantom_node.forward_node_id)
|
||||
{
|
||||
const auto new_weight = static_cast<TreeWeightType>(result_phantom_node.forward_weight * ratio);
|
||||
const auto new_weight =
|
||||
static_cast<TreeWeightType>(result_phantom_node.forward_weight * ratio);
|
||||
result_phantom_node.forward_weight = new_weight;
|
||||
}
|
||||
if (SPECIAL_NODEID != result_phantom_node.reverse_node_id)
|
||||
{
|
||||
const auto new_weight = static_cast<TreeWeightType>(result_phantom_node.reverse_weight * (1.f-ratio));
|
||||
const auto new_weight =
|
||||
static_cast<TreeWeightType>(result_phantom_node.reverse_weight * (1.f - ratio));
|
||||
result_phantom_node.reverse_weight = new_weight;
|
||||
}
|
||||
}
|
||||
|
||||
// fixup locations if too close to inputs
|
||||
inline void FixUpRoundingIssue(const FixedPointCoordinate &input_coordinate,
|
||||
PhantomNode &result_phantom_node) const
|
||||
PhantomNode &result_phantom_node) const
|
||||
{
|
||||
if (1 == std::abs(input_coordinate.lon - result_phantom_node.location.lon))
|
||||
{
|
||||
result_phantom_node.location.lon = input_coordinate.lon;
|
||||
}
|
||||
if (1 == std::abs(input_coordinate.lat - result_phantom_node.location.lat))
|
||||
{
|
||||
result_phantom_node.location.lat = input_coordinate.lat;
|
||||
}
|
||||
if (1 == std::abs(input_coordinate.lon - result_phantom_node.location.lon))
|
||||
{
|
||||
result_phantom_node.location.lon = input_coordinate.lon;
|
||||
}
|
||||
if (1 == std::abs(input_coordinate.lat - result_phantom_node.location.lat))
|
||||
{
|
||||
result_phantom_node.location.lat = input_coordinate.lat;
|
||||
}
|
||||
}
|
||||
|
||||
template <class QueueT>
|
||||
@ -1122,8 +1133,7 @@ class StaticRTree
|
||||
}
|
||||
const uint64_t seek_pos = sizeof(uint64_t) + leaf_id * sizeof(LeafNode);
|
||||
leaves_stream.seekg(seek_pos);
|
||||
BOOST_ASSERT_MSG(leaves_stream.good(),
|
||||
"Seeking to position in leaf file failed.");
|
||||
BOOST_ASSERT_MSG(leaves_stream.good(), "Seeking to position in leaf file failed.");
|
||||
leaves_stream.read((char *)&result_node, sizeof(LeafNode));
|
||||
BOOST_ASSERT_MSG(leaves_stream.good(), "Reading from leaf file failed.");
|
||||
}
|
||||
@ -1136,26 +1146,26 @@ class StaticRTree
|
||||
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
|
||||
}
|
||||
|
||||
inline void InitializeMBRectangle(RectangleT& rectangle,
|
||||
inline void InitializeMBRectangle(RectangleT &rectangle,
|
||||
const std::array<EdgeDataT, LEAF_NODE_SIZE> &objects,
|
||||
const uint32_t element_count,
|
||||
const std::vector<QueryNode> &coordinate_list)
|
||||
{
|
||||
for (uint32_t i = 0; i < element_count; ++i)
|
||||
{
|
||||
rectangle.min_lon = std::min(rectangle.min_lon,
|
||||
std::min(coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon));
|
||||
rectangle.max_lon = std::max(rectangle.max_lon,
|
||||
std::max(coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon));
|
||||
rectangle.min_lon =
|
||||
std::min(rectangle.min_lon, std::min(coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon));
|
||||
rectangle.max_lon =
|
||||
std::max(rectangle.max_lon, std::max(coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon));
|
||||
|
||||
rectangle.min_lat = std::min(rectangle.min_lat,
|
||||
std::min(coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat));
|
||||
rectangle.max_lat = std::max(rectangle.max_lat,
|
||||
std::max(coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat));
|
||||
rectangle.min_lat =
|
||||
std::min(rectangle.min_lat, std::min(coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat));
|
||||
rectangle.max_lat =
|
||||
std::max(rectangle.max_lat, std::max(coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat));
|
||||
}
|
||||
BOOST_ASSERT(rectangle.min_lat != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(rectangle.min_lon != std::numeric_limits<int>::min());
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,7 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef TRAVEL_MODE_HPP
|
||||
#define TRAVEL_MODE_HPP
|
||||
|
||||
namespace {
|
||||
namespace
|
||||
{
|
||||
using TravelMode = unsigned char;
|
||||
static const TravelMode TRAVEL_MODE_INACCESSIBLE = 0;
|
||||
static const TravelMode TRAVEL_MODE_DEFAULT = 1;
|
||||
|
40
data_structures/tribool.hpp
Normal file
40
data_structures/tribool.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
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 TRIBOOL_HPP
|
||||
#define TRIBOOL_HPP
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
enum class tribool : char
|
||||
{
|
||||
yes,
|
||||
no,
|
||||
indeterminate
|
||||
};
|
||||
}
|
||||
#endif // TRIBOOL_HPP
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,10 +30,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
enum class TurnInstruction : unsigned char
|
||||
{
|
||||
NoTurn = 0, GoStraight, TurnSlightRight, TurnRight, TurnSharpRight, UTurn,
|
||||
TurnSharpLeft, TurnLeft, TurnSlightLeft, ReachViaLocation, HeadOn, EnterRoundAbout,
|
||||
LeaveRoundAbout, StayOnRoundAbout, StartAtEndOfStreet, ReachedYourDestination,
|
||||
EnterAgainstAllowedDirection, LeaveAgainstAllowedDirection,
|
||||
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
|
||||
@ -42,7 +56,7 @@ enum class TurnInstruction : unsigned char
|
||||
struct TurnInstructionsClass
|
||||
{
|
||||
TurnInstructionsClass() = delete;
|
||||
TurnInstructionsClass(const TurnInstructionsClass&) = delete;
|
||||
TurnInstructionsClass(const TurnInstructionsClass &) = delete;
|
||||
|
||||
static inline TurnInstruction GetTurnDirectionOfInstruction(const double angle)
|
||||
{
|
||||
@ -79,7 +93,8 @@ struct TurnInstructionsClass
|
||||
|
||||
static inline bool TurnIsNecessary(const TurnInstruction turn_instruction)
|
||||
{
|
||||
if (TurnInstruction::NoTurn == turn_instruction || TurnInstruction::StayOnRoundAbout == turn_instruction)
|
||||
if (TurnInstruction::NoTurn == turn_instruction ||
|
||||
TurnInstruction::StayOnRoundAbout == turn_instruction)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
77
data_structures/upper_bound.hpp
Normal file
77
data_structures/upper_bound.hpp
Normal file
@ -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
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -61,8 +61,8 @@ class XORFastHash
|
||||
table2.resize(2 << 16);
|
||||
for (unsigned i = 0; i < (2 << 16); ++i)
|
||||
{
|
||||
table1[i] = i;
|
||||
table2[i] = i;
|
||||
table1[i] = static_cast<unsigned short>(i);
|
||||
table2[i] = static_cast<unsigned short>(i);
|
||||
}
|
||||
std::random_shuffle(table1.begin(), table1.end());
|
||||
std::random_shuffle(table2.begin(), table2.end());
|
||||
@ -92,10 +92,10 @@ class XORMiniHash
|
||||
table4.resize(1 << 8);
|
||||
for (unsigned i = 0; i < (1 << 8); ++i)
|
||||
{
|
||||
table1[i] = i;
|
||||
table2[i] = i;
|
||||
table3[i] = i;
|
||||
table4[i] = i;
|
||||
table1[i] = static_cast<unsigned char>(i);
|
||||
table2[i] = static_cast<unsigned char>(i);
|
||||
table3[i] = static_cast<unsigned char>(i);
|
||||
table4[i] = static_cast<unsigned char>(i);
|
||||
}
|
||||
std::random_shuffle(table1.begin(), table1.end());
|
||||
std::random_shuffle(table2.begin(), table2.end());
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -38,22 +38,24 @@ template <typename NodeID, typename Key> class XORFastHashStorage
|
||||
public:
|
||||
struct HashCell
|
||||
{
|
||||
Key key;
|
||||
NodeID id;
|
||||
unsigned time;
|
||||
NodeID id;
|
||||
Key key;
|
||||
HashCell()
|
||||
: key(std::numeric_limits<unsigned>::max()), id(std::numeric_limits<unsigned>::max()),
|
||||
time(std::numeric_limits<unsigned>::max())
|
||||
: time(std::numeric_limits<unsigned>::max()), id(std::numeric_limits<unsigned>::max()),
|
||||
key(std::numeric_limits<unsigned>::max())
|
||||
{
|
||||
}
|
||||
|
||||
HashCell(const HashCell &other) : key(other.key), id(other.id), time(other.time) {}
|
||||
HashCell(const HashCell &other) : time(other.key), id(other.id), key(other.time) {}
|
||||
|
||||
operator Key() const { return key; }
|
||||
|
||||
void operator=(const Key &key_to_insert) { key = key_to_insert; }
|
||||
void operator=(const Key key_to_insert) { key = key_to_insert; }
|
||||
};
|
||||
|
||||
XORFastHashStorage() = delete;
|
||||
|
||||
explicit XORFastHashStorage(size_t) : positions(2 << 16), current_timestamp(0) {}
|
||||
|
||||
HashCell &operator[](const NodeID node)
|
||||
@ -64,23 +66,33 @@ template <typename NodeID, typename Key> class XORFastHashStorage
|
||||
++position %= (2 << 16);
|
||||
}
|
||||
|
||||
positions[position].id = node;
|
||||
positions[position].time = current_timestamp;
|
||||
positions[position].id = node;
|
||||
return positions[position];
|
||||
}
|
||||
|
||||
// peek into table, get key for node, think of it as a read-only operator[]
|
||||
Key peek_index(const NodeID node) const
|
||||
{
|
||||
unsigned short position = fast_hasher(node);
|
||||
while ((positions[position].time == current_timestamp) && (positions[position].id != node))
|
||||
{
|
||||
++position %= (2 << 16);
|
||||
}
|
||||
return positions[position].key;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
++current_timestamp;
|
||||
if (std::numeric_limits<unsigned>::max() == current_timestamp)
|
||||
{
|
||||
positions.clear();
|
||||
positions.resize((2 << 16));
|
||||
positions.resize(2 << 16);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
XORFastHashStorage() : positions(2 << 16), current_timestamp(0) {}
|
||||
std::vector<HashCell> positions;
|
||||
XORFastHash fast_hasher;
|
||||
unsigned current_timestamp;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,22 +28,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "data_structures/original_edge_data.hpp"
|
||||
#include "data_structures/range_table.hpp"
|
||||
#include "data_structures/query_edge.hpp"
|
||||
#include "data_structures/query_node.hpp"
|
||||
#include "data_structures/shared_memory_factory.hpp"
|
||||
#include "data_structures/shared_memory_vector_wrapper.hpp"
|
||||
#include "data_structures/static_graph.hpp"
|
||||
#include "data_structures/static_rtree.hpp"
|
||||
#include "data_structures/travel_mode.hpp"
|
||||
#include "data_structures/turn_instructions.hpp"
|
||||
#include "Server/DataStructures/BaseDataFacade.h"
|
||||
#include "Server/DataStructures/SharedDataType.h"
|
||||
#include "Server/DataStructures/SharedBarriers.h"
|
||||
#include "Util/BoostFileSystemFix.h"
|
||||
#include "Util/DataStoreOptions.h"
|
||||
#include "Util/simple_logger.hpp"
|
||||
#include "Util/osrm_exception.hpp"
|
||||
#include "Util/FingerPrint.h"
|
||||
#include "server/data_structures/datafacade_base.hpp"
|
||||
#include "server/data_structures/shared_datatype.hpp"
|
||||
#include "server/data_structures/shared_barriers.hpp"
|
||||
#include "util/boost_filesystem_2_fix.hpp"
|
||||
#include "util/datastore_options.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/osrm_exception.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
#include "typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
#include <osrm/server_paths.hpp>
|
||||
|
||||
using RTreeLeaf = BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf;
|
||||
using RTreeNode = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode;
|
||||
@ -103,7 +106,8 @@ int main(const int argc, const char *argv[])
|
||||
const bool lock_flags = MCL_CURRENT | MCL_FUTURE;
|
||||
if (-1 == mlockall(lock_flags))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Process " << argv[0] << " could not request RAM lock";
|
||||
SimpleLogger().Write(logWARNING) << "Process " << argv[0]
|
||||
<< " could not request RAM lock";
|
||||
}
|
||||
#endif
|
||||
try
|
||||
@ -340,8 +344,8 @@ int main(const int argc, const char *argv[])
|
||||
geometry_input_stream.read((char *)&number_of_geometries_indices, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_INDEX,
|
||||
number_of_geometries_indices);
|
||||
boost::iostreams::seek(
|
||||
geometry_input_stream, number_of_geometries_indices * sizeof(unsigned), BOOST_IOS::cur);
|
||||
boost::iostreams::seek(geometry_input_stream,
|
||||
number_of_geometries_indices * sizeof(unsigned), BOOST_IOS::cur);
|
||||
geometry_input_stream.read((char *)&number_of_compressed_geometries, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_LIST,
|
||||
number_of_compressed_geometries);
|
||||
@ -410,9 +414,8 @@ int main(const int argc, const char *argv[])
|
||||
unsigned *name_id_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::NAME_ID_LIST);
|
||||
|
||||
TravelMode *travel_mode_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<TravelMode, true>(
|
||||
shared_memory_ptr, SharedDataLayout::TRAVEL_MODE);
|
||||
TravelMode *travel_mode_ptr = shared_layout_ptr->GetBlockPtr<TravelMode, true>(
|
||||
shared_memory_ptr, SharedDataLayout::TRAVEL_MODE);
|
||||
|
||||
TurnInstruction *turn_instructions_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<TurnInstruction, true>(
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -27,12 +27,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "description_factory.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "../algorithms/polyline_formatter.hpp"
|
||||
#include "../data_structures/raw_route_data.hpp"
|
||||
#include "../data_structures/coordinate_calculation.hpp"
|
||||
#include "../data_structures/internal_route_result.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
#include "../util/container.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
DescriptionFactory::DescriptionFactory() : entire_length(0) { via_indices.push_back(0); }
|
||||
|
||||
@ -45,9 +46,8 @@ void DescriptionFactory::SetStartSegment(const PhantomNode &source, const bool t
|
||||
(traversed_in_reverse ? source.reverse_weight : source.forward_weight);
|
||||
const TravelMode travel_mode =
|
||||
(traversed_in_reverse ? source.backward_travel_mode : source.forward_travel_mode);
|
||||
AppendSegment(
|
||||
source.location,
|
||||
PathData(0, source.name_id, TurnInstruction::HeadOn, segment_duration, travel_mode));
|
||||
AppendSegment(source.location, PathData(0, source.name_id, TurnInstruction::HeadOn,
|
||||
segment_duration, travel_mode));
|
||||
BOOST_ASSERT(path_description.back().duration == segment_duration);
|
||||
}
|
||||
|
||||
@ -60,15 +60,10 @@ void DescriptionFactory::SetEndSegment(const PhantomNode &target,
|
||||
(traversed_in_reverse ? target.reverse_weight : target.forward_weight);
|
||||
const TravelMode travel_mode =
|
||||
(traversed_in_reverse ? target.backward_travel_mode : target.forward_travel_mode);
|
||||
path_description.emplace_back(target.location,
|
||||
target.name_id,
|
||||
segment_duration,
|
||||
0.f,
|
||||
path_description.emplace_back(target.location, target.name_id, segment_duration, 0.f,
|
||||
is_via_location ? TurnInstruction::ReachViaLocation
|
||||
: TurnInstruction::NoTurn,
|
||||
true,
|
||||
true,
|
||||
travel_mode);
|
||||
true, true, travel_mode);
|
||||
BOOST_ASSERT(path_description.back().duration == segment_duration);
|
||||
}
|
||||
|
||||
@ -99,15 +94,11 @@ void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
|
||||
return path_point.turn_instruction;
|
||||
}();
|
||||
|
||||
path_description.emplace_back(coordinate,
|
||||
path_point.name_id,
|
||||
path_point.segment_duration,
|
||||
0.f,
|
||||
turn,
|
||||
path_point.travel_mode);
|
||||
path_description.emplace_back(coordinate, path_point.name_id, path_point.segment_duration, 0.f,
|
||||
turn, path_point.travel_mode);
|
||||
}
|
||||
|
||||
JSON::Value DescriptionFactory::AppendGeometryString(const bool return_encoded)
|
||||
osrm::json::Value DescriptionFactory::AppendGeometryString(const bool return_encoded)
|
||||
{
|
||||
if (return_encoded)
|
||||
{
|
||||
@ -122,3 +113,132 @@ void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned
|
||||
summary.target_name_id = target_phantom.name_id;
|
||||
summary.BuildDurationAndLengthStrings(distance, time);
|
||||
}
|
||||
|
||||
void DescriptionFactory::Run(const unsigned zoom_level)
|
||||
{
|
||||
if (path_description.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/** starts at index 1 */
|
||||
path_description[0].length = 0.f;
|
||||
for (const auto i : osrm::irange<std::size_t>(1, path_description.size()))
|
||||
{
|
||||
// move down names by one, q&d hack
|
||||
path_description[i - 1].name_id = path_description[i].name_id;
|
||||
path_description[i].length = coordinate_calculation::euclidean_distance(
|
||||
path_description[i - 1].location, path_description[i].location);
|
||||
}
|
||||
|
||||
/*Simplify turn instructions
|
||||
Input :
|
||||
10. Turn left on B 36 for 20 km
|
||||
11. Continue on B 35; B 36 for 2 km
|
||||
12. Continue on B 36 for 13 km
|
||||
|
||||
becomes:
|
||||
10. Turn left on B 36 for 35 km
|
||||
*/
|
||||
// TODO: rework to check only end and start of string.
|
||||
// stl string is way to expensive
|
||||
|
||||
// unsigned lastTurn = 0;
|
||||
// for(unsigned i = 1; i < path_description.size(); ++i) {
|
||||
// string1 = sEngine.GetEscapedNameForNameID(path_description[i].name_id);
|
||||
// if(TurnInstruction::GoStraight == path_description[i].turn_instruction) {
|
||||
// if(std::string::npos != string0.find(string1+";")
|
||||
// || std::string::npos != string0.find(";"+string1)
|
||||
// || std::string::npos != string0.find(string1+" ;")
|
||||
// || std::string::npos != string0.find("; "+string1)
|
||||
// ){
|
||||
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " <<
|
||||
// string1;
|
||||
// for(; lastTurn != i; ++lastTurn)
|
||||
// path_description[lastTurn].name_id = path_description[i].name_id;
|
||||
// path_description[i].turn_instruction = TurnInstruction::NoTurn;
|
||||
// } else if(std::string::npos != string1.find(string0+";")
|
||||
// || std::string::npos != string1.find(";"+string0)
|
||||
// || std::string::npos != string1.find(string0+" ;")
|
||||
// || std::string::npos != string1.find("; "+string0)
|
||||
// ){
|
||||
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " <<
|
||||
// string0;
|
||||
// path_description[i].name_id = path_description[i-1].name_id;
|
||||
// path_description[i].turn_instruction = TurnInstruction::NoTurn;
|
||||
// }
|
||||
// }
|
||||
// if (TurnInstruction::NoTurn != path_description[i].turn_instruction) {
|
||||
// lastTurn = i;
|
||||
// }
|
||||
// string0 = string1;
|
||||
// }
|
||||
|
||||
float segment_length = 0.;
|
||||
EdgeWeight segment_duration = 0;
|
||||
std::size_t segment_start_index = 0;
|
||||
|
||||
for (const auto i : osrm::irange<std::size_t>(1, path_description.size()))
|
||||
{
|
||||
entire_length += path_description[i].length;
|
||||
segment_length += path_description[i].length;
|
||||
segment_duration += path_description[i].duration;
|
||||
path_description[segment_start_index].length = segment_length;
|
||||
path_description[segment_start_index].duration = segment_duration;
|
||||
|
||||
if (TurnInstruction::NoTurn != path_description[i].turn_instruction)
|
||||
{
|
||||
BOOST_ASSERT(path_description[i].necessary);
|
||||
segment_length = 0;
|
||||
segment_duration = 0;
|
||||
segment_start_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Post-processing to remove empty or nearly empty path segments
|
||||
if (path_description.size() > 2 &&
|
||||
std::numeric_limits<float>::epsilon() > path_description.back().length)
|
||||
{
|
||||
path_description.pop_back();
|
||||
path_description.back().necessary = true;
|
||||
path_description.back().turn_instruction = TurnInstruction::NoTurn;
|
||||
target_phantom.name_id = (path_description.end() - 2)->name_id;
|
||||
}
|
||||
|
||||
if (path_description.size() > 2 &&
|
||||
std::numeric_limits<float>::epsilon() > path_description.front().length)
|
||||
{
|
||||
path_description.erase(path_description.begin());
|
||||
path_description.front().turn_instruction = TurnInstruction::HeadOn;
|
||||
path_description.front().necessary = true;
|
||||
start_phantom.name_id = path_description.front().name_id;
|
||||
}
|
||||
|
||||
// Generalize poly line
|
||||
polyline_generalizer.Run(path_description.begin(), path_description.end(), zoom_level);
|
||||
|
||||
// fix what needs to be fixed else
|
||||
unsigned necessary_segments = 0; // a running index that counts the necessary pieces
|
||||
osrm::for_each_pair(
|
||||
path_description, [&](SegmentInformation &first, const SegmentInformation &second)
|
||||
{
|
||||
if (!first.necessary)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
++necessary_segments;
|
||||
|
||||
if (first.is_via_location)
|
||||
{ // mark the end of a leg (of several segments)
|
||||
via_indices.push_back(necessary_segments);
|
||||
}
|
||||
|
||||
const double angle = coordinate_calculation::bearing(first.location, second.location);
|
||||
first.bearing = static_cast<short>(angle * 10);
|
||||
});
|
||||
|
||||
via_indices.push_back(necessary_segments + 1);
|
||||
BOOST_ASSERT(via_indices.size() >= 2);
|
||||
return;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,14 +30,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../algorithms/douglas_peucker.hpp"
|
||||
#include "../data_structures/phantom_node.hpp"
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@ -73,7 +72,7 @@ class DescriptionFactory
|
||||
{
|
||||
// compute distance/duration for route summary
|
||||
distance = static_cast<unsigned>(std::round(raw_distance));
|
||||
duration = static_cast<unsigned>(std::round(raw_duration / 10.));
|
||||
duration = static_cast<EdgeWeight>(std::round(raw_duration / 10.));
|
||||
}
|
||||
} summary;
|
||||
|
||||
@ -86,141 +85,12 @@ class DescriptionFactory
|
||||
void SetEndSegment(const PhantomNode &start_phantom,
|
||||
const bool traversed_in_reverse,
|
||||
const bool is_via_location = false);
|
||||
JSON::Value AppendGeometryString(const bool return_encoded);
|
||||
osrm::json::Value AppendGeometryString(const bool return_encoded);
|
||||
std::vector<unsigned> const &GetViaIndices() const;
|
||||
|
||||
double get_entire_length() const
|
||||
{
|
||||
return entire_length;
|
||||
}
|
||||
double get_entire_length() const { return entire_length; }
|
||||
|
||||
template <class DataFacadeT> void Run(const DataFacadeT *facade, const unsigned zoomLevel)
|
||||
{
|
||||
if (path_description.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/** starts at index 1 */
|
||||
path_description[0].length = 0;
|
||||
for (unsigned i = 1; i < path_description.size(); ++i)
|
||||
{
|
||||
// move down names by one, q&d hack
|
||||
path_description[i - 1].name_id = path_description[i].name_id;
|
||||
path_description[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
path_description[i - 1].location, path_description[i].location);
|
||||
}
|
||||
|
||||
/*Simplify turn instructions
|
||||
Input :
|
||||
10. Turn left on B 36 for 20 km
|
||||
11. Continue on B 35; B 36 for 2 km
|
||||
12. Continue on B 36 for 13 km
|
||||
|
||||
becomes:
|
||||
10. Turn left on B 36 for 35 km
|
||||
*/
|
||||
// TODO: rework to check only end and start of string.
|
||||
// stl string is way to expensive
|
||||
|
||||
// unsigned lastTurn = 0;
|
||||
// for(unsigned i = 1; i < path_description.size(); ++i) {
|
||||
// string1 = sEngine.GetEscapedNameForNameID(path_description[i].name_id);
|
||||
// if(TurnInstruction::GoStraight == path_description[i].turn_instruction) {
|
||||
// if(std::string::npos != string0.find(string1+";")
|
||||
// || std::string::npos != string0.find(";"+string1)
|
||||
// || std::string::npos != string0.find(string1+" ;")
|
||||
// || std::string::npos != string0.find("; "+string1)
|
||||
// ){
|
||||
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " <<
|
||||
// string1;
|
||||
// for(; lastTurn != i; ++lastTurn)
|
||||
// path_description[lastTurn].name_id = path_description[i].name_id;
|
||||
// path_description[i].turn_instruction = TurnInstruction::NoTurn;
|
||||
// } else if(std::string::npos != string1.find(string0+";")
|
||||
// || std::string::npos != string1.find(";"+string0)
|
||||
// || std::string::npos != string1.find(string0+" ;")
|
||||
// || std::string::npos != string1.find("; "+string0)
|
||||
// ){
|
||||
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " <<
|
||||
// string0;
|
||||
// path_description[i].name_id = path_description[i-1].name_id;
|
||||
// path_description[i].turn_instruction = TurnInstruction::NoTurn;
|
||||
// }
|
||||
// }
|
||||
// if (TurnInstruction::NoTurn != path_description[i].turn_instruction) {
|
||||
// lastTurn = i;
|
||||
// }
|
||||
// string0 = string1;
|
||||
// }
|
||||
|
||||
float segment_length = 0.;
|
||||
unsigned segment_duration = 0;
|
||||
unsigned segment_start_index = 0;
|
||||
|
||||
for (unsigned i = 1; i < path_description.size(); ++i)
|
||||
{
|
||||
entire_length += path_description[i].length;
|
||||
segment_length += path_description[i].length;
|
||||
segment_duration += path_description[i].duration;
|
||||
path_description[segment_start_index].length = segment_length;
|
||||
path_description[segment_start_index].duration = segment_duration;
|
||||
|
||||
if (TurnInstruction::NoTurn != path_description[i].turn_instruction)
|
||||
{
|
||||
BOOST_ASSERT(path_description[i].necessary);
|
||||
segment_length = 0;
|
||||
segment_duration = 0;
|
||||
segment_start_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Post-processing to remove empty or nearly empty path segments
|
||||
if (std::numeric_limits<double>::epsilon() > path_description.back().length)
|
||||
{
|
||||
if (path_description.size() > 2)
|
||||
{
|
||||
path_description.pop_back();
|
||||
path_description.back().necessary = true;
|
||||
path_description.back().turn_instruction = TurnInstruction::NoTurn;
|
||||
target_phantom.name_id = (path_description.end() - 2)->name_id;
|
||||
}
|
||||
}
|
||||
if (std::numeric_limits<double>::epsilon() > path_description.front().length)
|
||||
{
|
||||
if (path_description.size() > 2)
|
||||
{
|
||||
path_description.erase(path_description.begin());
|
||||
path_description.front().turn_instruction = TurnInstruction::HeadOn;
|
||||
path_description.front().necessary = true;
|
||||
start_phantom.name_id = path_description.front().name_id;
|
||||
}
|
||||
}
|
||||
|
||||
// Generalize poly line
|
||||
polyline_generalizer.Run(path_description.begin(), path_description.end(), zoomLevel);
|
||||
|
||||
// fix what needs to be fixed else
|
||||
unsigned necessary_pieces = 0; // a running index that counts the necessary pieces
|
||||
for (unsigned i = 0; i < path_description.size() - 1 && path_description.size() >= 2; ++i)
|
||||
{
|
||||
if (path_description[i].necessary)
|
||||
{
|
||||
++necessary_pieces;
|
||||
if (path_description[i].is_via_location)
|
||||
{ // mark the end of a leg
|
||||
via_indices.push_back(necessary_pieces);
|
||||
}
|
||||
const double angle =
|
||||
path_description[i + 1].location.GetBearing(path_description[i].location);
|
||||
path_description[i].bearing = static_cast<unsigned>(angle * 10);
|
||||
}
|
||||
}
|
||||
via_indices.push_back(necessary_pieces + 1);
|
||||
BOOST_ASSERT(via_indices.size() >= 2);
|
||||
// BOOST_ASSERT(0 != necessary_pieces || path_description.empty());
|
||||
return;
|
||||
}
|
||||
void Run(const unsigned zoom_level);
|
||||
};
|
||||
|
||||
#endif /* DESCRIPTION_FACTORY_HPP */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,17 +28,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef DESCRIPTOR_BASE_HPP
|
||||
#define DESCRIPTOR_BASE_HPP
|
||||
|
||||
#include "../data_structures/coordinate_calculation.hpp"
|
||||
#include "../data_structures/internal_route_result.hpp"
|
||||
#include "../data_structures/phantom_node.hpp"
|
||||
#include "../data_structures/raw_route_data.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
|
||||
struct DescriptorTable : public std::unordered_map<std::string, unsigned>
|
||||
{
|
||||
unsigned get_id(const std::string &key)
|
||||
@ -52,18 +54,16 @@ struct DescriptorTable : public std::unordered_map<std::string, unsigned>
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct DescriptorConfig
|
||||
{
|
||||
DescriptorConfig() : instructions(true), geometry(true), encode_geometry(true), zoom_level(18)
|
||||
{
|
||||
}
|
||||
|
||||
template<class OtherT>
|
||||
DescriptorConfig(const OtherT &other) : instructions(other.print_instructions),
|
||||
geometry(other.geometry),
|
||||
encode_geometry(other.compression),
|
||||
zoom_level(other.zoom_level)
|
||||
template <class OtherT>
|
||||
DescriptorConfig(const OtherT &other)
|
||||
: instructions(other.print_instructions), geometry(other.geometry),
|
||||
encode_geometry(other.compression), zoom_level(other.zoom_level)
|
||||
{
|
||||
BOOST_ASSERT(zoom_level >= 0);
|
||||
}
|
||||
@ -80,8 +80,8 @@ template <class DataFacadeT> class BaseDescriptor
|
||||
BaseDescriptor() {}
|
||||
// Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||
virtual ~BaseDescriptor() {}
|
||||
virtual void Run(const RawRouteData &raw_route, http::Reply &reply) = 0;
|
||||
virtual void SetConfig(const DescriptorConfig &config) = 0;
|
||||
virtual void Run(const InternalRouteResult &raw_route, osrm::json::Object &json_result) = 0;
|
||||
virtual void SetConfig(const DescriptorConfig &c) = 0;
|
||||
};
|
||||
|
||||
#endif // DESCRIPTOR_BASE_HPP
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -29,8 +29,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define GPX_DESCRIPTOR_HPP
|
||||
|
||||
#include "descriptor_base.hpp"
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "../Util/xml_renderer.hpp"
|
||||
#include "../util/xml_renderer.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -40,39 +41,39 @@ template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<D
|
||||
DescriptorConfig config;
|
||||
DataFacadeT *facade;
|
||||
|
||||
void AddRoutePoint(const FixedPointCoordinate &coordinate, JSON::Array &json_result)
|
||||
void AddRoutePoint(const FixedPointCoordinate &coordinate, osrm::json::Array &json_route)
|
||||
{
|
||||
JSON::Object json_lat;
|
||||
JSON::Object json_lon;
|
||||
JSON::Array json_row;
|
||||
osrm::json::Object json_lat;
|
||||
osrm::json::Object json_lon;
|
||||
osrm::json::Array json_row;
|
||||
|
||||
std::string tmp;
|
||||
|
||||
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
|
||||
coordinate_calculation::lat_or_lon_to_string(coordinate.lat, tmp);
|
||||
json_lat.values["_lat"] = tmp;
|
||||
|
||||
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
|
||||
coordinate_calculation::lat_or_lon_to_string(coordinate.lon, tmp);
|
||||
json_lon.values["_lon"] = tmp;
|
||||
|
||||
json_row.values.push_back(json_lat);
|
||||
json_row.values.push_back(json_lon);
|
||||
JSON::Object entry;
|
||||
osrm::json::Object entry;
|
||||
entry.values["rtept"] = json_row;
|
||||
json_result.values.push_back(entry);
|
||||
json_route.values.push_back(entry);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit GPXDescriptor(DataFacadeT *facade) : facade(facade) {}
|
||||
|
||||
void SetConfig(const DescriptorConfig &c) final { config = c; }
|
||||
virtual void SetConfig(const DescriptorConfig &c) final { config = c; }
|
||||
|
||||
void Run(const RawRouteData &raw_route, http::Reply &reply) final
|
||||
virtual void Run(const InternalRouteResult &raw_route, osrm::json::Object &json_result) final
|
||||
{
|
||||
JSON::Array json_result;
|
||||
osrm::json::Array json_route;
|
||||
if (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
AddRoutePoint(raw_route.segment_end_coordinates.front().source_phantom.location,
|
||||
json_result);
|
||||
json_route);
|
||||
|
||||
for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
|
||||
{
|
||||
@ -80,13 +81,14 @@ template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<D
|
||||
{
|
||||
const FixedPointCoordinate current_coordinate =
|
||||
facade->GetCoordinateOfNode(path_data.node);
|
||||
AddRoutePoint(current_coordinate, json_result);
|
||||
AddRoutePoint(current_coordinate, json_route);
|
||||
}
|
||||
}
|
||||
AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location,
|
||||
json_result);
|
||||
json_route);
|
||||
}
|
||||
JSON::gpx_render(reply.content, json_result);
|
||||
// osrm::json::gpx_render(reply.content, json_route);
|
||||
json_result.values["route"] = json_route;
|
||||
}
|
||||
};
|
||||
#endif // GPX_DESCRIPTOR_HPP
|
||||
|
@ -1,393 +1,392 @@
|
||||
/*
|
||||
|
||||
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 JSON_DESCRIPTOR_HPP
|
||||
#define JSON_DESCRIPTOR_HPP
|
||||
|
||||
#include "descriptor_base.hpp"
|
||||
#include "description_factory.hpp"
|
||||
#include "../algorithms/object_encoder.hpp"
|
||||
#include "../algorithms/route_name_extraction.hpp"
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
#include "../Util/bearing.hpp"
|
||||
#include "../Util/integer_range.hpp"
|
||||
#include "../Util/json_renderer.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/string_util.hpp"
|
||||
#include "../Util/timing_util.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<DataFacadeT>
|
||||
{
|
||||
private:
|
||||
DataFacadeT *facade;
|
||||
DescriptorConfig config;
|
||||
DescriptionFactory description_factory, alternate_description_factory;
|
||||
FixedPointCoordinate current;
|
||||
unsigned entered_restricted_area_count;
|
||||
struct RoundAbout
|
||||
{
|
||||
RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {}
|
||||
int start_index;
|
||||
unsigned name_id;
|
||||
int leave_at_exit;
|
||||
} round_about;
|
||||
|
||||
struct Segment
|
||||
{
|
||||
Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {}
|
||||
Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {}
|
||||
unsigned name_id;
|
||||
int length;
|
||||
unsigned position;
|
||||
};
|
||||
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||
ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
|
||||
|
||||
public:
|
||||
explicit JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0) {}
|
||||
|
||||
void SetConfig(const DescriptorConfig &c) final { config = c; }
|
||||
|
||||
unsigned DescribeLeg(const std::vector<PathData> route_leg,
|
||||
const PhantomNodes &leg_phantoms,
|
||||
const bool target_traversed_in_reverse,
|
||||
const bool is_via_leg)
|
||||
{
|
||||
unsigned added_element_count = 0;
|
||||
// Get all the coordinates for the computed route
|
||||
FixedPointCoordinate current_coordinate;
|
||||
for (const PathData &path_data : route_leg)
|
||||
{
|
||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||
description_factory.AppendSegment(current_coordinate, path_data);
|
||||
++added_element_count;
|
||||
}
|
||||
description_factory.SetEndSegment(
|
||||
leg_phantoms.target_phantom, target_traversed_in_reverse, is_via_leg);
|
||||
++added_element_count;
|
||||
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
|
||||
return added_element_count;
|
||||
}
|
||||
|
||||
void Run(const RawRouteData &raw_route, http::Reply &reply) final
|
||||
{
|
||||
JSON::Object json_result;
|
||||
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||
{
|
||||
// We do not need to do much, if there is no route ;-)
|
||||
json_result.values["status"] = 207;
|
||||
json_result.values["status_message"] = "Cannot find route between points";
|
||||
JSON::render(reply.content, json_result);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if first segment is non-zero
|
||||
std::string road_name = facade->GetEscapedNameForNameID(
|
||||
raw_route.segment_end_coordinates.front().source_phantom.name_id);
|
||||
|
||||
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
|
||||
raw_route.segment_end_coordinates.size());
|
||||
|
||||
description_factory.SetStartSegment(
|
||||
raw_route.segment_end_coordinates.front().source_phantom,
|
||||
raw_route.source_traversed_in_reverse.front());
|
||||
json_result.values["status"] = 0;
|
||||
json_result.values["status_message"] = "Found route between points";
|
||||
|
||||
// for each unpacked segment add the leg to the description
|
||||
for (const auto i : osrm::irange<std::size_t>(0, raw_route.unpacked_path_segments.size()))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
const int added_segments =
|
||||
#endif
|
||||
DescribeLeg(raw_route.unpacked_path_segments[i],
|
||||
raw_route.segment_end_coordinates[i],
|
||||
raw_route.target_traversed_in_reverse[i],
|
||||
raw_route.is_via_leg(i));
|
||||
BOOST_ASSERT(0 < added_segments);
|
||||
}
|
||||
description_factory.Run(facade, config.zoom_level);
|
||||
|
||||
if (config.geometry)
|
||||
{
|
||||
JSON::Value route_geometry =
|
||||
description_factory.AppendGeometryString(config.encode_geometry);
|
||||
json_result.values["route_geometry"] = route_geometry;
|
||||
}
|
||||
if (config.instructions)
|
||||
{
|
||||
JSON::Array json_route_instructions;
|
||||
BuildTextualDescription(description_factory,
|
||||
json_route_instructions,
|
||||
raw_route.shortest_path_length,
|
||||
shortest_path_segments);
|
||||
json_result.values["route_instructions"] = json_route_instructions;
|
||||
}
|
||||
description_factory.BuildRouteSummary(description_factory.get_entire_length(),
|
||||
raw_route.shortest_path_length);
|
||||
JSON::Object json_route_summary;
|
||||
json_route_summary.values["total_distance"] = description_factory.summary.distance;
|
||||
json_route_summary.values["total_time"] = description_factory.summary.duration;
|
||||
json_route_summary.values["start_point"] =
|
||||
facade->GetEscapedNameForNameID(description_factory.summary.source_name_id);
|
||||
json_route_summary.values["end_point"] =
|
||||
facade->GetEscapedNameForNameID(description_factory.summary.target_name_id);
|
||||
json_result.values["route_summary"] = json_route_summary;
|
||||
|
||||
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
|
||||
|
||||
JSON::Array json_via_points_array;
|
||||
JSON::Array json_first_coordinate;
|
||||
json_first_coordinate.values.push_back(
|
||||
raw_route.segment_end_coordinates.front().source_phantom.location.lat /
|
||||
COORDINATE_PRECISION);
|
||||
json_first_coordinate.values.push_back(
|
||||
raw_route.segment_end_coordinates.front().source_phantom.location.lon /
|
||||
COORDINATE_PRECISION);
|
||||
json_via_points_array.values.push_back(json_first_coordinate);
|
||||
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
|
||||
{
|
||||
std::string tmp;
|
||||
JSON::Array json_coordinate;
|
||||
json_coordinate.values.push_back(nodes.target_phantom.location.lat /
|
||||
COORDINATE_PRECISION);
|
||||
json_coordinate.values.push_back(nodes.target_phantom.location.lon /
|
||||
COORDINATE_PRECISION);
|
||||
json_via_points_array.values.push_back(json_coordinate);
|
||||
}
|
||||
json_result.values["via_points"] = json_via_points_array;
|
||||
|
||||
JSON::Array json_via_indices_array;
|
||||
|
||||
std::vector<unsigned> const &shortest_leg_end_indices = description_factory.GetViaIndices();
|
||||
json_via_indices_array.values.insert(json_via_indices_array.values.end(),
|
||||
shortest_leg_end_indices.begin(),
|
||||
shortest_leg_end_indices.end());
|
||||
json_result.values["via_indices"] = json_via_indices_array;
|
||||
|
||||
// only one alternative route is computed at this time, so this is hardcoded
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
json_result.values["found_alternative"] = JSON::True();
|
||||
BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty());
|
||||
alternate_description_factory.SetStartSegment(
|
||||
raw_route.segment_end_coordinates.front().source_phantom,
|
||||
raw_route.alt_source_traversed_in_reverse.front());
|
||||
// Get all the coordinates for the computed route
|
||||
for (const PathData &path_data : raw_route.unpacked_alternative)
|
||||
{
|
||||
current = facade->GetCoordinateOfNode(path_data.node);
|
||||
alternate_description_factory.AppendSegment(current, path_data);
|
||||
}
|
||||
alternate_description_factory.SetEndSegment(
|
||||
raw_route.segment_end_coordinates.back().target_phantom,
|
||||
raw_route.alt_source_traversed_in_reverse.back());
|
||||
alternate_description_factory.Run(facade, config.zoom_level);
|
||||
|
||||
if (config.geometry)
|
||||
{
|
||||
JSON::Value alternate_geometry_string =
|
||||
alternate_description_factory.AppendGeometryString(config.encode_geometry);
|
||||
JSON::Array json_alternate_geometries_array;
|
||||
json_alternate_geometries_array.values.push_back(alternate_geometry_string);
|
||||
json_result.values["alternative_geometries"] = json_alternate_geometries_array;
|
||||
}
|
||||
// Generate instructions for each alternative (simulated here)
|
||||
JSON::Array json_alt_instructions;
|
||||
JSON::Array json_current_alt_instructions;
|
||||
if (config.instructions)
|
||||
{
|
||||
BuildTextualDescription(alternate_description_factory,
|
||||
json_current_alt_instructions,
|
||||
raw_route.alternative_path_length,
|
||||
alternative_path_segments);
|
||||
json_alt_instructions.values.push_back(json_current_alt_instructions);
|
||||
json_result.values["alternative_instructions"] = json_alt_instructions;
|
||||
}
|
||||
alternate_description_factory.BuildRouteSummary(
|
||||
alternate_description_factory.get_entire_length(), raw_route.alternative_path_length);
|
||||
|
||||
JSON::Object json_alternate_route_summary;
|
||||
JSON::Array json_alternate_route_summary_array;
|
||||
json_alternate_route_summary.values["total_distance"] =
|
||||
alternate_description_factory.summary.distance;
|
||||
json_alternate_route_summary.values["total_time"] =
|
||||
alternate_description_factory.summary.duration;
|
||||
json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(
|
||||
alternate_description_factory.summary.source_name_id);
|
||||
json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(
|
||||
alternate_description_factory.summary.target_name_id);
|
||||
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
|
||||
json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
|
||||
|
||||
std::vector<unsigned> const &alternate_leg_end_indices =
|
||||
alternate_description_factory.GetViaIndices();
|
||||
JSON::Array json_altenative_indices_array;
|
||||
json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(),
|
||||
alternate_leg_end_indices.begin(),
|
||||
alternate_leg_end_indices.end());
|
||||
json_result.values["alternative_indices"] = json_altenative_indices_array;
|
||||
}
|
||||
else
|
||||
{
|
||||
json_result.values["found_alternative"] = JSON::False();
|
||||
}
|
||||
|
||||
// Get Names for both routes
|
||||
RouteNames route_names =
|
||||
GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
|
||||
JSON::Array json_route_names;
|
||||
json_route_names.values.push_back(route_names.shortest_path_name_1);
|
||||
json_route_names.values.push_back(route_names.shortest_path_name_2);
|
||||
json_result.values["route_name"] = json_route_names;
|
||||
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
JSON::Array json_alternate_names_array;
|
||||
JSON::Array json_alternate_names;
|
||||
json_alternate_names.values.push_back(route_names.alternative_path_name_1);
|
||||
json_alternate_names.values.push_back(route_names.alternative_path_name_2);
|
||||
json_alternate_names_array.values.push_back(json_alternate_names);
|
||||
json_result.values["alternative_names"] = json_alternate_names_array;
|
||||
}
|
||||
|
||||
JSON::Object json_hint_object;
|
||||
json_hint_object.values["checksum"] = facade->GetCheckSum();
|
||||
JSON::Array json_location_hint_array;
|
||||
std::string hint;
|
||||
for (const auto i : osrm::irange<std::size_t>(0, raw_route.segment_end_coordinates.size()))
|
||||
{
|
||||
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
|
||||
json_location_hint_array.values.push_back(hint);
|
||||
}
|
||||
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
|
||||
json_location_hint_array.values.push_back(hint);
|
||||
json_hint_object.values["locations"] = json_location_hint_array;
|
||||
json_result.values["hint_data"] = json_hint_object;
|
||||
|
||||
// render the content to the output array
|
||||
TIMER_START(route_render);
|
||||
JSON::render(reply.content, json_result);
|
||||
TIMER_STOP(route_render);
|
||||
SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
|
||||
}
|
||||
|
||||
// TODO: reorder parameters
|
||||
inline void BuildTextualDescription(DescriptionFactory &description_factory,
|
||||
JSON::Array &json_instruction_array,
|
||||
const int route_length,
|
||||
std::vector<Segment> &route_segments_list)
|
||||
{
|
||||
// Segment information has following format:
|
||||
//["instruction id","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||
unsigned necessary_segments_running_index = 0;
|
||||
round_about.leave_at_exit = 0;
|
||||
round_about.name_id = 0;
|
||||
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
||||
|
||||
// Fetch data from Factory and generate a string from it.
|
||||
for (const SegmentInformation &segment : description_factory.path_description)
|
||||
{
|
||||
JSON::Array json_instruction_row;
|
||||
TurnInstruction current_instruction = segment.turn_instruction;
|
||||
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
|
||||
{
|
||||
if (TurnInstruction::EnterRoundAbout == current_instruction)
|
||||
{
|
||||
round_about.name_id = segment.name_id;
|
||||
round_about.start_index = necessary_segments_running_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string current_turn_instruction;
|
||||
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
||||
{
|
||||
temp_instruction =
|
||||
cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::EnterRoundAbout));
|
||||
current_turn_instruction += temp_instruction;
|
||||
current_turn_instruction += "-";
|
||||
temp_instruction = cast::integral_to_string(round_about.leave_at_exit + 1);
|
||||
current_turn_instruction += temp_instruction;
|
||||
round_about.leave_at_exit = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_instruction = cast::integral_to_string(cast::enum_to_underlying(current_instruction));
|
||||
current_turn_instruction += temp_instruction;
|
||||
}
|
||||
json_instruction_row.values.push_back(current_turn_instruction);
|
||||
|
||||
json_instruction_row.values.push_back(
|
||||
facade->GetEscapedNameForNameID(segment.name_id));
|
||||
json_instruction_row.values.push_back(std::round(segment.length));
|
||||
json_instruction_row.values.push_back(necessary_segments_running_index);
|
||||
json_instruction_row.values.push_back(round(segment.duration / 10));
|
||||
json_instruction_row.values.push_back(
|
||||
cast::integral_to_string(static_cast<unsigned>(segment.length)) + "m");
|
||||
const double bearing_value = (segment.bearing / 10.);
|
||||
json_instruction_row.values.push_back(Bearing::Get(bearing_value));
|
||||
json_instruction_row.values.push_back(
|
||||
static_cast<unsigned>(round(bearing_value)));
|
||||
json_instruction_row.values.push_back(segment.travel_mode);
|
||||
|
||||
route_segments_list.emplace_back(
|
||||
segment.name_id,
|
||||
static_cast<int>(segment.length),
|
||||
static_cast<unsigned>(route_segments_list.size()));
|
||||
json_instruction_array.values.push_back(json_instruction_row);
|
||||
}
|
||||
}
|
||||
else if (TurnInstruction::StayOnRoundAbout == current_instruction)
|
||||
{
|
||||
++round_about.leave_at_exit;
|
||||
}
|
||||
if (segment.necessary)
|
||||
{
|
||||
++necessary_segments_running_index;
|
||||
}
|
||||
}
|
||||
|
||||
JSON::Array json_last_instruction_row;
|
||||
temp_instruction = cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::ReachedYourDestination));
|
||||
json_last_instruction_row.values.push_back(temp_instruction);
|
||||
json_last_instruction_row.values.push_back("");
|
||||
json_last_instruction_row.values.push_back(0);
|
||||
json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
|
||||
json_last_instruction_row.values.push_back(0);
|
||||
json_last_instruction_row.values.push_back("0m");
|
||||
json_last_instruction_row.values.push_back(Bearing::Get(0.0));
|
||||
json_last_instruction_row.values.push_back(0.);
|
||||
json_instruction_array.values.push_back(json_last_instruction_row);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* JSON_DESCRIPTOR_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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef JSON_DESCRIPTOR_HPP
|
||||
#define JSON_DESCRIPTOR_HPP
|
||||
|
||||
#include "descriptor_base.hpp"
|
||||
#include "description_factory.hpp"
|
||||
#include "../algorithms/object_encoder.hpp"
|
||||
#include "../algorithms/route_name_extraction.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
#include "../util/bearing.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../util/json_renderer.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/string_util.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<DataFacadeT>
|
||||
{
|
||||
private:
|
||||
DataFacadeT *facade;
|
||||
DescriptorConfig config;
|
||||
DescriptionFactory description_factory, alternate_description_factory;
|
||||
FixedPointCoordinate current;
|
||||
unsigned entered_restricted_area_count;
|
||||
struct RoundAbout
|
||||
{
|
||||
RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {}
|
||||
int start_index;
|
||||
unsigned name_id;
|
||||
int leave_at_exit;
|
||||
} round_about;
|
||||
|
||||
struct Segment
|
||||
{
|
||||
Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {}
|
||||
Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {}
|
||||
unsigned name_id;
|
||||
int length;
|
||||
unsigned position;
|
||||
};
|
||||
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||
ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
|
||||
|
||||
public:
|
||||
explicit JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void SetConfig(const DescriptorConfig &c) override final { config = c; }
|
||||
|
||||
unsigned DescribeLeg(const std::vector<PathData> &route_leg,
|
||||
const PhantomNodes &leg_phantoms,
|
||||
const bool target_traversed_in_reverse,
|
||||
const bool is_via_leg)
|
||||
{
|
||||
unsigned added_element_count = 0;
|
||||
// Get all the coordinates for the computed route
|
||||
FixedPointCoordinate current_coordinate;
|
||||
for (const PathData &path_data : route_leg)
|
||||
{
|
||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||
description_factory.AppendSegment(current_coordinate, path_data);
|
||||
++added_element_count;
|
||||
}
|
||||
description_factory.SetEndSegment(leg_phantoms.target_phantom, target_traversed_in_reverse,
|
||||
is_via_leg);
|
||||
++added_element_count;
|
||||
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
|
||||
return added_element_count;
|
||||
}
|
||||
|
||||
virtual void Run(const InternalRouteResult &raw_route,
|
||||
osrm::json::Object &json_result) override final
|
||||
{
|
||||
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||
{
|
||||
// We do not need to do much, if there is no route ;-)
|
||||
json_result.values["status"] = 207;
|
||||
json_result.values["status_message"] = "Cannot find route between points";
|
||||
// osrm::json::render(reply.content, json_result);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if first segment is non-zero
|
||||
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
|
||||
raw_route.segment_end_coordinates.size());
|
||||
|
||||
description_factory.SetStartSegment(
|
||||
raw_route.segment_end_coordinates.front().source_phantom,
|
||||
raw_route.source_traversed_in_reverse.front());
|
||||
json_result.values["status"] = 0;
|
||||
json_result.values["status_message"] = "Found route between points";
|
||||
|
||||
// for each unpacked segment add the leg to the description
|
||||
for (const auto i : osrm::irange<std::size_t>(0, raw_route.unpacked_path_segments.size()))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
const int added_segments =
|
||||
#endif
|
||||
DescribeLeg(raw_route.unpacked_path_segments[i],
|
||||
raw_route.segment_end_coordinates[i],
|
||||
raw_route.target_traversed_in_reverse[i], raw_route.is_via_leg(i));
|
||||
BOOST_ASSERT(0 < added_segments);
|
||||
}
|
||||
description_factory.Run(config.zoom_level);
|
||||
|
||||
if (config.geometry)
|
||||
{
|
||||
osrm::json::Value route_geometry =
|
||||
description_factory.AppendGeometryString(config.encode_geometry);
|
||||
json_result.values["route_geometry"] = route_geometry;
|
||||
}
|
||||
if (config.instructions)
|
||||
{
|
||||
osrm::json::Array json_route_instructions;
|
||||
BuildTextualDescription(description_factory, json_route_instructions,
|
||||
raw_route.shortest_path_length, shortest_path_segments);
|
||||
json_result.values["route_instructions"] = json_route_instructions;
|
||||
}
|
||||
description_factory.BuildRouteSummary(description_factory.get_entire_length(),
|
||||
raw_route.shortest_path_length);
|
||||
osrm::json::Object json_route_summary;
|
||||
json_route_summary.values["total_distance"] = description_factory.summary.distance;
|
||||
json_route_summary.values["total_time"] = description_factory.summary.duration;
|
||||
json_route_summary.values["start_point"] =
|
||||
facade->get_name_for_id(description_factory.summary.source_name_id);
|
||||
json_route_summary.values["end_point"] =
|
||||
facade->get_name_for_id(description_factory.summary.target_name_id);
|
||||
json_result.values["route_summary"] = json_route_summary;
|
||||
|
||||
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
|
||||
|
||||
osrm::json::Array json_via_points_array;
|
||||
osrm::json::Array json_first_coordinate;
|
||||
json_first_coordinate.values.push_back(
|
||||
raw_route.segment_end_coordinates.front().source_phantom.location.lat /
|
||||
COORDINATE_PRECISION);
|
||||
json_first_coordinate.values.push_back(
|
||||
raw_route.segment_end_coordinates.front().source_phantom.location.lon /
|
||||
COORDINATE_PRECISION);
|
||||
json_via_points_array.values.push_back(json_first_coordinate);
|
||||
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
|
||||
{
|
||||
std::string tmp;
|
||||
osrm::json::Array json_coordinate;
|
||||
json_coordinate.values.push_back(nodes.target_phantom.location.lat /
|
||||
COORDINATE_PRECISION);
|
||||
json_coordinate.values.push_back(nodes.target_phantom.location.lon /
|
||||
COORDINATE_PRECISION);
|
||||
json_via_points_array.values.push_back(json_coordinate);
|
||||
}
|
||||
json_result.values["via_points"] = json_via_points_array;
|
||||
|
||||
osrm::json::Array json_via_indices_array;
|
||||
|
||||
std::vector<unsigned> const &shortest_leg_end_indices = description_factory.GetViaIndices();
|
||||
json_via_indices_array.values.insert(json_via_indices_array.values.end(),
|
||||
shortest_leg_end_indices.begin(),
|
||||
shortest_leg_end_indices.end());
|
||||
json_result.values["via_indices"] = json_via_indices_array;
|
||||
|
||||
// only one alternative route is computed at this time, so this is hardcoded
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
json_result.values["found_alternative"] = osrm::json::True();
|
||||
BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty());
|
||||
alternate_description_factory.SetStartSegment(
|
||||
raw_route.segment_end_coordinates.front().source_phantom,
|
||||
raw_route.alt_source_traversed_in_reverse.front());
|
||||
// Get all the coordinates for the computed route
|
||||
for (const PathData &path_data : raw_route.unpacked_alternative)
|
||||
{
|
||||
current = facade->GetCoordinateOfNode(path_data.node);
|
||||
alternate_description_factory.AppendSegment(current, path_data);
|
||||
}
|
||||
alternate_description_factory.SetEndSegment(
|
||||
raw_route.segment_end_coordinates.back().target_phantom,
|
||||
raw_route.alt_source_traversed_in_reverse.back());
|
||||
alternate_description_factory.Run(config.zoom_level);
|
||||
|
||||
if (config.geometry)
|
||||
{
|
||||
osrm::json::Value alternate_geometry_string =
|
||||
alternate_description_factory.AppendGeometryString(config.encode_geometry);
|
||||
osrm::json::Array json_alternate_geometries_array;
|
||||
json_alternate_geometries_array.values.push_back(alternate_geometry_string);
|
||||
json_result.values["alternative_geometries"] = json_alternate_geometries_array;
|
||||
}
|
||||
// Generate instructions for each alternative (simulated here)
|
||||
osrm::json::Array json_alt_instructions;
|
||||
osrm::json::Array json_current_alt_instructions;
|
||||
if (config.instructions)
|
||||
{
|
||||
BuildTextualDescription(
|
||||
alternate_description_factory, json_current_alt_instructions,
|
||||
raw_route.alternative_path_length, alternative_path_segments);
|
||||
json_alt_instructions.values.push_back(json_current_alt_instructions);
|
||||
json_result.values["alternative_instructions"] = json_alt_instructions;
|
||||
}
|
||||
alternate_description_factory.BuildRouteSummary(
|
||||
alternate_description_factory.get_entire_length(),
|
||||
raw_route.alternative_path_length);
|
||||
|
||||
osrm::json::Object json_alternate_route_summary;
|
||||
osrm::json::Array json_alternate_route_summary_array;
|
||||
json_alternate_route_summary.values["total_distance"] =
|
||||
alternate_description_factory.summary.distance;
|
||||
json_alternate_route_summary.values["total_time"] =
|
||||
alternate_description_factory.summary.duration;
|
||||
json_alternate_route_summary.values["start_point"] =
|
||||
facade->get_name_for_id(alternate_description_factory.summary.source_name_id);
|
||||
json_alternate_route_summary.values["end_point"] =
|
||||
facade->get_name_for_id(alternate_description_factory.summary.target_name_id);
|
||||
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
|
||||
json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
|
||||
|
||||
std::vector<unsigned> const &alternate_leg_end_indices =
|
||||
alternate_description_factory.GetViaIndices();
|
||||
osrm::json::Array json_altenative_indices_array;
|
||||
json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(),
|
||||
alternate_leg_end_indices.begin(),
|
||||
alternate_leg_end_indices.end());
|
||||
json_result.values["alternative_indices"] = json_altenative_indices_array;
|
||||
}
|
||||
else
|
||||
{
|
||||
json_result.values["found_alternative"] = osrm::json::False();
|
||||
}
|
||||
|
||||
// Get Names for both routes
|
||||
RouteNames route_names =
|
||||
GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
|
||||
osrm::json::Array json_route_names;
|
||||
json_route_names.values.push_back(route_names.shortest_path_name_1);
|
||||
json_route_names.values.push_back(route_names.shortest_path_name_2);
|
||||
json_result.values["route_name"] = json_route_names;
|
||||
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
osrm::json::Array json_alternate_names_array;
|
||||
osrm::json::Array json_alternate_names;
|
||||
json_alternate_names.values.push_back(route_names.alternative_path_name_1);
|
||||
json_alternate_names.values.push_back(route_names.alternative_path_name_2);
|
||||
json_alternate_names_array.values.push_back(json_alternate_names);
|
||||
json_result.values["alternative_names"] = json_alternate_names_array;
|
||||
}
|
||||
|
||||
osrm::json::Object json_hint_object;
|
||||
json_hint_object.values["checksum"] = facade->GetCheckSum();
|
||||
osrm::json::Array json_location_hint_array;
|
||||
std::string hint;
|
||||
for (const auto i : osrm::irange<std::size_t>(0, raw_route.segment_end_coordinates.size()))
|
||||
{
|
||||
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates[i].source_phantom,
|
||||
hint);
|
||||
json_location_hint_array.values.push_back(hint);
|
||||
}
|
||||
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates.back().target_phantom,
|
||||
hint);
|
||||
json_location_hint_array.values.push_back(hint);
|
||||
json_hint_object.values["locations"] = json_location_hint_array;
|
||||
json_result.values["hint_data"] = json_hint_object;
|
||||
|
||||
// render the content to the output array
|
||||
// TIMER_START(route_render);
|
||||
// osrm::json::render(reply.content, json_result);
|
||||
// TIMER_STOP(route_render);
|
||||
// SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
|
||||
}
|
||||
|
||||
// TODO: reorder parameters
|
||||
inline void BuildTextualDescription(DescriptionFactory &description_factory,
|
||||
osrm::json::Array &json_instruction_array,
|
||||
const int route_length,
|
||||
std::vector<Segment> &route_segments_list)
|
||||
{
|
||||
// Segment information has following format:
|
||||
//["instruction id","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||
unsigned necessary_segments_running_index = 0;
|
||||
round_about.leave_at_exit = 0;
|
||||
round_about.name_id = 0;
|
||||
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
||||
|
||||
// Fetch data from Factory and generate a string from it.
|
||||
for (const SegmentInformation &segment : description_factory.path_description)
|
||||
{
|
||||
osrm::json::Array json_instruction_row;
|
||||
TurnInstruction current_instruction = segment.turn_instruction;
|
||||
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
|
||||
{
|
||||
if (TurnInstruction::EnterRoundAbout == current_instruction)
|
||||
{
|
||||
round_about.name_id = segment.name_id;
|
||||
round_about.start_index = necessary_segments_running_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string current_turn_instruction;
|
||||
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
||||
{
|
||||
temp_instruction = cast::integral_to_string(
|
||||
cast::enum_to_underlying(TurnInstruction::EnterRoundAbout));
|
||||
current_turn_instruction += temp_instruction;
|
||||
current_turn_instruction += "-";
|
||||
temp_instruction = cast::integral_to_string(round_about.leave_at_exit + 1);
|
||||
current_turn_instruction += temp_instruction;
|
||||
round_about.leave_at_exit = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_instruction =
|
||||
cast::integral_to_string(cast::enum_to_underlying(current_instruction));
|
||||
current_turn_instruction += temp_instruction;
|
||||
}
|
||||
json_instruction_row.values.push_back(current_turn_instruction);
|
||||
|
||||
json_instruction_row.values.push_back(facade->get_name_for_id(segment.name_id));
|
||||
json_instruction_row.values.push_back(std::round(segment.length));
|
||||
json_instruction_row.values.push_back(necessary_segments_running_index);
|
||||
json_instruction_row.values.push_back(std::round(segment.duration / 10.));
|
||||
json_instruction_row.values.push_back(
|
||||
cast::integral_to_string(static_cast<unsigned>(segment.length)) + "m");
|
||||
const double bearing_value = (segment.bearing / 10.);
|
||||
json_instruction_row.values.push_back(bearing::get(bearing_value));
|
||||
json_instruction_row.values.push_back(
|
||||
static_cast<unsigned>(round(bearing_value)));
|
||||
json_instruction_row.values.push_back(segment.travel_mode);
|
||||
|
||||
route_segments_list.emplace_back(
|
||||
segment.name_id, static_cast<int>(segment.length),
|
||||
static_cast<unsigned>(route_segments_list.size()));
|
||||
json_instruction_array.values.push_back(json_instruction_row);
|
||||
}
|
||||
}
|
||||
else if (TurnInstruction::StayOnRoundAbout == current_instruction)
|
||||
{
|
||||
++round_about.leave_at_exit;
|
||||
}
|
||||
if (segment.necessary)
|
||||
{
|
||||
++necessary_segments_running_index;
|
||||
}
|
||||
}
|
||||
|
||||
osrm::json::Array json_last_instruction_row;
|
||||
temp_instruction = cast::integral_to_string(
|
||||
cast::enum_to_underlying(TurnInstruction::ReachedYourDestination));
|
||||
json_last_instruction_row.values.push_back(temp_instruction);
|
||||
json_last_instruction_row.values.push_back("");
|
||||
json_last_instruction_row.values.push_back(0);
|
||||
json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
|
||||
json_last_instruction_row.values.push_back(0);
|
||||
json_last_instruction_row.values.push_back("0m");
|
||||
json_last_instruction_row.values.push_back(bearing::get(0.0));
|
||||
json_last_instruction_row.values.push_back(0.);
|
||||
json_instruction_array.values.push_back(json_last_instruction_row);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* JSON_DESCRIPTOR_H_ */
|
||||
|
51
extract.cpp
51
extract.cpp
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -26,17 +26,58 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "extractor/extractor.hpp"
|
||||
#include "Util/simple_logger.hpp"
|
||||
#include "extractor/extractor_options.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <exception>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
return Extractor().Run(argc, argv);
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
ExtractorConfig extractor_config;
|
||||
|
||||
const return_code result = ExtractorOptions::ParseArguments(argc, argv, extractor_config);
|
||||
|
||||
if (return_code::fail == result)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (return_code::exit == result)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ExtractorOptions::GenerateOutputFilesNames(extractor_config);
|
||||
|
||||
if (1 > extractor_config.requested_num_threads)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!boost::filesystem::is_regular_file(extractor_config.input_path))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "Input file " << extractor_config.input_path.string() << " not found!";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!boost::filesystem::is_regular_file(extractor_config.profile_path))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Profile " << extractor_config.profile_path.string()
|
||||
<< " not found!";
|
||||
return 1;
|
||||
}
|
||||
return extractor().run(extractor_config);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,12 +28,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "extraction_containers.hpp"
|
||||
#include "extraction_way.hpp"
|
||||
|
||||
#include "../data_structures/coordinate_calculation.hpp"
|
||||
#include "../data_structures/node_id.hpp"
|
||||
#include "../data_structures/range_table.hpp"
|
||||
|
||||
#include "../Util/osrm_exception.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/timing_util.hpp"
|
||||
#include "../util/osrm_exception.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
@ -82,41 +83,34 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
TIMER_STOP(erasing_dups);
|
||||
std::cout << "ok, after " << TIMER_SEC(erasing_dups) << "s" << std::endl;
|
||||
|
||||
|
||||
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
||||
TIMER_START(sorting_nodes);
|
||||
stxxl::sort(all_nodes_list.begin(),
|
||||
all_nodes_list.end(),
|
||||
ExternalMemoryNodeSTXXLCompare(),
|
||||
stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), ExternalMemoryNodeSTXXLCompare(),
|
||||
stxxl_memory);
|
||||
TIMER_STOP(sorting_nodes);
|
||||
std::cout << "ok, after " << TIMER_SEC(sorting_nodes) << "s" << std::endl;
|
||||
|
||||
|
||||
std::cout << "[extractor] Sorting used ways ... " << std::flush;
|
||||
TIMER_START(sort_ways);
|
||||
stxxl::sort(way_start_end_id_list.begin(),
|
||||
way_start_end_id_list.end(),
|
||||
FirstAndLastSegmentOfWayStxxlCompare(),
|
||||
stxxl_memory);
|
||||
stxxl::sort(way_start_end_id_list.begin(), way_start_end_id_list.end(),
|
||||
FirstAndLastSegmentOfWayStxxlCompare(), stxxl_memory);
|
||||
TIMER_STOP(sort_ways);
|
||||
std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl;
|
||||
|
||||
std::cout << "[extractor] Sorting " << restrictions_list.size() << " restrictions. by from... " << std::flush;
|
||||
std::cout << "[extractor] Sorting " << restrictions_list.size()
|
||||
<< " restrictions. by from... " << std::flush;
|
||||
TIMER_START(sort_restrictions);
|
||||
stxxl::sort(restrictions_list.begin(),
|
||||
restrictions_list.end(),
|
||||
CmpRestrictionContainerByFrom(),
|
||||
stxxl_memory);
|
||||
stxxl::sort(restrictions_list.begin(), restrictions_list.end(),
|
||||
CmpRestrictionContainerByFrom(), stxxl_memory);
|
||||
TIMER_STOP(sort_restrictions);
|
||||
std::cout << "ok, after " << TIMER_SEC(sort_restrictions) << "s" << std::endl;
|
||||
|
||||
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
|
||||
TIMER_START(fix_restriction_starts);
|
||||
auto restrictions_iterator = restrictions_list.begin();
|
||||
auto way_start_and_end_iterator = way_start_end_id_list.begin();
|
||||
auto way_start_and_end_iterator = way_start_end_id_list.cbegin();
|
||||
|
||||
while (way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||
while (way_start_and_end_iterator != way_start_end_id_list.cend() &&
|
||||
restrictions_iterator != restrictions_list.end())
|
||||
{
|
||||
if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.from.way)
|
||||
@ -131,27 +125,19 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
continue;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(way_start_and_end_iterator->way_id == restrictions_iterator->restriction.from.way);
|
||||
BOOST_ASSERT(way_start_and_end_iterator->way_id ==
|
||||
restrictions_iterator->restriction.from.way);
|
||||
const NodeID via_node_id = restrictions_iterator->restriction.via.node;
|
||||
|
||||
if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.from.node =
|
||||
way_start_and_end_iterator->first_segment_source_id;
|
||||
}
|
||||
else if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.from.node =
|
||||
way_start_and_end_iterator->first_segment_source_id;
|
||||
}
|
||||
else if (way_start_and_end_iterator->last_segment_source_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.from.node =
|
||||
way_start_and_end_iterator->last_segment_target_id;
|
||||
way_start_and_end_iterator->first_segment_target_id;
|
||||
}
|
||||
else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.from.node = way_start_and_end_iterator->last_segment_source_id;
|
||||
restrictions_iterator->restriction.from.node =
|
||||
way_start_and_end_iterator->last_segment_source_id;
|
||||
}
|
||||
++restrictions_iterator;
|
||||
}
|
||||
@ -161,19 +147,16 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
|
||||
std::cout << "[extractor] Sorting restrictions. by to ... " << std::flush;
|
||||
TIMER_START(sort_restrictions_to);
|
||||
stxxl::sort(restrictions_list.begin(),
|
||||
restrictions_list.end(),
|
||||
CmpRestrictionContainerByTo(),
|
||||
stxxl_memory);
|
||||
stxxl::sort(restrictions_list.begin(), restrictions_list.end(),
|
||||
CmpRestrictionContainerByTo(), stxxl_memory);
|
||||
TIMER_STOP(sort_restrictions_to);
|
||||
std::cout << "ok, after " << TIMER_SEC(sort_restrictions_to) << "s" << std::endl;
|
||||
|
||||
unsigned number_of_useable_restrictions = 0;
|
||||
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
|
||||
TIMER_START(fix_restriction_ends);
|
||||
restrictions_iterator = restrictions_list.begin();
|
||||
way_start_and_end_iterator = way_start_end_id_list.begin();
|
||||
while (way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||
way_start_and_end_iterator = way_start_end_id_list.cbegin();
|
||||
while (way_start_and_end_iterator != way_start_end_id_list.cend() &&
|
||||
restrictions_iterator != restrictions_list.end())
|
||||
{
|
||||
if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.to.way)
|
||||
@ -186,51 +169,48 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
++restrictions_iterator;
|
||||
continue;
|
||||
}
|
||||
NodeID via_node_id = restrictions_iterator->restriction.via.node;
|
||||
if (way_start_and_end_iterator->last_segment_source_id == via_node_id)
|
||||
BOOST_ASSERT(way_start_and_end_iterator->way_id ==
|
||||
restrictions_iterator->restriction.to.way);
|
||||
const NodeID via_node_id = restrictions_iterator->restriction.via.node;
|
||||
|
||||
if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.to.node = way_start_and_end_iterator->last_segment_target_id;
|
||||
restrictions_iterator->restriction.to.node =
|
||||
way_start_and_end_iterator->first_segment_target_id;
|
||||
}
|
||||
else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.to.node = way_start_and_end_iterator->last_segment_source_id;
|
||||
}
|
||||
else if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.to.node = way_start_and_end_iterator->first_segment_target_id;
|
||||
}
|
||||
else if (way_start_and_end_iterator->first_segment_target_id == via_node_id)
|
||||
{
|
||||
restrictions_iterator->restriction.to.node = way_start_and_end_iterator->first_segment_source_id;
|
||||
}
|
||||
|
||||
if (std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.from.node &&
|
||||
std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.to.node)
|
||||
{
|
||||
++number_of_useable_restrictions;
|
||||
restrictions_iterator->restriction.to.node =
|
||||
way_start_and_end_iterator->last_segment_source_id;
|
||||
}
|
||||
++restrictions_iterator;
|
||||
}
|
||||
TIMER_STOP(fix_restriction_ends);
|
||||
std::cout << "ok, after " << TIMER_SEC(fix_restriction_ends) << "s" << std::endl;
|
||||
|
||||
SimpleLogger().Write() << "usable restrictions: " << number_of_useable_restrictions;
|
||||
// serialize restrictions
|
||||
std::ofstream restrictions_out_stream;
|
||||
unsigned written_restriction_count = 0;
|
||||
restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
|
||||
restrictions_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
|
||||
restrictions_out_stream.write((char *)&number_of_useable_restrictions, sizeof(unsigned));
|
||||
const auto count_position = restrictions_out_stream.tellp();
|
||||
restrictions_out_stream.write((char *)&written_restriction_count, sizeof(unsigned));
|
||||
|
||||
for(const auto & restriction_container : restrictions_list)
|
||||
for (const auto &restriction_container : restrictions_list)
|
||||
{
|
||||
if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.from.node &&
|
||||
std::numeric_limits<unsigned>::max() != restriction_container.restriction.to.node)
|
||||
if (SPECIAL_NODEID != restriction_container.restriction.from.node &&
|
||||
SPECIAL_NODEID != restriction_container.restriction.to.node)
|
||||
{
|
||||
restrictions_out_stream.write((char *)&(restriction_container.restriction),
|
||||
sizeof(TurnRestriction));
|
||||
++written_restriction_count;
|
||||
}
|
||||
}
|
||||
restrictions_out_stream.seekp(count_position);
|
||||
restrictions_out_stream.write((char *)&written_restriction_count, sizeof(unsigned));
|
||||
|
||||
restrictions_out_stream.close();
|
||||
SimpleLogger().Write() << "usable restrictions: " << written_restriction_count;
|
||||
|
||||
std::ofstream file_out_stream;
|
||||
file_out_stream.open(output_file_name.c_str(), std::ios::binary);
|
||||
@ -280,7 +260,6 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
TIMER_STOP(sort_edges_by_start);
|
||||
std::cout << "ok, after " << TIMER_SEC(sort_edges_by_start) << "s" << std::endl;
|
||||
|
||||
|
||||
std::cout << "[extractor] Setting start coords ... " << std::flush;
|
||||
TIMER_START(set_start_coords);
|
||||
file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
|
||||
@ -311,7 +290,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
// Sort Edges by target
|
||||
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
|
||||
TIMER_START(sort_edges_by_target);
|
||||
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(), stxxl_memory);
|
||||
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(),
|
||||
stxxl_memory);
|
||||
TIMER_STOP(sort_edges_by_target);
|
||||
std::cout << "ok, after " << TIMER_SEC(sort_edges_by_target) << "s" << std::endl;
|
||||
|
||||
@ -341,20 +321,19 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
edge_iterator->target_coordinate.lat = node_iterator->lat;
|
||||
edge_iterator->target_coordinate.lon = node_iterator->lon;
|
||||
|
||||
const double distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
edge_iterator->source_coordinate.lat,
|
||||
edge_iterator->source_coordinate.lon,
|
||||
node_iterator->lat,
|
||||
node_iterator->lon);
|
||||
const double distance = coordinate_calculation::euclidean_distance(
|
||||
edge_iterator->source_coordinate.lat, edge_iterator->source_coordinate.lon,
|
||||
node_iterator->lat, node_iterator->lon);
|
||||
|
||||
const double weight = (distance * 10.) / (edge_iterator->speed / 3.6);
|
||||
int integer_weight = std::max(
|
||||
1,
|
||||
(int)std::floor(
|
||||
(edge_iterator->is_duration_set ? edge_iterator->speed : weight) + .5));
|
||||
int integer_distance = std::max(1, (int)distance);
|
||||
short zero = 0;
|
||||
short one = 1;
|
||||
1, (int)std::floor(
|
||||
(edge_iterator->is_duration_set ? edge_iterator->speed : weight) + .5));
|
||||
const int integer_distance = std::max(1, (int)distance);
|
||||
const short zero = 0;
|
||||
const short one = 1;
|
||||
const bool yes = true;
|
||||
const bool no = false;
|
||||
|
||||
file_out_stream.write((char *)&edge_iterator->start, sizeof(unsigned));
|
||||
file_out_stream.write((char *)&edge_iterator->target, sizeof(unsigned));
|
||||
@ -379,15 +358,43 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
|
||||
file_out_stream.write((char *)&integer_weight, sizeof(int));
|
||||
file_out_stream.write((char *)&edge_iterator->name_id, sizeof(unsigned));
|
||||
file_out_stream.write((char *)&edge_iterator->is_roundabout, sizeof(bool));
|
||||
file_out_stream.write((char *)&edge_iterator->is_in_tiny_cc, sizeof(bool));
|
||||
file_out_stream.write((char *)&edge_iterator->is_access_restricted, sizeof(bool));
|
||||
if (edge_iterator->is_roundabout)
|
||||
{
|
||||
file_out_stream.write((char *)&yes, sizeof(bool));
|
||||
}
|
||||
else
|
||||
{
|
||||
file_out_stream.write((char *)&no, sizeof(bool));
|
||||
}
|
||||
if (edge_iterator->is_in_tiny_cc)
|
||||
{
|
||||
file_out_stream.write((char *)&yes, sizeof(bool));
|
||||
}
|
||||
else
|
||||
{
|
||||
file_out_stream.write((char *)&no, sizeof(bool));
|
||||
}
|
||||
if (edge_iterator->is_access_restricted)
|
||||
{
|
||||
file_out_stream.write((char *)&yes, sizeof(bool));
|
||||
}
|
||||
else
|
||||
{
|
||||
file_out_stream.write((char *)&no, sizeof(bool));
|
||||
}
|
||||
|
||||
// cannot take adress of bit field, so use local
|
||||
const TravelMode travel_mode = edge_iterator->travel_mode;
|
||||
const TravelMode travel_mode = edge_iterator->travel_mode;
|
||||
file_out_stream.write((char *)&travel_mode, sizeof(TravelMode));
|
||||
|
||||
file_out_stream.write((char *)&edge_iterator->is_split, sizeof(bool));
|
||||
if (edge_iterator->is_split)
|
||||
{
|
||||
file_out_stream.write((char *)&yes, sizeof(bool));
|
||||
}
|
||||
else
|
||||
{
|
||||
file_out_stream.write((char *)&no, sizeof(bool));
|
||||
}
|
||||
++number_of_used_edges;
|
||||
}
|
||||
++edge_iterator;
|
||||
@ -411,7 +418,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
std::vector<unsigned> name_lengths;
|
||||
for (const std::string &temp_string : name_list)
|
||||
{
|
||||
const unsigned string_length = std::min(static_cast<unsigned>(temp_string.length()), 255u);
|
||||
const unsigned string_length =
|
||||
std::min(static_cast<unsigned>(temp_string.length()), 255u);
|
||||
name_lengths.push_back(string_length);
|
||||
total_length += string_length;
|
||||
}
|
||||
@ -419,11 +427,12 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
RangeTable<> table(name_lengths);
|
||||
name_file_stream << table;
|
||||
|
||||
name_file_stream.write((char*) &total_length, sizeof(unsigned));
|
||||
name_file_stream.write((char *)&total_length, sizeof(unsigned));
|
||||
// write all chars consecutively
|
||||
for (const std::string &temp_string : name_list)
|
||||
{
|
||||
const unsigned string_length = std::min(static_cast<unsigned>(temp_string.length()), 255u);
|
||||
const unsigned string_length =
|
||||
std::min(static_cast<unsigned>(temp_string.length()), 255u);
|
||||
name_file_stream.write(temp_string.c_str(), string_length);
|
||||
}
|
||||
|
||||
@ -434,5 +443,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes and "
|
||||
<< number_of_used_edges << " edges";
|
||||
}
|
||||
catch (const std::exception &e) { std::cerr << "Caught Execption:" << e.what() << std::endl; }
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
std::cerr << "Caught Execption:" << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -32,24 +32,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "first_and_last_segment_of_way.hpp"
|
||||
#include "../data_structures/external_memory_node.hpp"
|
||||
#include "../data_structures/restriction.hpp"
|
||||
#include "../Util/FingerPrint.h"
|
||||
#include "../util/fingerprint.hpp"
|
||||
|
||||
#include <stxxl/vector>
|
||||
|
||||
class ExtractionContainers
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
constexpr static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max() : std::numeric_limits<unsigned>::max());
|
||||
constexpr static unsigned stxxl_memory =
|
||||
((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max()
|
||||
: std::numeric_limits<unsigned>::max());
|
||||
#else
|
||||
const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX);
|
||||
#endif
|
||||
public:
|
||||
using STXXLNodeIDVector = stxxl::vector<NodeID>;
|
||||
using STXXLNodeVector = stxxl::vector<ExternalMemoryNode>;
|
||||
using STXXLEdgeVector = stxxl::vector<InternalExtractorEdge>;
|
||||
using STXXLStringVector = stxxl::vector<std::string>;
|
||||
using STXXLRestrictionsVector = stxxl::vector<InputRestrictionContainer>;
|
||||
using STXXLWayIDStartEndVector = stxxl::vector<FirstAndLastSegmentOfWay>;
|
||||
using STXXLNodeIDVector = stxxl::vector<NodeID>;
|
||||
using STXXLNodeVector = stxxl::vector<ExternalMemoryNode>;
|
||||
using STXXLEdgeVector = stxxl::vector<InternalExtractorEdge>;
|
||||
using STXXLStringVector = stxxl::vector<std::string>;
|
||||
using STXXLRestrictionsVector = stxxl::vector<InputRestrictionContainer>;
|
||||
using STXXLWayIDStartEndVector = stxxl::vector<FirstAndLastSegmentOfWay>;
|
||||
|
||||
STXXLNodeIDVector used_node_id_list;
|
||||
STXXLNodeVector all_nodes_list;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,7 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef EXTRACTION_HELPER_FUNCTIONS_HPP
|
||||
#define EXTRACTION_HELPER_FUNCTIONS_HPP
|
||||
|
||||
#include "../Util/cast.hpp"
|
||||
#include "../util/cast.hpp"
|
||||
#include "../util/iso_8601_duration_parser.hpp"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string_regex.hpp>
|
||||
@ -37,53 +38,81 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
// TODO: Move into LUA
|
||||
|
||||
bool durationIsValid(const std::string &s)
|
||||
bool simple_duration_is_valid(const std::string &s)
|
||||
{
|
||||
boost::regex e(
|
||||
boost::regex simple_format(
|
||||
"((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",
|
||||
boost::regex_constants::icase | boost::regex_constants::perl);
|
||||
|
||||
std::vector<std::string> result;
|
||||
boost::algorithm::split_regex(result, s, boost::regex(":"));
|
||||
const bool matched = regex_match(s, e);
|
||||
return matched;
|
||||
const bool simple_matched = regex_match(s, simple_format);
|
||||
|
||||
if (simple_matched)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool iso_8601_duration_is_valid(const std::string &s)
|
||||
{
|
||||
iso_8601_grammar<std::string::const_iterator> iso_parser;
|
||||
const bool result = qi::parse(s.begin(), s.end(), iso_parser);
|
||||
|
||||
// check if the was an error with the request
|
||||
if (result && (0 != iso_parser.get_duration()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool durationIsValid(const std::string &s)
|
||||
{
|
||||
return simple_duration_is_valid(s) || iso_8601_duration_is_valid(s);
|
||||
}
|
||||
|
||||
unsigned parseDuration(const std::string &s)
|
||||
{
|
||||
unsigned hours = 0;
|
||||
unsigned minutes = 0;
|
||||
unsigned seconds = 0;
|
||||
boost::regex e(
|
||||
"((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",
|
||||
boost::regex_constants::icase | boost::regex_constants::perl);
|
||||
|
||||
std::vector<std::string> result;
|
||||
boost::algorithm::split_regex(result, s, boost::regex(":"));
|
||||
const bool matched = regex_match(s, e);
|
||||
if (matched)
|
||||
if (simple_duration_is_valid(s))
|
||||
{
|
||||
if (1 == result.size())
|
||||
unsigned hours = 0;
|
||||
unsigned minutes = 0;
|
||||
unsigned seconds = 0;
|
||||
boost::regex e(
|
||||
"((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",
|
||||
boost::regex_constants::icase | boost::regex_constants::perl);
|
||||
|
||||
std::vector<std::string> result;
|
||||
boost::algorithm::split_regex(result, s, boost::regex(":"));
|
||||
const bool matched = regex_match(s, e);
|
||||
if (matched)
|
||||
{
|
||||
minutes = cast::string_to_int(result[0]);
|
||||
if (1 == result.size())
|
||||
{
|
||||
minutes = cast::string_to_int(result[0]);
|
||||
}
|
||||
if (2 == result.size())
|
||||
{
|
||||
minutes = cast::string_to_int(result[1]);
|
||||
hours = cast::string_to_int(result[0]);
|
||||
}
|
||||
if (3 == result.size())
|
||||
{
|
||||
seconds = cast::string_to_int(result[2]);
|
||||
minutes = cast::string_to_int(result[1]);
|
||||
hours = cast::string_to_int(result[0]);
|
||||
}
|
||||
return 10 * (3600 * hours + 60 * minutes + seconds);
|
||||
}
|
||||
if (2 == result.size())
|
||||
{
|
||||
minutes = cast::string_to_int(result[1]);
|
||||
hours = cast::string_to_int(result[0]);
|
||||
}
|
||||
if (3 == result.size())
|
||||
{
|
||||
seconds = cast::string_to_int(result[2]);
|
||||
minutes = cast::string_to_int(result[1]);
|
||||
hours = cast::string_to_int(result[0]);
|
||||
}
|
||||
return 10 * (3600 * hours + 60 * minutes + seconds);
|
||||
}
|
||||
else if (iso_8601_duration_is_valid(s))
|
||||
{
|
||||
iso_8601_grammar<std::string::const_iterator> iso_parser;
|
||||
qi::parse(s.begin(), s.end(), iso_parser);
|
||||
|
||||
return iso_parser.get_duration();
|
||||
}
|
||||
|
||||
return std::numeric_limits<unsigned>::max();
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,11 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
struct ExtractionNode
|
||||
{
|
||||
ExtractionNode() : traffic_lights(false), barrier(false) { }
|
||||
void clear()
|
||||
{
|
||||
traffic_lights = barrier = false;
|
||||
}
|
||||
ExtractionNode() : traffic_lights(false), barrier(false) {}
|
||||
void clear() { traffic_lights = barrier = false; }
|
||||
bool traffic_lights;
|
||||
bool barrier;
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -52,10 +52,12 @@ struct ExtractionWay
|
||||
}
|
||||
|
||||
enum Directions
|
||||
{ notSure = 0,
|
||||
oneway,
|
||||
bidirectional,
|
||||
opposite };
|
||||
{
|
||||
notSure = 0,
|
||||
oneway,
|
||||
bidirectional,
|
||||
opposite
|
||||
};
|
||||
|
||||
// These accessor methods exists to support the depreciated "way.direction" access
|
||||
// in LUA. Since the direction attribute was removed from ExtractionWay, the
|
||||
@ -69,19 +71,20 @@ struct ExtractionWay
|
||||
}
|
||||
else if (Directions::opposite == m)
|
||||
{
|
||||
forward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
|
||||
backward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||
forward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
|
||||
backward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||
}
|
||||
else if (Directions::bidirectional == m)
|
||||
{
|
||||
forward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||
backward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||
forward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||
backward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
Directions get_direction() const
|
||||
{
|
||||
if (TRAVEL_MODE_INACCESSIBLE != forward_travel_mode && TRAVEL_MODE_INACCESSIBLE != backward_travel_mode)
|
||||
if (TRAVEL_MODE_INACCESSIBLE != forward_travel_mode &&
|
||||
TRAVEL_MODE_INACCESSIBLE != backward_travel_mode)
|
||||
{
|
||||
return Directions::bidirectional;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -31,18 +31,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "extraction_node.hpp"
|
||||
#include "extraction_way.hpp"
|
||||
#include "extractor_callbacks.hpp"
|
||||
#include "extractor_options.hpp"
|
||||
#include "restriction_parser.hpp"
|
||||
#include "scripting_environment.hpp"
|
||||
|
||||
#include "../Util/git_sha.hpp"
|
||||
#include "../Util/IniFileUtil.h"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/timing_util.hpp"
|
||||
#include "../Util/make_unique.hpp"
|
||||
#include "../util/git_sha.hpp"
|
||||
#include "../util/make_unique.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <luabind/luabind.hpp>
|
||||
|
||||
#include <osmium/io/any_input.hpp>
|
||||
@ -63,43 +64,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
int Extractor::Run(int argc, char *argv[])
|
||||
int extractor::run(const ExtractorConfig &extractor_config)
|
||||
{
|
||||
ExtractorConfig extractor_config;
|
||||
|
||||
try
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
TIMER_START(extracting);
|
||||
|
||||
if (!ExtractorOptions::ParseArguments(argc, argv, extractor_config))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
ExtractorOptions::GenerateOutputFilesNames(extractor_config);
|
||||
|
||||
if (1 > extractor_config.requested_num_threads)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!boost::filesystem::is_regular_file(extractor_config.input_path))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "Input file " << extractor_config.input_path.string() << " not found!";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!boost::filesystem::is_regular_file(extractor_config.profile_path))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Profile " << extractor_config.profile_path.string()
|
||||
<< " not found!";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
|
||||
const auto number_of_threads = std::min(recommended_num_threads, extractor_config.requested_num_threads);
|
||||
const auto number_of_threads =
|
||||
std::min(recommended_num_threads, extractor_config.requested_num_threads);
|
||||
tbb::task_scheduler_init init(number_of_threads);
|
||||
|
||||
SimpleLogger().Write() << "Input file: " << extractor_config.input_path.filename().string();
|
||||
@ -120,10 +94,10 @@ int Extractor::Run(int argc, char *argv[])
|
||||
osmium::io::Reader reader(input_file);
|
||||
const osmium::io::Header header = reader.header();
|
||||
|
||||
std::atomic<unsigned> number_of_nodes {0};
|
||||
std::atomic<unsigned> number_of_ways {0};
|
||||
std::atomic<unsigned> number_of_relations {0};
|
||||
std::atomic<unsigned> number_of_others {0};
|
||||
std::atomic<unsigned> number_of_nodes{0};
|
||||
std::atomic<unsigned> number_of_ways{0};
|
||||
std::atomic<unsigned> number_of_relations{0};
|
||||
std::atomic<unsigned> number_of_others{0};
|
||||
|
||||
SimpleLogger().Write() << "Parsing in progress..";
|
||||
TIMER_START(parsing);
|
||||
@ -160,7 +134,8 @@ int Extractor::Run(int argc, char *argv[])
|
||||
{
|
||||
// create a vector of iterators into the buffer
|
||||
std::vector<osmium::memory::Buffer::const_iterator> osm_elements;
|
||||
for (auto iter = std::begin(buffer); iter != std::end(buffer); ++iter) {
|
||||
for (auto iter = std::begin(buffer); iter != std::end(buffer); ++iter)
|
||||
{
|
||||
osm_elements.push_back(iter);
|
||||
}
|
||||
|
||||
@ -170,55 +145,56 @@ int Extractor::Run(int argc, char *argv[])
|
||||
resulting_restrictions.clear();
|
||||
|
||||
// parse OSM entities in parallel, store in resulting vectors
|
||||
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, osm_elements.size()),
|
||||
[&](const tbb::blocked_range<std::size_t> &range)
|
||||
{
|
||||
for (auto x = range.begin(); x != range.end(); ++x)
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<std::size_t>(0, osm_elements.size()),
|
||||
[&](const tbb::blocked_range<std::size_t> &range)
|
||||
{
|
||||
const auto entity = osm_elements[x];
|
||||
|
||||
ExtractionNode result_node;
|
||||
ExtractionWay result_way;
|
||||
lua_State *local_state = scripting_environment.get_lua_state();
|
||||
|
||||
lua_State * local_state = scripting_environment.get_lua_state();
|
||||
|
||||
switch (entity->type())
|
||||
for (auto x = range.begin(); x != range.end(); ++x)
|
||||
{
|
||||
case osmium::item_type::node:
|
||||
++number_of_nodes;
|
||||
luabind::call_function<void>(
|
||||
local_state,
|
||||
"node_function",
|
||||
boost::cref(static_cast<const osmium::Node &>(*entity)),
|
||||
boost::ref(result_node));
|
||||
resulting_nodes.push_back(std::make_pair(x, result_node));
|
||||
break;
|
||||
case osmium::item_type::way:
|
||||
++number_of_ways;
|
||||
luabind::call_function<void>(
|
||||
local_state,
|
||||
"way_function",
|
||||
boost::cref(static_cast<const osmium::Way &>(*entity)),
|
||||
boost::ref(result_way));
|
||||
resulting_ways.push_back(std::make_pair(x, result_way));
|
||||
break;
|
||||
case osmium::item_type::relation:
|
||||
++number_of_relations;
|
||||
resulting_restrictions.push_back(
|
||||
restriction_parser.TryParse(static_cast<const osmium::Relation &>(*entity)));
|
||||
break;
|
||||
default:
|
||||
++number_of_others;
|
||||
break;
|
||||
const auto entity = osm_elements[x];
|
||||
|
||||
switch (entity->type())
|
||||
{
|
||||
case osmium::item_type::node:
|
||||
result_node.clear();
|
||||
++number_of_nodes;
|
||||
luabind::call_function<void>(
|
||||
local_state, "node_function",
|
||||
boost::cref(static_cast<const osmium::Node &>(*entity)),
|
||||
boost::ref(result_node));
|
||||
resulting_nodes.push_back(std::make_pair(x, result_node));
|
||||
break;
|
||||
case osmium::item_type::way:
|
||||
result_way.clear();
|
||||
++number_of_ways;
|
||||
luabind::call_function<void>(
|
||||
local_state, "way_function",
|
||||
boost::cref(static_cast<const osmium::Way &>(*entity)),
|
||||
boost::ref(result_way));
|
||||
resulting_ways.push_back(std::make_pair(x, result_way));
|
||||
break;
|
||||
case osmium::item_type::relation:
|
||||
++number_of_relations;
|
||||
resulting_restrictions.push_back(restriction_parser.TryParse(
|
||||
static_cast<const osmium::Relation &>(*entity)));
|
||||
break;
|
||||
default:
|
||||
++number_of_others;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// put parsed objects thru extractor callbacks
|
||||
for (const auto &result : resulting_nodes)
|
||||
{
|
||||
extractor_callbacks->ProcessNode(
|
||||
static_cast<const osmium::Node &>(*(osm_elements[result.first])), result.second);
|
||||
static_cast<const osmium::Node &>(*(osm_elements[result.first])),
|
||||
result.second);
|
||||
}
|
||||
for (const auto &result : resulting_ways)
|
||||
{
|
||||
@ -233,15 +209,10 @@ int Extractor::Run(int argc, char *argv[])
|
||||
TIMER_STOP(parsing);
|
||||
SimpleLogger().Write() << "Parsing finished after " << TIMER_SEC(parsing) << " seconds";
|
||||
|
||||
unsigned nn = number_of_nodes;
|
||||
unsigned nw = number_of_ways;
|
||||
unsigned nr = number_of_relations;
|
||||
unsigned no = number_of_others;
|
||||
SimpleLogger().Write() << "Raw input contains "
|
||||
<< nn << " nodes, "
|
||||
<< nw << " ways, and "
|
||||
<< nr << " relations, and "
|
||||
<< no << " unknown entities";
|
||||
SimpleLogger().Write() << "Raw input contains " << number_of_nodes.load() << " nodes, "
|
||||
<< number_of_ways.load() << " ways, and "
|
||||
<< number_of_relations.load() << " relations, and "
|
||||
<< number_of_others.load() << " unknown entities";
|
||||
|
||||
extractor_callbacks.reset();
|
||||
|
||||
|
@ -1,13 +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 EXTRACTOR_HPP
|
||||
#define EXTRACTOR_HPP
|
||||
|
||||
#include <string>
|
||||
#include "extractor_options.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
/** \brief Class of 'extract' utility. */
|
||||
struct Extractor
|
||||
struct extractor
|
||||
{
|
||||
int Run(int argc, char *argv[]);
|
||||
int run(const ExtractorConfig &extractor_config);
|
||||
};
|
||||
#endif /* EXTRACTOR_HPP */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -32,10 +32,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../data_structures/external_memory_node.hpp"
|
||||
#include "../data_structures/restriction.hpp"
|
||||
#include "../Util/container.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../util/container.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
@ -51,13 +51,12 @@ ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containe
|
||||
void ExtractorCallbacks::ProcessNode(const osmium::Node &input_node,
|
||||
const ExtractionNode &result_node)
|
||||
{
|
||||
external_memory.all_nodes_list.push_back({
|
||||
static_cast<int>(input_node.location().lat() * COORDINATE_PRECISION),
|
||||
static_cast<int>(input_node.location().lon() * COORDINATE_PRECISION),
|
||||
static_cast<NodeID>(input_node.id()),
|
||||
result_node.barrier,
|
||||
result_node.traffic_lights
|
||||
});
|
||||
external_memory.all_nodes_list.push_back(
|
||||
{static_cast<int>(input_node.location().lat() * COORDINATE_PRECISION),
|
||||
static_cast<int>(input_node.location().lon() * COORDINATE_PRECISION),
|
||||
static_cast<NodeID>(input_node.id()),
|
||||
result_node.barrier,
|
||||
result_node.traffic_lights});
|
||||
}
|
||||
|
||||
void ExtractorCallbacks::ProcessRestriction(
|
||||
@ -69,7 +68,8 @@ void ExtractorCallbacks::ProcessRestriction(
|
||||
// SimpleLogger().Write() << "from: " << restriction.get().restriction.from.node <<
|
||||
// ",via: " << restriction.get().restriction.via.node <<
|
||||
// ", to: " << restriction.get().restriction.to.node <<
|
||||
// ", only: " << (restriction.get().restriction.flags.is_only ? "y" : "n");
|
||||
// ", only: " << (restriction.get().restriction.flags.is_only ?
|
||||
// "y" : "n");
|
||||
}
|
||||
}
|
||||
/** warning: caller needs to take care of synchronization! */
|
||||
@ -99,8 +99,10 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
{
|
||||
// TODO: iterate all way segments and set duration corresponding to the length of each
|
||||
// segment
|
||||
const_cast<ExtractionWay&>(parsed_way).forward_speed = parsed_way.duration / (input_way.nodes().size() - 1);
|
||||
const_cast<ExtractionWay&>(parsed_way).backward_speed = parsed_way.duration / (input_way.nodes().size() - 1);
|
||||
const_cast<ExtractionWay &>(parsed_way).forward_speed =
|
||||
parsed_way.duration / (input_way.nodes().size() - 1);
|
||||
const_cast<ExtractionWay &>(parsed_way).backward_speed =
|
||||
parsed_way.duration / (input_way.nodes().size() - 1);
|
||||
}
|
||||
|
||||
if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.forward_speed))
|
||||
@ -129,41 +131,36 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
((parsed_way.forward_speed != parsed_way.backward_speed) ||
|
||||
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode));
|
||||
|
||||
auto pair_wise_segment_split = [&](const osmium::NodeRef &first_node,
|
||||
const osmium::NodeRef &last_node)
|
||||
auto pair_wise_segment_split =
|
||||
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node)
|
||||
{
|
||||
// SimpleLogger().Write() << "adding edge (" << first_node.ref() << "," <<
|
||||
// last_node.ref() << "), fwd speed: " << parsed_way.forward_speed;
|
||||
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
||||
first_node.ref(),
|
||||
last_node.ref(),
|
||||
first_node.ref(), last_node.ref(),
|
||||
((split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode)
|
||||
? ExtractionWay::oneway
|
||||
: ExtractionWay::bidirectional),
|
||||
parsed_way.forward_speed,
|
||||
name_id,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignore_in_grid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.is_access_restricted,
|
||||
parsed_way.forward_travel_mode,
|
||||
split_edge));
|
||||
parsed_way.forward_speed, name_id, parsed_way.roundabout, parsed_way.ignore_in_grid,
|
||||
(0 < parsed_way.duration), parsed_way.is_access_restricted,
|
||||
parsed_way.forward_travel_mode, split_edge));
|
||||
external_memory.used_node_id_list.push_back(first_node.ref());
|
||||
};
|
||||
|
||||
const bool is_opposite_way = TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode;
|
||||
if (is_opposite_way)
|
||||
{
|
||||
const_cast<ExtractionWay&>(parsed_way).forward_travel_mode = parsed_way.backward_travel_mode;
|
||||
const_cast<ExtractionWay&>(parsed_way).backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
|
||||
osrm::for_each_pair(
|
||||
input_way.nodes().crbegin(), input_way.nodes().crend(), pair_wise_segment_split);
|
||||
const_cast<ExtractionWay &>(parsed_way).forward_travel_mode =
|
||||
parsed_way.backward_travel_mode;
|
||||
const_cast<ExtractionWay &>(parsed_way).backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
|
||||
osrm::for_each_pair(input_way.nodes().crbegin(), input_way.nodes().crend(),
|
||||
pair_wise_segment_split);
|
||||
external_memory.used_node_id_list.push_back(input_way.nodes().front().ref());
|
||||
}
|
||||
else
|
||||
{
|
||||
osrm::for_each_pair(
|
||||
input_way.nodes().cbegin(), input_way.nodes().cend(), pair_wise_segment_split);
|
||||
osrm::for_each_pair(input_way.nodes().cbegin(), input_way.nodes().cend(),
|
||||
pair_wise_segment_split);
|
||||
external_memory.used_node_id_list.push_back(input_way.nodes().back().ref());
|
||||
}
|
||||
|
||||
@ -177,39 +174,30 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
|
||||
if (split_edge)
|
||||
{ // Only true if the way should be split
|
||||
BOOST_ASSERT(parsed_way.backward_travel_mode>0);
|
||||
auto pair_wise_segment_split_2 = [&](const osmium::NodeRef &first_node,
|
||||
const osmium::NodeRef &last_node)
|
||||
BOOST_ASSERT(parsed_way.backward_travel_mode > 0);
|
||||
auto pair_wise_segment_split_2 =
|
||||
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node)
|
||||
{
|
||||
// SimpleLogger().Write() << "adding edge (" << last_node.ref() << "," <<
|
||||
// first_node.ref() << "), bwd speed: " << parsed_way.backward_speed;
|
||||
external_memory.all_edges_list.push_back(
|
||||
InternalExtractorEdge(last_node.ref(),
|
||||
first_node.ref(),
|
||||
ExtractionWay::oneway,
|
||||
parsed_way.backward_speed,
|
||||
name_id,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignore_in_grid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.is_access_restricted,
|
||||
parsed_way.backward_travel_mode,
|
||||
split_edge));
|
||||
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
||||
last_node.ref(), first_node.ref(), ExtractionWay::oneway, parsed_way.backward_speed,
|
||||
name_id, parsed_way.roundabout, parsed_way.ignore_in_grid,
|
||||
(0 < parsed_way.duration), parsed_way.is_access_restricted,
|
||||
parsed_way.backward_travel_mode, split_edge));
|
||||
};
|
||||
|
||||
if (is_opposite_way)
|
||||
{
|
||||
// SimpleLogger().Write() << "opposite2";
|
||||
osrm::for_each_pair(input_way.nodes().crbegin(),
|
||||
input_way.nodes().crend(),
|
||||
pair_wise_segment_split_2);
|
||||
osrm::for_each_pair(input_way.nodes().crbegin(), input_way.nodes().crend(),
|
||||
pair_wise_segment_split_2);
|
||||
external_memory.used_node_id_list.push_back(input_way.nodes().front().ref());
|
||||
}
|
||||
else
|
||||
{
|
||||
osrm::for_each_pair(input_way.nodes().cbegin(),
|
||||
input_way.nodes().cend(),
|
||||
pair_wise_segment_split_2);
|
||||
osrm::for_each_pair(input_way.nodes().cbegin(), input_way.nodes().cend(),
|
||||
pair_wise_segment_split_2);
|
||||
external_memory.used_node_id_list.push_back(input_way.nodes().back().ref());
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -27,23 +27,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "extractor_options.hpp"
|
||||
|
||||
#include "../Util/git_sha.hpp"
|
||||
#include "../Util/IniFileUtil.h"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../util/git_sha.hpp"
|
||||
#include "../util/ini_file.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
bool ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config)
|
||||
return_code
|
||||
ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_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>(&extractor_config.config_file_path)
|
||||
->default_value("extractor.ini"),
|
||||
"config,c", boost::program_options::value<boost::filesystem::path>(
|
||||
&extractor_config.config_file_path)->default_value("extractor.ini"),
|
||||
"Path to a configuration file.");
|
||||
|
||||
// declare a group of options that will be allowed both on command line and in config file
|
||||
@ -60,10 +60,9 @@ bool ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &e
|
||||
// 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>(&extractor_config.input_path),
|
||||
"Input file in .osm, .osm.bz2 or .osm.pbf format");
|
||||
hidden_options.add_options()("input,i", boost::program_options::value<boost::filesystem::path>(
|
||||
&extractor_config.input_path),
|
||||
"Input file in .osm, .osm.bz2 or .osm.pbf format");
|
||||
|
||||
// positional option
|
||||
boost::program_options::positional_options_description positional_options;
|
||||
@ -81,46 +80,54 @@ bool ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &e
|
||||
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);
|
||||
|
||||
if (option_variables.count("version"))
|
||||
try
|
||||
{
|
||||
SimpleLogger().Write() << g_GIT_DESCRIPTION;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (option_variables.count("help"))
|
||||
{
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::program_options::notify(option_variables);
|
||||
|
||||
// parse config file
|
||||
if (boost::filesystem::is_regular_file(extractor_config.config_file_path))
|
||||
{
|
||||
SimpleLogger().Write() << "Reading options from: "
|
||||
<< extractor_config.config_file_path.string();
|
||||
std::string ini_file_contents =
|
||||
ReadIniFileAndLowerContents(extractor_config.config_file_path);
|
||||
std::stringstream config_stream(ini_file_contents);
|
||||
boost::program_options::store(parse_config_file(config_stream, config_file_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);
|
||||
if (option_variables.count("version"))
|
||||
{
|
||||
SimpleLogger().Write() << g_GIT_DESCRIPTION;
|
||||
return return_code::exit;
|
||||
}
|
||||
|
||||
if (option_variables.count("help"))
|
||||
{
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return return_code::exit;
|
||||
}
|
||||
|
||||
boost::program_options::notify(option_variables);
|
||||
|
||||
// parse config file
|
||||
if (boost::filesystem::is_regular_file(extractor_config.config_file_path))
|
||||
{
|
||||
SimpleLogger().Write()
|
||||
<< "Reading options from: " << extractor_config.config_file_path.string();
|
||||
std::string ini_file_contents =
|
||||
read_file_lower_content(extractor_config.config_file_path);
|
||||
std::stringstream config_stream(ini_file_contents);
|
||||
boost::program_options::store(parse_config_file(config_stream, config_file_options),
|
||||
option_variables);
|
||||
boost::program_options::notify(option_variables);
|
||||
}
|
||||
|
||||
if (!option_variables.count("input"))
|
||||
{
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return return_code::exit;
|
||||
}
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << e.what();
|
||||
return return_code::fail;
|
||||
}
|
||||
|
||||
if (!option_variables.count("input"))
|
||||
{
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return return_code::ok;
|
||||
}
|
||||
|
||||
void ExtractorOptions::GenerateOutputFilesNames(ExtractorConfig &extractor_config)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -28,12 +28,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef EXTRACTOR_OPTIONS_HPP
|
||||
#define EXTRACTOR_OPTIONS_HPP
|
||||
|
||||
#include "extractor.hpp"
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
enum class return_code : unsigned
|
||||
{
|
||||
ok,
|
||||
fail,
|
||||
exit
|
||||
};
|
||||
|
||||
struct ExtractorConfig
|
||||
{
|
||||
ExtractorConfig() noexcept : requested_num_threads(0) {}
|
||||
unsigned requested_num_threads;
|
||||
boost::filesystem::path config_file_path;
|
||||
boost::filesystem::path input_path;
|
||||
boost::filesystem::path profile_path;
|
||||
@ -41,11 +49,13 @@ struct ExtractorConfig
|
||||
std::string output_file_name;
|
||||
std::string restriction_file_name;
|
||||
std::string timestamp_file_name;
|
||||
|
||||
unsigned requested_num_threads;
|
||||
};
|
||||
|
||||
struct ExtractorOptions
|
||||
{
|
||||
static bool ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config);
|
||||
static return_code ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config);
|
||||
|
||||
static void GenerateOutputFilesNames(ExtractorConfig &extractor_config);
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user