Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d86eaa00a0 | |||
| 54c0d50b68 | |||
| 204189c326 | |||
| acdfa546a8 | |||
| 6a9216d6e4 | |||
| 9c2a1dc37f | |||
| 26c9d357f0 | |||
| 879d73c629 | |||
| 441146eeae | |||
| d453cadc8c | |||
| 74188206e8 | |||
| 700206099b | |||
| aa952df541 | |||
| b8944da9dc | |||
| 22dda2b285 | |||
| 0ee469c4e0 | |||
| a7eef27e99 | |||
| 4b40f1253f | |||
| 5ebe8080f9 | |||
| d92b28d2c3 | |||
| ec27881f39 | |||
| c5a8ec7c31 | |||
| afbd3347da | |||
| 41bcafc3a1 | |||
| 27d24885a9 | |||
| 805402b230 | |||
| 4918549bac | |||
| 784f417857 | |||
| 0bc3e098ac | |||
| dfd3a5d554 | |||
| 9dcc472c60 | |||
| c972e2cf41 | |||
| de9ab83cea | |||
| 174e388e2d | |||
| ee41fb45b7 | |||
| 93892b9806 | |||
| 749d83a69f | |||
| 8b109904c8 |
@@ -1,54 +0,0 @@
|
|||||||
---
|
|
||||||
Language: Cpp
|
|
||||||
# BasedOnStyle: LLVM
|
|
||||||
AccessModifierOffset: -2
|
|
||||||
ConstructorInitializerIndentWidth: 4
|
|
||||||
AlignEscapedNewlinesLeft: false
|
|
||||||
AlignTrailingComments: true
|
|
||||||
AllowAllParametersOfDeclarationOnNextLine: true
|
|
||||||
AllowShortIfStatementsOnASingleLine: false
|
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
||||||
AllowShortFunctionsOnASingleLine: true
|
|
||||||
AlwaysBreakTemplateDeclarations: false
|
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
|
||||||
BreakBeforeBinaryOperators: false
|
|
||||||
BreakBeforeTernaryOperators: true
|
|
||||||
BreakConstructorInitializersBeforeComma: false
|
|
||||||
BinPackParameters: false
|
|
||||||
ColumnLimit: 100
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
|
||||||
DerivePointerBinding: false
|
|
||||||
ExperimentalAutoDetectBinPacking: false
|
|
||||||
IndentCaseLabels: false
|
|
||||||
MaxEmptyLinesToKeep: 1
|
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
|
||||||
NamespaceIndentation: None
|
|
||||||
ObjCSpaceAfterProperty: false
|
|
||||||
ObjCSpaceBeforeProtocolList: true
|
|
||||||
PenaltyBreakBeforeFirstCallParameter: 19
|
|
||||||
PenaltyBreakComment: 300
|
|
||||||
PenaltyBreakString: 1000
|
|
||||||
PenaltyBreakFirstLessLess: 120
|
|
||||||
PenaltyExcessCharacter: 1000
|
|
||||||
PenaltyReturnTypeOnItsOwnLine: 60
|
|
||||||
PointerBindsToType: false
|
|
||||||
SpacesBeforeTrailingComments: 1
|
|
||||||
Cpp11BracedListStyle: true
|
|
||||||
Standard: Cpp11
|
|
||||||
IndentWidth: 4
|
|
||||||
TabWidth: 8
|
|
||||||
UseTab: Never
|
|
||||||
BreakBeforeBraces: Allman
|
|
||||||
IndentFunctionDeclarationAfterType: false
|
|
||||||
SpacesInParentheses: false
|
|
||||||
SpacesInAngles: false
|
|
||||||
SpaceInEmptyParentheses: false
|
|
||||||
SpacesInCStyleCastParentheses: false
|
|
||||||
SpacesInContainerLiterals: true
|
|
||||||
SpaceBeforeAssignmentOperators: true
|
|
||||||
ContinuationIndentWidth: 4
|
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
|
||||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
|
||||||
SpaceBeforeParens: ControlStatements
|
|
||||||
...
|
|
||||||
|
|
||||||
@@ -1,78 +1,2 @@
|
|||||||
# Compiled source #
|
/.settings
|
||||||
###################
|
/.project
|
||||||
*.com
|
|
||||||
*.class
|
|
||||||
*.dll
|
|
||||||
*.exe
|
|
||||||
*.o
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Packages #
|
|
||||||
############
|
|
||||||
# it's better to unpack these files and commit the raw source
|
|
||||||
# git has its own built in compression methods
|
|
||||||
*.7z
|
|
||||||
*.dmg
|
|
||||||
*.gz
|
|
||||||
*.iso
|
|
||||||
*.jar
|
|
||||||
*.rar
|
|
||||||
*.tar
|
|
||||||
*.zip
|
|
||||||
|
|
||||||
# Logs and databases #
|
|
||||||
######################
|
|
||||||
*.log
|
|
||||||
*.sql
|
|
||||||
*.sqlite
|
|
||||||
|
|
||||||
# OS generated files #
|
|
||||||
######################
|
|
||||||
.DS_Store
|
|
||||||
ehthumbs.db
|
|
||||||
Icon?
|
|
||||||
Thumbs.db
|
|
||||||
|
|
||||||
# build related files #
|
|
||||||
#######################
|
|
||||||
/build/
|
|
||||||
/util/fingerprint_impl.hpp
|
|
||||||
/util/git_sha.cpp
|
|
||||||
/cmake/postinst
|
|
||||||
|
|
||||||
# Eclipse related files #
|
|
||||||
#########################
|
|
||||||
.setting*
|
|
||||||
.scb
|
|
||||||
.cproject
|
|
||||||
.project
|
|
||||||
|
|
||||||
# stxxl related files #
|
|
||||||
#######################
|
|
||||||
.stxxl
|
|
||||||
stxxl.log
|
|
||||||
stxxl.errlog
|
|
||||||
|
|
||||||
# Compiled Binary Files #
|
|
||||||
####################################
|
|
||||||
/osrm-extract
|
|
||||||
/osrm-io-benchmark
|
|
||||||
/osrm-components
|
|
||||||
/osrm-routed
|
|
||||||
/osrm-datastore
|
|
||||||
/osrm-prepare
|
|
||||||
/osrm-unlock-all
|
|
||||||
/osrm-cli
|
|
||||||
/osrm-check-hsgr
|
|
||||||
/osrm-springclean
|
|
||||||
/nohup.out
|
|
||||||
|
|
||||||
# Sandbox folder #
|
|
||||||
###################
|
|
||||||
/sandbox/
|
|
||||||
|
|
||||||
/test/profile.lua
|
|
||||||
|
|
||||||
# Deprecated config file #
|
|
||||||
##########################
|
|
||||||
/server.ini
|
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
language: cpp
|
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
# - clang
|
|
||||||
# Make sure CMake is installed
|
|
||||||
install:
|
|
||||||
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
|
|
||||||
- sudo add-apt-repository -y ppa:boost-latest/ppa
|
|
||||||
- sudo apt-get update >/dev/null
|
|
||||||
- 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
|
|
||||||
- curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
|
|
||||||
# cmake
|
|
||||||
- curl -s https://gist.githubusercontent.com/DennisOSRM/5fad9bee5c7f09fd7fc9/raw/ | sudo bash
|
|
||||||
# osmpbf library
|
|
||||||
- curl -s https://gist.githubusercontent.com/DennisOSRM/13b1b4fe38a57ead850e/raw/install_osmpbf.sh | sudo bash
|
|
||||||
before_script:
|
|
||||||
- rvm use 1.9.3
|
|
||||||
- gem install bundler
|
|
||||||
- bundle install
|
|
||||||
- mkdir build
|
|
||||||
- cd build
|
|
||||||
- cmake .. $CMAKEOPTIONS -DBUILD_TOOLS=1
|
|
||||||
script:
|
|
||||||
- make
|
|
||||||
- make tests
|
|
||||||
- make benchmarks
|
|
||||||
- ./datastructure-tests
|
|
||||||
- cd ..
|
|
||||||
- cucumber -p verify
|
|
||||||
after_script:
|
|
||||||
# - cd ..
|
|
||||||
# - cucumber -p verify
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
- develop
|
|
||||||
cache:
|
|
||||||
- bundler
|
|
||||||
- apt
|
|
||||||
env:
|
|
||||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5000 OSRM_TIMEOUT=60
|
|
||||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5010 OSRM_TIMEOUT=60
|
|
||||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5020 OSRM_TIMEOUT=60
|
|
||||||
notifications:
|
|
||||||
slack: mapbox:4A6euphDwfxAQnhLurXbu6A1
|
|
||||||
irc:
|
|
||||||
channels:
|
|
||||||
- irc.oftc.net#osrm
|
|
||||||
on_success: change
|
|
||||||
on_failure: always
|
|
||||||
use_notice: true
|
|
||||||
skip_join: false
|
|
||||||
|
|
||||||
recipients:
|
|
||||||
- dennis@mapbox.com
|
|
||||||
email:
|
|
||||||
on_success: change
|
|
||||||
on_failure: always
|
|
||||||
@@ -1,378 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.8)
|
|
||||||
|
|
||||||
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 C CXX)
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
||||||
include(CheckCXXCompilerFlag)
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
|
||||||
include(GetGitRevisionDescription)
|
|
||||||
git_describe(GIT_DESCRIPTION)
|
|
||||||
|
|
||||||
set(bitness 32)
|
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
set(bitness 64)
|
|
||||||
message(STATUS "Building on a 64 bit system")
|
|
||||||
else()
|
|
||||||
message(WARNING "Building on a 32 bit system is unsupported")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
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(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_CURRENT_SOURCE_DIR}/include/)
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/)
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include/)
|
|
||||||
|
|
||||||
add_custom_target(FingerPrintConfigure ALL
|
|
||||||
${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
|
||||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake
|
|
||||||
COMMENT "Configuring revision fingerprint"
|
|
||||||
VERBATIM)
|
|
||||||
|
|
||||||
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_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(PHANTOMNODE OBJECT data_structures/phantom_node.cpp)
|
|
||||||
add_library(EXCEPTION OBJECT util/osrm_exception.cpp)
|
|
||||||
add_library(MERCATOR OBJECT util/mercator.cpp)
|
|
||||||
add_library(ANGLE OBJECT util/compute_angle.cpp)
|
|
||||||
|
|
||||||
set(ExtractorSources extract.cpp ${ExtractorGlob})
|
|
||||||
add_executable(osrm-extract ${ExtractorSources} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
|
||||||
|
|
||||||
add_library(RESTRICTION OBJECT data_structures/restriction_map.cpp)
|
|
||||||
|
|
||||||
file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp {RestrictionMapGlob})
|
|
||||||
set(PrepareSources prepare.cpp ${PrepareGlob})
|
|
||||||
add_executable(osrm-prepare ${PrepareSources} $<TARGET_OBJECTS:ANGLE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
|
||||||
|
|
||||||
file(GLOB ServerGlob server/*.cpp)
|
|
||||||
file(GLOB DescriptorGlob descriptors/*.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 AlgorithmGlob algorithms/*.cpp)
|
|
||||||
file(GLOB HttpGlob server/http/*.cpp)
|
|
||||||
file(GLOB LibOSRMGlob library/*.cpp)
|
|
||||||
file(GLOB DataStructureTestsGlob unit_tests/data_structures/*.cpp data_structures/hilbert_value.cpp)
|
|
||||||
file(GLOB AlgorithmTestsGlob unit_tests/algorithms/*.cpp)
|
|
||||||
|
|
||||||
set(
|
|
||||||
OSRMSources
|
|
||||||
${LibOSRMGlob}
|
|
||||||
${DescriptorGlob}
|
|
||||||
${DatastructureGlob}
|
|
||||||
${AlgorithmGlob}
|
|
||||||
${HttpGlob}
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(COORDINATE OBJECT ${CoordinateGlob})
|
|
||||||
add_library(GITDESCRIPTION OBJECT util/git_sha.cpp)
|
|
||||||
add_library(OSRM ${OSRMSources} $<TARGET_OBJECTS:ANGLE> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
|
||||||
|
|
||||||
add_library(FINGERPRINT OBJECT util/fingerprint.cpp)
|
|
||||||
add_dependencies(FINGERPRINT FingerPrintConfigure)
|
|
||||||
add_dependencies(OSRM FingerPrintConfigure)
|
|
||||||
set_target_properties(FINGERPRINT PROPERTIES LINKER_LANGUAGE CXX)
|
|
||||||
|
|
||||||
add_executable(osrm-routed routed.cpp ${ServerGlob} $<TARGET_OBJECTS:EXCEPTION>)
|
|
||||||
add_executable(osrm-datastore datastore.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
|
||||||
|
|
||||||
# Unit tests
|
|
||||||
add_executable(datastructure-tests EXCLUDE_FROM_ALL unit_tests/datastructure_tests.cpp ${DataStructureTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
|
||||||
add_executable(algorithm-tests EXCLUDE_FROM_ALL unit_tests/algorithm_tests.cpp ${AlgorithmTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION>)
|
|
||||||
|
|
||||||
# Benchmarks
|
|
||||||
add_executable(rtree-bench EXCLUDE_FROM_ALL benchmarks/static_rtree.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
|
||||||
|
|
||||||
# Check the release mode
|
|
||||||
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
|
||||||
set(CMAKE_BUILD_TYPE Release)
|
|
||||||
endif()
|
|
||||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
|
||||||
message(STATUS "Configuring OSRM in debug mode")
|
|
||||||
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")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
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" 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
|
|
||||||
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()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT WIN32)
|
|
||||||
add_definitions(-DBOOST_TEST_DYN_LINK)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Configuring compilers
|
|
||||||
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")
|
|
||||||
set(COLOR_FLAG "-fdiagnostics-color=auto")
|
|
||||||
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
|
|
||||||
add_definitions(-D_USE_MATH_DEFINES) # define M_PI, M_1_PI etc.
|
|
||||||
add_definitions(-DWIN32)
|
|
||||||
set(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
|
|
||||||
endif()
|
|
||||||
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")
|
|
||||||
# using Visual Studio C++
|
|
||||||
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} date_time chrono zlib)
|
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
|
||||||
add_definitions(-DNOMINMAX) # avoid min and max macros that can break compilation
|
|
||||||
add_definitions(-D_USE_MATH_DEFINES) # define M_PI
|
|
||||||
add_definitions(-D_WIN32_WINNT=0x0501)
|
|
||||||
add_definitions(-DXML_STATIC)
|
|
||||||
find_library(ws2_32_LIBRARY_PATH ws2_32)
|
|
||||||
target_link_libraries(osrm-extract wsock32 ws2_32)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Activate 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
|
|
||||||
if(APPLE)
|
|
||||||
set(CMAKE_OSX_ARCHITECTURES "x86_64")
|
|
||||||
message(STATUS "Set Architecture to x64 on OS X")
|
|
||||||
exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
|
|
||||||
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
|
|
||||||
if(OSXLIBSTD)
|
|
||||||
message(STATUS "linking against ${OSXLIBSTD}")
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}")
|
|
||||||
elseif(DARWIN_VERSION GREATER 12)
|
|
||||||
message(STATUS "linking against libc++")
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
|
||||||
target_link_libraries(osrm-prepare rt)
|
|
||||||
target_link_libraries(osrm-datastore rt)
|
|
||||||
target_link_libraries(OSRM rt)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#Check Boost
|
|
||||||
set(BOOST_MIN_VERSION "1.49.0")
|
|
||||||
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED)
|
|
||||||
if(NOT Boost_FOUND)
|
|
||||||
message(FATAL_ERROR "Fatal error: Boost (version >= 1.49.0) required.\n")
|
|
||||||
endif()
|
|
||||||
include_directories(${Boost_INCLUDE_DIRS})
|
|
||||||
|
|
||||||
target_link_libraries(OSRM ${Boost_LIBRARIES})
|
|
||||||
target_link_libraries(osrm-extract ${Boost_LIBRARIES})
|
|
||||||
target_link_libraries(osrm-prepare ${Boost_LIBRARIES})
|
|
||||||
target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
|
|
||||||
target_link_libraries(osrm-datastore ${Boost_LIBRARIES})
|
|
||||||
target_link_libraries(datastructure-tests ${Boost_LIBRARIES})
|
|
||||||
target_link_libraries(algorithm-tests ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
|
|
||||||
target_link_libraries(rtree-bench ${Boost_LIBRARIES})
|
|
||||||
|
|
||||||
find_package(Threads REQUIRED)
|
|
||||||
target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT})
|
|
||||||
target_link_libraries(osrm-datastore ${CMAKE_THREAD_LIBS_INIT})
|
|
||||||
target_link_libraries(osrm-prepare ${CMAKE_THREAD_LIBS_INIT})
|
|
||||||
target_link_libraries(OSRM ${CMAKE_THREAD_LIBS_INIT})
|
|
||||||
target_link_libraries(datastructure-tests ${CMAKE_THREAD_LIBS_INIT})
|
|
||||||
target_link_libraries(algorithm-tests ${CMAKE_THREAD_LIBS_INIT})
|
|
||||||
target_link_libraries(rtree-bench ${CMAKE_THREAD_LIBS_INIT})
|
|
||||||
|
|
||||||
find_package(TBB REQUIRED)
|
|
||||||
if(WIN32 AND CMAKE_BUILD_TYPE MATCHES Debug)
|
|
||||||
set(TBB_LIBRARIES ${TBB_DEBUG_LIBRARIES})
|
|
||||||
endif()
|
|
||||||
target_link_libraries(osrm-datastore ${TBB_LIBRARIES})
|
|
||||||
target_link_libraries(osrm-extract ${TBB_LIBRARIES})
|
|
||||||
target_link_libraries(osrm-prepare ${TBB_LIBRARIES})
|
|
||||||
target_link_libraries(osrm-routed ${TBB_LIBRARIES})
|
|
||||||
target_link_libraries(datastructure-tests ${TBB_LIBRARIES})
|
|
||||||
target_link_libraries(algorithm-tests ${TBB_LIBRARIES})
|
|
||||||
target_link_libraries(rtree-bench ${TBB_LIBRARIES})
|
|
||||||
include_directories(${TBB_INCLUDE_DIR})
|
|
||||||
|
|
||||||
find_package( Luabind REQUIRED )
|
|
||||||
include(check_luabind)
|
|
||||||
|
|
||||||
include_directories(${LUABIND_INCLUDE_DIR})
|
|
||||||
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
|
|
||||||
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
|
|
||||||
|
|
||||||
if(LUAJIT_FOUND)
|
|
||||||
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
|
|
||||||
target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES})
|
|
||||||
else()
|
|
||||||
target_link_libraries(osrm-extract ${LUA_LIBRARY})
|
|
||||||
target_link_libraries(osrm-prepare ${LUA_LIBRARY})
|
|
||||||
endif()
|
|
||||||
include_directories(${LUA_INCLUDE_DIR})
|
|
||||||
|
|
||||||
find_package(EXPAT REQUIRED)
|
|
||||||
include_directories(${EXPAT_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(osrm-extract ${EXPAT_LIBRARIES})
|
|
||||||
|
|
||||||
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})
|
|
||||||
|
|
||||||
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)
|
|
||||||
include_directories(${OSMPBF_INCLUDE_DIR})
|
|
||||||
target_link_libraries(osrm-extract ${OSMPBF_LIBRARY})
|
|
||||||
target_link_libraries(osrm-prepare ${OSMPBF_LIBRARY})
|
|
||||||
|
|
||||||
find_package(Protobuf REQUIRED)
|
|
||||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(osrm-extract ${PROTOBUF_LIBRARY})
|
|
||||||
target_link_libraries(osrm-prepare ${PROTOBUF_LIBRARY})
|
|
||||||
|
|
||||||
find_package(BZip2 REQUIRED)
|
|
||||||
include_directories(${BZIP_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(osrm-extract ${BZIP2_LIBRARIES})
|
|
||||||
|
|
||||||
find_package(ZLIB REQUIRED)
|
|
||||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(osrm-extract ${ZLIB_LIBRARY})
|
|
||||||
target_link_libraries(osrm-routed ${ZLIB_LIBRARY})
|
|
||||||
|
|
||||||
if (ENABLE_JSON_LOGGING)
|
|
||||||
message(STATUS "Enabling json logging")
|
|
||||||
add_definitions(-DENABLE_JSON_LOGGING)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_TOOLS OR BUILD_TOOLS)
|
|
||||||
message(STATUS "Activating OSRM internal tools")
|
|
||||||
find_package(GDAL)
|
|
||||||
if(GDAL_FOUND)
|
|
||||||
add_executable(osrm-components tools/components.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
|
||||||
target_link_libraries(osrm-components ${TBB_LIBRARIES})
|
|
||||||
include_directories(${GDAL_INCLUDE_DIR})
|
|
||||||
target_link_libraries(
|
|
||||||
osrm-components
|
|
||||||
${GDAL_LIBRARIES} ${Boost_LIBRARIES})
|
|
||||||
install(TARGETS osrm-components DESTINATION bin)
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "libgdal and/or development headers not found")
|
|
||||||
endif()
|
|
||||||
add_executable(osrm-cli tools/simpleclient.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:COORDINATE>)
|
|
||||||
target_link_libraries(osrm-cli ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
|
|
||||||
target_link_libraries(osrm-cli ${TBB_LIBRARIES})
|
|
||||||
add_executable(osrm-io-benchmark tools/io-benchmark.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
|
|
||||||
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES})
|
|
||||||
add_executable(osrm-unlock-all tools/unlock_all_mutexes.cpp $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION>)
|
|
||||||
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
|
||||||
if(UNIX AND NOT APPLE)
|
|
||||||
target_link_libraries(osrm-unlock-all rt)
|
|
||||||
endif()
|
|
||||||
add_executable(osrm-check-hsgr tools/check-hsgr.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER>)
|
|
||||||
target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES})
|
|
||||||
add_executable(osrm-springclean tools/springclean.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:EXCEPTION>)
|
|
||||||
target_link_libraries(osrm-springclean ${Boost_LIBRARIES})
|
|
||||||
add_executable(osrm-graph-compare tools/graph_compare.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
|
||||||
target_link_libraries(osrm-graph-compare ${Boost_LIBRARIES} ${TBB_LIBRARIES})
|
|
||||||
|
|
||||||
install(TARGETS osrm-cli DESTINATION bin)
|
|
||||||
install(TARGETS osrm-io-benchmark DESTINATION bin)
|
|
||||||
install(TARGETS osrm-unlock-all DESTINATION bin)
|
|
||||||
install(TARGETS osrm-check-hsgr DESTINATION bin)
|
|
||||||
install(TARGETS osrm-springclean DESTINATION bin)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
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
|
|
||||||
# more info see http://www.cmake.org/Wiki/CMake_RPATH_handling
|
|
||||||
set_property(TARGET osrm-extract PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
|
||||||
set_property(TARGET osrm-prepare PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
|
||||||
set_property(TARGET osrm-datastore PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
|
||||||
set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
|
||||||
|
|
||||||
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)
|
|
||||||
install(TARGETS osrm-routed DESTINATION bin)
|
|
||||||
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})
|
|
||||||
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()
|
|
||||||
|
|
||||||
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)
|
|
||||||
include(CPackDebianConfig)
|
|
||||||
include(CPack)
|
|
||||||
endif()
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
source "http://rubygems.org"
|
|
||||||
|
|
||||||
gem "cucumber"
|
|
||||||
gem "rake"
|
|
||||||
gem "osmlib-base"
|
|
||||||
gem "sys-proctable"
|
|
||||||
gem "rspec-expectations"
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
GEM
|
|
||||||
remote: http://rubygems.org/
|
|
||||||
specs:
|
|
||||||
builder (3.2.2)
|
|
||||||
cucumber (1.3.8)
|
|
||||||
builder (>= 2.1.2)
|
|
||||||
diff-lcs (>= 1.1.3)
|
|
||||||
gherkin (~> 2.12.1)
|
|
||||||
multi_json (>= 1.7.5, < 2.0)
|
|
||||||
multi_test (>= 0.0.2)
|
|
||||||
diff-lcs (1.2.4)
|
|
||||||
gherkin (2.12.1)
|
|
||||||
multi_json (~> 1.3)
|
|
||||||
multi_json (1.8.0)
|
|
||||||
multi_test (0.0.2)
|
|
||||||
osmlib-base (0.1.4)
|
|
||||||
rake (10.1.0)
|
|
||||||
rspec-expectations (2.14.3)
|
|
||||||
diff-lcs (>= 1.1.3, < 2.0)
|
|
||||||
sys-proctable (0.9.3)
|
|
||||||
|
|
||||||
PLATFORMS
|
|
||||||
ruby
|
|
||||||
|
|
||||||
DEPENDENCIES
|
|
||||||
cucumber
|
|
||||||
osmlib-base
|
|
||||||
rake
|
|
||||||
rspec-expectations
|
|
||||||
sys-proctable
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
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.
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
# Readme
|
|
||||||
|
|
||||||
For instructions on how to compile and run OSRM, please consult the Wiki at
|
|
||||||
|
|
||||||
https://github.com/Project-OSRM/osrm-backend/wiki
|
|
||||||
|
|
||||||
or use our free and daily updated online service at
|
|
||||||
|
|
||||||
http://map.project-osrm.org
|
|
||||||
|
|
||||||
## References in publications
|
|
||||||
|
|
||||||
When using the code in a (scientific) publication, please cite
|
|
||||||
|
|
||||||
```
|
|
||||||
@inproceedings{luxen-vetter-2011,
|
|
||||||
author = {Luxen, Dennis and Vetter, Christian},
|
|
||||||
title = {Real-time routing with OpenStreetMap data},
|
|
||||||
booktitle = {Proceedings of the 19th ACM SIGSPATIAL International Conference on Advances in Geographic Information Systems},
|
|
||||||
series = {GIS '11},
|
|
||||||
year = {2011},
|
|
||||||
isbn = {978-1-4503-1031-4},
|
|
||||||
location = {Chicago, Illinois},
|
|
||||||
pages = {513--516},
|
|
||||||
numpages = {4},
|
|
||||||
url = {http://doi.acm.org/10.1145/2093973.2094062},
|
|
||||||
doi = {10.1145/2093973.2094062},
|
|
||||||
acmid = {2094062},
|
|
||||||
publisher = {ACM},
|
|
||||||
address = {New York, NY, USA},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Current build status
|
|
||||||
|
|
||||||
| build config | branch | status |
|
|
||||||
|:-------------|:--------|:------------|
|
|
||||||
| Linux | master | [](https://travis-ci.org/DennisOSRM/Project-OSRM) |
|
|
||||||
| Linux | develop | [](https://travis-ci.org/DennisOSRM/Project-OSRM) |
|
|
||||||
| Windows | master/develop | [](https://ci.appveyor.com/project/DennisOSRM/osrm-backend) |
|
|
||||||
| LUAbind fork | master | [](https://travis-ci.org/DennisOSRM/luabind) |
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
require 'OSM/StreamParser'
|
|
||||||
require 'socket'
|
|
||||||
require 'digest/sha1'
|
|
||||||
require 'cucumber/rake/task'
|
|
||||||
require 'sys/proctable'
|
|
||||||
|
|
||||||
BUILD_FOLDER = 'build'
|
|
||||||
DATA_FOLDER = 'sandbox'
|
|
||||||
PROFILE = 'bicycle'
|
|
||||||
OSRM_PORT = 5000
|
|
||||||
PROFILES_FOLDER = '../profiles'
|
|
||||||
|
|
||||||
Cucumber::Rake::Task.new do |t|
|
|
||||||
t.cucumber_opts = %w{--format pretty}
|
|
||||||
end
|
|
||||||
|
|
||||||
areas = {
|
|
||||||
:kbh => { :country => 'denmark', :bbox => 'top=55.6972 left=12.5222 right=12.624 bottom=55.6376' },
|
|
||||||
:frd => { :country => 'denmark', :bbox => 'top=55.7007 left=12.4765 bottom=55.6576 right=12.5698' },
|
|
||||||
:regh => { :country => 'denmark', :bbox => 'top=56.164 left=11.792 bottom=55.403 right=12.731' },
|
|
||||||
:denmark => { :country => 'denmark', :bbox => nil },
|
|
||||||
:skaane => { :country => 'sweden', :bbox => 'top=56.55 left=12.4 bottom=55.3 right=14.6' }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
osm_data_area_name = ARGV[1] ? ARGV[1].to_s.to_sym : :kbh
|
|
||||||
raise "Unknown data area." unless areas[osm_data_area_name]
|
|
||||||
osm_data_country = areas[osm_data_area_name][:country]
|
|
||||||
osm_data_area_bbox = areas[osm_data_area_name][:bbox]
|
|
||||||
|
|
||||||
|
|
||||||
task osm_data_area_name.to_sym {} #define empty task to prevent rake from whining. will break if area has same name as a task
|
|
||||||
|
|
||||||
|
|
||||||
def each_process name, &block
|
|
||||||
Sys::ProcTable.ps do |process|
|
|
||||||
if process.comm.strip == name.strip && process.state != 'zombie'
|
|
||||||
yield process.pid.to_i, process.state.strip
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def up?
|
|
||||||
find_pid('osrm-routed') != nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_pid name
|
|
||||||
each_process(name) { |pid,state| return pid.to_i }
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def wait_for_shutdown name
|
|
||||||
timeout = 10
|
|
||||||
(timeout*10).times do
|
|
||||||
return if find_pid(name) == nil
|
|
||||||
sleep 0.1
|
|
||||||
end
|
|
||||||
raise "*** Could not terminate #{name}."
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
desc "Rebuild and run tests."
|
|
||||||
task :default => [:build]
|
|
||||||
|
|
||||||
desc "Build using CMake."
|
|
||||||
task :build do
|
|
||||||
if Dir.exists? BUILD_FOLDER
|
|
||||||
Dir.chdir BUILD_FOLDER do
|
|
||||||
system "make"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
system "mkdir build; cd build; cmake ..; make"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Setup config files."
|
|
||||||
task :setup do
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Download OSM data."
|
|
||||||
task :download do
|
|
||||||
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
|
|
||||||
puts "Downloading..."
|
|
||||||
puts "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
|
||||||
raise "Error while downloading data." unless system "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
|
||||||
if osm_data_area_bbox
|
|
||||||
puts "Cropping and converting to protobuffer..."
|
|
||||||
raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Crop OSM data"
|
|
||||||
task :crop do
|
|
||||||
if osm_data_area_bbox
|
|
||||||
raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Reprocess OSM data."
|
|
||||||
task :process => [:extract,:prepare] do
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Extract OSM data."
|
|
||||||
task :extract do
|
|
||||||
Dir.chdir DATA_FOLDER do
|
|
||||||
raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf --profile ../profiles/#{PROFILE}.lua"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Prepare OSM data."
|
|
||||||
task :prepare do
|
|
||||||
Dir.chdir DATA_FOLDER do
|
|
||||||
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm --profile ../profiles/#{PROFILE}.lua"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Delete preprocessing files."
|
|
||||||
task :clean do
|
|
||||||
File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm")
|
|
||||||
File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm.*")
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Run all cucumber test"
|
|
||||||
task :test do
|
|
||||||
system "cucumber"
|
|
||||||
puts
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Run the routing server in the terminal. Press Ctrl-C to stop."
|
|
||||||
task :run do
|
|
||||||
Dir.chdir DATA_FOLDER do
|
|
||||||
system "../#{BUILD_FOLDER}/osrm-routed #{osm_data_area_name}.osrm --port #{OSRM_PORT}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Launch the routing server in the background. Use rake:down to stop it."
|
|
||||||
task :up do
|
|
||||||
Dir.chdir DATA_FOLDER do
|
|
||||||
abort("Already up.") if up?
|
|
||||||
pipe = IO.popen("../#{BUILD_FOLDER}/osrm-routed #{osm_data_area_name}.osrm --port #{OSRM_PORT} 1>>osrm-routed.log 2>>osrm-routed.log")
|
|
||||||
timeout = 5
|
|
||||||
(timeout*10).times do
|
|
||||||
begin
|
|
||||||
socket = TCPSocket.new('localhost', OSRM_PORT)
|
|
||||||
socket.puts 'ping'
|
|
||||||
rescue Errno::ECONNREFUSED
|
|
||||||
sleep 0.1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Stop the routing server."
|
|
||||||
task :down do
|
|
||||||
pid = find_pid 'osrm-routed'
|
|
||||||
if pid
|
|
||||||
Process.kill 'TERM', pid
|
|
||||||
else
|
|
||||||
puts "Already down."
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Kill all osrm-extract, osrm-prepare and osrm-routed processes."
|
|
||||||
task :kill do
|
|
||||||
each_process('osrm-routed') { |pid,state| Process.kill 'KILL', pid }
|
|
||||||
each_process('osrm-prepare') { |pid,state| Process.kill 'KILL', pid }
|
|
||||||
each_process('osrm-extract') { |pid,state| Process.kill 'KILL', pid }
|
|
||||||
wait_for_shutdown 'osrm-routed'
|
|
||||||
wait_for_shutdown 'osrm-prepare'
|
|
||||||
wait_for_shutdown 'osrm-extract'
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Get PIDs of all osrm-extract, osrm-prepare and osrm-routed processes."
|
|
||||||
task :pid do
|
|
||||||
each_process 'osrm-routed' do |pid,state|
|
|
||||||
puts "#{pid}\t#{state}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Stop, reprocess and restart."
|
|
||||||
task :update => [:down,:process,:up] do
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
desc "Remove test cache files."
|
|
||||||
task :sweep do
|
|
||||||
system "rm test/cache/*"
|
|
||||||
end
|
|
||||||
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Leaflet extension: Dashed Polyline
|
||||||
|
// [adds dashed optionally dashed lines when using SVG or VML rendering]
|
||||||
|
|
||||||
|
|
||||||
|
// dashed polyline class
|
||||||
|
L.DashedPolyline = L.Polyline.extend({
|
||||||
|
initialize: function(latlngs, options) {
|
||||||
|
L.Polyline.prototype.initialize.call(this, latlngs, options);
|
||||||
|
},
|
||||||
|
|
||||||
|
options: {
|
||||||
|
dashed: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// svg rendering
|
||||||
|
L.DashedPolyline = !L.Browser.svg ? L.DashedPolyline : L.DashedPolyline.extend({
|
||||||
|
_updateStyle: function () {
|
||||||
|
L.Polyline.prototype._updateStyle.call(this);
|
||||||
|
if (this.options.stroke) {
|
||||||
|
if (this.options.dashed == true)
|
||||||
|
this._path.setAttribute('stroke-dasharray', '8,6');
|
||||||
|
else
|
||||||
|
this._path.setAttribute('stroke-dasharray', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// vml rendering
|
||||||
|
L.DashedPolyline = L.Browser.svg || !L.Browser.vml ? L.DashedPolyline : L.DashedPolyline.extend({
|
||||||
|
_updateStyle: function () {
|
||||||
|
L.Polyline.prototype._updateStyle.call(this);
|
||||||
|
if (this.options.stroke) {
|
||||||
|
if (this.options.dashed == true)
|
||||||
|
this._stroke.dashstyle = "dash";
|
||||||
|
else
|
||||||
|
this._stroke.dashstyle = "solid";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Leaflet extension: MouseMarker
|
||||||
|
// [marker class that propagates modifier and button presses]
|
||||||
|
// [currently deactivated: propagation mousemove events]
|
||||||
|
|
||||||
|
|
||||||
|
// extended marker class
|
||||||
|
L.MouseMarker = L.Marker.extend({
|
||||||
|
initialize: function (latlng, options) {
|
||||||
|
L.Marker.prototype.initialize.apply(this, arguments);
|
||||||
|
},
|
||||||
|
|
||||||
|
// _initInteraction: function (){
|
||||||
|
// L.Marker.prototype._initInteraction.apply(this, arguments);
|
||||||
|
// if (this.options.clickable)
|
||||||
|
// L.DomEvent.addListener(this._icon, 'mousemove', this._fireMouseEvent, this);
|
||||||
|
// },
|
||||||
|
|
||||||
|
// _fireMouseEvent: function (e) {
|
||||||
|
// this.fire(e.type, {
|
||||||
|
// latlng: this._map.mouseEventToLatLng(e),
|
||||||
|
// layerPoint: this._map.mouseEventToLayerPoint(e)
|
||||||
|
// });
|
||||||
|
// L.DomEvent.stopPropagation(e);
|
||||||
|
// },
|
||||||
|
|
||||||
|
_onMouseClick: function (e) {
|
||||||
|
L.DomEvent.stopPropagation(e);
|
||||||
|
if (this.dragging && this.dragging.moved()) { return; }
|
||||||
|
this.fire(e.type, {
|
||||||
|
altKey: e.altKey,
|
||||||
|
ctrlKey: e.ctrlKey,
|
||||||
|
shiftKey: e.shiftKey,
|
||||||
|
button: e.button
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// OSRM browser detection
|
||||||
|
// [simple detection routines to respect some browser peculiarities]
|
||||||
|
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var useragent = navigator.userAgent;
|
||||||
|
|
||||||
|
OSRM.Browser = {
|
||||||
|
FF3: useragent.search(/Firefox\/3/),
|
||||||
|
IE6_9: useragent.search(/MSIE (6|7|8|9)/)
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
|
// (runs anonymous function to prevent local variables cluttering global namespace)
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// OSRM GUI functionality
|
||||||
|
// [responsible for all non-routing related GUI behaviour]
|
||||||
|
|
||||||
|
|
||||||
|
OSRM.GUI = {
|
||||||
|
|
||||||
|
// show/hide main-gui
|
||||||
|
toggleMain: function() {
|
||||||
|
// show main-gui
|
||||||
|
if( document.getElementById('main-wrapper').style.left == "-410px" ) {
|
||||||
|
getElementsByClassName(document,'leaflet-control-zoom')[0].style.visibility="hidden";
|
||||||
|
getElementsByClassName(document,'leaflet-control-zoom')[0].style.left="420px";
|
||||||
|
getElementsByClassName(document,'leaflet-control-zoom')[0].style.top="5px";
|
||||||
|
|
||||||
|
document.getElementById('blob-wrapper').style.visibility="hidden";
|
||||||
|
document.getElementById('main-wrapper').style.left="5px";
|
||||||
|
if( OSRM.Browser.FF3!=-1 || OSRM.Browser.IE6_9!=-1 ) {
|
||||||
|
getElementsByClassName(document,'leaflet-control-zoom')[0].style.visibility="visible";
|
||||||
|
}
|
||||||
|
// hide main-gui
|
||||||
|
} else {
|
||||||
|
getElementsByClassName(document,'leaflet-control-zoom')[0].style.visibility="hidden";
|
||||||
|
getElementsByClassName(document,'leaflet-control-zoom')[0].style.left="30px";
|
||||||
|
getElementsByClassName(document,'leaflet-control-zoom')[0].style.top="5px";
|
||||||
|
|
||||||
|
document.getElementById('main-wrapper').style.left="-410px";
|
||||||
|
if( OSRM.Browser.FF3!=-1 || OSRM.Browser.IE6_9!=-1 ) {
|
||||||
|
document.getElementById('blob-wrapper').style.visibility="visible";
|
||||||
|
getElementsByClassName(document,'leaflet-control-zoom')[0].style.visibility="visible";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute after animation
|
||||||
|
if( OSRM.Browser.FF3==-1 && OSRM.Browser.IE6_9==-1 ) {
|
||||||
|
document.getElementById('main-wrapper').addEventListener("transitionend", OSRM.GUI.onMainTransitionEnd, false);
|
||||||
|
document.getElementById('main-wrapper').addEventListener("webkitTransitionEnd", OSRM.GUI.onMainTransitionEnd, false);
|
||||||
|
document.getElementById('main-wrapper').addEventListener("oTransitionEnd", OSRM.GUI.onMainTransitionEnd, false);
|
||||||
|
document.getElementById('main-wrapper').addEventListener("MSTransitionEnd", OSRM.GUI.onMainTransitionEnd, false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// do stuff after main-gui animation finished
|
||||||
|
onMainTransitionEnd: function() {
|
||||||
|
// after hiding main-gui
|
||||||
|
if( document.getElementById('main-wrapper').style.left == "-410px" ) {
|
||||||
|
document.getElementById('blob-wrapper').style.visibility="visible";
|
||||||
|
getElementsByClassName(document,'leaflet-control-zoom')[0].style.visibility="visible";
|
||||||
|
// after showing main-gui
|
||||||
|
} else {
|
||||||
|
getElementsByClassName(document,'leaflet-control-zoom')[0].style.visibility="visible";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// show/hide small options bubble
|
||||||
|
toggleOptions: function() {
|
||||||
|
if(document.getElementById('options-box').style.visibility=="visible") {
|
||||||
|
document.getElementById('options-box').style.visibility="hidden";
|
||||||
|
} else {
|
||||||
|
document.getElementById('options-box').style.visibility="visible";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// OSRM JSONP call wrapper
|
||||||
|
// [wrapper for JSONP calls with DOM cleaning, fencing, timout handling]
|
||||||
|
|
||||||
|
|
||||||
|
OSRM.JSONP = {
|
||||||
|
|
||||||
|
// storage to keep track of unfinished JSONP calls
|
||||||
|
fences: {},
|
||||||
|
callbacks: {},
|
||||||
|
timeouts: {},
|
||||||
|
timers: {},
|
||||||
|
|
||||||
|
|
||||||
|
// default callback routines
|
||||||
|
late: function() { /*OSRM.debug.log("[jsonp] reply too late");*/ },
|
||||||
|
empty: function() { /*OSRM.debug.log("[jsonp] empty callback");*/ },
|
||||||
|
|
||||||
|
|
||||||
|
// init JSONP call
|
||||||
|
call: function(source, callback_function, timeout_function, timeout, id) {
|
||||||
|
// only one active JSONP call per id
|
||||||
|
if (OSRM.JSONP.fences[id] == true)
|
||||||
|
return false;
|
||||||
|
OSRM.JSONP.fences[id] = true;
|
||||||
|
|
||||||
|
// wrap timeout function
|
||||||
|
OSRM.JSONP.timeouts[id] = function(response) {
|
||||||
|
timeout_function(response);
|
||||||
|
|
||||||
|
OSRM.JSONP.callbacks[id] = OSRM.JSONP.late; // clean functions
|
||||||
|
OSRM.JSONP.timeouts[id] = OSRM.JSONP.late;
|
||||||
|
OSRM.JSONP.fences[id] = undefined; // clean fence
|
||||||
|
|
||||||
|
// OSRM.debug.log("[jsonp] timout handling: "+id);
|
||||||
|
};
|
||||||
|
|
||||||
|
// wrap callback function
|
||||||
|
OSRM.JSONP.callbacks[id] = function(response) {
|
||||||
|
clearTimeout(OSRM.JSONP.timers[id]); // clear timeout timer
|
||||||
|
OSRM.JSONP.timers[id] = undefined;
|
||||||
|
|
||||||
|
callback_function(response); // actual wrapped callback
|
||||||
|
|
||||||
|
OSRM.JSONP.callbacks[id] = OSRM.JSONP.late; // clean functions
|
||||||
|
OSRM.JSONP.timeouts[id] = OSRM.JSONP.late;
|
||||||
|
OSRM.JSONP.fences[id] = undefined; // clean fence
|
||||||
|
|
||||||
|
// OSRM.debug.log("[jsonp] response handling: "+id);
|
||||||
|
};
|
||||||
|
|
||||||
|
// clean DOM (unfortunately, script elements cannot be reused by all browsers)
|
||||||
|
var jsonp = document.getElementById('jsonp_'+id);
|
||||||
|
if(jsonp)
|
||||||
|
jsonp.parentNode.removeChild(jsonp);
|
||||||
|
|
||||||
|
// add script to DOM
|
||||||
|
var script = document.createElement('script');
|
||||||
|
script.type = 'text/javascript';
|
||||||
|
script.id = 'jsonp_'+id;
|
||||||
|
script.src = source + "&json_callback=OSRM.JSONP.callbacks."+id + "&jsonp=OSRM.JSONP.callbacks."+id;
|
||||||
|
document.head.appendChild(script);
|
||||||
|
|
||||||
|
// start timeout timer
|
||||||
|
OSRM.JSONP.timers[id] = setTimeout(OSRM.JSONP.timeouts[id], timeout);
|
||||||
|
|
||||||
|
// OSRM.debug.log("[jsonp] init: "+id);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
// reset all data
|
||||||
|
reset: function() {
|
||||||
|
OSRM.JSONP.fences = {};
|
||||||
|
OSRM.JSONP.callbacks = {};
|
||||||
|
OSRM.JSONP.timeouts = {};
|
||||||
|
OSRM.JSONP.timers = {};
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// OSRM localization
|
||||||
|
// [basic localization options]
|
||||||
|
|
||||||
|
|
||||||
|
OSRM.Localization = {
|
||||||
|
|
||||||
|
// if existing, return localized string -> English string -> input string
|
||||||
|
translate: function(text) {
|
||||||
|
if( OSRM.Localization[OSRM.DEFAULTS.LANGUAGE][text] )
|
||||||
|
return OSRM.Localization[OSRM.DEFAULTS.LANGUAGE][text];
|
||||||
|
else if( OSRM.Localization["en"][text] )
|
||||||
|
return OSRM.Localization["en"][text];
|
||||||
|
else
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// shorter call to translate function
|
||||||
|
OSRM.loc = OSRM.Localization.translate;
|
||||||
|
|
||||||
|
|
||||||
|
// German language support
|
||||||
|
OSRM.Localization["de"] = {
|
||||||
|
//gui
|
||||||
|
"GUI_START": "Start",
|
||||||
|
"GUI_END": "Ziel",
|
||||||
|
"GUI_RESET": "Reset",
|
||||||
|
"GUI_SEARCH": "Zeigen",
|
||||||
|
"GUI_REVERSE": "Umdrehen",
|
||||||
|
"GUI_OPTIONS": "Optionen",
|
||||||
|
"GUI_HIGHLIGHT_UNNAMED_ROADS": "Unbenannte Straßen hervorheben",
|
||||||
|
"GUI_START_TOOLTIP": "Startposition eingeben",
|
||||||
|
"GUI_END_TOOLTIP": "Zielposition eingeben",
|
||||||
|
"GUI_LEGAL_NOTICE": "GUI2 v0.1.1 120316 - OSRM hosting by <a href='http://algo2.iti.kit.edu/'>KIT</a> - Geocoder by <a href='http://www.osm.org/'>OSM</a>",
|
||||||
|
// geocoder
|
||||||
|
"SEARCH_RESULTS": "Suchergebnisse",
|
||||||
|
"TIMED_OUT": "Zeitüberschreitung",
|
||||||
|
"NO_RESULTS_FOUND": "Keine Ergebnisse gefunden",
|
||||||
|
"NO_RESULTS_FOUND_SOURCE": "Keine Ergebnisse gefunden für Start",
|
||||||
|
"NO_RESULTS_FOUND_TARGET": "Keine Ergebnisse gefunden für Ziel",
|
||||||
|
// routing
|
||||||
|
"ROUTE_DESCRIPTION": "Routenbeschreibung",
|
||||||
|
"GET_LINK": "Generiere Link",
|
||||||
|
"LINK_TO_ROUTE_TIMEOUT": "nicht möglich",
|
||||||
|
"GPX_FILE": "GPX Datei",
|
||||||
|
"DISTANCE": "Distanz",
|
||||||
|
"DURATION": "Dauer",
|
||||||
|
"YOUR_ROUTE_IS_BEING_COMPUTED": "Ihre Route wird berechnet",
|
||||||
|
"NO_ROUTE_FOUND": "Keine Route hierher möglich",
|
||||||
|
// directions
|
||||||
|
"N": "Norden",
|
||||||
|
"O": "Ost",
|
||||||
|
"S": "Süden",
|
||||||
|
"W": "Westen",
|
||||||
|
"NO": "Nordost",
|
||||||
|
"SO": "Südost",
|
||||||
|
"SW": "Südwest",
|
||||||
|
"NW": "Nordwest"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// English language support
|
||||||
|
OSRM.Localization["en"] = {
|
||||||
|
//gui
|
||||||
|
"GUI_START": "Start",
|
||||||
|
"GUI_END": "End",
|
||||||
|
"GUI_RESET": " Reset ",
|
||||||
|
"GUI_SEARCH": " Show ",
|
||||||
|
"GUI_REVERSE": "Reverse",
|
||||||
|
"GUI_OPTIONS": "Options",
|
||||||
|
"GUI_HIGHLIGHT_UNNAMED_ROADS": "Highlight unnamed streets",
|
||||||
|
"GUI_START_TOOLTIP": "Enter start",
|
||||||
|
"GUI_END_TOOLTIP": "Enter destination",
|
||||||
|
"GUI_LEGAL_NOTICE": "GUI2 v0.1.1 120316 - OSRM hosting by <a href='http://algo2.iti.kit.edu/'>KIT</a> - Geocoder by <a href='http://www.osm.org/'>OSM</a>",
|
||||||
|
// geocoder
|
||||||
|
"SEARCH_RESULTS": "Search Results",
|
||||||
|
"TIMED_OUT": "Timed Out",
|
||||||
|
"NO_RESULTS_FOUND": "No results found",
|
||||||
|
"NO_RESULTS_FOUND_SOURCE": "No results found for start",
|
||||||
|
"NO_RESULTS_FOUND_TARGET": "No results found for end",
|
||||||
|
//routing
|
||||||
|
"ROUTE_DESCRIPTION": "Route Description",
|
||||||
|
"GET_LINK": "Generate Link",
|
||||||
|
"LINK_TO_ROUTE_TIMEOUT": "not available",
|
||||||
|
"GPX_FILE": "GPX File",
|
||||||
|
"DISTANCE": "Distance",
|
||||||
|
"DURATION": "Duration",
|
||||||
|
"YOUR_ROUTE_IS_BEING_COMPUTED": "Your route is being computed",
|
||||||
|
"NO_ROUTE_FOUND": "No route possible",
|
||||||
|
// directions
|
||||||
|
"N": "north",
|
||||||
|
"E": "east",
|
||||||
|
"S": "south",
|
||||||
|
"W": "west",
|
||||||
|
"NE": "northeast",
|
||||||
|
"SE": "southeast",
|
||||||
|
"SW": "southwest",
|
||||||
|
"NW": "northwest"
|
||||||
|
};
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// OSRM markers
|
||||||
|
// [base marker class, derived highlight marker and route marker classes, marker management]
|
||||||
|
|
||||||
|
|
||||||
|
// base marker class (wraps Leaflet markers)
|
||||||
|
OSRM.Marker = function( label, style, position ) {
|
||||||
|
this.label = label ? label : "marker";
|
||||||
|
this.position = position ? position : new L.LatLng(0,0);
|
||||||
|
|
||||||
|
this.marker = new L.MouseMarker( this.position, style );
|
||||||
|
this.marker.parent = this;
|
||||||
|
this.dirty_move = true;
|
||||||
|
this.dirty_type = true;
|
||||||
|
|
||||||
|
this.shown = false;
|
||||||
|
this.hint = undefined;
|
||||||
|
};
|
||||||
|
OSRM.extend( OSRM.Marker,{
|
||||||
|
show: function() {
|
||||||
|
map.addLayer(this.marker);
|
||||||
|
this.shown = true;
|
||||||
|
},
|
||||||
|
hide: function() {
|
||||||
|
map.removeLayer(this.marker);
|
||||||
|
this.shown = false;
|
||||||
|
},
|
||||||
|
setPosition: function( position ) {
|
||||||
|
this.position = position;
|
||||||
|
this.marker.setLatLng( position );
|
||||||
|
this.hint = undefined;
|
||||||
|
},
|
||||||
|
getPosition: function() {
|
||||||
|
return this.position;
|
||||||
|
},
|
||||||
|
getLat: function() {
|
||||||
|
return this.position.lat;
|
||||||
|
},
|
||||||
|
getLng: function() {
|
||||||
|
return this.position.lng;
|
||||||
|
},
|
||||||
|
isShown: function() {
|
||||||
|
return this.shown;
|
||||||
|
},
|
||||||
|
centerView: function(zooming) {
|
||||||
|
var zoom = OSRM.DEFAULTS.ZOOM_LEVEL;
|
||||||
|
if( zooming == false )
|
||||||
|
zoom = map.getZoom();
|
||||||
|
//map.setView( new L.LatLng( this.position.lat, this.position.lng-0.02), zoom); // dirty hack
|
||||||
|
map.setView( new L.LatLng( this.position.lat, this.position.lng), zoom);
|
||||||
|
},
|
||||||
|
toString: function() {
|
||||||
|
return "OSRM.Marker: \""+this.label+"\", "+this.position+")";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// highlight marker class (cannot be dragged)
|
||||||
|
OSRM.HighlightMarker = function( label, style, position) {
|
||||||
|
OSRM.HighlightMarker.prototype.base.constructor.apply( this, arguments );
|
||||||
|
this.label = label ? label : "highlight_marker";
|
||||||
|
|
||||||
|
this.marker.on( 'click', this.onClick );
|
||||||
|
};
|
||||||
|
OSRM.inheritFrom( OSRM.HighlightMarker, OSRM.Marker );
|
||||||
|
OSRM.extend( OSRM.HighlightMarker, {
|
||||||
|
toString: function() {
|
||||||
|
return "OSRM.HighlightMarker: \""+this.label+"\", "+this.position+")";
|
||||||
|
},
|
||||||
|
onClick: function(e) {
|
||||||
|
this.parent.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// route marker class (draggable, invokes route drawing routines)
|
||||||
|
OSRM.RouteMarker = function ( label, style, position ) {
|
||||||
|
OSRM.RouteMarker.prototype.base.constructor.apply( this, arguments );
|
||||||
|
this.label = label ? label : "route_marker";
|
||||||
|
|
||||||
|
this.marker.on( 'click', this.onClick );
|
||||||
|
this.marker.on( 'drag', this.onDrag );
|
||||||
|
this.marker.on( 'dragstart', this.onDragStart );
|
||||||
|
this.marker.on( 'dragend', this.onDragEnd );
|
||||||
|
};
|
||||||
|
OSRM.inheritFrom( OSRM.RouteMarker, OSRM.Marker );
|
||||||
|
OSRM.extend( OSRM.RouteMarker, {
|
||||||
|
onClick: function(e) {
|
||||||
|
for( var i=0; i<my_markers.route.length; i++) {
|
||||||
|
if( my_markers.route[i].marker === this ) {
|
||||||
|
my_markers.removeMarker( i );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getRoute(OSRM.FULL_DESCRIPTION);
|
||||||
|
my_markers.highlight.hide();
|
||||||
|
},
|
||||||
|
onDrag: function(e) {
|
||||||
|
this.parent.dirty_move = true;
|
||||||
|
this.parent.setPosition( e.target.getLatLng() );
|
||||||
|
if(OSRM.dragging == true) // TODO: hack that deals with drag events after dragend event
|
||||||
|
getRoute(OSRM.NO_DESCRIPTION);
|
||||||
|
else
|
||||||
|
getRoute(OSRM.FULL_DESCRIPTION);
|
||||||
|
|
||||||
|
updateLocation( this.parent.label );
|
||||||
|
},
|
||||||
|
onDragStart: function(e) {
|
||||||
|
OSRM.dragging = true;
|
||||||
|
|
||||||
|
// hack to store id of dragged marker
|
||||||
|
for( var i=0; i<my_markers.route.length; i++)
|
||||||
|
if( my_markers.route[i].marker === this ) {
|
||||||
|
OSRM.dragid = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_markers.highlight.hide();
|
||||||
|
if (my_route.isShown()) {
|
||||||
|
my_route.showOldRoute();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLocation( this.parent.label );
|
||||||
|
},
|
||||||
|
onDragEnd: function(e) {
|
||||||
|
getRoute(OSRM.FULL_DESCRIPTION);
|
||||||
|
if (my_route.isShown()) {
|
||||||
|
my_route.hideOldRoute();
|
||||||
|
my_route.hideUnnamedRoute();
|
||||||
|
}
|
||||||
|
OSRM.dragging = false;
|
||||||
|
|
||||||
|
updateLocation( this.parent.label );
|
||||||
|
if(my_route.isShown()==false) {
|
||||||
|
if(this.parent.label == "source")
|
||||||
|
updateReverseGeocoder("source");
|
||||||
|
else if(this.parent.label == "target")
|
||||||
|
updateReverseGeocoder("target");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toString: function() {
|
||||||
|
return "OSRM.RouteMarker: \""+this.label+"\", "+this.position+")";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// marker management class (all route markers should only be set and deleted with these routines!)
|
||||||
|
// [this holds the vital information of the route]
|
||||||
|
OSRM.Markers = function() {
|
||||||
|
this.route = new Array();
|
||||||
|
this.highlight = new OSRM.HighlightMarker("highlight", {draggable:false,icon:OSRM.icons['marker-highlight']});;
|
||||||
|
};
|
||||||
|
OSRM.extend( OSRM.Markers,{
|
||||||
|
removeAll: function() {
|
||||||
|
for(var i=0; i<this.route.length;i++)
|
||||||
|
this.route[i].hide();
|
||||||
|
this.route.splice(0, this.route.length);
|
||||||
|
},
|
||||||
|
removeVias: function() {
|
||||||
|
// assert correct route array s - v - t
|
||||||
|
for(var i=1; i<this.route.length-1;i++)
|
||||||
|
this.route[i].hide();
|
||||||
|
this.route.splice(1, this.route.length-2);
|
||||||
|
},
|
||||||
|
setSource: function(position) {
|
||||||
|
// source node is always first node
|
||||||
|
if( this.route[0] && this.route[0].label == OSRM.SOURCE_MARKER_LABEL )
|
||||||
|
this.route[0].setPosition(position);
|
||||||
|
else
|
||||||
|
this.route.splice(0,0, new OSRM.RouteMarker("source", {draggable:true,icon:OSRM.icons['marker-source']}, position));
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
setTarget: function(position) {
|
||||||
|
// target node is always last node
|
||||||
|
if( this.route[this.route.length-1] && this.route[ this.route.length-1 ].label == OSRM.TARGET_MARKER_LABEL )
|
||||||
|
this.route[this.route.length-1].setPosition(position);
|
||||||
|
else
|
||||||
|
this.route.splice( this.route.length,0, new OSRM.RouteMarker("target", {draggable:true,icon:OSRM.icons['marker-target']}, position));
|
||||||
|
return this.route.length-1;
|
||||||
|
},
|
||||||
|
setVia: function(id, position) {
|
||||||
|
// via nodes only between source and target nodes
|
||||||
|
if( this.route.length<2 || id > this.route.length-2 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
this.route.splice(id+1,0, new OSRM.RouteMarker("via", {draggable:true,icon:OSRM.icons['marker-via']}, position));
|
||||||
|
return id+1;
|
||||||
|
},
|
||||||
|
removeMarker: function(id) {
|
||||||
|
if( id >= this.route.length )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// also remove vias if source or target are removed
|
||||||
|
if( id==0 && this.route[0].label == OSRM.SOURCE_MARKER_LABEL )
|
||||||
|
this.removeVias();
|
||||||
|
else if( id == this.route.length-1 && this.route[ this.route.length-1 ].label == OSRM.TARGET_MARKER_LABEL ) {
|
||||||
|
this.removeVias();
|
||||||
|
id = this.route.length-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.route[id].hide();
|
||||||
|
this.route.splice(id, 1);
|
||||||
|
},
|
||||||
|
hasSource: function() {
|
||||||
|
if( my_markers.route[0] && my_markers.route[0].label == OSRM.SOURCE_MARKER_LABEL )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
hasTarget: function() {
|
||||||
|
if( my_markers.route[my_markers.route.length-1] && my_markers.route[my_markers.route.length-1].label == OSRM.TARGET_MARKER_LABEL )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// OSRM routes
|
||||||
|
// [drawing of all types of route geometry]
|
||||||
|
|
||||||
|
|
||||||
|
// simple route class (wraps Leaflet Polyline)
|
||||||
|
OSRM.SimpleRoute = function (label, style) {
|
||||||
|
this.label = (label ? label : "route");
|
||||||
|
this.route = new L.DashedPolyline();
|
||||||
|
this.route.setLatLngs( [] );
|
||||||
|
if(style) this.route.setStyle( style );
|
||||||
|
|
||||||
|
this.shown = false;
|
||||||
|
|
||||||
|
this.route.on('click', this.onClick);
|
||||||
|
};
|
||||||
|
OSRM.extend( OSRM.SimpleRoute,{
|
||||||
|
show: function() {
|
||||||
|
map.addLayer(this.route);
|
||||||
|
this.shown = true;
|
||||||
|
},
|
||||||
|
hide: function() {
|
||||||
|
map.removeLayer(this.route);
|
||||||
|
this.shown = false;
|
||||||
|
},
|
||||||
|
isShown: function() {
|
||||||
|
return this.shown;
|
||||||
|
},
|
||||||
|
getPositions: function() {
|
||||||
|
return this.route.getLatLngs();
|
||||||
|
},
|
||||||
|
setPositions: function(positions) {
|
||||||
|
this.route.setLatLngs( positions );
|
||||||
|
},
|
||||||
|
setStyle: function(style) {
|
||||||
|
this.route.setStyle(style);
|
||||||
|
},
|
||||||
|
centerView: function() {
|
||||||
|
var bounds = new L.LatLngBounds( this.getPositions() );
|
||||||
|
map.fitBounds( bounds );
|
||||||
|
},
|
||||||
|
onClick: function(e) {
|
||||||
|
if(my_route.isRoute())
|
||||||
|
findViaPosition( e.latlng );
|
||||||
|
},
|
||||||
|
toString: function() {
|
||||||
|
return "OSRM.Route("+ this.label + ", " + this.route.getLatLngs().length + " points)";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// multiroute class (wraps Leaflet LayerGroup to hold several disjoint routes)
|
||||||
|
OSRM.MultiRoute = function (label) {
|
||||||
|
this.label = (label ? label : "multiroute");
|
||||||
|
this.route = new L.LayerGroup();
|
||||||
|
|
||||||
|
this.shown = false;
|
||||||
|
};
|
||||||
|
OSRM.extend( OSRM.MultiRoute,{
|
||||||
|
show: function() {
|
||||||
|
map.addLayer(this.route);
|
||||||
|
this.shown = true;
|
||||||
|
},
|
||||||
|
hide: function() {
|
||||||
|
map.removeLayer(this.route);
|
||||||
|
this.shown = false;
|
||||||
|
},
|
||||||
|
isShown: function() {
|
||||||
|
return this.shown;
|
||||||
|
},
|
||||||
|
addRoute: function(positions) {
|
||||||
|
var line = new L.DashedPolyline( positions );
|
||||||
|
line.on('click', function(e) { my_route.fire('click',e); });
|
||||||
|
this.route.addLayer( line );
|
||||||
|
},
|
||||||
|
clearRoutes: function() {
|
||||||
|
this.route.clearLayers();
|
||||||
|
},
|
||||||
|
setStyle: function(style) {
|
||||||
|
this.route.invoke('setStyle', style);
|
||||||
|
},
|
||||||
|
toString: function() {
|
||||||
|
return "OSRM.MultiRoute("+ this.label + ")";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// route management (handles drawing of route geometry - current route, old route, unnamed route, highlight unnamed streets)
|
||||||
|
// [this holds the route geometry]
|
||||||
|
OSRM.Route = function() {
|
||||||
|
this._current_route = new OSRM.SimpleRoute("current" , {dashed:false} );
|
||||||
|
this._old_route = new OSRM.SimpleRoute("old", {dashed:false,color:"#123"} );
|
||||||
|
this._unnamed_route = new OSRM.MultiRoute("unnamed");
|
||||||
|
|
||||||
|
this._current_route_style = {dashed:false,color:'#0033FF', weight:5};
|
||||||
|
this._current_noroute_style = {dashed:true, color:'#222222', weight:2};
|
||||||
|
this._old_route_style = {dashed:false,color:'#112233', weight:5};
|
||||||
|
this._old_noroute_style = {dashed:true, color:'#000000', weight:2};
|
||||||
|
this._unnamed_route_style = {dashed:false, color:'#FF00FF', weight:10};
|
||||||
|
this._old_unnamed_route_style = {dashed:false, color:'#990099', weight:10};
|
||||||
|
|
||||||
|
this._noroute = OSRM.Route.ROUTE;
|
||||||
|
};
|
||||||
|
OSRM.Route.NOROUTE = true;
|
||||||
|
OSRM.Route.ROUTE = false;
|
||||||
|
OSRM.extend( OSRM.Route,{
|
||||||
|
|
||||||
|
showRoute: function(positions, noroute) {
|
||||||
|
this._noroute = noroute;
|
||||||
|
this._current_route.setPositions( positions );
|
||||||
|
if ( this._noroute == OSRM.Route.NOROUTE )
|
||||||
|
this._current_route.setStyle( this._current_noroute_style );
|
||||||
|
else
|
||||||
|
this._current_route.setStyle( this._current_route_style );
|
||||||
|
this._current_route.show();
|
||||||
|
//this._raiseUnnamedRoute();
|
||||||
|
},
|
||||||
|
hideRoute: function() {
|
||||||
|
this._current_route.hide();
|
||||||
|
this._unnamed_route.hide();
|
||||||
|
},
|
||||||
|
hideAll: function() {
|
||||||
|
this._current_route.hide();
|
||||||
|
this._unnamed_route.hide();
|
||||||
|
this._old_route.hide();
|
||||||
|
this._noroute = OSRM.Route.ROUTE;
|
||||||
|
},
|
||||||
|
|
||||||
|
showUnnamedRoute: function(positions) {
|
||||||
|
this._unnamed_route.clearRoutes();
|
||||||
|
for(var i=0; i<positions.length; i++) {
|
||||||
|
this._unnamed_route.addRoute(positions[i]);
|
||||||
|
}
|
||||||
|
this._unnamed_route.setStyle( this._unnamed_route_style );
|
||||||
|
this._unnamed_route.show();
|
||||||
|
},
|
||||||
|
hideUnnamedRoute: function() {
|
||||||
|
this._unnamed_route.hide();
|
||||||
|
},
|
||||||
|
// TODO: hack to put unnamed_route above old_route -> easier way in will be available Leaflet 0.4
|
||||||
|
_raiseUnnamedRoute: function() {
|
||||||
|
if(this._unnamed_route.isShown()) {
|
||||||
|
this._unnamed_route.hide();
|
||||||
|
this._unnamed_route.show();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showOldRoute: function() {
|
||||||
|
this._old_route.setPositions( this._current_route.getPositions() );
|
||||||
|
if ( this._noroute == OSRM.Route.NOROUTE)
|
||||||
|
this._old_route.setStyle( this._old_noroute_style );
|
||||||
|
else
|
||||||
|
this._old_route.setStyle( this._old_route_style );
|
||||||
|
this._old_route.show();
|
||||||
|
this._raiseUnnamedRoute();
|
||||||
|
// change color of unnamed route highlighting - no separate object as dragged route does not have unnamed route highlighting
|
||||||
|
this._unnamed_route.setStyle( this._old_unnamed_route_style );
|
||||||
|
},
|
||||||
|
hideOldRoute: function() {
|
||||||
|
this._old_route.hide();
|
||||||
|
},
|
||||||
|
|
||||||
|
isShown: function() {
|
||||||
|
return this._current_route.isShown();
|
||||||
|
},
|
||||||
|
isRoute: function() {
|
||||||
|
return !(this._noroute);
|
||||||
|
},
|
||||||
|
getPositions: function() {
|
||||||
|
return this._current_route.getPositions();
|
||||||
|
},
|
||||||
|
fire: function(type,event) {
|
||||||
|
this._current_route.route.fire(type,event);
|
||||||
|
},
|
||||||
|
centerView: function() {
|
||||||
|
this._current_route.centerView();
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// OSRM base class
|
||||||
|
// [has to loaded before all other OSRM classes]
|
||||||
|
|
||||||
|
OSRM = {};
|
||||||
|
OSRM.VERSION = '0.1.1';
|
||||||
|
|
||||||
|
|
||||||
|
// inheritance helper function (convenience function)
|
||||||
|
OSRM._inheritFromHelper = function() {};
|
||||||
|
OSRM.inheritFrom = function( sub_class, base_class ) {
|
||||||
|
OSRM._inheritFromHelper.prototype = base_class.prototype;
|
||||||
|
sub_class.prototype = new OSRM._inheritFromHelper();
|
||||||
|
sub_class.prototype.constructor = sub_class;
|
||||||
|
sub_class.prototype.base = base_class.prototype;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// class prototype extending helper function (convenience function)
|
||||||
|
OSRM.extend = function( target_class, properties ) {
|
||||||
|
for( property in properties ) {
|
||||||
|
target_class.prototype[property] = properties[property];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// usage:
|
||||||
|
// SubClass = function() {
|
||||||
|
// SubClass.prototype.base.constructor.apply(this, arguments);
|
||||||
|
// }
|
||||||
|
// OSRM.inheritFrom( SubClass, BaseClass );
|
||||||
|
// OSRM.extend( SubClass, { property:value } );
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// OSRM config file
|
||||||
|
// [has to be loaded directly after OSRM.base]
|
||||||
|
|
||||||
|
OSRM.DEFAULTS = {
|
||||||
|
HOST_ROUTING_URL: 'http://router.project-osrm.org/viaroute',
|
||||||
|
HOST_SHORTENER_URL: 'http://map.project-osrm.org/shorten/',
|
||||||
|
WEBSITE_URL: document.URL.replace(/#*\?.*/i,""),
|
||||||
|
JSONP_TIMEOUT: 5000,
|
||||||
|
ZOOM_LEVEL: 14,
|
||||||
|
ONLOAD_LATITUDE: 48.84,
|
||||||
|
ONLOAD_LONGITUDE: 10.10,
|
||||||
|
ONLOAD_SOURCE: "",
|
||||||
|
ONLOAD_TARGET: "",
|
||||||
|
LANGUAGE: "en"
|
||||||
|
};
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// debug code for OSRM
|
||||||
|
// [works better than console.log in older browsers and for logging event handling]
|
||||||
|
|
||||||
|
OSRM.debug = {};
|
||||||
|
|
||||||
|
|
||||||
|
// add elements to DOM
|
||||||
|
OSRM.debug.init = function() {
|
||||||
|
//create DOM objects for debug output
|
||||||
|
var wrapper = document.createElement('div');
|
||||||
|
wrapper.id = "OSRM.debug-wrapper";
|
||||||
|
wrapper.className = "gui-wrapper";
|
||||||
|
wrapper.style.cssText = "width:410px;height:95%;top:5px;right:50px;";
|
||||||
|
|
||||||
|
var box = document.createElement('div');
|
||||||
|
box.id = "OSRM.debug-box";
|
||||||
|
box.className = "gui-box";
|
||||||
|
box.style.cssText = "width:390px;top:0px;bottom:0px;";
|
||||||
|
|
||||||
|
var clear = document.createElement('a');
|
||||||
|
clear.id = "OSRM.debug-clear";
|
||||||
|
clear.className = "button not-selectable";
|
||||||
|
clear.innerHTML = "clear";
|
||||||
|
clear.onclick = OSRM.debug.clear;
|
||||||
|
|
||||||
|
OSRM.debug.content= document.createElement('div');
|
||||||
|
OSRM.debug.content.id = "OSRM.debug-content";
|
||||||
|
OSRM.debug.content.style.cssText = "position:absolute;bottom:0px;top:20px;width:380px;font-size:11px;overflow:auto;margin:5px;";
|
||||||
|
|
||||||
|
// add elements
|
||||||
|
document.body.appendChild(wrapper);
|
||||||
|
wrapper.appendChild(box);
|
||||||
|
box.appendChild(clear);
|
||||||
|
box.appendChild(OSRM.debug.content);
|
||||||
|
};
|
||||||
|
if(document.addEventListener) // FF, CH
|
||||||
|
document.addEventListener("DOMContentLoaded", OSRM.debug.init, false);
|
||||||
|
else // IE
|
||||||
|
OSRM.debug.init();
|
||||||
|
|
||||||
|
|
||||||
|
// working functions
|
||||||
|
OSRM.debug.log = function(text) {
|
||||||
|
OSRM.debug.content.innerHTML += text + "<hr style='border:none; margin:2px; height:1px; color:#F0F0F0; background:#F0F0F0;'/>";
|
||||||
|
OSRM.debug.content.scrollTop = OSRM.debug.content.scrollHeight;
|
||||||
|
};
|
||||||
|
OSRM.debug.clear = function() {
|
||||||
|
OSRM.debug.content.innerHTML = "";
|
||||||
|
};
|
||||||
@@ -0,0 +1,205 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// OSRM geocoding routines
|
||||||
|
// [geocoder query, management and display of geocoder results]
|
||||||
|
// [TODO: better separation of GUI and geocoding routines, reverse geocoding]
|
||||||
|
|
||||||
|
// some constants
|
||||||
|
OSRM.GEOCODE_POST = 'http://nominatim.openstreetmap.org/search?format=json&bounded=1&viewbox=-27.0,72.0,46.0,36.0';
|
||||||
|
OSRM.SOURCE_MARKER_LABEL = "source";
|
||||||
|
OSRM.TARGET_MARKER_LABEL = "target";
|
||||||
|
|
||||||
|
|
||||||
|
// update geo coordinates in input boxes
|
||||||
|
function updateLocation(marker_id) {
|
||||||
|
if (marker_id == OSRM.SOURCE_MARKER_LABEL && my_markers.route[0].dirty_move == true ) {
|
||||||
|
document.getElementById("input-source-name").value = my_markers.route[0].getPosition().lat.toFixed(6) + ", " + my_markers.route[0].getPosition().lng.toFixed(6);
|
||||||
|
} else if (marker_id == OSRM.TARGET_MARKER_LABEL && my_markers.route[my_markers.route.length-1].dirty_move == true) {
|
||||||
|
document.getElementById("input-target-name").value = my_markers.route[my_markers.route.length-1].getPosition().lat.toFixed(6) + ", " + my_markers.route[my_markers.route.length-1].getPosition().lng.toFixed(6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// process input request and call geocoder if needed
|
||||||
|
function callGeocoder(marker_id, query) {
|
||||||
|
if (marker_id == OSRM.SOURCE_MARKER_LABEL && my_markers.route[0] && my_markers.route[0].label == OSRM.SOURCE_MARKER_LABEL && my_markers.route[0].dirty_move == false && my_markers.route[0].dirty_type == false)
|
||||||
|
return;
|
||||||
|
if (marker_id == OSRM.TARGET_MARKER_LABEL && my_markers.route[my_markers.route.length-1] && my_markers.route[my_markers.route.length-1].label == OSRM.TARGET_MARKER_LABEL && my_markers.route[my_markers.route.length-1].dirty_move == false && my_markers.route[my_markers.route.length-1].dirty_type == false)
|
||||||
|
return;
|
||||||
|
if(query=="")
|
||||||
|
return;
|
||||||
|
|
||||||
|
//geo coordinates given -> go directly to drawing results
|
||||||
|
if(query.match(/^\s*[-+]?[0-9]*\.?[0-9]+\s*[,;]\s*[-+]?[0-9]*\.?[0-9]+\s*$/)){
|
||||||
|
var coord = query.split(/[,;]/);
|
||||||
|
onclickGeocoderResult(marker_id, coord[0], coord[1], true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//build request
|
||||||
|
if (marker_id == OSRM.SOURCE_MARKER_LABEL) {
|
||||||
|
var src= OSRM.GEOCODE_POST + "&q=" + query;
|
||||||
|
OSRM.JSONP.call( src, showGeocoderResults_Source, showGeocoderResults_Timeout, OSRM.DEFAULTS.JSONP_TIMEOUT, "geocoder_source" );
|
||||||
|
} else if (marker_id == OSRM.TARGET_MARKER_LABEL) {
|
||||||
|
var src = OSRM.GEOCODE_POST + "&q=" + query;
|
||||||
|
OSRM.JSONP.call( src, showGeocoderResults_Target, showGeocoderResults_Timeout, OSRM.DEFAULTS.JSONP_TIMEOUT, "geocoder_target" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// helper function for clicks on geocoder search results
|
||||||
|
function onclickGeocoderResult(marker_id, lat, lon, do_reverse_geocode, zoom ) {
|
||||||
|
var index;
|
||||||
|
if( marker_id == OSRM.SOURCE_MARKER_LABEL )
|
||||||
|
index = my_markers.setSource( new L.LatLng(lat, lon) );
|
||||||
|
else if( marker_id == OSRM.TARGET_MARKER_LABEL )
|
||||||
|
index = my_markers.setTarget( new L.LatLng(lat, lon) );
|
||||||
|
else
|
||||||
|
index = -1; // via nodes not yet implemented
|
||||||
|
|
||||||
|
if( do_reverse_geocode == true )
|
||||||
|
updateReverseGeocoder(marker_id);
|
||||||
|
if( zoom == undefined )
|
||||||
|
zoom = true;
|
||||||
|
|
||||||
|
my_markers.route[index].show();
|
||||||
|
if( !my_markers.route[index].dirty_move || my_markers.route[index].dirty_type )
|
||||||
|
my_markers.route[index].centerView(zoom);
|
||||||
|
getRoute(OSRM.FULL_DESCRIPTION);
|
||||||
|
|
||||||
|
my_markers.route[index].dirty_move = false;
|
||||||
|
my_markers.route[index].dirty_type = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process JSONP response of geocoder
|
||||||
|
// (with wrapper functions for source/target jsonp)
|
||||||
|
function showGeocoderResults_Source(response) { showGeocoderResults(OSRM.SOURCE_MARKER_LABEL, response); }
|
||||||
|
function showGeocoderResults_Target(response) { showGeocoderResults(OSRM.TARGET_MARKER_LABEL, response); }
|
||||||
|
function showGeocoderResults(marker_id, response) {
|
||||||
|
if(response){
|
||||||
|
if(response.length == 0) {
|
||||||
|
showGeocoderResults_Empty(marker_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var html = "";
|
||||||
|
html += '<table class="results-table">';
|
||||||
|
for(var i=0; i < response.length; i++){
|
||||||
|
var result = response[i];
|
||||||
|
|
||||||
|
//odd or even ?
|
||||||
|
var rowstyle='results-odd';
|
||||||
|
if(i%2==0) { rowstyle='results-even'; }
|
||||||
|
|
||||||
|
html += '<tr class="'+rowstyle+'">';
|
||||||
|
html += '<td class="result-counter"><span">'+(i+1)+'.</span></td>';
|
||||||
|
html += '<td class="result-items">';
|
||||||
|
|
||||||
|
if(result.display_name){
|
||||||
|
html += '<div class="result-item" onclick="onclickGeocoderResult(\''+marker_id+'\', '+result.lat+', '+result.lon+');">'+result.display_name+'</div>';
|
||||||
|
}
|
||||||
|
html += "</td></tr>";
|
||||||
|
}
|
||||||
|
html += '</table>';
|
||||||
|
|
||||||
|
document.getElementById('information-box-headline').innerHTML = OSRM.loc("SEARCH_RESULTS")+":";
|
||||||
|
document.getElementById('information-box').innerHTML = html;
|
||||||
|
|
||||||
|
onclickGeocoderResult(marker_id, response[0].lat, response[0].lon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function showGeocoderResults_Empty(marker_id) {
|
||||||
|
document.getElementById('information-box-headline').innerHTML = OSRM.loc("SEARCH_RESULTS")+":";
|
||||||
|
if(marker_id == OSRM.SOURCE_MARKER_LABEL)
|
||||||
|
document.getElementById('information-box').innerHTML = "<br><p style='font-size:14px;font-weight:bold;text-align:center;'>"+OSRM.loc("NO_RESULTS_FOUND_SOURCE")+".<p>";
|
||||||
|
else if(marker_id == OSRM.TARGET_MARKER_LABEL)
|
||||||
|
document.getElementById('information-box').innerHTML = "<br><p style='font-size:14px;font-weight:bold;text-align:center;'>"+OSRM.loc("NO_RESULTS_FOUND_TARGET")+".<p>";
|
||||||
|
else
|
||||||
|
document.getElementById('information-box').innerHTML = "<br><p style='font-size:14px;font-weight:bold;text-align:center;'>"+OSRM.loc("NO_RESULTS_FOUND")+".<p>";
|
||||||
|
}
|
||||||
|
function showGeocoderResults_Timeout() {
|
||||||
|
document.getElementById('information-box-headline').innerHTML = OSRM.loc("SEARCH_RESULTS")+":";
|
||||||
|
document.getElementById('information-box').innerHTML = "<br><p style='font-size:14px;font-weight:bold;text-align:center;'>"+OSRM.loc("TIMED_OUT")+".<p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// - [upcoming feature: reverse geocoding (untested) ] -
|
||||||
|
OSRM.REVERSE_GEOCODE_POST = 'http://nominatim.openstreetmap.org/reverse?format=json&bounded=1&viewbox=-27.0,72.0,46.0,36.0';
|
||||||
|
|
||||||
|
//update reverse geocoder informatiopn in input boxes
|
||||||
|
function updateReverseGeocoder(marker_id) {
|
||||||
|
if (marker_id == OSRM.SOURCE_MARKER_LABEL && my_markers.hasSource()==true) { //&& my_markers.route[0].dirty == true ) {
|
||||||
|
//document.getElementById("input-source-name").value = my_markers.route[0].getPosition().lat.toFixed(6) + ", " + my_markers.route[0].getPosition().lng.toFixed(6);
|
||||||
|
callReverseGeocoder("source", my_markers.route[0].getPosition().lat, my_markers.route[0].getPosition().lng);
|
||||||
|
} else if (marker_id == OSRM.TARGET_MARKER_LABEL && my_markers.hasTarget()==true) { //&& my_markers.route[my_markers.route.length-1].dirty == true) {
|
||||||
|
//document.getElementById("input-target-name").value = my_markers.route[my_markers.route.length-1].getPosition().lat.toFixed(6) + ", " + my_markers.route[my_markers.route.length-1].getPosition().lng.toFixed(6);
|
||||||
|
callReverseGeocoder("target", my_markers.route[my_markers.route.length-1].getPosition().lat, my_markers.route[my_markers.route.length-1].getPosition().lng);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//prepare request and call reverse geocoder
|
||||||
|
function callReverseGeocoder(marker_id, lat, lon) {
|
||||||
|
//build request
|
||||||
|
if (marker_id == OSRM.SOURCE_MARKER_LABEL) {
|
||||||
|
var src= OSRM.REVERSE_GEOCODE_POST + "&lat=" + lat + "&lon=" + lon;
|
||||||
|
OSRM.JSONP.call( src, showReverseGeocoderResults_Source, showReverseGeocoderResults_Timeout, OSRM.DEFAULTS.JSONP_TIMEOUT, "reverse_geocoder_source" );
|
||||||
|
} else if (marker_id == OSRM.TARGET_MARKER_LABEL) {
|
||||||
|
var src = OSRM.REVERSE_GEOCODE_POST + "&lat=" + lat + "&lon=" + lon;
|
||||||
|
OSRM.JSONP.call( src, showReverseGeocoderResults_Target, showReverseGeocoderResults_Timeout, OSRM.DEFAULTS.JSONP_TIMEOUT, "reverse_geocoder_target" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//processing JSONP response of reverse geocoder
|
||||||
|
//(with wrapper functions for source/target jsonp)
|
||||||
|
function showReverseGeocoderResults_Timeout() {}
|
||||||
|
function showReverseGeocoderResults_Source(response) { showReverseGeocoderResults(OSRM.SOURCE_MARKER_LABEL, response); }
|
||||||
|
function showReverseGeocoderResults_Target(response) { showReverseGeocoderResults(OSRM.TARGET_MARKER_LABEL, response); }
|
||||||
|
function showReverseGeocoderResults(marker_id, response) {
|
||||||
|
//OSRM.debug.log("[inner] reverse geocoder");
|
||||||
|
if(response){
|
||||||
|
if(response.address == undefined)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var address = "";
|
||||||
|
if( response.address.road)
|
||||||
|
address += response.address.road;
|
||||||
|
if( response.address.city ) {
|
||||||
|
if( address != "" )
|
||||||
|
address += ", ";
|
||||||
|
address += response.address.city;
|
||||||
|
} else if( response.address.village ) {
|
||||||
|
if( address != "" )
|
||||||
|
address += ", ";
|
||||||
|
address += response.address.village;
|
||||||
|
}
|
||||||
|
if( address == "" && response.address.country )
|
||||||
|
address += response.address.country;
|
||||||
|
if( address == "" )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(marker_id == OSRM.SOURCE_MARKER_LABEL) {
|
||||||
|
document.getElementById("input-source-name").value = address;
|
||||||
|
my_markers.route[0].dirty_move = false;
|
||||||
|
my_markers.route[0].dirty_type = false;
|
||||||
|
} else if(marker_id == OSRM.TARGET_MARKER_LABEL) {
|
||||||
|
document.getElementById("input-target-name").value = address;
|
||||||
|
my_markers.route[my_markers.route.length-1].dirty_move = false;
|
||||||
|
my_markers.route[my_markers.route.length-1].dirty_type = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 402 B |
|
After Width: | Height: | Size: 484 B |
|
After Width: | Height: | Size: 483 B |
|
After Width: | Height: | Size: 414 B |
|
After Width: | Height: | Size: 240 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 477 B |
|
After Width: | Height: | Size: 480 B |
|
After Width: | Height: | Size: 488 B |
|
After Width: | Height: | Size: 716 B |
|
After Width: | Height: | Size: 617 B |
|
After Width: | Height: | Size: 530 B |
|
After Width: | Height: | Size: 746 B |
|
After Width: | Height: | Size: 635 B |
|
After Width: | Height: | Size: 607 B |
|
After Width: | Height: | Size: 489 B |
|
After Width: | Height: | Size: 676 B |
|
After Width: | Height: | Size: 656 B |
|
After Width: | Height: | Size: 778 B |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 963 B |
|
After Width: | Height: | Size: 959 B |
@@ -0,0 +1,323 @@
|
|||||||
|
/* required styles */
|
||||||
|
|
||||||
|
.leaflet-map-pane,
|
||||||
|
.leaflet-tile,
|
||||||
|
.leaflet-marker-icon,
|
||||||
|
.leaflet-marker-shadow,
|
||||||
|
.leaflet-tile-pane,
|
||||||
|
.leaflet-overlay-pane,
|
||||||
|
.leaflet-shadow-pane,
|
||||||
|
.leaflet-marker-pane,
|
||||||
|
.leaflet-popup-pane,
|
||||||
|
.leaflet-overlay-pane svg,
|
||||||
|
.leaflet-zoom-box,
|
||||||
|
.leaflet-image-layer { /* TODO optimize classes */
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.leaflet-container {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.leaflet-tile-pane, .leaflet-container {
|
||||||
|
-webkit-transform: translate3d(0,0,0);
|
||||||
|
}
|
||||||
|
.leaflet-tile,
|
||||||
|
.leaflet-marker-icon,
|
||||||
|
.leaflet-marker-shadow {
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.leaflet-marker-icon,
|
||||||
|
.leaflet-marker-shadow {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.leaflet-clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.leaflet-container img {
|
||||||
|
max-width: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-tile-pane { z-index: 2; }
|
||||||
|
|
||||||
|
.leaflet-objects-pane { z-index: 3; }
|
||||||
|
.leaflet-overlay-pane { z-index: 4; }
|
||||||
|
.leaflet-shadow-pane { z-index: 5; }
|
||||||
|
.leaflet-marker-pane { z-index: 6; }
|
||||||
|
.leaflet-popup-pane { z-index: 7; }
|
||||||
|
|
||||||
|
.leaflet-zoom-box {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-tile {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
.leaflet-tile-loaded {
|
||||||
|
visibility: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.leaflet-active {
|
||||||
|
outline: 2px solid orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Leaflet controls */
|
||||||
|
|
||||||
|
.leaflet-control {
|
||||||
|
position: relative;
|
||||||
|
z-index: 7;
|
||||||
|
}
|
||||||
|
.leaflet-top,
|
||||||
|
.leaflet-bottom {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.leaflet-top {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.leaflet-right {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
.leaflet-bottom {
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.leaflet-left {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.leaflet-control {
|
||||||
|
float: left;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
.leaflet-right .leaflet-control {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.leaflet-top .leaflet-control {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.leaflet-bottom .leaflet-control {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.leaflet-left .leaflet-control {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.leaflet-right .leaflet-control {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-control-zoom, .leaflet-control-layers {
|
||||||
|
-moz-border-radius: 7px;
|
||||||
|
-webkit-border-radius: 7px;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
.leaflet-control-zoom {
|
||||||
|
padding: 5px;
|
||||||
|
background: rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
.leaflet-control-zoom a {
|
||||||
|
background-color: rgba(255, 255, 255, 0.75);
|
||||||
|
}
|
||||||
|
.leaflet-control-zoom a, .leaflet-control-layers a {
|
||||||
|
background-position: 50% 50%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.leaflet-control-zoom a {
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
width: 19px;
|
||||||
|
height: 19px;
|
||||||
|
}
|
||||||
|
.leaflet-control-zoom a:hover {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.leaflet-big-buttons .leaflet-control-zoom a {
|
||||||
|
width: 27px;
|
||||||
|
height: 27px;
|
||||||
|
}
|
||||||
|
.leaflet-control-zoom-in {
|
||||||
|
background-image: url(images/zoom-in.png);
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
.leaflet-control-zoom-out {
|
||||||
|
background-image: url(images/zoom-out.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-control-layers {
|
||||||
|
-moz-box-shadow: 0 0 7px #999;
|
||||||
|
-webkit-box-shadow: 0 0 7px #999;
|
||||||
|
box-shadow: 0 0 7px #999;
|
||||||
|
|
||||||
|
background: #f8f8f9;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers a {
|
||||||
|
background-image: url(images/layers.png);
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
|
.leaflet-big-buttons .leaflet-control-layers a {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers .leaflet-control-layers-list,
|
||||||
|
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers-expanded .leaflet-control-layers-list {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers-expanded {
|
||||||
|
padding: 6px 10px 6px 6px;
|
||||||
|
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||||
|
color: #333;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers input {
|
||||||
|
margin-top: 2px;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers-separator {
|
||||||
|
height: 0;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
margin: 5px -10px 5px -6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-container .leaflet-control-attribution {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 5px;
|
||||||
|
|
||||||
|
font: 11px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||||
|
color: #333;
|
||||||
|
|
||||||
|
background-color: rgba(255, 255, 255, 0.7);
|
||||||
|
|
||||||
|
-moz-box-shadow: 0 0 7px #ccc;
|
||||||
|
-webkit-box-shadow: 0 0 7px #ccc;
|
||||||
|
box-shadow: 0 0 7px #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Fade animations */
|
||||||
|
|
||||||
|
.leaflet-fade-anim .leaflet-tile {
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
-webkit-transition: opacity 0.2s linear;
|
||||||
|
-moz-transition: opacity 0.2s linear;
|
||||||
|
-o-transition: opacity 0.2s linear;
|
||||||
|
transition: opacity 0.2s linear;
|
||||||
|
}
|
||||||
|
.leaflet-fade-anim .leaflet-tile-loaded {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-fade-anim .leaflet-popup {
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
-webkit-transition: opacity 0.2s linear;
|
||||||
|
-moz-transition: opacity 0.2s linear;
|
||||||
|
-o-transition: opacity 0.2s linear;
|
||||||
|
transition: opacity 0.2s linear;
|
||||||
|
}
|
||||||
|
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-zoom-anim .leaflet-tile {
|
||||||
|
-webkit-transition: none;
|
||||||
|
-moz-transition: none;
|
||||||
|
-o-transition: none;
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-zoom-anim .leaflet-objects-pane {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Popup layout */
|
||||||
|
|
||||||
|
.leaflet-popup {
|
||||||
|
position: absolute;
|
||||||
|
text-align: center;
|
||||||
|
-webkit-transform: translate3d(0,0,0);
|
||||||
|
}
|
||||||
|
.leaflet-popup-content-wrapper {
|
||||||
|
padding: 1px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.leaflet-popup-content {
|
||||||
|
margin: 19px;
|
||||||
|
}
|
||||||
|
.leaflet-popup-tip-container {
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 40px;
|
||||||
|
height: 16px;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.leaflet-popup-tip {
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
padding: 1px;
|
||||||
|
|
||||||
|
margin: -8px auto 0;
|
||||||
|
|
||||||
|
-moz-transform: rotate(45deg);
|
||||||
|
-webkit-transform: rotate(45deg);
|
||||||
|
-ms-transform: rotate(45deg);
|
||||||
|
-o-transform: rotate(45deg);
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
.leaflet-popup-close-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 9px;
|
||||||
|
right: 9px;
|
||||||
|
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.leaflet-popup-content p {
|
||||||
|
margin: 18px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Visual appearance */
|
||||||
|
|
||||||
|
.leaflet-container {
|
||||||
|
background: #ddd;
|
||||||
|
}
|
||||||
|
.leaflet-container a {
|
||||||
|
color: #0078A8;
|
||||||
|
}
|
||||||
|
.leaflet-zoom-box {
|
||||||
|
border: 2px dotted #05f;
|
||||||
|
background: white;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
|
||||||
|
background: white;
|
||||||
|
|
||||||
|
box-shadow: 0 1px 10px #888;
|
||||||
|
-moz-box-shadow: 0 1px 10px #888;
|
||||||
|
-webkit-box-shadow: 0 1px 14px #999;
|
||||||
|
}
|
||||||
|
.leaflet-popup-content-wrapper {
|
||||||
|
-moz-border-radius: 20px;
|
||||||
|
-webkit-border-radius: 20px;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
.leaflet-popup-content {
|
||||||
|
font: 12px/1.4 "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
.leaflet-popup-close-button {
|
||||||
|
background: white url(images/popup-close.png);
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
.leaflet-tile {
|
||||||
|
filter: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-vml-shape {
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
}
|
||||||
|
.lvml {
|
||||||
|
behavior: url(#default#VML);
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-control {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-popup-tip {
|
||||||
|
width: 21px;
|
||||||
|
_width: 27px;
|
||||||
|
margin: 0 auto;
|
||||||
|
_margin-top: -3px;
|
||||||
|
|
||||||
|
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
|
||||||
|
}
|
||||||
|
.leaflet-popup-tip-container {
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
|
||||||
|
border: 1px solid #bbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-control-zoom {
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#3F000000',EndColorStr='#3F000000');
|
||||||
|
}
|
||||||
|
.leaflet-control-zoom a {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
.leaflet-control-zoom a:hover {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers-toggle {
|
||||||
|
}
|
||||||
|
.leaflet-control-attribution, .leaflet-control-layers {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
@@ -0,0 +1,336 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* OSRM CSS styles */
|
||||||
|
|
||||||
|
|
||||||
|
/* map -> fullscreen */
|
||||||
|
body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
html, body, #map {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
#map {
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* styles for gui */
|
||||||
|
.vquad
|
||||||
|
{
|
||||||
|
height:10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gui-wrapper
|
||||||
|
{
|
||||||
|
position:absolute;
|
||||||
|
border-radius:10px;
|
||||||
|
-moz-border-radius:10px;
|
||||||
|
-webkit-border-radius:10px;
|
||||||
|
background-color:#666666;
|
||||||
|
background-color:rgba(0, 0, 0, 0.25);
|
||||||
|
transition:left 1s;
|
||||||
|
-moz-transition:left 1s;
|
||||||
|
-webkit-transition:left 1s;
|
||||||
|
-o-transition:left 1s;
|
||||||
|
-ms-transition:left 1s;
|
||||||
|
}
|
||||||
|
.gui-box
|
||||||
|
{
|
||||||
|
position:absolute;
|
||||||
|
background-color:#ffffff;
|
||||||
|
background-color:rgba(255,255,255,1);
|
||||||
|
border-radius:10px;
|
||||||
|
-moz-border-radius:10px;
|
||||||
|
-webkit-border-radius:10px;
|
||||||
|
margin:5px;
|
||||||
|
padding:5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-wrapper
|
||||||
|
{
|
||||||
|
width:410px;
|
||||||
|
height:95%;
|
||||||
|
top:5px;
|
||||||
|
left:5px;
|
||||||
|
}
|
||||||
|
#main-input
|
||||||
|
{
|
||||||
|
width:390px;
|
||||||
|
height:200px;
|
||||||
|
}
|
||||||
|
#main-output
|
||||||
|
{
|
||||||
|
width:390px;
|
||||||
|
top:220px;
|
||||||
|
bottom:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#blob-wrapper
|
||||||
|
{
|
||||||
|
left:-5px;
|
||||||
|
top:5px;
|
||||||
|
width:36px;
|
||||||
|
height:36px;
|
||||||
|
border-top-left-radius:0px;
|
||||||
|
border-bottom-left-radius:0px;
|
||||||
|
-moz-border-radius-topleft:0px;
|
||||||
|
-moz-border-radius-bottomleft:0px;
|
||||||
|
-webkit-border-top-left-radius:0px;
|
||||||
|
-webkit-border-bottom-left-radius:0px;
|
||||||
|
visibility:hidden;
|
||||||
|
}
|
||||||
|
#blob-input
|
||||||
|
{
|
||||||
|
width:26px;
|
||||||
|
height:26px;
|
||||||
|
border-top-left-radius:0px;
|
||||||
|
border-bottom-left-radius:0px;
|
||||||
|
-moz-border-radius-topleft:0px;
|
||||||
|
-moz-border-radius-bottomleft:0px;
|
||||||
|
-webkit-border-top-left-radius:0px;
|
||||||
|
-webkit-border-bottom-left-radius:0px;
|
||||||
|
padding:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-toggle-out
|
||||||
|
{
|
||||||
|
cursor:pointer;
|
||||||
|
position:absolute;
|
||||||
|
right:5px;
|
||||||
|
top:5px;
|
||||||
|
width:16px;
|
||||||
|
height:16px;
|
||||||
|
background-image:url("images/cancel.png");
|
||||||
|
}
|
||||||
|
.main-toggle-out:hover
|
||||||
|
{
|
||||||
|
background-image:url("images/cancel_hover.png");
|
||||||
|
}
|
||||||
|
.main-toggle-out:active
|
||||||
|
{
|
||||||
|
background-image:url("images/cancel_active.png");
|
||||||
|
}
|
||||||
|
.main-toggle-in
|
||||||
|
{
|
||||||
|
cursor:pointer;
|
||||||
|
position:absolute;
|
||||||
|
right:5px;
|
||||||
|
top:5px;
|
||||||
|
width:16px;
|
||||||
|
height:16px;
|
||||||
|
background-image:url("images/restore.png");
|
||||||
|
}
|
||||||
|
.main-toggle-in:hover
|
||||||
|
{
|
||||||
|
background-image:url("images/restore_hover.png");
|
||||||
|
}
|
||||||
|
.main-toggle-in:active
|
||||||
|
{
|
||||||
|
background-image:url("images/restore_active.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-options
|
||||||
|
{
|
||||||
|
font-size:10px;
|
||||||
|
}
|
||||||
|
#options-toggle
|
||||||
|
{
|
||||||
|
cursor:pointer;
|
||||||
|
color:#0000ff
|
||||||
|
}
|
||||||
|
#options-toggle:hover
|
||||||
|
{
|
||||||
|
color:#ff0000
|
||||||
|
}
|
||||||
|
#options-box
|
||||||
|
{
|
||||||
|
visibility:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#osrm-logo
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
width: 200px;
|
||||||
|
height: 50px;
|
||||||
|
text-align:center;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-box
|
||||||
|
{
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.full
|
||||||
|
{
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
.right
|
||||||
|
{
|
||||||
|
text-align:right;
|
||||||
|
}
|
||||||
|
.center
|
||||||
|
{
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#information-box
|
||||||
|
{
|
||||||
|
position:absolute;
|
||||||
|
bottom:15px;
|
||||||
|
top:60px;
|
||||||
|
width:380px;
|
||||||
|
font-size:12px;
|
||||||
|
overflow:auto;
|
||||||
|
margin:5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-summary
|
||||||
|
{
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
#gpx-link
|
||||||
|
{
|
||||||
|
color:#0000ff;
|
||||||
|
text-decoration:none;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
#gpx-link:hover
|
||||||
|
{
|
||||||
|
color:#ff0000;
|
||||||
|
}
|
||||||
|
.results-table
|
||||||
|
{
|
||||||
|
border-spacing:0px;
|
||||||
|
}
|
||||||
|
.results-odd
|
||||||
|
{
|
||||||
|
background-color: #FAF3E9; //#ffffff;
|
||||||
|
}
|
||||||
|
.results-even
|
||||||
|
{
|
||||||
|
background-color: #F2DE9C; //#ffffe0;
|
||||||
|
}
|
||||||
|
.result-counter
|
||||||
|
{
|
||||||
|
text-align:right;
|
||||||
|
vertical-align: top;
|
||||||
|
width:30px;
|
||||||
|
font-weight:bold;
|
||||||
|
padding-left:5px;
|
||||||
|
padding-right:5px;
|
||||||
|
padding-top:1px;
|
||||||
|
padding-bottom:1px;
|
||||||
|
}
|
||||||
|
.result-items
|
||||||
|
{
|
||||||
|
text-align:left;
|
||||||
|
vertical-align: middle;
|
||||||
|
width:100%;
|
||||||
|
padding-left:1px;
|
||||||
|
padding-right:1px;
|
||||||
|
padding-top:1px;
|
||||||
|
padding-bottom:1px;
|
||||||
|
}
|
||||||
|
.result-direction
|
||||||
|
{
|
||||||
|
width:30px;
|
||||||
|
padding-left:1px;
|
||||||
|
padding-right:1px;
|
||||||
|
padding-top:1px;
|
||||||
|
padding-bottom:1px;
|
||||||
|
}
|
||||||
|
.result-distance
|
||||||
|
{
|
||||||
|
text-align:right;
|
||||||
|
vertical-align: middle;
|
||||||
|
width:30px;
|
||||||
|
padding-left:1px;
|
||||||
|
padding-right:1px;
|
||||||
|
padding-top:1px;
|
||||||
|
padding-bottom:1px;
|
||||||
|
}
|
||||||
|
.result-item
|
||||||
|
{
|
||||||
|
cursor:pointer;
|
||||||
|
color:#000000
|
||||||
|
}
|
||||||
|
.result-item:hover
|
||||||
|
{
|
||||||
|
color:#ff0000
|
||||||
|
}
|
||||||
|
|
||||||
|
#legal-notice
|
||||||
|
{
|
||||||
|
position:absolute;
|
||||||
|
right:0px;
|
||||||
|
bottom:0px;
|
||||||
|
padding:5px;
|
||||||
|
font-size:10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* utility styles (defined above buttons, so that buttons retain cursor:pointer)*/
|
||||||
|
.not-selectable
|
||||||
|
{
|
||||||
|
cursor:default;
|
||||||
|
-moz-user-select: -moz-none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-selectable
|
||||||
|
{
|
||||||
|
cursor:default;
|
||||||
|
-moz-user-select: text;
|
||||||
|
-webkit-user-select: text;
|
||||||
|
-ms-user-select: text;
|
||||||
|
user-select: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* buttons */
|
||||||
|
.button
|
||||||
|
{
|
||||||
|
cursor:pointer;
|
||||||
|
padding:2px 10px 2px 10px;
|
||||||
|
border-radius:5px;
|
||||||
|
-moz-border-radius:5px;
|
||||||
|
background-color:#EEEEEE;
|
||||||
|
border:1px solid #999999;
|
||||||
|
color:#333333;
|
||||||
|
text-decoration:none;
|
||||||
|
font-size:11px;
|
||||||
|
outline-style:none;
|
||||||
|
}
|
||||||
|
.button:hover
|
||||||
|
{
|
||||||
|
background-color:#F9F9F9;
|
||||||
|
color:#000000;
|
||||||
|
}
|
||||||
|
.button:active
|
||||||
|
{
|
||||||
|
background-color:#F4F4F4;
|
||||||
|
color:#FF0000;
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- head -->
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<!-- metatags -->
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
||||||
|
<title>OSRM Website</title>
|
||||||
|
<meta name="description" content="OSRM Website"/>
|
||||||
|
<meta name="author" content="Dennis Schieferdecker" />
|
||||||
|
|
||||||
|
<!-- favicon -->
|
||||||
|
<link rel="shortcut icon" href="images/osrm-favicon.ico" type="image/x-icon" />
|
||||||
|
|
||||||
|
<!-- stylesheets -->
|
||||||
|
<link rel="stylesheet" href="leaflet/leaflet.css" type="text/css"/>
|
||||||
|
<link rel="stylesheet" href="main.css" type="text/css"/>
|
||||||
|
|
||||||
|
<!-- scripts -->
|
||||||
|
<script src="leaflet/leaflet-src.js" type="text/javascript"></script>
|
||||||
|
<!--[if lte IE 8]><link rel="stylesheet" href="leaflet/leaflet.ie.css" type="text/css"/><![endif]-->
|
||||||
|
<script src="L.DashedPolyline.js" type="text/javascript"></script>
|
||||||
|
<script src="L.MouseMarker.js" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script src="OSRM.base.js" type="text/javascript"></script>
|
||||||
|
<script src="OSRM.config.js" type="text/javascript"></script>
|
||||||
|
<!-- <script defer="defer" src="OSRM.debug.js" type="text/javascript"></script> -->
|
||||||
|
|
||||||
|
<script src="OSRM.Browser.js" type="text/javascript"></script>
|
||||||
|
<script src="OSRM.GUI.js" type="text/javascript"></script>
|
||||||
|
<script src="OSRM.JSONP.js" type="text/javascript"></script>
|
||||||
|
<script src="OSRM.Markers.js" type="text/javascript"></script>
|
||||||
|
<script src="OSRM.Route.js" type="text/javascript"></script>
|
||||||
|
<script src="OSRM.Localization.js" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script src="main.js" type="text/javascript"></script>
|
||||||
|
<script src="routing.js" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script src="geocoder.js" type="text/javascript"></script>
|
||||||
|
<script src="via.js" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script src="utils.js" type="text/javascript"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- body -->
|
||||||
|
<body onload="init();">
|
||||||
|
|
||||||
|
<!--map-->
|
||||||
|
<div id="map"></div>
|
||||||
|
|
||||||
|
<!-- show ui blob -->
|
||||||
|
<div id="blob-wrapper" class="gui-wrapper">
|
||||||
|
<div id="blob-input" class="gui-box">
|
||||||
|
<div class="main-toggle-in" onclick="OSRM.GUI.toggleMain()"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- show main gui -->
|
||||||
|
<div id="main-wrapper" class="gui-wrapper">
|
||||||
|
|
||||||
|
<!-- input box -->
|
||||||
|
<div class="gui-box not-selectable" id="main-input">
|
||||||
|
<div class="main-toggle-out" onclick="OSRM.GUI.toggleMain()"></div>
|
||||||
|
<img id="osrm-logo" alt="OSRM Logo" src="images/osrm-logo.png" />
|
||||||
|
|
||||||
|
<!-- source/target input -->
|
||||||
|
<table class="full">
|
||||||
|
<tr>
|
||||||
|
<td id="gui-search-source-label">Start:</td>
|
||||||
|
<td><input id="input-source-name" class="input-box" type="text" maxlength="200" value="" title="Startposition eingeben" onchange="if( my_markers.route[0] && my_markers.route[0].label == OSRM.SOURCE_MARKER_LABEL) my_markers.route[0].dirty_type = true;" onblur="callGeocoder(OSRM.SOURCE_MARKER_LABEL, document.getElementById('input-source-name').value);" onkeypress="if(event.keyCode==13) {callGeocoder(OSRM.SOURCE_MARKER_LABEL, document.getElementById('input-source-name').value);}" /></td>
|
||||||
|
<td class="right"><a class="button not-selectable" id="gui-search-source" onclick="centerMarker('source')">Zeigen</a></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td id="gui-search-target-label">Ende:</td>
|
||||||
|
<td><input id="input-target-name" class="input-box" type="text" maxlength="200" value="" title="Zielposition eingeben" onchange="if( my_markers.route[my_markers.route.length-1] && my_markers.route[my_markers.route.length-1].label == OSRM.TARGET_MARKER_LABEL) my_markers.route[my_markers.route.length-1].dirty_type = true;" onblur="callGeocoder(OSRM.TARGET_MARKER_LABEL, document.getElementById('input-target-name').value);" onkeypress="if(event.keyCode==13) {callGeocoder(OSRM.TARGET_MARKER_LABEL, document.getElementById('input-target-name').value);}" /></td>
|
||||||
|
<td class="right"><a class="button not-selectable" id="gui-search-target" onclick="centerMarker('target');">Zeigen</a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- action buttons -->
|
||||||
|
<div class="vquad"></div>
|
||||||
|
<table style="width:100%">
|
||||||
|
<tr>
|
||||||
|
<td> <a class="button not-selectable" id="gui-reset" onclick="resetRouting();">Reset</a></td>
|
||||||
|
<td class="right"> <a class="button not-selectable" id="gui-reverse" onclick="reverseRouting();">Umdrehen</a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- options -->
|
||||||
|
<div class="vquad"></div>
|
||||||
|
<div class="main-options not-selectable" id="options-toggle" onclick="OSRM.GUI.toggleOptions()">Options</div>
|
||||||
|
<div class="main-options not-selectable" id="options-box">
|
||||||
|
<input type="checkbox" id="option-highlight-nonames" name="main-options" value="highlight-nonames" onclick="getRoute(OSRM.FULL_DESCRIPTION)" /><span id="gui-option-highlight-nonames-label">Unbenannte Straßen hervorheben</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- output box -->
|
||||||
|
<div class="gui-box not-selectable" id="main-output">
|
||||||
|
<div id="information-box-headline"></div>
|
||||||
|
<div id="information-box"></div>
|
||||||
|
<div id="legal-notice">GUI2 v0.1.1 120316 - OSRM hosting by <a href='http://algo2.iti.kit.edu/'>KIT</a> - Geocoder by <a href='http://www.osm.org/'>OSM</a></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// OSRM initialization
|
||||||
|
// [initialization of maps, local strings, image prefetching]
|
||||||
|
|
||||||
|
var map;
|
||||||
|
|
||||||
|
|
||||||
|
// onload initialization routine
|
||||||
|
function init() {
|
||||||
|
prefetchImages();
|
||||||
|
prefetchIcons();
|
||||||
|
|
||||||
|
initLocale();
|
||||||
|
initMap();
|
||||||
|
initRouting();
|
||||||
|
|
||||||
|
// check if the URL contains some GET parameter, e.g. for the route
|
||||||
|
checkURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// prefetch images
|
||||||
|
OSRM.images = Array();
|
||||||
|
function prefetchImages() {
|
||||||
|
var images = [ 'images/marker-source.png',
|
||||||
|
'images/marker-target.png',
|
||||||
|
'images/marker-via.png',
|
||||||
|
'images/marker-highlight.png',
|
||||||
|
'images/cancel.png',
|
||||||
|
'images/cancel_active.png',
|
||||||
|
'images/cancel_hover.png',
|
||||||
|
'images/restore.png',
|
||||||
|
'images/restore_active.png',
|
||||||
|
'images/restore_hover.png'
|
||||||
|
];
|
||||||
|
|
||||||
|
for(var i=0; i<images.length; i++) {
|
||||||
|
OSRM.images[i] = new Image();
|
||||||
|
OSRM.images[i].src = images[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// prefetch icons
|
||||||
|
OSRM.icons = Array();
|
||||||
|
function prefetchIcons() {
|
||||||
|
var images = [ 'marker-source',
|
||||||
|
'marker-target',
|
||||||
|
'marker-via',
|
||||||
|
'marker-highlight',
|
||||||
|
];
|
||||||
|
|
||||||
|
for(var i=0; i<images.length; i++)
|
||||||
|
OSRM.icons[images[i]] = new L.Icon('images/'+images[i]+'.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// init localization
|
||||||
|
function initLocale() {
|
||||||
|
document.getElementById("gui-reset").innerHTML = OSRM.loc("GUI_RESET");
|
||||||
|
document.getElementById("gui-reverse").innerHTML = OSRM.loc("GUI_REVERSE");
|
||||||
|
document.getElementById("gui-option-highlight-nonames-label").innerHTML = OSRM.loc("GUI_HIGHLIGHT_UNNAMED_ROADS");
|
||||||
|
document.getElementById("options-toggle").innerHTML = OSRM.loc("GUI_OPTIONS");
|
||||||
|
document.getElementById("gui-search-source").innerHTML = OSRM.loc("GUI_SEARCH");
|
||||||
|
document.getElementById("gui-search-target").innerHTML = OSRM.loc("GUI_SEARCH");
|
||||||
|
document.getElementById("gui-search-source-label").innerHTML = OSRM.loc("GUI_START")+":";
|
||||||
|
document.getElementById("gui-search-target-label").innerHTML = OSRM.loc("GUI_END")+":";
|
||||||
|
document.getElementById("input-source-name").title = OSRM.loc("GUI_START_TOOLTIP");
|
||||||
|
document.getElementById("input-target-name").title = OSRM.loc("GUI_END_TOOLTIP");
|
||||||
|
document.getElementById("legal-notice").innerHTML = OSRM.loc("GUI_LEGAL_NOTICE");
|
||||||
|
|
||||||
|
document.getElementById('input-source-name').value = OSRM.DEFAULTS.ONLOAD_SOURCE;
|
||||||
|
document.getElementById('input-target-name').value = OSRM.DEFAULTS.ONLOAD_TARGET;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// centering on geolocation
|
||||||
|
function callbak_centerOnGeolocation( position ) {
|
||||||
|
map.setView( new L.LatLng( position.coords.latitude, position.coords.longitude-0.02), OSRM.DEFAULTS.ZOOM_LEVEL);
|
||||||
|
}
|
||||||
|
function centerOnGeolocation() {
|
||||||
|
if (navigator.geolocation)
|
||||||
|
navigator.geolocation.getCurrentPosition( callbak_centerOnGeolocation );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// init map
|
||||||
|
function initMap() {
|
||||||
|
// setup tile servers
|
||||||
|
var osmorgURL = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||||
|
osmorgAttribution = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 Mapnik',
|
||||||
|
osmorgOptions = {maxZoom: 18, attribution: osmorgAttribution};
|
||||||
|
|
||||||
|
var osmdeURL = 'http://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png',
|
||||||
|
osmdeAttribution = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 Mapnik',
|
||||||
|
osmdeOptions = {maxZoom: 18, attribution: osmdeAttribution};
|
||||||
|
|
||||||
|
var mapquestURL = 'http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png',
|
||||||
|
mapquestAttribution = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 MapQuest',
|
||||||
|
mapquestOptions = {maxZoom: 18, attribution: mapquestAttribution, subdomains: '1234'};
|
||||||
|
|
||||||
|
var cloudmadeURL = 'http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png',
|
||||||
|
cloudmadeAttribution = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 CloudMade',
|
||||||
|
cloudmadeOptions = {maxZoom: 18, attribution: cloudmadeAttribution};
|
||||||
|
|
||||||
|
var osmorg = new L.TileLayer(osmorgURL, osmorgOptions),
|
||||||
|
osmde = new L.TileLayer(osmdeURL, osmdeOptions),
|
||||||
|
mapquest = new L.TileLayer(mapquestURL, mapquestOptions),
|
||||||
|
cloudmade = new L.TileLayer(cloudmadeURL, cloudmadeOptions);
|
||||||
|
|
||||||
|
// setup map
|
||||||
|
map = new L.Map('map', {
|
||||||
|
center: new L.LatLng(51.505, -0.09),
|
||||||
|
zoom: 13,
|
||||||
|
zoomAnimation: false, // false: removes animations and hiding of routes during zoom
|
||||||
|
fadeAnimation: false,
|
||||||
|
layers: [osmorg]
|
||||||
|
});
|
||||||
|
|
||||||
|
// add tileservers
|
||||||
|
var baseMaps = {
|
||||||
|
"osm.org": osmorg,
|
||||||
|
"osm.de": osmde,
|
||||||
|
"MapQuest": mapquest,
|
||||||
|
"CloudMade": cloudmade
|
||||||
|
};
|
||||||
|
|
||||||
|
var overlayMaps = {};
|
||||||
|
var layersControl = new L.Control.Layers(baseMaps, overlayMaps);
|
||||||
|
map.addControl(layersControl);
|
||||||
|
|
||||||
|
// move zoom markers
|
||||||
|
getElementsByClassName(document,'leaflet-control-zoom')[0].style.left="420px";
|
||||||
|
getElementsByClassName(document,'leaflet-control-zoom')[0].style.top="5px";
|
||||||
|
|
||||||
|
// initial map position and zoom
|
||||||
|
map.setView( new L.LatLng( OSRM.DEFAULTS.ONLOAD_LATITUDE, OSRM.DEFAULTS.ONLOAD_LONGITUDE), OSRM.DEFAULTS.ZOOM_LEVEL);
|
||||||
|
map.on('zoomend', function(e) { getRoute(OSRM.FULL_DESCRIPTION); });
|
||||||
|
map.on('contextmenu', function(e) {});
|
||||||
|
|
||||||
|
// click on map to set source and target nodes
|
||||||
|
map.on('click', function(e) {
|
||||||
|
if( !my_markers.route[0] || my_markers.route[0].label != OSRM.SOURCE_MARKER_LABEL) {
|
||||||
|
onclickGeocoderResult("source", e.latlng.lat, e.latlng.lng, true, false );
|
||||||
|
}
|
||||||
|
else if( !my_markers.route[my_markers.route.length-1] || my_markers.route[ my_markers.route.length-1 ].label != OSRM.TARGET_MARKER_LABEL) {
|
||||||
|
onclickGeocoderResult("target", e.latlng.lat, e.latlng.lng, true, false );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// parse URL GET parameters if any exist
|
||||||
|
function checkURL(){
|
||||||
|
var called_url = document.location.search.substr(1,document.location.search.length);
|
||||||
|
|
||||||
|
// reject messages that are clearly too long or too small
|
||||||
|
if( called_url.length > 1000 || called_url.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// storage for parameter values
|
||||||
|
var positions = [];
|
||||||
|
var destination = undefined;
|
||||||
|
var destination_name = undefined;
|
||||||
|
|
||||||
|
// parse input
|
||||||
|
var splitted_url = called_url.split('&');
|
||||||
|
for(var i=0; i<splitted_url.length; i++) {
|
||||||
|
var name_val = splitted_url[i].split('=');
|
||||||
|
if(name_val.length!=2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(name_val[0] == 'loc') {
|
||||||
|
var coordinates = unescape(name_val[1]).split(',');
|
||||||
|
if(coordinates.length!=2 || !isLatitude(coordinates[0]) || !isLongitude(coordinates[1]) )
|
||||||
|
return;
|
||||||
|
positions.push ( new L.LatLng( coordinates[0], coordinates[1]) );
|
||||||
|
}
|
||||||
|
else if(name_val[0] == 'dest') {
|
||||||
|
var coordinates = unescape(name_val[1]).split(',');
|
||||||
|
if(coordinates.length!=2 || !isLatitude(coordinates[0]) || !isLongitude(coordinates[1]) )
|
||||||
|
return;
|
||||||
|
destination = new L.LatLng( coordinates[0], coordinates[1]);
|
||||||
|
}
|
||||||
|
else if(name_val[0] == 'destname') {
|
||||||
|
destination_name = decodeURI(name_val[1]).replace(/<\/?[^>]+(>|$)/g ,""); // discard tags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// case 1: destination given
|
||||||
|
if( destination != undefined ) {
|
||||||
|
onclickGeocoderResult("target", destination.lat, destination.lng, (destination_name == undefined) );
|
||||||
|
if( destination_name != undefined )
|
||||||
|
document.getElementById("input-target-name").value = destination_name;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// case 2: locations given
|
||||||
|
if( positions != []) {
|
||||||
|
// draw via points
|
||||||
|
if( positions.length > 0) {
|
||||||
|
onclickGeocoderResult("source", positions[0].lat, positions[0].lng, true, false );
|
||||||
|
//my_markers.setSource( positions[0] );
|
||||||
|
}
|
||||||
|
if(positions.length > 1) {
|
||||||
|
onclickGeocoderResult("target", positions[positions.length-1].lat, positions[positions.length-1].lng, true, false );
|
||||||
|
//my_markers.setTarget( positions[positions.length-1] );
|
||||||
|
}
|
||||||
|
for(var i=1; i<positions.length-1;i++)
|
||||||
|
my_markers.setVia( i-1, positions[i] );
|
||||||
|
for(var i=0; i<my_markers.route.length;i++)
|
||||||
|
my_markers.route[i].show();
|
||||||
|
|
||||||
|
// center on route
|
||||||
|
var bounds = new L.LatLngBounds( positions );
|
||||||
|
map.fitBounds( bounds );
|
||||||
|
|
||||||
|
// compute route
|
||||||
|
getRoute(OSRM.FULL_DESCRIPTION);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,480 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// OSRM routing routines
|
||||||
|
// [management of routing/direction requests and processing of responses]
|
||||||
|
// [TODO: major refactoring scheduled]
|
||||||
|
|
||||||
|
// some variables
|
||||||
|
var my_route = undefined;
|
||||||
|
var my_markers = undefined;
|
||||||
|
|
||||||
|
OSRM.NO_DESCRIPTION = 0;
|
||||||
|
OSRM.FULL_DESCRIPTION = 1;
|
||||||
|
OSRM.dragging = false;
|
||||||
|
OSRM.pending = false;
|
||||||
|
OSRM.pendingTimer = undefined;
|
||||||
|
|
||||||
|
|
||||||
|
// init routing data structures
|
||||||
|
function initRouting() {
|
||||||
|
my_route = new OSRM.Route();
|
||||||
|
my_markers = new OSRM.Markers();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -- JSONP processing --
|
||||||
|
|
||||||
|
// process JSONP response of routing server
|
||||||
|
function timeoutRouteSimple() {
|
||||||
|
showNoRouteGeometry();
|
||||||
|
showNoRouteDescription();
|
||||||
|
document.getElementById('information-box').innerHTML = "<br><p style='font-size:14px;font-weight:bold;text-align:center;'>"+OSRM.loc("TIMED_OUT")+".<p>";
|
||||||
|
}
|
||||||
|
function timeoutRoute() {
|
||||||
|
showNoRouteGeometry();
|
||||||
|
my_route.hideUnnamedRoute();
|
||||||
|
showNoRouteDescription();
|
||||||
|
document.getElementById('information-box').innerHTML = "<br><p style='font-size:14px;font-weight:bold;text-align:center;'>"+OSRM.loc("TIMED_OUT")+".<p>";
|
||||||
|
}
|
||||||
|
function showRouteSimple(response) {
|
||||||
|
if(!response)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (OSRM.JSONP.fences.route) // prevent simple routing when real routing is done!
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( response.status == 207) {
|
||||||
|
showNoRouteGeometry();
|
||||||
|
showNoRouteDescription();
|
||||||
|
document.getElementById('information-box').innerHTML = "<br><p style='font-size:14px;font-weight:bold;text-align:center;'>"+OSRM.loc("YOUR_ROUTE_IS_BEING_COMPUTED")+".<p>";
|
||||||
|
} else {
|
||||||
|
showRouteGeometry(response);
|
||||||
|
showRouteDescriptionSimple(response);
|
||||||
|
}
|
||||||
|
updateHints(response);
|
||||||
|
|
||||||
|
// // TODO: hack to process final drag event, if it was fenced, but we are still dragging (alternative approach)
|
||||||
|
// if(OSRM.pending) {
|
||||||
|
// clearTimeout(OSRM.pendingTimer);
|
||||||
|
// OSRM.pendingTimer = setTimeout(timeoutDrag,100);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
function showRoute(response) {
|
||||||
|
if(!response)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(response.status == 207) {
|
||||||
|
showNoRouteGeometry();
|
||||||
|
my_route.hideUnnamedRoute();
|
||||||
|
showNoRouteDescription();
|
||||||
|
document.getElementById('information-box').innerHTML = "<br><p style='font-size:14px;font-weight:bold;text-align:center;'>"+OSRM.loc("NO_ROUTE_FOUND")+".<p>";
|
||||||
|
} else {
|
||||||
|
showRouteGeometry(response);
|
||||||
|
showRouteNonames(response);
|
||||||
|
showRouteDescription(response);
|
||||||
|
snapRoute();
|
||||||
|
}
|
||||||
|
updateHints(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// show route geometry
|
||||||
|
function showNoRouteGeometry() {
|
||||||
|
var positions = [];
|
||||||
|
for(var i=0; i<my_markers.route.length;i++)
|
||||||
|
positions.push( my_markers.route[i].getPosition() );
|
||||||
|
|
||||||
|
my_route.showRoute(positions, OSRM.Route.NOROUTE);
|
||||||
|
}
|
||||||
|
function showRouteGeometry(response) {
|
||||||
|
via_points = response.via_points.slice(0);
|
||||||
|
|
||||||
|
var geometry = decodeRouteGeometry(response.route_geometry, 5);
|
||||||
|
|
||||||
|
var points = [];
|
||||||
|
for( var i=0; i < geometry.length; i++) {
|
||||||
|
points.push( new L.LatLng(geometry[i][0], geometry[i][1]) );
|
||||||
|
}
|
||||||
|
my_route.showRoute(points, OSRM.Route.ROUTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// route description display (and helper functions)
|
||||||
|
function onClickRouteDescription(geometry_index) {
|
||||||
|
var positions = my_route.getPositions();
|
||||||
|
|
||||||
|
my_markers.highlight.setPosition( positions[geometry_index] );
|
||||||
|
my_markers.highlight.show();
|
||||||
|
my_markers.highlight.centerView();
|
||||||
|
}
|
||||||
|
function onClickCreateShortcut(src){
|
||||||
|
OSRM.JSONP.call(OSRM.DEFAULTS.HOST_SHORTENER_URL+src+'&jsonp=showRouteLink', showRouteLink, showRouteLink_TimeOut, 2000, 'shortener');
|
||||||
|
}
|
||||||
|
function showRouteLink(response){
|
||||||
|
document.getElementById('route-prelink').innerHTML = '[<a id="gpx-link" class = "text-selectable" href="' +response.ShortURL+ '">'+response.ShortURL+'</a>]';
|
||||||
|
}
|
||||||
|
function showRouteLink_TimeOut(){
|
||||||
|
document.getElementById('route-prelink').innerHTML = '['+OSRM.loc("LINK_TO_ROUTE_TIMEOUT")+']';
|
||||||
|
}
|
||||||
|
function showRouteDescription(response) {
|
||||||
|
// compute query string
|
||||||
|
var query_string = '?z='+ map.getZoom();
|
||||||
|
for(var i=0; i<my_markers.route.length; i++)
|
||||||
|
query_string += '&loc=' + my_markers.route[i].getLat() + ',' + my_markers.route[i].getLng();
|
||||||
|
|
||||||
|
// create link to the route
|
||||||
|
var route_link ='<span class="route-summary" id="route-prelink">[<a id="gpx-link" href="#" onclick="onClickCreateShortcut(\'' + OSRM.DEFAULTS.WEBSITE_URL + query_string + '\')">'+OSRM.loc("GET_LINK")+'</a>]</span>';
|
||||||
|
|
||||||
|
// create GPX link
|
||||||
|
var gpx_link = '<span class="route-summary">[<a id="gpx-link" onClick="javascript: document.location.href=\'' + OSRM.DEFAULTS.HOST_ROUTING_URL + query_string + '&output=gpx\';">'+OSRM.loc("GPX_FILE")+'</a>]</span>';
|
||||||
|
|
||||||
|
// create route description
|
||||||
|
var route_desc = "";
|
||||||
|
route_desc += '<table class="results-table">';
|
||||||
|
|
||||||
|
for(var i=0; i < response.route_instructions.length; i++){
|
||||||
|
//odd or even ?
|
||||||
|
var rowstyle='results-odd';
|
||||||
|
if(i%2==0) { rowstyle='results-even'; }
|
||||||
|
|
||||||
|
route_desc += '<tr class="'+rowstyle+'">';
|
||||||
|
|
||||||
|
route_desc += '<td class="result-directions">';
|
||||||
|
route_desc += '<img width="18px" src="images/'+getDirectionIcon(response.route_instructions[i][0])+'"/>';
|
||||||
|
route_desc += "</td>";
|
||||||
|
|
||||||
|
route_desc += '<td class="result-items">';
|
||||||
|
route_desc += '<span class="result-item" onclick="onClickRouteDescription('+response.route_instructions[i][3]+')">';
|
||||||
|
route_desc += response.route_instructions[i][0];
|
||||||
|
if( i == 0 )
|
||||||
|
route_desc += ' ' + OSRM.loc( response.route_instructions[i][6] );
|
||||||
|
if( response.route_instructions[i][1] != "" ) {
|
||||||
|
route_desc += ' on ';
|
||||||
|
route_desc += '<b>' + response.route_instructions[i][1] + '</b>';
|
||||||
|
}
|
||||||
|
//route_desc += ' for ';
|
||||||
|
route_desc += '</span>';
|
||||||
|
route_desc += "</td>";
|
||||||
|
|
||||||
|
route_desc += '<td class="result-distance">';
|
||||||
|
if( i != response.route_instructions.length-1 )
|
||||||
|
route_desc += '<b>'+getDistanceWithUnit(response.route_instructions[i][2])+'</b>';
|
||||||
|
route_desc += "</td>";
|
||||||
|
|
||||||
|
route_desc += "</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
route_desc += '</table>';
|
||||||
|
headline = "";
|
||||||
|
headline += OSRM.loc("ROUTE_DESCRIPTION")+":<br>";
|
||||||
|
headline += '<div style="float:left;width:40%">';
|
||||||
|
headline += "<span class='route-summary'>"
|
||||||
|
+ OSRM.loc("DISTANCE")+": " + getDistanceWithUnit(response.route_summary.total_distance)
|
||||||
|
+ "<br>"
|
||||||
|
+ OSRM.loc("DURATION")+": " + secondsToTime(response.route_summary.total_time)
|
||||||
|
+ "</span>";
|
||||||
|
headline += '</div>';
|
||||||
|
headline += '<div style="float:left;text-align:right;width:60%;">'+route_link+'<br>'+gpx_link+'</div>';
|
||||||
|
|
||||||
|
var output = "";
|
||||||
|
output += route_desc;
|
||||||
|
|
||||||
|
document.getElementById('information-box-headline').innerHTML = headline;
|
||||||
|
document.getElementById('information-box').innerHTML = output;
|
||||||
|
}
|
||||||
|
function showRouteDescriptionSimple(response) {
|
||||||
|
headline = OSRM.loc("ROUTE_DESCRIPTION")+":<br>";
|
||||||
|
headline += "<span class='route-summary'>"
|
||||||
|
+ OSRM.loc("DISTANCE")+": " + getDistanceWithUnit(response.route_summary.total_distance)
|
||||||
|
+ "<br>"
|
||||||
|
+ OSRM.loc("DURATION")+": " + secondsToTime(response.route_summary.total_time)
|
||||||
|
+ "</span>";
|
||||||
|
headline += '<br><br>';
|
||||||
|
|
||||||
|
document.getElementById('information-box-headline').innerHTML = headline;
|
||||||
|
document.getElementById('information-box').innerHTML = "<br><p style='font-size:14px;font-weight:bold;text-align:center;'>"+OSRM.loc("YOUR_ROUTE_IS_BEING_COMPUTED")+".<p>";
|
||||||
|
}
|
||||||
|
function showNoRouteDescription() {
|
||||||
|
headline = OSRM.loc("ROUTE_DESCRIPTION")+":<br>";
|
||||||
|
headline += "<span class='route-summary'>"
|
||||||
|
+ OSRM.loc("DISTANCE")+": N/A"
|
||||||
|
+ "<br>"
|
||||||
|
+ OSRM.loc("DURATION")+": N/A"
|
||||||
|
+ "</span>";
|
||||||
|
headline += '<br><br>';
|
||||||
|
|
||||||
|
document.getElementById('information-box-headline').innerHTML = headline;
|
||||||
|
document.getElementById('information-box').innerHTML = "<br><p style='font-size:14px;font-weight:bold;text-align:center;'>"+OSRM.loc("YOUR_ROUTE_IS_BEING_COMPUTED")+".<p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unnamed streets display
|
||||||
|
function showRouteNonames(response) {
|
||||||
|
// do not display unnamed streets?
|
||||||
|
if( document.getElementById('option-highlight-nonames').checked == false) {
|
||||||
|
my_route.hideUnnamedRoute();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark geometry positions where unnamed/named streets switch
|
||||||
|
var named = [];
|
||||||
|
for (var i = 0; i < response.route_instructions.length; i++) {
|
||||||
|
if( response.route_instructions[i][1] == '' )
|
||||||
|
named[ response.route_instructions[i][3] ] = false; // no street name
|
||||||
|
else
|
||||||
|
named[ response.route_instructions[i][3] ] = true; // yes street name
|
||||||
|
}
|
||||||
|
|
||||||
|
// aggregate geometry for unnamed streets
|
||||||
|
var geometry = decodeRouteGeometry(response.route_geometry, 5);
|
||||||
|
var is_named = true;
|
||||||
|
var current_positions = [];
|
||||||
|
var all_positions = [];
|
||||||
|
for( var i=0; i < geometry.length; i++) {
|
||||||
|
current_positions.push( new L.LatLng(geometry[i][0], geometry[i][1]) );
|
||||||
|
|
||||||
|
// still named/unnamed?
|
||||||
|
if( (named[i] == is_named || named[i] == undefined) && i != geometry.length-1 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// switch between named/unnamed!
|
||||||
|
if(is_named == false)
|
||||||
|
all_positions.push( current_positions );
|
||||||
|
current_positions = [];
|
||||||
|
current_positions.push( new L.LatLng(geometry[i][0], geometry[i][1]) );
|
||||||
|
is_named = named[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// display unnamed streets
|
||||||
|
my_route.showUnnamedRoute(all_positions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-- main function --
|
||||||
|
|
||||||
|
// generate server calls to query routes
|
||||||
|
function getRoute(do_description) {
|
||||||
|
|
||||||
|
// if source or target are not set -> hide route
|
||||||
|
if( my_markers.route.length < 2 ) {
|
||||||
|
my_route.hideRoute();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare JSONP call
|
||||||
|
var type = undefined;
|
||||||
|
var callback = undefined;
|
||||||
|
var timeout = undefined;
|
||||||
|
|
||||||
|
var source = OSRM.DEFAULTS.HOST_ROUTING_URL;
|
||||||
|
source += '?z=' + map.getZoom() + '&output=json' + '&geomformat=cmp';
|
||||||
|
if(my_markers.checksum)
|
||||||
|
source += '&checksum=' + my_markers.checksum;
|
||||||
|
for(var i=0; i<my_markers.route.length; i++) {
|
||||||
|
source += '&loc=' + my_markers.route[i].getLat() + ',' + my_markers.route[i].getLng();
|
||||||
|
if( my_markers.route[i].hint)
|
||||||
|
source += '&hint=' + my_markers.route[i].hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
// decide whether it is a dragging call or a normal one
|
||||||
|
if (do_description) {
|
||||||
|
callback = showRoute;
|
||||||
|
timeout = timeoutRoute;
|
||||||
|
source +='&instructions=true';
|
||||||
|
type = 'route';
|
||||||
|
} else {
|
||||||
|
callback = showRouteSimple;
|
||||||
|
timeout = timeoutRouteSimple;
|
||||||
|
source +='&instructions=false';
|
||||||
|
type = 'dragging';
|
||||||
|
}
|
||||||
|
|
||||||
|
// do call
|
||||||
|
var called = OSRM.JSONP.call(source, callback, timeout, OSRM.DEFAULTS.JSONP_TIMEOUT, type);
|
||||||
|
|
||||||
|
// TODO: hack to process final drag event, if it was fenced, but we are still dragging
|
||||||
|
if(called == false && !do_description) {
|
||||||
|
clearTimeout(OSRM.pendingTimer);
|
||||||
|
OSRM.pendingTimer = setTimeout(timeoutDrag,OSRM.DEFAULTS.JSONP_TIMEOUT);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
clearTimeout(OSRM.pendingTimer);
|
||||||
|
}
|
||||||
|
// // TODO: hack to process final drag event, if it was fenced, but we are still dragging (alternative approach)
|
||||||
|
// if(called == false && !do_description) {
|
||||||
|
// OSRM.pending = true;
|
||||||
|
// } else {
|
||||||
|
// clearTimeout(OSRM.pendingTimer);
|
||||||
|
// OSRM.pending = false;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
function timeoutDrag() {
|
||||||
|
my_markers.route[OSRM.dragid].hint = undefined;
|
||||||
|
getRoute(OSRM.NO_DESCRIPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-- helper functions --
|
||||||
|
|
||||||
|
//decode compressed route geometry
|
||||||
|
function decodeRouteGeometry(encoded, precision) {
|
||||||
|
precision = Math.pow(10, -precision);
|
||||||
|
var len = encoded.length, index=0, lat=0, lng = 0, array = [];
|
||||||
|
while (index < len) {
|
||||||
|
var b, shift = 0, result = 0;
|
||||||
|
do {
|
||||||
|
b = encoded.charCodeAt(index++) - 63;
|
||||||
|
result |= (b & 0x1f) << shift;
|
||||||
|
shift += 5;
|
||||||
|
} while (b >= 0x20);
|
||||||
|
var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
|
||||||
|
lat += dlat;
|
||||||
|
shift = 0;
|
||||||
|
result = 0;
|
||||||
|
do {
|
||||||
|
b = encoded.charCodeAt(index++) - 63;
|
||||||
|
result |= (b & 0x1f) << shift;
|
||||||
|
shift += 5;
|
||||||
|
} while (b >= 0x20);
|
||||||
|
var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
|
||||||
|
lng += dlng;
|
||||||
|
array.push([lat * precision, lng * precision]);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update hints of all markers
|
||||||
|
function updateHints(response) {
|
||||||
|
var hint_locations = response.hint_data.locations;
|
||||||
|
my_markers.checksum = response.hint_data.checksum;
|
||||||
|
for(var i=0; i<hint_locations.length; i++)
|
||||||
|
my_markers.route[i].hint = hint_locations[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// snap all markers to the received route
|
||||||
|
function snapRoute() {
|
||||||
|
var positions = my_route.getPositions();
|
||||||
|
|
||||||
|
my_markers.route[0].setPosition( positions[0] );
|
||||||
|
my_markers.route[my_markers.route.length-1].setPosition( positions[positions.length-1] );
|
||||||
|
for(var i=0; i<via_points.length; i++)
|
||||||
|
my_markers.route[i+1].setPosition( new L.LatLng(via_points[i][0], via_points[i][1]) );
|
||||||
|
|
||||||
|
// updateLocation( "source" );
|
||||||
|
// updateLocation( "target" );
|
||||||
|
|
||||||
|
//if(OSRM.dragid == 0 && my_markers.hasSource()==true)
|
||||||
|
updateReverseGeocoder("source");
|
||||||
|
//else if(OSRM.dragid == my_markers.route.length-1 && my_markers.hasTarget()==true)
|
||||||
|
updateReverseGeocoder("target");
|
||||||
|
}
|
||||||
|
|
||||||
|
// map driving instructions to icons
|
||||||
|
// [TODO: better implementation, language-safe]
|
||||||
|
function getDirectionIcon(name) {
|
||||||
|
var directions = {
|
||||||
|
"Turn left":"turn-left.png",
|
||||||
|
"Turn right":"turn-right.png",
|
||||||
|
"U-Turn":"u-turn.png",
|
||||||
|
"Head":"continue.png",
|
||||||
|
"Continue":"continue.png",
|
||||||
|
"Turn slight left":"slight-left.png",
|
||||||
|
"Turn slight right":"slight-right.png",
|
||||||
|
"Turn sharp left":"sharp-left.png",
|
||||||
|
"Turn sharp right":"sharp-right.png",
|
||||||
|
"Enter roundabout and leave at first exit":"round-about.png",
|
||||||
|
"Enter roundabout and leave at second exit":"round-about.png",
|
||||||
|
"Enter roundabout and leave at third exit":"round-about.png",
|
||||||
|
"Enter roundabout and leave at forth exit":"round-about.png",
|
||||||
|
"Enter roundabout and leave at fifth exit":"round-about.png",
|
||||||
|
"Enter roundabout and leave at sixth exit":"round-about.png",
|
||||||
|
"Enter roundabout and leave at seventh exit":"round-about.png",
|
||||||
|
"Enter roundabout and leave at eighth exit":"round-about.png",
|
||||||
|
"Enter roundabout and leave at nineth exit":"round-about.png",
|
||||||
|
"Enter roundabout and leave at tenth exit":"round-about.png",
|
||||||
|
"Enter roundabout and leave at one of the too many exit":"round-about.png",
|
||||||
|
"You have reached your destination":"target.png"
|
||||||
|
};
|
||||||
|
|
||||||
|
if( directions[name] )
|
||||||
|
return directions[name];
|
||||||
|
else
|
||||||
|
return "default.png";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -- gui functions --
|
||||||
|
|
||||||
|
// click: button "reset"
|
||||||
|
function resetRouting() {
|
||||||
|
document.getElementById('input-source-name').value = "";
|
||||||
|
document.getElementById('input-target-name').value = "";
|
||||||
|
|
||||||
|
my_route.hideAll();
|
||||||
|
my_markers.removeAll();
|
||||||
|
my_markers.highlight.hide();
|
||||||
|
|
||||||
|
document.getElementById('information-box').innerHTML = "";
|
||||||
|
document.getElementById('information-box-headline').innerHTML = "";
|
||||||
|
|
||||||
|
OSRM.JSONP.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// click: button "reverse"
|
||||||
|
function reverseRouting() {
|
||||||
|
// invert input boxes
|
||||||
|
var tmp = document.getElementById("input-source-name").value;
|
||||||
|
document.getElementById("input-source-name").value = document.getElementById("input-target-name").value;
|
||||||
|
document.getElementById("input-target-name").value = tmp;
|
||||||
|
|
||||||
|
// invert route
|
||||||
|
my_markers.route.reverse();
|
||||||
|
if(my_markers.route.length == 1) {
|
||||||
|
if(my_markers.route[0].label == OSRM.TARGET_MARKER_LABEL) {
|
||||||
|
my_markers.route[0].label = OSRM.SOURCE_MARKER_LABEL;
|
||||||
|
my_markers.route[0].marker.setIcon( new L.Icon('images/marker-source.png') );
|
||||||
|
} else if(my_markers.route[0].label == OSRM.SOURCE_MARKER_LABEL) {
|
||||||
|
my_markers.route[0].label = OSRM.TARGET_MARKER_LABEL;
|
||||||
|
my_markers.route[0].marker.setIcon( new L.Icon('images/marker-target.png') );
|
||||||
|
}
|
||||||
|
} else if(my_markers.route.length > 1){
|
||||||
|
my_markers.route[0].label = OSRM.SOURCE_MARKER_LABEL;
|
||||||
|
my_markers.route[0].marker.setIcon( new L.Icon('images/marker-source.png') );
|
||||||
|
|
||||||
|
my_markers.route[my_markers.route.length-1].label = OSRM.TARGET_MARKER_LABEL;
|
||||||
|
my_markers.route[my_markers.route.length-1].marker.setIcon( new L.Icon('images/marker-target.png') );
|
||||||
|
}
|
||||||
|
|
||||||
|
// recompute route
|
||||||
|
if( my_route.isShown() ) {
|
||||||
|
getRoute(OSRM.FULL_DESCRIPTION);
|
||||||
|
my_markers.highlight.hide();
|
||||||
|
} else {
|
||||||
|
document.getElementById('information-box').innerHTML = "";
|
||||||
|
document.getElementById('information-box-headline').innerHTML = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// click: button "show"
|
||||||
|
function centerMarker(marker_id) {
|
||||||
|
if( marker_id == OSRM.SOURCE_MARKER_LABEL && my_markers.route[0] && my_markers.route[0].label == OSRM.SOURCE_MARKER_LABEL && !my_markers.route[0].dirty_type ) {
|
||||||
|
my_markers.route[0].centerView();
|
||||||
|
} else if( marker_id == OSRM.TARGET_MARKER_LABEL && my_markers.route[my_markers.route.length-1] && my_markers.route[my_markers.route.length-1].label == OSRM.TARGET_MARKER_LABEL && !my_markers.route[my_markers.route.length-1].dirty_type) {
|
||||||
|
my_markers.route[my_markers.route.length-1].centerView();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// compatibility tools for old browsers
|
||||||
|
function getElementsByClassName(node, classname) {
|
||||||
|
var a = [];
|
||||||
|
var re = new RegExp('(^| )'+classname+'( |$)');
|
||||||
|
var els = node.getElementsByTagName("*");
|
||||||
|
for(var i=0,j=els.length; i<j; i++)
|
||||||
|
if(re.test(els[i].className))a.push(els[i]);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
document.head = document.head || document.getElementsByTagName('head')[0];
|
||||||
|
|
||||||
|
// ------------------------------------------------------
|
||||||
|
|
||||||
|
// human readable time
|
||||||
|
function secondsToTime(seconds){
|
||||||
|
seconds = parseInt(seconds);
|
||||||
|
minutes = parseInt(seconds/60);
|
||||||
|
seconds = seconds%60;
|
||||||
|
hours = parseInt(minutes/60);
|
||||||
|
minutes = minutes%60;
|
||||||
|
if(hours==0){
|
||||||
|
return minutes + ' ' + 'min';
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return hours + ' ' + 'h' + ' ' + minutes + ' ' + 'min';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// human readable distance
|
||||||
|
function getDistanceWithUnit(distance){
|
||||||
|
distance = parseInt(distance);
|
||||||
|
|
||||||
|
if(distance >= 100000){ return (parseInt(distance/1000))+' ' + 'km'; }
|
||||||
|
else if(distance >= 10000){ return (parseInt(distance/1000).toFixed(1))+' ' + 'km'; }
|
||||||
|
else if(distance >= 1000){ return (parseFloat(distance/1000).toFixed(2))+' ' + 'km'; }
|
||||||
|
else{ return distance+' ' + 'm'; }
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// verify angles
|
||||||
|
function isLatitude(value) {
|
||||||
|
if( value >=-90 && value <=90)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function isLongitude(value) {
|
||||||
|
if( value >=-180 && value <=180)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------
|
||||||
|
|
||||||
|
// distance between two points
|
||||||
|
function distanceBetweenPoint(x1, y1, x2, y2) {
|
||||||
|
var a = x1 - x2;
|
||||||
|
var b = y1 - y2;
|
||||||
|
return Math.sqrt(a*a + b*b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// distance from a point to a line or segment
|
||||||
|
// (x,y) point
|
||||||
|
// (x0,y0) line point A
|
||||||
|
// (x1,y1) line point B
|
||||||
|
// o specifies if the distance should respect the limits of the segment (overLine = true)
|
||||||
|
// or if it should consider the segment as an infinite line (overLine = false);
|
||||||
|
// if false returns the distance from the point to the line,
|
||||||
|
// otherwise the distance from the point to the segment
|
||||||
|
function dotLineLength(x, y, x0, y0, x1, y1, o){
|
||||||
|
function lineLength(x, y, x0, y0){return Math.sqrt((x -= x0) * x + (y -= y0) * y);}
|
||||||
|
|
||||||
|
if(o && !(o = function(x, y, x0, y0, x1, y1){
|
||||||
|
if(!(x1 - x0)) return {x: x0, y: y};
|
||||||
|
else if(!(y1 - y0)) return {x: x, y: y0};
|
||||||
|
var left, tg = -1 / ((y1 - y0) / (x1 - x0));
|
||||||
|
return {x: left = (x1 * (x * tg - y + y0) + x0 * (x * - tg + y - y1)) / (tg * (x1 - x0) + y0 - y1), y: tg * left - tg * x + y};
|
||||||
|
}(x, y, x0, y0, x1, y1) && o.x >= Math.min(x0, x1) && o.x <= Math.max(x0, x1) && o.y >= Math.min(y0, y1) && o.y <= Math.max(y0, y1))){
|
||||||
|
var l1 = lineLength(x, y, x0, y0), l2 = lineLength(x, y, x1, y1);
|
||||||
|
return l1 > l2 ? l2 : l1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var a = y0 - y1, b = x1 - x0, c = x0 * y1 - y0 * x1;
|
||||||
|
return Math.abs(a * x + b * y + c) / Math.sqrt(a * a + b * b);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// store location of via points returned by server
|
||||||
|
var via_points;
|
||||||
|
|
||||||
|
|
||||||
|
// find route segment of current route geometry that is closest to the new via node (marked by index of its endpoint)
|
||||||
|
function findNearestRouteSegment( new_via ) {
|
||||||
|
var min_dist = Number.MAX_VALUE;
|
||||||
|
var min_index = undefined;
|
||||||
|
|
||||||
|
var positions = my_route.getPositions();
|
||||||
|
for(var i=0; i<positions.length-1; i++) {
|
||||||
|
var dist = dotLineLength( new_via.lng, new_via.lat, positions[i].lng, positions[i].lat, positions[i+1].lng, positions[i+1].lat, true);
|
||||||
|
if( dist < min_dist) {
|
||||||
|
min_dist = dist;
|
||||||
|
min_index = i+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return min_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// find the correct index among all via nodes to insert the new via node, and insert it
|
||||||
|
function findViaPosition( new_via_position ) {
|
||||||
|
// find route segment that is closest to click position (marked by last index)
|
||||||
|
var nearest_index = findNearestRouteSegment( new_via_position );
|
||||||
|
|
||||||
|
// find correct index to insert new via node
|
||||||
|
var new_via_index = via_points.length;
|
||||||
|
var via_index = Array();
|
||||||
|
for(var i=0; i<via_points.length; i++) {
|
||||||
|
via_index[i] = findNearestRouteSegment( new L.LatLng(via_points[i][0], via_points[i][1]) );
|
||||||
|
if(via_index[i] > nearest_index) {
|
||||||
|
new_via_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add via node
|
||||||
|
var index = my_markers.setVia(new_via_index, new_via_position);
|
||||||
|
my_markers.route[index].show();
|
||||||
|
|
||||||
|
getRoute(OSRM.FULL_DESCRIPTION);
|
||||||
|
|
||||||
|
return new_via_index;
|
||||||
|
}
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2015, Project OSRM contributors
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BAYES_CLASSIFIER_HPP
|
|
||||||
#define BAYES_CLASSIFIER_HPP
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct NormalDistribution
|
|
||||||
{
|
|
||||||
NormalDistribution(const double mean, const double standard_deviation)
|
|
||||||
: mean(mean), standard_deviation(standard_deviation)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME implement log-probability version since its faster
|
|
||||||
double density_function(const double val) const
|
|
||||||
{
|
|
||||||
const double x = val - mean;
|
|
||||||
return 1.0 / (std::sqrt(2. * M_PI) * standard_deviation) *
|
|
||||||
std::exp(-x * x / (standard_deviation * standard_deviation));
|
|
||||||
}
|
|
||||||
|
|
||||||
double mean;
|
|
||||||
double standard_deviation;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LaplaceDistribution
|
|
||||||
{
|
|
||||||
LaplaceDistribution(const double location, const double scale)
|
|
||||||
: location(location), scale(scale)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME implement log-probability version since its faster
|
|
||||||
double density_function(const double val) const
|
|
||||||
{
|
|
||||||
const double x = std::abs(val - location);
|
|
||||||
return 1.0 / (2. * scale) * std::exp(-x / scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
double location;
|
|
||||||
double scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename PositiveDistributionT, typename NegativeDistributionT, typename ValueT>
|
|
||||||
class BayesClassifier
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum class ClassLabel : unsigned
|
|
||||||
{
|
|
||||||
NEGATIVE,
|
|
||||||
POSITIVE
|
|
||||||
};
|
|
||||||
using ClassificationT = std::pair<ClassLabel, double>;
|
|
||||||
|
|
||||||
BayesClassifier(const PositiveDistributionT &positive_distribution,
|
|
||||||
const NegativeDistributionT &negative_distribution,
|
|
||||||
const double positive_apriori_probability)
|
|
||||||
: positive_distribution(positive_distribution),
|
|
||||||
negative_distribution(negative_distribution),
|
|
||||||
positive_apriori_probability(positive_apriori_probability),
|
|
||||||
negative_apriori_probability(1. - positive_apriori_probability)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns label and the probability of the label.
|
|
||||||
ClassificationT classify(const ValueT &v) const
|
|
||||||
{
|
|
||||||
const double positive_postpriori =
|
|
||||||
positive_apriori_probability * positive_distribution.density_function(v);
|
|
||||||
const double negative_postpriori =
|
|
||||||
negative_apriori_probability * negative_distribution.density_function(v);
|
|
||||||
const double norm = positive_postpriori + negative_postpriori;
|
|
||||||
|
|
||||||
if (positive_postpriori > negative_postpriori)
|
|
||||||
{
|
|
||||||
return std::make_pair(ClassLabel::POSITIVE, positive_postpriori / norm);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_pair(ClassLabel::NEGATIVE, negative_postpriori / norm);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
PositiveDistributionT positive_distribution;
|
|
||||||
NegativeDistributionT negative_distribution;
|
|
||||||
double positive_apriori_probability;
|
|
||||||
double negative_apriori_probability;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // BAYES_CLASSIFIER_HPP
|
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2015, Project OSRM contributors
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BFS_COMPONENTS_HPP_
|
|
||||||
#define BFS_COMPONENTS_HPP_
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "../data_structures/restriction_map.hpp"
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
// Explores the components of the given graph while respecting turn restrictions
|
|
||||||
// and barriers.
|
|
||||||
template <typename GraphT> class BFSComponentExplorer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BFSComponentExplorer(const GraphT &dynamic_graph,
|
|
||||||
const RestrictionMap &restrictions,
|
|
||||||
const std::unordered_set<NodeID> &barrier_nodes)
|
|
||||||
: m_graph(dynamic_graph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the size of the component that the node belongs to.
|
|
||||||
*/
|
|
||||||
unsigned int GetComponentSize(const NodeID node) const
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(node < m_component_index_list.size());
|
|
||||||
|
|
||||||
return m_component_index_size[m_component_index_list[node]];
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int GetNumberOfComponents() { return m_component_index_size.size(); }
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Computes the component sizes.
|
|
||||||
*/
|
|
||||||
void run()
|
|
||||||
{
|
|
||||||
std::queue<std::pair<NodeID, NodeID>> bfs_queue;
|
|
||||||
unsigned current_component = 0;
|
|
||||||
|
|
||||||
BOOST_ASSERT(m_component_index_list.empty());
|
|
||||||
BOOST_ASSERT(m_component_index_size.empty());
|
|
||||||
|
|
||||||
unsigned num_nodes = m_graph.GetNumberOfNodes();
|
|
||||||
|
|
||||||
m_component_index_list.resize(num_nodes, std::numeric_limits<unsigned>::max());
|
|
||||||
|
|
||||||
BOOST_ASSERT(num_nodes > 0);
|
|
||||||
|
|
||||||
// put unexplorered node with parent pointer into queue
|
|
||||||
for (NodeID node = 0; node < num_nodes; ++node)
|
|
||||||
{
|
|
||||||
if (std::numeric_limits<unsigned>::max() == m_component_index_list[node])
|
|
||||||
{
|
|
||||||
unsigned size = ExploreComponent(bfs_queue, node, current_component);
|
|
||||||
|
|
||||||
// push size into vector
|
|
||||||
m_component_index_size.emplace_back(size);
|
|
||||||
++current_component;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/*!
|
|
||||||
* Explores the current component that starts at node using BFS.
|
|
||||||
*/
|
|
||||||
unsigned ExploreComponent(std::queue<std::pair<NodeID, NodeID>> &bfs_queue,
|
|
||||||
NodeID node,
|
|
||||||
unsigned current_component)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Graphical representation of variables:
|
|
||||||
|
|
||||||
u v w
|
|
||||||
*---------->*---------->*
|
|
||||||
e2
|
|
||||||
*/
|
|
||||||
|
|
||||||
bfs_queue.emplace(node, node);
|
|
||||||
// mark node as read
|
|
||||||
m_component_index_list[node] = current_component;
|
|
||||||
|
|
||||||
unsigned current_component_size = 1;
|
|
||||||
|
|
||||||
while (!bfs_queue.empty())
|
|
||||||
{
|
|
||||||
// fetch element from BFS queue
|
|
||||||
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
|
|
||||||
bfs_queue.pop();
|
|
||||||
|
|
||||||
const NodeID v = current_queue_item.first; // current node
|
|
||||||
const NodeID u = current_queue_item.second; // parent
|
|
||||||
// increment size counter of current component
|
|
||||||
++current_component_size;
|
|
||||||
if (m_barrier_nodes.find(v) != m_barrier_nodes.end())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const NodeID to_node_of_only_restriction =
|
|
||||||
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
|
|
||||||
|
|
||||||
for (auto e2 : m_graph.GetAdjacentEdgeRange(v))
|
|
||||||
{
|
|
||||||
const NodeID w = m_graph.GetTarget(e2);
|
|
||||||
|
|
||||||
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
|
|
||||||
w != to_node_of_only_restriction)
|
|
||||||
{
|
|
||||||
// At an only_-restriction but not at the right turn
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (u != w)
|
|
||||||
{
|
|
||||||
// only add an edge if turn is not a U-turn except
|
|
||||||
// when it is at the end of a dead-end street.
|
|
||||||
if (!m_restriction_map.CheckIfTurnIsRestricted(u, v, w))
|
|
||||||
{
|
|
||||||
// only add an edge if turn is not prohibited
|
|
||||||
if (std::numeric_limits<unsigned>::max() == m_component_index_list[w])
|
|
||||||
{
|
|
||||||
// insert next (node, parent) only if w has
|
|
||||||
// not yet been explored
|
|
||||||
// mark node as read
|
|
||||||
m_component_index_list[w] = current_component;
|
|
||||||
bfs_queue.emplace(w, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return current_component_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<unsigned> m_component_index_list;
|
|
||||||
std::vector<NodeID> m_component_index_size;
|
|
||||||
|
|
||||||
const GraphT &m_graph;
|
|
||||||
const RestrictionMap &m_restriction_map;
|
|
||||||
const std::unordered_set<NodeID> &m_barrier_nodes;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // BFS_COMPONENTS_HPP_
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2015, Project OSRM contributors
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ITERATOR_BASED_CRC32_H
|
|
||||||
#define ITERATOR_BASED_CRC32_H
|
|
||||||
|
|
||||||
#if defined(__x86_64__) && !defined(__MINGW64__)
|
|
||||||
#include <cpuid.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
|
||||||
|
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
class IteratorbasedCRC32
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool using_hardware() const { return use_hardware_implementation; }
|
|
||||||
|
|
||||||
IteratorbasedCRC32() : crc(0) { use_hardware_implementation = detect_hardware_support(); }
|
|
||||||
|
|
||||||
template <class Iterator> unsigned operator()(Iterator iter, const Iterator end)
|
|
||||||
{
|
|
||||||
unsigned crc = 0;
|
|
||||||
while (iter != end)
|
|
||||||
{
|
|
||||||
using value_type = typename std::iterator_traits<Iterator>::value_type;
|
|
||||||
const char *data = reinterpret_cast<const char *>(&(*iter));
|
|
||||||
|
|
||||||
if (use_hardware_implementation)
|
|
||||||
{
|
|
||||||
crc = compute_in_hardware(data, sizeof(value_type));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
crc = compute_in_software(data, sizeof(value_type));
|
|
||||||
}
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool detect_hardware_support() const
|
|
||||||
{
|
|
||||||
static const int sse42_bit = 0x00100000;
|
|
||||||
const unsigned ecx = cpuid();
|
|
||||||
const bool sse42_found = (ecx & sse42_bit) != 0;
|
|
||||||
return sse42_found;
|
|
||||||
}
|
|
||||||
|
|
||||||
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(const char *str, unsigned len)
|
|
||||||
{
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
unsigned q = len / sizeof(unsigned);
|
|
||||||
unsigned r = len % sizeof(unsigned);
|
|
||||||
unsigned *p = (unsigned *)str;
|
|
||||||
|
|
||||||
// crc=0;
|
|
||||||
while (q--)
|
|
||||||
{
|
|
||||||
__asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
|
||||||
: "=S"(crc)
|
|
||||||
: "0"(crc), "c"(*p));
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
|
|
||||||
str = reinterpret_cast<char *>(p);
|
|
||||||
while (r--)
|
|
||||||
{
|
|
||||||
__asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
|
||||||
: "=S"(crc)
|
|
||||||
: "0"(crc), "c"(*str));
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned cpuid() const
|
|
||||||
{
|
|
||||||
unsigned eax = 0, ebx = 0, ecx = 0, edx = 0;
|
|
||||||
// on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl.
|
|
||||||
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
|
|
||||||
return ecx;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__MINGW64__) || defined(_MSC_VER) || !defined(__x86_64__)
|
|
||||||
inline void
|
|
||||||
__get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) const
|
|
||||||
{
|
|
||||||
*ecx = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> crc_processor;
|
|
||||||
unsigned crc;
|
|
||||||
bool use_hardware_implementation;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RangebasedCRC32
|
|
||||||
{
|
|
||||||
template <typename Iteratable> unsigned operator()(const Iteratable &iterable)
|
|
||||||
{
|
|
||||||
return crc32(std::begin(iterable), std::end(iterable));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool using_hardware() const { return crc32.using_hardware(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
IteratorbasedCRC32 crc32;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* ITERATOR_BASED_CRC32_H */
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2015, Project OSRM contributors
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "douglas_peucker.hpp"
|
|
||||||
|
|
||||||
#include "../data_structures/segment_information.hpp"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <osrm/coordinate.hpp>
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
struct CoordinatePairCalculator
|
|
||||||
{
|
|
||||||
CoordinatePairCalculator() = delete;
|
|
||||||
CoordinatePairCalculator(const FixedPointCoordinate &coordinate_a,
|
|
||||||
const FixedPointCoordinate &coordinate_b)
|
|
||||||
{
|
|
||||||
// initialize distance calculator with two fixed coordinates a, b
|
|
||||||
const float RAD = 0.017453292519943295769236907684886f;
|
|
||||||
first_lat = (coordinate_a.lat / COORDINATE_PRECISION) * RAD;
|
|
||||||
first_lon = (coordinate_a.lon / COORDINATE_PRECISION) * RAD;
|
|
||||||
second_lat = (coordinate_b.lat / COORDINATE_PRECISION) * RAD;
|
|
||||||
second_lon = (coordinate_b.lon / COORDINATE_PRECISION) * RAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
int operator()(FixedPointCoordinate &other) const
|
|
||||||
{
|
|
||||||
// set third coordinate c
|
|
||||||
const float RAD = 0.017453292519943295769236907684886f;
|
|
||||||
const float earth_radius = 6372797.560856f;
|
|
||||||
const float float_lat1 = (other.lat / COORDINATE_PRECISION) * RAD;
|
|
||||||
const float float_lon1 = (other.lon / COORDINATE_PRECISION) * RAD;
|
|
||||||
|
|
||||||
// compute distance (a,c)
|
|
||||||
const float x_value_1 = (first_lon - float_lon1) * cos((float_lat1 + first_lat) / 2.f);
|
|
||||||
const float y_value_1 = first_lat - float_lat1;
|
|
||||||
const float dist1 = std::hypot(x_value_1, y_value_1) * earth_radius;
|
|
||||||
|
|
||||||
// compute distance (b,c)
|
|
||||||
const float x_value_2 = (second_lon - float_lon1) * cos((float_lat1 + second_lat) / 2.f);
|
|
||||||
const float y_value_2 = second_lat - float_lat1;
|
|
||||||
const float dist2 = std::hypot(x_value_2, y_value_2) * earth_radius;
|
|
||||||
|
|
||||||
// return the minimum
|
|
||||||
return static_cast<int>(std::min(dist1, dist2));
|
|
||||||
}
|
|
||||||
|
|
||||||
float first_lat;
|
|
||||||
float first_lon;
|
|
||||||
float second_lat;
|
|
||||||
float second_lon;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
|
|
||||||
{
|
|
||||||
Run(std::begin(input_geometry), std::end(input_geometry), zoom_level);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level)
|
|
||||||
{
|
|
||||||
const auto size = std::distance(begin, end);
|
|
||||||
if (size < 2)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
begin->necessary = true;
|
|
||||||
std::prev(end)->necessary = true;
|
|
||||||
|
|
||||||
{
|
|
||||||
BOOST_ASSERT_MSG(zoom_level < DOUGLAS_PEUCKER_THRESHOLDS.size(), "unsupported zoom level");
|
|
||||||
RandomAccessIt left_border = begin;
|
|
||||||
RandomAccessIt right_border = std::next(begin);
|
|
||||||
// Sweep over array and identify those ranges that need to be checked
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// traverse list until new border element found
|
|
||||||
if (right_border->necessary)
|
|
||||||
{
|
|
||||||
// sanity checks
|
|
||||||
BOOST_ASSERT(left_border->necessary);
|
|
||||||
BOOST_ASSERT(right_border->necessary);
|
|
||||||
recursion_stack.emplace(left_border, right_border);
|
|
||||||
left_border = right_border;
|
|
||||||
}
|
|
||||||
++right_border;
|
|
||||||
} while (right_border != end);
|
|
||||||
}
|
|
||||||
|
|
||||||
// mark locations as 'necessary' by divide-and-conquer
|
|
||||||
while (!recursion_stack.empty())
|
|
||||||
{
|
|
||||||
// pop next element
|
|
||||||
const GeometryRange pair = recursion_stack.top();
|
|
||||||
recursion_stack.pop();
|
|
||||||
// sanity checks
|
|
||||||
BOOST_ASSERT_MSG(pair.first->necessary, "left border must be necessary");
|
|
||||||
BOOST_ASSERT_MSG(pair.second->necessary, "right border must be necessary");
|
|
||||||
BOOST_ASSERT_MSG(std::distance(pair.second, end) > 0, "right border outside of geometry");
|
|
||||||
BOOST_ASSERT_MSG(std::distance(pair.first, pair.second) >= 0,
|
|
||||||
"left border on the wrong side");
|
|
||||||
|
|
||||||
int max_int_distance = 0;
|
|
||||||
auto farthest_entry_it = pair.second;
|
|
||||||
const CoordinatePairCalculator dist_calc(pair.first->location, pair.second->location);
|
|
||||||
|
|
||||||
// sweep over range to find the maximum
|
|
||||||
for (auto it = std::next(pair.first); it != pair.second; ++it)
|
|
||||||
{
|
|
||||||
const int distance = dist_calc(it->location);
|
|
||||||
// found new feasible maximum?
|
|
||||||
if (distance > max_int_distance && distance > DOUGLAS_PEUCKER_THRESHOLDS[zoom_level])
|
|
||||||
{
|
|
||||||
farthest_entry_it = it;
|
|
||||||
max_int_distance = distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if maximum violates a zoom level dependent threshold
|
|
||||||
if (max_int_distance > DOUGLAS_PEUCKER_THRESHOLDS[zoom_level])
|
|
||||||
{
|
|
||||||
// mark idx as necessary
|
|
||||||
farthest_entry_it->necessary = true;
|
|
||||||
if (1 < std::distance(pair.first, farthest_entry_it))
|
|
||||||
{
|
|
||||||
recursion_stack.emplace(pair.first, farthest_entry_it);
|
|
||||||
}
|
|
||||||
if (1 < std::distance(farthest_entry_it, pair.second))
|
|
||||||
{
|
|
||||||
recursion_stack.emplace(farthest_entry_it, pair.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM contributors
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DOUGLAS_PEUCKER_HPP_
|
|
||||||
#define DOUGLAS_PEUCKER_HPP_
|
|
||||||
|
|
||||||
#include "../data_structures/segment_information.hpp"
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <stack>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/* This class object computes the bitvector of indicating generalized input
|
|
||||||
* points according to the (Ramer-)Douglas-Peucker algorithm.
|
|
||||||
*
|
|
||||||
* Input is vector of pairs. Each pair consists of the point information and a
|
|
||||||
* bit indicating if the points is present in the generalization.
|
|
||||||
* Note: points may also be pre-selected*/
|
|
||||||
|
|
||||||
static const std::array<int, 19> DOUGLAS_PEUCKER_THRESHOLDS{{
|
|
||||||
512440, // z0
|
|
||||||
256720, // z1
|
|
||||||
122560, // z2
|
|
||||||
56780, // z3
|
|
||||||
28800, // z4
|
|
||||||
14400, // z5
|
|
||||||
7200, // z6
|
|
||||||
3200, // z7
|
|
||||||
2400, // z8
|
|
||||||
1000, // z9
|
|
||||||
600, // z10
|
|
||||||
120, // z11
|
|
||||||
60, // z12
|
|
||||||
45, // z13
|
|
||||||
36, // z14
|
|
||||||
20, // z15
|
|
||||||
8, // z16
|
|
||||||
6, // z17
|
|
||||||
4 // z18
|
|
||||||
}};
|
|
||||||
|
|
||||||
class DouglasPeucker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using RandomAccessIt = std::vector<SegmentInformation>::iterator;
|
|
||||||
|
|
||||||
using GeometryRange = std::pair<RandomAccessIt, RandomAccessIt>;
|
|
||||||
// Stack to simulate the recursion
|
|
||||||
std::stack<GeometryRange> recursion_stack;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level);
|
|
||||||
void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* DOUGLAS_PEUCKER_HPP_ */
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2015, Project OSRM contributors
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef OBJECT_ENCODER_HPP
|
|
||||||
#define OBJECT_ENCODER_HPP
|
|
||||||
|
|
||||||
#include "../util/string_util.hpp"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
|
||||||
#include <boost/archive/iterators/binary_from_base64.hpp>
|
|
||||||
#include <boost/archive/iterators/transform_width.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct ObjectEncoder
|
|
||||||
{
|
|
||||||
using base64_t = boost::archive::iterators::base64_from_binary<
|
|
||||||
boost::archive::iterators::transform_width<const char *, 6, 8>>;
|
|
||||||
|
|
||||||
using binary_t = boost::archive::iterators::transform_width<
|
|
||||||
boost::archive::iterators::binary_from_base64<std::string::const_iterator>,
|
|
||||||
8,
|
|
||||||
6>;
|
|
||||||
|
|
||||||
template <class ObjectT> static void EncodeToBase64(const ObjectT &object, std::string &encoded)
|
|
||||||
{
|
|
||||||
const char *char_ptr_to_object = reinterpret_cast<const char *>(&object);
|
|
||||||
std::vector<unsigned char> data(sizeof(object));
|
|
||||||
std::copy(char_ptr_to_object, char_ptr_to_object + sizeof(ObjectT), data.begin());
|
|
||||||
|
|
||||||
unsigned char number_of_padded_chars = 0; // is in {0,1,2};
|
|
||||||
while (data.size() % 3 != 0)
|
|
||||||
{
|
|
||||||
++number_of_padded_chars;
|
|
||||||
data.push_back(0x00);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(0 == data.size() % 3, "base64 input data size is not a multiple of 3!");
|
|
||||||
encoded.resize(sizeof(ObjectT));
|
|
||||||
encoded.assign(base64_t(&data[0]),
|
|
||||||
base64_t(&data[0] + (data.size() - number_of_padded_chars)));
|
|
||||||
replaceAll(encoded, "+", "-");
|
|
||||||
replaceAll(encoded, "/", "_");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class ObjectT> static void DecodeFromBase64(const std::string &input, ObjectT &object)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::string encoded(input);
|
|
||||||
// replace "-" with "+" and "_" with "/"
|
|
||||||
replaceAll(encoded, "-", "+");
|
|
||||||
replaceAll(encoded, "_", "/");
|
|
||||||
|
|
||||||
std::copy(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1),
|
|
||||||
reinterpret_cast<char *>(&object));
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* OBJECT_ENCODER_HPP */
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2014, Project OSRM contributors
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "polyline_compressor.hpp"
|
|
||||||
#include "../data_structures/segment_information.hpp"
|
|
||||||
|
|
||||||
#include <osrm/coordinate.hpp>
|
|
||||||
|
|
||||||
std::string PolylineCompressor::encode_vector(std::vector<int> &numbers) const
|
|
||||||
{
|
|
||||||
std::string output;
|
|
||||||
const auto end = numbers.size();
|
|
||||||
for (std::size_t i = 0; i < end; ++i)
|
|
||||||
{
|
|
||||||
numbers[i] <<= 1;
|
|
||||||
if (numbers[i] < 0)
|
|
||||||
{
|
|
||||||
numbers[i] = ~(numbers[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const int number : numbers)
|
|
||||||
{
|
|
||||||
output += encode_number(number);
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PolylineCompressor::encode_number(int number_to_encode) const
|
|
||||||
{
|
|
||||||
std::string output;
|
|
||||||
while (number_to_encode >= 0x20)
|
|
||||||
{
|
|
||||||
const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
|
|
||||||
output += static_cast<char>(next_value);
|
|
||||||
number_to_encode >>= 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
number_to_encode += 63;
|
|
||||||
output += static_cast<char>(number_to_encode);
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
PolylineCompressor::get_encoded_string(const std::vector<SegmentInformation> &polyline) const
|
|
||||||
{
|
|
||||||
if (polyline.empty())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<int> delta_numbers;
|
|
||||||
delta_numbers.reserve((polyline.size() - 1) * 2);
|
|
||||||
FixedPointCoordinate previous_coordinate = {0, 0};
|
|
||||||
for (const auto &segment : polyline)
|
|
||||||
{
|
|
||||||
if (segment.necessary)
|
|
||||||
{
|
|
||||||
const int lat_diff = segment.location.lat - previous_coordinate.lat;
|
|
||||||
const int lon_diff = segment.location.lon - previous_coordinate.lon;
|
|
||||||
delta_numbers.emplace_back(lat_diff);
|
|
||||||
delta_numbers.emplace_back(lon_diff);
|
|
||||||
previous_coordinate = segment.location;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return encode_vector(delta_numbers);
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM contributors
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef POLYLINECOMPRESSOR_H_
|
|
||||||
#define POLYLINECOMPRESSOR_H_
|
|
||||||
|
|
||||||
struct SegmentInformation;
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class PolylineCompressor
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::string encode_vector(std::vector<int> &numbers) const;
|
|
||||||
|
|
||||||
std::string encode_number(const int number_to_encode) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
std::string get_encoded_string(const std::vector<SegmentInformation> &polyline) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* POLYLINECOMPRESSOR_H_ */
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2015, Project OSRM contributors
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "polyline_formatter.hpp"
|
|
||||||
|
|
||||||
#include "polyline_compressor.hpp"
|
|
||||||
#include "../data_structures/segment_information.hpp"
|
|
||||||
|
|
||||||
#include <osrm/coordinate.hpp>
|
|
||||||
|
|
||||||
osrm::json::String
|
|
||||||
PolylineFormatter::printEncodedString(const std::vector<SegmentInformation> &polyline) const
|
|
||||||
{
|
|
||||||
return osrm::json::String(PolylineCompressor().get_encoded_string(polyline));
|
|
||||||
}
|
|
||||||
|
|
||||||
osrm::json::Array
|
|
||||||
PolylineFormatter::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
|
|
||||||
{
|
|
||||||
osrm::json::Array json_geometry_array;
|
|
||||||
for (const auto &segment : polyline)
|
|
||||||
{
|
|
||||||
if (segment.necessary)
|
|
||||||
{
|
|
||||||
osrm::json::Array json_coordinate;
|
|
||||||
json_coordinate.values.push_back(segment.location.lat / COORDINATE_PRECISION);
|
|
||||||
json_coordinate.values.push_back(segment.location.lon / COORDINATE_PRECISION);
|
|
||||||
json_geometry_array.values.push_back(json_coordinate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return json_geometry_array;
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2014, Project OSRM contributors
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef POLYLINE_FORMATTER_HPP
|
|
||||||
#define POLYLINE_FORMATTER_HPP
|
|
||||||
|
|
||||||
struct SegmentInformation;
|
|
||||||
|
|
||||||
#include <osrm/json_container.hpp>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct PolylineFormatter
|
|
||||||
{
|
|
||||||
osrm::json::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
|
|
||||||
|
|
||||||
osrm::json::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* POLYLINE_FORMATTER_HPP */
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2015, Project OSRM contributors
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EXTRACT_ROUTE_NAMES_H
|
|
||||||
#define EXTRACT_ROUTE_NAMES_H
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct RouteNames
|
|
||||||
{
|
|
||||||
std::string shortest_path_name_1;
|
|
||||||
std::string shortest_path_name_2;
|
|
||||||
std::string alternative_path_name_1;
|
|
||||||
std::string alternative_path_name_2;
|
|
||||||
};
|
|
||||||
|
|
||||||
// construct routes names
|
|
||||||
template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
SegmentT PickNextLongestSegment(const std::vector<SegmentT> &segment_list,
|
|
||||||
const unsigned blocked_name_id) const
|
|
||||||
{
|
|
||||||
SegmentT result_segment;
|
|
||||||
result_segment.length = 0;
|
|
||||||
|
|
||||||
for (const SegmentT &segment : segment_list)
|
|
||||||
{
|
|
||||||
if (segment.name_id != blocked_name_id && segment.length > result_segment.length &&
|
|
||||||
segment.name_id != 0)
|
|
||||||
{
|
|
||||||
result_segment = segment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result_segment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
RouteNames operator()(std::vector<SegmentT> &shortest_path_segments,
|
|
||||||
std::vector<SegmentT> &alternative_path_segments,
|
|
||||||
const DataFacadeT *facade) const
|
|
||||||
{
|
|
||||||
RouteNames route_names;
|
|
||||||
|
|
||||||
SegmentT shortest_segment_1, shortest_segment_2;
|
|
||||||
SegmentT alternative_segment_1, alternative_segment_2;
|
|
||||||
|
|
||||||
auto length_comperator = [](const SegmentT &a, const SegmentT &b)
|
|
||||||
{
|
|
||||||
return a.length > b.length;
|
|
||||||
};
|
|
||||||
auto name_id_comperator = [](const SegmentT &a, const SegmentT &b)
|
|
||||||
{
|
|
||||||
return a.name_id < b.name_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (shortest_path_segments.empty())
|
|
||||||
{
|
|
||||||
return route_names;
|
|
||||||
}
|
|
||||||
|
|
||||||
// pick the longest segment for the shortest path.
|
|
||||||
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator);
|
|
||||||
shortest_segment_1 = shortest_path_segments[0];
|
|
||||||
if (!alternative_path_segments.empty())
|
|
||||||
{
|
|
||||||
std::sort(alternative_path_segments.begin(), alternative_path_segments.end(),
|
|
||||||
length_comperator);
|
|
||||||
|
|
||||||
// also pick the longest segment for the alternative path
|
|
||||||
alternative_segment_1 = alternative_path_segments[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute the set difference (for shortest path) depending on names between shortest and
|
|
||||||
// alternative
|
|
||||||
std::vector<SegmentT> shortest_path_set_difference(shortest_path_segments.size());
|
|
||||||
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), name_id_comperator);
|
|
||||||
std::sort(alternative_path_segments.begin(), alternative_path_segments.end(),
|
|
||||||
name_id_comperator);
|
|
||||||
std::set_difference(shortest_path_segments.begin(), shortest_path_segments.end(),
|
|
||||||
alternative_path_segments.begin(), alternative_path_segments.end(),
|
|
||||||
shortest_path_set_difference.begin(), name_id_comperator);
|
|
||||||
|
|
||||||
std::sort(shortest_path_set_difference.begin(), shortest_path_set_difference.end(),
|
|
||||||
length_comperator);
|
|
||||||
shortest_segment_2 =
|
|
||||||
PickNextLongestSegment(shortest_path_set_difference, shortest_segment_1.name_id);
|
|
||||||
|
|
||||||
// compute the set difference (for alternative path) depending on names between shortest and
|
|
||||||
// alternative
|
|
||||||
// vectors are still sorted, no need to do again
|
|
||||||
BOOST_ASSERT(std::is_sorted(shortest_path_segments.begin(), shortest_path_segments.end(),
|
|
||||||
name_id_comperator));
|
|
||||||
BOOST_ASSERT(std::is_sorted(alternative_path_segments.begin(),
|
|
||||||
alternative_path_segments.end(), name_id_comperator));
|
|
||||||
|
|
||||||
std::vector<SegmentT> alternative_path_set_difference(alternative_path_segments.size());
|
|
||||||
std::set_difference(alternative_path_segments.begin(), alternative_path_segments.end(),
|
|
||||||
shortest_path_segments.begin(), shortest_path_segments.end(),
|
|
||||||
alternative_path_set_difference.begin(), name_id_comperator);
|
|
||||||
|
|
||||||
std::sort(alternative_path_set_difference.begin(), alternative_path_set_difference.end(),
|
|
||||||
length_comperator);
|
|
||||||
|
|
||||||
if (!alternative_path_segments.empty())
|
|
||||||
{
|
|
||||||
alternative_segment_2 = PickNextLongestSegment(alternative_path_set_difference,
|
|
||||||
alternative_segment_1.name_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// move the segments into the order in which they occur.
|
|
||||||
if (shortest_segment_1.position > shortest_segment_2.position)
|
|
||||||
{
|
|
||||||
std::swap(shortest_segment_1, shortest_segment_2);
|
|
||||||
}
|
|
||||||
if (alternative_segment_1.position > alternative_segment_2.position)
|
|
||||||
{
|
|
||||||
std::swap(alternative_segment_1, alternative_segment_2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetching names for the selected segments
|
|
||||||
route_names.shortest_path_name_1 = facade->get_name_for_id(shortest_segment_1.name_id);
|
|
||||||
route_names.shortest_path_name_2 = facade->get_name_for_id(shortest_segment_2.name_id);
|
|
||||||
|
|
||||||
route_names.alternative_path_name_1 =
|
|
||||||
facade->get_name_for_id(alternative_segment_1.name_id);
|
|
||||||
route_names.alternative_path_name_2 =
|
|
||||||
facade->get_name_for_id(alternative_segment_2.name_id);
|
|
||||||
|
|
||||||
return route_names;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EXTRACT_ROUTE_NAMES_H
|
|
||||||
@@ -1,239 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
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 TINY_COMPONENTS_HPP
|
|
||||||
#define TINY_COMPONENTS_HPP
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "../data_structures/deallocating_vector.hpp"
|
|
||||||
#include "../data_structures/import_edge.hpp"
|
|
||||||
#include "../data_structures/query_node.hpp"
|
|
||||||
#include "../data_structures/percent.hpp"
|
|
||||||
#include "../data_structures/restriction.hpp"
|
|
||||||
#include "../data_structures/restriction_map.hpp"
|
|
||||||
#include "../data_structures/turn_instructions.hpp"
|
|
||||||
|
|
||||||
#include "../util/integer_range.hpp"
|
|
||||||
#include "../util/simple_logger.hpp"
|
|
||||||
#include "../util/std_hash.hpp"
|
|
||||||
#include "../util/timing_util.hpp"
|
|
||||||
|
|
||||||
#include <osrm/coordinate.hpp>
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
#include <tbb/parallel_sort.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <stack>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
template <typename GraphT> class TarjanSCC
|
|
||||||
{
|
|
||||||
struct TarjanStackFrame
|
|
||||||
{
|
|
||||||
explicit TarjanStackFrame(NodeID v, NodeID parent) : v(v), parent(parent) {}
|
|
||||||
NodeID v;
|
|
||||||
NodeID parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TarjanNode
|
|
||||||
{
|
|
||||||
TarjanNode() : index(SPECIAL_NODEID), low_link(SPECIAL_NODEID), on_stack(false) {}
|
|
||||||
unsigned index;
|
|
||||||
unsigned low_link;
|
|
||||||
bool on_stack;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<unsigned> components_index;
|
|
||||||
std::vector<NodeID> component_size_vector;
|
|
||||||
std::shared_ptr<GraphT> m_node_based_graph;
|
|
||||||
std::unordered_set<NodeID> barrier_node_set;
|
|
||||||
RestrictionMap m_restriction_map;
|
|
||||||
std::size_t size_one_counter;
|
|
||||||
|
|
||||||
public:
|
|
||||||
template <class ContainerT>
|
|
||||||
TarjanSCC(std::shared_ptr<GraphT> graph,
|
|
||||||
const RestrictionMap &restrictions,
|
|
||||||
const ContainerT &barrier_node_list)
|
|
||||||
: components_index(graph->GetNumberOfNodes(), SPECIAL_NODEID), m_node_based_graph(graph),
|
|
||||||
m_restriction_map(restrictions), size_one_counter(0)
|
|
||||||
{
|
|
||||||
barrier_node_set.insert(std::begin(barrier_node_list), std::end(barrier_node_list));
|
|
||||||
BOOST_ASSERT(m_node_based_graph->GetNumberOfNodes() > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void run()
|
|
||||||
{
|
|
||||||
TIMER_START(SCC_RUN);
|
|
||||||
const NodeID max_node_id = m_node_based_graph->GetNumberOfNodes();
|
|
||||||
|
|
||||||
// The following is a hack to distinguish between stuff that happens
|
|
||||||
// before the recursive call and stuff that happens after
|
|
||||||
std::stack<TarjanStackFrame> recursion_stack;
|
|
||||||
// true = stuff before, false = stuff after call
|
|
||||||
std::stack<NodeID> tarjan_stack;
|
|
||||||
std::vector<TarjanNode> tarjan_node_list(max_node_id);
|
|
||||||
unsigned component_index = 0, size_of_current_component = 0;
|
|
||||||
unsigned index = 0;
|
|
||||||
std::vector<bool> processing_node_before_recursion(max_node_id, true);
|
|
||||||
for (const NodeID node : osrm::irange(0u, max_node_id))
|
|
||||||
{
|
|
||||||
if (SPECIAL_NODEID == components_index[node])
|
|
||||||
{
|
|
||||||
recursion_stack.emplace(TarjanStackFrame(node, node));
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!recursion_stack.empty())
|
|
||||||
{
|
|
||||||
TarjanStackFrame currentFrame = recursion_stack.top();
|
|
||||||
const NodeID u = currentFrame.parent;
|
|
||||||
const NodeID v = currentFrame.v;
|
|
||||||
recursion_stack.pop();
|
|
||||||
|
|
||||||
const bool before_recursion = processing_node_before_recursion[v];
|
|
||||||
|
|
||||||
if (before_recursion && tarjan_node_list[v].index != UINT_MAX)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (before_recursion)
|
|
||||||
{
|
|
||||||
// Mark frame to handle tail of recursion
|
|
||||||
recursion_stack.emplace(currentFrame);
|
|
||||||
processing_node_before_recursion[v] = false;
|
|
||||||
|
|
||||||
// Mark essential information for SCC
|
|
||||||
tarjan_node_list[v].index = index;
|
|
||||||
tarjan_node_list[v].low_link = index;
|
|
||||||
tarjan_stack.push(v);
|
|
||||||
tarjan_node_list[v].on_stack = true;
|
|
||||||
++index;
|
|
||||||
|
|
||||||
const NodeID to_node_of_only_restriction =
|
|
||||||
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
|
|
||||||
|
|
||||||
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(v))
|
|
||||||
{
|
|
||||||
const auto vprime = m_node_based_graph->GetTarget(current_edge);
|
|
||||||
|
|
||||||
// Traverse outgoing edges
|
|
||||||
if (barrier_node_set.find(v) != barrier_node_set.end() && u != vprime)
|
|
||||||
{
|
|
||||||
// continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
|
|
||||||
vprime == to_node_of_only_restriction)
|
|
||||||
{
|
|
||||||
// At an only_-restriction but not at the right turn
|
|
||||||
// continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_restriction_map.CheckIfTurnIsRestricted(u, v, vprime))
|
|
||||||
{
|
|
||||||
// continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SPECIAL_NODEID == tarjan_node_list[vprime].index)
|
|
||||||
{
|
|
||||||
recursion_stack.emplace(TarjanStackFrame(vprime, v));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (tarjan_node_list[vprime].on_stack &&
|
|
||||||
tarjan_node_list[vprime].index < tarjan_node_list[v].low_link)
|
|
||||||
{
|
|
||||||
tarjan_node_list[v].low_link = tarjan_node_list[vprime].index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
processing_node_before_recursion[v] = true;
|
|
||||||
tarjan_node_list[currentFrame.parent].low_link =
|
|
||||||
std::min(tarjan_node_list[currentFrame.parent].low_link,
|
|
||||||
tarjan_node_list[v].low_link);
|
|
||||||
// after recursion, lets do cycle checking
|
|
||||||
// Check if we found a cycle. This is the bottom part of the recursion
|
|
||||||
if (tarjan_node_list[v].low_link == tarjan_node_list[v].index)
|
|
||||||
{
|
|
||||||
NodeID vprime;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
vprime = tarjan_stack.top();
|
|
||||||
tarjan_stack.pop();
|
|
||||||
tarjan_node_list[vprime].on_stack = false;
|
|
||||||
components_index[vprime] = component_index;
|
|
||||||
++size_of_current_component;
|
|
||||||
} while (v != vprime);
|
|
||||||
|
|
||||||
component_size_vector.emplace_back(size_of_current_component);
|
|
||||||
|
|
||||||
if (size_of_current_component > 1000)
|
|
||||||
{
|
|
||||||
SimpleLogger().Write() << "large component [" << component_index
|
|
||||||
<< "]=" << size_of_current_component;
|
|
||||||
}
|
|
||||||
|
|
||||||
++component_index;
|
|
||||||
size_of_current_component = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TIMER_STOP(SCC_RUN);
|
|
||||||
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(),
|
|
||||||
[](unsigned value)
|
|
||||||
{
|
|
||||||
return 1 == value;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t get_number_of_components() const { return component_size_vector.size(); }
|
|
||||||
|
|
||||||
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]; }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* TINY_COMPONENTS_HPP */
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
environment:
|
|
||||||
matrix:
|
|
||||||
- configuration: Debug
|
|
||||||
- configuration: Release
|
|
||||||
|
|
||||||
# branches to build
|
|
||||||
branches:
|
|
||||||
# whitelist
|
|
||||||
only:
|
|
||||||
- develop
|
|
||||||
|
|
||||||
# scripts that are called at very beginning, before repo cloning
|
|
||||||
init:
|
|
||||||
- git config --global core.autocrlf input
|
|
||||||
|
|
||||||
# clone directory
|
|
||||||
clone_folder: c:\projects\osrm
|
|
||||||
|
|
||||||
platform: x64
|
|
||||||
|
|
||||||
install:
|
|
||||||
# by default, all script lines are interpreted as batch
|
|
||||||
- nuget install protobuf
|
|
||||||
- cd c:\projects\osrm
|
|
||||||
- curl -O http://build.project-osrm.org/libs_osrm_%Configuration%.7z
|
|
||||||
- 7z x libs_osrm_%Configuration%.7z | find ":"
|
|
||||||
|
|
||||||
build_script:
|
|
||||||
- cd c:/projects/osrm
|
|
||||||
- mkdir build
|
|
||||||
- cd build
|
|
||||||
- echo Running cmake...
|
|
||||||
- call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
|
|
||||||
- SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH%
|
|
||||||
- SET P=c:/projects/osrm
|
|
||||||
- set TBB_INSTALL_DIR=%P%/tbb
|
|
||||||
- set TBB_ARCH_PLATFORM=intel64/vc12
|
|
||||||
- cmake .. -G "Visual Studio 12 Win64" -DCMAKE_BUILD_TYPE=%Configuration% -DCMAKE_INSTALL_PREFIX=%P%/libs -DBOOST_ROOT=%P%/boost_min -DBoost_ADDITIONAL_VERSIONS=1.57 -DBoost_USE_STATIC_LIBS=ON -T CTP_Nov2013
|
|
||||||
- msbuild /clp:Verbosity=minimal /nologo OSRM.sln
|
|
||||||
- msbuild /clp:Verbosity=minimal /nologo tests.vcxproj
|
|
||||||
- cd %Configuration%
|
|
||||||
- if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip *.exe *.pdb %P%/libs/bin/*.dll -tzip)
|
|
||||||
- cd ..\..\profiles
|
|
||||||
- echo disk=c:\temp\stxxl,10000,wincall > .stxxl.txt
|
|
||||||
- if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip * -tzip)
|
|
||||||
- set PATH=%PATH%;c:/projects/osrm/libs/bin
|
|
||||||
- cd c:/projects/osrm/build/%Configuration%
|
|
||||||
- datastructure-tests.exe
|
|
||||||
- algorithm-tests.exe
|
|
||||||
|
|
||||||
test: off
|
|
||||||
|
|
||||||
artifacts:
|
|
||||||
- path: osrm_Debug.zip
|
|
||||||
name: osrm_Debug.zip
|
|
||||||
- path: osrm_Release.zip
|
|
||||||
name: osrm_Release.zip
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
provider: FTP
|
|
||||||
server:
|
|
||||||
secure: ef7oiQTTXFGt8NdNiOHm/uRFVrUttzyFbIlnaeHhQvw=
|
|
||||||
username:
|
|
||||||
secure: Bw+Se2GTJxA6+GtRkEc//tQSBHOuFIuJHBjFwR9cD+8=
|
|
||||||
password:
|
|
||||||
secure: eqwESZqxMXC/j5mOCpaXuw==
|
|
||||||
folder: /
|
|
||||||
enable_ssl: true
|
|
||||||
active_mode: false
|
|
||||||
|
|
||||||
# notifications:
|
|
||||||
# - provider: HipChat
|
|
||||||
# auth_token:
|
|
||||||
# secure: boLE7BjcahdIUxv9jkN7U3F8iOASF+MkhtctlVoWJoo=
|
|
||||||
# room: Directions
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2015, Project OSRM contributors
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../data_structures/original_edge_data.hpp"
|
|
||||||
#include "../data_structures/query_node.hpp"
|
|
||||||
#include "../data_structures/shared_memory_vector_wrapper.hpp"
|
|
||||||
#include "../data_structures/static_rtree.hpp"
|
|
||||||
#include "../util/boost_filesystem_2_fix.hpp"
|
|
||||||
#include "../data_structures/edge_based_node.hpp"
|
|
||||||
|
|
||||||
#include <osrm/coordinate.hpp>
|
|
||||||
|
|
||||||
#include <random>
|
|
||||||
|
|
||||||
// Choosen by a fair W20 dice roll (this value is completely arbitrary)
|
|
||||||
constexpr unsigned RANDOM_SEED = 13;
|
|
||||||
constexpr int32_t WORLD_MIN_LAT = -90 * COORDINATE_PRECISION;
|
|
||||||
constexpr int32_t WORLD_MAX_LAT = 90 * COORDINATE_PRECISION;
|
|
||||||
constexpr int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION;
|
|
||||||
constexpr int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;
|
|
||||||
|
|
||||||
using RTreeLeaf = EdgeBasedNode;
|
|
||||||
using FixedPointCoordinateListPtr = std::shared_ptr<std::vector<FixedPointCoordinate>>;
|
|
||||||
using BenchStaticRTree = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, false>::vector, false>;
|
|
||||||
|
|
||||||
FixedPointCoordinateListPtr LoadCoordinates(const boost::filesystem::path &nodes_file)
|
|
||||||
{
|
|
||||||
boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
|
|
||||||
|
|
||||||
QueryNode current_node;
|
|
||||||
unsigned coordinate_count = 0;
|
|
||||||
nodes_input_stream.read((char *)&coordinate_count, sizeof(unsigned));
|
|
||||||
auto coords = std::make_shared<std::vector<FixedPointCoordinate>>(coordinate_count);
|
|
||||||
for (unsigned i = 0; i < coordinate_count; ++i)
|
|
||||||
{
|
|
||||||
nodes_input_stream.read((char *)¤t_node, sizeof(QueryNode));
|
|
||||||
coords->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon);
|
|
||||||
BOOST_ASSERT((std::abs(coords->at(i).lat) >> 30) == 0);
|
|
||||||
BOOST_ASSERT((std::abs(coords->at(i).lon) >> 30) == 0);
|
|
||||||
}
|
|
||||||
nodes_input_stream.close();
|
|
||||||
return coords;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Benchmark(BenchStaticRTree &rtree, unsigned num_queries)
|
|
||||||
{
|
|
||||||
std::mt19937 mt_rand(RANDOM_SEED);
|
|
||||||
std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
|
|
||||||
std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);
|
|
||||||
std::vector<FixedPointCoordinate> queries;
|
|
||||||
for (unsigned i = 0; i < num_queries; i++)
|
|
||||||
{
|
|
||||||
queries.emplace_back(FixedPointCoordinate(lat_udist(mt_rand), lon_udist(mt_rand)));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const unsigned num_results = 5;
|
|
||||||
std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results
|
|
||||||
<< " phantom nodes"
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
TIMER_START(query_phantom);
|
|
||||||
std::vector<PhantomNode> phantom_node_vector;
|
|
||||||
for (const auto &q : queries)
|
|
||||||
{
|
|
||||||
phantom_node_vector.clear();
|
|
||||||
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results);
|
|
||||||
phantom_node_vector.clear();
|
|
||||||
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results);
|
|
||||||
}
|
|
||||||
TIMER_STOP(query_phantom);
|
|
||||||
|
|
||||||
std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries
|
|
||||||
<< " queries."
|
|
||||||
<< "\n";
|
|
||||||
std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query."
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
std::cout << "#### LocateClosestEndPointForCoordinate"
|
|
||||||
<< "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
TIMER_START(query_endpoint);
|
|
||||||
FixedPointCoordinate result;
|
|
||||||
for (const auto &q : queries)
|
|
||||||
{
|
|
||||||
rtree.LocateClosestEndPointForCoordinate(q, result, 3);
|
|
||||||
}
|
|
||||||
TIMER_STOP(query_endpoint);
|
|
||||||
|
|
||||||
std::cout << "Took " << TIMER_MSEC(query_endpoint) << " msec for " << num_queries << " queries."
|
|
||||||
<< "\n";
|
|
||||||
std::cout << TIMER_MSEC(query_endpoint) / ((double)num_queries) << " msec/query."
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
std::cout << "#### FindPhantomNodeForCoordinate"
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
TIMER_START(query_node);
|
|
||||||
for (const auto &q : queries)
|
|
||||||
{
|
|
||||||
PhantomNode phantom;
|
|
||||||
rtree.FindPhantomNodeForCoordinate(q, phantom, 3);
|
|
||||||
}
|
|
||||||
TIMER_STOP(query_node);
|
|
||||||
|
|
||||||
std::cout << "Took " << TIMER_MSEC(query_node) << " msec for " << num_queries << " queries."
|
|
||||||
<< "\n";
|
|
||||||
std::cout << TIMER_MSEC(query_node) / ((double)num_queries) << " msec/query."
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
{
|
|
||||||
const unsigned num_results = 1;
|
|
||||||
std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results
|
|
||||||
<< " phantom nodes"
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
TIMER_START(query_phantom);
|
|
||||||
std::vector<PhantomNode> phantom_node_vector;
|
|
||||||
for (const auto &q : queries)
|
|
||||||
{
|
|
||||||
phantom_node_vector.clear();
|
|
||||||
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results);
|
|
||||||
phantom_node_vector.clear();
|
|
||||||
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results);
|
|
||||||
}
|
|
||||||
TIMER_STOP(query_phantom);
|
|
||||||
|
|
||||||
std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries
|
|
||||||
<< " queries."
|
|
||||||
<< "\n";
|
|
||||||
std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query."
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
std::cout << "#### LocateClosestEndPointForCoordinate"
|
|
||||||
<< "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (argc < 4)
|
|
||||||
{
|
|
||||||
std::cout << "./rtree-bench file.ramIndex file.fileIndx file.nodes"
|
|
||||||
<< "\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *ramPath = argv[1];
|
|
||||||
const char *filePath = argv[2];
|
|
||||||
const char *nodesPath = argv[3];
|
|
||||||
|
|
||||||
auto coords = LoadCoordinates(nodesPath);
|
|
||||||
|
|
||||||
BenchStaticRTree rtree(ramPath, filePath, coords);
|
|
||||||
|
|
||||||
Benchmark(rtree, 10000);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
||||||
MESSAGE(FATAL_ERROR "Cannot configure CPack to generate Debian packages on non-linux systems.")
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
INCLUDE(FindDebArch)
|
|
||||||
|
|
||||||
SET(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md")
|
|
||||||
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENCE.TXT")
|
|
||||||
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CPACK_RESOURCE_FILE_README}")
|
|
||||||
SET(CPACK_PACKAGE_VERSION_MAJOR "0")
|
|
||||||
SET(CPACK_PACKAGE_VERSION_MINOR "4")
|
|
||||||
SET(CPACK_PACKAGE_VERSION_PATCH "3")
|
|
||||||
|
|
||||||
SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
|
||||||
|
|
||||||
string(TOLOWER "${CMAKE_PROJECT_NAME}" LOWER_PROJECT_NAME)
|
|
||||||
SET(CPACK_PACKAGE_FILE_NAME "${LOWER_PROJECT_NAME}_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
|
||||||
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${LOWER_PROJECT_NAME}_${CPACK_PACKAGE_VERSION}_orig")
|
|
||||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Open Source Routing Machine (OSRM).")
|
|
||||||
SET(CPACK_PACKAGE_DESCRIPTION "Open Source Routing Machine (OSRM) is a routing engine.")
|
|
||||||
|
|
||||||
# To create a proper Debian/Ubuntu package, the following CMake
|
|
||||||
# options should be used:
|
|
||||||
|
|
||||||
SET(CPACK_STRIP_FILES "TRUE")
|
|
||||||
SET(CPACK_INCLUDE_TOPLEVEL_DIRECTORY "FALSE")
|
|
||||||
SET(CPACK_GENERATOR "DEB")
|
|
||||||
|
|
||||||
SET(CPACK_DEBIAN_PACKAGE_NAME "${CPACK_PACKAGE_NAME}${VERSION_SUFFIX}")
|
|
||||||
SET(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}${CPACK_PACKAGE_REVISION}")
|
|
||||||
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Dennis Luxen <info@project-osrm.org>")
|
|
||||||
SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
|
||||||
SET(CPACK_DEBIAN_PACKAGE_SECTION "devel")
|
|
||||||
SET(CPACK_DEBIAN_PACKAGE_DESCRIPTION "Open Source Routing Machine (OSRM) is a high-performance routing engine.
|
|
||||||
It combines sophisticated routing algorithms with the open and free data of the OpenStreetMap."
|
|
||||||
)
|
|
||||||
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6-dev, libprotobuf-dev, libosmpbf-dev, libbz2-1.0, libstxxl1, libxml2, libzip2, liblua5.1-0, libtbb2, libboost-all-dev")
|
|
||||||
|
|
||||||
file(GLOB_RECURSE ProfileGlob ${CMAKE_SOURCE_DIR}/profiles/*)
|
|
||||||
install(FILES ${ProfileGlob} DESTINATION "share/doc/${LOWER_PROJECT_NAME}/profiles")
|
|
||||||
CONFIGURE_FILE (${CMAKE_SOURCE_DIR}/cmake/postinst.in postinst)
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_BINARY_DIR}/postinst;${CMAKE_CURRENT_BINARY_DIR}/copyright;")
|
|
||||||
|
|
||||||
MESSAGE(STATUS "Debian Package: ${CPACK_DEBIAN_PACKAGE_NAME} (${CPACK_DEBIAN_PACKAGE_VERSION}) [${CPACK_PACKAGE_FILE_NAME}.deb]")
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# - Check whether the CXX compiler supports a given flag.
|
|
||||||
# CHECK_CXX_COMPILER_FLAG(<flag> <var>)
|
|
||||||
# <flag> - the compiler flag
|
|
||||||
# <var> - variable to store the result
|
|
||||||
# This internally calls the check_cxx_source_compiles macro. See help
|
|
||||||
# for CheckCXXSourceCompiles for a listing of variables that can
|
|
||||||
# modify the build.
|
|
||||||
|
|
||||||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
|
|
||||||
#
|
|
||||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
|
||||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
|
||||||
|
|
||||||
|
|
||||||
INCLUDE(CheckCXXSourceCompiles)
|
|
||||||
|
|
||||||
MACRO (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT)
|
|
||||||
SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
|
|
||||||
SET(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
|
|
||||||
CHECK_CXX_SOURCE_COMPILES("int main() { return 0;}" ${_RESULT}
|
|
||||||
# Some compilers do not fail with a bad flag
|
|
||||||
FAIL_REGEX "unrecognized .*option" # GNU
|
|
||||||
FAIL_REGEX "ignoring unknown option" # MSVC
|
|
||||||
FAIL_REGEX "[Uu]nknown option" # HP
|
|
||||||
FAIL_REGEX "[Ww]arning: [Oo]ption" # SunPro
|
|
||||||
FAIL_REGEX "command option .* is not recognized" # XL
|
|
||||||
)
|
|
||||||
SET (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
|
|
||||||
ENDMACRO (CHECK_CXX_COMPILER_FLAG)
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2013 Emmanuel Roullit <emmanuel.roullit@gmail.com>
|
|
||||||
#
|
|
||||||
|
|
||||||
IF(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
|
|
||||||
FIND_PROGRAM(DPKG_CMD dpkg)
|
|
||||||
IF(NOT DPKG_CMD)
|
|
||||||
EXECUTE_PROCESS(COMMAND uname -p
|
|
||||||
OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
MESSAGE(STATUS "Can not find dpkg in your path, default to uname -p: ${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.")
|
|
||||||
ELSE(NOT DPKG_CMD)
|
|
||||||
EXECUTE_PROCESS(COMMAND "${DPKG_CMD}" --print-architecture
|
|
||||||
OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
ENDIF(NOT DPKG_CMD)
|
|
||||||
ENDIF(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
# Locate Lua library
|
|
||||||
# This module defines
|
|
||||||
# LUA52_FOUND, if false, do not try to link to Lua
|
|
||||||
# LUA_LIBRARIES
|
|
||||||
# LUA_INCLUDE_DIR, where to find lua.h
|
|
||||||
# LUA_VERSION_STRING, the version of Lua found (since CMake 2.8.8)
|
|
||||||
#
|
|
||||||
# Note that the expected include convention is
|
|
||||||
# #include "lua.h"
|
|
||||||
# and not
|
|
||||||
# #include <lua/lua.h>
|
|
||||||
# This is because, the lua location is not standardized and may exist
|
|
||||||
# in locations other than lua/
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright 2007-2009 Kitware, Inc.
|
|
||||||
# Copyright 2013 for Project-OSRM, Lua5.1 => Lua5.2
|
|
||||||
#
|
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
# see accompanying file Copyright.txt for details.
|
|
||||||
#
|
|
||||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
# See the License for more information.
|
|
||||||
#=============================================================================
|
|
||||||
# (To distribute this file outside of CMake, substitute the full
|
|
||||||
# License text for the above reference.)
|
|
||||||
|
|
||||||
find_path(LUA_INCLUDE_DIR lua.h
|
|
||||||
HINTS
|
|
||||||
ENV LUA_DIR
|
|
||||||
PATH_SUFFIXES include/lua52 include/lua5.2 include/lua-5.2 include/lua include
|
|
||||||
PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/sw # Fink
|
|
||||||
/opt/local # DarwinPorts
|
|
||||||
/opt/csw # Blastwave
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(LUA_LIBRARY
|
|
||||||
NAMES lua52 lua5.2 lua-5.2 lua
|
|
||||||
HINTS
|
|
||||||
ENV LUA_DIR
|
|
||||||
PATH_SUFFIXES lib
|
|
||||||
PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/sw
|
|
||||||
/opt/local
|
|
||||||
/opt/csw
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
if(LUA_LIBRARY)
|
|
||||||
# include the math library for Unix
|
|
||||||
if(UNIX AND NOT APPLE AND NOT BEOS)
|
|
||||||
find_library(LUA_MATH_LIBRARY m)
|
|
||||||
set( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries")
|
|
||||||
# For Windows and Mac, don't need to explicitly include the math library
|
|
||||||
else()
|
|
||||||
set( LUA_LIBRARIES "${LUA_LIBRARY}" CACHE STRING "Lua Libraries")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h")
|
|
||||||
file(STRINGS "${LUA_INCLUDE_DIR}/lua.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua .+\"")
|
|
||||||
|
|
||||||
string(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([^\"]+)\".*" "\\1" LUA_VERSION_STRING "${lua_version_str}")
|
|
||||||
unset(lua_version_str)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if
|
|
||||||
# all listed variables are TRUE
|
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua52
|
|
||||||
REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR
|
|
||||||
VERSION_VAR LUA_VERSION_STRING)
|
|
||||||
|
|
||||||
mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY)
|
|
||||||
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
# Locate Lua library
|
|
||||||
# This module defines
|
|
||||||
# LUAJIT_FOUND, if false, do not try to link to Lua
|
|
||||||
# LUAJIT_LIBRARIES
|
|
||||||
# LUAJIT_INCLUDE_DIR, where to find lua.h
|
|
||||||
#
|
|
||||||
# Note that the expected include convention is
|
|
||||||
# #include "lua.h"
|
|
||||||
# and not
|
|
||||||
# #include <lua/lua.h>
|
|
||||||
# This is because, the lua location is not standardized and may exist
|
|
||||||
# in locations other than lua/
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright 2007-2009 Kitware, Inc.
|
|
||||||
#
|
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
# see accompanying file Copyright.txt for details.
|
|
||||||
#
|
|
||||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
# See the License for more information.
|
|
||||||
#=============================================================================
|
|
||||||
# (To distributed this file outside of CMake, substitute the full
|
|
||||||
# License text for the above reference.)
|
|
||||||
#
|
|
||||||
# ################
|
|
||||||
# 2010 - modified for cronkite to find luajit instead of lua, as it was before.
|
|
||||||
#
|
|
||||||
|
|
||||||
if ( NOT LuaJIT_FIND_VERSION )
|
|
||||||
MESSAGE(FATAL_ERROR "You need to specify a version of libluajit to use")
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF( NOT LUAJIT_FIND_QUIETLY )
|
|
||||||
MESSAGE(STATUS "Looking for LuaJIT ${LuaJIT_FIND_VERSION}")
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
FIND_PATH(LUAJIT_INCLUDE_DIR lua.h
|
|
||||||
HINTS
|
|
||||||
$ENV{LUAJIT_DIR}
|
|
||||||
PATH_SUFFIXES include/luajit-2.0 include/luajit2.0 include/luajit include
|
|
||||||
PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/usr/local
|
|
||||||
/usr
|
|
||||||
/sw # Fink
|
|
||||||
/opt/local # DarwinPorts
|
|
||||||
/opt/csw # Blastwave
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
FIND_LIBRARY(LUAJIT_LIBRARY
|
|
||||||
NAMES luajit-${LuaJIT_FIND_VERSION_MAJOR}${LuaJIT_FIND_VERSION_MINOR} luajit-${LuaJIT_FIND_VERSION}
|
|
||||||
HINTS
|
|
||||||
$ENV{LUAJIT_DIR}
|
|
||||||
PATH_SUFFIXES lib64 lib
|
|
||||||
PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/usr/local
|
|
||||||
/usr
|
|
||||||
/sw
|
|
||||||
/opt/local
|
|
||||||
/opt/csw
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
IF(LUAJIT_LIBRARY)
|
|
||||||
# include the math library for Unix
|
|
||||||
IF(UNIX AND NOT APPLE)
|
|
||||||
FIND_LIBRARY(LUAJIT_MATH_LIBRARY m)
|
|
||||||
SET( LUAJIT_LIBRARIES "${LUAJIT_LIBRARY};${LUAJIT_MATH_LIBRARY}" CACHE STRING "Lua Libraries")
|
|
||||||
# For Windows and Mac, don't need to explicitly include the math library
|
|
||||||
ELSE(UNIX AND NOT APPLE)
|
|
||||||
SET( LUAJIT_LIBRARIES "${LUAJIT_LIBRARY}" CACHE STRING "Lua Libraries")
|
|
||||||
ENDIF(UNIX AND NOT APPLE)
|
|
||||||
ENDIF(LUAJIT_LIBRARY)
|
|
||||||
|
|
||||||
INCLUDE(FindPackageHandleStandardArgs)
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set LUAJIT_FOUND to TRUE if
|
|
||||||
# all listed variables are TRUE
|
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LUAJIT DEFAULT_MSG LUAJIT_LIBRARIES LUAJIT_INCLUDE_DIR)
|
|
||||||
|
|
||||||
IF( NOT LUAJIT_FIND_QUIETLY )
|
|
||||||
IF( LUAJIT_FOUND AND LUAJIT_LIBRARIES)
|
|
||||||
MESSAGE(STATUS "Found LuaJIT: ${LUAJIT_LIBRARY}" )
|
|
||||||
MARK_AS_ADVANCED(LUAJIT_INCLUDE_DIR LUAJIT_LIBRARIES LUAJIT_LIBRARY LUAJIT_MATH_LIBRARY)
|
|
||||||
ELSE()
|
|
||||||
SET ( LUAJIT_FOUND FALSE )
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
# Locate Luabind library
|
|
||||||
# This module defines
|
|
||||||
# LUABIND_FOUND, if false, do not try to link to Luabind
|
|
||||||
# LUABIND_LIBRARIES
|
|
||||||
# LUABIND_INCLUDE_DIR, where to find luabind.hpp
|
|
||||||
#
|
|
||||||
# Note that the expected include convention is
|
|
||||||
# #include <luabind/luabind.hpp>
|
|
||||||
# and not
|
|
||||||
# #include <luabind.hpp>
|
|
||||||
|
|
||||||
IF( NOT LUABIND_FIND_QUIETLY )
|
|
||||||
MESSAGE(STATUS "Looking for Luabind...")
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
FIND_PATH(LUABIND_INCLUDE_DIR luabind.hpp
|
|
||||||
HINTS
|
|
||||||
$ENV{LUABIND_DIR}
|
|
||||||
PATH_SUFFIXES luabind include/luabind include
|
|
||||||
PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/usr/local
|
|
||||||
/usr
|
|
||||||
/opt/local # DarwinPorts
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
FIND_LIBRARY(LUABIND_LIBRARY
|
|
||||||
NAMES luabind luabind09
|
|
||||||
HINTS
|
|
||||||
$ENV{LUABIND_DIR}
|
|
||||||
PATH_SUFFIXES lib64 lib
|
|
||||||
PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/usr/local
|
|
||||||
/usr
|
|
||||||
/opt/local
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
FIND_LIBRARY(LUABIND_LIBRARY_DBG
|
|
||||||
NAMES luabindd
|
|
||||||
HINTS
|
|
||||||
$ENV{LUABIND_DIR}
|
|
||||||
PATH_SUFFIXES lib64 lib
|
|
||||||
PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/usr/local
|
|
||||||
/usr
|
|
||||||
/opt/local
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
IF(LUABIND_LIBRARY)
|
|
||||||
SET( LUABIND_LIBRARIES "${LUABIND_LIBRARY}" CACHE STRING "Luabind Libraries")
|
|
||||||
ENDIF(LUABIND_LIBRARY)
|
|
||||||
|
|
||||||
INCLUDE(FindPackageHandleStandardArgs)
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set LUABIND_FOUND to TRUE if
|
|
||||||
# all listed variables are TRUE
|
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Luabind DEFAULT_MSG LUABIND_LIBRARIES LUABIND_INCLUDE_DIR)
|
|
||||||
|
|
||||||
IF( NOT LUABIND_FIND_QUIETLY )
|
|
||||||
IF( LUABIND_FOUND )
|
|
||||||
MESSAGE(STATUS "Found Luabind: ${LUABIND_LIBRARY}" )
|
|
||||||
ENDIF()
|
|
||||||
IF( LUABIND_LIBRARY_DBG )
|
|
||||||
MESSAGE(STATUS "Luabind debug library availible: ${LUABIND_LIBRARY_DBG}")
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
MARK_AS_ADVANCED(LUABIND_INCLUDE_DIR LUABIND_LIBRARIES LUABIND_LIBRARY LUABIND_LIBRARY_DBG)
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
# Locate OSMPBF library
|
|
||||||
# This module defines
|
|
||||||
# OSMPBF_FOUND, if false, do not try to link to OSMPBF
|
|
||||||
# OSMPBF_LIBRARIES
|
|
||||||
# OSMPBF_INCLUDE_DIR, where to find OSMPBF.hpp
|
|
||||||
#
|
|
||||||
# Note that the expected include convention is
|
|
||||||
# #include <osmpbf/osmpbf.h>
|
|
||||||
# and not
|
|
||||||
# #include <osmpbf.h>
|
|
||||||
|
|
||||||
IF( NOT OSMPBF_FIND_QUIETLY )
|
|
||||||
MESSAGE(STATUS "Looking for OSMPBF...")
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
FIND_PATH(OSMPBF_INCLUDE_DIR osmpbf.h
|
|
||||||
HINTS
|
|
||||||
$ENV{OSMPBF_DIR}
|
|
||||||
PATH_SUFFIXES OSMPBF include/osmpbf include
|
|
||||||
PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/usr/local
|
|
||||||
/usr
|
|
||||||
/opt/local # DarwinPorts
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
FIND_LIBRARY(OSMPBF_LIBRARY
|
|
||||||
NAMES osmpbf
|
|
||||||
HINTS
|
|
||||||
$ENV{OSMPBF_DIR}
|
|
||||||
PATH_SUFFIXES lib64 lib
|
|
||||||
PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/usr/local
|
|
||||||
/usr
|
|
||||||
/opt/local
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
INCLUDE(FindPackageHandleStandardArgs)
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set OSMPBF_FOUND to TRUE if
|
|
||||||
# all listed variables are TRUE
|
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OSMPBF DEFAULT_MSG OSMPBF_LIBRARY OSMPBF_INCLUDE_DIR)
|
|
||||||
|
|
||||||
IF( NOT OSMPBF_FIND_QUIETLY )
|
|
||||||
IF( OSMPBF_FOUND )
|
|
||||||
MESSAGE(STATUS "Found OSMPBF: ${OSMPBF_LIBRARY}" )
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
#MARK_AS_ADVANCED(OSMPBF_INCLUDE_DIR OSMPBF_LIBRARIES OSMPBF_LIBRARY OSMPBF_LIBRARY_DBG)
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
# Locate STXXL library
|
|
||||||
# This module defines
|
|
||||||
# STXXL_FOUND, if false, do not try to link to libstxxl
|
|
||||||
# STXXL_LIBRARY
|
|
||||||
# STXXL_INCLUDE_DIR, where to find stxxl.h
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
IF( NOT STXXL_FIND_QUIETLY )
|
|
||||||
MESSAGE(STATUS "Looking for STXXL...")
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
FIND_PATH(STXXL_INCLUDE_DIR stxxl.h
|
|
||||||
HINTS
|
|
||||||
$ENV{STXXL_DIR}
|
|
||||||
PATH_SUFFIXES stxxl include/stxxl/stxxl include/stxxl include
|
|
||||||
PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/usr/local
|
|
||||||
/usr
|
|
||||||
/opt/local # DarwinPorts
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
FIND_LIBRARY(STXXL_LIBRARY
|
|
||||||
NAMES stxxl
|
|
||||||
HINTS
|
|
||||||
$ENV{STXXL_DIR}
|
|
||||||
PATH_SUFFIXES lib64 lib
|
|
||||||
PATHS
|
|
||||||
~/Library/Frameworks
|
|
||||||
/Library/Frameworks
|
|
||||||
/usr/local
|
|
||||||
/usr
|
|
||||||
/opt/local
|
|
||||||
/opt
|
|
||||||
)
|
|
||||||
|
|
||||||
INCLUDE(FindPackageHandleStandardArgs)
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set STXXL_FOUND to TRUE if
|
|
||||||
# all listed variables are TRUE
|
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(STXXL DEFAULT_MSG STXXL_LIBRARY STXXL_INCLUDE_DIR)
|
|
||||||
|
|
||||||
IF( NOT STXXL_FIND_QUIETLY )
|
|
||||||
IF( STXXL_FOUND )
|
|
||||||
MESSAGE(STATUS "Found STXXL: ${STXXL_LIBRARY}" )
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
MARK_AS_ADVANCED(STXXL_INCLUDE_DIR STXXL_LIBRARY)
|
|
||||||
@@ -1,283 +0,0 @@
|
|||||||
# Locate Intel Threading Building Blocks include paths and libraries
|
|
||||||
# FindTBB.cmake can be found at https://code.google.com/p/findtbb/
|
|
||||||
# Written by Hannes Hofmann <hannes.hofmann _at_ informatik.uni-erlangen.de>
|
|
||||||
# Improvements by Gino van den Bergen <gino _at_ dtecta.com>,
|
|
||||||
# Florian Uhlig <F.Uhlig _at_ gsi.de>,
|
|
||||||
# Jiri Marsik <jiri.marsik89 _at_ gmail.com>
|
|
||||||
|
|
||||||
# The MIT License
|
|
||||||
#
|
|
||||||
# Copyright (c) 2011 Hannes Hofmann
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
|
||||||
# in the Software without restriction, including without limitation the rights
|
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included in
|
|
||||||
# all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
# THE SOFTWARE.
|
|
||||||
|
|
||||||
# GvdB: This module uses the environment variable TBB_ARCH_PLATFORM which defines architecture and compiler.
|
|
||||||
# e.g. "ia32/vc8" or "em64t/cc4.1.0_libc2.4_kernel2.6.16.21"
|
|
||||||
# TBB_ARCH_PLATFORM is set by the build script tbbvars[.bat|.sh|.csh], which can be found
|
|
||||||
# in the TBB installation directory (TBB_INSTALL_DIR).
|
|
||||||
#
|
|
||||||
# GvdB: Mac OS X distribution places libraries directly in lib directory.
|
|
||||||
#
|
|
||||||
# For backwards compatibility, you may explicitely set the CMake variables TBB_ARCHITECTURE and TBB_COMPILER.
|
|
||||||
# TBB_ARCHITECTURE [ ia32 | em64t | itanium ]
|
|
||||||
# which architecture to use
|
|
||||||
# TBB_COMPILER e.g. vc9 or cc3.2.3_libc2.3.2_kernel2.4.21 or cc4.0.1_os10.4.9
|
|
||||||
# which compiler to use (detected automatically on Windows)
|
|
||||||
|
|
||||||
# This module respects
|
|
||||||
# TBB_INSTALL_DIR or $ENV{TBB21_INSTALL_DIR} or $ENV{TBB_INSTALL_DIR}
|
|
||||||
|
|
||||||
# This module defines
|
|
||||||
# TBB_INCLUDE_DIRS, where to find task_scheduler_init.h, etc.
|
|
||||||
# TBB_LIBRARY_DIRS, where to find libtbb, libtbbmalloc
|
|
||||||
# TBB_DEBUG_LIBRARY_DIRS, where to find libtbb_debug, libtbbmalloc_debug
|
|
||||||
# TBB_INSTALL_DIR, the base TBB install directory
|
|
||||||
# TBB_LIBRARIES, the libraries to link against to use TBB.
|
|
||||||
# TBB_DEBUG_LIBRARIES, the libraries to link against to use TBB with debug symbols.
|
|
||||||
# TBB_FOUND, If false, don't try to use TBB.
|
|
||||||
# TBB_INTERFACE_VERSION, as defined in tbb/tbb_stddef.h
|
|
||||||
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
# has em64t/vc8 em64t/vc9
|
|
||||||
# has ia32/vc7.1 ia32/vc8 ia32/vc9
|
|
||||||
set(_TBB_DEFAULT_INSTALL_DIR "C:/Program Files/Intel/TBB" "C:/Program Files (x86)/Intel/TBB")
|
|
||||||
set(_TBB_LIB_NAME "tbb")
|
|
||||||
set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc")
|
|
||||||
set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug")
|
|
||||||
set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug")
|
|
||||||
if (MSVC71)
|
|
||||||
set (_TBB_COMPILER "vc7.1")
|
|
||||||
endif(MSVC71)
|
|
||||||
if (MSVC80)
|
|
||||||
set(_TBB_COMPILER "vc8")
|
|
||||||
endif(MSVC80)
|
|
||||||
if (MSVC90)
|
|
||||||
set(_TBB_COMPILER "vc9")
|
|
||||||
endif(MSVC90)
|
|
||||||
if(MSVC10)
|
|
||||||
set(_TBB_COMPILER "vc10")
|
|
||||||
endif(MSVC10)
|
|
||||||
# Todo: add other Windows compilers such as ICL.
|
|
||||||
set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
|
|
||||||
endif (WIN32)
|
|
||||||
|
|
||||||
if (UNIX)
|
|
||||||
if (APPLE)
|
|
||||||
# MAC
|
|
||||||
set(_TBB_DEFAULT_INSTALL_DIR "/Library/Frameworks/Intel_TBB.framework/Versions")
|
|
||||||
# libs: libtbb.dylib, libtbbmalloc.dylib, *_debug
|
|
||||||
set(_TBB_LIB_NAME "tbb")
|
|
||||||
set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc")
|
|
||||||
set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug")
|
|
||||||
set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug")
|
|
||||||
# default flavor on apple: ia32/cc4.0.1_os10.4.9
|
|
||||||
# Jiri: There is no reason to presume there is only one flavor and
|
|
||||||
# that user's setting of variables should be ignored.
|
|
||||||
if(NOT TBB_COMPILER)
|
|
||||||
set(_TBB_COMPILER "cc4.0.1_os10.4.9")
|
|
||||||
elseif (NOT TBB_COMPILER)
|
|
||||||
set(_TBB_COMPILER ${TBB_COMPILER})
|
|
||||||
endif(NOT TBB_COMPILER)
|
|
||||||
if(NOT TBB_ARCHITECTURE)
|
|
||||||
set(_TBB_ARCHITECTURE "ia32")
|
|
||||||
elseif(NOT TBB_ARCHITECTURE)
|
|
||||||
set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
|
|
||||||
endif(NOT TBB_ARCHITECTURE)
|
|
||||||
else (APPLE)
|
|
||||||
# LINUX
|
|
||||||
set(_TBB_DEFAULT_INSTALL_DIR "/opt/intel/tbb" "/usr/local/include" "/usr/include")
|
|
||||||
set(_TBB_LIB_NAME "tbb")
|
|
||||||
set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc")
|
|
||||||
set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug")
|
|
||||||
set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug")
|
|
||||||
# has em64t/cc3.2.3_libc2.3.2_kernel2.4.21 em64t/cc3.3.3_libc2.3.3_kernel2.6.5 em64t/cc3.4.3_libc2.3.4_kernel2.6.9 em64t/cc4.1.0_libc2.4_kernel2.6.16.21
|
|
||||||
# has ia32/*
|
|
||||||
# has itanium/*
|
|
||||||
set(_TBB_COMPILER ${TBB_COMPILER})
|
|
||||||
set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
|
|
||||||
endif (APPLE)
|
|
||||||
endif (UNIX)
|
|
||||||
|
|
||||||
if (CMAKE_SYSTEM MATCHES "SunOS.*")
|
|
||||||
# SUN
|
|
||||||
# not yet supported
|
|
||||||
# has em64t/cc3.4.3_kernel5.10
|
|
||||||
# has ia32/*
|
|
||||||
endif (CMAKE_SYSTEM MATCHES "SunOS.*")
|
|
||||||
|
|
||||||
|
|
||||||
#-- Clear the public variables
|
|
||||||
set (TBB_FOUND "NO")
|
|
||||||
|
|
||||||
|
|
||||||
#-- Find TBB install dir and set ${_TBB_INSTALL_DIR} and cached ${TBB_INSTALL_DIR}
|
|
||||||
# first: use CMake variable TBB_INSTALL_DIR
|
|
||||||
if (TBB_INSTALL_DIR)
|
|
||||||
set (_TBB_INSTALL_DIR ${TBB_INSTALL_DIR})
|
|
||||||
endif (TBB_INSTALL_DIR)
|
|
||||||
# second: use environment variable
|
|
||||||
if (NOT _TBB_INSTALL_DIR)
|
|
||||||
if (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "")
|
|
||||||
set (_TBB_INSTALL_DIR $ENV{TBB_INSTALL_DIR})
|
|
||||||
endif (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "")
|
|
||||||
# Intel recommends setting TBB21_INSTALL_DIR
|
|
||||||
if (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "")
|
|
||||||
set (_TBB_INSTALL_DIR $ENV{TBB21_INSTALL_DIR})
|
|
||||||
endif (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "")
|
|
||||||
if (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "")
|
|
||||||
set (_TBB_INSTALL_DIR $ENV{TBB22_INSTALL_DIR})
|
|
||||||
endif (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "")
|
|
||||||
if (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "")
|
|
||||||
set (_TBB_INSTALL_DIR $ENV{TBB30_INSTALL_DIR})
|
|
||||||
endif (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "")
|
|
||||||
endif (NOT _TBB_INSTALL_DIR)
|
|
||||||
# third: try to find path automatically
|
|
||||||
if (NOT _TBB_INSTALL_DIR)
|
|
||||||
if (_TBB_DEFAULT_INSTALL_DIR)
|
|
||||||
set (_TBB_INSTALL_DIR ${_TBB_DEFAULT_INSTALL_DIR})
|
|
||||||
endif (_TBB_DEFAULT_INSTALL_DIR)
|
|
||||||
endif (NOT _TBB_INSTALL_DIR)
|
|
||||||
# sanity check
|
|
||||||
if (NOT _TBB_INSTALL_DIR)
|
|
||||||
message ("ERROR: Unable to find Intel TBB install directory. ${_TBB_INSTALL_DIR}")
|
|
||||||
else (NOT _TBB_INSTALL_DIR)
|
|
||||||
# finally: set the cached CMake variable TBB_INSTALL_DIR
|
|
||||||
if (NOT TBB_INSTALL_DIR)
|
|
||||||
set (TBB_INSTALL_DIR ${_TBB_INSTALL_DIR} CACHE PATH "Intel TBB install directory")
|
|
||||||
mark_as_advanced(TBB_INSTALL_DIR)
|
|
||||||
endif (NOT TBB_INSTALL_DIR)
|
|
||||||
|
|
||||||
|
|
||||||
#-- A macro to rewrite the paths of the library. This is necessary, because
|
|
||||||
# find_library() always found the em64t/vc9 version of the TBB libs
|
|
||||||
macro(TBB_CORRECT_LIB_DIR var_name)
|
|
||||||
# if (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t")
|
|
||||||
string(REPLACE em64t "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}})
|
|
||||||
# endif (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t")
|
|
||||||
string(REPLACE ia32 "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}})
|
|
||||||
string(REPLACE vc7.1 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
|
|
||||||
string(REPLACE vc8 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
|
|
||||||
string(REPLACE vc9 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
|
|
||||||
string(REPLACE vc10 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
|
|
||||||
endmacro(TBB_CORRECT_LIB_DIR var_content)
|
|
||||||
|
|
||||||
|
|
||||||
#-- Look for include directory and set ${TBB_INCLUDE_DIR}
|
|
||||||
set (TBB_INC_SEARCH_DIR ${_TBB_INSTALL_DIR}/include)
|
|
||||||
# Jiri: tbbvars now sets the CPATH environment variable to the directory
|
|
||||||
# containing the headers.
|
|
||||||
find_path(TBB_INCLUDE_DIR
|
|
||||||
tbb/task_scheduler_init.h
|
|
||||||
PATHS ${TBB_INC_SEARCH_DIR} ENV CPATH
|
|
||||||
)
|
|
||||||
mark_as_advanced(TBB_INCLUDE_DIR)
|
|
||||||
|
|
||||||
|
|
||||||
#-- Look for libraries
|
|
||||||
# GvdB: $ENV{TBB_ARCH_PLATFORM} is set by the build script tbbvars[.bat|.sh|.csh]
|
|
||||||
if (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "")
|
|
||||||
set (_TBB_LIBRARY_DIR
|
|
||||||
${_TBB_INSTALL_DIR}/lib/$ENV{TBB_ARCH_PLATFORM}
|
|
||||||
${_TBB_INSTALL_DIR}/$ENV{TBB_ARCH_PLATFORM}/lib
|
|
||||||
)
|
|
||||||
endif (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "")
|
|
||||||
# Jiri: This block isn't mutually exclusive with the previous one
|
|
||||||
# (hence no else), instead I test if the user really specified
|
|
||||||
# the variables in question.
|
|
||||||
if ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL ""))
|
|
||||||
# HH: deprecated
|
|
||||||
message(STATUS "[Warning] FindTBB.cmake: The use of TBB_ARCHITECTURE and TBB_COMPILER is deprecated and may not be supported in future versions. Please set \$ENV{TBB_ARCH_PLATFORM} (using tbbvars.[bat|csh|sh]).")
|
|
||||||
# Jiri: It doesn't hurt to look in more places, so I store the hints from
|
|
||||||
# ENV{TBB_ARCH_PLATFORM} and the TBB_ARCHITECTURE and TBB_COMPILER
|
|
||||||
# variables and search them both.
|
|
||||||
set (_TBB_LIBRARY_DIR "${_TBB_INSTALL_DIR}/${_TBB_ARCHITECTURE}/${_TBB_COMPILER}/lib" ${_TBB_LIBRARY_DIR})
|
|
||||||
endif ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL ""))
|
|
||||||
|
|
||||||
# GvdB: Mac OS X distribution places libraries directly in lib directory.
|
|
||||||
list(APPEND _TBB_LIBRARY_DIR ${_TBB_INSTALL_DIR}/lib)
|
|
||||||
|
|
||||||
# Jiri: No reason not to check the default paths. From recent versions,
|
|
||||||
# tbbvars has started exporting the LIBRARY_PATH and LD_LIBRARY_PATH
|
|
||||||
# variables, which now point to the directories of the lib files.
|
|
||||||
# It all makes more sense to use the ${_TBB_LIBRARY_DIR} as a HINTS
|
|
||||||
# argument instead of the implicit PATHS as it isn't hard-coded
|
|
||||||
# but computed by system introspection. Searching the LIBRARY_PATH
|
|
||||||
# and LD_LIBRARY_PATH environment variables is now even more important
|
|
||||||
# that tbbvars doesn't export TBB_ARCH_PLATFORM and it facilitates
|
|
||||||
# the use of TBB built from sources.
|
|
||||||
find_library(TBB_LIBRARY ${_TBB_LIB_NAME} HINTS ${_TBB_LIBRARY_DIR}
|
|
||||||
PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
|
|
||||||
find_library(TBB_MALLOC_LIBRARY ${_TBB_LIB_MALLOC_NAME} HINTS ${_TBB_LIBRARY_DIR}
|
|
||||||
PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
|
|
||||||
|
|
||||||
#Extract path from TBB_LIBRARY name
|
|
||||||
get_filename_component(TBB_LIBRARY_DIR ${TBB_LIBRARY} PATH)
|
|
||||||
|
|
||||||
#TBB_CORRECT_LIB_DIR(TBB_LIBRARY)
|
|
||||||
#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY)
|
|
||||||
mark_as_advanced(TBB_LIBRARY TBB_MALLOC_LIBRARY)
|
|
||||||
|
|
||||||
#-- Look for debug libraries
|
|
||||||
# Jiri: Changed the same way as for the release libraries.
|
|
||||||
find_library(TBB_LIBRARY_DEBUG ${_TBB_LIB_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
|
|
||||||
PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
|
|
||||||
find_library(TBB_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_MALLOC_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
|
|
||||||
PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
|
|
||||||
|
|
||||||
# Jiri: Self-built TBB stores the debug libraries in a separate directory.
|
|
||||||
# Extract path from TBB_LIBRARY_DEBUG name
|
|
||||||
get_filename_component(TBB_LIBRARY_DEBUG_DIR ${TBB_LIBRARY_DEBUG} PATH)
|
|
||||||
|
|
||||||
#TBB_CORRECT_LIB_DIR(TBB_LIBRARY_DEBUG)
|
|
||||||
#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY_DEBUG)
|
|
||||||
mark_as_advanced(TBB_LIBRARY_DEBUG TBB_MALLOC_LIBRARY_DEBUG)
|
|
||||||
|
|
||||||
|
|
||||||
if (TBB_INCLUDE_DIR)
|
|
||||||
if (TBB_LIBRARY)
|
|
||||||
set (TBB_FOUND "YES")
|
|
||||||
set (TBB_LIBRARIES ${TBB_LIBRARY} ${TBB_MALLOC_LIBRARY} ${TBB_LIBRARIES})
|
|
||||||
set (TBB_DEBUG_LIBRARIES ${TBB_LIBRARY_DEBUG} ${TBB_MALLOC_LIBRARY_DEBUG} ${TBB_DEBUG_LIBRARIES})
|
|
||||||
set (TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR} CACHE PATH "TBB include directory" FORCE)
|
|
||||||
set (TBB_LIBRARY_DIRS ${TBB_LIBRARY_DIR} CACHE PATH "TBB library directory" FORCE)
|
|
||||||
# Jiri: Self-built TBB stores the debug libraries in a separate directory.
|
|
||||||
set (TBB_DEBUG_LIBRARY_DIRS ${TBB_LIBRARY_DEBUG_DIR} CACHE PATH "TBB debug library directory" FORCE)
|
|
||||||
mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARY_DIRS TBB_DEBUG_LIBRARY_DIRS TBB_LIBRARIES TBB_DEBUG_LIBRARIES)
|
|
||||||
message(STATUS "Found Intel TBB")
|
|
||||||
endif (TBB_LIBRARY)
|
|
||||||
endif (TBB_INCLUDE_DIR)
|
|
||||||
|
|
||||||
if (NOT TBB_FOUND)
|
|
||||||
message("ERROR: Intel TBB NOT found!")
|
|
||||||
message(STATUS "Looked for Threading Building Blocks in ${_TBB_INSTALL_DIR}")
|
|
||||||
# do only throw fatal, if this pkg is REQUIRED
|
|
||||||
if (TBB_FIND_REQUIRED)
|
|
||||||
message(FATAL_ERROR "Could NOT find TBB library.")
|
|
||||||
endif (TBB_FIND_REQUIRED)
|
|
||||||
endif (NOT TBB_FOUND)
|
|
||||||
|
|
||||||
endif (NOT _TBB_INSTALL_DIR)
|
|
||||||
|
|
||||||
if (TBB_FOUND)
|
|
||||||
set(TBB_INTERFACE_VERSION 0)
|
|
||||||
FILE(READ "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h" _TBB_VERSION_CONTENTS)
|
|
||||||
STRING(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${_TBB_VERSION_CONTENTS}")
|
|
||||||
set(TBB_INTERFACE_VERSION "${TBB_INTERFACE_VERSION}")
|
|
||||||
endif (TBB_FOUND)
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
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/data_structures/internal_datafacade.hpp MD5OBJECTS)
|
|
||||||
|
|
||||||
CONFIGURE_FILE(${SOURCE_DIR}/util/fingerprint_impl.hpp.in ${SOURCE_DIR}/util/fingerprint_impl.hpp)
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
# - Returns a version string from Git
|
|
||||||
#
|
|
||||||
# These functions force a re-configure on each git commit so that you can
|
|
||||||
# trust the values of the variables in your build system.
|
|
||||||
#
|
|
||||||
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
|
||||||
#
|
|
||||||
# Returns the refspec and sha hash of the current head revision
|
|
||||||
#
|
|
||||||
# git_describe(<var> [<additional arguments to git describe> ...])
|
|
||||||
#
|
|
||||||
# Returns the results of git describe on the source tree, and adjusting
|
|
||||||
# the output so that it tests false if an error occurs.
|
|
||||||
#
|
|
||||||
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
|
||||||
#
|
|
||||||
# Returns the results of git describe --exact-match on the source tree,
|
|
||||||
# and adjusting the output so that it tests false if there was no exact
|
|
||||||
# matching tag.
|
|
||||||
#
|
|
||||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
|
||||||
#
|
|
||||||
# Original Author:
|
|
||||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
|
||||||
# http://academic.cleardefinition.com
|
|
||||||
# Iowa State University HCI Graduate Program/VRAC
|
|
||||||
#
|
|
||||||
# Copyright Iowa State University 2009-2010.
|
|
||||||
# Distributed under the Boost Software License, Version 1.0.
|
|
||||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
# http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
if(__get_git_revision_description)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
set(__get_git_revision_description YES)
|
|
||||||
|
|
||||||
# We must run the following at "include" time, not at function call time,
|
|
||||||
# to find the path to this module rather than the path to a calling list file
|
|
||||||
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
|
||||||
|
|
||||||
function(get_git_head_revision _refspecvar _hashvar)
|
|
||||||
set(GIT_PARENT_DIR "${CMAKE_SOURCE_DIR}")
|
|
||||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
|
||||||
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
|
|
||||||
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
|
|
||||||
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
|
|
||||||
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
|
|
||||||
# We have reached the root directory, we are not in git
|
|
||||||
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
|
||||||
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
|
||||||
endwhile()
|
|
||||||
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
|
||||||
if(NOT EXISTS "${GIT_DATA}")
|
|
||||||
file(MAKE_DIRECTORY "${GIT_DATA}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT EXISTS "${GIT_DIR}/HEAD")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
|
||||||
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
|
|
||||||
|
|
||||||
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
|
||||||
"${GIT_DATA}/grabRef.cmake"
|
|
||||||
@ONLY)
|
|
||||||
include("${GIT_DATA}/grabRef.cmake")
|
|
||||||
|
|
||||||
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
|
|
||||||
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
function(git_describe _var)
|
|
||||||
if(NOT GIT_FOUND)
|
|
||||||
find_package(Git QUIET)
|
|
||||||
endif()
|
|
||||||
get_git_head_revision(refspec hash)
|
|
||||||
if(NOT GIT_FOUND)
|
|
||||||
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
if(NOT hash)
|
|
||||||
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# TODO sanitize
|
|
||||||
#if((${ARGN}" MATCHES "&&") OR
|
|
||||||
# (ARGN MATCHES "||") OR
|
|
||||||
# (ARGN MATCHES "\\;"))
|
|
||||||
# message("Please report the following error to the project!")
|
|
||||||
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
|
||||||
#endif()
|
|
||||||
|
|
||||||
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
|
||||||
|
|
||||||
execute_process(COMMAND
|
|
||||||
"${GIT_EXECUTABLE}"
|
|
||||||
describe
|
|
||||||
${hash}
|
|
||||||
${ARGN}
|
|
||||||
WORKING_DIRECTORY
|
|
||||||
"${CMAKE_SOURCE_DIR}"
|
|
||||||
RESULT_VARIABLE
|
|
||||||
res
|
|
||||||
OUTPUT_VARIABLE
|
|
||||||
out
|
|
||||||
ERROR_QUIET
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
if(NOT res EQUAL 0)
|
|
||||||
set(out "${out}-${res}-NOTFOUND")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${_var} "${out}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
function(git_get_exact_tag _var)
|
|
||||||
git_describe(out --exact-match ${ARGN})
|
|
||||||
set(${_var} "${out}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#
|
|
||||||
# Internal file for GetGitRevisionDescription.cmake
|
|
||||||
#
|
|
||||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
|
||||||
#
|
|
||||||
# Original Author:
|
|
||||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
|
||||||
# http://academic.cleardefinition.com
|
|
||||||
# Iowa State University HCI Graduate Program/VRAC
|
|
||||||
#
|
|
||||||
# Copyright Iowa State University 2009-2010.
|
|
||||||
# Distributed under the Boost Software License, Version 1.0.
|
|
||||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
# http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
set(HEAD_HASH)
|
|
||||||
|
|
||||||
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
|
||||||
|
|
||||||
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
|
||||||
if(HEAD_CONTENTS MATCHES "ref")
|
|
||||||
# named branch
|
|
||||||
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
|
||||||
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
|
||||||
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
|
||||||
elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}")
|
|
||||||
configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
|
||||||
set(HEAD_HASH "${HEAD_REF}")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
# detached HEAD
|
|
||||||
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT HEAD_HASH)
|
|
||||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
|
||||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
|
||||||
endif()
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
INCLUDE (CheckCXXSourceCompiles)
|
|
||||||
unset(LUABIND_WORKS CACHE)
|
|
||||||
unset(LUABIND51_WORKS CACHE)
|
|
||||||
set (LUABIND_CHECK_SRC "#include \"lua.h\"\n#include <luabind/luabind.hpp>\n int main() { lua_State *myLuaState = luaL_newstate(); luabind::open(myLuaState); return 0;}")
|
|
||||||
set (CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE})
|
|
||||||
set (CMAKE_REQUIRED_INCLUDES "${Boost_INCLUDE_DIR};${LUABIND_INCLUDE_DIR};${LUA_INCLUDE_DIR}")
|
|
||||||
set (CMAKE_REQUIRED_LIBRARIES "${LUABIND_LIBRARY};${LUA_LIBRARY}")
|
|
||||||
|
|
||||||
find_package(Lua52)
|
|
||||||
if(NOT APPLE)
|
|
||||||
find_package(LuaJIT 5.2)
|
|
||||||
endif()
|
|
||||||
if(LUA52_FOUND)
|
|
||||||
set (CMAKE_REQUIRED_INCLUDES "${Boost_INCLUDE_DIR};${LUABIND_INCLUDE_DIR};${LUA_INCLUDE_DIR}")
|
|
||||||
set (CMAKE_REQUIRED_LIBRARIES "${LUABIND_LIBRARY};${LUA_LIBRARY}")
|
|
||||||
CHECK_CXX_SOURCE_COMPILES("${LUABIND_CHECK_SRC}" LUABIND_WORKS)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(LUABIND_WORKS)
|
|
||||||
message(STATUS "Luabind/Lua5.2 combination working with ${LUA_LIBRARY}")
|
|
||||||
else()
|
|
||||||
message(STATUS "Luabind/Lua5.2 not feasible, falling back to Lua 5.1.")
|
|
||||||
unset(LUA_FOUND CACHE)
|
|
||||||
unset(LUA_INCLUDE_DIR CACHE)
|
|
||||||
unset(LUA_LIBRARY CACHE)
|
|
||||||
find_package(Lua51 REQUIRED)
|
|
||||||
if(NOT APPLE)
|
|
||||||
find_package(LuaJIT 5.1)
|
|
||||||
endif()
|
|
||||||
set (CMAKE_REQUIRED_INCLUDES "${Boost_INCLUDE_DIR};${LUABIND_INCLUDE_DIR};${LUA_INCLUDE_DIR}")
|
|
||||||
set (CMAKE_REQUIRED_LIBRARIES "${LUABIND_LIBRARY};${LUA_LIBRARY}")
|
|
||||||
|
|
||||||
CHECK_CXX_SOURCE_COMPILES("${LUABIND_CHECK_SRC}" LUABIND51_WORKS)
|
|
||||||
|
|
||||||
if(LUABIND51_WORKS)
|
|
||||||
message(STATUS "Luabind works with Lua 5.1 at ${LUA_LIBRARY}")
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "Luabind does not work with Lua 5.1 at ${LUA_LIBRARY}, no working Luabind found")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
# Based on @berenm's pull request https://github.com/quarnster/SublimeClang/pull/135
|
|
||||||
# Create the database with cmake with for example: cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
|
|
||||||
# or you could have set(CMAKE_EXPORT_COMPILE_COMMANDS ON) in your CMakeLists.txt
|
|
||||||
# Usage within SublimeClang:
|
|
||||||
# "sublimeclang_options_script": "python ${home}/code/cmake_options_script.py ${project_path:build}/compile_commands.json",
|
|
||||||
|
|
||||||
|
|
||||||
import re
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import pickle
|
|
||||||
import sys
|
|
||||||
import json
|
|
||||||
|
|
||||||
compilation_database_pattern = re.compile('(?<=\s)-[DIOUWfgs][^=\s]+(?:=\\"[^"]+\\"|=[^"]\S+)?')
|
|
||||||
|
|
||||||
def load_db(filename):
|
|
||||||
compilation_database = {}
|
|
||||||
with open(filename) as compilation_database_file:
|
|
||||||
compilation_database_entries = json.load(compilation_database_file)
|
|
||||||
|
|
||||||
total = len(compilation_database_entries)
|
|
||||||
entry = 0
|
|
||||||
for compilation_entry in compilation_database_entries:
|
|
||||||
entry = entry + 1
|
|
||||||
compilation_database[compilation_entry["file"]] = [ p.strip() for p in compilation_database_pattern.findall(compilation_entry["command"]) ]
|
|
||||||
return compilation_database
|
|
||||||
|
|
||||||
scriptpath = os.path.dirname(os.path.abspath(sys.argv[1]))
|
|
||||||
cache_file = "%s/cached_options.txt" % (scriptpath)
|
|
||||||
|
|
||||||
db = None
|
|
||||||
if os.access(cache_file, os.R_OK) == 0:
|
|
||||||
db = load_db(sys.argv[1])
|
|
||||||
f = open(cache_file, "wb")
|
|
||||||
pickle.dump(db, f)
|
|
||||||
f.close()
|
|
||||||
else:
|
|
||||||
f = open(cache_file)
|
|
||||||
db = pickle.load(f)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
if db and sys.argv[2] in db:
|
|
||||||
for option in db[sys.argv[2]]:
|
|
||||||
print option
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
prefix=@CMAKE_INSTALL_PREFIX@
|
|
||||||
includedir=${prefix}/include/osrm
|
|
||||||
libdir=${prefix}/lib
|
|
||||||
|
|
||||||
Name: libOSRM
|
|
||||||
Description: Project OSRM library
|
|
||||||
Version: @GIT_DESCRIPTION@
|
|
||||||
Requires:
|
|
||||||
Libs: -L${libdir} -lOSRM
|
|
||||||
Libs.private: @BOOST_LIBRARY_LISTING@
|
|
||||||
Cflags: -I${includedir}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#/usr/bin/env bash
|
|
||||||
ln -s /usr/share/doc/@CMAKE_PROJECT_NAME@/profiles/car.lua @CMAKE_INSTALL_PREFIX@/profile.lua
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# config/cucumber.yml
|
|
||||||
##YAML Template
|
|
||||||
---
|
|
||||||
default: --require features --tags ~@todo --tags ~@bug --tag ~@stress
|
|
||||||
verify: --require features --tags ~@todo --tags ~@bug --tags ~@stress -f progress
|
|
||||||
jenkins: --require features --tags ~@todo --tags ~@bug --tags ~@stress --tags ~@options -f progress
|
|
||||||
bugs: --require features --tags @bug
|
|
||||||
todo: --require features --tags @todo
|
|
||||||
all: --require features
|
|
||||||
@@ -1,962 +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 CONTRACTOR_HPP
|
|
||||||
#define CONTRACTOR_HPP
|
|
||||||
|
|
||||||
#include "../data_structures/binary_heap.hpp"
|
|
||||||
#include "../data_structures/deallocating_vector.hpp"
|
|
||||||
#include "../data_structures/dynamic_graph.hpp"
|
|
||||||
#include "../data_structures/percent.hpp"
|
|
||||||
#include "../data_structures/query_edge.hpp"
|
|
||||||
#include "../data_structures/xor_fast_hash.hpp"
|
|
||||||
#include "../data_structures/xor_fast_hash_storage.hpp"
|
|
||||||
#include "../util/integer_range.hpp"
|
|
||||||
#include "../util/simple_logger.hpp"
|
|
||||||
#include "../util/timing_util.hpp"
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
#include <stxxl/vector>
|
|
||||||
|
|
||||||
#include <tbb/enumerable_thread_specific.h>
|
|
||||||
#include <tbb/parallel_for.h>
|
|
||||||
#include <tbb/parallel_sort.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <limits>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class Contractor
|
|
||||||
{
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct ContractorEdgeData
|
|
||||||
{
|
|
||||||
ContractorEdgeData()
|
|
||||||
: distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0),
|
|
||||||
is_original_via_node_ID(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
ContractorEdgeData(unsigned distance,
|
|
||||||
unsigned original_edges,
|
|
||||||
unsigned id,
|
|
||||||
bool shortcut,
|
|
||||||
bool forward,
|
|
||||||
bool backward)
|
|
||||||
: distance(distance), id(id),
|
|
||||||
originalEdges(std::min((unsigned)1 << 28, original_edges)), shortcut(shortcut),
|
|
||||||
forward(forward), backward(backward), is_original_via_node_ID(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
unsigned distance;
|
|
||||||
unsigned id;
|
|
||||||
unsigned originalEdges : 28;
|
|
||||||
bool shortcut : 1;
|
|
||||||
bool forward : 1;
|
|
||||||
bool backward : 1;
|
|
||||||
bool is_original_via_node_ID : 1;
|
|
||||||
} data;
|
|
||||||
|
|
||||||
struct ContractorHeapData
|
|
||||||
{
|
|
||||||
short hop;
|
|
||||||
bool target;
|
|
||||||
ContractorHeapData() : hop(0), target(false) {}
|
|
||||||
ContractorHeapData(short h, bool t) : hop(h), target(t) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
using ContractorGraph = DynamicGraph<ContractorEdgeData>;
|
|
||||||
// using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData,
|
|
||||||
// ArrayStorage<NodeID, NodeID>
|
|
||||||
// >;
|
|
||||||
using ContractorHeap =
|
|
||||||
BinaryHeap<NodeID, NodeID, int, ContractorHeapData, XORFastHashStorage<NodeID, NodeID>>;
|
|
||||||
using ContractorEdge = ContractorGraph::InputEdge;
|
|
||||||
|
|
||||||
struct ContractorThreadData
|
|
||||||
{
|
|
||||||
ContractorHeap heap;
|
|
||||||
std::vector<ContractorEdge> inserted_edges;
|
|
||||||
std::vector<NodeID> neighbours;
|
|
||||||
explicit ContractorThreadData(NodeID nodes) : heap(nodes) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NodePriorityData
|
|
||||||
{
|
|
||||||
int depth;
|
|
||||||
NodePriorityData() : depth(0) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ContractionStats
|
|
||||||
{
|
|
||||||
int edges_deleted_count;
|
|
||||||
int edges_added_count;
|
|
||||||
int original_edges_deleted_count;
|
|
||||||
int original_edges_added_count;
|
|
||||||
ContractionStats()
|
|
||||||
: edges_deleted_count(0), edges_added_count(0), original_edges_deleted_count(0),
|
|
||||||
original_edges_added_count(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RemainingNodeData
|
|
||||||
{
|
|
||||||
RemainingNodeData() : id(0), is_independent(false) {}
|
|
||||||
NodeID id : 31;
|
|
||||||
bool is_independent : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ThreadDataContainer
|
|
||||||
{
|
|
||||||
explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {}
|
|
||||||
|
|
||||||
inline ContractorThreadData *getThreadData()
|
|
||||||
{
|
|
||||||
bool exists = false;
|
|
||||||
auto &ref = data.local(exists);
|
|
||||||
if (!exists)
|
|
||||||
{
|
|
||||||
ref = std::make_shared<ContractorThreadData>(number_of_nodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ref.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
int number_of_nodes;
|
|
||||||
using EnumerableThreadData =
|
|
||||||
tbb::enumerable_thread_specific<std::shared_ptr<ContractorThreadData>>;
|
|
||||||
EnumerableThreadData data;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
template <class ContainerT> Contractor(int nodes, ContainerT &input_edge_list)
|
|
||||||
{
|
|
||||||
std::vector<ContractorEdge> edges;
|
|
||||||
edges.reserve(input_edge_list.size() * 2);
|
|
||||||
|
|
||||||
const auto dend = input_edge_list.dend();
|
|
||||||
for (auto diter = input_edge_list.dbegin(); diter != dend; ++diter)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT_MSG(static_cast<unsigned int>(std::max(diter->weight, 1)) > 0,
|
|
||||||
"edge distance < 1");
|
|
||||||
#ifndef NDEBUG
|
|
||||||
if (static_cast<unsigned int>(std::max(diter->weight, 1)) > 24 * 60 * 60 * 10)
|
|
||||||
{
|
|
||||||
SimpleLogger().Write(logWARNING)
|
|
||||||
<< "Edge weight large -> "
|
|
||||||
<< static_cast<unsigned int>(std::max(diter->weight, 1));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
edges.emplace_back(diter->source, diter->target,
|
|
||||||
static_cast<unsigned int>(std::max(diter->weight, 1)), 1,
|
|
||||||
diter->edge_id, false, diter->forward ? true : false,
|
|
||||||
diter->backward ? true : false);
|
|
||||||
|
|
||||||
edges.emplace_back(diter->target, diter->source,
|
|
||||||
static_cast<unsigned int>(std::max(diter->weight, 1)), 1,
|
|
||||||
diter->edge_id, false, diter->backward ? true : false,
|
|
||||||
diter->forward ? true : false);
|
|
||||||
}
|
|
||||||
// clear input vector
|
|
||||||
input_edge_list.clear();
|
|
||||||
edges.shrink_to_fit();
|
|
||||||
|
|
||||||
tbb::parallel_sort(edges.begin(), edges.end());
|
|
||||||
NodeID edge = 0;
|
|
||||||
for (NodeID i = 0; i < edges.size();)
|
|
||||||
{
|
|
||||||
const NodeID source = edges[i].source;
|
|
||||||
const NodeID target = edges[i].target;
|
|
||||||
const NodeID id = edges[i].data.id;
|
|
||||||
// remove eigenloops
|
|
||||||
if (source == target)
|
|
||||||
{
|
|
||||||
++i;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ContractorEdge forward_edge;
|
|
||||||
ContractorEdge reverse_edge;
|
|
||||||
forward_edge.source = reverse_edge.source = source;
|
|
||||||
forward_edge.target = reverse_edge.target = target;
|
|
||||||
forward_edge.data.forward = reverse_edge.data.backward = true;
|
|
||||||
forward_edge.data.backward = reverse_edge.data.forward = false;
|
|
||||||
forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
|
|
||||||
forward_edge.data.id = reverse_edge.data.id = id;
|
|
||||||
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
|
|
||||||
forward_edge.data.distance = reverse_edge.data.distance =
|
|
||||||
std::numeric_limits<int>::max();
|
|
||||||
// remove parallel edges
|
|
||||||
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
|
|
||||||
{
|
|
||||||
if (edges[i].data.forward)
|
|
||||||
{
|
|
||||||
forward_edge.data.distance =
|
|
||||||
std::min(edges[i].data.distance, forward_edge.data.distance);
|
|
||||||
}
|
|
||||||
if (edges[i].data.backward)
|
|
||||||
{
|
|
||||||
reverse_edge.data.distance =
|
|
||||||
std::min(edges[i].data.distance, reverse_edge.data.distance);
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
// merge edges (s,t) and (t,s) into bidirectional edge
|
|
||||||
if (forward_edge.data.distance == reverse_edge.data.distance)
|
|
||||||
{
|
|
||||||
if ((int)forward_edge.data.distance != std::numeric_limits<int>::max())
|
|
||||||
{
|
|
||||||
forward_edge.data.backward = true;
|
|
||||||
edges[edge++] = forward_edge;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // insert seperate edges
|
|
||||||
if (((int)forward_edge.data.distance) != std::numeric_limits<int>::max())
|
|
||||||
{
|
|
||||||
edges[edge++] = forward_edge;
|
|
||||||
}
|
|
||||||
if ((int)reverse_edge.data.distance != std::numeric_limits<int>::max())
|
|
||||||
{
|
|
||||||
edges[edge++] = reverse_edge;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size()
|
|
||||||
<< std::endl;
|
|
||||||
edges.resize(edge);
|
|
||||||
contractor_graph = std::make_shared<ContractorGraph>(nodes, edges);
|
|
||||||
edges.clear();
|
|
||||||
edges.shrink_to_fit();
|
|
||||||
|
|
||||||
BOOST_ASSERT(0 == edges.capacity());
|
|
||||||
// unsigned maxdegree = 0;
|
|
||||||
// NodeID highestNode = 0;
|
|
||||||
//
|
|
||||||
// for(unsigned i = 0; i < contractor_graph->GetNumberOfNodes(); ++i) {
|
|
||||||
// unsigned degree = contractor_graph->EndEdges(i) -
|
|
||||||
// contractor_graph->BeginEdges(i);
|
|
||||||
// if(degree > maxdegree) {
|
|
||||||
// maxdegree = degree;
|
|
||||||
// highestNode = i;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// SimpleLogger().Write() << "edges at node with id " << highestNode << " has degree
|
|
||||||
// " << maxdegree;
|
|
||||||
// for(unsigned i = contractor_graph->BeginEdges(highestNode); i <
|
|
||||||
// contractor_graph->EndEdges(highestNode); ++i) {
|
|
||||||
// SimpleLogger().Write() << " ->(" << highestNode << "," <<
|
|
||||||
// contractor_graph->GetTarget(i)
|
|
||||||
// << "); via: " << contractor_graph->GetEdgeData(i).via;
|
|
||||||
// }
|
|
||||||
|
|
||||||
std::cout << "contractor finished initalization" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
~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;
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
|
||||||
Percent p(number_of_nodes);
|
|
||||||
|
|
||||||
ThreadDataContainer thread_data_list(number_of_nodes);
|
|
||||||
|
|
||||||
NodeID number_of_contracted_nodes = 0;
|
|
||||||
std::vector<RemainingNodeData> remaining_nodes(number_of_nodes);
|
|
||||||
std::vector<float> node_priorities(number_of_nodes);
|
|
||||||
std::vector<NodePriorityData> node_data(number_of_nodes);
|
|
||||||
|
|
||||||
// initialize priorities in parallel
|
|
||||||
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, InitGrainSize),
|
|
||||||
[&remaining_nodes](const tbb::blocked_range<int> &range)
|
|
||||||
{
|
|
||||||
for (int x = range.begin(); x != range.end(); ++x)
|
|
||||||
{
|
|
||||||
remaining_nodes[x].id = x;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
std::cout << "initializing elimination PQ ..." << std::flush;
|
|
||||||
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, PQGrainSize),
|
|
||||||
[this, &node_priorities, &node_data, &thread_data_list](
|
|
||||||
const tbb::blocked_range<int> &range)
|
|
||||||
{
|
|
||||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
|
||||||
for (int x = range.begin(); x != range.end(); ++x)
|
|
||||||
{
|
|
||||||
node_priorities[x] =
|
|
||||||
this->EvaluateNodePriority(data, &node_data[x], x);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
std::cout << "ok" << std::endl << "preprocessing " << number_of_nodes << " nodes ..."
|
|
||||||
<< std::flush;
|
|
||||||
|
|
||||||
bool flushed_contractor = false;
|
|
||||||
while (number_of_nodes > 2 && number_of_contracted_nodes < number_of_nodes)
|
|
||||||
{
|
|
||||||
if (!flushed_contractor && (number_of_contracted_nodes > (number_of_nodes * 0.65)))
|
|
||||||
{
|
|
||||||
DeallocatingVector<ContractorEdge> new_edge_set; // this one is not explicitely
|
|
||||||
// cleared since it goes out of
|
|
||||||
// scope anywa
|
|
||||||
std::cout << " [flush " << number_of_contracted_nodes << " nodes] " << std::flush;
|
|
||||||
|
|
||||||
// Delete old heap data to free memory that we need for the coming operations
|
|
||||||
thread_data_list.data.clear();
|
|
||||||
|
|
||||||
// Create new priority array
|
|
||||||
std::vector<float> new_node_priority(remaining_nodes.size());
|
|
||||||
// this map gives the old IDs from the new ones, necessary to get a consistent graph
|
|
||||||
// at the end of contraction
|
|
||||||
orig_node_id_to_new_id_map.resize(remaining_nodes.size());
|
|
||||||
// this map gives the new IDs from the old ones, necessary to remap targets from the
|
|
||||||
// remaining graph
|
|
||||||
std::vector<NodeID> new_node_id_from_orig_id_map(number_of_nodes, UINT_MAX);
|
|
||||||
|
|
||||||
// build forward and backward renumbering map and remap ids in remaining_nodes and
|
|
||||||
// Priorities.
|
|
||||||
for (const auto new_node_id : osrm::irange<std::size_t>(0, remaining_nodes.size()))
|
|
||||||
{
|
|
||||||
// create renumbering maps in both directions
|
|
||||||
orig_node_id_to_new_id_map[new_node_id] = remaining_nodes[new_node_id].id;
|
|
||||||
new_node_id_from_orig_id_map[remaining_nodes[new_node_id].id] = new_node_id;
|
|
||||||
new_node_priority[new_node_id] =
|
|
||||||
node_priorities[remaining_nodes[new_node_id].id];
|
|
||||||
remaining_nodes[new_node_id].id = new_node_id;
|
|
||||||
}
|
|
||||||
// walk over all nodes
|
|
||||||
for (const auto i :
|
|
||||||
osrm::irange<std::size_t>(0, contractor_graph->GetNumberOfNodes()))
|
|
||||||
{
|
|
||||||
const NodeID source = i;
|
|
||||||
for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source))
|
|
||||||
{
|
|
||||||
ContractorGraph::EdgeData &data =
|
|
||||||
contractor_graph->GetEdgeData(current_edge);
|
|
||||||
const NodeID target = contractor_graph->GetTarget(current_edge);
|
|
||||||
if (SPECIAL_NODEID == new_node_id_from_orig_id_map[i])
|
|
||||||
{
|
|
||||||
external_edge_list.push_back({source, target, data});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 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};
|
|
||||||
|
|
||||||
new_edge.data.is_original_via_node_ID = true;
|
|
||||||
BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[source],
|
|
||||||
"new source id not resolveable");
|
|
||||||
BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[target],
|
|
||||||
"new target id not resolveable");
|
|
||||||
new_edge_set.push_back(new_edge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete map from old NodeIDs to new ones.
|
|
||||||
new_node_id_from_orig_id_map.clear();
|
|
||||||
new_node_id_from_orig_id_map.shrink_to_fit();
|
|
||||||
|
|
||||||
// Replace old priorities array by new one
|
|
||||||
node_priorities.swap(new_node_priority);
|
|
||||||
// Delete old node_priorities vector
|
|
||||||
new_node_priority.clear();
|
|
||||||
new_node_priority.shrink_to_fit();
|
|
||||||
// old Graph is removed
|
|
||||||
contractor_graph.reset();
|
|
||||||
|
|
||||||
// create new graph
|
|
||||||
std::sort(new_edge_set.begin(), new_edge_set.end());
|
|
||||||
contractor_graph =
|
|
||||||
std::make_shared<ContractorGraph>(remaining_nodes.size(), new_edge_set);
|
|
||||||
|
|
||||||
new_edge_set.clear();
|
|
||||||
flushed_contractor = true;
|
|
||||||
|
|
||||||
// INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
|
|
||||||
// reinitialize heaps and ThreadData objects with appropriate size
|
|
||||||
thread_data_list.number_of_nodes = contractor_graph->GetNumberOfNodes();
|
|
||||||
}
|
|
||||||
|
|
||||||
const int last = (int)remaining_nodes.size();
|
|
||||||
tbb::parallel_for(tbb::blocked_range<int>(0, last, IndependentGrainSize),
|
|
||||||
[this, &node_priorities, &remaining_nodes, &thread_data_list](
|
|
||||||
const tbb::blocked_range<int> &range)
|
|
||||||
{
|
|
||||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
|
||||||
// determine independent node set
|
|
||||||
for (int i = range.begin(); i != range.end(); ++i)
|
|
||||||
{
|
|
||||||
const NodeID node = remaining_nodes[i].id;
|
|
||||||
remaining_nodes[i].is_independent =
|
|
||||||
this->IsNodeIndependent(node_priorities, data, node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const auto first = stable_partition(remaining_nodes.begin(), remaining_nodes.end(),
|
|
||||||
[](RemainingNodeData node_data)
|
|
||||||
{
|
|
||||||
return !node_data.is_independent;
|
|
||||||
});
|
|
||||||
const int first_independent_node = static_cast<int>(first - remaining_nodes.begin());
|
|
||||||
|
|
||||||
// contract independent nodes
|
|
||||||
tbb::parallel_for(
|
|
||||||
tbb::blocked_range<int>(first_independent_node, last, ContractGrainSize),
|
|
||||||
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
|
|
||||||
{
|
|
||||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
|
||||||
for (int position = range.begin(); position != range.end(); ++position)
|
|
||||||
{
|
|
||||||
const NodeID x = remaining_nodes[position].id;
|
|
||||||
this->ContractNode<false>(data, x);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// make sure we really sort each block
|
|
||||||
tbb::parallel_for(
|
|
||||||
thread_data_list.data.range(),
|
|
||||||
[&](const ThreadDataContainer::EnumerableThreadData::range_type &range)
|
|
||||||
{
|
|
||||||
for (auto &data : range)
|
|
||||||
std::sort(data->inserted_edges.begin(), data->inserted_edges.end());
|
|
||||||
});
|
|
||||||
tbb::parallel_for(
|
|
||||||
tbb::blocked_range<int>(first_independent_node, last, DeleteGrainSize),
|
|
||||||
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
|
|
||||||
{
|
|
||||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
|
||||||
for (int position = range.begin(); position != range.end(); ++position)
|
|
||||||
{
|
|
||||||
const NodeID x = remaining_nodes[position].id;
|
|
||||||
this->DeleteIncomingEdges(data, x);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// insert new edges
|
|
||||||
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);
|
|
||||||
if (current_edge_ID < contractor_graph->EndEdges(edge.source))
|
|
||||||
{
|
|
||||||
ContractorGraph::EdgeData ¤t_data =
|
|
||||||
contractor_graph->GetEdgeData(current_edge_ID);
|
|
||||||
if (current_data.shortcut && edge.data.forward == current_data.forward &&
|
|
||||||
edge.data.backward == current_data.backward &&
|
|
||||||
edge.data.distance < current_data.distance)
|
|
||||||
{
|
|
||||||
// found a duplicate edge with smaller weight, update it.
|
|
||||||
current_data = edge.data;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
contractor_graph->InsertEdge(edge.source, edge.target, edge.data);
|
|
||||||
}
|
|
||||||
data->inserted_edges.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
tbb::parallel_for(
|
|
||||||
tbb::blocked_range<int>(first_independent_node, last, NeighboursGrainSize),
|
|
||||||
[this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list](
|
|
||||||
const tbb::blocked_range<int> &range)
|
|
||||||
{
|
|
||||||
ContractorThreadData *data = thread_data_list.getThreadData();
|
|
||||||
for (int position = range.begin(); position != range.end(); ++position)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
remaining_nodes.resize(first_independent_node);
|
|
||||||
remaining_nodes.shrink_to_fit();
|
|
||||||
// unsigned maxdegree = 0;
|
|
||||||
// unsigned avgdegree = 0;
|
|
||||||
// unsigned mindegree = UINT_MAX;
|
|
||||||
// unsigned quaddegree = 0;
|
|
||||||
//
|
|
||||||
// for(unsigned i = 0; i < remaining_nodes.size(); ++i) {
|
|
||||||
// unsigned degree = contractor_graph->EndEdges(remaining_nodes[i].first)
|
|
||||||
// -
|
|
||||||
// contractor_graph->BeginEdges(remaining_nodes[i].first);
|
|
||||||
// if(degree > maxdegree)
|
|
||||||
// maxdegree = degree;
|
|
||||||
// if(degree < mindegree)
|
|
||||||
// mindegree = degree;
|
|
||||||
//
|
|
||||||
// avgdegree += degree;
|
|
||||||
// quaddegree += (degree*degree);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// avgdegree /= std::max((unsigned)1,(unsigned)remaining_nodes.size() );
|
|
||||||
// quaddegree /= std::max((unsigned)1,(unsigned)remaining_nodes.size() );
|
|
||||||
//
|
|
||||||
// SimpleLogger().Write() << "rest: " << remaining_nodes.size() << ", max: "
|
|
||||||
// << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ",
|
|
||||||
// quad: " << quaddegree;
|
|
||||||
|
|
||||||
p.printStatus(number_of_contracted_nodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_data_list.data.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Edge> inline void GetEdges(DeallocatingVector<Edge> &edges)
|
|
||||||
{
|
|
||||||
Percent p(contractor_graph->GetNumberOfNodes());
|
|
||||||
SimpleLogger().Write() << "Getting edges of minimized graph";
|
|
||||||
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
|
||||||
if (contractor_graph->GetNumberOfNodes())
|
|
||||||
{
|
|
||||||
Edge new_edge;
|
|
||||||
for (const auto node : osrm::irange(0u, number_of_nodes))
|
|
||||||
{
|
|
||||||
p.printStatus(node);
|
|
||||||
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const NodeID target = contractor_graph->GetTarget(edge);
|
|
||||||
const ContractorGraph::EdgeData &data = contractor_graph->GetEdgeData(edge);
|
|
||||||
if (!orig_node_id_to_new_id_map.empty())
|
|
||||||
{
|
|
||||||
new_edge.source = orig_node_id_to_new_id_map[node];
|
|
||||||
new_edge.target = orig_node_id_to_new_id_map[target];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new_edge.source = node;
|
|
||||||
new_edge.target = target;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT_MSG(UINT_MAX != new_edge.source, "Source id invalid");
|
|
||||||
BOOST_ASSERT_MSG(UINT_MAX != new_edge.target, "Target id invalid");
|
|
||||||
new_edge.data.distance = data.distance;
|
|
||||||
new_edge.data.shortcut = data.shortcut;
|
|
||||||
if (!data.is_original_via_node_ID && !orig_node_id_to_new_id_map.empty())
|
|
||||||
{
|
|
||||||
new_edge.data.id = orig_node_id_to_new_id_map[data.id];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new_edge.data.id = data.id;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT_MSG(new_edge.data.id != INT_MAX, // 2^31
|
|
||||||
"edge id invalid");
|
|
||||||
new_edge.data.forward = data.forward;
|
|
||||||
new_edge.data.backward = data.backward;
|
|
||||||
edges.push_back(new_edge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
contractor_graph.reset();
|
|
||||||
orig_node_id_to_new_id_map.clear();
|
|
||||||
orig_node_id_to_new_id_map.shrink_to_fit();
|
|
||||||
|
|
||||||
BOOST_ASSERT(0 == orig_node_id_to_new_id_map.capacity());
|
|
||||||
|
|
||||||
edges.append(external_edge_list.begin(), external_edge_list.end());
|
|
||||||
external_edge_list.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
inline void Dijkstra(const int max_distance,
|
|
||||||
const unsigned number_of_targets,
|
|
||||||
const int maxNodes,
|
|
||||||
ContractorThreadData *const data,
|
|
||||||
const NodeID middleNode)
|
|
||||||
{
|
|
||||||
|
|
||||||
ContractorHeap &heap = data->heap;
|
|
||||||
|
|
||||||
int nodes = 0;
|
|
||||||
unsigned number_of_targets_found = 0;
|
|
||||||
while (!heap.Empty())
|
|
||||||
{
|
|
||||||
const NodeID node = heap.DeleteMin();
|
|
||||||
const int distance = heap.GetKey(node);
|
|
||||||
const short current_hop = heap.GetData(node).hop + 1;
|
|
||||||
|
|
||||||
if (++nodes > maxNodes)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (distance > max_distance)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destination settled?
|
|
||||||
if (heap.GetData(node).target)
|
|
||||||
{
|
|
||||||
++number_of_targets_found;
|
|
||||||
if (number_of_targets_found >= number_of_targets)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// iterate over all edges of node
|
|
||||||
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const ContractorEdgeData &data = contractor_graph->GetEdgeData(edge);
|
|
||||||
if (!data.forward)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const NodeID to = contractor_graph->GetTarget(edge);
|
|
||||||
if (middleNode == to)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const int to_distance = distance + data.distance;
|
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
|
||||||
if (!heap.WasInserted(to))
|
|
||||||
{
|
|
||||||
heap.Insert(to, to_distance, ContractorHeapData(current_hop, false));
|
|
||||||
}
|
|
||||||
// Found a shorter Path -> Update distance
|
|
||||||
else if (to_distance < heap.GetKey(to))
|
|
||||||
{
|
|
||||||
heap.DecreaseKey(to, to_distance);
|
|
||||||
heap.GetData(to).hop = current_hop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float EvaluateNodePriority(ContractorThreadData *const data,
|
|
||||||
NodePriorityData *const node_data,
|
|
||||||
const NodeID node)
|
|
||||||
{
|
|
||||||
ContractionStats stats;
|
|
||||||
|
|
||||||
// perform simulated contraction
|
|
||||||
ContractNode<true>(data, node, &stats);
|
|
||||||
|
|
||||||
// Result will contain the priority
|
|
||||||
float result;
|
|
||||||
if (0 == (stats.edges_deleted_count * stats.original_edges_deleted_count))
|
|
||||||
{
|
|
||||||
result = 1.f * node_data->depth;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = 2.f * (((float)stats.edges_added_count) / stats.edges_deleted_count) +
|
|
||||||
4.f * (((float)stats.original_edges_added_count) /
|
|
||||||
stats.original_edges_deleted_count) +
|
|
||||||
1.f * node_data->depth;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT(result >= 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool RUNSIMULATION>
|
|
||||||
inline bool
|
|
||||||
ContractNode(ContractorThreadData *data, const NodeID node, ContractionStats *stats = nullptr)
|
|
||||||
{
|
|
||||||
ContractorHeap &heap = data->heap;
|
|
||||||
int inserted_edges_size = data->inserted_edges.size();
|
|
||||||
std::vector<ContractorEdge> &inserted_edges = data->inserted_edges;
|
|
||||||
|
|
||||||
for (auto in_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const ContractorEdgeData &in_data = contractor_graph->GetEdgeData(in_edge);
|
|
||||||
const NodeID source = contractor_graph->GetTarget(in_edge);
|
|
||||||
if (RUNSIMULATION)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(stats != nullptr);
|
|
||||||
++stats->edges_deleted_count;
|
|
||||||
stats->original_edges_deleted_count += in_data.originalEdges;
|
|
||||||
}
|
|
||||||
if (!in_data.backward)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
heap.Clear();
|
|
||||||
heap.Insert(source, 0, ContractorHeapData());
|
|
||||||
int max_distance = 0;
|
|
||||||
unsigned number_of_targets = 0;
|
|
||||||
|
|
||||||
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge);
|
|
||||||
if (!out_data.forward)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const NodeID target = contractor_graph->GetTarget(out_edge);
|
|
||||||
const int path_distance = in_data.distance + out_data.distance;
|
|
||||||
max_distance = std::max(max_distance, path_distance);
|
|
||||||
if (!heap.WasInserted(target))
|
|
||||||
{
|
|
||||||
heap.Insert(target, INT_MAX, ContractorHeapData(0, true));
|
|
||||||
++number_of_targets;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RUNSIMULATION)
|
|
||||||
{
|
|
||||||
Dijkstra(max_distance, number_of_targets, 1000, data, node);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Dijkstra(max_distance, number_of_targets, 2000, data, node);
|
|
||||||
}
|
|
||||||
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge);
|
|
||||||
if (!out_data.forward)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const NodeID target = contractor_graph->GetTarget(out_edge);
|
|
||||||
const int path_distance = in_data.distance + out_data.distance;
|
|
||||||
const int distance = heap.GetKey(target);
|
|
||||||
if (path_distance < distance)
|
|
||||||
{
|
|
||||||
if (RUNSIMULATION)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(stats != nullptr);
|
|
||||||
stats->edges_added_count += 2;
|
|
||||||
stats->original_edges_added_count +=
|
|
||||||
2 * (out_data.originalEdges + in_data.originalEdges);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inserted_edges.emplace_back(source, target, path_distance,
|
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
|
||||||
node, true, true, false);
|
|
||||||
|
|
||||||
inserted_edges.emplace_back(target, source, path_distance,
|
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
|
||||||
node, true, false, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!RUNSIMULATION)
|
|
||||||
{
|
|
||||||
int iend = inserted_edges.size();
|
|
||||||
for (int i = inserted_edges_size; i < iend; ++i)
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
for (int other = i + 1; other < iend; ++other)
|
|
||||||
{
|
|
||||||
if (inserted_edges[other].source != inserted_edges[i].source)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (inserted_edges[other].target != inserted_edges[i].target)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (inserted_edges[other].data.distance != inserted_edges[i].data.distance)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (inserted_edges[other].data.shortcut != inserted_edges[i].data.shortcut)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
inserted_edges[other].data.forward |= inserted_edges[i].data.forward;
|
|
||||||
inserted_edges[other].data.backward |= inserted_edges[i].data.backward;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
inserted_edges[inserted_edges_size++] = inserted_edges[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inserted_edges.resize(inserted_edges_size);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void DeleteIncomingEdges(ContractorThreadData *data, const NodeID node)
|
|
||||||
{
|
|
||||||
std::vector<NodeID> &neighbours = data->neighbours;
|
|
||||||
neighbours.clear();
|
|
||||||
|
|
||||||
// find all neighbours
|
|
||||||
for (auto e : contractor_graph->GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const NodeID u = contractor_graph->GetTarget(e);
|
|
||||||
if (u != node)
|
|
||||||
{
|
|
||||||
neighbours.push_back(u);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// eliminate duplicate entries ( forward + backward edges )
|
|
||||||
std::sort(neighbours.begin(), neighbours.end());
|
|
||||||
neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
|
|
||||||
|
|
||||||
for (const auto i : osrm::irange<std::size_t>(0, neighbours.size()))
|
|
||||||
{
|
|
||||||
contractor_graph->DeleteEdgesTo(neighbours[i], node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool UpdateNodeNeighbours(std::vector<float> &priorities,
|
|
||||||
std::vector<NodePriorityData> &node_data,
|
|
||||||
ContractorThreadData *const data,
|
|
||||||
const NodeID node)
|
|
||||||
{
|
|
||||||
std::vector<NodeID> &neighbours = data->neighbours;
|
|
||||||
neighbours.clear();
|
|
||||||
|
|
||||||
// find all neighbours
|
|
||||||
for (auto e : contractor_graph->GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const NodeID u = contractor_graph->GetTarget(e);
|
|
||||||
if (u == node)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
neighbours.push_back(u);
|
|
||||||
node_data[u].depth = (std::max)(node_data[node].depth + 1, node_data[u].depth);
|
|
||||||
}
|
|
||||||
// eliminate duplicate entries ( forward + backward edges )
|
|
||||||
std::sort(neighbours.begin(), neighbours.end());
|
|
||||||
neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
|
|
||||||
|
|
||||||
// re-evaluate priorities of neighboring nodes
|
|
||||||
for (const NodeID u : neighbours)
|
|
||||||
{
|
|
||||||
priorities[u] = EvaluateNodePriority(data, &(node_data)[u], u);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool IsNodeIndependent(const std::vector<float> &priorities,
|
|
||||||
ContractorThreadData *const data,
|
|
||||||
NodeID node) const
|
|
||||||
{
|
|
||||||
const float priority = priorities[node];
|
|
||||||
|
|
||||||
std::vector<NodeID> &neighbours = data->neighbours;
|
|
||||||
neighbours.clear();
|
|
||||||
|
|
||||||
for (auto e : contractor_graph->GetAdjacentEdgeRange(node))
|
|
||||||
{
|
|
||||||
const NodeID target = contractor_graph->GetTarget(e);
|
|
||||||
if (node == target)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const float target_priority = priorities[target];
|
|
||||||
BOOST_ASSERT(target_priority >= 0);
|
|
||||||
// found a neighbour with lower priority?
|
|
||||||
if (priority > target_priority)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// tie breaking
|
|
||||||
if (std::abs(priority - target_priority) < std::numeric_limits<float>::epsilon() &&
|
|
||||||
bias(node, target))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
neighbours.push_back(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(neighbours.begin(), neighbours.end());
|
|
||||||
neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
|
|
||||||
|
|
||||||
// examine all neighbours that are at most 2 hops away
|
|
||||||
for (const NodeID u : neighbours)
|
|
||||||
{
|
|
||||||
for (auto e : contractor_graph->GetAdjacentEdgeRange(u))
|
|
||||||
{
|
|
||||||
const NodeID target = contractor_graph->GetTarget(e);
|
|
||||||
if (node == target)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const float target_priority = priorities[target];
|
|
||||||
BOOST_ASSERT(target_priority >= 0);
|
|
||||||
// found a neighbour with lower priority?
|
|
||||||
if (priority > target_priority)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// tie breaking
|
|
||||||
if (std::abs(priority - target_priority) < std::numeric_limits<float>::epsilon() &&
|
|
||||||
bias(node, target))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This bias function takes up 22 assembly instructions in total on X86
|
|
||||||
inline bool bias(const NodeID a, const NodeID b) const
|
|
||||||
{
|
|
||||||
const unsigned short hasha = fast_hash(a);
|
|
||||||
const unsigned short hashb = fast_hash(b);
|
|
||||||
|
|
||||||
// The compiler optimizes that to conditional register flags but without branching
|
|
||||||
// statements!
|
|
||||||
if (hasha != hashb)
|
|
||||||
{
|
|
||||||
return hasha < hashb;
|
|
||||||
}
|
|
||||||
return a < b;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<ContractorGraph> contractor_graph;
|
|
||||||
std::vector<ContractorGraph::InputEdge> contracted_edge_list;
|
|
||||||
stxxl::vector<QueryEdge> external_edge_list;
|
|
||||||
std::vector<NodeID> orig_node_id_to_new_id_map;
|
|
||||||
XORFastHash fast_hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CONTRACTOR_HPP
|
|
||||||
@@ -1,762 +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.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "edge_based_graph_factory.hpp"
|
|
||||||
#include "../algorithms/tiny_components.hpp"
|
|
||||||
#include "../data_structures/percent.hpp"
|
|
||||||
#include "../util/compute_angle.hpp"
|
|
||||||
#include "../util/integer_range.hpp"
|
|
||||||
#include "../util/lua_util.hpp"
|
|
||||||
#include "../util/simple_logger.hpp"
|
|
||||||
#include "../util/timing_util.hpp"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
|
||||||
const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
|
|
||||||
std::unique_ptr<RestrictionMap> restriction_map,
|
|
||||||
std::vector<NodeID> &barrier_node_list,
|
|
||||||
std::vector<NodeID> &traffic_light_node_list,
|
|
||||||
std::vector<QueryNode> &node_info_list,
|
|
||||||
SpeedProfileProperties &speed_profile)
|
|
||||||
: speed_profile(speed_profile),
|
|
||||||
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
|
|
||||||
m_node_info_list(node_info_list), m_node_based_graph(node_based_graph),
|
|
||||||
m_restriction_map(std::move(restriction_map)), max_id(0), removed_node_count(0)
|
|
||||||
{
|
|
||||||
// insert into unordered sets for fast lookup
|
|
||||||
m_barrier_nodes.insert(barrier_node_list.begin(), barrier_node_list.end());
|
|
||||||
m_traffic_lights.insert(traffic_light_node_list.begin(), traffic_light_node_list.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &output_edge_list)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT_MSG(0 == output_edge_list.size(), "Vector is not empty");
|
|
||||||
m_edge_based_edge_list.swap(output_edge_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes)
|
|
||||||
{
|
|
||||||
#ifndef NDEBUG
|
|
||||||
for (const EdgeBasedNode &node : m_edge_based_node_list)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(m_node_info_list.at(node.u).lat != INT_MAX);
|
|
||||||
BOOST_ASSERT(m_node_info_list.at(node.u).lon != INT_MAX);
|
|
||||||
BOOST_ASSERT(m_node_info_list.at(node.v).lon != INT_MAX);
|
|
||||||
BOOST_ASSERT(m_node_info_list.at(node.v).lat != INT_MAX);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
nodes.swap(m_edge_based_node_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
|
|
||||||
const NodeID node_v,
|
|
||||||
const unsigned component_id)
|
|
||||||
{
|
|
||||||
// merge edges together into one EdgeBasedNode
|
|
||||||
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
|
||||||
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
|
||||||
|
|
||||||
// find forward edge id and
|
|
||||||
const EdgeID edge_id_1 = m_node_based_graph->FindEdge(node_u, node_v);
|
|
||||||
BOOST_ASSERT(edge_id_1 != SPECIAL_EDGEID);
|
|
||||||
|
|
||||||
const EdgeData &forward_data = m_node_based_graph->GetEdgeData(edge_id_1);
|
|
||||||
|
|
||||||
// find reverse edge id and
|
|
||||||
const EdgeID edge_id_2 = m_node_based_graph->FindEdge(node_v, node_u);
|
|
||||||
BOOST_ASSERT(edge_id_2 != SPECIAL_EDGEID);
|
|
||||||
|
|
||||||
const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(edge_id_2);
|
|
||||||
|
|
||||||
if (forward_data.edgeBasedNodeID == SPECIAL_NODEID &&
|
|
||||||
reverse_data.edgeBasedNodeID == SPECIAL_NODEID)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_ASSERT(m_geometry_compressor.HasEntryForID(edge_id_1) ==
|
|
||||||
m_geometry_compressor.HasEntryForID(edge_id_2));
|
|
||||||
if (m_geometry_compressor.HasEntryForID(edge_id_1))
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(m_geometry_compressor.HasEntryForID(edge_id_2));
|
|
||||||
|
|
||||||
// reconstruct geometry and put in each individual edge with its offset
|
|
||||||
const std::vector<GeometryCompressor::CompressedNode> &forward_geometry =
|
|
||||||
m_geometry_compressor.GetBucketReference(edge_id_1);
|
|
||||||
const std::vector<GeometryCompressor::CompressedNode> &reverse_geometry =
|
|
||||||
m_geometry_compressor.GetBucketReference(edge_id_2);
|
|
||||||
BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size());
|
|
||||||
BOOST_ASSERT(0 != forward_geometry.size());
|
|
||||||
const unsigned geometry_size = static_cast<unsigned>(forward_geometry.size());
|
|
||||||
BOOST_ASSERT(geometry_size > 1);
|
|
||||||
|
|
||||||
// reconstruct bidirectional edge with individual weights and put each into the NN index
|
|
||||||
|
|
||||||
std::vector<int> forward_dist_prefix_sum(forward_geometry.size(), 0);
|
|
||||||
std::vector<int> reverse_dist_prefix_sum(reverse_geometry.size(), 0);
|
|
||||||
|
|
||||||
// quick'n'dirty prefix sum as std::partial_sum needs addtional casts
|
|
||||||
// TODO: move to lambda function with C++11
|
|
||||||
int temp_sum = 0;
|
|
||||||
|
|
||||||
for (const auto i : osrm::irange(0u, geometry_size))
|
|
||||||
{
|
|
||||||
forward_dist_prefix_sum[i] = temp_sum;
|
|
||||||
temp_sum += forward_geometry[i].second;
|
|
||||||
|
|
||||||
BOOST_ASSERT(forward_data.distance >= temp_sum);
|
|
||||||
}
|
|
||||||
|
|
||||||
temp_sum = 0;
|
|
||||||
for (const auto i : osrm::irange(0u, geometry_size))
|
|
||||||
{
|
|
||||||
temp_sum += reverse_geometry[reverse_geometry.size() - 1 - i].second;
|
|
||||||
reverse_dist_prefix_sum[i] = reverse_data.distance - temp_sum;
|
|
||||||
// BOOST_ASSERT(reverse_data.distance >= temp_sum);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID current_edge_source_coordinate_id = node_u;
|
|
||||||
|
|
||||||
if (SPECIAL_NODEID != forward_data.edgeBasedNodeID)
|
|
||||||
{
|
|
||||||
max_id = std::max(forward_data.edgeBasedNodeID, max_id);
|
|
||||||
}
|
|
||||||
if (SPECIAL_NODEID != reverse_data.edgeBasedNodeID)
|
|
||||||
{
|
|
||||||
max_id = std::max(reverse_data.edgeBasedNodeID, max_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// traverse arrays from start and end respectively
|
|
||||||
for (const auto i : osrm::irange(0u, geometry_size))
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(current_edge_source_coordinate_id ==
|
|
||||||
reverse_geometry[geometry_size - 1 - i].first);
|
|
||||||
const NodeID current_edge_target_coordinate_id = forward_geometry[i].first;
|
|
||||||
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
|
|
||||||
|
|
||||||
// build edges
|
|
||||||
m_edge_based_node_list.emplace_back(
|
|
||||||
forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID,
|
|
||||||
current_edge_source_coordinate_id, current_edge_target_coordinate_id,
|
|
||||||
forward_data.nameID, forward_geometry[i].second,
|
|
||||||
reverse_geometry[geometry_size - 1 - i].second, forward_dist_prefix_sum[i],
|
|
||||||
reverse_dist_prefix_sum[i], m_geometry_compressor.GetPositionForID(edge_id_1),
|
|
||||||
component_id, i, forward_data.travel_mode, reverse_data.travel_mode);
|
|
||||||
current_edge_source_coordinate_id = current_edge_target_coordinate_id;
|
|
||||||
|
|
||||||
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
|
|
||||||
|
|
||||||
BOOST_ASSERT(node_u != m_edge_based_node_list.back().u ||
|
|
||||||
node_v != m_edge_based_node_list.back().v);
|
|
||||||
|
|
||||||
BOOST_ASSERT(node_u != m_edge_based_node_list.back().v ||
|
|
||||||
node_v != m_edge_based_node_list.back().u);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_ASSERT(current_edge_source_coordinate_id == node_v);
|
|
||||||
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(!m_geometry_compressor.HasEntryForID(edge_id_2));
|
|
||||||
|
|
||||||
if (forward_data.edgeBasedNodeID != SPECIAL_NODEID)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(forward_data.forward);
|
|
||||||
}
|
|
||||||
if (reverse_data.edgeBasedNodeID != SPECIAL_NODEID)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(reverse_data.forward);
|
|
||||||
}
|
|
||||||
if (forward_data.edgeBasedNodeID == SPECIAL_NODEID)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(!forward_data.forward);
|
|
||||||
}
|
|
||||||
if (reverse_data.edgeBasedNodeID == SPECIAL_NODEID)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(!reverse_data.forward);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_ASSERT(forward_data.edgeBasedNodeID != SPECIAL_NODEID ||
|
|
||||||
reverse_data.edgeBasedNodeID != SPECIAL_NODEID);
|
|
||||||
|
|
||||||
m_edge_based_node_list.emplace_back(
|
|
||||||
forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID, node_u, node_v,
|
|
||||||
forward_data.nameID, forward_data.distance, reverse_data.distance, 0, 0, SPECIAL_EDGEID,
|
|
||||||
component_id, 0, forward_data.travel_mode, reverse_data.travel_mode);
|
|
||||||
BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::FlushVectorToStream(
|
|
||||||
std::ofstream &edge_data_file, std::vector<OriginalEdgeData> &original_edge_data_vector) const
|
|
||||||
{
|
|
||||||
if (original_edge_data_vector.empty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
edge_data_file.write((char *)&(original_edge_data_vector[0]),
|
|
||||||
original_edge_data_vector.size() * sizeof(OriginalEdgeData));
|
|
||||||
original_edge_data_vector.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
|
|
||||||
const std::string &geometry_filename,
|
|
||||||
lua_State *lua_state)
|
|
||||||
{
|
|
||||||
|
|
||||||
TIMER_START(geometry);
|
|
||||||
CompressGeometry();
|
|
||||||
TIMER_STOP(geometry);
|
|
||||||
|
|
||||||
TIMER_START(renumber);
|
|
||||||
RenumberEdges();
|
|
||||||
TIMER_STOP(renumber);
|
|
||||||
|
|
||||||
TIMER_START(generate_nodes);
|
|
||||||
GenerateEdgeExpandedNodes();
|
|
||||||
TIMER_STOP(generate_nodes);
|
|
||||||
|
|
||||||
TIMER_START(generate_edges);
|
|
||||||
GenerateEdgeExpandedEdges(original_edge_data_filename, lua_state);
|
|
||||||
TIMER_STOP(generate_edges);
|
|
||||||
|
|
||||||
m_geometry_compressor.SerializeInternalVector(geometry_filename);
|
|
||||||
|
|
||||||
SimpleLogger().Write() << "Timing statistics for edge-expanded graph:";
|
|
||||||
SimpleLogger().Write() << "Geometry compression: " << TIMER_SEC(geometry) << "s";
|
|
||||||
SimpleLogger().Write() << "Renumbering edges: " << TIMER_SEC(renumber) << "s";
|
|
||||||
SimpleLogger().Write() << "Generating nodes: " << TIMER_SEC(generate_nodes) << "s";
|
|
||||||
SimpleLogger().Write() << "Generating edges: " << TIMER_SEC(generate_edges) << "s";
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::CompressGeometry()
|
|
||||||
{
|
|
||||||
SimpleLogger().Write() << "Removing graph geometry while preserving topology";
|
|
||||||
|
|
||||||
const unsigned original_number_of_nodes = m_node_based_graph->GetNumberOfNodes();
|
|
||||||
const unsigned original_number_of_edges = m_node_based_graph->GetNumberOfEdges();
|
|
||||||
|
|
||||||
Percent progress(original_number_of_nodes);
|
|
||||||
|
|
||||||
for (const NodeID node_v : osrm::irange(0u, original_number_of_nodes))
|
|
||||||
{
|
|
||||||
progress.printStatus(node_v);
|
|
||||||
|
|
||||||
// only contract degree 2 vertices
|
|
||||||
if (2 != m_node_based_graph->GetOutDegree(node_v))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't contract barrier node
|
|
||||||
if (m_barrier_nodes.end() != m_barrier_nodes.find(node_v))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if v is a via node for a turn restriction, i.e. a 'directed' barrier node
|
|
||||||
if (m_restriction_map->IsViaNode(node_v))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool reverse_edge_order =
|
|
||||||
!(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(node_v)).forward);
|
|
||||||
const EdgeID forward_e2 = m_node_based_graph->BeginEdges(node_v) + reverse_edge_order;
|
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != forward_e2);
|
|
||||||
const EdgeID reverse_e2 = m_node_based_graph->BeginEdges(node_v) + 1 - reverse_edge_order;
|
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2);
|
|
||||||
|
|
||||||
const EdgeData &fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2);
|
|
||||||
const EdgeData &rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2);
|
|
||||||
|
|
||||||
const NodeID node_w = m_node_based_graph->GetTarget(forward_e2);
|
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != node_w);
|
|
||||||
BOOST_ASSERT(node_v != node_w);
|
|
||||||
const NodeID node_u = m_node_based_graph->GetTarget(reverse_e2);
|
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != node_u);
|
|
||||||
BOOST_ASSERT(node_u != node_v);
|
|
||||||
|
|
||||||
const EdgeID forward_e1 = m_node_based_graph->FindEdge(node_u, node_v);
|
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != forward_e1);
|
|
||||||
BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(forward_e1));
|
|
||||||
const EdgeID reverse_e1 = m_node_based_graph->FindEdge(node_w, node_v);
|
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e1);
|
|
||||||
BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(reverse_e1));
|
|
||||||
|
|
||||||
const EdgeData &fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1);
|
|
||||||
const EdgeData &rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1);
|
|
||||||
|
|
||||||
if (m_node_based_graph->FindEdgeInEitherDirection(node_u, node_w) != SPECIAL_EDGEID)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( // TODO: rename to IsCompatibleTo
|
|
||||||
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;
|
|
||||||
const int forward_weight2 = m_node_based_graph->GetEdgeData(forward_e2).distance;
|
|
||||||
|
|
||||||
BOOST_ASSERT(0 != forward_weight1);
|
|
||||||
BOOST_ASSERT(0 != forward_weight2);
|
|
||||||
|
|
||||||
const int reverse_weight1 = m_node_based_graph->GetEdgeData(reverse_e1).distance;
|
|
||||||
const int reverse_weight2 = m_node_based_graph->GetEdgeData(reverse_e2).distance;
|
|
||||||
|
|
||||||
BOOST_ASSERT(0 != reverse_weight1);
|
|
||||||
BOOST_ASSERT(0 != forward_weight2);
|
|
||||||
|
|
||||||
const bool has_node_penalty = m_traffic_lights.find(node_v) != m_traffic_lights.end();
|
|
||||||
|
|
||||||
// add weight of e2's to e1
|
|
||||||
m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
|
|
||||||
m_node_based_graph->GetEdgeData(reverse_e1).distance += rev_edge_data2.distance;
|
|
||||||
if (has_node_penalty)
|
|
||||||
{
|
|
||||||
m_node_based_graph->GetEdgeData(forward_e1).distance +=
|
|
||||||
speed_profile.traffic_signal_penalty;
|
|
||||||
m_node_based_graph->GetEdgeData(reverse_e1).distance +=
|
|
||||||
speed_profile.traffic_signal_penalty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// extend e1's to targets of e2's
|
|
||||||
m_node_based_graph->SetTarget(forward_e1, node_w);
|
|
||||||
m_node_based_graph->SetTarget(reverse_e1, node_u);
|
|
||||||
|
|
||||||
// remove e2's (if bidir, otherwise only one)
|
|
||||||
m_node_based_graph->DeleteEdge(node_v, forward_e2);
|
|
||||||
m_node_based_graph->DeleteEdge(node_v, reverse_e2);
|
|
||||||
|
|
||||||
// update any involved turn restrictions
|
|
||||||
m_restriction_map->FixupStartingTurnRestriction(node_u, node_v, node_w);
|
|
||||||
m_restriction_map->FixupArrivingTurnRestriction(node_u, node_v, node_w,
|
|
||||||
m_node_based_graph);
|
|
||||||
|
|
||||||
m_restriction_map->FixupStartingTurnRestriction(node_w, node_v, node_u);
|
|
||||||
m_restriction_map->FixupArrivingTurnRestriction(node_w, node_v, node_u,
|
|
||||||
m_node_based_graph);
|
|
||||||
|
|
||||||
// store compressed geometry in container
|
|
||||||
m_geometry_compressor.CompressEdge(
|
|
||||||
forward_e1, forward_e2, node_v, node_w,
|
|
||||||
forward_weight1 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0),
|
|
||||||
forward_weight2);
|
|
||||||
m_geometry_compressor.CompressEdge(
|
|
||||||
reverse_e1, reverse_e2, node_v, node_u, reverse_weight1,
|
|
||||||
reverse_weight2 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0));
|
|
||||||
++removed_node_count;
|
|
||||||
|
|
||||||
BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
|
|
||||||
m_node_based_graph->GetEdgeData(reverse_e1).nameID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SimpleLogger().Write() << "removed " << removed_node_count << " nodes";
|
|
||||||
m_geometry_compressor.PrintStatistics();
|
|
||||||
|
|
||||||
unsigned new_node_count = 0;
|
|
||||||
unsigned new_edge_count = 0;
|
|
||||||
|
|
||||||
for (const auto i : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
|
||||||
{
|
|
||||||
if (m_node_based_graph->GetOutDegree(i) > 0)
|
|
||||||
{
|
|
||||||
++new_node_count;
|
|
||||||
new_edge_count += (m_node_based_graph->EndEdges(i) - m_node_based_graph->BeginEdges(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SimpleLogger().Write() << "new nodes: " << new_node_count << ", edges " << new_edge_count;
|
|
||||||
SimpleLogger().Write() << "Node compression ratio: "
|
|
||||||
<< new_node_count / (double)original_number_of_nodes;
|
|
||||||
SimpleLogger().Write() << "Edge compression ratio: "
|
|
||||||
<< new_edge_count / (double)original_number_of_edges;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the id of the edge in the edge expanded graph (into the edge in the node based graph)
|
|
||||||
*/
|
|
||||||
void EdgeBasedGraphFactory::RenumberEdges()
|
|
||||||
{
|
|
||||||
// renumber edge based node IDs
|
|
||||||
unsigned numbered_edges_count = 0;
|
|
||||||
for (const auto current_node : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
|
||||||
{
|
|
||||||
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(current_node))
|
|
||||||
{
|
|
||||||
EdgeData &edge_data = m_node_based_graph->GetEdgeData(current_edge);
|
|
||||||
if (!edge_data.forward)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges());
|
|
||||||
edge_data.edgeBasedNodeID = numbered_edges_count;
|
|
||||||
++numbered_edges_count;
|
|
||||||
|
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != edge_data.edgeBasedNodeID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_number_of_edge_based_nodes = numbered_edges_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the nodes in the edge expanded graph from edges in the node-based graph.
|
|
||||||
*/
|
|
||||||
void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
|
||||||
{
|
|
||||||
SimpleLogger().Write() << "Identifying components of the (compressed) road network";
|
|
||||||
|
|
||||||
// Run a BFS on the undirected graph and identify small components
|
|
||||||
TarjanSCC<NodeBasedDynamicGraph> component_explorer(m_node_based_graph, *m_restriction_map,
|
|
||||||
m_barrier_nodes);
|
|
||||||
|
|
||||||
component_explorer.run();
|
|
||||||
|
|
||||||
SimpleLogger().Write() << "identified: "
|
|
||||||
<< component_explorer.get_number_of_components() - removed_node_count
|
|
||||||
<< " (compressed) components";
|
|
||||||
SimpleLogger().Write() << "identified "
|
|
||||||
<< component_explorer.get_size_one_count() - removed_node_count
|
|
||||||
<< " (compressed) SCCs of size 1";
|
|
||||||
SimpleLogger().Write() << "generating edge-expanded nodes";
|
|
||||||
|
|
||||||
Percent progress(m_node_based_graph->GetNumberOfNodes());
|
|
||||||
|
|
||||||
// loop over all edges and generate new set of nodes
|
|
||||||
for (const auto node_u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
|
||||||
BOOST_ASSERT(node_u < m_node_based_graph->GetNumberOfNodes());
|
|
||||||
progress.printStatus(node_u);
|
|
||||||
for (EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(node_u))
|
|
||||||
{
|
|
||||||
const EdgeData &edge_data = m_node_based_graph->GetEdgeData(e1);
|
|
||||||
BOOST_ASSERT(e1 != SPECIAL_EDGEID);
|
|
||||||
const NodeID node_v = m_node_based_graph->GetTarget(e1);
|
|
||||||
|
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != node_v);
|
|
||||||
// pick only every other edge
|
|
||||||
if (node_u > node_v)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_ASSERT(node_u < node_v);
|
|
||||||
|
|
||||||
// Note: edges that end on barrier nodes or on a turn restriction
|
|
||||||
// may actually be in two distinct components. We choose the smallest
|
|
||||||
const unsigned size_of_component =
|
|
||||||
std::min(component_explorer.get_component_size(node_u),
|
|
||||||
component_explorer.get_component_size(node_v));
|
|
||||||
|
|
||||||
const unsigned id_of_smaller_component = [node_u, node_v, &component_explorer]
|
|
||||||
{
|
|
||||||
if (component_explorer.get_component_size(node_u) <
|
|
||||||
component_explorer.get_component_size(node_v))
|
|
||||||
{
|
|
||||||
return component_explorer.get_component_id(node_u);
|
|
||||||
}
|
|
||||||
return component_explorer.get_component_id(node_v);
|
|
||||||
}();
|
|
||||||
|
|
||||||
const bool component_is_tiny = size_of_component < 1000;
|
|
||||||
|
|
||||||
if (edge_data.edgeBasedNodeID == SPECIAL_NODEID)
|
|
||||||
{
|
|
||||||
InsertEdgeBasedNode(node_v, node_u,
|
|
||||||
(component_is_tiny ? id_of_smaller_component + 1 : 0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
InsertEdgeBasedNode(node_u, node_v,
|
|
||||||
(component_is_tiny ? id_of_smaller_component + 1 : 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size()
|
|
||||||
<< " nodes in edge-expanded graph";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Actually it also generates OriginalEdgeData and serializes them...
|
|
||||||
*/
|
|
||||||
void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|
||||||
const std::string &original_edge_data_filename, lua_State *lua_state)
|
|
||||||
{
|
|
||||||
SimpleLogger().Write() << "generating edge-expanded edges";
|
|
||||||
|
|
||||||
unsigned node_based_edge_counter = 0;
|
|
||||||
unsigned original_edges_counter = 0;
|
|
||||||
|
|
||||||
std::ofstream edge_data_file(original_edge_data_filename.c_str(), std::ios::binary);
|
|
||||||
|
|
||||||
// writes a dummy value that is updated later
|
|
||||||
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
|
|
||||||
|
|
||||||
std::vector<OriginalEdgeData> original_edge_data_vector;
|
|
||||||
original_edge_data_vector.reserve(1024 * 1024);
|
|
||||||
|
|
||||||
// Loop over all turns and generate new set of edges.
|
|
||||||
// Three nested loop look super-linear, but we are dealing with a (kind of)
|
|
||||||
// linear number of turns only.
|
|
||||||
unsigned restricted_turns_counter = 0;
|
|
||||||
unsigned skipped_uturns_counter = 0;
|
|
||||||
unsigned skipped_barrier_turns_counter = 0;
|
|
||||||
unsigned compressed = 0;
|
|
||||||
|
|
||||||
Percent progress(m_node_based_graph->GetNumberOfNodes());
|
|
||||||
|
|
||||||
for (const auto node_u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
|
||||||
{
|
|
||||||
progress.printStatus(node_u);
|
|
||||||
for (const EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(node_u))
|
|
||||||
{
|
|
||||||
if (!m_node_based_graph->GetEdgeData(e1).forward)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
++node_based_edge_counter;
|
|
||||||
const NodeID node_v = m_node_based_graph->GetTarget(e1);
|
|
||||||
const NodeID only_restriction_to_node =
|
|
||||||
m_restriction_map->CheckForEmanatingIsOnlyTurn(node_u, node_v);
|
|
||||||
const bool is_barrier_node = m_barrier_nodes.find(node_v) != m_barrier_nodes.end();
|
|
||||||
|
|
||||||
for (const EdgeID e2 : m_node_based_graph->GetAdjacentEdgeRange(node_v))
|
|
||||||
{
|
|
||||||
if (!m_node_based_graph->GetEdgeData(e2).forward)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const NodeID node_w = m_node_based_graph->GetTarget(e2);
|
|
||||||
|
|
||||||
if ((only_restriction_to_node != SPECIAL_NODEID) &&
|
|
||||||
(node_w != only_restriction_to_node))
|
|
||||||
{
|
|
||||||
// We are at an only_-restriction but not at the right turn.
|
|
||||||
++restricted_turns_counter;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_barrier_node)
|
|
||||||
{
|
|
||||||
if (node_u != node_w)
|
|
||||||
{
|
|
||||||
++skipped_barrier_turns_counter;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((node_u == node_w) && (m_node_based_graph->GetOutDegree(node_v) > 1))
|
|
||||||
{
|
|
||||||
++skipped_uturns_counter;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// only add an edge if turn is not a U-turn except when it is
|
|
||||||
// at the end of a dead-end street
|
|
||||||
if (m_restriction_map->CheckIfTurnIsRestricted(node_u, node_v, node_w) &&
|
|
||||||
(only_restriction_to_node == SPECIAL_NODEID) &&
|
|
||||||
(node_w != only_restriction_to_node))
|
|
||||||
{
|
|
||||||
// We are at an only_-restriction but not at the right turn.
|
|
||||||
++restricted_turns_counter;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// only add an edge if turn is not prohibited
|
|
||||||
const EdgeData &edge_data1 = m_node_based_graph->GetEdgeData(e1);
|
|
||||||
const EdgeData &edge_data2 = m_node_based_graph->GetEdgeData(e2);
|
|
||||||
|
|
||||||
BOOST_ASSERT(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
|
|
||||||
BOOST_ASSERT(edge_data1.forward);
|
|
||||||
BOOST_ASSERT(edge_data2.forward);
|
|
||||||
|
|
||||||
// the following is the core of the loop.
|
|
||||||
unsigned distance = edge_data1.distance;
|
|
||||||
if (m_traffic_lights.find(node_v) != m_traffic_lights.end())
|
|
||||||
{
|
|
||||||
distance += speed_profile.traffic_signal_penalty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unpack last node of first segment if packed
|
|
||||||
const auto first_coordinate =
|
|
||||||
m_node_info_list[(m_geometry_compressor.HasEntryForID(e1)
|
|
||||||
? m_geometry_compressor.GetLastNodeIDOfBucket(e1)
|
|
||||||
: node_u)];
|
|
||||||
|
|
||||||
// unpack first node of second segment if packed
|
|
||||||
const auto third_coordinate =
|
|
||||||
m_node_info_list[(m_geometry_compressor.HasEntryForID(e2)
|
|
||||||
? m_geometry_compressor.GetFirstNodeIDOfBucket(e2)
|
|
||||||
: node_w)];
|
|
||||||
|
|
||||||
const double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates(
|
|
||||||
first_coordinate, m_node_info_list[node_v], third_coordinate);
|
|
||||||
|
|
||||||
const int turn_penalty = GetTurnPenalty(turn_angle, lua_state);
|
|
||||||
TurnInstruction turn_instruction = AnalyzeTurn(node_u, node_v, node_w, turn_angle);
|
|
||||||
if (turn_instruction == TurnInstruction::UTurn)
|
|
||||||
{
|
|
||||||
distance += speed_profile.u_turn_penalty;
|
|
||||||
}
|
|
||||||
distance += turn_penalty;
|
|
||||||
|
|
||||||
const bool edge_is_compressed = m_geometry_compressor.HasEntryForID(e1);
|
|
||||||
|
|
||||||
if (edge_is_compressed)
|
|
||||||
{
|
|
||||||
++compressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
original_edge_data_vector.emplace_back(
|
|
||||||
(edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : node_v),
|
|
||||||
edge_data1.nameID, turn_instruction, edge_is_compressed,
|
|
||||||
edge_data2.travel_mode);
|
|
||||||
|
|
||||||
++original_edges_counter;
|
|
||||||
|
|
||||||
if (original_edge_data_vector.size() > 1024 * 1024 * 10)
|
|
||||||
{
|
|
||||||
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != edge_data1.edgeBasedNodeID);
|
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != edge_data2.edgeBasedNodeID);
|
|
||||||
|
|
||||||
m_edge_based_edge_list.emplace_back(
|
|
||||||
EdgeBasedEdge(edge_data1.edgeBasedNodeID, edge_data2.edgeBasedNodeID,
|
|
||||||
m_edge_based_edge_list.size(), distance, true, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
|
||||||
|
|
||||||
edge_data_file.seekp(std::ios::beg);
|
|
||||||
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
|
|
||||||
edge_data_file.close();
|
|
||||||
|
|
||||||
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " edge based nodes";
|
|
||||||
SimpleLogger().Write() << "Node-based graph contains " << node_based_edge_counter << " edges";
|
|
||||||
SimpleLogger().Write() << "Edge-expanded graph ...";
|
|
||||||
SimpleLogger().Write() << " contains " << m_edge_based_edge_list.size() << " edges";
|
|
||||||
SimpleLogger().Write() << " skips " << restricted_turns_counter << " turns, "
|
|
||||||
"defined by "
|
|
||||||
<< m_restriction_map->size() << " restrictions";
|
|
||||||
SimpleLogger().Write() << " skips " << skipped_uturns_counter << " U turns";
|
|
||||||
SimpleLogger().Write() << " skips " << skipped_barrier_turns_counter << " turns over barriers";
|
|
||||||
}
|
|
||||||
|
|
||||||
int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) const
|
|
||||||
{
|
|
||||||
|
|
||||||
if (speed_profile.has_turn_penalty_function)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// call lua profile to compute turn penalty
|
|
||||||
return luabind::call_function<int>(lua_state, "turn_function", 180. - angle);
|
|
||||||
}
|
|
||||||
catch (const luabind::error &er)
|
|
||||||
{
|
|
||||||
SimpleLogger().Write(logWARNING) << er.what();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID node_u,
|
|
||||||
const NodeID node_v,
|
|
||||||
const NodeID node_w,
|
|
||||||
const double angle) const
|
|
||||||
{
|
|
||||||
if (node_u == node_w)
|
|
||||||
{
|
|
||||||
return TurnInstruction::UTurn;
|
|
||||||
}
|
|
||||||
|
|
||||||
const EdgeID edge1 = m_node_based_graph->FindEdge(node_u, node_v);
|
|
||||||
const EdgeID edge2 = m_node_based_graph->FindEdge(node_v, node_w);
|
|
||||||
|
|
||||||
const EdgeData &data1 = m_node_based_graph->GetEdgeData(edge1);
|
|
||||||
const EdgeData &data2 = m_node_based_graph->GetEdgeData(edge2);
|
|
||||||
|
|
||||||
// roundabouts need to be handled explicitely
|
|
||||||
if (data1.roundabout && data2.roundabout)
|
|
||||||
{
|
|
||||||
// Is a turn possible? If yes, we stay on the roundabout!
|
|
||||||
if (1 == m_node_based_graph->GetDirectedOutDegree(node_v))
|
|
||||||
{
|
|
||||||
// No turn possible.
|
|
||||||
return TurnInstruction::NoTurn;
|
|
||||||
}
|
|
||||||
return TurnInstruction::StayOnRoundAbout;
|
|
||||||
}
|
|
||||||
// Does turn start or end on roundabout?
|
|
||||||
if (data1.roundabout || data2.roundabout)
|
|
||||||
{
|
|
||||||
// We are entering the roundabout
|
|
||||||
if ((!data1.roundabout) && data2.roundabout)
|
|
||||||
{
|
|
||||||
return TurnInstruction::EnterRoundAbout;
|
|
||||||
}
|
|
||||||
// We are leaving the roundabout
|
|
||||||
if (data1.roundabout && (!data2.roundabout))
|
|
||||||
{
|
|
||||||
return TurnInstruction::LeaveRoundAbout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If street names stay the same and if we are certain that it is not a
|
|
||||||
// a segment of a roundabout, we skip it.
|
|
||||||
if (data1.nameID == data2.nameID)
|
|
||||||
{
|
|
||||||
// TODO: Here we should also do a small graph exploration to check for
|
|
||||||
// more complex situations
|
|
||||||
if (0 != data1.nameID || m_node_based_graph->GetOutDegree(node_v) <= 2)
|
|
||||||
{
|
|
||||||
return TurnInstruction::NoTurn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned EdgeBasedGraphFactory::GetNumberOfEdgeBasedNodes() const
|
|
||||||
{
|
|
||||||
return m_number_of_edge_based_nodes;
|
|
||||||
}
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This class constructs the edge-expanded routing graph
|
|
||||||
|
|
||||||
#ifndef EDGE_BASED_GRAPH_FACTORY_HPP_
|
|
||||||
#define EDGE_BASED_GRAPH_FACTORY_HPP_
|
|
||||||
|
|
||||||
#include "geometry_compressor.hpp"
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "../data_structures/deallocating_vector.hpp"
|
|
||||||
#include "../data_structures/edge_based_node.hpp"
|
|
||||||
#include "../data_structures/original_edge_data.hpp"
|
|
||||||
#include "../data_structures/query_node.hpp"
|
|
||||||
#include "../data_structures/turn_instructions.hpp"
|
|
||||||
#include "../data_structures/node_based_graph.hpp"
|
|
||||||
#include "../data_structures/restriction_map.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iosfwd>
|
|
||||||
#include <memory>
|
|
||||||
#include <queue>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct lua_State;
|
|
||||||
|
|
||||||
class EdgeBasedGraphFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
EdgeBasedGraphFactory() = delete;
|
|
||||||
EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
|
|
||||||
|
|
||||||
struct SpeedProfileProperties;
|
|
||||||
|
|
||||||
explicit EdgeBasedGraphFactory(const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
|
|
||||||
std::unique_ptr<RestrictionMap> restricion_map,
|
|
||||||
std::vector<NodeID> &barrier_node_list,
|
|
||||||
std::vector<NodeID> &traffic_light_node_list,
|
|
||||||
std::vector<QueryNode> &node_info_list,
|
|
||||||
SpeedProfileProperties &speed_profile);
|
|
||||||
|
|
||||||
void Run(const std::string &original_edge_data_filename,
|
|
||||||
const std::string &geometry_filename,
|
|
||||||
lua_State *lua_state);
|
|
||||||
|
|
||||||
void GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &edges);
|
|
||||||
|
|
||||||
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
|
|
||||||
|
|
||||||
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, const double angle) const;
|
|
||||||
|
|
||||||
int GetTurnPenalty(double angle, lua_State *lua_state) const;
|
|
||||||
|
|
||||||
unsigned GetNumberOfEdgeBasedNodes() const;
|
|
||||||
|
|
||||||
struct SpeedProfileProperties
|
|
||||||
{
|
|
||||||
SpeedProfileProperties()
|
|
||||||
: traffic_signal_penalty(0), u_turn_penalty(0), has_turn_penalty_function(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int traffic_signal_penalty;
|
|
||||||
int u_turn_penalty;
|
|
||||||
bool has_turn_penalty_function;
|
|
||||||
} speed_profile;
|
|
||||||
|
|
||||||
private:
|
|
||||||
using EdgeData = NodeBasedDynamicGraph::EdgeData;
|
|
||||||
|
|
||||||
unsigned m_number_of_edge_based_nodes;
|
|
||||||
|
|
||||||
std::vector<QueryNode> m_node_info_list;
|
|
||||||
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
|
||||||
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
|
||||||
|
|
||||||
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
|
|
||||||
std::unordered_set<NodeID> m_barrier_nodes;
|
|
||||||
std::unordered_set<NodeID> m_traffic_lights;
|
|
||||||
|
|
||||||
std::unique_ptr<RestrictionMap> m_restriction_map;
|
|
||||||
|
|
||||||
GeometryCompressor m_geometry_compressor;
|
|
||||||
|
|
||||||
void CompressGeometry();
|
|
||||||
void RenumberEdges();
|
|
||||||
void GenerateEdgeExpandedNodes();
|
|
||||||
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
|
|
||||||
lua_State *lua_state);
|
|
||||||
|
|
||||||
void InsertEdgeBasedNode(const NodeID u, const NodeID v, const unsigned component_id);
|
|
||||||
|
|
||||||
void FlushVectorToStream(std::ofstream &edge_data_file,
|
|
||||||
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
|
||||||
|
|
||||||
NodeID max_id;
|
|
||||||
std::size_t removed_node_count;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* EDGE_BASED_GRAPH_FACTORY_HPP_ */
|
|
||||||
@@ -1,236 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2015, Project OSRM contributors
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "geometry_compressor.hpp"
|
|
||||||
#include "../util/simple_logger.hpp"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include <boost/filesystem/fstream.hpp>
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
GeometryCompressor::GeometryCompressor()
|
|
||||||
{
|
|
||||||
m_free_list.reserve(100);
|
|
||||||
IncreaseFreeList();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GeometryCompressor::IncreaseFreeList()
|
|
||||||
{
|
|
||||||
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
|
|
||||||
for (unsigned i = 100; i > 0; --i)
|
|
||||||
{
|
|
||||||
m_free_list.emplace_back(free_list_maximum);
|
|
||||||
++free_list_maximum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
|
|
||||||
{
|
|
||||||
auto iter = m_edge_id_to_list_index_map.find(edge_id);
|
|
||||||
return iter != m_edge_id_to_list_index_map.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
|
|
||||||
{
|
|
||||||
auto map_iterator = m_edge_id_to_list_index_map.find(edge_id);
|
|
||||||
BOOST_ASSERT(map_iterator != m_edge_id_to_list_index_map.end());
|
|
||||||
BOOST_ASSERT(map_iterator->second < m_compressed_geometries.size());
|
|
||||||
return map_iterator->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GeometryCompressor::SerializeInternalVector(const std::string &path) const
|
|
||||||
{
|
|
||||||
|
|
||||||
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary | std::ios::out);
|
|
||||||
const unsigned compressed_geometries = m_compressed_geometries.size() + 1;
|
|
||||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != compressed_geometries);
|
|
||||||
geometry_out_stream.write((char *)&compressed_geometries, sizeof(unsigned));
|
|
||||||
|
|
||||||
// write indices array
|
|
||||||
unsigned prefix_sum_of_list_indices = 0;
|
|
||||||
for (const auto &elem : m_compressed_geometries)
|
|
||||||
{
|
|
||||||
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
|
||||||
|
|
||||||
const std::vector<CompressedNode> ¤t_vector = elem;
|
|
||||||
const unsigned unpacked_size = current_vector.size();
|
|
||||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != unpacked_size);
|
|
||||||
prefix_sum_of_list_indices += unpacked_size;
|
|
||||||
}
|
|
||||||
// sentinel element
|
|
||||||
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
|
||||||
|
|
||||||
// number of geometry entries to follow, it is the (inclusive) prefix sum
|
|
||||||
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
|
||||||
|
|
||||||
unsigned control_sum = 0;
|
|
||||||
// write compressed geometries
|
|
||||||
for (auto &elem : m_compressed_geometries)
|
|
||||||
{
|
|
||||||
const std::vector<CompressedNode> ¤t_vector = elem;
|
|
||||||
const unsigned unpacked_size = current_vector.size();
|
|
||||||
control_sum += unpacked_size;
|
|
||||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != unpacked_size);
|
|
||||||
for (const CompressedNode current_node : current_vector)
|
|
||||||
{
|
|
||||||
geometry_out_stream.write((char *)&(current_node.first), sizeof(NodeID));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BOOST_ASSERT(control_sum == prefix_sum_of_list_indices);
|
|
||||||
// all done, let's close the resource
|
|
||||||
geometry_out_stream.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
|
|
||||||
const EdgeID edge_id_2,
|
|
||||||
const NodeID via_node_id,
|
|
||||||
const NodeID target_node_id,
|
|
||||||
const EdgeWeight weight1,
|
|
||||||
const EdgeWeight weight2)
|
|
||||||
{
|
|
||||||
// remove super-trivial geometries
|
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_1);
|
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2);
|
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != via_node_id);
|
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
|
|
||||||
BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight1);
|
|
||||||
BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight2);
|
|
||||||
|
|
||||||
// append list of removed edge_id plus via node to surviving edge id:
|
|
||||||
// <surv_1, .. , surv_n, via_node_id, rem_1, .. rem_n
|
|
||||||
//
|
|
||||||
// General scheme:
|
|
||||||
// 1. append via node id to list of edge_id_1
|
|
||||||
// 2. find list for edge_id_2, if yes add all elements and delete it
|
|
||||||
|
|
||||||
// Add via node id. List is created if it does not exist
|
|
||||||
if (!HasEntryForID(edge_id_1))
|
|
||||||
{
|
|
||||||
// create a new entry in the map
|
|
||||||
if (0 == m_free_list.size())
|
|
||||||
{
|
|
||||||
// make sure there is a place to put the entries
|
|
||||||
IncreaseFreeList();
|
|
||||||
}
|
|
||||||
BOOST_ASSERT(!m_free_list.empty());
|
|
||||||
m_edge_id_to_list_index_map[edge_id_1] = m_free_list.back();
|
|
||||||
m_free_list.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// find bucket index
|
|
||||||
const auto iter = m_edge_id_to_list_index_map.find(edge_id_1);
|
|
||||||
BOOST_ASSERT(iter != m_edge_id_to_list_index_map.end());
|
|
||||||
const unsigned edge_bucket_id1 = iter->second;
|
|
||||||
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
|
|
||||||
BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size());
|
|
||||||
|
|
||||||
std::vector<CompressedNode> &edge_bucket_list1 = m_compressed_geometries[edge_bucket_id1];
|
|
||||||
|
|
||||||
if (edge_bucket_list1.empty())
|
|
||||||
{
|
|
||||||
edge_bucket_list1.emplace_back(via_node_id, weight1);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_ASSERT(0 < edge_bucket_list1.size());
|
|
||||||
BOOST_ASSERT(!edge_bucket_list1.empty());
|
|
||||||
|
|
||||||
if (HasEntryForID(edge_id_2))
|
|
||||||
{
|
|
||||||
// second edge is not atomic anymore
|
|
||||||
const unsigned list_to_remove_index = GetPositionForID(edge_id_2);
|
|
||||||
BOOST_ASSERT(list_to_remove_index < m_compressed_geometries.size());
|
|
||||||
|
|
||||||
std::vector<CompressedNode> &edge_bucket_list2 =
|
|
||||||
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());
|
|
||||||
|
|
||||||
// remove the list of edge_id_2
|
|
||||||
m_edge_id_to_list_index_map.erase(edge_id_2);
|
|
||||||
BOOST_ASSERT(m_edge_id_to_list_index_map.end() ==
|
|
||||||
m_edge_id_to_list_index_map.find(edge_id_2));
|
|
||||||
edge_bucket_list2.clear();
|
|
||||||
BOOST_ASSERT(0 == edge_bucket_list2.size());
|
|
||||||
m_free_list.emplace_back(list_to_remove_index);
|
|
||||||
BOOST_ASSERT(list_to_remove_index == m_free_list.back());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// we are certain that the second edge is atomic.
|
|
||||||
edge_bucket_list1.emplace_back(target_node_id, weight2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GeometryCompressor::PrintStatistics() const
|
|
||||||
{
|
|
||||||
const uint64_t compressed_edges = m_compressed_geometries.size();
|
|
||||||
BOOST_ASSERT(0 == compressed_edges % 2);
|
|
||||||
BOOST_ASSERT(m_compressed_geometries.size() + m_free_list.size() > 0);
|
|
||||||
|
|
||||||
uint64_t compressed_geometries = 0;
|
|
||||||
uint64_t longest_chain_length = 0;
|
|
||||||
for (const std::vector<CompressedNode> ¤t_vector : m_compressed_geometries)
|
|
||||||
{
|
|
||||||
compressed_geometries += current_vector.size();
|
|
||||||
longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleLogger().Write() << "Geometry successfully removed:"
|
|
||||||
"\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 avg chain length: "
|
|
||||||
<< (float)compressed_geometries /
|
|
||||||
std::max((uint64_t)1, compressed_edges);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<GeometryCompressor::CompressedNode> &
|
|
||||||
GeometryCompressor::GetBucketReference(const EdgeID edge_id) const
|
|
||||||
{
|
|
||||||
const unsigned index = m_edge_id_to_list_index_map.at(edge_id);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GEOMETRY_COMPRESSOR_HPP_
|
|
||||||
#define GEOMETRY_COMPRESSOR_HPP_
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class GeometryCompressor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using CompressedNode = std::pair<NodeID, EdgeWeight>;
|
|
||||||
|
|
||||||
GeometryCompressor();
|
|
||||||
void CompressEdge(const EdgeID surviving_edge_id,
|
|
||||||
const EdgeID removed_edge_id,
|
|
||||||
const NodeID via_node_id,
|
|
||||||
const NodeID target_node,
|
|
||||||
const EdgeWeight weight1,
|
|
||||||
const EdgeWeight weight2);
|
|
||||||
|
|
||||||
bool HasEntryForID(const EdgeID edge_id) const;
|
|
||||||
void PrintStatistics() const;
|
|
||||||
void SerializeInternalVector(const std::string &path) const;
|
|
||||||
unsigned GetPositionForID(const EdgeID edge_id) const;
|
|
||||||
const std::vector<GeometryCompressor::CompressedNode> &
|
|
||||||
GetBucketReference(const EdgeID edge_id) const;
|
|
||||||
NodeID GetFirstNodeIDOfBucket(const EdgeID edge_id) const;
|
|
||||||
NodeID GetLastNodeIDOfBucket(const EdgeID edge_id) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
int free_list_maximum = 0;
|
|
||||||
|
|
||||||
void IncreaseFreeList();
|
|
||||||
std::vector<std::vector<CompressedNode>> m_compressed_geometries;
|
|
||||||
std::vector<unsigned> m_free_list;
|
|
||||||
std::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // GEOMETRY_COMPRESSOR_HPP_
|
|
||||||