diff --git a/.gitignore b/.gitignore index b905eeafb..6ed5d2a4e 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/.travis.yml b/.travis.yml index 643e00dff..ed023e4e9 100644 --- a/.travis.yml +++ b/.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 diff --git a/CMakeLists.txt b/CMakeLists.txt index b6a40f916..503171a59 100644 --- a/CMakeLists.txt +++ b/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} $ $ $ $ $ $) +add_executable(osrm-extract ${ExtractorSources} $ $ $ $ $ $ $) 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} $ $ $ $ $ $ $) +add_executable(osrm-prepare ${PrepareSources} $ $ $ $ $ $ $ $ $) -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} $ $ $ $ $ $) +add_library(GITDESCRIPTION OBJECT util/git_sha.cpp) +add_library(OSRM ${OSRMSources} $ $ $ $ $ $ $ $ $) + +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} $) -add_executable(osrm-datastore datastore.cpp $ $ $ $ $) +add_executable(osrm-datastore datastore.cpp $ $ $ $ $ $) # Unit tests -add_executable(datastructure-tests EXCLUDE_FROM_ALL UnitTests/datastructure_tests.cpp ${DataStructureTestsGlob} $ $ $ $) -add_executable(algorithm-tests EXCLUDE_FROM_ALL UnitTests/algorithm_tests.cpp ${AlgorithmTestsGlob} $ $ $ $) +add_executable(datastructure-tests EXCLUDE_FROM_ALL unit_tests/datastructure_tests.cpp ${DataStructureTestsGlob} $ $ $ $ $) +add_executable(algorithm-tests EXCLUDE_FROM_ALL unit_tests/algorithm_tests.cpp ${AlgorithmTestsGlob} $ $ $ $) # Benchmarks -add_executable(rtree-bench EXCLUDE_FROM_ALL benchmarks/static_rtree.cpp $ $ $ $) +add_executable(rtree-bench EXCLUDE_FROM_ALL benchmarks/static_rtree.cpp $ $ $ $ $) # 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 $ $ $ $ $ $) + add_executable(osrm-components tools/components.cpp $ $ $ $ $ $ $) 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 $ $) + add_executable(osrm-cli tools/simpleclient.cpp $ $ $) 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 $ $ $) @@ -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 $ $ $) + add_executable(osrm-check-hsgr tools/check-hsgr.cpp $ $ $) target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES}) add_executable(osrm-springclean tools/springclean.cpp $ $ $ $) target_link_libraries(osrm-springclean ${Boost_LIBRARIES}) + add_executable(osrm-graph-compare tools/graph_compare.cpp $ $ $ $ $ $ $) + 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) diff --git a/Gemfile b/Gemfile index 114808e49..31d044bd6 100644 --- a/Gemfile +++ b/Gemfile @@ -4,4 +4,4 @@ gem "cucumber" gem "rake" gem "osmlib-base" gem "sys-proctable" -gem "rspec-expectations" \ No newline at end of file +gem "rspec-expectations" diff --git a/Include/osrm/Coordinate.h b/Include/osrm/Coordinate.h deleted file mode 100644 index baac61f94..000000000 --- a/Include/osrm/Coordinate.h +++ /dev/null @@ -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 //for std::ostream -#include -#include - -namespace -{ -constexpr float COORDINATE_PRECISION = 1000000.f; -} -struct FixedPointCoordinate -{ - int lat; - int lon; - - FixedPointCoordinate(); - FixedPointCoordinate(int lat, int lon); - - template - FixedPointCoordinate(const T &coordinate) : lat(coordinate.lat), lon(coordinate.lon) - { - static_assert(std::is_same::value, "coordinate types incompatible"); - static_assert(std::is_same::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_ */ diff --git a/Include/osrm/Reply.h b/Include/osrm/Reply.h deleted file mode 100644 index a2ee1f486..000000000 --- a/Include/osrm/Reply.h +++ /dev/null @@ -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 - -#include - -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
headers; - std::vector ToBuffers(); - std::vector HeaderstoBuffers(); - std::vector 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 diff --git a/LICENCE.TXT b/LICENCE.TXT index 28fe97b35..c77e5cd1b 100644 --- a/LICENCE.TXT +++ b/LICENCE.TXT @@ -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, diff --git a/Server/APIGrammar.h b/Server/APIGrammar.h deleted file mode 100644 index 83a5cd03b..000000000 --- a/Server/APIGrammar.h +++ /dev/null @@ -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 -#include -#include - -namespace qi = boost::spirit::qi; - -template -struct APIGrammar : qi::grammar -{ - 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 api_call, query; - qi::rule 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_ */ diff --git a/Server/RequestHandler.cpp b/Server/RequestHandler.cpp deleted file mode 100644 index b1178ba2b..000000000 --- a/Server/RequestHandler.cpp +++ /dev/null @@ -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 -#include - -#include - -#include -#include - -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; } diff --git a/Server/RequestParser.cpp b/Server/RequestParser.cpp deleted file mode 100644 index a599381f0..000000000 --- a/Server/RequestParser.cpp +++ /dev/null @@ -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 -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'; } -} diff --git a/Util/TrigonometryTables.h b/Util/TrigonometryTables.h deleted file mode 100644 index d14540482..000000000 --- a/Util/TrigonometryTables.h +++ /dev/null @@ -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 - -#include - -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::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 diff --git a/Util/graph_loader.hpp b/Util/graph_loader.hpp deleted file mode 100644 index 5ab8eba83..000000000 --- a/Util/graph_loader.hpp +++ /dev/null @@ -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 -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include - -template -NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, - std::vector &edge_list, - std::vector &barrier_node_list, - std::vector &traffic_light_node_list, - std::vector *int_to_ext_node_id_map, - std::vector &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 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 -unsigned readHSGRFromStream(const boost::filesystem::path &hsgr_file, - std::vector &node_list, - std::vector &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 diff --git a/Util/range_algorithms.hpp b/Util/range_algorithms.hpp deleted file mode 100644 index 208236e6c..000000000 --- a/Util/range_algorithms.hpp +++ /dev/null @@ -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 - -namespace osrm { - -template -auto max_element(const Container & c) -> decltype(std::max_element(c.begin(), c.end())) -{ - return std::max_element(c.begin(), c.end()); -} - -template -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 diff --git a/algorithms/bayes_classifier.hpp b/algorithms/bayes_classifier.hpp new file mode 100644 index 000000000..3358144c7 --- /dev/null +++ b/algorithms/bayes_classifier.hpp @@ -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 + +#include + +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 +class BayesClassifier +{ + public: + enum class ClassLabel : unsigned + { + NEGATIVE, + POSITIVE + }; + using ClassificationT = std::pair; + + 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 diff --git a/algorithms/bfs_components.hpp b/algorithms/bfs_components.hpp index 57be63553..b3f536401 100644 --- a/algorithms/bfs_components.hpp +++ b/algorithms/bfs_components.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 class BFSComponentExplorer * Explores the current component that starts at node using BFS. */ unsigned ExploreComponent(std::queue> &bfs_queue, - NodeID node, - unsigned current_component) + NodeID node, + unsigned current_component) { /* Graphical representation of variables: @@ -118,7 +118,7 @@ template class BFSComponentExplorer std::pair 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; diff --git a/algorithms/crc32_processor.hpp b/algorithms/crc32_processor.hpp index a68514dce..a31b4ad23 100644 --- a/algorithms/crc32_processor.hpp +++ b/algorithms/crc32_processor.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, @@ -49,7 +49,7 @@ class IteratorbasedCRC32 while (iter != end) { using value_type = typename std::iterator_traits::value_type; - char *data = (char *)(&(*iter)); + const char *data = reinterpret_cast(&(*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(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 - unsigned operator()(const Iteratable &iterable) + template unsigned operator()(const Iteratable &iterable) { return crc32(std::begin(iterable), std::end(iterable)); } diff --git a/algorithms/douglas_peucker.cpp b/algorithms/douglas_peucker.cpp index 362f0a5a8..fa7d7826b 100644 --- a/algorithms/douglas_peucker.cpp +++ b/algorithms/douglas_peucker.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, @@ -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 #include +#include #include - #include +#include 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(std::min(dist1, dist2)); @@ -90,7 +88,7 @@ void DouglasPeucker::Run(std::vector &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; diff --git a/algorithms/douglas_peucker.hpp b/algorithms/douglas_peucker.hpp index 417e80a38..da02982f3 100644 --- a/algorithms/douglas_peucker.hpp +++ b/algorithms/douglas_peucker.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, @@ -28,9 +28,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef DOUGLAS_PEUCKER_HPP_ #define DOUGLAS_PEUCKER_HPP_ -#include -#include +#include "../data_structures/segment_information.hpp" + #include +#include +#include +#include /* 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 DOUGLAS_PEUCKER_THRESHOLDS {{ +static const std::array DOUGLAS_PEUCKER_THRESHOLDS{{ 512440, // z0 256720, // z1 122560, // z2 diff --git a/algorithms/object_encoder.hpp b/algorithms/object_encoder.hpp index af6e0d9ca..e880496a2 100644 --- a/algorithms/object_encoder.hpp +++ b/algorithms/object_encoder.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, @@ -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 #include @@ -49,10 +49,9 @@ struct ObjectEncoder 8, 6>; - template - static void EncodeToBase64(const ObjectT &object, std::string &encoded) + template 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(&object); std::vector 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 - static void DecodeFromBase64(const std::string &input, ObjectT &object) + template 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(&object)); } catch (...) { diff --git a/algorithms/polyline_compressor.cpp b/algorithms/polyline_compressor.cpp index 2f2972b15..d5fd5828b 100644 --- a/algorithms/polyline_compressor.cpp +++ b/algorithms/polyline_compressor.cpp @@ -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 +#include std::string PolylineCompressor::encode_vector(std::vector &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(next_value); - if (92 == next_value) - { - output += static_cast(next_value); - } number_to_encode >>= 5; } number_to_encode += 63; output += static_cast(number_to_encode); - if (92 == number_to_encode) - { - output += static_cast(number_to_encode); - } return output; } diff --git a/algorithms/polyline_compressor.hpp b/algorithms/polyline_compressor.hpp index 8bff4a040..933ac7afa 100644 --- a/algorithms/polyline_compressor.hpp +++ b/algorithms/polyline_compressor.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, diff --git a/algorithms/polyline_formatter.cpp b/algorithms/polyline_formatter.cpp index d72496ad6..670a6121f 100644 --- a/algorithms/polyline_formatter.cpp +++ b/algorithms/polyline_formatter.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, @@ -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 +#include -JSON::String +osrm::json::String PolylineFormatter::printEncodedString(const std::vector &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 &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); diff --git a/algorithms/polyline_formatter.hpp b/algorithms/polyline_formatter.hpp index 1d4744d0a..68cc70293 100644 --- a/algorithms/polyline_formatter.hpp +++ b/algorithms/polyline_formatter.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. struct SegmentInformation; -#include "../data_structures/json_container.hpp" +#include #include #include struct PolylineFormatter { - JSON::String printEncodedString(const std::vector &polyline) const; + osrm::json::String printEncodedString(const std::vector &polyline) const; - JSON::Array printUnencodedString(const std::vector &polyline) const; + osrm::json::Array printUnencodedString(const std::vector &polyline) const; }; #endif /* POLYLINE_FORMATTER_HPP */ diff --git a/algorithms/route_name_extraction.hpp b/algorithms/route_name_extraction.hpp index 519452f98..00dae89c4 100644 --- a/algorithms/route_name_extraction.hpp +++ b/algorithms/route_name_extraction.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 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 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 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 struct ExtractRouteNames // alternative std::vector 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 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 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 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; } diff --git a/algorithms/tiny_components.hpp b/algorithms/tiny_components.hpp index 5cf5a75c6..8eb61a912 100644 --- a/algorithms/tiny_components.hpp +++ b/algorithms/tiny_components.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, @@ -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 +#include #include #include - #include #include @@ -57,8 +56,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -template -class TarjanSCC +template class TarjanSCC { struct TarjanStackFrame { @@ -80,16 +78,15 @@ class TarjanSCC std::shared_ptr m_node_based_graph; std::unordered_set barrier_node_set; RestrictionMap m_restriction_map; - unsigned size_one_counter; + std::size_t size_one_counter; public: - template + template TarjanSCC(std::shared_ptr 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 recursion_stack; // true = stuff before, false = stuff after call std::stack tarjan_stack; - std::vector tarjan_node_list(m_node_based_graph->GetNumberOfNodes()); + std::vector 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 processing_node_before_recursion(m_node_based_graph->GetNumberOfNodes(), true); - for(const NodeID node : osrm::irange(0u, last_node)) + unsigned index = 0; + std::vector 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::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 */ diff --git a/appveyor.yml b/appveyor.yml index e650e1ae1..afb8dd406 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -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 diff --git a/benchmarks/static_rtree.cpp b/benchmarks/static_rtree.cpp index 7a24cfc8c..9d883311b 100644 --- a/benchmarks/static_rtree.cpp +++ b/benchmarks/static_rtree.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, @@ -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 +#include #include @@ -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); diff --git a/cmake/FingerPrint-Config.cmake b/cmake/FingerPrint-Config.cmake index 710368d7b..a3325d305 100644 --- a/cmake/FingerPrint-Config.cmake +++ b/cmake/FingerPrint-Config.cmake @@ -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) diff --git a/contractor/contractor.hpp b/contractor/contractor.hpp index c8c107cdb..ccfabbc8f 100644 --- a/contractor/contractor.hpp +++ b/contractor/contractor.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 @@ -92,9 +92,11 @@ class Contractor }; using ContractorGraph = DynamicGraph; - // using ContractorHeap = BinaryHeap + // using ContractorHeap = BinaryHeap // >; - using ContractorHeap = BinaryHeap>; + using ContractorHeap = + BinaryHeap>; 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(number_of_nodes); @@ -149,7 +150,8 @@ class Contractor } int number_of_nodes; - using EnumerableThreadData = tbb::enumerable_thread_specific>; + using EnumerableThreadData = + tbb::enumerable_thread_specific>; 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(std::max(diter->weight, 1)) > 0, "edge distance < 1"); + BOOST_ASSERT_MSG(static_cast(std::max(diter->weight, 1)) > 0, + "edge distance < 1"); #ifndef NDEBUG if (static_cast(std::max(diter->weight, 1)) > 24 * 60 * 60 * 10) { - SimpleLogger().Write(logWARNING) << "Edge weight large -> " - << static_cast(std::max(diter->weight, 1)); + SimpleLogger().Write(logWARNING) + << "Edge weight large -> " + << static_cast(std::max(diter->weight, 1)); } #endif edges.emplace_back(diter->source, diter->target, - static_cast(std::max(diter->weight, 1)), - 1, - diter->edge_id, - false, - diter->forward ? true : false, - diter->backward ? true : false); + static_cast(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(std::max(diter->weight, 1)), - 1, - diter->edge_id, - false, - diter->backward ? true : false, - diter->forward ? true : false); + static_cast(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 node_priorities(number_of_nodes); std::vector node_data(number_of_nodes); - // initialize priorities in parallel tbb::parallel_for(tbb::blocked_range(0, number_of_nodes, InitGrainSize), - [&remaining_nodes](const tbb::blocked_range& range) - { - for (int x = range.begin(); x != range.end(); ++x) - { - remaining_nodes[x].id = x; - } - } - ); - + [&remaining_nodes](const tbb::blocked_range &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(0, number_of_nodes, PQGrainSize), - [this, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range& 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 &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(0, contractor_graph->GetNumberOfNodes())) + for (const auto i : + osrm::irange(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(0, last, IndependentGrainSize), - [this, &node_priorities, &remaining_nodes, &thread_data_list](const tbb::blocked_range& 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 &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(first - remaining_nodes.begin()); // contract independent nodes - tbb::parallel_for(tbb::blocked_range(first_independent_node, last, ContractGrainSize), - [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range& range) + tbb::parallel_for( + tbb::blocked_range(first_independent_node, last, ContractGrainSize), + [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range &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(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(first_independent_node, last, DeleteGrainSize), - [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range& range) + for (auto &data : range) + std::sort(data->inserted_edges.begin(), data->inserted_edges.end()); + }); + tbb::parallel_for( + tbb::blocked_range(first_independent_node, last, DeleteGrainSize), + [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range &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(first_independent_node, last, NeighboursGrainSize), - [this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range& range) + tbb::parallel_for( + tbb::blocked_range(first_independent_node, last, NeighboursGrainSize), + [this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list]( + const tbb::blocked_range &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 &priorities, - ContractorThreadData *const data, - NodeID node) const + inline bool IsNodeIndependent(const std::vector &priorities, + ContractorThreadData *const data, + NodeID node) const { const float priority = priorities[node]; diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp index 144b1faaf..268bb9f8d 100644 --- a/contractor/edge_based_graph_factory.cpp +++ b/contractor/edge_based_graph_factory.cpp @@ -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 @@ -77,33 +77,25 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodes(std::vector &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 &forward_geometry = - m_geometry_compressor.GetBucketReference(e1); + m_geometry_compressor.GetBucketReference(edge_id_1); const std::vector &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(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 &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 component_explorer( - m_node_based_graph, *m_restriction_map, m_barrier_nodes); + TarjanSCC 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(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) { diff --git a/contractor/geometry_compressor.cpp b/contractor/geometry_compressor.cpp index 9458c4415..3997cdc99 100644 --- a/contractor/geometry_compressor.cpp +++ b/contractor/geometry_compressor.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,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 #include @@ -35,9 +35,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -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; +} diff --git a/contractor/geometry_compressor.hpp b/contractor/geometry_compressor.hpp index dd5748d91..ca83fa44c 100644 --- a/contractor/geometry_compressor.hpp +++ b/contractor/geometry_compressor.hpp @@ -58,6 +58,8 @@ class GeometryCompressor NodeID GetLastNodeIDOfBucket(const EdgeID edge_id) const; private: + int free_list_maximum = 0; + void IncreaseFreeList(); std::vector> m_compressed_geometries; std::vector m_free_list; diff --git a/contractor/processing_chain.cpp b/contractor/processing_chain.cpp index 23d406b2e..ccff7fd09 100644 --- a/contractor/processing_chain.cpp +++ b/contractor/processing_chain.cpp @@ -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 @@ -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 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(&config_file_path) - ->default_value("contractor.ini"), + "config,c", boost::program_options::value(&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(&restrictions_path), "Restrictions file in .osrm.restrictions format")( - "profile,p", - boost::program_options::value(&profile_path) - ->default_value("profile.lua"), + "profile,p", boost::program_options::value(&profile_path) + ->default_value("profile.lua"), "Path to LUA routing profile")( - "threads,t", - boost::program_options::value(&requested_num_threads) - ->default_value(tbb::task_scheduler_init::default_num_threads()), + "threads,t", boost::program_options::value(&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(&input_path), + "input,i", boost::program_options::value(&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(); + const auto &temp_config_path = option_variables["config"].as(); if (boost::filesystem::is_regular_file(temp_config_path)) { - boost::program_options::store(boost::program_options::parse_config_file(temp_config_path.string().c_str(), cmdline_options, true), + boost::program_options::store(boost::program_options::parse_config_file( + 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 node_based_graph = NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list); - std::unique_ptr restriction_map = osrm::make_unique(restriction_list); + std::unique_ptr restriction_map = + osrm::make_unique(restriction_list); std::shared_ptr edge_based_graph_factory = - std::make_shared(node_based_graph, - std::move(restriction_map), - barrier_node_list, - traffic_light_list, - internal_to_external_node_map, - speed_profile); + std::make_shared(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 &node_based_edge_list) { SimpleLogger().Write() << "building r-tree ..."; - StaticRTree(node_based_edge_list, - rtree_nodes_path.c_str(), - rtree_leafs_path.c_str(), - internal_to_external_node_map); + StaticRTree(node_based_edge_list, rtree_nodes_path.c_str(), + rtree_leafs_path.c_str(), internal_to_external_node_map); } diff --git a/data_structures/Coordinate.cpp b/data_structures/Coordinate.cpp deleted file mode 100644 index 4305256ef..000000000 --- a/data_structures/Coordinate.cpp +++ /dev/null @@ -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 -#include "../Util/MercatorUtil.h" -#ifndef NDEBUG -#include "../Util/simple_logger.hpp" -#endif -#include "../Util/string_util.hpp" - -#include - -#ifndef NDEBUG -#include -#endif -#include -#include - -FixedPointCoordinate::FixedPointCoordinate() - : lat(std::numeric_limits::min()), lon(std::numeric_limits::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::min(); - lon = std::numeric_limits::min(); -} -bool FixedPointCoordinate::isSet() const -{ - return (std::numeric_limits::min() != lat) && (std::numeric_limits::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::min()); - BOOST_ASSERT(lon1 != std::numeric_limits::min()); - BOOST_ASSERT(lat2 != std::numeric_limits::min()); - BOOST_ASSERT(lon2 != std::numeric_limits::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::min()); - BOOST_ASSERT(lon1 != std::numeric_limits::min()); - BOOST_ASSERT(lat2 != std::numeric_limits::min()); - BOOST_ASSERT(lon2 != std::numeric_limits::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(lat2y(point.lat / COORDINATE_PRECISION)); - const float y_value = point.lon / COORDINATE_PRECISION; - float a = static_cast(lat2y(source_coordinate.lat / COORDINATE_PRECISION)); - float b = source_coordinate.lon / COORDINATE_PRECISION; - float c = static_cast(lat2y(target_coordinate.lat / COORDINATE_PRECISION)); - float d = target_coordinate.lon / COORDINATE_PRECISION; - float p, q; - if (std::abs(a - c) > std::numeric_limits::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::epsilon() && - std::abs(a) < std::numeric_limits::epsilon()) - { - ratio = (q - b) / (d - b); - } - else - { - if (std::abs(c) < std::numeric_limits::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::epsilon()) - { - ratio = 0.f; - } - else if (std::abs(ratio - 1.f) <= std::numeric_limits::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(y2lat(p) * COORDINATE_PRECISION); - nearest_location.lon = static_cast(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::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::epsilon()) - { - ratio = 0.f; - } - else if (std::abs(ratio - 1.f) <= std::numeric_limits::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(y2lat(p) * COORDINATE_PRECISION); - nearest_location.lon = static_cast(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(M_PI) / 180.f); -} - -float FixedPointCoordinate::RadianToDegree(const float radian) -{ - return radian * (180.f * static_cast(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(lat2y(input_point.lat / COORDINATE_PRECISION)); - const float y = input_point.lon / COORDINATE_PRECISION; - const float a = static_cast(lat2y(segment_source.lat / COORDINATE_PRECISION)); - const float b = segment_source.lon / COORDINATE_PRECISION; - const float c = static_cast(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(q * COORDINATE_PRECISION); - dy = input_point.lat - static_cast(y2lat(p) * COORDINATE_PRECISION); - } - - // return an approximation in the plane - return static_cast(sqrt(dx * dx + dy * dy)); -} diff --git a/data_structures/InputReaderFactory.h b/data_structures/InputReaderFactory.h deleted file mode 100644 index 3f6aa3c63..000000000 --- a/data_structures/InputReaderFactory.h +++ /dev/null @@ -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 - -#include -#include - -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 diff --git a/data_structures/binary_heap.hpp b/data_structures/binary_heap.hpp index 049f12fca..a23a6b0f5 100644 --- a/data_structures/binary_heap.hpp +++ b/data_structures/binary_heap.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, @@ -36,24 +36,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include template 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 positions; }; template class MapStorage @@ -65,6 +63,16 @@ template 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::max(); + } + private: std::map nodes; }; @@ -76,6 +84,16 @@ template 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::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(inserted_nodes.size())) + const auto index = node_index.peek_index(node); + if (index >= static_cast(inserted_nodes.size())) { return false; } @@ -200,7 +218,7 @@ class BinaryHeap void DecreaseKey(NodeID node, Weight weight) { BOOST_ASSERT(std::numeric_limits::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(heap.size()); Key nextKey = key << 1; - while (nextKey < static_cast(heap.size())) + while (nextKey < heap_size) { const Key nextKeyOther = nextKey + 1; - if ((nextKeyOther < static_cast(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); } diff --git a/data_structures/concurrent_queue.hpp b/data_structures/concurrent_queue.hpp index b3d4e1a2a..7341a8cc4 100644 --- a/data_structures/concurrent_queue.hpp +++ b/data_structures/concurrent_queue.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, @@ -40,9 +40,10 @@ template class ConcurrentQueue inline void push(const Data &data) { std::unique_lock 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 class ConcurrentQueue inline void wait_and_pop(Data &popped_value) { std::unique_lock 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(); diff --git a/data_structures/coordinate.cpp b/data_structures/coordinate.cpp new file mode 100644 index 000000000..df3abe44a --- /dev/null +++ b/data_structures/coordinate.cpp @@ -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 + +#ifndef NDEBUG +#include +#endif +#include +#include + +FixedPointCoordinate::FixedPointCoordinate() + : lat(std::numeric_limits::min()), lon(std::numeric_limits::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); +} diff --git a/data_structures/coordinate_calculation.cpp b/data_structures/coordinate_calculation.cpp new file mode 100644 index 000000000..0c44989b4 --- /dev/null +++ b/data_structures/coordinate_calculation.cpp @@ -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 + +#include + +#include + +#include + +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::min()); + BOOST_ASSERT(lon1 != std::numeric_limits::min()); + BOOST_ASSERT(lat2 != std::numeric_limits::min()); + BOOST_ASSERT(lon2 != std::numeric_limits::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::min()); + BOOST_ASSERT(lon1 != std::numeric_limits::min()); + BOOST_ASSERT(lat2 != std::numeric_limits::min()); + BOOST_ASSERT(lon2 != std::numeric_limits::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 &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 &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::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((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::epsilon()) + { + ratio = 0.f; + } + else if (std::abs(ratio - 1.f) <= std::numeric_limits::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(mercator::y2lat(p) * COORDINATE_PRECISION); + nearest_location.lon = static_cast(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(M_PI) / 180.f); +} + +float coordinate_calculation::rad_to_deg(const float radian) +{ + return radian * (180.f * static_cast(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; +} diff --git a/data_structures/coordinate_calculation.hpp b/data_structures/coordinate_calculation.hpp new file mode 100644 index 000000000..73183dfa4 --- /dev/null +++ b/data_structures/coordinate_calculation.hpp @@ -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 +#include + +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 &projected_coordinate); + + static float perpendicular_distance_from_projected_coordinate( + const FixedPointCoordinate &segment_source, + const FixedPointCoordinate &segment_target, + const FixedPointCoordinate &query_location, + const std::pair &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 diff --git a/data_structures/deallocating_vector.hpp b/data_structures/deallocating_vector.hpp index 415fa69d3..de5a24d85 100644 --- a/data_structures/deallocating_vector.hpp +++ b/data_structures/deallocating_vector.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,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 +#include #include #include template struct DeallocatingVectorIteratorState { - DeallocatingVectorIteratorState() : index(-1), bucket_list(nullptr) {} + DeallocatingVectorIteratorState() + : index(std::numeric_limits::max()), bucket_list(nullptr) + { + } explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : index(r.index), bucket_list(r.bucket_list) { @@ -50,7 +54,7 @@ template struct DeallocatingVectorIteratorState std::size_t index; std::vector *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; - 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 &other) + void swap(DeallocatingVector &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 inline void emplace_back(Ts &&... element) + template 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(0), &bucket_list); } + iterator begin() { return iterator(static_cast(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(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(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 - const inline void append(InputIterator first, const InputIterator last) + template 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 */ diff --git a/data_structures/dynamic_graph.hpp b/data_structures/dynamic_graph.hpp index 7244d1e9c..43e6c3aca 100644 --- a/data_structures/dynamic_graph.hpp +++ b/data_structures/dynamic_graph.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 #include #include -#include -#include #include +#include +#include +#include template class DynamicGraph { @@ -55,26 +57,29 @@ template class DynamicGraph NodeIterator target; EdgeDataT data; - InputEdge() : source(std::numeric_limits::max()), target(std::numeric_limits::max()) { } - - template - InputEdge(NodeIterator source, NodeIterator target, Ts &&...data) : source(source), target(target), data(std::forward(data)...) { } - - bool operator<(const InputEdge &right) const + InputEdge() + : source(std::numeric_limits::max()), + target(std::numeric_limits::max()) { - if (source != right.source) - { - return source < right.source; - } - return target < right.target; + } + + template + InputEdge(NodeIterator source, NodeIterator target, Ts &&... data) + : source(source), target(target), data(std::forward(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 class DynamicGraph template 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(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(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 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 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 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 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 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::max() != node.edges); - const unsigned last = node.firstEdge + node.edges; + const unsigned last = node.first_edge + node.edges; BOOST_ASSERT(std::numeric_limits::max() != last); // swap with last edge edge_list[e] = edge_list[last]; @@ -242,7 +247,7 @@ template class DynamicGraph } number_of_edges -= deleted; - node_list[source].edges -= deleted; + node_array[source].edges -= deleted; return deleted; } @@ -257,7 +262,46 @@ template 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 class DynamicGraph struct Node { // index of the first edge - EdgeIterator firstEdge; + EdgeIterator first_edge; // amount of edges unsigned edges; }; @@ -288,7 +332,7 @@ template class DynamicGraph NodeIterator number_of_nodes; std::atomic_uint number_of_edges; - std::vector node_list; + std::vector node_array; DeallocatingVector edge_list; }; diff --git a/data_structures/edge_based_node.hpp b/data_structures/edge_based_node.hpp index 98746d9a8..72a585a13 100644 --- a/data_structures/edge_based_node.hpp +++ b/data_structures/edge_based_node.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, @@ -31,94 +31,74 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/travel_mode.hpp" #include "../typedefs.h" -#include - #include +#include + #include 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::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::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 diff --git a/data_structures/external_memory_node.cpp b/data_structures/external_memory_node.cpp index cd6271b1c..72b8198f9 100644 --- a/data_structures/external_memory_node.cpp +++ b/data_structures/external_memory_node.cpp @@ -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 @@ -44,11 +45,8 @@ ExternalMemoryNode ExternalMemoryNode::min_value() ExternalMemoryNode ExternalMemoryNode::max_value() { - return ExternalMemoryNode(std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::max(), - false, - false); + return ExternalMemoryNode(std::numeric_limits::max(), std::numeric_limits::max(), + std::numeric_limits::max(), false, false); } bool ExternalMemoryNodeSTXXLCompare::operator()(const ExternalMemoryNode &left, diff --git a/data_structures/external_memory_node.hpp b/data_structures/external_memory_node.hpp index f88a23e7b..83b88e759 100644 --- a/data_structures/external_memory_node.hpp +++ b/data_structures/external_memory_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, @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "query_node.hpp" -#include +#include "../typedefs.h" struct ExternalMemoryNode : QueryNode { diff --git a/data_structures/fixed_point_number.hpp b/data_structures/fixed_point_number.hpp index eab685026..c7ed257e5 100644 --- a/data_structures/fixed_point_number.hpp +++ b/data_structures/fixed_point_number.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, diff --git a/data_structures/hidden_markov_model.hpp b/data_structures/hidden_markov_model.hpp new file mode 100644 index 000000000..cccaf7b5d --- /dev/null +++ b/data_structures/hidden_markov_model.hpp @@ -0,0 +1,158 @@ +/* + +Copyright (c) 2015, Project OSRM contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef HIDDEN_MARKOV_MODEL +#define HIDDEN_MARKOV_MODEL + +#include "../util/integer_range.hpp" + +#include + +#include + +#include +#include + +namespace osrm +{ +namespace matching +{ +static const double log_2_pi = std::log(2. * M_PI); +static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits::infinity(); +static const double MINIMAL_LOG_PROB = std::numeric_limits::lowest(); +static const std::size_t INVALID_STATE = std::numeric_limits::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 struct HiddenMarkovModel +{ + std::vector> viterbi; + std::vector>> parents; + std::vector> path_lengths; + std::vector> pruned; + std::vector> suspicious; + std::vector 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(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 diff --git a/data_structures/hilbert_value.cpp b/data_structures/hilbert_value.cpp index 216b7c553..c09773118 100644 --- a/data_structures/hilbert_value.cpp +++ b/data_structures/hilbert_value.cpp @@ -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 +#include uint64_t HilbertCode::operator()(const FixedPointCoordinate ¤t_coordinate) const { diff --git a/data_structures/hilbert_value.hpp b/data_structures/hilbert_value.hpp index e1940296e..7b8bffa93 100644 --- a/data_structures/hilbert_value.hpp +++ b/data_structures/hilbert_value.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, diff --git a/data_structures/import_edge.cpp b/data_structures/import_edge.cpp index 55f5f161e..f41b066b1 100644 --- a/data_structures/import_edge.cpp +++ b/data_structures/import_edge.cpp @@ -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 +#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) { } diff --git a/data_structures/import_edge.hpp b/data_structures/import_edge.hpp index f9004d45a..f422de116 100644 --- a/data_structures/import_edge.hpp +++ b/data_structures/import_edge.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, diff --git a/data_structures/raw_route_data.hpp b/data_structures/internal_route_result.hpp similarity index 80% rename from data_structures/raw_route_data.hpp rename to data_structures/internal_route_result.hpp index f9242cfb0..068b63a80 100644 --- a/data_structures/raw_route_data.hpp +++ b/data_structures/internal_route_result.hpp @@ -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 +#include #include 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> unpacked_path_segments; std::vector 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 diff --git a/data_structures/lru_cache.hpp b/data_structures/lru_cache.hpp index cdbeb389c..155ab1ef4 100644 --- a/data_structures/lru_cache.hpp +++ b/data_structures/lru_cache.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, @@ -86,7 +86,7 @@ template 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; } diff --git a/data_structures/node_based_graph.hpp b/data_structures/node_based_graph.hpp index 8fe7b7550..54e07a7ec 100644 --- a/data_structures/node_based_graph.hpp +++ b/data_structures/node_based_graph.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,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 @@ -40,9 +40,9 @@ struct NodeBasedEdgeData { NodeBasedEdgeData() : distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID), - nameID(std::numeric_limits::max()), - isAccessRestricted(false), shortcut(false), forward(false), backward(false), - roundabout(false), ignore_in_grid(false), travel_mode(TRAVEL_MODE_INACCESSIBLE) + nameID(std::numeric_limits::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; inline std::shared_ptr NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector &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 edges_list; NodeBasedDynamicGraph::InputEdge edge; @@ -111,7 +112,7 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector(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::max(); + forward_edge.data.distance = reverse_edge.data.distance = std::numeric_limits::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::max()) + if (static_cast(forward_edge.data.distance) != std::numeric_limits::max()) { forward_edge.data.backward = true; edges_list[edge_count++] = forward_edge; @@ -178,28 +179,31 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector::max()) + if (static_cast(forward_edge.data.distance) != std::numeric_limits::max()) { edges_list[edge_count++] = forward_edge; } - if ((int)reverse_edge.data.distance != std::numeric_limits::max()) + if (static_cast(reverse_edge.data.distance) != std::numeric_limits::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(static_cast(number_of_nodes), edges_list); + auto graph = std::make_shared( + static_cast(number_of_nodes), edges_list); return graph; } -template +template inline std::shared_ptr SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector &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 edges_list; @@ -218,10 +222,10 @@ SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector(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(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(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(number_of_nodes, edges_list); return graph; diff --git a/data_structures/node_id.hpp b/data_structures/node_id.hpp index 4f0780965..4d6fff0b2 100644 --- a/data_structures/node_id.hpp +++ b/data_structures/node_id.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, diff --git a/data_structures/original_edge_data.hpp b/data_structures/original_edge_data.hpp index b4fdfd97f..cbbc1b276 100644 --- a/data_structures/original_edge_data.hpp +++ b/data_structures/original_edge_data.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, @@ -48,9 +48,8 @@ struct OriginalEdgeData OriginalEdgeData() : via_node(std::numeric_limits::max()), - name_id(std::numeric_limits::max()), - turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false), - travel_mode(TRAVEL_MODE_INACCESSIBLE) + name_id(std::numeric_limits::max()), turn_instruction(TurnInstruction::NoTurn), + compressed_geometry(false), travel_mode(TRAVEL_MODE_INACCESSIBLE) { } diff --git a/data_structures/percent.hpp b/data_structures/percent.hpp index 0c4e15246..392417e76 100644 --- a/data_structures/percent.hpp +++ b/data_structures/percent.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, @@ -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; diff --git a/data_structures/phantom_node.cpp b/data_structures/phantom_node.cpp index 413c0d79e..eba6492cd 100644 --- a/data_structures/phantom_node.cpp +++ b/data_structures/phantom_node.cpp @@ -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::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 + +#include + +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::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::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; } diff --git a/data_structures/phantom_node.hpp b/data_structures/phantom_node.hpp index 9286fb9b4..b048eb7f2 100644 --- a/data_structures/phantom_node.hpp +++ b/data_structures/phantom_node.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,11 +28,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef PHANTOM_NODES_H #define PHANTOM_NODES_H -#include -#include "../data_structures/travel_mode.hpp" +#include "travel_mode.hpp" #include "../typedefs.h" +#include + #include +#include #include struct PhantomNode @@ -53,6 +55,28 @@ struct PhantomNode PhantomNode(); + template 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>; class phantom_node_pair : public std::pair { - }; 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; } diff --git a/data_structures/query_edge.hpp b/data_structures/query_edge.hpp index 84a7f1591..417bb4a13 100644 --- a/data_structures/query_edge.hpp +++ b/data_structures/query_edge.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, @@ -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 + 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 diff --git a/data_structures/query_node.hpp b/data_structures/query_node.hpp index 7705df008..f3e990476 100644 --- a/data_structures/query_node.hpp +++ b/data_structures/query_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, @@ -30,16 +30,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" -#include - #include +#include + #include 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() diff --git a/data_structures/range_table.hpp b/data_structures/range_table.hpp index eef268b9d..4662f06c0 100644 --- a/data_structures/range_table.hpp +++ b/data_structures/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,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 class RangeTable; +template class RangeTable; -template -std::ostream& operator<<(std::ostream &out, const RangeTable &table); +template +std::ostream &operator<<(std::ostream &out, const RangeTable &table); -template -std::istream& operator>>(std::istream &in, RangeTable &table); +template +std::istream &operator>>(std::istream &in, RangeTable &table); /** * Stores adjacent ranges in a compressed format. @@ -58,33 +58,34 @@ std::istream& operator>>(std::istream &in, RangeTable -class RangeTable +template class RangeTable { -public: - + public: using BlockT = std::array; using BlockContainerT = typename ShM::vector; using OffsetContainerT = typename ShM::vector; using RangeT = osrm::range; - 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& lengths) + explicit RangeTable(const std::vector &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 RangeTable::PrefixSumAtIndex(int index, const BlockT& block) const +template +unsigned RangeTable::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::PrefixSumAtIndex(int index, return sum; } -template -std::ostream& operator<<(std::ostream &out, const RangeTable &table) +template +std::ostream &operator<<(std::ostream &out, const RangeTable &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 -std::istream& operator>>(std::istream &in, RangeTable &table) +template +std::istream &operator>>(std::istream &in, RangeTable &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 diff --git a/data_structures/rectangle.hpp b/data_structures/rectangle.hpp index 2f6815cac..55720a37d 100644 --- a/data_structures/rectangle.hpp +++ b/data_structures/rectangle.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 +#include + #include #include #include @@ -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::max()), - max_lon(std::numeric_limits::min()), - min_lat(std::numeric_limits::max()), - max_lat(std::numeric_limits::min()) {} + RectangleInt2D() + : min_lon(std::numeric_limits::max()), + max_lon(std::numeric_limits::min()), + min_lat(std::numeric_limits::max()), max_lat(std::numeric_limits::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::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::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::max()); + BOOST_ASSERT(min_dist < std::numeric_limits::max()); return min_dist; } - inline float GetMinMaxDist(const FixedPointCoordinate &location) const + float GetMinMaxDist(const FixedPointCoordinate &location) const { float min_max_dist = std::numeric_limits::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 << "," diff --git a/data_structures/restriction.hpp b/data_structures/restriction.hpp index 5f6e9b0f5..b808d3070 100644 --- a/data_structures/restriction.hpp +++ b/data_structures/restriction.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, @@ -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; } diff --git a/data_structures/restriction_map.cpp b/data_structures/restriction_map.cpp index 3c13d738a..017ee3251 100644 --- a/data_structures/restriction_map.cpp +++ b/data_structures/restriction_map.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, @@ -27,54 +27,51 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "restriction_map.hpp" -RestrictionMap::RestrictionMap(const std::vector &restriction_list) - : m_count(0) +RestrictionMap::RestrictionMap(const std::vector &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; diff --git a/data_structures/restriction_map.hpp b/data_structures/restriction_map.hpp index 7633faf4d..27a6698db 100644 --- a/data_structures/restriction_map.hpp +++ b/data_structures/restriction_map.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,14 +28,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef RESTRICTION_MAP_HPP #define RESTRICTION_MAP_HPP -#include - #include "restriction.hpp" -#include "../Util/std_hash.hpp" +#include "../util/std_hash.hpp" #include "../typedefs.h" #include +#include #include #include #include @@ -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 &restriction_list); // Replace end v with w in each turn restriction containing u as via node - template + template 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 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 m_no_turn_via_node_set; }; -#endif //RESTRICTION_MAP_HPP +#endif // RESTRICTION_MAP_HPP diff --git a/data_structures/route_parameters.cpp b/data_structures/route_parameters.cpp index 1019a9149..3b615e2c4 100644 --- a/data_structures/route_parameters.cpp +++ b/data_structures/route_parameters.cpp @@ -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 - #include #include #include +#include + 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 &transmitted_coordinates) +void RouteParameters::addCoordinate( + const boost::fusion::vector &received_coordinates) { coordinates.emplace_back( - static_cast(COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates)), - static_cast(COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates))); + static_cast(COORDINATE_PRECISION * boost::fusion::at_c<0>(received_coordinates)), + static_cast(COORDINATE_PRECISION * boost::fusion::at_c<1>(received_coordinates))); } diff --git a/data_structures/search_engine.hpp b/data_structures/search_engine.hpp index 0b2b888dc..7e47b1f5d 100644 --- a/data_structures/search_engine.hpp +++ b/data_structures/search_engine.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, @@ -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 @@ -45,13 +46,18 @@ template class SearchEngine ShortestPathRouting shortest_path; AlternativeRouting alternative_path; ManyToManyRouting distance_table; + MapMatching 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::value, "don't instantiate with ptr type"); - static_assert(std::is_object::value, "don't instantiate with void, function, or reference"); + static_assert(std::is_object::value, + "don't instantiate with void, function, or reference"); } ~SearchEngine() {} diff --git a/data_structures/search_engine_data.cpp b/data_structures/search_engine_data.cpp index 810762acd..3282a0ccb 100644 --- a/data_structures/search_engine_data.cpp +++ b/data_structures/search_engine_data.cpp @@ -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)); } } diff --git a/data_structures/search_engine_data.hpp b/data_structures/search_engine_data.hpp index 6c2efb1d6..8c1c1619e 100644 --- a/data_structures/search_engine_data.hpp +++ b/data_structures/search_engine_data.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, @@ -44,12 +44,12 @@ struct SearchEngineData using QueryHeap = BinaryHeap>; using SearchEngineHeapPtr = boost::thread_specific_ptr; - 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); diff --git a/data_structures/segment_information.hpp b/data_structures/segment_information.hpp index dd1fc574b..7118a320e 100644 --- a/data_structures/segment_information.hpp +++ b/data_structures/segment_information.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, @@ -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 +#include // Struct fits everything in one cache line struct SegmentInformation @@ -75,4 +75,4 @@ struct SegmentInformation } }; -#endif /* SEGMENT_INFORMATION_H */ +#endif /* SEGMENT_INFORMATION_HPP */ diff --git a/data_structures/shared_memory_factory.hpp b/data_structures/shared_memory_factory.hpp index dc714a68b..58fed9bb3 100644 --- a/data_structures/shared_memory_factory.hpp +++ b/data_structures/shared_memory_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,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 #include @@ -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; } diff --git a/data_structures/shared_memory_vector_wrapper.hpp b/data_structures/shared_memory_vector_wrapper.hpp index d508e5f56..dc51cff0d 100644 --- a/data_structures/shared_memory_vector_wrapper.hpp +++ b/data_structures/shared_memory_vector_wrapper.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, @@ -147,8 +147,8 @@ template <> class SharedMemoryWrapper template struct ShM { using vector = typename std::conditional, - std::vector>::type; + SharedMemoryWrapper, + std::vector>::type; }; #endif // SHARED_MEMORY_VECTOR_WRAPPER_HPP diff --git a/data_structures/static_graph.hpp b/data_structures/static_graph.hpp index 05d65eeee..7434b56de 100644 --- a/data_structures/static_graph.hpp +++ b/data_structures/static_graph.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 -#include - #include #include #include @@ -57,8 +55,11 @@ template class StaticGraph NodeIterator target; EdgeDataT data; - template - InputEdge(NodeIterator source, NodeIterator target, Ts &&...data) : source(source), target(target), data(std::forward(data)...) { } + template + InputEdge(NodeIterator source, NodeIterator target, Ts &&... data) + : source(source), target(target), data(std::forward(data)...) + { + } bool operator<(const InputEdge &right) const { if (source != right.source) @@ -88,13 +89,12 @@ template class StaticGraph StaticGraph(const int nodes, std::vector &graph) { - tbb::parallel_sort(graph.begin(), graph.end()); number_of_nodes = nodes; number_of_edges = static_cast(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 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 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 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; diff --git a/data_structures/static_kdtree.hpp b/data_structures/static_kdtree.hpp index b173d3a02..1e65dc844 100644 --- a/data_structures/static_kdtree.hpp +++ b/data_structures/static_kdtree.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, @@ -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)); } diff --git a/data_structures/static_rtree.hpp b/data_structures/static_rtree.hpp index f670ca34f..f219a6475 100644 --- a/data_structures/static_rtree.hpp +++ b/data_structures/static_rtree.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, @@ -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 +#include #include #include @@ -68,8 +69,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. template , 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::min()); BOOST_ASSERT(min_lon != std::numeric_limits::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::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::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(0, search_tree_size), [this, &search_tree_size](const tbb::blocked_range &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 &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 &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 projected_coordinate = { + mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION), + input_coordinate.lon / COORDINATE_PRECISION}; + + // upper bound pruning technique + upper_bound pruning_bound(max_number_of_phantom_nodes); + // initialize queue with root element std::priority_queue traversal_queue; traversal_queue.emplace(0.f, m_search_tree[0]); @@ -672,7 +673,8 @@ class StaticRTree if (current_query_node.node.template is()) { // current object is a tree node - const TreeNode & current_tree_node = current_query_node.node.template get(); + const TreeNode ¤t_tree_node = + current_query_node.node.template get(); 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(); + const EdgeDataT ¤t_segment = + current_query_node.node.template get(); // 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{}; } } - // 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> &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> &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 min_found_distances(number_of_results, std::numeric_limits::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 projected_coordinate = { + mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION), + input_coordinate.lon / COORDINATE_PRECISION}; + + // upper bound pruning technique + upper_bound pruning_bound(max_number_of_phantom_nodes); // initialize queue with root element std::priority_queue 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(); + if (current_query_node.node.template is()) + { // current object is a tree node + const TreeNode ¤t_tree_node = + current_query_node.node.template get(); 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(); + const EdgeDataT ¤t_segment = + current_query_node.node.template get(); - // 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{}; + 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{}; } } + // 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::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(result_phantom_node.forward_weight * ratio); + const auto new_weight = + static_cast(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(result_phantom_node.reverse_weight * (1.f-ratio)); + const auto new_weight = + static_cast(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 @@ -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 &objects, const uint32_t element_count, const std::vector &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::min()); BOOST_ASSERT(rectangle.min_lon != std::numeric_limits::min()); diff --git a/data_structures/travel_mode.hpp b/data_structures/travel_mode.hpp index 345ec90e3..2bbe46317 100644 --- a/data_structures/travel_mode.hpp +++ b/data_structures/travel_mode.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, @@ -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; diff --git a/data_structures/tribool.hpp b/data_structures/tribool.hpp new file mode 100644 index 000000000..2d4b6108d --- /dev/null +++ b/data_structures/tribool.hpp @@ -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 diff --git a/data_structures/turn_instructions.hpp b/data_structures/turn_instructions.hpp index 4b36658b3..1ca065f68 100644 --- a/data_structures/turn_instructions.hpp +++ b/data_structures/turn_instructions.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; } diff --git a/data_structures/upper_bound.hpp b/data_structures/upper_bound.hpp new file mode 100644 index 000000000..80695f2c5 --- /dev/null +++ b/data_structures/upper_bound.hpp @@ -0,0 +1,77 @@ +/* + +Copyright (c) 2015, Project OSRM contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef LOWER_BOUND_HPP +#define LOWER_BOUND_HPP + +#include +#include +#include +#include + +// 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 class upper_bound +{ + private: + using parameter_type = + typename std::conditional::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::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, std::less> queue; + const std::size_t size; +}; + +#endif // LOWER_BOUND_HPP diff --git a/data_structures/xor_fast_hash.hpp b/data_structures/xor_fast_hash.hpp index 1f6dc29bb..3af5ab1db 100644 --- a/data_structures/xor_fast_hash.hpp +++ b/data_structures/xor_fast_hash.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(i); + table2[i] = static_cast(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(i); + table2[i] = static_cast(i); + table3[i] = static_cast(i); + table4[i] = static_cast(i); } std::random_shuffle(table1.begin(), table1.end()); std::random_shuffle(table2.begin(), table2.end()); diff --git a/data_structures/xor_fast_hash_storage.hpp b/data_structures/xor_fast_hash_storage.hpp index 1d84260c2..ff65717a3 100644 --- a/data_structures/xor_fast_hash_storage.hpp +++ b/data_structures/xor_fast_hash_storage.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, @@ -38,22 +38,24 @@ template class XORFastHashStorage public: struct HashCell { - Key key; - NodeID id; unsigned time; + NodeID id; + Key key; HashCell() - : key(std::numeric_limits::max()), id(std::numeric_limits::max()), - time(std::numeric_limits::max()) + : time(std::numeric_limits::max()), id(std::numeric_limits::max()), + key(std::numeric_limits::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 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::max() == current_timestamp) { positions.clear(); - positions.resize((2 << 16)); + positions.resize(2 << 16); } } private: - XORFastHashStorage() : positions(2 << 16), current_timestamp(0) {} std::vector positions; XORFastHash fast_hasher; unsigned current_timestamp; diff --git a/datastore.cpp b/datastore.cpp index d29200420..3c032a2a9 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -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 +#include +#include using RTreeLeaf = BaseDataFacade::RTreeLeaf; using RTreeNode = StaticRTree::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(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(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( shared_memory_ptr, SharedDataLayout::NAME_ID_LIST); - TravelMode *travel_mode_ptr = - shared_layout_ptr->GetBlockPtr( - shared_memory_ptr, SharedDataLayout::TRAVEL_MODE); + TravelMode *travel_mode_ptr = shared_layout_ptr->GetBlockPtr( + shared_memory_ptr, SharedDataLayout::TRAVEL_MODE); TurnInstruction *turn_instructions_ptr = shared_layout_ptr->GetBlockPtr( diff --git a/descriptors/description_factory.cpp b/descriptors/description_factory.cpp index 075eff029..e4665622f 100644 --- a/descriptors/description_factory.cpp +++ b/descriptors/description_factory.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, @@ -27,12 +27,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "description_factory.hpp" -#include - -#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(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(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::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::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(angle * 10); + }); + + via_indices.push_back(necessary_segments + 1); + BOOST_ASSERT(via_indices.size() >= 2); + return; +} diff --git a/descriptors/description_factory.hpp b/descriptors/description_factory.hpp index 9b96dd20f..985f9c1c5 100644 --- a/descriptors/description_factory.hpp +++ b/descriptors/description_factory.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,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 -#include +#include +#include #include @@ -73,7 +72,7 @@ class DescriptionFactory { // compute distance/duration for route summary distance = static_cast(std::round(raw_distance)); - duration = static_cast(std::round(raw_duration / 10.)); + duration = static_cast(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 const &GetViaIndices() const; - double get_entire_length() const - { - return entire_length; - } + double get_entire_length() const { return entire_length; } - template 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::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::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(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 */ diff --git a/descriptors/descriptor_base.hpp b/descriptors/descriptor_base.hpp index 31c08eaf1..497c2161d 100644 --- a/descriptors/descriptor_base.hpp +++ b/descriptors/descriptor_base.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 +#include + +#include #include #include #include - struct DescriptorTable : public std::unordered_map { unsigned get_id(const std::string &key) @@ -52,18 +54,16 @@ struct DescriptorTable : public std::unordered_map } }; - struct DescriptorConfig { DescriptorConfig() : instructions(true), geometry(true), encode_geometry(true), zoom_level(18) { } - template - DescriptorConfig(const OtherT &other) : instructions(other.print_instructions), - geometry(other.geometry), - encode_geometry(other.compression), - zoom_level(other.zoom_level) + template + 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 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 diff --git a/descriptors/gpx_descriptor.hpp b/descriptors/gpx_descriptor.hpp index 2dd003490..fb4c5b9de 100644 --- a/descriptors/gpx_descriptor.hpp +++ b/descriptors/gpx_descriptor.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 #include @@ -40,39 +41,39 @@ template class GPXDescriptor final : public BaseDescriptor &path_data_vector : raw_route.unpacked_path_segments) { @@ -80,13 +81,14 @@ template class GPXDescriptor final : public BaseDescriptorGetCoordinateOfNode(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 diff --git a/descriptors/json_descriptor.hpp b/descriptors/json_descriptor.hpp index 2aae939a9..13b68c6ec 100644 --- a/descriptors/json_descriptor.hpp +++ b/descriptors/json_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 - -template class JSONDescriptor final : public BaseDescriptor -{ - 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 shortest_path_segments, alternative_path_segments; - ExtractRouteNames 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 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(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 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 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(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 &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(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(round(bearing_value))); - json_instruction_row.values.push_back(segment.travel_mode); - - route_segments_list.emplace_back( - segment.name_id, - static_cast(segment.length), - static_cast(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 + +#include + +template class JSONDescriptor final : public BaseDescriptor +{ + 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 shortest_path_segments, alternative_path_segments; + ExtractRouteNames 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 &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(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 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 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(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 &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(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(round(bearing_value))); + json_instruction_row.values.push_back(segment.travel_mode); + + route_segments_list.emplace_back( + segment.name_id, static_cast(segment.length), + static_cast(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_ */ diff --git a/extract.cpp b/extract.cpp index 2ad1f7af8..a14762983 100644 --- a/extract.cpp +++ b/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 + +#include + +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; } - } diff --git a/extractor/extraction_containers.cpp b/extractor/extraction_containers.cpp index 604f863cd..8c484eb81 100644 --- a/extractor/extraction_containers.cpp +++ b/extractor/extraction_containers.cpp @@ -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 #include @@ -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::max() != restrictions_iterator->restriction.from.node && - std::numeric_limits::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::max() != restriction_container.restriction.from.node && - std::numeric_limits::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 name_lengths; for (const std::string &temp_string : name_list) { - const unsigned string_length = std::min(static_cast(temp_string.length()), 255u); + const unsigned string_length = + std::min(static_cast(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(temp_string.length()), 255u); + const unsigned string_length = + std::min(static_cast(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; + } } diff --git a/extractor/extraction_containers.hpp b/extractor/extraction_containers.hpp index 8a1df8c36..12d88a26c 100644 --- a/extractor/extraction_containers.hpp +++ b/extractor/extraction_containers.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,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 class ExtractionContainers { #ifndef _MSC_VER - constexpr static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? std::numeric_limits::max() : std::numeric_limits::max()); + constexpr static unsigned stxxl_memory = + ((sizeof(std::size_t) == 4) ? std::numeric_limits::max() + : std::numeric_limits::max()); #else const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX); #endif public: - using STXXLNodeIDVector = stxxl::vector; - using STXXLNodeVector = stxxl::vector; - using STXXLEdgeVector = stxxl::vector; - using STXXLStringVector = stxxl::vector; - using STXXLRestrictionsVector = stxxl::vector; - using STXXLWayIDStartEndVector = stxxl::vector; + using STXXLNodeIDVector = stxxl::vector; + using STXXLNodeVector = stxxl::vector; + using STXXLEdgeVector = stxxl::vector; + using STXXLStringVector = stxxl::vector; + using STXXLRestrictionsVector = stxxl::vector; + using STXXLWayIDStartEndVector = stxxl::vector; STXXLNodeIDVector used_node_id_list; STXXLNodeVector all_nodes_list; diff --git a/extractor/extraction_helper_functions.hpp b/extractor/extraction_helper_functions.hpp index d2a73c9c9..d10200abb 100644 --- a/extractor/extraction_helper_functions.hpp +++ b/extractor/extraction_helper_functions.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, @@ -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 #include @@ -37,53 +38,81 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -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 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 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 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 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 iso_parser; + qi::parse(s.begin(), s.end(), iso_parser); + + return iso_parser.get_duration(); + } + return std::numeric_limits::max(); } diff --git a/extractor/extraction_node.hpp b/extractor/extraction_node.hpp index defd33394..e821d6ffa 100644 --- a/extractor/extraction_node.hpp +++ b/extractor/extraction_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, @@ -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; }; diff --git a/extractor/extraction_way.hpp b/extractor/extraction_way.hpp index b41448758..d47de20b0 100644 --- a/extractor/extraction_way.hpp +++ b/extractor/extraction_way.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, @@ -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; } diff --git a/extractor/extractor.cpp b/extractor/extractor.cpp index 880e9e47c..0581e4e5c 100644 --- a/extractor/extractor.cpp +++ b/extractor/extractor.cpp @@ -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 +#include + #include #include @@ -63,43 +64,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -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 number_of_nodes {0}; - std::atomic number_of_ways {0}; - std::atomic number_of_relations {0}; - std::atomic number_of_others {0}; + std::atomic number_of_nodes{0}; + std::atomic number_of_ways{0}; + std::atomic number_of_relations{0}; + std::atomic 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 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(0, osm_elements.size()), - [&](const tbb::blocked_range &range) - { - for (auto x = range.begin(); x != range.end(); ++x) + tbb::parallel_for( + tbb::blocked_range(0, osm_elements.size()), + [&](const tbb::blocked_range &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( - local_state, - "node_function", - boost::cref(static_cast(*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( - local_state, - "way_function", - boost::cref(static_cast(*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(*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( + local_state, "node_function", + boost::cref(static_cast(*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( + local_state, "way_function", + boost::cref(static_cast(*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(*entity))); + break; + default: + ++number_of_others; + break; + } } - } - }); + }); // put parsed objects thru extractor callbacks for (const auto &result : resulting_nodes) { extractor_callbacks->ProcessNode( - static_cast(*(osm_elements[result.first])), result.second); + static_cast(*(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(); diff --git a/extractor/extractor.hpp b/extractor/extractor.hpp index e9edbea54..8ea56c3cb 100644 --- a/extractor/extractor.hpp +++ b/extractor/extractor.hpp @@ -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 +#include "extractor_options.hpp" -#include - -/** \brief Class of 'extract' utility. */ -struct Extractor +struct extractor { - int Run(int argc, char *argv[]); + int run(const ExtractorConfig &extractor_config); }; #endif /* EXTRACTOR_HPP */ diff --git a/extractor/extractor_callbacks.cpp b/extractor/extractor_callbacks.cpp index 87e4f4f0b..224468b06 100644 --- a/extractor/extractor_callbacks.cpp +++ b/extractor/extractor_callbacks.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, @@ -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 +#include #include #include @@ -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(input_node.location().lat() * COORDINATE_PRECISION), - static_cast(input_node.location().lon() * COORDINATE_PRECISION), - static_cast(input_node.id()), - result_node.barrier, - result_node.traffic_lights - }); + external_memory.all_nodes_list.push_back( + {static_cast(input_node.location().lat() * COORDINATE_PRECISION), + static_cast(input_node.location().lon() * COORDINATE_PRECISION), + static_cast(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(parsed_way).forward_speed = parsed_way.duration / (input_way.nodes().size() - 1); - const_cast(parsed_way).backward_speed = parsed_way.duration / (input_way.nodes().size() - 1); + const_cast(parsed_way).forward_speed = + parsed_way.duration / (input_way.nodes().size() - 1); + const_cast(parsed_way).backward_speed = + parsed_way.duration / (input_way.nodes().size() - 1); } if (std::numeric_limits::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(parsed_way).forward_travel_mode = parsed_way.backward_travel_mode; - const_cast(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(parsed_way).forward_travel_mode = + parsed_way.backward_travel_mode; + const_cast(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()); } diff --git a/extractor/extractor_callbacks.hpp b/extractor/extractor_callbacks.hpp index 0bb30104b..8eab0182b 100644 --- a/extractor/extractor_callbacks.hpp +++ b/extractor/extractor_callbacks.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, diff --git a/extractor/extractor_options.cpp b/extractor/extractor_options.cpp index d14d8d9f8..9ae5cd4c1 100644 --- a/extractor/extractor_options.cpp +++ b/extractor/extractor_options.cpp @@ -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 #include #include -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(&extractor_config.config_file_path) - ->default_value("extractor.ini"), + "config,c", boost::program_options::value( + &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(&extractor_config.input_path), - "Input file in .osm, .osm.bz2 or .osm.pbf format"); + hidden_options.add_options()("input,i", boost::program_options::value( + &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) diff --git a/extractor/extractor_options.hpp b/extractor/extractor_options.hpp index 118da78d9..5712ea01a 100644 --- a/extractor/extractor_options.hpp +++ b/extractor/extractor_options.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,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 + +#include + +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); }; diff --git a/extractor/first_and_last_segment_of_way.hpp b/extractor/first_and_last_segment_of_way.hpp index 8e8ad7276..3a26be7ce 100644 --- a/extractor/first_and_last_segment_of_way.hpp +++ b/extractor/first_and_last_segment_of_way.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, diff --git a/extractor/internal_extractor_edge.hpp b/extractor/internal_extractor_edge.hpp index ffd2d4a36..27e1af146 100644 --- a/extractor/internal_extractor_edge.hpp +++ b/extractor/internal_extractor_edge.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,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" #include "../data_structures/travel_mode.hpp" -#include #include +#include + struct InternalExtractorEdge { InternalExtractorEdge() - : start(0), target(0), direction(0), speed(0), name_id(0), is_roundabout(false), + : start(0), target(0), speed(0), name_id(0), direction(0), is_roundabout(false), is_in_tiny_cc(false), is_duration_set(false), is_access_restricted(false), - travel_mode(TRAVEL_MODE_INACCESSIBLE), is_split(false) + is_split(false), travel_mode(TRAVEL_MODE_INACCESSIBLE) { } @@ -54,35 +55,36 @@ struct InternalExtractorEdge bool is_access_restricted, TravelMode travel_mode, bool is_split) - : start(start), target(target), direction(direction), speed(speed), - name_id(name_id), is_roundabout(is_roundabout), is_in_tiny_cc(is_in_tiny_cc), + : start(start), target(target), speed(speed), name_id(name_id), direction(direction), + is_roundabout(is_roundabout), is_in_tiny_cc(is_in_tiny_cc), is_duration_set(is_duration_set), is_access_restricted(is_access_restricted), - travel_mode(travel_mode), is_split(is_split) + is_split(is_split), travel_mode(travel_mode) { } // necessary static util functions for stxxl's sorting static InternalExtractorEdge min_value() { - return InternalExtractorEdge(0, 0, 0, 0, 0, false, false, false, false, TRAVEL_MODE_INACCESSIBLE, false); + return InternalExtractorEdge(0, 0, 0, 0, 0, false, false, false, false, + TRAVEL_MODE_INACCESSIBLE, false); } static InternalExtractorEdge max_value() { - return InternalExtractorEdge( - SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, false, false, false, false, TRAVEL_MODE_INACCESSIBLE, false); + return InternalExtractorEdge(SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, false, false, false, + false, TRAVEL_MODE_INACCESSIBLE, false); } NodeID start; NodeID target; - short direction; double speed; unsigned name_id; - bool is_roundabout; - bool is_in_tiny_cc; - bool is_duration_set; - bool is_access_restricted; + short direction; + bool is_roundabout : 1; + bool is_in_tiny_cc : 1; + bool is_duration_set : 1; + bool is_access_restricted : 1; + bool is_split : 1; TravelMode travel_mode : 4; - bool is_split; FixedPointCoordinate source_coordinate; FixedPointCoordinate target_coordinate; diff --git a/extractor/restriction_parser.cpp b/extractor/restriction_parser.cpp index 2f53d33c3..ea9cad27a 100644 --- a/extractor/restriction_parser.cpp +++ b/extractor/restriction_parser.cpp @@ -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, @@ -30,15 +30,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "scripting_environment.hpp" #include "../data_structures/external_memory_node.hpp" -#include "../Util/lua_util.hpp" -#include "../Util/osrm_exception.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/lua_util.hpp" +#include "../util/osrm_exception.hpp" +#include "../util/simple_logger.hpp" #include #include #include #include +#include + namespace { int lua_error_callback(lua_State *lua_state) @@ -85,8 +87,8 @@ void RestrictionParser::ReadRestrictionExceptions(lua_State *lua_state) { luabind::set_pcall_callback(&lua_error_callback); // get list of turn restriction exceptions - luabind::call_function( - lua_state, "get_exceptions", boost::ref(restriction_exceptions)); + luabind::call_function(lua_state, "get_exceptions", + boost::ref(restriction_exceptions)); const unsigned exception_count = restriction_exceptions.size(); SimpleLogger().Write() << "Found " << exception_count << " exceptions to turn restrictions:"; @@ -166,9 +168,8 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const continue; } BOOST_ASSERT(0 == strcmp("via", role)); - // set the via node id - // SimpleLogger().Write() << "via: " << member.ref(); + // set via node id restriction_container.restriction.via.node = member.ref(); break; @@ -177,37 +178,26 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const 0 == strcmp("via", role)); if (0 == strcmp("from", role)) { - // SimpleLogger().Write() << "from: " << member.ref(); restriction_container.restriction.from.way = member.ref(); } else if (0 == strcmp("to", role)) { - // SimpleLogger().Write() << "to: " << member.ref(); restriction_container.restriction.to.way = member.ref(); } - else if (0 == strcmp("via", role)) - { - // not yet suppported - // restriction_container.restriction.via.way = member.ref(); - } + // else if (0 == strcmp("via", role)) + // { + // not yet suppported + // restriction_container.restriction.via.way = member.ref(); + // } break; case osmium::item_type::relation: // not yet supported, but who knows what the future holds... - continue; break; default: - BOOST_ASSERT(false); + // shouldn't ever happen break; } } - - // SimpleLogger().Write() << (restriction_container.restriction.flags.is_only ? "only" : "no") - // << "-restriction " - // << "<" << restriction_container.restriction.from.node << "->" - // << restriction_container.restriction.via.node << "->" << - // restriction_container.restriction.to.node - // << ">"; - return mapbox::util::optional(restriction_container); } @@ -228,14 +218,16 @@ bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_st // only a few exceptions are actually defined. std::vector exceptions; boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*")); - for (std::string ¤t_string : exceptions) - { - const auto string_iterator = - std::find(restriction_exceptions.begin(), restriction_exceptions.end(), current_string); - if (restriction_exceptions.end() != string_iterator) - { - return true; - } - } - return false; + + return std::any_of(std::begin(exceptions), std::end(exceptions), + [&](const std::string ¤t_string) + { + if (std::end(restriction_exceptions) != + std::find(std::begin(restriction_exceptions), + std::end(restriction_exceptions), current_string)) + { + return true; + } + return false; + }); } diff --git a/extractor/restriction_parser.hpp b/extractor/restriction_parser.hpp index d5adb4317..0a632d83e 100644 --- a/extractor/restriction_parser.hpp +++ b/extractor/restriction_parser.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, @@ -46,7 +46,8 @@ class RestrictionParser public: // RestrictionParser(ScriptingEnvironment &scripting_environment); RestrictionParser(lua_State *lua_state); - mapbox::util::optional TryParse(const osmium::Relation &relation) const; + mapbox::util::optional + TryParse(const osmium::Relation &relation) const; private: void ReadUseRestrictionsSetting(lua_State *lua_state); diff --git a/extractor/scripting_environment.cpp b/extractor/scripting_environment.cpp index c51651e40..972772246 100644 --- a/extractor/scripting_environment.cpp +++ b/extractor/scripting_environment.cpp @@ -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,9 +31,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "extraction_node.hpp" #include "extraction_way.hpp" #include "../data_structures/external_memory_node.hpp" -#include "../Util/lua_util.hpp" -#include "../Util/osrm_exception.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/lua_util.hpp" +#include "../util/osrm_exception.hpp" +#include "../util/simple_logger.hpp" #include "../typedefs.h" #include @@ -41,10 +41,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace { +namespace +{ // wrapper method as luabind doesn't automatically overload funcs w/ default parameters -template -auto get_value_by_key(T const& object, const char *key) -> decltype(object.get_value_by_key(key)) +template +auto get_value_by_key(T const &object, const char *key) -> decltype(object.get_value_by_key(key)) { return object.get_value_by_key(key, ""); } @@ -59,16 +60,14 @@ int lua_error_callback(lua_State *L) // This is so I can use my own function as } } - -ScriptingEnvironment::ScriptingEnvironment(const std::string &file_name) -: file_name(file_name) +ScriptingEnvironment::ScriptingEnvironment(const std::string &file_name) : file_name(file_name) { SimpleLogger().Write() << "Using script " << file_name; } -void ScriptingEnvironment::init_lua_state(lua_State* lua_state) +void ScriptingEnvironment::init_lua_state(lua_State *lua_state) { - typedef double (osmium::Location::* location_member_ptr_type)() const; + typedef double (osmium::Location::*location_member_ptr_type)() const; luabind::open(lua_state); // open utility libraries string library; @@ -83,41 +82,47 @@ void ScriptingEnvironment::init_lua_state(lua_State* lua_state) luabind::def("parseDuration", parseDuration), luabind::class_>("vector") - .def("Add", static_cast::*)(const std::string &)>(&std::vector::push_back)), + .def("Add", static_cast::*)(const std::string &)>( + &std::vector::push_back)), luabind::class_("Location") - .def("lat", &osmium::Location::lat) - .def("lon", &osmium::Location::lon), + .def("lat", &osmium::Location::lat) + .def("lon", &osmium::Location::lon), luabind::class_("Node") - // .def("tags", &osmium::Node::tags) - .def("get_value_by_key", &osmium::Node::get_value_by_key) - .def("get_value_by_key", &get_value_by_key), + // .def("tags", &osmium::Node::tags) + .def("location", &osmium::Node::location) + .def("get_value_by_key", &osmium::Node::get_value_by_key) + .def("get_value_by_key", &get_value_by_key) + .def("id", &osmium::Node::id), luabind::class_("ResultNode") - .def_readwrite("traffic_lights", &ExtractionNode::traffic_lights) - .def_readwrite("barrier", &ExtractionNode::barrier), + .def_readwrite("traffic_lights", &ExtractionNode::traffic_lights) + .def_readwrite("barrier", &ExtractionNode::barrier), luabind::class_("ResultWay") - // .def(luabind::constructor<>()) - .def_readwrite("forward_speed", &ExtractionWay::forward_speed) - .def_readwrite("backward_speed", &ExtractionWay::backward_speed) - .def_readwrite("name", &ExtractionWay::name) - .def_readwrite("roundabout", &ExtractionWay::roundabout) - .def_readwrite("is_access_restricted", &ExtractionWay::is_access_restricted) - .def_readwrite("ignore_in_index", &ExtractionWay::ignore_in_grid) - .def_readwrite("duration", &ExtractionWay::duration) - .property("forward_mode", &ExtractionWay::get_forward_mode, &ExtractionWay::set_forward_mode) - .property("backward_mode", &ExtractionWay::get_backward_mode, &ExtractionWay::set_backward_mode) - .enum_("constants")[ - luabind::value("notSure", 0), - luabind::value("oneway", 1), - luabind::value("bidirectional", 2), - luabind::value("opposite", 3) - ], + // .def(luabind::constructor<>()) + .def_readwrite("forward_speed", &ExtractionWay::forward_speed) + .def_readwrite("backward_speed", &ExtractionWay::backward_speed) + .def_readwrite("name", &ExtractionWay::name) + .def_readwrite("roundabout", &ExtractionWay::roundabout) + .def_readwrite("is_access_restricted", &ExtractionWay::is_access_restricted) + .def_readwrite("ignore_in_index", &ExtractionWay::ignore_in_grid) + .def_readwrite("duration", &ExtractionWay::duration) + .property("forward_mode", &ExtractionWay::get_forward_mode, + &ExtractionWay::set_forward_mode) + .property("backward_mode", &ExtractionWay::get_backward_mode, + &ExtractionWay::set_backward_mode) + .enum_("constants")[ + luabind::value("notSure", 0), + luabind::value("oneway", 1), + luabind::value("bidirectional", 2), + luabind::value("opposite", 3) + ], luabind::class_("Way") - .def("get_value_by_key", &osmium::Way::get_value_by_key) - .def("get_value_by_key", &get_value_by_key) + .def("get_value_by_key", &osmium::Way::get_value_by_key) + .def("get_value_by_key", &get_value_by_key) + .def("id", &osmium::Way::id) ]; if (0 != luaL_dofile(lua_state, file_name.c_str())) @@ -133,7 +138,7 @@ lua_State *ScriptingEnvironment::get_lua_state() { std::lock_guard lock(init_mutex); bool initialized = false; - auto& ref = script_contexts.local(initialized); + auto &ref = script_contexts.local(initialized); if (!initialized) { std::shared_ptr state(luaL_newstate(), lua_close); diff --git a/extractor/scripting_environment.hpp b/extractor/scripting_environment.hpp index 6e0b079c9..be05103c8 100644 --- a/extractor/scripting_environment.hpp +++ b/extractor/scripting_environment.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, @@ -44,8 +44,8 @@ class ScriptingEnvironment lua_State *get_lua_state(); private: - void init_lua_state(lua_State* lua_state); - std::mutex init_mutex; + void init_lua_state(lua_State *lua_state); + std::mutex init_mutex; std::string file_name; tbb::enumerable_thread_specific> script_contexts; }; diff --git a/features/bicycle/bridge.feature b/features/bicycle/bridge.feature new file mode 100644 index 000000000..232581647 --- /dev/null +++ b/features/bicycle/bridge.feature @@ -0,0 +1,47 @@ +@routing @bicycle @bridge +Feature: Bicycle - Handle movable bridge + + Background: + Given the profile "bicycle" + + Scenario: Car - Use a ferry route + Given the node map + | a | b | c | | | + | | | d | | | + | | | e | f | g | + + And the ways + | nodes | highway | bridge | bicycle | + | abc | primary | | | + | cde | | movable | yes | + | efg | primary | | | + + When I route I should get + | from | to | route | modes | + | a | g | abc,cde,efg | 1,5,1 | + | b | f | abc,cde,efg | 1,5,1 | + | e | c | cde | 5 | + | e | b | cde,abc | 5,1 | + | e | a | cde,abc | 5,1 | + | c | e | cde | 5 | + | c | f | cde,efg | 5,1 | + | c | g | cde,efg | 5,1 | + + Scenario: Car - Properly handle durations + Given the node map + | a | b | c | | | + | | | d | | | + | | | e | f | g | + + And the ways + | nodes | highway | bridge | duration | + | abc | primary | | | + | cde | | movable | 00:05:00 | + | efg | primary | | | + + When I route I should get + | from | to | route | modes | speed | + | a | g | abc,cde,efg | 1,5,1 | 5 km/h | + | b | f | abc,cde,efg | 1,5,1 | 3 km/h | + | c | e | cde | 5 | 2 km/h | + | e | c | cde | 5 | 2 km/h | diff --git a/features/car/access.feature b/features/car/access.feature index 37dfed4c6..5fd56f395 100644 --- a/features/car/access.feature +++ b/features/car/access.feature @@ -93,6 +93,7 @@ Feature: Car - Restricted access | private | | | agricultural | | | forestry | | + | psv | | | some_tag | x | @@ -106,6 +107,7 @@ Feature: Car - Restricted access | private | | | agricultural | | | forestry | | + | psv | | | some_tag | x | Scenario: Car - Access tags on both node and way diff --git a/features/car/barrier.feature b/features/car/barrier.feature index e63704986..7c89688c9 100644 --- a/features/car/barrier.feature +++ b/features/car/barrier.feature @@ -10,6 +10,7 @@ Feature: Car - Barriers | | x | | bollard | | | gate | x | + | lift_gate | x | | cattle_grid | x | | border_control | x | | toll_booth | x | diff --git a/features/car/bridge.feature b/features/car/bridge.feature new file mode 100644 index 000000000..41dc10bdb --- /dev/null +++ b/features/car/bridge.feature @@ -0,0 +1,47 @@ +@routing @car @bridge +Feature: Car - Handle movable bridge + + Background: + Given the profile "car" + + Scenario: Car - Use a ferry route + Given the node map + | a | b | c | | | + | | | d | | | + | | | e | f | g | + + And the ways + | nodes | highway | bridge | bicycle | + | abc | primary | | | + | cde | | movable | yes | + | efg | primary | | | + + When I route I should get + | from | to | route | modes | + | a | g | abc,cde,efg | 1,3,1 | + | b | f | abc,cde,efg | 1,3,1 | + | e | c | cde | 3 | + | e | b | cde,abc | 3,1 | + | e | a | cde,abc | 3,1 | + | c | e | cde | 3 | + | c | f | cde,efg | 3,1 | + | c | g | cde,efg | 3,1 | + + Scenario: Car - Properly handle durations + Given the node map + | a | b | c | | | + | | | d | | | + | | | e | f | g | + + And the ways + | nodes | highway | bridge | duration | + | abc | primary | | | + | cde | | movable | 00:05:00 | + | efg | primary | | | + + When I route I should get + | from | to | route | modes | speed | + | a | g | abc,cde,efg | 1,3,1 | 6 km/h | + | b | f | abc,cde,efg | 1,3,1 | 4 km/h | + | c | e | cde | 3 | 2 km/h | + | e | c | cde | 3 | 2 km/h | diff --git a/features/car/ferry.feature b/features/car/ferry.feature index abbe5ed49..eb245598a 100644 --- a/features/car/ferry.feature +++ b/features/car/ferry.feature @@ -27,7 +27,7 @@ Feature: Car - Handle ferry routes | c | f | cde,efg | 2,1 | | c | g | cde,efg | 2,1 | - Scenario: Car - Properly handle durations + Scenario: Car - Properly handle simple durations Given the node map | a | b | c | | | | | | d | | | @@ -45,3 +45,22 @@ Feature: Car - Handle ferry routes | b | f | abc,cde,efg | 1,2,1 | 20 km/h | | c | e | cde | 2 | 12 km/h | | e | c | cde | 2 | 12 km/h | + + Scenario: Car - Properly handle ISO 8601 durations + Given the node map + | a | b | c | | | + | | | d | | | + | | | e | f | g | + + And the ways + | nodes | highway | route | duration | + | abc | primary | | | + | cde | | ferry | PT1M | + | efg | primary | | | + + When I route I should get + | from | to | route | modes | speed | + | a | g | abc,cde,efg | 1,2,1 | 26 km/h | + | b | f | abc,cde,efg | 1,2,1 | 20 km/h | + | c | e | cde | 2 | 12 km/h | + | e | c | cde | 2 | 12 km/h | diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index 8f85d3a67..781f4c617 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -73,3 +73,23 @@ OSRM will use 4/5 of the projected free-flow speed. | runway | | | 100 | | | | | runway | | | | 100 | | | | runway | | | | | 100 | | + + Scenario: Car - Too narrow streets should be ignored or incur a penalty + Then routability should be + + | highway | maxspeed | width | maxspeed:forward | maxspeed:backward | forw | backw | + | primary | | | | | 63 km/h | 63 km/h | + | primary | | 3 | | | 32 km/h | 32 km/h | + | primary | 60 | | | | 59 km/h | 59 km/h | + | primary | 60 | 3 | | | 30 km/h | 30 km/h | + | primary | | | 60 | | 59 km/h | 63 km/h | + | primary | | 3 | 60 | | 30 km/h | 32 km/h | + | primary | | | | 60 | 63 km/h | 59 km/h | + | primary | | 3 | | 60 | 32 km/h | 30 km/h | + | primary | 15 | | 60 | | 59 km/h | 23 km/h | + | primary | 15 | 3 | 60 | | 30 km/h | 7 km/h | + | primary | 15 | | | 60 | 23 km/h | 59 km/h | + | primary | 15 | 3 | | 60 | 7 km/h | 30 km/h | + | primary | 15 | | 30 | 60 | 34 km/h | 59 km/h | + | primary | 15 | 3 | 30 | 60 | 15 km/h | 30 km/h | + diff --git a/features/options/routed/help.feature b/features/options/routed/help.feature index 9603c40dd..c0fca4717 100644 --- a/features/options/routed/help.feature +++ b/features/options/routed/help.feature @@ -24,8 +24,10 @@ Feature: osrm-routed command line options: help And stdout should contain "--ip" And stdout should contain "--port" And stdout should contain "--threads" - And stdout should contain "--sharedmemory" - And stdout should contain 22 lines + And stdout should contain "--shared-memory" + And stdout should contain "--max-table-size" + And stdout should contain "--max-matching-size" + And stdout should contain 26 lines And it should exit with code 0 Scenario: osrm-routed - Help, short @@ -48,8 +50,10 @@ Feature: osrm-routed command line options: help And stdout should contain "--ip" And stdout should contain "--port" And stdout should contain "--threads" - And stdout should contain "--sharedmemory" - And stdout should contain 22 lines + And stdout should contain "--shared-memory" + And stdout should contain "--max-table-size" + And stdout should contain "--max-matching-size" + And stdout should contain 26 lines And it should exit with code 0 Scenario: osrm-routed - Help, long @@ -72,6 +76,8 @@ Feature: osrm-routed command line options: help And stdout should contain "--ip" And stdout should contain "--port" And stdout should contain "--threads" - And stdout should contain "--sharedmemory" - And stdout should contain 22 lines + And stdout should contain "--shared-memory" + And stdout should contain "--max-table-size" + And stdout should contain "--max-matching-size" + And stdout should contain 26 lines And it should exit with code 0 diff --git a/features/step_definitions/matching.rb b/features/step_definitions/matching.rb new file mode 100644 index 000000000..3f3181f64 --- /dev/null +++ b/features/step_definitions/matching.rb @@ -0,0 +1,96 @@ +When /^I match I should get$/ do |table| + reprocess + actual = [] + OSRMLoader.load(self,"#{prepared_file}.osrm") do + table.hashes.each_with_index do |row,ri| + if row['request'] + got = {'request' => row['request'] } + response = request_url row['request'] + else + params = @query_params + trace = [] + timestamps = [] + if row['trace'] + row['trace'].each_char do |n| + node = find_node_by_name(n.strip) + raise "*** unknown waypoint node '#{n.strip}" unless node + trace << node + end + if row['timestamps'] + timestamps = row['timestamps'].split(" ").compact.map { |t| t.to_i} + end + got = {'trace' => row['trace'] } + response = request_matching trace, timestamps, params + else + raise "*** no trace" + end + end + + row.each_pair do |k,v| + if k =~ /param:(.*)/ + if v=='(nil)' + params[$1]=nil + elsif v!=nil + params[$1]=v + end + got[k]=v + end + end + + if response.body.empty? == false + json = JSON.parse response.body + end + + if table.headers.include? 'status' + got['status'] = json['status'].to_s + end + if table.headers.include? 'message' + got['message'] = json['status_message'] + end + if table.headers.include? '#' # comment column + got['#'] = row['#'] # copy value so it always match + end + + sub_matchings = [] + if response.code == "200" + if table.headers.include? 'matchings' + sub_matchings = json['matchings'].compact.map { |sub| sub['matched_points']} + end + end + + ok = true + encoded_result = "" + extended_target = "" + row['matchings'].split(',').each_with_index do |sub, sub_idx| + if sub_idx >= sub_matchings.length + ok = false + break + end + sub.length.times do |node_idx| + node = find_node_by_name(sub[node_idx]) + out_node = sub_matchings[sub_idx][node_idx] + if FuzzyMatch.match_location out_node, node + encoded_result += sub[node_idx] + extended_target += sub[node_idx] + else + encoded_result += "? [#{out_node[0]},#{out_node[1]}]" + extended_target += "#{sub[node_idx]} [#{node.lat},#{node.lon}]" + ok = false + end + end + end + if ok + got['matchings'] = row['matchings'] + got['timestamps'] = row['timestamps'] + else + got['matchings'] = encoded_result + row['matchings'] = extended_target + log_fail row,got, { 'matching' => {:query => @query, :response => response} } + end + + actual << got + end + end + table.routing_diff! actual +end + diff --git a/features/support/env.rb b/features/support/env.rb index a01341dd6..f9a4fe436 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -64,6 +64,19 @@ unless File.exists? TEST_FOLDER raise "*** Test folder #{TEST_FOLDER} doesn't exist." end +def verify_osrm_is_not_running + if OSRMLoader::OSRMBaseLoader.new.osrm_up? + raise "*** osrm-routed is already running." + end +end + +def verify_existance_of_binaries + ["osrm-extract", "osrm-prepare", "osrm-routed"].each do |bin| + unless File.exists? "#{BIN_PATH}/#{bin}" + raise "*** #{BIN_PATH}/#{bin} is missing. Build failed?" + end + end +end if ENV['OS']=~/Windows.*/ then EXE='.exe' @@ -74,10 +87,9 @@ else end AfterConfiguration do |config| - if OSRMLoader::OSRMBaseLoader.new.osrm_up? - raise "*** osrm-routed is already running." - end clear_log_files + verify_osrm_is_not_running + verify_existance_of_binaries end at_exit do diff --git a/features/support/launch.rb b/features/support/launch.rb index 0f983c151..d8d23aeaa 100644 --- a/features/support/launch.rb +++ b/features/support/launch.rb @@ -4,7 +4,7 @@ require 'json' # Only one isntance of osrm-routed is ever launched, to avoid collisions. # The default is to keep osrm-routed running and load data with datastore. -# however, osrm-routed it shut down and relaunched for each scenario thats +# however, osrm-routed it shut down and relaunched for each scenario thats # loads data directly. class OSRMLoader @@ -118,7 +118,7 @@ class OSRMLoader def osrm_up return if osrm_up? - @@pid = Process.spawn("#{BIN_PATH}/osrm-routed --sharedmemory=1 --port #{OSRM_PORT}",:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE) + @@pid = Process.spawn("#{BIN_PATH}/osrm-routed --shared-memory=1 --port #{OSRM_PORT}",:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE) Process.detach(@@pid) # avoid zombie processes end end diff --git a/features/support/match.rb b/features/support/match.rb new file mode 100644 index 000000000..bf51189a4 --- /dev/null +++ b/features/support/match.rb @@ -0,0 +1,26 @@ +require 'net/http' + +HOST = "http://127.0.0.1:#{OSRM_PORT}" + +def request_matching trace=[], timestamps=[], options={} + defaults = { 'output' => 'json' } + locs = trace.compact.map { |w| "loc=#{w.lat},#{w.lon}" } + ts = timestamps.compact.map { |t| "t=#{t}" } + if ts.length > 0 + trace_params = locs.zip(ts).map { |a| a.join('&')} + else + trace_params = locs + end + params = (trace_params + defaults.merge(options).to_param).join('&') + params = nil if params=="" + uri = URI.parse ["#{HOST}/match", params].compact.join('?') + @query = uri.to_s + Timeout.timeout(OSRM_TIMEOUT) do + Net::HTTP.get_response uri + end +rescue Errno::ECONNREFUSED => e + raise "*** osrm-routed is not running." +rescue Timeout::Error + raise "*** osrm-routed did not respond." +end + diff --git a/features/testbot/loop.feature b/features/testbot/loop.feature index fe898ecf0..72cad33c0 100644 --- a/features/testbot/loop.feature +++ b/features/testbot/loop.feature @@ -64,13 +64,13 @@ Feature: Avoid weird loops caused by rounding errors | | d | | And the ways - | nodes | highway | - | ab | primary | - | bc | primary | - | cd | primary | - | be | secondary | - | ef | secondary | - | cf | secondary | + | nodes | highway | + | ab | residential | + | bc | residential | + | cd | residential | + | be | primary | + | ef | primary | + | cf | primary | When I route I should get | waypoints | route | turns | diff --git a/features/testbot/matching.feature b/features/testbot/matching.feature new file mode 100644 index 000000000..774e8a9d6 --- /dev/null +++ b/features/testbot/matching.feature @@ -0,0 +1,55 @@ +@match @testbot +Feature: Basic Map Matching + + Background: + Given the profile "testbot" + Given a grid size of 10 meters + + Scenario: Testbot - Map matching with trace splitting + Given the node map + | a | b | c | d | + | | | e | | + + And the ways + | nodes | oneway | + | abcd | no | + + When I match I should get + | trace | timestamps | matchings | + | abcd | 0 1 62 63 | ab,cd | + + Scenario: Testbot - Map matching with small distortion + Given the node map + | a | b | c | d | e | + | | f | | | | + | | | | | | + | | | | | | + | | | | | | + | | h | | | k | + + # The second way does not need to be a oneway + # but the grid spacing triggers the uturn + # detection on f + And the ways + | nodes | oneway | + | abcde | no | + | bfhke | yes | + + When I match I should get + | trace | matchings | + | afcde | abcde | + + Scenario: Testbot - Map matching with oneways + Given the node map + | a | b | c | d | + | e | f | g | h | + + And the ways + | nodes | oneway | + | abcd | yes | + | hgfe | yes | + + When I match I should get + | trace | matchings | + | dcba | hgfe | + diff --git a/include/osrm/coordinate.hpp b/include/osrm/coordinate.hpp new file mode 100644 index 000000000..6318465e1 --- /dev/null +++ b/include/osrm/coordinate.hpp @@ -0,0 +1,71 @@ +/* + +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_HPP_ +#define COORDINATE_HPP_ + +#include //for std::ostream +#include +#include + +namespace +{ +constexpr static const float COORDINATE_PRECISION = 1000000.f; +} + +struct FixedPointCoordinate +{ + int lat; + int lon; + + FixedPointCoordinate(); + FixedPointCoordinate(int lat, int lon); + + template + FixedPointCoordinate(const T &coordinate) + : lat(coordinate.lat), lon(coordinate.lon) + { + static_assert(std::is_same::value, + "coordinate types incompatible"); + static_assert(std::is_same::value, + "coordinate types incompatible"); + } + + bool is_valid() const; + bool operator==(const FixedPointCoordinate &other) const; + + float bearing(const FixedPointCoordinate &other) const; + void output(std::ostream &out) const; +}; + +inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate const &coordinate) +{ + coordinate.output(out_stream); + return out_stream; +} + +#endif /* COORDINATE_HPP_ */ diff --git a/data_structures/json_container.hpp b/include/osrm/json_container.hpp similarity index 92% rename from data_structures/json_container.hpp rename to include/osrm/json_container.hpp index 9bbbec433..40f39b825 100644 --- a/data_structures/json_container.hpp +++ b/include/osrm/json_container.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, @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // based on // https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp -#ifndef JSON_CONTAINER_H -#define JSON_CONTAINER_H +#ifndef JSON_CONTAINER_HPP +#define JSON_CONTAINER_HPP #include @@ -38,7 +38,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace JSON +namespace osrm +{ +namespace json { struct Object; @@ -90,5 +92,5 @@ struct Array }; } // namespace JSON - -#endif // JSON_CONTAINER_H +} // namespace osrm +#endif // JSON_CONTAINER_HPP diff --git a/include/osrm/libosrm_config.hpp b/include/osrm/libosrm_config.hpp new file mode 100644 index 000000000..500abf5bd --- /dev/null +++ b/include/osrm/libosrm_config.hpp @@ -0,0 +1,54 @@ +/* + +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 SERVER_CONFIG_HPP +#define SERVER_CONFIG_HPP + +#include + +struct libosrm_config +{ + libosrm_config(const libosrm_config &) = delete; + libosrm_config() + : max_locations_distance_table(100), max_locations_map_matching(-1), + use_shared_memory(false) + { + } + + libosrm_config(const ServerPaths &paths, const bool flag, const int max_table, const int max_matching) + : server_paths(paths), max_locations_distance_table(max_table), + max_locations_map_matching(max_matching), use_shared_memory(flag) + { + } + + ServerPaths server_paths; + int max_locations_distance_table; + int max_locations_map_matching; + bool use_shared_memory; +}; + +#endif // SERVER_CONFIG_HPP diff --git a/Include/osrm/RouteParameters.h b/include/osrm/route_parameters.hpp similarity index 84% rename from Include/osrm/RouteParameters.h rename to include/osrm/route_parameters.hpp index fd570a1ef..9babbd763 100644 --- a/Include/osrm/RouteParameters.h +++ b/include/osrm/route_parameters.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,10 +25,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ROUTE_PARAMETERS_H -#define ROUTE_PARAMETERS_H +#ifndef ROUTE_PARAMETERS_HPP +#define ROUTE_PARAMETERS_HPP -#include +#include #include @@ -40,7 +40,7 @@ struct RouteParameters RouteParameters(); void setZoomLevel(const short level); - + void setNumberOfResults(const short number); void setAlternateRouteFlag(const bool flag); @@ -49,6 +49,12 @@ struct RouteParameters void setAllUTurns(const bool flag); + void setClassify(const bool classify); + + void setMatchingBeta(const double beta); + + void setGPSPrecision(const double precision); + void setDeprecatedAPIFlag(const std::string &); void setChecksum(const unsigned check_sum); @@ -63,13 +69,15 @@ struct RouteParameters void addHint(const std::string &hint); + void addTimestamp(const unsigned timestamp); + void setLanguage(const std::string &language); void setGeometryFlag(const bool flag); void setCompressionFlag(const bool flag); - void addCoordinate(const boost::fusion::vector &coordinates); + void addCoordinate(const boost::fusion::vector &received_coordinates); short zoom_level; bool print_instructions; @@ -78,6 +86,9 @@ struct RouteParameters bool compression; bool deprecatedAPI; bool uturn_default; + bool classify; + double matching_beta; + double gps_precision; unsigned check_sum; short num_results; std::string service; @@ -85,8 +96,9 @@ struct RouteParameters std::string jsonp_parameter; std::string language; std::vector hints; + std::vector timestamps; std::vector uturns; std::vector coordinates; }; -#endif // ROUTE_PARAMETERS_H +#endif // ROUTE_PARAMETERS_HPP diff --git a/Include/osrm/ServerPaths.h b/include/osrm/server_paths.hpp similarity index 91% rename from Include/osrm/ServerPaths.h rename to include/osrm/server_paths.hpp index 52b60c7c4..669ee7de0 100644 --- a/Include/osrm/ServerPaths.h +++ b/include/osrm/server_paths.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, @@ -33,6 +33,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -typedef std::unordered_map ServerPaths; +using ServerPaths = std::unordered_map; #endif // SERVER_PATH_H diff --git a/Library/OSRM.h b/library/osrm.hpp similarity index 81% rename from Library/OSRM.h rename to library/osrm.hpp index 372e82c39..27acb4039 100644 --- a/Library/OSRM.h +++ b/library/osrm.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,19 +25,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OSRM_H -#define OSRM_H +#ifndef OSRM_HPP +#define OSRM_HPP -#include +#include #include class OSRM_impl; struct RouteParameters; -namespace http +namespace osrm { -class Reply; +namespace json +{ +struct Object; +} } class OSRM @@ -46,9 +49,9 @@ class OSRM std::unique_ptr OSRM_pimpl_; public: - explicit OSRM(ServerPaths paths, const bool use_shared_memory = false); + explicit OSRM(libosrm_config &lib_config); ~OSRM(); - void RunQuery(RouteParameters &route_parameters, http::Reply &reply); + int RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result); }; -#endif // OSRM_H +#endif // OSRM_HPP diff --git a/Library/OSRM_impl.cpp b/library/osrm_impl.cpp similarity index 52% rename from Library/OSRM_impl.cpp rename to library/osrm_impl.cpp index 40fef682c..5bb58d174 100644 --- a/Library/OSRM_impl.cpp +++ b/library/osrm_impl.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, @@ -25,14 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -namespace boost { namespace interprocess { class named_mutex; } } +namespace boost +{ +namespace interprocess +{ +class named_mutex; +} +} -#include "OSRM_impl.h" -#include "OSRM.h" - -#include -#include -#include +#include "osrm_impl.hpp" +#include "osrm.hpp" #include "../plugins/distance_table.hpp" #include "../plugins/hello_world.hpp" @@ -40,26 +42,29 @@ namespace boost { namespace interprocess { class named_mutex; } } #include "../plugins/nearest.hpp" #include "../plugins/timestamp.hpp" #include "../plugins/viaroute.hpp" -#include "../Server/DataStructures/BaseDataFacade.h" -#include "../Server/DataStructures/InternalDataFacade.h" -#include "../Server/DataStructures/SharedBarriers.h" -#include "../Server/DataStructures/SharedDataFacade.h" -#include "../Util/make_unique.hpp" -#include "../Util/ProgramOptions.h" -#include "../Util/simple_logger.hpp" +#include "../plugins/match.hpp" +#include "../server/data_structures/datafacade_base.hpp" +#include "../server/data_structures/internal_datafacade.hpp" +#include "../server/data_structures/shared_barriers.hpp" +#include "../server/data_structures/shared_datafacade.hpp" +#include "../util/make_unique.hpp" +#include "../util/routed_options.hpp" +#include "../util/simple_logger.hpp" #include #include #include +#include + #include #include #include #include -OSRM_impl::OSRM_impl(ServerPaths server_paths, const bool use_shared_memory) +OSRM_impl::OSRM_impl(libosrm_config &lib_config) { - if (use_shared_memory) + if (lib_config.use_shared_memory) { barrier = osrm::make_unique(); query_data_facade = new SharedDataFacade(); @@ -67,15 +72,18 @@ OSRM_impl::OSRM_impl(ServerPaths server_paths, const bool use_shared_memory) else { // populate base path - populate_base_path(server_paths); - query_data_facade = new InternalDataFacade(server_paths); + populate_base_path(lib_config.server_paths); + query_data_facade = new InternalDataFacade(lib_config.server_paths); } // The following plugins handle all requests. - RegisterPlugin(new DistanceTablePlugin>(query_data_facade)); + RegisterPlugin(new DistanceTablePlugin>( + query_data_facade, lib_config.max_locations_distance_table)); RegisterPlugin(new HelloWorldPlugin()); RegisterPlugin(new LocatePlugin>(query_data_facade)); RegisterPlugin(new NearestPlugin>(query_data_facade)); + RegisterPlugin(new MapMatchingPlugin>( + query_data_facade, lib_config.max_locations_map_matching)); RegisterPlugin(new TimestampPlugin>(query_data_facade)); RegisterPlugin(new ViaRoutePlugin>(query_data_facade)); } @@ -99,67 +107,75 @@ void OSRM_impl::RegisterPlugin(BasePlugin *plugin) plugin_map.emplace(plugin->GetDescriptor(), plugin); } -void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply) +int OSRM_impl::RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result) { - const PluginMap::const_iterator &iter = plugin_map.find(route_parameters.service); + const auto &plugin_iterator = plugin_map.find(route_parameters.service); - if (plugin_map.end() != iter) + if (plugin_map.end() == plugin_iterator) { - reply.status = http::Reply::ok; - if (barrier) - { - // lock update pending - boost::interprocess::scoped_lock pending_lock( - barrier->pending_update_mutex); - - // lock query - boost::interprocess::scoped_lock query_lock( - barrier->query_mutex); - - // unlock update pending - pending_lock.unlock(); - - // increment query count - ++(barrier->number_of_queries); - - (static_cast *>(query_data_facade)) - ->CheckAndReloadFacade(); - } - - iter->second->HandleRequest(route_parameters, reply); - if (barrier) - { - // lock query - boost::interprocess::scoped_lock query_lock( - barrier->query_mutex); - - // decrement query count - --(barrier->number_of_queries); - BOOST_ASSERT_MSG(0 <= barrier->number_of_queries, "invalid number of queries"); - - // notify all processes that were waiting for this condition - if (0 == barrier->number_of_queries) - { - barrier->no_running_queries_condition.notify_all(); - } - } + return 400; } - else + + increase_concurrent_query_count(); + plugin_iterator->second->HandleRequest(route_parameters, json_result); + decrease_concurrent_query_count(); + return 200; +} + +// decrease number of concurrent queries +void OSRM_impl::decrease_concurrent_query_count() +{ + if (!barrier) { - reply = http::Reply::StockReply(http::Reply::badRequest); + return; } + // lock query + boost::interprocess::scoped_lock query_lock( + barrier->query_mutex); + + // decrement query count + --(barrier->number_of_queries); + BOOST_ASSERT_MSG(0 <= barrier->number_of_queries, "invalid number of queries"); + + // notify all processes that were waiting for this condition + if (0 == barrier->number_of_queries) + { + barrier->no_running_queries_condition.notify_all(); + } +} + +// increase number of concurrent queries +void OSRM_impl::increase_concurrent_query_count() +{ + if (!barrier) + { + return; + } + + // lock update pending + boost::interprocess::scoped_lock pending_lock( + barrier->pending_update_mutex); + + // lock query + boost::interprocess::scoped_lock query_lock( + barrier->query_mutex); + + // unlock update pending + pending_lock.unlock(); + + // increment query count + ++(barrier->number_of_queries); + + (static_cast *>(query_data_facade)) + ->CheckAndReloadFacade(); } // proxy code for compilation firewall - -OSRM::OSRM(ServerPaths paths, const bool use_shared_memory) - : OSRM_pimpl_(osrm::make_unique(paths, use_shared_memory)) -{ -} +OSRM::OSRM(libosrm_config &lib_config) : OSRM_pimpl_(osrm::make_unique(lib_config)) {} OSRM::~OSRM() { OSRM_pimpl_.reset(); } -void OSRM::RunQuery(RouteParameters &route_parameters, http::Reply &reply) +int OSRM::RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result) { - OSRM_pimpl_->RunQuery(route_parameters, reply); + return OSRM_pimpl_->RunQuery(route_parameters, json_result); } diff --git a/Library/OSRM_impl.h b/library/osrm_impl.hpp similarity index 79% rename from Library/OSRM_impl.h rename to library/osrm_impl.hpp index e8b47df56..a736c042f 100644 --- a/Library/OSRM_impl.h +++ b/library/osrm_impl.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,17 +25,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OSRM_IMPL_H -#define OSRM_IMPL_H +#ifndef OSRM_IMPL_HPP +#define OSRM_IMPL_HPP class BasePlugin; -namespace http { class Reply; } struct RouteParameters; -#include - #include "../data_structures/query_edge.hpp" +#include +#include + #include #include #include @@ -49,10 +49,10 @@ class OSRM_impl using PluginMap = std::unordered_map; public: - OSRM_impl(ServerPaths paths, const bool use_shared_memory); + OSRM_impl(libosrm_config &lib_config); OSRM_impl(const OSRM_impl &) = delete; virtual ~OSRM_impl(); - void RunQuery(RouteParameters &route_parameters, http::Reply &reply); + int RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result); private: void RegisterPlugin(BasePlugin *plugin); @@ -61,6 +61,11 @@ class OSRM_impl std::unique_ptr barrier; // base class pointer to the objects BaseDataFacade *query_data_facade; + + // decrease number of concurrent queries + void decrease_concurrent_query_count(); + // increase number of concurrent queries + void increase_concurrent_query_count(); }; -#endif // OSRM_IMPL_H +#endif // OSRM_IMPL_HPP diff --git a/plugins/distance_table.hpp b/plugins/distance_table.hpp index 6ef90a5b8..d7a980419 100644 --- a/plugins/distance_table.hpp +++ b/plugins/distance_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, @@ -25,20 +25,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DISTANCE_TABLE_PLUGIN_H -#define DISTANCE_TABLE_PLUGIN_H +#ifndef DISTANCE_TABLE_HPP +#define DISTANCE_TABLE_HPP #include "plugin_base.hpp" #include "../algorithms/object_encoder.hpp" -#include "../data_structures/json_container.hpp" #include "../data_structures/query_edge.hpp" #include "../data_structures/search_engine.hpp" #include "../descriptors/descriptor_base.hpp" -#include "../Util/json_renderer.hpp" -#include "../Util/make_unique.hpp" -#include "../Util/string_util.hpp" -#include "../Util/timing_util.hpp" +#include "../util/json_renderer.hpp" +#include "../util/make_unique.hpp" +#include "../util/string_util.hpp" +#include "../util/timing_util.hpp" + +#include #include @@ -52,28 +53,33 @@ template class DistanceTablePlugin final : public BasePlugin { private: std::unique_ptr> search_engine_ptr; + int max_locations_distance_table; public: - explicit DistanceTablePlugin(DataFacadeT *facade) : descriptor_string("table"), facade(facade) + explicit DistanceTablePlugin(DataFacadeT *facade, const int max_locations_distance_table) + : max_locations_distance_table(max_locations_distance_table), descriptor_string("table"), + facade(facade) { search_engine_ptr = osrm::make_unique>(facade); } virtual ~DistanceTablePlugin() {} - const std::string GetDescriptor() const final { return descriptor_string; } + const std::string GetDescriptor() const override final { return descriptor_string; } - void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final + int HandleRequest(const RouteParameters &route_parameters, + osrm::json::Object &json_result) override final { if (!check_all_coordinates(route_parameters.coordinates)) { - reply = http::Reply::StockReply(http::Reply::badRequest); - return; + return 400; } const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); unsigned max_locations = - std::min(100u, static_cast(route_parameters.coordinates.size())); + std::min(static_cast(max_locations_distance_table), + static_cast(route_parameters.coordinates.size())); + PhantomNodeArray phantom_node_vector(max_locations); for (const auto i : osrm::irange(0u, max_locations)) { @@ -89,8 +95,7 @@ template class DistanceTablePlugin final : public BasePlugin } } facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i], - phantom_node_vector[i], - 1); + phantom_node_vector[i], 1); BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes())); } @@ -102,23 +107,22 @@ template class DistanceTablePlugin final : public BasePlugin if (!result_table) { - reply = http::Reply::StockReply(http::Reply::badRequest); - return; + return 400; } - JSON::Object json_object; - JSON::Array json_array; + osrm::json::Array json_array; const auto number_of_locations = phantom_node_vector.size(); for (const auto row : osrm::irange(0, number_of_locations)) { - JSON::Array json_row; + osrm::json::Array json_row; auto row_begin_iterator = result_table->begin() + (row * number_of_locations); auto row_end_iterator = result_table->begin() + ((row + 1) * number_of_locations); json_row.values.insert(json_row.values.end(), row_begin_iterator, row_end_iterator); json_array.values.push_back(json_row); } - json_object.values["distance_table"] = json_array; - JSON::render(reply.content, json_object); + json_result.values["distance_table"] = json_array; + // osrm::json::render(reply.content, json_object); + return 200; } private: @@ -126,4 +130,4 @@ template class DistanceTablePlugin final : public BasePlugin DataFacadeT *facade; }; -#endif // DISTANCE_TABLE_PLUGIN_H +#endif // DISTANCE_TABLE_HPP diff --git a/plugins/hello_world.hpp b/plugins/hello_world.hpp index c8b07b081..faf5b1048 100644 --- a/plugins/hello_world.hpp +++ b/plugins/hello_world.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, @@ -25,14 +25,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef HELLO_WORLD_PLUGIN_H -#define HELLO_WORLD_PLUGIN_H +#ifndef HELLO_WORLD_HPP +#define HELLO_WORLD_HPP #include "plugin_base.hpp" -#include "../data_structures/json_container.hpp" -#include "../Util/cast.hpp" -#include "../Util/json_renderer.hpp" +#include "../util/cast.hpp" +#include "../util/json_renderer.hpp" + +#include #include @@ -44,13 +45,11 @@ class HelloWorldPlugin final : public BasePlugin public: HelloWorldPlugin() : descriptor_string("hello") {} virtual ~HelloWorldPlugin() {} - const std::string GetDescriptor() const final { return descriptor_string; } + const std::string GetDescriptor() const override final { return descriptor_string; } - void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply) final + int HandleRequest(const RouteParameters &routeParameters, + osrm::json::Object &json_result) override final { - reply.status = http::Reply::ok; - - JSON::Object json_result; std::string temp_string; json_result.values["title"] = "Hello World"; @@ -72,15 +71,17 @@ class HelloWorldPlugin final : public BasePlugin temp_string = cast::integral_to_string(routeParameters.coordinates.size()); json_result.values["location_count"] = temp_string; - JSON::Array json_locations; + osrm::json::Array json_locations; unsigned counter = 0; for (const FixedPointCoordinate &coordinate : routeParameters.coordinates) { - JSON::Object json_location; - JSON::Array json_coordinates; + osrm::json::Object json_location; + osrm::json::Array json_coordinates; - json_coordinates.values.push_back(static_cast(coordinate.lat / COORDINATE_PRECISION)); - json_coordinates.values.push_back(static_cast(coordinate.lon / COORDINATE_PRECISION)); + json_coordinates.values.push_back( + static_cast(coordinate.lat / COORDINATE_PRECISION)); + json_coordinates.values.push_back( + static_cast(coordinate.lon / COORDINATE_PRECISION)); json_location.values[cast::integral_to_string(counter)] = json_coordinates; json_locations.values.push_back(json_location); ++counter; @@ -88,7 +89,7 @@ class HelloWorldPlugin final : public BasePlugin json_result.values["locations"] = json_locations; json_result.values["hint_count"] = routeParameters.hints.size(); - JSON::Array json_hints; + osrm::json::Array json_hints; counter = 0; for (const std::string ¤t_hint : routeParameters.hints) { @@ -96,12 +97,11 @@ class HelloWorldPlugin final : public BasePlugin ++counter; } json_result.values["hints"] = json_hints; - - JSON::render(reply.content, json_result); + return 200; } private: std::string descriptor_string; }; -#endif // HELLO_WORLD_PLUGIN_H +#endif // HELLO_WORLD_HPP diff --git a/plugins/locate.hpp b/plugins/locate.hpp index 6171395c4..144765ad8 100644 --- a/plugins/locate.hpp +++ b/plugins/locate.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, @@ -25,14 +25,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef LOCATE_PLUGIN_H -#define LOCATE_PLUGIN_H +#ifndef LOCATE_HPP +#define LOCATE_HPP #include "plugin_base.hpp" -#include "../data_structures/json_container.hpp" -#include "../Util/json_renderer.hpp" -#include "../Util/string_util.hpp" +#include "../util/json_renderer.hpp" +#include "../util/string_util.hpp" + +#include #include @@ -41,18 +42,18 @@ template class LocatePlugin final : public BasePlugin { public: explicit LocatePlugin(DataFacadeT *facade) : descriptor_string("locate"), facade(facade) {} - const std::string GetDescriptor() const final { return descriptor_string; } + const std::string GetDescriptor() const override final { return descriptor_string; } - void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final + int HandleRequest(const RouteParameters &route_parameters, + osrm::json::Object &json_result) override final { // check number of parameters - if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().is_valid()) + if (route_parameters.coordinates.empty() || + !route_parameters.coordinates.front().is_valid()) { - reply = http::Reply::StockReply(http::Reply::badRequest); - return; + return 400; } - JSON::Object json_result; FixedPointCoordinate result; if (!facade->LocateClosestEndPointForCoordinate(route_parameters.coordinates.front(), result)) @@ -61,15 +62,13 @@ template class LocatePlugin final : public BasePlugin } else { - reply.status = http::Reply::ok; json_result.values["status"] = 0; - JSON::Array json_coordinate; + osrm::json::Array json_coordinate; json_coordinate.values.push_back(result.lat / COORDINATE_PRECISION); json_coordinate.values.push_back(result.lon / COORDINATE_PRECISION); json_result.values["mapped_coordinate"] = json_coordinate; } - - JSON::render(reply.content, json_result); + return 200; } private: @@ -77,4 +76,4 @@ template class LocatePlugin final : public BasePlugin DataFacadeT *facade; }; -#endif /* LOCATE_PLUGIN_H */ +#endif /* LOCATE_HPP */ diff --git a/plugins/match.hpp b/plugins/match.hpp new file mode 100644 index 000000000..a866947b4 --- /dev/null +++ b/plugins/match.hpp @@ -0,0 +1,314 @@ +/* + +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 MATCH_HPP +#define MATCH_HPP + +#include "plugin_base.hpp" + +#include "../algorithms/bayes_classifier.hpp" +#include "../algorithms/object_encoder.hpp" +#include "../data_structures/search_engine.hpp" +#include "../descriptors/descriptor_base.hpp" +#include "../descriptors/json_descriptor.hpp" +#include "../routing_algorithms/map_matching.hpp" +#include "../util/compute_angle.hpp" +#include "../util/integer_range.hpp" +#include "../util/json_logger.hpp" +#include "../util/json_util.hpp" +#include "../util/string_util.hpp" + +#include + +#include +#include +#include +#include + +template class MapMatchingPlugin : public BasePlugin +{ + constexpr static const unsigned max_number_of_candidates = 10; + + std::shared_ptr> search_engine_ptr; + + using ClassifierT = BayesClassifier; + using TraceClassification = ClassifierT::ClassificationT; + + public: + MapMatchingPlugin(DataFacadeT *facade, const int max_locations_map_matching) + : descriptor_string("match"), facade(facade), + max_locations_map_matching(max_locations_map_matching), + // the values where derived from fitting a laplace distribution + // to the values of manually classified traces + classifier(LaplaceDistribution(0.005986, 0.016646), + LaplaceDistribution(0.054385, 0.458432), + 0.696774) // valid apriori probability + { + search_engine_ptr = std::make_shared>(facade); + } + + virtual ~MapMatchingPlugin() {} + + const std::string GetDescriptor() const final { return descriptor_string; } + + TraceClassification + classify(const float trace_length, const float matched_length, const int removed_points) const + { + const double distance_feature = -std::log(trace_length) + std::log(matched_length); + + // matched to the same point + if (!std::isfinite(distance_feature)) + { + return std::make_pair(ClassifierT::ClassLabel::NEGATIVE, 1.0); + } + + const auto label_with_confidence = classifier.classify(distance_feature); + + return label_with_confidence; + } + + bool getCandiates(const std::vector &input_coords, + std::vector &sub_trace_lengths, + osrm::matching::CandidateLists &candidates_lists) + { + double last_distance = + coordinate_calculation::great_circle_distance(input_coords[0], input_coords[1]); + sub_trace_lengths.resize(input_coords.size()); + sub_trace_lengths[0] = 0; + for (const auto current_coordinate : osrm::irange(0, input_coords.size())) + { + bool allow_uturn = false; + if (0 < current_coordinate) + { + last_distance = coordinate_calculation::great_circle_distance( + input_coords[current_coordinate - 1], input_coords[current_coordinate]); + sub_trace_lengths[current_coordinate] += + sub_trace_lengths[current_coordinate - 1] + last_distance; + } + + if (input_coords.size() - 1 > current_coordinate && 0 < current_coordinate) + { + double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates( + input_coords[current_coordinate - 1], input_coords[current_coordinate], + input_coords[current_coordinate + 1]); + + // sharp turns indicate a possible uturn + if (turn_angle <= 90.0 || turn_angle >= 270.0) + { + allow_uturn = true; + } + } + + std::vector> candidates; + if (!facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance( + input_coords[current_coordinate], candidates, last_distance / 2.0, 5, + max_number_of_candidates)) + { + return false; + } + + if (allow_uturn) + { + candidates_lists.push_back(candidates); + } + else + { + const auto compact_size = candidates.size(); + for (const auto i : osrm::irange(0, compact_size)) + { + // Split edge if it is bidirectional and append reverse direction to end of list + if (candidates[i].first.forward_node_id != SPECIAL_NODEID && + candidates[i].first.reverse_node_id != SPECIAL_NODEID) + { + PhantomNode reverse_node(candidates[i].first); + reverse_node.forward_node_id = SPECIAL_NODEID; + candidates.push_back(std::make_pair(reverse_node, candidates[i].second)); + + candidates[i].first.reverse_node_id = SPECIAL_NODEID; + } + } + candidates_lists.push_back(candidates); + } + } + + return true; + } + + osrm::json::Object submatchingToJSON(const osrm::matching::SubMatching &sub, + const RouteParameters &route_parameters, + const InternalRouteResult &raw_route) + { + osrm::json::Object subtrace; + + if (route_parameters.classify) + { + subtrace.values["confidence"] = sub.confidence; + } + + if (route_parameters.geometry) + { + DescriptionFactory factory; + FixedPointCoordinate current_coordinate; + factory.SetStartSegment(raw_route.segment_end_coordinates.front().source_phantom, + raw_route.source_traversed_in_reverse.front()); + for (const auto i : + osrm::irange(0, raw_route.unpacked_path_segments.size())) + { + for (const PathData &path_data : raw_route.unpacked_path_segments[i]) + { + current_coordinate = facade->GetCoordinateOfNode(path_data.node); + factory.AppendSegment(current_coordinate, path_data); + } + factory.SetEndSegment(raw_route.segment_end_coordinates[i].target_phantom, + raw_route.target_traversed_in_reverse[i], + raw_route.is_via_leg(i)); + } + // we need this because we don't run DP + for (auto &segment : factory.path_description) + { + segment.necessary = true; + } + subtrace.values["geometry"] = + factory.AppendGeometryString(route_parameters.compression); + } + + subtrace.values["indices"] = osrm::json::make_array(sub.indices); + + osrm::json::Array points; + for (const auto &node : sub.nodes) + { + points.values.emplace_back( + osrm::json::make_array(node.location.lat / COORDINATE_PRECISION, + node.location.lon / COORDINATE_PRECISION)); + } + subtrace.values["matched_points"] = points; + + return subtrace; + } + + int HandleRequest(const RouteParameters &route_parameters, + osrm::json::Object &json_result) final + { + // check number of parameters + if (!check_all_coordinates(route_parameters.coordinates)) + { + return 400; + } + + std::vector sub_trace_lengths; + osrm::matching::CandidateLists candidates_lists; + const auto &input_coords = route_parameters.coordinates; + const auto &input_timestamps = route_parameters.timestamps; + if (input_timestamps.size() > 0 && input_coords.size() != input_timestamps.size()) + { + return 400; + } + + // enforce maximum number of locations for performance reasons + if (max_locations_map_matching > 0 && + static_cast(input_coords.size()) < max_locations_map_matching) + { + return 400; + } + + const bool found_candidates = + getCandiates(input_coords, sub_trace_lengths, candidates_lists); + if (!found_candidates) + { + return 400; + } + + // setup logging if enabled + if (osrm::json::Logger::get()) + osrm::json::Logger::get()->initialize("matching"); + + // call the actual map matching + osrm::matching::SubMatchingList sub_matchings; + search_engine_ptr->map_matching(candidates_lists, input_coords, input_timestamps, + route_parameters.matching_beta, + route_parameters.gps_precision, sub_matchings); + + if (sub_matchings.empty()) + { + return 400; + } + + osrm::json::Array matchings; + for (auto &sub : sub_matchings) + { + // classify result + if (route_parameters.classify) + { + double trace_length = + sub_trace_lengths[sub.indices.back()] - sub_trace_lengths[sub.indices.front()]; + TraceClassification classification = + classify(trace_length, sub.length, + (sub.indices.back() - sub.indices.front() + 1) - sub.nodes.size()); + if (classification.first == ClassifierT::ClassLabel::POSITIVE) + { + sub.confidence = classification.second; + } + else + { + sub.confidence = 1 - classification.second; + } + } + + BOOST_ASSERT(sub.nodes.size() > 1); + + // FIXME we only run this to obtain the geometry + // The clean way would be to get this directly from the map matching plugin + InternalRouteResult raw_route; + PhantomNodes current_phantom_node_pair; + for (unsigned i = 0; i < sub.nodes.size() - 1; ++i) + { + current_phantom_node_pair.source_phantom = sub.nodes[i]; + current_phantom_node_pair.target_phantom = sub.nodes[i + 1]; + raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair); + } + search_engine_ptr->shortest_path( + raw_route.segment_end_coordinates, + std::vector(raw_route.segment_end_coordinates.size(), true), raw_route); + + matchings.values.emplace_back(submatchingToJSON(sub, route_parameters, raw_route)); + } + + if (osrm::json::Logger::get()) + osrm::json::Logger::get()->render("matching", json_result); + json_result.values["matchings"] = matchings; + + return 200; + } + + private: + std::string descriptor_string; + DataFacadeT *facade; + int max_locations_map_matching; + ClassifierT classifier; +}; + +#endif // MATCH_HPP diff --git a/plugins/nearest.hpp b/plugins/nearest.hpp index ac1079be4..bf4cff3a1 100644 --- a/plugins/nearest.hpp +++ b/plugins/nearest.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, @@ -25,15 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef NEAREST_PLUGIN_H -#define NEAREST_PLUGIN_H +#ifndef NEAREST_HPP +#define NEAREST_HPP #include "plugin_base.hpp" -#include "../data_structures/json_container.hpp" #include "../data_structures/phantom_node.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/json_renderer.hpp" +#include "../util/integer_range.hpp" +#include "../util/json_renderer.hpp" + +#include #include @@ -46,15 +47,16 @@ template class NearestPlugin final : public BasePlugin public: explicit NearestPlugin(DataFacadeT *facade) : facade(facade), descriptor_string("nearest") {} - const std::string GetDescriptor() const final { return descriptor_string; } + const std::string GetDescriptor() const override final { return descriptor_string; } - void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final + int HandleRequest(const RouteParameters &route_parameters, + osrm::json::Object &json_result) override final { // check number of parameters - if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().is_valid()) + if (route_parameters.coordinates.empty() || + !route_parameters.coordinates.front().is_valid()) { - reply = http::Reply::StockReply(http::Reply::badRequest); - return; + return 400; } auto number_of_results = static_cast(route_parameters.num_results); std::vector phantom_node_vector; @@ -62,51 +64,49 @@ template class NearestPlugin final : public BasePlugin phantom_node_vector, static_cast(number_of_results)); - JSON::Object json_result; if (phantom_node_vector.empty() || !phantom_node_vector.front().is_valid()) { json_result.values["status"] = 207; } else { - reply.status = http::Reply::ok; + // reply.status = http::Reply::ok; json_result.values["status"] = 0; if (number_of_results > 1) { - JSON::Array results; + osrm::json::Array results; auto vector_length = phantom_node_vector.size(); - for (const auto i : osrm::irange(0, std::min(number_of_results, vector_length))) + for (const auto i : + osrm::irange(0, std::min(number_of_results, vector_length))) { - JSON::Array json_coordinate; - JSON::Object result; + osrm::json::Array json_coordinate; + osrm::json::Object result; json_coordinate.values.push_back(phantom_node_vector.at(i).location.lat / COORDINATE_PRECISION); json_coordinate.values.push_back(phantom_node_vector.at(i).location.lon / COORDINATE_PRECISION); result.values["mapped coordinate"] = json_coordinate; - std::string temp_string; - facade->GetName(phantom_node_vector.at(i).name_id, temp_string); - result.values["name"] = temp_string; + result.values["name"] = + facade->get_name_for_id(phantom_node_vector.at(i).name_id); results.values.push_back(result); } json_result.values["results"] = results; } else { - JSON::Array json_coordinate; + osrm::json::Array json_coordinate; json_coordinate.values.push_back(phantom_node_vector.front().location.lat / COORDINATE_PRECISION); json_coordinate.values.push_back(phantom_node_vector.front().location.lon / COORDINATE_PRECISION); json_result.values["mapped_coordinate"] = json_coordinate; - std::string temp_string; - facade->GetName(phantom_node_vector.front().name_id, temp_string); - json_result.values["name"] = temp_string; + json_result.values["name"] = + facade->get_name_for_id(phantom_node_vector.front().name_id); } } - JSON::render(reply.content, json_result); + return 200; } private: @@ -114,4 +114,4 @@ template class NearestPlugin final : public BasePlugin std::string descriptor_string; }; -#endif /* NEAREST_PLUGIN_H */ +#endif /* NEAREST_HPP */ diff --git a/plugins/plugin_base.hpp b/plugins/plugin_base.hpp index bb23a4d57..acc820432 100644 --- a/plugins/plugin_base.hpp +++ b/plugins/plugin_base.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,13 +25,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BASEPLUGIN_H_ -#define BASEPLUGIN_H_ +#ifndef BASE_PLUGIN_HPP +#define BASE_PLUGIN_HPP -#include -#include -#include +#include +#include +#include +#include #include #include @@ -42,16 +43,15 @@ class BasePlugin // Maybe someone can explain the pure virtual destructor thing to me (dennis) virtual ~BasePlugin() {} virtual const std::string GetDescriptor() const = 0; - virtual void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply) = 0; - virtual bool check_all_coordinates(const std::vector coordinates) const final + virtual int HandleRequest(const RouteParameters &, osrm::json::Object &) = 0; + virtual bool + check_all_coordinates(const std::vector &coordinates) const final { - if (2 > coordinates.size() || - std::any_of(std::begin(coordinates), - std::end(coordinates), - [](const FixedPointCoordinate &coordinate) - { - return !coordinate.is_valid(); - })) + if (2 > coordinates.size() || std::any_of(std::begin(coordinates), std::end(coordinates), + [](const FixedPointCoordinate &coordinate) + { + return !coordinate.is_valid(); + })) { return false; } @@ -59,4 +59,4 @@ class BasePlugin } }; -#endif /* BASEPLUGIN_H_ */ +#endif /* BASE_PLUGIN_HPP */ diff --git a/plugins/timestamp.hpp b/plugins/timestamp.hpp index acdf32e7c..8a5d208b7 100644 --- a/plugins/timestamp.hpp +++ b/plugins/timestamp.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,8 +30,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "plugin_base.hpp" -#include "../data_structures/json_container.hpp" -#include "../Util/json_renderer.hpp" +#include "../util/json_renderer.hpp" + +#include #include @@ -42,15 +43,14 @@ template class TimestampPlugin final : public BasePlugin : facade(facade), descriptor_string("timestamp") { } - const std::string GetDescriptor() const final { return descriptor_string; } - void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final + const std::string GetDescriptor() const override final { return descriptor_string; } + int HandleRequest(const RouteParameters &route_parameters, + osrm::json::Object &json_result) override final { - reply.status = http::Reply::ok; - JSON::Object json_result; json_result.values["status"] = 0; const std::string timestamp = facade->GetTimestamp(); json_result.values["timestamp"] = timestamp; - JSON::render(reply.content, json_result); + return 200; } private: diff --git a/plugins/viaroute.hpp b/plugins/viaroute.hpp index 236ee395a..335bda1af 100644 --- a/plugins/viaroute.hpp +++ b/plugins/viaroute.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, @@ -35,10 +35,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../descriptors/descriptor_base.hpp" #include "../descriptors/gpx_descriptor.hpp" #include "../descriptors/json_descriptor.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/json_renderer.hpp" -#include "../Util/make_unique.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/integer_range.hpp" +#include "../util/json_renderer.hpp" +#include "../util/make_unique.hpp" +#include "../util/simple_logger.hpp" + +#include #include @@ -67,16 +69,15 @@ template class ViaRoutePlugin final : public BasePlugin virtual ~ViaRoutePlugin() {} - const std::string GetDescriptor() const final { return descriptor_string; } + const std::string GetDescriptor() const override final { return descriptor_string; } - void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final + int HandleRequest(const RouteParameters &route_parameters, + osrm::json::Object &json_result) override final { if (!check_all_coordinates(route_parameters.coordinates)) { - reply = http::Reply::StockReply(http::Reply::badRequest); - return; + return 400; } - reply.status = http::Reply::ok; std::vector phantom_node_pair_list(route_parameters.coordinates.size()); const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); @@ -143,7 +144,7 @@ template class ViaRoutePlugin final : public BasePlugin swap_phantom_from_big_cc_into_front); } - RawRouteData raw_route; + InternalRouteResult raw_route; auto build_phantom_pairs = [&raw_route](const phantom_node_pair &first_pair, const phantom_node_pair &second_pair) { @@ -183,7 +184,8 @@ template class ViaRoutePlugin final : public BasePlugin } descriptor->SetConfig(route_parameters); - descriptor->Run(raw_route, reply); + descriptor->Run(raw_route, json_result); + return 200; } }; diff --git a/prepare.cpp b/prepare.cpp index e50f134c3..af10df035 100644 --- a/prepare.cpp +++ b/prepare.cpp @@ -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, @@ -26,8 +26,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "contractor/processing_chain.hpp" +#include "util/simple_logger.hpp" -#include +#include + +#include +#include int main(int argc, char *argv[]) { diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 713c6b737..497321ccf 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -66,6 +66,10 @@ route_speeds = { ["ferry"] = 5 } +bridge_speeds = { + ["movable"] = 5 +} + surface_speeds = { ["asphalt"] = default_speed, ["cobblestone:flattened"] = 10, @@ -102,7 +106,7 @@ mode_normal = 1 mode_pushing = 2 mode_ferry = 3 mode_train = 4 - +mode_movable_bridge = 5 local function parse_maxspeed(source) if not source then @@ -159,12 +163,14 @@ function way_function (way, result) local railway = way:get_value_by_key("railway") local amenity = way:get_value_by_key("amenity") local public_transport = way:get_value_by_key("public_transport") + local bridge = way:get_value_by_key("bridge") if (not highway or highway == '') and (not route or route == '') and (not railway or railway=='') and (not amenity or amenity=='') and (not man_made or man_made=='') and - (not public_transport or public_transport=='') + (not public_transport or public_transport=='') and + (not bridge or bridge=='') then return end @@ -219,7 +225,17 @@ function way_function (way, result) end -- speed - if route_speeds[route] then + local bridge_speed = bridge_speeds[bridge] + if (bridge_speed and bridge_speed > 0) then + highway = bridge; + if duration and durationIsValid(duration) then + result.duration = math.max( parseDuration(duration), 1 ); + end + result.forward_mode = mode_movable_bridge + result.backward_mode = mode_movable_bridge + result.forward_speed = bridge_speed + result.backward_speed = bridge_speed + elseif route_speeds[route] then -- ferries (doesn't cover routes tagged using relations) result.forward_mode = mode_ferry result.backward_mode = mode_ferry diff --git a/profiles/car.lua b/profiles/car.lua index cd1f06bd4..813afd19c 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -1,9 +1,9 @@ -- Begin of globals --require("lib/access") --function temporarily inlined -barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["checkpoint"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true, ["entrance"] = true } +barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["checkpoint"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["lift_gate"] = true, ["no"] = true, ["entrance"] = true } access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true } -access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true, ["emergency"] = true } +access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true, ["emergency"] = true, ["psv"] = true } access_tag_restricted = { ["destination"] = true, ["delivery"] = true } access_tags = { "motorcar", "motor_vehicle", "vehicle" } access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" } @@ -28,6 +28,7 @@ speed_profile = { ["service"] = 15, -- ["track"] = 5, ["ferry"] = 5, + ["movable"] = 5, ["shuttle_train"] = 10, ["default"] = 10 } @@ -144,6 +145,7 @@ local speed_reduction = 0.8 --modes local mode_normal = 1 local mode_ferry = 2 +local mode_movable_bridge = 3 local function find_access_tag(source, access_tags_hierachy) for i,v in ipairs(access_tags_hierachy) do @@ -203,9 +205,7 @@ function node_function (node, result) else local barrier = node:get_value_by_key("barrier") if barrier and "" ~= barrier then - if barrier_whitelist[barrier] then - return - else + if not barrier_whitelist[barrier] then result.barrier = true end end @@ -221,8 +221,9 @@ end function way_function (way, result) local highway = way:get_value_by_key("highway") local route = way:get_value_by_key("route") + local bridge = way:get_value_by_key("bridge") - if not ((highway and highway ~= "") or (route and route ~= "")) then + if not ((highway and highway ~= "") or (route and route ~= "") or (bridge and bridge ~= "")) then return end @@ -248,15 +249,21 @@ function way_function (way, result) return end + local width = math.huge + local width_string = way:get_value_by_key("width") + if width_string and tonumber(width_string:match("%d*")) then + width = tonumber(width_string:match("%d*")) + end + -- Check if we are allowed to access the way local access = find_access_tag(way, access_tags_hierachy) if access_tag_blacklist[access] then return end - -- Handling ferries and piers + -- handling ferries and piers local route_speed = speed_profile[route] - if(route_speed and route_speed > 0) then + if (route_speed and route_speed > 0) then highway = route; local duration = way:get_value_by_key("duration") if duration and durationIsValid(duration) then @@ -268,6 +275,21 @@ function way_function (way, result) result.backward_speed = route_speed end + -- handling movable bridges + local bridge_speed = speed_profile[bridge] + local capacity_car = way:get_value_by_key("capacity:car") + if (bridge_speed and bridge_speed > 0) and (capacity_car ~= 0) then + highway = bridge; + local duration = way:get_value_by_key("duration") + if duration and durationIsValid(duration) then + result.duration = max( parseDuration(duration), 1 ); + end + result.forward_mode = mode_movable_bridge + result.backward_mode = mode_movable_bridge + result.forward_speed = bridge_speed + result.backward_speed = bridge_speed + end + -- leave early of this way is not accessible if "" == highway then return @@ -385,12 +407,24 @@ function way_function (way, result) result.ignore_in_grid = true end + -- scale speeds to get better avg driving times if result.forward_speed > 0 then - result.forward_speed = result.forward_speed*speed_reduction + 11; + local scaled_speed = result.forward_speed*speed_reduction + 11; + local penalized_speed = math.huge + if width <= 3 then + penalized_speed = result.forward_speed / 2; + end + result.forward_speed = math.min(penalized_speed, scaled_speed) end + if result.backward_speed > 0 then - result.backward_speed = result.backward_speed*speed_reduction + 11; + local scaled_speed = result.backward_speed*speed_reduction + 11; + local penalized_speed = math.huge + if width <= 3 then + penalized_speed = result.backward_speed / 2; + end + result.backward_speed = math.min(penalized_speed, scaled_speed) end end diff --git a/routed.cpp b/routed.cpp index 1be6dd805..8b0e2e88b 100644 --- a/routed.cpp +++ b/routed.cpp @@ -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, @@ -25,11 +25,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "Library/OSRM.h" -#include "Server/Server.h" -#include "Util/git_sha.hpp" -#include "Util/ProgramOptions.h" -#include "Util/simple_logger.hpp" +#include "library/osrm.hpp" +#include "server/server.hpp" +#include "util/git_sha.hpp" +#include "util/routed_options.hpp" +#include "util/simple_logger.hpp" #ifdef __linux__ #include @@ -69,20 +69,16 @@ int main(int argc, const char *argv[]) { LogPolicy::GetInstance().Unmute(); - bool use_shared_memory = false, trial_run = false; + bool trial_run = false; std::string ip_address; int ip_port, requested_thread_num; - ServerPaths server_paths; + libosrm_config lib_config; - const unsigned init_result = GenerateServerProgramOptions(argc, - argv, - server_paths, - ip_address, - ip_port, - requested_thread_num, - use_shared_memory, - trial_run); + const unsigned init_result = GenerateServerProgramOptions( + argc, argv, lib_config.server_paths, ip_address, ip_port, requested_thread_num, + lib_config.use_shared_memory, trial_run, lib_config.max_locations_distance_table, + lib_config.max_locations_map_matching); if (init_result == INIT_OK_DO_NOT_START_ENGINE) { return 0; @@ -101,7 +97,7 @@ int main(int argc, const char *argv[]) #endif SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION; - if (use_shared_memory) + if (lib_config.use_shared_memory) { SimpleLogger().Write(logDEBUG) << "Loading from shared memory"; } @@ -117,9 +113,8 @@ int main(int argc, const char *argv[]) pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask); #endif - OSRM osrm_lib(server_paths, use_shared_memory); - auto routing_server = - Server::CreateServer(ip_address, ip_port, requested_thread_num); + OSRM osrm_lib(lib_config); + auto routing_server = Server::CreateServer(ip_address, ip_port, requested_thread_num); routing_server->GetRequestHandlerPtr().RegisterRoutingMachine(&osrm_lib); @@ -129,7 +124,11 @@ int main(int argc, const char *argv[]) } else { - std::packaged_task server_task([&]()->int{ routing_server->Run(); return 0; }); + std::packaged_task server_task([&]() -> int + { + routing_server->Run(); + return 0; + }); auto future = server_task.get_future(); std::thread server_thread(std::move(server_task)); @@ -158,7 +157,7 @@ int main(int argc, const char *argv[]) if (status == std::future_status::ready) { - server_thread.join(); + server_thread.join(); } else { diff --git a/routing_algorithms/alternative_path.hpp b/routing_algorithms/alternative_path.hpp index 84b5856fb..1dcc02096 100644 --- a/routing_algorithms/alternative_path.hpp +++ b/routing_algorithms/alternative_path.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,8 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "routing_base.hpp" #include "../data_structures/search_engine_data.hpp" -#include "../Util/integer_range.hpp" -#include "../Util/container.hpp" +#include "../util/integer_range.hpp" +#include "../util/container.hpp" #include @@ -44,9 +44,11 @@ const double VIAPATH_ALPHA = 0.10; const double VIAPATH_EPSILON = 0.15; // alternative at most 15% longer const double VIAPATH_GAMMA = 0.75; // alternative shares at most 75% with the shortest. -template class AlternativeRouting final : private BasicRoutingInterface +template +class AlternativeRouting final + : private BasicRoutingInterface> { - using super = BasicRoutingInterface; + using super = BasicRoutingInterface>; using EdgeData = typename DataFacadeT::EdgeData; using QueryHeap = SearchEngineData::QueryHeap; using SearchSpaceEdge = std::pair; @@ -78,7 +80,7 @@ template class AlternativeRouting final : private BasicRouti virtual ~AlternativeRouting() {} - void operator()(const PhantomNodes &phantom_node_pair, RawRouteData &raw_route_data) + void operator()(const PhantomNodes &phantom_node_pair, InternalRouteResult &raw_route_data) { std::vector alternative_path; std::vector via_node_candidate_list; @@ -93,17 +95,16 @@ template class AlternativeRouting final : private BasicRouti engine_working_data.InitializeOrClearThirdThreadLocalStorage( super::facade->GetNumberOfNodes()); - QueryHeap &forward_heap1 = *(engine_working_data.forwardHeap); - QueryHeap &reverse_heap1 = *(engine_working_data.backwardHeap); - QueryHeap &forward_heap2 = *(engine_working_data.forwardHeap2); - QueryHeap &reverse_heap2 = *(engine_working_data.backwardHeap2); + QueryHeap &forward_heap1 = *(engine_working_data.forward_heap_1); + QueryHeap &reverse_heap1 = *(engine_working_data.reverse_heap_1); + QueryHeap &forward_heap2 = *(engine_working_data.forward_heap_2); + QueryHeap &reverse_heap2 = *(engine_working_data.reverse_heap_2); int upper_bound_to_shortest_path_distance = INVALID_EDGE_WEIGHT; NodeID middle_node = SPECIAL_NODEID; - EdgeWeight min_edge_offset = - std::min(0, -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset()); - min_edge_offset = std::min(min_edge_offset, - -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); + const EdgeWeight min_edge_offset = + std::min(phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); if (phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID) { @@ -148,22 +149,16 @@ template class AlternativeRouting final : private BasicRouti { if (0 < forward_heap1.Size()) { - AlternativeRoutingStep(forward_heap1, - reverse_heap1, - &middle_node, + AlternativeRoutingStep(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, - via_node_candidate_list, - forward_search_space, + via_node_candidate_list, forward_search_space, min_edge_offset); } if (0 < reverse_heap1.Size()) { - AlternativeRoutingStep(reverse_heap1, - forward_heap1, - &middle_node, + AlternativeRoutingStep(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, - via_node_candidate_list, - reverse_search_space, + via_node_candidate_list, reverse_search_space, min_edge_offset); } } @@ -274,19 +269,16 @@ template class AlternativeRouting final : private BasicRouti std::vector &packed_shortest_path = packed_forward_path; std::reverse(packed_shortest_path.begin(), packed_shortest_path.end()); packed_shortest_path.emplace_back(middle_node); - packed_shortest_path.insert( - packed_shortest_path.end(), packed_reverse_path.begin(), packed_reverse_path.end()); + packed_shortest_path.insert(packed_shortest_path.end(), packed_reverse_path.begin(), + packed_reverse_path.end()); std::vector ranked_candidates_list; // prioritizing via nodes for deep inspection for (const NodeID node : preselected_node_list) { int length_of_via_path = 0, sharing_of_via_path = 0; - ComputeLengthAndSharingOfViaPath(node, - &length_of_via_path, - &sharing_of_via_path, - packed_shortest_path, - min_edge_offset); + ComputeLengthAndSharingOfViaPath(node, &length_of_via_path, &sharing_of_via_path, + packed_shortest_path, min_edge_offset); const int maximum_allowed_sharing = static_cast(upper_bound_to_shortest_path_distance * VIAPATH_GAMMA); if (sharing_of_via_path <= maximum_allowed_sharing && @@ -302,16 +294,10 @@ template class AlternativeRouting final : private BasicRouti NodeID s_v_middle = SPECIAL_NODEID, v_t_middle = SPECIAL_NODEID; for (const RankedCandidateNode &candidate : ranked_candidates_list) { - if (ViaNodeCandidatePassesTTest(forward_heap1, - reverse_heap1, - forward_heap2, - reverse_heap2, - candidate, - upper_bound_to_shortest_path_distance, - &length_of_via_path, - &s_v_middle, - &v_t_middle, - min_edge_offset)) + if (ViaNodeCandidatePassesTTest( + forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, candidate, + upper_bound_to_shortest_path_distance, &length_of_via_path, &s_v_middle, + &v_t_middle, min_edge_offset)) { // select first admissable selected_via_node = candidate.node; @@ -343,13 +329,8 @@ template class AlternativeRouting final : private BasicRouti { std::vector packed_alternate_path; // retrieve alternate path - RetrievePackedAlternatePath(forward_heap1, - reverse_heap1, - forward_heap2, - reverse_heap2, - s_v_middle, - v_t_middle, - packed_alternate_path); + RetrievePackedAlternatePath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, + s_v_middle, v_t_middle, packed_alternate_path); raw_route_data.alt_source_traversed_in_reverse.push_back(( packed_alternate_path.front() != phantom_node_pair.source_phantom.forward_node_id)); @@ -357,8 +338,8 @@ template class AlternativeRouting final : private BasicRouti (packed_alternate_path.back() != phantom_node_pair.target_phantom.forward_node_id)); // unpack the alternate path - super::UnpackPath( - packed_alternate_path, phantom_node_pair, raw_route_data.unpacked_alternative); + super::UnpackPath(packed_alternate_path, phantom_node_pair, + raw_route_data.unpacked_alternative); raw_route_data.alternative_path_length = length_of_via_path; } @@ -370,13 +351,13 @@ template class AlternativeRouting final : private BasicRouti private: // unpack alternate by exploring search spaces from v - inline void RetrievePackedAlternatePath(const QueryHeap &forward_heap1, - const QueryHeap &reverse_heap1, - const QueryHeap &forward_heap2, - const QueryHeap &reverse_heap2, - const NodeID s_v_middle, - const NodeID v_t_middle, - std::vector &packed_path) const + void RetrievePackedAlternatePath(const QueryHeap &forward_heap1, + const QueryHeap &reverse_heap1, + const QueryHeap &forward_heap2, + const QueryHeap &reverse_heap2, + const NodeID s_v_middle, + const NodeID v_t_middle, + std::vector &packed_path) const { // fetch packed path [s,v) std::vector packed_v_t_path; @@ -384,8 +365,8 @@ template class AlternativeRouting final : private BasicRouti packed_path.pop_back(); // remove middle node. It's in both half-paths // fetch patched path [v,t] - super::RetrievePackedPathFromHeap( - forward_heap2, reverse_heap1, v_t_middle, packed_v_t_path); + super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap1, v_t_middle, + packed_v_t_path); packed_path.insert(packed_path.end(), packed_v_t_path.begin(), packed_v_t_path.end()); } @@ -394,19 +375,19 @@ template class AlternativeRouting final : private BasicRouti // compute and unpack and by exploring search spaces // from v and intersecting against queues. only half-searches have to be // done at this stage - inline void ComputeLengthAndSharingOfViaPath(const NodeID via_node, - int *real_length_of_via_path, - int *sharing_of_via_path, - const std::vector &packed_shortest_path, - const EdgeWeight min_edge_offset) + void ComputeLengthAndSharingOfViaPath(const NodeID via_node, + int *real_length_of_via_path, + int *sharing_of_via_path, + const std::vector &packed_shortest_path, + const EdgeWeight min_edge_offset) { engine_working_data.InitializeOrClearSecondThreadLocalStorage( super::facade->GetNumberOfNodes()); - QueryHeap &existing_forward_heap = *engine_working_data.forwardHeap; - QueryHeap &existing_reverse_heap = *engine_working_data.backwardHeap; - QueryHeap &new_forward_heap = *engine_working_data.forwardHeap2; - QueryHeap &new_reverse_heap = *engine_working_data.backwardHeap2; + QueryHeap &existing_forward_heap = *engine_working_data.forward_heap_1; + QueryHeap &existing_reverse_heap = *engine_working_data.reverse_heap_1; + QueryHeap &new_forward_heap = *engine_working_data.forward_heap_2; + QueryHeap &new_reverse_heap = *engine_working_data.reverse_heap_2; std::vector packed_s_v_path; std::vector packed_v_t_path; @@ -420,12 +401,8 @@ template class AlternativeRouting final : private BasicRouti // compute path by reusing forward search from s while (!new_reverse_heap.Empty()) { - super::RoutingStep(new_reverse_heap, - existing_forward_heap, - &s_v_middle, - &upper_bound_s_v_path_length, - min_edge_offset, - false); + super::RoutingStep(new_reverse_heap, existing_forward_heap, &s_v_middle, + &upper_bound_s_v_path_length, min_edge_offset, false); } // compute path by reusing backward search from node t NodeID v_t_middle = SPECIAL_NODEID; @@ -433,12 +410,8 @@ template class AlternativeRouting final : private BasicRouti new_forward_heap.Insert(via_node, 0, via_node); while (!new_forward_heap.Empty()) { - super::RoutingStep(new_forward_heap, - existing_reverse_heap, - &v_t_middle, - &upper_bound_of_v_t_path_length, - min_edge_offset, - true); + super::RoutingStep(new_forward_heap, existing_reverse_heap, &v_t_middle, + &upper_bound_of_v_t_path_length, min_edge_offset, true); } *real_length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length; @@ -448,10 +421,10 @@ template class AlternativeRouting final : private BasicRouti } // retrieve packed paths - super::RetrievePackedPathFromHeap( - existing_forward_heap, new_reverse_heap, s_v_middle, packed_s_v_path); - super::RetrievePackedPathFromHeap( - new_forward_heap, existing_reverse_heap, v_t_middle, packed_v_t_path); + super::RetrievePackedPathFromHeap(existing_forward_heap, new_reverse_heap, s_v_middle, + packed_s_v_path); + super::RetrievePackedPathFromHeap(new_forward_heap, existing_reverse_heap, v_t_middle, + packed_v_t_path); // partial unpacking, compute sharing // First partially unpack s-->v until paths deviate, note length of common path. @@ -484,12 +457,11 @@ template class AlternativeRouting final : private BasicRouti const int64_t packed_path_length = std::min(partially_unpacked_via_path.size(), partially_unpacked_shortest_path.size()) - 1; - for (int64_t current_node = 0; - (current_node < packed_path_length) && - (partially_unpacked_via_path[current_node] == - partially_unpacked_shortest_path[current_node] && - partially_unpacked_via_path[current_node + 1] == - partially_unpacked_shortest_path[current_node + 1]); + for (int64_t current_node = 0; (current_node < packed_path_length) && + (partially_unpacked_via_path[current_node] == + partially_unpacked_shortest_path[current_node] && + partially_unpacked_via_path[current_node + 1] == + partially_unpacked_shortest_path[current_node + 1]); ++current_node) { EdgeID selected_edge = @@ -517,8 +489,7 @@ template class AlternativeRouting final : private BasicRouti if (packed_v_t_path[via_path_index] == packed_shortest_path[shortest_path_index]) { super::UnpackEdge(packed_v_t_path[via_path_index - 1], - packed_v_t_path[via_path_index], - partially_unpacked_via_path); + packed_v_t_path[via_path_index], partially_unpacked_via_path); super::UnpackEdge(packed_shortest_path[shortest_path_index - 1], packed_shortest_path[shortest_path_index], partially_unpacked_shortest_path); @@ -551,7 +522,7 @@ template class AlternativeRouting final : private BasicRouti // variable } - // inline int approximateAmountOfSharing( + // int approximateAmountOfSharing( // const NodeID alternate_path_middle_node_id, // QueryHeap & forward_heap, // QueryHeap & reverse_heap, @@ -598,14 +569,17 @@ template class AlternativeRouting final : private BasicRouti // todo: reorder parameters template - inline void AlternativeRoutingStep(QueryHeap &forward_heap, - QueryHeap &reverse_heap, - NodeID *middle_node, - int *upper_bound_to_shortest_path_distance, - std::vector &search_space_intersection, - std::vector &search_space, - const EdgeWeight min_edge_offset) const + void AlternativeRoutingStep(QueryHeap &heap1, + QueryHeap &heap2, + NodeID *middle_node, + int *upper_bound_to_shortest_path_distance, + std::vector &search_space_intersection, + std::vector &search_space, + const EdgeWeight min_edge_offset) const { + QueryHeap &forward_heap = (is_forward_directed ? heap1 : heap2); + QueryHeap &reverse_heap = (is_forward_directed ? heap2 : heap1); + const NodeID node = forward_heap.DeleteMin(); const int distance = forward_heap.GetKey(node); // const NodeID parentnode = forward_heap.GetData(node).parent; @@ -674,16 +648,16 @@ template class AlternativeRouting final : private BasicRouti } // conduct T-Test - inline bool ViaNodeCandidatePassesTTest(QueryHeap &existing_forward_heap, - QueryHeap &existing_reverse_heap, - QueryHeap &new_forward_heap, - QueryHeap &new_reverse_heap, - const RankedCandidateNode &candidate, - const int length_of_shortest_path, - int *length_of_via_path, - NodeID *s_v_middle, - NodeID *v_t_middle, - const EdgeWeight min_edge_offset) const + bool ViaNodeCandidatePassesTTest(QueryHeap &existing_forward_heap, + QueryHeap &existing_reverse_heap, + QueryHeap &new_forward_heap, + QueryHeap &new_reverse_heap, + const RankedCandidateNode &candidate, + const int length_of_shortest_path, + int *length_of_via_path, + NodeID *s_v_middle, + NodeID *v_t_middle, + const EdgeWeight min_edge_offset) const { new_forward_heap.Clear(); new_reverse_heap.Clear(); @@ -696,12 +670,8 @@ template class AlternativeRouting final : private BasicRouti new_reverse_heap.Insert(candidate.node, 0, candidate.node); while (new_reverse_heap.Size() > 0) { - super::RoutingStep(new_reverse_heap, - existing_forward_heap, - s_v_middle, - &upper_bound_s_v_path_length, - min_edge_offset, - false); + super::RoutingStep(new_reverse_heap, existing_forward_heap, s_v_middle, + &upper_bound_s_v_path_length, min_edge_offset, false); } if (INVALID_EDGE_WEIGHT == upper_bound_s_v_path_length) @@ -715,12 +685,8 @@ template class AlternativeRouting final : private BasicRouti new_forward_heap.Insert(candidate.node, 0, candidate.node); while (new_forward_heap.Size() > 0) { - super::RoutingStep(new_forward_heap, - existing_reverse_heap, - v_t_middle, - &upper_bound_of_v_t_path_length, - min_edge_offset, - true); + super::RoutingStep(new_forward_heap, existing_reverse_heap, v_t_middle, + &upper_bound_of_v_t_path_length, min_edge_offset, true); } if (INVALID_EDGE_WEIGHT == upper_bound_of_v_t_path_length) @@ -731,11 +697,11 @@ template class AlternativeRouting final : private BasicRouti *length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length; // retrieve packed paths - super::RetrievePackedPathFromHeap( - existing_forward_heap, new_reverse_heap, *s_v_middle, packed_s_v_path); + super::RetrievePackedPathFromHeap(existing_forward_heap, new_reverse_heap, *s_v_middle, + packed_s_v_path); - super::RetrievePackedPathFromHeap( - new_forward_heap, existing_reverse_heap, *v_t_middle, packed_v_t_path); + super::RetrievePackedPathFromHeap(new_forward_heap, existing_reverse_heap, *v_t_middle, + packed_v_t_path); NodeID s_P = *s_v_middle, t_P = *v_t_middle; if (SPECIAL_NODEID == s_P) @@ -815,8 +781,7 @@ template class AlternativeRouting final : private BasicRouti // Traverse path s-->v BOOST_ASSERT(!packed_v_t_path.empty()); for (unsigned i = 0, packed_path_length = static_cast(packed_v_t_path.size() - 1); - (i < packed_path_length) && unpack_stack.empty(); - ++i) + (i < packed_path_length) && unpack_stack.empty(); ++i) { const EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_v_t_path[i], packed_v_t_path[i + 1]); @@ -876,8 +841,8 @@ template class AlternativeRouting final : private BasicRouti engine_working_data.InitializeOrClearThirdThreadLocalStorage( super::facade->GetNumberOfNodes()); - QueryHeap &forward_heap3 = *engine_working_data.forwardHeap3; - QueryHeap &reverse_heap3 = *engine_working_data.backwardHeap3; + QueryHeap &forward_heap3 = *engine_working_data.forward_heap_3; + QueryHeap &reverse_heap3 = *engine_working_data.reverse_heap_3; int upper_bound = INVALID_EDGE_WEIGHT; NodeID middle = SPECIAL_NODEID; @@ -888,13 +853,13 @@ template class AlternativeRouting final : private BasicRouti { if (!forward_heap3.Empty()) { - super::RoutingStep( - forward_heap3, reverse_heap3, &middle, &upper_bound, min_edge_offset, true); + super::RoutingStep(forward_heap3, reverse_heap3, &middle, &upper_bound, + min_edge_offset, true); } if (!reverse_heap3.Empty()) { - super::RoutingStep( - reverse_heap3, forward_heap3, &middle, &upper_bound, min_edge_offset, false); + super::RoutingStep(reverse_heap3, forward_heap3, &middle, &upper_bound, + min_edge_offset, false); } } return (upper_bound <= t_test_path_length); diff --git a/routing_algorithms/many_to_many.hpp b/routing_algorithms/many_to_many.hpp index f1e996096..238880471 100644 --- a/routing_algorithms/many_to_many.hpp +++ b/routing_algorithms/many_to_many.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, @@ -39,9 +39,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -template class ManyToManyRouting final : public BasicRoutingInterface +template +class ManyToManyRouting final + : public BasicRoutingInterface> { - using super = BasicRoutingInterface; + using super = BasicRoutingInterface>; using QueryHeap = SearchEngineData::QueryHeap; SearchEngineData &engine_working_data; @@ -64,8 +66,8 @@ template class ManyToManyRouting final : public BasicRouting ~ManyToManyRouting() {} - std::shared_ptr> operator()(const PhantomNodeArray &phantom_nodes_array) - const + std::shared_ptr> + operator()(const PhantomNodeArray &phantom_nodes_array) const { const auto number_of_locations = phantom_nodes_array.size(); std::shared_ptr> result_table = @@ -75,7 +77,7 @@ template class ManyToManyRouting final : public BasicRouting engine_working_data.InitializeOrClearFirstThreadLocalStorage( super::facade->GetNumberOfNodes()); - QueryHeap &query_heap = *(engine_working_data.forwardHeap); + QueryHeap &query_heap = *(engine_working_data.forward_heap_1); SearchSpaceWithBuckets search_space_with_buckets; @@ -134,11 +136,8 @@ template class ManyToManyRouting final : public BasicRouting // explore search space while (!query_heap.Empty()) { - ForwardRoutingStep(source_id, - number_of_locations, - query_heap, - search_space_with_buckets, - result_table); + ForwardRoutingStep(source_id, number_of_locations, query_heap, + search_space_with_buckets, result_table); } ++source_id; @@ -237,8 +236,8 @@ template class ManyToManyRouting final : public BasicRouting // Stalling template - inline bool StallAtNode(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap) - const + inline bool + StallAtNode(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap) const { for (auto edge : super::facade->GetAdjacentEdgeRange(node)) { diff --git a/routing_algorithms/map_matching.hpp b/routing_algorithms/map_matching.hpp new file mode 100644 index 000000000..737494b64 --- /dev/null +++ b/routing_algorithms/map_matching.hpp @@ -0,0 +1,344 @@ +/* + +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 MAP_MATCHING_HPP +#define MAP_MATCHING_HPP + +#include "routing_base.hpp" + +#include "../data_structures/coordinate_calculation.hpp" +#include "../data_structures/hidden_markov_model.hpp" +#include "../util/json_logger.hpp" +#include "../util/matching_debug_info.hpp" + +#include + +#include +#include +#include + +namespace osrm +{ +namespace matching +{ + +struct SubMatching +{ + std::vector nodes; + std::vector indices; + double length; + double confidence; +}; + +using CandidateList = std::vector>; +using CandidateLists = std::vector; +using HMM = HiddenMarkovModel; +using SubMatchingList = std::vector; + +constexpr static const unsigned MAX_BROKEN_STATES = 6; +constexpr static const unsigned MAX_BROKEN_TIME = 60; + +constexpr static const unsigned MAX_DISTANCE_DELTA = 200; +constexpr static const unsigned SUSPICIOUS_DISTANCE_DELTA = 100; + +constexpr static const double default_beta = 5.0; +constexpr static const double default_sigma_z = 4.07; +} +} + +// implements a hidden markov model map matching algorithm +template +class MapMatching final : public BasicRoutingInterface> +{ + using super = BasicRoutingInterface>; + using QueryHeap = SearchEngineData::QueryHeap; + SearchEngineData &engine_working_data; + + public: + MapMatching(DataFacadeT *facade, SearchEngineData &engine_working_data) + : super(facade), engine_working_data(engine_working_data) + { + } + + void operator()(const osrm::matching::CandidateLists &candidates_list, + const std::vector &trace_coordinates, + const std::vector &trace_timestamps, + const double matching_beta, + const double gps_precision, + osrm::matching::SubMatchingList &sub_matchings) const + { + BOOST_ASSERT(!candidates_list.empty() && !trace_coordinates.empty()); + + // TODO replace default values with table lookup based on sampling frequency + EmissionLogProbability emission_log_probability( + gps_precision > 0. ? gps_precision : osrm::matching::default_sigma_z); + TransitionLogProbability transition_log_probability( + matching_beta > 0. ? matching_beta : osrm::matching::default_beta); + + osrm::matching::HMM model(candidates_list, emission_log_probability); + + std::size_t initial_timestamp = model.initialize(0); + if (initial_timestamp == osrm::matching::INVALID_STATE) + { + return; + } + + MatchingDebugInfo matching_debug(osrm::json::Logger::get()); + matching_debug.initialize(candidates_list); + + std::size_t breakage_begin = osrm::matching::INVALID_STATE; + std::vector split_points; + std::vector prev_unbroken_timestamps; + prev_unbroken_timestamps.reserve(candidates_list.size()); + prev_unbroken_timestamps.push_back(initial_timestamp); + for (auto t = initial_timestamp + 1; t < candidates_list.size(); ++t) + { + // breakage recover has removed all previous good points + bool trace_split = prev_unbroken_timestamps.empty(); + + // use temporal information if available to determine a split + if (!trace_timestamps.empty()) + { + trace_split = + trace_split || + (trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()] > + osrm::matching::MAX_BROKEN_TIME); + } + else + { + trace_split = trace_split || (t - prev_unbroken_timestamps.back() > + osrm::matching::MAX_BROKEN_STATES); + } + + if (trace_split) + { + std::size_t split_index = t; + if (breakage_begin != osrm::matching::INVALID_STATE) + { + split_index = breakage_begin; + breakage_begin = osrm::matching::INVALID_STATE; + } + split_points.push_back(split_index); + + // note: this preserves everything before split_index + model.clear(split_index); + std::size_t new_start = model.initialize(split_index); + // no new start was found -> stop viterbi calculation + if (new_start == osrm::matching::INVALID_STATE) + { + break; + } + + prev_unbroken_timestamps.clear(); + prev_unbroken_timestamps.push_back(new_start); + // Important: We potentially go back here! + // However since t > new_start >= breakge_begin + // we can only reset trace_coordindates.size() times. + t = new_start + 1; + } + + BOOST_ASSERT(!prev_unbroken_timestamps.empty()); + const std::size_t prev_unbroken_timestamp = prev_unbroken_timestamps.back(); + + const auto &prev_viterbi = model.viterbi[prev_unbroken_timestamp]; + const auto &prev_pruned = model.pruned[prev_unbroken_timestamp]; + const auto &prev_unbroken_timestamps_list = candidates_list[prev_unbroken_timestamp]; + const auto &prev_coordinate = trace_coordinates[prev_unbroken_timestamp]; + + auto ¤t_viterbi = model.viterbi[t]; + auto ¤t_pruned = model.pruned[t]; + auto ¤t_suspicious = model.suspicious[t]; + auto ¤t_parents = model.parents[t]; + auto ¤t_lengths = model.path_lengths[t]; + const auto ¤t_timestamps_list = candidates_list[t]; + const auto ¤t_coordinate = trace_coordinates[t]; + + engine_working_data.InitializeOrClearFirstThreadLocalStorage( + super::facade->GetNumberOfNodes()); + engine_working_data.InitializeOrClearSecondThreadLocalStorage( + super::facade->GetNumberOfNodes()); + + QueryHeap &forward_heap = *(engine_working_data.forward_heap_1); + QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1); + + // compute d_t for this timestamp and the next one + for (const auto s : osrm::irange(0u, prev_viterbi.size())) + { + if (prev_pruned[s]) + { + continue; + } + + for (const auto s_prime : osrm::irange(0u, current_viterbi.size())) + { + // how likely is candidate s_prime at time t to be emitted? + const double emission_pr = + emission_log_probability(candidates_list[t][s_prime].second); + double new_value = prev_viterbi[s] + emission_pr; + if (current_viterbi[s_prime] > new_value) + { + continue; + } + + forward_heap.Clear(); + reverse_heap.Clear(); + + // get distance diff between loc1/2 and locs/s_prime + const auto network_distance = super::get_network_distance( + forward_heap, reverse_heap, prev_unbroken_timestamps_list[s].first, + current_timestamps_list[s_prime].first); + const auto great_circle_distance = + coordinate_calculation::great_circle_distance(prev_coordinate, + current_coordinate); + + const auto d_t = std::abs(network_distance - great_circle_distance); + + // very low probability transition -> prune + if (d_t > osrm::matching::MAX_DISTANCE_DELTA) + { + continue; + } + + const double transition_pr = transition_log_probability(d_t); + new_value += transition_pr; + + matching_debug.add_transition_info(prev_unbroken_timestamp, t, s, s_prime, + prev_viterbi[s], emission_pr, transition_pr, + network_distance, great_circle_distance); + + if (new_value > current_viterbi[s_prime]) + { + current_viterbi[s_prime] = new_value; + current_parents[s_prime] = std::make_pair(prev_unbroken_timestamp, s); + current_lengths[s_prime] = network_distance; + current_pruned[s_prime] = false; + current_suspicious[s_prime] = d_t > osrm::matching::SUSPICIOUS_DISTANCE_DELTA; + model.breakage[t] = false; + } + } + } + + if (model.breakage[t]) + { + // save start of breakage -> we need this as split point + if (t < breakage_begin) + { + breakage_begin = t; + } + + BOOST_ASSERT(prev_unbroken_timestamps.size() > 0); + // remove both ends of the breakage + prev_unbroken_timestamps.pop_back(); + } + else + { + prev_unbroken_timestamps.push_back(t); + } + } + + matching_debug.set_viterbi(model.viterbi, model.pruned, model.suspicious); + + if (!prev_unbroken_timestamps.empty()) + { + split_points.push_back(prev_unbroken_timestamps.back() + 1); + } + + std::size_t sub_matching_begin = initial_timestamp; + for (const auto sub_matching_end : split_points) + { + osrm::matching::SubMatching matching; + + // find real end of trace + // not sure if this is really needed + std::size_t parent_timestamp_index = sub_matching_end - 1; + while (parent_timestamp_index >= sub_matching_begin && + model.breakage[parent_timestamp_index]) + { + --parent_timestamp_index; + } + + // matchings that only consist of one candidate are invalid + if (parent_timestamp_index - sub_matching_begin + 1 < 2) + { + sub_matching_begin = sub_matching_end; + continue; + } + + // loop through the columns, and only compare the last entry + const auto max_element_iter = + std::max_element(model.viterbi[parent_timestamp_index].begin(), + model.viterbi[parent_timestamp_index].end()); + + std::size_t parent_candidate_index = + std::distance(model.viterbi[parent_timestamp_index].begin(), max_element_iter); + + std::deque> reconstructed_indices; + while (parent_timestamp_index > sub_matching_begin) + { + if (model.breakage[parent_timestamp_index]) + { + continue; + } + + reconstructed_indices.emplace_front(parent_timestamp_index, parent_candidate_index); + const auto &next = model.parents[parent_timestamp_index][parent_candidate_index]; + parent_timestamp_index = next.first; + parent_candidate_index = next.second; + } + reconstructed_indices.emplace_front(parent_timestamp_index, parent_candidate_index); + if (reconstructed_indices.size() < 2) + { + sub_matching_begin = sub_matching_end; + continue; + } + + matching.length = 0.0f; + matching.nodes.resize(reconstructed_indices.size()); + matching.indices.resize(reconstructed_indices.size()); + for (const auto i : osrm::irange(0u, reconstructed_indices.size())) + { + const auto timestamp_index = reconstructed_indices[i].first; + const auto location_index = reconstructed_indices[i].second; + + matching.indices[i] = timestamp_index; + matching.nodes[i] = candidates_list[timestamp_index][location_index].first; + matching.length += model.path_lengths[timestamp_index][location_index]; + + matching_debug.add_chosen(timestamp_index, location_index); + } + + sub_matchings.push_back(matching); + sub_matching_begin = sub_matching_end; + } + matching_debug.add_breakage(model.breakage); + } +}; + +//[1] "Hidden Markov Map Matching Through Noise and Sparseness"; P. Newson and J. Krumm; 2009; ACM +// GIS + +#endif /* MAP_MATCHING_HPP */ diff --git a/routing_algorithms/routing_base.hpp b/routing_algorithms/routing_base.hpp index 20610ea17..52c16a77e 100644 --- a/routing_algorithms/routing_base.hpp +++ b/routing_algorithms/routing_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, @@ -28,26 +28,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ROUTING_BASE_HPP #define ROUTING_BASE_HPP -#include "../data_structures/raw_route_data.hpp" +#include "../data_structures/coordinate_calculation.hpp" +#include "../data_structures/internal_route_result.hpp" #include "../data_structures/search_engine_data.hpp" #include "../data_structures/turn_instructions.hpp" -// #include "../Util/simple_logger.hpp.h" +// #include "../util/simple_logger.hpp" #include #include -SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap; -SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap; -SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap2; -SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap2; -SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3; -SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::forward_heap_1; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::reverse_heap_1; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::forward_heap_2; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::reverse_heap_2; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::forward_heap_3; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::reverse_heap_3; -template class BasicRoutingInterface +template class BasicRoutingInterface { private: - typedef typename DataFacadeT::EdgeData EdgeData; + using EdgeData = typename DataFacadeT::EdgeData; protected: DataFacadeT *facade; @@ -56,20 +57,21 @@ template class BasicRoutingInterface BasicRoutingInterface() = delete; BasicRoutingInterface(const BasicRoutingInterface &) = delete; explicit BasicRoutingInterface(DataFacadeT *facade) : facade(facade) {} - virtual ~BasicRoutingInterface() {}; + ~BasicRoutingInterface() {} - inline void RoutingStep(SearchEngineData::QueryHeap &forward_heap, - SearchEngineData::QueryHeap &reverse_heap, - NodeID *middle_node_id, - int *upper_bound, - const int min_edge_offset, - const bool forward_direction) const + void RoutingStep(SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + NodeID *middle_node_id, + int *upper_bound, + const int min_edge_offset, + const bool forward_direction) const { const NodeID node = forward_heap.DeleteMin(); const int distance = forward_heap.GetKey(node); // const NodeID parentnode = forward_heap.GetData(node).parent; - // SimpleLogger().Write() << (forward_direction ? "[fwd] " : "[rev] ") << "settled edge (" << parentnode << "," << node << "), dist: " << distance; + // SimpleLogger().Write() << (forward_direction ? "[fwd] " : "[rev] ") << "settled edge (" + // << parentnode << "," << node << "), dist: " << distance; if (reverse_heap.WasInserted(node)) { @@ -80,9 +82,11 @@ template class BasicRoutingInterface { *middle_node_id = node; *upper_bound = new_distance; - // SimpleLogger().Write() << "accepted middle node " << node << " at distance " << new_distance; - // } else { - // SimpleLogger().Write() << "discared middle node " << node << " at distance " << new_distance; + // SimpleLogger().Write() << "accepted middle node " << node << " at + // distance " << new_distance; + // } else { + // SimpleLogger().Write() << "discared middle node " << node << " at + // distance " << new_distance; } } } @@ -145,9 +149,9 @@ template class BasicRoutingInterface } } - inline void UnpackPath(const std::vector &packed_path, - const PhantomNodes &phantom_node_pair, - std::vector &unpacked_path) const + void UnpackPath(const std::vector &packed_path, + const PhantomNodes &phantom_node_pair, + std::vector &unpacked_path) const { const bool start_traversed_in_reverse = (packed_path.front() != phantom_node_pair.source_phantom.forward_node_id); @@ -228,15 +232,11 @@ template class BasicRoutingInterface const TurnInstruction turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id); const TravelMode travel_mode = facade->GetTravelModeForEdgeID(ed.id); - if (!facade->EdgeIsCompressed(ed.id)) { BOOST_ASSERT(!facade->EdgeIsCompressed(ed.id)); - unpacked_path.emplace_back(facade->GetGeometryIndexForEdgeID(ed.id), - name_index, - turn_instruction, - ed.distance, - travel_mode); + unpacked_path.emplace_back(facade->GetGeometryIndexForEdgeID(ed.id), name_index, + turn_instruction, ed.distance, travel_mode); } else { @@ -257,7 +257,8 @@ template class BasicRoutingInterface BOOST_ASSERT(start_index <= end_index); for (std::size_t i = start_index; i < end_index; ++i) { - unpacked_path.emplace_back(id_vector[i], name_index, TurnInstruction::NoTurn, 0, travel_mode); + unpacked_path.emplace_back(id_vector[i], name_index, + TurnInstruction::NoTurn, 0, travel_mode); } unpacked_path.back().turn_instruction = turn_instruction; unpacked_path.back().segment_duration = ed.distance; @@ -294,18 +295,19 @@ template class BasicRoutingInterface if (start_index > end_index) { - start_index = std::min(start_index, id_vector.size()-1); + start_index = std::min(start_index, id_vector.size() - 1); } for (std::size_t i = start_index; i != end_index; (start_index < end_index ? ++i : --i)) { BOOST_ASSERT(i < id_vector.size()); - BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode>0 ); - unpacked_path.emplace_back(PathData{id_vector[i], - phantom_node_pair.target_phantom.name_id, - TurnInstruction::NoTurn, - 0, - phantom_node_pair.target_phantom.forward_travel_mode}); + BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode > 0); + unpacked_path.emplace_back( + PathData{id_vector[i], + phantom_node_pair.target_phantom.name_id, + TurnInstruction::NoTurn, + 0, + phantom_node_pair.target_phantom.forward_travel_mode}); } } @@ -330,7 +332,7 @@ template class BasicRoutingInterface } } - inline void UnpackEdge(const NodeID s, const NodeID t, std::vector &unpacked_path) const + void UnpackEdge(const NodeID s, const NodeID t, std::vector &unpacked_path) const { std::stack> recursion_stack; recursion_stack.emplace(s, t); @@ -367,7 +369,8 @@ template class BasicRoutingInterface } } } - BOOST_ASSERT_MSG(edge_weight != std::numeric_limits::max(), "edge weight invalid"); + BOOST_ASSERT_MSG(edge_weight != std::numeric_limits::max(), + "edge weight invalid"); const EdgeData &ed = facade->GetEdgeData(smaller_edge_id); if (ed.shortcut) @@ -386,10 +389,10 @@ template class BasicRoutingInterface unpacked_path.emplace_back(t); } - inline void RetrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap, - const SearchEngineData::QueryHeap &reverse_heap, - const NodeID middle_node_id, - std::vector &packed_path) const + void RetrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap, + const SearchEngineData::QueryHeap &reverse_heap, + const NodeID middle_node_id, + std::vector &packed_path) const { RetrievePackedPathFromSingleHeap(forward_heap, middle_node_id, packed_path); std::reverse(packed_path.begin(), packed_path.end()); @@ -397,9 +400,9 @@ template class BasicRoutingInterface RetrievePackedPathFromSingleHeap(reverse_heap, middle_node_id, packed_path); } - inline void RetrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap, - const NodeID middle_node_id, - std::vector &packed_path) const + void RetrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap, + const NodeID middle_node_id, + std::vector &packed_path) const { NodeID current_node_id = middle_node_id; while (current_node_id != search_heap.GetData(current_node_id).parent) @@ -408,6 +411,84 @@ template class BasicRoutingInterface packed_path.emplace_back(current_node_id); } } + + double get_network_distance(SearchEngineData::QueryHeap &forward_heap, + SearchEngineData::QueryHeap &reverse_heap, + const PhantomNode &source_phantom, + const PhantomNode &target_phantom) const + { + EdgeWeight upper_bound = INVALID_EDGE_WEIGHT; + NodeID middle_node = SPECIAL_NODEID; + EdgeWeight edge_offset = std::min(0, -source_phantom.GetForwardWeightPlusOffset()); + edge_offset = std::min(edge_offset, -source_phantom.GetReverseWeightPlusOffset()); + + if (source_phantom.forward_node_id != SPECIAL_NODEID) + { + forward_heap.Insert(source_phantom.forward_node_id, + -source_phantom.GetForwardWeightPlusOffset(), + source_phantom.forward_node_id); + } + if (source_phantom.reverse_node_id != SPECIAL_NODEID) + { + forward_heap.Insert(source_phantom.reverse_node_id, + -source_phantom.GetReverseWeightPlusOffset(), + source_phantom.reverse_node_id); + } + + if (target_phantom.forward_node_id != SPECIAL_NODEID) + { + reverse_heap.Insert(target_phantom.forward_node_id, + target_phantom.GetForwardWeightPlusOffset(), + target_phantom.forward_node_id); + } + if (target_phantom.reverse_node_id != SPECIAL_NODEID) + { + reverse_heap.Insert(target_phantom.reverse_node_id, + target_phantom.GetReverseWeightPlusOffset(), + target_phantom.reverse_node_id); + } + + // search from s and t till new_min/(1+epsilon) > length_of_shortest_path + while (0 < (forward_heap.Size() + reverse_heap.Size())) + { + if (0 < forward_heap.Size()) + { + RoutingStep(forward_heap, reverse_heap, &middle_node, &upper_bound, edge_offset, + true); + } + if (0 < reverse_heap.Size()) + { + RoutingStep(reverse_heap, forward_heap, &middle_node, &upper_bound, edge_offset, + false); + } + } + + double distance = std::numeric_limits::max(); + if (upper_bound != INVALID_EDGE_WEIGHT) + { + std::vector packed_leg; + RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle_node, packed_leg); + std::vector unpacked_path; + PhantomNodes nodes; + nodes.source_phantom = source_phantom; + nodes.target_phantom = target_phantom; + UnpackPath(packed_leg, nodes, unpacked_path); + + FixedPointCoordinate previous_coordinate = source_phantom.location; + FixedPointCoordinate current_coordinate; + distance = 0; + for (const auto &p : unpacked_path) + { + current_coordinate = facade->GetCoordinateOfNode(p.node); + distance += coordinate_calculation::great_circle_distance(previous_coordinate, + current_coordinate); + previous_coordinate = current_coordinate; + } + distance += coordinate_calculation::great_circle_distance(previous_coordinate, + target_phantom.location); + } + return distance; + } }; #endif // ROUTING_BASE_HPP diff --git a/routing_algorithms/shortest_path.hpp b/routing_algorithms/shortest_path.hpp index cab09ab9f..3dedc2b76 100644 --- a/routing_algorithms/shortest_path.hpp +++ b/routing_algorithms/shortest_path.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,12 +32,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "routing_base.hpp" #include "../data_structures/search_engine_data.hpp" -#include "../Util/integer_range.hpp" +#include "../util/integer_range.hpp" #include "../typedefs.h" -template class ShortestPathRouting final : public BasicRoutingInterface +template +class ShortestPathRouting final + : public BasicRoutingInterface> { - using super = BasicRoutingInterface; + using super = BasicRoutingInterface>; using QueryHeap = SearchEngineData::QueryHeap; SearchEngineData &engine_working_data; @@ -51,7 +53,7 @@ template class ShortestPathRouting final : public BasicRouti void operator()(const std::vector &phantom_nodes_vector, const std::vector &uturn_indicators, - RawRouteData &raw_route_data) const + InternalRouteResult &raw_route_data) const { int distance1 = 0; int distance2 = 0; @@ -69,10 +71,10 @@ template class ShortestPathRouting final : public BasicRouti engine_working_data.InitializeOrClearThirdThreadLocalStorage( super::facade->GetNumberOfNodes()); - QueryHeap &forward_heap1 = *(engine_working_data.forwardHeap); - QueryHeap &reverse_heap1 = *(engine_working_data.backwardHeap); - QueryHeap &forward_heap2 = *(engine_working_data.forwardHeap2); - QueryHeap &reverse_heap2 = *(engine_working_data.backwardHeap2); + QueryHeap &forward_heap1 = *(engine_working_data.forward_heap_1); + QueryHeap &reverse_heap1 = *(engine_working_data.reverse_heap_1); + QueryHeap &forward_heap2 = *(engine_working_data.forward_heap_2); + QueryHeap &reverse_heap2 = *(engine_working_data.reverse_heap_2); std::size_t current_leg = 0; // Get distance to next pair of target nodes. @@ -88,8 +90,11 @@ template class ShortestPathRouting final : public BasicRouti middle1 = SPECIAL_NODEID; middle2 = SPECIAL_NODEID; - const bool allow_u_turn = current_leg > 0 && uturn_indicators.size() > current_leg && uturn_indicators[current_leg-1]; - EdgeWeight min_edge_offset = 0; + const bool allow_u_turn = current_leg > 0 && uturn_indicators.size() > current_leg && + uturn_indicators[current_leg - 1]; + const EdgeWeight min_edge_offset = + std::min(phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); // insert new starting nodes into forward heap, adjusted by previous distances. if ((allow_u_turn || search_from_1st_node) && @@ -97,35 +102,32 @@ template class ShortestPathRouting final : public BasicRouti { forward_heap1.Insert( phantom_node_pair.source_phantom.forward_node_id, - (allow_u_turn ? 0 : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), phantom_node_pair.source_phantom.forward_node_id); - min_edge_offset = std::min(min_edge_offset, (allow_u_turn ? 0 : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset()); - // SimpleLogger().Write(logDEBUG) << "fwd-a2 insert: " << phantom_node_pair.source_phantom.forward_node_id << ", w: " << (allow_u_turn ? 0 : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); + // SimpleLogger().Write(logDEBUG) << "fwd-a2 insert: " << + // phantom_node_pair.source_phantom.forward_node_id << ", w: " << -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); forward_heap2.Insert( phantom_node_pair.source_phantom.forward_node_id, - (allow_u_turn ? 0 : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), phantom_node_pair.source_phantom.forward_node_id); - min_edge_offset = std::min(min_edge_offset, (allow_u_turn ? 0 : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset()); - // SimpleLogger().Write(logDEBUG) << "fwd-b2 insert: " << phantom_node_pair.source_phantom.forward_node_id << ", w: " << (allow_u_turn ? 0 : distance1) - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); - + // SimpleLogger().Write(logDEBUG) << "fwd-b2 insert: " << + // phantom_node_pair.source_phantom.forward_node_id << ", w: " << -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); } if ((allow_u_turn || search_from_2nd_node) && phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID) { forward_heap1.Insert( phantom_node_pair.source_phantom.reverse_node_id, - (allow_u_turn ? 0 : distance2) - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), + -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), phantom_node_pair.source_phantom.reverse_node_id); - min_edge_offset = std::min(min_edge_offset, (allow_u_turn ? 0 : distance2) - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); - // SimpleLogger().Write(logDEBUG) << "fwd-a2 insert: " << phantom_node_pair.source_phantom.reverse_node_id << - // ", w: " << (allow_u_turn ? 0 : distance2) - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); + // SimpleLogger().Write(logDEBUG) << "fwd-a2 insert: " << + // phantom_node_pair.source_phantom.reverse_node_id << ", w: " << -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); forward_heap2.Insert( phantom_node_pair.source_phantom.reverse_node_id, - (allow_u_turn ? 0 : distance2) - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), + -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), phantom_node_pair.source_phantom.reverse_node_id); - min_edge_offset = std::min(min_edge_offset, (allow_u_turn ? 0 : distance2) - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset()); - // SimpleLogger().Write(logDEBUG) << "fwd-b2 insert: " << phantom_node_pair.source_phantom.reverse_node_id << - // ", w: " << (allow_u_turn ? 0 : distance2) - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); + // SimpleLogger().Write(logDEBUG) << "fwd-b2 insert: " << + // phantom_node_pair.source_phantom.reverse_node_id << ", w: " << -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); } // insert new backward nodes into backward heap, unadjusted. @@ -134,17 +136,17 @@ template class ShortestPathRouting final : public BasicRouti reverse_heap1.Insert(phantom_node_pair.target_phantom.forward_node_id, phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(), phantom_node_pair.target_phantom.forward_node_id); - // SimpleLogger().Write(logDEBUG) << "rev-a insert: " << phantom_node_pair.target_phantom.forward_node_id << - // ", w: " << phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(); - } + // SimpleLogger().Write(logDEBUG) << "rev-a insert: " << + // phantom_node_pair.target_phantom.forward_node_id << ", w: " << phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(); + } if (phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID) { reverse_heap2.Insert(phantom_node_pair.target_phantom.reverse_node_id, phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(), phantom_node_pair.target_phantom.reverse_node_id); - // SimpleLogger().Write(logDEBUG) << "rev-a insert: " << phantom_node_pair.target_phantom.reverse_node_id << - // ", w: " << phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(); + // SimpleLogger().Write(logDEBUG) << "rev-a insert: " << + // phantom_node_pair.target_phantom.reverse_node_id << ", w: " << phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(); } // run two-Target Dijkstra routing step. @@ -152,13 +154,13 @@ template class ShortestPathRouting final : public BasicRouti { if (!forward_heap1.Empty()) { - super::RoutingStep( - forward_heap1, reverse_heap1, &middle1, &local_upper_bound1, min_edge_offset, true); + super::RoutingStep(forward_heap1, reverse_heap1, &middle1, &local_upper_bound1, + min_edge_offset, true); } if (!reverse_heap1.Empty()) { - super::RoutingStep( - reverse_heap1, forward_heap1, &middle1, &local_upper_bound1, min_edge_offset, false); + super::RoutingStep(reverse_heap1, forward_heap1, &middle1, &local_upper_bound1, + min_edge_offset, false); } } @@ -168,13 +170,13 @@ template class ShortestPathRouting final : public BasicRouti { if (!forward_heap2.Empty()) { - super::RoutingStep( - forward_heap2, reverse_heap2, &middle2, &local_upper_bound2, min_edge_offset, true); + super::RoutingStep(forward_heap2, reverse_heap2, &middle2, + &local_upper_bound2, min_edge_offset, true); } if (!reverse_heap2.Empty()) { - super::RoutingStep( - reverse_heap2, forward_heap2, &middle2, &local_upper_bound2, min_edge_offset, false); + super::RoutingStep(reverse_heap2, forward_heap2, &middle2, + &local_upper_bound2, min_edge_offset, false); } } } @@ -200,29 +202,31 @@ template class ShortestPathRouting final : public BasicRouti } // Was at most one of the two paths not found? - BOOST_ASSERT_MSG((INVALID_EDGE_WEIGHT != distance1 || INVALID_EDGE_WEIGHT != distance2), "no path found"); + BOOST_ASSERT_MSG((INVALID_EDGE_WEIGHT != distance1 || INVALID_EDGE_WEIGHT != distance2), + "no path found"); // Unpack paths if they exist std::vector temporary_packed_leg1; std::vector temporary_packed_leg2; - BOOST_ASSERT((unsigned)current_leg < packed_legs1.size()); - BOOST_ASSERT((unsigned)current_leg < packed_legs2.size()); + BOOST_ASSERT(current_leg < packed_legs1.size()); + BOOST_ASSERT(current_leg < packed_legs2.size()); if (INVALID_EDGE_WEIGHT != local_upper_bound1) { - super::RetrievePackedPathFromHeap( - forward_heap1, reverse_heap1, middle1, temporary_packed_leg1); + super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap1, middle1, + temporary_packed_leg1); } if (INVALID_EDGE_WEIGHT != local_upper_bound2) { - super::RetrievePackedPathFromHeap( - forward_heap2, reverse_heap2, middle2, temporary_packed_leg2); + super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap2, middle2, + temporary_packed_leg2); } // if one of the paths was not found, replace it with the other one. - if ((allow_u_turn && local_upper_bound1 > local_upper_bound2) || temporary_packed_leg1.empty()) + if ((allow_u_turn && local_upper_bound1 > local_upper_bound2) || + temporary_packed_leg1.empty()) { temporary_packed_leg1.clear(); temporary_packed_leg1.insert(temporary_packed_leg1.end(), @@ -230,7 +234,8 @@ template class ShortestPathRouting final : public BasicRouti temporary_packed_leg2.end()); local_upper_bound1 = local_upper_bound2; } - if ((allow_u_turn && local_upper_bound2 > local_upper_bound1) || temporary_packed_leg2.empty()) + if ((allow_u_turn && local_upper_bound2 > local_upper_bound1) || + temporary_packed_leg2.empty()) { temporary_packed_leg2.clear(); temporary_packed_leg2.insert(temporary_packed_leg2.end(), @@ -287,7 +292,8 @@ template class ShortestPathRouting final : public BasicRouti temporary_packed_leg2.end()); BOOST_ASSERT(packed_legs2[current_leg].size() == temporary_packed_leg2.size()); - if (!allow_u_turn && (packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) && + if (!allow_u_turn && + (packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) && phantom_node_pair.target_phantom.is_bidirected()) { const NodeID last_node_id = packed_legs2[current_leg].back(); @@ -298,8 +304,8 @@ template class ShortestPathRouting final : public BasicRouti BOOST_ASSERT(search_from_1st_node != search_from_2nd_node); } - distance1 = local_upper_bound1; - distance2 = local_upper_bound2; + distance1 += local_upper_bound1; + distance2 += local_upper_bound2; ++current_leg; } @@ -324,9 +330,11 @@ template class ShortestPathRouting final : public BasicRouti raw_route_data.unpacked_path_segments[index]); raw_route_data.source_traversed_in_reverse.push_back( - (packed_legs1[index].front() != phantom_nodes_vector[index].source_phantom.forward_node_id)); + (packed_legs1[index].front() != + phantom_nodes_vector[index].source_phantom.forward_node_id)); raw_route_data.target_traversed_in_reverse.push_back( - (packed_legs1[index].back() != phantom_nodes_vector[index].target_phantom.forward_node_id)); + (packed_legs1[index].back() != + phantom_nodes_vector[index].target_phantom.forward_node_id)); } raw_route_data.shortest_path_length = std::min(distance1, distance2); } diff --git a/server/api_grammar.hpp b/server/api_grammar.hpp new file mode 100644 index 000000000..a629cfbf7 --- /dev/null +++ b/server/api_grammar.hpp @@ -0,0 +1,101 @@ +/* + +Copyright (c) 2013, Project OSRM contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef API_GRAMMAR_HPP +#define API_GRAMMAR_HPP + +#include +#include +#include + +namespace qi = boost::spirit::qi; + +template struct APIGrammar : qi::grammar +{ + 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 | timestamp | u | cmp | + language | instruction | geometry | alt_route | old_API | num_results | + matching_beta | gps_precision | classify)); + + 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)]; + timestamp = (-qi::lit('&')) >> qi::lit("t") >> '=' >> + qi::uint_[boost::bind(&HandlerT::addTimestamp, 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)]; + matching_beta = (-qi::lit('&')) >> qi::lit("matching_beta") >> '=' >> + qi::short_[boost::bind(&HandlerT::setMatchingBeta, handler, ::_1)]; + gps_precision = (-qi::lit('&')) >> qi::lit("gps_precision") >> '=' >> + qi::short_[boost::bind(&HandlerT::setGPSPrecision, handler, ::_1)]; + classify = (-qi::lit('&')) >> qi::lit("classify") >> '=' >> + qi::bool_[boost::bind(&HandlerT::setClassify, 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 api_call, query; + qi::rule service, zoom, output, string, jsonp, checksum, location, + hint, timestamp, stringwithDot, stringwithPercent, language, instruction, geometry, cmp, alt_route, u, + uturns, old_API, num_results, matching_beta, gps_precision, classify; + + HandlerT *handler; +}; + +#endif /* API_GRAMMAR_HPP */ diff --git a/Server/Connection.cpp b/server/connection.cpp similarity index 60% rename from Server/Connection.cpp rename to server/connection.cpp index 82402a649..41b653e82 100644 --- a/Server/Connection.cpp +++ b/server/connection.cpp @@ -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,9 +25,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "Connection.h" -#include "RequestHandler.h" -#include "RequestParser.h" +#include "connection.hpp" +#include "request_handler.hpp" +#include "request_parser.hpp" #include #include @@ -52,8 +52,7 @@ void Connection::start() { TCP_socket.async_read_some( boost::asio::buffer(incoming_data_buffer), - strand.wrap(boost::bind(&Connection::handle_read, - this->shared_from_this(), + strand.wrap(boost::bind(&Connection::handle_read, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); } @@ -66,19 +65,17 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t } // no error detected, let's parse the request - CompressionType compression_type(noCompression); - boost::tribool result; - boost::tie(result, boost::tuples::ignore) = - RequestParser().Parse(request, - incoming_data_buffer.data(), - incoming_data_buffer.data() + bytes_transferred, - compression_type); + compression_type compression_type(no_compression); + osrm::tribool result; + std::tie(result, compression_type) = + request_parser.parse(current_request, incoming_data_buffer.data(), + incoming_data_buffer.data() + bytes_transferred); // the request has been parsed - if (result) + if (result == osrm::tribool::yes) { - request.endpoint = TCP_socket.remote_endpoint().address(); - request_handler.handle_request(request, reply); + current_request.endpoint = TCP_socket.remote_endpoint().address(); + request_handler.handle_request(current_request, current_reply); // Header compression_header; std::vector compressed_output; @@ -87,52 +84,51 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t // compress the result w/ gzip/deflate if requested switch (compression_type) { - case deflateRFC1951: + case deflate_rfc1951: // use deflate for compression - reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "deflate"}); - CompressBufferCollection(reply.content, compression_type, compressed_output); - reply.SetSize(static_cast(compressed_output.size())); - output_buffer = reply.HeaderstoBuffers(); + current_reply.headers.insert(current_reply.headers.begin(), + {"Content-Encoding", "deflate"}); + compressed_output = compress_buffers(current_reply.content, compression_type); + current_reply.set_size(static_cast(compressed_output.size())); + output_buffer = current_reply.headers_to_buffers(); output_buffer.push_back(boost::asio::buffer(compressed_output)); break; - case gzipRFC1952: + case gzip_rfc1952: // use gzip for compression - reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "gzip"}); - CompressBufferCollection(reply.content, compression_type, compressed_output); - reply.SetSize(static_cast(compressed_output.size())); - output_buffer = reply.HeaderstoBuffers(); + current_reply.headers.insert(current_reply.headers.begin(), + {"Content-Encoding", "gzip"}); + compressed_output = compress_buffers(current_reply.content, compression_type); + current_reply.set_size(static_cast(compressed_output.size())); + output_buffer = current_reply.headers_to_buffers(); output_buffer.push_back(boost::asio::buffer(compressed_output)); break; - case noCompression: + case no_compression: // don't use any compression - reply.SetUncompressedSize(); - output_buffer = reply.ToBuffers(); + current_reply.set_uncompressed_size(); + output_buffer = current_reply.to_buffers(); break; } // write result to stream - boost::asio::async_write(TCP_socket, - output_buffer, - strand.wrap(boost::bind(&Connection::handle_write, - this->shared_from_this(), - boost::asio::placeholders::error))); + boost::asio::async_write( + TCP_socket, output_buffer, + strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(), + boost::asio::placeholders::error))); } - else if (!result) + else if (result == osrm::tribool::no) { // request is not parseable - reply = Reply::StockReply(Reply::badRequest); + current_reply = reply::stock_reply(reply::bad_request); - boost::asio::async_write(TCP_socket, - reply.ToBuffers(), - strand.wrap(boost::bind(&Connection::handle_write, - this->shared_from_this(), - boost::asio::placeholders::error))); + boost::asio::async_write( + TCP_socket, current_reply.to_buffers(), + strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(), + boost::asio::placeholders::error))); } else { // we don't have a result yet, so continue reading TCP_socket.async_read_some( boost::asio::buffer(incoming_data_buffer), - strand.wrap(boost::bind(&Connection::handle_read, - this->shared_from_this(), + strand.wrap(boost::bind(&Connection::handle_read, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); } @@ -149,26 +145,27 @@ void Connection::handle_write(const boost::system::error_code &error) } } -void Connection::CompressBufferCollection(std::vector uncompressed_data, - CompressionType compression_type, - std::vector &compressed_data) +std::vector Connection::compress_buffers(const std::vector &uncompressed_data, + const compression_type compression_type) { boost::iostreams::gzip_params compression_parameters; // there's a trade-off between speed and size. speed wins compression_parameters.level = boost::iostreams::zlib::best_speed; // check which compression flavor is used - if (deflateRFC1951 == compression_type) + if (deflate_rfc1951 == compression_type) { compression_parameters.noheader = true; } - BOOST_ASSERT(compressed_data.empty()); + std::vector compressed_data; // plug data into boost's compression stream boost::iostreams::filtering_ostream gzip_stream; gzip_stream.push(boost::iostreams::gzip_compressor(compression_parameters)); gzip_stream.push(boost::iostreams::back_inserter(compressed_data)); gzip_stream.write(&uncompressed_data[0], uncompressed_data.size()); boost::iostreams::close(gzip_stream); + + return compressed_data; } } diff --git a/Server/Connection.h b/server/connection.hpp similarity index 74% rename from Server/Connection.h rename to server/connection.hpp index 41b06d3a2..9228a18a0 100644 --- a/Server/Connection.h +++ b/server/connection.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,44 +25,34 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CONNECTION_H -#define CONNECTION_H +#ifndef CONNECTION_HPP +#define CONNECTION_HPP -// #include "RequestParser.h" -#include "Http/CompressionType.h" -#include "Http/Request.h" - -#include +#include "http/compression_type.hpp" +#include "http/reply.hpp" +#include "http/request.hpp" +#include "request_parser.hpp" #include #include #include #include - #include - #include +#include +#include -//workaround for incomplete std::shared_ptr compatibility in old boost versions +// workaround for incomplete std::shared_ptr compatibility in old boost versions #if BOOST_VERSION < 105300 || defined BOOST_NO_CXX11_SMART_PTR -namespace boost { -template -const T* get_pointer(std::shared_ptr const& p) +namespace boost { - return p.get(); -} +template const T *get_pointer(std::shared_ptr const &p) { return p.get(); } -template -T* get_pointer(std::shared_ptr& p) -{ - return p.get(); -} +template T *get_pointer(std::shared_ptr &p) { return p.get(); } } // namespace boost #endif - - class RequestHandler; namespace http @@ -87,18 +77,18 @@ class Connection : public std::enable_shared_from_this /// Handle completion of a write operation. void handle_write(const boost::system::error_code &e); - void CompressBufferCollection(std::vector uncompressed_data, - CompressionType compression_type, - std::vector &compressed_data); + std::vector compress_buffers(const std::vector &uncompressed_data, + const compression_type compression_type); boost::asio::io_service::strand strand; boost::asio::ip::tcp::socket TCP_socket; RequestHandler &request_handler; + RequestParser request_parser; boost::array incoming_data_buffer; - Request request; - Reply reply; + request current_request; + reply current_reply; }; } // namespace http -#endif // CONNECTION_H +#endif // CONNECTION_HPP diff --git a/Server/DataStructures/BaseDataFacade.h b/server/data_structures/datafacade_base.hpp similarity index 83% rename from Server/DataStructures/BaseDataFacade.h rename to server/data_structures/datafacade_base.hpp index 3ea391cab..20d043057 100644 --- a/Server/DataStructures/BaseDataFacade.h +++ b/server/data_structures/datafacade_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, @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BASE_DATA_FACADE_H -#define BASE_DATA_FACADE_H +#ifndef DATAFACADE_BASE_HPP +#define DATAFACADE_BASE_HPP // Exposes all data access interfaces to the algorithms via base class ptr @@ -34,22 +34,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../data_structures/external_memory_node.hpp" #include "../../data_structures/phantom_node.hpp" #include "../../data_structures/turn_instructions.hpp" -#include "../../Util/integer_range.hpp" -#include "../../Util/osrm_exception.hpp" -#include "../../Util/string_util.hpp" +#include "../../util/integer_range.hpp" +#include "../../util/osrm_exception.hpp" +#include "../../util/string_util.hpp" #include "../../typedefs.h" -#include +#include #include -typedef osrm::range EdgeRange; +using EdgeRange = osrm::range; template class BaseDataFacade { public: - typedef EdgeBasedNode RTreeLeaf; - typedef EdgeDataT EdgeData; + using RTreeLeaf = EdgeBasedNode; + using EdgeData = EdgeDataT; BaseDataFacade() {} virtual ~BaseDataFacade() {} @@ -62,8 +62,6 @@ template class BaseDataFacade virtual NodeID GetTarget(const EdgeID e) const = 0; - // virtual EdgeDataT &GetEdgeData(const EdgeID e) = 0; - virtual const EdgeDataT &GetEdgeData(const EdgeID e) const = 0; virtual EdgeID BeginEdges(const NodeID n) const = 0; @@ -106,21 +104,20 @@ template class BaseDataFacade virtual bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, PhantomNode &resulting_phantom_node) = 0; + virtual bool IncrementalFindPhantomNodeForCoordinateWithMaxDistance( + const FixedPointCoordinate &input_coordinate, + std::vector> &resulting_phantom_node_vector, + const double max_distance, + const unsigned min_number_of_phantom_nodes, + const unsigned max_number_of_phantom_nodes) = 0; virtual unsigned GetCheckSum() const = 0; virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0; - virtual void GetName(const unsigned name_id, std::string &result) const = 0; - - std::string GetEscapedNameForNameID(const unsigned name_id) const - { - std::string temporary_string; - GetName(name_id, temporary_string); - return EscapeJSONString(temporary_string); - } + virtual std::string get_name_for_id(const unsigned name_id) const = 0; virtual std::string GetTimestamp() const = 0; }; -#endif // BASE_DATA_FACADE_H +#endif // DATAFACADE_BASE_HPP diff --git a/Server/DataStructures/InternalDataFacade.h b/server/data_structures/internal_datafacade.hpp similarity index 80% rename from Server/DataStructures/InternalDataFacade.h rename to server/data_structures/internal_datafacade.hpp index d4f715c61..823ac3329 100644 --- a/Server/DataStructures/InternalDataFacade.h +++ b/server/data_structures/internal_datafacade.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,12 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef INTERNAL_DATA_FACADE -#define INTERNAL_DATA_FACADE +#ifndef INTERNAL_DATAFACADE_HPP +#define INTERNAL_DATAFACADE_HPP // implements all data storage when shared memory is _NOT_ used -#include "BaseDataFacade.h" +#include "datafacade_base.hpp" #include "../../data_structures/original_edge_data.hpp" #include "../../data_structures/query_node.hpp" @@ -39,21 +39,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../data_structures/static_graph.hpp" #include "../../data_structures/static_rtree.hpp" #include "../../data_structures/range_table.hpp" -#include "../../Util/BoostFileSystemFix.h" -#include "../../Util/graph_loader.hpp" -#include "../../Util/simple_logger.hpp" +#include "../../util/boost_filesystem_2_fix.hpp" +#include "../../util/graph_loader.hpp" +#include "../../util/simple_logger.hpp" -#include -#include +#include +#include -template class InternalDataFacade : public BaseDataFacade +#include + +template class InternalDataFacade final : public BaseDataFacade { private: - typedef BaseDataFacade super; - typedef StaticGraph QueryGraph; - typedef typename QueryGraph::InputEdge InputEdge; - typedef typename super::RTreeLeaf RTreeLeaf; + using super = BaseDataFacade; + using QueryGraph = StaticGraph; + using InputEdge = typename QueryGraph::InputEdge; + using RTreeLeaf = typename super::RTreeLeaf; InternalDataFacade() {} @@ -309,94 +311,101 @@ template class InternalDataFacade : public BaseDataFacadeGetNumberOfNodes(); } + unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); } - unsigned GetNumberOfEdges() const final { return m_query_graph->GetNumberOfEdges(); } + unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); } - unsigned GetOutDegree(const NodeID n) const final { return m_query_graph->GetOutDegree(n); } + unsigned GetOutDegree(const NodeID n) const override final + { + return m_query_graph->GetOutDegree(n); + } - NodeID GetTarget(const EdgeID e) const final { return m_query_graph->GetTarget(e); } + NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); } - // EdgeDataT &GetEdgeData(const EdgeID e) final { return m_query_graph->GetEdgeData(e); } + EdgeDataT &GetEdgeData(const EdgeID e) const override final + { + return m_query_graph->GetEdgeData(e); + } - EdgeDataT &GetEdgeData(const EdgeID e) const final { return m_query_graph->GetEdgeData(e); } + EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); } - EdgeID BeginEdges(const NodeID n) const final { return m_query_graph->BeginEdges(n); } + EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); } - EdgeID EndEdges(const NodeID n) const final { return m_query_graph->EndEdges(n); } - - EdgeRange GetAdjacentEdgeRange(const NodeID node) const final + EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final { return m_query_graph->GetAdjacentEdgeRange(node); }; // searches for a specific edge - EdgeID FindEdge(const NodeID from, const NodeID to) const final + EdgeID FindEdge(const NodeID from, const NodeID to) const override final { return m_query_graph->FindEdge(from, to); } - EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const final + EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final { return m_query_graph->FindEdgeInEitherDirection(from, to); } - EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const final + EdgeID + FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final { return m_query_graph->FindEdgeIndicateIfReverse(from, to, result); } // node and edge information access - FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const final + FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const override final { return m_coordinate_list->at(id); }; - bool EdgeIsCompressed(const unsigned id) const { return m_edge_is_compressed.at(id); } + bool EdgeIsCompressed(const unsigned id) const override final + { + return m_edge_is_compressed.at(id); + } - TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const final + TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const override final { return m_turn_instruction_list.at(id); } - TravelMode GetTravelModeForEdgeID(const unsigned id) const + TravelMode GetTravelModeForEdgeID(const unsigned id) const override final { - return m_travel_mode_list.at(id); + return m_travel_mode_list.at(id); } bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate, FixedPointCoordinate &result, - const unsigned zoom_level = 18) final + const unsigned zoom_level = 18) override final { if (!m_static_rtree.get()) { LoadRTree(); } - return m_static_rtree->LocateClosestEndPointForCoordinate( - input_coordinate, result, zoom_level); + return m_static_rtree->LocateClosestEndPointForCoordinate(input_coordinate, result, + zoom_level); } - bool - IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, - PhantomNode &resulting_phantom_node) final + bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, + PhantomNode &resulting_phantom_node) override final { std::vector resulting_phantom_node_vector; auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate, - resulting_phantom_node_vector, - 1); + resulting_phantom_node_vector, 1); if (result) { BOOST_ASSERT(!resulting_phantom_node_vector.empty()); resulting_phantom_node = resulting_phantom_node_vector.front(); } + return result; } bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, std::vector &resulting_phantom_node_vector, - const unsigned number_of_results) final + const unsigned number_of_results) override final { if (!m_static_rtree.get()) { @@ -407,49 +416,66 @@ template class InternalDataFacade : public BaseDataFacade> &resulting_phantom_node_vector, + const double max_distance, + const unsigned min_number_of_phantom_nodes, + const unsigned max_number_of_phantom_nodes) override final + { + if (!m_static_rtree.get()) + { + LoadRTree(); + } - unsigned GetNameIndexFromEdgeID(const unsigned id) const final + return m_static_rtree->IncrementalFindPhantomNodeForCoordinateWithDistance( + input_coordinate, resulting_phantom_node_vector, max_distance, + min_number_of_phantom_nodes, max_number_of_phantom_nodes); + } + + unsigned GetCheckSum() const override final { return m_check_sum; } + + unsigned GetNameIndexFromEdgeID(const unsigned id) const override final { return m_name_ID_list.at(id); - }; + } - void GetName(const unsigned name_id, std::string &result) const final + std::string get_name_for_id(const unsigned name_id) const override final { - if (UINT_MAX == name_id) + if (std::numeric_limits::max() == name_id) { - result = ""; - return; + return ""; } auto range = m_name_table.GetRange(name_id); - result.clear(); + std::string result; + result.reserve(range.size()); if (range.begin() != range.end()) { result.resize(range.back() - range.front() + 1); std::copy(m_names_char_list.begin() + range.front(), - m_names_char_list.begin() + range.back() + 1, - result.begin()); + m_names_char_list.begin() + range.back() + 1, result.begin()); } + return result; } - virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const final + virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const override final { return m_via_node_list.at(id); } virtual void GetUncompressedGeometry(const unsigned id, - std::vector &result_nodes) const final + std::vector &result_nodes) const override final { const unsigned begin = m_geometry_indices.at(id); const unsigned end = m_geometry_indices.at(id + 1); result_nodes.clear(); - result_nodes.insert( - result_nodes.begin(), m_geometry_list.begin() + begin, m_geometry_list.begin() + end); + result_nodes.insert(result_nodes.begin(), m_geometry_list.begin() + begin, + m_geometry_list.begin() + end); } - std::string GetTimestamp() const final { return m_timestamp; } + std::string GetTimestamp() const override final { return m_timestamp; } }; -#endif // INTERNAL_DATA_FACADE +#endif // INTERNAL_DATAFACADE_HPP diff --git a/Server/DataStructures/SharedBarriers.h b/server/data_structures/shared_barriers.hpp similarity index 94% rename from Server/DataStructures/SharedBarriers.h rename to server/data_structures/shared_barriers.hpp index 36ba08b1f..e6f1234ca 100644 --- a/Server/DataStructures/SharedBarriers.h +++ b/server/data_structures/shared_barriers.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,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SHARED_BARRIER_H -#define SHARED_BARRIER_H +#ifndef SHARED_BARRIERS_HPP +#define SHARED_BARRIERS_HPP #include #include @@ -57,4 +57,4 @@ struct SharedBarriers int number_of_queries; }; -#endif // SHARED_BARRIER_H +#endif // SHARED_BARRIERS_HPP diff --git a/Server/DataStructures/SharedDataFacade.h b/server/data_structures/shared_datafacade.hpp similarity index 75% rename from Server/DataStructures/SharedDataFacade.h rename to server/data_structures/shared_datafacade.hpp index 9120f8236..b15642316 100644 --- a/Server/DataStructures/SharedDataFacade.h +++ b/server/data_structures/shared_datafacade.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, @@ -25,36 +25,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SHARED_DATA_FACADE_H -#define SHARED_DATA_FACADE_H +#ifndef SHARED_DATAFACADE_HPP +#define SHARED_DATAFACADE_HPP // implements all data storage when shared memory _IS_ used -#include "BaseDataFacade.h" -#include "SharedDataType.h" +#include "datafacade_base.hpp" +#include "shared_datatype.hpp" #include "../../data_structures/range_table.hpp" #include "../../data_structures/static_graph.hpp" #include "../../data_structures/static_rtree.hpp" -#include "../../Util/BoostFileSystemFix.h" -#include "../../Util/make_unique.hpp" -#include "../../Util/simple_logger.hpp" +#include "../../util/boost_filesystem_2_fix.hpp" +#include "../../util/make_unique.hpp" +#include "../../util/simple_logger.hpp" #include +#include #include -template class SharedDataFacade : public BaseDataFacade +template class SharedDataFacade final : public BaseDataFacade { private: - typedef EdgeDataT EdgeData; - typedef BaseDataFacade super; - typedef StaticGraph QueryGraph; - typedef typename StaticGraph::NodeArrayEntry GraphNode; - typedef typename StaticGraph::EdgeArrayEntry GraphEdge; - typedef typename RangeTable<16, true>::BlockT NameIndexBlock; - typedef typename QueryGraph::InputEdge InputEdge; - typedef typename super::RTreeLeaf RTreeLeaf; + using EdgeData = EdgeDataT; + using super = BaseDataFacade; + using QueryGraph = StaticGraph; + using GraphNode = typename StaticGraph::NodeArrayEntry; + using GraphEdge = typename StaticGraph::EdgeArrayEntry; + using NameIndexBlock = typename RangeTable<16, true>::BlockT; + using InputEdge = typename QueryGraph::InputEdge; + using RTreeLeaf = typename super::RTreeLeaf; using SharedRTree = StaticRTree::vector, true>; using TimeStampedRTreePair = std::pair>; using RTreeNode = typename SharedRTree::TreeNode; @@ -112,12 +113,11 @@ template class SharedDataFacade : public BaseDataFacadeGetBlockPtr(shared_memory, SharedDataLayout::R_SEARCH_TREE); - m_static_rtree.reset(new TimeStampedRTreePair(CURRENT_TIMESTAMP, + m_static_rtree.reset(new TimeStampedRTreePair( + CURRENT_TIMESTAMP, osrm::make_unique( - tree_ptr, - data_layout->num_entries[SharedDataLayout::R_SEARCH_TREE], - file_index_path, - m_coordinate_list))); + tree_ptr, data_layout->num_entries[SharedDataLayout::R_SEARCH_TREE], + file_index_path, m_coordinate_list))); } void LoadGraph() @@ -143,11 +143,10 @@ template class SharedDataFacade : public BaseDataFacade::vector>( coordinate_list_ptr, data_layout->num_entries[SharedDataLayout::COORDINATE_LIST]); - TravelMode *travel_mode_list_ptr = data_layout->GetBlockPtr( - shared_memory, SharedDataLayout::TRAVEL_MODE); + TravelMode *travel_mode_list_ptr = + data_layout->GetBlockPtr(shared_memory, SharedDataLayout::TRAVEL_MODE); typename ShM::vector travel_mode_list( - travel_mode_list_ptr, - data_layout->num_entries[SharedDataLayout::TRAVEL_MODE]); + travel_mode_list_ptr, data_layout->num_entries[SharedDataLayout::TRAVEL_MODE]); m_travel_mode_list.swap(travel_mode_list); TurnInstruction *turn_instruction_list_ptr = data_layout->GetBlockPtr( @@ -259,7 +258,7 @@ template class SharedDataFacade : public BaseDataFacade class SharedDataFacade : public BaseDataFacadeGetNumberOfNodes(); } + unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); } - unsigned GetNumberOfEdges() const final { return m_query_graph->GetNumberOfEdges(); } + unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); } - unsigned GetOutDegree(const NodeID n) const final { return m_query_graph->GetOutDegree(n); } + unsigned GetOutDegree(const NodeID n) const override final + { + return m_query_graph->GetOutDegree(n); + } - NodeID GetTarget(const EdgeID e) const final { return m_query_graph->GetTarget(e); } + NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); } - EdgeDataT &GetEdgeData(const EdgeID e) const final { return m_query_graph->GetEdgeData(e); } + EdgeDataT &GetEdgeData(const EdgeID e) const override final + { + return m_query_graph->GetEdgeData(e); + } - EdgeID BeginEdges(const NodeID n) const final { return m_query_graph->BeginEdges(n); } + EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); } - EdgeID EndEdges(const NodeID n) const final { return m_query_graph->EndEdges(n); } + EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); } - EdgeRange GetAdjacentEdgeRange(const NodeID node) const final + EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final { return m_query_graph->GetAdjacentEdgeRange(node); }; // searches for a specific edge - EdgeID FindEdge(const NodeID from, const NodeID to) const final + EdgeID FindEdge(const NodeID from, const NodeID to) const override final { return m_query_graph->FindEdge(from, to); } - EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const final + EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final { return m_query_graph->FindEdgeInEitherDirection(from, to); } - EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const final + EdgeID + FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final { return m_query_graph->FindEdgeIndicateIfReverse(from, to, result); } // node and edge information access - FixedPointCoordinate GetCoordinateOfNode(const NodeID id) const final + FixedPointCoordinate GetCoordinateOfNode(const NodeID id) const override final { return m_coordinate_list->at(id); }; - virtual bool EdgeIsCompressed(const unsigned id) const final + virtual bool EdgeIsCompressed(const unsigned id) const override final { return m_edge_is_compressed.at(id); } virtual void GetUncompressedGeometry(const unsigned id, - std::vector &result_nodes) const final + std::vector &result_nodes) const override final { const unsigned begin = m_geometry_indices.at(id); const unsigned end = m_geometry_indices.at(id + 1); result_nodes.clear(); - result_nodes.insert( - result_nodes.begin(), m_geometry_list.begin() + begin, m_geometry_list.begin() + end); + result_nodes.insert(result_nodes.begin(), m_geometry_list.begin() + begin, + m_geometry_list.begin() + end); } - virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const final + virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const override final { return m_via_node_list.at(id); } - TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const final + TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const override final { return m_turn_instruction_list.at(id); } - TravelMode GetTravelModeForEdgeID(const unsigned id) const + TravelMode GetTravelModeForEdgeID(const unsigned id) const override final { return m_travel_mode_list.at(id); } bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate, FixedPointCoordinate &result, - const unsigned zoom_level = 18) final + const unsigned zoom_level = 18) override final { if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first) { LoadRTree(); } - return m_static_rtree->second->LocateClosestEndPointForCoordinate( - input_coordinate, result, zoom_level); + return m_static_rtree->second->LocateClosestEndPointForCoordinate(input_coordinate, result, + zoom_level); } - bool - IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, - PhantomNode &resulting_phantom_node) final + bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, + PhantomNode &resulting_phantom_node) override final { std::vector resulting_phantom_node_vector; auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate, - resulting_phantom_node_vector, - 1); + resulting_phantom_node_vector, 1); if (result) { BOOST_ASSERT(!resulting_phantom_node_vector.empty()); resulting_phantom_node = resulting_phantom_node_vector.front(); } + return result; } bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate, std::vector &resulting_phantom_node_vector, - const unsigned number_of_results) final + const unsigned number_of_results) override final { if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first) { @@ -399,33 +404,50 @@ template class SharedDataFacade : public BaseDataFacade> &resulting_phantom_node_vector, + const double max_distance, + const unsigned min_number_of_phantom_nodes, + const unsigned max_number_of_phantom_nodes) override final + { + if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first) + { + LoadRTree(); + } - unsigned GetNameIndexFromEdgeID(const unsigned id) const final + return m_static_rtree->second->IncrementalFindPhantomNodeForCoordinateWithDistance( + input_coordinate, resulting_phantom_node_vector, max_distance, + min_number_of_phantom_nodes, max_number_of_phantom_nodes); + } + + unsigned GetCheckSum() const override final { return m_check_sum; } + + unsigned GetNameIndexFromEdgeID(const unsigned id) const override final { return m_name_ID_list.at(id); }; - void GetName(const unsigned name_id, std::string &result) const final + std::string get_name_for_id(const unsigned name_id) const override final { - if (UINT_MAX == name_id) + if (std::numeric_limits::max() == name_id) { - result = ""; - return; + return ""; } auto range = m_name_table->GetRange(name_id); - result.clear(); + std::string result; + result.reserve(range.size()); if (range.begin() != range.end()) { result.resize(range.back() - range.front() + 1); std::copy(m_names_char_list.begin() + range.front(), - m_names_char_list.begin() + range.back() + 1, - result.begin()); + m_names_char_list.begin() + range.back() + 1, result.begin()); } + return result; } - std::string GetTimestamp() const final { return m_timestamp; } + std::string GetTimestamp() const override final { return m_timestamp; } }; -#endif // SHARED_DATA_FACADE_H +#endif // SHARED_DATAFACADE_HPP diff --git a/Server/DataStructures/SharedDataType.h b/server/data_structures/shared_datatype.hpp similarity index 52% rename from Server/DataStructures/SharedDataType.h rename to server/data_structures/shared_datatype.hpp index 6357fd791..326157389 100644 --- a/Server/DataStructures/SharedDataType.h +++ b/server/data_structures/shared_datatype.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, @@ -25,22 +25,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SHARED_DATA_TYPE_H_ -#define SHARED_DATA_TYPE_H_ +#ifndef SHARED_DATA_TYPE_HPP +#define SHARED_DATA_TYPE_HPP -#include "../../Util/osrm_exception.hpp" -#include "../../Util/simple_logger.hpp" +#include "../../util/osrm_exception.hpp" +#include "../../util/simple_logger.hpp" #include #include +namespace +{ // Added at the start and end of each block as sanity check static const char CANARY[] = "OSRM"; +} struct SharedDataLayout { - enum BlockID { + enum BlockID + { NAME_OFFSETS = 0, NAME_BLOCKS, NAME_CHAR_LIST, @@ -64,54 +68,81 @@ struct SharedDataLayout std::array num_entries; std::array entry_size; - SharedDataLayout() - : num_entries() - , entry_size() - { - } + SharedDataLayout() : num_entries(), entry_size() {} void PrintInformation() const { SimpleLogger().Write(logDEBUG) << "-"; - SimpleLogger().Write(logDEBUG) << "name_offsets_size: " << num_entries[NAME_OFFSETS]; - SimpleLogger().Write(logDEBUG) << "name_blocks_size: " << num_entries[NAME_BLOCKS]; - SimpleLogger().Write(logDEBUG) << "name_char_list_size: " << num_entries[NAME_CHAR_LIST]; - SimpleLogger().Write(logDEBUG) << "name_id_list_size: " << num_entries[NAME_ID_LIST]; - SimpleLogger().Write(logDEBUG) << "via_node_list_size: " << num_entries[VIA_NODE_LIST]; - SimpleLogger().Write(logDEBUG) << "graph_node_list_size: " << num_entries[GRAPH_NODE_LIST]; - SimpleLogger().Write(logDEBUG) << "graph_edge_list_size: " << num_entries[GRAPH_EDGE_LIST]; + SimpleLogger().Write(logDEBUG) + << "name_offsets_size: " << num_entries[NAME_OFFSETS]; + SimpleLogger().Write(logDEBUG) + << "name_blocks_size: " << num_entries[NAME_BLOCKS]; + SimpleLogger().Write(logDEBUG) + << "name_char_list_size: " << num_entries[NAME_CHAR_LIST]; + SimpleLogger().Write(logDEBUG) + << "name_id_list_size: " << num_entries[NAME_ID_LIST]; + SimpleLogger().Write(logDEBUG) + << "via_node_list_size: " << num_entries[VIA_NODE_LIST]; + SimpleLogger().Write(logDEBUG) + << "graph_node_list_size: " << num_entries[GRAPH_NODE_LIST]; + SimpleLogger().Write(logDEBUG) + << "graph_edge_list_size: " << num_entries[GRAPH_EDGE_LIST]; SimpleLogger().Write(logDEBUG) << "timestamp_length: " << num_entries[TIMESTAMP]; - SimpleLogger().Write(logDEBUG) << "coordinate_list_size: " << num_entries[COORDINATE_LIST]; - SimpleLogger().Write(logDEBUG) << "turn_instruction_list_size: " << num_entries[TURN_INSTRUCTION]; - SimpleLogger().Write(logDEBUG) << "travel_mode_list_size: " << num_entries[TRAVEL_MODE]; - SimpleLogger().Write(logDEBUG) << "r_search_tree_size: " << num_entries[R_SEARCH_TREE]; - SimpleLogger().Write(logDEBUG) << "geometries_indicators: " << num_entries[GEOMETRIES_INDICATORS] - << "/" << ((num_entries[GEOMETRIES_INDICATORS] / 8) + 1); - SimpleLogger().Write(logDEBUG) << "geometries_index_list_size: " << num_entries[GEOMETRIES_INDEX]; - SimpleLogger().Write(logDEBUG) << "geometries_list_size: " << num_entries[GEOMETRIES_LIST]; - SimpleLogger().Write(logDEBUG) << "sizeof(checksum): " << entry_size[HSGR_CHECKSUM]; + SimpleLogger().Write(logDEBUG) + << "coordinate_list_size: " << num_entries[COORDINATE_LIST]; + SimpleLogger().Write(logDEBUG) + << "turn_instruction_list_size: " << num_entries[TURN_INSTRUCTION]; + SimpleLogger().Write(logDEBUG) + << "travel_mode_list_size: " << num_entries[TRAVEL_MODE]; + SimpleLogger().Write(logDEBUG) + << "r_search_tree_size: " << num_entries[R_SEARCH_TREE]; + SimpleLogger().Write(logDEBUG) + << "geometries_indicators: " << num_entries[GEOMETRIES_INDICATORS] << "/" + << ((num_entries[GEOMETRIES_INDICATORS] / 8) + 1); + SimpleLogger().Write(logDEBUG) + << "geometries_index_list_size: " << num_entries[GEOMETRIES_INDEX]; + SimpleLogger().Write(logDEBUG) + << "geometries_list_size: " << num_entries[GEOMETRIES_LIST]; + SimpleLogger().Write(logDEBUG) + << "sizeof(checksum): " << entry_size[HSGR_CHECKSUM]; - SimpleLogger().Write(logDEBUG) << "NAME_OFFSETS " << ": " << GetBlockSize(NAME_OFFSETS ); - SimpleLogger().Write(logDEBUG) << "NAME_BLOCKS " << ": " << GetBlockSize(NAME_BLOCKS ); - SimpleLogger().Write(logDEBUG) << "NAME_CHAR_LIST " << ": " << GetBlockSize(NAME_CHAR_LIST ); - SimpleLogger().Write(logDEBUG) << "NAME_ID_LIST " << ": " << GetBlockSize(NAME_ID_LIST ); - SimpleLogger().Write(logDEBUG) << "VIA_NODE_LIST " << ": " << GetBlockSize(VIA_NODE_LIST ); - SimpleLogger().Write(logDEBUG) << "GRAPH_NODE_LIST " << ": " << GetBlockSize(GRAPH_NODE_LIST ); - SimpleLogger().Write(logDEBUG) << "GRAPH_EDGE_LIST " << ": " << GetBlockSize(GRAPH_EDGE_LIST ); - SimpleLogger().Write(logDEBUG) << "COORDINATE_LIST " << ": " << GetBlockSize(COORDINATE_LIST ); - SimpleLogger().Write(logDEBUG) << "TURN_INSTRUCTION " << ": " << GetBlockSize(TURN_INSTRUCTION ); - SimpleLogger().Write(logDEBUG) << "TRAVEL_MODE " << ": " << GetBlockSize(TRAVEL_MODE ); - SimpleLogger().Write(logDEBUG) << "R_SEARCH_TREE " << ": " << GetBlockSize(R_SEARCH_TREE ); - SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDEX " << ": " << GetBlockSize(GEOMETRIES_INDEX ); - SimpleLogger().Write(logDEBUG) << "GEOMETRIES_LIST " << ": " << GetBlockSize(GEOMETRIES_LIST ); - SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDICATORS" << ": " << GetBlockSize(GEOMETRIES_INDICATORS); - SimpleLogger().Write(logDEBUG) << "HSGR_CHECKSUM " << ": " << GetBlockSize(HSGR_CHECKSUM ); - SimpleLogger().Write(logDEBUG) << "TIMESTAMP " << ": " << GetBlockSize(TIMESTAMP ); - SimpleLogger().Write(logDEBUG) << "FILE_INDEX_PATH " << ": " << GetBlockSize(FILE_INDEX_PATH ); + SimpleLogger().Write(logDEBUG) << "NAME_OFFSETS " + << ": " << GetBlockSize(NAME_OFFSETS); + SimpleLogger().Write(logDEBUG) << "NAME_BLOCKS " + << ": " << GetBlockSize(NAME_BLOCKS); + SimpleLogger().Write(logDEBUG) << "NAME_CHAR_LIST " + << ": " << GetBlockSize(NAME_CHAR_LIST); + SimpleLogger().Write(logDEBUG) << "NAME_ID_LIST " + << ": " << GetBlockSize(NAME_ID_LIST); + SimpleLogger().Write(logDEBUG) << "VIA_NODE_LIST " + << ": " << GetBlockSize(VIA_NODE_LIST); + SimpleLogger().Write(logDEBUG) << "GRAPH_NODE_LIST " + << ": " << GetBlockSize(GRAPH_NODE_LIST); + SimpleLogger().Write(logDEBUG) << "GRAPH_EDGE_LIST " + << ": " << GetBlockSize(GRAPH_EDGE_LIST); + SimpleLogger().Write(logDEBUG) << "COORDINATE_LIST " + << ": " << GetBlockSize(COORDINATE_LIST); + SimpleLogger().Write(logDEBUG) << "TURN_INSTRUCTION " + << ": " << GetBlockSize(TURN_INSTRUCTION); + SimpleLogger().Write(logDEBUG) << "TRAVEL_MODE " + << ": " << GetBlockSize(TRAVEL_MODE); + SimpleLogger().Write(logDEBUG) << "R_SEARCH_TREE " + << ": " << GetBlockSize(R_SEARCH_TREE); + SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDEX " + << ": " << GetBlockSize(GEOMETRIES_INDEX); + SimpleLogger().Write(logDEBUG) << "GEOMETRIES_LIST " + << ": " << GetBlockSize(GEOMETRIES_LIST); + SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDICATORS" + << ": " << GetBlockSize(GEOMETRIES_INDICATORS); + SimpleLogger().Write(logDEBUG) << "HSGR_CHECKSUM " + << ": " << GetBlockSize(HSGR_CHECKSUM); + SimpleLogger().Write(logDEBUG) << "TIMESTAMP " + << ": " << GetBlockSize(TIMESTAMP); + SimpleLogger().Write(logDEBUG) << "FILE_INDEX_PATH " + << ": " << GetBlockSize(FILE_INDEX_PATH); } - template - inline void SetBlockSize(BlockID bid, uint64_t entries) + template inline void SetBlockSize(BlockID bid, uint64_t entries) { num_entries[bid] = entries; entry_size[bid] = sizeof(T); @@ -122,7 +153,8 @@ struct SharedDataLayout // special encoding if (bid == GEOMETRIES_INDICATORS) { - return (num_entries[GEOMETRIES_INDICATORS]/32 + 1) * entry_size[GEOMETRIES_INDICATORS]; + return (num_entries[GEOMETRIES_INDICATORS] / 32 + 1) * + entry_size[GEOMETRIES_INDICATORS]; } return num_entries[bid] * entry_size[bid]; @@ -130,7 +162,7 @@ struct SharedDataLayout inline uint64_t GetSizeOfLayout() const { - return GetBlockOffset(NUM_BLOCKS) + NUM_BLOCKS*2*sizeof(CANARY); + return GetBlockOffset(NUM_BLOCKS) + NUM_BLOCKS * 2 * sizeof(CANARY); } inline uint64_t GetBlockOffset(BlockID bid) const @@ -138,26 +170,26 @@ struct SharedDataLayout uint64_t result = sizeof(CANARY); for (auto i = 0; i < bid; i++) { - result += GetBlockSize((BlockID) i) + 2*sizeof(CANARY); + result += GetBlockSize((BlockID)i) + 2 * sizeof(CANARY); } return result; } - template - inline T* GetBlockPtr(char* shared_memory, BlockID bid) + template + inline T *GetBlockPtr(char *shared_memory, BlockID bid) { - T* ptr = (T*)(shared_memory + GetBlockOffset(bid)); + T *ptr = (T *)(shared_memory + GetBlockOffset(bid)); if (WRITE_CANARY) { - char* start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY); - char* end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid); + char *start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY); + char *end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid); std::copy(CANARY, CANARY + sizeof(CANARY), start_canary_ptr); std::copy(CANARY, CANARY + sizeof(CANARY), end_canary_ptr); } else { - char* start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY); - char* end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid); + char *start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY); + char *end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid); bool start_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), start_canary_ptr); bool end_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), end_canary_ptr); if (!start_canary_alive) @@ -175,13 +207,15 @@ struct SharedDataLayout }; enum SharedDataType -{ CURRENT_REGIONS, - LAYOUT_1, - DATA_1, - LAYOUT_2, - DATA_2, - LAYOUT_NONE, - DATA_NONE }; +{ + CURRENT_REGIONS, + LAYOUT_1, + DATA_1, + LAYOUT_2, + DATA_2, + LAYOUT_NONE, + DATA_NONE +}; struct SharedDataTimestamp { @@ -190,4 +224,4 @@ struct SharedDataTimestamp unsigned timestamp; }; -#endif /* SHARED_DATA_TYPE_H_ */ +#endif /* SHARED_DATA_TYPE_HPP */ diff --git a/Server/Http/CompressionType.h b/server/http/compression_type.hpp similarity index 85% rename from Server/Http/CompressionType.h rename to server/http/compression_type.hpp index 3836cd749..f0dc692fa 100644 --- a/Server/Http/CompressionType.h +++ b/server/http/compression_type.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,17 +25,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef COMPRESSION_TYPE_H -#define COMPRESSION_TYPE_H +#ifndef COMPRESSION_TYPE_HPP +#define COMPRESSION_TYPE_HPP namespace http { -enum CompressionType -{ noCompression, - gzipRFC1952, - deflateRFC1951 }; - +enum compression_type +{ + no_compression, + gzip_rfc1952, + deflate_rfc1951 +}; } -#endif // COMPRESSION_TYPE_H +#endif // COMPRESSION_TYPE_HPP diff --git a/Include/osrm/Header.h b/server/http/header.hpp similarity index 76% rename from Include/osrm/Header.h rename to server/http/header.hpp index d126c4c98..08d2476b1 100644 --- a/Include/osrm/Header.h +++ b/server/http/header.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,21 +25,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef HTTP_HEADER_H -#define HTTP_HEADER_H +#ifndef HEADER_HPP +#define HEADER_HPP #include #include namespace http { -struct Header +struct header { - Header& operator=(const Header& other) = default; - Header(const std::string & name, const std::string & value) : name(name), value(value) {} - Header(Header && other) : name(std::move(other.name)), value(std::move(other.value)) {} + // explicitly use default copy c'tor as adding move c'tor + header &operator=(const header &other) = default; + header(const std::string &name, const std::string &value) : name(name), value(value) {} + header(header &&other) : name(std::move(other.name)), value(std::move(other.value)) {} - void Clear() + void clear() { name.clear(); value.clear(); @@ -50,4 +51,4 @@ struct Header }; } -#endif // HTTP_HEADER_H +#endif // HEADER_HPP diff --git a/Server/Http/Reply.cpp b/server/http/reply.cpp similarity index 59% rename from Server/Http/Reply.cpp rename to server/http/reply.cpp index e2cf0aecf..036d1ae05 100644 --- a/Server/Http/Reply.cpp +++ b/server/http/reply.cpp @@ -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,16 +25,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include "reply.hpp" -#include "../../Util/cast.hpp" +#include "../../util/cast.hpp" namespace http { -void Reply::SetSize(const unsigned size) +const char ok_html[] = ""; +const char bad_request_html[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; +const char internal_server_error_html[] = + "{\"status\": 500,\"status_message\":\"Internal Server Error\"}"; +const char seperators[] = {':', ' '}; +const char crlf[] = {'\r', '\n'}; +const std::string http_ok_string = "HTTP/1.0 200 OK\r\n"; +const std::string http_bad_request_string = "HTTP/1.0 400 Bad Request\r\n"; +const std::string http_internal_server_error_string = "HTTP/1.0 500 Internal Server Error\r\n"; + +void reply::set_size(const std::size_t size) { - for (Header &h : headers) + for (header &h : headers) { if ("Content-Length" == h.name) { @@ -43,14 +53,13 @@ void Reply::SetSize(const unsigned size) } } -// Sets the size of the uncompressed output. -void Reply::SetUncompressedSize() { SetSize(static_cast(content.size())); } +void reply::set_uncompressed_size() { set_size(content.size()); } -std::vector Reply::ToBuffers() +std::vector reply::to_buffers() { std::vector buffers; - buffers.push_back(ToBuffer(status)); - for (const Header &h : headers) + buffers.push_back(status_to_buffer(status)); + for (const header &h : headers) { buffers.push_back(boost::asio::buffer(h.name)); buffers.push_back(boost::asio::buffer(seperators)); @@ -62,13 +71,12 @@ std::vector Reply::ToBuffers() return buffers; } -std::vector Reply::HeaderstoBuffers() +std::vector reply::headers_to_buffers() { std::vector buffers; - buffers.push_back(ToBuffer(status)); - for (std::size_t i = 0; i < headers.size(); ++i) + buffers.push_back(status_to_buffer(status)); + for (const header ¤t_header : headers) { - Header ¤t_header = headers[i]; buffers.push_back(boost::asio::buffer(current_header.name)); buffers.push_back(boost::asio::buffer(seperators)); buffers.push_back(boost::asio::buffer(current_header.value)); @@ -78,13 +86,13 @@ std::vector Reply::HeaderstoBuffers() return buffers; } -Reply Reply::StockReply(Reply::status_type status) +reply reply::stock_reply(const reply::status_type status) { - Reply reply; + reply reply; reply.status = status; reply.content.clear(); - const std::string status_string = reply.ToString(status); + const std::string status_string = reply.status_to_string(status); reply.content.insert(reply.content.end(), status_string.begin(), status_string.end()); reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size())); @@ -92,31 +100,31 @@ Reply Reply::StockReply(Reply::status_type status) return reply; } -std::string Reply::ToString(Reply::status_type status) +std::string reply::status_to_string(const reply::status_type status) { - if (Reply::ok == status) + if (reply::ok == status) { - return okHTML; + return ok_html; } - if (Reply::badRequest == status) + if (reply::bad_request == status) { - return badRequestHTML; + return bad_request_html; } - return internalServerErrorHTML; + return internal_server_error_html; } -boost::asio::const_buffer Reply::ToBuffer(Reply::status_type status) +boost::asio::const_buffer reply::status_to_buffer(const reply::status_type status) { - if (Reply::ok == status) + if (reply::ok == status) { - return boost::asio::buffer(okString); + return boost::asio::buffer(http_ok_string); } - if (Reply::internalServerError == status) + if (reply::internal_server_error == status) { - return boost::asio::buffer(internalServerErrorString); + return boost::asio::buffer(http_internal_server_error_string); } - return boost::asio::buffer(badRequestString); + return boost::asio::buffer(http_bad_request_string); } -Reply::Reply() : status(ok) {} +reply::reply() : status(ok) {} } diff --git a/server/http/reply.hpp b/server/http/reply.hpp new file mode 100644 index 000000000..733818c2c --- /dev/null +++ b/server/http/reply.hpp @@ -0,0 +1,65 @@ +/* + +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 REPLY_HPP +#define REPLY_HPP + +#include "header.hpp" + +#include + +#include + +namespace http +{ +class reply +{ + public: + enum status_type + { + ok = 200, + bad_request = 400, + internal_server_error = 500 + } status; + + std::vector
headers; + std::vector to_buffers(); + std::vector headers_to_buffers(); + std::vector content; + static reply stock_reply(const status_type status); + void set_size(const std::size_t size); + void set_uncompressed_size(); + + reply(); + + private: + std::string status_to_string(reply::status_type status); + boost::asio::const_buffer status_to_buffer(reply::status_type status); +}; +} + +#endif // REPLY_HPP diff --git a/Server/Http/Request.h b/server/http/request.hpp similarity index 92% rename from Server/Http/Request.h rename to server/http/request.hpp index 4746a5ec2..c487fba65 100644 --- a/Server/Http/Request.h +++ b/server/http/request.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,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef REQUEST_H -#define REQUEST_H +#ifndef REQUEST_HPP +#define REQUEST_HPP #include @@ -35,7 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace http { -struct Request +struct request { std::string uri; std::string referrer; @@ -45,4 +45,4 @@ struct Request } // namespace http -#endif // REQUEST_H +#endif // REQUEST_HPP diff --git a/server/request_handler.cpp b/server/request_handler.cpp new file mode 100644 index 000000000..d1c6e6265 --- /dev/null +++ b/server/request_handler.cpp @@ -0,0 +1,175 @@ +/* + +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 "request_handler.hpp" + +#include "api_grammar.hpp" +#include "http/reply.hpp" +#include "http/request.hpp" + +#include "../library/osrm.hpp" +#include "../util/json_renderer.hpp" +#include "../util/simple_logger.hpp" +#include "../util/string_util.hpp" +#include "../util/xml_renderer.hpp" +#include "../typedefs.h" + +#include +#include + +#include + +#include +#include + +RequestHandler::RequestHandler() : routing_machine(nullptr) {} + +void RequestHandler::handle_request(const http::request ¤t_request, + http::reply ¤t_reply) +{ + // parse command + try + { + std::string request_string; + URIDecode(current_request.uri, request_string); + + // 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") << + // " " << current_request.endpoint.to_string() << " " << + // current_request.referrer << ( 0 == current_request.referrer.length() ? "- " :" ") << + // current_request.agent << ( 0 == current_request.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 << " " << current_request.endpoint.to_string() + << " " << current_request.referrer + << (0 == current_request.referrer.length() ? "- " : " ") + << current_request.agent + << (0 == current_request.agent.length() ? "- " : " ") + << request_string; + + RouteParameters route_parameters; + APIGrammarParser api_parser(&route_parameters); + + auto api_iterator = request_string.begin(); + const bool result = + boost::spirit::qi::parse(api_iterator, request_string.end(), api_parser); + + osrm::json::Object json_result; + // check if the was an error with the request + if (!result || (api_iterator != request_string.end())) + { + current_reply = http::reply::stock_reply(http::reply::bad_request); + current_reply.content.clear(); + const auto position = std::distance(request_string.begin(), api_iterator); + + 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; + osrm::json::render(current_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 + "("); + current_reply.content.insert(current_reply.content.end(), json_p.begin(), json_p.end()); + } + const auto return_code = routing_machine->RunQuery(route_parameters, json_result); + if (200 != return_code) + { + current_reply = http::reply::stock_reply(http::reply::bad_request); + current_reply.content.clear(); + json_result.values["status"] = 400; + std::string message = "Bad Request"; + json_result.values["status_message"] = message; + osrm::json::render(current_reply.content, json_result); + return; + } + + current_reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); + current_reply.headers.emplace_back("Access-Control-Allow-Methods", "GET"); + current_reply.headers.emplace_back("Access-Control-Allow-Headers", + "X-Requested-With, Content-Type"); + + // set headers + current_reply.headers.emplace_back("Content-Length", + cast::integral_to_string(current_reply.content.size())); + if ("gpx" == route_parameters.output_format) + { // gpx file + osrm::json::gpx_render(current_reply.content, json_result.values["route"]); + current_reply.headers.emplace_back("Content-Type", + "application/gpx+xml; charset=UTF-8"); + current_reply.headers.emplace_back("Content-Disposition", + "attachment; filename=\"route.gpx\""); + } + else if (route_parameters.jsonp_parameter.empty()) + { // json file + osrm::json::render(current_reply.content, json_result); + current_reply.headers.emplace_back("Content-Type", "application/json; charset=UTF-8"); + current_reply.headers.emplace_back("Content-Disposition", + "inline; filename=\"response.json\""); + } + else + { // jsonp + osrm::json::render(current_reply.content, json_result); + current_reply.headers.emplace_back("Content-Type", "text/javascript; charset=UTF-8"); + current_reply.headers.emplace_back("Content-Disposition", + "inline; filename=\"response.js\""); + } + if (!route_parameters.jsonp_parameter.empty()) + { // append brace to jsonp response + current_reply.content.push_back(')'); + } + } + catch (const std::exception &e) + { + current_reply = http::reply::stock_reply(http::reply::internal_server_error); + SimpleLogger().Write(logWARNING) << "[server error] code: " << e.what() + << ", uri: " << current_request.uri; + return; + } +} + +void RequestHandler::RegisterRoutingMachine(OSRM *osrm) { routing_machine = osrm; } diff --git a/Server/RequestHandler.h b/server/request_handler.hpp similarity index 86% rename from Server/RequestHandler.h rename to server/request_handler.hpp index 7263dad4e..b4019db7d 100644 --- a/Server/RequestHandler.h +++ b/server/request_handler.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,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef REQUEST_HANDLER_H -#define REQUEST_HANDLER_H +#ifndef REQUEST_HANDLER_HPP +#define REQUEST_HANDLER_HPP #include @@ -36,8 +36,8 @@ class OSRM; namespace http { -class Reply; -struct Request; +class reply; +struct request; } class RequestHandler @@ -49,11 +49,11 @@ class RequestHandler RequestHandler(); RequestHandler(const RequestHandler &) = delete; - void handle_request(const http::Request &req, http::Reply &rep); + void handle_request(const http::request ¤t_request, http::reply ¤t_reply); void RegisterRoutingMachine(OSRM *osrm); private: OSRM *routing_machine; }; -#endif // REQUEST_HANDLER_H +#endif // REQUEST_HANDLER_HPP diff --git a/server/request_parser.cpp b/server/request_parser.cpp new file mode 100644 index 000000000..584dcbeeb --- /dev/null +++ b/server/request_parser.cpp @@ -0,0 +1,323 @@ +/* + +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 "request_parser.hpp" + +#include "http/compression_type.hpp" +#include "http/header.hpp" +#include "http/request.hpp" + +#include "../data_structures/tribool.hpp" + +#include + +#include + +namespace http +{ + +RequestParser::RequestParser() + : state(internal_state::method_start), current_header({"", ""}), + selected_compression(no_compression) +{ +} + +std::tuple +RequestParser::parse(request ¤t_request, char *begin, char *end) +{ + while (begin != end) + { + osrm::tribool result = consume(current_request, *begin++); + if (result != osrm::tribool::indeterminate) + { + return std::make_tuple(result, selected_compression); + } + } + osrm::tribool result = osrm::tribool::indeterminate; + return std::make_tuple(result, selected_compression); +} + +osrm::tribool RequestParser::consume(request ¤t_request, const char input) +{ + switch (state) + { + case internal_state::method_start: + if (!is_char(input) || is_CTL(input) || is_special(input)) + { + return osrm::tribool::no; + } + state = internal_state::method; + return osrm::tribool::indeterminate; + case internal_state::method: + if (input == ' ') + { + state = internal_state::uri; + return osrm::tribool::indeterminate; + } + if (!is_char(input) || is_CTL(input) || is_special(input)) + { + return osrm::tribool::no; + } + return osrm::tribool::indeterminate; + case internal_state::uri_start: + if (is_CTL(input)) + { + return osrm::tribool::no; + } + state = internal_state::uri; + current_request.uri.push_back(input); + return osrm::tribool::indeterminate; + case internal_state::uri: + if (input == ' ') + { + state = internal_state::http_version_h; + return osrm::tribool::indeterminate; + } + if (is_CTL(input)) + { + return osrm::tribool::no; + } + current_request.uri.push_back(input); + return osrm::tribool::indeterminate; + case internal_state::http_version_h: + if (input == 'H') + { + state = internal_state::http_version_t_1; + return osrm::tribool::indeterminate; + } + return osrm::tribool::no; + case internal_state::http_version_t_1: + if (input == 'T') + { + state = internal_state::http_version_t_2; + return osrm::tribool::indeterminate; + } + return osrm::tribool::no; + case internal_state::http_version_t_2: + if (input == 'T') + { + state = internal_state::http_version_p; + return osrm::tribool::indeterminate; + } + return osrm::tribool::no; + case internal_state::http_version_p: + if (input == 'P') + { + state = internal_state::http_version_slash; + return osrm::tribool::indeterminate; + } + return osrm::tribool::no; + case internal_state::http_version_slash: + if (input == '/') + { + state = internal_state::http_version_major_start; + return osrm::tribool::indeterminate; + } + return osrm::tribool::no; + case internal_state::http_version_major_start: + if (is_digit(input)) + { + state = internal_state::http_version_major; + return osrm::tribool::indeterminate; + } + return osrm::tribool::no; + case internal_state::http_version_major: + if (input == '.') + { + state = internal_state::http_version_minor_start; + return osrm::tribool::indeterminate; + } + if (is_digit(input)) + { + return osrm::tribool::indeterminate; + } + return osrm::tribool::no; + case internal_state::http_version_minor_start: + if (is_digit(input)) + { + state = internal_state::http_version_minor; + return osrm::tribool::indeterminate; + } + return osrm::tribool::no; + case internal_state::http_version_minor: + if (input == '\r') + { + state = internal_state::expecting_newline_1; + return osrm::tribool::indeterminate; + } + if (is_digit(input)) + { + return osrm::tribool::indeterminate; + } + return osrm::tribool::no; + case internal_state::expecting_newline_1: + if (input == '\n') + { + state = internal_state::header_line_start; + return osrm::tribool::indeterminate; + } + return osrm::tribool::no; + case internal_state::header_line_start: + if (boost::iequals(current_header.name, "Accept-Encoding")) + { + /* giving gzip precedence over deflate */ + if (boost::icontains(current_header.value, "deflate")) + { + selected_compression = deflate_rfc1951; + } + if (boost::icontains(current_header.value, "gzip")) + { + selected_compression = gzip_rfc1952; + } + } + + if (boost::iequals(current_header.name, "Referer")) + { + current_request.referrer = current_header.value; + } + + if (boost::iequals(current_header.name, "User-Agent")) + { + current_request.agent = current_header.value; + } + + if (input == '\r') + { + state = internal_state::expecting_newline_3; + return osrm::tribool::indeterminate; + } + if (!is_char(input) || is_CTL(input) || is_special(input)) + { + return osrm::tribool::no; + } + state = internal_state::header_name; + current_header.clear(); + current_header.name.push_back(input); + return osrm::tribool::indeterminate; + case internal_state::header_lws: + if (input == '\r') + { + state = internal_state::expecting_newline_2; + return osrm::tribool::indeterminate; + } + if (input == ' ' || input == '\t') + { + return osrm::tribool::indeterminate; + } + if (is_CTL(input)) + { + return osrm::tribool::no; + } + state = internal_state::header_value; + return osrm::tribool::indeterminate; + case internal_state::header_name: + if (input == ':') + { + state = internal_state::space_before_header_value; + return osrm::tribool::indeterminate; + } + if (!is_char(input) || is_CTL(input) || is_special(input)) + { + return osrm::tribool::no; + } + current_header.name.push_back(input); + return osrm::tribool::indeterminate; + case internal_state::space_before_header_value: + if (input == ' ') + { + state = internal_state::header_value; + return osrm::tribool::indeterminate; + } + return osrm::tribool::no; + case internal_state::header_value: + if (input == '\r') + { + state = internal_state::expecting_newline_2; + return osrm::tribool::indeterminate; + } + if (is_CTL(input)) + { + return osrm::tribool::no; + } + current_header.value.push_back(input); + return osrm::tribool::indeterminate; + case internal_state::expecting_newline_2: + if (input == '\n') + { + state = internal_state::header_line_start; + return osrm::tribool::indeterminate; + } + return osrm::tribool::no; + default: // expecting_newline_3 + return input == '\n' ? osrm::tribool::yes : osrm::tribool::no; + } +} + +bool RequestParser::is_char(const int character) const +{ + return character >= 0 && character <= 127; +} + +bool RequestParser::is_CTL(const int character) const +{ + return (character >= 0 && character <= 31) || (character == 127); +} + +bool RequestParser::is_special(const int character) const +{ + 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; + } +} + +bool RequestParser::is_digit(const int character) const +{ + return character >= '0' && character <= '9'; +} +} diff --git a/Server/RequestParser.h b/server/request_parser.hpp similarity index 51% rename from Server/RequestParser.h rename to server/request_parser.hpp index 7f302a257..2b6bf6944 100644 --- a/Server/RequestParser.h +++ b/server/request_parser.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,66 +25,68 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef REQUEST_PARSER_H -#define REQUEST_PARSER_H +#ifndef REQUEST_PARSER_HPP +#define REQUEST_PARSER_HPP -#include "Http/CompressionType.h" -#include +#include "http/compression_type.hpp" +#include "http/header.hpp" +#include "../data_structures/tribool.hpp" -#include -#include +#include namespace http { -struct Request; +struct request; class RequestParser { public: RequestParser(); - void Reset(); - boost::tuple - Parse(Request &req, char *begin, char *end, CompressionType &compression_type); + std::tuple + parse(request ¤t_request, char *begin, char *end); private: - boost::tribool consume(Request &req, char input, CompressionType &compression_type); + osrm::tribool consume(request ¤t_request, const char input); - inline bool isChar(int c); + bool is_char(const int character) const; - inline bool isCTL(int c); + bool is_CTL(const int character) const; - inline bool isTSpecial(int c); + bool is_special(const int character) const; - inline bool isDigit(int c); + bool is_digit(const int character) const; - enum state - { method_start, - method, - uri_start, - uri, - http_version_h, - http_version_t_1, - http_version_t_2, - http_version_p, - http_version_slash, - http_version_major_start, - http_version_major, - http_version_minor_start, - http_version_minor, - expecting_newline_1, - header_line_start, - header_lws, - header_name, - space_before_header_value, - header_value, - expecting_newline_2, - expecting_newline_3 } state_; + enum class internal_state : unsigned char + { + method_start, + method, + uri_start, + uri, + http_version_h, + http_version_t_1, + http_version_t_2, + http_version_p, + http_version_slash, + http_version_major_start, + http_version_major, + http_version_minor_start, + http_version_minor, + expecting_newline_1, + header_line_start, + header_lws, + header_name, + space_before_header_value, + header_value, + expecting_newline_2, + expecting_newline_3 + } state; - Header header; + header current_header; + compression_type selected_compression; }; } // namespace http -#endif // REQUEST_PARSER_H +#endif // REQUEST_PARSER_HPP diff --git a/Server/Server.h b/server/server.hpp similarity index 90% rename from Server/Server.h rename to server/server.hpp index 8e0b10130..0ec316379 100644 --- a/Server/Server.h +++ b/server/server.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,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SERVER_H -#define SERVER_H +#ifndef SERVER_HPP +#define SERVER_HPP -#include "Connection.h" -#include "RequestHandler.h" +#include "connection.hpp" +#include "request_handler.hpp" -#include "../Util/cast.hpp" -#include "../Util/make_unique.hpp" -#include "../Util/simple_logger.hpp" +#include "../util/cast.hpp" +#include "../util/integer_range.hpp" +#include "../util/simple_logger.hpp" #include #include @@ -48,9 +48,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class Server { public: - // Note: returns a shared instead of a unique ptr as it is captured in a lambda somewhere else - static std::shared_ptr CreateServer(std::string &ip_address, int ip_port, unsigned requested_num_threads) + static std::shared_ptr + CreateServer(std::string &ip_address, int ip_port, unsigned requested_num_threads) { SimpleLogger().Write() << "http 1.1 compression handled by zlib version " << zlibVersion(); const unsigned hardware_threads = std::max(1u, std::thread::hardware_concurrency()); @@ -60,7 +60,7 @@ class Server explicit Server(const std::string &address, const int port, const unsigned thread_pool_size) : thread_pool_size(thread_pool_size), acceptor(io_service), - new_connection(std::make_shared(io_service, request_handler)), request_handler() + new_connection(std::make_shared(io_service, request_handler)) { const std::string port_string = cast::integral_to_string(port); @@ -116,4 +116,4 @@ class Server RequestHandler request_handler; }; -#endif // SERVER_H +#endif // SERVER_HPP diff --git a/third_party/libosmium/.gitignore b/third_party/libosmium/.gitignore new file mode 100644 index 000000000..50139035b --- /dev/null +++ b/third_party/libosmium/.gitignore @@ -0,0 +1,2 @@ +*.swp +.ycm_extra_conf.pyc diff --git a/third_party/libosmium/.travis.yml b/third_party/libosmium/.travis.yml new file mode 100644 index 000000000..73dff72a1 --- /dev/null +++ b/third_party/libosmium/.travis.yml @@ -0,0 +1,51 @@ +#----------------------------------------------------------------------------- +# +# Configuration for continuous integration service at travis-ci.org +# +#----------------------------------------------------------------------------- + +language: cpp + +compiler: + - gcc + - clang + +env: + - CONFIGURATION=Dev + - CONFIGURATION=Release + +before_install: + # we need at least g++-4.8 for c++11 features + - sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test + - sudo apt-get update --yes --quiet + +install: + - cd .. + # upgrade compilers + - sudo apt-get install --yes gcc-4.8 g++-4.8 + # make sure 'cpp' is the just installed current one + - sudo rm /usr/bin/cpp + - sudo ln -s /usr/bin/cpp-4.8 /usr/bin/cpp + # upgrade libosmium dependencies + - sudo apt-get install --yes make libboost-dev libboost-program-options-dev libsparsehash-dev libprotobuf-dev protobuf-compiler libgeos++-dev libproj-dev libgdal1h libgdal-dev + - git clone https://github.com/osmcode/osm-testdata.git + # OSMPBF is too old, install from git + #- sudo apt-get install --yes libosmpbf-dev + - git clone https://github.com/scrosby/OSM-binary.git + - cd OSM-binary/src + - make + - sudo make install + - cd ../.. + - cd libosmium + +before_script: + - true + +script: + - if [ "${CXX}" = 'g++' ]; then export CXX=g++-4.8; fi; + - mkdir build + - cd build + - cmake -LA -DCMAKE_BUILD_TYPE=${CONFIGURATION} .. + - make VERBOSE=1 + - ctest --output-on-failure + diff --git a/third_party/libosmium/.ycm_extra_conf.py b/third_party/libosmium/.ycm_extra_conf.py new file mode 100644 index 000000000..2b8730616 --- /dev/null +++ b/third_party/libosmium/.ycm_extra_conf.py @@ -0,0 +1,48 @@ +#----------------------------------------------------------------------------- +# +# Configuration for YouCompleteMe Vim plugin +# +# http://valloric.github.io/YouCompleteMe/ +# +#----------------------------------------------------------------------------- + +from os.path import realpath, dirname + +basedir = dirname(realpath(__file__)) + +# some default flags +# for more information install clang-3.2-doc package and +# check UsersManual.html +flags = [ +'-Werror', +'-Wall', +'-Wextra', +'-pedantic', +'-Wno-return-type', +'-Wno-unused-parameter', +'-Wno-unused-variable', + +'-std=c++11', + +# '-x' and 'c++' also required +# use 'c' for C projects +'-x', +'c++', + +# libosmium include dirs +'-I%s/include' % basedir, +'-I%s/test/include' % basedir, +'-I%s/test/data-test/include' % basedir, + +# include third party libraries +'-I/usr/include/gdal', +] + +# youcompleteme is calling this function to get flags +# You can also set database for flags. Check: JSONCompilationDatabase.html in +# clang-3.2-doc package +def FlagsForFile( filename ): + return { + 'flags': flags, + 'do_cache': True + } diff --git a/third_party/libosmium/CHANGELOG.md b/third_party/libosmium/CHANGELOG.md new file mode 100644 index 000000000..4c345a498 --- /dev/null +++ b/third_party/libosmium/CHANGELOG.md @@ -0,0 +1,31 @@ + +# Change Log + +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## [unreleased] - + +## [2.1.0] - 2015-03-31 + +### Added + +- When writing PBF files, sorting the PBF stringtables is now optional. +- More tests and documentation. + +### Changed + +- Some functions are now declared `noexcept`. +- XML parser fails now if the top-level element is not `osm` or `osmChange`. + +### Fixed + +- Race condition in PBF reader. +- Multipolygon collector was accessing non-existent NodeRef. +- Doxygen documentation wan't showing all classes/functions due to a bug in + Doxygen (up to version 1.8.8). This version contains a workaround to fix + this. + +[unreleased]: https://github.com/osmcode/libosmium/compare/v2.1.0...HEAD +[2.1.0]: https://github.com/osmcode/libosmium/compare/v2.0.0...v2.1.0 + diff --git a/third_party/libosmium/CMakeLists.txt b/third_party/libosmium/CMakeLists.txt new file mode 100644 index 000000000..5e70a9935 --- /dev/null +++ b/third_party/libosmium/CMakeLists.txt @@ -0,0 +1,333 @@ +#----------------------------------------------------------------------------- +# +# CMake Config +# +# Libosmium +# +#----------------------------------------------------------------------------- + +cmake_minimum_required(VERSION 2.8 FATAL_ERROR) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + + +#----------------------------------------------------------------------------- +# +# Project version +# +#----------------------------------------------------------------------------- + +set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev" + CACHE STRING + "List of available configuration types" + FORCE) + +project(libosmium) + +set(LIBOSMIUM_VERSION_MAJOR 2) +set(LIBOSMIUM_VERSION_MINOR 1) +set(LIBOSMIUM_VERSION_PATCH 0) + +set(LIBOSMIUM_VERSION + ${LIBOSMIUM_VERSION_MAJOR}.${LIBOSMIUM_VERSION_MINOR}.${LIBOSMIUM_VERSION_PATCH}) + + +#----------------------------------------------------------------------------- +# +# Build options +# +# (Change with -DOPTION=VALUE on cmake command line.) +# +#----------------------------------------------------------------------------- + +if(CMAKE_BUILD_TYPE STREQUAL "Dev") + set(dev_build ON) +else() + set(dev_build OFF) +endif() + +option(BUILD_EXAMPLES "compile example programs" ON) +option(BUILD_TESTING "compile unit tests, please run them with ctest" ON) + +option(BUILD_HEADERS "compile every header file on its own" ${dev_build}) +option(BUILD_BENCHMARKS "compile benchmark programs" ${dev_build}) +option(BUILD_DATA_TESTS "compile data tests, please run them with ctest" ${dev_build}) + + +#----------------------------------------------------------------------------- +# +# Find external dependencies +# +#----------------------------------------------------------------------------- + +find_package(Boost 1.38) +mark_as_advanced(CLEAR BOOST_ROOT) + +if(Boost_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) +else() + set(BOOST_ROOT "NOT FOUND: please choose" CACHE PATH "") + message(FATAL_ERROR "PLEASE, specify the directory where the Boost library is installed in BOOST_ROOT") +endif() + +set(OSMIUM_INCLUDE_DIR include) +find_package(Osmium COMPONENTS io gdal geos proj sparsehash) +include_directories(${OSMIUM_INCLUDE_DIRS}) + +if(MSVC) + find_path(GETOPT_INCLUDE_DIR getopt.h) + find_library(GETOPT_LIBRARY NAMES wingetopt) + if(GETOPT_INCLUDE_DIR AND GETOPT_LIBRARY) + include_directories(${GETOPT_INCLUDE_DIR}) + list(APPEND OSMIUM_LIBRARIES ${GETOPT_LIBRARY}) + else() + set(GETOPT_MISSING 1) + endif() +endif() + +include_directories(include) + + +#----------------------------------------------------------------------------- +# +# Decide which C++ version to use (Minimum/default: C++11). +# +#----------------------------------------------------------------------------- +if(NOT MSVC) + if(NOT USE_CPP_VERSION) + set(USE_CPP_VERSION c++11) + endif() + message(STATUS "Use C++ version: ${USE_CPP_VERSION}") + # following only available from cmake 2.8.12: + # add_compile_options(-std=${USE_CPP_VERSION}) + # so using this instead: + add_definitions(-std=${USE_CPP_VERSION}) +endif() + + +#----------------------------------------------------------------------------- +# +# Compiler and Linker flags +# +#----------------------------------------------------------------------------- +if(MSVC) + set(USUAL_COMPILE_OPTIONS "/Ox") +else() + set(USUAL_COMPILE_OPTIONS "-O3 -g") +endif() + +if(WIN32) + add_definitions(-DWIN32 -D_WIN32 -DMSWIN32 -DBGDWIN32 + -DWINVER=0x0500 -D_WIN32_WINNT=0x0500 -D_WIN32_IE=0x0600) +endif() + +set(CMAKE_CXX_FLAGS_DEV "${USUAL_COMPILE_OPTIONS}" + CACHE STRING "Flags used by the compiler during developer builds." + FORCE) + +set(CMAKE_EXE_LINKER_FLAGS_DEV "" + CACHE STRING "Flags used by the linker during developer builds." + FORCE) +mark_as_advanced( + CMAKE_CXX_FLAGS_DEV + CMAKE_EXE_LINKER_FLAGS_DEV +) + +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${USUAL_COMPILE_OPTIONS}" + CACHE STRING "Flags used by the compiler during RELWITHDEBINFO builds." + FORCE) + + +#----------------------------------------------------------------------------- +# +# Build Type +# +#----------------------------------------------------------------------------- +# In 'Dev' mode: compile with very strict warnings and turn them into errors. +if(CMAKE_BUILD_TYPE STREQUAL "Dev") + if(NOT MSVC) + add_definitions(-Werror) + endif() + add_definitions(${OSMIUM_WARNING_OPTIONS}) +endif() + +# Force RelWithDebInfo build type if none was given +if(CMAKE_BUILD_TYPE) + set(build_type ${CMAKE_BUILD_TYPE}) +else() + set(build_type "RelWithDebInfo") +endif() + +set(CMAKE_BUILD_TYPE ${build_type} + CACHE STRING + "Choose the type of build, options are: ${CMAKE_CONFIGURATION_TYPES}." + FORCE) + + +#----------------------------------------------------------------------------- +# +# Unit and data tests +# +#----------------------------------------------------------------------------- +enable_testing() + +if(BUILD_TESTING OR BUILD_DATA_TESTS) + find_program(MEMORYCHECK_COMMAND valgrind) + + set(MEMORYCHECK_COMMAND_OPTIONS + "--trace-children=yes --leak-check=full --show-reachable=yes --error-exitcode=1") + + set(MEMORYCHECK_SUPPRESSIONS_FILE "${PROJECT_SOURCE_DIR}/test/valgrind.supp") +endif() + +if(BUILD_TESTING) + add_subdirectory(test) +endif() + +if(BUILD_DATA_TESTS) + add_subdirectory(test/data-tests) +endif() + + +#----------------------------------------------------------------------------- +# +# Optional "cppcheck" target that checks C++ code +# +#----------------------------------------------------------------------------- +message(STATUS "Looking for cppcheck") +find_program(CPPCHECK cppcheck) + +if(CPPCHECK) + message(STATUS "Looking for cppcheck - found") + set(CPPCHECK_OPTIONS + --enable=warning,style,performance,portability,information,missingInclude) + + # cpp doesn't find system includes for some reason, suppress that report + set(CPPCHECK_OPTIONS ${CPPCHECK_OPTIONS} --suppress=missingIncludeSystem) + + file(GLOB_RECURSE ALL_INCLUDES include/osmium/*.hpp) + file(GLOB ALL_EXAMPLES examples/*.cpp) + file(GLOB ALL_UNIT_TESTS test/t/*/test_*.cpp) + file(GLOB ALL_DATA_TESTS test/data-tests/*.cpp) + + if(Osmium_DEBUG) + message(STATUS "Checking includes : ${ALL_INCLUDES}") + message(STATUS "Checking example code : ${ALL_EXAMPLES}") + message(STATUS "Checking unit test code: ${ALL_UNIT_TESTS}") + message(STATUS "Checking data test code: ${ALL_DATA_TESTS}") + endif() + + set(CPPCHECK_FILES + ${ALL_INCLUDES} + ${ALL_EXAMPLES} + ${ALL_UNIT_TESTS} + ${ALL_DATA_TESTS}) + + add_custom_target(cppcheck + ${CPPCHECK} + --std=c++11 ${CPPCHECK_OPTIONS} + -I ${CMAKE_SOURCE_DIR}/include + ${CPPCHECK_FILES} + ) +else() + message(STATUS "Looking for cppcheck - not found") + message(STATUS " Build target 'cppcheck' will not be available.") +endif(CPPCHECK) + + +#----------------------------------------------------------------------------- +# +# Examples, benchmarks and documentation +# +#----------------------------------------------------------------------------- + +if(BUILD_EXAMPLES) + add_subdirectory(examples) +endif() + +if(BUILD_BENCHMARKS) + add_subdirectory(benchmarks) +endif() + +add_subdirectory(doc) + + +#----------------------------------------------------------------------------- +# +# Headers +# +# This will try to compile include files on their own to detect missing +# include directives and other dependency-related problems. Note that if this +# work, it is not enough to be sure it will compile in production code. +# But if it reports an error we know we are missing something. +# +#----------------------------------------------------------------------------- +if(BUILD_HEADERS) + file(GLOB_RECURSE + ALL_HPPS + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/include" + include/osmium/*.hpp) + + file(MAKE_DIRECTORY header_check) + + foreach(hpp ${ALL_HPPS}) + string(REPLACE ".hpp" "" tmp ${hpp}) + string(REPLACE "/" "__" libname ${tmp}) + + # Create a dummy .cpp file that includes the header file we want to + # check. + set(DUMMYCPP ${CMAKE_BINARY_DIR}/header_check/${libname}.cpp) + file(WRITE ${DUMMYCPP} "#include <${hpp}>\n") + + # There is no way in CMake to just compile but not link a C++ file, + # so we pretend to build a library here. + add_library(${libname} STATIC ${DUMMYCPP} include/${hpp}) + + #### this is better but only supported from cmake 3.0: + ###add_library(${libname} OBJECT ${DUMMYCPP} include/${hpp}) + + endforeach() +endif() + +install(DIRECTORY include/osmium DESTINATION include) + +# We only have a copy of this file so we can use older boost versions which +# don't have it. We probably don't want to install it. +#install(FILES include/boost_unicode_iterator.hpp DESTINATION include) + + +#----------------------------------------------------------------------------- +# +# Packaging +# +#----------------------------------------------------------------------------- + +set(CPACK_PACKAGE_VERSION_MAJOR ${LIBOSMIUM_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${LIBOSMIUM_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${LIBOSMIUM_VERSION_PATCH}) + +if(WIN32) + set(CPACK_GENERATOR ZIP) +else() + set(CPACK_GENERATOR TGZ) +endif() + +include(CPack) + + +#----------------------------------------------------------------------------- +# +# Print warnings at the end +# +#----------------------------------------------------------------------------- +if(BUILD_DATA_TESTS AND OSM_TESTDATA STREQUAL "OSM_TESTDATA-NOTFOUND") + message("\n========================== WARNING ==========================") + message("osm-testdata directory not found, data tests were disabled!\n") + message("You can get it from https://github.com/osmcode/osm-testdata") + message("Clone it into the same directory libosmium is in") + message("or set the OSM_TESTDATA cmake variable to its path.") + message("=============================================================\n") +endif() + +#----------------------------------------------------------------------------- diff --git a/third_party/libosmium/CONTRIBUTING.md b/third_party/libosmium/CONTRIBUTING.md new file mode 100644 index 000000000..323c84744 --- /dev/null +++ b/third_party/libosmium/CONTRIBUTING.md @@ -0,0 +1,132 @@ + +# Notes for Developers + +Read this if you want to contribute to Libosmium. + + +## Versioning + +Osmium is currently considered in beta and doesn't use versioning yet. Proper +versions will be introduced as soon as it is somewhat stable. + + +## Namespace + +All Osmium code MUST be in the `osmium` namespace or one of its sub-namespaces. + + +## Include-Only + +Osmium is a include-only library. You can't compile the library itself. There +is no libosmium.so. + +One drawback ist that you can't have static data in classes, because there +is no place to put this data. + +All free functions must be declared `inline`. + + +## Coding Conventions + +These coding conventions have been changing over time and some code is still +different. + +* All include files have `#ifdef` guards around them, macros are the path name + in all uppercase where the slashes (`/`) have been changed to underscore (`_`). +* Class names begin with uppercase chars and use CamelCase. Smaller helper + classes are usually defined as struct and have lowercase names. +* Macros (and only macros) are all uppercase. Use macros sparingly, usually + a constexpr is better. +* Variables, attributes, and function names are lowercase with + `underscores_between_words`. +* Class attribute names start with `m_` (member). +* Template parameters are single uppercase letters or start with uppercase `T` + and use CamelCase. +* Typedefs have `names_like_this_type` which end in `_type`. +* Macros should only be used for controlling which parts of the code should be + included when compiling. +* Use `descriptive_variable_names`, exceptions are well-established conventions + like `i` for a loop variable. Iterators are usually called `it`. +* Declare variables where they are first used (C++ style), not at the beginning + of a function (old C style). +* Names from external namespaces (even `std`) are always mentioned explicitly. + Do not use `using` (except for `std::swap`). This way we can't even by + accident pollute the namespace of the code including Osmium. +* `#include` directives appear in three "blocks" after the copyright notice. + The blocks are separated by blank lines. First block contains `#include`s for + standard C/C++ includes, second block for any external libs used, third + block for osmium internal includes. Within each block `#include`s are usually + sorted by path name. All `#include`s use `<>` syntax not `""`. +* Names not to be used from outside the library should be in a namespace + called `detail` under the namespace where they would otherwise appear. If + whole include files are never meant to be included from outside they should + be in a subdirectory called `detail`. +* All files have suffix `.hpp`. +* Closing } of all classes and namespaces should have a trailing comment + with the name of the class/namespace. +* All constructors with one or more arguments should be declared "explicit" + unless there is a reason for them not to be. Document that reason. + +Keep to the indentation and other styles used in the code. Use `make indent` +in the toplevel directory to fix indentation and styling. It calls `astyle` +with the right parameters. This program is in the `astyle` Debian package. + + +## C++11 + +Osmium uses C++11 and you can use its features such as auto, lambdas, +threading, etc. There are a few features we do not use, because even modern +compilers don't support them yet. This list might change as we get more data +about which compilers support which feature and what operating system versions +or distributions have which versions of these compilers installed. + +GCC 4.6 - too old, not supported (Ubuntu 12.04 LTS) +GCC 4.7.2 - can probably not be supported (Debian wheezy/stable) +GCC 4.7.3 - works +GCC 4.8 - works +clang 3.0 - too old, not supported (Debian wheezy/stable, Ubuntu 12.04 LTS) +clang 3.2 - works + +C++11 features you should not use: +* Inherited Constructors (works only in GCC 4.8+ and clang 3.3+, not in Visual + Studio) + + +## Checking your code + +The Osmium makefiles use pretty draconian warning options for the compiler. +This is good. Code MUST never produce any warnings, even with those settings. +If absolutely necessary pragmas can be used to disable certain warnings in +specific areas of the code. + +If the static code checker `cppcheck` is installed, the CMake configuration +will add a new build target `cppcheck` that will check all `.cpp` and `.hpp` +files. Cppcheck finds some bugs that gcc/clang doesn't. But take the result +with a grain of salt, it also sometimes produces wrong warnings. + +Set `BUILD_HEADERS=ON` in the CMake config to enable compiling all include +files on their own to check whether dependencies are all okay. All include +files MUST include all other include files they depend on. + +Call `cmake/iwyu.sh` to check for proper includes and forward declarations. +This uses the clang-based `include-what-you-use` program. Note that it does +produce some false reports and crashes often. The `osmium.imp` file can be +used to define mappings for iwyu. See the IWYU tool at +. + + +## Testing + +There are a unit tests using the Catch Unit Test Framework in the `test` +directory and some data tests in `test/osm-testdata`. They are built by the +default cmake config. Run `ctest` to run them. Many more tests are needed. + + +## Documenting the code + +All namespaces, classes, functions, attributes, etc. should be documented. + +Osmium uses the Doxygen (www.doxygen.org) source code documentation system. +If it is installed, the CMake configuration will add a new build target, so +you can build it with `make doc`. + diff --git a/third_party/osmium/config/constexpr.hpp b/third_party/libosmium/LICENSE.txt similarity index 76% rename from third_party/osmium/config/constexpr.hpp rename to third_party/libosmium/LICENSE.txt index 3eddc84a2..36b7cd93c 100644 --- a/third_party/osmium/config/constexpr.hpp +++ b/third_party/libosmium/LICENSE.txt @@ -1,12 +1,3 @@ -#ifndef OSMIUM_CONFIG_CONSTEXPR_HPP -#define OSMIUM_CONFIG_CONSTEXPR_HPP - -/* - -This file is part of Osmium (http://osmcode.org/libosmium). - -Copyright 2013,2014 Jochen Topf and others (see README). - Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization @@ -30,14 +21,3 @@ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -*/ - -// Workaround for MSVC which doesn't support constexpr in all cases yet -#ifdef _MSC_VER -# define OSMIUM_CONSTEXPR -#else -# define OSMIUM_CONSTEXPR constexpr -#endif - -#endif // OSMIUM_CONFIG_CONSTEXPR_HPP diff --git a/third_party/libosmium/Makefile b/third_party/libosmium/Makefile new file mode 100644 index 000000000..7b2b83d7b --- /dev/null +++ b/third_party/libosmium/Makefile @@ -0,0 +1,25 @@ + +all: + mkdir -p build && cd build && cmake .. && $(MAKE) + +doc: + mkdir -p build && cd build && cmake .. && $(MAKE) doc + +clean: + if test -d build; then cd build && $(MAKE) clean; fi + +distclean: + rm -fr build + +#deb: +# debuild -I -us -uc +# +#deb-clean: +# debuild clean + +indent: + astyle --style=java --indent-namespaces --indent-switches --pad-header --lineend=linux --suffix=none --recursive include/\*.hpp examples/\*.cpp test/\*.cpp +# astyle --style=java --indent-namespaces --indent-switches --pad-header --unpad-paren --align-pointer=type --lineend=linux --suffix=none --recursive include/\*.hpp examples/\*.cpp test/\*.cpp + +.PHONY: clean distclean deb deb-clean doc indent + diff --git a/third_party/libosmium/README.md b/third_party/libosmium/README.md new file mode 100644 index 000000000..503440e8e --- /dev/null +++ b/third_party/libosmium/README.md @@ -0,0 +1,104 @@ +# Libosmium + +http://osmcode.org/libosmium + +A fast and flexible C++ library for working with OpenStreetMap data. + +[![Build Status](https://secure.travis-ci.org/osmcode/libosmium.png)](http://travis-ci.org/osmcode/libosmium) +[![Build status](https://ci.appveyor.com/api/projects/status/mkbg6e6stdgq7c1b?svg=true)](https://ci.appveyor.com/project/Mapbox/libosmium) + +Libosmium is developed on Linux, but also works on OSX and Windows (with some +limitations). + +There are a few applications that use the Osmium library in the examples +directory. See the [osmium-contrib](http://github.com/osmcode/osmium-contrib) +repository for more example code. + +## Prerequisites + +Because Libosmium uses many C++11 features you need a modern compiler and +standard C++ library. Osmium needs at least GCC 4.8 or clang (LLVM) 3.4. +(Some parts may work with older versions.) + +Different parts of Libosmium (and the applications built on top of it) need +different libraries. You DO NOT NEED to install all of them, just install those +you need for your programs. + +For details see the +[list of dependencies](https://github.com/osmcode/libosmium/wiki/Libosmium-dependencies). + + +## Directories + +* benchmarks: Some benchmarks checking different parts of Libosmium. + +* cmake: CMake configuration scripts. + +* doc: Config for documentation. + +* examples: Osmium example applications. + +* include: C/C++ include files. All of Libosmium is in those header files + which are needed for building Osmium applications. + +* test: Tests (see below). + + +## Building + +Osmium is a header-only library, so there is nothing to build for the +library itself. + +But there are some tests and examples that can be build. Libosmium uses +cmake: + + mkdir build + cd build + cmake .. + make + +This will build the examples and tests. Call `ctest` to run the tests. + +For more see the +[Libosmium Wiki](https://github.com/osmcode/libosmium/wiki/Building-Libosmium). + + +## Testing + +See the +[Libosmium Wiki](https://github.com/osmcode/libosmium/wiki/Testing-Libosmium) +for instructions. + + +## Osmium on 32bit Machines + +Osmium works well on 64 bit machines, but on 32 bit machines there are some +problems. Be aware that not everything will work on 32 bit architectures. +This is mostly due to the 64 bit needed for node IDs. Also Osmium hasn't been +tested well on 32 bit systems. Here are some issues you might run into: + +* Google Sparsehash does not work on 32 bit machines in our use case. +* The `mmap` system call is called with a `size_t` argument, so it can't + give you more than 4GByte of memory on 32 bit systems. This might be a + problem. + +Please report any issues you have and we might be able to solve them. + + +## Switching from the old Osmium + +If you have been using the old version of Osmium at +https://github.com/joto/osmium you might want to read about the +[changes needed](https://github.com/osmcode/libosmium/wiki/Changes-from-old-versions-of-Osmium). + + +## License + +Libosmium is available under the Boost Software License. See LICENSE.txt. + + +## Authors + +Libosmium was mainly written and is maintained by Jochen Topf +(jochen@topf.org). See the git commit log for other authors. + diff --git a/third_party/libosmium/appveyor.yml b/third_party/libosmium/appveyor.yml new file mode 100644 index 000000000..06c8e6974 --- /dev/null +++ b/third_party/libosmium/appveyor.yml @@ -0,0 +1,77 @@ +#----------------------------------------------------------------------------- +# +# Configuration for continuous integration service at appveyor.com +# +#----------------------------------------------------------------------------- + +environment: + matrix: + - config: Dev + - config: RelWithDebInfo + +# branches to build +branches: + # whitelist + only: + - master + +# Operating system (build VM template) +os: Visual Studio 2014 CTP4 + +# scripts that are called at very beginning, before repo cloning +init: + +# clone directory +clone_folder: c:\projects\libosmium + +platform: x64 + +install: + # show all availble env vars + - set + - echo cmake on AppVeyor + - cmake -version + - call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 + - set PATH=c:\projects\libosmium\cmake-3.1.0-win32-x86\bin;%PATH% + - set LODEPSDIR=c:\projects\libosmium\libosmium-deps + - set PROJ_LIB=%LODEPSDIR%\proj\share + - set GDAL_DATA=%LODEPSDIR%\gdal\data + #geos.dll + - set PATH=%LODEPSDIR%\geos\lib;%PATH% + #gdal.dll + - set PATH=%LODEPSDIR%\gdal\lib;%PATH% + #libexpat.dll + - set PATH=%LODEPSDIR%\expat\lib;%PATH% + #libtiff.dll + - set PATH=%LODEPSDIR%\libtiff\lib;%PATH% + #zlibwapi.dll + - set PATH=%LODEPSDIR%\zlib\lib;%PATH% + #convert backslashes in bzip2 path to forward slashes + #cmake cannot find it otherwise + - set LIBBZIP2=%LODEPSDIR%\bzip2\lib\libbz2.lib + - set LIBBZIP2=%LIBBZIP2:\=/% + - ps: Start-FileDownload https://mapnik.s3.amazonaws.com/deps/cmake-3.1.0-win32-x86.7z -FileName cm.7z + - ps: Start-FileDownload https://mapnik.s3.amazonaws.com/dist/dev/libosmium-deps-win-14.0-x64.7z -FileName lodeps.7z + - 7z x cm.7z | %windir%\system32\find "ing archive" + - 7z x lodeps.7z | %windir%\system32\find "ing archive" + - echo %LODEPSDIR% + - dir %LODEPSDIR% + - echo our own cmake + - cmake -version + - cd c:\projects + - git clone https://github.com/osmcode/osm-testdata.git + +build_script: + - cd c:\projects\libosmium + - mkdir build + - cd build + - echo %config% + - cmake .. -LA -G "Visual Studio 14 Win64" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBUILD_BENCHMARKS=OFF -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include + - msbuild libosmium.sln /p:Configuration=%config% /toolsversion:14.0 /p:Platform=x64 /p:PlatformToolset=v140 + #- cmake .. -LA -G "NMake Makefiles" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include + #- nmake + +test_script: + # -LE fails_on_windows exempts tests we know will fail + - ctest --output-on-failure -C %config% -LE fails_on_windows + diff --git a/third_party/libosmium/benchmarks/CMakeLists.txt b/third_party/libosmium/benchmarks/CMakeLists.txt new file mode 100644 index 000000000..6a4ca162d --- /dev/null +++ b/third_party/libosmium/benchmarks/CMakeLists.txt @@ -0,0 +1,48 @@ +#----------------------------------------------------------------------------- +# +# CMake Config +# +# Libosmium benchmarks +# +#----------------------------------------------------------------------------- + +message(STATUS "Configuring benchmarks") + +set(BENCHMARKS + count + count_tag + index_map + static_vs_dynamic_index + CACHE STRING "Benchmark programs" +) + + +#----------------------------------------------------------------------------- +# +# Configure benchmarks +# +#----------------------------------------------------------------------------- + +message(STATUS "Configuring benchmarks - Building these benchmarks:") +foreach(benchmark ${BENCHMARKS}) + message(STATUS " - osmium_benchmark_${benchmark}") + add_executable(osmium_benchmark_${benchmark} + "osmium_benchmark_${benchmark}.cpp") + target_link_libraries(osmium_benchmark_${benchmark} + ${OSMIUM_IO_LIBRARIES} + ${BENCHMARK_LIBS_${benchmark}}) + configure_file(run_benchmark_${benchmark}.sh + ${CMAKE_CURRENT_BINARY_DIR}/run_benchmark_${benchmark}.sh + @ONLY) +endforeach() + +foreach(file setup run_benchmarks) + configure_file(${file}.sh ${CMAKE_CURRENT_BINARY_DIR}/${file}.sh @ONLY) +endforeach() + + +#----------------------------------------------------------------------------- +message(STATUS "Configuring benchmarks - done") + + +#----------------------------------------------------------------------------- diff --git a/third_party/libosmium/benchmarks/README.md b/third_party/libosmium/benchmarks/README.md new file mode 100644 index 000000000..f10045ca0 --- /dev/null +++ b/third_party/libosmium/benchmarks/README.md @@ -0,0 +1,41 @@ + +# Benchmarks + +Benchmarks check the performance of different parts of Libosmium. + +## Preparations + +To run the benchmarks first make a directory for the data files somewhere +(outside the repository) and set the `DATA_DIR` environment variable: + + export DATA_DIR=benchmark_data + mkdir $DATA_DIR + +Then copy the OSM files you want to do the benchmarks with into this directory. +You can use the `download_data.sh` script to download a selection of OSM files +in different sizes, but you can use a different selection, too. The benchmarks +will use whatever files you have in the `DATA_DIR` directory. + +The download script will start the data files names with a number in order of +the size of the file from smallest to largest. You can use the same convention +or use a different one. Benchmarks will be run on the files in alphabetical +order. + +The files don't have to be in that directory, you can add soft links from that +directory to the real file locations if that suits you. + +## Compiling the benchmarks + +To build the benchmarks set the `BUILD_BENCHMARKS` option when configuring with +CMake and run the compilation by calling `make` (or whatever build tool you +are using). + +## Running the benchmarks + +Go to the build directory and run `benchmarks/run_benchmarks.sh`. You can also +run each benchmark on its own by calling the respective script in the +`benchmarks` directory. + +Results of the benchmarks will be printed to stdout, you might want to redirect +them into a file. + diff --git a/third_party/libosmium/benchmarks/download_data.sh b/third_party/libosmium/benchmarks/download_data.sh new file mode 100755 index 000000000..8a6a8ff50 --- /dev/null +++ b/third_party/libosmium/benchmarks/download_data.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# download_data.sh +# + +cd $DATA_DIR +curl --location --output 1_liechtenstein.osm.pbf http://download.geofabrik.de/europe/liechtenstein-latest.osm.pbf # about 1 MB +curl --location --output 2_bremen.osm.pbf http://download.geofabrik.de/europe/germany/bremen-latest.osm.pbf # about 13 MB +curl --location --output 3_sachsen.osm.pbf http://download.geofabrik.de/europe/germany/sachsen-latest.osm.pbf # about 120 MB +curl --location --output 4_germany.osm.pbf http://download.geofabrik.de/europe/germany-latest.osm.pbf # about 2 GB +curl --location --output 5_planet.osm.pbf http://planet.osm.org/pbf/planet-latest.osm.pbf # about 26 GB + diff --git a/third_party/libosmium/benchmarks/osmium_benchmark_count.cpp b/third_party/libosmium/benchmarks/osmium_benchmark_count.cpp new file mode 100644 index 000000000..701d6faec --- /dev/null +++ b/third_party/libosmium/benchmarks/osmium_benchmark_count.cpp @@ -0,0 +1,54 @@ +/* + + The code in this file is released into the Public Domain. + +*/ + +#include + +#include +#include +#include + +struct CountHandler : public osmium::handler::Handler { + + int nodes = 0; + int ways = 0; + int relations = 0; + + void node(osmium::Node&) { + ++nodes; + } + + void way(osmium::Way&) { + ++ways; + } + + void relation(osmium::Relation&) { + ++relations; + } + +}; + + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " OSMFILE\n"; + exit(1); + } + + std::string input_filename = argv[1]; + + osmium::io::Reader reader(input_filename); + + CountHandler handler; + osmium::apply(reader, handler); + reader.close(); + + std::cout << "Nodes: " << handler.nodes << "\n"; + std::cout << "Ways: " << handler.ways << "\n"; + std::cout << "Relations: " << handler.relations << "\n"; + + google::protobuf::ShutdownProtobufLibrary(); +} + diff --git a/third_party/libosmium/benchmarks/osmium_benchmark_count_tag.cpp b/third_party/libosmium/benchmarks/osmium_benchmark_count_tag.cpp new file mode 100644 index 000000000..4a77c3452 --- /dev/null +++ b/third_party/libosmium/benchmarks/osmium_benchmark_count_tag.cpp @@ -0,0 +1,55 @@ +/* + + The code in this file is released into the Public Domain. + +*/ + +#include + +#include +#include +#include + +struct CountHandler : public osmium::handler::Handler { + + int counter = 0; + int all = 0; + + void node(osmium::Node& node) { + ++all; + const char* amenity = node.tags().get_value_by_key("amenity"); + if (amenity && !strcmp(amenity, "post_box")) { + ++counter; + } + } + + void way(osmium::Way&) { + ++all; + } + + void relation(osmium::Relation&) { + ++all; + } + +}; + + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " OSMFILE\n"; + exit(1); + } + + std::string input_filename = argv[1]; + + osmium::io::Reader reader(input_filename); + + CountHandler handler; + osmium::apply(reader, handler); + reader.close(); + + std::cout << "r_all=" << handler.all << " r_counter=" << handler.counter << "\n"; + + google::protobuf::ShutdownProtobufLibrary(); +} + diff --git a/third_party/libosmium/benchmarks/osmium_benchmark_index_map.cpp b/third_party/libosmium/benchmarks/osmium_benchmark_index_map.cpp new file mode 100644 index 000000000..fa75fb2b8 --- /dev/null +++ b/third_party/libosmium/benchmarks/osmium_benchmark_index_map.cpp @@ -0,0 +1,41 @@ +/* + + The code in this file is released into the Public Domain. + +*/ + +#include + +#include +#include +#include + +#include +#include + +typedef osmium::index::map::Map index_type; + +typedef osmium::handler::NodeLocationsForWays location_handler_type; + +int main(int argc, char* argv[]) { + if (argc != 3) { + std::cerr << "Usage: " << argv[0] << " OSMFILE FORMAT\n"; + exit(1); + } + + std::string input_filename = argv[1]; + std::string location_store = argv[2]; + + osmium::io::Reader reader(input_filename); + + const auto& map_factory = osmium::index::MapFactory::instance(); + std::unique_ptr index = map_factory.create_map(location_store); + location_handler_type location_handler(*index); + location_handler.ignore_errors(); + + osmium::apply(reader, location_handler); + reader.close(); + + google::protobuf::ShutdownProtobufLibrary(); +} + diff --git a/third_party/libosmium/benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp b/third_party/libosmium/benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp new file mode 100644 index 000000000..9c47c8449 --- /dev/null +++ b/third_party/libosmium/benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp @@ -0,0 +1,136 @@ +/* + + This benchmarks compares the run time for statically vs. dynamically + configured index maps. You can configure index maps at compile-time using + typedefs or at run-time using polymorphism. + + This will read the input file into a buffer and then run the + NodeLocationForWays handler multiple times over the complete data. The + number of runs depends on the size of the input, but is never smaller + than 10. + + Do not run this with very large input files! It will need about 10 times + as much RAM as the file size of the input file. + + The code in this file is released into the Public Domain. + +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +typedef osmium::index::map::SparseMemArray static_index_type; +const std::string location_store="sparse_mem_array"; + +typedef osmium::index::map::Map dynamic_index_type; + +typedef osmium::handler::NodeLocationsForWays static_location_handler_type; +typedef osmium::handler::NodeLocationsForWays dynamic_location_handler_type; + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " OSMFILE\n"; + exit(1); + } + + std::string input_filename = argv[1]; + + osmium::memory::Buffer buffer = osmium::io::read_file(input_filename); + google::protobuf::ShutdownProtobufLibrary(); + + const auto& map_factory = osmium::index::MapFactory::instance(); + + const auto buffer_size = buffer.committed() / (1024*1024); // buffer size in MBytes + const int runs = std::max(10, static_cast(5000ull / buffer_size)); + + std::cout << "input: filename=" << input_filename << " buffer_size=" << buffer_size << "MBytes\n"; + std::cout << "runs: " << runs << "\n"; + + double static_min = std::numeric_limits::max(); + double static_sum = 0; + double static_max = 0; + + double dynamic_min = std::numeric_limits::max(); + double dynamic_sum = 0; + double dynamic_max = 0; + + for (int i = 0; i < runs; ++i) { + + { + // static index + osmium::memory::Buffer tmp_buffer(buffer.committed()); + for (const auto& item : buffer) { + tmp_buffer.add_item(item); + tmp_buffer.commit(); + } + + static_index_type static_index; + static_location_handler_type static_location_handler(static_index); + + auto start = std::chrono::steady_clock::now(); + osmium::apply(tmp_buffer, static_location_handler); + auto end = std::chrono::steady_clock::now(); + + double duration = std::chrono::duration(end-start).count(); + + if (duration < static_min) static_min = duration; + if (duration > static_max) static_max = duration; + static_sum += duration; + } + + { + // dynamic index + osmium::memory::Buffer tmp_buffer(buffer.committed()); + for (const auto& item : buffer) { + tmp_buffer.add_item(item); + tmp_buffer.commit(); + } + + std::unique_ptr index = map_factory.create_map(location_store); + dynamic_location_handler_type dynamic_location_handler(*index); + dynamic_location_handler.ignore_errors(); + + auto start = std::chrono::steady_clock::now(); + osmium::apply(tmp_buffer, dynamic_location_handler); + auto end = std::chrono::steady_clock::now(); + + double duration = std::chrono::duration(end-start).count(); + + if (duration < dynamic_min) dynamic_min = duration; + if (duration > dynamic_max) dynamic_max = duration; + dynamic_sum += duration; + } + } + + double static_avg = static_sum/runs; + double dynamic_avg = dynamic_sum/runs; + + std::cout << "static min=" << static_min << "ms avg=" << static_avg << "ms max=" << static_max << "ms\n"; + std::cout << "dynamic min=" << dynamic_min << "ms avg=" << dynamic_avg << "ms max=" << dynamic_max << "ms\n"; + + double rfactor = 100.0; + double diff_min = std::round((dynamic_min - static_min) * rfactor) / rfactor; + double diff_avg = std::round((dynamic_avg - static_avg) * rfactor) / rfactor; + double diff_max = std::round((dynamic_max - static_max) * rfactor) / rfactor; + + double prfactor = 10.0; + double percent_min = std::round((100.0 * diff_min / static_min) * prfactor) / prfactor; + double percent_avg = std::round((100.0 * diff_avg / static_avg) * prfactor) / prfactor; + double percent_max = std::round((100.0 * diff_max / static_max) * prfactor) / prfactor; + + std::cout << "difference:"; + std::cout << " min=" << diff_min << "ms (" << percent_min << "%)"; + std::cout << " avg=" << diff_avg << "ms (" << percent_avg << "%)"; + std::cout << " max=" << diff_max << "ms (" << percent_max << "%)\n"; +} + diff --git a/third_party/libosmium/benchmarks/run_benchmark_count.sh b/third_party/libosmium/benchmarks/run_benchmark_count.sh new file mode 100755 index 000000000..d71508f76 --- /dev/null +++ b/third_party/libosmium/benchmarks/run_benchmark_count.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# +# run_benchmark_count.sh +# + +set -e + +BENCHMARK_NAME=count + +. @CMAKE_BINARY_DIR@/benchmarks/setup.sh + +CMD=$OB_DIR/osmium_benchmark_$BENCHMARK_NAME + +echo "# file size num mem time cpu_kernel cpu_user cpu_percent cmd options" +for data in $OB_DATA_FILES; do + filename=`basename $data` + filesize=`stat --format="%s" --dereference $data` + for n in $OB_SEQ; do + $OB_TIME_CMD -f "$filename $filesize $n $OB_TIME_FORMAT" $CMD $data 2>&1 >/dev/null | sed -e "s%$DATA_DIR/%%" | sed -e "s%$OB_DIR/%%" + done +done + diff --git a/third_party/libosmium/benchmarks/run_benchmark_count_tag.sh b/third_party/libosmium/benchmarks/run_benchmark_count_tag.sh new file mode 100755 index 000000000..4fa6a1068 --- /dev/null +++ b/third_party/libosmium/benchmarks/run_benchmark_count_tag.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# +# run_benchmark_count_tag.sh +# + +set -e + +BENCHMARK_NAME=count_tag + +. @CMAKE_BINARY_DIR@/benchmarks/setup.sh + +CMD=$OB_DIR/osmium_benchmark_$BENCHMARK_NAME + +echo "# file size num mem time cpu_kernel cpu_user cpu_percent cmd options" +for data in $OB_DATA_FILES; do + filename=`basename $data` + filesize=`stat --format="%s" --dereference $data` + for n in $OB_SEQ; do + $OB_TIME_CMD -f "$filename $filesize $n $OB_TIME_FORMAT" $CMD $data 2>&1 >/dev/null | sed -e "s%$DATA_DIR/%%" | sed -e "s%$OB_DIR/%%" + done +done + diff --git a/third_party/libosmium/benchmarks/run_benchmark_index_map.sh b/third_party/libosmium/benchmarks/run_benchmark_index_map.sh new file mode 100755 index 000000000..30984d460 --- /dev/null +++ b/third_party/libosmium/benchmarks/run_benchmark_index_map.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# +# run_benchmark_index_map.sh +# + +set -e + +BENCHMARK_NAME=index_map + +. @CMAKE_BINARY_DIR@/benchmarks/setup.sh + +CMD=$OB_DIR/osmium_benchmark_$BENCHMARK_NAME + +#MAPS="sparse_mem_map sparse_mem_table sparse_mem_array sparse_mmap_array sparse_file_array dense_mem_array dense_mmap_array dense_file_array" +MAPS="sparse_mem_map sparse_mem_table sparse_mem_array sparse_mmap_array sparse_file_array" + +echo "# file size num mem time cpu_kernel cpu_user cpu_percent cmd options" +for data in $OB_DATA_FILES; do + filename=`basename $data` + filesize=`stat --format="%s" --dereference $data` + for map in $MAPS; do + for n in $OB_SEQ; do + $OB_TIME_CMD -f "$filename $filesize $n $OB_TIME_FORMAT" $CMD $data $map 2>&1 >/dev/null | sed -e "s%$DATA_DIR/%%" | sed -e "s%$OB_DIR/%%" + done + done +done + diff --git a/third_party/libosmium/benchmarks/run_benchmark_static_vs_dynamic_index.sh b/third_party/libosmium/benchmarks/run_benchmark_static_vs_dynamic_index.sh new file mode 100755 index 000000000..05e32f126 --- /dev/null +++ b/third_party/libosmium/benchmarks/run_benchmark_static_vs_dynamic_index.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# +# run_benchmark_static_vs_dynamic_index.sh +# + +set -e + +BENCHMARK_NAME=static_vs_dynamic_index + +. @CMAKE_BINARY_DIR@/benchmarks/setup.sh + +CMD=$OB_DIR/osmium_benchmark_$BENCHMARK_NAME + +for data in $OB_DATA_FILES; do + filesize=`stat --format="%s" --dereference $data` + if [ $filesize -lt 500000000 ]; then + echo "========================" + $CMD $data + fi +done + diff --git a/third_party/libosmium/benchmarks/run_benchmarks.sh b/third_party/libosmium/benchmarks/run_benchmarks.sh new file mode 100755 index 000000000..6a20c0214 --- /dev/null +++ b/third_party/libosmium/benchmarks/run_benchmarks.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# +# run_benchmarks.sh +# +# Run all benchmarks. +# + +set -e + +for benchmark in @CMAKE_BINARY_DIR@/benchmarks/run_benchmark_*.sh; do + name=`basename $benchmark` + echo "Running $name..." + $benchmark +done + diff --git a/third_party/libosmium/benchmarks/setup.sh b/third_party/libosmium/benchmarks/setup.sh new file mode 100755 index 000000000..9733bfe1b --- /dev/null +++ b/third_party/libosmium/benchmarks/setup.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# setup.sh +# + +if [ -z $DATA_DIR ]; then + echo "Please set DATA_DIR environment variable before running benchmark" + exit 1 +fi + +OB_DIR=@CMAKE_BINARY_DIR@/benchmarks + +OB_RUNS=3 +OB_SEQ=`seq -s' ' 1 $OB_RUNS` + +OB_TIME_CMD=/usr/bin/time +OB_TIME_FORMAT="%M %e %S %U %P %C" + +OB_DATA_FILES=`find -L $DATA_DIR -mindepth 1 -maxdepth 1 -type f | sort` + +echo "BENCHMARK: $BENCHMARK_NAME" +echo "---------------------" +echo "CPU:" +grep '^model name' /proc/cpuinfo | tail -1 +grep '^cpu MHz' /proc/cpuinfo | tail -1 +grep '^cpu cores' /proc/cpuinfo | tail -1 +grep '^siblings' /proc/cpuinfo | tail -1 + +echo "---------------------" +echo "MEMORY:" +free +echo "---------------------" +echo "RESULTS:" + diff --git a/third_party/libosmium/cmake/FindGem.cmake b/third_party/libosmium/cmake/FindGem.cmake new file mode 100644 index 000000000..f5389d1e8 --- /dev/null +++ b/third_party/libosmium/cmake/FindGem.cmake @@ -0,0 +1,153 @@ +# Author thomas.roehr@dfki.de +# +# Version 0.3 2013-07-02 +# - rely on `gem content` to find library and header +# - introduce GEM_OS_PKG to allow search via pkgconfig +# Version 0.2 2010-01-14 +# - add support for searching for multiple gems +# Version 0.1 2010-12-15 +# - support basic search functionality +# - tested to find rice +# +# OUTPUT: +# +# GEM_INCLUDE_DIRS After successful search contains the include directores +# +# GEM_LIBRARIES After successful search contains the full path of each found library +# +# +# Usage: +# set(GEM_DEBUG TRUE) +# find_package(Gem COMPONENTS rice hoe) +# include_directories(${GEM_INCLUDE_DIRS}) +# target_link_libraries(${GEM_LIBRARIES} +# +# in case pkg-config should be used to search for the os pkg, set GEM_OS_PKG, i.e. +# set(GEM_OS_PKG TRUE) +# +# Check for how 'gem' should be called +include(FindPackageHandleStandardArgs) +find_program(GEM_EXECUTABLE + NAMES "gem${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}" + "gem${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}" + "gem-${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}" + "gem-${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}" + "gem${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}${RUBY_VERSION_PATCH}" + "gem${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}.${RUBY_VERSION_PATCH}" + "gem-${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}${RUBY_VERSION_PATCH}" + "gem-${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}.${RUBY_VERSION_PATCH}" + "gem") + +# Making backward compatible +if(Gem_DEBUG) + set(GEM_DEBUG TRUE) +endif() + +if(NOT GEM_EXECUTABLE) + MESSAGE(FATAL_ERROR "Could not find the gem executable - install 'gem' first") +endif() + +if(NOT Gem_FIND_COMPONENTS) + MESSAGE(FATAL_ERROR "If searching for a Gem you have to provide COMPONENTS with the name of the gem") +endif() + +foreach(Gem_NAME ${Gem_FIND_COMPONENTS}) + set(GEM_${Gem_NAME}_FOUND TRUE) + list(APPEND components_found_vars GEM_${Gem_NAME}_FOUND) + # If the gem is installed as a gem + if(NOT GEM_OS_PKG) + set(GEM_HOME ENV{GEM_HOME}) + + # Use `gem content ` to extract current information about installed gems + # Store the information into ${GEM_LOCAL_INFO} + EXECUTE_PROCESS(COMMAND ${GEM_EXECUTABLE} content ${Gem_NAME} + RESULT_VARIABLE GEM_RUN_RESULT + OUTPUT_VARIABLE GEM_LOCAL_INFO) + + if(GEM_RUN_RESULT STREQUAL "0") + list(APPEND FOUND_GEMS ${Gem_NAME}) + set(_library_NAME_PATTERN lib${Gem_NAME}.a + lib${Gem_NAME}.so + lib${Gem_NAME}.dylib + ${Gem_NAME}.a + ${Gem_NAME}.so + ${Gem_NAME}.dylib + .*.a + .*.so + .*.dylib + ) + + set(_header_SUFFIX_PATTERN + .h + .hh + .hpp + ) + + # Create a list from the output results of the gem command + string(REPLACE "\n" ";" GEM_CONTENT_LIST "${GEM_LOCAL_INFO}") + foreach(_gem_CONTENT_PATH ${GEM_CONTENT_LIST}) + + # Convert so that only '/' Unix path separator are being using + # needed to do proper regex matching + FILE(TO_CMAKE_PATH ${_gem_CONTENT_PATH} gem_CONTENT_PATH) + + # Identify library -- checking for a library in the gems 'lib' (sub)directory + # Search for an existing library, but only within the gems folder + foreach(_library_NAME ${_library_NAME_PATTERN}) + STRING(REGEX MATCH ".*${Gem_NAME}.*/lib/.*${_library_NAME}$" GEM_PATH_INFO "${gem_CONTENT_PATH}") + if(NOT "${GEM_PATH_INFO}" STREQUAL "") + list(APPEND GEM_LIBRARIES ${GEM_PATH_INFO}) + break() + endif() + endforeach() + + # Identify headers + # Checking for available headers in an include directory + foreach(_header_PATTERN ${_header_SUFFIX_PATTERN}) + STRING(REGEX MATCH ".*${Gem_NAME}.*/include/.*${_header_PATTERN}$" GEM_PATH_INFO "${gem_CONTENT_PATH}") + if(NOT "${GEM_PATH_INFO}" STREQUAL "") + STRING(REGEX REPLACE "(.*${Gem_NAME}.*/include/).*${_header_PATTERN}$" "\\1" GEM_PATH_INFO "${gem_CONTENT_PATH}") + list(APPEND GEM_INCLUDE_DIRS ${GEM_PATH_INFO}) + break() + endif() + endforeach() + endforeach() + else() + set(GEM_${Gem_NAME}_FOUND FALSE) + endif() + else(NOT GEM_OS_PKG) + pkg_check_modules(GEM_PKG ${Gem_NAME}) + set(GEM_${GEM_NAME}_FOUND GEM_PKG_FOUND) + set(GEM_INCLUDE_DIRS ${GEM_PKG_INCLUDE_DIRS}) + set(GEM_LIBRARIES ${GEM_PKG_LIBRARIES} ${GEM_PKG_STATIC_LIBRARIES}) + list(APPEND GEM_LIBRARIES ${GEM_PKG_LDFLAGS} ${GEM_PKG_STATIC_LDFLAGS}) + list(APPEND GEM_LIBRARIES ${GEM_PKG_LDFLAGS_OTHER} ${GEM_PKG_STATIC_LDFLAGS_OTHER}) + + if(GEM_DEBUG) + message(STATUS "GEM_OS_PKG is defined") + message(STATUS "GEM_INCLUDE_DIRS ${GEM_INCLUDE_DIRS}") + message(STATUS "GEM_STATIC_LIBRARY_DIRS ${GEM_PKG_STATIC_LIBRARY_DIRS}") + message(STATUS "GEM_LIBRARY_DIRS ${GEM_PKG_STATIC_LIBRARY_DIRS}") + message(STATUS "GEM_STATIC_LIBRARIES ${GEM_PKG_STATIC_LIBRARIES}") + message(STATUS "GEM_LIBRARIES ${GEM_LIBRARIES}") + endif() + endif() + + if(GEM_DEBUG) + message(STATUS "${Gem_NAME} library dir: ${GEM_LIBRARIES}") + message(STATUS "${Gem_NAME} include dir: ${GEM_INCLUDE_DIRS}") + endif() +endforeach() + +# Compact the lists +if(DEFINED GEM_LIBRARIES) + LIST(REMOVE_DUPLICATES GEM_LIBRARIES) +endif() +if(DEFINED GEM_INCLUDE_DIRS) + LIST(REMOVE_DUPLICATES GEM_INCLUDE_DIRS) +endif() + +find_package_handle_standard_args(GEM + REQUIRED_VARS ${components_found_vars} + FAIL_MESSAGE "Could not find all required gems") + diff --git a/third_party/libosmium/cmake/FindOSMPBF.cmake b/third_party/libosmium/cmake/FindOSMPBF.cmake new file mode 100644 index 000000000..deeebd8b6 --- /dev/null +++ b/third_party/libosmium/cmake/FindOSMPBF.cmake @@ -0,0 +1,50 @@ +# +# Locate OSMPBF library +# +# This module defines +# OSMPBF_FOUND - if false, do not try to link to OSMPBF +# OSMPBF_LIBRARIES - full library path name +# OSMPBF_INCLUDE_DIRS - where to find OSMPBF.hpp +# +# Note that the expected include convention is +# #include +# and not +# #include +# + +find_path(OSMPBF_INCLUDE_DIR osmpbf/osmpbf.h + HINTS $ENV{OSMPBF_DIR} + PATH_SUFFIXES include + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /opt/local # DarwinPorts + /opt +) + +find_library(OSMPBF_LIBRARY + NAMES osmpbf + HINTS $ENV{OSMPBF_DIR} + PATH_SUFFIXES lib64 lib + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /opt/local + /opt +) + +# Handle the QUIETLY and REQUIRED arguments and set OSMPBF_FOUND to TRUE if +# all listed variables are TRUE. +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OSMPBF DEFAULT_MSG OSMPBF_LIBRARY OSMPBF_INCLUDE_DIR) + +# Copy the results to the output variables. +if(OSMPBF_FOUND) + set(OSMPBF_INCLUDE_DIRS ${OSMPBF_INCLUDE_DIR}) + set(OSMPBF_LIBRARIES ${OSMPBF_LIBRARY}) +endif() + diff --git a/third_party/libosmium/cmake/FindOsmium.cmake b/third_party/libosmium/cmake/FindOsmium.cmake new file mode 100644 index 000000000..1de41a022 --- /dev/null +++ b/third_party/libosmium/cmake/FindOsmium.cmake @@ -0,0 +1,340 @@ +#---------------------------------------------------------------------- +# +# FindOsmium.cmake +# +# Find the Libosmium headers and, optionally, several components needed for +# different Libosmium functions. +# +#---------------------------------------------------------------------- +# +# Usage: +# +# Copy this file somewhere into your project directory, where cmake can +# find it. Usually this will be a directory called "cmake" which you can +# add to the CMake module search path with the following line in your +# CMakeLists.txt: +# +# list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +# +# Then add the following in your CMakeLists.txt: +# +# find_package(Osmium REQUIRED COMPONENTS ) +# include_directories(${OSMIUM_INCLUDE_DIRS}) +# +# For the substitute a space separated list of one or more of the +# following components: +# +# pbf - include libraries needed for PBF input and output +# xml - include libraries needed for XML input and output +# io - include libraries needed for any type of input/output +# geos - include if you want to use any of the GEOS functions +# gdal - include if you want to use any of the OGR functions +# proj - include if you want to use any of the Proj.4 functions +# sparsehash - include if you use the sparsehash index +# +# You can check for success with something like this: +# +# if(NOT OSMIUM_FOUND) +# message(WARNING "Libosmium not found!\n") +# endif() +# +#---------------------------------------------------------------------- +# +# Variables: +# +# OSMIUM_FOUND - True if Osmium found. +# OSMIUM_INCLUDE_DIRS - Where to find include files. +# OSMIUM_XML_LIBRARIES - Libraries needed for XML I/O. +# OSMIUM_PBF_LIBRARIES - Libraries needed for PBF I/O. +# OSMIUM_IO_LIBRARIES - Libraries needed for XML or PBF I/O. +# OSMIUM_LIBRARIES - All libraries Osmium uses somewhere. +# +#---------------------------------------------------------------------- + +# Look for the header file. +find_path(OSMIUM_INCLUDE_DIR osmium/osm.hpp + PATH_SUFFIXES include + PATHS + ../libosmium + ../../libosmium + libosmium + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr/ + /opt/local # DarwinPorts + /opt +) + +# Handle the QUIETLY and REQUIRED arguments and set OSMIUM_FOUND to TRUE if +# all listed variables are TRUE. +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OSMIUM REQUIRED_VARS OSMIUM_INCLUDE_DIR) + +# Copy the results to the output variables. +if(OSMIUM_FOUND) + set(OSMIUM_INCLUDE_DIRS ${OSMIUM_INCLUDE_DIR}) +else() + set(OSMIUM_INCLUDE_DIRS "") +endif() + +if(Osmium_FIND_REQUIRED AND NOT OSMIUM_FOUND) + message(FATAL_ERROR "Can not find libosmium headers, please install them or configure the paths") +endif() + +#---------------------------------------------------------------------- +# +# Check for optional components +# +#---------------------------------------------------------------------- +if(Osmium_FIND_COMPONENTS) + foreach(_component ${Osmium_FIND_COMPONENTS}) + string(TOUPPER ${_component} _component_uppercase) + set(Osmium_USE_${_component_uppercase} TRUE) + endforeach() +endif() + +#---------------------------------------------------------------------- +# Component 'io' is an alias for 'pbf' and 'xml' +if(Osmium_USE_IO) + set(Osmium_USE_PBF TRUE) + set(Osmium_USE_XML TRUE) +endif() + +#---------------------------------------------------------------------- +# Component 'ogr' is an alias for 'gdal' +if(Osmium_USE_OGR) + set(Osmium_USE_GDAL TRUE) +endif() + +#---------------------------------------------------------------------- +# Component 'pbf' +if(Osmium_USE_PBF) + find_package(OSMPBF) + find_package(Protobuf) + find_package(ZLIB) + find_package(Threads) + + if(OSMPBF_FOUND AND PROTOBUF_FOUND AND ZLIB_FOUND AND Threads_FOUND) + list(APPEND OSMIUM_PBF_LIBRARIES + ${OSMPBF_LIBRARIES} + ${PROTOBUF_LITE_LIBRARY} + ${ZLIB_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ) + if(WIN32) + list(APPEND OSMIUM_PBF_LIBRARIES ws2_32) + endif() + list(APPEND OSMIUM_INCLUDE_DIRS + ${OSMPBF_INCLUDE_DIRS} + ${PROTOBUF_INCLUDE_DIR} + ${ZLIB_INCLUDE_DIR} + ) + else() + set(_missing_libraries 1) + message(WARNING "Osmium: Can not find some libraries for PBF input/output, please install them or configure the paths.") + endif() +endif() + +#---------------------------------------------------------------------- +# Component 'xml' +if(Osmium_USE_XML) + find_package(EXPAT) + find_package(BZip2) + find_package(ZLIB) + find_package(Threads) + + if(EXPAT_FOUND AND BZIP2_FOUND AND ZLIB_FOUND AND Threads_FOUND) + list(APPEND OSMIUM_XML_LIBRARIES + ${EXPAT_LIBRARIES} + ${BZIP2_LIBRARIES} + ${ZLIB_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ) + list(APPEND OSMIUM_INCLUDE_DIRS + ${EXPAT_INCLUDE_DIR} + ${BZIP2_INCLUDE_DIR} + ${ZLIB_INCLUDE_DIR} + ) + else() + set(_missing_libraries 1) + message(WARNING "Osmium: Can not find some libraries for XML input/output, please install them or configure the paths.") + endif() +endif() + +#---------------------------------------------------------------------- +list(APPEND OSMIUM_IO_LIBRARIES + ${OSMIUM_PBF_LIBRARIES} + ${OSMIUM_XML_LIBRARIES} +) + +list(APPEND OSMIUM_LIBRARIES + ${OSMIUM_IO_LIBRARIES} +) + +#---------------------------------------------------------------------- +# Component 'geos' +if(Osmium_USE_GEOS) + find_path(GEOS_INCLUDE_DIR geos/geom.h) + find_library(GEOS_LIBRARY NAMES geos) + + if(GEOS_INCLUDE_DIR AND GEOS_LIBRARY) + SET(GEOS_FOUND 1) + list(APPEND OSMIUM_LIBRARIES ${GEOS_LIBRARY}) + list(APPEND OSMIUM_INCLUDE_DIRS ${GEOS_INCLUDE_DIR}) + else() + set(_missing_libraries 1) + message(WARNING "Osmium: GEOS library is required but not found, please install it or configure the paths.") + endif() +endif() + +#---------------------------------------------------------------------- +# Component 'gdal' (alias 'ogr') +if(Osmium_USE_GDAL) + find_package(GDAL) + + if(GDAL_FOUND) + list(APPEND OSMIUM_LIBRARIES ${GDAL_LIBRARIES}) + list(APPEND OSMIUM_INCLUDE_DIRS ${GDAL_INCLUDE_DIRS}) + else() + set(_missing_libraries 1) + message(WARNING "Osmium: GDAL library is required but not found, please install it or configure the paths.") + endif() +endif() + +#---------------------------------------------------------------------- +# Component 'proj' +if(Osmium_USE_PROJ) + find_path(PROJ_INCLUDE_DIR proj_api.h) + find_library(PROJ_LIBRARY NAMES proj) + + if(PROJ_INCLUDE_DIR AND PROJ_LIBRARY) + set(PROJ_FOUND 1) + list(APPEND OSMIUM_LIBRARIES ${PROJ_LIBRARY}) + list(APPEND OSMIUM_INCLUDE_DIRS ${PROJ_INCLUDE_DIR}) + else() + set(_missing_libraries 1) + message(WARNING "Osmium: PROJ.4 library is required but not found, please install it or configure the paths.") + endif() +endif() + +#---------------------------------------------------------------------- +# Component 'sparsehash' +if(Osmium_USE_SPARSEHASH) + find_path(SPARSEHASH_INCLUDE_DIR google/sparsetable) + + if(SPARSEHASH_INCLUDE_DIR) + # Find size of sparsetable::size_type. This does not work on older + # CMake versions because they can do this check only in C, not in C++. + include(CheckTypeSize) + set(CMAKE_REQUIRED_INCLUDES ${SPARSEHASH_INCLUDE_DIR}) + set(CMAKE_EXTRA_INCLUDE_FILES "google/sparsetable") + check_type_size("google::sparsetable::size_type" SPARSETABLE_SIZE_TYPE LANGUAGE CXX) + set(CMAKE_EXTRA_INCLUDE_FILES) + set(CMAKE_REQUIRED_INCLUDES) + + # Falling back to checking size_t if google::sparsetable::size_type + # could not be checked. + if(SPARSETABLE_SIZE_TYPE STREQUAL "") + check_type_size("void*" VOID_PTR_SIZE) + set(SPARSETABLE_SIZE_TYPE ${VOID_PTR_SIZE}) + endif() + + # Sparsetable::size_type must be at least 8 bytes (64bit), otherwise + # OSM object IDs will not fit. + if(SPARSETABLE_SIZE_TYPE GREATER 7) + set(SPARSEHASH_FOUND 1) + add_definitions(-DOSMIUM_WITH_SPARSEHASH=${SPARSEHASH_FOUND}) + list(APPEND OSMIUM_INCLUDE_DIRS ${SPARSEHASH_INCLUDE_DIR}) + else() + message(WARNING "Osmium: Disabled Google SparseHash library on 32bit system (size_type=${SPARSETABLE_SIZE_TYPE}).") + endif() + else() + set(_missing_libraries 1) + message(WARNING "Osmium: Google SparseHash library is required but not found, please install it or configure the paths.") + endif() +endif() + +#---------------------------------------------------------------------- + +list(REMOVE_DUPLICATES OSMIUM_INCLUDE_DIRS) + +if(OSMIUM_XML_LIBRARIES) + list(REMOVE_DUPLICATES OSMIUM_XML_LIBRARIES) +endif() + +if(OSMIUM_PBF_LIBRARIES) + list(REMOVE_DUPLICATES OSMIUM_PBF_LIBRARIES) +endif() + +if(OSMIUM_IO_LIBRARIES) + list(REMOVE_DUPLICATES OSMIUM_IO_LIBRARIES) +endif() + +if(OSMIUM_LIBRARIES) + list(REMOVE_DUPLICATES OSMIUM_LIBRARIES) +endif() + +#---------------------------------------------------------------------- +# +# Check that all required libraries are available +# +#---------------------------------------------------------------------- +if(Osmium_FIND_REQUIRED AND _missing_libraries) + message(FATAL_ERROR "Required library or libraries missing. Aborting.") +endif() + +#---------------------------------------------------------------------- +# +# Add compiler flags +# +#---------------------------------------------------------------------- +add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64) + +if(MSVC) + add_definitions(-wd4996) + + # Disable warning C4068: "unknown pragma" because we want it to ignore + # pragmas for other compilers. + add_definitions(-wd4068) + + # Disable warning C4715: "not all control paths return a value" because + # it generates too many false positives. + add_definitions(-wd4715) + + # Disable warning C4351: new behavior: elements of array '...' will be + # default initialized. The new behaviour is correct and we don't support + # old compilers anyway. + add_definitions(-wd4351) + + add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS) +endif() + +if(APPLE) +# following only available from cmake 2.8.12: +# add_compile_options(-stdlib=libc++) +# so using this instead: + add_definitions(-stdlib=libc++) + set(LDFLAGS ${LDFLAGS} -stdlib=libc++) +endif() + +#---------------------------------------------------------------------- + +# This is a set of recommended warning options that can be added when compiling +# libosmium code. +if(MSVC) + set(OSMIUM_WARNING_OPTIONS "/W3 /wd4514" CACHE STRING "Recommended warning options for libosmium") +else() + set(OSMIUM_WARNING_OPTIONS "-Wall -Wextra -pedantic -Wredundant-decls -Wdisabled-optimization -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo -Wold-style-cast -Wno-return-type" CACHE STRING "Recommended warning options for libosmium") +endif() + +set(OSMIUM_DRACONIC_CLANG_OPTIONS "-Wdocumentation -Wunused-exception-parameter -Wmissing-declarations -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-unused-macros -Wno-exit-time-destructors -Wno-global-constructors -Wno-padded -Wno-switch-enum -Wno-missing-prototypes -Wno-weak-vtables -Wno-cast-align -Wno-float-equal") + +if(Osmium_DEBUG) + message(STATUS "OSMIUM_XML_LIBRARIES=" ${OSMIUM_XML_LIBRARIES}) + message(STATUS "OSMIUM_PBF_LIBRARIES=" ${OSMIUM_PBF_LIBRARIES}) + message(STATUS "OSMIUM_IO_LIBRARIES=" ${OSMIUM_IO_LIBRARIES}) + message(STATUS "OSMIUM_LIBRARIES=" ${OSMIUM_LIBRARIES}) + message(STATUS "OSMIUM_INCLUDE_DIRS=" ${OSMIUM_INCLUDE_DIRS}) +endif() + diff --git a/third_party/libosmium/cmake/README b/third_party/libosmium/cmake/README new file mode 100644 index 000000000..4a035f7b2 --- /dev/null +++ b/third_party/libosmium/cmake/README @@ -0,0 +1,3 @@ + +FindGem.cmake from https://github.com/rock-core/base-cmake + diff --git a/third_party/libosmium/cmake/build.bat b/third_party/libosmium/cmake/build.bat new file mode 100644 index 000000000..5ffab124e --- /dev/null +++ b/third_party/libosmium/cmake/build.bat @@ -0,0 +1,15 @@ +call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64 +set CMAKE_PREFIX_PATH=C:\PROJ +set VERSION=Debug +set TESTS=ON +set ALLHPPS=ON +set PREFIX=d:\libs18d +set BOOST_ROOT=d:\boost + +cmake .. -G "Visual Studio 12 Win64" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=%PREFIX% -DBOOST_ROOT=%BOOST_ROOT% -DBoost_USE_STATIC_LIBS=ON -DBUILD_TESTING=%TESTS% -DBUILD_TRY_HPPS=%ALLHPPS$ -T CTP_Nov2013 +msbuild /clp:Verbosity=minimal /nologo libosmium.sln /flp1:logfile=build_errors.txt;errorsonly /flp2:logfile=build_warnings.txt;warningsonly +set PATH=%PATH%;%PREFIX%/bin + +del test\osm-testdata\*.db +del test\osm-testdata\*.json +if "%TESTS%"=="ON" ctest -VV >build_tests.log diff --git a/third_party/libosmium/cmake/iwyu.sh b/third_party/libosmium/cmake/iwyu.sh new file mode 100755 index 000000000..d20384491 --- /dev/null +++ b/third_party/libosmium/cmake/iwyu.sh @@ -0,0 +1,43 @@ +#!/bin/sh +# +# This will run IWYU (Include What You Use) on includes files. The iwyu +# program isn't very reliable and crashes often, but is still useful. +# +# TODO: This script should be integrated with cmake in some way... +# + +cmdline="iwyu -Xiwyu --mapping_file=osmium.imp -std=c++11 -I include" + +log=build/iwyu.log + +echo "INCLUDE WHAT YOU USE REPORT:" >$log + +allok=yes + +mkdir -p build/check_reports + +for file in `find include/osmium -name \*.hpp`; do + mkdir -p `dirname build/check_reports/$file` + ifile="build/check_reports/${file%.hpp}.iwyu" + $cmdline $file >$ifile 2>&1 + if grep -q 'has correct #includes/fwd-decls' ${ifile}; then + echo "\n\033[1m\033[32m========\033[0m \033[1m${file}\033[0m" >>$log + echo "[OK] ${file}" + elif grep -q 'Assertion failed' ${ifile}; then + echo "\n\033[1m======== ${file}\033[0m" >>$log + echo "[--] ${file}" + allok=no + else + echo "\n\033[1m\033[31m========\033[0m \033[1m${file}\033[0m" >>$log + echo "[ ] ${file}" + allok=no + fi + cat $ifile >>$log +done + +if [ "$allok" = "yes" ]; then + echo "All files OK" +else + echo "There were errors" +fi + diff --git a/third_party/libosmium/doc/CMakeLists.txt b/third_party/libosmium/doc/CMakeLists.txt new file mode 100644 index 000000000..9d69a16bd --- /dev/null +++ b/third_party/libosmium/doc/CMakeLists.txt @@ -0,0 +1,35 @@ +#----------------------------------------------------------------------------- +# +# CMake Config +# +# Libosmium documentation +# +#----------------------------------------------------------------------------- + +message(STATUS "Configuring documentation") + +message(STATUS "Looking for doxygen") +find_package(Doxygen) + +if(DOXYGEN_FOUND) + message(STATUS "Looking for doxygen - found") + configure_file(header.html ${CMAKE_CURRENT_BINARY_DIR}/header.html @ONLY) + configure_file(Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) + add_custom_target(doc + ${DOXYGEN_EXECUTABLE} + ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" VERBATIM + ) +# install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html" +# DESTINATION "share/doc/libosmium-dev") +else() + message(STATUS "Looking for doxygen - not found") + message(STATUS " Disabled making of documentation.") +endif() + +#----------------------------------------------------------------------------- +message(STATUS "Configuring documentation - done") + + +#----------------------------------------------------------------------------- diff --git a/third_party/libosmium/doc/Doxyfile.in b/third_party/libosmium/doc/Doxyfile.in new file mode 100644 index 000000000..c03e255e9 --- /dev/null +++ b/third_party/libosmium/doc/Doxyfile.in @@ -0,0 +1,2313 @@ +# Doxyfile 1.8.7 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "Libosmium" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = @LIBOSMIUM_VERSION@ + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "Fast and flexible C++ library for working with OpenStreetMap data" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = "@PROJECT_BINARY_DIR@/doc" + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@/include + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = @PROJECT_SOURCE_DIR@/include/osmium \ + @PROJECT_SOURCE_DIR@/doc/doc.txt + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.hpp + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = detail + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = *::detail + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = "grep -v static_assert" + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = YES + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = NO + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = header.html + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = "@PROJECT_SOURCE_DIR@/doc/osmium.css" + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NONE + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /