Compare commits

..

20 Commits

Author SHA1 Message Date
DennisSchiefer 5ebe8080f9 small bug class/id mixed up 2012-03-14 11:24:40 +01:00
DennisSchiefer d92b28d2c3 restructured for release 2012-03-14 10:39:37 +01:00
DennisSchiefer ec27881f39 test fencing 2012-03-13 22:39:28 +01:00
DennisSchiefer c5a8ec7c31 added better lat/lng display when dragging,
added experimental faster route redraw (commented out),
changed default website url and routing url,
removed drag after dragend event workaround
2012-03-13 22:25:40 +01:00
DennisSchiefer afbd3347da added clear debug log button,
removed showing of links in gpx, route requests,
checked html with validator
2012-03-13 20:51:44 +01:00
DennisSchiefer 41bcafc3a1 added lat/lng processing 2012-03-13 17:57:48 +01:00
DennisSchiefer 27d24885a9 debug window stays at botoom when adding data 2012-03-13 17:36:40 +01:00
DennisSchiefer 805402b230 starting to reverse geocoding 2012-03-13 17:32:18 +01:00
DennisSchiefer 4918549bac fixed bug when selecting city options in geocoder,
added clicking on map to create markers,
reset also clears input boxes now
2012-03-13 15:26:53 +01:00
DennisSchiefer 784f417857 changed geocoder to official OSM geocoder,
switched default map style to osm.org
2012-03-13 14:31:23 +01:00
DennisSchiefer 0bc3e098ac added GUI support for IE9 and IE10,
changed GUI legal text,
changed via-node deletion to click only,
moved default entries for input boxes to config file,
made input boxes selectable again
2012-03-13 14:15:07 +01:00
DennisSchiefer dfd3a5d554 changed round-about symbol, corrected bug with ENTER not working on
location input
2012-03-13 10:26:31 +01:00
DennisSchiefer 9dcc472c60 Merge branch 'feature/prefetching' into develop 2012-03-12 13:33:14 +01:00
DennisSchiefer c972e2cf41 Merge branch 'gui/buttons' into develop 2012-03-12 13:26:38 +01:00
DennisSchiefer de9ab83cea ignore eclipse files 2012-03-12 13:16:32 +01:00
schiefer 174e388e2d debug window added,
when including OSRM.debug, a debug window is shown
2012-03-12 11:33:39 +01:00
DennisSchiefer ee41fb45b7 added more turn instructions, changed clickability of gui 2012-03-10 17:08:25 +01:00
schiefer 93892b9806 changed buttons look 2012-03-09 17:33:06 +01:00
schiefer 749d83a69f - store prefetched images permanently
(otherwise they are not prefetched before the function terminated)
- store each type of marker icon once
2012-03-09 15:26:32 +01:00
schiefer 8b109904c8 initial import 2012-03-09 09:24:51 +01:00
711 changed files with 8144 additions and 111449 deletions
-54
View File
@@ -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
...
+2 -82
View File
@@ -1,82 +1,2 @@
# pre compiled dependencies #
#############################
osrm-deps
# Compiled source #
###################
*.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
/.settings
/.project
View File
-65
View File
@@ -1,65 +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
- ./algorithm-tests
- ./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:
- patrick@mapbox.com
email:
on_success: change
on_failure: always
-376
View File
@@ -1,376 +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> $<TARGET_OBJECTS:IMPORT>)
add_library(FINGERPRINT OBJECT util/fingerprint.cpp)
add_dependencies(FINGERPRINT FingerPrintConfigure)
add_dependencies(OSRM FingerPrintConfigure)
set_target_properties(FINGERPRINT PROPERTIES LINKER_LANGUAGE CXX)
add_executable(osrm-routed routed.cpp ${ServerGlob} $<TARGET_OBJECTS:EXCEPTION>)
add_executable(osrm-datastore datastore.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
# Unit tests
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_OBJECTS:IMPORT>)
target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES} ${TBB_LIBRARIES})
add_executable(osrm-springclean tools/springclean.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:EXCEPTION>)
target_link_libraries(osrm-springclean ${Boost_LIBRARIES})
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()
-7
View File
@@ -1,7 +0,0 @@
source "http://rubygems.org"
gem "cucumber"
gem "rake"
gem "osmlib-base"
gem "sys-proctable"
gem "rspec-expectations"
-35
View File
@@ -1,35 +0,0 @@
GEM
remote: http://rubygems.org/
specs:
builder (3.2.2)
cucumber (2.0.0)
builder (>= 2.1.2)
cucumber-core (~> 1.1.3)
diff-lcs (>= 1.1.3)
gherkin (~> 2.12)
multi_json (>= 1.7.5, < 2.0)
multi_test (>= 0.1.2)
cucumber-core (1.1.3)
gherkin (~> 2.12.0)
diff-lcs (1.2.5)
gherkin (2.12.2)
multi_json (~> 1.3)
multi_json (1.11.0)
multi_test (0.1.2)
osmlib-base (0.1.4)
rake (10.4.2)
rspec-expectations (3.2.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
rspec-support (3.2.2)
sys-proctable (0.9.8)
PLATFORMS
ruby
DEPENDENCIES
cucumber
osmlib-base
rake
rspec-expectations
sys-proctable
-22
View File
@@ -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.
-46
View File
@@ -1,46 +0,0 @@
## About
The Open Source Routing Machine is a high performance routing engine written in C++11 designed to run on OpenStreetMap data.
## Current build status
| build config | branch | status |
|:-------------|:--------|:------------|
| Linux | master | [![Build Status](https://travis-ci.org/Project-OSRM/osrm-backend.png?branch=master)](https://travis-ci.org/Project-OSRM/osrm-backend) |
| Linux | develop | [![Build Status](https://travis-ci.org/Project-OSRM/osrm-backend.png?branch=develop)](https://travis-ci.org/Project-OSRM/osrm-backend) |
| Windows | master/develop | [![Build status](https://ci.appveyor.com/api/projects/status/4iuo3s9gxprmcjjh)](https://ci.appveyor.com/project/DennisOSRM/osrm-backend) |
| LUAbind fork | master | [![Build Status](https://travis-ci.org/DennisOSRM/luabind.png?branch=master)](https://travis-ci.org/DennisOSRM/luabind) |
## Building
For instructions on how to [build](https://github.com/Project-OSRM/osrm-backend/wiki/Building-OSRM) and [run OSRM](https://github.com/Project-OSRM/osrm-backend/wiki/Running-OSRM), please consult [the Wiki](https://github.com/Project-OSRM/osrm-backend/wiki).
To quickly try OSRM use our [free and daily updated online service](http://map.project-osrm.org)
## Documentation
See the Wiki's [server API documentation](https://github.com/Project-OSRM/osrm-backend/wiki/Server-api) as well as the [library API documentation](https://github.com/Project-OSRM/osrm-backend/wiki/Library-api)
## 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},
}
```
-190
View File
@@ -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
+39
View File
@@ -0,0 +1,39 @@
// dashed polyline
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";
}
},
});
+30
View File
@@ -0,0 +1,30 @@
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
});
},
});
+13
View File
@@ -0,0 +1,13 @@
// OSRM browser detection
(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)
+62
View File
@@ -0,0 +1,62 @@
// GUI functionality
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";
}
},
};
+77
View File
@@ -0,0 +1,77 @@
// OSRM JSONP call wrapper
// w/ DOM cleaning, fencing, timout handling
OSRM.JSONP = {
fences: {},
callbacks: {},
timeouts: {},
timers: {},
TIMEOUT: OSRM.DEFAULTS.JSONP_TIMEOUT,
late: function() { },//console.log("reply too late");},
empty: function() { },//console.log("empty callback");},
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;
// console.log("[status] jsonp init for "+id);
// console.log("[status] jsonp request ",source);
// wrap timeout function
OSRM.JSONP.timeouts[id] = function(response) {
timeout_function(response);
// var jsonp = document.getElementById('jsonp_'+id); // clean DOM
// if(jsonp)
// jsonp.parentNode.removeChild(jsonp);
OSRM.JSONP.callbacks[id] = OSRM.JSONP.late; // clean functions
OSRM.JSONP.timeouts[id] = OSRM.JSONP.late;
OSRM.JSONP.fences[id] = undefined; // clean fence
// console.log("timeout: "+id); // at the end - otherwise racing conditions may happen
// document.getElementById('information-box').innerHTML += "timeout:" + id + "<br>";
};
// wrap callback function
OSRM.JSONP.callbacks[id] = function(response) {
clearTimeout(OSRM.JSONP.timers[id]); // clear timeout timer
OSRM.JSONP.timers[id] = undefined;
if( OSRM.JSONP.fences[id] == undefined ) // fence to prevent execution after timeout function (when precompiled!)
return;
callback_function(response); // actual wrapped callback
// var jsonp = document.getElementById('jsonp_'+id); // clean DOM
// if(jsonp)
// jsonp.parentNode.removeChild(jsonp);
OSRM.JSONP.callbacks[id] = OSRM.JSONP.late; // clean functions
OSRM.JSONP.timeouts[id] = OSRM.JSONP.late;
OSRM.JSONP.fences[id] = undefined; // clean fence
// console.log("[status] jsonp response for "+id); // at the end - otherwise racing conditions may happen
// document.getElementById('information-box').innerHTML += "callback:" + id + "<br>";
};
// clean DOM (cannot reuse script element with all browsers, unfortunately)
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);
return true;
}
};
+73
View File
@@ -0,0 +1,73 @@
// localization
OSRM.Localization = {
language: "en",
translate: function(text) {
if( OSRM.Localization[OSRM.Localization.language][text] )
return OSRM.Localization[OSRM.Localization.language][text];
else if( OSRM.Localization[OSRM.Localization.language][text] )
return OSRM.Localization[OSRM.Localization.language][text];
else
return text;
},
};
OSRM.loc = OSRM.Localization.translate;
OSRM.Localization["de"] = {
//gui
"GUI_START": "Start",
"GUI_END": "Ende",
"GUI_RESET": "Reset",
"GUI_SEARCH": "Suchen",
"GUI_ROUTE": "Route",
"GUI_REVERSE": "Umdrehen",
"GUI_OPTIONS": "Optionen",
"GUI_HIGHLIGHT_UNNAMED_ROADS": "Unbenannte Straen hervorheben",
"GUI_START_TOOLTIP": "Startposition eingeben",
"GUI_END_TOOLTIP": "Zielposition eingeben",
"GUI_LEGAL_NOTICE": "GUI2 v0.1 120313 - 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": "Zeitberschreitung",
"NO_RESULTS_FOUND": "Keine Ergebnisse gefunden",
// routing
"ROUTE_DESCRIPTION": "Routenbeschreibung",
"GET_LINK": "Generiere Link",
"LINK_TO_ROUTE": "Link zur Route",
"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 mglich",
};
OSRM.Localization["en"] = {
//gui
"GUI_START": "Start",
"GUI_END": "End",
"GUI_RESET": "Reset",
"GUI_SEARCH": "Search",
"GUI_ROUTE": "Route",
"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 120313 - 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",
//routing
"ROUTE_DESCRIPTION": "Route Description",
"GET_LINK": "Generate Link",
"LINK_TO_ROUTE": "Route 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",
};
+194
View File
@@ -0,0 +1,194 @@
// OSRM.Marker class
// + sub-classes
// base class
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.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
OSRM.HighlightMarker = function( label, style, position) {
OSRM.HighlightMarker.prototype.base.constructor.apply( this, arguments );
this.label = label ? label : "highlight_marker";
};
OSRM.inheritFrom( OSRM.HighlightMarker, OSRM.Marker );
OSRM.extend( OSRM.HighlightMarker, {
toString: function() {
return "OSRM.HighlightMarker: \""+this.label+"\", "+this.position+")";
},
});
// route marker
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) {
// if(!e.ctrlKey)
// return;
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) {
// OSRM.debug.log("[event] drag event");
this.parent.setPosition( e.target.getLatLng() );
if(OSRM.dragging == true) // TODO: hack to deal with drag events after dragend event
getRoute(OSRM.NO_DESCRIPTION);
else
getRoute(OSRM.FULL_DESCRIPTION);
updateLocation( this.parent.label );
},
onDragStart: function(e) {
// OSRM.debug.log("[event] dragstart event");
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) {
// OSRM.debug.log("[event] dragend event");
getRoute(OSRM.FULL_DESCRIPTION);
if (my_route.isShown()) {
my_route.hideOldRoute();
my_route.hideUnnamedRoute(); // provides better visuals
}
OSRM.dragging = false;
updateLocation( this.parent.label );
},
toString: function() {
return "OSRM.RouteMarker: \""+this.label+"\", "+this.position+")";
},
});
//marker array class
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);
}
});
+169
View File
@@ -0,0 +1,169 @@
// OSRM route classes
// base route class
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() );
bounds._southWest.lng-=1.02; // dirty hack
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 (several separate route parts)
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 + ")";
}
});
// main route class
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();
},
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 Leaglet 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();
}
});
+12
View File
@@ -0,0 +1,12 @@
// OSRM route class
OSRM.TheRoute = {
};
OSRM.extend( OSRM.TheRoute, {
show: function() {},
hide: function() {},
});
+27
View File
@@ -0,0 +1,27 @@
// OSRM base class
OSRM = {};
OSRM.VERSION = '0.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 } );
+14
View File
@@ -0,0 +1,14 @@
// 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: 'http://map.project-osrm.org/',
JSONP_TIMEOUT: 2000,
ZOOM_LEVEL: 14,
ONLOAD_LATITUDE: 48.84,
ONLOAD_LONGITUDE: 10.10,
ONLOAD_SOURCE: "",
ONLOAD_TARGET: "",
};
+49
View File
@@ -0,0 +1,49 @@
// debug code for OSRM
// (works faster than console.log in time-critical events)
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 = "";
};
+164
View File
@@ -0,0 +1,164 @@
// some constants
OSRM.GEOCODE_POST = 'http://nominatim.openstreetmap.org/search?format=json';
OSRM.REVERSE_GEOCODE_POST = 'http://nominatim.openstreetmap.org/reverse?format=json';
OSRM.SOURCE_MARKER_LABEL = "source";
OSRM.TARGET_MARKER_LABEL = "target";
// update locations in input boxes
function updateLocation(marker_id) {
if (marker_id == OSRM.SOURCE_MARKER_LABEL) {
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) {
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);
}
}
function updateReverseGeocoder(marker_id) {
if (marker_id == OSRM.SOURCE_MARKER_LABEL) {
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) {
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);
}
}
function updateLocations() {
if( my_markers.route[0] && my_markers.route[0].label == OSRM.SOURCE_MARKER_LABEL) {
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);
//OSRM.debug.log("[call1] reverse geocoder");
}
if( my_markers.route[my_markers.route.length-1] && my_markers.route[ my_markers.route.length-1 ].label == OSRM.TARGET_MARKER_LABEL) {
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);
}
}
function timeout_ReverseGeocoder() {
//OSRM.debug.log("[timeout] reverse geocoder");
}
//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, timeout_ReverseGeocoder, OSRM.JSONP.TIMEOUT, "reverse_geocoder_source" );
//OSRM.debug.log("[call2] reverse geocoder");
} else if (marker_id == OSRM.TARGET_MARKER_LABEL) {
var src = OSRM.REVERSE_GEOCODE_POST + "&lat=" + lat + "&lon=" + lon;
OSRM.JSONP.call( src, showReverseGeocoderResults_Target, timeout_ReverseGeocoder, OSRM.JSONP.TIMEOUT, "reverse_geocoder_target" );
}
}
//processing JSONP response of reverse geocoder
//(with wrapper functions for source/target jsonp)
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( response.address.road)
address += ", ";
address += response.address.city;
}
if( address == "" )
return;
if(marker_id == OSRM.SOURCE_MARKER_LABEL)
document.getElementById("input-source-name").value = address;
else if(marker_id == OSRM.TARGET_MARKER_LABEL)
document.getElementById("input-target-name").value = address;
}
}
// prepare request and call geocoder
function callGeocoder(marker_id, query) {
//geo coordinate given?
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]);
// updateReverseGeocoder(marker_id);
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.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.JSONP.TIMEOUT, "geocoder_target" );
}
}
// helper function for clicks on geocoder search results
function onclickGeocoderResult(marker_id, lat, lon) {
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; // search via positions not yet implemented
my_markers.route[index].show();
my_markers.route[index].centerView();
getRoute(OSRM.FULL_DESCRIPTION);
}
// processing 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();
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() {
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("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>";
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 963 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 959 B

File diff suppressed because it is too large Load Diff
+323
View File
@@ -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);
}
+48
View File
@@ -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;
}
File diff suppressed because one or more lines are too long
+286
View File
@@ -0,0 +1,286 @@
/* styles for map */
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
{
cursor:pointer;
position:absolute;
right:5px;
top:5px;
width:16px;
height:16px;
background-image:url("images/cancel.png");
}
.main-toggle:hover
{
background-image:url("images/cancel_hover.png");
}
.main-toggle:active
{
background-image:url("images/cancel_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-item
{
cursor:pointer;
color:#000000
}
.result-item:hover
{
color:#ff0000
}
#legal-notice
{
position:absolute;
right:0px;
bottom:0px;
padding:5px;
font-size:10px;
}
/* generally useful styles (above buttons, so that they get their special cursor!)*/
.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;
}
+111
View File
@@ -0,0 +1,111 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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" />
<!-- 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" 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" 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" value="" title="Startposition eingeben" 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-here-target" onclick="">i</a></td> -->
<td class="right"><a class="button not-selectable" id="gui-search-source" onclick="callGeocoder(OSRM.SOURCE_MARKER_LABEL, document.getElementById('input-source-name').value);">Suchen</a></td>
</tr>
<tr>
<td id="gui-search-target-label">Ende:</td>
<td><input id="input-target-name" class="input-box" type="text" value="" title="Zielposition eingeben" 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-here-target" onclick="">i</a></td> -->
<td class="right"><a class="button not-selectable" id="gui-search-target" onclick="callGeocoder(OSRM.TARGET_MARKER_LABEL, document.getElementById('input-target-name').value);">Suchen</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="center"> <a class="button not-selectable" id="gui-reverse" onclick="reverseRouting();">Reverse</a></td>
<td class="right"> <a class="button not-selectable" id="gui-route" onclick="startRouting();">Route</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 120313 - 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>
+214
View File
@@ -0,0 +1,214 @@
var map;
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'
];
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-route").innerHTML = OSRM.loc("GUI_ROUTE");
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() {
var osmorgURL = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
osmorgAttribution = 'Map data &copy; 2011 OpenStreetMap contributors, Imagery &copy; 2011 Mapnik',
osmorgOptions = {maxZoom: 18, attribution: osmorgAttribution};
var osmdeURL = 'http://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png',
osmdeAttribution = 'Map data &copy; 2011 OpenStreetMap contributors, Imagery &copy; 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 &copy; 2011 OpenStreetMap contributors, Imagery &copy; 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 &copy; 2011 OpenStreetMap contributors, Imagery &copy; 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);
map = new L.Map('map', {
center: new L.LatLng(51.505, -0.09),
zoom: 13,
zoomAnimation: false, // uncomment to remove animations and hiding of routes during zoom
fadeAnimation: false,
layers: [osmorg]
});
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);
getElementsByClassName(document,'leaflet-control-zoom')[0].style.left="420px";
getElementsByClassName(document,'leaflet-control-zoom')[0].style.top="5px";
map.setView( new L.LatLng( OSRM.DEFAULTS.ONLOAD_LATITUDE, OSRM.DEFAULTS.ONLOAD_LONGITUDE-0.02), OSRM.DEFAULTS.ZOOM_LEVEL);
map.on('zoomend', function(e) { getRoute(OSRM.FULL_DESCRIPTION); });
map.on('click', function(e) {
if( !my_markers.route[0] || my_markers.route[0].label != OSRM.SOURCE_MARKER_LABEL) {
index = my_markers.setSource( e.latlng );
my_markers.route[index].show();
my_markers.route[index].centerView(false);
getRoute(OSRM.FULL_DESCRIPTION);
updateLocation("source");
// updateReverseGeocoder("source");
}
else if( !my_markers.route[my_markers.route.length-1] || my_markers.route[ my_markers.route.length-1 ].label != OSRM.TARGET_MARKER_LABEL) {
index = my_markers.setTarget( e.latlng );
my_markers.route[index].show();
my_markers.route[index].centerView(false);
getRoute(OSRM.FULL_DESCRIPTION);
updateLocation("target");
// updateReverseGeocoder("target");
}
} );
// onmousemove test
// map.on('mousemove', function(e) { console.log("pos: " + e.latlng); });
// map.on('mousemove', function(e) {
// var objs = new Array;
// var obj = null;
// do {
// obj = document.elementFromPoint(e.layerPoint.x, e.layerPoint.y);
//
// if (obj == null)
// break;
// if (obj == document.body)
// break;
// if (obj instanceof SVGPathElement)
// break;
//
// objs.push(obj);
// obj.style.display = 'none';
// } while(true);
// for(var i=0; i<objs.length; ++i)
// objs[i].style.display ='';
//
// if (obj == null)
// return;
//
// if (obj instanceof SVGPathElement)
// xroute.route.fire('mousemove',e);
// else
// xroute.route.fire('mouseout',e);
// });
}
// parse URL GET parameters if existing
function checkURL(){
var called_url = document.location.search.substr(1,document.location.search.length);
if( called_url != '') {
var positions = [];
// parse input (currently only parses start, dest, via)
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;
var coordinates = unescape(name_val[1]).split(',');
if(coordinates.length!=2)
continue;
if(name_val[0] == 'loc')
positions.push ( new L.LatLng( coordinates[0], coordinates[1]) );
}
// draw via points
if( positions.length > 0)
my_markers.setSource( positions[0] );
for(var i=1; i<positions.length-1;i++)
my_markers.setVia( i-1, positions[i] );
if(positions.length > 1)
my_markers.setTarget( positions[positions.length-1] );
for(var i=0; i<my_markers.route.length;i++)
my_markers.route[i].show();
// compute route
getRoute(OSRM.FULL_DESCRIPTION);
var bounds = new L.LatLngBounds( positions );
//bounds._southWest.lng-=1.02; // dirty hacks
map.fitBounds( bounds );
//my_route.centerView();
}
}
+423
View File
@@ -0,0 +1,423 @@
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 data
function initRouting() {
my_route = new OSRM.Route();
my_markers = new OSRM.Markers();
}
// 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;
}
// display a transmitted route
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);
// if(OSRM.pending) {
// clearTimeout(OSRM.pendingTimer);
// OSRM.pendingTimer = setTimeout(timeoutDrag,100); // dirty dirty!
// }
}
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);
}
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);
}
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-link').innerHTML = '[<a id="gpx-link" href="' +response.ShortURL+ '">'+OSRM.loc("LINK_TO_ROUTE")+'</a>]';
}
function showRouteLink_TimeOut(){
document.getElementById('route-link').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-link">[<a id="gpx-link" onclick="onClickCreateShortcut(\'' + OSRM.DEFAULTS.WEBSITE_URL + query_string + '\')">'+OSRM.loc("GET_LINK")+'</a>]</span>';
//var route_link ='<span class="route-summary" id="route-link">[<a id="gpx-link" href="#" onclick="onClickCreateShortcut(\'' + document.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-counter"><span">'+(i+1)+'.</span></td>';
route_desc += '<td class="result-items">';
route_desc += '<span class="result-item" onclick="onClickRouteDescription('+response.route_instructions[i][3]+')">'
+ response.route_instructions[i][0] + ' on ';
if( response.route_instructions[i][2] > 0 )
route_desc += response.route_instructions[i][1] + ' for '
+ getDistanceWithUnit(response.route_instructions[i][2])
+ '</span>';
route_desc += "</td>";
route_desc += "</tr>";
}
route_desc += '</table>';
headline = "";
headline += OSRM.loc("ROUTE_DESCRIPTION")+":<br>";
headline += '<div style="float:left;width:70%">';
headline += "<span class='route-summary'>"
+ OSRM.loc("DISTANCE")+": " + getDistanceWithUnit(response.route_summary.total_distance)
+ " - "
+ OSRM.loc("DURATION")+": " + secondsToTime(response.route_summary.total_time)
+ "</span>";
headline += '</div>';
headline += '<div style="float:left;text-align:right;width:30%;">'+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)
+ " - "
+ 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"
+ " - "
+ 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>";
}
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);
}
// function for dragging and drawing routes
function getRoute(do_description) {
// if source or target are not set -> hide route
if( my_markers.route.length < 2 ) {
my_route.hideRoute();
//my_markers.removeVias(); // TODO: do I need this?
//my_markers.highlight.hide();
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.JSONP.TIMEOUT, type);
// TODO: guarantee to do last drag
if(called == false && !do_description) {
clearTimeout(OSRM.pendingTimer);
OSRM.pendingTimer = setTimeout(timeoutDrag,OSRM.JSONP.TIMEOUT);
}
else {
clearTimeout(OSRM.pendingTimer);
}
// 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);
}
function startRouting() {
getRoute(OSRM.FULL_DESCRIPTION);
}
function resetRouting() {
document.getElementById('input-source-name').value = "";
document.getElementById('input-target-name').value = "";
my_route.hideRoute();
my_markers.removeAll();
my_markers.highlight.hide();
document.getElementById('information-box').innerHTML = "";
document.getElementById('information-box-headline').innerHTML = "";
}
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];
}
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" );
}
function positionsToInput() {
if(my_markers.route[0].label == OSRM.SOURCE_MARKER_LABEL) {
document.getElementById('input-source-name').value = my_markers.route[0].getPosition().lat.toFixed(6)+","+my_markers.route[0].getPosition().lng.toFixed(6);
}
if(my_markers.route[my_markers.route.length-1].label == OSRM.TARGET_MARKER_LABEL) {
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);
}
}
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
getRoute(OSRM.FULL_DESCRIPTION);
my_markers.highlight.hide();
}
//--------------------
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 round-about and leave at first exit":"round-about.png",
"Enter round-about and leave at second exit":"round-about.png",
"Enter round-about and leave at third exit":"round-about.png",
"Enter round-about and leave at forth exit":"round-about.png",
"Enter round-about and leave at fifth exit":"round-about.png",
"Enter round-about and leave at sixth exit":"round-about.png",
"Enter round-about and leave at seventh exit":"round-about.png",
"Enter round-about and leave at eighth exit":"round-about.png",
"Enter round-about and leave at nineth exit":"round-about.png",
"Enter round-about and leave at tenth exit":"round-about.png",
"Enter round-about and leave at one of the too many exit":"round-about.png",
};
if( directions[name] )
return directions[name];
else
return "default.png";
}
+27
View File
@@ -0,0 +1,27 @@
<html>
<head>
<script src="leaflet/leaflet-src.js"></script>
<script src="OSRM.js"></script>
<script src="OSRM.Markers.js"></script>
<script type="text/javascript">
function testSnippet()
{
var marker = new OSRM.RouteMarker("source",undefined,new L.Icon('images/marker-source.png'));
marker.yyy();
for(a in marker)
alert(a);
alert(marker);
}
</script>
</head>
<body>
<h1>Test Javascript Snippets</h1>
<p id="output">This could be your output.</p>
<button type="button" onclick="testSnippet()">Run Snippet</button>
</body>
</html>
+69
View File
@@ -0,0 +1,69 @@
// compatibility mode for old browser
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 >= 1000){ return (parseInt(distance/1000))+' km'; }
else{ return distance+' m'; }
}
// ------------------------------------------------------
// 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);
}
};
+42
View File
@@ -0,0 +1,42 @@
var via_points;
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;
}
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;
}
-117
View File
@@ -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
-174
View File
@@ -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_
-145
View File
@@ -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 */
-164
View File
@@ -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);
}
}
}
}
-81
View File
@@ -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_ */
-91
View File
@@ -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 */
-128
View File
@@ -1,128 +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);
}
std::vector<FixedPointCoordinate> PolylineCompressor::decode_string(const std::string &geometry_string) const
{
std::vector<FixedPointCoordinate> new_coordinates;
int index = 0, len = geometry_string.size();
int lat = 0, lng = 0;
while (index < len)
{
int b, shift = 0, result = 0;
do
{
b = geometry_string.at(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do
{
b = geometry_string.at(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
FixedPointCoordinate p;
p.lat = COORDINATE_PRECISION * (((double) lat / 1E6));
p.lon = COORDINATE_PRECISION * (((double) lng / 1E6));
new_coordinates.push_back(p);
}
return new_coordinates;
}
-51
View File
@@ -1,51 +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 <osrm/coordinate.hpp>
#include <string>
#include <vector>
class PolylineCompressor
{
private:
std::string encode_vector(std::vector<int> &numbers) const;
std::string encode_number(const int number_to_encode) const;
public:
std::string get_encoded_string(const std::vector<SegmentInformation> &polyline) const;
std::vector<FixedPointCoordinate> decode_string(const std::string &geometry_string) const;
};
#endif /* POLYLINECOMPRESSOR_H_ */
-56
View File
@@ -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;
}
-45
View File
@@ -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 */
-162
View File
@@ -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
-239
View File
@@ -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 */
-113
View File
@@ -1,113 +0,0 @@
@ECHO OFF
SETLOCAL
SET EL=0
ECHO platform^: %platform%
:: HARDCODE "x64" as it is uppercase on AppVeyor and download from S3 is case sensitive
SET DEPSPKG=osrm-deps-win-x64-14.0.7z
:: local development
IF "%computername%"=="MB" GOTO SKIPDL
IF EXIST %DEPSPKG% DEL %DEPSPKG%
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
ECHO downloading %DEPSPKG%
powershell Invoke-WebRequest https://mapbox.s3.amazonaws.com/windows-builds/windows-deps/$env:DEPSPKG -OutFile C:\projects\osrm\$env:DEPSPKG
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
7z -y x %DEPSPKG% | %windir%\system32\FIND "ing archive"
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
:SKIPDL
IF EXIST build rd /s /q build
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
mkdir build
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
cd build
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
SET OSRMDEPSDIR=c:\projects\osrm\osrm-deps
set PREFIX=%OSRMDEPSDIR%/libs
set BOOST_ROOT=%OSRMDEPSDIR%/boost
set TBB_INSTALL_DIR=%OSRMDEPSDIR%/tbb
set TBB_ARCH_PLATFORM=intel64/vc14
ECHO calling cmake ....
cmake .. ^
-G "Visual Studio 14 Win64" ^
-DBOOST_ROOT=%BOOST_ROOT% ^
-DBoost_ADDITIONAL_VERSIONS=1.57 ^
-DBoost_USE_MULTITHREADED=ON ^
-DBoost_USE_STATIC_LIBS=ON ^
-DCMAKE_BUILD_TYPE=%CONFIGURATION% ^
-DCMAKE_INSTALL_PREFIX=%PREFIX%
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
ECHO building ...
msbuild OSRM.sln ^
/p:Configuration=%Configuration% ^
/p:Platform=x64 ^
/t:rebuild ^
/p:BuildInParallel=true ^
/m:%NUMBER_OF_PROCESSORS% ^
/toolsversion:14.0 ^
/p:PlatformToolset=v140 ^
/clp:Verbosity=normal ^
/nologo ^
/flp1:logfile=build_errors.txt;errorsonly ^
/flp2:logfile=build_warnings.txt;warningsonly
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
ECHO ========= TODO^: CREATE PACKAGES ==========
CD c:\projects\osrm\build\%Configuration%
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
SET PATH=c:\projects\osrm\osrm-deps\libs\bin;%PATH%
ECHO running datastructure-tests.exe ...
datastructure-tests.exe
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
ECHO running algorithm-tests.exe ...
algorithm-tests.exe
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
GOTO DONE
:ERROR
SET EL=%ERRORLEVEL%
ECHO ============== ERROR ===============
:DONE
ECHO ============= DONE ===============
CD C:\projects\osrm
EXIT /b %EL%
- cd c:/projects/osrm
- mkdir build
- cd build
- echo Running cmake...
- call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
- SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH%
- SET P=c:/projects/osrm
- set TBB_INSTALL_DIR=%P%/tbb
- set TBB_ARCH_PLATFORM=intel64/vc12
- cmake .. -G "Visual Studio 14 Win64" -DCMAKE_BUILD_TYPE=%Configuration% -DCMAKE_INSTALL_PREFIX=%P%/libs -DBOOST_ROOT=%P%/boost_min -DBoost_ADDITIONAL_VERSIONS=1.57 -DBoost_USE_STATIC_LIBS=ON
- SET PLATFORM_TOOLSET=v140
- SET TOOLS_VERSION=14.0
- msbuild /p:Platform=x64 /clp:Verbosity=minimal /toolsversion:%TOOLS_VERSION% /p:PlatformToolset=%PLATFORM_TOOLSET% /nologo OSRM.sln
- msbuild /p:Platform=x64 /clp:Verbosity=minimal /toolsversion:%TOOLS_VERSION% /p:PlatformToolset=%PLATFORM_TOOLSET% /nologo tests.vcxproj
- cd %Configuration%
- if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip *.exe *.pdb %P%/libs/bin/*.dll -tzip)
- cd ..\..\profiles
- echo disk=c:\temp\stxxl,10000,wincall > .stxxl.txt
- if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip * -tzip)
- set PATH=%PATH%;c:/projects/osrm/libs/bin
- cd c:/projects/osrm/build/%Configuration%
- datastructure-tests.exe
- algorithm-tests.exe
-48
View File
@@ -1,48 +0,0 @@
environment:
matrix:
- configuration: Release
# - configuration: Debug
# scripts that are called at very beginning, before repo cloning
init:
- git config --global core.autocrlf input
os: Visual Studio 2015 RC
# clone directory
clone_folder: c:\projects\osrm
platform: x64
install:
- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
- CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
build_script:
- CALL appveyor-build.bat
test: off
artifacts:
- path: osrm_Release.zip
name: osrm_Release.zip
# - path: osrm_Debug.zip
# name: osrm_Debug.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
-184
View File
@@ -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 *)&current_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;
}
-19
View File
@@ -1,19 +0,0 @@
@ECHO OFF
SET PLATFORM=x64
SET CONFIGURATION=Release
WHERE msbuild
IF %ERRORLEVEL% EQU 0 GOTO RUNBUILD
SET PATH=C:\mb\windows-builds-64\tmp-bin\cmake-3.1.0-win32-x86\bin;%PATH%
SET PATH=C:\Program Files\7-Zip;%PATH%
ECHO activating VS command prompt ...
SET PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
:RUNBUILD
powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted -Force
CALL appveyor-build.bat
EXIT /b %ERRORLEVEL%
-44
View File
@@ -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]")
-29
View File
@@ -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)
-19
View File
@@ -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)
-82
View File
@@ -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)
-93
View File
@@ -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()
-75
View File
@@ -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)
-54
View File
@@ -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)
-51
View File
@@ -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)
-283
View File
@@ -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)
-10
View File
@@ -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)
-123
View File
@@ -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()
-38
View File
@@ -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()
-40
View File
@@ -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()
-45
View File
@@ -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
-11
View File
@@ -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}
-2
View File
@@ -1,2 +0,0 @@
#/usr/bin/env bash
ln -s /usr/share/doc/@CMAKE_PROJECT_NAME@/profiles/car.lua @CMAKE_INSTALL_PREFIX@/profile.lua
-9
View File
@@ -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
-963
View File
@@ -1,963 +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)) << " : "
<< static_cast<unsigned int>(diter->source) << " -> " << static_cast<unsigned int>(diter->target);
}
#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();
// FIXME not sure if we need this
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 &current_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;
stxxl::vector<QueryEdge> external_edge_list;
std::vector<NodeID> orig_node_id_to_new_id_map;
XORFastHash fast_hash;
};
#endif // CONTRACTOR_HPP
-135
View File
@@ -1,135 +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 "contractor_options.hpp"
#include "../util/git_sha.hpp"
#include "../util/simple_logger.hpp"
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <tbb/task_scheduler_init.h>
return_code
ContractorOptions::ParseArguments(int argc, char *argv[], ContractorConfig &contractor_config)
{
// declare a group of options that will be allowed only on command line
boost::program_options::options_description generic_options("Options");
generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
"config,c", boost::program_options::value<boost::filesystem::path>(&contractor_config.config_file_path)
->default_value("contractor.ini"),
"Path to a configuration file.");
// declare a group of options that will be allowed both on command line and in config file
boost::program_options::options_description config_options("Configuration");
config_options.add_options()(
"restrictions,r",
boost::program_options::value<boost::filesystem::path>(&contractor_config.restrictions_path),
"Restrictions file in .osrm.restrictions format")(
"profile,p", boost::program_options::value<boost::filesystem::path>(&contractor_config.profile_path)
->default_value("profile.lua"),
"Path to LUA routing profile")(
"threads,t", boost::program_options::value<unsigned int>(&contractor_config.requested_num_threads)
->default_value(tbb::task_scheduler_init::default_num_threads()),
"Number of threads to use");
// hidden options, will be allowed both on command line and in config file, but will not be
// shown to the user
boost::program_options::options_description hidden_options("Hidden options");
hidden_options.add_options()(
"input,i", boost::program_options::value<boost::filesystem::path>(&contractor_config.osrm_input_path),
"Input file in .osm, .osm.bz2 or .osm.pbf format");
// positional option
boost::program_options::positional_options_description positional_options;
positional_options.add("input", 1);
// combine above options for parsing
boost::program_options::options_description cmdline_options;
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
boost::program_options::options_description config_file_options;
config_file_options.add(config_options).add(hidden_options);
boost::program_options::options_description visible_options(
"Usage: " + boost::filesystem::basename(argv[0]) + " <input.osrm> [options]");
visible_options.add(generic_options).add(config_options);
// parse command line options
boost::program_options::variables_map option_variables;
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
.options(cmdline_options)
.positional(positional_options)
.run(),
option_variables);
const auto &temp_config_path = option_variables["config"].as<boost::filesystem::path>();
if (boost::filesystem::is_regular_file(temp_config_path))
{
boost::program_options::store(boost::program_options::parse_config_file<char>(
temp_config_path.string().c_str(), cmdline_options, true),
option_variables);
}
if (option_variables.count("version"))
{
SimpleLogger().Write() << g_GIT_DESCRIPTION;
return return_code::exit;
}
if (option_variables.count("help"))
{
SimpleLogger().Write() << "\n" << visible_options;
return return_code::exit;
}
boost::program_options::notify(option_variables);
if (!option_variables.count("restrictions"))
{
contractor_config.restrictions_path = contractor_config.osrm_input_path.string() + ".restrictions";
}
if (!option_variables.count("input"))
{
SimpleLogger().Write() << "\n" << visible_options;
return return_code::fail;
}
return return_code::ok;
}
void ContractorOptions::GenerateOutputFilesNames(ContractorConfig &contractor_config)
{
contractor_config.node_output_path = contractor_config.osrm_input_path.string() + ".nodes";
contractor_config.edge_output_path = contractor_config.osrm_input_path.string() + ".edges";
contractor_config.geometry_output_path = contractor_config.osrm_input_path.string() + ".geometry";
contractor_config.graph_output_path = contractor_config.osrm_input_path.string() + ".hsgr";
contractor_config.rtree_nodes_output_path = contractor_config.osrm_input_path.string() + ".ramIndex";
contractor_config.rtree_leafs_output_path = contractor_config.osrm_input_path.string() + ".fileIndex";
}
-68
View File
@@ -1,68 +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 CONTRACTOR_OPTIONS_HPP
#define CONTRACTOR_OPTIONS_HPP
#include <boost/filesystem/path.hpp>
#include <string>
enum class return_code : unsigned
{
ok,
fail,
exit
};
struct ContractorConfig
{
ContractorConfig() noexcept : requested_num_threads(0) {}
boost::filesystem::path config_file_path;
boost::filesystem::path osrm_input_path;
boost::filesystem::path restrictions_path;
boost::filesystem::path profile_path;
std::string node_output_path;
std::string edge_output_path;
std::string geometry_output_path;
std::string graph_output_path;
std::string rtree_nodes_output_path;
std::string rtree_leafs_output_path;
unsigned requested_num_threads;
};
struct ContractorOptions
{
static return_code ParseArguments(int argc, char *argv[], ContractorConfig &extractor_config);
static void GenerateOutputFilesNames(ContractorConfig &extractor_config);
};
#endif // EXTRACTOR_OPTIONS_HPP
-796
View File
@@ -1,796 +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(std::shared_ptr<NodeBasedDynamicGraph> node_based_graph,
std::shared_ptr<RestrictionMap> restriction_map,
std::unique_ptr<std::vector<NodeID>> barrier_node_list,
std::unique_ptr<std::vector<NodeID>> traffic_light_node_list,
const std::vector<QueryNode> &node_info_list,
const SpeedProfileProperties &speed_profile)
: speed_profile(speed_profile),
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
m_node_info_list(node_info_list),
m_node_based_graph(std::move(node_based_graph)),
m_restriction_map(std::move(restriction_map)), max_id(0), removed_node_count(0)
{
// insert into unordered sets for fast lookup
m_barrier_nodes.insert(barrier_node_list->begin(), barrier_node_list->end());
m_traffic_lights.insert(traffic_light_node_list->begin(), traffic_light_node_list->end());
}
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &output_edge_list)
{
BOOST_ASSERT_MSG(0 == output_edge_list.size(), "Vector is not empty");
m_edge_based_edge_list.swap(output_edge_list);
}
void EdgeBasedGraphFactory::GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes)
{
#ifndef NDEBUG
for (const EdgeBasedNode &node : m_edge_based_node_list)
{
BOOST_ASSERT(m_node_info_list.at(node.u).lat != INT_MAX);
BOOST_ASSERT(m_node_info_list.at(node.u).lon != INT_MAX);
BOOST_ASSERT(m_node_info_list.at(node.v).lon != INT_MAX);
BOOST_ASSERT(m_node_info_list.at(node.v).lat != INT_MAX);
}
#endif
nodes.swap(m_edge_based_node_list);
}
void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
const NodeID node_v,
const unsigned component_id)
{
// merge edges together into one EdgeBasedNode
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
// find forward edge id and
const EdgeID edge_id_1 = m_node_based_graph->FindEdge(node_u, node_v);
BOOST_ASSERT(edge_id_1 != SPECIAL_EDGEID);
const EdgeData &forward_data = m_node_based_graph->GetEdgeData(edge_id_1);
// find reverse edge id and
const EdgeID edge_id_2 = m_node_based_graph->FindEdge(node_v, node_u);
BOOST_ASSERT(edge_id_2 != SPECIAL_EDGEID);
const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(edge_id_2);
if (forward_data.edgeBasedNodeID == SPECIAL_NODEID &&
reverse_data.edgeBasedNodeID == SPECIAL_NODEID)
{
return;
}
BOOST_ASSERT(m_geometry_compressor.HasEntryForID(edge_id_1) ==
m_geometry_compressor.HasEntryForID(edge_id_2));
if (m_geometry_compressor.HasEntryForID(edge_id_1))
{
BOOST_ASSERT(m_geometry_compressor.HasEntryForID(edge_id_2));
// reconstruct geometry and put in each individual edge with its offset
const std::vector<GeometryCompressor::CompressedNode> &forward_geometry =
m_geometry_compressor.GetBucketReference(edge_id_1);
const std::vector<GeometryCompressor::CompressedNode> &reverse_geometry =
m_geometry_compressor.GetBucketReference(edge_id_2);
BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size());
BOOST_ASSERT(0 != forward_geometry.size());
const unsigned geometry_size = static_cast<unsigned>(forward_geometry.size());
BOOST_ASSERT(geometry_size > 1);
// reconstruct bidirectional edge with individual weights and put each into the NN index
std::vector<int> forward_dist_prefix_sum(forward_geometry.size(), 0);
std::vector<int> reverse_dist_prefix_sum(reverse_geometry.size(), 0);
// quick'n'dirty prefix sum as std::partial_sum needs addtional casts
// TODO: move to lambda function with C++11
int temp_sum = 0;
for (const auto i : osrm::irange(0u, geometry_size))
{
forward_dist_prefix_sum[i] = temp_sum;
temp_sum += forward_geometry[i].second;
BOOST_ASSERT(forward_data.distance >= temp_sum);
}
temp_sum = 0;
for (const auto i : osrm::irange(0u, geometry_size))
{
temp_sum += reverse_geometry[reverse_geometry.size() - 1 - i].second;
reverse_dist_prefix_sum[i] = reverse_data.distance - temp_sum;
// BOOST_ASSERT(reverse_data.distance >= temp_sum);
}
NodeID current_edge_source_coordinate_id = node_u;
if (SPECIAL_NODEID != forward_data.edgeBasedNodeID)
{
max_id = std::max(forward_data.edgeBasedNodeID, max_id);
}
if (SPECIAL_NODEID != reverse_data.edgeBasedNodeID)
{
max_id = std::max(reverse_data.edgeBasedNodeID, max_id);
}
// traverse arrays from start and end respectively
for (const auto i : osrm::irange(0u, geometry_size))
{
BOOST_ASSERT(current_edge_source_coordinate_id ==
reverse_geometry[geometry_size - 1 - i].first);
const NodeID current_edge_target_coordinate_id = forward_geometry[i].first;
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
// build edges
m_edge_based_node_list.emplace_back(
forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID,
current_edge_source_coordinate_id, current_edge_target_coordinate_id,
forward_data.nameID, forward_geometry[i].second,
reverse_geometry[geometry_size - 1 - i].second, forward_dist_prefix_sum[i],
reverse_dist_prefix_sum[i], m_geometry_compressor.GetPositionForID(edge_id_1),
component_id, i, forward_data.travel_mode, reverse_data.travel_mode);
current_edge_source_coordinate_id = current_edge_target_coordinate_id;
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
BOOST_ASSERT(node_u != m_edge_based_node_list.back().u ||
node_v != m_edge_based_node_list.back().v);
BOOST_ASSERT(node_u != m_edge_based_node_list.back().v ||
node_v != m_edge_based_node_list.back().u);
}
BOOST_ASSERT(current_edge_source_coordinate_id == node_v);
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
}
else
{
BOOST_ASSERT(!m_geometry_compressor.HasEntryForID(edge_id_2));
if (forward_data.edgeBasedNodeID != SPECIAL_NODEID)
{
BOOST_ASSERT(forward_data.forward);
}
else
{
BOOST_ASSERT(!forward_data.forward);
}
if (reverse_data.edgeBasedNodeID != SPECIAL_NODEID)
{
BOOST_ASSERT(reverse_data.forward);
}
else
{
BOOST_ASSERT(!reverse_data.forward);
}
BOOST_ASSERT(forward_data.edgeBasedNodeID != SPECIAL_NODEID ||
reverse_data.edgeBasedNodeID != SPECIAL_NODEID);
m_edge_based_node_list.emplace_back(
forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID, node_u, node_v,
forward_data.nameID, forward_data.distance, reverse_data.distance, 0, 0, SPECIAL_EDGEID,
component_id, 0, forward_data.travel_mode, reverse_data.travel_mode);
BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed());
}
}
void EdgeBasedGraphFactory::FlushVectorToStream(
std::ofstream &edge_data_file, std::vector<OriginalEdgeData> &original_edge_data_vector) const
{
if (original_edge_data_vector.empty())
{
return;
}
edge_data_file.write((char *)&(original_edge_data_vector[0]),
original_edge_data_vector.size() * sizeof(OriginalEdgeData));
original_edge_data_vector.clear();
}
void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
const std::string &geometry_filename,
lua_State *lua_state)
{
TIMER_START(geometry);
CompressGeometry();
TIMER_STOP(geometry);
TIMER_START(renumber);
RenumberEdges();
TIMER_STOP(renumber);
TIMER_START(generate_nodes);
GenerateEdgeExpandedNodes();
TIMER_STOP(generate_nodes);
TIMER_START(generate_edges);
GenerateEdgeExpandedEdges(original_edge_data_filename, lua_state);
TIMER_STOP(generate_edges);
m_geometry_compressor.SerializeInternalVector(geometry_filename);
SimpleLogger().Write() << "Timing statistics for edge-expanded graph:";
SimpleLogger().Write() << "Geometry compression: " << TIMER_SEC(geometry) << "s";
SimpleLogger().Write() << "Renumbering edges: " << TIMER_SEC(renumber) << "s";
SimpleLogger().Write() << "Generating nodes: " << TIMER_SEC(generate_nodes) << "s";
SimpleLogger().Write() << "Generating edges: " << TIMER_SEC(generate_edges) << "s";
}
void EdgeBasedGraphFactory::CompressGeometry()
{
SimpleLogger().Write() << "Removing graph geometry while preserving topology";
const unsigned original_number_of_nodes = m_node_based_graph->GetNumberOfNodes();
const unsigned original_number_of_edges = m_node_based_graph->GetNumberOfEdges();
Percent progress(original_number_of_nodes);
for (const NodeID node_v : osrm::irange(0u, original_number_of_nodes))
{
progress.printStatus(node_v);
// only contract degree 2 vertices
if (2 != m_node_based_graph->GetOutDegree(node_v))
{
continue;
}
// don't contract barrier node
if (m_barrier_nodes.end() != m_barrier_nodes.find(node_v))
{
continue;
}
// check if v is a via node for a turn restriction, i.e. a 'directed' barrier node
if (m_restriction_map->IsViaNode(node_v))
{
continue;
}
/*
* reverse_e2 forward_e2
* u <---------- v -----------> w
* ----------> <-----------
* forward_e1 reverse_e1
*
* Will be compressed to:
*
* reverse_e1
* u <---------- w
* ---------->
* forward_e1
*
* If the edges are compatible.
*
*/
const bool reverse_edge_order =
!(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(node_v)).forward);
const EdgeID forward_e2 = m_node_based_graph->BeginEdges(node_v) + reverse_edge_order;
BOOST_ASSERT(SPECIAL_EDGEID != forward_e2);
BOOST_ASSERT(forward_e2 >= m_node_based_graph->BeginEdges(node_v) &&
forward_e2 < m_node_based_graph->EndEdges(node_v));
const EdgeID reverse_e2 = m_node_based_graph->BeginEdges(node_v) + 1 - reverse_edge_order;
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2);
BOOST_ASSERT(reverse_e2 >= m_node_based_graph->BeginEdges(node_v) &&
reverse_e2 < m_node_based_graph->EndEdges(node_v));
const EdgeData &fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2);
const EdgeData &rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2);
const NodeID node_w = m_node_based_graph->GetTarget(forward_e2);
BOOST_ASSERT(SPECIAL_NODEID != node_w);
BOOST_ASSERT(node_v != node_w);
const NodeID node_u = m_node_based_graph->GetTarget(reverse_e2);
BOOST_ASSERT(SPECIAL_NODEID != node_u);
BOOST_ASSERT(node_u != node_v);
const EdgeID forward_e1 = m_node_based_graph->FindEdge(node_u, node_v);
BOOST_ASSERT(SPECIAL_EDGEID != forward_e1);
BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(forward_e1));
const EdgeID reverse_e1 = m_node_based_graph->FindEdge(node_w, node_v);
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e1);
BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(reverse_e1));
const EdgeData &fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1);
const EdgeData &rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1);
if (m_node_based_graph->FindEdgeInEitherDirection(node_u, node_w) != SPECIAL_EDGEID)
{
continue;
}
// this case can happen if two ways with different names overlap
if (fwd_edge_data1.nameID != rev_edge_data1.nameID ||
fwd_edge_data2.nameID != rev_edge_data2.nameID)
{
continue;
}
if (fwd_edge_data1.IsCompatibleTo(fwd_edge_data2) && rev_edge_data1.IsCompatibleTo(rev_edge_data2))
{
BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
m_node_based_graph->GetEdgeData(reverse_e1).nameID);
BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e2).nameID ==
m_node_based_graph->GetEdgeData(reverse_e2).nameID);
// Get distances before graph is modified
const int forward_weight1 = m_node_based_graph->GetEdgeData(forward_e1).distance;
const int forward_weight2 = m_node_based_graph->GetEdgeData(forward_e2).distance;
BOOST_ASSERT(0 != forward_weight1);
BOOST_ASSERT(0 != forward_weight2);
const int reverse_weight1 = m_node_based_graph->GetEdgeData(reverse_e1).distance;
const int reverse_weight2 = m_node_based_graph->GetEdgeData(reverse_e2).distance;
BOOST_ASSERT(0 != reverse_weight1);
BOOST_ASSERT(0 != reverse_weight2);
const bool has_node_penalty = m_traffic_lights.find(node_v) != m_traffic_lights.end();
// add weight of e2's to e1
m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
m_node_based_graph->GetEdgeData(reverse_e1).distance += rev_edge_data2.distance;
if (has_node_penalty)
{
m_node_based_graph->GetEdgeData(forward_e1).distance +=
speed_profile.traffic_signal_penalty;
m_node_based_graph->GetEdgeData(reverse_e1).distance +=
speed_profile.traffic_signal_penalty;
}
// extend e1's to targets of e2's
m_node_based_graph->SetTarget(forward_e1, node_w);
m_node_based_graph->SetTarget(reverse_e1, node_u);
// remove e2's (if bidir, otherwise only one)
m_node_based_graph->DeleteEdge(node_v, forward_e2);
m_node_based_graph->DeleteEdge(node_v, reverse_e2);
// update any involved turn restrictions
m_restriction_map->FixupStartingTurnRestriction(node_u, node_v, node_w);
m_restriction_map->FixupArrivingTurnRestriction(node_u, node_v, node_w,
*m_node_based_graph);
m_restriction_map->FixupStartingTurnRestriction(node_w, node_v, node_u);
m_restriction_map->FixupArrivingTurnRestriction(node_w, node_v, node_u,
*m_node_based_graph);
// store compressed geometry in container
m_geometry_compressor.CompressEdge(
forward_e1, forward_e2, node_v, node_w,
forward_weight1 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0),
forward_weight2);
m_geometry_compressor.CompressEdge(
reverse_e1, reverse_e2, node_v, node_u, reverse_weight1,
reverse_weight2 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0));
++removed_node_count;
}
}
SimpleLogger().Write() << "removed " << removed_node_count << " nodes";
m_geometry_compressor.PrintStatistics();
unsigned new_node_count = 0;
unsigned new_edge_count = 0;
for (const auto i : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
{
if (m_node_based_graph->GetOutDegree(i) > 0)
{
++new_node_count;
new_edge_count += (m_node_based_graph->EndEdges(i) - m_node_based_graph->BeginEdges(i));
}
}
SimpleLogger().Write() << "new nodes: " << new_node_count << ", edges " << new_edge_count;
SimpleLogger().Write() << "Node compression ratio: "
<< new_node_count / (double)original_number_of_nodes;
SimpleLogger().Write() << "Edge compression ratio: "
<< new_edge_count / (double)original_number_of_edges;
}
/// Renumbers all _forward_ edges and sets the edgeBasedNodeID.
/// A specific numbering is not important. Any unique ID will do.
void EdgeBasedGraphFactory::RenumberEdges()
{
// renumber edge based node of outgoing edges
unsigned numbered_edges_count = 0;
for (const auto current_node : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
{
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(current_node))
{
EdgeData &edge_data = m_node_based_graph->GetEdgeData(current_edge);
// this edge is an incoming edge
if (!edge_data.forward)
{
continue;
}
BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges());
edge_data.edgeBasedNodeID = numbered_edges_count;
++numbered_edges_count;
BOOST_ASSERT(SPECIAL_NODEID != edge_data.edgeBasedNodeID);
}
}
m_number_of_edge_based_nodes = numbered_edges_count;
}
/**
* Creates the nodes in the edge expanded graph from edges in the node-based graph.
*/
void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
{
SimpleLogger().Write() << "Identifying components of the (compressed) road network";
// Run a BFS on the undirected graph and identify small components
TarjanSCC<NodeBasedDynamicGraph> component_explorer(m_node_based_graph, *m_restriction_map,
m_barrier_nodes);
component_explorer.run();
SimpleLogger().Write() << "identified: "
<< component_explorer.get_number_of_components() - removed_node_count
<< " (compressed) components";
SimpleLogger().Write() << "identified "
<< component_explorer.get_size_one_count() - removed_node_count
<< " (compressed) SCCs of size 1";
SimpleLogger().Write() << "generating edge-expanded nodes";
Percent progress(m_node_based_graph->GetNumberOfNodes());
// loop over all edges and generate new set of nodes
for (const auto node_u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
{
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_u < m_node_based_graph->GetNumberOfNodes());
progress.printStatus(node_u);
for (EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(node_u))
{
const EdgeData &edge_data = m_node_based_graph->GetEdgeData(e1);
BOOST_ASSERT(e1 != SPECIAL_EDGEID);
const NodeID node_v = m_node_based_graph->GetTarget(e1);
BOOST_ASSERT(SPECIAL_NODEID != node_v);
// pick only every other edge, since we have every edge as an outgoing
// and incoming egde
if (node_u > node_v)
{
continue;
}
BOOST_ASSERT(node_u < node_v);
// Note: edges that end on barrier nodes or on a turn restriction
// may actually be in two distinct components. We choose the smallest
const unsigned size_of_component =
std::min(component_explorer.get_component_size(node_u),
component_explorer.get_component_size(node_v));
const unsigned id_of_smaller_component = [node_u, node_v, &component_explorer]
{
if (component_explorer.get_component_size(node_u) <
component_explorer.get_component_size(node_v))
{
return component_explorer.get_component_id(node_u);
}
return component_explorer.get_component_id(node_v);
}();
const bool component_is_tiny = size_of_component < 1000;
// we only set edgeBasedNodeID for forward edges
if (edge_data.edgeBasedNodeID == SPECIAL_NODEID)
{
InsertEdgeBasedNode(node_v, node_u,
(component_is_tiny ? id_of_smaller_component + 1 : 0));
}
else
{
InsertEdgeBasedNode(node_u, node_v,
(component_is_tiny ? id_of_smaller_component + 1 : 0));
}
}
}
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size()
<< " nodes in edge-expanded graph";
}
/**
* Actually it also generates OriginalEdgeData and serializes them...
*/
void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
const std::string &original_edge_data_filename, lua_State *lua_state)
{
SimpleLogger().Write() << "generating edge-expanded edges";
unsigned node_based_edge_counter = 0;
unsigned original_edges_counter = 0;
std::ofstream edge_data_file(original_edge_data_filename.c_str(), std::ios::binary);
// writes a dummy value that is updated later
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
std::vector<OriginalEdgeData> original_edge_data_vector;
original_edge_data_vector.reserve(1024 * 1024);
// Loop over all turns and generate new set of edges.
// Three nested loop look super-linear, but we are dealing with a (kind of)
// linear number of turns only.
unsigned restricted_turns_counter = 0;
unsigned skipped_uturns_counter = 0;
unsigned skipped_barrier_turns_counter = 0;
unsigned compressed = 0;
Percent progress(m_node_based_graph->GetNumberOfNodes());
for (const auto node_u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
{
progress.printStatus(node_u);
for (const EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(node_u))
{
if (!m_node_based_graph->GetEdgeData(e1).forward)
{
continue;
}
++node_based_edge_counter;
const NodeID node_v = m_node_based_graph->GetTarget(e1);
const NodeID only_restriction_to_node =
m_restriction_map->CheckForEmanatingIsOnlyTurn(node_u, node_v);
const bool is_barrier_node = m_barrier_nodes.find(node_v) != m_barrier_nodes.end();
for (const EdgeID e2 : m_node_based_graph->GetAdjacentEdgeRange(node_v))
{
if (!m_node_based_graph->GetEdgeData(e2).forward)
{
continue;
}
const NodeID node_w = m_node_based_graph->GetTarget(e2);
if ((only_restriction_to_node != SPECIAL_NODEID) &&
(node_w != only_restriction_to_node))
{
// We are at an only_-restriction but not at the right turn.
++restricted_turns_counter;
continue;
}
if (is_barrier_node)
{
if (node_u != node_w)
{
++skipped_barrier_turns_counter;
continue;
}
}
else
{
if ((node_u == node_w) && (m_node_based_graph->GetOutDegree(node_v) > 1))
{
++skipped_uturns_counter;
continue;
}
}
// only add an edge if turn is not a U-turn except when it is
// at the end of a dead-end street
if (m_restriction_map->CheckIfTurnIsRestricted(node_u, node_v, node_w) &&
(only_restriction_to_node == SPECIAL_NODEID) &&
(node_w != only_restriction_to_node))
{
// We are at an only_-restriction but not at the right turn.
++restricted_turns_counter;
continue;
}
// only add an edge if turn is not prohibited
const EdgeData &edge_data1 = m_node_based_graph->GetEdgeData(e1);
const EdgeData &edge_data2 = m_node_based_graph->GetEdgeData(e2);
BOOST_ASSERT(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
BOOST_ASSERT(edge_data1.forward);
BOOST_ASSERT(edge_data2.forward);
// the following is the core of the loop.
unsigned distance = edge_data1.distance;
if (m_traffic_lights.find(node_v) != m_traffic_lights.end())
{
distance += speed_profile.traffic_signal_penalty;
}
// unpack last node of first segment if packed
const auto first_coordinate =
m_node_info_list[(m_geometry_compressor.HasEntryForID(e1)
? m_geometry_compressor.GetLastNodeIDOfBucket(e1)
: node_u)];
// unpack first node of second segment if packed
const auto third_coordinate =
m_node_info_list[(m_geometry_compressor.HasEntryForID(e2)
? m_geometry_compressor.GetFirstNodeIDOfBucket(e2)
: node_w)];
const double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates(
first_coordinate, m_node_info_list[node_v], third_coordinate);
const int turn_penalty = GetTurnPenalty(turn_angle, lua_state);
TurnInstruction turn_instruction = AnalyzeTurn(node_u, node_v, node_w, turn_angle);
if (turn_instruction == TurnInstruction::UTurn)
{
distance += speed_profile.u_turn_penalty;
}
distance += turn_penalty;
const bool edge_is_compressed = m_geometry_compressor.HasEntryForID(e1);
if (edge_is_compressed)
{
++compressed;
}
original_edge_data_vector.emplace_back(
(edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : node_v),
edge_data1.nameID, turn_instruction, edge_is_compressed,
edge_data2.travel_mode);
++original_edges_counter;
if (original_edge_data_vector.size() > 1024 * 1024 * 10)
{
FlushVectorToStream(edge_data_file, original_edge_data_vector);
}
BOOST_ASSERT(SPECIAL_NODEID != edge_data1.edgeBasedNodeID);
BOOST_ASSERT(SPECIAL_NODEID != edge_data2.edgeBasedNodeID);
m_edge_based_edge_list.emplace_back(
EdgeBasedEdge(edge_data1.edgeBasedNodeID, edge_data2.edgeBasedNodeID,
m_edge_based_edge_list.size(), distance, true, false));
}
}
}
FlushVectorToStream(edge_data_file, original_edge_data_vector);
edge_data_file.seekp(std::ios::beg);
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
edge_data_file.close();
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " edge based nodes";
SimpleLogger().Write() << "Node-based graph contains " << node_based_edge_counter << " edges";
SimpleLogger().Write() << "Edge-expanded graph ...";
SimpleLogger().Write() << " contains " << m_edge_based_edge_list.size() << " edges";
SimpleLogger().Write() << " skips " << restricted_turns_counter << " turns, "
"defined by "
<< m_restriction_map->size() << " restrictions";
SimpleLogger().Write() << " skips " << skipped_uturns_counter << " U turns";
SimpleLogger().Write() << " skips " << skipped_barrier_turns_counter << " turns over barriers";
}
int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) const
{
if (speed_profile.has_turn_penalty_function)
{
try
{
// call lua profile to compute turn penalty
return luabind::call_function<int>(lua_state, "turn_function", 180. - angle);
}
catch (const luabind::error &er)
{
SimpleLogger().Write(logWARNING) << er.what();
}
}
return 0;
}
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID node_u,
const NodeID node_v,
const NodeID node_w,
const double angle) const
{
if (node_u == node_w)
{
return TurnInstruction::UTurn;
}
const EdgeID edge1 = m_node_based_graph->FindEdge(node_u, node_v);
const EdgeID edge2 = m_node_based_graph->FindEdge(node_v, node_w);
const EdgeData &data1 = m_node_based_graph->GetEdgeData(edge1);
const EdgeData &data2 = m_node_based_graph->GetEdgeData(edge2);
// roundabouts need to be handled explicitely
if (data1.roundabout && data2.roundabout)
{
// Is a turn possible? If yes, we stay on the roundabout!
if (1 == m_node_based_graph->GetDirectedOutDegree(node_v))
{
// No turn possible.
return TurnInstruction::NoTurn;
}
return TurnInstruction::StayOnRoundAbout;
}
// Does turn start or end on roundabout?
if (data1.roundabout || data2.roundabout)
{
// We are entering the roundabout
if ((!data1.roundabout) && data2.roundabout)
{
return TurnInstruction::EnterRoundAbout;
}
// We are leaving the roundabout
if (data1.roundabout && (!data2.roundabout))
{
return TurnInstruction::LeaveRoundAbout;
}
}
// If street names stay the same and if we are certain that it is not a
// a segment of a roundabout, we skip it.
if (data1.nameID == data2.nameID)
{
// TODO: Here we should also do a small graph exploration to check for
// more complex situations
if (0 != data1.nameID || m_node_based_graph->GetOutDegree(node_v) <= 2)
{
return TurnInstruction::NoTurn;
}
}
return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle);
}
unsigned EdgeBasedGraphFactory::GetNumberOfEdgeBasedNodes() const
{
return m_number_of_edge_based_nodes;
}
-129
View File
@@ -1,129 +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(std::shared_ptr<NodeBasedDynamicGraph> node_based_graph,
std::shared_ptr<RestrictionMap> restricion_map,
std::unique_ptr<std::vector<NodeID>> barrier_node_list,
std::unique_ptr<std::vector<NodeID>> traffic_light_node_list,
const std::vector<QueryNode> &node_info_list,
const SpeedProfileProperties &speed_profile);
void Run(const std::string &original_edge_data_filename,
const std::string &geometry_filename,
lua_State *lua_state);
void GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &edges);
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, const double angle) const;
int GetTurnPenalty(double angle, lua_State *lua_state) const;
unsigned GetNumberOfEdgeBasedNodes() const;
struct SpeedProfileProperties
{
SpeedProfileProperties()
: traffic_signal_penalty(0), u_turn_penalty(0), has_turn_penalty_function(false)
{
}
int traffic_signal_penalty;
int u_turn_penalty;
bool has_turn_penalty_function;
} speed_profile;
private:
using EdgeData = NodeBasedDynamicGraph::EdgeData;
unsigned m_number_of_edge_based_nodes;
std::vector<EdgeBasedNode> m_edge_based_node_list;
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
const std::vector<QueryNode>& m_node_info_list;
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
std::shared_ptr<RestrictionMap> m_restriction_map;
std::unordered_set<NodeID> m_barrier_nodes;
std::unordered_set<NodeID> m_traffic_lights;
GeometryCompressor m_geometry_compressor;
void CompressGeometry();
void RenumberEdges();
void GenerateEdgeExpandedNodes();
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
lua_State *lua_state);
void InsertEdgeBasedNode(const NodeID u, const NodeID v, const unsigned component_id);
void FlushVectorToStream(std::ofstream &edge_data_file,
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
NodeID max_id;
std::size_t removed_node_count;
};
#endif /* EDGE_BASED_GRAPH_FACTORY_HPP_ */
-236
View File
@@ -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> &current_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> &current_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> &current_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;
}
-69
View File
@@ -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_

Some files were not shown because too many files have changed in this diff Show More